summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2020-12-31 09:37:29 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2020-12-31 09:37:29 +0900
commitb9a5c35f80c8e05cd8178bace99809eb5b129c7a (patch)
tree2abb0ff788d1bd4dd94fa061e0cceabdb6f2a729 /numpy
parentd5925ce9bd335463f9561bdd10271fee77d2b9af (diff)
downloadpython-numpy-b9a5c35f80c8e05cd8178bace99809eb5b129c7a.tar.gz
python-numpy-b9a5c35f80c8e05cd8178bace99809eb5b129c7a.tar.bz2
python-numpy-b9a5c35f80c8e05cd8178bace99809eb5b129c7a.zip
Imported Upstream version 1.17.0upstream/1.17.0
Diffstat (limited to 'numpy')
-rw-r--r--numpy/_build_utils/src/apple_sgemv_fix.c54
-rw-r--r--numpy/compat/py3k.py18
-rw-r--r--numpy/compat/tests/test_compat.py7
-rw-r--r--numpy/core/__init__.py48
-rw-r--r--numpy/core/_add_newdocs.py1150
-rw-r--r--numpy/core/_asarray.py324
-rw-r--r--numpy/core/_dtype_ctypes.py2
-rw-r--r--numpy/core/_exceptions.py151
-rw-r--r--numpy/core/_internal.py83
-rw-r--r--numpy/core/_methods.py112
-rw-r--r--numpy/core/_ufunc_config.py458
-rw-r--r--numpy/core/arrayprint.py88
-rw-r--r--numpy/core/code_generators/genapi.py5
-rw-r--r--numpy/core/code_generators/generate_umath.py166
-rw-r--r--numpy/core/code_generators/ufunc_docstrings.py232
-rw-r--r--numpy/core/defchararray.py68
-rw-r--r--numpy/core/einsumfunc.py88
-rw-r--r--numpy/core/fromnumeric.py333
-rw-r--r--numpy/core/function_base.py25
-rw-r--r--numpy/core/getlimits.py6
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h2
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h32
-rw-r--r--numpy/core/include/numpy/npy_common.h17
-rw-r--r--numpy/core/include/numpy/npy_math.h32
-rw-r--r--numpy/core/include/numpy/random/bitgen.h20
-rw-r--r--numpy/core/include/numpy/ufuncobject.h8
-rw-r--r--numpy/core/machar.py2
-rw-r--r--numpy/core/memmap.py8
-rw-r--r--numpy/core/multiarray.py123
-rw-r--r--numpy/core/numeric.py1051
-rw-r--r--numpy/core/numerictypes.py36
-rw-r--r--numpy/core/overrides.py39
-rw-r--r--numpy/core/records.py158
-rw-r--r--numpy/core/setup.py115
-rw-r--r--numpy/core/setup_common.py57
-rw-r--r--numpy/core/shape_base.py95
-rw-r--r--numpy/core/src/common/array_assign.c2
-rw-r--r--numpy/core/src/common/lowlevel_strided_loops.h3
-rw-r--r--numpy/core/src/common/npy_sort.h.src17
-rw-r--r--numpy/core/src/multiarray/alloc.c18
-rw-r--r--numpy/core/src/multiarray/array_assign_array.c27
-rw-r--r--numpy/core/src/multiarray/arrayfunction_override.c2
-rw-r--r--numpy/core/src/multiarray/arrayobject.c10
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src205
-rw-r--r--numpy/core/src/multiarray/buffer.c23
-rw-r--r--numpy/core/src/multiarray/calculation.c21
-rw-r--r--numpy/core/src/multiarray/common.c12
-rw-r--r--numpy/core/src/multiarray/common.h2
-rw-r--r--numpy/core/src/multiarray/compiled_base.c557
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c27
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c214
-rw-r--r--numpy/core/src/multiarray/convert_datatype.h18
-rw-r--r--numpy/core/src/multiarray/ctors.c175
-rw-r--r--numpy/core/src/multiarray/ctors.h33
-rw-r--r--numpy/core/src/multiarray/datetime.c211
-rw-r--r--numpy/core/src/multiarray/descriptor.c259
-rw-r--r--numpy/core/src/multiarray/descriptor.h16
-rw-r--r--numpy/core/src/multiarray/dragon4.c38
-rw-r--r--numpy/core/src/multiarray/dragon4.h38
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c8
-rw-r--r--numpy/core/src/multiarray/einsum.c.src2
-rw-r--r--numpy/core/src/multiarray/flagsobject.c88
-rw-r--r--numpy/core/src/multiarray/getset.c9
-rw-r--r--numpy/core/src/multiarray/hashdescr.c22
-rw-r--r--numpy/core/src/multiarray/item_selection.c203
-rw-r--r--numpy/core/src/multiarray/iterators.c289
-rw-r--r--numpy/core/src/multiarray/lowlevel_strided_loops.c.src57
-rw-r--r--numpy/core/src/multiarray/mapping.c138
-rw-r--r--numpy/core/src/multiarray/methods.c124
-rw-r--r--numpy/core/src/multiarray/methods.h23
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c85
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.h3
-rw-r--r--numpy/core/src/multiarray/nditer_api.c2
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c8
-rw-r--r--numpy/core/src/multiarray/number.c2
-rw-r--r--numpy/core/src/multiarray/number.h1
-rw-r--r--numpy/core/src/multiarray/scalarapi.c17
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src107
-rw-r--r--numpy/core/src/npymath/ieee754.c.src3
-rw-r--r--numpy/core/src/npymath/npy_math_complex.c.src7
-rw-r--r--numpy/core/src/npysort/npysort_common.h8
-rw-r--r--numpy/core/src/npysort/radixsort.c.src231
-rw-r--r--numpy/core/src/npysort/selection.c.src2
-rw-r--r--numpy/core/src/npysort/timsort.c.src2574
-rw-r--r--numpy/core/src/umath/_struct_ufunc_tests.c.src61
-rw-r--r--numpy/core/src/umath/clip.c.src119
-rw-r--r--numpy/core/src/umath/clip.h.src18
-rw-r--r--numpy/core/src/umath/cpuid.c23
-rw-r--r--numpy/core/src/umath/fast_loop_macros.h234
-rw-r--r--numpy/core/src/umath/funcs.inc.src44
-rw-r--r--numpy/core/src/umath/loops.c.src345
-rw-r--r--numpy/core/src/umath/loops.h.src36
-rw-r--r--numpy/core/src/umath/matmul.c.src56
-rw-r--r--numpy/core/src/umath/override.c6
-rw-r--r--numpy/core/src/umath/reduction.c31
-rw-r--r--numpy/core/src/umath/simd.inc.src556
-rw-r--r--numpy/core/src/umath/ufunc_object.c215
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c504
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.h16
-rw-r--r--numpy/core/src/umath/umathmodule.c7
-rw-r--r--numpy/core/tests/data/umath-validation-set-README15
-rw-r--r--numpy/core/tests/data/umath-validation-set-cos707
-rw-r--r--numpy/core/tests/data/umath-validation-set-exp135
-rw-r--r--numpy/core/tests/data/umath-validation-set-log118
-rw-r--r--numpy/core/tests/data/umath-validation-set-sin707
-rw-r--r--numpy/core/tests/test_api.py12
-rw-r--r--numpy/core/tests/test_datetime.py63
-rw-r--r--numpy/core/tests/test_deprecations.py15
-rw-r--r--numpy/core/tests/test_dtype.py156
-rw-r--r--numpy/core/tests/test_einsum.py10
-rw-r--r--numpy/core/tests/test_errstate.py8
-rw-r--r--numpy/core/tests/test_half.py2
-rw-r--r--numpy/core/tests/test_item_selection.py10
-rw-r--r--numpy/core/tests/test_memmap.py10
-rw-r--r--numpy/core/tests/test_multiarray.py352
-rw-r--r--numpy/core/tests/test_nditer.py2
-rw-r--r--numpy/core/tests/test_numeric.py295
-rw-r--r--numpy/core/tests/test_overrides.py57
-rw-r--r--numpy/core/tests/test_records.py58
-rw-r--r--numpy/core/tests/test_regression.py35
-rw-r--r--numpy/core/tests/test_scalar_methods.py109
-rw-r--r--numpy/core/tests/test_scalarbuffer.py2
-rw-r--r--numpy/core/tests/test_scalarprint.py2
-rw-r--r--numpy/core/tests/test_shape_base.py16
-rw-r--r--numpy/core/tests/test_ufunc.py448
-rw-r--r--numpy/core/tests/test_umath.py130
-rw-r--r--numpy/core/tests/test_umath_accuracy.py53
-rw-r--r--numpy/core/tests/test_umath_complex.py3
-rw-r--r--numpy/core/umath.py4
-rw-r--r--numpy/ctypeslib.py19
-rw-r--r--numpy/distutils/_shell_utils.py4
-rw-r--r--numpy/distutils/command/autodist.py128
-rw-r--r--numpy/distutils/command/build_ext.py4
-rw-r--r--numpy/distutils/command/build_src.py62
-rw-r--r--numpy/distutils/command/config.py149
-rw-r--r--numpy/distutils/command/install.py19
-rw-r--r--numpy/distutils/command/install_clib.py3
-rw-r--r--numpy/distutils/conv_template.py28
-rw-r--r--numpy/distutils/exec_command.py23
-rw-r--r--numpy/distutils/fcompiler/__init__.py6
-rw-r--r--numpy/distutils/fcompiler/ibm.py17
-rw-r--r--numpy/distutils/from_template.py28
-rw-r--r--numpy/distutils/line_endings.py16
-rw-r--r--numpy/distutils/mingw32ccompiler.py32
-rw-r--r--numpy/distutils/misc_util.py135
-rw-r--r--numpy/distutils/system_info.py664
-rw-r--r--numpy/distutils/tests/test_exec_command.py31
-rw-r--r--numpy/distutils/tests/test_system_info.py24
-rw-r--r--numpy/doc/basics.py39
-rw-r--r--numpy/doc/byteswapping.py20
-rw-r--r--numpy/doc/constants.py307
-rw-r--r--numpy/doc/glossary.py70
-rw-r--r--numpy/doc/indexing.py16
-rw-r--r--numpy/doc/structured_arrays.py125
-rw-r--r--numpy/dual.py4
-rwxr-xr-xnumpy/f2py/f2py2e.py8
-rw-r--r--numpy/f2py/rules.py103
-rw-r--r--numpy/f2py/tests/test_callback.py6
-rw-r--r--numpy/f2py/tests/test_mixed.py7
-rw-r--r--numpy/f2py/tests/util.py72
-rw-r--r--numpy/fft/README.md53
-rw-r--r--numpy/fft/__init__.py2
-rw-r--r--numpy/fft/fftpack.c1536
-rw-r--r--numpy/fft/fftpack.h28
-rw-r--r--numpy/fft/fftpack_litemodule.c366
-rw-r--r--numpy/fft/helper.py107
-rw-r--r--numpy/fft/pocketfft.c2406
-rw-r--r--numpy/fft/pocketfft.py (renamed from numpy/fft/fftpack.py)226
-rw-r--r--numpy/fft/setup.py6
-rw-r--r--numpy/fft/tests/test_helper.py79
-rw-r--r--numpy/fft/tests/test_pocketfft.py (renamed from numpy/fft/tests/test_fftpack.py)68
-rw-r--r--numpy/lib/_datasource.py35
-rw-r--r--numpy/lib/_iotools.py37
-rw-r--r--numpy/lib/_version.py5
-rw-r--r--numpy/lib/arraypad.py1427
-rw-r--r--numpy/lib/arraysetops.py27
-rw-r--r--numpy/lib/arrayterator.py7
-rw-r--r--numpy/lib/financial.py26
-rw-r--r--numpy/lib/format.py148
-rw-r--r--numpy/lib/function_base.py436
-rw-r--r--numpy/lib/histograms.py69
-rw-r--r--numpy/lib/index_tricks.py47
-rw-r--r--numpy/lib/nanfunctions.py154
-rw-r--r--numpy/lib/npyio.py658
-rw-r--r--numpy/lib/polynomial.py58
-rw-r--r--numpy/lib/recfunctions.py68
-rw-r--r--numpy/lib/scimath.py45
-rw-r--r--numpy/lib/shape_base.py197
-rw-r--r--numpy/lib/stride_tricks.py25
-rw-r--r--numpy/lib/tests/test_arraypad.py595
-rw-r--r--numpy/lib/tests/test_format.py25
-rw-r--r--numpy/lib/tests/test_function_base.py282
-rw-r--r--numpy/lib/tests/test_histograms.py23
-rw-r--r--numpy/lib/tests/test_index_tricks.py38
-rw-r--r--numpy/lib/tests/test_io.py206
-rw-r--r--numpy/lib/tests/test_nanfunctions.py28
-rw-r--r--numpy/lib/tests/test_packbits.py122
-rw-r--r--numpy/lib/tests/test_recfunctions.py58
-rw-r--r--numpy/lib/tests/test_stride_tricks.py43
-rw-r--r--numpy/lib/tests/test_twodim_base.py2
-rw-r--r--numpy/lib/tests/test_type_check.py40
-rw-r--r--numpy/lib/tests/test_utils.py46
-rw-r--r--numpy/lib/twodim_base.py47
-rw-r--r--numpy/lib/type_check.py90
-rw-r--r--numpy/lib/ufunclike.py34
-rw-r--r--numpy/lib/utils.py53
-rw-r--r--numpy/linalg/lapack_lite/clapack_scrub.py5
-rw-r--r--numpy/linalg/lapack_lite/fortran.py17
-rw-r--r--numpy/linalg/linalg.py274
-rw-r--r--numpy/linalg/tests/test_linalg.py66
-rw-r--r--numpy/ma/core.py1227
-rw-r--r--numpy/ma/extras.py272
-rw-r--r--numpy/ma/mrecords.py16
-rw-r--r--numpy/ma/tests/test_core.py13
-rw-r--r--numpy/ma/tests/test_extras.py107
-rw-r--r--numpy/ma/tests/test_mrecords.py2
-rw-r--r--numpy/ma/tests/test_old_ma.py16
-rw-r--r--numpy/ma/tests/test_regression.py4
-rw-r--r--numpy/ma/tests/test_subclassing.py4
-rw-r--r--numpy/ma/timer_comparison.py15
-rw-r--r--numpy/matlib.py50
-rw-r--r--numpy/matrixlib/defmatrix.py72
-rw-r--r--numpy/matrixlib/tests/test_masked_matrix.py6
-rw-r--r--numpy/polynomial/_polybase.py77
-rw-r--r--numpy/polynomial/chebyshev.py262
-rw-r--r--numpy/polynomial/hermite.py290
-rw-r--r--numpy/polynomial/hermite_e.py287
-rw-r--r--numpy/polynomial/laguerre.py271
-rw-r--r--numpy/polynomial/legendre.py283
-rw-r--r--numpy/polynomial/polynomial.py286
-rw-r--r--numpy/polynomial/polyutils.py380
-rw-r--r--numpy/polynomial/tests/test_chebyshev.py6
-rw-r--r--numpy/polynomial/tests/test_classes.py13
-rw-r--r--numpy/polynomial/tests/test_hermite.py6
-rw-r--r--numpy/polynomial/tests/test_hermite_e.py6
-rw-r--r--numpy/polynomial/tests/test_laguerre.py6
-rw-r--r--numpy/polynomial/tests/test_legendre.py6
-rw-r--r--numpy/polynomial/tests/test_polynomial.py23
-rw-r--r--numpy/random/LICENSE.md71
-rw-r--r--numpy/random/__init__.py108
-rw-r--r--numpy/random/_pickle.py82
-rw-r--r--numpy/random/bit_generator.pxd26
-rw-r--r--numpy/random/bit_generator.pyx627
-rw-r--r--numpy/random/bounded_integers.pxd.in26
-rw-r--r--numpy/random/bounded_integers.pyx.in305
-rw-r--r--numpy/random/common.pxd114
-rw-r--r--numpy/random/common.pyx976
-rw-r--r--numpy/random/distributions.pxd140
-rw-r--r--numpy/random/entropy.pyx155
-rw-r--r--numpy/random/examples/cython/extending.pyx78
-rw-r--r--numpy/random/examples/cython/extending_distributions.pyx59
-rw-r--r--numpy/random/examples/cython/setup.py27
-rw-r--r--numpy/random/examples/numba/extending.py77
-rw-r--r--numpy/random/examples/numba/extending_distributions.py61
-rw-r--r--numpy/random/generator.pyx4004
-rw-r--r--numpy/random/legacy_distributions.pxd48
-rw-r--r--numpy/random/mt19937.pyx273
-rw-r--r--numpy/random/mtrand.pyx (renamed from numpy/random/mtrand/mtrand.pyx)2839
-rw-r--r--numpy/random/mtrand/Python.pxi43
-rw-r--r--numpy/random/mtrand/distributions.c942
-rw-r--r--numpy/random/mtrand/distributions.h185
-rw-r--r--numpy/random/mtrand/generate_mtrand_c.py42
-rw-r--r--numpy/random/mtrand/initarray.c152
-rw-r--r--numpy/random/mtrand/initarray.h8
-rw-r--r--numpy/random/mtrand/mtrand_py_helper.h23
-rw-r--r--numpy/random/mtrand/numpy.pxd163
-rw-r--r--numpy/random/mtrand/randint_helpers.pxi.in77
-rw-r--r--numpy/random/mtrand/randomkit.c626
-rw-r--r--numpy/random/pcg64.pyx270
-rw-r--r--numpy/random/philox.pyx336
-rw-r--r--numpy/random/setup.py146
-rw-r--r--numpy/random/sfc64.pyx144
-rw-r--r--numpy/random/src/aligned_malloc/aligned_malloc.c9
-rw-r--r--numpy/random/src/aligned_malloc/aligned_malloc.h54
-rw-r--r--numpy/random/src/distributions/LICENSE.md61
-rw-r--r--numpy/random/src/distributions/distributions.c1782
-rw-r--r--numpy/random/src/distributions/distributions.h205
-rw-r--r--numpy/random/src/distributions/logfactorial.c158
-rw-r--r--numpy/random/src/distributions/logfactorial.h9
-rw-r--r--numpy/random/src/distributions/random_hypergeometric.c260
-rw-r--r--numpy/random/src/distributions/ziggurat_constants.h1206
-rw-r--r--numpy/random/src/entropy/entropy.c114
-rw-r--r--numpy/random/src/entropy/entropy.h14
-rw-r--r--numpy/random/src/legacy/legacy-distributions.c361
-rw-r--r--numpy/random/src/legacy/legacy-distributions.h52
-rw-r--r--numpy/random/src/mt19937/LICENSE.md61
-rw-r--r--numpy/random/src/mt19937/mt19937-benchmark.c31
-rw-r--r--numpy/random/src/mt19937/mt19937-jump.c224
-rw-r--r--numpy/random/src/mt19937/mt19937-jump.h15
-rw-r--r--numpy/random/src/mt19937/mt19937-poly.h207
-rw-r--r--numpy/random/src/mt19937/mt19937-test-data-gen.c59
-rw-r--r--numpy/random/src/mt19937/mt19937.c107
-rw-r--r--numpy/random/src/mt19937/mt19937.h61
-rw-r--r--numpy/random/src/mt19937/randomkit.c578
-rw-r--r--numpy/random/src/mt19937/randomkit.h (renamed from numpy/random/mtrand/randomkit.h)75
-rw-r--r--numpy/random/src/pcg64/LICENSE.md22
-rw-r--r--numpy/random/src/pcg64/pcg64-benchmark.c42
-rw-r--r--numpy/random/src/pcg64/pcg64-test-data-gen.c73
-rw-r--r--numpy/random/src/pcg64/pcg64.c187
-rw-r--r--numpy/random/src/pcg64/pcg64.h294
-rw-r--r--numpy/random/src/pcg64/pcg64.orig.c11
-rw-r--r--numpy/random/src/pcg64/pcg64.orig.h2025
-rw-r--r--numpy/random/src/philox/LICENSE.md31
-rw-r--r--numpy/random/src/philox/philox-benchmark.c38
-rw-r--r--numpy/random/src/philox/philox-test-data-gen.c82
-rw-r--r--numpy/random/src/philox/philox.c29
-rw-r--r--numpy/random/src/philox/philox.h248
-rw-r--r--numpy/random/src/sfc64/LICENSE.md27
-rw-r--r--numpy/random/src/sfc64/sfc64.c39
-rw-r--r--numpy/random/src/sfc64/sfc64.h60
-rw-r--r--numpy/random/src/splitmix64/LICENSE.md9
-rw-r--r--numpy/random/src/splitmix64/splitmix64.c29
-rw-r--r--numpy/random/src/splitmix64/splitmix64.h30
-rw-r--r--numpy/random/src/splitmix64/splitmix64.orig.c28
-rw-r--r--numpy/random/tests/data/__init__.py0
-rw-r--r--numpy/random/tests/data/mt19937-testset-1.csv1001
-rw-r--r--numpy/random/tests/data/mt19937-testset-2.csv1001
-rw-r--r--numpy/random/tests/data/pcg64-testset-1.csv1001
-rw-r--r--numpy/random/tests/data/pcg64-testset-2.csv1001
-rw-r--r--numpy/random/tests/data/philox-testset-1.csv1001
-rw-r--r--numpy/random/tests/data/philox-testset-2.csv1001
-rw-r--r--numpy/random/tests/data/sfc64-testset-1.csv1001
-rw-r--r--numpy/random/tests/data/sfc64-testset-2.csv1001
-rw-r--r--numpy/random/tests/test_direct.py418
-rw-r--r--numpy/random/tests/test_generator_mt19937.py2018
-rw-r--r--numpy/random/tests/test_generator_mt19937_regressions.py158
-rw-r--r--numpy/random/tests/test_random.py41
-rw-r--r--numpy/random/tests/test_randomstate.py1951
-rw-r--r--numpy/random/tests/test_randomstate_regression.py183
-rw-r--r--numpy/random/tests/test_regression.py3
-rw-r--r--numpy/random/tests/test_seed_sequence.py54
-rw-r--r--numpy/random/tests/test_smoke.py828
-rw-r--r--numpy/testing/_private/utils.py98
-rw-r--r--numpy/testing/tests/test_utils.py65
-rw-r--r--numpy/tests/test_public_api.py1
-rw-r--r--numpy/tests/test_reloading.py2
-rw-r--r--numpy/tests/test_warnings.py2
337 files changed, 52576 insertions, 17088 deletions
diff --git a/numpy/_build_utils/src/apple_sgemv_fix.c b/numpy/_build_utils/src/apple_sgemv_fix.c
index c33c68992..b1dbeb681 100644
--- a/numpy/_build_utils/src/apple_sgemv_fix.c
+++ b/numpy/_build_utils/src/apple_sgemv_fix.c
@@ -102,7 +102,7 @@ using_mavericks()
__attribute__((destructor))
static void unloadlib(void)
{
- if (veclib) dlclose(veclib);
+ if (veclib) dlclose(veclib);
}
__attribute__((constructor))
@@ -224,30 +224,30 @@ void cblas_sgemv(const enum CBLAS_ORDER order,
const float *X, const int incX, const float beta,
float *Y, const int incY)
{
- char TA;
- if (order == CblasColMajor)
- {
- if (TransA == CblasNoTrans) TA = 'N';
- else if (TransA == CblasTrans) TA = 'T';
- else if (TransA == CblasConjTrans) TA = 'C';
- else
- {
- cblas_xerbla(2, "cblas_sgemv","Illegal TransA setting, %d\n", TransA);
- }
- sgemv_(&TA, &M, &N, &alpha, A, &lda, X, &incX, &beta, Y, &incY);
- }
- else if (order == CblasRowMajor)
- {
- if (TransA == CblasNoTrans) TA = 'T';
- else if (TransA == CblasTrans) TA = 'N';
- else if (TransA == CblasConjTrans) TA = 'N';
- else
- {
- cblas_xerbla(2, "cblas_sgemv", "Illegal TransA setting, %d\n", TransA);
- return;
- }
- sgemv_(&TA, &N, &M, &alpha, A, &lda, X, &incX, &beta, Y, &incY);
- }
- else
- cblas_xerbla(1, "cblas_sgemv", "Illegal Order setting, %d\n", order);
+ char TA;
+ if (order == CblasColMajor)
+ {
+ if (TransA == CblasNoTrans) TA = 'N';
+ else if (TransA == CblasTrans) TA = 'T';
+ else if (TransA == CblasConjTrans) TA = 'C';
+ else
+ {
+ cblas_xerbla(2, "cblas_sgemv","Illegal TransA setting, %d\n", TransA);
+ }
+ sgemv_(&TA, &M, &N, &alpha, A, &lda, X, &incX, &beta, Y, &incY);
+ }
+ else if (order == CblasRowMajor)
+ {
+ if (TransA == CblasNoTrans) TA = 'T';
+ else if (TransA == CblasTrans) TA = 'N';
+ else if (TransA == CblasConjTrans) TA = 'N';
+ else
+ {
+ cblas_xerbla(2, "cblas_sgemv", "Illegal TransA setting, %d\n", TransA);
+ return;
+ }
+ sgemv_(&TA, &N, &M, &alpha, A, &lda, X, &incX, &beta, Y, &incY);
+ }
+ else
+ cblas_xerbla(1, "cblas_sgemv", "Illegal Order setting, %d\n", order);
}
diff --git a/numpy/compat/py3k.py b/numpy/compat/py3k.py
index 067292776..c9ed9d52c 100644
--- a/numpy/compat/py3k.py
+++ b/numpy/compat/py3k.py
@@ -8,9 +8,10 @@ __all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
'asstr', 'open_latin1', 'long', 'basestring', 'sixu',
'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path',
- 'contextlib_nullcontext', 'os_fspath', 'os_PathLike']
+ 'pickle', 'contextlib_nullcontext', 'os_fspath', 'os_PathLike']
import sys
+import os
try:
from pathlib import Path, PurePath
except ImportError:
@@ -19,6 +20,11 @@ except ImportError:
if sys.version_info[0] >= 3:
import io
+ try:
+ import pickle5 as pickle
+ except ImportError:
+ import pickle
+
long = int
integer_types = (int,)
basestring = str
@@ -51,8 +57,9 @@ if sys.version_info[0] >= 3:
strchar = 'U'
-
else:
+ import cpickle as pickle
+
bytes = str
long = long
basestring = basestring
@@ -76,7 +83,6 @@ else:
def sixu(s):
return unicode(s, 'unicode_escape')
-
def getexception():
return sys.exc_info()[1]
@@ -168,7 +174,6 @@ else:
"""
import imp
- import os
if info is None:
path = os.path.dirname(fn)
fo, fn, info = imp.find_module(name, [path])
@@ -190,7 +195,6 @@ else:
# Backport os.fs_path, os.PathLike, and PurePath.__fspath__
if sys.version_info[:2] >= (3, 6):
- import os
os_fspath = os.fspath
os_PathLike = os.PathLike
else:
@@ -219,7 +223,7 @@ else:
path representation is not str or bytes, TypeError is raised. If the
provided path is not str, bytes, or os.PathLike, TypeError is raised.
"""
- if isinstance(path, (unicode, bytes)):
+ if isinstance(path, (str, bytes)):
return path
# Work from the object's type to match method resolution of other magic
@@ -235,7 +239,7 @@ else:
else:
raise TypeError("expected str, bytes or os.PathLike object, "
"not " + path_type.__name__)
- if isinstance(path_repr, (unicode, bytes)):
+ if isinstance(path_repr, (str, bytes)):
return path_repr
else:
raise TypeError("expected {}.__fspath__() to return str or bytes, "
diff --git a/numpy/compat/tests/test_compat.py b/numpy/compat/tests/test_compat.py
index 9bb316a4d..1543aafaf 100644
--- a/numpy/compat/tests/test_compat.py
+++ b/numpy/compat/tests/test_compat.py
@@ -2,7 +2,7 @@ from __future__ import division, absolute_import, print_function
from os.path import join
-from numpy.compat import isfileobj, os_fspath
+from numpy.compat import isfileobj
from numpy.testing import assert_
from numpy.testing import tempdir
@@ -19,8 +19,3 @@ def test_isfileobj():
with open(filename, 'rb') as f:
assert_(isfileobj(f))
-
-
-def test_os_fspath_strings():
- for string_path in (b'/a/b/c.d', u'/a/b/c.d'):
- assert_(os_fspath(string_path) == string_path)
diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py
index c6a4e930b..ce443bb22 100644
--- a/numpy/core/__init__.py
+++ b/numpy/core/__init__.py
@@ -5,29 +5,6 @@ from numpy.version import version as __version__
import os
-# on Windows NumPy loads an important OpenBLAS-related DLL
-# and the code below aims to alleviate issues with DLL
-# path resolution portability with an absolute path DLL load
-if os.name == 'nt':
- from ctypes import WinDLL
- import glob
- # convention for storing / loading the DLL from
- # numpy/.libs/, if present
- libs_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
- '..', '.libs'))
- DLL_filenames = []
- if os.path.isdir(libs_path):
- for filename in glob.glob(os.path.join(libs_path, '*openblas*dll')):
- # NOTE: would it change behavior to load ALL
- # DLLs at this path vs. the name restriction?
- WinDLL(os.path.abspath(filename))
- DLL_filenames.append(filename)
- if len(DLL_filenames) > 1:
- import warnings
- warnings.warn("loaded more than 1 DLL from .libs:\n%s" %
- "\n".join(DLL_filenames),
- stacklevel=1)
-
# disables OpenBLAS affinity setting of the main thread that limits
# python threads or processes to one core
env_added = []
@@ -44,17 +21,12 @@ except ImportError as exc:
IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
-Importing the multiarray numpy extension module failed. Most
-likely you are trying to import a failed build of numpy.
-Here is how to proceed:
-- If you're working with a numpy git repository, try `git clean -xdf`
- (removes all files not under version control) and rebuild numpy.
-- If you are simply trying to use the numpy version that you have installed:
- your installation is broken - please reinstall numpy.
-- If you have already reinstalled and that did not fix the problem, then:
- 1. Check that you are using the Python you expect (you're using %s),
+Importing the numpy c-extensions failed.
+- Try uninstalling and reinstalling numpy.
+- If you have already done that, then:
+ 1. Check that you expected to use Python%d.%d from "%s",
and that you have no directories in your PATH or PYTHONPATH that can
- interfere with the Python and numpy versions you're trying to use.
+ interfere with the Python and numpy version "%s" you're trying to use.
2. If (1) looks fine, you can open a new issue at
https://github.com/numpy/numpy/issues. Please include details on:
- how you installed Python
@@ -63,11 +35,15 @@ Here is how to proceed:
- whether or not you have multiple versions of Python installed
- if you built from source, your compiler versions and ideally a build log
- Note: this error has many possible causes, so please don't comment on
- an existing issue about this - open a new one instead.
+- If you're working with a numpy git repository, try `git clean -xdf`
+ (removes all files not under version control) and rebuild numpy.
+
+Note: this error has many possible causes, so please don't comment on
+an existing issue about this - open a new one instead.
Original error was: %s
-""" % (sys.executable, exc)
+""" % (sys.version_info[0], sys.version_info[1], sys.executable,
+ __version__, exc)
raise ImportError(msg)
finally:
for envkey in env_added:
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index 2ed11b2f1..02700c8ca 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -51,7 +51,7 @@ add_newdoc('numpy.core', 'flatiter',
>>> x = np.arange(6).reshape(2, 3)
>>> fl = x.flat
>>> type(fl)
- <type 'numpy.flatiter'>
+ <class 'numpy.flatiter'>
>>> for item in fl:
... print(item)
...
@@ -163,62 +163,63 @@ add_newdoc('numpy.core', 'nditer',
----------
op : ndarray or sequence of array_like
The array(s) to iterate over.
+
flags : sequence of str, optional
- Flags to control the behavior of the iterator.
+ Flags to control the behavior of the iterator.
- * "buffered" enables buffering when required.
- * "c_index" causes a C-order index to be tracked.
- * "f_index" causes a Fortran-order index to be tracked.
- * "multi_index" causes a multi-index, or a tuple of indices
+ * ``buffered`` enables buffering when required.
+ * ``c_index`` causes a C-order index to be tracked.
+ * ``f_index`` causes a Fortran-order index to be tracked.
+ * ``multi_index`` causes a multi-index, or a tuple of indices
with one per iteration dimension, to be tracked.
- * "common_dtype" causes all the operands to be converted to
+ * ``common_dtype`` causes all the operands to be converted to
a common data type, with copying or buffering as necessary.
- * "copy_if_overlap" causes the iterator to determine if read
+ * ``copy_if_overlap`` causes the iterator to determine if read
operands have overlap with write operands, and make temporary
copies as necessary to avoid overlap. False positives (needless
copying) are possible in some cases.
- * "delay_bufalloc" delays allocation of the buffers until
- a reset() call is made. Allows "allocate" operands to
+ * ``delay_bufalloc`` delays allocation of the buffers until
+ a reset() call is made. Allows ``allocate`` operands to
be initialized before their values are copied into the buffers.
- * "external_loop" causes the `values` given to be
+ * ``external_loop`` causes the ``values`` given to be
one-dimensional arrays with multiple values instead of
zero-dimensional arrays.
- * "grow_inner" allows the `value` array sizes to be made
- larger than the buffer size when both "buffered" and
- "external_loop" is used.
- * "ranged" allows the iterator to be restricted to a sub-range
+ * ``grow_inner`` allows the ``value`` array sizes to be made
+ larger than the buffer size when both ``buffered`` and
+ ``external_loop`` is used.
+ * ``ranged`` allows the iterator to be restricted to a sub-range
of the iterindex values.
- * "refs_ok" enables iteration of reference types, such as
+ * ``refs_ok`` enables iteration of reference types, such as
object arrays.
- * "reduce_ok" enables iteration of "readwrite" operands
+ * ``reduce_ok`` enables iteration of ``readwrite`` operands
which are broadcasted, also known as reduction operands.
- * "zerosize_ok" allows `itersize` to be zero.
+ * ``zerosize_ok`` allows `itersize` to be zero.
op_flags : list of list of str, optional
- This is a list of flags for each operand. At minimum, one of
- "readonly", "readwrite", or "writeonly" must be specified.
-
- * "readonly" indicates the operand will only be read from.
- * "readwrite" indicates the operand will be read from and written to.
- * "writeonly" indicates the operand will only be written to.
- * "no_broadcast" prevents the operand from being broadcasted.
- * "contig" forces the operand data to be contiguous.
- * "aligned" forces the operand data to be aligned.
- * "nbo" forces the operand data to be in native byte order.
- * "copy" allows a temporary read-only copy if required.
- * "updateifcopy" allows a temporary read-write copy if required.
- * "allocate" causes the array to be allocated if it is None
- in the `op` parameter.
- * "no_subtype" prevents an "allocate" operand from using a subtype.
- * "arraymask" indicates that this operand is the mask to use
+ This is a list of flags for each operand. At minimum, one of
+ ``readonly``, ``readwrite``, or ``writeonly`` must be specified.
+
+ * ``readonly`` indicates the operand will only be read from.
+ * ``readwrite`` indicates the operand will be read from and written to.
+ * ``writeonly`` indicates the operand will only be written to.
+ * ``no_broadcast`` prevents the operand from being broadcasted.
+ * ``contig`` forces the operand data to be contiguous.
+ * ``aligned`` forces the operand data to be aligned.
+ * ``nbo`` forces the operand data to be in native byte order.
+ * ``copy`` allows a temporary read-only copy if required.
+ * ``updateifcopy`` allows a temporary read-write copy if required.
+ * ``allocate`` causes the array to be allocated if it is None
+ in the ``op`` parameter.
+ * ``no_subtype`` prevents an ``allocate`` operand from using a subtype.
+ * ``arraymask`` indicates that this operand is the mask to use
for selecting elements when writing to operands with the
'writemasked' flag set. The iterator does not enforce this,
but when writing from a buffer back to the array, it only
copies those elements indicated by this mask.
- * 'writemasked' indicates that only elements where the chosen
- 'arraymask' operand is True will be written to.
- * "overlap_assume_elementwise" can be used to mark operands that are
+ * ``writemasked`` indicates that only elements where the chosen
+ ``arraymask`` operand is True will be written to.
+ * ``overlap_assume_elementwise`` can be used to mark operands that are
accessed only in the iterator order, to allow less conservative
- copying when "copy_if_overlap" is present.
+ copying when ``copy_if_overlap`` is present.
op_dtypes : dtype or tuple of dtype(s), optional
The required data type(s) of the operands. If copying or buffering
is enabled, the data will be converted to/from their original types.
@@ -227,7 +228,7 @@ add_newdoc('numpy.core', 'nditer',
Fortran order, 'A' means 'F' order if all the arrays are Fortran
contiguous, 'C' order otherwise, and 'K' means as close to the
order the array elements appear in memory as possible. This also
- affects the element memory order of "allocate" operands, as they
+ affects the element memory order of ``allocate`` operands, as they
are allocated to be compatible with iteration order.
Default is 'K'.
casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
@@ -235,20 +236,20 @@ add_newdoc('numpy.core', 'nditer',
or buffering. Setting this to 'unsafe' is not recommended,
as it can adversely affect accumulations.
- * 'no' means the data types should not be cast at all.
- * 'equiv' means only byte-order changes are allowed.
- * 'safe' means only casts which can preserve values are allowed.
- * 'same_kind' means only safe casts or casts within a kind,
- like float64 to float32, are allowed.
- * 'unsafe' means any data conversions may be done.
+ * 'no' means the data types should not be cast at all.
+ * 'equiv' means only byte-order changes are allowed.
+ * 'safe' means only casts which can preserve values are allowed.
+ * 'same_kind' means only safe casts or casts within a kind,
+ like float64 to float32, are allowed.
+ * 'unsafe' means any data conversions may be done.
op_axes : list of list of ints, optional
If provided, is a list of ints or None for each operands.
The list of axes for an operand is a mapping from the dimensions
of the iterator to the dimensions of the operand. A value of
-1 can be placed for entries, causing that dimension to be
- treated as "newaxis".
+ treated as `newaxis`.
itershape : tuple of ints, optional
- The desired shape of the iterator. This allows "allocate" operands
+ The desired shape of the iterator. This allows ``allocate`` operands
with a dimension mapped by op_axes not corresponding to a dimension
of a different operand to get a value not equal to 1 for that
dimension.
@@ -265,19 +266,19 @@ add_newdoc('numpy.core', 'nditer',
finished : bool
Whether the iteration over the operands is finished or not.
has_delayed_bufalloc : bool
- If True, the iterator was created with the "delay_bufalloc" flag,
+ If True, the iterator was created with the ``delay_bufalloc`` flag,
and no reset() function was called on it yet.
has_index : bool
- If True, the iterator was created with either the "c_index" or
- the "f_index" flag, and the property `index` can be used to
+ If True, the iterator was created with either the ``c_index`` or
+ the ``f_index`` flag, and the property `index` can be used to
retrieve it.
has_multi_index : bool
- If True, the iterator was created with the "multi_index" flag,
+ If True, the iterator was created with the ``multi_index`` flag,
and the property `multi_index` can be used to retrieve it.
index
- When the "c_index" or "f_index" flag was used, this property
+ When the ``c_index`` or ``f_index`` flag was used, this property
provides access to the index. Raises a ValueError if accessed
- and `has_index` is False.
+ and ``has_index`` is False.
iterationneedsapi : bool
Whether iteration requires access to the Python API, for example
if one of the operands is an object array.
@@ -290,11 +291,11 @@ add_newdoc('numpy.core', 'nditer',
and optimized iterator access pattern. Valid only before the iterator
is closed.
multi_index
- When the "multi_index" flag was used, this property
+ When the ``multi_index`` flag was used, this property
provides access to the index. Raises a ValueError if accessed
- accessed and `has_multi_index` is False.
+ accessed and ``has_multi_index`` is False.
ndim : int
- The iterator's dimension.
+ The dimensions of the iterator.
nop : int
The number of iterator operands.
operands : tuple of operand(s)
@@ -303,8 +304,8 @@ add_newdoc('numpy.core', 'nditer',
shape : tuple of ints
Shape tuple, the shape of the iterator.
value
- Value of `operands` at current iteration. Normally, this is a
- tuple of array scalars, but if the flag "external_loop" is used,
+ Value of ``operands`` at current iteration. Normally, this is a
+ tuple of array scalars, but if the flag ``external_loop`` is used,
it is a tuple of one dimensional arrays.
Notes
@@ -315,78 +316,75 @@ add_newdoc('numpy.core', 'nditer',
The Python exposure supplies two iteration interfaces, one which follows
the Python iterator protocol, and another which mirrors the C-style
do-while pattern. The native Python approach is better in most cases, but
- if you need the iterator's coordinates or index, use the C-style pattern.
+ if you need the coordinates or index of an iterator, use the C-style pattern.
Examples
--------
Here is how we might write an ``iter_add`` function, using the
- Python iterator protocol::
-
- def iter_add_py(x, y, out=None):
- addop = np.add
- it = np.nditer([x, y, out], [],
- [['readonly'], ['readonly'], ['writeonly','allocate']])
- with it:
- for (a, b, c) in it:
- addop(a, b, out=c)
- return it.operands[2]
-
- Here is the same function, but following the C-style pattern::
-
- def iter_add(x, y, out=None):
- addop = np.add
-
- it = np.nditer([x, y, out], [],
- [['readonly'], ['readonly'], ['writeonly','allocate']])
- with it:
- while not it.finished:
- addop(it[0], it[1], out=it[2])
- it.iternext()
-
- return it.operands[2]
-
- Here is an example outer product function::
-
- def outer_it(x, y, out=None):
- mulop = np.multiply
-
- it = np.nditer([x, y, out], ['external_loop'],
- [['readonly'], ['readonly'], ['writeonly', 'allocate']],
- op_axes=[list(range(x.ndim)) + [-1] * y.ndim,
- [-1] * x.ndim + list(range(y.ndim)),
- None])
- with it:
- for (a, b, c) in it:
- mulop(a, b, out=c)
- return it.operands[2]
-
- >>> a = np.arange(2)+1
- >>> b = np.arange(3)+1
- >>> outer_it(a,b)
- array([[1, 2, 3],
- [2, 4, 6]])
-
- Here is an example function which operates like a "lambda" ufunc::
-
- def luf(lamdaexpr, *args, **kwargs):
- "luf(lambdaexpr, op1, ..., opn, out=None, order='K', casting='safe', buffersize=0)"
- nargs = len(args)
- op = (kwargs.get('out',None),) + args
- it = np.nditer(op, ['buffered','external_loop'],
- [['writeonly','allocate','no_broadcast']] +
- [['readonly','nbo','aligned']]*nargs,
- order=kwargs.get('order','K'),
- casting=kwargs.get('casting','safe'),
- buffersize=kwargs.get('buffersize',0))
- while not it.finished:
- it[0] = lamdaexpr(*it[1:])
- it.iternext()
- return it.operands[0]
-
- >>> a = np.arange(5)
- >>> b = np.ones(5)
- >>> luf(lambda i,j:i*i + j/2, a, b)
- array([ 0.5, 1.5, 4.5, 9.5, 16.5])
+ Python iterator protocol:
+
+ >>> def iter_add_py(x, y, out=None):
+ ... addop = np.add
+ ... it = np.nditer([x, y, out], [],
+ ... [['readonly'], ['readonly'], ['writeonly','allocate']])
+ ... with it:
+ ... for (a, b, c) in it:
+ ... addop(a, b, out=c)
+ ... return it.operands[2]
+
+ Here is the same function, but following the C-style pattern:
+
+ >>> def iter_add(x, y, out=None):
+ ... addop = np.add
+ ... it = np.nditer([x, y, out], [],
+ ... [['readonly'], ['readonly'], ['writeonly','allocate']])
+ ... with it:
+ ... while not it.finished:
+ ... addop(it[0], it[1], out=it[2])
+ ... it.iternext()
+ ... return it.operands[2]
+
+ Here is an example outer product function:
+
+ >>> def outer_it(x, y, out=None):
+ ... mulop = np.multiply
+ ... it = np.nditer([x, y, out], ['external_loop'],
+ ... [['readonly'], ['readonly'], ['writeonly', 'allocate']],
+ ... op_axes=[list(range(x.ndim)) + [-1] * y.ndim,
+ ... [-1] * x.ndim + list(range(y.ndim)),
+ ... None])
+ ... with it:
+ ... for (a, b, c) in it:
+ ... mulop(a, b, out=c)
+ ... return it.operands[2]
+
+ >>> a = np.arange(2)+1
+ >>> b = np.arange(3)+1
+ >>> outer_it(a,b)
+ array([[1, 2, 3],
+ [2, 4, 6]])
+
+ Here is an example function which operates like a "lambda" ufunc:
+
+ >>> def luf(lamdaexpr, *args, **kwargs):
+ ... '''luf(lambdaexpr, op1, ..., opn, out=None, order='K', casting='safe', buffersize=0)'''
+ ... nargs = len(args)
+ ... op = (kwargs.get('out',None),) + args
+ ... it = np.nditer(op, ['buffered','external_loop'],
+ ... [['writeonly','allocate','no_broadcast']] +
+ ... [['readonly','nbo','aligned']]*nargs,
+ ... order=kwargs.get('order','K'),
+ ... casting=kwargs.get('casting','safe'),
+ ... buffersize=kwargs.get('buffersize',0))
+ ... while not it.finished:
+ ... it[0] = lamdaexpr(*it[1:])
+ ... it.iternext()
+ ... return it.operands[0]
+
+ >>> a = np.arange(5)
+ >>> b = np.ones(5)
+ >>> luf(lambda i,j:i*i + j/2, a, b)
+ array([ 0.5, 1.5, 4.5, 9.5, 16.5])
If operand flags `"writeonly"` or `"readwrite"` are used the operands may
be views into the original data with the `WRITEBACKIFCOPY` flag. In this case
@@ -395,16 +393,16 @@ add_newdoc('numpy.core', 'nditer',
data will be written back to the original data when the `__exit__`
function is called but not before:
- >>> a = np.arange(6, dtype='i4')[::-2]
- >>> with nditer(a, [],
- ... [['writeonly', 'updateifcopy']],
- ... casting='unsafe',
- ... op_dtypes=[np.dtype('f4')]) as i:
- ... x = i.operands[0]
- ... x[:] = [-1, -2, -3]
- ... # a still unchanged here
- >>> a, x
- array([-1, -2, -3]), array([-1, -2, -3])
+ >>> a = np.arange(6, dtype='i4')[::-2]
+ >>> with np.nditer(a, [],
+ ... [['writeonly', 'updateifcopy']],
+ ... casting='unsafe',
+ ... op_dtypes=[np.dtype('f4')]) as i:
+ ... x = i.operands[0]
+ ... x[:] = [-1, -2, -3]
+ ... # a still unchanged here
+ >>> a, x
+ (array([-1, -2, -3], dtype=int32), array([-1., -2., -3.], dtype=float32))
It is important to note that once the iterator is exited, dangling
references (like `x` in the example) may or may not share data with
@@ -430,10 +428,10 @@ add_newdoc('numpy.core', 'nditer', ('copy',
>>> x = np.arange(10)
>>> y = x + 1
>>> it = np.nditer([x, y])
- >>> it.next()
+ >>> next(it)
(array(0), array(1))
>>> it2 = it.copy()
- >>> it2.next()
+ >>> next(it2)
(array(1), array(2))
"""))
@@ -546,7 +544,6 @@ add_newdoc('numpy.core', 'nested_iters',
... print(i.multi_index)
... for y in j:
... print('', j.multi_index, y)
-
(0,)
(0, 0) 0
(0, 1) 1
@@ -619,9 +616,9 @@ add_newdoc('numpy.core', 'broadcast',
>>> out = np.empty(b.shape)
>>> out.flat = [u+v for (u,v) in b]
>>> out
- array([[ 5., 6., 7.],
- [ 6., 7., 8.],
- [ 7., 8., 9.]])
+ array([[5., 6., 7.],
+ [6., 7., 8.],
+ [7., 8., 9.]])
Compare against built-in broadcasting:
@@ -645,7 +642,7 @@ add_newdoc('numpy.core', 'broadcast', ('index',
>>> b = np.broadcast(x, y)
>>> b.index
0
- >>> b.next(), b.next(), b.next()
+ >>> next(b), next(b), next(b)
((1, 4), (1, 5), (1, 6))
>>> b.index
3
@@ -764,11 +761,11 @@ add_newdoc('numpy.core', 'broadcast', ('reset',
Examples
--------
>>> x = np.array([1, 2, 3])
- >>> y = np.array([[4], [5], [6]]
+ >>> y = np.array([[4], [5], [6]])
>>> b = np.broadcast(x, y)
>>> b.index
0
- >>> b.next(), b.next(), b.next()
+ >>> next(b), next(b), next(b)
((1, 4), (2, 4), (3, 4))
>>> b.index
3
@@ -941,11 +938,11 @@ add_newdoc('numpy.core.multiarray', 'empty',
--------
>>> np.empty([2, 2])
array([[ -9.74499359e+001, 6.69583040e-309],
- [ 2.13182611e-314, 3.06959433e-309]]) #random
+ [ 2.13182611e-314, 3.06959433e-309]]) #uninitialized
>>> np.empty([2, 2], dtype=int)
array([[-1073741821, -1067949133],
- [ 496041986, 19249760]]) #random
+ [ 496041986, 19249760]]) #uninitialized
""")
@@ -1046,9 +1043,14 @@ add_newdoc('numpy.core.multiarray', 'fromstring',
elements is also ignored.
.. deprecated:: 1.14
- If this argument is not provided, `fromstring` falls back on the
- behaviour of `frombuffer` after encoding unicode string inputs as
- either utf-8 (python 3), or the default encoding (python 2).
+ Passing ``sep=''``, the default, is deprecated since it will
+ trigger the deprecated binary mode of this function. This mode
+ interprets `string` as binary bytes, rather than ASCII text with
+ decimal numbers, an operation which is better spelt
+ ``frombuffer(string, dtype, count)``. If `string` contains unicode
+ text, the binary mode of `fromstring` will first encode it into
+ bytes using either utf-8 (python 3) or the default encoding
+ (python 2), neither of which produce sane results.
Returns
-------
@@ -1147,7 +1149,7 @@ add_newdoc('numpy.core.multiarray', 'fromiter',
add_newdoc('numpy.core.multiarray', 'fromfile',
"""
- fromfile(file, dtype=float, count=-1, sep='')
+ fromfile(file, dtype=float, count=-1, sep='', offset=0)
Construct an array from data in a text or binary file.
@@ -1157,8 +1159,12 @@ add_newdoc('numpy.core.multiarray', 'fromfile',
Parameters
----------
- file : file or str
+ file : file or str or Path
Open file object or filename.
+
+ .. versionchanged:: 1.17.0
+ `pathlib.Path` objects are now accepted.
+
dtype : data-type
Data type of the returned array.
For binary files, it is used to determine the size and byte-order
@@ -1172,6 +1178,11 @@ add_newdoc('numpy.core.multiarray', 'fromfile',
Spaces (" ") in the separator match zero or more whitespace characters.
A separator consisting only of spaces must match at least one
whitespace.
+ offset : int
+ The offset (in bytes) from the file's current position. Defaults to 0.
+ Only permitted for binary files.
+
+ .. versionadded:: 1.17.0
See also
--------
@@ -1191,32 +1202,32 @@ add_newdoc('numpy.core.multiarray', 'fromfile',
--------
Construct an ndarray:
- >>> dt = np.dtype([('time', [('min', int), ('sec', int)]),
+ >>> dt = np.dtype([('time', [('min', np.int64), ('sec', np.int64)]),
... ('temp', float)])
>>> x = np.zeros((1,), dtype=dt)
>>> x['time']['min'] = 10; x['temp'] = 98.25
>>> x
array([((10, 0), 98.25)],
- dtype=[('time', [('min', '<i4'), ('sec', '<i4')]), ('temp', '<f8')])
+ dtype=[('time', [('min', '<i8'), ('sec', '<i8')]), ('temp', '<f8')])
Save the raw data to disk:
- >>> import os
- >>> fname = os.tmpnam()
+ >>> import tempfile
+ >>> fname = tempfile.mkstemp()[1]
>>> x.tofile(fname)
Read the raw data from disk:
>>> np.fromfile(fname, dtype=dt)
array([((10, 0), 98.25)],
- dtype=[('time', [('min', '<i4'), ('sec', '<i4')]), ('temp', '<f8')])
+ dtype=[('time', [('min', '<i8'), ('sec', '<i8')]), ('temp', '<f8')])
The recommended way to store and load data:
>>> np.save(fname, x)
>>> np.load(fname + '.npy')
array([((10, 0), 98.25)],
- dtype=[('time', [('min', '<i4'), ('sec', '<i4')]), ('temp', '<f8')])
+ dtype=[('time', [('min', '<i8'), ('sec', '<i8')]), ('temp', '<f8')])
""")
@@ -1244,17 +1255,16 @@ add_newdoc('numpy.core.multiarray', 'frombuffer',
>>> dt = np.dtype(int)
>>> dt = dt.newbyteorder('>')
- >>> np.frombuffer(buf, dtype=dt)
+ >>> np.frombuffer(buf, dtype=dt) # doctest: +SKIP
The data of the resulting array will not be byteswapped, but will be
interpreted correctly.
Examples
--------
- >>> s = 'hello world'
+ >>> s = b'hello world'
>>> np.frombuffer(s, dtype='S1', count=5, offset=6)
- array(['w', 'o', 'r', 'l', 'd'],
- dtype='|S1')
+ array([b'w', b'o', b'r', b'l', b'd'], dtype='|S1')
>>> np.frombuffer(b'\\x01\\x02', dtype=np.uint8)
array([1, 2], dtype=uint8)
@@ -1944,8 +1954,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray',
First mode, `buffer` is None:
>>> np.ndarray(shape=(2,2), dtype=float, order='F')
- array([[ -1.13698227e+002, 4.25087011e-303],
- [ 2.88528414e-306, 3.27025015e-309]]) #random
+ array([[0.0e+000, 0.0e+000], # random
+ [ nan, 2.5e-323]])
Second mode:
@@ -2032,21 +2042,27 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('ctypes',
as well as documented private attributes):
.. autoattribute:: numpy.core._internal._ctypes.data
+ :noindex:
.. autoattribute:: numpy.core._internal._ctypes.shape
+ :noindex:
.. autoattribute:: numpy.core._internal._ctypes.strides
+ :noindex:
.. automethod:: numpy.core._internal._ctypes.data_as
+ :noindex:
.. automethod:: numpy.core._internal._ctypes.shape_as
+ :noindex:
.. automethod:: numpy.core._internal._ctypes.strides_as
+ :noindex:
If the ctypes module is not available, then the ctypes attribute
of array objects still returns something useful, but ctypes objects
are not returned and errors may be raised instead. In particular,
- the object will still have the as parameter attribute which will
+ the object will still have the ``as_parameter`` attribute which will
return an integer equal to the data attribute.
Examples
@@ -2244,7 +2260,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('flat',
>>> x.T.flat[3]
5
>>> type(x.flat)
- <type 'numpy.flatiter'>
+ <class 'numpy.flatiter'>
An assignment example:
@@ -2444,8 +2460,9 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('strides',
add_newdoc('numpy.core.multiarray', 'ndarray', ('T',
"""
- Same as self.transpose(), except that self is returned if
- self.ndim < 2.
+ The transposed array.
+
+ Same as ``self.transpose()``.
Examples
--------
@@ -2462,6 +2479,10 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('T',
>>> x.T
array([ 1., 2., 3., 4.])
+ See Also
+ --------
+ transpose
+
"""))
@@ -2603,7 +2624,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('argmin',
add_newdoc('numpy.core.multiarray', 'ndarray', ('argsort',
"""
- a.argsort(axis=-1, kind='quicksort', order=None)
+ a.argsort(axis=-1, kind=None, order=None)
Returns the indices that would sort this array.
@@ -2699,7 +2720,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('astype',
--------
>>> x = np.array([1, 2, 2.5])
>>> x
- array([ 1. , 2. , 2.5])
+ array([1. , 2. , 2.5])
>>> x.astype(int)
array([1, 2, 2])
@@ -2730,19 +2751,20 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('byteswap',
Examples
--------
>>> A = np.array([1, 256, 8755], dtype=np.int16)
- >>> map(hex, A)
+ >>> list(map(hex, A))
['0x1', '0x100', '0x2233']
>>> A.byteswap(inplace=True)
array([ 256, 1, 13090], dtype=int16)
- >>> map(hex, A)
+ >>> list(map(hex, A))
['0x100', '0x1', '0x3322']
Arrays of strings are not swapped
>>> A = np.array(['ceg', 'fac'])
>>> A.byteswap()
- array(['ceg', 'fac'],
- dtype='|S3')
+ Traceback (most recent call last):
+ ...
+ UnicodeDecodeError: ...
"""))
@@ -2764,7 +2786,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('choose',
add_newdoc('numpy.core.multiarray', 'ndarray', ('clip',
"""
- a.clip(min=None, max=None, out=None)
+ a.clip(min=None, max=None, out=None, **kwargs)
Return an array whose values are limited to ``[min, max]``.
One of max or min must be given.
@@ -2930,14 +2952,14 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('dot',
>>> a = np.eye(2)
>>> b = np.ones((2, 2)) * 2
>>> a.dot(b)
- array([[ 2., 2.],
- [ 2., 2.]])
+ array([[2., 2.],
+ [2., 2.]])
This array method can be conveniently chained:
>>> a.dot(b).dot(b)
- array([[ 8., 8.],
- [ 8., 8.]])
+ array([[8., 8.],
+ [8., 8.]])
"""))
@@ -2950,9 +2972,12 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('dump',
Parameters
----------
- file : str
+ file : str or Path
A string naming the dump file.
+ .. versionchanged:: 1.17.0
+ `pathlib.Path` objects are now accepted.
+
"""))
@@ -2990,7 +3015,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('fill',
>>> a = np.empty(2)
>>> a.fill(1)
>>> a
- array([ 1., 1.])
+ array([1., 1.])
"""))
@@ -3059,18 +3084,18 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('getfield',
>>> x = np.diag([1.+1.j]*2)
>>> x[1, 1] = 2 + 4.j
>>> x
- array([[ 1.+1.j, 0.+0.j],
- [ 0.+0.j, 2.+4.j]])
+ array([[1.+1.j, 0.+0.j],
+ [0.+0.j, 2.+4.j]])
>>> x.getfield(np.float64)
- array([[ 1., 0.],
- [ 0., 2.]])
+ array([[1., 0.],
+ [0., 2.]])
By choosing an offset of 8 bytes we can select the complex part of the
array for our view:
>>> x.getfield(np.float64, offset=8)
- array([[ 1., 0.],
- [ 0., 4.]])
+ array([[1., 0.],
+ [0., 4.]])
"""))
@@ -3116,19 +3141,20 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('item',
Examples
--------
+ >>> np.random.seed(123)
>>> x = np.random.randint(9, size=(3, 3))
>>> x
- array([[3, 1, 7],
- [2, 8, 3],
- [8, 5, 3]])
+ array([[2, 2, 6],
+ [1, 3, 6],
+ [1, 0, 1]])
>>> x.item(3)
- 2
+ 1
>>> x.item(7)
- 5
+ 0
>>> x.item((0, 1))
- 1
+ 2
>>> x.item((2, 2))
- 3
+ 1
"""))
@@ -3164,24 +3190,25 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('itemset',
Examples
--------
+ >>> np.random.seed(123)
>>> x = np.random.randint(9, size=(3, 3))
>>> x
- array([[3, 1, 7],
- [2, 8, 3],
- [8, 5, 3]])
+ array([[2, 2, 6],
+ [1, 3, 6],
+ [1, 0, 1]])
>>> x.itemset(4, 0)
>>> x.itemset((2, 2), 9)
>>> x
- array([[3, 1, 7],
- [2, 0, 3],
- [8, 5, 9]])
+ array([[2, 2, 6],
+ [1, 0, 6],
+ [1, 0, 9]])
"""))
add_newdoc('numpy.core.multiarray', 'ndarray', ('max',
"""
- a.max(axis=None, out=None, keepdims=False)
+ a.max(axis=None, out=None, keepdims=False, initial=<no value>, where=True)
Return the maximum along a given axis.
@@ -3211,7 +3238,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('mean',
add_newdoc('numpy.core.multiarray', 'ndarray', ('min',
"""
- a.min(axis=None, out=None, keepdims=False)
+ a.min(axis=None, out=None, keepdims=False, initial=<no value>, where=True)
Return the minimum along a given axis.
@@ -3283,7 +3310,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('nonzero',
add_newdoc('numpy.core.multiarray', 'ndarray', ('prod',
"""
- a.prod(axis=None, dtype=None, out=None, keepdims=False)
+ a.prod(axis=None, dtype=None, out=None, keepdims=False, initial=1, where=True)
Return the product of the array elements over the given axis
@@ -3459,7 +3486,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('resize',
>>> a.resize((1, 1))
Traceback (most recent call last):
...
- ValueError: cannot resize an array that has been referenced ...
+ ValueError: cannot resize an array that references or is referenced ...
Unless `refcheck` is False:
@@ -3532,23 +3559,23 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('setfield',
--------
>>> x = np.eye(3)
>>> x.getfield(np.float64)
- array([[ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]])
+ array([[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]])
>>> x.setfield(3, np.int32)
>>> x.getfield(np.int32)
array([[3, 3, 3],
[3, 3, 3],
- [3, 3, 3]])
+ [3, 3, 3]], dtype=int32)
>>> x
- array([[ 1.00000000e+000, 1.48219694e-323, 1.48219694e-323],
- [ 1.48219694e-323, 1.00000000e+000, 1.48219694e-323],
- [ 1.48219694e-323, 1.48219694e-323, 1.00000000e+000]])
+ array([[1.0e+000, 1.5e-323, 1.5e-323],
+ [1.5e-323, 1.0e+000, 1.5e-323],
+ [1.5e-323, 1.5e-323, 1.0e+000]])
>>> x.setfield(np.eye(3), np.int32)
>>> x
- array([[ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]])
+ array([[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]])
"""))
@@ -3601,6 +3628,9 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('setflags',
Examples
--------
+ >>> y = np.array([[3, 1, 7],
+ ... [2, 0, 0],
+ ... [8, 5, 9]])
>>> y
array([[3, 1, 7],
[2, 0, 0],
@@ -3632,9 +3662,9 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('setflags',
add_newdoc('numpy.core.multiarray', 'ndarray', ('sort',
"""
- a.sort(axis=-1, kind='quicksort', order=None)
+ a.sort(axis=-1, kind=None, order=None)
- Sort an array, in-place.
+ Sort an array in-place. Refer to `numpy.sort` for full documentation.
Parameters
----------
@@ -3642,7 +3672,14 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('sort',
Axis along which to sort. Default is -1, which means sort along the
last axis.
kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
- Sorting algorithm. Default is 'quicksort'.
+ Sorting algorithm. The default is 'quicksort'. Note that both 'stable'
+ and 'mergesort' use timsort under the covers and, in general, the
+ actual implementation will vary with datatype. The 'mergesort' option
+ is retained for backwards compatibility.
+
+ .. versionchanged:: 1.15.0.
+ The 'stable' option was added.
+
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
which fields to compare first, second, etc. A single field can
@@ -3660,7 +3697,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('sort',
Notes
-----
- See ``sort`` for notes on the different sorting algorithms.
+ See `numpy.sort` for notes on the different sorting algorithms.
Examples
--------
@@ -3680,8 +3717,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('sort',
>>> a = np.array([('a', 2), ('c', 1)], dtype=[('x', 'S1'), ('y', int)])
>>> a.sort(order='y')
>>> a
- array([('c', 1), ('a', 2)],
- dtype=[('x', '|S1'), ('y', '<i4')])
+ array([(b'c', 1), (b'a', 2)],
+ dtype=[('x', 'S1'), ('y', '<i8')])
"""))
@@ -3737,6 +3774,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('partition',
array([2, 1, 3, 4])
>>> a.partition((1, 3))
+ >>> a
array([1, 2, 3, 4])
"""))
@@ -3773,7 +3811,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('std',
add_newdoc('numpy.core.multiarray', 'ndarray', ('sum',
"""
- a.sum(axis=None, dtype=None, out=None, keepdims=False)
+ a.sum(axis=None, dtype=None, out=None, keepdims=False, initial=0, where=True)
Return the sum of the array elements over the given axis.
@@ -3828,8 +3866,12 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tofile',
Parameters
----------
- fid : file or str
+ fid : file or str or Path
An open file object, or a string containing a filename.
+
+ .. versionchanged:: 1.17.0
+ `pathlib.Path` objects are now accepted.
+
sep : str
Separator between array items for text output.
If "" (empty), a binary file is written, equivalent to
@@ -3860,10 +3902,14 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tolist',
"""
a.tolist()
- Return the array as a (possibly nested) list.
+ Return the array as an ``a.ndim``-levels deep nested list of Python scalars.
Return a copy of the array data as a (nested) Python list.
- Data items are converted to the nearest compatible Python type.
+ Data items are converted to the nearest compatible builtin Python type, via
+ the `~numpy.ndarray.item` function.
+
+ If ``a.ndim`` is 0, then since the depth of the nested list is 0, it will
+ not be a list at all, but a simple Python scalar.
Parameters
----------
@@ -3871,24 +3917,41 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tolist',
Returns
-------
- y : list
+ y : object, or list of object, or list of list of object, or ...
The possibly nested list of array elements.
Notes
-----
- The array may be recreated, ``a = np.array(a.tolist())``.
+ The array may be recreated via ``a = np.array(a.tolist())``, although this
+ may sometimes lose precision.
Examples
--------
+ For a 1D array, ``a.tolist()`` is almost the same as ``list(a)``:
+
>>> a = np.array([1, 2])
+ >>> list(a)
+ [1, 2]
>>> a.tolist()
[1, 2]
+
+ However, for a 2D array, ``tolist`` applies recursively:
+
>>> a = np.array([[1, 2], [3, 4]])
>>> list(a)
[array([1, 2]), array([3, 4])]
>>> a.tolist()
[[1, 2], [3, 4]]
+ The base case for this recursion is a 0D array:
+
+ >>> a = np.array(1)
+ >>> list(a)
+ Traceback (most recent call last):
+ ...
+ TypeError: iteration over a 0-d array
+ >>> a.tolist()
+ 1
"""))
@@ -3918,13 +3981,13 @@ tobytesdoc = """
Examples
--------
- >>> x = np.array([[0, 1], [2, 3]])
+ >>> x = np.array([[0, 1], [2, 3]], dtype='<u2')
>>> x.tobytes()
- b'\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00'
+ b'\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00'
>>> x.tobytes('C') == x.tobytes()
True
>>> x.tobytes('F')
- b'\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03\\x00\\x00\\x00'
+ b'\\x00\\x00\\x02\\x00\\x01\\x00\\x03\\x00'
"""
@@ -3960,9 +4023,11 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('transpose',
Returns a view of the array with axes transposed.
- For a 1-D array, this has no effect. (To change between column and
- row vectors, first cast the 1-D array into a matrix object.)
- For a 2-D array, this is the usual matrix transpose.
+ For a 1-D array this has no effect, as a transposed vector is simply the
+ same vector. To convert a 1-D array into a 2D column vector, an additional
+ dimension must be added. `np.atleast2d(a).T` achieves this, as does
+ `a[:, np.newaxis]`.
+ For a 2-D array, this is a standard matrix transpose.
For an n-D array, if axes are given, their order indicates how the
axes are permuted (see Examples). If axes are not provided and
``a.shape = (i[0], i[1], ... i[n-2], i[n-1])``, then
@@ -3988,6 +4053,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('transpose',
See Also
--------
ndarray.T : Array property returning the array transposed.
+ ndarray.reshape : Give a new shape to an array without changing its data.
Examples
--------
@@ -4074,7 +4140,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('view',
>>> y
matrix([[513]], dtype=int16)
>>> print(type(y))
- <class 'numpy.matrixlib.defmatrix.matrix'>
+ <class 'numpy.matrix'>
Creating a view on a structured array so it can be used in calculations
@@ -4084,19 +4150,19 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('view',
array([[1, 2],
[3, 4]], dtype=int8)
>>> xv.mean(0)
- array([ 2., 3.])
+ array([2., 3.])
Making changes to the view changes the underlying array
>>> xv[0,1] = 20
- >>> print(x)
- [(1, 20) (3, 4)]
+ >>> x
+ array([(1, 20), (3, 4)], dtype=[('a', 'i1'), ('b', 'i1')])
Using a view to convert an array to a recarray:
>>> z = x.view(np.recarray)
>>> z.a
- array([1], dtype=int8)
+ array([1, 3], dtype=int8)
Views share data:
@@ -4114,8 +4180,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('view',
[4, 5]], dtype=int16)
>>> y.view(dtype=[('width', np.int16), ('length', np.int16)])
Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- ValueError: new type not compatible with array.
+ ...
+ ValueError: To change to a dtype of a different size, the array must be C-contiguous
>>> z = y.copy()
>>> z.view(dtype=[('width', np.int16), ('length', np.int16)])
array([[(1, 2)],
@@ -4166,10 +4232,9 @@ add_newdoc('numpy.core.umath', 'frompyfunc',
>>> oct_array = np.frompyfunc(oct, 1, 1)
>>> oct_array(np.array((10, 30, 100)))
- array([012, 036, 0144], dtype=object)
+ array(['0o12', '0o36', '0o144'], dtype=object)
>>> np.array((oct(10), oct(30), oct(100))) # for comparison
- array(['012', '036', '0144'],
- dtype='|S4')
+ array(['0o12', '0o36', '0o144'], dtype='<U5')
""")
@@ -4216,7 +4281,7 @@ add_newdoc('numpy.core.umath', 'geterrobj',
Examples
--------
>>> np.geterrobj() # first get the defaults
- [10000, 0, None]
+ [8192, 521, None]
>>> def err_handler(type, flag):
... print("Floating point error (%s), with flag %s" % (type, flag))
@@ -4225,13 +4290,13 @@ add_newdoc('numpy.core.umath', 'geterrobj',
>>> old_err = np.seterr(divide='raise')
>>> old_handler = np.seterrcall(err_handler)
>>> np.geterrobj()
- [20000, 2, <function err_handler at 0x91dcaac>]
+ [8192, 521, <function err_handler at 0x91dcaac>]
>>> old_err = np.seterr(all='ignore')
>>> np.base_repr(np.geterrobj()[1], 8)
'0'
>>> old_err = np.seterr(divide='warn', over='log', under='call',
- invalid='print')
+ ... invalid='print')
>>> np.base_repr(np.geterrobj()[1], 8)
'4351'
@@ -4280,7 +4345,7 @@ add_newdoc('numpy.core.umath', 'seterrobj',
--------
>>> old_errobj = np.geterrobj() # first get the defaults
>>> old_errobj
- [10000, 0, None]
+ [8192, 521, None]
>>> def err_handler(type, flag):
... print("Floating point error (%s), with flag %s" % (type, flag))
@@ -4339,94 +4404,6 @@ add_newdoc('numpy.core.umath', '_add_newdoc_ufunc',
and then throwing away the ufunc.
""")
-add_newdoc('numpy.core.multiarray', 'packbits',
- """
- packbits(myarray, axis=None)
-
- Packs the elements of a binary-valued array into bits in a uint8 array.
-
- The result is padded to full bytes by inserting zero bits at the end.
-
- Parameters
- ----------
- myarray : array_like
- An array of integers or booleans whose elements should be packed to
- bits.
- axis : int, optional
- The dimension over which bit-packing is done.
- ``None`` implies packing the flattened array.
-
- Returns
- -------
- packed : ndarray
- Array of type uint8 whose elements represent bits corresponding to the
- logical (0 or nonzero) value of the input elements. The shape of
- `packed` has the same number of dimensions as the input (unless `axis`
- is None, in which case the output is 1-D).
-
- See Also
- --------
- unpackbits: Unpacks elements of a uint8 array into a binary-valued output
- array.
-
- Examples
- --------
- >>> a = np.array([[[1,0,1],
- ... [0,1,0]],
- ... [[1,1,0],
- ... [0,0,1]]])
- >>> b = np.packbits(a, axis=-1)
- >>> b
- array([[[160],[64]],[[192],[32]]], dtype=uint8)
-
- Note that in binary 160 = 1010 0000, 64 = 0100 0000, 192 = 1100 0000,
- and 32 = 0010 0000.
-
- """)
-
-add_newdoc('numpy.core.multiarray', 'unpackbits',
- """
- unpackbits(myarray, axis=None)
-
- Unpacks elements of a uint8 array into a binary-valued output array.
-
- Each element of `myarray` represents a bit-field that should be unpacked
- into a binary-valued output array. The shape of the output array is either
- 1-D (if `axis` is None) or the same shape as the input array with unpacking
- done along the axis specified.
-
- Parameters
- ----------
- myarray : ndarray, uint8 type
- Input array.
- axis : int, optional
- The dimension over which bit-unpacking is done.
- ``None`` implies unpacking the flattened array.
-
- Returns
- -------
- unpacked : ndarray, uint8 type
- The elements are binary-valued (0 or 1).
-
- See Also
- --------
- packbits : Packs the elements of a binary-valued array into bits in a uint8
- array.
-
- Examples
- --------
- >>> a = np.array([[2], [7], [23]], dtype=np.uint8)
- >>> a
- array([[ 2],
- [ 7],
- [23]], dtype=uint8)
- >>> b = np.unpackbits(a, axis=1)
- >>> b
- array([[0, 0, 0, 0, 0, 0, 1, 0],
- [0, 0, 0, 0, 0, 1, 1, 1],
- [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)
-
- """)
add_newdoc('numpy.core._multiarray_tests', 'format_float_OSprintf_g',
"""
@@ -4507,10 +4484,12 @@ add_newdoc('numpy.core', 'ufunc',
number of outputs; use `None` for uninitialized outputs to be
allocated by the ufunc.
where : array_like, optional
- Values of True indicate to calculate the ufunc at that position, values
- of False indicate to leave the value in the output alone. Note that if
- an uninitialized return array is created via the default ``out=None``,
- then the elements where the values are False will remain uninitialized.
+ This condition is broadcast over the input. At locations where the
+ condition is True, the `out` array will be set to the ufunc result.
+ Elsewhere, the `out` array will retain its original value.
+ Note that if an uninitialized `out` array is created via the default
+ ``out=None``, locations within it where the condition is False will
+ remain uninitialized.
**kwargs
For other keyword-only arguments, see the :ref:`ufunc docs <ufuncs.kwargs>`.
@@ -4717,7 +4696,7 @@ add_newdoc('numpy.core', 'ufunc', ('signature',
add_newdoc('numpy.core', 'ufunc', ('reduce',
"""
- reduce(a, axis=0, dtype=None, out=None, keepdims=False, initial)
+ reduce(a, axis=0, dtype=None, out=None, keepdims=False, initial=<no value>, where=True)
Reduces `a`'s dimension by one, by applying ufunc along one axis.
@@ -4762,7 +4741,7 @@ add_newdoc('numpy.core', 'ufunc', ('reduce',
out : ndarray, None, or tuple of ndarray and None, optional
A location into which the result is stored. If not provided or `None`,
a freshly-allocated array is returned. For consistency with
- :ref:`ufunc.__call__`, if given as a keyword, this may be wrapped in a
+ ``ufunc.__call__``, if given as a keyword, this may be wrapped in a
1-element tuple.
.. versionchanged:: 1.13.0
@@ -4782,6 +4761,14 @@ add_newdoc('numpy.core', 'ufunc', ('reduce',
.. versionadded:: 1.15.0
+ where : array_like of bool, optional
+ A boolean array which is broadcasted to match the dimensions
+ of `a`, and selects elements to include in the reduction. Note
+ that for ufuncs like ``minimum`` that do not have an identity
+ defined, one has to pass in also ``initial``.
+
+ .. versionadded:: 1.17.0
+
Returns
-------
r : ndarray
@@ -4813,19 +4800,24 @@ add_newdoc('numpy.core', 'ufunc', ('reduce',
array([[ 1, 5],
[ 9, 13]])
- You can use the ``initial`` keyword argument to initialize the reduction with a
- different value.
+ You can use the ``initial`` keyword argument to initialize the reduction
+ with a different value, and ``where`` to select specific elements to include:
>>> np.add.reduce([10], initial=5)
15
- >>> np.add.reduce(np.ones((2, 2, 2)), axis=(0, 2), initializer=10)
+ >>> np.add.reduce(np.ones((2, 2, 2)), axis=(0, 2), initial=10)
array([14., 14.])
+ >>> a = np.array([10., np.nan, 10])
+ >>> np.add.reduce(a, where=~np.isnan(a))
+ 20.0
Allows reductions of empty arrays where they would normally fail, i.e.
for ufuncs without an identity.
>>> np.minimum.reduce([], initial=np.inf)
inf
+ >>> np.minimum.reduce([[1., 2.], [3., 4.]], initial=10., where=[True, False])
+ array([ 1., 10.])
>>> np.minimum.reduce([])
Traceback (most recent call last):
...
@@ -4866,7 +4858,7 @@ add_newdoc('numpy.core', 'ufunc', ('accumulate',
out : ndarray, None, or tuple of ndarray and None, optional
A location into which the result is stored. If not provided or `None`,
a freshly-allocated array is returned. For consistency with
- :ref:`ufunc.__call__`, if given as a keyword, this may be wrapped in a
+ ``ufunc.__call__``, if given as a keyword, this may be wrapped in a
1-element tuple.
.. versionchanged:: 1.13.0
@@ -4891,23 +4883,23 @@ add_newdoc('numpy.core', 'ufunc', ('accumulate',
>>> I = np.eye(2)
>>> I
- array([[ 1., 0.],
- [ 0., 1.]])
+ array([[1., 0.],
+ [0., 1.]])
Accumulate along axis 0 (rows), down columns:
>>> np.add.accumulate(I, 0)
- array([[ 1., 0.],
- [ 1., 1.]])
+ array([[1., 0.],
+ [1., 1.]])
>>> np.add.accumulate(I) # no axis specified = axis zero
- array([[ 1., 0.],
- [ 1., 1.]])
+ array([[1., 0.],
+ [1., 1.]])
Accumulate along axis 1 (columns), through rows:
>>> np.add.accumulate(I, 1)
- array([[ 1., 1.],
- [ 0., 1.]])
+ array([[1., 1.],
+ [0., 1.]])
"""))
@@ -4948,7 +4940,7 @@ add_newdoc('numpy.core', 'ufunc', ('reduceat',
out : ndarray, None, or tuple of ndarray and None, optional
A location into which the result is stored. If not provided or `None`,
a freshly-allocated array is returned. For consistency with
- :ref:`ufunc.__call__`, if given as a keyword, this may be wrapped in a
+ ``ufunc.__call__``, if given as a keyword, this may be wrapped in a
1-element tuple.
.. versionchanged:: 1.13.0
@@ -4984,10 +4976,10 @@ add_newdoc('numpy.core', 'ufunc', ('reduceat',
>>> x = np.linspace(0, 15, 16).reshape(4,4)
>>> x
- array([[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.],
- [ 8., 9., 10., 11.],
- [ 12., 13., 14., 15.]])
+ array([[ 0., 1., 2., 3.],
+ [ 4., 5., 6., 7.],
+ [ 8., 9., 10., 11.],
+ [12., 13., 14., 15.]])
::
@@ -4999,11 +4991,11 @@ add_newdoc('numpy.core', 'ufunc', ('reduceat',
# [row1 + row2 + row3 + row4]
>>> np.add.reduceat(x, [0, 3, 1, 2, 0])
- array([[ 12., 15., 18., 21.],
- [ 12., 13., 14., 15.],
- [ 4., 5., 6., 7.],
- [ 8., 9., 10., 11.],
- [ 24., 28., 32., 36.]])
+ array([[12., 15., 18., 21.],
+ [12., 13., 14., 15.],
+ [ 4., 5., 6., 7.],
+ [ 8., 9., 10., 11.],
+ [24., 28., 32., 36.]])
::
@@ -5011,10 +5003,10 @@ add_newdoc('numpy.core', 'ufunc', ('reduceat',
# [col1 * col2 * col3, col4]
>>> np.multiply.reduceat(x, [0, 3], 1)
- array([[ 0., 3.],
- [ 120., 7.],
- [ 720., 11.],
- [ 2184., 15.]])
+ array([[ 0., 3.],
+ [ 120., 7.],
+ [ 720., 11.],
+ [2184., 15.]])
"""))
@@ -5113,14 +5105,14 @@ add_newdoc('numpy.core', 'ufunc', ('at',
>>> a = np.array([1, 2, 3, 4])
>>> np.negative.at(a, [0, 1])
- >>> print(a)
- array([-1, -2, 3, 4])
+ >>> a
+ array([-1, -2, 3, 4])
Increment items 0 and 1, and increment item 2 twice:
>>> a = np.array([1, 2, 3, 4])
>>> np.add.at(a, [0, 1, 2, 2], 1)
- >>> print(a)
+ >>> a
array([2, 3, 5, 4])
Add items 0 and 1 in first array to second array,
@@ -5129,7 +5121,7 @@ add_newdoc('numpy.core', 'ufunc', ('at',
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array([1, 2])
>>> np.add.at(a, [0, 1], b)
- >>> print(a)
+ >>> a
array([2, 4, 3, 4])
"""))
@@ -5194,13 +5186,13 @@ add_newdoc('numpy.core.multiarray', 'dtype',
Structured type, two fields: the first field contains an unsigned int, the
second an int32:
- >>> np.dtype([('f1', np.uint), ('f2', np.int32)])
- dtype([('f1', '<u4'), ('f2', '<i4')])
+ >>> np.dtype([('f1', np.uint64), ('f2', np.int32)])
+ dtype([('f1', '<u8'), ('f2', '<i4')])
Using array-protocol type strings:
>>> np.dtype([('a','f8'),('b','S10')])
- dtype([('a', '<f8'), ('b', '|S10')])
+ dtype([('a', '<f8'), ('b', 'S10')])
Using comma-separated field formats. The shape is (2,3):
@@ -5210,24 +5202,24 @@ add_newdoc('numpy.core.multiarray', 'dtype',
Using tuples. ``int`` is a fixed type, 3 the field's shape. ``void``
is a flexible type, here of size 10:
- >>> np.dtype([('hello',(int,3)),('world',np.void,10)])
- dtype([('hello', '<i4', 3), ('world', '|V10')])
+ >>> np.dtype([('hello',(np.int64,3)),('world',np.void,10)])
+ dtype([('hello', '<i8', (3,)), ('world', 'V10')])
Subdivide ``int16`` into 2 ``int8``'s, called x and y. 0 and 1 are
the offsets in bytes:
>>> np.dtype((np.int16, {'x':(np.int8,0), 'y':(np.int8,1)}))
- dtype(('<i2', [('x', '|i1'), ('y', '|i1')]))
+ dtype((numpy.int16, [('x', 'i1'), ('y', 'i1')]))
Using dictionaries. Two fields named 'gender' and 'age':
>>> np.dtype({'names':['gender','age'], 'formats':['S1',np.uint8]})
- dtype([('gender', '|S1'), ('age', '|u1')])
+ dtype([('gender', 'S1'), ('age', 'u1')])
Offsets in bytes, here 0 and 25:
>>> np.dtype({'surname':('S25',0),'age':(np.uint8,25)})
- dtype([('surname', '|S25'), ('age', '|u1')])
+ dtype([('surname', 'S25'), ('age', 'u1')])
""")
@@ -5243,6 +5235,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('alignment',
More information is available in the C-API section of the manual.
+ Examples
+ --------
+
+ >>> x = np.dtype('i4')
+ >>> x.alignment
+ 4
+
+ >>> x = np.dtype(float)
+ >>> x.alignment
+ 8
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('byteorder',
@@ -5289,7 +5292,16 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('byteorder',
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('char',
- """A unique character code for each of the 21 different built-in types."""))
+ """A unique character code for each of the 21 different built-in types.
+
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.char
+ 'd'
+
+ """))
add_newdoc('numpy.core.multiarray', 'dtype', ('descr',
"""
@@ -5300,6 +5312,18 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('descr',
Warning: This attribute exists specifically for `__array_interface__`,
and is not a datatype description compatible with `np.dtype`.
+
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.descr
+ [('', '<f8')]
+
+ >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
+ >>> dt.descr
+ [('name', '<U16'), ('grades', '<f8', (2,))]
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('fields',
@@ -5340,6 +5364,18 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('flags',
of these flags is in C-API documentation; they are largely useful
for user-defined data-types.
+ The following example demonstrates that operations on this particular
+ dtype requires Python C-API.
+
+ Examples
+ --------
+
+ >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)])
+ >>> x.flags
+ 16
+ >>> np.core.multiarray.NEEDS_PYAPI
+ 16
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('hasobject',
@@ -5397,6 +5433,7 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('isalignedstruct',
field alignment. This flag is sticky, so when combining multiple
structs together, it is preserved and produces new dtypes which
are also aligned.
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('itemsize',
@@ -5406,6 +5443,19 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('itemsize',
For 18 of the 21 types this number is fixed by the data-type.
For the flexible data-types, this number can be anything.
+ Examples
+ --------
+
+ >>> arr = np.array([[1, 2], [3, 4]])
+ >>> arr.dtype
+ dtype('int64')
+ >>> arr.itemsize
+ 8
+
+ >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
+ >>> dt.itemsize
+ 80
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('kind',
@@ -5426,6 +5476,19 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('kind',
V void
= ======================
+ Examples
+ --------
+
+ >>> dt = np.dtype('i4')
+ >>> dt.kind
+ 'i'
+ >>> dt = np.dtype('f8')
+ >>> dt.kind
+ 'f'
+ >>> dt = np.dtype([('field1', 'f8')])
+ >>> dt.kind
+ 'V'
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('name',
@@ -5434,6 +5497,16 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('name',
Un-sized flexible data-type objects do not have this attribute.
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.name
+ 'float64'
+ >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)])
+ >>> x.name
+ 'void640'
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('names',
@@ -5457,6 +5530,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('num',
These are roughly ordered from least-to-most precision.
+ Examples
+ --------
+
+ >>> dt = np.dtype(str)
+ >>> dt.num
+ 19
+
+ >>> dt = np.dtype(float)
+ >>> dt.num
+ 12
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('shape',
@@ -5464,6 +5548,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('shape',
Shape tuple of the sub-array if this data type describes a sub-array,
and ``()`` otherwise.
+ Examples
+ --------
+
+ >>> dt = np.dtype(('i4', 4))
+ >>> dt.shape
+ (4,)
+
+ >>> dt = np.dtype(('i4', (2, 3)))
+ >>> dt.shape
+ (2, 3)
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('ndim',
@@ -5473,6 +5568,20 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('ndim',
.. versionadded:: 1.13.0
+ Examples
+ --------
+ >>> x = np.dtype(float)
+ >>> x.ndim
+ 0
+
+ >>> x = np.dtype((float, 8))
+ >>> x.ndim
+ 1
+
+ >>> x = np.dtype(('i4', (3, 4)))
+ >>> x.ndim
+ 2
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('str',
@@ -5490,6 +5599,41 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('subdtype',
then the extra dimensions implied by *shape* are tacked on to
the end of the retrieved array.
+ See Also
+ --------
+ dtype.base
+
+ Examples
+ --------
+ >>> x = numpy.dtype('8f')
+ >>> x.subdtype
+ (dtype('float32'), (8,))
+
+ >>> x = numpy.dtype('i2')
+ >>> x.subdtype
+ >>>
+
+ """))
+
+add_newdoc('numpy.core.multiarray', 'dtype', ('base',
+ """
+ Returns dtype for the base element of the subarrays,
+ regardless of their dimension or shape.
+
+ See Also
+ --------
+ dtype.subdtype
+
+ Examples
+ --------
+ >>> x = numpy.dtype('8f')
+ >>> x.base
+ dtype('float32')
+
+ >>> x = numpy.dtype('i2')
+ >>> x.base
+ dtype('int16')
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('type',
@@ -5631,7 +5775,7 @@ add_newdoc('numpy.core.multiarray', 'busdaycalendar',
... holidays=['2011-07-01', '2011-07-04', '2011-07-17'])
>>> # Default is Monday to Friday weekdays
... bdd.weekmask
- array([ True, True, True, True, True, False, False], dtype='bool')
+ array([ True, True, True, True, True, False, False])
>>> # Any holidays already on the weekend are removed
... bdd.holidays
array(['2011-07-01', '2011-07-04'], dtype='datetime64[D]')
@@ -5728,7 +5872,7 @@ add_newdoc('numpy.core.multiarray', 'datetime_data',
as a timedelta
>>> np.datetime64('2010', np.datetime_data(dt_25s))
- numpy.datetime64('2010-01-01T00:00:00', '25s')
+ numpy.datetime64('2010-01-01T00:00:00','25s')
""")
@@ -5760,9 +5904,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('T',
albeit unimplemented, all the attributes of the ndarray class so as to
provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5774,9 +5916,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('base',
albeit unimplemented, all the attributes of the ndarray class so as to
a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5826,9 +5966,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('all',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5840,9 +5978,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('any',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5854,9 +5990,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('argmax',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5868,9 +6002,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('argmin',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5882,9 +6014,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('argsort',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5896,9 +6026,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('astype',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5910,9 +6038,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('byteswap',
albeit unimplemented, all the attributes of the ndarray class so as to
provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5924,9 +6050,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('choose',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5938,9 +6062,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('clip',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5952,9 +6074,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('compress',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5966,9 +6086,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('conjugate',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5980,9 +6098,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('copy',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -5994,9 +6110,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('cumprod',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6008,9 +6122,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('cumsum',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6022,9 +6134,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('diagonal',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6036,9 +6146,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('dump',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6050,9 +6158,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('dumps',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6064,9 +6170,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('fill',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6078,9 +6182,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('flatten',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6092,9 +6194,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('getfield',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6106,9 +6206,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('item',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6120,9 +6218,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('itemset',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6134,9 +6230,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('max',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6148,9 +6242,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('mean',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6162,9 +6254,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('min',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6209,9 +6299,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('nonzero',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6223,9 +6311,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('prod',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6237,9 +6323,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('ptp',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6251,9 +6335,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('put',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6265,9 +6347,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('ravel',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6279,9 +6359,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('repeat',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6293,9 +6371,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('reshape',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6307,9 +6383,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('resize',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6321,9 +6395,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('round',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6335,9 +6407,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('searchsorted',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6349,9 +6419,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('setfield',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6363,9 +6431,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('setflags',
albeit unimplemented, all the attributes of the ndarray class so as to
provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6377,9 +6443,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('sort',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6391,9 +6455,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('squeeze',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6405,9 +6467,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('std',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6419,9 +6479,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('sum',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6433,9 +6491,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('swapaxes',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6447,9 +6503,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('take',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6461,9 +6515,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('tofile',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6475,9 +6527,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('tolist',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6489,9 +6539,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('tostring',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6503,9 +6551,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('trace',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6517,9 +6563,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('transpose',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6531,9 +6575,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('var',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6545,9 +6587,7 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('view',
albeit unimplemented, all the attributes of the ndarray class
so as to provide a uniform API.
- See Also
- --------
- The corresponding attribute of the derived class of interest.
+ See also the corresponding attribute of the derived class of interest.
"""))
@@ -6562,25 +6602,25 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('view',
add_newdoc('numpy.core.numerictypes', 'number',
"""
Abstract base class of all numeric scalar types.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'integer',
"""
Abstract base class of all integer scalar types.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'signedinteger',
"""
Abstract base class of all signed integer scalar types.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'unsignedinteger',
"""
Abstract base class of all unsigned integer scalar types.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'inexact',
@@ -6588,20 +6628,20 @@ add_newdoc('numpy.core.numerictypes', 'inexact',
Abstract base class of all numeric scalar types with a (potentially)
inexact representation of the values in its range, such as
floating-point numbers.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'floating',
"""
Abstract base class of all floating-point scalar types.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'complexfloating',
"""
Abstract base class of all complex number scalar types that are made up of
floating-point numbers.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'flexible',
@@ -6609,13 +6649,13 @@ add_newdoc('numpy.core.numerictypes', 'flexible',
Abstract base class of all scalar types without predefined length.
The actual size of these types depends on the specific `np.dtype`
instantiation.
-
+
""")
add_newdoc('numpy.core.numerictypes', 'character',
"""
Abstract base class of all character string scalar types.
-
+
""")
@@ -6779,3 +6819,21 @@ add_newdoc_for_scalar_type('object_', [],
"""
Any Python object.
""")
+
+# TODO: work out how to put this on the base class, np.floating
+for float_name in ('half', 'single', 'double', 'longdouble'):
+ add_newdoc('numpy.core.numerictypes', float_name, ('as_integer_ratio',
+ """
+ {ftype}.as_integer_ratio() -> (int, int)
+
+ Return a pair of integers, whose ratio is exactly equal to the original
+ floating point number, and with a positive denominator.
+ Raise OverflowError on infinities and a ValueError on NaNs.
+
+ >>> np.{ftype}(10.0).as_integer_ratio()
+ (10, 1)
+ >>> np.{ftype}(0.0).as_integer_ratio()
+ (0, 1)
+ >>> np.{ftype}(-.25).as_integer_ratio()
+ (-1, 4)
+ """.format(ftype=float_name)))
diff --git a/numpy/core/_asarray.py b/numpy/core/_asarray.py
new file mode 100644
index 000000000..0ad4161f4
--- /dev/null
+++ b/numpy/core/_asarray.py
@@ -0,0 +1,324 @@
+"""
+Functions in the ``as*array`` family that promote array-likes into arrays.
+
+`require` fits this category despite its name not matching this pattern.
+"""
+from __future__ import division, absolute_import, print_function
+
+from .overrides import set_module
+from .multiarray import array
+
+
+__all__ = [
+ "asarray", "asanyarray", "ascontiguousarray", "asfortranarray", "require",
+]
+
+@set_module('numpy')
+def asarray(a, dtype=None, order=None):
+ """Convert the input to an array.
+
+ Parameters
+ ----------
+ a : array_like
+ Input data, in any form that can be converted to an array. This
+ includes lists, lists of tuples, tuples, tuples of tuples, tuples
+ of lists and ndarrays.
+ dtype : data-type, optional
+ By default, the data-type is inferred from the input data.
+ order : {'C', 'F'}, optional
+ Whether to use row-major (C-style) or
+ column-major (Fortran-style) memory representation.
+ Defaults to 'C'.
+
+ Returns
+ -------
+ out : ndarray
+ Array interpretation of `a`. No copy is performed if the input
+ is already an ndarray with matching dtype and order. If `a` is a
+ subclass of ndarray, a base class ndarray is returned.
+
+ See Also
+ --------
+ asanyarray : Similar function which passes through subclasses.
+ ascontiguousarray : Convert input to a contiguous array.
+ asfarray : Convert input to a floating point ndarray.
+ asfortranarray : Convert input to an ndarray with column-major
+ memory order.
+ asarray_chkfinite : Similar function which checks input for NaNs and Infs.
+ fromiter : Create an array from an iterator.
+ fromfunction : Construct an array by executing a function on grid
+ positions.
+
+ Examples
+ --------
+ Convert a list into an array:
+
+ >>> a = [1, 2]
+ >>> np.asarray(a)
+ array([1, 2])
+
+ Existing arrays are not copied:
+
+ >>> a = np.array([1, 2])
+ >>> np.asarray(a) is a
+ True
+
+ If `dtype` is set, array is copied only if dtype does not match:
+
+ >>> a = np.array([1, 2], dtype=np.float32)
+ >>> np.asarray(a, dtype=np.float32) is a
+ True
+ >>> np.asarray(a, dtype=np.float64) is a
+ False
+
+ Contrary to `asanyarray`, ndarray subclasses are not passed through:
+
+ >>> issubclass(np.recarray, np.ndarray)
+ True
+ >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray)
+ >>> np.asarray(a) is a
+ False
+ >>> np.asanyarray(a) is a
+ True
+
+ """
+ return array(a, dtype, copy=False, order=order)
+
+
+@set_module('numpy')
+def asanyarray(a, dtype=None, order=None):
+ """Convert the input to an ndarray, but pass ndarray subclasses through.
+
+ Parameters
+ ----------
+ a : array_like
+ Input data, in any form that can be converted to an array. This
+ includes scalars, lists, lists of tuples, tuples, tuples of tuples,
+ tuples of lists, and ndarrays.
+ dtype : data-type, optional
+ By default, the data-type is inferred from the input data.
+ order : {'C', 'F'}, optional
+ Whether to use row-major (C-style) or column-major
+ (Fortran-style) memory representation. Defaults to 'C'.
+
+ Returns
+ -------
+ out : ndarray or an ndarray subclass
+ Array interpretation of `a`. If `a` is an ndarray or a subclass
+ of ndarray, it is returned as-is and no copy is performed.
+
+ See Also
+ --------
+ asarray : Similar function which always returns ndarrays.
+ ascontiguousarray : Convert input to a contiguous array.
+ asfarray : Convert input to a floating point ndarray.
+ asfortranarray : Convert input to an ndarray with column-major
+ memory order.
+ asarray_chkfinite : Similar function which checks input for NaNs and
+ Infs.
+ fromiter : Create an array from an iterator.
+ fromfunction : Construct an array by executing a function on grid
+ positions.
+
+ Examples
+ --------
+ Convert a list into an array:
+
+ >>> a = [1, 2]
+ >>> np.asanyarray(a)
+ array([1, 2])
+
+ Instances of `ndarray` subclasses are passed through as-is:
+
+ >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray)
+ >>> np.asanyarray(a) is a
+ True
+
+ """
+ return array(a, dtype, copy=False, order=order, subok=True)
+
+
+@set_module('numpy')
+def ascontiguousarray(a, dtype=None):
+ """
+ Return a contiguous array (ndim >= 1) in memory (C order).
+
+ Parameters
+ ----------
+ a : array_like
+ Input array.
+ dtype : str or dtype object, optional
+ Data-type of returned array.
+
+ Returns
+ -------
+ out : ndarray
+ Contiguous array of same shape and content as `a`, with type `dtype`
+ if specified.
+
+ See Also
+ --------
+ asfortranarray : Convert input to an ndarray with column-major
+ memory order.
+ require : Return an ndarray that satisfies requirements.
+ ndarray.flags : Information about the memory layout of the array.
+
+ Examples
+ --------
+ >>> x = np.arange(6).reshape(2,3)
+ >>> np.ascontiguousarray(x, dtype=np.float32)
+ array([[0., 1., 2.],
+ [3., 4., 5.]], dtype=float32)
+ >>> x.flags['C_CONTIGUOUS']
+ True
+
+ Note: This function returns an array with at least one-dimension (1-d)
+ so it will not preserve 0-d arrays.
+
+ """
+ return array(a, dtype, copy=False, order='C', ndmin=1)
+
+
+@set_module('numpy')
+def asfortranarray(a, dtype=None):
+ """
+ Return an array (ndim >= 1) laid out in Fortran order in memory.
+
+ Parameters
+ ----------
+ a : array_like
+ Input array.
+ dtype : str or dtype object, optional
+ By default, the data-type is inferred from the input data.
+
+ Returns
+ -------
+ out : ndarray
+ The input `a` in Fortran, or column-major, order.
+
+ See Also
+ --------
+ ascontiguousarray : Convert input to a contiguous (C order) array.
+ asanyarray : Convert input to an ndarray with either row or
+ column-major memory order.
+ require : Return an ndarray that satisfies requirements.
+ ndarray.flags : Information about the memory layout of the array.
+
+ Examples
+ --------
+ >>> x = np.arange(6).reshape(2,3)
+ >>> y = np.asfortranarray(x)
+ >>> x.flags['F_CONTIGUOUS']
+ False
+ >>> y.flags['F_CONTIGUOUS']
+ True
+
+ Note: This function returns an array with at least one-dimension (1-d)
+ so it will not preserve 0-d arrays.
+
+ """
+ return array(a, dtype, copy=False, order='F', ndmin=1)
+
+
+@set_module('numpy')
+def require(a, dtype=None, requirements=None):
+ """
+ Return an ndarray of the provided type that satisfies requirements.
+
+ This function is useful to be sure that an array with the correct flags
+ is returned for passing to compiled code (perhaps through ctypes).
+
+ Parameters
+ ----------
+ a : array_like
+ The object to be converted to a type-and-requirement-satisfying array.
+ dtype : data-type
+ The required data-type. If None preserve the current dtype. If your
+ application requires the data to be in native byteorder, include
+ a byteorder specification as a part of the dtype specification.
+ requirements : str or list of str
+ The requirements list can be any of the following
+
+ * 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array
+ * 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array
+ * 'ALIGNED' ('A') - ensure a data-type aligned array
+ * 'WRITEABLE' ('W') - ensure a writable array
+ * 'OWNDATA' ('O') - ensure an array that owns its own data
+ * 'ENSUREARRAY', ('E') - ensure a base array, instead of a subclass
+
+ Returns
+ -------
+ out : ndarray
+ Array with specified requirements and type if given.
+
+ See Also
+ --------
+ asarray : Convert input to an ndarray.
+ asanyarray : Convert to an ndarray, but pass through ndarray subclasses.
+ ascontiguousarray : Convert input to a contiguous array.
+ asfortranarray : Convert input to an ndarray with column-major
+ memory order.
+ ndarray.flags : Information about the memory layout of the array.
+
+ Notes
+ -----
+ The returned array will be guaranteed to have the listed requirements
+ by making a copy if needed.
+
+ Examples
+ --------
+ >>> x = np.arange(6).reshape(2,3)
+ >>> x.flags
+ C_CONTIGUOUS : True
+ F_CONTIGUOUS : False
+ OWNDATA : False
+ WRITEABLE : True
+ ALIGNED : True
+ WRITEBACKIFCOPY : False
+ UPDATEIFCOPY : False
+
+ >>> y = np.require(x, dtype=np.float32, requirements=['A', 'O', 'W', 'F'])
+ >>> y.flags
+ C_CONTIGUOUS : False
+ F_CONTIGUOUS : True
+ OWNDATA : True
+ WRITEABLE : True
+ ALIGNED : True
+ WRITEBACKIFCOPY : False
+ UPDATEIFCOPY : False
+
+ """
+ possible_flags = {'C': 'C', 'C_CONTIGUOUS': 'C', 'CONTIGUOUS': 'C',
+ 'F': 'F', 'F_CONTIGUOUS': 'F', 'FORTRAN': 'F',
+ 'A': 'A', 'ALIGNED': 'A',
+ 'W': 'W', 'WRITEABLE': 'W',
+ 'O': 'O', 'OWNDATA': 'O',
+ 'E': 'E', 'ENSUREARRAY': 'E'}
+ if not requirements:
+ return asanyarray(a, dtype=dtype)
+ else:
+ requirements = {possible_flags[x.upper()] for x in requirements}
+
+ if 'E' in requirements:
+ requirements.remove('E')
+ subok = False
+ else:
+ subok = True
+
+ order = 'A'
+ if requirements >= {'C', 'F'}:
+ raise ValueError('Cannot specify both "C" and "F" order')
+ elif 'F' in requirements:
+ order = 'F'
+ requirements.remove('F')
+ elif 'C' in requirements:
+ order = 'C'
+ requirements.remove('C')
+
+ arr = array(a, dtype=dtype, order=order, copy=False, subok=subok)
+
+ for prop in requirements:
+ if not arr.flags[prop]:
+ arr = arr.copy(order)
+ break
+ return arr
diff --git a/numpy/core/_dtype_ctypes.py b/numpy/core/_dtype_ctypes.py
index 0852b1ef2..708241289 100644
--- a/numpy/core/_dtype_ctypes.py
+++ b/numpy/core/_dtype_ctypes.py
@@ -1,7 +1,7 @@
"""
Conversion from ctypes to dtype.
-In an ideal world, we could acheive this through the PEP3118 buffer protocol,
+In an ideal world, we could achieve this through the PEP3118 buffer protocol,
something like::
def dtype_from_ctypes_type(t):
diff --git a/numpy/core/_exceptions.py b/numpy/core/_exceptions.py
new file mode 100644
index 000000000..a1af7a78d
--- /dev/null
+++ b/numpy/core/_exceptions.py
@@ -0,0 +1,151 @@
+"""
+Various richly-typed exceptions, that also help us deal with string formatting
+in python where it's easier.
+
+By putting the formatting in `__str__`, we also avoid paying the cost for
+users who silence the exceptions.
+"""
+from numpy.core.overrides import set_module
+
+def _unpack_tuple(tup):
+ if len(tup) == 1:
+ return tup[0]
+ else:
+ return tup
+
+
+def _display_as_base(cls):
+ """
+ A decorator that makes an exception class look like its base.
+
+ We use this to hide subclasses that are implementation details - the user
+ should catch the base type, which is what the traceback will show them.
+
+ Classes decorated with this decorator are subject to removal without a
+ deprecation warning.
+ """
+ assert issubclass(cls, Exception)
+ cls.__name__ = cls.__base__.__name__
+ cls.__qualname__ = cls.__base__.__qualname__
+ return cls
+
+
+class UFuncTypeError(TypeError):
+ """ Base class for all ufunc exceptions """
+ def __init__(self, ufunc):
+ self.ufunc = ufunc
+
+
+@_display_as_base
+class _UFuncBinaryResolutionError(UFuncTypeError):
+ """ Thrown when a binary resolution fails """
+ def __init__(self, ufunc, dtypes):
+ super().__init__(ufunc)
+ self.dtypes = tuple(dtypes)
+ assert len(self.dtypes) == 2
+
+ def __str__(self):
+ return (
+ "ufunc {!r} cannot use operands with types {!r} and {!r}"
+ ).format(
+ self.ufunc.__name__, *self.dtypes
+ )
+
+
+@_display_as_base
+class _UFuncNoLoopError(UFuncTypeError):
+ """ Thrown when a ufunc loop cannot be found """
+ def __init__(self, ufunc, dtypes):
+ super().__init__(ufunc)
+ self.dtypes = tuple(dtypes)
+
+ def __str__(self):
+ return (
+ "ufunc {!r} did not contain a loop with signature matching types "
+ "{!r} -> {!r}"
+ ).format(
+ self.ufunc.__name__,
+ _unpack_tuple(self.dtypes[:self.ufunc.nin]),
+ _unpack_tuple(self.dtypes[self.ufunc.nin:])
+ )
+
+
+@_display_as_base
+class _UFuncCastingError(UFuncTypeError):
+ def __init__(self, ufunc, casting, from_, to):
+ super().__init__(ufunc)
+ self.casting = casting
+ self.from_ = from_
+ self.to = to
+
+
+@_display_as_base
+class _UFuncInputCastingError(_UFuncCastingError):
+ """ Thrown when a ufunc input cannot be casted """
+ def __init__(self, ufunc, casting, from_, to, i):
+ super().__init__(ufunc, casting, from_, to)
+ self.in_i = i
+
+ def __str__(self):
+ # only show the number if more than one input exists
+ i_str = "{} ".format(self.in_i) if self.ufunc.nin != 1 else ""
+ return (
+ "Cannot cast ufunc {!r} input {}from {!r} to {!r} with casting "
+ "rule {!r}"
+ ).format(
+ self.ufunc.__name__, i_str, self.from_, self.to, self.casting
+ )
+
+
+@_display_as_base
+class _UFuncOutputCastingError(_UFuncCastingError):
+ """ Thrown when a ufunc output cannot be casted """
+ def __init__(self, ufunc, casting, from_, to, i):
+ super().__init__(ufunc, casting, from_, to)
+ self.out_i = i
+
+ def __str__(self):
+ # only show the number if more than one output exists
+ i_str = "{} ".format(self.out_i) if self.ufunc.nout != 1 else ""
+ return (
+ "Cannot cast ufunc {!r} output {}from {!r} to {!r} with casting "
+ "rule {!r}"
+ ).format(
+ self.ufunc.__name__, i_str, self.from_, self.to, self.casting
+ )
+
+
+# Exception used in shares_memory()
+@set_module('numpy')
+class TooHardError(RuntimeError):
+ pass
+
+
+@set_module('numpy')
+class AxisError(ValueError, IndexError):
+ """ Axis supplied was invalid. """
+ def __init__(self, axis, ndim=None, msg_prefix=None):
+ # single-argument form just delegates to base class
+ if ndim is None and msg_prefix is None:
+ msg = axis
+
+ # do the string formatting here, to save work in the C code
+ else:
+ msg = ("axis {} is out of bounds for array of dimension {}"
+ .format(axis, ndim))
+ if msg_prefix is not None:
+ msg = "{}: {}".format(msg_prefix, msg)
+
+ super(AxisError, self).__init__(msg)
+
+
+@_display_as_base
+class _ArrayMemoryError(MemoryError):
+ """ Thrown when an array cannot be allocated"""
+ def __init__(self, shape, dtype):
+ self.shape = shape
+ self.dtype = dtype
+
+ def __str__(self):
+ return "Unable to allocate array with shape {} and data type {}".format(self.shape, self.dtype)
+
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py
index 2a4906767..c70718cb6 100644
--- a/numpy/core/_internal.py
+++ b/numpy/core/_internal.py
@@ -11,7 +11,6 @@ import sys
import platform
from numpy.compat import unicode
-from numpy.core.overrides import set_module
from .multiarray import dtype, array, ndarray
try:
import ctypes
@@ -147,7 +146,7 @@ def _reconstruct(subtype, shape, dtype):
# format_re was originally from numarray by J. Todd Miller
format_re = re.compile(br'(?P<order1>[<>|=]?)'
- br'(?P<repeats> *[(]?[ ,0-9L]*[)]? *)'
+ br'(?P<repeats> *[(]?[ ,0-9]*[)]? *)'
br'(?P<order2>[<>|=]?)'
br'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')
sep_re = re.compile(br'\s*,\s*')
@@ -248,13 +247,55 @@ class _missing_ctypes(object):
self.value = ptr
+class _unsafe_first_element_pointer(object):
+ """
+ Helper to allow viewing an array as a ctypes pointer to the first element
+
+ This avoids:
+ * dealing with strides
+ * `.view` rejecting object-containing arrays
+ * `memoryview` not supporting overlapping fields
+ """
+ def __init__(self, arr):
+ self.base = arr
+
+ @property
+ def __array_interface__(self):
+ i = dict(
+ shape=(),
+ typestr='|V0',
+ data=(self.base.__array_interface__['data'][0], False),
+ strides=(),
+ version=3,
+ )
+ return i
+
+
+def _get_void_ptr(arr):
+ """
+ Get a `ctypes.c_void_p` to arr.data, that keeps a reference to the array
+ """
+ import numpy as np
+ # convert to a 0d array that has a data pointer referrign to the start
+ # of arr. This holds a reference to arr.
+ simple_arr = np.asarray(_unsafe_first_element_pointer(arr))
+
+ # create a `char[0]` using the same memory.
+ c_arr = (ctypes.c_char * 0).from_buffer(simple_arr)
+
+ # finally cast to void*
+ return ctypes.cast(ctypes.pointer(c_arr), ctypes.c_void_p)
+
+
class _ctypes(object):
def __init__(self, array, ptr=None):
self._arr = array
if ctypes:
self._ctypes = ctypes
- self._data = self._ctypes.c_void_p(ptr)
+ # get a void pointer to the buffer, which keeps the array alive
+ self._data = _get_void_ptr(array)
+ assert self._data.value == ptr
else:
# fake a pointer-like object that holds onto the reference
self._ctypes = _missing_ctypes()
@@ -276,14 +317,7 @@ class _ctypes(object):
The returned pointer will keep a reference to the array.
"""
- # _ctypes.cast function causes a circular reference of self._data in
- # self._data._objects. Attributes of self._data cannot be released
- # until gc.collect is called. Make a copy of the pointer first then let
- # it hold the array reference. This is a workaround to circumvent the
- # CPython bug https://bugs.python.org/issue12836
- ptr = self._ctypes.cast(self._data, obj)
- ptr._arr = self._arr
- return ptr
+ return self._ctypes.cast(self._data, obj)
def shape_as(self, obj):
"""
@@ -351,7 +385,7 @@ class _ctypes(object):
Enables `c_func(some_array.ctypes)`
"""
- return self.data_as(ctypes.c_void_p)
+ return self._data
# kept for compatibility
get_data = data.fget
@@ -425,7 +459,7 @@ def _getfield_is_safe(oldtype, newtype, offset):
if newtype.hasobject or oldtype.hasobject:
if offset == 0 and newtype == oldtype:
return
- if oldtype.names is not None:
+ if oldtype.names:
for name in oldtype.names:
if (oldtype.fields[name][1] == offset and
oldtype.fields[name][0] == newtype):
@@ -763,29 +797,6 @@ def _gcd(a, b):
def _lcm(a, b):
return a // _gcd(a, b) * b
-# Exception used in shares_memory()
-@set_module('numpy')
-class TooHardError(RuntimeError):
- pass
-
-@set_module('numpy')
-class AxisError(ValueError, IndexError):
- """ Axis supplied was invalid. """
- def __init__(self, axis, ndim=None, msg_prefix=None):
- # single-argument form just delegates to base class
- if ndim is None and msg_prefix is None:
- msg = axis
-
- # do the string formatting here, to save work in the C code
- else:
- msg = ("axis {} is out of bounds for array of dimension {}"
- .format(axis, ndim))
- if msg_prefix is not None:
- msg = "{}: {}".format(msg_prefix, msg)
-
- super(AxisError, self).__init__(msg)
-
-
def array_ufunc_errmsg_formatter(dummy, ufunc, method, *inputs, **kwargs):
""" Format the error message for when __array_ufunc__ gives up. """
args_string = ', '.join(['{!r}'.format(arg) for arg in inputs] +
diff --git a/numpy/core/_methods.py b/numpy/core/_methods.py
index 33f6d01a8..269e509b8 100644
--- a/numpy/core/_methods.py
+++ b/numpy/core/_methods.py
@@ -9,9 +9,11 @@ import warnings
from numpy.core import multiarray as mu
from numpy.core import umath as um
-from numpy.core.numeric import asanyarray
+from numpy.core._asarray import asanyarray
from numpy.core import numerictypes as nt
+from numpy.core import _exceptions
from numpy._globals import _NoValue
+from numpy.compat import pickle, os_fspath, contextlib_nullcontext
# save those O(100) nanoseconds!
umr_maximum = um.maximum.reduce
@@ -24,20 +26,20 @@ umr_all = um.logical_and.reduce
# avoid keyword arguments to speed up parsing, saves about 15%-20% for very
# small reductions
def _amax(a, axis=None, out=None, keepdims=False,
- initial=_NoValue):
- return umr_maximum(a, axis, None, out, keepdims, initial)
+ initial=_NoValue, where=True):
+ return umr_maximum(a, axis, None, out, keepdims, initial, where)
def _amin(a, axis=None, out=None, keepdims=False,
- initial=_NoValue):
- return umr_minimum(a, axis, None, out, keepdims, initial)
+ initial=_NoValue, where=True):
+ return umr_minimum(a, axis, None, out, keepdims, initial, where)
def _sum(a, axis=None, dtype=None, out=None, keepdims=False,
- initial=_NoValue):
- return umr_sum(a, axis, dtype, out, keepdims, initial)
+ initial=_NoValue, where=True):
+ return umr_sum(a, axis, dtype, out, keepdims, initial, where)
def _prod(a, axis=None, dtype=None, out=None, keepdims=False,
- initial=_NoValue):
- return umr_prod(a, axis, dtype, out, keepdims, initial)
+ initial=_NoValue, where=True):
+ return umr_prod(a, axis, dtype, out, keepdims, initial, where)
def _any(a, axis=None, dtype=None, out=None, keepdims=False):
return umr_any(a, axis, dtype, out, keepdims)
@@ -55,6 +57,80 @@ def _count_reduce_items(arr, axis):
items *= arr.shape[ax]
return items
+# Numpy 1.17.0, 2019-02-24
+# Various clip behavior deprecations, marked with _clip_dep as a prefix.
+
+def _clip_dep_is_scalar_nan(a):
+ # guarded to protect circular imports
+ from numpy.core.fromnumeric import ndim
+ if ndim(a) != 0:
+ return False
+ try:
+ return um.isnan(a)
+ except TypeError:
+ return False
+
+def _clip_dep_is_byte_swapped(a):
+ if isinstance(a, mu.ndarray):
+ return not a.dtype.isnative
+ return False
+
+def _clip_dep_invoke_with_casting(ufunc, *args, out=None, casting=None, **kwargs):
+ # normal path
+ if casting is not None:
+ return ufunc(*args, out=out, casting=casting, **kwargs)
+
+ # try to deal with broken casting rules
+ try:
+ return ufunc(*args, out=out, **kwargs)
+ except _exceptions._UFuncOutputCastingError as e:
+ # Numpy 1.17.0, 2019-02-24
+ warnings.warn(
+ "Converting the output of clip from {!r} to {!r} is deprecated. "
+ "Pass `casting=\"unsafe\"` explicitly to silence this warning, or "
+ "correct the type of the variables.".format(e.from_, e.to),
+ DeprecationWarning,
+ stacklevel=2
+ )
+ return ufunc(*args, out=out, casting="unsafe", **kwargs)
+
+def _clip(a, min=None, max=None, out=None, *, casting=None, **kwargs):
+ if min is None and max is None:
+ raise ValueError("One of max or min must be given")
+
+ # Numpy 1.17.0, 2019-02-24
+ # This deprecation probably incurs a substantial slowdown for small arrays,
+ # it will be good to get rid of it.
+ if not _clip_dep_is_byte_swapped(a) and not _clip_dep_is_byte_swapped(out):
+ using_deprecated_nan = False
+ if _clip_dep_is_scalar_nan(min):
+ min = -float('inf')
+ using_deprecated_nan = True
+ if _clip_dep_is_scalar_nan(max):
+ max = float('inf')
+ using_deprecated_nan = True
+ if using_deprecated_nan:
+ warnings.warn(
+ "Passing `np.nan` to mean no clipping in np.clip has always "
+ "been unreliable, and is now deprecated. "
+ "In future, this will always return nan, like it already does "
+ "when min or max are arrays that contain nan. "
+ "To skip a bound, pass either None or an np.inf of an "
+ "appropriate sign.",
+ DeprecationWarning,
+ stacklevel=2
+ )
+
+ if min is None:
+ return _clip_dep_invoke_with_casting(
+ um.minimum, a, max, out=out, casting=casting, **kwargs)
+ elif max is None:
+ return _clip_dep_invoke_with_casting(
+ um.maximum, a, min, out=out, casting=casting, **kwargs)
+ else:
+ return _clip_dep_invoke_with_casting(
+ um.clip, a, min, max, out=out, casting=casting, **kwargs)
+
def _mean(a, axis=None, dtype=None, out=None, keepdims=False):
arr = asanyarray(a)
@@ -115,10 +191,11 @@ def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
# Note that x may not be inexact and that we need it to be an array,
# not a scalar.
x = asanyarray(arr - arrmean)
- if issubclass(arr.dtype.type, nt.complexfloating):
- x = um.multiply(x, um.conjugate(x), out=x).real
- else:
+ if issubclass(arr.dtype.type, (nt.floating, nt.integer)):
x = um.multiply(x, x, out=x)
+ else:
+ x = um.multiply(x, um.conjugate(x), out=x).real
+
ret = umr_sum(x, axis, dtype, out, keepdims)
# Compute degrees of freedom and make sure it is not negative.
@@ -154,3 +231,14 @@ def _ptp(a, axis=None, out=None, keepdims=False):
umr_minimum(a, axis, None, None, keepdims),
out
)
+
+def _dump(self, file, protocol=2):
+ if hasattr(file, 'write'):
+ ctx = contextlib_nullcontext(file)
+ else:
+ ctx = open(os_fspath(file), "wb")
+ with ctx as f:
+ pickle.dump(self, f, protocol=protocol)
+
+def _dumps(self, protocol=2):
+ return pickle.dumps(self, protocol=protocol)
diff --git a/numpy/core/_ufunc_config.py b/numpy/core/_ufunc_config.py
new file mode 100644
index 000000000..c3951cc09
--- /dev/null
+++ b/numpy/core/_ufunc_config.py
@@ -0,0 +1,458 @@
+"""
+Functions for changing global ufunc configuration
+
+This provides helpers which wrap `umath.geterrobj` and `umath.seterrobj`
+"""
+from __future__ import division, absolute_import, print_function
+
+try:
+ # Accessing collections abstract classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
+import contextlib
+
+from .overrides import set_module
+from .umath import (
+ UFUNC_BUFSIZE_DEFAULT,
+ ERR_IGNORE, ERR_WARN, ERR_RAISE, ERR_CALL, ERR_PRINT, ERR_LOG, ERR_DEFAULT,
+ SHIFT_DIVIDEBYZERO, SHIFT_OVERFLOW, SHIFT_UNDERFLOW, SHIFT_INVALID,
+)
+from . import umath
+
+__all__ = [
+ "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall",
+ "errstate",
+]
+
+_errdict = {"ignore": ERR_IGNORE,
+ "warn": ERR_WARN,
+ "raise": ERR_RAISE,
+ "call": ERR_CALL,
+ "print": ERR_PRINT,
+ "log": ERR_LOG}
+
+_errdict_rev = {value: key for key, value in _errdict.items()}
+
+
+@set_module('numpy')
+def seterr(all=None, divide=None, over=None, under=None, invalid=None):
+ """
+ Set how floating-point errors are handled.
+
+ Note that operations on integer scalar types (such as `int16`) are
+ handled like floating point, and are affected by these settings.
+
+ Parameters
+ ----------
+ all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
+ Set treatment for all types of floating-point errors at once:
+
+ - ignore: Take no action when the exception occurs.
+ - warn: Print a `RuntimeWarning` (via the Python `warnings` module).
+ - raise: Raise a `FloatingPointError`.
+ - call: Call a function specified using the `seterrcall` function.
+ - print: Print a warning directly to ``stdout``.
+ - log: Record error in a Log object specified by `seterrcall`.
+
+ The default is not to change the current behavior.
+ divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
+ Treatment for division by zero.
+ over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
+ Treatment for floating-point overflow.
+ under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
+ Treatment for floating-point underflow.
+ invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
+ Treatment for invalid floating-point operation.
+
+ Returns
+ -------
+ old_settings : dict
+ Dictionary containing the old settings.
+
+ See also
+ --------
+ seterrcall : Set a callback function for the 'call' mode.
+ geterr, geterrcall, errstate
+
+ Notes
+ -----
+ The floating-point exceptions are defined in the IEEE 754 standard [1]_:
+
+ - Division by zero: infinite result obtained from finite numbers.
+ - Overflow: result too large to be expressed.
+ - Underflow: result so close to zero that some precision
+ was lost.
+ - Invalid operation: result is not an expressible number, typically
+ indicates that a NaN was produced.
+
+ .. [1] https://en.wikipedia.org/wiki/IEEE_754
+
+ Examples
+ --------
+ >>> old_settings = np.seterr(all='ignore') #seterr to known value
+ >>> np.seterr(over='raise')
+ {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'}
+ >>> np.seterr(**old_settings) # reset to default
+ {'divide': 'ignore', 'over': 'raise', 'under': 'ignore', 'invalid': 'ignore'}
+
+ >>> np.int16(32000) * np.int16(3)
+ 30464
+ >>> old_settings = np.seterr(all='warn', over='raise')
+ >>> np.int16(32000) * np.int16(3)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ FloatingPointError: overflow encountered in short_scalars
+
+ >>> from collections import OrderedDict
+ >>> old_settings = np.seterr(all='print')
+ >>> OrderedDict(np.geterr())
+ OrderedDict([('divide', 'print'), ('over', 'print'), ('under', 'print'), ('invalid', 'print')])
+ >>> np.int16(32000) * np.int16(3)
+ 30464
+
+ """
+
+ pyvals = umath.geterrobj()
+ old = geterr()
+
+ if divide is None:
+ divide = all or old['divide']
+ if over is None:
+ over = all or old['over']
+ if under is None:
+ under = all or old['under']
+ if invalid is None:
+ invalid = all or old['invalid']
+
+ maskvalue = ((_errdict[divide] << SHIFT_DIVIDEBYZERO) +
+ (_errdict[over] << SHIFT_OVERFLOW) +
+ (_errdict[under] << SHIFT_UNDERFLOW) +
+ (_errdict[invalid] << SHIFT_INVALID))
+
+ pyvals[1] = maskvalue
+ umath.seterrobj(pyvals)
+ return old
+
+
+@set_module('numpy')
+def geterr():
+ """
+ Get the current way of handling floating-point errors.
+
+ Returns
+ -------
+ res : dict
+ A dictionary with keys "divide", "over", "under", and "invalid",
+ whose values are from the strings "ignore", "print", "log", "warn",
+ "raise", and "call". The keys represent possible floating-point
+ exceptions, and the values define how these exceptions are handled.
+
+ See Also
+ --------
+ geterrcall, seterr, seterrcall
+
+ Notes
+ -----
+ For complete documentation of the types of floating-point exceptions and
+ treatment options, see `seterr`.
+
+ Examples
+ --------
+ >>> from collections import OrderedDict
+ >>> sorted(np.geterr().items())
+ [('divide', 'warn'), ('invalid', 'warn'), ('over', 'warn'), ('under', 'ignore')]
+ >>> np.arange(3.) / np.arange(3.)
+ array([nan, 1., 1.])
+
+ >>> oldsettings = np.seterr(all='warn', over='raise')
+ >>> OrderedDict(sorted(np.geterr().items()))
+ OrderedDict([('divide', 'warn'), ('invalid', 'warn'), ('over', 'raise'), ('under', 'warn')])
+ >>> np.arange(3.) / np.arange(3.)
+ array([nan, 1., 1.])
+
+ """
+ maskvalue = umath.geterrobj()[1]
+ mask = 7
+ res = {}
+ val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask
+ res['divide'] = _errdict_rev[val]
+ val = (maskvalue >> SHIFT_OVERFLOW) & mask
+ res['over'] = _errdict_rev[val]
+ val = (maskvalue >> SHIFT_UNDERFLOW) & mask
+ res['under'] = _errdict_rev[val]
+ val = (maskvalue >> SHIFT_INVALID) & mask
+ res['invalid'] = _errdict_rev[val]
+ return res
+
+
+@set_module('numpy')
+def setbufsize(size):
+ """
+ Set the size of the buffer used in ufuncs.
+
+ Parameters
+ ----------
+ size : int
+ Size of buffer.
+
+ """
+ if size > 10e6:
+ raise ValueError("Buffer size, %s, is too big." % size)
+ if size < 5:
+ raise ValueError("Buffer size, %s, is too small." % size)
+ if size % 16 != 0:
+ raise ValueError("Buffer size, %s, is not a multiple of 16." % size)
+
+ pyvals = umath.geterrobj()
+ old = getbufsize()
+ pyvals[0] = size
+ umath.seterrobj(pyvals)
+ return old
+
+
+@set_module('numpy')
+def getbufsize():
+ """
+ Return the size of the buffer used in ufuncs.
+
+ Returns
+ -------
+ getbufsize : int
+ Size of ufunc buffer in bytes.
+
+ """
+ return umath.geterrobj()[0]
+
+
+@set_module('numpy')
+def seterrcall(func):
+ """
+ Set the floating-point error callback function or log object.
+
+ There are two ways to capture floating-point error messages. The first
+ is to set the error-handler to 'call', using `seterr`. Then, set
+ the function to call using this function.
+
+ The second is to set the error-handler to 'log', using `seterr`.
+ Floating-point errors then trigger a call to the 'write' method of
+ the provided object.
+
+ Parameters
+ ----------
+ func : callable f(err, flag) or object with write method
+ Function to call upon floating-point errors ('call'-mode) or
+ object whose 'write' method is used to log such message ('log'-mode).
+
+ The call function takes two arguments. The first is a string describing
+ the type of error (such as "divide by zero", "overflow", "underflow",
+ or "invalid value"), and the second is the status flag. The flag is a
+ byte, whose four least-significant bits indicate the type of error, one
+ of "divide", "over", "under", "invalid"::
+
+ [0 0 0 0 divide over under invalid]
+
+ In other words, ``flags = divide + 2*over + 4*under + 8*invalid``.
+
+ If an object is provided, its write method should take one argument,
+ a string.
+
+ Returns
+ -------
+ h : callable, log instance or None
+ The old error handler.
+
+ See Also
+ --------
+ seterr, geterr, geterrcall
+
+ Examples
+ --------
+ Callback upon error:
+
+ >>> def err_handler(type, flag):
+ ... print("Floating point error (%s), with flag %s" % (type, flag))
+ ...
+
+ >>> saved_handler = np.seterrcall(err_handler)
+ >>> save_err = np.seterr(all='call')
+ >>> from collections import OrderedDict
+
+ >>> np.array([1, 2, 3]) / 0.0
+ Floating point error (divide by zero), with flag 1
+ array([inf, inf, inf])
+
+ >>> np.seterrcall(saved_handler)
+ <function err_handler at 0x...>
+ >>> OrderedDict(sorted(np.seterr(**save_err).items()))
+ OrderedDict([('divide', 'call'), ('invalid', 'call'), ('over', 'call'), ('under', 'call')])
+
+ Log error message:
+
+ >>> class Log(object):
+ ... def write(self, msg):
+ ... print("LOG: %s" % msg)
+ ...
+
+ >>> log = Log()
+ >>> saved_handler = np.seterrcall(log)
+ >>> save_err = np.seterr(all='log')
+
+ >>> np.array([1, 2, 3]) / 0.0
+ LOG: Warning: divide by zero encountered in true_divide
+ array([inf, inf, inf])
+
+ >>> np.seterrcall(saved_handler)
+ <numpy.core.numeric.Log object at 0x...>
+ >>> OrderedDict(sorted(np.seterr(**save_err).items()))
+ OrderedDict([('divide', 'log'), ('invalid', 'log'), ('over', 'log'), ('under', 'log')])
+
+ """
+ if func is not None and not isinstance(func, collections_abc.Callable):
+ if not hasattr(func, 'write') or not isinstance(func.write, collections_abc.Callable):
+ raise ValueError("Only callable can be used as callback")
+ pyvals = umath.geterrobj()
+ old = geterrcall()
+ pyvals[2] = func
+ umath.seterrobj(pyvals)
+ return old
+
+
+@set_module('numpy')
+def geterrcall():
+ """
+ Return the current callback function used on floating-point errors.
+
+ When the error handling for a floating-point error (one of "divide",
+ "over", "under", or "invalid") is set to 'call' or 'log', the function
+ that is called or the log instance that is written to is returned by
+ `geterrcall`. This function or log instance has been set with
+ `seterrcall`.
+
+ Returns
+ -------
+ errobj : callable, log instance or None
+ The current error handler. If no handler was set through `seterrcall`,
+ ``None`` is returned.
+
+ See Also
+ --------
+ seterrcall, seterr, geterr
+
+ Notes
+ -----
+ For complete documentation of the types of floating-point exceptions and
+ treatment options, see `seterr`.
+
+ Examples
+ --------
+ >>> np.geterrcall() # we did not yet set a handler, returns None
+
+ >>> oldsettings = np.seterr(all='call')
+ >>> def err_handler(type, flag):
+ ... print("Floating point error (%s), with flag %s" % (type, flag))
+ >>> oldhandler = np.seterrcall(err_handler)
+ >>> np.array([1, 2, 3]) / 0.0
+ Floating point error (divide by zero), with flag 1
+ array([inf, inf, inf])
+
+ >>> cur_handler = np.geterrcall()
+ >>> cur_handler is err_handler
+ True
+
+ """
+ return umath.geterrobj()[2]
+
+
+class _unspecified(object):
+ pass
+
+
+_Unspecified = _unspecified()
+
+
+@set_module('numpy')
+class errstate(contextlib.ContextDecorator):
+ """
+ errstate(**kwargs)
+
+ Context manager for floating-point error handling.
+
+ Using an instance of `errstate` as a context manager allows statements in
+ that context to execute with a known error handling behavior. Upon entering
+ the context the error handling is set with `seterr` and `seterrcall`, and
+ upon exiting it is reset to what it was before.
+
+ .. versionchanged:: 1.17.0
+ `errstate` is also usable as a function decorator, saving
+ a level of indentation if an entire function is wrapped.
+ See :py:class:`contextlib.ContextDecorator` for more information.
+
+ Parameters
+ ----------
+ kwargs : {divide, over, under, invalid}
+ Keyword arguments. The valid keywords are the possible floating-point
+ exceptions. Each keyword should have a string value that defines the
+ treatment for the particular error. Possible values are
+ {'ignore', 'warn', 'raise', 'call', 'print', 'log'}.
+
+ See Also
+ --------
+ seterr, geterr, seterrcall, geterrcall
+
+ Notes
+ -----
+ For complete documentation of the types of floating-point exceptions and
+ treatment options, see `seterr`.
+
+ Examples
+ --------
+ >>> from collections import OrderedDict
+ >>> olderr = np.seterr(all='ignore') # Set error handling to known state.
+
+ >>> np.arange(3) / 0.
+ array([nan, inf, inf])
+ >>> with np.errstate(divide='warn'):
+ ... np.arange(3) / 0.
+ array([nan, inf, inf])
+
+ >>> np.sqrt(-1)
+ nan
+ >>> with np.errstate(invalid='raise'):
+ ... np.sqrt(-1)
+ Traceback (most recent call last):
+ File "<stdin>", line 2, in <module>
+ FloatingPointError: invalid value encountered in sqrt
+
+ Outside the context the error handling behavior has not changed:
+
+ >>> OrderedDict(sorted(np.geterr().items()))
+ OrderedDict([('divide', 'ignore'), ('invalid', 'ignore'), ('over', 'ignore'), ('under', 'ignore')])
+
+ """
+ # Note that we don't want to run the above doctests because they will fail
+ # without a from __future__ import with_statement
+
+ def __init__(self, **kwargs):
+ self.call = kwargs.pop('call', _Unspecified)
+ self.kwargs = kwargs
+
+ def __enter__(self):
+ self.oldstate = seterr(**self.kwargs)
+ if self.call is not _Unspecified:
+ self.oldcall = seterrcall(self.call)
+
+ def __exit__(self, *exc_info):
+ seterr(**self.oldstate)
+ if self.call is not _Unspecified:
+ seterrcall(self.oldcall)
+
+
+def _setdef():
+ defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None]
+ umath.seterrobj(defval)
+
+
+# set the default values
+_setdef()
diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py
index a305552ee..3e8cdf6ab 100644
--- a/numpy/core/arrayprint.py
+++ b/numpy/core/arrayprint.py
@@ -163,7 +163,8 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
- 'str_kind' : sets 'str' and 'numpystr'
floatmode : str, optional
Controls the interpretation of the `precision` option for
- floating-point types. Can take the following values:
+ floating-point types. Can take the following values
+ (default maxprec_equal):
* 'fixed': Always print exactly `precision` fractional digits,
even if this would print more or fewer digits than
@@ -201,21 +202,21 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
Floating point precision can be set:
>>> np.set_printoptions(precision=4)
- >>> print(np.array([1.123456789]))
- [ 1.1235]
+ >>> np.array([1.123456789])
+ [1.1235]
Long arrays can be summarised:
>>> np.set_printoptions(threshold=5)
- >>> print(np.arange(10))
- [0 1 2 ..., 7 8 9]
+ >>> np.arange(10)
+ array([0, 1, 2, ..., 7, 8, 9])
Small results can be suppressed:
>>> eps = np.finfo(float).eps
>>> x = np.arange(4.)
>>> x**2 - (x + eps)**2
- array([ -4.9304e-32, -4.4409e-16, 0.0000e+00, 0.0000e+00])
+ array([-4.9304e-32, -4.4409e-16, 0.0000e+00, 0.0000e+00])
>>> np.set_printoptions(suppress=True)
>>> x**2 - (x + eps)**2
array([-0., -0., 0., 0.])
@@ -299,9 +300,10 @@ def printoptions(*args, **kwargs):
Examples
--------
+ >>> from numpy.testing import assert_equal
>>> with np.printoptions(precision=2):
- ... print(np.array([2.0])) / 3
- [0.67]
+ ... np.array([2.0]) / 3
+ array([0.67])
The `as`-clause of the `with`-statement gives the current print options:
@@ -529,14 +531,17 @@ def array2string(a, max_line_width=None, precision=None,
a : array_like
Input array.
max_line_width : int, optional
- The maximum number of columns the string should span. Newline
- characters splits the string appropriately after array elements.
+ Inserts newlines if text is longer than `max_line_width`.
+ Defaults to ``numpy.get_printoptions()['linewidth']``.
precision : int or None, optional
- Floating point precision. Default is the current printing
- precision (usually 8), which can be altered using `set_printoptions`.
+ Floating point precision.
+ Defaults to ``numpy.get_printoptions()['precision']``.
suppress_small : bool, optional
- Represent very small numbers as zero. A number is "very small" if it
- is smaller than the current printing precision.
+ Represent numbers "very close" to zero as zero; default is False.
+ Very close is defined by precision: if the precision is 8, e.g.,
+ numbers smaller (in absolute value) than 5e-9 are represented as
+ zero.
+ Defaults to ``numpy.get_printoptions()['suppress']``.
separator : str, optional
Inserted between elements.
prefix : str, optional
@@ -583,17 +588,22 @@ def array2string(a, max_line_width=None, precision=None,
threshold : int, optional
Total number of array elements which trigger summarization
rather than full repr.
+ Defaults to ``numpy.get_printoptions()['threshold']``.
edgeitems : int, optional
Number of array items in summary at beginning and end of
each dimension.
+ Defaults to ``numpy.get_printoptions()['edgeitems']``.
sign : string, either '-', '+', or ' ', optional
Controls printing of the sign of floating-point types. If '+', always
print the sign of positive values. If ' ', always prints a space
(whitespace character) in the sign position of positive values. If
'-', omit the sign character of positive values.
+ Defaults to ``numpy.get_printoptions()['sign']``.
floatmode : str, optional
Controls the interpretation of the `precision` option for
- floating-point types. Can take the following values:
+ floating-point types.
+ Defaults to ``numpy.get_printoptions()['floatmode']``.
+ Can take the following values:
- 'fixed': Always print exactly `precision` fractional digits,
even if this would print more or fewer digits than
@@ -644,9 +654,9 @@ def array2string(a, max_line_width=None, precision=None,
Examples
--------
>>> x = np.array([1e-16,1,2,3])
- >>> print(np.array2string(x, precision=2, separator=',',
- ... suppress_small=True))
- [ 0., 1., 2., 3.]
+ >>> np.array2string(x, precision=2, separator=',',
+ ... suppress_small=True)
+ '[0.,1.,2.,3.]'
>>> x = np.arange(3.)
>>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x})
@@ -654,7 +664,7 @@ def array2string(a, max_line_width=None, precision=None,
>>> x = np.arange(3)
>>> np.array2string(x, formatter={'int':lambda x: hex(x)})
- '[0x0L 0x1L 0x2L]'
+ '[0x0 0x1 0x2]'
"""
legacy = kwarg.pop('legacy', None)
@@ -672,7 +682,7 @@ def array2string(a, max_line_width=None, precision=None,
if style is np._NoValue:
style = repr
- if a.shape == () and a.dtype.names is None:
+ if a.shape == () and not a.dtype.names:
return style(a.item())
elif style is not np._NoValue:
# Deprecation 11-9-2017 v1.14
@@ -1357,7 +1367,7 @@ def dtype_is_implied(dtype):
>>> np.core.arrayprint.dtype_is_implied(np.int8)
False
>>> np.array([1, 2, 3], np.int8)
- array([1, 2, 3], dtype=np.int8)
+ array([1, 2, 3], dtype=int8)
"""
dtype = np.dtype(dtype)
if _format_options['legacy'] == '1.13' and dtype.type == bool_:
@@ -1377,6 +1387,7 @@ def dtype_short_repr(dtype):
The intent is roughly that the following holds
>>> from numpy import *
+ >>> dt = np.int64([1, 2]).dtype
>>> assert eval(dtype_short_repr(dt)) == dt
"""
if dtype.names is not None:
@@ -1456,15 +1467,17 @@ def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
arr : ndarray
Input array.
max_line_width : int, optional
- The maximum number of columns the string should span. Newline
- characters split the string appropriately after array elements.
+ Inserts newlines if text is longer than `max_line_width`.
+ Defaults to ``numpy.get_printoptions()['linewidth']``.
precision : int, optional
- Floating point precision. Default is the current printing precision
- (usually 8), which can be altered using `set_printoptions`.
+ Floating point precision.
+ Defaults to ``numpy.get_printoptions()['precision']``.
suppress_small : bool, optional
- Represent very small numbers as zero, default is False. Very small
- is defined by `precision`, if the precision is 8 then
- numbers smaller than 5e-9 are represented as zero.
+ Represent numbers "very close" to zero as zero; default is False.
+ Very close is defined by precision: if the precision is 8, e.g.,
+ numbers smaller (in absolute value) than 5e-9 are represented as
+ zero.
+ Defaults to ``numpy.get_printoptions()['suppress']``.
Returns
-------
@@ -1480,13 +1493,13 @@ def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
>>> np.array_repr(np.array([1,2]))
'array([1, 2])'
>>> np.array_repr(np.ma.array([0.]))
- 'MaskedArray([ 0.])'
+ 'MaskedArray([0.])'
>>> np.array_repr(np.array([], np.int32))
'array([], dtype=int32)'
>>> x = np.array([1e-6, 4e-7, 2, 3])
>>> np.array_repr(x, precision=6, suppress_small=True)
- 'array([ 0.000001, 0. , 2. , 3. ])'
+ 'array([0.000001, 0. , 2. , 3. ])'
"""
return _array_repr_implementation(
@@ -1535,16 +1548,17 @@ def array_str(a, max_line_width=None, precision=None, suppress_small=None):
a : ndarray
Input array.
max_line_width : int, optional
- Inserts newlines if text is longer than `max_line_width`. The
- default is, indirectly, 75.
+ Inserts newlines if text is longer than `max_line_width`.
+ Defaults to ``numpy.get_printoptions()['linewidth']``.
precision : int, optional
- Floating point precision. Default is the current printing precision
- (usually 8), which can be altered using `set_printoptions`.
+ Floating point precision.
+ Defaults to ``numpy.get_printoptions()['precision']``.
suppress_small : bool, optional
Represent numbers "very close" to zero as zero; default is False.
Very close is defined by precision: if the precision is 8, e.g.,
numbers smaller (in absolute value) than 5e-9 are represented as
zero.
+ Defaults to ``numpy.get_printoptions()['suppress']``.
See Also
--------
@@ -1597,8 +1611,8 @@ def set_string_function(f, repr=True):
>>> a = np.arange(10)
>>> a
HA! - What are you going to do now?
- >>> print(a)
- [0 1 2 3 4 5 6 7 8 9]
+ >>> _ = a
+ >>> # [0 1 2 3 4 5 6 7 8 9]
We can reset the function to the default:
@@ -1616,7 +1630,7 @@ def set_string_function(f, repr=True):
>>> x.__str__()
'random'
>>> x.__repr__()
- 'array([ 0, 1, 2, 3])'
+ 'array([0, 1, 2, 3])'
"""
if f is None:
diff --git a/numpy/core/code_generators/genapi.py b/numpy/core/code_generators/genapi.py
index 4aca2373c..923c34425 100644
--- a/numpy/core/code_generators/genapi.py
+++ b/numpy/core/code_generators/genapi.py
@@ -483,14 +483,11 @@ def get_versions_hash():
d = []
file = os.path.join(os.path.dirname(__file__), 'cversions.txt')
- fid = open(file, 'r')
- try:
+ with open(file, 'r') as fid:
for line in fid:
m = VERRE.match(line)
if m:
d.append((int(m.group(1), 16), m.group(2)))
- finally:
- fid.close()
return dict(d)
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py
index daf5949d0..bf1747272 100644
--- a/numpy/core/code_generators/generate_umath.py
+++ b/numpy/core/code_generators/generate_umath.py
@@ -74,8 +74,16 @@ class TypeDescription(object):
assert len(self.out) == nout
self.astype = self.astype_dict.get(self.type, None)
-_fdata_map = dict(e='npy_%sf', f='npy_%sf', d='npy_%s', g='npy_%sl',
- F='nc_%sf', D='nc_%s', G='nc_%sl')
+_fdata_map = dict(
+ e='npy_%sf',
+ f='npy_%sf',
+ d='npy_%s',
+ g='npy_%sl',
+ F='nc_%sf',
+ D='nc_%s',
+ G='nc_%sl'
+)
+
def build_func_data(types, f):
func_data = [_fdata_map.get(t, '%s') % (f,) for t in types]
return func_data
@@ -191,31 +199,32 @@ def english_upper(s):
# output specification (optional)
# ]
-chartoname = {'?': 'bool',
- 'b': 'byte',
- 'B': 'ubyte',
- 'h': 'short',
- 'H': 'ushort',
- 'i': 'int',
- 'I': 'uint',
- 'l': 'long',
- 'L': 'ulong',
- 'q': 'longlong',
- 'Q': 'ulonglong',
- 'e': 'half',
- 'f': 'float',
- 'd': 'double',
- 'g': 'longdouble',
- 'F': 'cfloat',
- 'D': 'cdouble',
- 'G': 'clongdouble',
- 'M': 'datetime',
- 'm': 'timedelta',
- 'O': 'OBJECT',
- # '.' is like 'O', but calls a method of the object instead
- # of a function
- 'P': 'OBJECT',
- }
+chartoname = {
+ '?': 'bool',
+ 'b': 'byte',
+ 'B': 'ubyte',
+ 'h': 'short',
+ 'H': 'ushort',
+ 'i': 'int',
+ 'I': 'uint',
+ 'l': 'long',
+ 'L': 'ulong',
+ 'q': 'longlong',
+ 'Q': 'ulonglong',
+ 'e': 'half',
+ 'f': 'float',
+ 'd': 'double',
+ 'g': 'longdouble',
+ 'F': 'cfloat',
+ 'D': 'cdouble',
+ 'G': 'clongdouble',
+ 'M': 'datetime',
+ 'm': 'timedelta',
+ 'O': 'OBJECT',
+ # '.' is like 'O', but calls a method of the object instead
+ # of a function
+ 'P': 'OBJECT',
+}
all = '?bBhHiIlLqQefdgFDGOMm'
O = 'O'
@@ -407,7 +416,7 @@ defdict = {
'positive':
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.positive'),
- 'PyUFunc_SimpleUnaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(ints+flts+timedeltaonly),
TD(cmplx, f='pos'),
TD(O, f='PyNumber_Positive'),
@@ -415,7 +424,7 @@ defdict = {
'sign':
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.sign'),
- 'PyUFunc_SimpleUnaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(nobool_or_datetime),
),
'greater':
@@ -491,28 +500,35 @@ defdict = {
'maximum':
Ufunc(2, 1, ReorderableNone,
docstrings.get('numpy.core.umath.maximum'),
- 'PyUFunc_SimpleBinaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(noobj),
TD(O, f='npy_ObjectMax')
),
'minimum':
Ufunc(2, 1, ReorderableNone,
docstrings.get('numpy.core.umath.minimum'),
- 'PyUFunc_SimpleBinaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(noobj),
TD(O, f='npy_ObjectMin')
),
+'clip':
+ Ufunc(3, 1, ReorderableNone,
+ docstrings.get('numpy.core.umath.clip'),
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
+ TD(noobj),
+ [TypeDescription('O', 'npy_ObjectClip', 'OOO', 'O')]
+ ),
'fmax':
Ufunc(2, 1, ReorderableNone,
docstrings.get('numpy.core.umath.fmax'),
- 'PyUFunc_SimpleBinaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(noobj),
TD(O, f='npy_ObjectMax')
),
'fmin':
Ufunc(2, 1, ReorderableNone,
docstrings.get('numpy.core.umath.fmin'),
- 'PyUFunc_SimpleBinaryOperationTypeResolver',
+ 'PyUFunc_SimpleUniformOperationTypeResolver',
TD(noobj),
TD(O, f='npy_ObjectMin')
),
@@ -688,6 +704,8 @@ defdict = {
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.exp'),
None,
+ TD('e', f='exp', astype={'e':'f'}),
+ TD('f', simd=[('avx2', 'f'), ('avx512f', 'f')]),
TD(inexact, f='exp', astype={'e':'f'}),
TD(P, f='exp'),
),
@@ -709,6 +727,8 @@ defdict = {
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.log'),
None,
+ TD('e', f='log', astype={'e':'f'}),
+ TD('f', simd=[('avx2', 'f'), ('avx512f', 'f')]),
TD(inexact, f='log', astype={'e':'f'}),
TD(P, f='log'),
),
@@ -754,14 +774,14 @@ defdict = {
docstrings.get('numpy.core.umath.ceil'),
None,
TD(flts, f='ceil', astype={'e':'f'}),
- TD(P, f='ceil'),
+ TD(O, f='npy_ObjectCeil'),
),
'trunc':
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.trunc'),
None,
TD(flts, f='trunc', astype={'e':'f'}),
- TD(P, f='trunc'),
+ TD(O, f='npy_ObjectTrunc'),
),
'fabs':
Ufunc(1, 1, None,
@@ -775,7 +795,7 @@ defdict = {
docstrings.get('numpy.core.umath.floor'),
None,
TD(flts, f='floor', astype={'e':'f'}),
- TD(P, f='floor'),
+ TD(O, f='npy_ObjectFloor'),
),
'rint':
Ufunc(1, 1, None,
@@ -818,7 +838,7 @@ defdict = {
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.isnan'),
None,
- TD(inexact, out='?'),
+ TD(nodatetime_or_obj, out='?'),
),
'isnat':
Ufunc(1, 1, None,
@@ -830,13 +850,13 @@ defdict = {
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.isinf'),
None,
- TD(inexact, out='?'),
+ TD(nodatetime_or_obj, out='?'),
),
'isfinite':
Ufunc(1, 1, None,
docstrings.get('numpy.core.umath.isfinite'),
- None,
- TD(inexact, out='?'),
+ 'PyUFunc_IsFiniteTypeResolver',
+ TD(noobj, out='?'),
),
'signbit':
Ufunc(1, 1, None,
@@ -895,21 +915,21 @@ defdict = {
'gcd' :
Ufunc(2, 1, Zero,
docstrings.get('numpy.core.umath.gcd'),
- "PyUFunc_SimpleBinaryOperationTypeResolver",
+ "PyUFunc_SimpleUniformOperationTypeResolver",
TD(ints),
TD('O', f='npy_ObjectGCD'),
),
'lcm' :
Ufunc(2, 1, None,
docstrings.get('numpy.core.umath.lcm'),
- "PyUFunc_SimpleBinaryOperationTypeResolver",
+ "PyUFunc_SimpleUniformOperationTypeResolver",
TD(ints),
TD('O', f='npy_ObjectLCM'),
),
'matmul' :
Ufunc(2, 1, None,
docstrings.get('numpy.core.umath.matmul'),
- "PyUFunc_SimpleBinaryOperationTypeResolver",
+ "PyUFunc_SimpleUniformOperationTypeResolver",
TD(notimes_or_obj),
TD(O),
signature='(n?,k),(k,m?)->(n?,m?)',
@@ -927,25 +947,35 @@ def indent(st, spaces):
indented = re.sub(r' +$', r'', indented)
return indented
-chartotype1 = {'e': 'e_e',
- 'f': 'f_f',
- 'd': 'd_d',
- 'g': 'g_g',
- 'F': 'F_F',
- 'D': 'D_D',
- 'G': 'G_G',
- 'O': 'O_O',
- 'P': 'O_O_method'}
+# maps [nin, nout][type] to a suffix
+arity_lookup = {
+ (1, 1): {
+ 'e': 'e_e',
+ 'f': 'f_f',
+ 'd': 'd_d',
+ 'g': 'g_g',
+ 'F': 'F_F',
+ 'D': 'D_D',
+ 'G': 'G_G',
+ 'O': 'O_O',
+ 'P': 'O_O_method',
+ },
+ (2, 1): {
+ 'e': 'ee_e',
+ 'f': 'ff_f',
+ 'd': 'dd_d',
+ 'g': 'gg_g',
+ 'F': 'FF_F',
+ 'D': 'DD_D',
+ 'G': 'GG_G',
+ 'O': 'OO_O',
+ 'P': 'OO_O_method',
+ },
+ (3, 1): {
+ 'O': 'OOO_O',
+ }
+}
-chartotype2 = {'e': 'ee_e',
- 'f': 'ff_f',
- 'd': 'dd_d',
- 'g': 'gg_g',
- 'F': 'FF_F',
- 'D': 'DD_D',
- 'G': 'GG_G',
- 'O': 'OO_O',
- 'P': 'OO_O_method'}
#for each name
# 1) create functions, data, and signature
# 2) fill in functions and data in InitOperators
@@ -995,11 +1025,9 @@ def make_arrays(funcdict):
))
else:
funclist.append('NULL')
- if (uf.nin, uf.nout) == (2, 1):
- thedict = chartotype2
- elif (uf.nin, uf.nout) == (1, 1):
- thedict = chartotype1
- else:
+ try:
+ thedict = arity_lookup[uf.nin, uf.nout]
+ except KeyError:
raise ValueError("Could not handle {}[{}]".format(name, t.type))
astype = ''
@@ -1122,6 +1150,7 @@ def make_code(funcdict, filename):
#include "ufunc_type_resolution.h"
#include "loops.h"
#include "matmul.h"
+ #include "clip.h"
%s
static int
@@ -1139,7 +1168,6 @@ def make_code(funcdict, filename):
if __name__ == "__main__":
filename = __file__
- fid = open('__umath_generated.c', 'w')
code = make_code(defdict, filename)
- fid.write(code)
- fid.close()
+ with open('__umath_generated.c', 'w') as fid:
+ fid.write(code)
diff --git a/numpy/core/code_generators/ufunc_docstrings.py b/numpy/core/code_generators/ufunc_docstrings.py
index 6c0555e23..fb418aadc 100644
--- a/numpy/core/code_generators/ufunc_docstrings.py
+++ b/numpy/core/code_generators/ufunc_docstrings.py
@@ -26,12 +26,19 @@ subst = {
a freshly-allocated array is returned. A tuple (possible only as a
keyword argument) must have length equal to the number of outputs.
where : array_like, optional
- Values of True indicate to calculate the ufunc at that position, values
- of False indicate to leave the value in the output alone.
+ This condition is broadcast over the input. At locations where the
+ condition is True, the `out` array will be set to the ufunc result.
+ Elsewhere, the `out` array will retain its original value.
+ Note that if an uninitialized `out` array is created via the default
+ ``out=None``, locations within it where the condition is False will
+ remain uninitialized.
**kwargs
For other keyword-only arguments, see the
:ref:`ufunc docs <ufuncs.kwargs>`.
""").strip(),
+ 'BROADCASTABLE_2': ("If ``x1.shape != x2.shape``, they must be "
+ "broadcastable to a common shape (which becomes the "
+ "shape of the output)."),
'OUT_SCALAR_1': "This is a scalar if `x` is a scalar.",
'OUT_SCALAR_2': "This is a scalar if both `x1` and `x2` are scalars.",
}
@@ -39,14 +46,20 @@ subst = {
def add_newdoc(place, name, doc):
doc = textwrap.dedent(doc).strip()
- if name[0] != '_' and name != 'matmul':
- # matmul is special, it does not use the OUT_SCALAR replacement strings
+ skip = (
+ # gufuncs do not use the OUT_SCALAR replacement strings
+ 'matmul',
+ # clip has 3 inputs, which is not handled by this
+ 'clip',
+ )
+ if name[0] != '_' and name not in skip:
if '\nx :' in doc:
assert '$OUT_SCALAR_1' in doc, "in {}".format(name)
elif '\nx2 :' in doc or '\nx1, x2 :' in doc:
assert '$OUT_SCALAR_2' in doc, "in {}".format(name)
else:
assert False, "Could not detect number of inputs in {}".format(name)
+
for k, v in subst.items():
doc = doc.replace('$' + k, v)
@@ -104,9 +117,7 @@ add_newdoc('numpy.core.umath', 'add',
Parameters
----------
x1, x2 : array_like
- The arrays to be added. If ``x1.shape != x2.shape``, they must be
- broadcastable to a common shape (which may be the shape of one or
- the other).
+ The arrays to be added. $BROADCASTABLE_2
$PARAMS
Returns
@@ -432,8 +443,7 @@ add_newdoc('numpy.core.umath', 'arctan2',
x1 : array_like, real-valued
`y`-coordinates.
x2 : array_like, real-valued
- `x`-coordinates. `x2` must be broadcastable to match the shape of
- `x1` or vice versa.
+ `x`-coordinates. $BROADCASTABLE_2
$PARAMS
Returns
@@ -556,7 +566,7 @@ add_newdoc('numpy.core.umath', 'bitwise_and',
Parameters
----------
x1, x2 : array_like
- Only integer and boolean types are handled.
+ Only integer and boolean types are handled. $BROADCASTABLE_2
$PARAMS
Returns
@@ -609,7 +619,7 @@ add_newdoc('numpy.core.umath', 'bitwise_or',
Parameters
----------
x1, x2 : array_like
- Only integer and boolean types are handled.
+ Only integer and boolean types are handled. $BROADCASTABLE_2
$PARAMS
Returns
@@ -648,8 +658,8 @@ add_newdoc('numpy.core.umath', 'bitwise_or',
array([ 6, 5, 255])
>>> np.array([2, 5, 255]) | np.array([4, 4, 4])
array([ 6, 5, 255])
- >>> np.bitwise_or(np.array([2, 5, 255, 2147483647L], dtype=np.int32),
- ... np.array([4, 4, 4, 2147483647L], dtype=np.int32))
+ >>> np.bitwise_or(np.array([2, 5, 255, 2147483647], dtype=np.int32),
+ ... np.array([4, 4, 4, 2147483647], dtype=np.int32))
array([ 6, 5, 255, 2147483647])
>>> np.bitwise_or([True, True], [False, True])
array([ True, True])
@@ -667,7 +677,7 @@ add_newdoc('numpy.core.umath', 'bitwise_xor',
Parameters
----------
x1, x2 : array_like
- Only integer and boolean types are handled.
+ Only integer and boolean types are handled. $BROADCASTABLE_2
$PARAMS
Returns
@@ -793,6 +803,13 @@ add_newdoc('numpy.core.umath', 'conjugate',
The complex conjugate of `x`, with same dtype as `y`.
$OUT_SCALAR_1
+ Notes
+ -----
+ `conj` is an alias for `conjugate`:
+
+ >>> np.conj is np.conjugate
+ True
+
Examples
--------
>>> np.conjugate(1+2j)
@@ -837,6 +854,7 @@ add_newdoc('numpy.core.umath', 'cos',
array([ 1.00000000e+00, 6.12303177e-17, -1.00000000e+00])
>>>
>>> # Example of providing the optional output parameter
+ >>> out1 = np.array([0], dtype='d')
>>> out2 = np.cos([0.1], out1)
>>> out2 is out1
True
@@ -912,7 +930,7 @@ add_newdoc('numpy.core.umath', 'degrees',
270., 300., 330.])
>>> out = np.zeros((rad.shape))
- >>> r = degrees(rad, out)
+ >>> r = np.degrees(rad, out)
>>> np.all(r == out)
True
@@ -969,7 +987,7 @@ add_newdoc('numpy.core.umath', 'heaviside',
x1 : array_like
Input values.
x2 : array_like
- The value of the function when x1 is 0.
+ The value of the function when x1 is 0. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1004,7 +1022,7 @@ add_newdoc('numpy.core.umath', 'divide',
x1 : array_like
Dividend array.
x2 : array_like
- Divisor array.
+ Divisor array. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1073,7 +1091,7 @@ add_newdoc('numpy.core.umath', 'equal',
Parameters
----------
x1, x2 : array_like
- Input arrays of the same shape.
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1312,7 +1330,7 @@ add_newdoc('numpy.core.umath', 'floor_divide',
"""
Return the largest integer smaller or equal to the division of the inputs.
It is equivalent to the Python ``//`` operator and pairs with the
- Python ``%`` (`remainder`), function so that ``b = a % b + b * (a // b)``
+ Python ``%`` (`remainder`), function so that ``a = a % b + b * (a // b)``
up to roundoff.
Parameters
@@ -1320,7 +1338,7 @@ add_newdoc('numpy.core.umath', 'floor_divide',
x1 : array_like
Numerator.
x2 : array_like
- Denominator.
+ Denominator. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1360,7 +1378,7 @@ add_newdoc('numpy.core.umath', 'fmod',
x1 : array_like
Dividend.
x2 : array_like
- Divisor.
+ Divisor. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1410,9 +1428,7 @@ add_newdoc('numpy.core.umath', 'greater',
Parameters
----------
x1, x2 : array_like
- Input arrays. If ``x1.shape != x2.shape``, they must be
- broadcastable to a common shape (which may be the shape of one or
- the other).
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1448,9 +1464,7 @@ add_newdoc('numpy.core.umath', 'greater_equal',
Parameters
----------
x1, x2 : array_like
- Input arrays. If ``x1.shape != x2.shape``, they must be
- broadcastable to a common shape (which may be the shape of one or
- the other).
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1483,7 +1497,7 @@ add_newdoc('numpy.core.umath', 'hypot',
Parameters
----------
x1, x2 : array_like
- Leg of the triangle(s).
+ Leg of the triangle(s). $BROADCASTABLE_2
$PARAMS
Returns
@@ -1559,33 +1573,31 @@ add_newdoc('numpy.core.umath', 'invert',
We've seen that 13 is represented by ``00001101``.
The invert or bit-wise NOT of 13 is then:
- >>> np.invert(np.array([13], dtype=uint8))
- array([242], dtype=uint8)
+ >>> x = np.invert(np.array(13, dtype=np.uint8))
+ >>> x
+ 242
>>> np.binary_repr(x, width=8)
- '00001101'
- >>> np.binary_repr(242, width=8)
'11110010'
The result depends on the bit-width:
- >>> np.invert(np.array([13], dtype=uint16))
- array([65522], dtype=uint16)
+ >>> x = np.invert(np.array(13, dtype=np.uint16))
+ >>> x
+ 65522
>>> np.binary_repr(x, width=16)
- '0000000000001101'
- >>> np.binary_repr(65522, width=16)
'1111111111110010'
When using signed integer types the result is the two's complement of
the result for the unsigned type:
- >>> np.invert(np.array([13], dtype=int8))
+ >>> np.invert(np.array([13], dtype=np.int8))
array([-14], dtype=int8)
>>> np.binary_repr(-14, width=8)
'11110010'
Booleans are accepted as well:
- >>> np.invert(array([True, False]))
+ >>> np.invert(np.array([True, False]))
array([False, True])
""")
@@ -1784,6 +1796,7 @@ add_newdoc('numpy.core.umath', 'left_shift',
Input values.
x2 : array_like of integer type
Number of zeros to append to `x1`. Has to be non-negative.
+ $BROADCASTABLE_2
$PARAMS
Returns
@@ -1819,9 +1832,7 @@ add_newdoc('numpy.core.umath', 'less',
Parameters
----------
x1, x2 : array_like
- Input arrays. If ``x1.shape != x2.shape``, they must be
- broadcastable to a common shape (which may be the shape of one or
- the other).
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1849,9 +1860,7 @@ add_newdoc('numpy.core.umath', 'less_equal',
Parameters
----------
x1, x2 : array_like
- Input arrays. If ``x1.shape != x2.shape``, they must be
- broadcastable to a common shape (which may be the shape of one or
- the other).
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -1969,7 +1978,7 @@ add_newdoc('numpy.core.umath', 'log10',
Examples
--------
>>> np.log10([1e-15, -3.])
- array([-15., NaN])
+ array([-15., nan])
""")
@@ -2035,7 +2044,7 @@ add_newdoc('numpy.core.umath', 'logaddexp',
Parameters
----------
x1, x2 : array_like
- Input values.
+ Input values. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2077,7 +2086,7 @@ add_newdoc('numpy.core.umath', 'logaddexp2',
Parameters
----------
x1, x2 : array_like
- Input values.
+ Input values. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2168,14 +2177,14 @@ add_newdoc('numpy.core.umath', 'logical_and',
Parameters
----------
x1, x2 : array_like
- Input arrays. `x1` and `x2` must be of the same shape.
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
-------
y : ndarray or bool
- Boolean result with the same shape as `x1` and `x2` of the logical
- AND operation on corresponding elements of `x1` and `x2`.
+ Boolean result of the logical OR operation applied to the elements
+ of `x1` and `x2`; the shape is determined by broadcasting.
$OUT_SCALAR_2
See Also
@@ -2238,14 +2247,14 @@ add_newdoc('numpy.core.umath', 'logical_or',
----------
x1, x2 : array_like
Logical OR is applied to the elements of `x1` and `x2`.
- They have to be of the same shape.
+ $BROADCASTABLE_2
$PARAMS
Returns
-------
y : ndarray or bool
- Boolean result with the same shape as `x1` and `x2` of the logical
- OR operation on elements of `x1` and `x2`.
+ Boolean result of the logical OR operation applied to the elements
+ of `x1` and `x2`; the shape is determined by broadcasting.
$OUT_SCALAR_2
See Also
@@ -2273,16 +2282,14 @@ add_newdoc('numpy.core.umath', 'logical_xor',
Parameters
----------
x1, x2 : array_like
- Logical XOR is applied to the elements of `x1` and `x2`. They must
- be broadcastable to the same shape.
+ Logical XOR is applied to the elements of `x1` and `x2`. $BROADCASTABLE_2
$PARAMS
Returns
-------
y : bool or ndarray of bool
Boolean result of the logical XOR operation applied to the elements
- of `x1` and `x2`; the shape is determined by whether or not
- broadcasting of one or both arrays was required.
+ of `x1` and `x2`; the shape is determined by broadcasting.
$OUT_SCALAR_2
See Also
@@ -2322,8 +2329,7 @@ add_newdoc('numpy.core.umath', 'maximum',
Parameters
----------
x1, x2 : array_like
- The arrays holding the elements to be compared. They must have
- the same shape, or shapes that can be broadcast to a single shape.
+ The arrays holding the elements to be compared. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2361,7 +2367,7 @@ add_newdoc('numpy.core.umath', 'maximum',
[ 0.5, 2. ]])
>>> np.maximum([np.nan, 0, np.nan], [0, np.nan, np.nan])
- array([ NaN, NaN, NaN])
+ array([nan, nan, nan])
>>> np.maximum(np.Inf, 1)
inf
@@ -2381,8 +2387,7 @@ add_newdoc('numpy.core.umath', 'minimum',
Parameters
----------
x1, x2 : array_like
- The arrays holding the elements to be compared. They must have
- the same shape, or shapes that can be broadcast to a single shape.
+ The arrays holding the elements to be compared. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2420,7 +2425,7 @@ add_newdoc('numpy.core.umath', 'minimum',
[ 0. , 1. ]])
>>> np.minimum([np.nan, 0, np.nan],[0, np.nan, np.nan])
- array([ NaN, NaN, NaN])
+ array([nan, nan, nan])
>>> np.minimum(-np.Inf, 1)
-inf
@@ -2440,8 +2445,7 @@ add_newdoc('numpy.core.umath', 'fmax',
Parameters
----------
x1, x2 : array_like
- The arrays holding the elements to be compared. They must have
- the same shape.
+ The arrays holding the elements to be compared. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2480,7 +2484,7 @@ add_newdoc('numpy.core.umath', 'fmax',
[ 0.5, 2. ]])
>>> np.fmax([np.nan, 0, np.nan],[0, np.nan, np.nan])
- array([ 0., 0., NaN])
+ array([ 0., 0., nan])
""")
@@ -2498,8 +2502,7 @@ add_newdoc('numpy.core.umath', 'fmin',
Parameters
----------
x1, x2 : array_like
- The arrays holding the elements to be compared. They must have
- the same shape.
+ The arrays holding the elements to be compared. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2538,8 +2541,48 @@ add_newdoc('numpy.core.umath', 'fmin',
[ 0. , 1. ]])
>>> np.fmin([np.nan, 0, np.nan],[0, np.nan, np.nan])
- array([ 0., 0., NaN])
+ array([ 0., 0., nan])
+
+ """)
+
+add_newdoc('numpy.core.umath', 'clip',
+ """
+ Clip (limit) the values in an array.
+ Given an interval, values outside the interval are clipped to
+ the interval edges. For example, if an interval of ``[0, 1]``
+ is specified, values smaller than 0 become 0, and values larger
+ than 1 become 1.
+
+ Equivalent to but faster than ``np.minimum(np.maximum(a, a_min), a_max)``.
+
+ Parameters
+ ----------
+ a : array_like
+ Array containing elements to clip.
+ a_min : array_like
+ Minimum value.
+ a_max : array_like
+ Maximum value.
+ out : ndarray, optional
+ The results will be placed in this array. It may be the input
+ array for in-place clipping. `out` must be of the right shape
+ to hold the output. Its type is preserved.
+ $PARAMS
+
+ See Also
+ --------
+ numpy.clip :
+ Wrapper that makes the ``a_min`` and ``a_max`` arguments optional,
+ dispatching to one of `~numpy.core.umath.clip`,
+ `~numpy.core.umath.minimum`, and `~numpy.core.umath.maximum`.
+
+ Returns
+ -------
+ clipped_array : ndarray
+ An array with the elements of `a`, but where values
+ < `a_min` are replaced with `a_min`, and those > `a_max`
+ with `a_max`.
""")
add_newdoc('numpy.core.umath', 'matmul',
@@ -2558,8 +2601,8 @@ add_newdoc('numpy.core.umath', 'matmul',
For other keyword-only arguments, see the
:ref:`ufunc docs <ufuncs.kwargs>`.
- ..versionadded:: 1.16
- Now handles ufunc kwargs
+ .. versionadded:: 1.16
+ Now handles ufunc kwargs
Returns
-------
@@ -2622,7 +2665,7 @@ add_newdoc('numpy.core.umath', 'matmul',
>>> a = np.array([[1, 0],
... [0, 1]])
>>> b = np.array([[4, 1],
- ... [2, 2]]
+ ... [2, 2]])
>>> np.matmul(a, b)
array([[4, 1],
[2, 2]])
@@ -2630,7 +2673,7 @@ add_newdoc('numpy.core.umath', 'matmul',
For 2-D mixed with 1-D, the result is the usual.
>>> a = np.array([[1, 0],
- ... [0, 1]]
+ ... [0, 1]])
>>> b = np.array([1, 2])
>>> np.matmul(a, b)
array([1, 2])
@@ -2712,7 +2755,7 @@ add_newdoc('numpy.core.umath', 'multiply',
Parameters
----------
x1, x2 : array_like
- Input arrays to be multiplied.
+ Input arrays to be multiplied. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2793,7 +2836,7 @@ add_newdoc('numpy.core.umath', 'not_equal',
Parameters
----------
x1, x2 : array_like
- Input arrays.
+ Input arrays. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2842,7 +2885,7 @@ add_newdoc('numpy.core.umath', 'power',
x1 : array_like
The bases.
x2 : array_like
- The exponents.
+ The exponents. $BROADCASTABLE_2
$PARAMS
Returns
@@ -2901,7 +2944,7 @@ add_newdoc('numpy.core.umath', 'float_power',
x1 : array_like
The bases.
x2 : array_like
- The exponents.
+ The exponents. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3073,7 +3116,7 @@ add_newdoc('numpy.core.umath', 'remainder',
x1 : array_like
Dividend array.
x2 : array_like
- Divisor array.
+ Divisor array. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3093,6 +3136,7 @@ add_newdoc('numpy.core.umath', 'remainder',
-----
Returns 0 when `x2` is 0 and both `x1` and `x2` are (arrays of)
integers.
+ ``mod`` is an alias of ``remainder``.
Examples
--------
@@ -3118,7 +3162,7 @@ add_newdoc('numpy.core.umath', 'divmod',
x1 : array_like
Dividend array.
x2 : array_like
- Divisor array.
+ Divisor array. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3157,7 +3201,7 @@ add_newdoc('numpy.core.umath', 'right_shift',
x1 : array_like, int
Input values.
x2 : array_like, int
- Number of bits to remove at the right of `x1`.
+ Number of bits to remove at the right of `x1`. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3284,16 +3328,14 @@ add_newdoc('numpy.core.umath', 'copysign',
"""
Change the sign of x1 to that of x2, element-wise.
- If both arguments are arrays or sequences, they have to be of the same
- length. If `x2` is a scalar, its sign will be copied to all elements of
- `x1`.
+ If `x2` is a scalar, its sign will be copied to all elements of `x1`.
Parameters
----------
x1 : array_like
Values to change the sign of.
x2 : array_like
- The sign of `x2` is copied to `x1`.
+ The sign of `x2` is copied to `x1`. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3328,6 +3370,7 @@ add_newdoc('numpy.core.umath', 'nextafter',
Values to find the next representable value of.
x2 : array_like
The direction where to look for the next representable value of `x1`.
+ $BROADCASTABLE_2
$PARAMS
Returns
@@ -3476,6 +3519,7 @@ add_newdoc('numpy.core.umath', 'sinh',
>>> # Discrepancy due to vagaries of floating point arithmetic.
>>> # Example of providing the optional output parameter
+ >>> out1 = np.array([0], dtype='d')
>>> out2 = np.sinh([0.1], out1)
>>> out2 is out1
True
@@ -3529,8 +3573,8 @@ add_newdoc('numpy.core.umath', 'sqrt',
>>> np.sqrt([4, -1, -3+4J])
array([ 2.+0.j, 0.+1.j, 1.+2.j])
- >>> np.sqrt([4, -1, numpy.inf])
- array([ 2., NaN, Inf])
+ >>> np.sqrt([4, -1, np.inf])
+ array([ 2., nan, inf])
""")
@@ -3598,7 +3642,7 @@ add_newdoc('numpy.core.umath', 'subtract',
Parameters
----------
x1, x2 : array_like
- The arrays to be subtracted from each other.
+ The arrays to be subtracted from each other. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3661,6 +3705,7 @@ add_newdoc('numpy.core.umath', 'tan',
>>>
>>> # Example of providing the optional output parameter illustrating
>>> # that what is returned is a reference to said parameter
+ >>> out1 = np.array([0], dtype='d')
>>> out2 = np.cos([0.1], out1)
>>> out2 is out1
True
@@ -3712,6 +3757,7 @@ add_newdoc('numpy.core.umath', 'tanh',
>>> # Example of providing the optional output parameter illustrating
>>> # that what is returned is a reference to said parameter
+ >>> out1 = np.array([0], dtype='d')
>>> out2 = np.tanh([0.1], out1)
>>> out2 is out1
True
@@ -3737,7 +3783,7 @@ add_newdoc('numpy.core.umath', 'true_divide',
x1 : array_like
Dividend array.
x2 : array_like
- Divisor array.
+ Divisor array. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3762,8 +3808,6 @@ add_newdoc('numpy.core.umath', 'true_divide',
>>> np.true_divide(x, 4)
array([ 0. , 0.25, 0.5 , 0.75, 1. ])
- >>> x/4
- array([0, 0, 0, 0, 1])
>>> x//4
array([0, 0, 0, 0, 1])
@@ -3836,7 +3880,7 @@ add_newdoc('numpy.core.umath', 'ldexp',
x1 : array_like
Array of multipliers.
x2 : array_like, int
- Array of twos exponents.
+ Array of twos exponents. $BROADCASTABLE_2
$PARAMS
Returns
@@ -3859,7 +3903,7 @@ add_newdoc('numpy.core.umath', 'ldexp',
Examples
--------
>>> np.ldexp(5, np.arange(4))
- array([ 5., 10., 20., 40.], dtype=float32)
+ array([ 5., 10., 20., 40.], dtype=float16)
>>> x = np.arange(6)
>>> np.ldexp(*np.frexp(x))
@@ -3874,7 +3918,7 @@ add_newdoc('numpy.core.umath', 'gcd',
Parameters
----------
x1, x2 : array_like, int
- Arrays of values
+ Arrays of values. $BROADCASTABLE_2
Returns
-------
@@ -3904,7 +3948,7 @@ add_newdoc('numpy.core.umath', 'lcm',
Parameters
----------
x1, x2 : array_like, int
- Arrays of values
+ Arrays of values. $BROADCASTABLE_2
Returns
-------
diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py
index 12ba3f02e..d7ecce1b4 100644
--- a/numpy/core/defchararray.py
+++ b/numpy/core/defchararray.py
@@ -29,7 +29,7 @@ from numpy.compat import asbytes, long
import numpy
__all__ = [
- 'chararray', 'equal', 'not_equal', 'greater_equal', 'less_equal',
+ 'equal', 'not_equal', 'greater_equal', 'less_equal',
'greater', 'less', 'str_len', 'add', 'multiply', 'mod', 'capitalize',
'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs',
'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
@@ -498,8 +498,7 @@ def count(a, sub, start=0, end=None):
--------
>>> c = np.array(['aAaAaA', ' aA ', 'abBABba'])
>>> c
- array(['aAaAaA', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', ' aA ', 'abBABba'], dtype='<U7')
>>> np.char.count(c, 'A')
array([3, 1, 1])
>>> np.char.count(c, 'aA')
@@ -552,8 +551,7 @@ def decode(a, encoding=None, errors=None):
--------
>>> c = np.array(['aAaAaA', ' aA ', 'abBABba'])
>>> c
- array(['aAaAaA', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', ' aA ', 'abBABba'], dtype='<U7')
>>> np.char.encode(c, encoding='cp037')
array(['\\x81\\xc1\\x81\\xc1\\x81\\xc1', '@@\\x81\\xc1@@',
'\\x81\\x82\\xc2\\xc1\\xc2\\x82\\x81'],
@@ -637,8 +635,7 @@ def endswith(a, suffix, start=0, end=None):
>>> s[0] = 'foo'
>>> s[1] = 'bar'
>>> s
- array(['foo', 'bar'],
- dtype='|S3')
+ array(['foo', 'bar'], dtype='<U3')
>>> np.char.endswith(s, 'ar')
array([False, True])
>>> np.char.endswith(s, 'a', start=1, end=2)
@@ -1036,11 +1033,9 @@ def lower(a):
Examples
--------
>>> c = np.array(['A1B C', '1BCA', 'BCA1']); c
- array(['A1B C', '1BCA', 'BCA1'],
- dtype='|S5')
+ array(['A1B C', '1BCA', 'BCA1'], dtype='<U5')
>>> np.char.lower(c)
- array(['a1b c', '1bca', 'bca1'],
- dtype='|S5')
+ array(['a1b c', '1bca', 'bca1'], dtype='<U5')
"""
a_arr = numpy.asarray(a)
@@ -1084,23 +1079,20 @@ def lstrip(a, chars=None):
--------
>>> c = np.array(['aAaAaA', ' aA ', 'abBABba'])
>>> c
- array(['aAaAaA', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', ' aA ', 'abBABba'], dtype='<U7')
The 'a' variable is unstripped from c[1] because whitespace leading.
>>> np.char.lstrip(c, 'a')
- array(['AaAaA', ' aA ', 'bBABba'],
- dtype='|S7')
+ array(['AaAaA', ' aA ', 'bBABba'], dtype='<U7')
>>> np.char.lstrip(c, 'A') # leaves c unchanged
- array(['aAaAaA', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', ' aA ', 'abBABba'], dtype='<U7')
>>> (np.char.lstrip(c, ' ') == np.char.lstrip(c, '')).all()
- ... # XXX: is this a regression? this line now returns False
+ ... # XXX: is this a regression? This used to return True
... # np.char.lstrip(c,'') does not modify c at all.
- True
+ False
>>> (np.char.lstrip(c, ' ') == np.char.lstrip(c, None)).all()
True
@@ -1400,10 +1392,10 @@ def rstrip(a, chars=None):
>>> c = np.array(['aAaAaA', 'abBABba'], dtype='S7'); c
array(['aAaAaA', 'abBABba'],
dtype='|S7')
- >>> np.char.rstrip(c, 'a')
+ >>> np.char.rstrip(c, b'a')
array(['aAaAaA', 'abBABb'],
dtype='|S7')
- >>> np.char.rstrip(c, 'A')
+ >>> np.char.rstrip(c, b'A')
array(['aAaAa', 'abBABba'],
dtype='|S7')
@@ -1549,17 +1541,13 @@ def strip(a, chars=None):
--------
>>> c = np.array(['aAaAaA', ' aA ', 'abBABba'])
>>> c
- array(['aAaAaA', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', ' aA ', 'abBABba'], dtype='<U7')
>>> np.char.strip(c)
- array(['aAaAaA', 'aA', 'abBABba'],
- dtype='|S7')
+ array(['aAaAaA', 'aA', 'abBABba'], dtype='<U7')
>>> np.char.strip(c, 'a') # 'a' unstripped from c[1] because whitespace leads
- array(['AaAaA', ' aA ', 'bBABb'],
- dtype='|S7')
+ array(['AaAaA', ' aA ', 'bBABb'], dtype='<U7')
>>> np.char.strip(c, 'A') # 'A' unstripped from c[1] because (unprinted) ws trails
- array(['aAaAa', ' aA ', 'abBABba'],
- dtype='|S7')
+ array(['aAaAa', ' aA ', 'abBABba'], dtype='<U7')
"""
a_arr = numpy.asarray(a)
@@ -1711,11 +1699,9 @@ def upper(a):
Examples
--------
>>> c = np.array(['a1b c', '1bca', 'bca1']); c
- array(['a1b c', '1bca', 'bca1'],
- dtype='|S5')
+ array(['a1b c', '1bca', 'bca1'], dtype='<U5')
>>> np.char.upper(c)
- array(['A1B C', '1BCA', 'BCA1'],
- dtype='|S5')
+ array(['A1B C', '1BCA', 'BCA1'], dtype='<U5')
"""
a_arr = numpy.asarray(a)
@@ -1950,18 +1936,16 @@ class chararray(ndarray):
>>> charar = np.chararray((3, 3))
>>> charar[:] = 'a'
>>> charar
- chararray([['a', 'a', 'a'],
- ['a', 'a', 'a'],
- ['a', 'a', 'a']],
- dtype='|S1')
+ chararray([[b'a', b'a', b'a'],
+ [b'a', b'a', b'a'],
+ [b'a', b'a', b'a']], dtype='|S1')
>>> charar = np.chararray(charar.shape, itemsize=5)
>>> charar[:] = 'abc'
>>> charar
- chararray([['abc', 'abc', 'abc'],
- ['abc', 'abc', 'abc'],
- ['abc', 'abc', 'abc']],
- dtype='|S5')
+ chararray([[b'abc', b'abc', b'abc'],
+ [b'abc', b'abc', b'abc'],
+ [b'abc', b'abc', b'abc']], dtype='|S5')
"""
def __new__(subtype, shape, itemsize=1, unicode=False, buffer=None,
@@ -2140,7 +2124,7 @@ class chararray(ndarray):
def __rmod__(self, other):
return NotImplemented
- def argsort(self, axis=-1, kind='quicksort', order=None):
+ def argsort(self, axis=-1, kind=None, order=None):
"""
Return the indices that sort the array lexicographically.
diff --git a/numpy/core/einsumfunc.py b/numpy/core/einsumfunc.py
index c4fc77e9e..3412c3fd5 100644
--- a/numpy/core/einsumfunc.py
+++ b/numpy/core/einsumfunc.py
@@ -41,10 +41,10 @@ def _flop_count(idx_contraction, inner, num_terms, size_dictionary):
--------
>>> _flop_count('abc', False, 1, {'a': 2, 'b':3, 'c':5})
- 90
+ 30
>>> _flop_count('abc', True, 2, {'a': 2, 'b':3, 'c':5})
- 270
+ 60
"""
@@ -171,7 +171,7 @@ def _optimal_path(input_sets, output_set, idx_dict, memory_limit):
>>> isets = [set('abd'), set('ac'), set('bdc')]
>>> oset = set()
>>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4}
- >>> _path__optimal_path(isets, oset, idx_sizes, 5000)
+ >>> _optimal_path(isets, oset, idx_sizes, 5000)
[(0, 2), (0, 1)]
"""
@@ -287,7 +287,7 @@ def _update_other_results(results, best):
Returns
-------
mod_results : list
- The list of modifed results, updated with outcome of ``best`` contraction.
+ The list of modified results, updated with outcome of ``best`` contraction.
"""
best_con = best[1]
@@ -342,7 +342,7 @@ def _greedy_path(input_sets, output_set, idx_dict, memory_limit):
>>> isets = [set('abd'), set('ac'), set('bdc')]
>>> oset = set()
>>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4}
- >>> _path__greedy_path(isets, oset, idx_sizes, 5000)
+ >>> _greedy_path(isets, oset, idx_sizes, 5000)
[(0, 2), (0, 1)]
"""
@@ -539,13 +539,14 @@ def _parse_einsum_input(operands):
--------
The operand list is simplified to reduce printing:
+ >>> np.random.seed(123)
>>> a = np.random.rand(4, 4)
>>> b = np.random.rand(4, 4, 4)
- >>> __parse_einsum_input(('...a,...a->...', a, b))
- ('za,xza', 'xz', [a, b])
+ >>> _parse_einsum_input(('...a,...a->...', a, b))
+ ('za,xza', 'xz', [a, b]) # may vary
- >>> __parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0]))
- ('za,xza', 'xz', [a, b])
+ >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0]))
+ ('za,xza', 'xz', [a, b]) # may vary
"""
if len(operands) == 0:
@@ -763,6 +764,7 @@ def einsum_path(*operands, **kwargs):
of the contraction and the remaining contraction ``(0, 1)`` is then
completed.
+ >>> np.random.seed(123)
>>> a = np.random.rand(2, 2)
>>> b = np.random.rand(2, 5)
>>> c = np.random.rand(5, 2)
@@ -770,7 +772,7 @@ def einsum_path(*operands, **kwargs):
>>> print(path_info[0])
['einsum_path', (1, 2), (0, 1)]
>>> print(path_info[1])
- Complete contraction: ij,jk,kl->il
+ Complete contraction: ij,jk,kl->il # may vary
Naive scaling: 4
Optimized scaling: 3
Naive FLOP count: 1.600e+02
@@ -789,12 +791,12 @@ def einsum_path(*operands, **kwargs):
>>> I = np.random.rand(10, 10, 10, 10)
>>> C = np.random.rand(10, 10)
>>> path_info = np.einsum_path('ea,fb,abcd,gc,hd->efgh', C, C, I, C, C,
- optimize='greedy')
+ ... optimize='greedy')
>>> print(path_info[0])
['einsum_path', (0, 2), (0, 3), (0, 2), (0, 1)]
- >>> print(path_info[1])
- Complete contraction: ea,fb,abcd,gc,hd->efgh
+ >>> print(path_info[1])
+ Complete contraction: ea,fb,abcd,gc,hd->efgh # may vary
Naive scaling: 8
Optimized scaling: 5
Naive FLOP count: 8.000e+08
@@ -1274,32 +1276,32 @@ def einsum(*operands, **kwargs):
>>> a = np.arange(60.).reshape(3,4,5)
>>> b = np.arange(24.).reshape(4,3,2)
>>> np.einsum('ijk,jil->kl', a, b)
- array([[ 4400., 4730.],
- [ 4532., 4874.],
- [ 4664., 5018.],
- [ 4796., 5162.],
- [ 4928., 5306.]])
+ array([[4400., 4730.],
+ [4532., 4874.],
+ [4664., 5018.],
+ [4796., 5162.],
+ [4928., 5306.]])
>>> np.einsum(a, [0,1,2], b, [1,0,3], [2,3])
- array([[ 4400., 4730.],
- [ 4532., 4874.],
- [ 4664., 5018.],
- [ 4796., 5162.],
- [ 4928., 5306.]])
+ array([[4400., 4730.],
+ [4532., 4874.],
+ [4664., 5018.],
+ [4796., 5162.],
+ [4928., 5306.]])
>>> np.tensordot(a,b, axes=([1,0],[0,1]))
- array([[ 4400., 4730.],
- [ 4532., 4874.],
- [ 4664., 5018.],
- [ 4796., 5162.],
- [ 4928., 5306.]])
+ array([[4400., 4730.],
+ [4532., 4874.],
+ [4664., 5018.],
+ [4796., 5162.],
+ [4928., 5306.]])
Writeable returned arrays (since version 1.10.0):
>>> a = np.zeros((3, 3))
>>> np.einsum('ii->i', a)[:] = 1
>>> a
- array([[ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]])
+ array([[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]])
Example of ellipsis use:
@@ -1322,19 +1324,27 @@ def einsum(*operands, **kwargs):
particularly significant with larger arrays:
>>> a = np.ones(64).reshape(2,4,8)
- # Basic `einsum`: ~1520ms (benchmarked on 3.1GHz Intel i5.)
+
+ Basic `einsum`: ~1520ms (benchmarked on 3.1GHz Intel i5.)
+
>>> for iteration in range(500):
- ... np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a)
- # Sub-optimal `einsum` (due to repeated path calculation time): ~330ms
+ ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a)
+
+ Sub-optimal `einsum` (due to repeated path calculation time): ~330ms
+
>>> for iteration in range(500):
- ... np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='optimal')
- # Greedy `einsum` (faster optimal path approximation): ~160ms
+ ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='optimal')
+
+ Greedy `einsum` (faster optimal path approximation): ~160ms
+
>>> for iteration in range(500):
- ... np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='greedy')
- # Optimal `einsum` (best usage pattern in some use cases): ~110ms
+ ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='greedy')
+
+ Optimal `einsum` (best usage pattern in some use cases): ~110ms
+
>>> path = np.einsum_path('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='optimal')[0]
>>> for iteration in range(500):
- ... np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize=path)
+ ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize=path)
"""
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 59a820d53..08f17aae4 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -13,7 +13,8 @@ from . import multiarray as mu
from . import overrides
from . import umath as um
from . import numerictypes as nt
-from .numeric import asarray, array, asanyarray, concatenate
+from ._asarray import asarray, array, asanyarray
+from .multiarray import concatenate
from . import _methods
_dt_ = nt.sctype2char
@@ -52,17 +53,20 @@ def _wrapit(obj, method, *args, **kwds):
def _wrapfunc(obj, method, *args, **kwds):
- try:
- return getattr(obj, method)(*args, **kwds)
-
- # An AttributeError occurs if the object does not have
- # such a method in its class.
+ bound = getattr(obj, method, None)
+ if bound is None:
+ return _wrapit(obj, method, *args, **kwds)
- # A TypeError occurs if the object does have such a method
- # in its class, but its signature is not identical to that
- # of NumPy's. This situation has occurred in the case of
- # a downstream library like 'pandas'.
- except (AttributeError, TypeError):
+ try:
+ return bound(*args, **kwds)
+ except TypeError:
+ # A TypeError occurs if the object does have such a method in its
+ # class, but its signature is not identical to that of NumPy's. This
+ # situation has occurred in the case of a downstream library like
+ # 'pandas'.
+ #
+ # Call _wrapit from within the except clause to ensure a potential
+ # exception has a traceback chain.
return _wrapit(obj, method, *args, **kwds)
@@ -127,7 +131,8 @@ def take(a, indices, axis=None, out=None, mode='raise'):
input array is used.
out : ndarray, optional (Ni..., Nj..., Nk...)
If provided, the result will be placed in this array. It should
- be of the appropriate shape and dtype.
+ be of the appropriate shape and dtype. Note that `out` is always
+ buffered if `mode='raise'`; use other modes for better performance.
mode : {'raise', 'wrap', 'clip'}, optional
Specifies how out-of-bounds indices will behave.
@@ -240,12 +245,16 @@ def reshape(a, newshape, order='C'):
you should assign the new shape to the shape attribute of the array::
>>> a = np.zeros((10, 2))
+
# A transpose makes the array non-contiguous
>>> b = a.T
+
# Taking a view makes it possible to modify the shape without modifying
# the initial object.
>>> c = b.view()
>>> c.shape = (20)
+ Traceback (most recent call last):
+ ...
AttributeError: incompatible shape for a non-contiguous array
The `order` keyword gives the index ordering both for *fetching* the values
@@ -348,7 +357,8 @@ def choose(a, choices, out=None, mode='raise'):
``choices.shape[0]``) is taken as defining the "sequence".
out : array, optional
If provided, the result will be inserted into this array. It should
- be of the appropriate shape and dtype.
+ be of the appropriate shape and dtype. Note that `out` is always
+ buffered if `mode='raise'`; use other modes for better performance.
mode : {'raise' (default), 'wrap', 'clip'}, optional
Specifies how indices outside `[0, n-1]` will be treated:
@@ -505,7 +515,8 @@ def put(a, ind, v, mode='raise'):
'clip' mode means that all indices that are too large are replaced
by the index that addresses the last element along that axis. Note
- that this disables indexing with negative numbers.
+ that this disables indexing with negative numbers. In 'raise' mode,
+ if an exception occurs the target array may still be modified.
See Also
--------
@@ -813,7 +824,7 @@ def _sort_dispatcher(a, axis=None, kind=None, order=None):
@array_function_dispatch(_sort_dispatcher)
-def sort(a, axis=-1, kind='quicksort', order=None):
+def sort(a, axis=-1, kind=None, order=None):
"""
Return a sorted copy of an array.
@@ -825,7 +836,14 @@ def sort(a, axis=-1, kind='quicksort', order=None):
Axis along which to sort. If None, the array is flattened before
sorting. The default is -1, which sorts along the last axis.
kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
- Sorting algorithm. Default is 'quicksort'.
+ Sorting algorithm. The default is 'quicksort'. Note that both 'stable'
+ and 'mergesort' use timsort or radix sort under the covers and, in general,
+ the actual implementation will vary with data type. The 'mergesort' option
+ is retained for backwards compatibility.
+
+ .. versionchanged:: 1.15.0.
+ The 'stable' option was added.
+
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
which fields to compare first, second, etc. A single field can
@@ -851,17 +869,22 @@ def sort(a, axis=-1, kind='quicksort', order=None):
The various sorting algorithms are characterized by their average speed,
worst case performance, work space size, and whether they are stable. A
stable sort keeps items with the same key in the same relative
- order. The three available algorithms have the following
+ order. The four algorithms implemented in NumPy have the following
properties:
=========== ======= ============= ============ ========
kind speed worst case work space stable
=========== ======= ============= ============ ========
'quicksort' 1 O(n^2) 0 no
- 'mergesort' 2 O(n*log(n)) ~n/2 yes
'heapsort' 3 O(n*log(n)) 0 no
+ 'mergesort' 2 O(n*log(n)) ~n/2 yes
+ 'timsort' 2 O(n*log(n)) ~n/2 yes
=========== ======= ============= ============ ========
+ .. note:: The datatype determines which of 'mergesort' or 'timsort'
+ is actually used, even if 'mergesort' is specified. User selection
+ at a finer scale is not currently available.
+
All the sort algorithms make temporary copies of the data when
sorting along any but the last axis. Consequently, sorting along
the last axis is faster and uses less space than sorting along
@@ -890,8 +913,21 @@ def sort(a, axis=-1, kind='quicksort', order=None):
worst case O(n*log(n)).
'stable' automatically choses the best stable sorting algorithm
- for the data type being sorted. It is currently mapped to
- merge sort.
+ for the data type being sorted. It, along with 'mergesort' is
+ currently mapped to timsort or radix sort depending on the
+ data type. API forward compatibility currently limits the
+ ability to select the implementation and it is hardwired for the different
+ data types.
+
+ .. versionadded:: 1.17.0
+
+ Timsort is added for better performance on already or nearly
+ sorted data. On random data timsort is almost identical to
+ mergesort. It is now used for stable sort while quicksort is still the
+ default sort if none is chosen. For details of timsort, refer to
+ `CPython listsort.txt <https://github.com/python/cpython/blob/3.7/Objects/listsort.txt>`_.
+ 'mergesort' and 'stable' are mapped to radix sort for integer data types. Radix sort is an
+ O(n) sort instead of O(n log n).
Examples
--------
@@ -940,7 +976,7 @@ def _argsort_dispatcher(a, axis=None, kind=None, order=None):
@array_function_dispatch(_argsort_dispatcher)
-def argsort(a, axis=-1, kind='quicksort', order=None):
+def argsort(a, axis=-1, kind=None, order=None):
"""
Returns the indices that would sort an array.
@@ -956,7 +992,13 @@ def argsort(a, axis=-1, kind='quicksort', order=None):
Axis along which to sort. The default is -1 (the last axis). If None,
the flattened array is used.
kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
- Sorting algorithm.
+ Sorting algorithm. The default is 'quicksort'. Note that both 'stable'
+ and 'mergesort' use timsort under the covers and, in general, the
+ actual implementation will vary with data type. The 'mergesort' option
+ is retained for backwards compatibility.
+
+ .. versionchanged:: 1.15.0.
+ The 'stable' option was added.
order : str or list of str, optional
When `a` is an array with fields defined, this argument specifies
which fields to compare first, second, etc. A single field can
@@ -967,10 +1009,10 @@ def argsort(a, axis=-1, kind='quicksort', order=None):
Returns
-------
index_array : ndarray, int
- Array of indices that sort `a` along the specified axis.
+ Array of indices that sort `a` along the specified `axis`.
If `a` is one-dimensional, ``a[index_array]`` yields a sorted `a`.
- More generally, ``np.take_along_axis(a, index_array, axis=a)`` always
- yields the sorted `a`, irrespective of dimensionality.
+ More generally, ``np.take_along_axis(a, index_array, axis=axis)``
+ always yields the sorted `a`, irrespective of dimensionality.
See Also
--------
@@ -1001,13 +1043,21 @@ def argsort(a, axis=-1, kind='quicksort', order=None):
array([[0, 3],
[2, 2]])
- >>> np.argsort(x, axis=0) # sorts along first axis (down)
+ >>> ind = np.argsort(x, axis=0) # sorts along first axis (down)
+ >>> ind
array([[0, 1],
[1, 0]])
+ >>> np.take_along_axis(x, ind, axis=0) # same as np.sort(x, axis=0)
+ array([[0, 2],
+ [2, 3]])
- >>> np.argsort(x, axis=1) # sorts along last axis (across)
+ >>> ind = np.argsort(x, axis=1) # sorts along last axis (across)
+ >>> ind
array([[0, 1],
[0, 1]])
+ >>> np.take_along_axis(x, ind, axis=1) # same as np.sort(x, axis=1)
+ array([[0, 3],
+ [2, 2]])
Indices of the sorted elements of a N-dimensional array:
@@ -1229,7 +1279,7 @@ def searchsorted(a, v, side='left', sorter=None):
As of NumPy 1.4.0 `searchsorted` works with real/complex arrays containing
`nan` values. The enhanced sort order is documented in `sort`.
- This function is a faster version of the builtin python `bisect.bisect_left`
+ This function uses the same algorithm as the builtin python `bisect.bisect_left`
(``side='left'``) and `bisect.bisect_right` (``side='right'``) functions,
which is also vectorized in the `v` argument.
@@ -1381,7 +1431,7 @@ def squeeze(a, axis=None):
try:
squeeze = a.squeeze
except AttributeError:
- return _wrapit(a, 'squeeze')
+ return _wrapit(a, 'squeeze', axis=axis)
if axis is None:
return squeeze()
else:
@@ -1448,7 +1498,7 @@ def diagonal(a, offset=0, axis1=0, axis2=1):
same type as `a` is returned unless `a` is a `matrix`, in which case
a 1-D array rather than a (2-D) `matrix` is returned in order to
maintain backward compatibility.
-
+
If ``a.ndim > 2``, then the dimensions specified by `axis1` and `axis2`
are removed, and a new axis inserted at the end corresponding to the
diagonal.
@@ -1482,9 +1532,9 @@ def diagonal(a, offset=0, axis1=0, axis2=1):
[2, 3]],
[[4, 5],
[6, 7]]])
- >>> a.diagonal(0, # Main diagonals of two arrays created by skipping
- ... 0, # across the outer(left)-most axis last and
- ... 1) # the "middle" (row) axis first.
+ >>> a.diagonal(0, # Main diagonals of two arrays created by skipping
+ ... 0, # across the outer(left)-most axis last and
+ ... 1) # the "middle" (row) axis first.
array([[0, 6],
[1, 7]])
@@ -1492,13 +1542,28 @@ def diagonal(a, offset=0, axis1=0, axis2=1):
corresponds to fixing the right-most (column) axis, and that the
diagonals are "packed" in rows.
- >>> a[:,:,0] # main diagonal is [0 6]
+ >>> a[:,:,0] # main diagonal is [0 6]
array([[0, 2],
[4, 6]])
- >>> a[:,:,1] # main diagonal is [1 7]
+ >>> a[:,:,1] # main diagonal is [1 7]
array([[1, 3],
[5, 7]])
+ The anti-diagonal can be obtained by reversing the order of elements
+ using either `numpy.flipud` or `numpy.fliplr`.
+
+ >>> a = np.arange(9).reshape(3, 3)
+ >>> a
+ array([[0, 1, 2],
+ [3, 4, 5],
+ [6, 7, 8]])
+ >>> np.fliplr(a).diagonal() # Horizontal flip
+ array([2, 4, 6])
+ >>> np.flipud(a).diagonal() # Vertical flip
+ array([6, 4, 2])
+
+ Note that the order in which the diagonal is retrieved varies depending
+ on the flip function.
"""
if isinstance(a, np.matrix):
# Make diagonal of matrix 1-D to preserve backward compatibility.
@@ -1644,21 +1709,21 @@ def ravel(a, order='C'):
It is equivalent to ``reshape(-1, order=order)``.
>>> x = np.array([[1, 2, 3], [4, 5, 6]])
- >>> print(np.ravel(x))
- [1 2 3 4 5 6]
+ >>> np.ravel(x)
+ array([1, 2, 3, 4, 5, 6])
- >>> print(x.reshape(-1))
- [1 2 3 4 5 6]
+ >>> x.reshape(-1)
+ array([1, 2, 3, 4, 5, 6])
- >>> print(np.ravel(x, order='F'))
- [1 4 2 5 3 6]
+ >>> np.ravel(x, order='F')
+ array([1, 4, 2, 5, 3, 6])
When ``order`` is 'A', it will preserve the array's 'C' or 'F' ordering:
- >>> print(np.ravel(x.T))
- [1 4 2 5 3 6]
- >>> print(np.ravel(x.T, order='A'))
- [1 2 3 4 5 6]
+ >>> np.ravel(x.T)
+ array([1, 4, 2, 5, 3, 6])
+ >>> np.ravel(x.T, order='A')
+ array([1, 2, 3, 4, 5, 6])
When ``order`` is 'K', it will preserve orderings that are neither 'C'
nor 'F', but won't reverse axes:
@@ -1699,17 +1764,17 @@ def nonzero(a):
Returns a tuple of arrays, one for each dimension of `a`,
containing the indices of the non-zero elements in that
dimension. The values in `a` are always tested and returned in
- row-major, C-style order. The corresponding non-zero
- values can be obtained with::
-
- a[nonzero(a)]
+ row-major, C-style order.
- To group the indices by element, rather than dimension, use::
+ To group the indices by element, rather than dimension, use `argwhere`,
+ which returns a row for each non-zero element.
- transpose(nonzero(a))
+ .. note::
+ When called on a zero-d array or scalar, ``nonzero(a)`` is treated
+ as ``nonzero(atleast1d(a))``.
- The result of this is always a 2-D array, with a row for
- each non-zero element.
+ ..deprecated:: 1.17.0
+ Use `atleast1d` explicitly if this behavior is deliberate.
Parameters
----------
@@ -1731,6 +1796,12 @@ def nonzero(a):
count_nonzero :
Counts the number of non-zero elements in the input array.
+ Notes
+ -----
+ While the nonzero values can be obtained with ``a[nonzero(a)]``, it is
+ recommended to use ``x[x.astype(bool)]`` or ``x[x != 0]`` instead, which
+ will correctly handle 0-d arrays.
+
Examples
--------
>>> x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])
@@ -1747,7 +1818,7 @@ def nonzero(a):
array([[0, 0],
[1, 1],
[2, 0],
- [2, 1])
+ [2, 1]])
A common use for ``nonzero`` is to find the indices of an array, where
a condition is True. Given an array `a`, the condition `a` > 3 is a
@@ -1896,12 +1967,12 @@ def compress(condition, a, axis=None, out=None):
return _wrapfunc(a, 'compress', condition, axis=axis, out=out)
-def _clip_dispatcher(a, a_min, a_max, out=None):
+def _clip_dispatcher(a, a_min, a_max, out=None, **kwargs):
return (a, a_min, a_max)
@array_function_dispatch(_clip_dispatcher)
-def clip(a, a_min, a_max, out=None):
+def clip(a, a_min, a_max, out=None, **kwargs):
"""
Clip (limit) the values in an array.
@@ -1910,6 +1981,9 @@ def clip(a, a_min, a_max, out=None):
is specified, values smaller than 0 become 0, and values larger
than 1 become 1.
+ Equivalent to but faster than ``np.maximum(a_min, np.minimum(a, a_max))``.
+ No check is performed to ensure ``a_min < a_max``.
+
Parameters
----------
a : array_like
@@ -1927,6 +2001,11 @@ def clip(a, a_min, a_max, out=None):
The results will be placed in this array. It may be the input
array for in-place clipping. `out` must be of the right shape
to hold the output. Its type is preserved.
+ **kwargs
+ For other keyword-only arguments, see the
+ :ref:`ufunc docs <ufuncs.kwargs>`.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -1955,16 +2034,17 @@ def clip(a, a_min, a_max, out=None):
array([3, 4, 2, 3, 4, 5, 6, 7, 8, 8])
"""
- return _wrapfunc(a, 'clip', a_min, a_max, out=out)
+ return _wrapfunc(a, 'clip', a_min, a_max, out=out, **kwargs)
def _sum_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None,
- initial=None):
+ initial=None, where=None):
return (a, out)
@array_function_dispatch(_sum_dispatcher)
-def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
+def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
+ initial=np._NoValue, where=np._NoValue):
"""
Sum of array elements over a given axis.
@@ -2008,6 +2088,11 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
.. versionadded:: 1.15.0
+ where : array_like of bool, optional
+ Elements to include in the sum. See `~numpy.ufunc.reduce` for details.
+
+ .. versionadded:: 1.17.0
+
Returns
-------
sum_along_axis : ndarray
@@ -2020,6 +2105,8 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
--------
ndarray.sum : Equivalent method.
+ add.reduce : Equivalent functionality of `add`.
+
cumsum : Cumulative sum of array elements.
trapz : Integration of array values using the composite trapezoidal rule.
@@ -2036,6 +2123,23 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
>>> np.sum([])
0.0
+ For floating point numbers the numerical precision of sum (and
+ ``np.add.reduce``) is in general limited by directly adding each number
+ individually to the result causing rounding errors in every step.
+ However, often numpy will use a numerically better approach (partial
+ pairwise summation) leading to improved precision in many use-cases.
+ This improved precision is always provided when no ``axis`` is given.
+ When ``axis`` is given, it will depend on which axis is summed.
+ Technically, to provide the best speed possible, the improved precision
+ is only used when the summation is along the fast axis in memory.
+ Note that the exact precision may vary depending on other parameters.
+ In contrast to NumPy, Python's ``math.fsum`` function uses a slower but
+ more precise approach to summation.
+ Especially when summing a large number of lower precision floating point
+ numbers, such as ``float32``, numerical errors can become significant.
+ In such cases it can be advisable to use `dtype="float64"` to use a higher
+ precision for the output.
+
Examples
--------
>>> np.sum([0.5, 1.5])
@@ -2048,6 +2152,8 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
array([0, 6])
>>> np.sum([[0, 1], [0, 5]], axis=1)
array([1, 5])
+ >>> np.sum([[0, 1], [np.nan, 5]], where=[False, True], axis=1)
+ array([1., 5.])
If the accumulator is too small, overflow occurs:
@@ -2064,7 +2170,7 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
warnings.warn(
"Calling np.sum(generator) is deprecated, and in the future will give a different result. "
"Use np.sum(np.fromiter(generator)) or the python sum builtin instead.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
res = _sum_(a)
if out is not None:
@@ -2073,7 +2179,7 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._No
return res
return _wrapreduction(a, np.add, 'sum', axis, dtype, out, keepdims=keepdims,
- initial=initial)
+ initial=initial, where=where)
def _any_dispatcher(a, axis=None, out=None, keepdims=None):
@@ -2150,10 +2256,10 @@ def any(a, axis=None, out=None, keepdims=np._NoValue):
>>> np.any(np.nan)
True
- >>> o=np.array([False])
+ >>> o=np.array(False)
>>> z=np.any([-1, 4, 5], out=o)
>>> z, o
- (array([ True]), array([ True]))
+ (array(True), array(True))
>>> # Check now that z is a reference to o
>>> z is o
True
@@ -2236,10 +2342,10 @@ def all(a, axis=None, out=None, keepdims=np._NoValue):
>>> np.all([1.0, np.nan])
True
- >>> o=np.array([False])
+ >>> o=np.array(False)
>>> z=np.all([-1, 4, 5], out=o)
- >>> id(z), id(o), z # doctest: +SKIP
- (28293632, 28293632, array([ True]))
+ >>> id(z), id(o), z
+ (28293632, 28293632, array(True)) # may vary
"""
return _wrapreduction(a, np.logical_and, 'all', axis, None, out, keepdims=keepdims)
@@ -2390,12 +2496,14 @@ def ptp(a, axis=None, out=None, keepdims=np._NoValue):
return _methods._ptp(a, axis=axis, out=out, **kwargs)
-def _amax_dispatcher(a, axis=None, out=None, keepdims=None, initial=None):
+def _amax_dispatcher(a, axis=None, out=None, keepdims=None, initial=None,
+ where=None):
return (a, out)
@array_function_dispatch(_amax_dispatcher)
-def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
+def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
+ where=np._NoValue):
"""
Return the maximum of an array or maximum along an axis.
@@ -2433,6 +2541,11 @@ def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
.. versionadded:: 1.15.0
+ where : array_like of bool, optional
+ Elements to compare for the maximum. See `~numpy.ufunc.reduce`
+ for details.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -2478,11 +2591,14 @@ def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
array([2, 3])
>>> np.amax(a, axis=1) # Maxima along the second axis
array([1, 3])
-
+ >>> np.amax(a, where=[False, True], initial=-1, axis=0)
+ array([-1, 3])
>>> b = np.arange(5, dtype=float)
>>> b[2] = np.NaN
>>> np.amax(b)
nan
+ >>> np.amax(b, where=~np.isnan(b), initial=-1)
+ 4.0
>>> np.nanmax(b)
4.0
@@ -2501,16 +2617,18 @@ def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
>>> max([5], default=6)
5
"""
- return _wrapreduction(a, np.maximum, 'max', axis, None, out, keepdims=keepdims,
- initial=initial)
+ return _wrapreduction(a, np.maximum, 'max', axis, None, out,
+ keepdims=keepdims, initial=initial, where=where)
-def _amin_dispatcher(a, axis=None, out=None, keepdims=None, initial=None):
+def _amin_dispatcher(a, axis=None, out=None, keepdims=None, initial=None,
+ where=None):
return (a, out)
@array_function_dispatch(_amin_dispatcher)
-def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
+def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
+ where=np._NoValue):
"""
Return the minimum of an array or minimum along an axis.
@@ -2548,6 +2666,12 @@ def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
.. versionadded:: 1.15.0
+ where : array_like of bool, optional
+ Elements to compare for the minimum. See `~numpy.ufunc.reduce`
+ for details.
+
+ .. versionadded:: 1.17.0
+
Returns
-------
amin : ndarray or scalar
@@ -2592,11 +2716,15 @@ def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
array([0, 1])
>>> np.amin(a, axis=1) # Minima along the second axis
array([0, 2])
+ >>> np.amin(a, where=[False, True], initial=10, axis=0)
+ array([10, 1])
>>> b = np.arange(5, dtype=float)
>>> b[2] = np.NaN
>>> np.amin(b)
nan
+ >>> np.amin(b, where=~np.isnan(b), initial=10)
+ 0.0
>>> np.nanmin(b)
0.0
@@ -2614,8 +2742,8 @@ def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
>>> min([6], default=5)
6
"""
- return _wrapreduction(a, np.minimum, 'min', axis, None, out, keepdims=keepdims,
- initial=initial)
+ return _wrapreduction(a, np.minimum, 'min', axis, None, out,
+ keepdims=keepdims, initial=initial, where=where)
def _alen_dispathcer(a):
@@ -2656,13 +2784,14 @@ def alen(a):
return len(array(a, ndmin=1))
-def _prod_dispatcher(
- a, axis=None, dtype=None, out=None, keepdims=None, initial=None):
+def _prod_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None,
+ initial=None, where=None):
return (a, out)
@array_function_dispatch(_prod_dispatcher)
-def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
+def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
+ initial=np._NoValue, where=np._NoValue):
"""
Return the product of array elements over a given axis.
@@ -2707,6 +2836,11 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._N
.. versionadded:: 1.15.0
+ where : array_like of bool, optional
+ Elements to include in the product. See `~numpy.ufunc.reduce` for details.
+
+ .. versionadded:: 1.17.0
+
Returns
-------
product_along_axis : ndarray, see `dtype` parameter above.
@@ -2724,8 +2858,8 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._N
raised on overflow. That means that, on a 32-bit platform:
>>> x = np.array([536870910, 536870910, 536870910, 536870910])
- >>> np.prod(x) # random
- 16
+ >>> np.prod(x)
+ 16 # may vary
The product of an empty array is the neutral element 1:
@@ -2749,6 +2883,11 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._N
>>> np.prod([[1.,2.],[3.,4.]], axis=1)
array([ 2., 12.])
+ Or select specific elements to include:
+
+ >>> np.prod([1., np.nan, 3.], where=[True, False, True])
+ 3.0
+
If the type of `x` is unsigned, then the output type is
the unsigned platform integer:
@@ -2768,8 +2907,8 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._N
>>> np.prod([1, 2], initial=5)
10
"""
- return _wrapreduction(a, np.multiply, 'prod', axis, dtype, out, keepdims=keepdims,
- initial=initial)
+ return _wrapreduction(a, np.multiply, 'prod', axis, dtype, out,
+ keepdims=keepdims, initial=initial, where=where)
def _cumprod_dispatcher(a, axis=None, dtype=None, out=None):
@@ -2993,11 +3132,11 @@ def around(a, decimals=0, out=None):
Examples
--------
>>> np.around([0.37, 1.64])
- array([ 0., 2.])
+ array([0., 2.])
>>> np.around([0.37, 1.64], decimals=1)
- array([ 0.4, 1.6])
+ array([0.4, 1.6])
>>> np.around([.5, 1.5, 2.5, 3.5, 4.5]) # rounds to nearest even value
- array([ 0., 2., 2., 4., 4.])
+ array([0., 2., 2., 4., 4.])
>>> np.around([1,2,3,11], decimals=1) # ndarray of ints is returned
array([ 1, 2, 3, 11])
>>> np.around([1,2,3,11], decimals=-1)
@@ -3085,9 +3224,9 @@ def mean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
>>> np.mean(a)
2.5
>>> np.mean(a, axis=0)
- array([ 2., 3.])
+ array([2., 3.])
>>> np.mean(a, axis=1)
- array([ 1.5, 3.5])
+ array([1.5, 3.5])
In single precision, `mean` can be inaccurate:
@@ -3100,7 +3239,7 @@ def mean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
Computing the mean in float64 is more accurate:
>>> np.mean(a, dtype=np.float64)
- 0.55000000074505806
+ 0.55000000074505806 # may vary
"""
kwargs = {}
@@ -3206,11 +3345,11 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
--------
>>> a = np.array([[1, 2], [3, 4]])
>>> np.std(a)
- 1.1180339887498949
+ 1.1180339887498949 # may vary
>>> np.std(a, axis=0)
- array([ 1., 1.])
+ array([1., 1.])
>>> np.std(a, axis=1)
- array([ 0.5, 0.5])
+ array([0.5, 0.5])
In single precision, std() can be inaccurate:
@@ -3223,7 +3362,7 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
Computing the standard deviation in float64 is more accurate:
>>> np.std(a, dtype=np.float64)
- 0.44999999925494177
+ 0.44999999925494177 # may vary
"""
kwargs = {}
@@ -3300,7 +3439,7 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
See Also
--------
- std , mean, nanmean, nanstd, nanvar
+ std, mean, nanmean, nanstd, nanvar
numpy.doc.ufuncs : Section "Output arguments"
Notes
@@ -3330,9 +3469,9 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
>>> np.var(a)
1.25
>>> np.var(a, axis=0)
- array([ 1., 1.])
+ array([1., 1.])
>>> np.var(a, axis=1)
- array([ 0.25, 0.25])
+ array([0.25, 0.25])
In single precision, var() can be inaccurate:
@@ -3345,7 +3484,7 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
Computing the variance in float64 is more accurate:
>>> np.var(a, dtype=np.float64)
- 0.20249999932944759
+ 0.20249999932944759 # may vary
>>> ((1-0.55)**2 + (0.1-0.55)**2)/2
0.2025
@@ -3455,5 +3594,5 @@ def rank(a):
warnings.warn(
"`rank` is deprecated; use the `ndim` attribute or function instead. "
"To find the rank of a matrix see `numpy.linalg.matrix_rank`.",
- VisibleDeprecationWarning, stacklevel=2)
+ VisibleDeprecationWarning, stacklevel=3)
return ndim(a)
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py
index 804452627..c1067299d 100644
--- a/numpy/core/function_base.py
+++ b/numpy/core/function_base.py
@@ -102,11 +102,11 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
Examples
--------
>>> np.linspace(2.0, 3.0, num=5)
- array([ 2. , 2.25, 2.5 , 2.75, 3. ])
+ array([2. , 2.25, 2.5 , 2.75, 3. ])
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
- array([ 2. , 2.2, 2.4, 2.6, 2.8])
+ array([2. , 2.2, 2.4, 2.6, 2.8])
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
- (array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
+ (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
Graphical illustration:
@@ -252,11 +252,11 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
Examples
--------
>>> np.logspace(2.0, 3.0, num=4)
- array([ 100. , 215.443469 , 464.15888336, 1000. ])
+ array([ 100. , 215.443469 , 464.15888336, 1000. ])
>>> np.logspace(2.0, 3.0, num=4, endpoint=False)
- array([ 100. , 177.827941 , 316.22776602, 562.34132519])
+ array([100. , 177.827941 , 316.22776602, 562.34132519])
>>> np.logspace(2.0, 3.0, num=4, base=2.0)
- array([ 4. , 5.0396842 , 6.34960421, 8. ])
+ array([4. , 5.0396842 , 6.34960421, 8. ])
Graphical illustration:
@@ -361,15 +361,15 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
Negative, decreasing, and complex inputs are allowed:
>>> np.geomspace(1000, 1, num=4)
- array([ 1000., 100., 10., 1.])
+ array([1000., 100., 10., 1.])
>>> np.geomspace(-1000, -1, num=4)
array([-1000., -100., -10., -1.])
>>> np.geomspace(1j, 1000j, num=4) # Straight line
- array([ 0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
+ array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
>>> np.geomspace(-1+0j, 1+0j, num=5) # Circle
- array([-1.00000000+0.j , -0.70710678+0.70710678j,
- 0.00000000+1.j , 0.70710678+0.70710678j,
- 1.00000000+0.j ])
+ array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j,
+ 6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j,
+ 1.00000000e+00+0.00000000e+00j])
Graphical illustration of ``endpoint`` parameter:
@@ -377,8 +377,11 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
>>> N = 10
>>> y = np.zeros(N)
>>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
>>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
>>> plt.axis([0.5, 2000, 0, 3])
+ [0.5, 2000, 0, 3]
>>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
>>> plt.show()
diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py
index 544b8b35f..31fa6b9bf 100644
--- a/numpy/core/getlimits.py
+++ b/numpy/core/getlimits.py
@@ -505,6 +505,7 @@ class iinfo(object):
if self.kind not in 'iu':
raise ValueError("Invalid integer data type %r." % (self.kind,))
+ @property
def min(self):
"""Minimum value of given dtype."""
if self.kind == 'u':
@@ -517,8 +518,7 @@ class iinfo(object):
iinfo._min_vals[self.key] = val
return val
- min = property(min)
-
+ @property
def max(self):
"""Maximum value of given dtype."""
try:
@@ -531,8 +531,6 @@ class iinfo(object):
iinfo._max_vals[self.key] = val
return val
- max = property(max)
-
def __str__(self):
"""String representation."""
fmt = (
diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h
index 95e9cb060..2cc7ced35 100644
--- a/numpy/core/include/numpy/ndarrayobject.h
+++ b/numpy/core/include/numpy/ndarrayobject.h
@@ -23,7 +23,7 @@ extern "C" {
/* C-API that requires previous API to be defined */
-#define PyArray_DescrCheck(op) PyObject_TypeCheck(op, &PyArrayDescr_Type)
+#define PyArray_DescrCheck(op) (((PyObject*)(op))->ob_type==&PyArrayDescr_Type)
#define PyArray_Check(op) PyObject_TypeCheck(op, &PyArray_Type)
#define PyArray_CheckExact(op) (((PyObject*)(op))->ob_type == &PyArray_Type)
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h
index b0b749c80..1221aeece 100644
--- a/numpy/core/include/numpy/ndarraytypes.h
+++ b/numpy/core/include/numpy/ndarraytypes.h
@@ -156,12 +156,20 @@ enum NPY_TYPECHAR {
NPY_COMPLEXLTR = 'c'
};
+/*
+ * Changing this may break Numpy API compatibility
+ * due to changing offsets in PyArray_ArrFuncs, so be
+ * careful. Here we have reused the mergesort slot for
+ * any kind of stable sort, the actual implementation will
+ * depend on the data type.
+ */
typedef enum {
NPY_QUICKSORT=0,
NPY_HEAPSORT=1,
- NPY_MERGESORT=2
+ NPY_MERGESORT=2,
+ NPY_STABLESORT=2,
} NPY_SORTKIND;
-#define NPY_NSORTS (NPY_MERGESORT + 1)
+#define NPY_NSORTS (NPY_STABLESORT + 1)
typedef enum {
@@ -950,12 +958,12 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
*/
-#define PyArray_ISCONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)
-#define PyArray_ISWRITEABLE(m) PyArray_CHKFLAGS(m, NPY_ARRAY_WRITEABLE)
-#define PyArray_ISALIGNED(m) PyArray_CHKFLAGS(m, NPY_ARRAY_ALIGNED)
+#define PyArray_ISCONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS)
+#define PyArray_ISWRITEABLE(m) PyArray_CHKFLAGS((m), NPY_ARRAY_WRITEABLE)
+#define PyArray_ISALIGNED(m) PyArray_CHKFLAGS((m), NPY_ARRAY_ALIGNED)
-#define PyArray_IS_C_CONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)
-#define PyArray_IS_F_CONTIGUOUS(m) PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS)
+#define PyArray_IS_C_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS)
+#define PyArray_IS_F_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_F_CONTIGUOUS)
/* the variable is used in some places, so always define it */
#define NPY_BEGIN_THREADS_DEF PyThreadState *_save=NULL;
@@ -965,15 +973,15 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
#define NPY_BEGIN_THREADS do {_save = PyEval_SaveThread();} while (0);
#define NPY_END_THREADS do { if (_save) \
{ PyEval_RestoreThread(_save); _save = NULL;} } while (0);
-#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) do { if (loop_size > 500) \
+#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) do { if ((loop_size) > 500) \
{ _save = PyEval_SaveThread();} } while (0);
#define NPY_BEGIN_THREADS_DESCR(dtype) \
- do {if (!(PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI))) \
+ do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \
NPY_BEGIN_THREADS;} while (0);
#define NPY_END_THREADS_DESCR(dtype) \
- do {if (!(PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI))) \
+ do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \
NPY_END_THREADS; } while (0);
#define NPY_ALLOW_C_API_DEF PyGILState_STATE __save__;
@@ -1110,7 +1118,7 @@ struct PyArrayIterObject_tag {
/* Iterator API */
-#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type)
+#define PyArrayIter_Check(op) PyObject_TypeCheck((op), &PyArrayIter_Type)
#define _PyAIT(it) ((PyArrayIterObject *)(it))
#define PyArray_ITER_RESET(it) do { \
@@ -1188,7 +1196,7 @@ struct PyArrayIterObject_tag {
#define PyArray_ITER_GOTO1D(it, ind) do { \
int __npy_i; \
- npy_intp __npy_ind = (npy_intp) (ind); \
+ npy_intp __npy_ind = (npy_intp)(ind); \
if (__npy_ind < 0) __npy_ind += _PyAIT(it)->size; \
_PyAIT(it)->index = __npy_ind; \
if (_PyAIT(it)->nd_m1 == 0) { \
diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h
index 64aaaacff..108c0a202 100644
--- a/numpy/core/include/numpy/npy_common.h
+++ b/numpy/core/include/numpy/npy_common.h
@@ -46,10 +46,20 @@
#endif
#if defined HAVE_ATTRIBUTE_TARGET_AVX2 && defined HAVE_LINK_AVX2
#define NPY_GCC_TARGET_AVX2 __attribute__((target("avx2")))
+#elif defined HAVE_ATTRIBUTE_TARGET_AVX2_WITH_INTRINSICS
+#define NPY_GCC_TARGET_AVX2 __attribute__((target("avx2")))
#else
#define NPY_GCC_TARGET_AVX2
#endif
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F && defined HAVE_LINK_AVX512F
+#define NPY_GCC_TARGET_AVX512F __attribute__((target("avx512f")))
+#elif defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS
+#define NPY_GCC_TARGET_AVX512F __attribute__((target("avx512f")))
+#else
+#define NPY_GCC_TARGET_AVX512F
+#endif
+
/*
* mark an argument (starting from 1) that must not be NULL and is not checked
* DO NOT USE IF FUNCTION CHECKS FOR NULL!! the compiler will remove the check
@@ -68,6 +78,13 @@
#define NPY_HAVE_SSE2_INTRINSICS
#endif
+#if defined HAVE_IMMINTRIN_H && defined HAVE_LINK_AVX2
+#define NPY_HAVE_AVX2_INTRINSICS
+#endif
+
+#if defined HAVE_IMMINTRIN_H && defined HAVE_LINK_AVX512F
+#define NPY_HAVE_AVX512F_INTRINSICS
+#endif
/*
* give a hint to the compiler which branch is more likely or unlikely
* to occur, e.g. rare error cases:
diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h
index 582390cdc..dfb8ff526 100644
--- a/numpy/core/include/numpy/npy_math.h
+++ b/numpy/core/include/numpy/npy_math.h
@@ -113,6 +113,38 @@ NPY_INLINE static float __npy_nzerof(void)
#define NPY_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */
#define NPY_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */
+/*
+ * Constants used in vector implementation of exp(x)
+ */
+#define NPY_RINT_CVT_MAGICf 0x1.800000p+23f
+#define NPY_CODY_WAITE_LOGE_2_HIGHf -6.93145752e-1f
+#define NPY_CODY_WAITE_LOGE_2_LOWf -1.42860677e-6f
+#define NPY_COEFF_P0_EXPf 9.999999999980870924916e-01f
+#define NPY_COEFF_P1_EXPf 7.257664613233124478488e-01f
+#define NPY_COEFF_P2_EXPf 2.473615434895520810817e-01f
+#define NPY_COEFF_P3_EXPf 5.114512081637298353406e-02f
+#define NPY_COEFF_P4_EXPf 6.757896990527504603057e-03f
+#define NPY_COEFF_P5_EXPf 5.082762527590693718096e-04f
+#define NPY_COEFF_Q0_EXPf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_EXPf -2.742335390411667452936e-01f
+#define NPY_COEFF_Q2_EXPf 2.159509375685829852307e-02f
+
+/*
+ * Constants used in vector implementation of log(x)
+ */
+#define NPY_COEFF_P0_LOGf 0.000000000000000000000e+00f
+#define NPY_COEFF_P1_LOGf 9.999999999999998702752e-01f
+#define NPY_COEFF_P2_LOGf 2.112677543073053063722e+00f
+#define NPY_COEFF_P3_LOGf 1.480000633576506585156e+00f
+#define NPY_COEFF_P4_LOGf 3.808837741388407920751e-01f
+#define NPY_COEFF_P5_LOGf 2.589979117907922693523e-02f
+#define NPY_COEFF_Q0_LOGf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_LOGf 2.612677543073109236779e+00f
+#define NPY_COEFF_Q2_LOGf 2.453006071784736363091e+00f
+#define NPY_COEFF_Q3_LOGf 9.864942958519418960339e-01f
+#define NPY_COEFF_Q4_LOGf 1.546476374983906719538e-01f
+#define NPY_COEFF_Q5_LOGf 5.875095403124574342950e-03f
+
/*
* C99 double math funcs
*/
diff --git a/numpy/core/include/numpy/random/bitgen.h b/numpy/core/include/numpy/random/bitgen.h
new file mode 100644
index 000000000..0adaaf2ee
--- /dev/null
+++ b/numpy/core/include/numpy/random/bitgen.h
@@ -0,0 +1,20 @@
+#ifndef _RANDOM_BITGEN_H
+#define _RANDOM_BITGEN_H
+
+#pragma once
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Must match the declaration in numpy/random/common.pxd */
+
+typedef struct bitgen {
+ void *state;
+ uint64_t (*next_uint64)(void *st);
+ uint32_t (*next_uint32)(void *st);
+ double (*next_double)(void *st);
+ uint64_t (*next_raw)(void *st);
+} bitgen_t;
+
+
+#endif
diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h
index 90d837a9b..15dcdf010 100644
--- a/numpy/core/include/numpy/ufuncobject.h
+++ b/numpy/core/include/numpy/ufuncobject.h
@@ -120,7 +120,11 @@ typedef struct _tagPyUFuncObject {
*/
int nin, nout, nargs;
- /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */
+ /*
+ * Identity for reduction, any of PyUFunc_One, PyUFunc_Zero
+ * PyUFunc_MinusOne, PyUFunc_None, PyUFunc_ReorderableNone,
+ * PyUFunc_IdentityValue.
+ */
int identity;
/* Array of one-dimensional core loops */
@@ -301,7 +305,7 @@ typedef struct _tagPyUFuncObject {
*/
#define PyUFunc_ReorderableNone -2
/*
- * UFunc unit is in identity_value, and the order of operations can be reordered
+ * UFunc unit is an identity_value, and the order of operations can be reordered
* This case allows reduction with multiple axes at once.
*/
#define PyUFunc_IdentityValue -3
diff --git a/numpy/core/machar.py b/numpy/core/machar.py
index 91fb4eda8..202580bdb 100644
--- a/numpy/core/machar.py
+++ b/numpy/core/machar.py
@@ -10,7 +10,7 @@ from __future__ import division, absolute_import, print_function
__all__ = ['MachAr']
from numpy.core.fromnumeric import any
-from numpy.core.numeric import errstate
+from numpy.core._ufunc_config import errstate
from numpy.core.overrides import set_module
# Need to speed this up...especially for longfloat
diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py
index 82bc4707c..062645551 100644
--- a/numpy/core/memmap.py
+++ b/numpy/core/memmap.py
@@ -135,9 +135,9 @@ class memmap(ndarray):
>>> fp = np.memmap(filename, dtype='float32', mode='w+', shape=(3,4))
>>> fp
- memmap([[ 0., 0., 0., 0.],
- [ 0., 0., 0., 0.],
- [ 0., 0., 0., 0.]], dtype=float32)
+ memmap([[0., 0., 0., 0.],
+ [0., 0., 0., 0.],
+ [0., 0., 0., 0.]], dtype=float32)
Write data to memmap array:
@@ -246,7 +246,7 @@ class memmap(ndarray):
bytes = long(offset + size*_dbytes)
- if mode == 'w+' or (mode == 'r+' and flen < bytes):
+ if mode in ('w+', 'r+') and flen < bytes:
fid.seek(bytes - 1, 0)
fid.write(b'\0')
fid.flush()
diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py
index 205d362ec..c0fcc10ff 100644
--- a/numpy/core/multiarray.py
+++ b/numpy/core/multiarray.py
@@ -9,6 +9,7 @@ by importing from the extension module.
import functools
import sys
import warnings
+import sys
from . import overrides
from . import _multiarray_umath
@@ -74,9 +75,9 @@ array_function_from_c_func_and_dispatcher = functools.partial(
@array_function_from_c_func_and_dispatcher(_multiarray_umath.empty_like)
-def empty_like(prototype, dtype=None, order=None, subok=None):
+def empty_like(prototype, dtype=None, order=None, subok=None, shape=None):
"""
- empty_like(prototype, dtype=None, order='K', subok=True)
+ empty_like(prototype, dtype=None, order='K', subok=True, shape=None)
Return a new array with the same shape and type as a given array.
@@ -100,6 +101,12 @@ def empty_like(prototype, dtype=None, order=None, subok=None):
If True, then the newly created array will use the sub-class
type of 'a', otherwise it will be a base-class array. Defaults
to True.
+ shape : int or sequence of ints, optional.
+ Overrides the shape of the result. If order='K' and the number of
+ dimensions is unchanged, will try to keep order, otherwise,
+ order='C' is implied.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -124,11 +131,11 @@ def empty_like(prototype, dtype=None, order=None, subok=None):
--------
>>> a = ([1,2,3], [4,5,6]) # a is array-like
>>> np.empty_like(a)
- array([[-1073741821, -1073741821, 3], #random
+ array([[-1073741821, -1073741821, 3], # uninitialized
[ 0, 0, -1073741821]])
>>> a = np.array([[1., 2., 3.],[4.,5.,6.]])
>>> np.empty_like(a)
- array([[ -2.00000715e+000, 1.48219694e-323, -2.00000572e+000],#random
+ array([[ -2.00000715e+000, 1.48219694e-323, -2.00000572e+000], # uninitialized
[ 4.38791518e-305, -2.00000715e+000, 4.17269252e-309]])
"""
@@ -295,8 +302,8 @@ def inner(a, b):
An example where `b` is a scalar:
>>> np.inner(np.eye(2), 7)
- array([[ 7., 0.],
- [ 0., 7.]])
+ array([[7., 0.],
+ [0., 7.]])
"""
return (a, b)
@@ -430,8 +437,8 @@ def lexsort(keys, axis=None):
>>> a = [1,5,1,4,3,4,4] # First column
>>> b = [9,4,0,4,0,2,1] # Second column
>>> ind = np.lexsort((b,a)) # Sort by a, then by b
- >>> print(ind)
- [2 0 4 6 5 3 1]
+ >>> ind
+ array([2, 0, 4, 6, 5, 3, 1])
>>> [(a[i],b[i]) for i in ind]
[(1, 0), (1, 9), (3, 0), (4, 1), (4, 2), (4, 4), (5, 4)]
@@ -1114,9 +1121,9 @@ def putmask(a, mask, values):
@array_function_from_c_func_and_dispatcher(_multiarray_umath.packbits)
-def packbits(myarray, axis=None):
+def packbits(a, axis=None, bitorder='big'):
"""
- packbits(myarray, axis=None)
+ packbits(a, axis=None, bitorder='big')
Packs the elements of a binary-valued array into bits in a uint8 array.
@@ -1124,12 +1131,19 @@ def packbits(myarray, axis=None):
Parameters
----------
- myarray : array_like
+ a : array_like
An array of integers or booleans whose elements should be packed to
bits.
axis : int, optional
The dimension over which bit-packing is done.
``None`` implies packing the flattened array.
+ bitorder : {'big', 'little'}, optional
+ The order of the input bits. 'big' will mimic bin(val),
+ ``[0, 0, 0, 0, 0, 0, 1, 1] => 3 = 0b00000011 => ``, 'little' will
+ reverse the order so ``[1, 1, 0, 0, 0, 0, 0, 0] => 3``.
+ Defaults to 'big'.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -1152,34 +1166,56 @@ def packbits(myarray, axis=None):
... [0,0,1]]])
>>> b = np.packbits(a, axis=-1)
>>> b
- array([[[160],[64]],[[192],[32]]], dtype=uint8)
+ array([[[160],
+ [ 64]],
+ [[192],
+ [ 32]]], dtype=uint8)
Note that in binary 160 = 1010 0000, 64 = 0100 0000, 192 = 1100 0000,
and 32 = 0010 0000.
"""
- return (myarray,)
+ return (a,)
@array_function_from_c_func_and_dispatcher(_multiarray_umath.unpackbits)
-def unpackbits(myarray, axis=None):
+def unpackbits(a, axis=None, count=None, bitorder='big'):
"""
- unpackbits(myarray, axis=None)
+ unpackbits(a, axis=None, count=None, bitorder='big')
Unpacks elements of a uint8 array into a binary-valued output array.
- Each element of `myarray` represents a bit-field that should be unpacked
- into a binary-valued output array. The shape of the output array is either
- 1-D (if `axis` is None) or the same shape as the input array with unpacking
- done along the axis specified.
+ Each element of `a` represents a bit-field that should be unpacked
+ into a binary-valued output array. The shape of the output array is
+ either 1-D (if `axis` is ``None``) or the same shape as the input
+ array with unpacking done along the axis specified.
Parameters
----------
- myarray : ndarray, uint8 type
+ a : ndarray, uint8 type
Input array.
axis : int, optional
The dimension over which bit-unpacking is done.
``None`` implies unpacking the flattened array.
+ count : int or None, optional
+ The number of elements to unpack along `axis`, provided as a way
+ of undoing the effect of packing a size that is not a multiple
+ of eight. A non-negative number means to only unpack `count`
+ bits. A negative number means to trim off that many bits from
+ the end. ``None`` means to unpack the entire array (the
+ default). Counts larger than the available number of bits will
+ add zero padding to the output. Negative counts must not
+ exceed the available number of bits.
+
+ .. versionadded:: 1.17.0
+
+ bitorder : {'big', 'little'}, optional
+ The order of the returned bits. 'big' will mimic bin(val),
+ ``3 = 0b00000011 => [0, 0, 0, 0, 0, 0, 1, 1]``, 'little' will reverse
+ the order to ``[1, 1, 0, 0, 0, 0, 0, 0]``.
+ Defaults to 'big'.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -1188,8 +1224,8 @@ def unpackbits(myarray, axis=None):
See Also
--------
- packbits : Packs the elements of a binary-valued array into bits in a uint8
- array.
+ packbits : Packs the elements of a binary-valued array into bits in
+ a uint8 array.
Examples
--------
@@ -1203,9 +1239,27 @@ def unpackbits(myarray, axis=None):
array([[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)
+ >>> c = np.unpackbits(a, axis=1, count=-3)
+ >>> c
+ array([[0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0],
+ [0, 0, 0, 1, 0]], dtype=uint8)
+
+ >>> p = np.packbits(b, axis=0)
+ >>> np.unpackbits(p, axis=0)
+ array([[0, 0, 0, 0, 0, 0, 1, 0],
+ [0, 0, 0, 0, 0, 1, 1, 1],
+ [0, 0, 0, 1, 0, 1, 1, 1],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
+ >>> np.array_equal(b, np.unpackbits(p, axis=0, count=b.shape[0]))
+ True
"""
- return (myarray,)
+ return (a,)
@array_function_from_c_func_and_dispatcher(_multiarray_umath.shares_memory)
@@ -1342,7 +1396,7 @@ def is_busday(dates, weekmask=None, holidays=None, busdaycal=None, out=None):
>>> # The weekdays are Friday, Saturday, and Monday
... np.is_busday(['2011-07-01', '2011-07-02', '2011-07-18'],
... holidays=['2011-07-01', '2011-07-04', '2011-07-17'])
- array([False, False, True], dtype='bool')
+ array([False, False, True])
"""
return (dates, weekmask, holidays, out)
@@ -1416,27 +1470,27 @@ def busday_offset(dates, offsets, roll=None, weekmask=None, holidays=None,
--------
>>> # First business day in October 2011 (not accounting for holidays)
... np.busday_offset('2011-10', 0, roll='forward')
- numpy.datetime64('2011-10-03','D')
+ numpy.datetime64('2011-10-03')
>>> # Last business day in February 2012 (not accounting for holidays)
... np.busday_offset('2012-03', -1, roll='forward')
- numpy.datetime64('2012-02-29','D')
+ numpy.datetime64('2012-02-29')
>>> # Third Wednesday in January 2011
... np.busday_offset('2011-01', 2, roll='forward', weekmask='Wed')
- numpy.datetime64('2011-01-19','D')
+ numpy.datetime64('2011-01-19')
>>> # 2012 Mother's Day in Canada and the U.S.
... np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun')
- numpy.datetime64('2012-05-13','D')
+ numpy.datetime64('2012-05-13')
>>> # First business day on or after a date
... np.busday_offset('2011-03-20', 0, roll='forward')
- numpy.datetime64('2011-03-21','D')
+ numpy.datetime64('2011-03-21')
>>> np.busday_offset('2011-03-22', 0, roll='forward')
- numpy.datetime64('2011-03-22','D')
+ numpy.datetime64('2011-03-22')
>>> # First business day after a date
... np.busday_offset('2011-03-20', 1, roll='backward')
- numpy.datetime64('2011-03-21','D')
+ numpy.datetime64('2011-03-21')
>>> np.busday_offset('2011-03-22', 1, roll='backward')
- numpy.datetime64('2011-03-23','D')
+ numpy.datetime64('2011-03-23')
"""
return (dates, offsets, weekmask, holidays, out)
@@ -1500,7 +1554,7 @@ def busday_count(begindates, enddates, weekmask=None, holidays=None,
... np.busday_count('2011-01', '2011-02')
21
>>> # Number of weekdays in 2011
- ... np.busday_count('2011', '2012')
+ >>> np.busday_count('2011', '2012')
260
>>> # Number of Saturdays in 2011
... np.busday_count('2011', '2012', weekmask='Sat')
@@ -1538,6 +1592,7 @@ def datetime_as_string(arr, unit=None, timezone=None, casting=None):
Examples
--------
+ >>> import pytz
>>> d = np.arange('2002-10-27T04:30', 4*60, 60, dtype='M8[m]')
>>> d
array(['2002-10-27T04:30', '2002-10-27T05:30', '2002-10-27T06:30',
@@ -1568,6 +1623,8 @@ def datetime_as_string(arr, unit=None, timezone=None, casting=None):
'casting' can be used to specify whether precision can be changed
>>> np.datetime_as_string(d, unit='h', casting='safe')
+ Traceback (most recent call last):
+ ...
TypeError: Cannot create a datetime string as units 'h' from a NumPy
datetime with units 'm' according to the rule 'safe'
"""
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index 8768cbe56..ea2ef900e 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -1,19 +1,15 @@
from __future__ import division, absolute_import, print_function
-try:
- # Accessing collections abstract classes from collections
- # has been deprecated since Python 3.3
- import collections.abc as collections_abc
-except ImportError:
- import collections as collections_abc
import functools
import itertools
import operator
import sys
import warnings
import numbers
+import contextlib
import numpy as np
+from numpy.compat import pickle, basestring
from . import multiarray
from .multiarray import (
_fastCopyAndTranspose as fastCopyAndTranspose, ALLOW_THREADS,
@@ -31,29 +27,20 @@ if sys.version_info[0] < 3:
from . import overrides
from . import umath
from .overrides import set_module
-from .umath import (multiply, invert, sin, UFUNC_BUFSIZE_DEFAULT,
- ERR_IGNORE, ERR_WARN, ERR_RAISE, ERR_CALL, ERR_PRINT,
- ERR_LOG, ERR_DEFAULT, PINF, NAN)
+from .umath import (multiply, invert, sin, PINF, NAN)
from . import numerictypes
from .numerictypes import longlong, intc, int_, float_, complex_, bool_
-from ._internal import TooHardError, AxisError
+from ._exceptions import TooHardError, AxisError
+from ._asarray import asarray, asanyarray
+from ._ufunc_config import errstate
bitwise_not = invert
ufunc = type(sin)
newaxis = None
if sys.version_info[0] >= 3:
- if sys.version_info[1] in (6, 7):
- try:
- import pickle5 as pickle
- except ImportError:
- import pickle
- else:
- import pickle
- basestring = str
import builtins
else:
- import cPickle as pickle
import __builtin__ as builtins
@@ -75,15 +62,13 @@ __all__ = [
'fromstring', 'fromfile', 'frombuffer', 'int_asbuffer', 'where',
'argwhere', 'copyto', 'concatenate', 'fastCopyAndTranspose', 'lexsort',
'set_numeric_ops', 'can_cast', 'promote_types', 'min_scalar_type',
- 'result_type', 'asarray', 'asanyarray', 'ascontiguousarray',
- 'asfortranarray', 'isfortran', 'empty_like', 'zeros_like', 'ones_like',
+ 'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like',
'correlate', 'convolve', 'inner', 'dot', 'outer', 'vdot', 'roll',
- 'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian', 'require',
+ 'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian',
'fromiter', 'array_equal', 'array_equiv', 'indices', 'fromfunction',
'isclose', 'load', 'loads', 'isscalar', 'binary_repr', 'base_repr', 'ones',
- 'identity', 'allclose', 'compare_chararrays', 'putmask', 'seterr',
- 'geterr', 'setbufsize', 'getbufsize', 'seterrcall', 'geterrcall',
- 'errstate', 'flatnonzero', 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN',
+ 'identity', 'allclose', 'compare_chararrays', 'putmask',
+ 'flatnonzero', 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN',
'False_', 'True_', 'bitwise_not', 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS',
'BUFSIZE', 'ALLOW_THREADS', 'ComplexWarning', 'full', 'full_like',
'matmul', 'shares_memory', 'may_share_memory', 'MAY_SHARE_BOUNDS',
@@ -105,12 +90,12 @@ class ComplexWarning(RuntimeWarning):
pass
-def _zeros_like_dispatcher(a, dtype=None, order=None, subok=None):
+def _zeros_like_dispatcher(a, dtype=None, order=None, subok=None, shape=None):
return (a,)
@array_function_dispatch(_zeros_like_dispatcher)
-def zeros_like(a, dtype=None, order='K', subok=True):
+def zeros_like(a, dtype=None, order='K', subok=True, shape=None):
"""
Return an array of zeros with the same shape and type as a given array.
@@ -134,6 +119,12 @@ def zeros_like(a, dtype=None, order='K', subok=True):
If True, then the newly created array will use the sub-class
type of 'a', otherwise it will be a base-class array. Defaults
to True.
+ shape : int or sequence of ints, optional.
+ Overrides the shape of the result. If order='K' and the number of
+ dimensions is unchanged, will try to keep order, otherwise,
+ order='C' is implied.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -160,12 +151,12 @@ def zeros_like(a, dtype=None, order='K', subok=True):
>>> y = np.arange(3, dtype=float)
>>> y
- array([ 0., 1., 2.])
+ array([0., 1., 2.])
>>> np.zeros_like(y)
- array([ 0., 0., 0.])
+ array([0., 0., 0.])
"""
- res = empty_like(a, dtype=dtype, order=order, subok=subok)
+ res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
# needed instead of a 0 to get same result as zeros for for string dtypes
z = zeros(1, dtype=res.dtype)
multiarray.copyto(res, z, casting='unsafe')
@@ -205,19 +196,19 @@ def ones(shape, dtype=None, order='C'):
Examples
--------
>>> np.ones(5)
- array([ 1., 1., 1., 1., 1.])
+ array([1., 1., 1., 1., 1.])
>>> np.ones((5,), dtype=int)
array([1, 1, 1, 1, 1])
>>> np.ones((2, 1))
- array([[ 1.],
- [ 1.]])
+ array([[1.],
+ [1.]])
>>> s = (2,2)
>>> np.ones(s)
- array([[ 1., 1.],
- [ 1., 1.]])
+ array([[1., 1.],
+ [1., 1.]])
"""
a = empty(shape, dtype, order)
@@ -225,12 +216,12 @@ def ones(shape, dtype=None, order='C'):
return a
-def _ones_like_dispatcher(a, dtype=None, order=None, subok=None):
+def _ones_like_dispatcher(a, dtype=None, order=None, subok=None, shape=None):
return (a,)
@array_function_dispatch(_ones_like_dispatcher)
-def ones_like(a, dtype=None, order='K', subok=True):
+def ones_like(a, dtype=None, order='K', subok=True, shape=None):
"""
Return an array of ones with the same shape and type as a given array.
@@ -254,6 +245,12 @@ def ones_like(a, dtype=None, order='K', subok=True):
If True, then the newly created array will use the sub-class
type of 'a', otherwise it will be a base-class array. Defaults
to True.
+ shape : int or sequence of ints, optional.
+ Overrides the shape of the result. If order='K' and the number of
+ dimensions is unchanged, will try to keep order, otherwise,
+ order='C' is implied.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -280,12 +277,12 @@ def ones_like(a, dtype=None, order='K', subok=True):
>>> y = np.arange(3, dtype=float)
>>> y
- array([ 0., 1., 2.])
+ array([0., 1., 2.])
>>> np.ones_like(y)
- array([ 1., 1., 1.])
+ array([1., 1., 1.])
"""
- res = empty_like(a, dtype=dtype, order=order, subok=subok)
+ res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
multiarray.copyto(res, 1, casting='unsafe')
return res
@@ -323,8 +320,8 @@ def full(shape, fill_value, dtype=None, order='C'):
Examples
--------
>>> np.full((2, 2), np.inf)
- array([[ inf, inf],
- [ inf, inf]])
+ array([[inf, inf],
+ [inf, inf]])
>>> np.full((2, 2), 10)
array([[10, 10],
[10, 10]])
@@ -337,12 +334,12 @@ def full(shape, fill_value, dtype=None, order='C'):
return a
-def _full_like_dispatcher(a, fill_value, dtype=None, order=None, subok=None):
+def _full_like_dispatcher(a, fill_value, dtype=None, order=None, subok=None, shape=None):
return (a,)
@array_function_dispatch(_full_like_dispatcher)
-def full_like(a, fill_value, dtype=None, order='K', subok=True):
+def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):
"""
Return a full array with the same shape and type as a given array.
@@ -364,6 +361,12 @@ def full_like(a, fill_value, dtype=None, order='K', subok=True):
If True, then the newly created array will use the sub-class
type of 'a', otherwise it will be a base-class array. Defaults
to True.
+ shape : int or sequence of ints, optional.
+ Overrides the shape of the result. If order='K' and the number of
+ dimensions is unchanged, will try to keep order, otherwise,
+ order='C' is implied.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -385,16 +388,16 @@ def full_like(a, fill_value, dtype=None, order='K', subok=True):
>>> np.full_like(x, 0.1)
array([0, 0, 0, 0, 0, 0])
>>> np.full_like(x, 0.1, dtype=np.double)
- array([ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
+ array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
>>> np.full_like(x, np.nan, dtype=np.double)
- array([ nan, nan, nan, nan, nan, nan])
+ array([nan, nan, nan, nan, nan, nan])
>>> y = np.arange(6, dtype=np.double)
>>> np.full_like(y, 0.1)
- array([ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
+ array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
"""
- res = empty_like(a, dtype=dtype, order=order, subok=subok)
+ res = empty_like(a, dtype=dtype, order=order, subok=subok, shape=shape)
multiarray.copyto(res, fill_value, casting='unsafe')
return res
@@ -467,315 +470,9 @@ def count_nonzero(a, axis=None):
@set_module('numpy')
-def asarray(a, dtype=None, order=None):
- """Convert the input to an array.
-
- Parameters
- ----------
- a : array_like
- Input data, in any form that can be converted to an array. This
- includes lists, lists of tuples, tuples, tuples of tuples, tuples
- of lists and ndarrays.
- dtype : data-type, optional
- By default, the data-type is inferred from the input data.
- order : {'C', 'F'}, optional
- Whether to use row-major (C-style) or
- column-major (Fortran-style) memory representation.
- Defaults to 'C'.
-
- Returns
- -------
- out : ndarray
- Array interpretation of `a`. No copy is performed if the input
- is already an ndarray with matching dtype and order. If `a` is a
- subclass of ndarray, a base class ndarray is returned.
-
- See Also
- --------
- asanyarray : Similar function which passes through subclasses.
- ascontiguousarray : Convert input to a contiguous array.
- asfarray : Convert input to a floating point ndarray.
- asfortranarray : Convert input to an ndarray with column-major
- memory order.
- asarray_chkfinite : Similar function which checks input for NaNs and Infs.
- fromiter : Create an array from an iterator.
- fromfunction : Construct an array by executing a function on grid
- positions.
-
- Examples
- --------
- Convert a list into an array:
-
- >>> a = [1, 2]
- >>> np.asarray(a)
- array([1, 2])
-
- Existing arrays are not copied:
-
- >>> a = np.array([1, 2])
- >>> np.asarray(a) is a
- True
-
- If `dtype` is set, array is copied only if dtype does not match:
-
- >>> a = np.array([1, 2], dtype=np.float32)
- >>> np.asarray(a, dtype=np.float32) is a
- True
- >>> np.asarray(a, dtype=np.float64) is a
- False
-
- Contrary to `asanyarray`, ndarray subclasses are not passed through:
-
- >>> issubclass(np.recarray, np.ndarray)
- True
- >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray)
- >>> np.asarray(a) is a
- False
- >>> np.asanyarray(a) is a
- True
-
- """
- return array(a, dtype, copy=False, order=order)
-
-
-@set_module('numpy')
-def asanyarray(a, dtype=None, order=None):
- """Convert the input to an ndarray, but pass ndarray subclasses through.
-
- Parameters
- ----------
- a : array_like
- Input data, in any form that can be converted to an array. This
- includes scalars, lists, lists of tuples, tuples, tuples of tuples,
- tuples of lists, and ndarrays.
- dtype : data-type, optional
- By default, the data-type is inferred from the input data.
- order : {'C', 'F'}, optional
- Whether to use row-major (C-style) or column-major
- (Fortran-style) memory representation. Defaults to 'C'.
-
- Returns
- -------
- out : ndarray or an ndarray subclass
- Array interpretation of `a`. If `a` is an ndarray or a subclass
- of ndarray, it is returned as-is and no copy is performed.
-
- See Also
- --------
- asarray : Similar function which always returns ndarrays.
- ascontiguousarray : Convert input to a contiguous array.
- asfarray : Convert input to a floating point ndarray.
- asfortranarray : Convert input to an ndarray with column-major
- memory order.
- asarray_chkfinite : Similar function which checks input for NaNs and
- Infs.
- fromiter : Create an array from an iterator.
- fromfunction : Construct an array by executing a function on grid
- positions.
-
- Examples
- --------
- Convert a list into an array:
-
- >>> a = [1, 2]
- >>> np.asanyarray(a)
- array([1, 2])
-
- Instances of `ndarray` subclasses are passed through as-is:
-
- >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray)
- >>> np.asanyarray(a) is a
- True
-
- """
- return array(a, dtype, copy=False, order=order, subok=True)
-
-
-@set_module('numpy')
-def ascontiguousarray(a, dtype=None):
- """
- Return a contiguous array (ndim >= 1) in memory (C order).
-
- Parameters
- ----------
- a : array_like
- Input array.
- dtype : str or dtype object, optional
- Data-type of returned array.
-
- Returns
- -------
- out : ndarray
- Contiguous array of same shape and content as `a`, with type `dtype`
- if specified.
-
- See Also
- --------
- asfortranarray : Convert input to an ndarray with column-major
- memory order.
- require : Return an ndarray that satisfies requirements.
- ndarray.flags : Information about the memory layout of the array.
-
- Examples
- --------
- >>> x = np.arange(6).reshape(2,3)
- >>> np.ascontiguousarray(x, dtype=np.float32)
- array([[ 0., 1., 2.],
- [ 3., 4., 5.]], dtype=float32)
- >>> x.flags['C_CONTIGUOUS']
- True
-
- Note: This function returns an array with at least one-dimension (1-d)
- so it will not preserve 0-d arrays.
-
- """
- return array(a, dtype, copy=False, order='C', ndmin=1)
-
-
-@set_module('numpy')
-def asfortranarray(a, dtype=None):
- """
- Return an array (ndim >= 1) laid out in Fortran order in memory.
-
- Parameters
- ----------
- a : array_like
- Input array.
- dtype : str or dtype object, optional
- By default, the data-type is inferred from the input data.
-
- Returns
- -------
- out : ndarray
- The input `a` in Fortran, or column-major, order.
-
- See Also
- --------
- ascontiguousarray : Convert input to a contiguous (C order) array.
- asanyarray : Convert input to an ndarray with either row or
- column-major memory order.
- require : Return an ndarray that satisfies requirements.
- ndarray.flags : Information about the memory layout of the array.
-
- Examples
- --------
- >>> x = np.arange(6).reshape(2,3)
- >>> y = np.asfortranarray(x)
- >>> x.flags['F_CONTIGUOUS']
- False
- >>> y.flags['F_CONTIGUOUS']
- True
-
- Note: This function returns an array with at least one-dimension (1-d)
- so it will not preserve 0-d arrays.
-
- """
- return array(a, dtype, copy=False, order='F', ndmin=1)
-
-
-@set_module('numpy')
-def require(a, dtype=None, requirements=None):
- """
- Return an ndarray of the provided type that satisfies requirements.
-
- This function is useful to be sure that an array with the correct flags
- is returned for passing to compiled code (perhaps through ctypes).
-
- Parameters
- ----------
- a : array_like
- The object to be converted to a type-and-requirement-satisfying array.
- dtype : data-type
- The required data-type. If None preserve the current dtype. If your
- application requires the data to be in native byteorder, include
- a byteorder specification as a part of the dtype specification.
- requirements : str or list of str
- The requirements list can be any of the following
-
- * 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array
- * 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array
- * 'ALIGNED' ('A') - ensure a data-type aligned array
- * 'WRITEABLE' ('W') - ensure a writable array
- * 'OWNDATA' ('O') - ensure an array that owns its own data
- * 'ENSUREARRAY', ('E') - ensure a base array, instead of a subclass
-
- See Also
- --------
- asarray : Convert input to an ndarray.
- asanyarray : Convert to an ndarray, but pass through ndarray subclasses.
- ascontiguousarray : Convert input to a contiguous array.
- asfortranarray : Convert input to an ndarray with column-major
- memory order.
- ndarray.flags : Information about the memory layout of the array.
-
- Notes
- -----
- The returned array will be guaranteed to have the listed requirements
- by making a copy if needed.
-
- Examples
- --------
- >>> x = np.arange(6).reshape(2,3)
- >>> x.flags
- C_CONTIGUOUS : True
- F_CONTIGUOUS : False
- OWNDATA : False
- WRITEABLE : True
- ALIGNED : True
- WRITEBACKIFCOPY : False
- UPDATEIFCOPY : False
-
- >>> y = np.require(x, dtype=np.float32, requirements=['A', 'O', 'W', 'F'])
- >>> y.flags
- C_CONTIGUOUS : False
- F_CONTIGUOUS : True
- OWNDATA : True
- WRITEABLE : True
- ALIGNED : True
- WRITEBACKIFCOPY : False
- UPDATEIFCOPY : False
-
- """
- possible_flags = {'C': 'C', 'C_CONTIGUOUS': 'C', 'CONTIGUOUS': 'C',
- 'F': 'F', 'F_CONTIGUOUS': 'F', 'FORTRAN': 'F',
- 'A': 'A', 'ALIGNED': 'A',
- 'W': 'W', 'WRITEABLE': 'W',
- 'O': 'O', 'OWNDATA': 'O',
- 'E': 'E', 'ENSUREARRAY': 'E'}
- if not requirements:
- return asanyarray(a, dtype=dtype)
- else:
- requirements = {possible_flags[x.upper()] for x in requirements}
-
- if 'E' in requirements:
- requirements.remove('E')
- subok = False
- else:
- subok = True
-
- order = 'A'
- if requirements >= {'C', 'F'}:
- raise ValueError('Cannot specify both "C" and "F" order')
- elif 'F' in requirements:
- order = 'F'
- requirements.remove('F')
- elif 'C' in requirements:
- order = 'C'
- requirements.remove('C')
-
- arr = array(a, dtype=dtype, order=order, copy=False, subok=subok)
-
- for prop in requirements:
- if not arr.flags[prop]:
- arr = arr.copy(order)
- break
- return arr
-
-
-@set_module('numpy')
def isfortran(a):
"""
- Returns True if the array is Fortran contiguous but *not* C contiguous.
+ Check if the array is Fortran contiguous but *not* C contiguous.
This function is obsolete and, because of changes due to relaxed stride
checking, its return value for the same array may differ for versions
@@ -787,6 +484,11 @@ def isfortran(a):
a : ndarray
Input array.
+ Returns
+ -------
+ isfortran : bool
+ Returns True if the array is Fortran contiguous but *not* C contiguous.
+
Examples
--------
@@ -802,7 +504,7 @@ def isfortran(a):
>>> np.isfortran(a)
False
- >>> b = np.array([[1, 2, 3], [4, 5, 6]], order='FORTRAN')
+ >>> b = np.array([[1, 2, 3], [4, 5, 6]], order='F')
>>> b
array([[1, 2, 3],
[4, 5, 6]])
@@ -987,11 +689,11 @@ def correlate(a, v, mode='valid'):
Examples
--------
>>> np.correlate([1, 2, 3], [0, 1, 0.5])
- array([ 3.5])
+ array([3.5])
>>> np.correlate([1, 2, 3], [0, 1, 0.5], "same")
- array([ 2. , 3.5, 3. ])
+ array([2. , 3.5, 3. ])
>>> np.correlate([1, 2, 3], [0, 1, 0.5], "full")
- array([ 0.5, 2. , 3.5, 3. , 0. ])
+ array([0.5, 2. , 3.5, 3. , 0. ])
Using complex sequences:
@@ -1087,20 +789,20 @@ def convolve(a, v, mode='full'):
before "sliding" the two across one another:
>>> np.convolve([1, 2, 3], [0, 1, 0.5])
- array([ 0. , 1. , 2.5, 4. , 1.5])
+ array([0. , 1. , 2.5, 4. , 1.5])
Only return the middle values of the convolution.
Contains boundary effects, where zeros are taken
into account:
>>> np.convolve([1,2,3],[0,1,0.5], 'same')
- array([ 1. , 2.5, 4. ])
+ array([1. , 2.5, 4. ])
The two arrays are of the same length, so there
is only one position where they completely overlap:
>>> np.convolve([1,2,3],[0,1,0.5], 'valid')
- array([ 2.5])
+ array([2.5])
"""
a, v = array(a, copy=False, ndmin=1), array(v, copy=False, ndmin=1)
@@ -1176,11 +878,11 @@ def outer(a, b, out=None):
[-2., -1., 0., 1., 2.]])
>>> im = np.outer(1j*np.linspace(2, -2, 5), np.ones((5,)))
>>> im
- array([[ 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j],
- [ 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j],
- [ 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]])
+ array([[0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j],
+ [0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j],
+ [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
+ [0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j],
+ [0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]])
>>> grid = rl + im
>>> grid
array([[-2.+2.j, -1.+2.j, 0.+2.j, 1.+2.j, 2.+2.j],
@@ -1193,9 +895,9 @@ def outer(a, b, out=None):
>>> x = np.array(['a', 'b', 'c'], dtype=object)
>>> np.outer(x, [1, 2, 3])
- array([[a, aa, aaa],
- [b, bb, bbb],
- [c, cc, ccc]], dtype=object)
+ array([['a', 'aa', 'aaa'],
+ ['b', 'bb', 'bbb'],
+ ['c', 'cc', 'ccc']], dtype=object)
"""
a = asarray(a)
@@ -1210,20 +912,18 @@ def _tensordot_dispatcher(a, b, axes=None):
@array_function_dispatch(_tensordot_dispatcher)
def tensordot(a, b, axes=2):
"""
- Compute tensor dot product along specified axes for arrays >= 1-D.
+ Compute tensor dot product along specified axes.
- Given two tensors (arrays of dimension greater than or equal to one),
- `a` and `b`, and an array_like object containing two array_like
- objects, ``(a_axes, b_axes)``, sum the products of `a`'s and `b`'s
- elements (components) over the axes specified by ``a_axes`` and
- ``b_axes``. The third argument can be a single non-negative
- integer_like scalar, ``N``; if it is such, then the last ``N``
- dimensions of `a` and the first ``N`` dimensions of `b` are summed
- over.
+ Given two tensors, `a` and `b`, and an array_like object containing
+ two array_like objects, ``(a_axes, b_axes)``, sum the products of
+ `a`'s and `b`'s elements (components) over the axes specified by
+ ``a_axes`` and ``b_axes``. The third argument can be a single non-negative
+ integer_like scalar, ``N``; if it is such, then the last ``N`` dimensions
+ of `a` and the first ``N`` dimensions of `b` are summed over.
Parameters
----------
- a, b : array_like, len(shape) >= 1
+ a, b : array_like
Tensors to "dot".
axes : int or (2,) array_like
@@ -1234,6 +934,11 @@ def tensordot(a, b, axes=2):
Or, a list of axes to be summed over, first sequence applying to `a`,
second to `b`. Both elements array_like must be of the same length.
+ Returns
+ -------
+ output : ndarray
+ The tensor dot product of the input.
+
See Also
--------
dot, einsum
@@ -1264,11 +969,11 @@ def tensordot(a, b, axes=2):
>>> c.shape
(5, 2)
>>> c
- array([[ 4400., 4730.],
- [ 4532., 4874.],
- [ 4664., 5018.],
- [ 4796., 5162.],
- [ 4928., 5306.]])
+ array([[4400., 4730.],
+ [4532., 4874.],
+ [4664., 5018.],
+ [4796., 5162.],
+ [4928., 5306.]])
>>> # A slower but equivalent way of computing the same...
>>> d = np.zeros((5,2))
>>> for i in range(5):
@@ -1294,40 +999,40 @@ def tensordot(a, b, axes=2):
[3, 4]],
[[5, 6],
[7, 8]]])
- array([[a, b],
- [c, d]], dtype=object)
+ array([['a', 'b'],
+ ['c', 'd']], dtype=object)
>>> np.tensordot(a, A) # third argument default is 2 for double-contraction
- array([abbcccdddd, aaaaabbbbbbcccccccdddddddd], dtype=object)
+ array(['abbcccdddd', 'aaaaabbbbbbcccccccdddddddd'], dtype=object)
>>> np.tensordot(a, A, 1)
- array([[[acc, bdd],
- [aaacccc, bbbdddd]],
- [[aaaaacccccc, bbbbbdddddd],
- [aaaaaaacccccccc, bbbbbbbdddddddd]]], dtype=object)
+ array([[['acc', 'bdd'],
+ ['aaacccc', 'bbbdddd']],
+ [['aaaaacccccc', 'bbbbbdddddd'],
+ ['aaaaaaacccccccc', 'bbbbbbbdddddddd']]], dtype=object)
>>> np.tensordot(a, A, 0) # tensor product (result too long to incl.)
- array([[[[[a, b],
- [c, d]],
+ array([[[[['a', 'b'],
+ ['c', 'd']],
...
>>> np.tensordot(a, A, (0, 1))
- array([[[abbbbb, cddddd],
- [aabbbbbb, ccdddddd]],
- [[aaabbbbbbb, cccddddddd],
- [aaaabbbbbbbb, ccccdddddddd]]], dtype=object)
+ array([[['abbbbb', 'cddddd'],
+ ['aabbbbbb', 'ccdddddd']],
+ [['aaabbbbbbb', 'cccddddddd'],
+ ['aaaabbbbbbbb', 'ccccdddddddd']]], dtype=object)
>>> np.tensordot(a, A, (2, 1))
- array([[[abb, cdd],
- [aaabbbb, cccdddd]],
- [[aaaaabbbbbb, cccccdddddd],
- [aaaaaaabbbbbbbb, cccccccdddddddd]]], dtype=object)
+ array([[['abb', 'cdd'],
+ ['aaabbbb', 'cccdddd']],
+ [['aaaaabbbbbb', 'cccccdddddd'],
+ ['aaaaaaabbbbbbbb', 'cccccccdddddddd']]], dtype=object)
>>> np.tensordot(a, A, ((0, 1), (0, 1)))
- array([abbbcccccddddddd, aabbbbccccccdddddddd], dtype=object)
+ array(['abbbcccccddddddd', 'aabbbbccccccdddddddd'], dtype=object)
>>> np.tensordot(a, A, ((2, 1), (1, 0)))
- array([acccbbdddd, aaaaacccccccbbbbbbdddddddd], dtype=object)
+ array(['acccbbdddd', 'aaaaacccccccbbbbbbdddddddd'], dtype=object)
"""
try:
@@ -1442,6 +1147,8 @@ def roll(a, shift, axis=None):
>>> x = np.arange(10)
>>> np.roll(x, 2)
array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])
+ >>> np.roll(x, -2)
+ array([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
>>> x2 = np.reshape(x, (2,5))
>>> x2
@@ -1450,12 +1157,21 @@ def roll(a, shift, axis=None):
>>> np.roll(x2, 1)
array([[9, 0, 1, 2, 3],
[4, 5, 6, 7, 8]])
+ >>> np.roll(x2, -1)
+ array([[1, 2, 3, 4, 5],
+ [6, 7, 8, 9, 0]])
>>> np.roll(x2, 1, axis=0)
array([[5, 6, 7, 8, 9],
[0, 1, 2, 3, 4]])
+ >>> np.roll(x2, -1, axis=0)
+ array([[5, 6, 7, 8, 9],
+ [0, 1, 2, 3, 4]])
>>> np.roll(x2, 1, axis=1)
array([[4, 0, 1, 2, 3],
[9, 5, 6, 7, 8]])
+ >>> np.roll(x2, -1, axis=1)
+ array([[1, 2, 3, 4, 0],
+ [6, 7, 8, 9, 5]])
"""
a = asanyarray(a)
@@ -1780,7 +1496,7 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None):
>>> x = [1,2]
>>> y = [4,5]
>>> np.cross(x, y)
- -3
+ array(-3)
Multiple vector cross-products. Note that the direction of the cross
product vector is defined by the `right-hand rule`.
@@ -1900,11 +1616,11 @@ little_endian = (sys.byteorder == 'little')
@set_module('numpy')
-def indices(dimensions, dtype=int):
+def indices(dimensions, dtype=int, sparse=False):
"""
Return an array representing the indices of a grid.
- Compute an array where the subarrays contain index values 0,1,...
+ Compute an array where the subarrays contain index values 0, 1, ...
varying only along the corresponding axis.
Parameters
@@ -1913,28 +1629,38 @@ def indices(dimensions, dtype=int):
The shape of the grid.
dtype : dtype, optional
Data type of the result.
+ sparse : boolean, optional
+ Return a sparse representation of the grid instead of a dense
+ representation. Default is False.
+
+ .. versionadded:: 1.17
Returns
-------
- grid : ndarray
- The array of grid indices,
- ``grid.shape = (len(dimensions),) + tuple(dimensions)``.
+ grid : one ndarray or tuple of ndarrays
+ If sparse is False:
+ Returns one array of grid indices,
+ ``grid.shape = (len(dimensions),) + tuple(dimensions)``.
+ If sparse is True:
+ Returns a tuple of arrays, with
+ ``grid[i].shape = (1, ..., 1, dimensions[i], 1, ..., 1)`` with
+ dimensions[i] in the ith place
See Also
--------
- mgrid, meshgrid
+ mgrid, ogrid, meshgrid
Notes
-----
- The output shape is obtained by prepending the number of dimensions
- in front of the tuple of dimensions, i.e. if `dimensions` is a tuple
- ``(r0, ..., rN-1)`` of length ``N``, the output shape is
- ``(N,r0,...,rN-1)``.
+ The output shape in the dense case is obtained by prepending the number
+ of dimensions in front of the tuple of dimensions, i.e. if `dimensions`
+ is a tuple ``(r0, ..., rN-1)`` of length ``N``, the output shape is
+ ``(N, r0, ..., rN-1)``.
The subarrays ``grid[k]`` contains the N-D array of indices along the
``k-th`` axis. Explicitly::
- grid[k,i0,i1,...,iN-1] = ik
+ grid[k, i0, i1, ..., iN-1] = ik
Examples
--------
@@ -1959,15 +1685,36 @@ def indices(dimensions, dtype=int):
Note that it would be more straightforward in the above example to
extract the required elements directly with ``x[:2, :3]``.
+ If sparse is set to true, the grid will be returned in a sparse
+ representation.
+
+ >>> i, j = np.indices((2, 3), sparse=True)
+ >>> i.shape
+ (2, 1)
+ >>> j.shape
+ (1, 3)
+ >>> i # row indices
+ array([[0],
+ [1]])
+ >>> j # column indices
+ array([[0, 1, 2]])
+
"""
dimensions = tuple(dimensions)
N = len(dimensions)
shape = (1,)*N
- res = empty((N,)+dimensions, dtype=dtype)
+ if sparse:
+ res = tuple()
+ else:
+ res = empty((N,)+dimensions, dtype=dtype)
for i, dim in enumerate(dimensions):
- res[i] = arange(dim, dtype=dtype).reshape(
+ idx = arange(dim, dtype=dtype).reshape(
shape[:i] + (dim,) + shape[i+1:]
)
+ if sparse:
+ res = res + (idx,)
+ else:
+ res[i] = idx
return res
@@ -2097,10 +1844,10 @@ def isscalar(num):
NumPy supports PEP 3141 numbers:
>>> from fractions import Fraction
- >>> isscalar(Fraction(5, 17))
+ >>> np.isscalar(Fraction(5, 17))
True
>>> from numbers import Number
- >>> isscalar(Number())
+ >>> np.isscalar(Number())
True
"""
@@ -2296,7 +2043,8 @@ def load(file):
"np.core.numeric.load is deprecated, use pickle.load instead",
DeprecationWarning, stacklevel=2)
if isinstance(file, type("")):
- file = open(file, "rb")
+ with open(file, "rb") as file_pointer:
+ return pickle.load(file_pointer)
return pickle.load(file)
@@ -2339,9 +2087,9 @@ def identity(n, dtype=None):
Examples
--------
>>> np.identity(3)
- array([[ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]])
+ array([[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]])
"""
from numpy import eye
@@ -2487,23 +2235,23 @@ def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
Examples
--------
>>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
- array([True, False])
+ array([ True, False])
>>> np.isclose([1e10,1e-8], [1.00001e10,1e-9])
- array([True, True])
+ array([ True, True])
>>> np.isclose([1e10,1e-8], [1.0001e10,1e-9])
- array([False, True])
+ array([False, True])
>>> np.isclose([1.0, np.nan], [1.0, np.nan])
- array([True, False])
+ array([ True, False])
>>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True)
- array([True, True])
+ array([ True, True])
>>> np.isclose([1e-8, 1e-7], [0.0, 0.0])
- array([ True, False], dtype=bool)
+ array([ True, False])
>>> np.isclose([1e-100, 1e-7], [0.0, 0.0], atol=0.0)
- array([False, False], dtype=bool)
+ array([False, False])
>>> np.isclose([1e-10, 1e-10], [1e-20, 0.0])
- array([ True, True], dtype=bool)
+ array([ True, True])
>>> np.isclose([1e-10, 1e-10], [1e-20, 0.999999e-10], atol=0.0)
- array([False, True], dtype=bool)
+ array([False, True])
"""
def within_tol(x, y, atol, rtol):
with errstate(invalid='ignore'):
@@ -2643,437 +2391,6 @@ def array_equiv(a1, a2):
return bool(asarray(a1 == a2).all())
-_errdict = {"ignore": ERR_IGNORE,
- "warn": ERR_WARN,
- "raise": ERR_RAISE,
- "call": ERR_CALL,
- "print": ERR_PRINT,
- "log": ERR_LOG}
-
-_errdict_rev = {value: key for key, value in _errdict.items()}
-
-
-@set_module('numpy')
-def seterr(all=None, divide=None, over=None, under=None, invalid=None):
- """
- Set how floating-point errors are handled.
-
- Note that operations on integer scalar types (such as `int16`) are
- handled like floating point, and are affected by these settings.
-
- Parameters
- ----------
- all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
- Set treatment for all types of floating-point errors at once:
-
- - ignore: Take no action when the exception occurs.
- - warn: Print a `RuntimeWarning` (via the Python `warnings` module).
- - raise: Raise a `FloatingPointError`.
- - call: Call a function specified using the `seterrcall` function.
- - print: Print a warning directly to ``stdout``.
- - log: Record error in a Log object specified by `seterrcall`.
-
- The default is not to change the current behavior.
- divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
- Treatment for division by zero.
- over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
- Treatment for floating-point overflow.
- under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
- Treatment for floating-point underflow.
- invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
- Treatment for invalid floating-point operation.
-
- Returns
- -------
- old_settings : dict
- Dictionary containing the old settings.
-
- See also
- --------
- seterrcall : Set a callback function for the 'call' mode.
- geterr, geterrcall, errstate
-
- Notes
- -----
- The floating-point exceptions are defined in the IEEE 754 standard [1]_:
-
- - Division by zero: infinite result obtained from finite numbers.
- - Overflow: result too large to be expressed.
- - Underflow: result so close to zero that some precision
- was lost.
- - Invalid operation: result is not an expressible number, typically
- indicates that a NaN was produced.
-
- .. [1] https://en.wikipedia.org/wiki/IEEE_754
-
- Examples
- --------
- >>> old_settings = np.seterr(all='ignore') #seterr to known value
- >>> np.seterr(over='raise')
- {'over': 'ignore', 'divide': 'ignore', 'invalid': 'ignore',
- 'under': 'ignore'}
- >>> np.seterr(**old_settings) # reset to default
- {'over': 'raise', 'divide': 'ignore', 'invalid': 'ignore',
- 'under': 'ignore'}
-
- >>> np.int16(32000) * np.int16(3)
- 30464
- >>> old_settings = np.seterr(all='warn', over='raise')
- >>> np.int16(32000) * np.int16(3)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- FloatingPointError: overflow encountered in short_scalars
-
- >>> old_settings = np.seterr(all='print')
- >>> np.geterr()
- {'over': 'print', 'divide': 'print', 'invalid': 'print', 'under': 'print'}
- >>> np.int16(32000) * np.int16(3)
- Warning: overflow encountered in short_scalars
- 30464
-
- """
-
- pyvals = umath.geterrobj()
- old = geterr()
-
- if divide is None:
- divide = all or old['divide']
- if over is None:
- over = all or old['over']
- if under is None:
- under = all or old['under']
- if invalid is None:
- invalid = all or old['invalid']
-
- maskvalue = ((_errdict[divide] << SHIFT_DIVIDEBYZERO) +
- (_errdict[over] << SHIFT_OVERFLOW) +
- (_errdict[under] << SHIFT_UNDERFLOW) +
- (_errdict[invalid] << SHIFT_INVALID))
-
- pyvals[1] = maskvalue
- umath.seterrobj(pyvals)
- return old
-
-
-@set_module('numpy')
-def geterr():
- """
- Get the current way of handling floating-point errors.
-
- Returns
- -------
- res : dict
- A dictionary with keys "divide", "over", "under", and "invalid",
- whose values are from the strings "ignore", "print", "log", "warn",
- "raise", and "call". The keys represent possible floating-point
- exceptions, and the values define how these exceptions are handled.
-
- See Also
- --------
- geterrcall, seterr, seterrcall
-
- Notes
- -----
- For complete documentation of the types of floating-point exceptions and
- treatment options, see `seterr`.
-
- Examples
- --------
- >>> np.geterr()
- {'over': 'warn', 'divide': 'warn', 'invalid': 'warn',
- 'under': 'ignore'}
- >>> np.arange(3.) / np.arange(3.)
- array([ NaN, 1., 1.])
-
- >>> oldsettings = np.seterr(all='warn', over='raise')
- >>> np.geterr()
- {'over': 'raise', 'divide': 'warn', 'invalid': 'warn', 'under': 'warn'}
- >>> np.arange(3.) / np.arange(3.)
- __main__:1: RuntimeWarning: invalid value encountered in divide
- array([ NaN, 1., 1.])
-
- """
- maskvalue = umath.geterrobj()[1]
- mask = 7
- res = {}
- val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask
- res['divide'] = _errdict_rev[val]
- val = (maskvalue >> SHIFT_OVERFLOW) & mask
- res['over'] = _errdict_rev[val]
- val = (maskvalue >> SHIFT_UNDERFLOW) & mask
- res['under'] = _errdict_rev[val]
- val = (maskvalue >> SHIFT_INVALID) & mask
- res['invalid'] = _errdict_rev[val]
- return res
-
-
-@set_module('numpy')
-def setbufsize(size):
- """
- Set the size of the buffer used in ufuncs.
-
- Parameters
- ----------
- size : int
- Size of buffer.
-
- """
- if size > 10e6:
- raise ValueError("Buffer size, %s, is too big." % size)
- if size < 5:
- raise ValueError("Buffer size, %s, is too small." % size)
- if size % 16 != 0:
- raise ValueError("Buffer size, %s, is not a multiple of 16." % size)
-
- pyvals = umath.geterrobj()
- old = getbufsize()
- pyvals[0] = size
- umath.seterrobj(pyvals)
- return old
-
-
-@set_module('numpy')
-def getbufsize():
- """
- Return the size of the buffer used in ufuncs.
-
- Returns
- -------
- getbufsize : int
- Size of ufunc buffer in bytes.
-
- """
- return umath.geterrobj()[0]
-
-
-@set_module('numpy')
-def seterrcall(func):
- """
- Set the floating-point error callback function or log object.
-
- There are two ways to capture floating-point error messages. The first
- is to set the error-handler to 'call', using `seterr`. Then, set
- the function to call using this function.
-
- The second is to set the error-handler to 'log', using `seterr`.
- Floating-point errors then trigger a call to the 'write' method of
- the provided object.
-
- Parameters
- ----------
- func : callable f(err, flag) or object with write method
- Function to call upon floating-point errors ('call'-mode) or
- object whose 'write' method is used to log such message ('log'-mode).
-
- The call function takes two arguments. The first is a string describing
- the type of error (such as "divide by zero", "overflow", "underflow",
- or "invalid value"), and the second is the status flag. The flag is a
- byte, whose four least-significant bits indicate the type of error, one
- of "divide", "over", "under", "invalid"::
-
- [0 0 0 0 divide over under invalid]
-
- In other words, ``flags = divide + 2*over + 4*under + 8*invalid``.
-
- If an object is provided, its write method should take one argument,
- a string.
-
- Returns
- -------
- h : callable, log instance or None
- The old error handler.
-
- See Also
- --------
- seterr, geterr, geterrcall
-
- Examples
- --------
- Callback upon error:
-
- >>> def err_handler(type, flag):
- ... print("Floating point error (%s), with flag %s" % (type, flag))
- ...
-
- >>> saved_handler = np.seterrcall(err_handler)
- >>> save_err = np.seterr(all='call')
-
- >>> np.array([1, 2, 3]) / 0.0
- Floating point error (divide by zero), with flag 1
- array([ Inf, Inf, Inf])
-
- >>> np.seterrcall(saved_handler)
- <function err_handler at 0x...>
- >>> np.seterr(**save_err)
- {'over': 'call', 'divide': 'call', 'invalid': 'call', 'under': 'call'}
-
- Log error message:
-
- >>> class Log(object):
- ... def write(self, msg):
- ... print("LOG: %s" % msg)
- ...
-
- >>> log = Log()
- >>> saved_handler = np.seterrcall(log)
- >>> save_err = np.seterr(all='log')
-
- >>> np.array([1, 2, 3]) / 0.0
- LOG: Warning: divide by zero encountered in divide
- <BLANKLINE>
- array([ Inf, Inf, Inf])
-
- >>> np.seterrcall(saved_handler)
- <__main__.Log object at 0x...>
- >>> np.seterr(**save_err)
- {'over': 'log', 'divide': 'log', 'invalid': 'log', 'under': 'log'}
-
- """
- if func is not None and not isinstance(func, collections_abc.Callable):
- if not hasattr(func, 'write') or not isinstance(func.write, collections_abc.Callable):
- raise ValueError("Only callable can be used as callback")
- pyvals = umath.geterrobj()
- old = geterrcall()
- pyvals[2] = func
- umath.seterrobj(pyvals)
- return old
-
-
-@set_module('numpy')
-def geterrcall():
- """
- Return the current callback function used on floating-point errors.
-
- When the error handling for a floating-point error (one of "divide",
- "over", "under", or "invalid") is set to 'call' or 'log', the function
- that is called or the log instance that is written to is returned by
- `geterrcall`. This function or log instance has been set with
- `seterrcall`.
-
- Returns
- -------
- errobj : callable, log instance or None
- The current error handler. If no handler was set through `seterrcall`,
- ``None`` is returned.
-
- See Also
- --------
- seterrcall, seterr, geterr
-
- Notes
- -----
- For complete documentation of the types of floating-point exceptions and
- treatment options, see `seterr`.
-
- Examples
- --------
- >>> np.geterrcall() # we did not yet set a handler, returns None
-
- >>> oldsettings = np.seterr(all='call')
- >>> def err_handler(type, flag):
- ... print("Floating point error (%s), with flag %s" % (type, flag))
- >>> oldhandler = np.seterrcall(err_handler)
- >>> np.array([1, 2, 3]) / 0.0
- Floating point error (divide by zero), with flag 1
- array([ Inf, Inf, Inf])
-
- >>> cur_handler = np.geterrcall()
- >>> cur_handler is err_handler
- True
-
- """
- return umath.geterrobj()[2]
-
-
-class _unspecified(object):
- pass
-
-
-_Unspecified = _unspecified()
-
-
-@set_module('numpy')
-class errstate(object):
- """
- errstate(**kwargs)
-
- Context manager for floating-point error handling.
-
- Using an instance of `errstate` as a context manager allows statements in
- that context to execute with a known error handling behavior. Upon entering
- the context the error handling is set with `seterr` and `seterrcall`, and
- upon exiting it is reset to what it was before.
-
- Parameters
- ----------
- kwargs : {divide, over, under, invalid}
- Keyword arguments. The valid keywords are the possible floating-point
- exceptions. Each keyword should have a string value that defines the
- treatment for the particular error. Possible values are
- {'ignore', 'warn', 'raise', 'call', 'print', 'log'}.
-
- See Also
- --------
- seterr, geterr, seterrcall, geterrcall
-
- Notes
- -----
- For complete documentation of the types of floating-point exceptions and
- treatment options, see `seterr`.
-
- Examples
- --------
- >>> olderr = np.seterr(all='ignore') # Set error handling to known state.
-
- >>> np.arange(3) / 0.
- array([ NaN, Inf, Inf])
- >>> with np.errstate(divide='warn'):
- ... np.arange(3) / 0.
- ...
- __main__:2: RuntimeWarning: divide by zero encountered in divide
- array([ NaN, Inf, Inf])
-
- >>> np.sqrt(-1)
- nan
- >>> with np.errstate(invalid='raise'):
- ... np.sqrt(-1)
- Traceback (most recent call last):
- File "<stdin>", line 2, in <module>
- FloatingPointError: invalid value encountered in sqrt
-
- Outside the context the error handling behavior has not changed:
-
- >>> np.geterr()
- {'over': 'warn', 'divide': 'warn', 'invalid': 'warn',
- 'under': 'ignore'}
-
- """
- # Note that we don't want to run the above doctests because they will fail
- # without a from __future__ import with_statement
-
- def __init__(self, **kwargs):
- self.call = kwargs.pop('call', _Unspecified)
- self.kwargs = kwargs
-
- def __enter__(self):
- self.oldstate = seterr(**self.kwargs)
- if self.call is not _Unspecified:
- self.oldcall = seterrcall(self.call)
-
- def __exit__(self, *exc_info):
- seterr(**self.oldstate)
- if self.call is not _Unspecified:
- seterrcall(self.oldcall)
-
-
-def _setdef():
- defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None]
- umath.seterrobj(defval)
-
-
-# set the default values
-_setdef()
-
Inf = inf = infty = Infinity = PINF
nan = NaN = NAN
False_ = bool_(False)
@@ -3094,7 +2411,13 @@ from . import fromnumeric
from .fromnumeric import *
from . import arrayprint
from .arrayprint import *
+from . import _asarray
+from ._asarray import *
+from . import _ufunc_config
+from ._ufunc_config import *
extend_all(fromnumeric)
extend_all(umath)
extend_all(numerictypes)
extend_all(arrayprint)
+extend_all(_asarray)
+extend_all(_ufunc_config)
diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py
index f00f92286..ab1ff65a4 100644
--- a/numpy/core/numerictypes.py
+++ b/numpy/core/numerictypes.py
@@ -140,6 +140,7 @@ genericTypeRank = ['bool', 'int8', 'uint8', 'int16', 'uint16',
'complex32', 'complex64', 'complex128', 'complex160',
'complex192', 'complex256', 'complex512', 'object']
+@set_module('numpy')
def maximum_sctype(t):
"""
Return the scalar type of highest precision of the same kind as the input.
@@ -163,19 +164,19 @@ def maximum_sctype(t):
Examples
--------
>>> np.maximum_sctype(int)
- <type 'numpy.int64'>
+ <class 'numpy.int64'>
>>> np.maximum_sctype(np.uint8)
- <type 'numpy.uint64'>
+ <class 'numpy.uint64'>
>>> np.maximum_sctype(complex)
- <type 'numpy.complex192'>
+ <class 'numpy.complex256'> # may vary
>>> np.maximum_sctype(str)
- <type 'numpy.string_'>
+ <class 'numpy.str_'>
>>> np.maximum_sctype('i2')
- <type 'numpy.int64'>
+ <class 'numpy.int64'>
>>> np.maximum_sctype('f4')
- <type 'numpy.float96'>
+ <class 'numpy.float128'> # may vary
"""
g = obj2sctype(t)
@@ -260,22 +261,21 @@ def obj2sctype(rep, default=None):
Examples
--------
>>> np.obj2sctype(np.int32)
- <type 'numpy.int32'>
+ <class 'numpy.int32'>
>>> np.obj2sctype(np.array([1., 2.]))
- <type 'numpy.float64'>
+ <class 'numpy.float64'>
>>> np.obj2sctype(np.array([1.j]))
- <type 'numpy.complex128'>
+ <class 'numpy.complex128'>
>>> np.obj2sctype(dict)
- <type 'numpy.object_'>
+ <class 'numpy.object_'>
>>> np.obj2sctype('string')
- <type 'numpy.string_'>
>>> np.obj2sctype(1, default=list)
- <type 'list'>
+ <class 'list'>
"""
- # prevent abtract classes being upcast
+ # prevent abstract classes being upcast
if isinstance(rep, type) and issubclass(rep, generic):
return rep
# extract dtype from arrays
@@ -319,7 +319,7 @@ def issubclass_(arg1, arg2):
Examples
--------
>>> np.issubclass_(np.int32, int)
- True
+ False # True on Python 2.7
>>> np.issubclass_(np.int32, float)
False
@@ -347,12 +347,12 @@ def issubsctype(arg1, arg2):
See Also
--------
- issctype, issubdtype,obj2sctype
+ issctype, issubdtype, obj2sctype
Examples
--------
>>> np.issubsctype('S8', str)
- True
+ False
>>> np.issubsctype(np.array([1]), int)
True
>>> np.issubsctype(np.array([1]), float)
@@ -485,9 +485,9 @@ def sctype2char(sctype):
Examples
--------
- >>> for sctype in [np.int32, float, complex, np.string_, np.ndarray]:
+ >>> for sctype in [np.int32, np.double, np.complex, np.string_, np.ndarray]:
... print(np.sctype2char(sctype))
- l
+ l # may vary
d
D
S
diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py
index c55174ecd..04a5a995f 100644
--- a/numpy/core/overrides.py
+++ b/numpy/core/overrides.py
@@ -2,14 +2,15 @@
import collections
import functools
import os
+import textwrap
from numpy.core._multiarray_umath import (
add_docstring, implement_array_function, _get_implementing_args)
from numpy.compat._inspect import getargspec
-ENABLE_ARRAY_FUNCTION = bool(
- int(os.environ.get('NUMPY_EXPERIMENTAL_ARRAY_FUNCTION', 0)))
+ARRAY_FUNCTION_ENABLED = bool(
+ int(os.environ.get('NUMPY_EXPERIMENTAL_ARRAY_FUNCTION', 1)))
add_docstring(
@@ -141,13 +142,12 @@ def array_function_dispatch(dispatcher, module=None, verify=True,
Function suitable for decorating the implementation of a NumPy function.
"""
- if not ENABLE_ARRAY_FUNCTION:
- # __array_function__ requires an explicit opt-in for now
+ if not ARRAY_FUNCTION_ENABLED:
def decorator(implementation):
- if module is not None:
- implementation.__module__ = module
if docs_from_dispatcher:
add_docstring(implementation, dispatcher.__doc__)
+ if module is not None:
+ implementation.__module__ = module
return implementation
return decorator
@@ -158,18 +158,35 @@ def array_function_dispatch(dispatcher, module=None, verify=True,
if docs_from_dispatcher:
add_docstring(implementation, dispatcher.__doc__)
+ # Equivalently, we could define this function directly instead of using
+ # exec. This version has the advantage of giving the helper function a
+ # more interpettable name. Otherwise, the original function does not
+ # show up at all in many cases, e.g., if it's written in C or if the
+ # dispatcher gets an invalid keyword argument.
+ source = textwrap.dedent("""
@functools.wraps(implementation)
- def public_api(*args, **kwargs):
+ def {name}(*args, **kwargs):
relevant_args = dispatcher(*args, **kwargs)
return implement_array_function(
- implementation, public_api, relevant_args, args, kwargs)
+ implementation, {name}, relevant_args, args, kwargs)
+ """).format(name=implementation.__name__)
+
+ source_object = compile(
+ source, filename='<__array_function__ internals>', mode='exec')
+ scope = {
+ 'implementation': implementation,
+ 'dispatcher': dispatcher,
+ 'functools': functools,
+ 'implement_array_function': implement_array_function,
+ }
+ exec(source_object, scope)
+
+ public_api = scope[implementation.__name__]
if module is not None:
public_api.__module__ = module
- # TODO: remove this when we drop Python 2 support (functools.wraps
- # adds __wrapped__ automatically in later versions)
- public_api.__wrapped__ = implementation
+ public_api._implementation = implementation
return public_api
diff --git a/numpy/core/records.py b/numpy/core/records.py
index 79b55fec1..659ffa42b 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -7,10 +7,9 @@ Most commonly, ndarrays contain elements of a single type, e.g. floats,
integers, bools etc. However, it is possible for elements to be combinations
of these using structured types, such as::
- >>> a = np.array([(1, 2.0), (1, 2.0)], dtype=[('x', int), ('y', float)])
+ >>> a = np.array([(1, 2.0), (1, 2.0)], dtype=[('x', np.int64), ('y', np.float64)])
>>> a
- array([(1, 2.0), (1, 2.0)],
- dtype=[('x', '<i4'), ('y', '<f8')])
+ array([(1, 2.), (1, 2.)], dtype=[('x', '<i8'), ('y', '<f8')])
Here, each element consists of two fields: x (and int), and y (a float).
This is known as a structured array. The different fields are analogous
@@ -21,7 +20,7 @@ one would a dictionary::
array([1, 1])
>>> a['y']
- array([ 2., 2.])
+ array([2., 2.])
Record arrays allow us to access fields as properties::
@@ -31,7 +30,7 @@ Record arrays allow us to access fields as properties::
array([1, 1])
>>> ar.y
- array([ 2., 2.])
+ array([2., 2.])
"""
from __future__ import division, absolute_import, print_function
@@ -39,10 +38,13 @@ from __future__ import division, absolute_import, print_function
import sys
import os
import warnings
+from collections import Counter, OrderedDict
from . import numeric as sb
from . import numerictypes as nt
-from numpy.compat import isfileobj, bytes, long, unicode, os_fspath
+from numpy.compat import (
+ isfileobj, bytes, long, unicode, os_fspath, contextlib_nullcontext
+)
from numpy.core.overrides import set_module
from .arrayprint import get_printoptions
@@ -74,14 +76,25 @@ _byteorderconv = {'b':'>',
numfmt = nt.typeDict
+# taken from OrderedDict recipes in the Python documentation
+# https://docs.python.org/3.3/library/collections.html#ordereddict-examples-and-recipes
+class _OrderedCounter(Counter, OrderedDict):
+ """Counter that remembers the order elements are first encountered"""
+
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
+
+ def __reduce__(self):
+ return self.__class__, (OrderedDict(self),)
+
+
def find_duplicate(list):
"""Find duplication in a list, return a list of duplicated elements"""
- dup = []
- for i in range(len(list)):
- if (list[i] in list[i + 1:]):
- if (list[i] not in dup):
- dup.append(list[i])
- return dup
+ return [
+ item
+ for item, counts in _OrderedCounter(list).items()
+ if counts > 1
+ ]
@set_module('numpy')
@@ -128,10 +141,9 @@ class format_parser(object):
Examples
--------
- >>> np.format_parser(['f8', 'i4', 'a5'], ['col1', 'col2', 'col3'],
+ >>> np.format_parser(['<f8', '<i4', '<a5'], ['col1', 'col2', 'col3'],
... ['T1', 'T2', 'T3']).dtype
- dtype([(('T1', 'col1'), '<f8'), (('T2', 'col2'), '<i4'),
- (('T3', 'col3'), '|S5')])
+ dtype([(('T1', 'col1'), '<f8'), (('T2', 'col2'), '<i4'), (('T3', 'col3'), 'S5')])
`names` and/or `titles` can be empty lists. If `titles` is an empty list,
titles will simply not appear. If `names` is empty, default field names
@@ -139,9 +151,9 @@ class format_parser(object):
>>> np.format_parser(['f8', 'i4', 'a5'], ['col1', 'col2', 'col3'],
... []).dtype
- dtype([('col1', '<f8'), ('col2', '<i4'), ('col3', '|S5')])
- >>> np.format_parser(['f8', 'i4', 'a5'], [], []).dtype
- dtype([('f0', '<f8'), ('f1', '<i4'), ('f2', '|S5')])
+ dtype([('col1', '<f8'), ('col2', '<i4'), ('col3', '<S5')])
+ >>> np.format_parser(['<f8', '<i4', '<a5'], [], []).dtype
+ dtype([('f0', '<f8'), ('f1', '<i4'), ('f2', 'S5')])
"""
@@ -157,10 +169,12 @@ class format_parser(object):
if formats is None:
raise ValueError("Need formats argument")
if isinstance(formats, list):
- if len(formats) < 2:
- formats.append('')
- formats = ','.join(formats)
- dtype = sb.dtype(formats, aligned)
+ dtype = sb.dtype(
+ [('f{}'.format(i), format_) for i, format_ in enumerate(formats)],
+ aligned,
+ )
+ else:
+ dtype = sb.dtype(formats, aligned)
fields = dtype.fields
if fields is None:
dtype = sb.dtype([('f1', dtype)], aligned)
@@ -254,8 +268,8 @@ class record(nt.void):
except AttributeError:
#happens if field is Object type
return obj
- if dt.names is not None:
- return obj.view((self.__class__, obj.dtype))
+ if dt.fields:
+ return obj.view((self.__class__, obj.dtype.fields))
return obj
else:
raise AttributeError("'record' object has no "
@@ -279,8 +293,8 @@ class record(nt.void):
obj = nt.void.__getitem__(self, indx)
# copy behavior of record.__getattribute__,
- if isinstance(obj, nt.void) and obj.dtype.names is not None:
- return obj.view((self.__class__, obj.dtype))
+ if isinstance(obj, nt.void) and obj.dtype.fields:
+ return obj.view((self.__class__, obj.dtype.fields))
else:
# return a single element
return obj
@@ -380,20 +394,19 @@ class recarray(ndarray):
--------
Create an array with two fields, ``x`` and ``y``:
- >>> x = np.array([(1.0, 2), (3.0, 4)], dtype=[('x', float), ('y', int)])
+ >>> x = np.array([(1.0, 2), (3.0, 4)], dtype=[('x', '<f8'), ('y', '<i8')])
>>> x
- array([(1.0, 2), (3.0, 4)],
- dtype=[('x', '<f8'), ('y', '<i4')])
+ array([(1., 2), (3., 4)], dtype=[('x', '<f8'), ('y', '<i8')])
>>> x['x']
- array([ 1., 3.])
+ array([1., 3.])
View the array as a record array:
>>> x = x.view(np.recarray)
>>> x.x
- array([ 1., 3.])
+ array([1., 3.])
>>> x.y
array([2, 4])
@@ -431,7 +444,7 @@ class recarray(ndarray):
return self
def __array_finalize__(self, obj):
- if self.dtype.type is not record and self.dtype.names is not None:
+ if self.dtype.type is not record and self.dtype.fields:
# if self.dtype is not np.record, invoke __setattr__ which will
# convert it to a record if it is a void dtype.
self.dtype = self.dtype
@@ -459,7 +472,7 @@ class recarray(ndarray):
# with void type convert it to the same dtype.type (eg to preserve
# numpy.record type if present), since nested structured fields do not
# inherit type. Don't do this for non-void structures though.
- if obj.dtype.names is not None:
+ if obj.dtype.fields:
if issubclass(obj.dtype.type, nt.void):
return obj.view(dtype=(self.dtype.type, obj.dtype))
return obj
@@ -474,7 +487,7 @@ class recarray(ndarray):
# Automatically convert (void) structured types to records
# (but not non-void structures, subarrays, or non-structured voids)
- if attr == 'dtype' and issubclass(val.type, nt.void) and val.names is not None:
+ if attr == 'dtype' and issubclass(val.type, nt.void) and val.fields:
val = sb.dtype((record, val))
newattr = attr not in self.__dict__
@@ -508,7 +521,7 @@ class recarray(ndarray):
# copy behavior of getattr, except that here
# we might also be returning a single element
if isinstance(obj, ndarray):
- if obj.dtype.names is not None:
+ if obj.dtype.fields:
obj = obj.view(type(self))
if issubclass(obj.dtype.type, nt.void):
return obj.view(dtype=(self.dtype.type, obj.dtype))
@@ -564,7 +577,7 @@ class recarray(ndarray):
if val is None:
obj = self.getfield(*res)
- if obj.dtype.names is not None:
+ if obj.dtype.fields:
return obj
return obj.view(ndarray)
else:
@@ -580,7 +593,7 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None,
>>> x3=np.array([1.1,2,3,4])
>>> r = np.core.records.fromarrays([x1,x2,x3],names='a,b,c')
>>> print(r[1])
- (2, 'dd', 2.0)
+ (2, 'dd', 2.0) # may vary
>>> x1[1]=34
>>> r.a
array([1, 2, 3, 4])
@@ -599,10 +612,7 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None,
# and determine the formats.
formats = []
for obj in arrayList:
- if not isinstance(obj, ndarray):
- raise ValueError("item in the array list must be an ndarray.")
- formats.append(obj.dtype.str)
- formats = ','.join(formats)
+ formats.append(obj.dtype)
if dtype is not None:
descr = sb.dtype(dtype)
@@ -659,11 +669,11 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
>>> r.col1
array([456, 2])
>>> r.col2
- array(['dbe', 'de'],
- dtype='|S3')
+ array(['dbe', 'de'], dtype='<U3')
>>> import pickle
- >>> print(pickle.loads(pickle.dumps(r)))
- [(456, 'dbe', 1.2) (2, 'de', 1.3)]
+ >>> pickle.loads(pickle.dumps(r))
+ rec.array([(456, 'dbe', 1.2), ( 2, 'de', 1.3)],
+ dtype=[('col1', '<i8'), ('col2', '<U3'), ('col3', '<f8')])
"""
if formats is None and dtype is None: # slower
@@ -750,7 +760,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
>>> a = a.newbyteorder('<')
>>> a.tofile(fd)
>>>
- >>> fd.seek(0)
+ >>> _ = fd.seek(0)
>>> r=np.core.records.fromfile(fd, formats='f8,i4,a5', shape=10,
... byteorder='<')
>>> print(r[5])
@@ -758,7 +768,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
>>> r.shape
(10,)
"""
-
+
if dtype is None and formats is None:
raise TypeError("fromfile() needs a 'dtype' or 'formats' argument")
@@ -769,44 +779,42 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
if isfileobj(fd):
# file already opened
- name = 0
+ ctx = contextlib_nullcontext(fd)
else:
# open file
- fd = open(os_fspath(fd), 'rb')
- name = 1
+ ctx = open(os_fspath(fd), 'rb')
- if (offset > 0):
- fd.seek(offset, 1)
- size = get_remaining_size(fd)
+ with ctx as fd:
+ if (offset > 0):
+ fd.seek(offset, 1)
+ size = get_remaining_size(fd)
- if dtype is not None:
- descr = sb.dtype(dtype)
- else:
- descr = format_parser(formats, names, titles, aligned, byteorder)._descr
+ if dtype is not None:
+ descr = sb.dtype(dtype)
+ else:
+ descr = format_parser(formats, names, titles, aligned, byteorder)._descr
- itemsize = descr.itemsize
+ itemsize = descr.itemsize
- shapeprod = sb.array(shape).prod(dtype=nt.intp)
- shapesize = shapeprod * itemsize
- if shapesize < 0:
- shape = list(shape)
- shape[shape.index(-1)] = size // -shapesize
- shape = tuple(shape)
shapeprod = sb.array(shape).prod(dtype=nt.intp)
+ shapesize = shapeprod * itemsize
+ if shapesize < 0:
+ shape = list(shape)
+ shape[shape.index(-1)] = size // -shapesize
+ shape = tuple(shape)
+ shapeprod = sb.array(shape).prod(dtype=nt.intp)
- nbytes = shapeprod * itemsize
+ nbytes = shapeprod * itemsize
- if nbytes > size:
- raise ValueError(
- "Not enough bytes left in file for specified shape and type")
+ if nbytes > size:
+ raise ValueError(
+ "Not enough bytes left in file for specified shape and type")
- # create the array
- _array = recarray(shape, descr)
- nbytesread = fd.readinto(_array.data)
- if nbytesread != nbytes:
- raise IOError("Didn't read as many bytes as expected")
- if name:
- fd.close()
+ # create the array
+ _array = recarray(shape, descr)
+ nbytesread = fd.readinto(_array.data)
+ if nbytesread != nbytes:
+ raise IOError("Didn't read as many bytes as expected")
return _array
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index aad0aae43..338502791 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -6,7 +6,9 @@ import pickle
import copy
import warnings
import platform
+import textwrap
from os.path import join
+
from numpy.distutils import log
from distutils.dep_util import newer
from distutils.sysconfig import get_config_var
@@ -171,6 +173,11 @@ def check_math_capabilities(config, moredefs, mathlibs):
if config.check_gcc_function_attribute(dec, fn):
moredefs.append((fname2def(fn), 1))
+ for dec, fn, code, header in OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS:
+ if config.check_gcc_function_attribute_with_intrinsics(dec, fn, code,
+ header):
+ moredefs.append((fname2def(fn), 1))
+
for fn in OPTIONAL_VARIABLE_ATTRIBUTES:
if config.check_gcc_variable_attribute(fn):
m = fn.replace("(", "_").replace(")", "_")
@@ -461,45 +468,42 @@ def configuration(parent_package='',top_path=None):
moredefs.append(('NPY_PY3K', 1))
# Generate the config.h file from moredefs
- target_f = open(target, 'w')
- for d in moredefs:
- if isinstance(d, str):
- target_f.write('#define %s\n' % (d))
+ with open(target, 'w') as target_f:
+ for d in moredefs:
+ if isinstance(d, str):
+ target_f.write('#define %s\n' % (d))
+ else:
+ target_f.write('#define %s %s\n' % (d[0], d[1]))
+
+ # define inline to our keyword, or nothing
+ target_f.write('#ifndef __cplusplus\n')
+ if inline == 'inline':
+ target_f.write('/* #undef inline */\n')
else:
- target_f.write('#define %s %s\n' % (d[0], d[1]))
+ target_f.write('#define inline %s\n' % inline)
+ target_f.write('#endif\n')
+
+ # add the guard to make sure config.h is never included directly,
+ # but always through npy_config.h
+ target_f.write(textwrap.dedent("""
+ #ifndef _NPY_NPY_CONFIG_H_
+ #error config.h should never be included directly, include npy_config.h instead
+ #endif
+ """))
- # define inline to our keyword, or nothing
- target_f.write('#ifndef __cplusplus\n')
- if inline == 'inline':
- target_f.write('/* #undef inline */\n')
- else:
- target_f.write('#define inline %s\n' % inline)
- target_f.write('#endif\n')
-
- # add the guard to make sure config.h is never included directly,
- # but always through npy_config.h
- target_f.write("""
-#ifndef _NPY_NPY_CONFIG_H_
-#error config.h should never be included directly, include npy_config.h instead
-#endif
-""")
-
- target_f.close()
print('File:', target)
- target_f = open(target)
- print(target_f.read())
- target_f.close()
+ with open(target) as target_f:
+ print(target_f.read())
print('EOF')
else:
mathlibs = []
- target_f = open(target)
- for line in target_f:
- s = '#define MATHLIB'
- if line.startswith(s):
- value = line[len(s):].strip()
- if value:
- mathlibs.extend(value.split(','))
- target_f.close()
+ with open(target) as target_f:
+ for line in target_f:
+ s = '#define MATHLIB'
+ if line.startswith(s):
+ value = line[len(s):].strip()
+ if value:
+ mathlibs.extend(value.split(','))
# Ugly: this can be called within a library and not an extension,
# in which case there is no libraries attributes (and none is
@@ -562,26 +566,24 @@ def configuration(parent_package='',top_path=None):
moredefs.append(('NPY_API_VERSION', '0x%.8X' % C_API_VERSION))
# Add moredefs to header
- target_f = open(target, 'w')
- for d in moredefs:
- if isinstance(d, str):
- target_f.write('#define %s\n' % (d))
- else:
- target_f.write('#define %s %s\n' % (d[0], d[1]))
-
- # Define __STDC_FORMAT_MACROS
- target_f.write("""
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS 1
-#endif
-""")
- target_f.close()
+ with open(target, 'w') as target_f:
+ for d in moredefs:
+ if isinstance(d, str):
+ target_f.write('#define %s\n' % (d))
+ else:
+ target_f.write('#define %s %s\n' % (d[0], d[1]))
+
+ # Define __STDC_FORMAT_MACROS
+ target_f.write(textwrap.dedent("""
+ #ifndef __STDC_FORMAT_MACROS
+ #define __STDC_FORMAT_MACROS 1
+ #endif
+ """))
# Dump the numpyconfig.h header to stdout
print('File: %s' % target)
- target_f = open(target)
- print(target_f.read())
- target_f.close()
+ with open(target) as target_f:
+ print(target_f.read())
print('EOF')
config.add_data_files((header_dir, target))
return target
@@ -608,7 +610,7 @@ def configuration(parent_package='',top_path=None):
config.add_include_dirs(join(local_dir, "src"))
config.add_include_dirs(join(local_dir))
- config.add_data_files('include/numpy/*.h')
+ config.add_data_dir('include/numpy')
config.add_include_dirs(join('src', 'npymath'))
config.add_include_dirs(join('src', 'multiarray'))
config.add_include_dirs(join('src', 'umath'))
@@ -703,7 +705,9 @@ def configuration(parent_package='',top_path=None):
npysort_sources = [join('src', 'common', 'npy_sort.h.src'),
join('src', 'npysort', 'quicksort.c.src'),
join('src', 'npysort', 'mergesort.c.src'),
+ join('src', 'npysort', 'timsort.c.src'),
join('src', 'npysort', 'heapsort.c.src'),
+ join('src', 'npysort', 'radixsort.c.src'),
join('src', 'common', 'npy_partition.h.src'),
join('src', 'npysort', 'selection.c.src'),
join('src', 'common', 'npy_binsearch.h.src'),
@@ -884,10 +888,9 @@ def configuration(parent_package='',top_path=None):
os.makedirs(dir)
script = generate_umath_py
if newer(script, target):
- f = open(target, 'w')
- f.write(generate_umath.make_code(generate_umath.defdict,
- generate_umath.__file__))
- f.close()
+ with open(target, 'w') as f:
+ f.write(generate_umath.make_code(generate_umath.defdict,
+ generate_umath.__file__))
return []
umath_src = [
@@ -899,6 +902,8 @@ def configuration(parent_package='',top_path=None):
join('src', 'umath', 'loops.c.src'),
join('src', 'umath', 'matmul.h.src'),
join('src', 'umath', 'matmul.c.src'),
+ join('src', 'umath', 'clip.h.src'),
+ join('src', 'umath', 'clip.c.src'),
join('src', 'umath', 'ufunc_object.c'),
join('src', 'umath', 'extobj.c'),
join('src', 'umath', 'cpuid.c'),
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 85b863e50..307fab334 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -81,7 +81,7 @@ def get_api_versions(apiversion, codegen_dir):
return curapi_hash, apis_hash[apiversion]
def check_api_version(apiversion, codegen_dir):
- """Emits a MismacthCAPIWarning if the C API version needs updating."""
+ """Emits a MismatchCAPIWarning if the C API version needs updating."""
curapi_hash, api_hash = get_api_versions(apiversion, codegen_dir)
# If different hash, it means that the api .txt files in
@@ -118,6 +118,7 @@ OPTIONAL_HEADERS = [
# sse headers only enabled automatically on amd64/x32 builds
"xmmintrin.h", # SSE
"emmintrin.h", # SSE2
+ "immintrin.h", # AVX
"features.h", # for glibc version linux
"xlocale.h", # see GH#8367
"dlfcn.h", # dladdr
@@ -137,6 +138,8 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
# broken on OSX 10.11, make sure its not optimized away
("volatile int r = __builtin_cpu_supports", '"sse"',
"stdio.h", "__BUILTIN_CPU_SUPPORTS"),
+ ("volatile int r = __builtin_cpu_supports", '"avx512f"',
+ "stdio.h", "__BUILTIN_CPU_SUPPORTS_AVX512F"),
# MMX only needed for icc, but some clangs don't have it
("_m_from_int64", '0', "emmintrin.h"),
("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE
@@ -149,6 +152,8 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
"stdio.h", "LINK_AVX"),
("__asm__ volatile", '"vpand %ymm1, %ymm2, %ymm3"',
"stdio.h", "LINK_AVX2"),
+ ("__asm__ volatile", '"vpaddd %zmm1, %zmm2, %zmm3"',
+ "stdio.h", "LINK_AVX512F"),
("__asm__ volatile", '"xgetbv"', "stdio.h", "XGETBV"),
]
@@ -165,6 +170,23 @@ OPTIONAL_FUNCTION_ATTRIBUTES = [('__attribute__((optimize("unroll-loops")))',
'attribute_target_avx'),
('__attribute__((target ("avx2")))',
'attribute_target_avx2'),
+ ('__attribute__((target ("avx512f")))',
+ 'attribute_target_avx512f'),
+ ]
+
+# function attributes with intrinsics
+# To ensure your compiler can compile avx intrinsics with just the attributes
+# gcc 4.8.4 support attributes but not with intrisics
+# tested via "#include<%s> int %s %s(void *){code; return 0;};" % (header, attribute, name, code)
+# function name will be converted to HAVE_<upper-case-name> preprocessor macro
+OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS = [('__attribute__((target("avx2")))',
+ 'attribute_target_avx2_with_intrinsics',
+ '__m256 temp = _mm256_set1_ps(1.0)',
+ 'immintrin.h'),
+ ('__attribute__((target("avx512f")))',
+ 'attribute_target_avx512f_with_intrinsics',
+ '__m512 temp = _mm512_set1_ps(1.0)',
+ 'immintrin.h'),
]
# variable attributes tested via "int %s a" % attribute
@@ -243,9 +265,8 @@ def check_long_double_representation(cmd):
except ValueError:
# try linking to support CC="gcc -flto" or icc -ipo
# struct needs to be volatile so it isn't optimized away
- # additionally "clang -flto" requires the foo struct to be used
body = body.replace('struct', 'volatile struct')
- body += "int main(void) { return foo.before[0]; }\n"
+ body += "int main(void) { return 0; }\n"
src, obj = cmd._compile(body, None, None, 'c')
cmd.temp_files.append("_configtest")
cmd.compiler.link_executable([obj], "_configtest")
@@ -293,30 +314,24 @@ def pyod(filename):
def _pyod2():
out = []
- fid = open(filename, 'rb')
- try:
+ with open(filename, 'rb') as fid:
yo = [int(oct(int(binascii.b2a_hex(o), 16))) for o in fid.read()]
- for i in range(0, len(yo), 16):
- line = ['%07d' % int(oct(i))]
- line.extend(['%03d' % c for c in yo[i:i+16]])
- out.append(" ".join(line))
- return out
- finally:
- fid.close()
+ for i in range(0, len(yo), 16):
+ line = ['%07d' % int(oct(i))]
+ line.extend(['%03d' % c for c in yo[i:i+16]])
+ out.append(" ".join(line))
+ return out
def _pyod3():
out = []
- fid = open(filename, 'rb')
- try:
+ with open(filename, 'rb') as fid:
yo2 = [oct(o)[2:] for o in fid.read()]
- for i in range(0, len(yo2), 16):
- line = ['%07d' % int(oct(i)[2:])]
- line.extend(['%03d' % int(c) for c in yo2[i:i+16]])
- out.append(" ".join(line))
- return out
- finally:
- fid.close()
+ for i in range(0, len(yo2), 16):
+ line = ['%07d' % int(oct(i)[2:])]
+ line.extend(['%03d' % int(c) for c in yo2[i:i+16]])
+ out.append(" ".join(line))
+ return out
if sys.version_info[0] < 3:
return _pyod2()
diff --git a/numpy/core/shape_base.py b/numpy/core/shape_base.py
index d20afd8be..710f64827 100644
--- a/numpy/core/shape_base.py
+++ b/numpy/core/shape_base.py
@@ -5,7 +5,6 @@ __all__ = ['atleast_1d', 'atleast_2d', 'atleast_3d', 'block', 'hstack',
import functools
import operator
-import types
import warnings
from . import numeric as _nx
@@ -48,13 +47,13 @@ def atleast_1d(*arys):
Examples
--------
>>> np.atleast_1d(1.0)
- array([ 1.])
+ array([1.])
>>> x = np.arange(9.0).reshape(3,3)
>>> np.atleast_1d(x)
- array([[ 0., 1., 2.],
- [ 3., 4., 5.],
- [ 6., 7., 8.]])
+ array([[0., 1., 2.],
+ [3., 4., 5.],
+ [6., 7., 8.]])
>>> np.atleast_1d(x) is x
True
@@ -106,11 +105,11 @@ def atleast_2d(*arys):
Examples
--------
>>> np.atleast_2d(3.0)
- array([[ 3.]])
+ array([[3.]])
>>> x = np.arange(3.0)
>>> np.atleast_2d(x)
- array([[ 0., 1., 2.]])
+ array([[0., 1., 2.]])
>>> np.atleast_2d(x).base is x
True
@@ -124,7 +123,7 @@ def atleast_2d(*arys):
if ary.ndim == 0:
result = ary.reshape(1, 1)
elif ary.ndim == 1:
- result = ary[newaxis,:]
+ result = ary[newaxis, :]
else:
result = ary
res.append(result)
@@ -166,7 +165,7 @@ def atleast_3d(*arys):
Examples
--------
>>> np.atleast_3d(3.0)
- array([[[ 3.]]])
+ array([[[3.]]])
>>> x = np.arange(3.0)
>>> np.atleast_3d(x).shape
@@ -179,7 +178,7 @@ def atleast_3d(*arys):
True
>>> for arr in np.atleast_3d([1, 2], [[1, 2]], [[[1, 2]]]):
- ... print(arr, arr.shape)
+ ... print(arr, arr.shape) # doctest: +SKIP
...
[[[1]
[2]]] (1, 2, 1)
@@ -194,9 +193,9 @@ def atleast_3d(*arys):
if ary.ndim == 0:
result = ary.reshape(1, 1, 1)
elif ary.ndim == 1:
- result = ary[newaxis,:, newaxis]
+ result = ary[newaxis, :, newaxis]
elif ary.ndim == 2:
- result = ary[:,:, newaxis]
+ result = ary[:, :, newaxis]
else:
result = ary
res.append(result)
@@ -217,11 +216,6 @@ def _arrays_for_stack_dispatcher(arrays, stacklevel=4):
return arrays
-def _warn_for_nonsequence(arrays):
- if not overrides.ENABLE_ARRAY_FUNCTION:
- _arrays_for_stack_dispatcher(arrays, stacklevel=4)
-
-
def _vhstack_dispatcher(tup):
return _arrays_for_stack_dispatcher(tup)
@@ -279,8 +273,13 @@ def vstack(tup):
[4]])
"""
- _warn_for_nonsequence(tup)
- return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)
+ if not overrides.ARRAY_FUNCTION_ENABLED:
+ # raise warning if necessary
+ _arrays_for_stack_dispatcher(tup, stacklevel=2)
+ arrs = atleast_2d(*tup)
+ if not isinstance(arrs, list):
+ arrs = [arrs]
+ return _nx.concatenate(arrs, 0)
@array_function_dispatch(_vhstack_dispatcher)
@@ -331,8 +330,13 @@ def hstack(tup):
[3, 4]])
"""
- _warn_for_nonsequence(tup)
- arrs = [atleast_1d(_m) for _m in tup]
+ if not overrides.ARRAY_FUNCTION_ENABLED:
+ # raise warning if necessary
+ _arrays_for_stack_dispatcher(tup, stacklevel=2)
+
+ arrs = atleast_1d(*tup)
+ if not isinstance(arrs, list):
+ arrs = [arrs]
# As a special case, dimension 0 of 1-dimensional arrays is "horizontal"
if arrs and arrs[0].ndim == 1:
return _nx.concatenate(arrs, 0)
@@ -354,9 +358,9 @@ def stack(arrays, axis=0, out=None):
"""
Join a sequence of arrays along a new axis.
- The `axis` parameter specifies the index of the new axis in the dimensions
- of the result. For example, if ``axis=0`` it will be the first dimension
- and if ``axis=-1`` it will be the last dimension.
+ The ``axis`` parameter specifies the index of the new axis in the
+ dimensions of the result. For example, if ``axis=0`` it will be the first
+ dimension and if ``axis=-1`` it will be the last dimension.
.. versionadded:: 1.10.0
@@ -364,8 +368,10 @@ def stack(arrays, axis=0, out=None):
----------
arrays : sequence of array_like
Each array must have the same shape.
+
axis : int, optional
The axis in the result array along which the input arrays are stacked.
+
out : ndarray, optional
If provided, the destination to place the result. The shape must be
correct, matching that of what stack would have returned if no
@@ -406,7 +412,10 @@ def stack(arrays, axis=0, out=None):
[3, 4]])
"""
- _warn_for_nonsequence(arrays)
+ if not overrides.ARRAY_FUNCTION_ENABLED:
+ # raise warning if necessary
+ _arrays_for_stack_dispatcher(arrays, stacklevel=2)
+
arrays = [asanyarray(arr) for arr in arrays]
if not arrays:
raise ValueError('need at least one array to stack')
@@ -423,6 +432,14 @@ def stack(arrays, axis=0, out=None):
return _nx.concatenate(expanded_arrays, axis=axis, out=out)
+# Internal functions to eliminate the overhead of repeated dispatch in one of
+# the two possible paths inside np.block.
+# Use getattr to protect against __array_function__ being disabled.
+_size = getattr(_nx.size, '__wrapped__', _nx.size)
+_ndim = getattr(_nx.ndim, '__wrapped__', _nx.ndim)
+_concatenate = getattr(_nx.concatenate, '__wrapped__', _nx.concatenate)
+
+
def _block_format_index(index):
"""
Convert a list of indices ``[0, 1, 2]`` into ``"arrays[0][1][2]"``.
@@ -503,8 +520,8 @@ def _block_check_depths_match(arrays, parent_index=[]):
return parent_index + [None], 0, 0
else:
# We've 'bottomed out' - arrays is either a scalar or an array
- size = _nx.size(arrays)
- return parent_index, _nx.ndim(arrays), size
+ size = _size(arrays)
+ return parent_index, _ndim(arrays), size
def _atleast_nd(a, ndim):
@@ -551,10 +568,10 @@ def _concatenate_shapes(shapes, axis):
ret[(slice(None),) * axis + sl_c] == c
```
- Thses are called slice prefixes since they are used in the recursive
+ These are called slice prefixes since they are used in the recursive
blocking algorithm to compute the left-most slices during the
recursion. Therefore, they must be prepended to rest of the slice
- that was computed deeper in the recusion.
+ that was computed deeper in the recursion.
These are returned as tuples to ensure that they can quickly be added
to existing slice tuple without creating a new tuple everytime.
@@ -647,7 +664,7 @@ def _block(arrays, max_depth, result_ndim, depth=0):
if depth < max_depth:
arrs = [_block(arr, max_depth, result_ndim, depth+1)
for arr in arrays]
- return _nx.concatenate(arrs, axis=-(max_depth-depth))
+ return _concatenate(arrs, axis=-(max_depth-depth))
else:
# We've 'bottomed out' - arrays is either a scalar or an array
# type(arrays) is not list
@@ -761,11 +778,11 @@ def block(arrays):
... [A, np.zeros((2, 3))],
... [np.ones((3, 2)), B ]
... ])
- array([[ 2., 0., 0., 0., 0.],
- [ 0., 2., 0., 0., 0.],
- [ 1., 1., 3., 0., 0.],
- [ 1., 1., 0., 3., 0.],
- [ 1., 1., 0., 0., 3.]])
+ array([[2., 0., 0., 0., 0.],
+ [0., 2., 0., 0., 0.],
+ [1., 1., 3., 0., 0.],
+ [1., 1., 0., 3., 0.],
+ [1., 1., 0., 0., 3.]])
With a list of depth 1, `block` can be used as `hstack`
@@ -775,7 +792,7 @@ def block(arrays):
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.block([a, b, 10]) # hstack([a, b, 10])
- array([1, 2, 3, 2, 3, 4, 10])
+ array([ 1, 2, 3, 2, 3, 4, 10])
>>> A = np.ones((2, 2), int)
>>> B = 2 * A
@@ -837,9 +854,9 @@ def block(arrays):
return _block_concatenate(arrays, list_ndim, result_ndim)
-# Theses helper functions are mostly used for testing.
+# These helper functions are mostly used for testing.
# They allow us to write tests that directly call `_block_slicing`
-# or `_block_concatenate` wtihout blocking large arrays to forse the wisdom
+# or `_block_concatenate` without blocking large arrays to force the wisdom
# to trigger the desired path.
def _block_setup(arrays):
"""
@@ -865,7 +882,7 @@ def _block_slicing(arrays, list_ndim, result_ndim):
# Test preferring F only in the case that all input arrays are F
F_order = all(arr.flags['F_CONTIGUOUS'] for arr in arrays)
- C_order = all(arr.flags['C_CONTIGUOUS'] for arr in arrays)
+ C_order = all(arr.flags['C_CONTIGUOUS'] for arr in arrays)
order = 'F' if F_order and not C_order else 'C'
result = _nx.empty(shape=shape, dtype=dtype, order=order)
# Note: In a c implementation, the function
diff --git a/numpy/core/src/common/array_assign.c b/numpy/core/src/common/array_assign.c
index 02a423e3a..0ac1b01c6 100644
--- a/numpy/core/src/common/array_assign.c
+++ b/numpy/core/src/common/array_assign.c
@@ -79,7 +79,7 @@ broadcast_error: {
Py_DECREF(errmsg);
return -1;
- }
+ }
}
/* See array_assign.h for parameter documentation */
diff --git a/numpy/core/src/common/lowlevel_strided_loops.h b/numpy/core/src/common/lowlevel_strided_loops.h
index 5f139cffb..bacd27473 100644
--- a/numpy/core/src/common/lowlevel_strided_loops.h
+++ b/numpy/core/src/common/lowlevel_strided_loops.h
@@ -4,6 +4,9 @@
#include <npy_config.h>
#include "mem_overlap.h"
+/* For PyArray_ macros used below */
+#include "numpy/ndarrayobject.h"
+
/*
* NOTE: This API should remain private for the time being, to allow
* for further refinement. I think the 'aligned' mechanism
diff --git a/numpy/core/src/common/npy_sort.h.src b/numpy/core/src/common/npy_sort.h.src
index c31a82764..16a105499 100644
--- a/numpy/core/src/common/npy_sort.h.src
+++ b/numpy/core/src/common/npy_sort.h.src
@@ -36,9 +36,22 @@ static NPY_INLINE int npy_get_msb(npy_uintp unum)
int quicksort_@suff@(void *vec, npy_intp cnt, void *null);
int heapsort_@suff@(void *vec, npy_intp cnt, void *null);
int mergesort_@suff@(void *vec, npy_intp cnt, void *null);
+int timsort_@suff@(void *vec, npy_intp cnt, void *null);
int aquicksort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
int aheapsort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
int amergesort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
+int atimsort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
+
+/**end repeat**/
+
+/**begin repeat
+ *
+ * #suff = bool, byte, ubyte, short, ushort, int, uint, long, ulong,
+ * longlong, ulonglong#
+ */
+
+int radixsort_@suff@(void *vec, npy_intp cnt, void *null);
+int aradixsort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
/**end repeat**/
@@ -59,9 +72,11 @@ int amergesort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *null);
int quicksort_@suff@(void *vec, npy_intp cnt, void *arr);
int heapsort_@suff@(void *vec, npy_intp cnt, void *arr);
int mergesort_@suff@(void *vec, npy_intp cnt, void *arr);
+int timsort_@suff@(void *vec, npy_intp cnt, void *arr);
int aquicksort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
int aheapsort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
int amergesort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
+int atimsort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
/**end repeat**/
@@ -76,8 +91,10 @@ int amergesort_@suff@(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
int npy_quicksort(void *vec, npy_intp cnt, void *arr);
int npy_heapsort(void *vec, npy_intp cnt, void *arr);
int npy_mergesort(void *vec, npy_intp cnt, void *arr);
+int npy_timsort(void *vec, npy_intp cnt, void *arr);
int npy_aquicksort(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
int npy_aheapsort(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
int npy_amergesort(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
+int npy_atimsort(void *vec, npy_intp *ind, npy_intp cnt, void *arr);
#endif
diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c
index 21a60914e..addc9f006 100644
--- a/numpy/core/src/multiarray/alloc.c
+++ b/numpy/core/src/multiarray/alloc.c
@@ -25,14 +25,10 @@
#include <assert.h>
-#ifdef NPY_OS_LINUX
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
-#ifndef MADV_HUGEPAGE
-/*
- * Use code 14 (MADV_HUGEPAGE) if it isn't defined. This gives a chance of
- * enabling huge pages even if built with linux kernel < 2.6.38
- */
-#define MADV_HUGEPAGE 14
+#if defined MADV_HUGEPAGE && defined HAVE_MADVISE
+#define HAVE_MADV_HUGEPAGE
#endif
#endif
@@ -78,15 +74,11 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
#ifdef _PyPyGC_AddMemoryPressure
_PyPyPyGC_AddMemoryPressure(nelem * esz);
#endif
-#ifdef NPY_OS_LINUX
+#ifdef HAVE_MADV_HUGEPAGE
/* allow kernel allocating huge pages for large arrays */
if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u)))) {
npy_uintp offset = 4096u - (npy_uintp)p % (4096u);
npy_uintp length = nelem * esz - offset;
- /**
- * Intentionally not checking for errors that may be returned by
- * older kernel versions; optimistically tries enabling huge pages.
- */
madvise((void*)((npy_uintp)p + offset), length, MADV_HUGEPAGE);
}
#endif
@@ -226,6 +218,7 @@ PyDataMem_NEW(size_t size)
{
void *result;
+ assert(size != 0);
result = malloc(size);
if (_PyDataMem_eventhook != NULL) {
NPY_ALLOW_C_API_DEF
@@ -289,6 +282,7 @@ PyDataMem_RENEW(void *ptr, size_t size)
{
void *result;
+ assert(size != 0);
result = realloc(ptr, size);
if (result != ptr) {
PyTraceMalloc_Untrack(NPY_TRACE_DOMAIN, (npy_uintp)ptr);
diff --git a/numpy/core/src/multiarray/array_assign_array.c b/numpy/core/src/multiarray/array_assign_array.c
index b9c1e1be7..7ff33ebd7 100644
--- a/numpy/core/src/multiarray/array_assign_array.c
+++ b/numpy/core/src/multiarray/array_assign_array.c
@@ -24,7 +24,10 @@
#include "array_assign.h"
-/* Check both uint and true alignment */
+/*
+ * Check that array data is both uint-aligned and true-aligned for all array
+ * elements, as required by the copy/casting code in lowlevel_strided_loops.c
+ */
NPY_NO_EXPORT int
copycast_isaligned(int ndim, npy_intp *shape,
PyArray_Descr *dtype, char *data, npy_intp *strides)
@@ -40,6 +43,12 @@ copycast_isaligned(int ndim, npy_intp *shape,
return 0;
}
+ /*
+ * As an optimization, it is unnecessary to check the alignment to the
+ * smaller of (uint_aln, true_aln) if the data is aligned to the bigger of
+ * the two and the big is a multiple of the small aln. We check the bigger
+ * one first and only check the smaller if necessary.
+ */
if (true_aln >= uint_aln) {
big_aln = true_aln;
small_aln = uint_aln;
@@ -411,14 +420,14 @@ PyArray_AssignArray(PyArrayObject *dst, PyArrayObject *src,
/* A straightforward where-masked assignment */
/* Do the masked assignment with raw array iteration */
- if (raw_array_wheremasked_assign_array(
- PyArray_NDIM(dst), PyArray_DIMS(dst),
- PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
- PyArray_DESCR(src), PyArray_DATA(src), src_strides,
- PyArray_DESCR(wheremask), PyArray_DATA(wheremask),
- wheremask_strides) < 0) {
- goto fail;
- }
+ if (raw_array_wheremasked_assign_array(
+ PyArray_NDIM(dst), PyArray_DIMS(dst),
+ PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
+ PyArray_DESCR(src), PyArray_DATA(src), src_strides,
+ PyArray_DESCR(wheremask), PyArray_DATA(wheremask),
+ wheremask_strides) < 0) {
+ goto fail;
+ }
}
if (copied_src) {
diff --git a/numpy/core/src/multiarray/arrayfunction_override.c b/numpy/core/src/multiarray/arrayfunction_override.c
index e62b32ab2..62e597764 100644
--- a/numpy/core/src/multiarray/arrayfunction_override.c
+++ b/numpy/core/src/multiarray/arrayfunction_override.c
@@ -173,7 +173,7 @@ array_function_method_impl(PyObject *func, PyObject *types, PyObject *args,
}
}
- implementation = PyObject_GetAttr(func, npy_ma_str_wrapped);
+ implementation = PyObject_GetAttr(func, npy_ma_str_implementation);
if (implementation == NULL) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c
index d20dd639d..bbb736fd0 100644
--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -655,13 +655,11 @@ NPY_NO_EXPORT int
array_might_be_written(PyArrayObject *obj)
{
const char *msg =
- "Numpy has detected that you (may be) writing to an array returned\n"
- "by numpy.diagonal. This code will likely break in a future numpy\n"
- "release -- see numpy.diagonal docs for details. The quick fix is\n"
- "to make an explicit copy (e.g., do arr.diagonal().copy()).";
+ "Numpy has detected that you (may be) writing to an array with\n"
+ "overlapping memory from np.broadcast_arrays. If this is intentional\n"
+ "set the WRITEABLE flag True or make a copy immediately before writing.";
if (PyArray_FLAGS(obj) & NPY_ARRAY_WARN_ON_WRITE) {
- /* 2012-07-17, 1.7 */
- if (DEPRECATE_FUTUREWARNING(msg) < 0) {
+ if (DEPRECATE(msg) < 0) {
return -1;
}
/* Only warn once per array */
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index d921b9d90..c586a0b1d 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -2260,7 +2260,7 @@ VOID_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
char *dstptr, *srcptr;
/*
* In certain cases subarray copy can be optimized. This is when
- * swapping is unecessary and the subarrays data type can certainly
+ * swapping is unnecessary and the subarrays data type can certainly
* be simply copied (no object, fields, subarray, and not a user dtype).
*/
npy_bool can_optimize_subarray = (!swap &&
@@ -2347,7 +2347,7 @@ VOID_copyswap (char *dst, char *src, int swap, PyArrayObject *arr)
int subitemsize;
/*
* In certain cases subarray copy can be optimized. This is when
- * swapping is unecessary and the subarrays data type can certainly
+ * swapping is unnecessary and the subarrays data type can certainly
* be simply copied (no object, fields, subarray, and not a user dtype).
*/
npy_bool can_optimize_subarray = (!swap &&
@@ -3810,176 +3810,6 @@ static void
/*
*****************************************************************************
- ** FASTCLIP **
- *****************************************************************************
- */
-
-#define _LESS_THAN(a, b) ((a) < (b))
-#define _GREATER_THAN(a, b) ((a) > (b))
-
-/*
- * In fastclip, 'b' was already checked for NaN, so the half comparison
- * only needs to check 'a' for NaN.
- */
-
-#define _HALF_LESS_THAN(a, b) (!npy_half_isnan(a) && npy_half_lt_nonan(a, b))
-#define _HALF_GREATER_THAN(a, b) (!npy_half_isnan(a) && npy_half_lt_nonan(b, a))
-
-/**begin repeat
- *
- * #name = BOOL,
- * BYTE, UBYTE, SHORT, USHORT, INT, UINT,
- * LONG, ULONG, LONGLONG, ULONGLONG,
- * HALF, FLOAT, DOUBLE, LONGDOUBLE,
- * DATETIME, TIMEDELTA#
- * #type = npy_bool,
- * npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- * npy_long, npy_ulong, npy_longlong, npy_ulonglong,
- * npy_half, npy_float, npy_double, npy_longdouble,
- * npy_datetime, npy_timedelta#
- * #isfloat = 0*11, 1*4, 0*2#
- * #isnan = nop*11, npy_half_isnan, npy_isnan*3, nop*2#
- * #lt = _LESS_THAN*11, _HALF_LESS_THAN, _LESS_THAN*5#
- * #gt = _GREATER_THAN*11, _HALF_GREATER_THAN, _GREATER_THAN*5#
- */
-static void
-@name@_fastclip(@type@ *in, npy_intp ni, @type@ *min, @type@ *max, @type@ *out)
-{
- npy_intp i;
- @type@ max_val = 0, min_val = 0;
-
- if (max != NULL) {
- max_val = *max;
-#if @isfloat@
- /* NaNs result in no clipping, so optimize the case away */
- if (@isnan@(max_val)) {
- if (min == NULL) {
- memmove(out, in, ni * sizeof(@type@));
- return;
- }
- max = NULL;
- }
-#endif
- }
- if (min != NULL) {
- min_val = *min;
-#if @isfloat@
- if (@isnan@(min_val)) {
- if (max == NULL) {
- memmove(out, in, ni * sizeof(@type@));
- return;
- }
- min = NULL;
- }
-#endif
- }
- if (max == NULL) {
- for (i = 0; i < ni; i++) {
- if (@lt@(in[i], min_val)) {
- out[i] = min_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
- else if (min == NULL) {
- for (i = 0; i < ni; i++) {
- if (@gt@(in[i], max_val)) {
- out[i] = max_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
- else {
- /*
- * Visual Studio 2015 loop vectorizer handles NaN in an unexpected
- * manner, see: https://github.com/numpy/numpy/issues/7601
- */
- #if (_MSC_VER == 1900)
- #pragma loop( no_vector )
- #endif
- for (i = 0; i < ni; i++) {
- if (@lt@(in[i], min_val)) {
- out[i] = min_val;
- }
- else if (@gt@(in[i], max_val)) {
- out[i] = max_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
-}
-/**end repeat**/
-
-#undef _LESS_THAN
-#undef _GREATER_THAN
-#undef _HALF_LESS_THAN
-#undef _HALF_GREATER_THAN
-
-/**begin repeat
- *
- * #name = CFLOAT, CDOUBLE, CLONGDOUBLE#
- * #type = npy_cfloat, npy_cdouble, npy_clongdouble#
- */
-static void
-@name@_fastclip(@type@ *in, npy_intp ni, @type@ *min, @type@ *max, @type@ *out)
-{
- npy_intp i;
- @type@ max_val, min_val;
-
- if (max != NULL) {
- max_val = *max;
- }
- if (min != NULL) {
- min_val = *min;
- }
- if (max == NULL) {
- for (i = 0; i < ni; i++) {
- if (PyArray_CLT(in[i],min_val)) {
- out[i] = min_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
- else if (min == NULL) {
- for (i = 0; i < ni; i++) {
- if (PyArray_CGT(in[i], max_val)) {
- out[i] = max_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
- else {
- for (i = 0; i < ni; i++) {
- if (PyArray_CLT(in[i], min_val)) {
- out[i] = min_val;
- }
- else if (PyArray_CGT(in[i], max_val)) {
- out[i] = max_val;
- }
- else {
- out[i] = in[i];
- }
- }
- }
-}
-
-/**end repeat**/
-
-#define OBJECT_fastclip NULL
-
-
-/*
- *****************************************************************************
** FASTPUTMASK **
*****************************************************************************
*/
@@ -4332,12 +4162,12 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
{
quicksort_@suff@,
heapsort_@suff@,
- mergesort_@suff@
+ timsort_@suff@
},
{
aquicksort_@suff@,
aheapsort_@suff@,
- amergesort_@suff@
+ atimsort_@suff@
},
#else
{
@@ -4417,6 +4247,7 @@ static PyArray_Descr @from@_Descr = {
* npy_half, npy_float, npy_double, npy_longdouble,
* npy_cfloat, npy_cdouble, npy_clongdouble,
* PyObject *, npy_datetime, npy_timedelta#
+ * #rsort = 1*5, 0*16#
* #NAME = Bool,
* Byte, UByte, Short, UShort, Int, UInt,
* Long, ULong, LongLong, ULongLong,
@@ -4473,12 +4304,20 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
{
quicksort_@suff@,
heapsort_@suff@,
- mergesort_@suff@
+ #if @rsort@
+ radixsort_@suff@
+ #else
+ timsort_@suff@
+ #endif
},
{
aquicksort_@suff@,
aheapsort_@suff@,
- amergesort_@suff@
+ #if @rsort@
+ aradixsort_@suff@
+ #else
+ atimsort_@suff@
+ #endif
},
#else
{
@@ -4492,7 +4331,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
(PyArray_ScalarKindFunc*)NULL,
NULL,
NULL,
- (PyArray_FastClipFunc*)@from@_fastclip,
+ (PyArray_FastClipFunc*)NULL,
(PyArray_FastPutmaskFunc*)@from@_fastputmask,
(PyArray_FastTakeFunc*)@from@_fasttake,
(PyArray_ArgFunc*)@from@_argmin
@@ -4575,7 +4414,17 @@ PyArray_DescrFromType(int type)
{
PyArray_Descr *ret = NULL;
- if (type < NPY_NTYPES) {
+ if (type < 0) {
+ /*
+ * It's not valid for type to be less than 0.
+ * If that happens, then no other branch of
+ * this if/else chain should be followed.
+ * This is effectively a no-op that ensures
+ * the default error is raised.
+ */
+ ret = NULL;
+ }
+ else if (type < NPY_NTYPES) {
ret = _builtin_descrs[type];
}
else if (type == NPY_NOTYPE) {
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index d8ad80266..b729027ad 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -771,17 +771,6 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
goto fail;
}
}
- /*
- * If a read-only buffer is requested on a read-write array, we return a
- * read-write buffer, which is dubious behavior. But that's why this call
- * is guarded by PyArray_ISWRITEABLE rather than (flags &
- * PyBUF_WRITEABLE).
- */
- if (PyArray_ISWRITEABLE(self)) {
- if (array_might_be_written(self) < 0) {
- goto fail;
- }
- }
if (view == NULL) {
PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
@@ -797,7 +786,17 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
view->buf = PyArray_DATA(self);
view->suboffsets = NULL;
view->itemsize = PyArray_ITEMSIZE(self);
- view->readonly = !PyArray_ISWRITEABLE(self);
+ /*
+ * If a read-only buffer is requested on a read-write array, we return a
+ * read-write buffer as per buffer protocol.
+ * We set a requested buffer to readonly also if the array will be readonly
+ * after a deprecation. This jumps the deprecation, but avoiding the
+ * warning is not convenient here. A warning is given if a writeable
+ * buffer is requested since `PyArray_FailUnlessWriteable` is called above
+ * (and clears the `NPY_ARRAY_WARN_ON_WRITE` flag).
+ */
+ view->readonly = (!PyArray_ISWRITEABLE(self) ||
+ PyArray_CHKFLAGS(self, NPY_ARRAY_WARN_ON_WRITE));
view->internal = NULL;
view->len = PyArray_NBYTES(self);
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c
index 90ee2c5b2..1d72a5227 100644
--- a/numpy/core/src/multiarray/calculation.c
+++ b/numpy/core/src/multiarray/calculation.c
@@ -918,6 +918,27 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
}
func = PyArray_DESCR(self)->f->fastclip;
+ if (func == NULL) {
+ if (min == NULL) {
+ return PyObject_CallFunctionObjArgs(n_ops.minimum, self, max, out, NULL);
+ }
+ else if (max == NULL) {
+ return PyObject_CallFunctionObjArgs(n_ops.maximum, self, min, out, NULL);
+ }
+ else {
+ return PyObject_CallFunctionObjArgs(n_ops.clip, self, min, max, out, NULL);
+ }
+ }
+
+ /* NumPy 1.17.0, 2019-02-24 */
+ if (DEPRECATE(
+ "->f->fastclip is deprecated. Use PyUFunc_RegisterLoopForDescr to "
+ "attach a custom loop to np.core.umath.clip, np.minimum, and "
+ "np.maximum") < 0) {
+ return NULL;
+ }
+ /* everything below can be removed once this deprecation completes */
+
if (func == NULL
|| (min != NULL && !PyArray_CheckAnyScalar(min))
|| (max != NULL && !PyArray_CheckAnyScalar(max))
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 8e167a37e..a17d77586 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -632,8 +632,18 @@ _IsWriteable(PyArrayObject *ap)
ap = (PyArrayObject *)base;
base = PyArray_BASE(ap);
+ if (PyArray_ISWRITEABLE(ap)) {
+ /*
+ * If any base is writeable, it must be OK to switch, note that
+ * bases are typically collapsed to always point to the most
+ * general one.
+ */
+ return NPY_TRUE;
+ }
+
if (base == NULL || PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA)) {
- return (npy_bool) PyArray_ISWRITEABLE(ap);
+ /* there is no further base to test the writeable flag for */
+ return NPY_FALSE;
}
assert(!PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA));
}
diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h
index 0e162903d..487d530a1 100644
--- a/numpy/core/src/multiarray/common.h
+++ b/numpy/core/src/multiarray/common.h
@@ -149,7 +149,7 @@ check_and_adjust_axis_msg(int *axis, int ndim, PyObject *msg_prefix)
PyObject *exc;
if (AxisError_cls == NULL) {
- PyObject *mod = PyImport_ImportModule("numpy.core._internal");
+ PyObject *mod = PyImport_ImportModule("numpy.core._exceptions");
if (mod != NULL) {
AxisError_cls = PyObject_GetAttrString(mod, "AxisError");
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index 625028bfb..dc79bfa09 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -567,6 +567,7 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
if (lenxp <= lenx) {
slopes = PyArray_malloc((lenxp - 1) * sizeof(npy_double));
if (slopes == NULL) {
+ PyErr_NoMemory();
goto fail;
}
}
@@ -602,9 +603,18 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
dres[i] = dy[j];
}
else {
- const npy_double slope = (slopes != NULL) ? slopes[j] :
- (dy[j+1] - dy[j]) / (dx[j+1] - dx[j]);
+ const npy_double slope =
+ (slopes != NULL) ? slopes[j] :
+ (dy[j+1] - dy[j]) / (dx[j+1] - dx[j]);
+
+ /* If we get nan in one direction, try the other */
dres[i] = slope*(x_val - dx[j]) + dy[j];
+ if (NPY_UNLIKELY(npy_isnan(dres[i]))) {
+ dres[i] = slope*(x_val - dx[j+1]) + dy[j+1];
+ if (NPY_UNLIKELY(npy_isnan(dres[i])) && dy[j] == dy[j+1]) {
+ dres[i] = dy[j];
+ }
+ }
}
}
@@ -736,6 +746,7 @@ arr_interp_complex(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
if (lenxp <= lenx) {
slopes = PyArray_malloc((lenxp - 1) * sizeof(npy_cdouble));
if (slopes == NULL) {
+ PyErr_NoMemory();
goto fail;
}
}
@@ -774,16 +785,32 @@ arr_interp_complex(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
dres[i] = dy[j];
}
else {
- if (slopes!=NULL) {
- dres[i].real = slopes[j].real*(x_val - dx[j]) + dy[j].real;
- dres[i].imag = slopes[j].imag*(x_val - dx[j]) + dy[j].imag;
+ npy_cdouble slope;
+ if (slopes != NULL) {
+ slope = slopes[j];
}
else {
const npy_double inv_dx = 1.0 / (dx[j+1] - dx[j]);
- dres[i].real = (dy[j+1].real - dy[j].real)*(x_val - dx[j])*
- inv_dx + dy[j].real;
- dres[i].imag = (dy[j+1].imag - dy[j].imag)*(x_val - dx[j])*
- inv_dx + dy[j].imag;
+ slope.real = (dy[j+1].real - dy[j].real) * inv_dx;
+ slope.imag = (dy[j+1].imag - dy[j].imag) * inv_dx;
+ }
+
+ /* If we get nan in one direction, try the other */
+ dres[i].real = slope.real*(x_val - dx[j]) + dy[j].real;
+ if (NPY_UNLIKELY(npy_isnan(dres[i].real))) {
+ dres[i].real = slope.real*(x_val - dx[j+1]) + dy[j+1].real;
+ if (NPY_UNLIKELY(npy_isnan(dres[i].real)) &&
+ dy[j].real == dy[j+1].real) {
+ dres[i].real = dy[j].real;
+ }
+ }
+ dres[i].imag = slope.imag*(x_val - dx[j]) + dy[j].imag;
+ if (NPY_UNLIKELY(npy_isnan(dres[i].imag))) {
+ dres[i].imag = slope.imag*(x_val - dx[j+1]) + dy[j+1].imag;
+ if (NPY_UNLIKELY(npy_isnan(dres[i].imag)) &&
+ dy[j].imag == dy[j+1].imag) {
+ dres[i].imag = dy[j].imag;
+ }
}
}
}
@@ -805,17 +832,63 @@ fail:
return NULL;
}
+static const char *EMPTY_SEQUENCE_ERR_MSG = "indices must be integral: the provided " \
+ "empty sequence was inferred as float. Wrap it with " \
+ "'np.array(indices, dtype=np.intp)'";
+
+static const char *NON_INTEGRAL_ERROR_MSG = "only int indices permitted";
+
+/* Convert obj to an ndarray with integer dtype or fail */
+static PyArrayObject *
+astype_anyint(PyObject *obj) {
+ PyArrayObject *ret;
+
+ if (!PyArray_Check(obj)) {
+ /* prefer int dtype */
+ PyArray_Descr *dtype_guess = NULL;
+ if (PyArray_DTypeFromObject(obj, NPY_MAXDIMS, &dtype_guess) < 0) {
+ return NULL;
+ }
+ if (dtype_guess == NULL) {
+ if (PySequence_Check(obj) && PySequence_Size(obj) == 0) {
+ PyErr_SetString(PyExc_TypeError, EMPTY_SEQUENCE_ERR_MSG);
+ }
+ return NULL;
+ }
+ ret = (PyArrayObject*)PyArray_FromAny(obj, dtype_guess, 0, 0, 0, NULL);
+ if (ret == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ ret = (PyArrayObject *)obj;
+ Py_INCREF(ret);
+ }
+
+ if (!(PyArray_ISINTEGER(ret) || PyArray_ISBOOL(ret))) {
+ /* ensure dtype is int-based */
+ PyErr_SetString(PyExc_TypeError, NON_INTEGRAL_ERROR_MSG);
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
/*
* Converts a Python sequence into 'count' PyArrayObjects
*
- * seq - Input Python object, usually a tuple but any sequence works.
- * op - Where the arrays are placed.
- * count - How many arrays there should be (errors if it doesn't match).
- * paramname - The name of the parameter that produced 'seq'.
+ * seq - Input Python object, usually a tuple but any sequence works.
+ * Must have integral content.
+ * paramname - The name of the parameter that produced 'seq'.
+ * count - How many arrays there should be (errors if it doesn't match).
+ * op - Where the arrays are placed.
*/
-static int sequence_to_arrays(PyObject *seq,
- PyArrayObject **op, int count,
- char *paramname)
+static int int_sequence_to_arrays(PyObject *seq,
+ char *paramname,
+ int count,
+ PyArrayObject **op
+ )
{
int i;
@@ -829,30 +902,26 @@ static int sequence_to_arrays(PyObject *seq,
for (i = 0; i < count; ++i) {
PyObject *item = PySequence_GetItem(seq, i);
if (item == NULL) {
- while (--i >= 0) {
- Py_DECREF(op[i]);
- op[i] = NULL;
- }
- return -1;
+ goto fail;
}
-
- op[i] = (PyArrayObject *)PyArray_FROM_O(item);
+ op[i] = astype_anyint(item);
+ Py_DECREF(item);
if (op[i] == NULL) {
- while (--i >= 0) {
- Py_DECREF(op[i]);
- op[i] = NULL;
- }
- Py_DECREF(item);
- return -1;
+ goto fail;
}
-
- Py_DECREF(item);
}
return 0;
+
+fail:
+ while (--i >= 0) {
+ Py_XDECREF(op[i]);
+ op[i] = NULL;
+ }
+ return -1;
}
-/* Inner loop for unravel_index */
+/* Inner loop for ravel_multi_index */
static int
ravel_multi_index_loop(int ravel_ndim, npy_intp *ravel_dims,
npy_intp *ravel_strides,
@@ -996,11 +1065,10 @@ arr_ravel_multi_index(PyObject *self, PyObject *args, PyObject *kwds)
}
/* Get the multi_index into op */
- if (sequence_to_arrays(coords0, op, dimensions.len, "multi_index") < 0) {
+ if (int_sequence_to_arrays(coords0, "multi_index", dimensions.len, op) < 0) {
goto fail;
}
-
for (i = 0; i < dimensions.len; ++i) {
op_flags[i] = NPY_ITER_READONLY|
NPY_ITER_ALIGNED;
@@ -1067,67 +1135,44 @@ fail:
return NULL;
}
-/* C-order inner loop for unravel_index */
-static int
-unravel_index_loop_corder(int unravel_ndim, npy_intp *unravel_dims,
- npy_intp unravel_size, npy_intp count,
- char *indices, npy_intp indices_stride,
- npy_intp *coords)
-{
- int i;
- char invalid;
- npy_intp val;
- NPY_BEGIN_ALLOW_THREADS;
- invalid = 0;
- while (count--) {
- val = *(npy_intp *)indices;
- if (val < 0 || val >= unravel_size) {
- invalid = 1;
- break;
- }
- for (i = unravel_ndim-1; i >= 0; --i) {
- coords[i] = val % unravel_dims[i];
- val /= unravel_dims[i];
- }
- coords += unravel_ndim;
- indices += indices_stride;
- }
- NPY_END_ALLOW_THREADS;
- if (invalid) {
- PyErr_Format(PyExc_ValueError,
- "index %" NPY_INTP_FMT " is out of bounds for array with size "
- "%" NPY_INTP_FMT,
- val, unravel_size
- );
- return NPY_FAIL;
- }
- return NPY_SUCCEED;
-}
-
-/* Fortran-order inner loop for unravel_index */
+/*
+ * Inner loop for unravel_index
+ * order must be NPY_CORDER or NPY_FORTRANORDER
+ */
static int
-unravel_index_loop_forder(int unravel_ndim, npy_intp *unravel_dims,
- npy_intp unravel_size, npy_intp count,
- char *indices, npy_intp indices_stride,
- npy_intp *coords)
+unravel_index_loop(int unravel_ndim, npy_intp *unravel_dims,
+ npy_intp unravel_size, npy_intp count,
+ char *indices, npy_intp indices_stride,
+ npy_intp *coords, NPY_ORDER order)
{
- int i;
- char invalid;
- npy_intp val;
+ int i, idx;
+ int idx_start = (order == NPY_CORDER) ? unravel_ndim - 1: 0;
+ int idx_step = (order == NPY_CORDER) ? -1 : 1;
+ char invalid = 0;
+ npy_intp val = 0;
NPY_BEGIN_ALLOW_THREADS;
- invalid = 0;
+ /* NPY_KEEPORDER or NPY_ANYORDER have no meaning in this setting */
+ assert(order == NPY_CORDER || order == NPY_FORTRANORDER);
while (count--) {
val = *(npy_intp *)indices;
if (val < 0 || val >= unravel_size) {
invalid = 1;
break;
}
+ idx = idx_start;
for (i = 0; i < unravel_ndim; ++i) {
- *coords++ = val % unravel_dims[i];
- val /= unravel_dims[i];
+ /*
+ * Using a local seems to enable single-divide optimization
+ * but only if the / precedes the %
+ */
+ npy_intp tmp = val / unravel_dims[idx];
+ coords[idx] = val % unravel_dims[idx];
+ val = tmp;
+ idx += idx_step;
}
+ coords += unravel_ndim;
indices += indices_stride;
}
NPY_END_ALLOW_THREADS;
@@ -1146,11 +1191,12 @@ unravel_index_loop_forder(int unravel_ndim, npy_intp *unravel_dims,
NPY_NO_EXPORT PyObject *
arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *indices0 = NULL, *ret_tuple = NULL;
+ PyObject *indices0 = NULL;
+ PyObject *ret_tuple = NULL;
PyArrayObject *ret_arr = NULL;
PyArrayObject *indices = NULL;
PyArray_Descr *dtype = NULL;
- PyArray_Dims dimensions={0,0};
+ PyArray_Dims dimensions = {0, 0};
NPY_ORDER order = NPY_CORDER;
npy_intp unravel_size;
@@ -1171,7 +1217,7 @@ arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds)
* if "dims" is detected in keywords, then replace it with
* the new "shape" argument and continue processing as usual.
*/
- if (kwds) {
+ if (kwds) {
PyObject *dims_item, *shape_item;
dims_item = PyDict_GetItemString(kwds, "dims");
shape_item = PyDict_GetItemString(kwds, "shape");
@@ -1193,17 +1239,17 @@ arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds)
goto fail;
}
- unravel_size = PyArray_MultiplyList(dimensions.ptr, dimensions.len);
-
- if (!PyArray_Check(indices0)) {
- indices = (PyArrayObject*)PyArray_FROM_O(indices0);
- if (indices == NULL) {
- goto fail;
- }
+ unravel_size = PyArray_OverflowMultiplyList(dimensions.ptr, dimensions.len);
+ if (unravel_size == -1) {
+ PyErr_SetString(PyExc_ValueError,
+ "dimensions are too large; arrays and shapes with "
+ "a total size greater than 'intp' are not supported.");
+ goto fail;
}
- else {
- indices = (PyArrayObject *)indices0;
- Py_INCREF(indices);
+
+ indices = astype_anyint(indices0);
+ if (indices == NULL) {
+ goto fail;
}
dtype = PyArray_DescrFromType(NPY_INTP);
@@ -1253,64 +1299,35 @@ arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds)
goto fail;
}
- if (order == NPY_CORDER) {
- if (NpyIter_GetIterSize(iter) != 0) {
- NpyIter_IterNextFunc *iternext;
- char **dataptr;
- npy_intp *strides;
- npy_intp *countptr, count;
- npy_intp *coordsptr = (npy_intp *)PyArray_DATA(ret_arr);
+ if (order != NPY_CORDER && order != NPY_FORTRANORDER) {
+ PyErr_SetString(PyExc_ValueError,
+ "only 'C' or 'F' order is permitted");
+ goto fail;
+ }
+ if (NpyIter_GetIterSize(iter) != 0) {
+ NpyIter_IterNextFunc *iternext;
+ char **dataptr;
+ npy_intp *strides;
+ npy_intp *countptr, count;
+ npy_intp *coordsptr = (npy_intp *)PyArray_DATA(ret_arr);
- iternext = NpyIter_GetIterNext(iter, NULL);
- if (iternext == NULL) {
- goto fail;
- }
- dataptr = NpyIter_GetDataPtrArray(iter);
- strides = NpyIter_GetInnerStrideArray(iter);
- countptr = NpyIter_GetInnerLoopSizePtr(iter);
-
- do {
- count = *countptr;
- if (unravel_index_loop_corder(dimensions.len, dimensions.ptr,
- unravel_size, count, *dataptr, *strides,
- coordsptr) != NPY_SUCCEED) {
- goto fail;
- }
- coordsptr += count*dimensions.len;
- } while(iternext(iter));
+ iternext = NpyIter_GetIterNext(iter, NULL);
+ if (iternext == NULL) {
+ goto fail;
}
- }
- else if (order == NPY_FORTRANORDER) {
- if (NpyIter_GetIterSize(iter) != 0) {
- NpyIter_IterNextFunc *iternext;
- char **dataptr;
- npy_intp *strides;
- npy_intp *countptr, count;
- npy_intp *coordsptr = (npy_intp *)PyArray_DATA(ret_arr);
+ dataptr = NpyIter_GetDataPtrArray(iter);
+ strides = NpyIter_GetInnerStrideArray(iter);
+ countptr = NpyIter_GetInnerLoopSizePtr(iter);
- iternext = NpyIter_GetIterNext(iter, NULL);
- if (iternext == NULL) {
+ do {
+ count = *countptr;
+ if (unravel_index_loop(dimensions.len, dimensions.ptr,
+ unravel_size, count, *dataptr, *strides,
+ coordsptr, order) != NPY_SUCCEED) {
goto fail;
}
- dataptr = NpyIter_GetDataPtrArray(iter);
- strides = NpyIter_GetInnerStrideArray(iter);
- countptr = NpyIter_GetInnerLoopSizePtr(iter);
-
- do {
- count = *countptr;
- if (unravel_index_loop_forder(dimensions.len, dimensions.ptr,
- unravel_size, count, *dataptr, *strides,
- coordsptr) != NPY_SUCCEED) {
- goto fail;
- }
- coordsptr += count*dimensions.len;
- } while(iternext(iter));
- }
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "only 'C' or 'F' order is permitted");
- goto fail;
+ coordsptr += count * dimensions.len;
+ } while (iternext(iter));
}
@@ -1494,7 +1511,8 @@ pack_inner(const char *inptr,
npy_intp in_stride,
char *outptr,
npy_intp n_out,
- npy_intp out_stride)
+ npy_intp out_stride,
+ char order)
{
/*
* Loop through the elements of inptr.
@@ -1514,9 +1532,13 @@ pack_inner(const char *inptr,
vn_out -= (vn_out & 1);
for (index = 0; index < vn_out; index += 2) {
unsigned int r;
- /* swap as packbits is "big endian", note x86 can load unaligned */
- npy_uint64 a = npy_bswap8(*(npy_uint64*)inptr);
- npy_uint64 b = npy_bswap8(*(npy_uint64*)(inptr + 8));
+ npy_uint64 a = *(npy_uint64*)inptr;
+ npy_uint64 b = *(npy_uint64*)(inptr + 8);
+ if (order == 'b') {
+ a = npy_bswap8(a);
+ b = npy_bswap8(b);
+ }
+ /* note x86 can load unaligned */
__m128i v = _mm_set_epi64(_m_from_int64(b), _m_from_int64(a));
/* false -> 0x00 and true -> 0xFF (there is no cmpneq) */
v = _mm_cmpeq_epi8(v, zero);
@@ -1536,30 +1558,45 @@ pack_inner(const char *inptr,
if (remain == 0) { /* assumes n_in > 0 */
remain = 8;
}
- /* don't reset index to handle remainder of above block */
+ /* Don't reset index. Just handle remainder of above block */
for (; index < n_out; index++) {
- char build = 0;
+ unsigned char build = 0;
int i, maxi;
npy_intp j;
maxi = (index == n_out - 1) ? remain : 8;
- for (i = 0; i < maxi; i++) {
- build <<= 1;
- for (j = 0; j < element_size; j++) {
- build |= (inptr[j] != 0);
+ if (order == 'b') {
+ for (i = 0; i < maxi; i++) {
+ build <<= 1;
+ for (j = 0; j < element_size; j++) {
+ build |= (inptr[j] != 0);
+ }
+ inptr += in_stride;
+ }
+ if (index == n_out - 1) {
+ build <<= 8 - remain;
}
- inptr += in_stride;
}
- if (index == n_out - 1) {
- build <<= 8 - remain;
+ else
+ {
+ for (i = 0; i < maxi; i++) {
+ build >>= 1;
+ for (j = 0; j < element_size; j++) {
+ build |= (inptr[j] != 0) ? 128 : 0;
+ }
+ inptr += in_stride;
+ }
+ if (index == n_out - 1) {
+ build >>= 8 - remain;
+ }
}
- *outptr = build;
+ *outptr = (char)build;
outptr += out_stride;
}
}
static PyObject *
-pack_bits(PyObject *input, int axis)
+pack_bits(PyObject *input, int axis, char order)
{
PyArrayObject *inp;
PyArrayObject *new = NULL;
@@ -1644,7 +1681,7 @@ pack_bits(PyObject *input, int axis)
pack_inner(PyArray_ITER_DATA(it), PyArray_ITEMSIZE(new),
PyArray_DIM(new, axis), PyArray_STRIDE(new, axis),
PyArray_ITER_DATA(ot), PyArray_DIM(out, axis),
- PyArray_STRIDE(out, axis));
+ PyArray_STRIDE(out, axis), order);
PyArray_ITER_NEXT(it);
PyArray_ITER_NEXT(ot);
}
@@ -1664,17 +1701,24 @@ fail:
}
static PyObject *
-unpack_bits(PyObject *input, int axis)
+unpack_bits(PyObject *input, int axis, PyObject *count_obj, char order)
{
static int unpack_init = 0;
- static char unpack_lookup[256][8];
+ /*
+ * lookuptable for bitorder big as it has been around longer
+ * bitorder little is handled via byteswapping in the loop
+ */
+ static union {
+ npy_uint8 bytes[8];
+ npy_uint64 uint64;
+ } unpack_lookup_big[256];
PyArrayObject *inp;
PyArrayObject *new = NULL;
PyArrayObject *out = NULL;
npy_intp outdims[NPY_MAXDIMS];
int i;
PyArrayIterObject *it, *ot;
- npy_intp n_in, in_stride, out_stride;
+ npy_intp count, in_n, in_tail, out_pad, in_stride, out_stride;
NPY_BEGIN_THREADS_DEF;
inp = (PyArrayObject *)PyArray_FROM_O(input);
@@ -1703,20 +1747,37 @@ unpack_bits(PyObject *input, int axis)
newdim.ptr = &shape;
temp = (PyArrayObject *)PyArray_Newshape(new, &newdim, NPY_CORDER);
+ Py_DECREF(new);
if (temp == NULL) {
- goto fail;
+ return NULL;
}
- Py_DECREF(new);
new = temp;
}
/* Setup output shape */
- for (i=0; i<PyArray_NDIM(new); i++) {
+ for (i = 0; i < PyArray_NDIM(new); i++) {
outdims[i] = PyArray_DIM(new, i);
}
/* Multiply axis dimension by 8 */
- outdims[axis] <<= 3;
+ outdims[axis] *= 8;
+ if (count_obj != Py_None) {
+ count = PyArray_PyIntAsIntp(count_obj);
+ if (error_converting(count)) {
+ goto fail;
+ }
+ if (count < 0) {
+ outdims[axis] += count;
+ if (outdims[axis] < 0) {
+ PyErr_Format(PyExc_ValueError,
+ "-count larger than number of elements");
+ goto fail;
+ }
+ }
+ else {
+ outdims[axis] = count;
+ }
+ }
/* Create output array */
out = (PyArrayObject *)PyArray_NewFromDescr(
@@ -1726,6 +1787,7 @@ unpack_bits(PyObject *input, int axis)
if (out == NULL) {
goto fail;
}
+
/* Setup iterators to iterate over all but given axis */
it = (PyArrayIterObject *)PyArray_IterAllButAxis((PyObject *)new, &axis);
ot = (PyArrayIterObject *)PyArray_IterAllButAxis((PyObject *)out, &axis);
@@ -1735,34 +1797,39 @@ unpack_bits(PyObject *input, int axis)
goto fail;
}
- /* setup lookup table under GIL, big endian 0..256 as bytes */
+ /*
+ * setup lookup table under GIL, 256 8 byte blocks representing 8 bits
+ * expanded to 1/0 bytes
+ */
if (unpack_init == 0) {
- npy_uint64 j;
- npy_uint64 * unpack_lookup_64 = (npy_uint64 *)unpack_lookup;
+ npy_intp j;
for (j=0; j < 256; j++) {
- npy_uint64 v = 0;
- v |= (npy_uint64)((j & 1) == 1);
- v |= (npy_uint64)((j & 2) == 2) << 8;
- v |= (npy_uint64)((j & 4) == 4) << 16;
- v |= (npy_uint64)((j & 8) == 8) << 24;
- v |= (npy_uint64)((j & 16) == 16) << 32;
- v |= (npy_uint64)((j & 32) == 32) << 40;
- v |= (npy_uint64)((j & 64) == 64) << 48;
- v |= (npy_uint64)((j & 128) == 128) << 56;
-#if NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN
- v = npy_bswap8(v);
-#endif
- unpack_lookup_64[j] = v;
+ npy_intp k;
+ for (k=0; k < 8; k++) {
+ npy_uint8 v = (j & (1 << k)) == (1 << k);
+ unpack_lookup_big[j].bytes[7 - k] = v;
+ }
}
unpack_init = 1;
}
- NPY_BEGIN_THREADS_THRESHOLDED(PyArray_DIM(new, axis));
+ count = PyArray_DIM(new, axis) * 8;
+ if (outdims[axis] > count) {
+ in_n = count / 8;
+ in_tail = 0;
+ out_pad = outdims[axis] - count;
+ }
+ else {
+ in_n = outdims[axis] / 8;
+ in_tail = outdims[axis] % 8;
+ out_pad = 0;
+ }
- n_in = PyArray_DIM(new, axis);
in_stride = PyArray_STRIDE(new, axis);
out_stride = PyArray_STRIDE(out, axis);
+ NPY_BEGIN_THREADS_THRESHOLDED(PyArray_Size((PyObject *)out) / 8);
+
while (PyArray_ITER_NOTDONE(it)) {
npy_intp index;
unsigned const char *inptr = PyArray_ITER_DATA(it);
@@ -1770,24 +1837,74 @@ unpack_bits(PyObject *input, int axis)
if (out_stride == 1) {
/* for unity stride we can just copy out of the lookup table */
- for (index = 0; index < n_in; index++) {
- memcpy(outptr, unpack_lookup[*inptr], 8);
- outptr += 8;
- inptr += in_stride;
+ if (order == 'b') {
+ for (index = 0; index < in_n; index++) {
+ npy_uint64 v = unpack_lookup_big[*inptr].uint64;
+ memcpy(outptr, &v, 8);
+ outptr += 8;
+ inptr += in_stride;
+ }
+ }
+ else {
+ for (index = 0; index < in_n; index++) {
+ npy_uint64 v = unpack_lookup_big[*inptr].uint64;
+ if (order != 'b') {
+ v = npy_bswap8(v);
+ }
+ memcpy(outptr, &v, 8);
+ outptr += 8;
+ inptr += in_stride;
+ }
+ }
+ /* Clean up the tail portion */
+ if (in_tail) {
+ npy_uint64 v = unpack_lookup_big[*inptr].uint64;
+ if (order != 'b') {
+ v = npy_bswap8(v);
+ }
+ memcpy(outptr, &v, in_tail);
+ }
+ /* Add padding */
+ else if (out_pad) {
+ memset(outptr, 0, out_pad);
}
}
else {
- for (index = 0; index < n_in; index++) {
- unsigned char mask = 128;
-
- for (i = 0; i < 8; i++) {
- *outptr = ((mask & (*inptr)) != 0);
+ if (order == 'b') {
+ for (index = 0; index < in_n; index++) {
+ for (i = 0; i < 8; i++) {
+ *outptr = ((*inptr & (128 >> i)) != 0);
+ outptr += out_stride;
+ }
+ inptr += in_stride;
+ }
+ /* Clean up the tail portion */
+ for (i = 0; i < in_tail; i++) {
+ *outptr = ((*inptr & (128 >> i)) != 0);
outptr += out_stride;
- mask >>= 1;
}
- inptr += in_stride;
+ }
+ else {
+ for (index = 0; index < in_n; index++) {
+ for (i = 0; i < 8; i++) {
+ *outptr = ((*inptr & (1 << i)) != 0);
+ outptr += out_stride;
+ }
+ inptr += in_stride;
+ }
+ /* Clean up the tail portion */
+ for (i = 0; i < in_tail; i++) {
+ *outptr = ((*inptr & (1 << i)) != 0);
+ outptr += out_stride;
+ }
+ }
+ /* Add padding */
+ for (index = 0; index < out_pad; index++) {
+ *outptr = 0;
+ outptr += out_stride;
}
}
+
PyArray_ITER_NEXT(it);
PyArray_ITER_NEXT(ot);
}
@@ -1811,25 +1928,49 @@ io_pack(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
{
PyObject *obj;
int axis = NPY_MAXDIMS;
- static char *kwlist[] = {"in", "axis", NULL};
+ static char *kwlist[] = {"in", "axis", "bitorder", NULL};
+ char c = 'b';
+ const char * order_str = NULL;
- if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&:pack" , kwlist,
- &obj, PyArray_AxisConverter, &axis)) {
+ if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&s:pack" , kwlist,
+ &obj, PyArray_AxisConverter, &axis, &order_str)) {
return NULL;
}
- return pack_bits(obj, axis);
+ if (order_str != NULL) {
+ if (strncmp(order_str, "little", 6) == 0)
+ c = 'l';
+ else if (strncmp(order_str, "big", 3) == 0)
+ c = 'b';
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "'order' must be either 'little' or 'big'");
+ return NULL;
+ }
+ }
+ return pack_bits(obj, axis, c);
}
+
NPY_NO_EXPORT PyObject *
io_unpack(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
{
PyObject *obj;
int axis = NPY_MAXDIMS;
- static char *kwlist[] = {"in", "axis", NULL};
+ PyObject *count = Py_None;
+ static char *kwlist[] = {"in", "axis", "count", "bitorder", NULL};
+ const char * c = NULL;
- if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&:unpack" , kwlist,
- &obj, PyArray_AxisConverter, &axis)) {
+ if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|O&Os:unpack" , kwlist,
+ &obj, PyArray_AxisConverter, &axis, &count, &c)) {
+ return NULL;
+ }
+ if (c == NULL) {
+ c = "b";
+ }
+ if (c[0] != 'l' && c[0] != 'b') {
+ PyErr_SetString(PyExc_ValueError,
+ "'order' must begin with 'l' or 'b'");
return NULL;
}
- return unpack_bits(obj, axis);
+ return unpack_bits(obj, axis, count, c[0]);
}
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index cef3c27ed..a370874a6 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -116,8 +116,8 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
return NPY_FAIL;
}
if (len > NPY_MAXDIMS) {
- PyErr_Format(PyExc_ValueError, "sequence too large; "
- "cannot be greater than %d", NPY_MAXDIMS);
+ PyErr_Format(PyExc_ValueError, "maximum supported dimension for an ndarray is %d"
+ ", found %d", NPY_MAXDIMS, len);
return NPY_FAIL;
}
if (len > 0) {
@@ -393,6 +393,11 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
char *str;
PyObject *tmp = NULL;
+ if (obj == Py_None) {
+ *sortkind = NPY_QUICKSORT;
+ return NPY_SUCCEED;
+ }
+
if (PyUnicode_Check(obj)) {
obj = tmp = PyUnicode_AsASCIIString(obj);
if (obj == NULL) {
@@ -401,6 +406,8 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
}
*sortkind = NPY_QUICKSORT;
+
+
str = PyBytes_AsString(obj);
if (!str) {
Py_XDECREF(tmp);
@@ -419,11 +426,23 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
*sortkind = NPY_HEAPSORT;
}
else if (str[0] == 'm' || str[0] == 'M') {
+ /*
+ * Mergesort is an alias for NPY_STABLESORT.
+ * That maintains backwards compatibility while
+ * allowing other types of stable sorts to be used.
+ */
*sortkind = NPY_MERGESORT;
}
else if (str[0] == 's' || str[0] == 'S') {
- /* mergesort is the only stable sorting method in numpy */
- *sortkind = NPY_MERGESORT;
+ /*
+ * NPY_STABLESORT is one of
+ *
+ * - mergesort
+ * - timsort
+ *
+ * Which one is used depends on the data type.
+ */
+ *sortkind = NPY_STABLESORT;
}
else {
PyErr_Format(PyExc_ValueError,
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index 3407c537c..025c66013 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -47,11 +47,10 @@ PyArray_CastToType(PyArrayObject *arr, PyArray_Descr *dtype, int is_f_order)
PyObject *out;
/* If the requested dtype is flexible, adapt it */
- PyArray_AdaptFlexibleDType((PyObject *)arr, PyArray_DESCR(arr), &dtype);
+ dtype = PyArray_AdaptFlexibleDType((PyObject *)arr, PyArray_DESCR(arr), dtype);
if (dtype == NULL) {
return NULL;
}
-
out = PyArray_NewFromDescr(Py_TYPE(arr), dtype,
PyArray_NDIM(arr),
PyArray_DIMS(arr),
@@ -128,9 +127,9 @@ PyArray_GetCastFunc(PyArray_Descr *descr, int type_num)
}
/*
- * This function calls Py_DECREF on flex_dtype, and replaces it with
- * a new dtype that has been adapted based on the values in data_dtype
- * and data_obj. If the flex_dtype is not flexible, it leaves it as is.
+ * This function returns a dtype based on flex_dtype and the values in
+ * data_dtype and data_obj. It also calls Py_DECREF on the flex_dtype. If the
+ * flex_dtype is not flexible, it returns it as-is.
*
* Usually, if data_obj is not an array, dtype should be the result
* given by the PyArray_GetArrayParamsFromObject function.
@@ -138,40 +137,37 @@ PyArray_GetCastFunc(PyArray_Descr *descr, int type_num)
* The data_obj may be NULL if just a dtype is known for the source.
*
* If *flex_dtype is NULL, returns immediately, without setting an
- * exception. This basically assumes an error was already set previously.
+ * exception, leaving any previous error handling intact.
*
* The current flexible dtypes include NPY_STRING, NPY_UNICODE, NPY_VOID,
* and NPY_DATETIME with generic units.
*/
-NPY_NO_EXPORT void
+NPY_NO_EXPORT PyArray_Descr *
PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
- PyArray_Descr **flex_dtype)
+ PyArray_Descr *flex_dtype)
{
PyArray_DatetimeMetaData *meta;
+ PyArray_Descr *retval = NULL;
int flex_type_num;
- if (*flex_dtype == NULL) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_RuntimeError,
- "NumPy AdaptFlexibleDType was called with NULL flex_dtype "
- "but no error set");
- }
- return;
+ if (flex_dtype == NULL) {
+ return retval;
}
- flex_type_num = (*flex_dtype)->type_num;
+ flex_type_num = flex_dtype->type_num;
/* Flexible types with expandable size */
- if (PyDataType_ISUNSIZED(*flex_dtype)) {
+ if (PyDataType_ISUNSIZED(flex_dtype)) {
/* First replace the flex_dtype */
- PyArray_DESCR_REPLACE(*flex_dtype);
- if (*flex_dtype == NULL) {
- return;
+ retval = PyArray_DescrNew(flex_dtype);
+ Py_DECREF(flex_dtype);
+ if (retval == NULL) {
+ return retval;
}
if (data_dtype->type_num == flex_type_num ||
flex_type_num == NPY_VOID) {
- (*flex_dtype)->elsize = data_dtype->elsize;
+ (retval)->elsize = data_dtype->elsize;
}
else if (flex_type_num == NPY_STRING || flex_type_num == NPY_UNICODE) {
npy_intp size = 8;
@@ -199,7 +195,7 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
}
else if (data_dtype->elsize > 8 ||
data_dtype->elsize < 0) {
- /*
+ /*
* Element size should never be greater than 8 or
* less than 0 for integer type, but just in case...
*/
@@ -237,9 +233,8 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
PyObject *s = PyObject_Str(list);
if (s == NULL) {
Py_DECREF(list);
- Py_DECREF(*flex_dtype);
- *flex_dtype = NULL;
- return;
+ Py_DECREF(retval);
+ return NULL;
}
else {
size = PyObject_Length(s);
@@ -262,9 +257,16 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
list = PyArray_ToList((PyArrayObject *)data_obj);
result = PyArray_GetArrayParamsFromObject(
list,
- *flex_dtype,
+ retval,
0, &dtype,
&ndim, dims, &arr, NULL);
+ Py_DECREF(list);
+ Py_XDECREF(arr);
+ if (result < 0) {
+ Py_XDECREF(dtype);
+ Py_DECREF(retval);
+ return NULL;
+ }
if (result == 0 && dtype != NULL) {
if (flex_type_num == NPY_UNICODE) {
size = dtype->elsize / 4;
@@ -274,15 +276,12 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
}
}
Py_XDECREF(dtype);
- Py_XDECREF(arr);
- Py_DECREF(list);
}
else if (PyArray_IsPythonScalar(data_obj)) {
PyObject *s = PyObject_Str(data_obj);
if (s == NULL) {
- Py_DECREF(*flex_dtype);
- *flex_dtype = NULL;
- return;
+ Py_DECREF(retval);
+ return NULL;
}
else {
size = PyObject_Length(s);
@@ -301,9 +300,8 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
case NPY_DATETIME:
meta = get_datetime_metadata_from_dtype(data_dtype);
if (meta == NULL) {
- Py_DECREF(*flex_dtype);
- *flex_dtype = NULL;
- return;
+ Py_DECREF(retval);
+ return NULL;
}
size = get_datetime_iso_8601_strlen(0, meta->base);
break;
@@ -313,10 +311,10 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
}
if (flex_type_num == NPY_STRING) {
- (*flex_dtype)->elsize = size;
+ retval->elsize = size;
}
else if (flex_type_num == NPY_UNICODE) {
- (*flex_dtype)->elsize = size * 4;
+ retval->elsize = size * 4;
}
}
else {
@@ -326,18 +324,17 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
*/
PyErr_SetString(PyExc_TypeError,
"don't know how to adapt flex dtype");
- *flex_dtype = NULL;
- return;
+ Py_DECREF(retval);
+ return NULL;
}
}
/* Flexible type with generic time unit that adapts */
else if (flex_type_num == NPY_DATETIME ||
flex_type_num == NPY_TIMEDELTA) {
- meta = get_datetime_metadata_from_dtype(*flex_dtype);
+ meta = get_datetime_metadata_from_dtype(flex_dtype);
+ retval = flex_dtype;
if (meta == NULL) {
- Py_DECREF(*flex_dtype);
- *flex_dtype = NULL;
- return;
+ return NULL;
}
if (meta->base == NPY_FR_GENERIC) {
@@ -345,22 +342,24 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
data_dtype->type_num == NPY_TIMEDELTA) {
meta = get_datetime_metadata_from_dtype(data_dtype);
if (meta == NULL) {
- Py_DECREF(*flex_dtype);
- *flex_dtype = NULL;
- return;
+ return NULL;
}
- Py_DECREF(*flex_dtype);
- *flex_dtype = create_datetime_dtype(flex_type_num, meta);
+ retval = create_datetime_dtype(flex_type_num, meta);
+ Py_DECREF(flex_dtype);
}
else if (data_obj != NULL) {
/* Detect the unit from the input's data */
- Py_DECREF(*flex_dtype);
- *flex_dtype = find_object_datetime_type(data_obj,
+ retval = find_object_datetime_type(data_obj,
flex_type_num);
+ Py_DECREF(flex_dtype);
}
}
}
+ else {
+ retval = flex_dtype;
+ }
+ return retval;
}
/*
@@ -518,7 +517,7 @@ PyArray_CanCastTo(PyArray_Descr *from, PyArray_Descr *to)
* stringified value of the object.
*/
else if (to_type_num == NPY_STRING || to_type_num == NPY_UNICODE) {
- /*
+ /*
* Boolean value cast to string type is 5 characters max
* for string 'False'.
*/
@@ -531,7 +530,7 @@ PyArray_CanCastTo(PyArray_Descr *from, PyArray_Descr *to)
if (PyDataType_ISUNSIZED(to)) {
ret = 1;
}
- /*
+ /*
* Need at least 5 characters to convert from boolean
* to 'True' or 'False'.
*/
@@ -1233,7 +1232,11 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
PyArray_Descr *ret = NULL;
PyArray_Descr *temp = PyArray_DescrNew(type1);
PyDataType_MAKEUNSIZED(temp);
- PyArray_AdaptFlexibleDType(NULL, type2, &temp);
+
+ temp = PyArray_AdaptFlexibleDType(NULL, type2, temp);
+ if (temp == NULL) {
+ return NULL;
+ }
if (temp->elsize > type1->elsize) {
ret = ensure_dtype_nbo(temp);
}
@@ -1271,7 +1274,10 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
PyArray_Descr *ret = NULL;
PyArray_Descr *temp = PyArray_DescrNew(type1);
PyDataType_MAKEUNSIZED(temp);
- PyArray_AdaptFlexibleDType(NULL, type2, &temp);
+ temp = PyArray_AdaptFlexibleDType(NULL, type2, temp);
+ if (temp == NULL) {
+ return NULL;
+ }
if (temp->elsize > type1->elsize) {
ret = ensure_dtype_nbo(temp);
}
@@ -1319,7 +1325,10 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
PyArray_Descr *ret = NULL;
PyArray_Descr *temp = PyArray_DescrNew(type2);
PyDataType_MAKEUNSIZED(temp);
- PyArray_AdaptFlexibleDType(NULL, type1, &temp);
+ temp = PyArray_AdaptFlexibleDType(NULL, type1, temp);
+ if (temp == NULL) {
+ return NULL;
+ }
if (temp->elsize > type2->elsize) {
ret = ensure_dtype_nbo(temp);
}
@@ -1336,7 +1345,10 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
PyArray_Descr *ret = NULL;
PyArray_Descr *temp = PyArray_DescrNew(type2);
PyDataType_MAKEUNSIZED(temp);
- PyArray_AdaptFlexibleDType(NULL, type1, &temp);
+ temp = PyArray_AdaptFlexibleDType(NULL, type1, temp);
+ if (temp == NULL) {
+ return NULL;
+ }
if (temp->elsize > type2->elsize) {
ret = ensure_dtype_nbo(temp);
}
@@ -1755,46 +1767,22 @@ dtype_kind_to_simplified_ordering(char kind)
}
}
-/*NUMPY_API
- * Produces the result type of a bunch of inputs, using the UFunc
- * type promotion rules. Use this function when you have a set of
- * input arrays, and need to determine an output array dtype.
- *
- * If all the inputs are scalars (have 0 dimensions) or the maximum "kind"
- * of the scalars is greater than the maximum "kind" of the arrays, does
- * a regular type promotion.
- *
- * Otherwise, does a type promotion on the MinScalarType
- * of all the inputs. Data types passed directly are treated as array
- * types.
- *
+
+/*
+ * Determine if there is a mix of scalars and arrays/dtypes.
+ * If this is the case, the scalars should be handled as the minimum type
+ * capable of holding the value when the maximum "category" of the scalars
+ * surpasses the maximum "category" of the arrays/dtypes.
+ * If the scalars are of a lower or same category as the arrays, they may be
+ * demoted to a lower type within their category (the lowest type they can
+ * be cast to safely according to scalar casting rules).
*/
-NPY_NO_EXPORT PyArray_Descr *
-PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
- npy_intp ndtypes, PyArray_Descr **dtypes)
+NPY_NO_EXPORT int
+should_use_min_scalar(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes)
{
- npy_intp i;
- int use_min_scalar;
-
- /* If there's just one type, pass it through */
- if (narrs + ndtypes == 1) {
- PyArray_Descr *ret = NULL;
- if (narrs == 1) {
- ret = PyArray_DESCR(arr[0]);
- }
- else {
- ret = dtypes[0];
- }
- Py_INCREF(ret);
- return ret;
- }
+ int use_min_scalar = 0;
- /*
- * Determine if there are any scalars, and if so, whether
- * the maximum "kind" of the scalars surpasses the maximum
- * "kind" of the arrays
- */
- use_min_scalar = 0;
if (narrs > 0) {
int all_scalars;
int max_scalar_kind = -1;
@@ -1803,7 +1791,7 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
all_scalars = (ndtypes > 0) ? 0 : 1;
/* Compute the maximum "kinds" and whether everything is scalar */
- for (i = 0; i < narrs; ++i) {
+ for (npy_intp i = 0; i < narrs; ++i) {
if (PyArray_NDIM(arr[i]) == 0) {
int kind = dtype_kind_to_simplified_ordering(
PyArray_DESCR(arr[i])->kind);
@@ -1824,7 +1812,7 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
* If the max scalar kind is bigger than the max array kind,
* finish computing the max array kind
*/
- for (i = 0; i < ndtypes; ++i) {
+ for (npy_intp i = 0; i < ndtypes; ++i) {
int kind = dtype_kind_to_simplified_ordering(dtypes[i]->kind);
if (kind > max_array_kind) {
max_array_kind = kind;
@@ -1836,6 +1824,44 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
use_min_scalar = 1;
}
}
+ return use_min_scalar;
+}
+
+
+/*NUMPY_API
+ * Produces the result type of a bunch of inputs, using the UFunc
+ * type promotion rules. Use this function when you have a set of
+ * input arrays, and need to determine an output array dtype.
+ *
+ * If all the inputs are scalars (have 0 dimensions) or the maximum "kind"
+ * of the scalars is greater than the maximum "kind" of the arrays, does
+ * a regular type promotion.
+ *
+ * Otherwise, does a type promotion on the MinScalarType
+ * of all the inputs. Data types passed directly are treated as array
+ * types.
+ *
+ */
+NPY_NO_EXPORT PyArray_Descr *
+PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes)
+{
+ npy_intp i;
+
+ /* If there's just one type, pass it through */
+ if (narrs + ndtypes == 1) {
+ PyArray_Descr *ret = NULL;
+ if (narrs == 1) {
+ ret = PyArray_DESCR(arr[0]);
+ }
+ else {
+ ret = dtypes[0];
+ }
+ Py_INCREF(ret);
+ return ret;
+ }
+
+ int use_min_scalar = should_use_min_scalar(narrs, arr, ndtypes, dtypes);
/* Loop through all the types, promoting them */
if (!use_min_scalar) {
diff --git a/numpy/core/src/multiarray/convert_datatype.h b/numpy/core/src/multiarray/convert_datatype.h
index bf77d699a..72867ead8 100644
--- a/numpy/core/src/multiarray/convert_datatype.h
+++ b/numpy/core/src/multiarray/convert_datatype.h
@@ -18,16 +18,28 @@ NPY_NO_EXPORT npy_bool
can_cast_scalar_to(PyArray_Descr *scal_type, char *scal_data,
PyArray_Descr *to, NPY_CASTING casting);
+NPY_NO_EXPORT int
+should_use_min_scalar(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes);
+
/*
* This function calls Py_DECREF on flex_dtype, and replaces it with
* a new dtype that has been adapted based on the values in data_dtype
- * and data_obj. If the flex_dtype is not flexible, it leaves it as is.
+ * and data_obj. If the flex_dtype is not flexible, it returns it as-is.
+ *
+ * Usually, if data_obj is not an array, dtype should be the result
+ * given by the PyArray_GetArrayParamsFromObject function.
+ *
+ * The data_obj may be NULL if just a dtype is known for the source.
+ *
+ * If *flex_dtype is NULL, returns immediately, without setting an
+ * exception, leaving any previous error handling intact.
*
* The current flexible dtypes include NPY_STRING, NPY_UNICODE, NPY_VOID,
* and NPY_DATETIME with generic units.
*/
-NPY_NO_EXPORT void
+NPY_NO_EXPORT PyArray_Descr *
PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
- PyArray_Descr **flex_dtype);
+ PyArray_Descr *flex_dtype);
#endif
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index e72e602c1..509331775 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -919,10 +919,11 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
* be decrefed.
*/
NPY_NO_EXPORT PyObject *
-PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
- npy_intp *dims, npy_intp *strides, void *data,
- int flags, PyObject *obj, PyObject *base, int zeroed,
- int allow_emptystring)
+PyArray_NewFromDescr_int(
+ PyTypeObject *subtype, PyArray_Descr *descr, int nd,
+ npy_intp const *dims, npy_intp const *strides, void *data,
+ int flags, PyObject *obj, PyObject *base, int zeroed,
+ int allow_emptystring)
{
PyArrayObject_fields *fa;
int i;
@@ -1087,8 +1088,30 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
data = npy_alloc_cache(nbytes);
}
if (data == NULL) {
- PyErr_NoMemory();
- goto fail;
+ static PyObject *exc_type = NULL;
+
+ npy_cache_import(
+ "numpy.core._exceptions", "_ArrayMemoryError",
+ &exc_type);
+ if (exc_type == NULL) {
+ return NULL;
+ }
+
+ PyObject *shape = PyArray_IntTupleFromIntp(fa->nd,fa->dimensions);
+ if (shape == NULL) {
+ return NULL;
+ }
+
+ /* produce an error object */
+ PyObject *exc_value = PyTuple_Pack(2, shape, descr);
+ Py_DECREF(shape);
+ if (exc_value == NULL){
+ return NULL;
+ }
+ PyErr_SetObject(exc_type, exc_value);
+ Py_DECREF(exc_value);
+ return NULL;
+
}
fa->flags |= NPY_ARRAY_OWNDATA;
@@ -1174,9 +1197,10 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
* true, dtype will be decrefed.
*/
NPY_NO_EXPORT PyObject *
-PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr,
- int nd, npy_intp *dims, npy_intp *strides, void *data,
- int flags, PyObject *obj)
+PyArray_NewFromDescr(
+ PyTypeObject *subtype, PyArray_Descr *descr,
+ int nd, npy_intp const *dims, npy_intp const *strides, void *data,
+ int flags, PyObject *obj)
{
return PyArray_NewFromDescrAndBase(
subtype, descr,
@@ -1190,7 +1214,7 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr,
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescrAndBase(
PyTypeObject *subtype, PyArray_Descr *descr,
- int nd, npy_intp *dims, npy_intp *strides, void *data,
+ int nd, npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base)
{
return PyArray_NewFromDescr_int(subtype, descr, nd,
@@ -1198,9 +1222,9 @@ PyArray_NewFromDescrAndBase(
flags, obj, base, 0, 0);
}
-/*NUMPY_API
+/*
* Creates a new array with the same shape as the provided one,
- * with possible memory layout order and data type changes.
+ * with possible memory layout order, data type and shape changes.
*
* prototype - The array the new one should be like.
* order - NPY_CORDER - C-contiguous result.
@@ -1208,6 +1232,8 @@ PyArray_NewFromDescrAndBase(
* NPY_ANYORDER - Fortran if prototype is Fortran, C otherwise.
* NPY_KEEPORDER - Keeps the axis ordering of prototype.
* dtype - If not NULL, overrides the data type of the result.
+ * ndim - If not 0 and dims not NULL, overrides the shape of the result.
+ * dims - If not NULL and ndim not 0, overrides the shape of the result.
* subok - If 1, use the prototype's array subtype, otherwise
* always create a base-class array.
*
@@ -1215,11 +1241,18 @@ PyArray_NewFromDescrAndBase(
* dtype->subarray is true, dtype will be decrefed.
*/
NPY_NO_EXPORT PyObject *
-PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
- PyArray_Descr *dtype, int subok)
+PyArray_NewLikeArrayWithShape(PyArrayObject *prototype, NPY_ORDER order,
+ PyArray_Descr *dtype, int ndim, npy_intp const *dims, int subok)
{
PyObject *ret = NULL;
- int ndim = PyArray_NDIM(prototype);
+
+ if (dims == NULL) {
+ ndim = PyArray_NDIM(prototype);
+ dims = PyArray_DIMS(prototype);
+ }
+ else if (order == NPY_KEEPORDER && (ndim != PyArray_NDIM(prototype))) {
+ order = NPY_CORDER;
+ }
/* If no override data type, use the one from the prototype */
if (dtype == NULL) {
@@ -1252,7 +1285,7 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
ret = PyArray_NewFromDescr(subok ? Py_TYPE(prototype) : &PyArray_Type,
dtype,
ndim,
- PyArray_DIMS(prototype),
+ dims,
NULL,
NULL,
order,
@@ -1261,11 +1294,10 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
/* KEEPORDER needs some analysis of the strides */
else {
npy_intp strides[NPY_MAXDIMS], stride;
- npy_intp *shape = PyArray_DIMS(prototype);
npy_stride_sort_item strideperm[NPY_MAXDIMS];
int idim;
- PyArray_CreateSortedStridePerm(PyArray_NDIM(prototype),
+ PyArray_CreateSortedStridePerm(ndim,
PyArray_STRIDES(prototype),
strideperm);
@@ -1274,14 +1306,14 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
for (idim = ndim-1; idim >= 0; --idim) {
npy_intp i_perm = strideperm[idim].perm;
strides[i_perm] = stride;
- stride *= shape[i_perm];
+ stride *= dims[i_perm];
}
/* Finally, allocate the array */
ret = PyArray_NewFromDescr(subok ? Py_TYPE(prototype) : &PyArray_Type,
dtype,
ndim,
- shape,
+ dims,
strides,
NULL,
0,
@@ -1292,12 +1324,36 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
}
/*NUMPY_API
+ * Creates a new array with the same shape as the provided one,
+ * with possible memory layout order and data type changes.
+ *
+ * prototype - The array the new one should be like.
+ * order - NPY_CORDER - C-contiguous result.
+ * NPY_FORTRANORDER - Fortran-contiguous result.
+ * NPY_ANYORDER - Fortran if prototype is Fortran, C otherwise.
+ * NPY_KEEPORDER - Keeps the axis ordering of prototype.
+ * dtype - If not NULL, overrides the data type of the result.
+ * subok - If 1, use the prototype's array subtype, otherwise
+ * always create a base-class array.
+ *
+ * NOTE: If dtype is not NULL, steals the dtype reference. On failure or when
+ * dtype->subarray is true, dtype will be decrefed.
+ */
+NPY_NO_EXPORT PyObject *
+PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
+ PyArray_Descr *dtype, int subok)
+{
+ return PyArray_NewLikeArrayWithShape(prototype, order, dtype, 0, NULL, subok);
+}
+
+/*NUMPY_API
* Generic new array creation routine.
*/
NPY_NO_EXPORT PyObject *
-PyArray_New(PyTypeObject *subtype, int nd, npy_intp *dims, int type_num,
- npy_intp *strides, void *data, int itemsize, int flags,
- PyObject *obj)
+PyArray_New(
+ PyTypeObject *subtype, int nd, npy_intp const *dims, int type_num,
+ npy_intp const *strides, void *data, int itemsize, int flags,
+ PyObject *obj)
{
PyArray_Descr *descr;
PyObject *new;
@@ -1827,9 +1883,12 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
/* If the requested dtype is flexible, adapt it */
if (newtype != NULL) {
- PyArray_AdaptFlexibleDType(op,
+ newtype = PyArray_AdaptFlexibleDType(op,
(dtype == NULL) ? PyArray_DESCR(arr) : dtype,
- &newtype);
+ newtype);
+ if (newtype == NULL) {
+ return NULL;
+ }
}
/* If we got dimensions and dtype instead of an array */
@@ -3017,7 +3076,7 @@ PyArray_CheckAxis(PyArrayObject *arr, int *axis, int flags)
* accepts NULL type
*/
NPY_NO_EXPORT PyObject *
-PyArray_Zeros(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
+PyArray_Zeros(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order)
{
PyArrayObject *ret;
@@ -3052,10 +3111,10 @@ PyArray_Zeros(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
* Empty
*
* accepts NULL type
- * steals referenct to type
+ * steals a reference to type
*/
NPY_NO_EXPORT PyObject *
-PyArray_Empty(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
+PyArray_Empty(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order)
{
PyArrayObject *ret;
@@ -3580,13 +3639,17 @@ array_from_text(PyArray_Descr *dtype, npy_intp num, char *sep, size_t *nread,
}
}
if (num < 0) {
- tmp = PyDataMem_RENEW(PyArray_DATA(r), PyArray_MAX(*nread,1)*dtype->elsize);
- if (tmp == NULL) {
- err = 1;
- }
- else {
- PyArray_DIMS(r)[0] = *nread;
- ((PyArrayObject_fields *)r)->data = tmp;
+ const size_t nsize = PyArray_MAX(*nread,1)*dtype->elsize;
+
+ if (nsize != 0) {
+ tmp = PyDataMem_RENEW(PyArray_DATA(r), nsize);
+ if (tmp == NULL) {
+ err = 1;
+ }
+ else {
+ PyArray_DIMS(r)[0] = *nread;
+ ((PyArrayObject_fields *)r)->data = tmp;
+ }
}
}
NPY_END_ALLOW_THREADS;
@@ -3707,32 +3770,12 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
Py_DECREF(type);
return NULL;
}
- if (Py_TYPE(buf)->tp_as_buffer == NULL
-#if defined(NPY_PY3K)
- || Py_TYPE(buf)->tp_as_buffer->bf_getbuffer == NULL
-#else
- || (Py_TYPE(buf)->tp_as_buffer->bf_getwritebuffer == NULL
- && Py_TYPE(buf)->tp_as_buffer->bf_getreadbuffer == NULL)
-#endif
- ) {
- PyObject *newbuf;
- newbuf = PyObject_GetAttr(buf, npy_ma_str_buffer);
- if (newbuf == NULL) {
- Py_DECREF(type);
- return NULL;
- }
- buf = newbuf;
- }
- else {
- Py_INCREF(buf);
- }
#if defined(NPY_PY3K)
if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
writeable = 0;
PyErr_Clear();
if (PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE) < 0) {
- Py_DECREF(buf);
Py_DECREF(type);
return NULL;
}
@@ -3752,7 +3795,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
writeable = 0;
PyErr_Clear();
if (PyObject_AsReadBuffer(buf, (void *)&data, &ts) == -1) {
- Py_DECREF(buf);
Py_DECREF(type);
return NULL;
}
@@ -3763,7 +3805,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
PyErr_Format(PyExc_ValueError,
"offset must be non-negative and no greater than buffer "\
"length (%" NPY_INTP_FMT ")", (npy_intp)ts);
- Py_DECREF(buf);
Py_DECREF(type);
return NULL;
}
@@ -3777,7 +3818,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
PyErr_SetString(PyExc_ValueError,
"buffer size must be a multiple"\
" of element size");
- Py_DECREF(buf);
Py_DECREF(type);
return NULL;
}
@@ -3788,7 +3828,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
PyErr_SetString(PyExc_ValueError,
"buffer is smaller than requested"\
" size");
- Py_DECREF(buf);
Py_DECREF(type);
return NULL;
}
@@ -3798,7 +3837,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
&PyArray_Type, type,
1, &n, NULL, data,
NPY_ARRAY_DEFAULT, NULL, buf);
- Py_DECREF(buf);
if (ret == NULL) {
return NULL;
}
@@ -3938,7 +3976,16 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
"Must specify length when using variable-size data-type.");
goto done;
}
- elcount = (count < 0) ? 0 : count;
+ if (count < 0) {
+ elcount = PyObject_LengthHint(obj, 0);
+ if (elcount < 0) {
+ goto done;
+ }
+ }
+ else {
+ elcount = count;
+ }
+
elsize = dtype->elsize;
/*
@@ -4005,9 +4052,9 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
* Realloc the data so that don't keep extra memory tied up
* (assuming realloc is reasonably good about reusing space...)
*/
- if (i == 0) {
+ if (i == 0 || elsize == 0) {
/* The size cannot be zero for PyDataMem_RENEW. */
- i = 1;
+ goto done;
}
new_data = PyDataMem_RENEW(PyArray_DATA(ret), i * elsize);
if (new_data == NULL) {
@@ -4047,7 +4094,7 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
*/
NPY_NO_EXPORT void
-_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
+_array_fill_strides(npy_intp *strides, npy_intp const *dims, int nd, size_t itemsize,
int inflag, int *objflags)
{
int i;
diff --git a/numpy/core/src/multiarray/ctors.h b/numpy/core/src/multiarray/ctors.h
index e9a2532da..4768e4efd 100644
--- a/numpy/core/src/multiarray/ctors.h
+++ b/numpy/core/src/multiarray/ctors.h
@@ -2,24 +2,33 @@
#define _NPY_ARRAY_CTORS_H_
NPY_NO_EXPORT PyObject *
-PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
- npy_intp *dims, npy_intp *strides, void *data,
- int flags, PyObject *obj);
+PyArray_NewFromDescr(
+ PyTypeObject *subtype, PyArray_Descr *descr, int nd,
+ npy_intp const *dims, npy_intp const *strides, void *data,
+ int flags, PyObject *obj);
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescrAndBase(
- PyTypeObject *subtype, PyArray_Descr *descr,
- int nd, npy_intp *dims, npy_intp *strides, void *data,
+ PyTypeObject *subtype, PyArray_Descr *descr, int nd,
+ npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base);
NPY_NO_EXPORT PyObject *
-PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
- npy_intp *dims, npy_intp *strides, void *data,
- int flags, PyObject *obj, PyObject *base, int zeroed,
- int allow_emptystring);
+PyArray_NewFromDescr_int(
+ PyTypeObject *subtype, PyArray_Descr *descr, int nd,
+ npy_intp const *dims, npy_intp const *strides, void *data,
+ int flags, PyObject *obj, PyObject *base, int zeroed,
+ int allow_emptystring);
-NPY_NO_EXPORT PyObject *PyArray_New(PyTypeObject *, int nd, npy_intp *,
- int, npy_intp *, void *, int, int, PyObject *);
+NPY_NO_EXPORT PyObject *
+PyArray_NewLikeArrayWithShape(
+ PyArrayObject *prototype, NPY_ORDER order,
+ PyArray_Descr *dtype, int ndim, npy_intp const *dims, int subok);
+
+NPY_NO_EXPORT PyObject *
+PyArray_New(
+ PyTypeObject *, int nd, npy_intp const *,
+ int, npy_intp const*, void *, int, int, PyObject *);
NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
@@ -64,7 +73,7 @@ PyArray_CopyAsFlat(PyArrayObject *dst, PyArrayObject *src,
/* FIXME: remove those from here */
NPY_NO_EXPORT void
-_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
+_array_fill_strides(npy_intp *strides, npy_intp const *dims, int nd, size_t itemsize,
int inflag, int *objflags);
NPY_NO_EXPORT void
diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c
index a33f643f1..f1e4feac2 100644
--- a/numpy/core/src/multiarray/datetime.c
+++ b/numpy/core/src/multiarray/datetime.c
@@ -409,6 +409,26 @@ PyArray_TimedeltaStructToTimedelta(NPY_DATETIMEUNIT fr, npy_timedeltastruct *d)
}
/*
+ * Computes the python `ret, d = divmod(d, unit)`.
+ *
+ * Note that GCC is smart enough at -O2 to eliminate the `if(*d < 0)` branch
+ * for subsequent calls to this command - it is able to deduce that `*d >= 0`.
+ */
+static inline
+npy_int64 extract_unit(npy_datetime *d, npy_datetime unit) {
+ assert(unit > 0);
+ npy_int64 div = *d / unit;
+ npy_int64 mod = *d % unit;
+ if (mod < 0) {
+ mod += unit;
+ div -= 1;
+ }
+ assert(mod >= 0);
+ *d = mod;
+ return div;
+}
+
+/*
* Converts a datetime based on the given metadata into a datetimestruct
*/
NPY_NO_EXPORT int
@@ -451,14 +471,8 @@ convert_datetime_to_datetimestruct(PyArray_DatetimeMetaData *meta,
break;
case NPY_FR_M:
- if (dt >= 0) {
- out->year = 1970 + dt / 12;
- out->month = dt % 12 + 1;
- }
- else {
- out->year = 1969 + (dt + 1) / 12;
- out->month = 12 + (dt + 1)% 12;
- }
+ out->year = 1970 + extract_unit(&dt, 12);
+ out->month = dt + 1;
break;
case NPY_FR_W:
@@ -473,169 +487,100 @@ convert_datetime_to_datetimestruct(PyArray_DatetimeMetaData *meta,
case NPY_FR_h:
perday = 24LL;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
out->hour = (int)dt;
break;
case NPY_FR_m:
perday = 24LL * 60;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / 60);
- out->min = (int)(dt % 60);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 60);
+ out->min = (int)dt;
break;
case NPY_FR_s:
perday = 24LL * 60 * 60;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / (60*60));
- out->min = (int)((dt / 60) % 60);
- out->sec = (int)(dt % 60);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 60*60);
+ out->min = (int)extract_unit(&dt, 60);
+ out->sec = (int)dt;
break;
case NPY_FR_ms:
perday = 24LL * 60 * 60 * 1000;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / (60*60*1000LL));
- out->min = (int)((dt / (60*1000LL)) % 60);
- out->sec = (int)((dt / 1000LL) % 60);
- out->us = (int)((dt % 1000LL) * 1000);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 1000LL*60*60);
+ out->min = (int)extract_unit(&dt, 1000LL*60);
+ out->sec = (int)extract_unit(&dt, 1000LL);
+ out->us = (int)(dt * 1000);
break;
case NPY_FR_us:
perday = 24LL * 60LL * 60LL * 1000LL * 1000LL;
-
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / (60*60*1000000LL));
- out->min = (int)((dt / (60*1000000LL)) % 60);
- out->sec = (int)((dt / 1000000LL) % 60);
- out->us = (int)(dt % 1000000LL);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 1000LL*1000*60*60);
+ out->min = (int)extract_unit(&dt, 1000LL*1000*60);
+ out->sec = (int)extract_unit(&dt, 1000LL*1000);
+ out->us = (int)dt;
break;
case NPY_FR_ns:
perday = 24LL * 60LL * 60LL * 1000LL * 1000LL * 1000LL;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / (60*60*1000000000LL));
- out->min = (int)((dt / (60*1000000000LL)) % 60);
- out->sec = (int)((dt / 1000000000LL) % 60);
- out->us = (int)((dt / 1000LL) % 1000000LL);
- out->ps = (int)((dt % 1000LL) * 1000);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 1000LL*1000*1000*60*60);
+ out->min = (int)extract_unit(&dt, 1000LL*1000*1000*60);
+ out->sec = (int)extract_unit(&dt, 1000LL*1000*1000);
+ out->us = (int)extract_unit(&dt, 1000LL);
+ out->ps = (int)(dt * 1000);
break;
case NPY_FR_ps:
perday = 24LL * 60 * 60 * 1000 * 1000 * 1000 * 1000;
- if (dt >= 0) {
- set_datetimestruct_days(dt / perday, out);
- dt = dt % perday;
- }
- else {
- set_datetimestruct_days((dt - (perday-1)) / perday, out);
- dt = (perday-1) + (dt + 1) % perday;
- }
- out->hour = (int)(dt / (60*60*1000000000000LL));
- out->min = (int)((dt / (60*1000000000000LL)) % 60);
- out->sec = (int)((dt / 1000000000000LL) % 60);
- out->us = (int)((dt / 1000000LL) % 1000000LL);
- out->ps = (int)(dt % 1000000LL);
+ set_datetimestruct_days(extract_unit(&dt, perday), out);
+ out->hour = (int)extract_unit(&dt, 1000LL*1000*1000*1000*60*60);
+ out->min = (int)extract_unit(&dt, 1000LL*1000*1000*1000*60);
+ out->sec = (int)extract_unit(&dt, 1000LL*1000*1000*1000);
+ out->us = (int)extract_unit(&dt, 1000LL*1000);
+ out->ps = (int)(dt);
break;
case NPY_FR_fs:
/* entire range is only +- 2.6 hours */
- if (dt >= 0) {
- out->hour = (int)(dt / (60*60*1000000000000000LL));
- out->min = (int)((dt / (60*1000000000000000LL)) % 60);
- out->sec = (int)((dt / 1000000000000000LL) % 60);
- out->us = (int)((dt / 1000000000LL) % 1000000LL);
- out->ps = (int)((dt / 1000LL) % 1000000LL);
- out->as = (int)((dt % 1000LL) * 1000);
- }
- else {
- npy_datetime minutes;
-
- minutes = dt / (60*1000000000000000LL);
- dt = dt % (60*1000000000000000LL);
- if (dt < 0) {
- dt += (60*1000000000000000LL);
- --minutes;
- }
- /* Offset the negative minutes */
- add_minutes_to_datetimestruct(out, minutes);
- out->sec = (int)((dt / 1000000000000000LL) % 60);
- out->us = (int)((dt / 1000000000LL) % 1000000LL);
- out->ps = (int)((dt / 1000LL) % 1000000LL);
- out->as = (int)((dt % 1000LL) * 1000);
- }
+ out->hour = (int)extract_unit(&dt, 1000LL*1000*1000*1000*1000*60*60);
+ if (out->hour < 0) {
+ out->year = 1969;
+ out->month = 12;
+ out->day = 31;
+ out->hour += 24;
+ assert(out->hour >= 0);
+ }
+ out->min = (int)extract_unit(&dt, 1000LL*1000*1000*1000*1000*60);
+ out->sec = (int)extract_unit(&dt, 1000LL*1000*1000*1000*1000);
+ out->us = (int)extract_unit(&dt, 1000LL*1000*1000);
+ out->ps = (int)extract_unit(&dt, 1000LL);
+ out->as = (int)(dt * 1000);
break;
case NPY_FR_as:
/* entire range is only +- 9.2 seconds */
- if (dt >= 0) {
- out->sec = (int)((dt / 1000000000000000000LL) % 60);
- out->us = (int)((dt / 1000000000000LL) % 1000000LL);
- out->ps = (int)((dt / 1000000LL) % 1000000LL);
- out->as = (int)(dt % 1000000LL);
- }
- else {
- npy_datetime seconds;
-
- seconds = dt / 1000000000000000000LL;
- dt = dt % 1000000000000000000LL;
- if (dt < 0) {
- dt += 1000000000000000000LL;
- --seconds;
- }
- /* Offset the negative seconds */
- add_seconds_to_datetimestruct(out, seconds);
- out->us = (int)((dt / 1000000000000LL) % 1000000LL);
- out->ps = (int)((dt / 1000000LL) % 1000000LL);
- out->as = (int)(dt % 1000000LL);
- }
+ out->sec = (int)extract_unit(&dt, 1000LL*1000*1000*1000*1000*1000);
+ if (out->sec < 0) {
+ out->year = 1969;
+ out->month = 12;
+ out->day = 31;
+ out->hour = 23;
+ out->min = 59;
+ out->sec += 60;
+ assert(out->sec >= 0);
+ }
+ out->us = (int)extract_unit(&dt, 1000LL*1000*1000*1000);
+ out->ps = (int)extract_unit(&dt, 1000LL*1000);
+ out->as = (int)dt;
break;
default:
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 53d74512c..ff85c3fcb 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -77,31 +77,51 @@ _arraydescr_from_ctypes_type(PyTypeObject *type)
* and it can be converted to a dtype object.
*
* Returns a new reference to a dtype object, or NULL
- * if this is not possible. When it returns NULL, it does
- * not set a Python exception.
+ * if this is not possible.
+ * When the return value is true, the dtype attribute should have been used
+ * and parsed. Currently the only failure mode for a 1 return is a
+ * RecursionError and the descriptor is set to NULL.
+ * When the return value is false, no error will be set.
*/
-NPY_NO_EXPORT PyArray_Descr *
-_arraydescr_from_dtype_attr(PyObject *obj)
+int
+_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr)
{
PyObject *dtypedescr;
- PyArray_Descr *newdescr = NULL;
int ret;
/* For arbitrary objects that have a "dtype" attribute */
dtypedescr = PyObject_GetAttrString(obj, "dtype");
- PyErr_Clear();
if (dtypedescr == NULL) {
- return NULL;
+ /*
+ * This can be reached due to recursion limit being hit while fetching
+ * the attribute (tested for py3.7). This removes the custom message.
+ */
+ goto fail;
}
- ret = PyArray_DescrConverter(dtypedescr, &newdescr);
+ if (Py_EnterRecursiveCall(
+ " while trying to convert the given data type from its "
+ "`.dtype` attribute.") != 0) {
+ return 1;
+ }
+
+ ret = PyArray_DescrConverter(dtypedescr, newdescr);
+
Py_DECREF(dtypedescr);
+ Py_LeaveRecursiveCall();
if (ret != NPY_SUCCEED) {
- PyErr_Clear();
- return NULL;
+ goto fail;
}
- return newdescr;
+ return 1;
+
+ fail:
+ /* Ignore all but recursion errors, to give ctypes a full try. */
+ if (!PyErr_ExceptionMatches(PyExc_RecursionError)) {
+ PyErr_Clear();
+ return 0;
+ }
+ return 1;
}
/*
@@ -280,15 +300,22 @@ _convert_from_tuple(PyObject *obj, int align)
"invalid shape in fixed-type tuple.");
goto fail;
}
- /*
- * If (type, 1) was given, it is equivalent to type...
- * or (type, ()) was given it is equivalent to type...
- */
- if ((shape.len == 1
- && shape.ptr[0] == 1
- && PyNumber_Check(val))
- || (shape.len == 0
- && PyTuple_Check(val))) {
+ /* if (type, ()) was given it is equivalent to type... */
+ if (shape.len == 0 && PyTuple_Check(val)) {
+ npy_free_cache_dim_obj(shape);
+ return type;
+ }
+ /* (type, 1) use to be equivalent to type, but is deprecated */
+ if (shape.len == 1
+ && shape.ptr[0] == 1
+ && PyNumber_Check(val)) {
+ /* 2019-05-20, 1.17 */
+ if (DEPRECATE_FUTUREWARNING(
+ "Passing (type, 1) or '1type' as a synonym of type is "
+ "deprecated; in a future version of numpy, it will be "
+ "understood as (type, (1,)) / '(1,)type'.") < 0) {
+ goto fail;
+ }
npy_free_cache_dim_obj(shape);
return type;
}
@@ -470,6 +497,9 @@ _convert_from_array_descr(PyObject *obj, int align)
else {
ret = PyArray_DescrConverter(PyTuple_GET_ITEM(item, 1), &conv);
}
+ if (ret == NPY_FAIL) {
+ PyObject_Print(PyTuple_GET_ITEM(item, 1), stderr, 0);
+ }
}
else if (PyTuple_GET_SIZE(item) == 3) {
newobj = PyTuple_GetSlice(item, 1, 3);
@@ -487,7 +517,6 @@ _convert_from_array_descr(PyObject *obj, int align)
if (ret == NPY_FAIL) {
goto fail;
}
-
if ((PyDict_GetItem(fields, name) != NULL)
|| (title
&& PyBaseString_Check(title)
@@ -1416,11 +1445,16 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
check_num = NPY_VOID;
}
else {
- *at = _arraydescr_from_dtype_attr(obj);
- if (*at) {
+ if (_arraydescr_from_dtype_attr(obj, at)) {
+ /*
+ * Using dtype attribute, *at may be NULL if a
+ * RecursionError occurred.
+ */
+ if (*at == NULL) {
+ goto error;
+ }
return NPY_SUCCEED;
}
-
/*
* Note: this comes after _arraydescr_from_dtype_attr because the ctypes
* type might override the dtype if numpy does not otherwise
@@ -1512,7 +1546,8 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
/* A typecode like 'd' */
if (len == 1) {
- check_num = type[0];
+ /* Python byte string characters are unsigned */
+ check_num = (unsigned char) type[0];
}
/* A kind + size like 'f8' */
else {
@@ -1599,14 +1634,16 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
goto fail;
}
else {
- *at = _arraydescr_from_dtype_attr(obj);
- if (*at) {
+ if (_arraydescr_from_dtype_attr(obj, at)) {
+ /*
+ * Using dtype attribute, *at may be NULL if a
+ * RecursionError occurred.
+ */
+ if (*at == NULL) {
+ goto error;
+ }
return NPY_SUCCEED;
}
- if (PyErr_Occurred()) {
- return NPY_FAIL;
- }
-
/*
* Note: this comes after _arraydescr_from_dtype_attr because the ctypes
* type might override the dtype if numpy does not otherwise
@@ -2751,11 +2788,11 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
}
}
else {
+#if defined(NPY_PY3K)
/*
- * At least one of the names is not of the expected type.
- * The difference might originate from pickles that were
- * created on another Python version (PY2/PY3). Go through
- * the names and convert if possible for compatibility
+ * To support pickle.load(f, encoding='bytes') for loading Py2
+ * generated pickles on Py3, we need to be more lenient and convert
+ * field names from byte strings to unicode.
*/
PyObject *tmp, *new_name, *field;
@@ -2780,14 +2817,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
return NULL;
}
-#if defined(NPY_PY3K)
- /*
- * To support pickle.load(f, encoding='bytes') for loading Py2
- * generated pickles on Py3, we need to be more lenient and convert
- * field names from byte strings to unicode.
- */
if (PyUnicode_Check(name)) {
- // no transformation needed, keep it as is
new_name = name;
Py_INCREF(new_name);
}
@@ -2797,35 +2827,17 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
return NULL;
}
}
-#else
- // PY2 should be able to read PY3 pickles. See gh-2407
- if (PyString_Check(name)) {
- // It is a PY2 string, no transformation is needed
- new_name = name;
- Py_INCREF(new_name);
- }
- else if (PyUnicode_Check(name)) {
- // The field names of a structured dtype were pickled in PY3 as unicode strings
- // so, to unpickle them in PY2, we need to convert them to PY2 strings
- new_name = PyUnicode_AsEncodedString(name, "ASCII", "strict");
- if (new_name == NULL) {
- return NULL;
- }
- }
- else {
- // The field name is not a string or a unicode object, we cannot process it
- PyErr_Format(PyExc_ValueError,
- "non-string/non-unicode names in Numpy dtype unpickling");
- return NULL;
- }
-
-#endif
PyTuple_SET_ITEM(self->names, i, new_name);
if (PyDict_SetItem(self->fields, new_name, field) != 0) {
return NULL;
}
}
+#else
+ PyErr_Format(PyExc_ValueError,
+ "non-string names in Numpy dtype unpickling");
+ return NULL;
+#endif
}
}
@@ -3392,6 +3404,117 @@ _subscript_by_index(PyArray_Descr *self, Py_ssize_t i)
return ret;
}
+static npy_bool
+_is_list_of_strings(PyObject *obj)
+{
+ int seqlen, i;
+ if (!PyList_CheckExact(obj)) {
+ return NPY_FALSE;
+ }
+ seqlen = PyList_GET_SIZE(obj);
+ for (i = 0; i < seqlen; i++) {
+ PyObject *item = PyList_GET_ITEM(obj, i);
+ if (!PyBaseString_Check(item)) {
+ return NPY_FALSE;
+ }
+ }
+
+ return NPY_TRUE;
+}
+
+NPY_NO_EXPORT PyArray_Descr *
+arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind)
+{
+ int seqlen, i;
+ PyObject *fields = NULL;
+ PyObject *names = NULL;
+ PyArray_Descr *view_dtype;
+
+ seqlen = PySequence_Size(ind);
+ if (seqlen == -1) {
+ return NULL;
+ }
+
+ fields = PyDict_New();
+ if (fields == NULL) {
+ goto fail;
+ }
+ names = PyTuple_New(seqlen);
+ if (names == NULL) {
+ goto fail;
+ }
+
+ for (i = 0; i < seqlen; i++) {
+ PyObject *name;
+ PyObject *tup;
+
+ name = PySequence_GetItem(ind, i);
+ if (name == NULL) {
+ goto fail;
+ }
+
+ /* Let the names tuple steal a reference now, so we don't need to
+ * decref name if an error occurs further on.
+ */
+ PyTuple_SET_ITEM(names, i, name);
+
+ tup = PyDict_GetItem(self->fields, name);
+ if (tup == NULL) {
+ PyErr_SetObject(PyExc_KeyError, name);
+ goto fail;
+ }
+
+ /* disallow use of titles as index */
+ if (PyTuple_Size(tup) == 3) {
+ PyObject *title = PyTuple_GET_ITEM(tup, 2);
+ int titlecmp = PyObject_RichCompareBool(title, name, Py_EQ);
+ if (titlecmp < 0) {
+ goto fail;
+ }
+ if (titlecmp == 1) {
+ /* if title == name, we were given a title, not a field name */
+ PyErr_SetString(PyExc_KeyError,
+ "cannot use field titles in multi-field index");
+ goto fail;
+ }
+ if (PyDict_SetItem(fields, title, tup) < 0) {
+ goto fail;
+ }
+ }
+ /* disallow duplicate field indices */
+ if (PyDict_Contains(fields, name)) {
+ PyObject *msg = NULL;
+ PyObject *fmt = PyUString_FromString(
+ "duplicate field of name {!r}");
+ if (fmt != NULL) {
+ msg = PyObject_CallMethod(fmt, "format", "O", name);
+ Py_DECREF(fmt);
+ }
+ PyErr_SetObject(PyExc_ValueError, msg);
+ Py_XDECREF(msg);
+ goto fail;
+ }
+ if (PyDict_SetItem(fields, name, tup) < 0) {
+ goto fail;
+ }
+ }
+
+ view_dtype = PyArray_DescrNewFromType(NPY_VOID);
+ if (view_dtype == NULL) {
+ goto fail;
+ }
+ view_dtype->elsize = self->elsize;
+ view_dtype->names = names;
+ view_dtype->fields = fields;
+ view_dtype->flags = self->flags;
+ return view_dtype;
+
+fail:
+ Py_XDECREF(fields);
+ Py_XDECREF(names);
+ return NULL;
+}
+
static PyObject *
descr_subscript(PyArray_Descr *self, PyObject *op)
{
@@ -3402,6 +3525,9 @@ descr_subscript(PyArray_Descr *self, PyObject *op)
if (PyBaseString_Check(op)) {
return _subscript_by_name(self, op);
}
+ else if (_is_list_of_strings(op)) {
+ return (PyObject *)arraydescr_field_subset_view(self, op);
+ }
else {
Py_ssize_t i = PyArray_PyIntAsIntp(op);
if (error_converting(i)) {
@@ -3409,7 +3535,8 @@ descr_subscript(PyArray_Descr *self, PyObject *op)
PyObject *err = PyErr_Occurred();
if (PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
PyErr_SetString(PyExc_TypeError,
- "Field key must be an integer, string, or unicode.");
+ "Field key must be an integer field offset, "
+ "single field name, or list of field names.");
}
return NULL;
}
diff --git a/numpy/core/src/multiarray/descriptor.h b/numpy/core/src/multiarray/descriptor.h
index a5f3b8cdf..6024c5e77 100644
--- a/numpy/core/src/multiarray/descriptor.h
+++ b/numpy/core/src/multiarray/descriptor.h
@@ -7,13 +7,25 @@ NPY_NO_EXPORT PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self);
NPY_NO_EXPORT PyObject *
array_set_typeDict(PyObject *NPY_UNUSED(ignored), PyObject *args);
-NPY_NO_EXPORT PyArray_Descr *
-_arraydescr_from_dtype_attr(PyObject *obj);
+int
+_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr);
NPY_NO_EXPORT int
is_dtype_struct_simple_unaligned_layout(PyArray_Descr *dtype);
+/*
+ * Filter the fields of a dtype to only those in the list of strings, ind.
+ *
+ * No type checking is performed on the input.
+ *
+ * Raises:
+ * ValueError - if a field is repeated
+ * KeyError - if an invalid field name (or any field title) is used
+ */
+NPY_NO_EXPORT PyArray_Descr *
+arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind);
+
extern NPY_NO_EXPORT char *_datetime_strings[];
#endif
diff --git a/numpy/core/src/multiarray/dragon4.c b/numpy/core/src/multiarray/dragon4.c
index 8d52672e3..1694596e9 100644
--- a/numpy/core/src/multiarray/dragon4.c
+++ b/numpy/core/src/multiarray/dragon4.c
@@ -1,31 +1,33 @@
/*
* Copyright (c) 2014 Ryan Juckett
- * http://www.ryanjuckett.com/
*
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
*
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
/*
* This file contains a modified version of Ryan Juckett's Dragon4
- * implementation, which has been ported from C++ to C and which has
+ * implementation, obtained from http://www.ryanjuckett.com,
+ * which has been ported from C++ to C and which has
* modifications specific to printing floats in numpy.
+ *
+ * Ryan Juckett's original code was under the Zlib license; he gave numpy
+ * permission to include it under the MIT license instead.
*/
#include "dragon4.h"
diff --git a/numpy/core/src/multiarray/dragon4.h b/numpy/core/src/multiarray/dragon4.h
index 2b8b4cef4..3a99bde6c 100644
--- a/numpy/core/src/multiarray/dragon4.h
+++ b/numpy/core/src/multiarray/dragon4.h
@@ -1,31 +1,33 @@
/*
* Copyright (c) 2014 Ryan Juckett
- * http://www.ryanjuckett.com/
*
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
*
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
/*
* This file contains a modified version of Ryan Juckett's Dragon4
- * implementation, which has been ported from C++ to C and which has
+ * implementation, obtained from http://www.ryanjuckett.com,
+ * which has been ported from C++ to C and which has
* modifications specific to printing floats in numpy.
+ *
+ * Ryan Juckett's original code was under the Zlib license; he gave numpy
+ * permission to include it under the MIT license instead.
*/
#ifndef _NPY_DRAGON4_H_
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index 6347d35eb..a90416a40 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -1127,7 +1127,7 @@ get_datetime_to_unicode_transfer_function(int aligned,
/* Get an ASCII string data type, adapted to match the UNICODE one */
str_dtype = PyArray_DescrFromType(NPY_STRING);
- PyArray_AdaptFlexibleDType(NULL, dst_dtype, &str_dtype);
+ str_dtype = PyArray_AdaptFlexibleDType(NULL, dst_dtype, str_dtype);
if (str_dtype == NULL) {
return NPY_FAIL;
}
@@ -1249,7 +1249,7 @@ get_unicode_to_datetime_transfer_function(int aligned,
/* Get an ASCII string data type, adapted to match the UNICODE one */
str_dtype = PyArray_DescrFromType(NPY_STRING);
- PyArray_AdaptFlexibleDType(NULL, src_dtype, &str_dtype);
+ str_dtype = PyArray_AdaptFlexibleDType(NULL, src_dtype, str_dtype);
if (str_dtype == NULL) {
return NPY_FAIL;
}
@@ -2375,7 +2375,7 @@ get_subarray_transfer_function(int aligned,
/* Get the subarray shapes and sizes */
if (PyDataType_HASSUBARRAY(src_dtype)) {
- if (!(PyArray_IntpConverter(src_dtype->subarray->shape,
+ if (!(PyArray_IntpConverter(src_dtype->subarray->shape,
&src_shape))) {
PyErr_SetString(PyExc_ValueError,
"invalid subarray shape");
@@ -2385,7 +2385,7 @@ get_subarray_transfer_function(int aligned,
src_dtype = src_dtype->subarray->base;
}
if (PyDataType_HASSUBARRAY(dst_dtype)) {
- if (!(PyArray_IntpConverter(dst_dtype->subarray->shape,
+ if (!(PyArray_IntpConverter(dst_dtype->subarray->shape,
&dst_shape))) {
npy_free_cache_dim_obj(src_shape);
PyErr_SetString(PyExc_ValueError,
diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src
index 58af44091..e7bbc3d0b 100644
--- a/numpy/core/src/multiarray/einsum.c.src
+++ b/numpy/core/src/multiarray/einsum.c.src
@@ -1876,7 +1876,7 @@ parse_operand_subscripts(char *subscripts, int length,
* later where it matters the char is cast to a signed char.
*/
for (idim = 0; idim < ndim - 1; ++idim) {
- int label = (signed char)op_labels[idim];
+ int label = op_labels[idim];
/* If it is a proper label, find any duplicates of it. */
if (label > 0) {
/* Search for the next matching label. */
diff --git a/numpy/core/src/multiarray/flagsobject.c b/numpy/core/src/multiarray/flagsobject.c
index 85ea49fb4..a66b9d40d 100644
--- a/numpy/core/src/multiarray/flagsobject.c
+++ b/numpy/core/src/multiarray/flagsobject.c
@@ -7,6 +7,7 @@
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#include "numpy/arrayobject.h"
+#include "arrayobject.h"
#include "numpy/arrayscalars.h"
#include "npy_config.h"
@@ -147,7 +148,7 @@ _UpdateContiguousFlags(PyArrayObject *ap)
if (PyArray_STRIDES(ap)[i] != sd) {
is_c_contig = 0;
break;
- }
+ }
/* contiguous, if it got this far */
if (dim == 0) {
break;
@@ -201,21 +202,36 @@ arrayflags_dealloc(PyArrayFlagsObject *self)
static PyObject * \
arrayflags_ ## lower ## _get(PyArrayFlagsObject *self) \
{ \
- PyObject *item; \
- item = ((self->flags & (UPPER)) == (UPPER)) ? Py_True : Py_False; \
- Py_INCREF(item); \
- return item; \
+ return PyBool_FromLong((self->flags & (UPPER)) == (UPPER)); \
+ }
+
+static char *msg = "future versions will not create a writeable "
+ "array from broadcast_array. Set the writable flag explicitly to "
+ "avoid this warning.";
+
+#define _define_get_warn(UPPER, lower) \
+ static PyObject * \
+ arrayflags_ ## lower ## _get(PyArrayFlagsObject *self) \
+ { \
+ if (self->flags & NPY_ARRAY_WARN_ON_WRITE) { \
+ if (PyErr_Warn(PyExc_FutureWarning, msg) < 0) {\
+ return NULL; \
+ } \
+ }\
+ return PyBool_FromLong((self->flags & (UPPER)) == (UPPER)); \
}
+
_define_get(NPY_ARRAY_C_CONTIGUOUS, contiguous)
_define_get(NPY_ARRAY_F_CONTIGUOUS, fortran)
_define_get(NPY_ARRAY_WRITEBACKIFCOPY, writebackifcopy)
_define_get(NPY_ARRAY_OWNDATA, owndata)
_define_get(NPY_ARRAY_ALIGNED, aligned)
-_define_get(NPY_ARRAY_WRITEABLE, writeable)
-_define_get(NPY_ARRAY_ALIGNED|
+_define_get(NPY_ARRAY_WRITEABLE, writeable_no_warn)
+_define_get_warn(NPY_ARRAY_WRITEABLE, writeable)
+_define_get_warn(NPY_ARRAY_ALIGNED|
NPY_ARRAY_WRITEABLE, behaved)
-_define_get(NPY_ARRAY_ALIGNED|
+_define_get_warn(NPY_ARRAY_ALIGNED|
NPY_ARRAY_WRITEABLE|
NPY_ARRAY_C_CONTIGUOUS, carray)
@@ -398,6 +414,40 @@ arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj)
return 0;
}
+static int
+arrayflags_warn_on_write_set(PyArrayFlagsObject *self, PyObject *obj)
+{
+ /*
+ * This code should go away in a future release, so do not mangle the
+ * array_setflags function with an extra kwarg
+ */
+ int ret;
+ if (obj == NULL) {
+ PyErr_SetString(PyExc_AttributeError,
+ "Cannot delete flags _warn_on_write attribute");
+ return -1;
+ }
+ ret = PyObject_IsTrue(obj);
+ if (ret > 0) {
+ if (!(PyArray_FLAGS((PyArrayObject*)self->arr) & NPY_ARRAY_WRITEABLE)) {
+ PyErr_SetString(PyExc_ValueError,
+ "cannot set '_warn_on_write' flag when 'writable' is "
+ "False");
+ return -1;
+ }
+ PyArray_ENABLEFLAGS((PyArrayObject*)self->arr, NPY_ARRAY_WARN_ON_WRITE);
+ }
+ else if (ret < 0) {
+ return -1;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "cannot clear '_warn_on_write', set "
+ "writeable True to clear this private flag");
+ return -1;
+ }
+ return 0;
+}
static PyGetSetDef arrayflags_getsets[] = {
{"contiguous",
@@ -436,6 +486,14 @@ static PyGetSetDef arrayflags_getsets[] = {
(getter)arrayflags_writeable_get,
(setter)arrayflags_writeable_set,
NULL, NULL},
+ {"_writeable_no_warn",
+ (getter)arrayflags_writeable_no_warn_get,
+ (setter)NULL,
+ NULL, NULL},
+ {"_warn_on_write",
+ (getter)NULL,
+ (setter)arrayflags_warn_on_write_set,
+ NULL, NULL},
{"fnc",
(getter)arrayflags_fnc_get,
NULL,
@@ -623,7 +681,7 @@ arrayflags_setitem(PyArrayFlagsObject *self, PyObject *ind, PyObject *item)
((n==1) && (strncmp(key, "U", n) == 0))) {
return arrayflags_updateifcopy_set(self, item);
}
- else if (((n==14) && (strncmp(key, "WRITEBACKIFCOPY", n) == 0)) ||
+ else if (((n==15) && (strncmp(key, "WRITEBACKIFCOPY", n) == 0)) ||
((n==1) && (strncmp(key, "X", n) == 0))) {
return arrayflags_writebackifcopy_set(self, item);
}
@@ -648,19 +706,25 @@ static PyObject *
arrayflags_print(PyArrayFlagsObject *self)
{
int fl = self->flags;
+ const char *_warn_on_write = "";
+ if (fl & NPY_ARRAY_WARN_ON_WRITE) {
+ _warn_on_write = " (with WARN_ON_WRITE=True)";
+ }
return PyUString_FromFormat(
" %s : %s\n %s : %s\n"
+ " %s : %s\n %s : %s%s\n"
" %s : %s\n %s : %s\n"
- " %s : %s\n %s : %s\n"
- " %s : %s",
+ " %s : %s\n",
"C_CONTIGUOUS", _torf_(fl, NPY_ARRAY_C_CONTIGUOUS),
"F_CONTIGUOUS", _torf_(fl, NPY_ARRAY_F_CONTIGUOUS),
"OWNDATA", _torf_(fl, NPY_ARRAY_OWNDATA),
"WRITEABLE", _torf_(fl, NPY_ARRAY_WRITEABLE),
+ _warn_on_write,
"ALIGNED", _torf_(fl, NPY_ARRAY_ALIGNED),
"WRITEBACKIFCOPY", _torf_(fl, NPY_ARRAY_WRITEBACKIFCOPY),
- "UPDATEIFCOPY", _torf_(fl, NPY_ARRAY_UPDATEIFCOPY));
+ "UPDATEIFCOPY", _torf_(fl, NPY_ARRAY_UPDATEIFCOPY)
+ );
}
static int
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index c5577c196..bed92403f 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -73,7 +73,7 @@ array_shape_set(PyArrayObject *self, PyObject *val)
((PyArrayObject_fields *)self)->nd = nd;
if (nd > 0) {
/* create new dimensions and strides */
- ((PyArrayObject_fields *)self)->dimensions = npy_alloc_cache_dim(3*nd);
+ ((PyArrayObject_fields *)self)->dimensions = npy_alloc_cache_dim(2 * nd);
if (PyArray_DIMS(self) == NULL) {
Py_DECREF(ret);
PyErr_SetString(PyExc_MemoryError,"");
@@ -192,12 +192,7 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
static PyObject *
array_priority_get(PyArrayObject *self)
{
- if (PyArray_CheckExact(self)) {
- return PyFloat_FromDouble(NPY_PRIORITY);
- }
- else {
- return PyFloat_FromDouble(NPY_PRIORITY);
- }
+ return PyFloat_FromDouble(NPY_PRIORITY);
}
static PyObject *
diff --git a/numpy/core/src/multiarray/hashdescr.c b/numpy/core/src/multiarray/hashdescr.c
index 8465093b9..0b23b6c21 100644
--- a/numpy/core/src/multiarray/hashdescr.c
+++ b/numpy/core/src/multiarray/hashdescr.c
@@ -36,17 +36,17 @@ static int _array_descr_builtin(PyArray_Descr* descr, PyObject *l);
*/
static char _normalize_byteorder(char byteorder)
{
- switch(byteorder) {
- case '=':
- if (PyArray_GetEndianness() == NPY_CPU_BIG) {
- return '>';
- }
- else {
- return '<';
- }
- default:
- return byteorder;
- }
+ switch(byteorder) {
+ case '=':
+ if (PyArray_GetEndianness() == NPY_CPU_BIG) {
+ return '>';
+ }
+ else {
+ return '<';
+ }
+ default:
+ return byteorder;
+ }
}
/*
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index a7c6b14f4..11c45dce5 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -98,6 +98,10 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
goto fail;
}
+ if (arrays_overlap(out, self)) {
+ flags |= NPY_ARRAY_ENSURECOPY;
+ }
+
if (clipmode == NPY_RAISE) {
/*
* we need to make sure and get a copy
@@ -261,6 +265,7 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0,
npy_intp i, chunk, ni, max_item, nv, tmp;
char *src, *dest;
int copied = 0;
+ int overlap = 0;
indices = NULL;
values = NULL;
@@ -274,24 +279,6 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0,
return NULL;
}
- if (!PyArray_ISCONTIGUOUS(self)) {
- PyArrayObject *obj;
- int flags = NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY;
-
- if (clipmode == NPY_RAISE) {
- flags |= NPY_ARRAY_ENSURECOPY;
- }
- Py_INCREF(PyArray_DESCR(self));
- obj = (PyArrayObject *)PyArray_FromArray(self,
- PyArray_DESCR(self), flags);
- if (obj != self) {
- copied = 1;
- }
- self = obj;
- }
- max_item = PyArray_SIZE(self);
- dest = PyArray_DATA(self);
- chunk = PyArray_DESCR(self)->elsize;
indices = (PyArrayObject *)PyArray_ContiguousFromAny(indices0,
NPY_INTP, 0, 0);
if (indices == NULL) {
@@ -308,6 +295,25 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0,
if (nv <= 0) {
goto finish;
}
+
+ overlap = arrays_overlap(self, values) || arrays_overlap(self, indices);
+ if (overlap || !PyArray_ISCONTIGUOUS(self)) {
+ PyArrayObject *obj;
+ int flags = NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY |
+ NPY_ARRAY_ENSURECOPY;
+
+ Py_INCREF(PyArray_DESCR(self));
+ obj = (PyArrayObject *)PyArray_FromArray(self,
+ PyArray_DESCR(self), flags);
+ if (obj != self) {
+ copied = 1;
+ }
+ self = obj;
+ }
+ max_item = PyArray_SIZE(self);
+ dest = PyArray_DATA(self);
+ chunk = PyArray_DESCR(self)->elsize;
+
if (PyDataType_REFCHK(PyArray_DESCR(self))) {
switch(clipmode) {
case NPY_RAISE:
@@ -434,10 +440,11 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
PyArray_FastPutmaskFunc *func;
PyArrayObject *mask, *values;
PyArray_Descr *dtype;
- npy_intp i, j, chunk, ni, max_item, nv;
+ npy_intp i, j, chunk, ni, nv;
char *src, *dest;
npy_bool *mask_data;
int copied = 0;
+ int overlap = 0;
mask = NULL;
values = NULL;
@@ -447,29 +454,14 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
"be an array");
return NULL;
}
- if (!PyArray_ISCONTIGUOUS(self)) {
- PyArrayObject *obj;
- dtype = PyArray_DESCR(self);
- Py_INCREF(dtype);
- obj = (PyArrayObject *)PyArray_FromArray(self, dtype,
- NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY);
- if (obj != self) {
- copied = 1;
- }
- self = obj;
- }
-
- max_item = PyArray_SIZE(self);
- dest = PyArray_DATA(self);
- chunk = PyArray_DESCR(self)->elsize;
mask = (PyArrayObject *)PyArray_FROM_OTF(mask0, NPY_BOOL,
NPY_ARRAY_CARRAY | NPY_ARRAY_FORCECAST);
if (mask == NULL) {
goto fail;
}
ni = PyArray_SIZE(mask);
- if (ni != max_item) {
+ if (ni != PyArray_SIZE(self)) {
PyErr_SetString(PyExc_ValueError,
"putmask: mask and data must be "
"the same size");
@@ -491,6 +483,27 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
}
src = PyArray_DATA(values);
+ overlap = arrays_overlap(self, values) || arrays_overlap(self, mask);
+ if (overlap || !PyArray_ISCONTIGUOUS(self)) {
+ int flags = NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY;
+ PyArrayObject *obj;
+
+ if (overlap) {
+ flags |= NPY_ARRAY_ENSURECOPY;
+ }
+
+ dtype = PyArray_DESCR(self);
+ Py_INCREF(dtype);
+ obj = (PyArrayObject *)PyArray_FromArray(self, dtype, flags);
+ if (obj != self) {
+ copied = 1;
+ }
+ self = obj;
+ }
+
+ chunk = PyArray_DESCR(self)->elsize;
+ dest = PyArray_DATA(self);
+
if (PyDataType_REFCHK(PyArray_DESCR(self))) {
for (i = 0, j = 0; i < ni; i++, j++) {
if (j >= nv) {
@@ -594,7 +607,8 @@ PyArray_Repeat(PyArrayObject *aop, PyObject *op, int axis)
else {
for (j = 0; j < n; j++) {
if (counts[j] < 0) {
- PyErr_SetString(PyExc_ValueError, "count < 0");
+ PyErr_SetString(PyExc_ValueError,
+ "repeats may not contain negative values.");
goto fail;
}
total += counts[j];
@@ -712,6 +726,13 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *out,
"choose: invalid shape for output array.");
goto fail;
}
+
+ for (i = 0; i < n; i++) {
+ if (arrays_overlap(out, mps[i])) {
+ flags |= NPY_ARRAY_ENSURECOPY;
+ }
+ }
+
if (clipmode == NPY_RAISE) {
/*
* we need to make sure and get a copy
@@ -1105,7 +1126,7 @@ fail:
NPY_NO_EXPORT int
PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
{
- PyArray_SortFunc *sort;
+ PyArray_SortFunc *sort = NULL;
int n = PyArray_NDIM(op);
if (check_and_adjust_axis(&axis, n) < 0) {
@@ -1122,6 +1143,7 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
}
sort = PyArray_DESCR(op)->f->sort[which];
+
if (sort == NULL) {
if (PyArray_DESCR(op)->f->compare) {
switch (which) {
@@ -1132,8 +1154,8 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
case NPY_HEAPSORT:
sort = npy_heapsort;
break;
- case NPY_MERGESORT:
- sort = npy_mergesort;
+ case NPY_STABLESORT:
+ sort = npy_timsort;
break;
}
}
@@ -1263,16 +1285,11 @@ NPY_NO_EXPORT PyObject *
PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
{
PyArrayObject *op2;
- PyArray_ArgSortFunc *argsort;
+ PyArray_ArgSortFunc *argsort = NULL;
PyObject *ret;
- if (which < 0 || which >= NPY_NSORTS) {
- PyErr_SetString(PyExc_ValueError,
- "not a valid sort kind");
- return NULL;
- }
-
argsort = PyArray_DESCR(op)->f->argsort[which];
+
if (argsort == NULL) {
if (PyArray_DESCR(op)->f->compare) {
switch (which) {
@@ -1283,8 +1300,8 @@ PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
case NPY_HEAPSORT:
argsort = npy_aheapsort;
break;
- case NPY_MERGESORT:
- argsort = npy_amergesort;
+ case NPY_STABLESORT:
+ argsort = npy_atimsort;
break;
}
}
@@ -1425,7 +1442,7 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
goto fail;
}
}
- if (!PyArray_DESCR(mps[i])->f->argsort[NPY_MERGESORT]
+ if (!PyArray_DESCR(mps[i])->f->argsort[NPY_STABLESORT]
&& !PyArray_DESCR(mps[i])->f->compare) {
PyErr_Format(PyExc_TypeError,
"item %zd type does not have compare function", i);
@@ -1499,6 +1516,9 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
char *valbuffer, *indbuffer;
int *swaps;
+ if (N == 0 || maxelsize == 0 || sizeof(npy_intp) == 0) {
+ goto fail;
+ }
valbuffer = PyDataMem_NEW(N * maxelsize);
if (valbuffer == NULL) {
goto fail;
@@ -1521,9 +1541,9 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
int rcode;
elsize = PyArray_DESCR(mps[j])->elsize;
astride = PyArray_STRIDES(mps[j])[axis];
- argsort = PyArray_DESCR(mps[j])->f->argsort[NPY_MERGESORT];
+ argsort = PyArray_DESCR(mps[j])->f->argsort[NPY_STABLESORT];
if(argsort == NULL) {
- argsort = npy_amergesort;
+ argsort = npy_atimsort;
}
_unaligned_strided_byte_copy(valbuffer, (npy_intp) elsize,
its[j]->dataptr, astride, N, elsize);
@@ -1560,9 +1580,9 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
}
for (j = 0; j < n; j++) {
int rcode;
- argsort = PyArray_DESCR(mps[j])->f->argsort[NPY_MERGESORT];
+ argsort = PyArray_DESCR(mps[j])->f->argsort[NPY_STABLESORT];
if(argsort == NULL) {
- argsort = npy_amergesort;
+ argsort = npy_atimsort;
}
rcode = argsort(its[j]->dataptr,
(npy_intp *)rit->dataptr, N, mps[j]);
@@ -2185,12 +2205,46 @@ PyArray_Nonzero(PyArrayObject *self)
npy_intp ret_dims[2];
PyArray_NonzeroFunc *nonzero = PyArray_DESCR(self)->f->nonzero;
npy_intp nonzero_count;
+ npy_intp added_count = 0;
+ int is_bool;
NpyIter *iter;
NpyIter_IterNextFunc *iternext;
NpyIter_GetMultiIndexFunc *get_multi_index;
char **dataptr;
- int is_empty = 0;
+
+ /* Special case - nonzero(zero_d) is nonzero(atleast_1d(zero_d)) */
+ if (ndim == 0) {
+ char const* msg;
+ if (PyArray_ISBOOL(self)) {
+ msg =
+ "Calling nonzero on 0d arrays is deprecated, as it behaves "
+ "surprisingly. Use `atleast_1d(cond).nonzero()` if the old "
+ "behavior was intended. If the context of this warning is of "
+ "the form `arr[nonzero(cond)]`, just use `arr[cond]`.";
+ }
+ else {
+ msg =
+ "Calling nonzero on 0d arrays is deprecated, as it behaves "
+ "surprisingly. Use `atleast_1d(arr).nonzero()` if the old "
+ "behavior was intended.";
+ }
+ if (DEPRECATE(msg) < 0) {
+ return NULL;
+ }
+
+ static npy_intp const zero_dim_shape[1] = {1};
+ static npy_intp const zero_dim_strides[1] = {0};
+
+ PyArrayObject *self_1d = (PyArrayObject *)PyArray_NewFromDescrAndBase(
+ Py_TYPE(self), PyArray_DESCR(self),
+ 1, zero_dim_shape, zero_dim_strides, PyArray_BYTES(self),
+ PyArray_FLAGS(self), (PyObject *)self, (PyObject *)self);
+ if (self_1d == NULL) {
+ return NULL;
+ }
+ return PyArray_Nonzero(self_1d);
+ }
/*
* First count the number of non-zeros in 'self'.
@@ -2200,9 +2254,11 @@ PyArray_Nonzero(PyArrayObject *self)
return NULL;
}
+ is_bool = PyArray_ISBOOL(self);
+
/* Allocate the result as a 2D array */
ret_dims[0] = nonzero_count;
- ret_dims[1] = (ndim == 0) ? 1 : ndim;
+ ret_dims[1] = ndim;
ret = (PyArrayObject *)PyArray_NewFromDescr(
&PyArray_Type, PyArray_DescrFromType(NPY_INTP),
2, ret_dims, NULL, NULL,
@@ -2212,11 +2268,11 @@ PyArray_Nonzero(PyArrayObject *self)
}
/* If it's a one-dimensional result, don't use an iterator */
- if (ndim <= 1) {
+ if (ndim == 1) {
npy_intp * multi_index = (npy_intp *)PyArray_DATA(ret);
char * data = PyArray_BYTES(self);
- npy_intp stride = (ndim == 0) ? 0 : PyArray_STRIDE(self, 0);
- npy_intp count = (ndim == 0) ? 1 : PyArray_DIM(self, 0);
+ npy_intp stride = PyArray_STRIDE(self, 0);
+ npy_intp count = PyArray_DIM(self, 0);
NPY_BEGIN_THREADS_DEF;
/* nothing to do */
@@ -2227,7 +2283,7 @@ PyArray_Nonzero(PyArrayObject *self)
NPY_BEGIN_THREADS_THRESHOLDED(count);
/* avoid function call for bool */
- if (PyArray_ISBOOL(self)) {
+ if (is_bool) {
/*
* use fast memchr variant for sparse data, see gh-4370
* the fast bool count is followed by this sparse path is faster
@@ -2260,6 +2316,9 @@ PyArray_Nonzero(PyArrayObject *self)
npy_intp j;
for (j = 0; j < count; ++j) {
if (nonzero(data, self)) {
+ if (++added_count > nonzero_count) {
+ break;
+ }
*multi_index++ = j;
}
data += stride;
@@ -2310,7 +2369,7 @@ PyArray_Nonzero(PyArrayObject *self)
multi_index = (npy_intp *)PyArray_DATA(ret);
/* Get the multi-index for each non-zero element */
- if (PyArray_ISBOOL(self)) {
+ if (is_bool) {
/* avoid function call for bool */
do {
if (**dataptr != 0) {
@@ -2322,6 +2381,9 @@ PyArray_Nonzero(PyArrayObject *self)
else {
do {
if (nonzero(*dataptr, self)) {
+ if (++added_count > nonzero_count) {
+ break;
+ }
get_multi_index(iter, multi_index);
multi_index += ndim;
}
@@ -2334,9 +2396,13 @@ PyArray_Nonzero(PyArrayObject *self)
NpyIter_Deallocate(iter);
finish:
- /* Treat zero-dimensional as shape (1,) */
- if (ndim == 0) {
- ndim = 1;
+ /* if executed `nonzero()` check for miscount due to side-effect */
+ if (!is_bool && added_count != nonzero_count) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "number of non-zero array elements "
+ "changed during function execution.");
+ Py_DECREF(ret);
+ return NULL;
}
ret_tuple = PyTuple_New(ndim);
@@ -2345,18 +2411,11 @@ finish:
return NULL;
}
- for (i = 0; i < PyArray_NDIM(ret); ++i) {
- if (PyArray_DIMS(ret)[i] == 0) {
- is_empty = 1;
- break;
- }
- }
-
/* Create views into ret, one for each dimension */
for (i = 0; i < ndim; ++i) {
npy_intp stride = ndim * NPY_SIZEOF_INTP;
/* the result is an empty array, the view must point to valid memory */
- npy_intp data_offset = is_empty ? 0 : i * NPY_SIZEOF_INTP;
+ npy_intp data_offset = nonzero_count == 0 ? 0 : i * NPY_SIZEOF_INTP;
PyArrayObject *view = (PyArrayObject *)PyArray_NewFromDescrAndBase(
Py_TYPE(ret), PyArray_DescrFromType(NPY_INTP),
@@ -2392,7 +2451,7 @@ PyArray_MultiIndexGetItem(PyArrayObject *self, npy_intp *multi_index)
npy_intp ind = multi_index[idim];
if (check_and_adjust_index(&ind, shapevalue, idim, NULL) < 0) {
- return NULL;
+ return NULL;
}
data += ind * strides[idim];
}
diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c
index d14f1a72e..64c978361 100644
--- a/numpy/core/src/multiarray/iterators.c
+++ b/numpy/core/src/multiarray/iterators.c
@@ -667,8 +667,9 @@ iter_subscript(PyArrayIterObject *self, PyObject *ind)
}
Py_DECREF(indtype);
Py_DECREF(obj);
- Py_SETREF(new, iter_subscript_int(self, (PyArrayObject *)new));
- return new;
+ ret = (PyArrayObject *)iter_subscript_int(self, (PyArrayObject *)new);
+ Py_DECREF(new);
+ return (PyObject *)ret;
fail:
@@ -1241,151 +1242,150 @@ PyArray_Broadcast(PyArrayMultiIterObject *mit)
return 0;
}
-/*NUMPY_API
- * Get MultiIterator from array of Python objects and any additional
- *
- * PyObject **mps -- array of PyObjects
- * int n - number of PyObjects in the array
- * int nadd - number of additional arrays to include in the iterator.
- *
- * Returns a multi-iterator object.
+static NPY_INLINE PyObject*
+multiiter_wrong_number_of_args(void)
+{
+ return PyErr_Format(PyExc_ValueError,
+ "Need at least 0 and at most %d "
+ "array objects.", NPY_MAXARGS);
+}
+
+/*
+ * Common implementation for all PyArrayMultiIterObject constructors.
*/
-NPY_NO_EXPORT PyObject *
-PyArray_MultiIterFromObjects(PyObject **mps, int n, int nadd, ...)
+static PyObject*
+multiiter_new_impl(int n_args, PyObject **args)
{
- va_list va;
PyArrayMultiIterObject *multi;
- PyObject *current;
- PyObject *arr;
-
- int i, ntot, err=0;
+ int i;
- ntot = n + nadd;
- if (ntot < 1 || ntot > NPY_MAXARGS) {
- PyErr_Format(PyExc_ValueError,
- "Need at least 1 and at most %d "
- "array objects.", NPY_MAXARGS);
- return NULL;
- }
multi = PyArray_malloc(sizeof(PyArrayMultiIterObject));
if (multi == NULL) {
return PyErr_NoMemory();
}
PyObject_Init((PyObject *)multi, &PyArrayMultiIter_Type);
+ multi->numiter = 0;
- for (i = 0; i < ntot; i++) {
- multi->iters[i] = NULL;
- }
- multi->numiter = ntot;
- multi->index = 0;
+ for (i = 0; i < n_args; ++i) {
+ PyObject *obj = args[i];
+ PyObject *arr;
+ PyArrayIterObject *it;
- va_start(va, nadd);
- for (i = 0; i < ntot; i++) {
- if (i < n) {
- current = mps[i];
- }
- else {
- current = va_arg(va, PyObject *);
- }
- arr = PyArray_FROM_O(current);
- if (arr == NULL) {
- err = 1;
- break;
+ if (PyObject_IsInstance(obj, (PyObject *)&PyArrayMultiIter_Type)) {
+ PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)obj;
+ int j;
+
+ if (multi->numiter + mit->numiter > NPY_MAXARGS) {
+ multiiter_wrong_number_of_args();
+ goto fail;
+ }
+ for (j = 0; j < mit->numiter; ++j) {
+ arr = (PyObject *)mit->iters[j]->ao;
+ it = (PyArrayIterObject *)PyArray_IterNew(arr);
+ if (it == NULL) {
+ goto fail;
+ }
+ multi->iters[multi->numiter++] = it;
+ }
}
- else {
- multi->iters[i] = (PyArrayIterObject *)PyArray_IterNew(arr);
- if (multi->iters[i] == NULL) {
- err = 1;
- break;
+ else if (multi->numiter < NPY_MAXARGS) {
+ arr = PyArray_FromAny(obj, NULL, 0, 0, 0, NULL);
+ if (arr == NULL) {
+ goto fail;
}
+ it = (PyArrayIterObject *)PyArray_IterNew(arr);
Py_DECREF(arr);
+ if (it == NULL) {
+ goto fail;
+ }
+ multi->iters[multi->numiter++] = it;
+ }
+ else {
+ multiiter_wrong_number_of_args();
+ goto fail;
}
}
- va_end(va);
- if (!err && PyArray_Broadcast(multi) < 0) {
- err = 1;
+ if (multi->numiter < 0) {
+ multiiter_wrong_number_of_args();
+ goto fail;
}
- if (err) {
- Py_DECREF(multi);
- return NULL;
+ if (PyArray_Broadcast(multi) < 0) {
+ goto fail;
}
PyArray_MultiIter_RESET(multi);
+
return (PyObject *)multi;
+
+fail:
+ Py_DECREF(multi);
+
+ return NULL;
}
/*NUMPY_API
- * Get MultiIterator,
+ * Get MultiIterator from array of Python objects and any additional
+ *
+ * PyObject **mps - array of PyObjects
+ * int n - number of PyObjects in the array
+ * int nadd - number of additional arrays to include in the iterator.
+ *
+ * Returns a multi-iterator object.
*/
-NPY_NO_EXPORT PyObject *
-PyArray_MultiIterNew(int n, ...)
+NPY_NO_EXPORT PyObject*
+PyArray_MultiIterFromObjects(PyObject **mps, int n, int nadd, ...)
{
+ PyObject *args_impl[NPY_MAXARGS];
+ int ntot = n + nadd;
+ int i;
va_list va;
- PyArrayMultiIterObject *multi;
- PyObject *current;
- PyObject *arr;
-
- int i, err = 0;
- if (n < 1 || n > NPY_MAXARGS) {
- PyErr_Format(PyExc_ValueError,
- "Need at least 1 and at most %d "
- "array objects.", NPY_MAXARGS);
- return NULL;
+ if ((ntot > NPY_MAXARGS) || (ntot < 0)) {
+ return multiiter_wrong_number_of_args();
}
- /* fprintf(stderr, "multi new...");*/
+ for (i = 0; i < n; ++i) {
+ args_impl[i] = mps[i];
+ }
- multi = PyArray_malloc(sizeof(PyArrayMultiIterObject));
- if (multi == NULL) {
- return PyErr_NoMemory();
+ va_start(va, nadd);
+ for (; i < ntot; ++i) {
+ args_impl[i] = va_arg(va, PyObject *);
}
- PyObject_Init((PyObject *)multi, &PyArrayMultiIter_Type);
+ va_end(va);
- for (i = 0; i < n; i++) {
- multi->iters[i] = NULL;
+ return multiiter_new_impl(ntot, args_impl);
+}
+
+/*NUMPY_API
+ * Get MultiIterator,
+ */
+NPY_NO_EXPORT PyObject*
+PyArray_MultiIterNew(int n, ...)
+{
+ PyObject *args_impl[NPY_MAXARGS];
+ int i;
+ va_list va;
+
+ if ((n > NPY_MAXARGS) || (n < 0)) {
+ return multiiter_wrong_number_of_args();
}
- multi->numiter = n;
- multi->index = 0;
va_start(va, n);
- for (i = 0; i < n; i++) {
- current = va_arg(va, PyObject *);
- arr = PyArray_FROM_O(current);
- if (arr == NULL) {
- err = 1;
- break;
- }
- else {
- multi->iters[i] = (PyArrayIterObject *)PyArray_IterNew(arr);
- if (multi->iters[i] == NULL) {
- err = 1;
- break;
- }
- Py_DECREF(arr);
- }
+ for (i = 0; i < n; ++i) {
+ args_impl[i] = va_arg(va, PyObject *);
}
va_end(va);
- if (!err && PyArray_Broadcast(multi) < 0) {
- err = 1;
- }
- if (err) {
- Py_DECREF(multi);
- return NULL;
- }
- PyArray_MultiIter_RESET(multi);
- return (PyObject *)multi;
+ return multiiter_new_impl(n, args_impl);
}
-static PyObject *
-arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds)
+static PyObject*
+arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args,
+ PyObject *kwds)
{
-
- Py_ssize_t n = 0;
- Py_ssize_t i, j, k;
- PyArrayMultiIterObject *multi;
- PyObject *arr;
+ PyObject *ret, *fast_seq;
+ Py_ssize_t n;
if (kwds != NULL && PyDict_Size(kwds) > 0) {
PyErr_SetString(PyExc_ValueError,
@@ -1393,80 +1393,17 @@ arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *k
return NULL;
}
- for (j = 0; j < PyTuple_Size(args); ++j) {
- PyObject *obj = PyTuple_GET_ITEM(args, j);
-
- if (PyObject_IsInstance(obj, (PyObject *)&PyArrayMultiIter_Type)) {
- /*
- * If obj is a multi-iterator, all its arrays will be added
- * to the new multi-iterator.
- */
- n += ((PyArrayMultiIterObject *)obj)->numiter;
- }
- else {
- /* If not, will try to convert it to a single array */
- ++n;
- }
- }
- if (n < 1 || n > NPY_MAXARGS) {
- if (PyErr_Occurred()) {
- return NULL;
- }
- PyErr_Format(PyExc_ValueError,
- "Need at least 1 and at most %d "
- "array objects.", NPY_MAXARGS);
+ fast_seq = PySequence_Fast(args, ""); // needed for pypy
+ if (fast_seq == NULL) {
return NULL;
}
-
- multi = PyArray_malloc(sizeof(PyArrayMultiIterObject));
- if (multi == NULL) {
- return PyErr_NoMemory();
- }
- PyObject_Init((PyObject *)multi, &PyArrayMultiIter_Type);
-
- multi->numiter = n;
- multi->index = 0;
- i = 0;
- for (j = 0; j < PyTuple_GET_SIZE(args); ++j) {
- PyObject *obj = PyTuple_GET_ITEM(args, j);
- PyArrayIterObject *it;
-
- if (PyObject_IsInstance(obj, (PyObject *)&PyArrayMultiIter_Type)) {
- PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)obj;
-
- for (k = 0; k < mit->numiter; ++k) {
- arr = (PyObject *)mit->iters[k]->ao;
- assert (arr != NULL);
- it = (PyArrayIterObject *)PyArray_IterNew(arr);
- if (it == NULL) {
- goto fail;
- }
- multi->iters[i++] = it;
- }
- }
- else {
- arr = PyArray_FROM_O(obj);
- if (arr == NULL) {
- goto fail;
- }
- it = (PyArrayIterObject *)PyArray_IterNew(arr);
- if (it == NULL) {
- goto fail;
- }
- multi->iters[i++] = it;
- Py_DECREF(arr);
- }
+ n = PySequence_Fast_GET_SIZE(fast_seq);
+ if (n > NPY_MAXARGS) {
+ return multiiter_wrong_number_of_args();
}
- assert (i == n);
- if (PyArray_Broadcast(multi) < 0) {
- goto fail;
- }
- PyArray_MultiIter_RESET(multi);
- return (PyObject *)multi;
-
- fail:
- Py_DECREF(multi);
- return NULL;
+ ret = multiiter_new_impl(n, PySequence_Fast_ITEMS(fast_seq));
+ Py_DECREF(fast_seq);
+ return ret;
}
static PyObject *
diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
index 16bacf1ab..63b2a8842 100644
--- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
+++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
@@ -417,32 +417,31 @@ PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride,
#if !NPY_USE_UNALIGNED_ACCESS
}
else {
- /* contiguous dst */
- if (itemsize != 0 && dst_stride == itemsize) {
- /* contiguous src */
- if (itemsize != 0 && src_stride == itemsize) {
- return &_contig_to_contig;
- }
- /* general src */
- else {
- switch (itemsize) {
- case 1:
- return &_aligned_strided_to_contig_size1;
+ if (itemsize != 0) {
+ if (dst_stride == itemsize) {
+ /* contiguous dst */
+ if (src_stride == itemsize) {
+ /* contiguous src, dst */
+ return &_contig_to_contig;
+ }
+ else {
+ /* general src */
+ switch (itemsize) {
+ case 1:
+ return &_aligned_strided_to_contig_size1;
/**begin repeat
* #elsize = 2, 4, 8, 16#
*/
- case @elsize@:
- return &_strided_to_contig_size@elsize@;
+ case @elsize@:
+ return &_strided_to_contig_size@elsize@;
/**end repeat**/
+ }
}
- }
- return &_strided_to_strided;
- }
- /* general dst */
- else {
- /* contiguous src */
- if (itemsize != 0 && src_stride == itemsize) {
+ return &_strided_to_strided;
+ }
+ else if (src_stride == itemsize) {
+ /* contiguous src, general dst */
switch (itemsize) {
case 1:
return &_aligned_contig_to_strided_size1;
@@ -456,18 +455,18 @@ PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride,
return &_strided_to_strided;
}
- /* general src */
- else {
- switch (itemsize) {
- case 1:
- return &_aligned_strided_to_strided_size1;
+ }
+ else {
+ /* general src, dst */
+ switch (itemsize) {
+ case 1:
+ return &_aligned_strided_to_strided_size1;
/**begin repeat
* #elsize = 2, 4, 8, 16#
*/
- case @elsize@:
- return &_strided_to_strided_size@elsize@;
+ case @elsize@:
+ return &_strided_to_strided_size@elsize@;
/**end repeat**/
- }
}
}
}
@@ -592,7 +591,7 @@ NPY_NO_EXPORT PyArray_StridedUnaryOp *
/* contiguous dst */
if (itemsize != 0 && dst_stride == itemsize) {
/* contiguous src */
- if (itemsize != 0 && src_stride == itemsize) {
+ if (src_stride == itemsize) {
switch (itemsize) {
/**begin repeat1
* #elsize = 2, 4, 8, 16#
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index a7b4ff236..9e54a2c64 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -15,6 +15,7 @@
#include "common.h"
#include "ctors.h"
+#include "descriptor.h"
#include "iterators.h"
#include "mapping.h"
#include "lowlevel_strided_loops.h"
@@ -712,26 +713,26 @@ prepare_index(PyArrayObject *self, PyObject *index,
* to find the ellipsis value or append an ellipsis if necessary.
*/
if (used_ndim < PyArray_NDIM(self)) {
- if (index_type & HAS_ELLIPSIS) {
- indices[ellipsis_pos].value = PyArray_NDIM(self) - used_ndim;
- used_ndim = PyArray_NDIM(self);
- new_ndim += indices[ellipsis_pos].value;
- }
- else {
- /*
- * There is no ellipsis yet, but it is not a full index
- * so we append an ellipsis to the end.
- */
- index_type |= HAS_ELLIPSIS;
- indices[curr_idx].object = NULL;
- indices[curr_idx].type = HAS_ELLIPSIS;
- indices[curr_idx].value = PyArray_NDIM(self) - used_ndim;
- ellipsis_pos = curr_idx;
-
- used_ndim = PyArray_NDIM(self);
- new_ndim += indices[curr_idx].value;
- curr_idx += 1;
- }
+ if (index_type & HAS_ELLIPSIS) {
+ indices[ellipsis_pos].value = PyArray_NDIM(self) - used_ndim;
+ used_ndim = PyArray_NDIM(self);
+ new_ndim += indices[ellipsis_pos].value;
+ }
+ else {
+ /*
+ * There is no ellipsis yet, but it is not a full index
+ * so we append an ellipsis to the end.
+ */
+ index_type |= HAS_ELLIPSIS;
+ indices[curr_idx].object = NULL;
+ indices[curr_idx].type = HAS_ELLIPSIS;
+ indices[curr_idx].value = PyArray_NDIM(self) - used_ndim;
+ ellipsis_pos = curr_idx;
+
+ used_ndim = PyArray_NDIM(self);
+ new_ndim += indices[curr_idx].value;
+ curr_idx += 1;
+ }
}
else if (used_ndim > PyArray_NDIM(self)) {
PyErr_SetString(PyExc_IndexError,
@@ -1395,9 +1396,9 @@ array_subscript_asarray(PyArrayObject *self, PyObject *op)
/*
* Attempts to subscript an array using a field name or list of field names.
*
- * If an error occurred, return 0 and set view to NULL. If the subscript is not
- * a string or list of strings, return -1 and set view to NULL. Otherwise
- * return 0 and set view to point to a new view into arr for the given fields.
+ * ret = 0, view != NULL: view points to the requested fields of arr
+ * ret = 0, view == NULL: an error occurred
+ * ret = -1, view == NULL: unrecognized input, this is not a field index.
*/
NPY_NO_EXPORT int
_get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view)
@@ -1440,111 +1441,44 @@ _get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view)
}
return 0;
}
+
/* next check for a list of field names */
else if (PySequence_Check(ind) && !PyTuple_Check(ind)) {
npy_intp seqlen, i;
- PyObject *name = NULL, *tup;
- PyObject *fields, *names;
PyArray_Descr *view_dtype;
seqlen = PySequence_Size(ind);
- /* quit if have a 0-d array (seqlen==-1) or a 0-len array */
+ /* quit if have a fake sequence-like, which errors on len()*/
if (seqlen == -1) {
PyErr_Clear();
return -1;
}
+ /* 0-len list is handled elsewhere as an integer index */
if (seqlen == 0) {
return -1;
}
- fields = PyDict_New();
- if (fields == NULL) {
- return 0;
- }
- names = PyTuple_New(seqlen);
- if (names == NULL) {
- Py_DECREF(fields);
- return 0;
- }
-
+ /* check the items are strings */
for (i = 0; i < seqlen; i++) {
- name = PySequence_GetItem(ind, i);
- if (name == NULL) {
- /* only happens for strange sequence objects */
+ npy_bool is_string;
+ PyObject *item = PySequence_GetItem(ind, i);
+ if (item == NULL) {
PyErr_Clear();
- Py_DECREF(fields);
- Py_DECREF(names);
return -1;
}
-
- if (!PyBaseString_Check(name)) {
- Py_DECREF(name);
- Py_DECREF(fields);
- Py_DECREF(names);
+ is_string = PyBaseString_Check(item);
+ Py_DECREF(item);
+ if (!is_string) {
return -1;
}
-
- tup = PyDict_GetItem(PyArray_DESCR(arr)->fields, name);
- if (tup == NULL){
- PyObject *errmsg = PyUString_FromString("no field of name ");
- PyUString_ConcatAndDel(&errmsg, name);
- PyErr_SetObject(PyExc_ValueError, errmsg);
- Py_DECREF(errmsg);
- Py_DECREF(fields);
- Py_DECREF(names);
- return 0;
- }
- /* disallow use of titles as index */
- if (PyTuple_Size(tup) == 3) {
- PyObject *title = PyTuple_GET_ITEM(tup, 2);
- int titlecmp = PyObject_RichCompareBool(title, name, Py_EQ);
- if (titlecmp == 1) {
- /* if title == name, we got a title, not a field name */
- PyErr_SetString(PyExc_KeyError,
- "cannot use field titles in multi-field index");
- }
- if (titlecmp != 0 || PyDict_SetItem(fields, title, tup) < 0) {
- Py_DECREF(name);
- Py_DECREF(fields);
- Py_DECREF(names);
- return 0;
- }
- }
- /* disallow duplicate field indices */
- if (PyDict_Contains(fields, name)) {
- PyObject *errmsg = PyUString_FromString(
- "duplicate field of name ");
- PyUString_ConcatAndDel(&errmsg, name);
- PyErr_SetObject(PyExc_ValueError, errmsg);
- Py_DECREF(errmsg);
- Py_DECREF(fields);
- Py_DECREF(names);
- return 0;
- }
- if (PyDict_SetItem(fields, name, tup) < 0) {
- Py_DECREF(name);
- Py_DECREF(fields);
- Py_DECREF(names);
- return 0;
- }
- if (PyTuple_SetItem(names, i, name) < 0) {
- Py_DECREF(fields);
- Py_DECREF(names);
- return 0;
- }
}
- view_dtype = PyArray_DescrNewFromType(NPY_VOID);
+ /* Call into the dtype subscript */
+ view_dtype = arraydescr_field_subset_view(PyArray_DESCR(arr), ind);
if (view_dtype == NULL) {
- Py_DECREF(fields);
- Py_DECREF(names);
return 0;
}
- view_dtype->elsize = PyArray_DESCR(arr)->elsize;
- view_dtype->names = names;
- view_dtype->fields = fields;
- view_dtype->flags = PyArray_DESCR(arr)->flags;
*view = (PyArrayObject*)PyArray_NewFromDescr_int(
Py_TYPE(arr),
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index c3040b473..d458638ae 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -6,6 +6,7 @@
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#include "numpy/arrayobject.h"
+#include "arrayobject.h"
#include "numpy/arrayscalars.h"
#include "arrayfunction_override.h"
@@ -577,6 +578,10 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
+ file = NpyPath_PathlikeToFspath(file);
+ if (file == NULL) {
+ return NULL;
+ }
if (PyBytes_Check(file) || PyUnicode_Check(file)) {
file = npy_PyFile_OpenFile(file, "wb");
if (file == NULL) {
@@ -824,8 +829,8 @@ array_astype(PyArrayObject *self, PyObject *args, PyObject *kwds)
PyArrayObject *ret;
/* If the requested dtype is flexible, adapt it */
- PyArray_AdaptFlexibleDType((PyObject *)self, PyArray_DESCR(self),
- &dtype);
+ dtype = PyArray_AdaptFlexibleDType((PyObject *)self,
+ PyArray_DESCR(self), dtype);
if (dtype == NULL) {
return NULL;
}
@@ -1687,7 +1692,7 @@ array_reduce(PyArrayObject *self, PyObject *NPY_UNUSED(args))
Notice because Python does not describe a mechanism to write
raw data to the pickle, this performs a copy to a string first
- This issue is now adressed in protocol 5, where a buffer is serialized
+ This issue is now addressed in protocol 5, where a buffer is serialized
instead of a string,
*/
@@ -2002,7 +2007,7 @@ array_setstate(PyArrayObject *self, PyObject *args)
fa->nd = nd;
if (nd > 0) {
- fa->dimensions = npy_alloc_cache_dim(3*nd);
+ fa->dimensions = npy_alloc_cache_dim(2 * nd);
if (fa->dimensions == NULL) {
return PyErr_NoMemory();
}
@@ -2029,10 +2034,11 @@ array_setstate(PyArrayObject *self, PyObject *args)
if (!IsAligned(self) || swap || (len <= 1000)) {
#endif
npy_intp num = PyArray_NBYTES(self);
+ if (num == 0) {
+ Py_RETURN_NONE;
+ }
fa->data = PyDataMem_NEW(num);
if (PyArray_DATA(self) == NULL) {
- fa->nd = 0;
- npy_free_cache_dim_array(self);
Py_DECREF(rawdata);
return PyErr_NoMemory();
}
@@ -2074,11 +2080,13 @@ array_setstate(PyArrayObject *self, PyObject *args)
}
}
else {
- fa->data = PyDataMem_NEW(PyArray_NBYTES(self));
+ npy_intp num = PyArray_NBYTES(self);
+ int elsize = PyArray_DESCR(self)->elsize;
+ if (num == 0 || elsize == 0) {
+ Py_RETURN_NONE;
+ }
+ fa->data = PyDataMem_NEW(num);
if (PyArray_DATA(self) == NULL) {
- fa->nd = 0;
- fa->data = PyDataMem_NEW(PyArray_DESCR(self)->elsize);
- npy_free_cache_dim_array(self);
return PyErr_NoMemory();
}
if (PyDataType_FLAGCHK(PyArray_DESCR(self), NPY_NEEDS_INIT)) {
@@ -2100,37 +2108,22 @@ array_setstate(PyArrayObject *self, PyObject *args)
NPY_NO_EXPORT int
PyArray_Dump(PyObject *self, PyObject *file, int protocol)
{
- PyObject *cpick = NULL;
+ static PyObject *method = NULL;
PyObject *ret;
- if (protocol < 0) {
- protocol = 2;
- }
-
-#if defined(NPY_PY3K)
- cpick = PyImport_ImportModule("pickle");
-#else
- cpick = PyImport_ImportModule("cPickle");
-#endif
- if (cpick == NULL) {
+ npy_cache_import("numpy.core._methods", "_dump", &method);
+ if (method == NULL) {
return -1;
}
- if (PyBytes_Check(file) || PyUnicode_Check(file)) {
- file = npy_PyFile_OpenFile(file, "wb");
- if (file == NULL) {
- Py_DECREF(cpick);
- return -1;
- }
+ if (protocol < 0) {
+ ret = PyObject_CallFunction(method, "OO", self, file);
}
else {
- Py_INCREF(file);
+ ret = PyObject_CallFunction(method, "OOi", self, file, protocol);
}
- ret = PyObject_CallMethod(cpick, "dump", "OOi", self, file, protocol);
- Py_XDECREF(ret);
- Py_DECREF(file);
- Py_DECREF(cpick);
- if (PyErr_Occurred()) {
+ if (ret == NULL) {
return -1;
}
+ Py_DECREF(ret);
return 0;
}
@@ -2138,49 +2131,31 @@ PyArray_Dump(PyObject *self, PyObject *file, int protocol)
NPY_NO_EXPORT PyObject *
PyArray_Dumps(PyObject *self, int protocol)
{
- PyObject *cpick = NULL;
- PyObject *ret;
+ static PyObject *method = NULL;
+ npy_cache_import("numpy.core._methods", "_dumps", &method);
+ if (method == NULL) {
+ return NULL;
+ }
if (protocol < 0) {
- protocol = 2;
+ return PyObject_CallFunction(method, "O", self);
}
-#if defined(NPY_PY3K)
- cpick = PyImport_ImportModule("pickle");
-#else
- cpick = PyImport_ImportModule("cPickle");
-#endif
- if (cpick == NULL) {
- return NULL;
+ else {
+ return PyObject_CallFunction(method, "Oi", self, protocol);
}
- ret = PyObject_CallMethod(cpick, "dumps", "Oi", self, protocol);
- Py_DECREF(cpick);
- return ret;
}
static PyObject *
-array_dump(PyArrayObject *self, PyObject *args)
+array_dump(PyArrayObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *file = NULL;
- int ret;
-
- if (!PyArg_ParseTuple(args, "O:dump", &file)) {
- return NULL;
- }
- ret = PyArray_Dump((PyObject *)self, file, 2);
- if (ret < 0) {
- return NULL;
- }
- Py_RETURN_NONE;
+ NPY_FORWARD_NDARRAY_METHOD("_dump");
}
static PyObject *
-array_dumps(PyArrayObject *self, PyObject *args)
+array_dumps(PyArrayObject *self, PyObject *args, PyObject *kwds)
{
- if (!PyArg_ParseTuple(args, "")) {
- return NULL;
- }
- return PyArray_Dumps((PyObject *)self, 2);
+ NPY_FORWARD_NDARRAY_METHOD("_dumps");
}
@@ -2403,21 +2378,7 @@ array_trace(PyArrayObject *self, PyObject *args, PyObject *kwds)
static PyObject *
array_clip(PyArrayObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *min = NULL, *max = NULL;
- PyArrayObject *out = NULL;
- static char *kwlist[] = {"min", "max", "out", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO&:clip", kwlist,
- &min,
- &max,
- PyArray_OutputConverter, &out)) {
- return NULL;
- }
- if (max == NULL && min == NULL) {
- PyErr_SetString(PyExc_ValueError, "One of max or min must be given.");
- return NULL;
- }
- return PyArray_Return((PyArrayObject *)PyArray_Clip(self, min, max, out));
+ NPY_FORWARD_NDARRAY_METHOD("_clip");
}
@@ -2567,6 +2528,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
}
}
PyArray_ENABLEFLAGS(self, NPY_ARRAY_WRITEABLE);
+ PyArray_CLEARFLAGS(self, NPY_ARRAY_WARN_ON_WRITE);
}
else {
fa->flags = flagback;
@@ -2579,9 +2541,9 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
}
else {
PyArray_CLEARFLAGS(self, NPY_ARRAY_WRITEABLE);
+ PyArray_CLEARFLAGS(self, NPY_ARRAY_WARN_ON_WRITE);
}
}
-
Py_RETURN_NONE;
}
@@ -2769,10 +2731,10 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
METH_VARARGS, NULL},
{"dumps",
(PyCFunction) array_dumps,
- METH_VARARGS, NULL},
+ METH_VARARGS | METH_KEYWORDS, NULL},
{"dump",
(PyCFunction) array_dump,
- METH_VARARGS, NULL},
+ METH_VARARGS | METH_KEYWORDS, NULL},
{"__complex__",
(PyCFunction) array_complex,
diff --git a/numpy/core/src/multiarray/methods.h b/numpy/core/src/multiarray/methods.h
index 7bf87f42d..b96a3c8a8 100644
--- a/numpy/core/src/multiarray/methods.h
+++ b/numpy/core/src/multiarray/methods.h
@@ -1,9 +1,32 @@
#ifndef _NPY_ARRAY_METHODS_H_
#define _NPY_ARRAY_METHODS_H_
+#include "npy_import.h"
+
extern NPY_NO_EXPORT PyMethodDef array_methods[];
NPY_NO_EXPORT const char *
npy_casting_to_string(NPY_CASTING casting);
+/* Pathlib support */
+static inline PyObject *
+NpyPath_PathlikeToFspath(PyObject *file)
+{
+ static PyObject *os_PathLike = NULL;
+ static PyObject *os_fspath = NULL;
+ npy_cache_import("numpy.compat", "os_PathLike", &os_PathLike);
+ if (os_PathLike == NULL) {
+ return NULL;
+ }
+ npy_cache_import("numpy.compat", "os_fspath", &os_fspath);
+ if (os_fspath == NULL) {
+ return NULL;
+ }
+
+ if (!PyObject_IsInstance(file, os_PathLike)) {
+ return file;
+ }
+ return PyObject_CallFunctionObjArgs(os_fspath, file, NULL);
+}
+
#endif
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 88ed4664a..915c9fcd9 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -130,7 +130,7 @@ PyArray_GetPriority(PyObject *obj, double default_)
* Multiply a List of ints
*/
NPY_NO_EXPORT int
-PyArray_MultiplyIntList(int *l1, int n)
+PyArray_MultiplyIntList(int const *l1, int n)
{
int s = 1;
@@ -144,7 +144,7 @@ PyArray_MultiplyIntList(int *l1, int n)
* Multiply a List
*/
NPY_NO_EXPORT npy_intp
-PyArray_MultiplyList(npy_intp *l1, int n)
+PyArray_MultiplyList(npy_intp const *l1, int n)
{
npy_intp s = 1;
@@ -180,7 +180,7 @@ PyArray_OverflowMultiplyList(npy_intp *l1, int n)
* Produce a pointer into array
*/
NPY_NO_EXPORT void *
-PyArray_GetPtr(PyArrayObject *obj, npy_intp* ind)
+PyArray_GetPtr(PyArrayObject *obj, npy_intp const* ind)
{
int n = PyArray_NDIM(obj);
npy_intp *strides = PyArray_STRIDES(obj);
@@ -196,7 +196,7 @@ PyArray_GetPtr(PyArrayObject *obj, npy_intp* ind)
* Compare Lists
*/
NPY_NO_EXPORT int
-PyArray_CompareLists(npy_intp *l1, npy_intp *l2, int n)
+PyArray_CompareLists(npy_intp const *l1, npy_intp const *l2, int n)
{
int i;
@@ -411,9 +411,12 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis,
npy_intp *arr_shape;
if (PyArray_NDIM(arrays[iarrays]) != ndim) {
- PyErr_SetString(PyExc_ValueError,
- "all the input arrays must have same "
- "number of dimensions");
+ PyErr_Format(PyExc_ValueError,
+ "all the input arrays must have same number of "
+ "dimensions, but the array at index %d has %d "
+ "dimension(s) and the array at index %d has %d "
+ "dimension(s)",
+ 0, ndim, iarrays, PyArray_NDIM(arrays[iarrays]));
return NULL;
}
arr_shape = PyArray_SHAPE(arrays[iarrays]);
@@ -425,10 +428,12 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis,
}
/* Validate that the rest of the dimensions match */
else if (shape[idim] != arr_shape[idim]) {
- PyErr_SetString(PyExc_ValueError,
- "all the input array dimensions "
- "except for the concatenation axis "
- "must match exactly");
+ PyErr_Format(PyExc_ValueError,
+ "all the input array dimensions for the "
+ "concatenation axis must match exactly, but "
+ "along dimension %d, the array at index %d has "
+ "size %d and the array at index %d has size %d",
+ idim, 0, shape[idim], iarrays, arr_shape[idim]);
return NULL;
}
}
@@ -1755,7 +1760,7 @@ static PyObject *
array_copyto(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"dst","src","casting","where",NULL};
+ static char *kwlist[] = {"dst", "src", "casting", "where", NULL};
PyObject *wheremask_in = NULL;
PyArrayObject *dst = NULL, *src = NULL, *wheremask = NULL;
NPY_CASTING casting = NPY_SAME_KIND_CASTING;
@@ -1800,7 +1805,7 @@ static PyObject *
array_empty(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"shape","dtype","order",NULL};
+ static char *kwlist[] = {"shape", "dtype", "order", NULL};
PyArray_Descr *typecode = NULL;
PyArray_Dims shape = {NULL, 0};
NPY_ORDER order = NPY_CORDER;
@@ -1843,23 +1848,28 @@ static PyObject *
array_empty_like(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"prototype","dtype","order","subok",NULL};
+ static char *kwlist[] = {"prototype", "dtype", "order", "subok", "shape", NULL};
PyArrayObject *prototype = NULL;
PyArray_Descr *dtype = NULL;
NPY_ORDER order = NPY_KEEPORDER;
PyArrayObject *ret = NULL;
int subok = 1;
+ PyArray_Dims shape = {NULL, 0};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&i:empty_like", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&iO&:empty_like", kwlist,
&PyArray_Converter, &prototype,
&PyArray_DescrConverter2, &dtype,
&PyArray_OrderConverter, &order,
- &subok)) {
+ &subok,
+ &PyArray_IntpConverter, &shape)) {
goto fail;
}
/* steals the reference to dtype if it's not NULL */
- ret = (PyArrayObject *)PyArray_NewLikeArray(prototype,
- order, dtype, subok);
+ ret = (PyArrayObject *)PyArray_NewLikeArrayWithShape(prototype, order, dtype,
+ shape.len, shape.ptr, subok);
+ if (!ret) {
+ goto fail;
+ }
Py_DECREF(prototype);
return (PyObject *)ret;
@@ -1878,7 +1888,7 @@ static PyObject *
array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"dtype","obj", NULL};
+ static char *kwlist[] = {"dtype", "obj", NULL};
PyArray_Descr *typecode;
PyObject *obj = NULL, *tmpobj = NULL;
int alloc = 0;
@@ -1954,7 +1964,7 @@ array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
static PyObject *
array_zeros(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"shape","dtype","order",NULL};
+ static char *kwlist[] = {"shape", "dtype", "order", NULL};
PyArray_Descr *typecode = NULL;
PyArray_Dims shape = {NULL, 0};
NPY_ORDER order = NPY_CORDER;
@@ -2052,22 +2062,32 @@ array_fromstring(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds
static PyObject *
array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
{
- PyObject *file = NULL, *ret;
+ PyObject *file = NULL, *ret = NULL;
PyObject *err_type = NULL, *err_value = NULL, *err_traceback = NULL;
char *sep = "";
Py_ssize_t nin = -1;
- static char *kwlist[] = {"file", "dtype", "count", "sep", NULL};
+ static char *kwlist[] = {"file", "dtype", "count", "sep", "offset", NULL};
PyArray_Descr *type = NULL;
int own;
- npy_off_t orig_pos = 0;
+ npy_off_t orig_pos = 0, offset = 0;
FILE *fp;
if (!PyArg_ParseTupleAndKeywords(args, keywds,
- "O|O&" NPY_SSIZE_T_PYFMT "s:fromfile", kwlist,
- &file, PyArray_DescrConverter, &type, &nin, &sep)) {
+ "O|O&" NPY_SSIZE_T_PYFMT "s" NPY_OFF_T_PYFMT ":fromfile", kwlist,
+ &file, PyArray_DescrConverter, &type, &nin, &sep, &offset)) {
Py_XDECREF(type);
return NULL;
}
+
+ file = NpyPath_PathlikeToFspath(file);
+ if (file == NULL) {
+ return NULL;
+ }
+
+ if (offset != 0 && strcmp(sep, "") != 0) {
+ PyErr_SetString(PyExc_TypeError, "'offset' argument only permitted for binary files");
+ return NULL;
+ }
if (PyString_Check(file) || PyUnicode_Check(file)) {
file = npy_PyFile_OpenFile(file, "rb");
if (file == NULL) {
@@ -2084,6 +2104,10 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
Py_DECREF(file);
return NULL;
}
+ if (npy_fseek(fp, offset, SEEK_CUR) != 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ goto cleanup;
+ }
if (type == NULL) {
type = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
}
@@ -2093,6 +2117,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
* we need to clear it, and restore it later to ensure that
* we can cleanup the duplicated file descriptor properly.
*/
+cleanup:
PyErr_Fetch(&err_type, &err_value, &err_traceback);
if (npy_PyFile_DupClose2(file, fp, orig_pos) < 0) {
npy_PyErr_ChainExceptions(err_type, err_value, err_traceback);
@@ -4012,7 +4037,7 @@ array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_
}
else if (result == MEM_OVERLAP_TOO_HARD) {
if (raise_exceptions) {
- npy_cache_import("numpy.core._internal", "TooHardError",
+ npy_cache_import("numpy.core._exceptions", "TooHardError",
&too_hard_cls);
if (too_hard_cls) {
PyErr_SetString(too_hard_cls, "Exceeded max_work");
@@ -4489,9 +4514,8 @@ NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_prepare = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_wrap = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_finalize = NULL;
-NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_buffer = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ufunc = NULL;
-NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_wrapped = NULL;
+NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_implementation = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_order = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_copy = NULL;
NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_dtype = NULL;
@@ -4506,9 +4530,8 @@ intern_strings(void)
npy_ma_str_array_prepare = PyUString_InternFromString("__array_prepare__");
npy_ma_str_array_wrap = PyUString_InternFromString("__array_wrap__");
npy_ma_str_array_finalize = PyUString_InternFromString("__array_finalize__");
- npy_ma_str_buffer = PyUString_InternFromString("__buffer__");
npy_ma_str_ufunc = PyUString_InternFromString("__array_ufunc__");
- npy_ma_str_wrapped = PyUString_InternFromString("__wrapped__");
+ npy_ma_str_implementation = PyUString_InternFromString("_implementation");
npy_ma_str_order = PyUString_InternFromString("order");
npy_ma_str_copy = PyUString_InternFromString("copy");
npy_ma_str_dtype = PyUString_InternFromString("dtype");
@@ -4518,7 +4541,7 @@ intern_strings(void)
return npy_ma_str_array && npy_ma_str_array_prepare &&
npy_ma_str_array_wrap && npy_ma_str_array_finalize &&
- npy_ma_str_buffer && npy_ma_str_ufunc && npy_ma_str_wrapped &&
+ npy_ma_str_ufunc && npy_ma_str_implementation &&
npy_ma_str_order && npy_ma_str_copy && npy_ma_str_dtype &&
npy_ma_str_ndmin && npy_ma_str_axis1 && npy_ma_str_axis2;
}
diff --git a/numpy/core/src/multiarray/multiarraymodule.h b/numpy/core/src/multiarray/multiarraymodule.h
index 60a3965c9..dd437e091 100644
--- a/numpy/core/src/multiarray/multiarraymodule.h
+++ b/numpy/core/src/multiarray/multiarraymodule.h
@@ -5,9 +5,8 @@ NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_prepare;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_wrap;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_finalize;
-NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_buffer;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_ufunc;
-NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_wrapped;
+NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_implementation;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_order;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_copy;
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_dtype;
diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c
index 7a33ac05e..18ca127e1 100644
--- a/numpy/core/src/multiarray/nditer_api.c
+++ b/numpy/core/src/multiarray/nditer_api.c
@@ -406,7 +406,7 @@ NpyIter_ResetToIterIndexRange(NpyIter *iter,
* Returns NPY_SUCCEED on success, NPY_FAIL on failure.
*/
NPY_NO_EXPORT int
-NpyIter_GotoMultiIndex(NpyIter *iter, npy_intp *multi_index)
+NpyIter_GotoMultiIndex(NpyIter *iter, npy_intp const *multi_index)
{
npy_uint32 itflags = NIT_ITFLAGS(iter);
int idim, ndim = NIT_NDIM(iter);
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index 18a2cc84f..3b3635afe 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -1101,8 +1101,8 @@ npyiter_prepare_one_operand(PyArrayObject **op,
/* We just have a borrowed reference to op_request_dtype */
Py_INCREF(op_request_dtype);
/* If the requested dtype is flexible, adapt it */
- PyArray_AdaptFlexibleDType((PyObject *)(*op), PyArray_DESCR(*op),
- &op_request_dtype);
+ op_request_dtype = PyArray_AdaptFlexibleDType((PyObject *)(*op), PyArray_DESCR(*op),
+ op_request_dtype);
if (op_request_dtype == NULL) {
return 0;
}
@@ -2120,8 +2120,8 @@ npyiter_apply_forced_iteration_order(NpyIter *iter, NPY_ORDER order)
/* Check that all the array inputs are fortran order */
for (iop = 0; iop < nop; ++iop, ++op) {
if (*op && !PyArray_CHKFLAGS(*op, NPY_ARRAY_F_CONTIGUOUS)) {
- forder = 0;
- break;
+ forder = 0;
+ break;
}
}
diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c
index 420501ce2..0ceb994ef 100644
--- a/numpy/core/src/multiarray/number.c
+++ b/numpy/core/src/multiarray/number.c
@@ -113,6 +113,7 @@ _PyArray_SetNumericOps(PyObject *dict)
SET(rint);
SET(conjugate);
SET(matmul);
+ SET(clip);
return 0;
}
@@ -179,6 +180,7 @@ _PyArray_GetNumericOps(void)
GET(rint);
GET(conjugate);
GET(matmul);
+ GET(clip);
return dict;
fail:
diff --git a/numpy/core/src/multiarray/number.h b/numpy/core/src/multiarray/number.h
index 33a7cf872..643241b3d 100644
--- a/numpy/core/src/multiarray/number.h
+++ b/numpy/core/src/multiarray/number.h
@@ -40,6 +40,7 @@ typedef struct {
PyObject *rint;
PyObject *conjugate;
PyObject *matmul;
+ PyObject *clip;
} NumericOps;
extern NPY_NO_EXPORT NumericOps n_ops;
diff --git a/numpy/core/src/multiarray/scalarapi.c b/numpy/core/src/multiarray/scalarapi.c
index bc435d1ca..b669a3e76 100644
--- a/numpy/core/src/multiarray/scalarapi.c
+++ b/numpy/core/src/multiarray/scalarapi.c
@@ -471,12 +471,18 @@ PyArray_DescrFromTypeObject(PyObject *type)
/* Do special thing for VOID sub-types */
if (PyType_IsSubtype((PyTypeObject *)type, &PyVoidArrType_Type)) {
new = PyArray_DescrNewFromType(NPY_VOID);
- conv = _arraydescr_from_dtype_attr(type);
- if (conv) {
+ if (new == NULL) {
+ return NULL;
+ }
+ if (_arraydescr_from_dtype_attr(type, &conv)) {
+ if (conv == NULL) {
+ Py_DECREF(new);
+ return NULL;
+ }
new->fields = conv->fields;
- Py_INCREF(new->fields);
+ Py_XINCREF(new->fields);
new->names = conv->names;
- Py_INCREF(new->names);
+ Py_XINCREF(new->names);
new->elsize = conv->elsize;
new->subarray = conv->subarray;
conv->subarray = NULL;
@@ -802,6 +808,9 @@ PyArray_Scalar(void *data, PyArray_Descr *descr, PyObject *base)
return obj;
}
}
+ if (itemsize == 0) {
+ return obj;
+ }
destptr = PyDataMem_NEW(itemsize);
if (destptr == NULL) {
Py_DECREF(obj);
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 52de31289..34839b866 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -1993,6 +1993,92 @@ static PyObject *
}
/**end repeat**/
+/**begin repeat
+ * #name = half, float, double, longdouble#
+ * #Name = Half, Float, Double, LongDouble#
+ * #is_half = 1,0,0,0#
+ * #c = f, f, , l#
+ * #convert = PyLong_FromDouble, PyLong_FromDouble, PyLong_FromDouble,
+ * npy_longdouble_to_PyLong#
+ * #
+ */
+/* Heavily copied from the builtin float.as_integer_ratio */
+static PyObject *
+@name@_as_integer_ratio(PyObject *self)
+{
+#if @is_half@
+ npy_double val = npy_half_to_double(PyArrayScalar_VAL(self, @Name@));
+ npy_double frac;
+#else
+ npy_@name@ val = PyArrayScalar_VAL(self, @Name@);
+ npy_@name@ frac;
+#endif
+ int exponent;
+ int i;
+
+ PyObject *py_exponent = NULL;
+ PyObject *numerator = NULL;
+ PyObject *denominator = NULL;
+ PyObject *result_pair = NULL;
+ PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
+
+ if (npy_isnan(val)) {
+ PyErr_SetString(PyExc_ValueError,
+ "cannot convert NaN to integer ratio");
+ return NULL;
+ }
+ if (!npy_isfinite(val)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "cannot convert Infinity to integer ratio");
+ return NULL;
+ }
+
+ frac = npy_frexp@c@(val, &exponent); /* val == frac * 2**exponent exactly */
+
+ /* This relies on the floating point type being base 2 to converge */
+ for (i = 0; frac != npy_floor@c@(frac); i++) {
+ frac *= 2.0;
+ exponent--;
+ }
+
+ /* self == frac * 2**exponent exactly and frac is integral. */
+ numerator = @convert@(frac);
+ if (numerator == NULL)
+ goto error;
+ denominator = PyLong_FromLong(1);
+ if (denominator == NULL)
+ goto error;
+ py_exponent = PyLong_FromLong(exponent < 0 ? -exponent : exponent);
+ if (py_exponent == NULL)
+ goto error;
+
+ /* fold in 2**exponent */
+ if (exponent > 0) {
+ PyObject *temp = long_methods->nb_lshift(numerator, py_exponent);
+ if (temp == NULL)
+ goto error;
+ Py_DECREF(numerator);
+ numerator = temp;
+ }
+ else {
+ PyObject *temp = long_methods->nb_lshift(denominator, py_exponent);
+ if (temp == NULL)
+ goto error;
+ Py_DECREF(denominator);
+ denominator = temp;
+ }
+
+ result_pair = PyTuple_Pack(2, numerator, denominator);
+
+error:
+ Py_XDECREF(py_exponent);
+ Py_XDECREF(denominator);
+ Py_XDECREF(numerator);
+ return result_pair;
+}
+/**end repeat**/
+
+
/*
* need to fill in doc-strings for these methods on import -- copy from
* array docstrings
@@ -2256,6 +2342,17 @@ static PyMethodDef @name@type_methods[] = {
};
/**end repeat**/
+/**begin repeat
+ * #name = half,float,double,longdouble#
+ */
+static PyMethodDef @name@type_methods[] = {
+ {"as_integer_ratio",
+ (PyCFunction)@name@_as_integer_ratio,
+ METH_NOARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
+/**end repeat**/
+
/************* As_mapping functions for void array scalar ************/
static Py_ssize_t
@@ -3927,7 +4024,6 @@ initialize_casting_tables(void)
}
_npy_can_cast_safely_table[NPY_STRING][NPY_UNICODE] = 1;
- _npy_can_cast_safely_table[NPY_BOOL][NPY_TIMEDELTA] = 1;
#ifndef NPY_SIZEOF_BYTE
#define NPY_SIZEOF_BYTE 1
@@ -4311,6 +4407,15 @@ initialize_numeric_types(void)
/**end repeat**/
+ /**begin repeat
+ * #name = half, float, double, longdouble#
+ * #Name = Half, Float, Double, LongDouble#
+ */
+
+ Py@Name@ArrType_Type.tp_methods = @name@type_methods;
+
+ /**end repeat**/
+
#if (NPY_SIZEOF_INT != NPY_SIZEOF_LONG) || defined(NPY_PY3K)
/* We won't be inheriting from Python Int type. */
PyIntArrType_Type.tp_hash = int_arrtype_hash;
diff --git a/numpy/core/src/npymath/ieee754.c.src b/numpy/core/src/npymath/ieee754.c.src
index d960838c8..3f66b24a4 100644
--- a/numpy/core/src/npymath/ieee754.c.src
+++ b/numpy/core/src/npymath/ieee754.c.src
@@ -681,7 +681,8 @@ void npy_set_floatstatus_invalid(void)
fp_raise_xcp(FP_INVALID);
}
-#elif defined(_MSC_VER) || (defined(__osf__) && defined(__alpha))
+#elif defined(_MSC_VER) || (defined(__osf__) && defined(__alpha)) || \
+ defined (__UCLIBC__) || (defined(__arc__) && defined(__GLIBC__))
/*
* By using a volatile floating point value,
diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src
index cf427dad8..dad381232 100644
--- a/numpy/core/src/npymath/npy_math_complex.c.src
+++ b/numpy/core/src/npymath/npy_math_complex.c.src
@@ -1246,7 +1246,7 @@ _clog_for_large_values@c@(@type@ x, @type@ y,
* Divide x and y by E, and then add 1 to the logarithm. This depends
* on E being larger than sqrt(2).
* Dividing by E causes an insignificant loss of accuracy; however
- * this method is still poor since it is uneccessarily slow.
+ * this method is still poor since it is unnecessarily slow.
*/
if (ax > @TMAX@ / 2) {
*rr = npy_log@c@(npy_hypot@c@(x / NPY_E@c@, y / NPY_E@c@)) + 1;
@@ -1430,19 +1430,14 @@ npy_casinh@c@(@ctype@ z)
#if @precision@ == 1
/* this is sqrt(6*EPS) */
const npy_float SQRT_6_EPSILON = 8.4572793338e-4f;
- /* chosen such that pio2_hi + pio2_lo == pio2_hi but causes FE_INEXACT. */
- const volatile npy_float pio2_lo = 7.5497899549e-9f;
#endif
#if @precision@ == 2
const npy_double SQRT_6_EPSILON = 3.65002414998885671e-08;
- const volatile npy_double pio2_lo = 6.1232339957367659e-17;
#endif
#if @precision@ == 3
const npy_longdouble SQRT_6_EPSILON = 8.0654900873493277169e-10l;
- const volatile npy_longdouble pio2_lo = 2.710505431213761085e-20l;
#endif
const @type@ RECIP_EPSILON = 1.0@c@ / @TEPS@;
- const @type@ pio2_hi = NPY_PI_2@c@;
@type@ x, y, ax, ay, wx, wy, rx, ry, B, sqrt_A2my2, new_y;
npy_int B_is_usable;
diff --git a/numpy/core/src/npysort/npysort_common.h b/numpy/core/src/npysort/npysort_common.h
index a22045b41..5fd03b96f 100644
--- a/numpy/core/src/npysort/npysort_common.h
+++ b/numpy/core/src/npysort/npysort_common.h
@@ -273,10 +273,10 @@ STRING_SWAP(char *s1, char *s2, size_t len)
NPY_INLINE static int
-STRING_LT(char *s1, char *s2, size_t len)
+STRING_LT(const char *s1, const char *s2, size_t len)
{
- const unsigned char *c1 = (unsigned char *)s1;
- const unsigned char *c2 = (unsigned char *)s2;
+ const unsigned char *c1 = (const unsigned char *)s1;
+ const unsigned char *c2 = (const unsigned char *)s2;
size_t i;
int ret = 0;
@@ -311,7 +311,7 @@ UNICODE_SWAP(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
NPY_INLINE static int
-UNICODE_LT(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
+UNICODE_LT(const npy_ucs4 *s1, const npy_ucs4 *s2, size_t len)
{
size_t i;
int ret = 0;
diff --git a/numpy/core/src/npysort/radixsort.c.src b/numpy/core/src/npysort/radixsort.c.src
new file mode 100644
index 000000000..c90b06974
--- /dev/null
+++ b/numpy/core/src/npysort/radixsort.c.src
@@ -0,0 +1,231 @@
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include "npy_sort.h"
+#include "npysort_common.h"
+#include <stdlib.h>
+
+/*
+ *****************************************************************************
+ ** INTEGER SORTS **
+ *****************************************************************************
+ */
+
+
+/**begin repeat
+ *
+ * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
+ * LONGLONG, ULONGLONG#
+ * #suff = bool, byte, ubyte, short, ushort, int, uint, long, ulong,
+ * longlong, ulonglong#
+ * #type = npy_ubyte, npy_ubyte, npy_ubyte, npy_ushort, npy_ushort, npy_uint,
+ * npy_uint, npy_ulong, npy_ulong, npy_ulonglong, npy_ulonglong#
+ * #sign = 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0#
+ * #floating = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0#
+ */
+
+// Reference: https://github.com/eloj/radix-sorting#-key-derivation
+#if @sign@
+ // Floating-point is currently disabled.
+ // Floating-point tests succeed for double and float on macOS but not on Windows/Linux.
+ // Basic sorting tests succeed but others relying on sort fail.
+ // Possibly related to floating-point normalisation or multiple NaN reprs? Not sure.
+ #if @floating@
+ // For floats, we invert the key if the sign bit is set, else we invert the sign bit.
+ #define KEY_OF(x) ((x) ^ (-((x) >> (sizeof(@type@) * 8 - 1)) | ((@type@)1 << (sizeof(@type@) * 8 - 1))))
+ #else
+ // For signed ints, we flip the sign bit so the negatives are below the positives.
+ #define KEY_OF(x) ((x) ^ ((@type@)1 << (sizeof(@type@) * 8 - 1)))
+ #endif
+#else
+ // For unsigned ints, the key is as-is
+ #define KEY_OF(x) (x)
+#endif
+
+static inline npy_ubyte
+nth_byte_@suff@(@type@ key, npy_intp l) {
+ return (key >> (l << 3)) & 0xFF;
+}
+
+@type@*
+radixsort0_@suff@(@type@ *arr, @type@ *aux, npy_intp num)
+{
+ npy_intp cnt[sizeof(@type@)][1 << 8] = { { 0 } };
+ npy_intp i;
+ size_t l;
+ @type@ key0 = KEY_OF(arr[0]);
+ size_t ncols = 0;
+ npy_ubyte cols[sizeof(@type@)];
+
+ for (i = 0; i < num; i++) {
+ @type@ k = KEY_OF(arr[i]);
+
+ for (l = 0; l < sizeof(@type@); l++) {
+ cnt[l][nth_byte_@suff@(k, l)]++;
+ }
+ }
+
+ for (l = 0; l < sizeof(@type@); l++) {
+ if (cnt[l][nth_byte_@suff@(key0, l)] != num) {
+ cols[ncols++] = l;
+ }
+ }
+
+ for (l = 0; l < ncols; l++) {
+ npy_intp a = 0;
+ for (i = 0; i < 256; i++) {
+ npy_intp b = cnt[cols[l]][i];
+ cnt[cols[l]][i] = a;
+ a += b;
+ }
+ }
+
+ for (l = 0; l < ncols; l++) {
+ @type@* temp;
+ for (i = 0; i < num; i++) {
+ @type@ k = KEY_OF(arr[i]);
+ npy_intp dst = cnt[cols[l]][nth_byte_@suff@(k, cols[l])]++;
+ aux[dst] = arr[i];
+ }
+
+ temp = aux;
+ aux = arr;
+ arr = temp;
+ }
+
+ return arr;
+}
+
+int
+radixsort_@suff@(void *start, npy_intp num, void *NPY_UNUSED(varr))
+{
+ void *sorted;
+ @type@ *aux;
+ @type@ *arr = start;
+ @type@ k1, k2;
+ npy_bool all_sorted = 1;
+
+ if (num < 2) {
+ return 0;
+ }
+
+ k1 = KEY_OF(arr[0]);
+ for (npy_intp i = 1; i < num; i++) {
+ k2 = KEY_OF(arr[i]);
+ if (k1 > k2) {
+ all_sorted = 0;
+ break;
+ }
+ k1 = k2;
+ }
+
+ if (all_sorted) {
+ return 0;
+ }
+
+ aux = malloc(num * sizeof(@type@));
+ if (aux == NULL) {
+ return -NPY_ENOMEM;
+ }
+
+ sorted = radixsort0_@suff@(start, aux, num);
+ if (sorted != start) {
+ memcpy(start, sorted, num * sizeof(@type@));
+ }
+
+ free(aux);
+ return 0;
+}
+
+npy_intp*
+aradixsort0_@suff@(@type@ *arr, npy_intp *aux, npy_intp *tosort, npy_intp num)
+{
+ npy_intp cnt[sizeof(@type@)][1 << 8] = { { 0 } };
+ npy_intp i;
+ size_t l;
+ @type@ key0 = KEY_OF(arr[0]);
+ size_t ncols = 0;
+ npy_ubyte cols[sizeof(@type@)];
+
+ for (i = 0; i < num; i++) {
+ @type@ k = KEY_OF(arr[i]);
+
+ for (l = 0; l < sizeof(@type@); l++) {
+ cnt[l][nth_byte_@suff@(k, l)]++;
+ }
+ }
+
+ for (l = 0; l < sizeof(@type@); l++) {
+ if (cnt[l][nth_byte_@suff@(key0, l)] != num) {
+ cols[ncols++] = l;
+ }
+ }
+
+ for (l = 0; l < ncols; l++) {
+ npy_intp a = 0;
+ for (i = 0; i < 256; i++) {
+ npy_intp b = cnt[cols[l]][i];
+ cnt[cols[l]][i] = a;
+ a += b;
+ }
+ }
+
+ for (l = 0; l < ncols; l++) {
+ npy_intp* temp;
+ for (i = 0; i < num; i++) {
+ @type@ k = KEY_OF(arr[tosort[i]]);
+ npy_intp dst = cnt[cols[l]][nth_byte_@suff@(k, cols[l])]++;
+ aux[dst] = tosort[i];
+ }
+
+ temp = aux;
+ aux = tosort;
+ tosort = temp;
+ }
+
+ return tosort;
+}
+
+int
+aradixsort_@suff@(void *start, npy_intp* tosort, npy_intp num, void *NPY_UNUSED(varr))
+{
+ npy_intp *sorted;
+ npy_intp *aux;
+ @type@ *arr = start;
+ @type@ k1, k2;
+ npy_bool all_sorted = 1;
+
+ if (num < 2) {
+ return 0;
+ }
+
+ k1 = KEY_OF(arr[0]);
+ for (npy_intp i = 1; i < num; i++) {
+ k2 = KEY_OF(arr[i]);
+ if (k1 > k2) {
+ all_sorted = 0;
+ break;
+ }
+ k1 = k2;
+ }
+
+ if (all_sorted) {
+ return 0;
+ }
+
+ aux = malloc(num * sizeof(npy_intp));
+ if (aux == NULL) {
+ return -NPY_ENOMEM;
+ }
+
+ sorted = aradixsort0_@suff@(start, aux, tosort, num);
+ if (sorted != tosort) {
+ memcpy(tosort, sorted, num * sizeof(npy_intp));
+ }
+
+ free(aux);
+ return 0;
+}
+
+#undef KEY_OF
+
+/**end repeat**/
diff --git a/numpy/core/src/npysort/selection.c.src b/numpy/core/src/npysort/selection.c.src
index 1e0934558..be645450f 100644
--- a/numpy/core/src/npysort/selection.c.src
+++ b/numpy/core/src/npysort/selection.c.src
@@ -40,7 +40,7 @@ static NPY_INLINE void store_pivot(npy_intp pivot, npy_intp kth,
}
/*
- * If pivot is the requested kth store it, overwritting other pivots if
+ * If pivot is the requested kth store it, overwriting other pivots if
* required. This must be done so iterative partition can work without
* manually shifting lower data offset by kth each time
*/
diff --git a/numpy/core/src/npysort/timsort.c.src b/numpy/core/src/npysort/timsort.c.src
new file mode 100644
index 000000000..26313ca5b
--- /dev/null
+++ b/numpy/core/src/npysort/timsort.c.src
@@ -0,0 +1,2574 @@
+/* -*- c -*- */
+
+/*
+ * The purpose of this module is to add faster sort functions
+ * that are type-specific. This is done by altering the
+ * function table for the builtin descriptors.
+ *
+ * These sorting functions are copied almost directly from numarray
+ * with a few modifications (complex comparisons compare the imaginary
+ * part if the real parts are equal, for example), and the names
+ * are changed.
+ *
+ * The original sorting code is due to Charles R. Harris who wrote
+ * it for numarray.
+ */
+
+/*
+ * Quick sort is usually the fastest, but the worst case scenario can
+ * be slower than the merge and heap sorts. The merge sort requires
+ * extra memory and so for large arrays may not be useful.
+ *
+ * The merge sort is *stable*, meaning that equal components
+ * are unmoved from their entry versions, so it can be used to
+ * implement lexigraphic sorting on multiple keys.
+ *
+ * The heap sort is included for completeness.
+ */
+
+
+/* For details of Timsort, refer to
+ * https://github.com/python/cpython/blob/3.7/Objects/listsort.txt
+ */
+
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include "npy_sort.h"
+#include "npysort_common.h"
+#include <stdlib.h>
+
+/* enough for 32 * 1.618 ** 128 elements */
+#define TIMSORT_STACK_SIZE 128
+
+
+
+npy_intp compute_min_run(npy_intp num)
+{
+ npy_intp r = 0;
+
+ while (64 < num) {
+ r |= num & 1;
+ num >>= 1;
+ }
+
+ return num + r;
+}
+
+typedef struct {
+ npy_intp s; /* start pointer */
+ npy_intp l; /* length */
+} run;
+
+
+/* buffer for argsort. Declared here to avoid multiple declarations. */
+typedef struct {
+ npy_intp *pw;
+ npy_intp size;
+} buffer_intp;
+
+
+/* buffer method */
+static NPY_INLINE int
+resize_buffer_intp(buffer_intp *buffer, npy_intp new_size)
+{
+ if (new_size <= buffer->size) {
+ return 0;
+ }
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ buffer->pw = malloc(new_size * sizeof(npy_intp));
+ } else {
+ buffer->pw = realloc(buffer->pw, new_size * sizeof(npy_intp));
+ }
+
+ buffer->size = new_size;
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ return -NPY_ENOMEM;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ *****************************************************************************
+ ** NUMERIC SORTS **
+ *****************************************************************************
+ */
+
+
+/**begin repeat
+ *
+ * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
+ * LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE,
+ * CFLOAT, CDOUBLE, CLONGDOUBLE, DATETIME, TIMEDELTA#
+ * #suff = bool, byte, ubyte, short, ushort, int, uint, long, ulong,
+ * longlong, ulonglong, half, float, double, longdouble,
+ * cfloat, cdouble, clongdouble, datetime, timedelta#
+ * #type = npy_bool, npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int,
+ * npy_uint, npy_long, npy_ulong, npy_longlong, npy_ulonglong,
+ * npy_ushort, npy_float, npy_double, npy_longdouble, npy_cfloat,
+ * npy_cdouble, npy_clongdouble, npy_datetime, npy_timedelta#
+ */
+
+
+typedef struct {
+ @type@ * pw;
+ npy_intp size;
+} buffer_@suff@;
+
+
+static NPY_INLINE int
+resize_buffer_@suff@(buffer_@suff@ *buffer, npy_intp new_size)
+{
+ if (new_size <= buffer->size) {
+ return 0;
+ }
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ buffer->pw = malloc(new_size * sizeof(@type@));
+ } else {
+ buffer->pw = realloc(buffer->pw, new_size * sizeof(@type@));
+ }
+
+ buffer->size = new_size;
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ return -NPY_ENOMEM;
+ } else {
+ return 0;
+ }
+}
+
+
+static npy_intp
+count_run_@suff@(@type@ *arr, npy_intp l, npy_intp num, npy_intp minrun)
+{
+ npy_intp sz;
+ @type@ vc, *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = arr + l;
+
+ /* (not strictly) ascending sequence */
+ if (!@TYPE@_LT(*(pl + 1), *pl)) {
+ for (pi = pl + 1; pi < arr + num - 1 && !@TYPE@_LT(*(pi + 1), *pi); ++pi) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + 1; pi < arr + num - 1 && @TYPE@_LT(*(pi + 1), *pi); ++pi) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; ++pj, --pr) {
+ @TYPE@_SWAP(*pj, *pr);
+ }
+ }
+
+ ++pi;
+ sz = pi - pl;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz;
+
+ /* insertion sort */
+ for (; pi < pr; ++pi) {
+ vc = *pi;
+ pj = pi;
+
+ while (pl < pj && @TYPE@_LT(vc, *(pj - 1))) {
+ *pj = *(pj - 1);
+ --pj;
+ }
+
+ *pj = vc;
+ }
+ }
+
+ return sz;
+}
+
+
+/* when the left part of the array (p1) is smaller, copy p1 to buffer
+ * and merge from left to right
+ */
+static void
+merge_left_@suff@(@type@ *p1, npy_intp l1, @type@ *p2, npy_intp l2,
+ @type@ *p3)
+{
+ @type@ *end = p2 + l2;
+ memcpy(p3, p1, sizeof(@type@) * l1);
+ /* first element must be in p2 otherwise skipped in the caller */
+ *p1++ = *p2++;
+
+ while (p1 < p2 && p2 < end) {
+ if (@TYPE@_LT(*p2, *p3)) {
+ *p1++ = *p2++;
+ } else {
+ *p1++ = *p3++;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(@type@) * (p2 - p1));
+ }
+}
+
+
+/* when the right part of the array (p2) is smaller, copy p2 to buffer
+ * and merge from right to left
+ */
+static void
+merge_right_@suff@(@type@ *p1, npy_intp l1, @type@ *p2, npy_intp l2,
+ @type@ *p3)
+{
+ npy_intp ofs;
+ @type@ *start = p1 - 1;
+ memcpy(p3, p2, sizeof(@type@) * l2);
+ p1 += l1 - 1;
+ p2 += l2 - 1;
+ p3 += l2 - 1;
+ /* first element must be in p1 otherwise skipped in the caller */
+ *p2-- = *p1--;
+
+ while (p1 < p2 && start < p1) {
+ if (@TYPE@_LT(*p3, *p1)) {
+ *p2-- = *p1--;
+ } else {
+ *p2-- = *p3--;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + 1, p3 - ofs + 1, sizeof(@type@) * ofs);
+ }
+}
+
+
+/* Note: the naming convention of gallop functions are different from that of
+ * CPython. For example, here gallop_right means gallop from left toward right,
+ * whereas in CPython gallop_right means gallop
+ * and find the right most element among equal elements
+ */
+static npy_intp
+gallop_right_@suff@(const @type@ *arr, const npy_intp size, const @type@ key)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (@TYPE@_LT(key, arr[0])) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (@TYPE@_LT(key, arr[ofs])) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[last_ofs] <= key < arr[ofs] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (@TYPE@_LT(key, arr[m])) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[ofs-1] <= key < arr[ofs] */
+ return ofs;
+}
+
+
+static npy_intp
+gallop_left_@suff@(const @type@ *arr, const npy_intp size, const @type@ key)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (@TYPE@_LT(arr[size - 1], key)) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (@TYPE@_LT(arr[size - ofs - 1], key)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[size-ofs-1] < key <= arr[size-last_ofs-1] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (@TYPE@_LT(arr[m], key)) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[r-1] < key <= arr[r] */
+ return r;
+}
+
+
+static int
+merge_at_@suff@(@type@ *arr, const run *stack, const npy_intp at,
+ buffer_@suff@ *buffer)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ @type@ *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* arr[s2] belongs to arr[s1+k].
+ * if try to comment this out for debugging purpose, remember
+ * in the merging process the first element is skipped
+ */
+ k = gallop_right_@suff@(arr + s1, l1, arr[s2]);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = arr + s1 + k;
+ l1 -= k;
+ p2 = arr + s2;
+ /* arr[s2-1] belongs to arr[s2+l2] */
+ l2 = gallop_left_@suff@(arr + s2, l2, arr[s2 - 1]);
+
+ if (l2 < l1) {
+ ret = resize_buffer_@suff@(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ merge_right_@suff@(p1, l1, p2, l2, buffer->pw);
+ } else {
+ ret = resize_buffer_@suff@(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ merge_left_@suff@(p1, l1, p2, l2, buffer->pw);
+ }
+
+ return 0;
+}
+
+
+static int
+try_collapse_@suff@(@type@ *arr, run *stack, npy_intp *stack_ptr,
+ buffer_@suff@ *buffer)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = merge_at_@suff@(arr, stack, top - 3, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+static int
+force_collapse_@suff@(@type@ *arr, run *stack, npy_intp *stack_ptr,
+ buffer_@suff@ *buffer)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = merge_at_@suff@(arr, stack, top - 3, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+timsort_@suff@(void *start, npy_intp num, void *NPY_UNUSED(varr))
+{
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ buffer_@suff@ buffer;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer.pw = NULL;
+ buffer.size = 0;
+ stack_ptr = 0;
+ minrun = compute_min_run(num);
+
+ for (l = 0; l < num;) {
+ n = count_run_@suff@(start, l, num, minrun);
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = try_collapse_@suff@(start, stack, &stack_ptr, &buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = force_collapse_@suff@(start, stack, &stack_ptr, &buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+cleanup:
+
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+
+ return ret;
+}
+
+
+/* argsort */
+
+
+static npy_intp
+acount_run_@suff@(@type@ *arr, npy_intp *tosort, npy_intp l, npy_intp num,
+ npy_intp minrun)
+{
+ npy_intp sz;
+ @type@ vc;
+ npy_intp vi;
+ npy_intp *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = tosort + l;
+
+ /* (not strictly) ascending sequence */
+ if (!@TYPE@_LT(arr[*(pl + 1)], arr[*pl])) {
+ for (pi = pl + 1; pi < tosort + num - 1
+ && !@TYPE@_LT(arr[*(pi + 1)], arr[*pi]); ++pi) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + 1; pi < tosort + num - 1
+ && @TYPE@_LT(arr[*(pi + 1)], arr[*pi]); ++pi) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; ++pj, --pr) {
+ INTP_SWAP(*pj, *pr);
+ }
+ }
+
+ ++pi;
+ sz = pi - pl;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz;
+
+ /* insertion sort */
+ for (; pi < pr; ++pi) {
+ vi = *pi;
+ vc = arr[*pi];
+ pj = pi;
+
+ while (pl < pj && @TYPE@_LT(vc, arr[*(pj - 1)])) {
+ *pj = *(pj - 1);
+ --pj;
+ }
+
+ *pj = vi;
+ }
+ }
+
+ return sz;
+}
+
+
+static npy_intp
+agallop_right_@suff@(const @type@ *arr, const npy_intp *tosort,
+ const npy_intp size, const @type@ key)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (@TYPE@_LT(key, arr[tosort[0]])) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (@TYPE@_LT(key, arr[tosort[ofs]])) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[last_ofs]] <= key < arr[tosort[ofs]] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (@TYPE@_LT(key, arr[tosort[m]])) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[tosort[ofs-1]] <= key < arr[tosort[ofs]] */
+ return ofs;
+}
+
+
+
+static npy_intp
+agallop_left_@suff@(const @type@ *arr, const npy_intp *tosort,
+ const npy_intp size, const @type@ key)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (@TYPE@_LT(arr[tosort[size - 1]], key)) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (@TYPE@_LT(arr[tosort[size - ofs - 1]], key)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[size-ofs-1]] < key <= arr[tosort[size-last_ofs-1]] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (@TYPE@_LT(arr[tosort[m]], key)) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[tosort[r-1]] < key <= arr[tosort[r]] */
+ return r;
+}
+
+
+static void
+amerge_left_@suff@(@type@ *arr, npy_intp *p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2,
+ npy_intp *p3)
+{
+ npy_intp *end = p2 + l2;
+ memcpy(p3, p1, sizeof(npy_intp) * l1);
+ /* first element must be in p2 otherwise skipped in the caller */
+ *p1++ = *p2++;
+
+ while (p1 < p2 && p2 < end) {
+ if (@TYPE@_LT(arr[*p2], arr[*p3])) {
+ *p1++ = *p2++;
+ } else {
+ *p1++ = *p3++;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(npy_intp) * (p2 - p1));
+ }
+}
+
+
+static void
+amerge_right_@suff@(@type@ *arr, npy_intp* p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2,
+ npy_intp *p3)
+{
+ npy_intp ofs;
+ npy_intp *start = p1 - 1;
+ memcpy(p3, p2, sizeof(npy_intp) * l2);
+ p1 += l1 - 1;
+ p2 += l2 - 1;
+ p3 += l2 - 1;
+ /* first element must be in p1 otherwise skipped in the caller */
+ *p2-- = *p1--;
+
+ while (p1 < p2 && start < p1) {
+ if (@TYPE@_LT(arr[*p3], arr[*p1])) {
+ *p2-- = *p1--;
+ } else {
+ *p2-- = *p3--;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + 1, p3 - ofs + 1, sizeof(npy_intp) * ofs);
+ }
+}
+
+
+static int
+amerge_at_@suff@(@type@ *arr, npy_intp *tosort, const run *stack,
+ const npy_intp at,
+ buffer_intp *buffer)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ npy_intp *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* tosort[s2] belongs to tosort[s1+k] */
+ k = agallop_right_@suff@(arr, tosort + s1, l1, arr[tosort[s2]]);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = tosort + s1 + k;
+ l1 -= k;
+ p2 = tosort + s2;
+ /* tosort[s2-1] belongs to tosort[s2+l2] */
+ l2 = agallop_left_@suff@(arr, tosort + s2, l2, arr[tosort[s2 - 1]]);
+
+ if (l2 < l1) {
+ ret = resize_buffer_intp(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ amerge_right_@suff@(arr, p1, l1, p2, l2, buffer->pw);
+ } else {
+ ret = resize_buffer_intp(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ amerge_left_@suff@(arr, p1, l1, p2, l2, buffer->pw);
+ }
+
+ return 0;
+}
+
+
+static int
+atry_collapse_@suff@(@type@ *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr,
+ buffer_intp *buffer)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 3, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+
+static int
+aforce_collapse_@suff@(@type@ *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr,
+ buffer_intp *buffer)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 3, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+atimsort_@suff@(void *v, npy_intp *tosort, npy_intp num,
+ void *NPY_UNUSED(varr))
+{
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ buffer_intp buffer;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer.pw = NULL;
+ buffer.size = 0;
+ stack_ptr = 0;
+ minrun = compute_min_run(num);
+
+ for (l = 0; l < num;) {
+ n = acount_run_@suff@(v, tosort, l, num, minrun);
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = atry_collapse_@suff@(v, tosort, stack, &stack_ptr, &buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = aforce_collapse_@suff@(v, tosort, stack, &stack_ptr, &buffer);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+cleanup:
+
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+
+ return ret;
+}
+
+/**end repeat**/
+
+
+
+/* For string sorts and generic sort, element comparisons are very expensive,
+ * and the time cost of insertion sort (involves N**2 comparison) clearly hurts.
+ * Implementing binary insertion sort and probably gallop mode during merging process
+ * can hopefully boost the performance. Here as a temporary workaround we use shorter
+ * run length to reduce the cost of insertion sort.
+ */
+
+npy_intp compute_min_run_short(npy_intp num)
+{
+ npy_intp r = 0;
+
+ while (16 < num) {
+ r |= num & 1;
+ num >>= 1;
+ }
+
+ return num + r;
+}
+
+/*
+ *****************************************************************************
+ ** STRING SORTS **
+ *****************************************************************************
+ */
+
+
+/**begin repeat
+ *
+ * #TYPE = STRING, UNICODE#
+ * #suff = string, unicode#
+ * #type = npy_char, npy_ucs4#
+ */
+
+
+typedef struct {
+ @type@ * pw;
+ npy_intp size;
+ size_t len;
+} buffer_@suff@;
+
+
+static NPY_INLINE int
+resize_buffer_@suff@(buffer_@suff@ *buffer, npy_intp new_size)
+{
+ if (new_size <= buffer->size) {
+ return 0;
+ }
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ buffer->pw = malloc(sizeof(@type@) * new_size * buffer->len);
+ } else {
+ buffer->pw = realloc(buffer->pw, sizeof(@type@) * new_size * buffer->len);
+ }
+
+ buffer->size = new_size;
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ return -NPY_ENOMEM;
+ } else {
+ return 0;
+ }
+}
+
+
+static npy_intp
+count_run_@suff@(@type@ *arr, npy_intp l, npy_intp num, npy_intp minrun,
+ @type@ *vp, size_t len)
+{
+ npy_intp sz;
+ @type@ *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = arr + l * len;
+
+ /* (not strictly) ascending sequence */
+ if (!@TYPE@_LT(pl + len, pl, len)) {
+ for (pi = pl + len; pi < arr + (num - 1) * len
+ && !@TYPE@_LT(pi + len, pi, len); pi += len) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + len; pi < arr + (num - 1) * len
+ && @TYPE@_LT(pi + len, pi, len); pi += len) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; pj += len, pr -= len) {
+ @TYPE@_SWAP(pj, pr, len);
+ }
+ }
+
+ pi += len;
+ sz = (pi - pl) / len;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz * len;
+
+ /* insertion sort */
+ for (; pi < pr; pi += len) {
+ @TYPE@_COPY(vp, pi, len);
+ pj = pi;
+
+ while (pl < pj && @TYPE@_LT(vp, pj - len, len)) {
+ @TYPE@_COPY(pj, pj - len, len);
+ pj -= len;
+ }
+
+ @TYPE@_COPY(pj, vp, len);
+ }
+ }
+
+ return sz;
+}
+
+
+static npy_intp
+gallop_right_@suff@(const @type@ *arr, const npy_intp size,
+ const @type@ *key, size_t len)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (@TYPE@_LT(key, arr, len)) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (@TYPE@_LT(key, arr + ofs * len, len)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[last_ofs*len] <= key < arr[ofs*len] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (@TYPE@_LT(key, arr + m * len, len)) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[(ofs-1)*len] <= key < arr[ofs*len] */
+ return ofs;
+}
+
+
+
+static npy_intp
+gallop_left_@suff@(const @type@ *arr, const npy_intp size, const @type@ *key,
+ size_t len)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (@TYPE@_LT(arr + (size - 1) * len, key, len)) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (@TYPE@_LT(arr + (size - ofs - 1) * len, key, len)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[(size-ofs-1)*len] < key <= arr[(size-last_ofs-1)*len] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (@TYPE@_LT(arr + m * len, key, len)) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[(r-1)*len] < key <= arr[r*len] */
+ return r;
+}
+
+
+static void
+merge_left_@suff@(@type@ *p1, npy_intp l1, @type@ *p2, npy_intp l2,
+ @type@ *p3, size_t len)
+{
+ @type@ *end = p2 + l2 * len;
+ memcpy(p3, p1, sizeof(@type@) * l1 * len);
+ /* first element must be in p2 otherwise skipped in the caller */
+ @TYPE@_COPY(p1, p2, len);
+ p1 += len;
+ p2 += len;
+
+ while (p1 < p2 && p2 < end) {
+ if (@TYPE@_LT(p2, p3, len)) {
+ @TYPE@_COPY(p1, p2, len);
+ p1 += len;
+ p2 += len;
+ } else {
+ @TYPE@_COPY(p1, p3, len);
+ p1 += len;
+ p3 += len;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(@type@) * (p2 - p1));
+ }
+}
+
+
+static void
+merge_right_@suff@(@type@ *p1, npy_intp l1, @type@ *p2, npy_intp l2,
+ @type@ *p3, size_t len)
+{
+ npy_intp ofs;
+ @type@ *start = p1 - len;
+ memcpy(p3, p2, sizeof(@type@) * l2 * len);
+ p1 += (l1 - 1) * len;
+ p2 += (l2 - 1) * len;
+ p3 += (l2 - 1) * len;
+ /* first element must be in p1 otherwise skipped in the caller */
+ @TYPE@_COPY(p2, p1, len);
+ p2 -= len;
+ p1 -= len;
+
+ while (p1 < p2 && start < p1) {
+ if (@TYPE@_LT(p3, p1, len)) {
+ @TYPE@_COPY(p2, p1, len);
+ p2 -= len;
+ p1 -= len;
+ } else {
+ @TYPE@_COPY(p2, p3, len);
+ p2 -= len;
+ p3 -= len;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + len, p3 - ofs + len, sizeof(@type@) * ofs);
+ }
+}
+
+
+static int
+merge_at_@suff@(@type@ *arr, const run *stack, const npy_intp at,
+ buffer_@suff@ *buffer, size_t len)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ @type@ *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* arr[s2] belongs to arr[s1+k] */
+ @TYPE@_COPY(buffer->pw, arr + s2 * len, len);
+ k = gallop_right_@suff@(arr + s1 * len, l1, buffer->pw, len);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = arr + (s1 + k) * len;
+ l1 -= k;
+ p2 = arr + s2 * len;
+ /* arr[s2-1] belongs to arr[s2+l2] */
+ @TYPE@_COPY(buffer->pw, arr + (s2 - 1) * len, len);
+ l2 = gallop_left_@suff@(arr + s2 * len, l2, buffer->pw, len);
+
+ if (l2 < l1) {
+ ret = resize_buffer_@suff@(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ merge_right_@suff@(p1, l1, p2, l2, buffer->pw, len);
+ } else {
+ ret = resize_buffer_@suff@(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ merge_left_@suff@(p1, l1, p2, l2, buffer->pw, len);
+ }
+
+ return 0;
+}
+
+
+static int
+try_collapse_@suff@(@type@ *arr, run *stack, npy_intp *stack_ptr,
+ buffer_@suff@ *buffer, size_t len)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = merge_at_@suff@(arr, stack, top - 3, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+
+static int
+force_collapse_@suff@(@type@ *arr, run *stack, npy_intp *stack_ptr,
+ buffer_@suff@ *buffer, size_t len)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = merge_at_@suff@(arr, stack, top - 3, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = merge_at_@suff@(arr, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+timsort_@suff@(void *start, npy_intp num, void *varr)
+{
+ PyArrayObject *arr = varr;
+ size_t elsize = PyArray_ITEMSIZE(arr);
+ size_t len = elsize / sizeof(@type@);
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer_@suff@ buffer;
+
+ /* Items that have zero size don't make sense to sort */
+ if (len == 0) {
+ return 0;
+ }
+
+ buffer.pw = NULL;
+ buffer.size = 0;
+ buffer.len = len;
+ stack_ptr = 0;
+ minrun = compute_min_run_short(num);
+ /* used for insertion sort and gallop key */
+ ret = resize_buffer_@suff@(&buffer, 1);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ for (l = 0; l < num;) {
+ n = count_run_@suff@(start, l, num, minrun, buffer.pw, len);
+ /* both s and l are scaled by len */
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = try_collapse_@suff@(start, stack, &stack_ptr, &buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = force_collapse_@suff@(start, stack, &stack_ptr, &buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+
+cleanup:
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+ return ret;
+}
+
+
+/* argsort */
+
+
+static npy_intp
+acount_run_@suff@(@type@ *arr, npy_intp *tosort, npy_intp l, npy_intp num,
+ npy_intp minrun, size_t len)
+{
+ npy_intp sz;
+ npy_intp vi;
+ npy_intp *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = tosort + l;
+
+ /* (not strictly) ascending sequence */
+ if (!@TYPE@_LT(arr + (*(pl + 1)) * len, arr + (*pl) * len, len)) {
+ for (pi = pl + 1; pi < tosort + num - 1
+ && !@TYPE@_LT(arr + (*(pi + 1)) * len, arr + (*pi) * len, len); ++pi) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + 1; pi < tosort + num - 1
+ && @TYPE@_LT(arr + (*(pi + 1)) * len, arr + (*pi) * len, len); ++pi) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; ++pj, --pr) {
+ INTP_SWAP(*pj, *pr);
+ }
+ }
+
+ ++pi;
+ sz = pi - pl;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz;
+
+ /* insertion sort */
+ for (; pi < pr; ++pi) {
+ vi = *pi;
+ pj = pi;
+
+ while (pl < pj && @TYPE@_LT(arr + vi * len, arr + (*(pj - 1)) * len, len)) {
+ *pj = *(pj - 1);
+ --pj;
+ }
+
+ *pj = vi;
+ }
+ }
+
+ return sz;
+}
+
+
+static npy_intp
+agallop_left_@suff@(const @type@ *arr, const npy_intp *tosort,
+ const npy_intp size, const @type@ *key, size_t len)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (@TYPE@_LT(arr + tosort[size - 1] * len, key, len)) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (@TYPE@_LT(arr + tosort[size - ofs - 1] * len, key, len)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[size-ofs-1]*len] < key <= arr[tosort[size-last_ofs-1]*len] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (@TYPE@_LT(arr + tosort[m] * len, key, len)) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[tosort[r-1]*len] < key <= arr[tosort[r]*len] */
+ return r;
+}
+
+
+static npy_intp
+agallop_right_@suff@(const @type@ *arr, const npy_intp *tosort,
+ const npy_intp size, const @type@ *key, size_t len)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (@TYPE@_LT(key, arr + tosort[0] * len, len)) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (@TYPE@_LT(key, arr + tosort[ofs] * len, len)) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[last_ofs]*len] <= key < arr[tosort[ofs]*len] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (@TYPE@_LT(key, arr + tosort[m] * len, len)) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[tosort[ofs-1]*len] <= key < arr[tosort[ofs]*len] */
+ return ofs;
+}
+
+
+
+static void
+amerge_left_@suff@(@type@ *arr, npy_intp *p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2, npy_intp *p3, size_t len)
+{
+ npy_intp *end = p2 + l2;
+ memcpy(p3, p1, sizeof(npy_intp) * l1);
+ /* first element must be in p2 otherwise skipped in the caller */
+ *p1++ = *p2++;
+
+ while (p1 < p2 && p2 < end) {
+ if (@TYPE@_LT(arr + (*p2) * len, arr + (*p3) * len, len)) {
+ *p1++ = *p2++;
+ } else {
+ *p1++ = *p3++;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(npy_intp) * (p2 - p1));
+ }
+}
+
+
+static void
+amerge_right_@suff@(@type@ *arr, npy_intp* p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2, npy_intp *p3, size_t len)
+{
+ npy_intp ofs;
+ npy_intp *start = p1 - 1;
+ memcpy(p3, p2, sizeof(npy_intp) * l2);
+ p1 += l1 - 1;
+ p2 += l2 - 1;
+ p3 += l2 - 1;
+ /* first element must be in p1 otherwise skipped in the caller */
+ *p2-- = *p1--;
+
+ while (p1 < p2 && start < p1) {
+ if (@TYPE@_LT(arr + (*p3) * len, arr + (*p1) * len, len)) {
+ *p2-- = *p1--;
+ } else {
+ *p2-- = *p3--;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + 1, p3 - ofs + 1, sizeof(npy_intp) * ofs);
+ }
+}
+
+
+
+static int
+amerge_at_@suff@(@type@ *arr, npy_intp *tosort, const run *stack,
+ const npy_intp at, buffer_intp *buffer, size_t len)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ npy_intp *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* tosort[s2] belongs to tosort[s1+k] */
+ k = agallop_right_@suff@(arr, tosort + s1, l1, arr + tosort[s2] * len, len);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = tosort + s1 + k;
+ l1 -= k;
+ p2 = tosort + s2;
+ /* tosort[s2-1] belongs to tosort[s2+l2] */
+ l2 = agallop_left_@suff@(arr, tosort + s2, l2, arr + tosort[s2 - 1] * len,
+ len);
+
+ if (l2 < l1) {
+ ret = resize_buffer_intp(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ amerge_right_@suff@(arr, p1, l1, p2, l2, buffer->pw, len);
+ } else {
+ ret = resize_buffer_intp(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ amerge_left_@suff@(arr, p1, l1, p2, l2, buffer->pw, len);
+ }
+
+ return 0;
+}
+
+
+static int
+atry_collapse_@suff@(@type@ *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr, buffer_intp *buffer, size_t len)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 3, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+
+
+static int
+aforce_collapse_@suff@(@type@ *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr, buffer_intp *buffer, size_t len)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 3, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = amerge_at_@suff@(arr, tosort, stack, top - 2, buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+atimsort_@suff@(void *start, npy_intp *tosort, npy_intp num, void *varr)
+{
+ PyArrayObject *arr = varr;
+ size_t elsize = PyArray_ITEMSIZE(arr);
+ size_t len = elsize / sizeof(@type@);
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer_intp buffer;
+
+ /* Items that have zero size don't make sense to sort */
+ if (len == 0) {
+ return 0;
+ }
+
+ buffer.pw = NULL;
+ buffer.size = 0;
+ stack_ptr = 0;
+ minrun = compute_min_run_short(num);
+
+ for (l = 0; l < num;) {
+ n = acount_run_@suff@(start, tosort, l, num, minrun, len);
+ /* both s and l are scaled by len */
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = atry_collapse_@suff@(start, tosort, stack, &stack_ptr, &buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = aforce_collapse_@suff@(start, tosort, stack, &stack_ptr, &buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+
+cleanup:
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+ return ret;
+}
+
+
+/**end repeat**/
+
+
+
+/*
+ *****************************************************************************
+ ** GENERIC SORT **
+ *****************************************************************************
+ */
+
+
+typedef struct {
+ char *pw;
+ npy_intp size;
+ size_t len;
+} buffer_char;
+
+
+static NPY_INLINE int
+resize_buffer_char(buffer_char *buffer, npy_intp new_size)
+{
+ if (new_size <= buffer->size) {
+ return 0;
+ }
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ buffer->pw = malloc(sizeof(char) * new_size * buffer->len);
+ } else {
+ buffer->pw = realloc(buffer->pw, sizeof(char) * new_size * buffer->len);
+ }
+
+ buffer->size = new_size;
+
+ if (NPY_UNLIKELY(buffer->pw == NULL)) {
+ return -NPY_ENOMEM;
+ } else {
+ return 0;
+ }
+}
+
+
+static npy_intp
+npy_count_run(char *arr, npy_intp l, npy_intp num, npy_intp minrun,
+ char *vp, size_t len, PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp sz;
+ char *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = arr + l * len;
+
+ /* (not strictly) ascending sequence */
+ if (cmp(pl, pl + len, py_arr) <= 0) {
+ for (pi = pl + len; pi < arr + (num - 1) * len
+ && cmp(pi, pi + len, py_arr) <= 0; pi += len) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + len; pi < arr + (num - 1) * len
+ && cmp(pi + len, pi, py_arr) < 0; pi += len) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; pj += len, pr -= len) {
+ GENERIC_SWAP(pj, pr, len);
+ }
+ }
+
+ pi += len;
+ sz = (pi - pl) / len;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz * len;
+
+ /* insertion sort */
+ for (; pi < pr; pi += len) {
+ GENERIC_COPY(vp, pi, len);
+ pj = pi;
+
+ while (pl < pj && cmp(vp, pj - len, py_arr) < 0) {
+ GENERIC_COPY(pj, pj - len, len);
+ pj -= len;
+ }
+
+ GENERIC_COPY(pj, vp, len);
+ }
+ }
+
+ return sz;
+}
+
+
+static npy_intp
+npy_gallop_right(const char *arr, const npy_intp size, const char *key,
+ size_t len, PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (cmp(key, arr, py_arr) < 0) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (cmp(key, arr + ofs * len, py_arr) < 0) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[last_ofs*len] <= key < arr[ofs*len] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (cmp(key, arr + m * len, py_arr) < 0) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[(ofs-1)*len] <= key < arr[ofs*len] */
+ return ofs;
+}
+
+
+
+static npy_intp
+npy_gallop_left(const char *arr, const npy_intp size, const char *key,
+ size_t len, PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (cmp(arr + (size - 1) * len, key, py_arr) < 0) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (cmp(arr + (size - ofs - 1) * len, key, py_arr) < 0) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[(size-ofs-1)*len] < key <= arr[(size-last_ofs-1)*len] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (cmp(arr + m * len, key, py_arr) < 0) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[(r-1)*len] < key <= arr[r*len] */
+ return r;
+}
+
+
+static void
+npy_merge_left(char *p1, npy_intp l1, char *p2, npy_intp l2,
+ char *p3, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ char *end = p2 + l2 * len;
+ memcpy(p3, p1, sizeof(char) * l1 * len);
+ /* first element must be in p2 otherwise skipped in the caller */
+ GENERIC_COPY(p1, p2, len);
+ p1 += len;
+ p2 += len;
+
+ while (p1 < p2 && p2 < end) {
+ if (cmp(p2, p3, py_arr) < 0) {
+ GENERIC_COPY(p1, p2, len);
+ p1 += len;
+ p2 += len;
+ } else {
+ GENERIC_COPY(p1, p3, len);
+ p1 += len;
+ p3 += len;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(char) * (p2 - p1));
+ }
+}
+
+
+static void
+npy_merge_right(char *p1, npy_intp l1, char *p2, npy_intp l2,
+ char *p3, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp ofs;
+ char *start = p1 - len;
+ memcpy(p3, p2, sizeof(char) * l2 * len);
+ p1 += (l1 - 1) * len;
+ p2 += (l2 - 1) * len;
+ p3 += (l2 - 1) * len;
+ /* first element must be in p1 otherwise skipped in the caller */
+ GENERIC_COPY(p2, p1, len);
+ p2 -= len;
+ p1 -= len;
+
+ while (p1 < p2 && start < p1) {
+ if (cmp(p3, p1, py_arr) < 0) {
+ GENERIC_COPY(p2, p1, len);
+ p2 -= len;
+ p1 -= len;
+ } else {
+ GENERIC_COPY(p2, p3, len);
+ p2 -= len;
+ p3 -= len;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + len, p3 - ofs + len, sizeof(char) * ofs);
+ }
+}
+
+
+
+static int
+npy_merge_at(char *arr, const run *stack, const npy_intp at,
+ buffer_char *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ char *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* arr[s2] belongs to arr[s1+k] */
+ GENERIC_COPY(buffer->pw, arr + s2 * len, len);
+ k = npy_gallop_right(arr + s1 * len, l1, buffer->pw, len, cmp, py_arr);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = arr + (s1 + k) * len;
+ l1 -= k;
+ p2 = arr + s2 * len;
+ /* arr[s2-1] belongs to arr[s2+l2] */
+ GENERIC_COPY(buffer->pw, arr + (s2 - 1) * len, len);
+ l2 = npy_gallop_left(arr + s2 * len, l2, buffer->pw, len, cmp, py_arr);
+
+ if (l2 < l1) {
+ ret = resize_buffer_char(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ npy_merge_right(p1, l1, p2, l2, buffer->pw, len, cmp, py_arr);
+ } else {
+ ret = resize_buffer_char(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ npy_merge_left(p1, l1, p2, l2, buffer->pw, len, cmp, py_arr);
+ }
+
+ return 0;
+}
+
+
+static int
+npy_try_collapse(char *arr, run *stack, npy_intp *stack_ptr,
+ buffer_char *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = npy_merge_at(arr, stack, top - 3, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = npy_merge_at(arr, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = npy_merge_at(arr, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+
+static int
+npy_force_collapse(char *arr, run *stack, npy_intp *stack_ptr,
+ buffer_char *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = npy_merge_at(arr, stack, top - 3, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = npy_merge_at(arr, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = npy_merge_at(arr, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+npy_timsort(void *start, npy_intp num, void *varr)
+{
+ PyArrayObject *arr = varr;
+ size_t len = PyArray_ITEMSIZE(arr);
+ PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare;
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer_char buffer;
+
+ /* Items that have zero size don't make sense to sort */
+ if (len == 0) {
+ return 0;
+ }
+
+ buffer.pw = NULL;
+ buffer.size = 0;
+ buffer.len = len;
+ stack_ptr = 0;
+ minrun = compute_min_run_short(num);
+
+ /* used for insertion sort and gallop key */
+ ret = resize_buffer_char(&buffer, len);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ for (l = 0; l < num;) {
+ n = npy_count_run(start, l, num, minrun, buffer.pw, len, cmp, arr);
+
+ /* both s and l are scaled by len */
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = npy_try_collapse(start, stack, &stack_ptr, &buffer, len, cmp, arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = npy_force_collapse(start, stack, &stack_ptr, &buffer, len, cmp, arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+
+cleanup:
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+ return ret;
+}
+
+
+/* argsort */
+
+static npy_intp
+npy_acount_run(char *arr, npy_intp *tosort, npy_intp l, npy_intp num,
+ npy_intp minrun, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp sz;
+ npy_intp vi;
+ npy_intp *pl, *pi, *pj, *pr;
+
+ if (NPY_UNLIKELY(num - l == 1)) {
+ return 1;
+ }
+
+ pl = tosort + l;
+
+ /* (not strictly) ascending sequence */
+ if (cmp(arr + (*pl) * len, arr + (*(pl + 1)) * len, py_arr) <= 0) {
+ for (pi = pl + 1; pi < tosort + num - 1
+ && cmp(arr + (*pi) * len, arr + (*(pi + 1)) * len, py_arr) <= 0; ++pi) {
+ }
+ } else { /* (strictly) descending sequence */
+ for (pi = pl + 1; pi < tosort + num - 1
+ && cmp(arr + (*(pi + 1)) * len, arr + (*pi) * len, py_arr) < 0; ++pi) {
+ }
+
+ for (pj = pl, pr = pi; pj < pr; ++pj, --pr) {
+ INTP_SWAP(*pj, *pr);
+ }
+ }
+
+ ++pi;
+ sz = pi - pl;
+
+ if (sz < minrun) {
+ if (l + minrun < num) {
+ sz = minrun;
+ } else {
+ sz = num - l;
+ }
+
+ pr = pl + sz;
+
+ /* insertion sort */
+ for (; pi < pr; ++pi) {
+ vi = *pi;
+ pj = pi;
+
+ while (pl < pj && cmp(arr + vi * len, arr + (*(pj - 1)) * len, py_arr) < 0) {
+ *pj = *(pj - 1);
+ --pj;
+ }
+
+ *pj = vi;
+ }
+ }
+
+ return sz;
+}
+
+
+static npy_intp
+npy_agallop_left(const char *arr, const npy_intp *tosort,
+ const npy_intp size, const char *key, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp last_ofs, ofs, l, m, r;
+
+ if (cmp(arr + tosort[size - 1] * len, key, py_arr) < 0) {
+ return size;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size;
+ break;
+ }
+
+ if (cmp(arr + tosort[size - ofs - 1] * len, key, py_arr) < 0) {
+ break;
+ } else {
+ last_ofs = ofs;
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[size-ofs-1]*len] < key <= arr[tosort[size-last_ofs-1]*len] */
+ l = size - ofs - 1;
+ r = size - last_ofs - 1;
+
+ while (l + 1 < r) {
+ m = l + ((r - l) >> 1);
+
+ if (cmp(arr + tosort[m] * len, key, py_arr) < 0) {
+ l = m;
+ } else {
+ r = m;
+ }
+ }
+
+ /* now that arr[tosort[r-1]*len] < key <= arr[tosort[r]*len] */
+ return r;
+}
+
+
+static npy_intp
+npy_agallop_right(const char *arr, const npy_intp *tosort,
+ const npy_intp size, const char *key, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp last_ofs, ofs, m;
+
+ if (cmp(key, arr + tosort[0] * len, py_arr) < 0) {
+ return 0;
+ }
+
+ last_ofs = 0;
+ ofs = 1;
+
+ for (;;) {
+ if (size <= ofs || ofs < 0) {
+ ofs = size; /* arr[ofs] is never accessed */
+ break;
+ }
+
+ if (cmp(key, arr + tosort[ofs] * len, py_arr) < 0) {
+ break;
+ } else {
+ last_ofs = ofs;
+ /* ofs = 1, 3, 7, 15... */
+ ofs = (ofs << 1) + 1;
+ }
+ }
+
+ /* now that arr[tosort[last_ofs]*len] <= key < arr[tosort[ofs]*len] */
+ while (last_ofs + 1 < ofs) {
+ m = last_ofs + ((ofs - last_ofs) >> 1);
+
+ if (cmp(key, arr + tosort[m] * len, py_arr) < 0) {
+ ofs = m;
+ } else {
+ last_ofs = m;
+ }
+ }
+
+ /* now that arr[tosort[ofs-1]*len] <= key < arr[tosort[ofs]*len] */
+ return ofs;
+}
+
+
+static void
+npy_amerge_left(char *arr, npy_intp *p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2, npy_intp *p3, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp *end = p2 + l2;
+ memcpy(p3, p1, sizeof(npy_intp) * l1);
+ /* first element must be in p2 otherwise skipped in the caller */
+ *p1++ = *p2++;
+
+ while (p1 < p2 && p2 < end) {
+ if (cmp(arr + (*p2) * len, arr + (*p3) * len, py_arr) < 0) {
+ *p1++ = *p2++;
+ } else {
+ *p1++ = *p3++;
+ }
+ }
+
+ if (p1 != p2) {
+ memcpy(p1, p3, sizeof(npy_intp) * (p2 - p1));
+ }
+}
+
+
+static void
+npy_amerge_right(char *arr, npy_intp* p1, npy_intp l1, npy_intp *p2,
+ npy_intp l2, npy_intp *p3, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ npy_intp ofs;
+ npy_intp *start = p1 - 1;
+ memcpy(p3, p2, sizeof(npy_intp) * l2);
+ p1 += l1 - 1;
+ p2 += l2 - 1;
+ p3 += l2 - 1;
+ /* first element must be in p1 otherwise skipped in the caller */
+ *p2-- = *p1--;
+
+ while (p1 < p2 && start < p1) {
+ if (cmp(arr + (*p3) * len, arr + (*p1) * len, py_arr) < 0) {
+ *p2-- = *p1--;
+ } else {
+ *p2-- = *p3--;
+ }
+ }
+
+ if (p1 != p2) {
+ ofs = p2 - start;
+ memcpy(start + 1, p3 - ofs + 1, sizeof(npy_intp) * ofs);
+ }
+}
+
+
+
+static int
+npy_amerge_at(char *arr, npy_intp *tosort, const run *stack,
+ const npy_intp at, buffer_intp *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp s1, l1, s2, l2, k;
+ npy_intp *p1, *p2;
+ s1 = stack[at].s;
+ l1 = stack[at].l;
+ s2 = stack[at + 1].s;
+ l2 = stack[at + 1].l;
+ /* tosort[s2] belongs to tosort[s1+k] */
+ k = npy_agallop_right(arr, tosort + s1, l1, arr + tosort[s2] * len, len, cmp,
+ py_arr);
+
+ if (l1 == k) {
+ /* already sorted */
+ return 0;
+ }
+
+ p1 = tosort + s1 + k;
+ l1 -= k;
+ p2 = tosort + s2;
+ /* tosort[s2-1] belongs to tosort[s2+l2] */
+ l2 = npy_agallop_left(arr, tosort + s2, l2, arr + tosort[s2 - 1] * len,
+ len, cmp, py_arr);
+
+ if (l2 < l1) {
+ ret = resize_buffer_intp(buffer, l2);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ npy_amerge_right(arr, p1, l1, p2, l2, buffer->pw, len, cmp, py_arr);
+ } else {
+ ret = resize_buffer_intp(buffer, l1);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ npy_amerge_left(arr, p1, l1, p2, l2, buffer->pw, len, cmp, py_arr);
+ }
+
+ return 0;
+}
+
+
+static int
+npy_atry_collapse(char *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr, buffer_intp *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp A, B, C, top;
+ top = *stack_ptr;
+
+ while (1 < top) {
+ B = stack[top - 2].l;
+ C = stack[top - 1].l;
+
+ if ((2 < top && stack[top - 3].l <= B + C) ||
+ (3 < top && stack[top - 4].l <= stack[top - 3].l + B)) {
+ A = stack[top - 3].l;
+
+ if (A <= C) {
+ ret = npy_amerge_at(arr, tosort, stack, top - 3, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += B;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = npy_amerge_at(arr, tosort, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ }
+ } else if (1 < top && B <= C) {
+ ret = npy_amerge_at(arr, tosort, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += C;
+ --top;
+ } else {
+ break;
+ }
+ }
+
+ *stack_ptr = top;
+ return 0;
+}
+
+
+static int
+npy_aforce_collapse(char *arr, npy_intp *tosort, run *stack,
+ npy_intp *stack_ptr, buffer_intp *buffer, size_t len,
+ PyArray_CompareFunc *cmp, PyArrayObject *py_arr)
+{
+ int ret;
+ npy_intp top = *stack_ptr;
+
+ while (2 < top) {
+ if (stack[top - 3].l <= stack[top - 1].l) {
+ ret = npy_amerge_at(arr, tosort, stack, top - 3, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 3].l += stack[top - 2].l;
+ stack[top - 2] = stack[top - 1];
+ --top;
+ } else {
+ ret = npy_amerge_at(arr, tosort, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+
+ stack[top - 2].l += stack[top - 1].l;
+ --top;
+ }
+ }
+
+ if (1 < top) {
+ ret = npy_amerge_at(arr, tosort, stack, top - 2, buffer, len, cmp, py_arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { return ret; }
+ }
+
+ return 0;
+}
+
+
+int
+npy_atimsort(void *start, npy_intp *tosort, npy_intp num, void *varr)
+{
+ PyArrayObject *arr = varr;
+ size_t len = PyArray_ITEMSIZE(arr);
+ PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare;
+ int ret;
+ npy_intp l, n, stack_ptr, minrun;
+ run stack[TIMSORT_STACK_SIZE];
+ buffer_intp buffer;
+
+ /* Items that have zero size don't make sense to sort */
+ if (len == 0) {
+ return 0;
+ }
+
+ buffer.pw = NULL;
+ buffer.size = 0;
+ stack_ptr = 0;
+ minrun = compute_min_run_short(num);
+
+ for (l = 0; l < num;) {
+ n = npy_acount_run(start, tosort, l, num, minrun, len, cmp, arr);
+ /* both s and l are scaled by len */
+ stack[stack_ptr].s = l;
+ stack[stack_ptr].l = n;
+ ++stack_ptr;
+ ret = npy_atry_collapse(start, tosort, stack, &stack_ptr, &buffer, len, cmp,
+ arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ l += n;
+ }
+
+ ret = npy_aforce_collapse(start, tosort, stack, &stack_ptr, &buffer, len,
+ cmp, arr);
+
+ if (NPY_UNLIKELY(ret < 0)) { goto cleanup; }
+
+ ret = 0;
+
+cleanup:
+ if (buffer.pw != NULL) {
+ free(buffer.pw);
+ }
+ return ret;
+}
diff --git a/numpy/core/src/umath/_struct_ufunc_tests.c.src b/numpy/core/src/umath/_struct_ufunc_tests.c.src
index 5c6e235e0..3eaac73e1 100644
--- a/numpy/core/src/umath/_struct_ufunc_tests.c.src
+++ b/numpy/core/src/umath/_struct_ufunc_tests.c.src
@@ -17,12 +17,6 @@
* docs.python.org .
*/
-static PyMethodDef StructUfuncTestMethods[] = {
- {NULL, NULL, 0, NULL}
-};
-
-/* The loop definition must precede the PyMODINIT_FUNC. */
-
static void add_uint64_triplet(char **args, npy_intp *dimensions,
npy_intp* steps, void* data)
{
@@ -53,6 +47,59 @@ static void add_uint64_triplet(char **args, npy_intp *dimensions,
}
}
+static PyObject*
+register_fail(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args))
+{
+ PyObject *add_triplet;
+ PyObject *dtype_dict;
+ PyArray_Descr *dtype;
+ PyArray_Descr *dtypes[3];
+ int retval;
+
+ add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1,
+ PyUFunc_None, "add_triplet",
+ "add_triplet_docstring", 0);
+
+ dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]",
+ "f0", "u8", "f1", "u8", "f2", "u8");
+ PyArray_DescrConverter(dtype_dict, &dtype);
+ Py_DECREF(dtype_dict);
+
+ dtypes[0] = dtype;
+ dtypes[1] = dtype;
+ dtypes[2] = dtype;
+
+ retval = PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet,
+ dtype,
+ &add_uint64_triplet,
+ dtypes,
+ NULL);
+
+ if (retval < 0) {
+ Py_DECREF(add_triplet);
+ Py_DECREF(dtype);
+ return NULL;
+ }
+ retval = PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet,
+ dtype,
+ &add_uint64_triplet,
+ dtypes,
+ NULL);
+ Py_DECREF(add_triplet);
+ Py_DECREF(dtype);
+ if (retval < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef StructUfuncTestMethods[] = {
+ {"register_fail",
+ register_fail,
+ METH_NOARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
+
#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
@@ -100,7 +147,7 @@ PyMODINIT_FUNC init_struct_ufunc_tests(void)
"add_triplet_docstring", 0);
dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]",
- "f0", "u8", "f1", "u8", "f2", "u8");
+ "f0", "u8", "f1", "u8", "f2", "u8");
PyArray_DescrConverter(dtype_dict, &dtype);
Py_DECREF(dtype_dict);
diff --git a/numpy/core/src/umath/clip.c.src b/numpy/core/src/umath/clip.c.src
new file mode 100644
index 000000000..30fa3d2b3
--- /dev/null
+++ b/numpy/core/src/umath/clip.c.src
@@ -0,0 +1,119 @@
+/**
+ * This module provides the inner loops for the clip ufunc
+ */
+#define _UMATHMODULE
+#define _MULTIARRAYMODULE
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include "Python.h"
+
+#include "numpy/halffloat.h"
+#include "numpy/npy_math.h"
+#include "numpy/ndarraytypes.h"
+#include "numpy/npy_common.h"
+#include "numpy/utils.h"
+#include "fast_loop_macros.h"
+
+/*
+ * Produce macros that perform nan/nat-propagating min and max
+ */
+
+/**begin repeat
+ * #name = BOOL,
+ * BYTE, UBYTE, SHORT, USHORT, INT, UINT,
+ * LONG, ULONG, LONGLONG, ULONGLONG#
+ */
+#define _NPY_@name@_MIN(a, b) PyArray_MIN(a, b)
+#define _NPY_@name@_MAX(a, b) PyArray_MAX(a, b)
+/**end repeat**/
+
+#define _NPY_HALF_MIN(a, b) (npy_half_isnan(a) || npy_half_le(a, b) ? (a) : (b))
+#define _NPY_HALF_MAX(a, b) (npy_half_isnan(a) || npy_half_ge(a, b) ? (a) : (b))
+
+/**begin repeat
+ * #name = FLOAT, DOUBLE, LONGDOUBLE#
+ */
+#define _NPY_@name@_MIN(a, b) (npy_isnan(a) ? (a) : PyArray_MIN(a, b))
+#define _NPY_@name@_MAX(a, b) (npy_isnan(a) ? (a) : PyArray_MAX(a, b))
+/**end repeat**/
+
+/**begin repeat
+ * #name = CFLOAT, CDOUBLE, CLONGDOUBLE#
+ */
+#define _NPY_@name@_MIN(a, b) (npy_isnan((a).real) || npy_isnan((a).imag) || PyArray_CLT(a, b) ? (a) : (b))
+#define _NPY_@name@_MAX(a, b) (npy_isnan((a).real) || npy_isnan((a).imag) || PyArray_CGT(a, b) ? (a) : (b))
+/**end repeat**/
+
+/**begin repeat
+ * #name = DATETIME, TIMEDELTA#
+ */
+#define _NPY_@name@_MIN(a, b) ( \
+ (a) == NPY_DATETIME_NAT ? (a) : \
+ (b) == NPY_DATETIME_NAT ? (b) : \
+ (a) < (b) ? (a) : (b) \
+)
+#define _NPY_@name@_MAX(a, b) ( \
+ (a) == NPY_DATETIME_NAT ? (a) : \
+ (b) == NPY_DATETIME_NAT ? (b) : \
+ (a) > (b) ? (a) : (b) \
+)
+/**end repeat**/
+
+/**begin repeat
+ *
+ * #name = BOOL,
+ * BYTE, UBYTE, SHORT, USHORT, INT, UINT,
+ * LONG, ULONG, LONGLONG, ULONGLONG,
+ * HALF, FLOAT, DOUBLE, LONGDOUBLE,
+ * CFLOAT, CDOUBLE, CLONGDOUBLE,
+ * DATETIME, TIMEDELTA#
+ * #type = npy_bool,
+ * npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
+ * npy_long, npy_ulong, npy_longlong, npy_ulonglong,
+ * npy_half, npy_float, npy_double, npy_longdouble,
+ * npy_cfloat, npy_cdouble, npy_clongdouble,
+ * npy_datetime, npy_timedelta#
+ */
+
+#define _NPY_CLIP(x, min, max) \
+ _NPY_@name@_MIN(_NPY_@name@_MAX((x), (min)), (max))
+
+NPY_NO_EXPORT void
+@name@_clip(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+{
+ if (steps[1] == 0 && steps[2] == 0) {
+ /* min and max are constant throughout the loop, the most common case */
+ /* NOTE: it may be possible to optimize these checks for nan */
+ @type@ min_val = *(@type@ *)args[1];
+ @type@ max_val = *(@type@ *)args[2];
+
+ char *ip1 = args[0], *op1 = args[3];
+ npy_intp is1 = steps[0], os1 = steps[3];
+ npy_intp n = dimensions[0];
+
+ /* contiguous, branch to let the compiler optimize */
+ if (is1 == sizeof(@type@) && os1 == sizeof(@type@)) {
+ for(npy_intp i = 0; i < n; i++, ip1 += is1, op1 += os1) {
+ *(@type@ *)op1 = _NPY_CLIP(*(@type@ *)ip1, min_val, max_val);
+ }
+ }
+ else {
+ for(npy_intp i = 0; i < n; i++, ip1 += is1, op1 += os1) {
+ *(@type@ *)op1 = _NPY_CLIP(*(@type@ *)ip1, min_val, max_val);
+ }
+ }
+ }
+ else {
+ TERNARY_LOOP {
+ *(@type@ *)op1 = _NPY_CLIP(*(@type@ *)ip1, *(@type@ *)ip2, *(@type@ *)ip3);
+ }
+ }
+ npy_clear_floatstatus_barrier((char*)dimensions);
+}
+
+// clean up the macros we defined above
+#undef _NPY_CLIP
+#undef _NPY_@name@_MAX
+#undef _NPY_@name@_MIN
+
+/**end repeat**/
diff --git a/numpy/core/src/umath/clip.h.src b/numpy/core/src/umath/clip.h.src
new file mode 100644
index 000000000..d77971ad7
--- /dev/null
+++ b/numpy/core/src/umath/clip.h.src
@@ -0,0 +1,18 @@
+#ifndef _NPY_UMATH_CLIP_H_
+#define _NPY_UMATH_CLIP_H_
+
+
+/**begin repeat
+ *
+ * #name = BOOL,
+ * BYTE, UBYTE, SHORT, USHORT, INT, UINT,
+ * LONG, ULONG, LONGLONG, ULONGLONG,
+ * HALF, FLOAT, DOUBLE, LONGDOUBLE,
+ * CFLOAT, CDOUBLE, CLONGDOUBLE,
+ * DATETIME, TIMEDELTA#
+ */
+NPY_NO_EXPORT void
+@name@_clip(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+/**end repeat**/
+
+#endif
diff --git a/numpy/core/src/umath/cpuid.c b/numpy/core/src/umath/cpuid.c
index 6744ceb05..8673f1736 100644
--- a/numpy/core/src/umath/cpuid.c
+++ b/numpy/core/src/umath/cpuid.c
@@ -11,6 +11,7 @@
#define XCR_XFEATURE_ENABLED_MASK 0x0
#define XSTATE_SSE 0x2
#define XSTATE_YMM 0x4
+#define XSTATE_ZMM 0x70
/*
* verify the OS supports avx instructions
@@ -33,6 +34,19 @@ int os_avx_support(void)
#endif
}
+static NPY_INLINE
+int os_avx512_support(void)
+{
+#if HAVE_XGETBV
+ unsigned int eax, edx;
+ unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
+ unsigned int xcr0 = XSTATE_ZMM | XSTATE_YMM | XSTATE_SSE;
+ __asm__("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ return (eax & xcr0) == xcr0;
+#else
+ return 0;
+#endif
+}
/*
* Primitive cpu feature detect function
@@ -42,7 +56,14 @@ NPY_NO_EXPORT int
npy_cpu_supports(const char * feature)
{
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
- if (strcmp(feature, "avx2") == 0) {
+ if (strcmp(feature, "avx512f") == 0) {
+#ifdef HAVE___BUILTIN_CPU_SUPPORTS_AVX512F
+ return __builtin_cpu_supports("avx512f") && os_avx512_support();
+#else
+ return 0;
+#endif
+ }
+ else if (strcmp(feature, "avx2") == 0) {
return __builtin_cpu_supports("avx2") && os_avx_support();
}
else if (strcmp(feature, "avx") == 0) {
diff --git a/numpy/core/src/umath/fast_loop_macros.h b/numpy/core/src/umath/fast_loop_macros.h
new file mode 100644
index 000000000..ae6d69a3e
--- /dev/null
+++ b/numpy/core/src/umath/fast_loop_macros.h
@@ -0,0 +1,234 @@
+/**
+ * Macros to help build fast ufunc inner loops.
+ *
+ * These expect to have access to the arguments of a typical ufunc loop,
+ *
+ * char **args
+ * npy_intp *dimensions
+ * npy_intp *steps
+ */
+#ifndef _NPY_UMATH_FAST_LOOP_MACROS_H_
+#define _NPY_UMATH_FAST_LOOP_MACROS_H_
+
+#include "simd.inc"
+
+/**
+ * Simple unoptimized loop macros that iterate over the ufunc arguments in
+ * parallel.
+ * @{
+ */
+
+/** (<ignored>) -> (op1) */
+#define OUTPUT_LOOP\
+ char *op1 = args[1];\
+ npy_intp os1 = steps[1];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, op1 += os1)
+
+/** (ip1) -> (op1) */
+#define UNARY_LOOP\
+ char *ip1 = args[0], *op1 = args[1];\
+ npy_intp is1 = steps[0], os1 = steps[1];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, ip1 += is1, op1 += os1)
+
+/** (ip1) -> (op1, op2) */
+#define UNARY_LOOP_TWO_OUT\
+ char *ip1 = args[0], *op1 = args[1], *op2 = args[2];\
+ npy_intp is1 = steps[0], os1 = steps[1], os2 = steps[2];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, ip1 += is1, op1 += os1, op2 += os2)
+
+/** (ip1, ip2) -> (op1) */
+#define BINARY_LOOP\
+ char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1)
+
+/** (ip1, ip2) -> (op1, op2) */
+#define BINARY_LOOP_TWO_OUT\
+ char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3];\
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2], os2 = steps[3];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1, op2 += os2)
+
+/** (ip1, ip2, ip3) -> (op1) */
+#define TERNARY_LOOP\
+ char *ip1 = args[0], *ip2 = args[1], *ip3 = args[2], *op1 = args[3];\
+ npy_intp is1 = steps[0], is2 = steps[1], is3 = steps[2], os1 = steps[3];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, ip3 += is3, op1 += os1)
+
+/** @} */
+
+/* unary loop input and output contiguous */
+#define IS_UNARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \
+ steps[1] == sizeof(tout))
+
+#define IS_OUTPUT_CONT(tout) (steps[1] == sizeof(tout))
+
+#define IS_BINARY_REDUCE ((args[0] == args[2])\
+ && (steps[0] == steps[2])\
+ && (steps[0] == 0))
+
+/* binary loop input and output contiguous */
+#define IS_BINARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \
+ steps[1] == sizeof(tin) && \
+ steps[2] == sizeof(tout))
+
+/* binary loop input and output contiguous with first scalar */
+#define IS_BINARY_CONT_S1(tin, tout) (steps[0] == 0 && \
+ steps[1] == sizeof(tin) && \
+ steps[2] == sizeof(tout))
+
+/* binary loop input and output contiguous with second scalar */
+#define IS_BINARY_CONT_S2(tin, tout) (steps[0] == sizeof(tin) && \
+ steps[1] == 0 && \
+ steps[2] == sizeof(tout))
+
+/*
+ * loop with contiguous specialization
+ * op should be the code working on `tin in` and
+ * storing the result in `tout *out`
+ * combine with NPY_GCC_OPT_3 to allow autovectorization
+ * should only be used where its worthwhile to avoid code bloat
+ */
+#define BASE_UNARY_LOOP(tin, tout, op) \
+ UNARY_LOOP { \
+ const tin in = *(tin *)ip1; \
+ tout *out = (tout *)op1; \
+ op; \
+ }
+
+#define UNARY_LOOP_FAST(tin, tout, op) \
+ do { \
+ /* condition allows compiler to optimize the generic macro */ \
+ if (IS_UNARY_CONT(tin, tout)) { \
+ if (args[0] == args[1]) { \
+ BASE_UNARY_LOOP(tin, tout, op) \
+ } \
+ else { \
+ BASE_UNARY_LOOP(tin, tout, op) \
+ } \
+ } \
+ else { \
+ BASE_UNARY_LOOP(tin, tout, op) \
+ } \
+ } \
+ while (0)
+
+/*
+ * loop with contiguous specialization
+ * op should be the code working on `tin in1`, `tin in2` and
+ * storing the result in `tout *out`
+ * combine with NPY_GCC_OPT_3 to allow autovectorization
+ * should only be used where its worthwhile to avoid code bloat
+ */
+#define BASE_BINARY_LOOP(tin, tout, op) \
+ BINARY_LOOP { \
+ const tin in1 = *(tin *)ip1; \
+ const tin in2 = *(tin *)ip2; \
+ tout *out = (tout *)op1; \
+ op; \
+ }
+
+/*
+ * unfortunately gcc 6/7 regressed and we need to give it additional hints to
+ * vectorize inplace operations (PR80198)
+ * must only be used after op1 == ip1 or ip2 has been checked
+ * TODO: using ivdep might allow other compilers to vectorize too
+ */
+#if __GNUC__ >= 6
+#define IVDEP_LOOP _Pragma("GCC ivdep")
+#else
+#define IVDEP_LOOP
+#endif
+#define BASE_BINARY_LOOP_INP(tin, tout, op) \
+ char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\
+ npy_intp n = dimensions[0];\
+ npy_intp i;\
+ IVDEP_LOOP \
+ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) { \
+ const tin in1 = *(tin *)ip1; \
+ const tin in2 = *(tin *)ip2; \
+ tout *out = (tout *)op1; \
+ op; \
+ }
+
+#define BASE_BINARY_LOOP_S(tin, tout, cin, cinp, vin, vinp, op) \
+ const tin cin = *(tin *)cinp; \
+ BINARY_LOOP { \
+ const tin vin = *(tin *)vinp; \
+ tout *out = (tout *)op1; \
+ op; \
+ }
+
+/* PR80198 again, scalar works without the pragma */
+#define BASE_BINARY_LOOP_S_INP(tin, tout, cin, cinp, vin, vinp, op) \
+ const tin cin = *(tin *)cinp; \
+ BINARY_LOOP { \
+ const tin vin = *(tin *)vinp; \
+ tout *out = (tout *)vinp; \
+ op; \
+ }
+
+#define BINARY_LOOP_FAST(tin, tout, op) \
+ do { \
+ /* condition allows compiler to optimize the generic macro */ \
+ if (IS_BINARY_CONT(tin, tout)) { \
+ if (abs_ptrdiff(args[2], args[0]) == 0 && \
+ abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \
+ BASE_BINARY_LOOP_INP(tin, tout, op) \
+ } \
+ else if (abs_ptrdiff(args[2], args[1]) == 0 && \
+ abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \
+ BASE_BINARY_LOOP_INP(tin, tout, op) \
+ } \
+ else { \
+ BASE_BINARY_LOOP(tin, tout, op) \
+ } \
+ } \
+ else if (IS_BINARY_CONT_S1(tin, tout)) { \
+ if (abs_ptrdiff(args[2], args[1]) == 0) { \
+ BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \
+ } \
+ else { \
+ BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \
+ } \
+ } \
+ else if (IS_BINARY_CONT_S2(tin, tout)) { \
+ if (abs_ptrdiff(args[2], args[0]) == 0) { \
+ BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \
+ } \
+ else { \
+ BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \
+ }\
+ } \
+ else { \
+ BASE_BINARY_LOOP(tin, tout, op) \
+ } \
+ } \
+ while (0)
+
+#define BINARY_REDUCE_LOOP_INNER\
+ char *ip2 = args[1]; \
+ npy_intp is2 = steps[1]; \
+ npy_intp n = dimensions[0]; \
+ npy_intp i; \
+ for(i = 0; i < n; i++, ip2 += is2)
+
+#define BINARY_REDUCE_LOOP(TYPE)\
+ char *iop1 = args[0]; \
+ TYPE io1 = *(TYPE *)iop1; \
+ BINARY_REDUCE_LOOP_INNER
+
+
+#endif /* _NPY_UMATH_FAST_LOOP_MACROS_H_ */
diff --git a/numpy/core/src/umath/funcs.inc.src b/numpy/core/src/umath/funcs.inc.src
index da2ab07f8..c2732f925 100644
--- a/numpy/core/src/umath/funcs.inc.src
+++ b/numpy/core/src/umath/funcs.inc.src
@@ -160,6 +160,39 @@ npy_ObjectLogicalNot(PyObject *i1)
}
static PyObject *
+npy_ObjectFloor(PyObject *obj) {
+ PyObject *math_floor_func = NULL;
+
+ npy_cache_import("math", "floor", &math_floor_func);
+ if (math_floor_func == NULL) {
+ return NULL;
+ }
+ return PyObject_CallFunction(math_floor_func, "O", obj);
+}
+
+static PyObject *
+npy_ObjectCeil(PyObject *obj) {
+ PyObject *math_ceil_func = NULL;
+
+ npy_cache_import("math", "ceil", &math_ceil_func);
+ if (math_ceil_func == NULL) {
+ return NULL;
+ }
+ return PyObject_CallFunction(math_ceil_func, "O", obj);
+}
+
+static PyObject *
+npy_ObjectTrunc(PyObject *obj) {
+ PyObject *math_trunc_func = NULL;
+
+ npy_cache_import("math", "trunc", &math_trunc_func);
+ if (math_trunc_func == NULL) {
+ return NULL;
+ }
+ return PyObject_CallFunction(math_trunc_func, "O", obj);
+}
+
+static PyObject *
npy_ObjectGCD(PyObject *i1, PyObject *i2)
{
PyObject *gcd = NULL;
@@ -226,6 +259,17 @@ npy_ObjectLCM(PyObject *i1, PyObject *i2)
return PyNumber_Absolute(tmp);
}
+
+static PyObject *
+npy_ObjectClip(PyObject *arr, PyObject *min, PyObject *max) {
+ PyObject *o = npy_ObjectMax(arr, min);
+ if (o == NULL) {
+ return NULL;
+ }
+ Py_SETREF(o, npy_ObjectMin(o, max));
+ return o;
+}
+
/*
*****************************************************************************
** COMPLEX FUNCTIONS **
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index 975a5e6b8..f84d74efe 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -46,200 +46,9 @@
*/
#include "simd.inc"
+/** Provides the various *_LOOP macros */
+#include "fast_loop_macros.h"
-/*
- *****************************************************************************
- ** UFUNC LOOPS **
- *****************************************************************************
- */
-
-/* unary loop input and output contiguous */
-#define IS_UNARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \
- steps[1] == sizeof(tout))
-
-#define IS_BINARY_REDUCE ((args[0] == args[2])\
- && (steps[0] == steps[2])\
- && (steps[0] == 0))
-
-/* binary loop input and output contiguous */
-#define IS_BINARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \
- steps[1] == sizeof(tin) && \
- steps[2] == sizeof(tout))
-/* binary loop input and output contiguous with first scalar */
-#define IS_BINARY_CONT_S1(tin, tout) (steps[0] == 0 && \
- steps[1] == sizeof(tin) && \
- steps[2] == sizeof(tout))
-/* binary loop input and output contiguous with second scalar */
-#define IS_BINARY_CONT_S2(tin, tout) (steps[0] == sizeof(tin) && \
- steps[1] == 0 && \
- steps[2] == sizeof(tout))
-
-#define OUTPUT_LOOP\
- char *op1 = args[1];\
- npy_intp os1 = steps[1];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- for(i = 0; i < n; i++, op1 += os1)
-
-#define UNARY_LOOP\
- char *ip1 = args[0], *op1 = args[1];\
- npy_intp is1 = steps[0], os1 = steps[1];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- for(i = 0; i < n; i++, ip1 += is1, op1 += os1)
-
-/*
- * loop with contiguous specialization
- * op should be the code working on `tin in` and
- * storing the result in `tout * out`
- * combine with NPY_GCC_OPT_3 to allow autovectorization
- * should only be used where its worthwhile to avoid code bloat
- */
-#define BASE_UNARY_LOOP(tin, tout, op) \
- UNARY_LOOP { \
- const tin in = *(tin *)ip1; \
- tout * out = (tout *)op1; \
- op; \
- }
-#define UNARY_LOOP_FAST(tin, tout, op) \
- do { \
- /* condition allows compiler to optimize the generic macro */ \
- if (IS_UNARY_CONT(tin, tout)) { \
- if (args[0] == args[1]) { \
- BASE_UNARY_LOOP(tin, tout, op) \
- } \
- else { \
- BASE_UNARY_LOOP(tin, tout, op) \
- } \
- } \
- else { \
- BASE_UNARY_LOOP(tin, tout, op) \
- } \
- } \
- while (0)
-
-#define UNARY_LOOP_TWO_OUT\
- char *ip1 = args[0], *op1 = args[1], *op2 = args[2];\
- npy_intp is1 = steps[0], os1 = steps[1], os2 = steps[2];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- for(i = 0; i < n; i++, ip1 += is1, op1 += os1, op2 += os2)
-
-#define BINARY_LOOP\
- char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\
- npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1)
-
-/*
- * loop with contiguous specialization
- * op should be the code working on `tin in1`, `tin in2` and
- * storing the result in `tout * out`
- * combine with NPY_GCC_OPT_3 to allow autovectorization
- * should only be used where its worthwhile to avoid code bloat
- */
-#define BASE_BINARY_LOOP(tin, tout, op) \
- BINARY_LOOP { \
- const tin in1 = *(tin *)ip1; \
- const tin in2 = *(tin *)ip2; \
- tout * out = (tout *)op1; \
- op; \
- }
-/*
- * unfortunately gcc 6/7 regressed and we need to give it additional hints to
- * vectorize inplace operations (PR80198)
- * must only be used after op1 == ip1 or ip2 has been checked
- * TODO: using ivdep might allow other compilers to vectorize too
- */
-#if __GNUC__ >= 6
-#define IVDEP_LOOP _Pragma("GCC ivdep")
-#else
-#define IVDEP_LOOP
-#endif
-#define BASE_BINARY_LOOP_INP(tin, tout, op) \
- char *ip1 = args[0], *ip2 = args[1], *op1 = args[2];\
- npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- IVDEP_LOOP \
- for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) { \
- const tin in1 = *(tin *)ip1; \
- const tin in2 = *(tin *)ip2; \
- tout * out = (tout *)op1; \
- op; \
- }
-#define BASE_BINARY_LOOP_S(tin, tout, cin, cinp, vin, vinp, op) \
- const tin cin = *(tin *)cinp; \
- BINARY_LOOP { \
- const tin vin = *(tin *)vinp; \
- tout * out = (tout *)op1; \
- op; \
- }
-/* PR80198 again, scalar works without the pragma */
-#define BASE_BINARY_LOOP_S_INP(tin, tout, cin, cinp, vin, vinp, op) \
- const tin cin = *(tin *)cinp; \
- BINARY_LOOP { \
- const tin vin = *(tin *)vinp; \
- tout * out = (tout *)vinp; \
- op; \
- }
-#define BINARY_LOOP_FAST(tin, tout, op) \
- do { \
- /* condition allows compiler to optimize the generic macro */ \
- if (IS_BINARY_CONT(tin, tout)) { \
- if (abs_ptrdiff(args[2], args[0]) == 0 && \
- abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \
- BASE_BINARY_LOOP_INP(tin, tout, op) \
- } \
- else if (abs_ptrdiff(args[2], args[1]) == 0 && \
- abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \
- BASE_BINARY_LOOP_INP(tin, tout, op) \
- } \
- else { \
- BASE_BINARY_LOOP(tin, tout, op) \
- } \
- } \
- else if (IS_BINARY_CONT_S1(tin, tout)) { \
- if (abs_ptrdiff(args[2], args[1]) == 0) { \
- BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \
- } \
- else { \
- BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \
- } \
- } \
- else if (IS_BINARY_CONT_S2(tin, tout)) { \
- if (abs_ptrdiff(args[2], args[0]) == 0) { \
- BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \
- } \
- else { \
- BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \
- }\
- } \
- else { \
- BASE_BINARY_LOOP(tin, tout, op) \
- } \
- } \
- while (0)
-
-#define BINARY_REDUCE_LOOP_INNER\
- char *ip2 = args[1]; \
- npy_intp is2 = steps[1]; \
- npy_intp n = dimensions[0]; \
- npy_intp i; \
- for(i = 0; i < n; i++, ip2 += is2)
-
-#define BINARY_REDUCE_LOOP(TYPE)\
- char *iop1 = args[0]; \
- TYPE io1 = *(TYPE *)iop1; \
- BINARY_REDUCE_LOOP_INNER
-
-#define BINARY_LOOP_TWO_OUT\
- char *ip1 = args[0], *ip2 = args[1], *op1 = args[2], *op2 = args[3];\
- npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2], os2 = steps[3];\
- npy_intp n = dimensions[0];\
- npy_intp i;\
- for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1, op2 += os2)
/******************************************************************************
** GENERIC FLOAT LOOPS **
@@ -566,16 +375,36 @@ NPY_NO_EXPORT void
PyUFunc_O_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
{
char *meth = (char *)func;
+ PyObject *tup = PyTuple_New(0);
+ if (tup == NULL) {
+ return;
+ }
UNARY_LOOP {
PyObject *in1 = *(PyObject **)ip1;
PyObject **out = (PyObject **)op1;
- PyObject *ret = PyObject_CallMethod(in1 ? in1 : Py_None, meth, NULL);
+ PyObject *ret, *func;
+ func = PyObject_GetAttrString(in1 ? in1 : Py_None, meth);
+ if (func == NULL || !PyCallable_Check(func)) {
+ PyObject *exc, *val, *tb;
+ PyTypeObject *type = in1 ? Py_TYPE(in1) : Py_TYPE(Py_None);
+ PyErr_Fetch(&exc, &val, &tb);
+ PyErr_Format(PyExc_TypeError,
+ "loop of ufunc does not support argument %d of "
+ "type %s which has no callable %s method",
+ i, type->tp_name, meth);
+ npy_PyErr_ChainExceptionsCause(exc, val, tb);
+ Py_DECREF(tup);
+ return;
+ }
+ ret = PyObject_Call(func, tup, NULL);
if (ret == NULL) {
+ Py_DECREF(tup);
return;
}
Py_XDECREF(*out);
*out = ret;
}
+ Py_DECREF(tup);
}
/*UFUNC_API*/
@@ -596,6 +425,28 @@ PyUFunc_OO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
}
}
+NPY_NO_EXPORT void
+PyUFunc_OOO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+{
+ ternaryfunc f = (ternaryfunc)func;
+ TERNARY_LOOP {
+ PyObject *in1 = *(PyObject **)ip1;
+ PyObject *in2 = *(PyObject **)ip2;
+ PyObject *in3 = *(PyObject **)ip3;
+ PyObject **out = (PyObject **)op1;
+ PyObject *ret = f(
+ in1 ? in1 : Py_None,
+ in2 ? in2 : Py_None,
+ in3 ? in3 : Py_None
+ );
+ if (ret == NULL) {
+ return;
+ }
+ Py_XDECREF(*out);
+ *out = ret;
+ }
+}
+
/*UFUNC_API*/
NPY_NO_EXPORT void
PyUFunc_OO_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
@@ -815,6 +666,23 @@ BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN
}
+/**begin repeat
+ * #kind = isnan, isinf, isfinite#
+ * #func = npy_isnan, npy_isinf, npy_isfinite#
+ * #val = NPY_FALSE, NPY_FALSE, NPY_TRUE#
+ **/
+NPY_NO_EXPORT void
+BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+{
+ /*
+ * The (void)in; suppresses an unused variable warning raised by gcc and allows
+ * us to re-use this macro even though we do not depend on in
+ */
+ UNARY_LOOP_FAST(npy_bool, npy_bool, (void)in; *out = @val@);
+}
+
+/**end repeat**/
+
/*
*****************************************************************************
** INTEGER LOOPS
@@ -1046,6 +914,22 @@ NPY_NO_EXPORT void
}
}
+/**begin repeat1
+ * #kind = isnan, isinf, isfinite#
+ * #func = npy_isnan, npy_isinf, npy_isfinite#
+ * #val = NPY_FALSE, NPY_FALSE, NPY_TRUE#
+ **/
+NPY_NO_EXPORT void
+@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+{
+ /*
+ * The (void)in; suppresses an unused variable warning raised by gcc and allows
+ * us to re-use this macro even though we do not depend on in
+ */
+ UNARY_LOOP_FAST(@type@, npy_bool, (void)in; *out = @val@);
+}
+/**end repeat1**/
+
/**end repeat**/
/**begin repeat
@@ -1165,13 +1049,10 @@ NPY_NO_EXPORT void
* #c = u,u,u,ul,ull#
*/
-NPY_NO_EXPORT void
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
{
- UNARY_LOOP {
- const @type@ in1 = *(@type@ *)ip1;
- *((@type@ *)op1) = in1;
- }
+ UNARY_LOOP_FAST(@type@, @type@, *out = in);
}
NPY_NO_EXPORT NPY_GCC_OPT_3 void
@@ -1313,6 +1194,15 @@ NPY_NO_EXPORT void
}
NPY_NO_EXPORT void
+@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+{
+ UNARY_LOOP {
+ const @type@ in1 = *(@type@ *)ip1;
+ *((npy_bool *)op1) = (in1 != NPY_DATETIME_NAT);
+ }
+}
+
+NPY_NO_EXPORT void
@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
{
OUTPUT_LOOP {
@@ -1701,6 +1591,56 @@ NPY_NO_EXPORT void
/**end repeat**/
+/**begin repeat
+ * #func = exp, log#
+ * #scalarf = npy_expf, npy_logf#
+ */
+
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
+FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+{
+ UNARY_LOOP {
+ const npy_float in1 = *(npy_float *)ip1;
+ *(npy_float *)op1 = @scalarf@(in1);
+ }
+}
+
+/**end repeat**/
+
+/**begin repeat
+ * #isa = avx512f, avx2#
+ * #ISA = AVX512F, AVX2#
+ * #CHK = HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS, HAVE_ATTRIBUTE_TARGET_AVX2_WITH_INTRINSICS#
+ */
+
+/**begin repeat1
+ * #func = exp, log#
+ * #scalarf = npy_expf, npy_logf#
+ */
+
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
+FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+{
+ if (!run_unary_@isa@_@func@_FLOAT(args, dimensions, steps)) {
+ UNARY_LOOP {
+ /*
+ * We use the AVX function to compute exp/log for scalar elements as well.
+ * This is needed to ensure the output of strided and non-strided
+ * cases match. SIMD code handles strided input cases, but not
+ * strided output.
+ */
+#if defined @CHK@ && defined NPY_HAVE_SSE2_INTRINSICS
+ @ISA@_@func@_FLOAT((npy_float *)op1, (npy_float *)ip1, 1, steps[0]);
+#else
+ const npy_float in1 = *(npy_float *)ip1;
+ *(npy_float *)op1 = @scalarf@(in1);
+#endif
+ }
+ }
+}
+
+/**end repeat1**/
+/**end repeat**/
/**begin repeat
* Float types
@@ -2369,13 +2309,10 @@ HALF_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
}
}
-NPY_NO_EXPORT void
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
HALF_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
{
- UNARY_LOOP {
- const npy_half in1 = *(npy_half *)ip1;
- *((npy_half *)op1) = in1&0x7fffu;
- }
+ UNARY_LOOP_FAST(npy_half, npy_half, *out = in&0x7fffu);
}
NPY_NO_EXPORT void
diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src
index 5264a6533..7f05a693a 100644
--- a/numpy/core/src/umath/loops.h.src
+++ b/numpy/core/src/umath/loops.h.src
@@ -38,6 +38,13 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
NPY_NO_EXPORT void
BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+/**begin repeat
+ * #kind = isnan, isinf, isfinite#
+ **/
+NPY_NO_EXPORT void
+BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+/**end repeat**/
+
/*
*****************************************************************************
** INTEGER LOOPS
@@ -146,6 +153,13 @@ NPY_NO_EXPORT void
NPY_NO_EXPORT void
@S@@TYPE@_lcm(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+/**begin repeat2
+ * #kind = isnan, isinf, isfinite#
+ **/
+NPY_NO_EXPORT void
+@S@@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+/**end repeat2**/
+
/**end repeat1**/
/**end repeat**/
@@ -164,6 +178,22 @@ NPY_NO_EXPORT void
/**end repeat**/
/**begin repeat
+ * #func = exp, log#
+ */
+NPY_NO_EXPORT void
+FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+
+/**begin repeat1
+ * #isa = avx512f, avx2#
+ */
+
+NPY_NO_EXPORT void
+FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+
+/**end repeat1**/
+/**end repeat**/
+
+/**begin repeat
* Float types
* #TYPE = HALF, FLOAT, DOUBLE, LONGDOUBLE#
* #c = f, f, , l#
@@ -414,6 +444,9 @@ NPY_NO_EXPORT void
@TYPE@_isnat(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
NPY_NO_EXPORT void
+@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+
+NPY_NO_EXPORT void
@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
/**begin repeat1
@@ -516,6 +549,9 @@ OBJECT@suffix@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *
NPY_NO_EXPORT void
OBJECT_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+NPY_NO_EXPORT void
+PyUFunc_OOO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func);
+
/*
*****************************************************************************
** END LOOPS **
diff --git a/numpy/core/src/umath/matmul.c.src b/numpy/core/src/umath/matmul.c.src
index bc00d3562..480c0c72f 100644
--- a/numpy/core/src/umath/matmul.c.src
+++ b/numpy/core/src/umath/matmul.c.src
@@ -196,14 +196,16 @@ NPY_NO_EXPORT void
* FLOAT, DOUBLE, HALF,
* CFLOAT, CDOUBLE, CLONGDOUBLE,
* UBYTE, USHORT, UINT, ULONG, ULONGLONG,
- * BYTE, SHORT, INT, LONG, LONGLONG#
+ * BYTE, SHORT, INT, LONG, LONGLONG,
+ * BOOL#
* #typ = npy_longdouble,
* npy_float,npy_double,npy_half,
* npy_cfloat, npy_cdouble, npy_clongdouble,
* npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong,
- * npy_byte, npy_short, npy_int, npy_long, npy_longlong#
- * #IS_COMPLEX = 0, 0, 0, 0, 1, 1, 1, 0*10#
- * #IS_HALF = 0, 0, 0, 1, 0*13#
+ * npy_byte, npy_short, npy_int, npy_long, npy_longlong,
+ * npy_bool#
+ * #IS_COMPLEX = 0, 0, 0, 0, 1, 1, 1, 0*11#
+ * #IS_HALF = 0, 0, 0, 1, 0*14#
*/
NPY_NO_EXPORT void
@@ -211,6 +213,7 @@ NPY_NO_EXPORT void
void *_ip2, npy_intp is2_n, npy_intp is2_p,
void *_op, npy_intp os_m, npy_intp os_p,
npy_intp dm, npy_intp dn, npy_intp dp)
+
{
npy_intp m, n, p;
npy_intp ib1_n, ib2_n, ib2_p, ob_p;
@@ -263,49 +266,13 @@ NPY_NO_EXPORT void
}
/**end repeat**/
-NPY_NO_EXPORT void
-BOOL_matmul_inner_noblas(void *_ip1, npy_intp is1_m, npy_intp is1_n,
- void *_ip2, npy_intp is2_n, npy_intp is2_p,
- void *_op, npy_intp os_m, npy_intp os_p,
- npy_intp dm, npy_intp dn, npy_intp dp)
-{
- npy_intp m, n, p;
- npy_intp ib2_p, ob_p;
- char *ip1 = (char *)_ip1, *ip2 = (char *)_ip2, *op = (char *)_op;
-
- ib2_p = is2_p * dp;
- ob_p = os_p * dp;
- for (m = 0; m < dm; m++) {
- for (p = 0; p < dp; p++) {
- char *ip1tmp = ip1;
- char *ip2tmp = ip2;
- *(npy_bool *)op = NPY_FALSE;
- for (n = 0; n < dn; n++) {
- npy_bool val1 = (*(npy_bool *)ip1tmp);
- npy_bool val2 = (*(npy_bool *)ip2tmp);
- if (val1 != 0 && val2 != 0) {
- *(npy_bool *)op = NPY_TRUE;
- break;
- }
- ip2tmp += is2_n;
- ip1tmp += is1_n;
- }
- op += os_p;
- ip2 += is2_p;
- }
- op -= ob_p;
- ip2 -= ib2_p;
- ip1 += is1_m;
- op += os_m;
- }
-}
NPY_NO_EXPORT void
OBJECT_matmul_inner_noblas(void *_ip1, npy_intp is1_m, npy_intp is1_n,
void *_ip2, npy_intp is2_n, npy_intp is2_p,
void *_op, npy_intp os_m, npy_intp os_p,
- npy_intp dm, npy_intp dn, npy_intp dp)
+ npy_intp dm, npy_intp dn, npy_intp dp)
{
char *ip1 = (char *)_ip1, *ip2 = (char *)_ip2, *op = (char *)_op;
@@ -313,12 +280,11 @@ OBJECT_matmul_inner_noblas(void *_ip1, npy_intp is1_m, npy_intp is1_n,
npy_intp ib2_n = is2_n * dn;
npy_intp ib2_p = is2_p * dp;
npy_intp ob_p = os_p * dp;
- npy_intp m, p, n;
PyObject *product, *sum_of_products = NULL;
- for (m = 0; m < dm; m++) {
- for (p = 0; p < dp; p++) {
+ for (npy_intp m = 0; m < dm; m++) {
+ for (npy_intp p = 0; p < dp; p++) {
if ( 0 == dn ) {
sum_of_products = PyLong_FromLong(0);
if (sum_of_products == NULL) {
@@ -326,7 +292,7 @@ OBJECT_matmul_inner_noblas(void *_ip1, npy_intp is1_m, npy_intp is1_n,
}
}
- for (n = 0; n < dn; n++) {
+ for (npy_intp n = 0; n < dn; n++) {
PyObject *obj1 = *(PyObject**)ip1, *obj2 = *(PyObject**)ip2;
if (obj1 == NULL) {
obj1 = Py_None;
diff --git a/numpy/core/src/umath/override.c b/numpy/core/src/umath/override.c
index 2ea23311b..8d67f96ac 100644
--- a/numpy/core/src/umath/override.c
+++ b/numpy/core/src/umath/override.c
@@ -226,14 +226,14 @@ normalize_reduce_args(PyUFuncObject *ufunc, PyObject *args,
PyObject *obj;
static PyObject *NoValue = NULL;
static char *kwlist[] = {"array", "axis", "dtype", "out", "keepdims",
- "initial"};
+ "initial", "where"};
npy_cache_import("numpy", "_NoValue", &NoValue);
if (NoValue == NULL) return -1;
- if (nargs < 1 || nargs > 6) {
+ if (nargs < 1 || nargs > 7) {
PyErr_Format(PyExc_TypeError,
- "ufunc.reduce() takes from 1 to 6 positional "
+ "ufunc.reduce() takes from 1 to 7 positional "
"arguments but %"NPY_INTP_FMT" were given", nargs);
return -1;
}
diff --git a/numpy/core/src/umath/reduction.c b/numpy/core/src/umath/reduction.c
index 654893511..fda2a12f6 100644
--- a/numpy/core/src/umath/reduction.c
+++ b/numpy/core/src/umath/reduction.c
@@ -447,9 +447,9 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
/* Iterator parameters */
NpyIter *iter = NULL;
- PyArrayObject *op[2];
- PyArray_Descr *op_dtypes[2];
- npy_uint32 flags, op_flags[2];
+ PyArrayObject *op[3];
+ PyArray_Descr *op_dtypes[3];
+ npy_uint32 flags, op_flags[3];
/* More than one axis means multiple orders are possible */
if (!reorderable && count_axes(PyArray_NDIM(operand), axis_flags) > 1) {
@@ -459,13 +459,12 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
funcname);
return NULL;
}
-
-
- /* Validate that the parameters for future expansion are NULL */
- if (wheremask != NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "Reduce operations in NumPy do not yet support "
- "a where mask");
+ /* Can only use where with an initial ( from identity or argument) */
+ if (wheremask != NULL && identity == Py_None) {
+ PyErr_Format(PyExc_ValueError,
+ "reduction operation '%s' does not have an identity, "
+ "so to use a where mask one has to specify 'initial'",
+ funcname);
return NULL;
}
@@ -527,8 +526,16 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
NPY_ITER_NO_SUBTYPE;
op_flags[1] = NPY_ITER_READONLY |
NPY_ITER_ALIGNED;
+ if (wheremask != NULL) {
+ op[2] = wheremask;
+ op_dtypes[2] = PyArray_DescrFromType(NPY_BOOL);
+ if (op_dtypes[2] == NULL) {
+ goto fail;
+ }
+ op_flags[2] = NPY_ITER_READONLY;
+ }
- iter = NpyIter_AdvancedNew(2, op, flags,
+ iter = NpyIter_AdvancedNew(wheremask == NULL ? 2 : 3, op, flags,
NPY_KEEPORDER, casting,
op_flags,
op_dtypes,
@@ -571,7 +578,7 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
goto fail;
}
}
-
+
/* Check whether any errors occurred during the loop */
if (PyErr_Occurred() ||
_check_ufunc_fperr(errormask, NULL, "reduce") < 0) {
diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src
index 4bb8569be..6b07a9d88 100644
--- a/numpy/core/src/umath/simd.inc.src
+++ b/numpy/core/src/umath/simd.inc.src
@@ -40,7 +40,6 @@ abs_ptrdiff(char *a, char *b)
return (a > b) ? (a - b) : (b - a);
}
-
/*
* stride is equal to element size and input and destination are equal or
* don't overlap within one register. The check of the steps against
@@ -52,6 +51,15 @@ abs_ptrdiff(char *a, char *b)
((abs_ptrdiff(args[1], args[0]) >= (vsize)) || \
((abs_ptrdiff(args[1], args[0]) == 0))))
+/*
+ * output should be contiguous, can handle strided input data
+ */
+#define IS_OUTPUT_BLOCKABLE_UNARY(esize, vsize) \
+ (steps[1] == (esize) && \
+ (npy_is_aligned(args[0], esize) && npy_is_aligned(args[1], esize)) && \
+ ((abs_ptrdiff(args[1], args[0]) >= (vsize)) || \
+ ((abs_ptrdiff(args[1], args[0]) == 0))))
+
#define IS_BLOCKABLE_REDUCE(esize, vsize) \
(steps[1] == (esize) && abs_ptrdiff(args[1], args[0]) >= (vsize) && \
npy_is_aligned(args[1], (esize)) && \
@@ -122,6 +130,43 @@ abs_ptrdiff(char *a, char *b)
*/
/**begin repeat
+ * #ISA = AVX2, AVX512F#
+ * #isa = avx2, avx512f#
+ * #REGISTER_SIZE = 32, 64#
+ */
+
+/* prototypes */
+
+/**begin repeat1
+ * #func = exp, log#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_@ISA@_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_INLINE void
+@ISA@_@func@_FLOAT(npy_float *, npy_float *, const npy_intp n, const npy_intp stride);
+#endif
+
+static NPY_INLINE int
+run_unary_@isa@_@func@_FLOAT(char **args, npy_intp *dimensions, npy_intp *steps)
+{
+#if defined HAVE_ATTRIBUTE_TARGET_@ISA@_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+ if (IS_OUTPUT_BLOCKABLE_UNARY(sizeof(npy_float), @REGISTER_SIZE@)) {
+ @ISA@_@func@_FLOAT((npy_float*)args[1], (npy_float*)args[0], dimensions[0], steps[0]);
+ return 1;
+ }
+ else
+ return 0;
+#endif
+ return 0;
+}
+
+/**end repeat1**/
+
+/**end repeat**/
+
+
+
+/**begin repeat
* Float types
* #type = npy_float, npy_double, npy_longdouble#
* #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
@@ -1075,6 +1120,515 @@ sse2_@kind@_@TYPE@(@type@ * ip, @type@ * op, const npy_intp n)
/**end repeat**/
+/* bunch of helper functions used in ISA_exp/log_FLOAT*/
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX2_WITH_INTRINSICS
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_fmadd(__m256 a, __m256 b, __m256 c)
+{
+ return _mm256_add_ps(_mm256_mul_ps(a, b), c);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_get_full_load_mask(void)
+{
+ return _mm256_set1_ps(-1.0);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_get_partial_load_mask(const npy_int num_lanes, const npy_int total_elem)
+{
+ float maskint[16] = {-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,
+ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+ float* addr = maskint + total_elem - num_lanes;
+ return _mm256_loadu_ps(addr);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_masked_gather(__m256 src,
+ npy_float* addr,
+ __m256i vindex,
+ __m256 mask)
+{
+ return _mm256_mask_i32gather_ps(src, addr, vindex, mask, 4);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_masked_load(__m256 mask, npy_float* addr)
+{
+ return _mm256_maskload_ps(addr, _mm256_cvtps_epi32(mask));
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_set_masked_lanes(__m256 x, __m256 val, __m256 mask)
+{
+ return _mm256_blendv_ps(x, val, mask);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_blend(__m256 x, __m256 y, __m256 ymask)
+{
+ return _mm256_blendv_ps(x, y, ymask);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_get_exponent(__m256 x)
+{
+ /*
+ * Special handling of denormals:
+ * 1) Multiply denormal elements with 2**100 (0x71800000)
+ * 2) Get the 8 bits of unbiased exponent
+ * 3) Subtract 100 from exponent of denormals
+ */
+
+ __m256 two_power_100 = _mm256_castsi256_ps(_mm256_set1_epi32(0x71800000));
+ __m256 denormal_mask = _mm256_cmp_ps(x, _mm256_set1_ps(FLT_MIN), _CMP_LT_OQ);
+ __m256 normal_mask = _mm256_cmp_ps(x, _mm256_set1_ps(FLT_MIN), _CMP_GE_OQ);
+
+ __m256 temp1 = _mm256_blendv_ps(x, _mm256_set1_ps(0.0f), normal_mask);
+ __m256 temp = _mm256_mul_ps(temp1, two_power_100);
+ x = _mm256_blendv_ps(x, temp, denormal_mask);
+
+ __m256 exp = _mm256_cvtepi32_ps(
+ _mm256_sub_epi32(
+ _mm256_srli_epi32(
+ _mm256_castps_si256(x), 23),_mm256_set1_epi32(0x7E)));
+
+ __m256 denorm_exp = _mm256_sub_ps(exp, _mm256_set1_ps(100.0f));
+ return _mm256_blendv_ps(exp, denorm_exp, denormal_mask);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_get_mantissa(__m256 x)
+{
+ /*
+ * Special handling of denormals:
+ * 1) Multiply denormal elements with 2**100 (0x71800000)
+ * 2) Get the 23 bits of mantissa
+ * 3) Mantissa for denormals is not affected by the multiplication
+ */
+
+ __m256 two_power_100 = _mm256_castsi256_ps(_mm256_set1_epi32(0x71800000));
+ __m256 denormal_mask = _mm256_cmp_ps(x, _mm256_set1_ps(FLT_MIN), _CMP_LT_OQ);
+ __m256 normal_mask = _mm256_cmp_ps(x, _mm256_set1_ps(FLT_MIN), _CMP_GE_OQ);
+
+ __m256 temp1 = _mm256_blendv_ps(x, _mm256_set1_ps(0.0f), normal_mask);
+ __m256 temp = _mm256_mul_ps(temp1, two_power_100);
+ x = _mm256_blendv_ps(x, temp, denormal_mask);
+
+ __m256i mantissa_bits = _mm256_set1_epi32(0x7fffff);
+ __m256i exp_126_bits = _mm256_set1_epi32(126 << 23);
+ return _mm256_castsi256_ps(
+ _mm256_or_si256(
+ _mm256_and_si256(
+ _mm256_castps_si256(x), mantissa_bits), exp_126_bits));
+}
+
+NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX2 __m256
+avx2_scalef_ps(__m256 poly, __m256 quadrant)
+{
+ /*
+ * Handle denormals (which occur when quadrant <= -125):
+ * 1) This function computes poly*(2^quad) by adding the exponent of
+ poly to quad
+ * 2) When quad <= -125, the output is a denormal and the above logic
+ breaks down
+ * 3) To handle such cases, we split quadrant: -125 + (quadrant + 125)
+ * 4) poly*(2^-125) is computed the usual way
+ * 5) 2^(quad-125) can be computed by: 2 << abs(quad-125)
+ * 6) The final div operation generates the denormal
+ */
+ __m256 minquadrant = _mm256_set1_ps(-125.0f);
+ __m256 denormal_mask = _mm256_cmp_ps(quadrant, minquadrant, _CMP_LE_OQ);
+ if (_mm256_movemask_ps(denormal_mask) != 0x0000) {
+ __m256 quad_diff = _mm256_sub_ps(quadrant, minquadrant);
+ quad_diff = _mm256_sub_ps(_mm256_setzero_ps(), quad_diff);
+ quad_diff = _mm256_blendv_ps(_mm256_setzero_ps(), quad_diff, denormal_mask);
+ __m256i two_power_diff = _mm256_sllv_epi32(
+ _mm256_set1_epi32(1), _mm256_cvtps_epi32(quad_diff));
+ quadrant = _mm256_max_ps(quadrant, minquadrant); //keep quadrant >= -126
+ __m256i exponent = _mm256_slli_epi32(_mm256_cvtps_epi32(quadrant), 23);
+ poly = _mm256_castsi256_ps(
+ _mm256_add_epi32(
+ _mm256_castps_si256(poly), exponent));
+ __m256 denorm_poly = _mm256_div_ps(poly, _mm256_cvtepi32_ps(two_power_diff));
+ return _mm256_blendv_ps(poly, denorm_poly, denormal_mask);
+ }
+ else {
+ __m256i exponent = _mm256_slli_epi32(_mm256_cvtps_epi32(quadrant), 23);
+ poly = _mm256_castsi256_ps(
+ _mm256_add_epi32(
+ _mm256_castps_si256(poly), exponent));
+ return poly;
+ }
+}
+
+#endif
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __mmask16
+avx512_get_full_load_mask(void)
+{
+ return 0xFFFF;
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __mmask16
+avx512_get_partial_load_mask(const npy_int num_elem, const npy_int total_elem)
+{
+ return (0x0001 << num_elem) - 0x0001;
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_masked_gather(__m512 src,
+ npy_float* addr,
+ __m512i vindex,
+ __mmask16 kmask)
+{
+ return _mm512_mask_i32gather_ps(src, kmask, vindex, addr, 4);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_masked_load(__mmask16 mask, npy_float* addr)
+{
+ return _mm512_maskz_loadu_ps(mask, (__m512 *)addr);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_set_masked_lanes(__m512 x, __m512 val, __mmask16 mask)
+{
+ return _mm512_mask_blend_ps(mask, x, val);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_blend(__m512 x, __m512 y, __mmask16 ymask)
+{
+ return _mm512_mask_mov_ps(x, ymask, y);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_get_exponent(__m512 x)
+{
+ return _mm512_add_ps(_mm512_getexp_ps(x), _mm512_set1_ps(1.0f));
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_get_mantissa(__m512 x)
+{
+ return _mm512_getmant_ps(x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512
+avx512_scalef_ps(__m512 poly, __m512 quadrant)
+{
+ return _mm512_scalef_ps(poly, quadrant);
+}
+#endif
+
+/**begin repeat
+ * #ISA = AVX2, AVX512F#
+ * #isa = avx2, avx512#
+ * #vtype = __m256, __m512#
+ * #vsize = 256, 512#
+ * #or = or_ps, kor#
+ * #vsub = , _mask#
+ * #mask = __m256, __mmask16#
+ * #fmadd = avx2_fmadd,_mm512_fmadd_ps#
+ **/
+
+#if defined HAVE_ATTRIBUTE_TARGET_@ISA@_WITH_INTRINSICS
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ @vtype@
+@isa@_range_reduction(@vtype@ x, @vtype@ y, @vtype@ c1, @vtype@ c2, @vtype@ c3)
+{
+ @vtype@ reduced_x = @fmadd@(y, c1, x);
+ reduced_x = @fmadd@(y, c2, reduced_x);
+ reduced_x = @fmadd@(y, c3, reduced_x);
+ return reduced_x;
+}
+#endif
+/**end repeat**/
+
+/**begin repeat
+ * #ISA = AVX2, AVX512F#
+ * #isa = avx2, avx512#
+ * #vtype = __m256, __m512#
+ * #vsize = 256, 512#
+ * #BYTES = 32, 64#
+ * #mask = __m256, __mmask16#
+ * #vsub = , _mask#
+ * #or_masks =_mm256_or_ps, _mm512_kor#
+ * #and_masks =_mm256_and_ps, _mm512_kand#
+ * #xor_masks =_mm256_xor_ps, _mm512_kxor#
+ * #fmadd = avx2_fmadd,_mm512_fmadd_ps#
+ * #mask_to_int = _mm256_movemask_ps, #
+ * #full_mask= 0xFF, 0xFFFF#
+ * #masked_store = _mm256_maskstore_ps, _mm512_mask_storeu_ps#
+ * #cvtps_epi32 = _mm256_cvtps_epi32, #
+ */
+
+
+/*
+ * Vectorized implementation of exp using AVX2 and AVX512:
+ * 1) if x >= xmax; return INF (overflow)
+ * 2) if x <= xmin; return 0.0f (underflow)
+ * 3) Range reduction (using Coyd-Waite):
+ * a) y = x - k*ln(2); k = rint(x/ln(2)); y \in [0, ln(2)]
+ * 4) Compute exp(y) = P/Q, ratio of 2 polynomials P and Q
+ * b) P = 5th order and Q = 2nd order polynomials obtained from Remez's
+ * algorithm (mini-max polynomial approximation)
+ * 5) Compute exp(x) = exp(y) * 2^k
+ * 6) Max ULP error measured across all 32-bit FP's = 2.52 (x = 0xc2781e37)
+ * 7) Max relative error measured across all 32-bit FP's= 2.1264E-07 (for the
+ * same x = 0xc2781e37)
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_@ISA@_WITH_INTRINSICS
+static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
+@ISA@_exp_FLOAT(npy_float * op,
+ npy_float * ip,
+ const npy_intp array_size,
+ const npy_intp steps)
+{
+ const npy_intp stride = steps/sizeof(npy_float);
+ const npy_int num_lanes = @BYTES@/sizeof(npy_float);
+ npy_float xmax = 88.72283935546875f;
+ npy_float xmin = -103.97208404541015625f;
+ npy_int indexarr[16];
+ for (npy_int ii = 0; ii < 16; ii++) {
+ indexarr[ii] = ii*stride;
+ }
+
+ /* Load up frequently used constants */
+ @vtype@ codyw_c1 = _mm@vsize@_set1_ps(NPY_CODY_WAITE_LOGE_2_HIGHf);
+ @vtype@ codyw_c2 = _mm@vsize@_set1_ps(NPY_CODY_WAITE_LOGE_2_LOWf);
+ @vtype@ exp_p0 = _mm@vsize@_set1_ps(NPY_COEFF_P0_EXPf);
+ @vtype@ exp_p1 = _mm@vsize@_set1_ps(NPY_COEFF_P1_EXPf);
+ @vtype@ exp_p2 = _mm@vsize@_set1_ps(NPY_COEFF_P2_EXPf);
+ @vtype@ exp_p3 = _mm@vsize@_set1_ps(NPY_COEFF_P3_EXPf);
+ @vtype@ exp_p4 = _mm@vsize@_set1_ps(NPY_COEFF_P4_EXPf);
+ @vtype@ exp_p5 = _mm@vsize@_set1_ps(NPY_COEFF_P5_EXPf);
+ @vtype@ exp_q0 = _mm@vsize@_set1_ps(NPY_COEFF_Q0_EXPf);
+ @vtype@ exp_q1 = _mm@vsize@_set1_ps(NPY_COEFF_Q1_EXPf);
+ @vtype@ exp_q2 = _mm@vsize@_set1_ps(NPY_COEFF_Q2_EXPf);
+ @vtype@ cvt_magic = _mm@vsize@_set1_ps(NPY_RINT_CVT_MAGICf);
+ @vtype@ log2e = _mm@vsize@_set1_ps(NPY_LOG2Ef);
+ @vtype@ inf = _mm@vsize@_set1_ps(NPY_INFINITYF);
+ @vtype@ zeros_f = _mm@vsize@_set1_ps(0.0f);
+ @vtype@ poly, num_poly, denom_poly, quadrant;
+ @vtype@i vindex = _mm@vsize@_loadu_si@vsize@((@vtype@i*)&indexarr[0]);
+
+ @mask@ xmax_mask, xmin_mask, nan_mask, inf_mask;
+ @mask@ overflow_mask = @isa@_get_partial_load_mask(0, num_lanes);
+ @mask@ load_mask = @isa@_get_full_load_mask();
+ npy_intp num_remaining_elements = array_size;
+
+ while (num_remaining_elements > 0) {
+
+ if (num_remaining_elements < num_lanes) {
+ load_mask = @isa@_get_partial_load_mask(num_remaining_elements,
+ num_lanes);
+ }
+
+ @vtype@ x;
+ if (stride == 1) {
+ x = @isa@_masked_load(load_mask, ip);
+ }
+ else {
+ x = @isa@_masked_gather(zeros_f, ip, vindex, load_mask);
+ }
+
+ nan_mask = _mm@vsize@_cmp_ps@vsub@(x, x, _CMP_NEQ_UQ);
+ x = @isa@_set_masked_lanes(x, zeros_f, nan_mask);
+
+ xmax_mask = _mm@vsize@_cmp_ps@vsub@(x, _mm@vsize@_set1_ps(xmax), _CMP_GE_OQ);
+ xmin_mask = _mm@vsize@_cmp_ps@vsub@(x, _mm@vsize@_set1_ps(xmin), _CMP_LE_OQ);
+ inf_mask = _mm@vsize@_cmp_ps@vsub@(x, inf, _CMP_EQ_OQ);
+ overflow_mask = @or_masks@(overflow_mask,
+ @xor_masks@(xmax_mask, inf_mask));
+
+ x = @isa@_set_masked_lanes(x, zeros_f, @or_masks@(
+ @or_masks@(nan_mask, xmin_mask), xmax_mask));
+
+ quadrant = _mm@vsize@_mul_ps(x, log2e);
+
+ /* round to nearest */
+ quadrant = _mm@vsize@_add_ps(quadrant, cvt_magic);
+ quadrant = _mm@vsize@_sub_ps(quadrant, cvt_magic);
+
+ /* Cody-Waite's range reduction algorithm */
+ x = @isa@_range_reduction(x, quadrant, codyw_c1, codyw_c2, zeros_f);
+
+ num_poly = @fmadd@(exp_p5, x, exp_p4);
+ num_poly = @fmadd@(num_poly, x, exp_p3);
+ num_poly = @fmadd@(num_poly, x, exp_p2);
+ num_poly = @fmadd@(num_poly, x, exp_p1);
+ num_poly = @fmadd@(num_poly, x, exp_p0);
+ denom_poly = @fmadd@(exp_q2, x, exp_q1);
+ denom_poly = @fmadd@(denom_poly, x, exp_q0);
+ poly = _mm@vsize@_div_ps(num_poly, denom_poly);
+
+ /*
+ * compute val = poly * 2^quadrant; which is same as adding the
+ * exponent of quadrant to the exponent of poly. quadrant is an int,
+ * so extracting exponent is simply extracting 8 bits.
+ */
+ poly = @isa@_scalef_ps(poly, quadrant);
+
+ /*
+ * elem > xmax; return inf
+ * elem < xmin; return 0.0f
+ * elem = +/- nan, return nan
+ */
+ poly = @isa@_set_masked_lanes(poly, _mm@vsize@_set1_ps(NPY_NANF), nan_mask);
+ poly = @isa@_set_masked_lanes(poly, inf, xmax_mask);
+ poly = @isa@_set_masked_lanes(poly, zeros_f, xmin_mask);
+
+ @masked_store@(op, @cvtps_epi32@(load_mask), poly);
+
+ ip += num_lanes*stride;
+ op += num_lanes;
+ num_remaining_elements -= num_lanes;
+ }
+
+ if (@mask_to_int@(overflow_mask)) {
+ npy_set_floatstatus_overflow();
+ }
+}
+
+/*
+ * Vectorized implementation of log using AVX2 and AVX512
+ * 1) if x < 0.0f; return -NAN (invalid input)
+ * 2) Range reduction: y = x/2^k;
+ * a) y = normalized mantissa, k is the exponent (0.5 <= y < 1)
+ * 3) Compute log(y) = P/Q, ratio of 2 polynomials P and Q
+ * b) P = 5th order and Q = 5th order polynomials obtained from Remez's
+ * algorithm (mini-max polynomial approximation)
+ * 5) Compute log(x) = log(y) + k*ln(2)
+ * 6) Max ULP error measured across all 32-bit FP's = 3.83 (x = 0x3f486945)
+ * 7) Max relative error measured across all 32-bit FP's = 2.359E-07 (for same
+ * x = 0x3f486945)
+ */
+
+static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
+@ISA@_log_FLOAT(npy_float * op,
+ npy_float * ip,
+ const npy_intp array_size,
+ const npy_intp steps)
+{
+ const npy_intp stride = steps/sizeof(npy_float);
+ const npy_int num_lanes = @BYTES@/sizeof(npy_float);
+ npy_int indexarr[16];
+ for (npy_int ii = 0; ii < 16; ii++) {
+ indexarr[ii] = ii*stride;
+ }
+
+ /* Load up frequently used constants */
+ @vtype@ log_p0 = _mm@vsize@_set1_ps(NPY_COEFF_P0_LOGf);
+ @vtype@ log_p1 = _mm@vsize@_set1_ps(NPY_COEFF_P1_LOGf);
+ @vtype@ log_p2 = _mm@vsize@_set1_ps(NPY_COEFF_P2_LOGf);
+ @vtype@ log_p3 = _mm@vsize@_set1_ps(NPY_COEFF_P3_LOGf);
+ @vtype@ log_p4 = _mm@vsize@_set1_ps(NPY_COEFF_P4_LOGf);
+ @vtype@ log_p5 = _mm@vsize@_set1_ps(NPY_COEFF_P5_LOGf);
+ @vtype@ log_q0 = _mm@vsize@_set1_ps(NPY_COEFF_Q0_LOGf);
+ @vtype@ log_q1 = _mm@vsize@_set1_ps(NPY_COEFF_Q1_LOGf);
+ @vtype@ log_q2 = _mm@vsize@_set1_ps(NPY_COEFF_Q2_LOGf);
+ @vtype@ log_q3 = _mm@vsize@_set1_ps(NPY_COEFF_Q3_LOGf);
+ @vtype@ log_q4 = _mm@vsize@_set1_ps(NPY_COEFF_Q4_LOGf);
+ @vtype@ log_q5 = _mm@vsize@_set1_ps(NPY_COEFF_Q5_LOGf);
+ @vtype@ loge2 = _mm@vsize@_set1_ps(NPY_LOGE2f);
+ @vtype@ nan = _mm@vsize@_set1_ps(NPY_NANF);
+ @vtype@ neg_nan = _mm@vsize@_set1_ps(-NPY_NANF);
+ @vtype@ neg_inf = _mm@vsize@_set1_ps(-NPY_INFINITYF);
+ @vtype@ inf = _mm@vsize@_set1_ps(NPY_INFINITYF);
+ @vtype@ zeros_f = _mm@vsize@_set1_ps(0.0f);
+ @vtype@ ones_f = _mm@vsize@_set1_ps(1.0f);
+ @vtype@i vindex = _mm@vsize@_loadu_si@vsize@((@vtype@i*)indexarr);
+ @vtype@ poly, num_poly, denom_poly, exponent;
+
+ @mask@ inf_mask, nan_mask, sqrt2_mask, zero_mask, negx_mask;
+ @mask@ invalid_mask = @isa@_get_partial_load_mask(0, num_lanes);
+ @mask@ divide_by_zero_mask = invalid_mask;
+ @mask@ load_mask = @isa@_get_full_load_mask();
+ npy_intp num_remaining_elements = array_size;
+
+ while (num_remaining_elements > 0) {
+
+ if (num_remaining_elements < num_lanes) {
+ load_mask = @isa@_get_partial_load_mask(num_remaining_elements,
+ num_lanes);
+ }
+
+ @vtype@ x_in;
+ if (stride == 1) {
+ x_in = @isa@_masked_load(load_mask, ip);
+ }
+ else {
+ x_in = @isa@_masked_gather(zeros_f, ip, vindex, load_mask);
+ }
+
+ negx_mask = _mm@vsize@_cmp_ps@vsub@(x_in, zeros_f, _CMP_LT_OQ);
+ zero_mask = _mm@vsize@_cmp_ps@vsub@(x_in, zeros_f, _CMP_EQ_OQ);
+ inf_mask = _mm@vsize@_cmp_ps@vsub@(x_in, inf, _CMP_EQ_OQ);
+ nan_mask = _mm@vsize@_cmp_ps@vsub@(x_in, x_in, _CMP_NEQ_UQ);
+ divide_by_zero_mask = @or_masks@(divide_by_zero_mask,
+ @and_masks@(zero_mask, load_mask));
+ invalid_mask = @or_masks@(invalid_mask, negx_mask);
+
+ @vtype@ x = @isa@_set_masked_lanes(x_in, zeros_f, negx_mask);
+
+ /* set x = normalized mantissa */
+ exponent = @isa@_get_exponent(x);
+ x = @isa@_get_mantissa(x);
+
+ /* if x < sqrt(2) {exp = exp-1; x = 2*x} */
+ sqrt2_mask = _mm@vsize@_cmp_ps@vsub@(x, _mm@vsize@_set1_ps(NPY_SQRT1_2f), _CMP_LE_OQ);
+ x = @isa@_blend(x, _mm@vsize@_add_ps(x,x), sqrt2_mask);
+ exponent = @isa@_blend(exponent,
+ _mm@vsize@_sub_ps(exponent,ones_f), sqrt2_mask);
+
+ /* x = x - 1 */
+ x = _mm@vsize@_sub_ps(x, ones_f);
+
+ /* Polynomial approximation for log(1+x) */
+ num_poly = @fmadd@(log_p5, x, log_p4);
+ num_poly = @fmadd@(num_poly, x, log_p3);
+ num_poly = @fmadd@(num_poly, x, log_p2);
+ num_poly = @fmadd@(num_poly, x, log_p1);
+ num_poly = @fmadd@(num_poly, x, log_p0);
+ denom_poly = @fmadd@(log_q5, x, log_q4);
+ denom_poly = @fmadd@(denom_poly, x, log_q3);
+ denom_poly = @fmadd@(denom_poly, x, log_q2);
+ denom_poly = @fmadd@(denom_poly, x, log_q1);
+ denom_poly = @fmadd@(denom_poly, x, log_q0);
+ poly = _mm@vsize@_div_ps(num_poly, denom_poly);
+ poly = @fmadd@(exponent, loge2, poly);
+
+ /*
+ * x < 0.0f; return -NAN
+ * x = +/- NAN; return NAN
+ * x = 0.0f; return -INF
+ */
+ poly = @isa@_set_masked_lanes(poly, nan, nan_mask);
+ poly = @isa@_set_masked_lanes(poly, neg_nan, negx_mask);
+ poly = @isa@_set_masked_lanes(poly, neg_inf, zero_mask);
+ poly = @isa@_set_masked_lanes(poly, inf, inf_mask);
+
+ @masked_store@(op, @cvtps_epi32@(load_mask), poly);
+
+ ip += num_lanes*stride;
+ op += num_lanes;
+ num_remaining_elements -= num_lanes;
+ }
+
+ if (@mask_to_int@(invalid_mask)) {
+ npy_set_floatstatus_invalid();
+ }
+ if (@mask_to_int@(divide_by_zero_mask)) {
+ npy_set_floatstatus_divbyzero();
+ }
+}
+#endif
+/**end repeat**/
+
/*
*****************************************************************************
** BOOL LOOPS
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index d1b029c18..cb24f2a70 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -563,14 +563,14 @@ _get_size(const char* str)
if (stop == str || _is_alpha_underscore(*stop)) {
/* not a well formed number */
- return -1;
+ return -1;
}
if (size >= NPY_MAX_INTP || size <= NPY_MIN_INTP) {
/* len(str) too long */
return -1;
}
return size;
- }
+}
/*
* Return the ending position of a variable name including optional modifier
@@ -654,8 +654,8 @@ _parse_signature(PyUFuncObject *ufunc, const char *signature)
PyErr_NoMemory();
goto fail;
}
- for (i = 0; i < len; i++) {
- ufunc->core_dim_flags[i] = 0;
+ for (size_t j = 0; j < len; j++) {
+ ufunc->core_dim_flags[j] = 0;
}
i = _next_non_white_space(signature, 0);
@@ -3468,12 +3468,15 @@ reduce_loop(NpyIter *iter, char **dataptrs, npy_intp *strides,
PyUFuncObject *ufunc = (PyUFuncObject *)data;
char *dataptrs_copy[3];
npy_intp strides_copy[3];
+ npy_bool masked;
/* The normal selected inner loop */
PyUFuncGenericFunction innerloop = NULL;
void *innerloopdata = NULL;
NPY_BEGIN_THREADS_DEF;
+ /* Get the number of operands, to determine whether "where" is used */
+ masked = (NpyIter_GetNOp(iter) == 3);
/* Get the inner loop */
iter_dtypes = NpyIter_GetDescrArray(iter);
@@ -3533,8 +3536,36 @@ reduce_loop(NpyIter *iter, char **dataptrs, npy_intp *strides,
strides_copy[0] = strides[0];
strides_copy[1] = strides[1];
strides_copy[2] = strides[0];
- innerloop(dataptrs_copy, countptr,
- strides_copy, innerloopdata);
+
+ if (!masked) {
+ innerloop(dataptrs_copy, countptr,
+ strides_copy, innerloopdata);
+ }
+ else {
+ npy_intp count = *countptr;
+ char *maskptr = dataptrs[2];
+ npy_intp mask_stride = strides[2];
+ /* Optimization for when the mask is broadcast */
+ npy_intp n = mask_stride == 0 ? count : 1;
+ while (count) {
+ char mask = *maskptr;
+ maskptr += mask_stride;
+ while (n < count && mask == *maskptr) {
+ n++;
+ maskptr += mask_stride;
+ }
+ /* If mask set, apply inner loop on this contiguous region */
+ if (mask) {
+ innerloop(dataptrs_copy, &n,
+ strides_copy, innerloopdata);
+ }
+ dataptrs_copy[0] += n * strides[0];
+ dataptrs_copy[1] += n * strides[1];
+ dataptrs_copy[2] = dataptrs_copy[0];
+ count -= n;
+ n = 1;
+ }
+ }
} while (iternext(iter));
finish_loop:
@@ -3563,7 +3594,7 @@ finish_loop:
static PyArrayObject *
PyUFunc_Reduce(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
int naxes, int *axes, PyArray_Descr *odtype, int keepdims,
- PyObject *initial)
+ PyObject *initial, PyArrayObject *wheremask)
{
int iaxes, ndim;
npy_bool reorderable;
@@ -3629,7 +3660,7 @@ PyUFunc_Reduce(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
return NULL;
}
- result = PyUFunc_ReduceWrapper(arr, out, NULL, dtype, dtype,
+ result = PyUFunc_ReduceWrapper(arr, out, wheremask, dtype, dtype,
NPY_UNSAFE_CASTING,
axis_flags, reorderable,
keepdims, 0,
@@ -4386,7 +4417,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
int i, naxes=0, ndim;
int axes[NPY_MAXDIMS];
PyObject *axes_in = NULL;
- PyArrayObject *mp = NULL, *ret = NULL;
+ PyArrayObject *mp = NULL, *wheremask = NULL, *ret = NULL;
PyObject *op;
PyObject *obj_ind, *context;
PyArrayObject *indices = NULL;
@@ -4395,7 +4426,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
int keepdims = 0;
PyObject *initial = NULL;
static char *reduce_kwlist[] = {
- "array", "axis", "dtype", "out", "keepdims", "initial", NULL};
+ "array", "axis", "dtype", "out", "keepdims", "initial", "where", NULL};
static char *accumulate_kwlist[] = {
"array", "axis", "dtype", "out", NULL};
static char *reduceat_kwlist[] = {
@@ -4458,22 +4489,23 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
}
else if (operation == UFUNC_ACCUMULATE) {
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO&O&:accumulate",
- accumulate_kwlist,
- &op,
- &axes_in,
- PyArray_DescrConverter2, &otype,
- PyArray_OutputConverter, &out)) {
+ accumulate_kwlist,
+ &op,
+ &axes_in,
+ PyArray_DescrConverter2, &otype,
+ PyArray_OutputConverter, &out)) {
goto fail;
}
}
else {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO&O&iO:reduce",
- reduce_kwlist,
- &op,
- &axes_in,
- PyArray_DescrConverter2, &otype,
- PyArray_OutputConverter, &out,
- &keepdims, &initial)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO&O&iOO&:reduce",
+ reduce_kwlist,
+ &op,
+ &axes_in,
+ PyArray_DescrConverter2, &otype,
+ PyArray_OutputConverter, &out,
+ &keepdims, &initial,
+ _wheremask_converter, &wheremask)) {
goto fail;
}
}
@@ -4503,11 +4535,17 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
/* Convert the 'axis' parameter into a list of axes */
if (axes_in == NULL) {
- naxes = 1;
- axes[0] = 0;
+ /* apply defaults */
+ if (ndim == 0) {
+ naxes = 0;
+ }
+ else {
+ naxes = 1;
+ axes[0] = 0;
+ }
}
- /* Convert 'None' into all the axes */
else if (axes_in == Py_None) {
+ /* Convert 'None' into all the axes */
naxes = ndim;
for (i = 0; i < naxes; ++i) {
axes[i] = i;
@@ -4532,40 +4570,28 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
axes[i] = (int)axis;
}
}
- /* Try to interpret axis as an integer */
else {
+ /* Try to interpret axis as an integer */
int axis = PyArray_PyIntAsInt(axes_in);
/* TODO: PyNumber_Index would be good to use here */
if (error_converting(axis)) {
goto fail;
}
- /* Special case letting axis={0 or -1} slip through for scalars */
- if (ndim == 0 && (axis == 0 || axis == -1)) {
- axis = 0;
- }
- else if (check_and_adjust_axis(&axis, ndim) < 0) {
- goto fail;
- }
- axes[0] = (int)axis;
- naxes = 1;
- }
-
- /* Check to see if input is zero-dimensional. */
- if (ndim == 0) {
/*
- * A reduction with no axes is still valid but trivial.
* As a special case for backwards compatibility in 'sum',
- * 'prod', et al, also allow a reduction where axis=0, even
+ * 'prod', et al, also allow a reduction for scalars even
* though this is technically incorrect.
*/
- naxes = 0;
-
- if (!(operation == UFUNC_REDUCE &&
- (naxes == 0 || (naxes == 1 && axes[0] == 0)))) {
- PyErr_Format(PyExc_TypeError, "cannot %s on a scalar",
- _reduce_type[operation]);
+ if (ndim == 0 && (axis == 0 || axis == -1)) {
+ naxes = 0;
+ }
+ else if (check_and_adjust_axis(&axis, ndim) < 0) {
goto fail;
}
+ else {
+ axes[0] = (int)axis;
+ naxes = 1;
+ }
}
/*
@@ -4604,9 +4630,14 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
switch(operation) {
case UFUNC_REDUCE:
ret = PyUFunc_Reduce(ufunc, mp, out, naxes, axes,
- otype, keepdims, initial);
+ otype, keepdims, initial, wheremask);
+ Py_XDECREF(wheremask);
break;
case UFUNC_ACCUMULATE:
+ if (ndim == 0) {
+ PyErr_SetString(PyExc_TypeError, "cannot accumulate on a scalar");
+ goto fail;
+ }
if (naxes != 1) {
PyErr_SetString(PyExc_ValueError,
"accumulate does not allow multiple axes");
@@ -4616,6 +4647,10 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
otype->type_num);
break;
case UFUNC_REDUCEAT:
+ if (ndim == 0) {
+ PyErr_SetString(PyExc_TypeError, "cannot reduceat on a scalar");
+ goto fail;
+ }
if (naxes != 1) {
PyErr_SetString(PyExc_ValueError,
"reduceat does not allow multiple axes");
@@ -4662,6 +4697,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
fail:
Py_XDECREF(otype);
Py_XDECREF(mp);
+ Py_XDECREF(wheremask);
return NULL;
}
@@ -4894,12 +4930,15 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
return NULL;
}
- ufunc = PyArray_malloc(sizeof(PyUFuncObject));
+ ufunc = PyObject_GC_New(PyUFuncObject, &PyUFunc_Type);
+ /*
+ * We use GC_New here for ufunc->obj, but do not use GC_Track since
+ * ufunc->obj is still NULL at the end of this function.
+ * See ufunc_frompyfunc where ufunc->obj is set and GC_Track is called.
+ */
if (ufunc == NULL) {
return NULL;
}
- memset(ufunc, 0, sizeof(PyUFuncObject));
- PyObject_Init((PyObject *)ufunc, &PyUFunc_Type);
ufunc->nin = nin;
ufunc->nout = nout;
@@ -4907,13 +4946,30 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
ufunc->identity = identity;
if (ufunc->identity == PyUFunc_IdentityValue) {
Py_INCREF(identity_value);
+ ufunc->identity_value = identity_value;
+ }
+ else {
+ ufunc->identity_value = NULL;
}
- ufunc->identity_value = identity_value;
ufunc->functions = func;
ufunc->data = data;
ufunc->types = types;
ufunc->ntypes = ntypes;
+ ufunc->core_signature = NULL;
+ ufunc->core_enabled = 0;
+ ufunc->obj = NULL;
+ ufunc->core_num_dims = NULL;
+ ufunc->core_num_dim_ix = 0;
+ ufunc->core_offsets = NULL;
+ ufunc->core_dim_ixs = NULL;
+ ufunc->core_dim_sizes = NULL;
+ ufunc->core_dim_flags = NULL;
+ ufunc->userloops = NULL;
+ ufunc->ptr = NULL;
+ ufunc->reserved2 = NULL;
+ ufunc->reserved1 = 0;
+ ufunc->iter_flags = 0;
/* Type resolution and inner loop selection functions */
ufunc->type_resolver = &PyUFunc_DefaultTypeResolver;
@@ -5056,11 +5112,14 @@ _loop1d_list_free(void *ptr)
* instead of dtype type num values. This allows a 1-d loop to be registered
* for a structured array dtype or a custom dtype. The ufunc is called
* whenever any of it's input arguments match the user_dtype argument.
- * ufunc - ufunc object created from call to PyUFunc_FromFuncAndData
+ *
+ * ufunc - ufunc object created from call to PyUFunc_FromFuncAndData
* user_dtype - dtype that ufunc will be registered with
- * function - 1-d loop function pointer
+ * function - 1-d loop function pointer
* arg_dtypes - array of dtype objects describing the ufunc operands
- * data - arbitrary data pointer passed in to loop function
+ * data - arbitrary data pointer passed in to loop function
+ *
+ * returns 0 on success, -1 for failure
*/
/*UFUNC_API*/
NPY_NO_EXPORT int
@@ -5124,7 +5183,7 @@ PyUFunc_RegisterLoopForDescr(PyUFuncObject *ufunc,
}
current = current->next;
}
- if (cmp == 0 && current->arg_dtypes == NULL) {
+ if (cmp == 0 && current != NULL && current->arg_dtypes == NULL) {
current->arg_dtypes = PyArray_malloc(ufunc->nargs *
sizeof(PyArray_Descr*));
if (arg_dtypes != NULL) {
@@ -5142,6 +5201,8 @@ PyUFunc_RegisterLoopForDescr(PyUFuncObject *ufunc,
current->nargs = ufunc->nargs;
}
else {
+ PyErr_SetString(PyExc_RuntimeError,
+ "loop already registered");
result = -1;
}
}
@@ -5279,6 +5340,7 @@ PyUFunc_RegisterLoopForType(PyUFuncObject *ufunc,
static void
ufunc_dealloc(PyUFuncObject *ufunc)
{
+ PyObject_GC_UnTrack((PyObject *)ufunc);
PyArray_free(ufunc->core_num_dims);
PyArray_free(ufunc->core_dim_ixs);
PyArray_free(ufunc->core_dim_sizes);
@@ -5288,11 +5350,13 @@ ufunc_dealloc(PyUFuncObject *ufunc)
PyArray_free(ufunc->ptr);
PyArray_free(ufunc->op_flags);
Py_XDECREF(ufunc->userloops);
- Py_XDECREF(ufunc->obj);
if (ufunc->identity == PyUFunc_IdentityValue) {
Py_DECREF(ufunc->identity_value);
}
- PyArray_free(ufunc);
+ if (ufunc->obj != NULL) {
+ Py_DECREF(ufunc->obj);
+ }
+ PyObject_GC_Del(ufunc);
}
static PyObject *
@@ -5301,6 +5365,15 @@ ufunc_repr(PyUFuncObject *ufunc)
return PyUString_FromFormat("<ufunc '%s'>", ufunc->name);
}
+static int
+ufunc_traverse(PyUFuncObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->obj);
+ if (self->identity == PyUFunc_IdentityValue) {
+ Py_VISIT(self->identity_value);
+ }
+ return 0;
+}
/******************************************************************************
*** UFUNC METHODS ***
@@ -5323,6 +5396,8 @@ ufunc_outer(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
PyArrayObject *ap1 = NULL, *ap2 = NULL, *ap_new = NULL;
PyObject *new_args, *tmp;
PyObject *shape1, *shape2, *newshape;
+ static PyObject *_numpy_matrix;
+
errval = PyUFunc_CheckOverride(ufunc, "outer", args, kwds, &override);
if (errval) {
@@ -5355,7 +5430,18 @@ ufunc_outer(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
if (tmp == NULL) {
return NULL;
}
- ap1 = (PyArrayObject *) PyArray_FromObject(tmp, NPY_NOTYPE, 0, 0);
+
+ npy_cache_import(
+ "numpy",
+ "matrix",
+ &_numpy_matrix);
+
+ if (PyObject_IsInstance(tmp, _numpy_matrix)) {
+ ap1 = (PyArrayObject *) PyArray_FromObject(tmp, NPY_NOTYPE, 0, 0);
+ }
+ else {
+ ap1 = (PyArrayObject *) PyArray_FROM_O(tmp);
+ }
Py_DECREF(tmp);
if (ap1 == NULL) {
return NULL;
@@ -5364,7 +5450,12 @@ ufunc_outer(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
if (tmp == NULL) {
return NULL;
}
- ap2 = (PyArrayObject *)PyArray_FromObject(tmp, NPY_NOTYPE, 0, 0);
+ if (PyObject_IsInstance(tmp, _numpy_matrix)) {
+ ap2 = (PyArrayObject *) PyArray_FromObject(tmp, NPY_NOTYPE, 0, 0);
+ }
+ else {
+ ap2 = (PyArrayObject *) PyArray_FROM_O(tmp);
+ }
Py_DECREF(tmp);
if (ap2 == NULL) {
Py_DECREF(ap1);
@@ -6017,9 +6108,9 @@ NPY_NO_EXPORT PyTypeObject PyUFunc_Type = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)ufunc_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c
index c2d81fc5d..25dd002ac 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.c
+++ b/numpy/core/src/umath/ufunc_type_resolution.c
@@ -12,21 +12,45 @@
#define _MULTIARRAYMODULE
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+#include <stdbool.h>
+
#include "Python.h"
#include "npy_config.h"
#include "npy_pycompat.h"
+#include "npy_import.h"
#include "numpy/ufuncobject.h"
#include "ufunc_type_resolution.h"
#include "ufunc_object.h"
#include "common.h"
+#include "convert_datatype.h"
#include "mem_overlap.h"
#if defined(HAVE_CBLAS)
#include "cblasfuncs.h"
#endif
+static PyObject *
+npy_casting_to_py_object(NPY_CASTING casting)
+{
+ switch (casting) {
+ case NPY_NO_CASTING:
+ return PyUString_FromString("no");
+ case NPY_EQUIV_CASTING:
+ return PyUString_FromString("equiv");
+ case NPY_SAFE_CASTING:
+ return PyUString_FromString("safe");
+ case NPY_SAME_KIND_CASTING:
+ return PyUString_FromString("same_kind");
+ case NPY_UNSAFE_CASTING:
+ return PyUString_FromString("unsafe");
+ default:
+ return PyInt_FromLong(casting);
+ }
+}
+
+
static const char *
npy_casting_to_string(NPY_CASTING casting)
{
@@ -46,23 +70,156 @@ npy_casting_to_string(NPY_CASTING casting)
}
}
+/**
+ * Always returns -1 to indicate the exception was raised, for convenience
+ */
static int
raise_binary_type_reso_error(PyUFuncObject *ufunc, PyArrayObject **operands) {
- PyObject *errmsg;
- const char *ufunc_name = ufunc_get_name_cstr(ufunc);
- errmsg = PyUString_FromFormat("ufunc %s cannot use operands "
- "with types ", ufunc_name);
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)PyArray_DESCR(operands[0])));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromString(" and "));
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)PyArray_DESCR(operands[1])));
- PyErr_SetObject(PyExc_TypeError, errmsg);
- Py_DECREF(errmsg);
+ static PyObject *exc_type = NULL;
+ PyObject *exc_value;
+
+ npy_cache_import(
+ "numpy.core._exceptions", "_UFuncBinaryResolutionError",
+ &exc_type);
+ if (exc_type == NULL) {
+ return -1;
+ }
+
+ /* produce an error object */
+ exc_value = Py_BuildValue(
+ "O(OO)", ufunc,
+ (PyObject *)PyArray_DESCR(operands[0]),
+ (PyObject *)PyArray_DESCR(operands[1])
+ );
+ if (exc_value == NULL){
+ return -1;
+ }
+ PyErr_SetObject(exc_type, exc_value);
+ Py_DECREF(exc_value);
+
return -1;
}
+/** Helper function to raise UFuncNoLoopError
+ * Always returns -1 to indicate the exception was raised, for convenience
+ */
+static int
+raise_no_loop_found_error(
+ PyUFuncObject *ufunc, PyArray_Descr **dtypes)
+{
+ static PyObject *exc_type = NULL;
+ PyObject *exc_value;
+ PyObject *dtypes_tup;
+ npy_intp i;
+
+ npy_cache_import(
+ "numpy.core._exceptions", "_UFuncNoLoopError",
+ &exc_type);
+ if (exc_type == NULL) {
+ return -1;
+ }
+
+ /* convert dtypes to a tuple */
+ dtypes_tup = PyTuple_New(ufunc->nargs);
+ if (dtypes_tup == NULL) {
+ return -1;
+ }
+ for (i = 0; i < ufunc->nargs; ++i) {
+ Py_INCREF(dtypes[i]);
+ PyTuple_SET_ITEM(dtypes_tup, i, (PyObject *)dtypes[i]);
+ }
+
+ /* produce an error object */
+ exc_value = PyTuple_Pack(2, ufunc, dtypes_tup);
+ Py_DECREF(dtypes_tup);
+ if (exc_value == NULL){
+ return -1;
+ }
+ PyErr_SetObject(exc_type, exc_value);
+ Py_DECREF(exc_value);
+
+ return -1;
+}
+
+static int
+raise_casting_error(
+ PyObject *exc_type,
+ PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArray_Descr *from,
+ PyArray_Descr *to,
+ npy_intp i)
+{
+ PyObject *exc_value;
+ PyObject *casting_value;
+
+ casting_value = npy_casting_to_py_object(casting);
+ if (casting_value == NULL) {
+ return -1;
+ }
+
+ exc_value = Py_BuildValue(
+ "ONOOi",
+ ufunc,
+ casting_value,
+ (PyObject *)from,
+ (PyObject *)to,
+ i
+ );
+ if (exc_value == NULL){
+ return -1;
+ }
+ PyErr_SetObject(exc_type, exc_value);
+ Py_DECREF(exc_value);
+
+ return -1;
+}
+
+/** Helper function to raise UFuncInputCastingError
+ * Always returns -1 to indicate the exception was raised, for convenience
+ */
+static int
+raise_input_casting_error(
+ PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArray_Descr *from,
+ PyArray_Descr *to,
+ npy_intp i)
+{
+ static PyObject *exc_type = NULL;
+ npy_cache_import(
+ "numpy.core._exceptions", "_UFuncInputCastingError",
+ &exc_type);
+ if (exc_type == NULL) {
+ return -1;
+ }
+
+ return raise_casting_error(exc_type, ufunc, casting, from, to, i);
+}
+
+
+/** Helper function to raise UFuncOutputCastingError
+ * Always returns -1 to indicate the exception was raised, for convenience
+ */
+static int
+raise_output_casting_error(
+ PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArray_Descr *from,
+ PyArray_Descr *to,
+ npy_intp i)
+{
+ static PyObject *exc_type = NULL;
+ npy_cache_import(
+ "numpy.core._exceptions", "_UFuncOutputCastingError",
+ &exc_type);
+ if (exc_type == NULL) {
+ return -1;
+ }
+
+ return raise_casting_error(exc_type, ufunc, casting, from, to, i);
+}
+
/*UFUNC_API
*
@@ -79,45 +236,18 @@ PyUFunc_ValidateCasting(PyUFuncObject *ufunc,
PyArray_Descr **dtypes)
{
int i, nin = ufunc->nin, nop = nin + ufunc->nout;
- const char *ufunc_name = ufunc_get_name_cstr(ufunc);
for (i = 0; i < nop; ++i) {
if (i < nin) {
if (!PyArray_CanCastArrayTo(operands[i], dtypes[i], casting)) {
- PyObject *errmsg;
- errmsg = PyUString_FromFormat("Cannot cast ufunc %s "
- "input from ", ufunc_name);
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)PyArray_DESCR(operands[i])));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromString(" to "));
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)dtypes[i]));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromFormat(" with casting rule %s",
- npy_casting_to_string(casting)));
- PyErr_SetObject(PyExc_TypeError, errmsg);
- Py_DECREF(errmsg);
- return -1;
+ return raise_input_casting_error(
+ ufunc, casting, PyArray_DESCR(operands[i]), dtypes[i], i);
}
} else if (operands[i] != NULL) {
if (!PyArray_CanCastTypeTo(dtypes[i],
PyArray_DESCR(operands[i]), casting)) {
- PyObject *errmsg;
- errmsg = PyUString_FromFormat("Cannot cast ufunc %s "
- "output from ", ufunc_name);
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)dtypes[i]));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromString(" to "));
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)PyArray_DESCR(operands[i])));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromFormat(" with casting rule %s",
- npy_casting_to_string(casting)));
- PyErr_SetObject(PyExc_TypeError, errmsg);
- Py_DECREF(errmsg);
- return -1;
+ return raise_output_casting_error(
+ ufunc, casting, dtypes[i], PyArray_DESCR(operands[i]), i);
}
}
}
@@ -290,99 +420,6 @@ PyUFunc_SimpleBinaryComparisonTypeResolver(PyUFuncObject *ufunc,
return 0;
}
-/*
- * This function applies special type resolution rules for the case
- * where all the functions have the pattern X->X, copying
- * the input descr directly so that metadata is maintained.
- *
- * Note that a simpler linear search through the functions loop
- * is still done, but switching to a simple array lookup for
- * built-in types would be better at some point.
- *
- * Returns 0 on success, -1 on error.
- */
-NPY_NO_EXPORT int
-PyUFunc_SimpleUnaryOperationTypeResolver(PyUFuncObject *ufunc,
- NPY_CASTING casting,
- PyArrayObject **operands,
- PyObject *type_tup,
- PyArray_Descr **out_dtypes)
-{
- int i, type_num1;
- const char *ufunc_name = ufunc_get_name_cstr(ufunc);
-
- if (ufunc->nin != 1 || ufunc->nout != 1) {
- PyErr_Format(PyExc_RuntimeError, "ufunc %s is configured "
- "to use unary operation type resolution but has "
- "the wrong number of inputs or outputs",
- ufunc_name);
- return -1;
- }
-
- /*
- * Use the default type resolution if there's a custom data type
- * or object arrays.
- */
- type_num1 = PyArray_DESCR(operands[0])->type_num;
- if (type_num1 >= NPY_NTYPES || type_num1 == NPY_OBJECT) {
- return PyUFunc_DefaultTypeResolver(ufunc, casting, operands,
- type_tup, out_dtypes);
- }
-
- if (type_tup == NULL) {
- /* Input types are the result type */
- out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0]));
- if (out_dtypes[0] == NULL) {
- return -1;
- }
- out_dtypes[1] = out_dtypes[0];
- Py_INCREF(out_dtypes[1]);
- }
- else {
- PyObject *item;
- PyArray_Descr *dtype = NULL;
-
- /*
- * If the type tuple isn't a single-element tuple, let the
- * default type resolution handle this one.
- */
- if (!PyTuple_Check(type_tup) || PyTuple_GET_SIZE(type_tup) != 1) {
- return PyUFunc_DefaultTypeResolver(ufunc, casting,
- operands, type_tup, out_dtypes);
- }
-
- item = PyTuple_GET_ITEM(type_tup, 0);
-
- if (item == Py_None) {
- PyErr_SetString(PyExc_ValueError,
- "require data type in the type tuple");
- return -1;
- }
- else if (!PyArray_DescrConverter(item, &dtype)) {
- return -1;
- }
-
- out_dtypes[0] = ensure_dtype_nbo(dtype);
- if (out_dtypes[0] == NULL) {
- return -1;
- }
- out_dtypes[1] = out_dtypes[0];
- Py_INCREF(out_dtypes[1]);
- }
-
- /* Check against the casting rules */
- if (PyUFunc_ValidateCasting(ufunc, casting, operands, out_dtypes) < 0) {
- for (i = 0; i < 2; ++i) {
- Py_DECREF(out_dtypes[i]);
- out_dtypes[i] = NULL;
- }
- return -1;
- }
-
- return 0;
-}
-
-
NPY_NO_EXPORT int
PyUFunc_NegativeTypeResolver(PyUFuncObject *ufunc,
NPY_CASTING casting,
@@ -391,7 +428,7 @@ PyUFunc_NegativeTypeResolver(PyUFuncObject *ufunc,
PyArray_Descr **out_dtypes)
{
int ret;
- ret = PyUFunc_SimpleUnaryOperationTypeResolver(ufunc, casting, operands,
+ ret = PyUFunc_SimpleUniformOperationTypeResolver(ufunc, casting, operands,
type_tup, out_dtypes);
if (ret < 0) {
return ret;
@@ -421,16 +458,15 @@ PyUFunc_OnesLikeTypeResolver(PyUFuncObject *ufunc,
PyObject *type_tup,
PyArray_Descr **out_dtypes)
{
- return PyUFunc_SimpleUnaryOperationTypeResolver(ufunc,
+ return PyUFunc_SimpleUniformOperationTypeResolver(ufunc,
NPY_UNSAFE_CASTING,
operands, type_tup, out_dtypes);
}
-
/*
* This function applies special type resolution rules for the case
- * where all the functions have the pattern XX->X, using
- * PyArray_ResultType instead of a linear search to get the best
+ * where all of the types in the signature are the same, eg XX->X or XX->XX.
+ * It uses PyArray_ResultType instead of a linear search to get the best
* loop.
*
* Note that a simpler linear search through the functions loop
@@ -440,45 +476,52 @@ PyUFunc_OnesLikeTypeResolver(PyUFuncObject *ufunc,
* Returns 0 on success, -1 on error.
*/
NPY_NO_EXPORT int
-PyUFunc_SimpleBinaryOperationTypeResolver(PyUFuncObject *ufunc,
- NPY_CASTING casting,
- PyArrayObject **operands,
- PyObject *type_tup,
- PyArray_Descr **out_dtypes)
+PyUFunc_SimpleUniformOperationTypeResolver(
+ PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArrayObject **operands,
+ PyObject *type_tup,
+ PyArray_Descr **out_dtypes)
{
- int i, type_num1, type_num2;
const char *ufunc_name = ufunc_get_name_cstr(ufunc);
- if (ufunc->nin != 2 || ufunc->nout != 1) {
+ if (ufunc->nin < 1) {
PyErr_Format(PyExc_RuntimeError, "ufunc %s is configured "
- "to use binary operation type resolution but has "
- "the wrong number of inputs or outputs",
+ "to use uniform operation type resolution but has "
+ "no inputs",
ufunc_name);
return -1;
}
+ int nop = ufunc->nin + ufunc->nout;
/*
- * Use the default type resolution if there's a custom data type
- * or object arrays.
+ * There's a custom data type or an object array
*/
- type_num1 = PyArray_DESCR(operands[0])->type_num;
- type_num2 = PyArray_DESCR(operands[1])->type_num;
- if (type_num1 >= NPY_NTYPES || type_num2 >= NPY_NTYPES ||
- type_num1 == NPY_OBJECT || type_num2 == NPY_OBJECT) {
+ bool has_custom_or_object = false;
+ for (int iop = 0; iop < ufunc->nin; iop++) {
+ int type_num = PyArray_DESCR(operands[iop])->type_num;
+ if (type_num >= NPY_NTYPES || type_num == NPY_OBJECT) {
+ has_custom_or_object = true;
+ break;
+ }
+ }
+
+ if (has_custom_or_object) {
return PyUFunc_DefaultTypeResolver(ufunc, casting, operands,
type_tup, out_dtypes);
}
if (type_tup == NULL) {
- /* Input types are the result type */
- out_dtypes[0] = PyArray_ResultType(2, operands, 0, NULL);
+ /* PyArray_ResultType forgets to force a byte order when n == 1 */
+ if (ufunc->nin == 1){
+ out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0]));
+ }
+ else {
+ out_dtypes[0] = PyArray_ResultType(ufunc->nin, operands, 0, NULL);
+ }
if (out_dtypes[0] == NULL) {
return -1;
}
- out_dtypes[1] = out_dtypes[0];
- Py_INCREF(out_dtypes[1]);
- out_dtypes[2] = out_dtypes[0];
- Py_INCREF(out_dtypes[2]);
}
else {
PyObject *item;
@@ -508,17 +551,19 @@ PyUFunc_SimpleBinaryOperationTypeResolver(PyUFuncObject *ufunc,
if (out_dtypes[0] == NULL) {
return -1;
}
- out_dtypes[1] = out_dtypes[0];
- Py_INCREF(out_dtypes[1]);
- out_dtypes[2] = out_dtypes[0];
- Py_INCREF(out_dtypes[2]);
+ }
+
+ /* All types are the same - copy the first one to the rest */
+ for (int iop = 1; iop < nop; iop++) {
+ out_dtypes[iop] = out_dtypes[0];
+ Py_INCREF(out_dtypes[iop]);
}
/* Check against the casting rules */
if (PyUFunc_ValidateCasting(ufunc, casting, operands, out_dtypes) < 0) {
- for (i = 0; i < 3; ++i) {
- Py_DECREF(out_dtypes[i]);
- out_dtypes[i] = NULL;
+ for (int iop = 0; iop < nop; iop++) {
+ Py_DECREF(out_dtypes[iop]);
+ out_dtypes[iop] = NULL;
}
return -1;
}
@@ -546,7 +591,7 @@ PyUFunc_AbsoluteTypeResolver(PyUFuncObject *ufunc,
type_tup, out_dtypes);
}
else {
- return PyUFunc_SimpleUnaryOperationTypeResolver(ufunc, casting,
+ return PyUFunc_SimpleUniformOperationTypeResolver(ufunc, casting,
operands, type_tup, out_dtypes);
}
}
@@ -577,6 +622,26 @@ PyUFunc_IsNaTTypeResolver(PyUFuncObject *ufunc,
return 0;
}
+
+NPY_NO_EXPORT int
+PyUFunc_IsFiniteTypeResolver(PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArrayObject **operands,
+ PyObject *type_tup,
+ PyArray_Descr **out_dtypes)
+{
+ if (!PyTypeNum_ISDATETIME(PyArray_DESCR(operands[0])->type_num)) {
+ return PyUFunc_DefaultTypeResolver(ufunc, casting, operands,
+ type_tup, out_dtypes);
+ }
+
+ out_dtypes[0] = ensure_dtype_nbo(PyArray_DESCR(operands[0]));
+ out_dtypes[1] = PyArray_DescrFromType(NPY_BOOL);
+
+ return 0;
+}
+
+
/*
* Creates a new NPY_TIMEDELTA dtype, copying the datetime metadata
* from the given dtype.
@@ -635,7 +700,7 @@ PyUFunc_AdditionTypeResolver(PyUFuncObject *ufunc,
/* Use the default when datetime and timedelta are not involved */
if (!PyTypeNum_ISDATETIME(type_num1) && !PyTypeNum_ISDATETIME(type_num2)) {
- return PyUFunc_SimpleBinaryOperationTypeResolver(ufunc, casting,
+ return PyUFunc_SimpleUniformOperationTypeResolver(ufunc, casting,
operands, type_tup, out_dtypes);
}
@@ -808,7 +873,7 @@ PyUFunc_SubtractionTypeResolver(PyUFuncObject *ufunc,
/* Use the default when datetime and timedelta are not involved */
if (!PyTypeNum_ISDATETIME(type_num1) && !PyTypeNum_ISDATETIME(type_num2)) {
int ret;
- ret = PyUFunc_SimpleBinaryOperationTypeResolver(ufunc, casting,
+ ret = PyUFunc_SimpleUniformOperationTypeResolver(ufunc, casting,
operands, type_tup, out_dtypes);
if (ret < 0) {
return ret;
@@ -971,7 +1036,7 @@ PyUFunc_MultiplicationTypeResolver(PyUFuncObject *ufunc,
/* Use the default when datetime and timedelta are not involved */
if (!PyTypeNum_ISDATETIME(type_num1) && !PyTypeNum_ISDATETIME(type_num2)) {
- return PyUFunc_SimpleBinaryOperationTypeResolver(ufunc, casting,
+ return PyUFunc_SimpleUniformOperationTypeResolver(ufunc, casting,
operands, type_tup, out_dtypes);
}
@@ -1382,12 +1447,8 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc,
{
int nargs = ufunc->nargs;
char *types;
- const char *ufunc_name;
- PyObject *errmsg;
int i, j;
- ufunc_name = ufunc_get_name_cstr(ufunc);
-
/*
* If there are user-loops search them first.
* TODO: There needs to be a loop selection acceleration structure,
@@ -1422,19 +1483,7 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc,
types += nargs;
}
- errmsg = PyUString_FromFormat("ufunc '%s' did not contain a loop "
- "with signature matching types ", ufunc_name);
- for (i = 0; i < nargs; ++i) {
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)dtypes[i]));
- if (i < nargs - 1) {
- PyUString_ConcatAndDel(&errmsg, PyUString_FromString(" "));
- }
- }
- PyErr_SetObject(PyExc_TypeError, errmsg);
- Py_DECREF(errmsg);
-
- return -1;
+ return raise_no_loop_found_error(ufunc, dtypes);
}
typedef struct {
@@ -1699,7 +1748,7 @@ set_ufunc_loop_data_types(PyUFuncObject *self, PyArrayObject **op,
}
/*
* For outputs, copy the dtype from op[0] if the type_num
- * matches, similarly to preserve metdata.
+ * matches, similarly to preserve metadata.
*/
else if (i >= nin && op[0] != NULL &&
PyArray_DESCR(op[0])->type_num == type_nums[i]) {
@@ -1890,73 +1939,6 @@ type_tuple_userloop_type_resolver(PyUFuncObject *self,
return 0;
}
-/*
- * Provides an ordering for the dtype 'kind' character codes, to help
- * determine when to use the min_scalar_type function. This groups
- * 'kind' into boolean, integer, floating point, and everything else.
- */
-
-static int
-dtype_kind_to_simplified_ordering(char kind)
-{
- switch (kind) {
- /* Boolean kind */
- case 'b':
- return 0;
- /* Unsigned int kind */
- case 'u':
- /* Signed int kind */
- case 'i':
- return 1;
- /* Float kind */
- case 'f':
- /* Complex kind */
- case 'c':
- return 2;
- /* Anything else */
- default:
- return 3;
- }
-}
-
-static int
-should_use_min_scalar(PyArrayObject **op, int nop)
-{
- int i, use_min_scalar, kind;
- int all_scalars = 1, max_scalar_kind = -1, max_array_kind = -1;
-
- /*
- * Determine if there are any scalars, and if so, whether
- * the maximum "kind" of the scalars surpasses the maximum
- * "kind" of the arrays
- */
- use_min_scalar = 0;
- if (nop > 1) {
- for(i = 0; i < nop; ++i) {
- kind = dtype_kind_to_simplified_ordering(
- PyArray_DESCR(op[i])->kind);
- if (PyArray_NDIM(op[i]) == 0) {
- if (kind > max_scalar_kind) {
- max_scalar_kind = kind;
- }
- }
- else {
- all_scalars = 0;
- if (kind > max_array_kind) {
- max_array_kind = kind;
- }
-
- }
- }
-
- /* Indicate whether to use the min_scalar_type function */
- if (!all_scalars && max_array_kind >= max_scalar_kind) {
- use_min_scalar = 1;
- }
- }
-
- return use_min_scalar;
-}
/*
* Does a linear search for the best inner loop of the ufunc.
@@ -1982,7 +1964,7 @@ linear_search_type_resolver(PyUFuncObject *self,
ufunc_name = ufunc_get_name_cstr(self);
- use_min_scalar = should_use_min_scalar(op, nin);
+ use_min_scalar = should_use_min_scalar(nin, op, 0, NULL);
/* If the ufunc has userloops, search for them. */
if (self->userloops) {
@@ -2091,7 +2073,7 @@ type_tuple_type_resolver(PyUFuncObject *self,
ufunc_name = ufunc_get_name_cstr(self);
- use_min_scalar = should_use_min_scalar(op, nin);
+ use_min_scalar = should_use_min_scalar(nin, op, 0, NULL);
/* Fill in specified_types from the tuple or string */
if (PyTuple_Check(type_tup)) {
@@ -2251,7 +2233,7 @@ type_tuple_type_resolver(PyUFuncObject *self,
/* If no function was found, throw an error */
PyErr_Format(PyExc_TypeError,
- "No loop matching the specified signature and casting\n"
+ "No loop matching the specified signature and casting "
"was found for ufunc %s", ufunc_name);
return -1;
diff --git a/numpy/core/src/umath/ufunc_type_resolution.h b/numpy/core/src/umath/ufunc_type_resolution.h
index 78313b1ef..a4e670a8e 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.h
+++ b/numpy/core/src/umath/ufunc_type_resolution.h
@@ -9,13 +9,6 @@ PyUFunc_SimpleBinaryComparisonTypeResolver(PyUFuncObject *ufunc,
PyArray_Descr **out_dtypes);
NPY_NO_EXPORT int
-PyUFunc_SimpleUnaryOperationTypeResolver(PyUFuncObject *ufunc,
- NPY_CASTING casting,
- PyArrayObject **operands,
- PyObject *type_tup,
- PyArray_Descr **out_dtypes);
-
-NPY_NO_EXPORT int
PyUFunc_NegativeTypeResolver(PyUFuncObject *ufunc,
NPY_CASTING casting,
PyArrayObject **operands,
@@ -30,7 +23,7 @@ PyUFunc_OnesLikeTypeResolver(PyUFuncObject *ufunc,
PyArray_Descr **out_dtypes);
NPY_NO_EXPORT int
-PyUFunc_SimpleBinaryOperationTypeResolver(PyUFuncObject *ufunc,
+PyUFunc_SimpleUniformOperationTypeResolver(PyUFuncObject *ufunc,
NPY_CASTING casting,
PyArrayObject **operands,
PyObject *type_tup,
@@ -51,6 +44,13 @@ PyUFunc_IsNaTTypeResolver(PyUFuncObject *ufunc,
PyArray_Descr **out_dtypes);
NPY_NO_EXPORT int
+PyUFunc_IsFiniteTypeResolver(PyUFuncObject *ufunc,
+ NPY_CASTING casting,
+ PyArrayObject **operands,
+ PyObject *type_tup,
+ PyArray_Descr **out_dtypes);
+
+NPY_NO_EXPORT int
PyUFunc_AdditionTypeResolver(PyUFuncObject *ufunc,
NPY_CASTING casting,
PyArrayObject **operands,
diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c
index b334a89da..6ec474376 100644
--- a/numpy/core/src/umath/umathmodule.c
+++ b/numpy/core/src/umath/umathmodule.c
@@ -161,6 +161,7 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
self->type_resolver = &object_ufunc_type_resolver;
self->legacy_inner_loop_selector = &object_ufunc_loop_selector;
+ PyObject_GC_Track(self);
return (PyObject *)self;
}
@@ -170,12 +171,10 @@ PyObject *
add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
PyUFuncObject *ufunc;
- PyObject *str;
+ PyObject *str, *tmp;
char *docstr, *newdocstr;
#if defined(NPY_PY3K)
- PyObject *tmp;
-
if (!PyArg_ParseTuple(args, "O!O!:_add_newdoc_ufunc", &PyUFunc_Type, &ufunc,
&PyUnicode_Type, &str)) {
return NULL;
@@ -188,7 +187,7 @@ add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
#else
if (!PyArg_ParseTuple(args, "O!O!:_add_newdoc_ufunc", &PyUFunc_Type, &ufunc,
&PyString_Type, &str)) {
- return NULL;
+ return NULL;
}
docstr = PyString_AS_STRING(str);
#endif
diff --git a/numpy/core/tests/data/umath-validation-set-README b/numpy/core/tests/data/umath-validation-set-README
new file mode 100644
index 000000000..6561ca3b5
--- /dev/null
+++ b/numpy/core/tests/data/umath-validation-set-README
@@ -0,0 +1,15 @@
+Steps to validate transcendental functions:
+1) Add a file 'umath-validation-set-<ufuncname>', where ufuncname is name of
+ the function in NumPy you want to validate
+2) The file should contain 4 columns: dtype,input,expected output,ulperror
+ a. dtype: one of np.float16, np.float32, np.float64
+ b. input: floating point input to ufunc in hex. Example: 0x414570a4
+ represents 12.340000152587890625
+ c. expected output: floating point output for the corresponding input in hex.
+ This should be computed using a high(er) precision library and then rounded to
+ same format as the input.
+ d. ulperror: expected maximum ulp error of the function. This
+ should be same across all rows of the same dtype. Otherwise, the function is
+ tested for the maximum ulp error among all entries of that dtype.
+3) Add file umath-validation-set-<ufuncname> to the test file test_umath_accuracy.py
+ which will then validate your ufunc.
diff --git a/numpy/core/tests/data/umath-validation-set-cos b/numpy/core/tests/data/umath-validation-set-cos
new file mode 100644
index 000000000..360ebcd6a
--- /dev/null
+++ b/numpy/core/tests/data/umath-validation-set-cos
@@ -0,0 +1,707 @@
+dtype,input,output,ulperrortol
+## +ve denormals ##
+np.float32,0x004b4716,0x3f800000,2
+np.float32,0x007b2490,0x3f800000,2
+np.float32,0x007c99fa,0x3f800000,2
+np.float32,0x00734a0c,0x3f800000,2
+np.float32,0x0070de24,0x3f800000,2
+np.float32,0x007fffff,0x3f800000,2
+np.float32,0x00000001,0x3f800000,2
+## -ve denormals ##
+np.float32,0x80495d65,0x3f800000,2
+np.float32,0x806894f6,0x3f800000,2
+np.float32,0x80555a76,0x3f800000,2
+np.float32,0x804e1fb8,0x3f800000,2
+np.float32,0x80687de9,0x3f800000,2
+np.float32,0x807fffff,0x3f800000,2
+np.float32,0x80000001,0x3f800000,2
+## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ##
+np.float32,0x00000000,0x3f800000,2
+np.float32,0x80000000,0x3f800000,2
+np.float32,0x00800000,0x3f800000,2
+np.float32,0x7f7fffff,0x3f5a5f96,2
+np.float32,0x80800000,0x3f800000,2
+np.float32,0xff7fffff,0x3f5a5f96,2
+## 1.00f + 0x00000001 ##
+np.float32,0x3f800000,0x3f0a5140,2
+np.float32,0x3f800001,0x3f0a513f,2
+np.float32,0x3f800002,0x3f0a513d,2
+np.float32,0xc090a8b0,0xbe4332ce,2
+np.float32,0x41ce3184,0x3f4d1de1,2
+np.float32,0xc1d85848,0xbeaa8980,2
+np.float32,0x402b8820,0xbf653aa3,2
+np.float32,0x42b4e454,0xbf4a338b,2
+np.float32,0x42a67a60,0x3c58202e,2
+np.float32,0x41d92388,0xbed987c7,2
+np.float32,0x422dd66c,0x3f5dcab3,2
+np.float32,0xc28f5be6,0xbf5688d8,2
+np.float32,0x41ab2674,0xbf53aa3b,2
+np.float32,0xd0102756,0x3f45d12d,2
+np.float32,0xcf99405e,0xbe9cf281,2
+np.float32,0xcfd83a12,0x3eaae4ca,2
+np.float32,0x4fb54db0,0xbf7b2894,2
+np.float32,0xcfcca29d,0x3f752e4e,2
+np.float32,0xceec2ac0,0xbf745303,2
+np.float32,0xcfdca97f,0x3ef554a7,2
+np.float32,0xcfe92b0a,0x3f4618f2,2
+np.float32,0x5014b0eb,0x3ee933e6,2
+np.float32,0xcfa7ee96,0xbeedeeb2,2
+np.float32,0x754c09a0,0xbef298de,2
+np.float32,0x77a731fb,0x3f24599f,2
+np.float32,0x76de2494,0x3f79576c,2
+np.float32,0xf74920dc,0xbf4d196e,2
+np.float32,0x7707a312,0xbeb5cb8e,2
+np.float32,0x75bf9790,0xbf7fd7fe,2
+np.float32,0xf4ca7c40,0xbe15107d,2
+np.float32,0x77e91899,0xbe8a968b,2
+np.float32,0xf74c9820,0xbf7f9677,2
+np.float32,0x7785ca29,0xbe6ef93b,2
+np.float32,0x3f490fdb,0x3f3504f3,2
+np.float32,0xbf490fdb,0x3f3504f3,2
+np.float32,0x3fc90fdb,0xb33bbd2e,2
+np.float32,0xbfc90fdb,0xb33bbd2e,2
+np.float32,0x40490fdb,0xbf800000,2
+np.float32,0xc0490fdb,0xbf800000,2
+np.float32,0x3fc90fdb,0xb33bbd2e,2
+np.float32,0xbfc90fdb,0xb33bbd2e,2
+np.float32,0x40490fdb,0xbf800000,2
+np.float32,0xc0490fdb,0xbf800000,2
+np.float32,0x40c90fdb,0x3f800000,2
+np.float32,0xc0c90fdb,0x3f800000,2
+np.float32,0x4016cbe4,0xbf3504f3,2
+np.float32,0xc016cbe4,0xbf3504f3,2
+np.float32,0x4096cbe4,0x324cde2e,2
+np.float32,0xc096cbe4,0x324cde2e,2
+np.float32,0x4116cbe4,0xbf800000,2
+np.float32,0xc116cbe4,0xbf800000,2
+np.float32,0x40490fdb,0xbf800000,2
+np.float32,0xc0490fdb,0xbf800000,2
+np.float32,0x40c90fdb,0x3f800000,2
+np.float32,0xc0c90fdb,0x3f800000,2
+np.float32,0x41490fdb,0x3f800000,2
+np.float32,0xc1490fdb,0x3f800000,2
+np.float32,0x407b53d2,0xbf3504f1,2
+np.float32,0xc07b53d2,0xbf3504f1,2
+np.float32,0x40fb53d2,0xb4b5563d,2
+np.float32,0xc0fb53d2,0xb4b5563d,2
+np.float32,0x417b53d2,0xbf800000,2
+np.float32,0xc17b53d2,0xbf800000,2
+np.float32,0x4096cbe4,0x324cde2e,2
+np.float32,0xc096cbe4,0x324cde2e,2
+np.float32,0x4116cbe4,0xbf800000,2
+np.float32,0xc116cbe4,0xbf800000,2
+np.float32,0x4196cbe4,0x3f800000,2
+np.float32,0xc196cbe4,0x3f800000,2
+np.float32,0x40afede0,0x3f3504f7,2
+np.float32,0xc0afede0,0x3f3504f7,2
+np.float32,0x412fede0,0x353222c4,2
+np.float32,0xc12fede0,0x353222c4,2
+np.float32,0x41afede0,0xbf800000,2
+np.float32,0xc1afede0,0xbf800000,2
+np.float32,0x40c90fdb,0x3f800000,2
+np.float32,0xc0c90fdb,0x3f800000,2
+np.float32,0x41490fdb,0x3f800000,2
+np.float32,0xc1490fdb,0x3f800000,2
+np.float32,0x41c90fdb,0x3f800000,2
+np.float32,0xc1c90fdb,0x3f800000,2
+np.float32,0x40e231d6,0x3f3504f3,2
+np.float32,0xc0e231d6,0x3f3504f3,2
+np.float32,0x416231d6,0xb319a6a2,2
+np.float32,0xc16231d6,0xb319a6a2,2
+np.float32,0x41e231d6,0xbf800000,2
+np.float32,0xc1e231d6,0xbf800000,2
+np.float32,0x40fb53d2,0xb4b5563d,2
+np.float32,0xc0fb53d2,0xb4b5563d,2
+np.float32,0x417b53d2,0xbf800000,2
+np.float32,0xc17b53d2,0xbf800000,2
+np.float32,0x41fb53d2,0x3f800000,2
+np.float32,0xc1fb53d2,0x3f800000,2
+np.float32,0x410a3ae7,0xbf3504fb,2
+np.float32,0xc10a3ae7,0xbf3504fb,2
+np.float32,0x418a3ae7,0x35b08908,2
+np.float32,0xc18a3ae7,0x35b08908,2
+np.float32,0x420a3ae7,0xbf800000,2
+np.float32,0xc20a3ae7,0xbf800000,2
+np.float32,0x4116cbe4,0xbf800000,2
+np.float32,0xc116cbe4,0xbf800000,2
+np.float32,0x4196cbe4,0x3f800000,2
+np.float32,0xc196cbe4,0x3f800000,2
+np.float32,0x4216cbe4,0x3f800000,2
+np.float32,0xc216cbe4,0x3f800000,2
+np.float32,0x41235ce2,0xbf3504ef,2
+np.float32,0xc1235ce2,0xbf3504ef,2
+np.float32,0x41a35ce2,0xb53889b6,2
+np.float32,0xc1a35ce2,0xb53889b6,2
+np.float32,0x42235ce2,0xbf800000,2
+np.float32,0xc2235ce2,0xbf800000,2
+np.float32,0x412fede0,0x353222c4,2
+np.float32,0xc12fede0,0x353222c4,2
+np.float32,0x41afede0,0xbf800000,2
+np.float32,0xc1afede0,0xbf800000,2
+np.float32,0x422fede0,0x3f800000,2
+np.float32,0xc22fede0,0x3f800000,2
+np.float32,0x413c7edd,0x3f3504f4,2
+np.float32,0xc13c7edd,0x3f3504f4,2
+np.float32,0x41bc7edd,0x33800add,2
+np.float32,0xc1bc7edd,0x33800add,2
+np.float32,0x423c7edd,0xbf800000,2
+np.float32,0xc23c7edd,0xbf800000,2
+np.float32,0x41490fdb,0x3f800000,2
+np.float32,0xc1490fdb,0x3f800000,2
+np.float32,0x41c90fdb,0x3f800000,2
+np.float32,0xc1c90fdb,0x3f800000,2
+np.float32,0x42490fdb,0x3f800000,2
+np.float32,0xc2490fdb,0x3f800000,2
+np.float32,0x4155a0d9,0x3f3504eb,2
+np.float32,0xc155a0d9,0x3f3504eb,2
+np.float32,0x41d5a0d9,0xb5b3bc81,2
+np.float32,0xc1d5a0d9,0xb5b3bc81,2
+np.float32,0x4255a0d9,0xbf800000,2
+np.float32,0xc255a0d9,0xbf800000,2
+np.float32,0x416231d6,0xb319a6a2,2
+np.float32,0xc16231d6,0xb319a6a2,2
+np.float32,0x41e231d6,0xbf800000,2
+np.float32,0xc1e231d6,0xbf800000,2
+np.float32,0x426231d6,0x3f800000,2
+np.float32,0xc26231d6,0x3f800000,2
+np.float32,0x416ec2d4,0xbf3504f7,2
+np.float32,0xc16ec2d4,0xbf3504f7,2
+np.float32,0x41eec2d4,0x353ef0a7,2
+np.float32,0xc1eec2d4,0x353ef0a7,2
+np.float32,0x426ec2d4,0xbf800000,2
+np.float32,0xc26ec2d4,0xbf800000,2
+np.float32,0x417b53d2,0xbf800000,2
+np.float32,0xc17b53d2,0xbf800000,2
+np.float32,0x41fb53d2,0x3f800000,2
+np.float32,0xc1fb53d2,0x3f800000,2
+np.float32,0x427b53d2,0x3f800000,2
+np.float32,0xc27b53d2,0x3f800000,2
+np.float32,0x4183f268,0xbf3504e7,2
+np.float32,0xc183f268,0xbf3504e7,2
+np.float32,0x4203f268,0xb6059a13,2
+np.float32,0xc203f268,0xb6059a13,2
+np.float32,0x4283f268,0xbf800000,2
+np.float32,0xc283f268,0xbf800000,2
+np.float32,0x418a3ae7,0x35b08908,2
+np.float32,0xc18a3ae7,0x35b08908,2
+np.float32,0x420a3ae7,0xbf800000,2
+np.float32,0xc20a3ae7,0xbf800000,2
+np.float32,0x428a3ae7,0x3f800000,2
+np.float32,0xc28a3ae7,0x3f800000,2
+np.float32,0x41908365,0x3f3504f0,2
+np.float32,0xc1908365,0x3f3504f0,2
+np.float32,0x42108365,0xb512200d,2
+np.float32,0xc2108365,0xb512200d,2
+np.float32,0x42908365,0xbf800000,2
+np.float32,0xc2908365,0xbf800000,2
+np.float32,0x4196cbe4,0x3f800000,2
+np.float32,0xc196cbe4,0x3f800000,2
+np.float32,0x4216cbe4,0x3f800000,2
+np.float32,0xc216cbe4,0x3f800000,2
+np.float32,0x4296cbe4,0x3f800000,2
+np.float32,0xc296cbe4,0x3f800000,2
+np.float32,0x419d1463,0x3f3504ef,2
+np.float32,0xc19d1463,0x3f3504ef,2
+np.float32,0x421d1463,0xb5455799,2
+np.float32,0xc21d1463,0xb5455799,2
+np.float32,0x429d1463,0xbf800000,2
+np.float32,0xc29d1463,0xbf800000,2
+np.float32,0x41a35ce2,0xb53889b6,2
+np.float32,0xc1a35ce2,0xb53889b6,2
+np.float32,0x42235ce2,0xbf800000,2
+np.float32,0xc2235ce2,0xbf800000,2
+np.float32,0x42a35ce2,0x3f800000,2
+np.float32,0xc2a35ce2,0x3f800000,2
+np.float32,0x41a9a561,0xbf3504ff,2
+np.float32,0xc1a9a561,0xbf3504ff,2
+np.float32,0x4229a561,0x360733d0,2
+np.float32,0xc229a561,0x360733d0,2
+np.float32,0x42a9a561,0xbf800000,2
+np.float32,0xc2a9a561,0xbf800000,2
+np.float32,0x41afede0,0xbf800000,2
+np.float32,0xc1afede0,0xbf800000,2
+np.float32,0x422fede0,0x3f800000,2
+np.float32,0xc22fede0,0x3f800000,2
+np.float32,0x42afede0,0x3f800000,2
+np.float32,0xc2afede0,0x3f800000,2
+np.float32,0x41b6365e,0xbf3504f6,2
+np.float32,0xc1b6365e,0xbf3504f6,2
+np.float32,0x4236365e,0x350bb91c,2
+np.float32,0xc236365e,0x350bb91c,2
+np.float32,0x42b6365e,0xbf800000,2
+np.float32,0xc2b6365e,0xbf800000,2
+np.float32,0x41bc7edd,0x33800add,2
+np.float32,0xc1bc7edd,0x33800add,2
+np.float32,0x423c7edd,0xbf800000,2
+np.float32,0xc23c7edd,0xbf800000,2
+np.float32,0x42bc7edd,0x3f800000,2
+np.float32,0xc2bc7edd,0x3f800000,2
+np.float32,0x41c2c75c,0x3f3504f8,2
+np.float32,0xc1c2c75c,0x3f3504f8,2
+np.float32,0x4242c75c,0x354bbe8a,2
+np.float32,0xc242c75c,0x354bbe8a,2
+np.float32,0x42c2c75c,0xbf800000,2
+np.float32,0xc2c2c75c,0xbf800000,2
+np.float32,0x41c90fdb,0x3f800000,2
+np.float32,0xc1c90fdb,0x3f800000,2
+np.float32,0x42490fdb,0x3f800000,2
+np.float32,0xc2490fdb,0x3f800000,2
+np.float32,0x42c90fdb,0x3f800000,2
+np.float32,0xc2c90fdb,0x3f800000,2
+np.float32,0x41cf585a,0x3f3504e7,2
+np.float32,0xc1cf585a,0x3f3504e7,2
+np.float32,0x424f585a,0xb608cd8c,2
+np.float32,0xc24f585a,0xb608cd8c,2
+np.float32,0x42cf585a,0xbf800000,2
+np.float32,0xc2cf585a,0xbf800000,2
+np.float32,0x41d5a0d9,0xb5b3bc81,2
+np.float32,0xc1d5a0d9,0xb5b3bc81,2
+np.float32,0x4255a0d9,0xbf800000,2
+np.float32,0xc255a0d9,0xbf800000,2
+np.float32,0x42d5a0d9,0x3f800000,2
+np.float32,0xc2d5a0d9,0x3f800000,2
+np.float32,0x41dbe958,0xbf350507,2
+np.float32,0xc1dbe958,0xbf350507,2
+np.float32,0x425be958,0x365eab75,2
+np.float32,0xc25be958,0x365eab75,2
+np.float32,0x42dbe958,0xbf800000,2
+np.float32,0xc2dbe958,0xbf800000,2
+np.float32,0x41e231d6,0xbf800000,2
+np.float32,0xc1e231d6,0xbf800000,2
+np.float32,0x426231d6,0x3f800000,2
+np.float32,0xc26231d6,0x3f800000,2
+np.float32,0x42e231d6,0x3f800000,2
+np.float32,0xc2e231d6,0x3f800000,2
+np.float32,0x41e87a55,0xbf3504ef,2
+np.float32,0xc1e87a55,0xbf3504ef,2
+np.float32,0x42687a55,0xb552257b,2
+np.float32,0xc2687a55,0xb552257b,2
+np.float32,0x42e87a55,0xbf800000,2
+np.float32,0xc2e87a55,0xbf800000,2
+np.float32,0x41eec2d4,0x353ef0a7,2
+np.float32,0xc1eec2d4,0x353ef0a7,2
+np.float32,0x426ec2d4,0xbf800000,2
+np.float32,0xc26ec2d4,0xbf800000,2
+np.float32,0x42eec2d4,0x3f800000,2
+np.float32,0xc2eec2d4,0x3f800000,2
+np.float32,0x41f50b53,0x3f3504ff,2
+np.float32,0xc1f50b53,0x3f3504ff,2
+np.float32,0x42750b53,0x360a6748,2
+np.float32,0xc2750b53,0x360a6748,2
+np.float32,0x42f50b53,0xbf800000,2
+np.float32,0xc2f50b53,0xbf800000,2
+np.float32,0x41fb53d2,0x3f800000,2
+np.float32,0xc1fb53d2,0x3f800000,2
+np.float32,0x427b53d2,0x3f800000,2
+np.float32,0xc27b53d2,0x3f800000,2
+np.float32,0x42fb53d2,0x3f800000,2
+np.float32,0xc2fb53d2,0x3f800000,2
+np.float32,0x4200ce28,0x3f3504f6,2
+np.float32,0xc200ce28,0x3f3504f6,2
+np.float32,0x4280ce28,0x34fdd672,2
+np.float32,0xc280ce28,0x34fdd672,2
+np.float32,0x4300ce28,0xbf800000,2
+np.float32,0xc300ce28,0xbf800000,2
+np.float32,0x4203f268,0xb6059a13,2
+np.float32,0xc203f268,0xb6059a13,2
+np.float32,0x4283f268,0xbf800000,2
+np.float32,0xc283f268,0xbf800000,2
+np.float32,0x4303f268,0x3f800000,2
+np.float32,0xc303f268,0x3f800000,2
+np.float32,0x420716a7,0xbf3504f8,2
+np.float32,0xc20716a7,0xbf3504f8,2
+np.float32,0x428716a7,0x35588c6d,2
+np.float32,0xc28716a7,0x35588c6d,2
+np.float32,0x430716a7,0xbf800000,2
+np.float32,0xc30716a7,0xbf800000,2
+np.float32,0x420a3ae7,0xbf800000,2
+np.float32,0xc20a3ae7,0xbf800000,2
+np.float32,0x428a3ae7,0x3f800000,2
+np.float32,0xc28a3ae7,0x3f800000,2
+np.float32,0x430a3ae7,0x3f800000,2
+np.float32,0xc30a3ae7,0x3f800000,2
+np.float32,0x420d5f26,0xbf3504e7,2
+np.float32,0xc20d5f26,0xbf3504e7,2
+np.float32,0x428d5f26,0xb60c0105,2
+np.float32,0xc28d5f26,0xb60c0105,2
+np.float32,0x430d5f26,0xbf800000,2
+np.float32,0xc30d5f26,0xbf800000,2
+np.float32,0x42108365,0xb512200d,2
+np.float32,0xc2108365,0xb512200d,2
+np.float32,0x42908365,0xbf800000,2
+np.float32,0xc2908365,0xbf800000,2
+np.float32,0x43108365,0x3f800000,2
+np.float32,0xc3108365,0x3f800000,2
+np.float32,0x4213a7a5,0x3f350507,2
+np.float32,0xc213a7a5,0x3f350507,2
+np.float32,0x4293a7a5,0x3661deee,2
+np.float32,0xc293a7a5,0x3661deee,2
+np.float32,0x4313a7a5,0xbf800000,2
+np.float32,0xc313a7a5,0xbf800000,2
+np.float32,0x4216cbe4,0x3f800000,2
+np.float32,0xc216cbe4,0x3f800000,2
+np.float32,0x4296cbe4,0x3f800000,2
+np.float32,0xc296cbe4,0x3f800000,2
+np.float32,0x4316cbe4,0x3f800000,2
+np.float32,0xc316cbe4,0x3f800000,2
+np.float32,0x4219f024,0x3f3504d8,2
+np.float32,0xc219f024,0x3f3504d8,2
+np.float32,0x4299f024,0xb69bde6c,2
+np.float32,0xc299f024,0xb69bde6c,2
+np.float32,0x4319f024,0xbf800000,2
+np.float32,0xc319f024,0xbf800000,2
+np.float32,0x421d1463,0xb5455799,2
+np.float32,0xc21d1463,0xb5455799,2
+np.float32,0x429d1463,0xbf800000,2
+np.float32,0xc29d1463,0xbf800000,2
+np.float32,0x431d1463,0x3f800000,2
+np.float32,0xc31d1463,0x3f800000,2
+np.float32,0x422038a3,0xbf350516,2
+np.float32,0xc22038a3,0xbf350516,2
+np.float32,0x42a038a3,0x36c6cd61,2
+np.float32,0xc2a038a3,0x36c6cd61,2
+np.float32,0x432038a3,0xbf800000,2
+np.float32,0xc32038a3,0xbf800000,2
+np.float32,0x42235ce2,0xbf800000,2
+np.float32,0xc2235ce2,0xbf800000,2
+np.float32,0x42a35ce2,0x3f800000,2
+np.float32,0xc2a35ce2,0x3f800000,2
+np.float32,0x43235ce2,0x3f800000,2
+np.float32,0xc3235ce2,0x3f800000,2
+np.float32,0x42268121,0xbf3504f6,2
+np.float32,0xc2268121,0xbf3504f6,2
+np.float32,0x42a68121,0x34e43aac,2
+np.float32,0xc2a68121,0x34e43aac,2
+np.float32,0x43268121,0xbf800000,2
+np.float32,0xc3268121,0xbf800000,2
+np.float32,0x4229a561,0x360733d0,2
+np.float32,0xc229a561,0x360733d0,2
+np.float32,0x42a9a561,0xbf800000,2
+np.float32,0xc2a9a561,0xbf800000,2
+np.float32,0x4329a561,0x3f800000,2
+np.float32,0xc329a561,0x3f800000,2
+np.float32,0x422cc9a0,0x3f3504f8,2
+np.float32,0xc22cc9a0,0x3f3504f8,2
+np.float32,0x42acc9a0,0x35655a50,2
+np.float32,0xc2acc9a0,0x35655a50,2
+np.float32,0x432cc9a0,0xbf800000,2
+np.float32,0xc32cc9a0,0xbf800000,2
+np.float32,0x422fede0,0x3f800000,2
+np.float32,0xc22fede0,0x3f800000,2
+np.float32,0x42afede0,0x3f800000,2
+np.float32,0xc2afede0,0x3f800000,2
+np.float32,0x432fede0,0x3f800000,2
+np.float32,0xc32fede0,0x3f800000,2
+np.float32,0x4233121f,0x3f3504e7,2
+np.float32,0xc233121f,0x3f3504e7,2
+np.float32,0x42b3121f,0xb60f347d,2
+np.float32,0xc2b3121f,0xb60f347d,2
+np.float32,0x4333121f,0xbf800000,2
+np.float32,0xc333121f,0xbf800000,2
+np.float32,0x4236365e,0x350bb91c,2
+np.float32,0xc236365e,0x350bb91c,2
+np.float32,0x42b6365e,0xbf800000,2
+np.float32,0xc2b6365e,0xbf800000,2
+np.float32,0x4336365e,0x3f800000,2
+np.float32,0xc336365e,0x3f800000,2
+np.float32,0x42395a9e,0xbf350507,2
+np.float32,0xc2395a9e,0xbf350507,2
+np.float32,0x42b95a9e,0x36651267,2
+np.float32,0xc2b95a9e,0x36651267,2
+np.float32,0x43395a9e,0xbf800000,2
+np.float32,0xc3395a9e,0xbf800000,2
+np.float32,0x423c7edd,0xbf800000,2
+np.float32,0xc23c7edd,0xbf800000,2
+np.float32,0x42bc7edd,0x3f800000,2
+np.float32,0xc2bc7edd,0x3f800000,2
+np.float32,0x433c7edd,0x3f800000,2
+np.float32,0xc33c7edd,0x3f800000,2
+np.float32,0x423fa31d,0xbf3504d7,2
+np.float32,0xc23fa31d,0xbf3504d7,2
+np.float32,0x42bfa31d,0xb69d7828,2
+np.float32,0xc2bfa31d,0xb69d7828,2
+np.float32,0x433fa31d,0xbf800000,2
+np.float32,0xc33fa31d,0xbf800000,2
+np.float32,0x4242c75c,0x354bbe8a,2
+np.float32,0xc242c75c,0x354bbe8a,2
+np.float32,0x42c2c75c,0xbf800000,2
+np.float32,0xc2c2c75c,0xbf800000,2
+np.float32,0x4342c75c,0x3f800000,2
+np.float32,0xc342c75c,0x3f800000,2
+np.float32,0x4245eb9c,0x3f350517,2
+np.float32,0xc245eb9c,0x3f350517,2
+np.float32,0x42c5eb9c,0x36c8671d,2
+np.float32,0xc2c5eb9c,0x36c8671d,2
+np.float32,0x4345eb9c,0xbf800000,2
+np.float32,0xc345eb9c,0xbf800000,2
+np.float32,0x42490fdb,0x3f800000,2
+np.float32,0xc2490fdb,0x3f800000,2
+np.float32,0x42c90fdb,0x3f800000,2
+np.float32,0xc2c90fdb,0x3f800000,2
+np.float32,0x43490fdb,0x3f800000,2
+np.float32,0xc3490fdb,0x3f800000,2
+np.float32,0x424c341a,0x3f3504f5,2
+np.float32,0xc24c341a,0x3f3504f5,2
+np.float32,0x42cc341a,0x34ca9ee6,2
+np.float32,0xc2cc341a,0x34ca9ee6,2
+np.float32,0x434c341a,0xbf800000,2
+np.float32,0xc34c341a,0xbf800000,2
+np.float32,0x424f585a,0xb608cd8c,2
+np.float32,0xc24f585a,0xb608cd8c,2
+np.float32,0x42cf585a,0xbf800000,2
+np.float32,0xc2cf585a,0xbf800000,2
+np.float32,0x434f585a,0x3f800000,2
+np.float32,0xc34f585a,0x3f800000,2
+np.float32,0x42527c99,0xbf3504f9,2
+np.float32,0xc2527c99,0xbf3504f9,2
+np.float32,0x42d27c99,0x35722833,2
+np.float32,0xc2d27c99,0x35722833,2
+np.float32,0x43527c99,0xbf800000,2
+np.float32,0xc3527c99,0xbf800000,2
+np.float32,0x4255a0d9,0xbf800000,2
+np.float32,0xc255a0d9,0xbf800000,2
+np.float32,0x42d5a0d9,0x3f800000,2
+np.float32,0xc2d5a0d9,0x3f800000,2
+np.float32,0x4355a0d9,0x3f800000,2
+np.float32,0xc355a0d9,0x3f800000,2
+np.float32,0x4258c518,0xbf3504e6,2
+np.float32,0xc258c518,0xbf3504e6,2
+np.float32,0x42d8c518,0xb61267f6,2
+np.float32,0xc2d8c518,0xb61267f6,2
+np.float32,0x4358c518,0xbf800000,2
+np.float32,0xc358c518,0xbf800000,2
+np.float32,0x425be958,0x365eab75,2
+np.float32,0xc25be958,0x365eab75,2
+np.float32,0x42dbe958,0xbf800000,2
+np.float32,0xc2dbe958,0xbf800000,2
+np.float32,0x435be958,0x3f800000,2
+np.float32,0xc35be958,0x3f800000,2
+np.float32,0x425f0d97,0x3f350508,2
+np.float32,0xc25f0d97,0x3f350508,2
+np.float32,0x42df0d97,0x366845e0,2
+np.float32,0xc2df0d97,0x366845e0,2
+np.float32,0x435f0d97,0xbf800000,2
+np.float32,0xc35f0d97,0xbf800000,2
+np.float32,0x426231d6,0x3f800000,2
+np.float32,0xc26231d6,0x3f800000,2
+np.float32,0x42e231d6,0x3f800000,2
+np.float32,0xc2e231d6,0x3f800000,2
+np.float32,0x436231d6,0x3f800000,2
+np.float32,0xc36231d6,0x3f800000,2
+np.float32,0x42655616,0x3f3504d7,2
+np.float32,0xc2655616,0x3f3504d7,2
+np.float32,0x42e55616,0xb69f11e5,2
+np.float32,0xc2e55616,0xb69f11e5,2
+np.float32,0x43655616,0xbf800000,2
+np.float32,0xc3655616,0xbf800000,2
+np.float32,0x42687a55,0xb552257b,2
+np.float32,0xc2687a55,0xb552257b,2
+np.float32,0x42e87a55,0xbf800000,2
+np.float32,0xc2e87a55,0xbf800000,2
+np.float32,0x43687a55,0x3f800000,2
+np.float32,0xc3687a55,0x3f800000,2
+np.float32,0x426b9e95,0xbf350517,2
+np.float32,0xc26b9e95,0xbf350517,2
+np.float32,0x42eb9e95,0x36ca00d9,2
+np.float32,0xc2eb9e95,0x36ca00d9,2
+np.float32,0x436b9e95,0xbf800000,2
+np.float32,0xc36b9e95,0xbf800000,2
+np.float32,0x426ec2d4,0xbf800000,2
+np.float32,0xc26ec2d4,0xbf800000,2
+np.float32,0x42eec2d4,0x3f800000,2
+np.float32,0xc2eec2d4,0x3f800000,2
+np.float32,0x436ec2d4,0x3f800000,2
+np.float32,0xc36ec2d4,0x3f800000,2
+np.float32,0x4271e713,0xbf3504f5,2
+np.float32,0xc271e713,0xbf3504f5,2
+np.float32,0x42f1e713,0x34b10321,2
+np.float32,0xc2f1e713,0x34b10321,2
+np.float32,0x4371e713,0xbf800000,2
+np.float32,0xc371e713,0xbf800000,2
+np.float32,0x42750b53,0x360a6748,2
+np.float32,0xc2750b53,0x360a6748,2
+np.float32,0x42f50b53,0xbf800000,2
+np.float32,0xc2f50b53,0xbf800000,2
+np.float32,0x43750b53,0x3f800000,2
+np.float32,0xc3750b53,0x3f800000,2
+np.float32,0x42782f92,0x3f3504f9,2
+np.float32,0xc2782f92,0x3f3504f9,2
+np.float32,0x42f82f92,0x357ef616,2
+np.float32,0xc2f82f92,0x357ef616,2
+np.float32,0x43782f92,0xbf800000,2
+np.float32,0xc3782f92,0xbf800000,2
+np.float32,0x427b53d2,0x3f800000,2
+np.float32,0xc27b53d2,0x3f800000,2
+np.float32,0x42fb53d2,0x3f800000,2
+np.float32,0xc2fb53d2,0x3f800000,2
+np.float32,0x437b53d2,0x3f800000,2
+np.float32,0xc37b53d2,0x3f800000,2
+np.float32,0x427e7811,0x3f3504e6,2
+np.float32,0xc27e7811,0x3f3504e6,2
+np.float32,0x42fe7811,0xb6159b6f,2
+np.float32,0xc2fe7811,0xb6159b6f,2
+np.float32,0x437e7811,0xbf800000,2
+np.float32,0xc37e7811,0xbf800000,2
+np.float32,0x4280ce28,0x34fdd672,2
+np.float32,0xc280ce28,0x34fdd672,2
+np.float32,0x4300ce28,0xbf800000,2
+np.float32,0xc300ce28,0xbf800000,2
+np.float32,0x4380ce28,0x3f800000,2
+np.float32,0xc380ce28,0x3f800000,2
+np.float32,0x42826048,0xbf350508,2
+np.float32,0xc2826048,0xbf350508,2
+np.float32,0x43026048,0x366b7958,2
+np.float32,0xc3026048,0x366b7958,2
+np.float32,0x43826048,0xbf800000,2
+np.float32,0xc3826048,0xbf800000,2
+np.float32,0x4283f268,0xbf800000,2
+np.float32,0xc283f268,0xbf800000,2
+np.float32,0x4303f268,0x3f800000,2
+np.float32,0xc303f268,0x3f800000,2
+np.float32,0x4383f268,0x3f800000,2
+np.float32,0xc383f268,0x3f800000,2
+np.float32,0x42858487,0xbf350504,2
+np.float32,0xc2858487,0xbf350504,2
+np.float32,0x43058487,0x363ea8be,2
+np.float32,0xc3058487,0x363ea8be,2
+np.float32,0x43858487,0xbf800000,2
+np.float32,0xc3858487,0xbf800000,2
+np.float32,0x428716a7,0x35588c6d,2
+np.float32,0xc28716a7,0x35588c6d,2
+np.float32,0x430716a7,0xbf800000,2
+np.float32,0xc30716a7,0xbf800000,2
+np.float32,0x438716a7,0x3f800000,2
+np.float32,0xc38716a7,0x3f800000,2
+np.float32,0x4288a8c7,0x3f350517,2
+np.float32,0xc288a8c7,0x3f350517,2
+np.float32,0x4308a8c7,0x36cb9a96,2
+np.float32,0xc308a8c7,0x36cb9a96,2
+np.float32,0x4388a8c7,0xbf800000,2
+np.float32,0xc388a8c7,0xbf800000,2
+np.float32,0x428a3ae7,0x3f800000,2
+np.float32,0xc28a3ae7,0x3f800000,2
+np.float32,0x430a3ae7,0x3f800000,2
+np.float32,0xc30a3ae7,0x3f800000,2
+np.float32,0x438a3ae7,0x3f800000,2
+np.float32,0xc38a3ae7,0x3f800000,2
+np.float32,0x428bcd06,0x3f3504f5,2
+np.float32,0xc28bcd06,0x3f3504f5,2
+np.float32,0x430bcd06,0x3497675b,2
+np.float32,0xc30bcd06,0x3497675b,2
+np.float32,0x438bcd06,0xbf800000,2
+np.float32,0xc38bcd06,0xbf800000,2
+np.float32,0x428d5f26,0xb60c0105,2
+np.float32,0xc28d5f26,0xb60c0105,2
+np.float32,0x430d5f26,0xbf800000,2
+np.float32,0xc30d5f26,0xbf800000,2
+np.float32,0x438d5f26,0x3f800000,2
+np.float32,0xc38d5f26,0x3f800000,2
+np.float32,0x428ef146,0xbf350526,2
+np.float32,0xc28ef146,0xbf350526,2
+np.float32,0x430ef146,0x3710bc40,2
+np.float32,0xc30ef146,0x3710bc40,2
+np.float32,0x438ef146,0xbf800000,2
+np.float32,0xc38ef146,0xbf800000,2
+np.float32,0x42908365,0xbf800000,2
+np.float32,0xc2908365,0xbf800000,2
+np.float32,0x43108365,0x3f800000,2
+np.float32,0xc3108365,0x3f800000,2
+np.float32,0x43908365,0x3f800000,2
+np.float32,0xc3908365,0x3f800000,2
+np.float32,0x42921585,0xbf3504e6,2
+np.float32,0xc2921585,0xbf3504e6,2
+np.float32,0x43121585,0xb618cee8,2
+np.float32,0xc3121585,0xb618cee8,2
+np.float32,0x43921585,0xbf800000,2
+np.float32,0xc3921585,0xbf800000,2
+np.float32,0x4293a7a5,0x3661deee,2
+np.float32,0xc293a7a5,0x3661deee,2
+np.float32,0x4313a7a5,0xbf800000,2
+np.float32,0xc313a7a5,0xbf800000,2
+np.float32,0x4393a7a5,0x3f800000,2
+np.float32,0xc393a7a5,0x3f800000,2
+np.float32,0x429539c5,0x3f350536,2
+np.float32,0xc29539c5,0x3f350536,2
+np.float32,0x431539c5,0x373bab34,2
+np.float32,0xc31539c5,0x373bab34,2
+np.float32,0x439539c5,0xbf800000,2
+np.float32,0xc39539c5,0xbf800000,2
+np.float32,0x4296cbe4,0x3f800000,2
+np.float32,0xc296cbe4,0x3f800000,2
+np.float32,0x4316cbe4,0x3f800000,2
+np.float32,0xc316cbe4,0x3f800000,2
+np.float32,0x4396cbe4,0x3f800000,2
+np.float32,0xc396cbe4,0x3f800000,2
+np.float32,0x42985e04,0x3f3504d7,2
+np.float32,0xc2985e04,0x3f3504d7,2
+np.float32,0x43185e04,0xb6a2455d,2
+np.float32,0xc3185e04,0xb6a2455d,2
+np.float32,0x43985e04,0xbf800000,2
+np.float32,0xc3985e04,0xbf800000,2
+np.float32,0x4299f024,0xb69bde6c,2
+np.float32,0xc299f024,0xb69bde6c,2
+np.float32,0x4319f024,0xbf800000,2
+np.float32,0xc319f024,0xbf800000,2
+np.float32,0x4399f024,0x3f800000,2
+np.float32,0xc399f024,0x3f800000,2
+np.float32,0x429b8243,0xbf3504ea,2
+np.float32,0xc29b8243,0xbf3504ea,2
+np.float32,0x431b8243,0xb5cb2eb8,2
+np.float32,0xc31b8243,0xb5cb2eb8,2
+np.float32,0x439b8243,0xbf800000,2
+np.float32,0xc39b8243,0xbf800000,2
+np.float32,0x435b2047,0x3f3504c1,2
+np.float32,0x42a038a2,0xb5e4ca7e,2
+np.float32,0x432038a2,0xbf800000,2
+np.float32,0x4345eb9b,0xbf800000,2
+np.float32,0x42c5eb9b,0xb5de638c,2
+np.float32,0x42eb9e94,0xb5d7fc9b,2
+np.float32,0x4350ea79,0x3631dadb,2
+np.float32,0x42dbe957,0xbf800000,2
+np.float32,0x425be957,0xb505522a,2
+np.float32,0x435be957,0x3f800000,2
+np.float32,0x487fe5ab,0xba140185,2
+np.float32,0x497fe5ab,0x3f7fffd5,2
+np.float32,0x49ffe5ab,0x3f7fff55,2
+np.float32,0x49ffeb37,0x3b9382f5,2
+np.float32,0x497ff0c3,0x3b13049f,2
+np.float32,0x49fff0c3,0xbf7fff57,2
+np.float32,0x49fff64f,0xbb928618,2
+np.float32,0x497ffbdb,0xbf7fffd6,2
+np.float32,0x49fffbdb,0x3f7fff59,2
+np.float32,0x48fffbdb,0xba9207c6,2
+np.float32,0x4e736e56,0xbf800000,2
+np.float32,0x4d4da377,0xbf800000,2
+np.float32,0x4ece58c3,0xbf800000,2
+np.float32,0x4ee0db9c,0xbf800000,2
+np.float32,0x4dee7002,0x3f800000,2
+np.float32,0x4ee86afc,0x38857a23,2
+np.float32,0x4dca4f3f,0xbf800000,2
+np.float32,0x4ecb48af,0xb95d1e10,2
+np.float32,0x4e51e33f,0xbf800000,2
+np.float32,0x4ef5f421,0xbf800000,2
+np.float32,0x46027eb2,0x3e7d94c9,2
+np.float32,0x4477baed,0xbe7f1824,2
+np.float32,0x454b8024,0x3e7f5268,2
+np.float32,0x455d2c09,0x3e7f40cb,2
+np.float32,0x4768d3de,0xba14b4af,2
+np.float32,0x46c1e7cd,0x3e7fb102,2
+np.float32,0x44a52949,0xbe7dc9d5,2
+np.float32,0x4454633a,0x3e7dbc7d,2
+np.float32,0x4689810b,0x3e7eb02b,2
+np.float32,0x473473cd,0xbe7eef6f,2
+np.float32,0x44a5193f,0x3e7e1b1f,2
+np.float32,0x46004b36,0x3e7dac59,2
+np.float32,0x467f604b,0x3d7ffd3a,2
+np.float32,0x45ea1805,0x3dffd2e0,2
+np.float32,0x457b6af3,0x3dff7831,2
+np.float32,0x44996159,0xbe7d85f4,2
+np.float32,0x47883553,0xbb80584e,2
+np.float32,0x44e19f0c,0xbdffcfe6,2
+np.float32,0x472b3bf6,0xbe7f7a82,2
+np.float32,0x4600bb4e,0x3a135e33,2
+np.float32,0x449f4556,0x3e7e42e5,2
+np.float32,0x474e9420,0x3dff77b2,2
+np.float32,0x45cbdb23,0x3dff7240,2
+np.float32,0x44222747,0x3dffb039,2
+np.float32,0x4772e419,0xbdff74b8,2
diff --git a/numpy/core/tests/data/umath-validation-set-exp b/numpy/core/tests/data/umath-validation-set-exp
new file mode 100644
index 000000000..1b2cc9ce4
--- /dev/null
+++ b/numpy/core/tests/data/umath-validation-set-exp
@@ -0,0 +1,135 @@
+dtype,input,output,ulperrortol
+## +ve denormals ##
+np.float32,0x004b4716,0x3f800000,3
+np.float32,0x007b2490,0x3f800000,3
+np.float32,0x007c99fa,0x3f800000,3
+np.float32,0x00734a0c,0x3f800000,3
+np.float32,0x0070de24,0x3f800000,3
+np.float32,0x00495d65,0x3f800000,3
+np.float32,0x006894f6,0x3f800000,3
+np.float32,0x00555a76,0x3f800000,3
+np.float32,0x004e1fb8,0x3f800000,3
+np.float32,0x00687de9,0x3f800000,3
+## -ve denormals ##
+np.float32,0x805b59af,0x3f800000,3
+np.float32,0x807ed8ed,0x3f800000,3
+np.float32,0x807142ad,0x3f800000,3
+np.float32,0x80772002,0x3f800000,3
+np.float32,0x8062abcb,0x3f800000,3
+np.float32,0x8045e31c,0x3f800000,3
+np.float32,0x805f01c2,0x3f800000,3
+np.float32,0x80506432,0x3f800000,3
+np.float32,0x8060089d,0x3f800000,3
+np.float32,0x8071292f,0x3f800000,3
+## floats that output a denormal ##
+np.float32,0xc2cf3fc1,0x00000001,3
+np.float32,0xc2c79726,0x00000021,3
+np.float32,0xc2cb295d,0x00000005,3
+np.float32,0xc2b49e6b,0x00068c4c,3
+np.float32,0xc2ca8116,0x00000008,3
+np.float32,0xc2c23f82,0x000001d7,3
+np.float32,0xc2cb69c0,0x00000005,3
+np.float32,0xc2cc1f4d,0x00000003,3
+np.float32,0xc2ae094e,0x00affc4c,3
+np.float32,0xc2c86c44,0x00000015,3
+## random floats between -87.0f and 88.0f ##
+np.float32,0x4030d7e0,0x417d9a05,3
+np.float32,0x426f60e8,0x6aa1be2c,3
+np.float32,0x41a1b220,0x4e0efc11,3
+np.float32,0xc20cc722,0x26159da7,3
+np.float32,0x41c492bc,0x512ec79d,3
+np.float32,0x40980210,0x42e73a0e,3
+np.float32,0xbf1f7b80,0x3f094de3,3
+np.float32,0x42a678a4,0x7b87a383,3
+np.float32,0xc20f3cfd,0x25a1c304,3
+np.float32,0x423ff34c,0x6216467f,3
+np.float32,0x00000000,0x3f800000,3
+## floats that cause an overflow ##
+np.float32,0x7f06d8c1,0x7f800000,3
+np.float32,0x7f451912,0x7f800000,3
+np.float32,0x7ecceac3,0x7f800000,3
+np.float32,0x7f643b45,0x7f800000,3
+np.float32,0x7e910ea0,0x7f800000,3
+np.float32,0x7eb4756b,0x7f800000,3
+np.float32,0x7f4ec708,0x7f800000,3
+np.float32,0x7f6b4551,0x7f800000,3
+np.float32,0x7d8edbda,0x7f800000,3
+np.float32,0x7f730718,0x7f800000,3
+np.float32,0x42b17217,0x7f7fff84,3
+np.float32,0x42b17218,0x7f800000,3
+np.float32,0x42b17219,0x7f800000,3
+np.float32,0xfef2b0bc,0x00000000,3
+np.float32,0xff69f83e,0x00000000,3
+np.float32,0xff4ecb12,0x00000000,3
+np.float32,0xfeac6d86,0x00000000,3
+np.float32,0xfde0cdb8,0x00000000,3
+np.float32,0xff26aef4,0x00000000,3
+np.float32,0xff6f9277,0x00000000,3
+np.float32,0xff7adfc4,0x00000000,3
+np.float32,0xff0ad40e,0x00000000,3
+np.float32,0xff6fd8f3,0x00000000,3
+np.float32,0xc2cff1b4,0x00000001,3
+np.float32,0xc2cff1b5,0x00000000,3
+np.float32,0xc2cff1b6,0x00000000,3
+np.float32,0x7f800000,0x7f800000,3
+np.float32,0xff800000,0x00000000,3
+np.float32,0x4292f27c,0x7480000a,3
+np.float32,0x42a920be,0x7c7fff94,3
+np.float32,0x41c214c9,0x50ffffd9,3
+np.float32,0x41abe686,0x4effffd9,3
+np.float32,0x4287db5a,0x707fffd3,3
+np.float32,0x41902cbb,0x4c800078,3
+np.float32,0x42609466,0x67ffffeb,3
+np.float32,0x41a65af5,0x4e7fffd1,3
+np.float32,0x417f13ff,0x4affffc9,3
+np.float32,0x426d0e6c,0x6a3504f2,3
+np.float32,0x41bc8934,0x507fff51,3
+np.float32,0x42a7bdde,0x7c0000d6,3
+np.float32,0x4120cf66,0x46b504f6,3
+np.float32,0x4244da8f,0x62ffff1a,3
+np.float32,0x41a0cf69,0x4e000034,3
+np.float32,0x41cd2bec,0x52000005,3
+np.float32,0x42893e41,0x7100009e,3
+np.float32,0x41b437e1,0x4fb50502,3
+np.float32,0x41d8430f,0x5300001d,3
+np.float32,0x4244da92,0x62ffffda,3
+np.float32,0x41a0cf63,0x4dffffa9,3
+np.float32,0x3eb17218,0x3fb504f3,3
+np.float32,0x428729e8,0x703504dc,3
+np.float32,0x41a0cf67,0x4e000014,3
+np.float32,0x4252b77d,0x65800011,3
+np.float32,0x41902cb9,0x4c800058,3
+np.float32,0x42a0cf67,0x79800052,3
+np.float32,0x4152b77b,0x48ffffe9,3
+np.float32,0x41265af3,0x46ffffc8,3
+np.float32,0x42187e0b,0x5affff9a,3
+np.float32,0xc0d2b77c,0x3ab504f6,3
+np.float32,0xc283b2ac,0x10000072,3
+np.float32,0xc1cff1b4,0x2cb504f5,3
+np.float32,0xc05dce9e,0x3d000000,3
+np.float32,0xc28ec9d2,0x0bfffea5,3
+np.float32,0xc23c893a,0x1d7fffde,3
+np.float32,0xc2a920c0,0x027fff6c,3
+np.float32,0xc1f9886f,0x2900002b,3
+np.float32,0xc2c42920,0x000000b5,3
+np.float32,0xc2893e41,0x0dfffec5,3
+np.float32,0xc2c4da93,0x00000080,3
+np.float32,0xc17f1401,0x3400000c,3
+np.float32,0xc1902cb6,0x327fffaf,3
+np.float32,0xc27c4e3b,0x11ffffc5,3
+np.float32,0xc268e5c5,0x157ffe9d,3
+np.float32,0xc2b4e953,0x0005a826,3
+np.float32,0xc287db5a,0x0e800016,3
+np.float32,0xc207db5a,0x2700000b,3
+np.float32,0xc2b2d4fe,0x000ffff1,3
+np.float32,0xc268e5c0,0x157fffdd,3
+np.float32,0xc22920bd,0x2100003b,3
+np.float32,0xc2902caf,0x0b80011e,3
+np.float32,0xc1902cba,0x327fff2f,3
+np.float32,0xc2ca6625,0x00000008,3
+np.float32,0xc280ece8,0x10fffeb5,3
+np.float32,0xc2918f94,0x0b0000ea,3
+np.float32,0xc29b43d5,0x077ffffc,3
+np.float32,0xc1e61ff7,0x2ab504f5,3
+np.float32,0xc2867878,0x0effff15,3
+np.float32,0xc2a2324a,0x04fffff4,3
diff --git a/numpy/core/tests/data/umath-validation-set-log b/numpy/core/tests/data/umath-validation-set-log
new file mode 100644
index 000000000..a7bd98481
--- /dev/null
+++ b/numpy/core/tests/data/umath-validation-set-log
@@ -0,0 +1,118 @@
+dtype,input,output,ulperrortol
+## +ve denormals ##
+np.float32,0x004b4716,0xc2afbc1b,4
+np.float32,0x007b2490,0xc2aec01e,4
+np.float32,0x007c99fa,0xc2aeba17,4
+np.float32,0x00734a0c,0xc2aee1dc,4
+np.float32,0x0070de24,0xc2aeecba,4
+np.float32,0x007fffff,0xc2aeac50,4
+np.float32,0x00000001,0xc2ce8ed0,4
+## -ve denormals ##
+np.float32,0x80495d65,0xffc00000,4
+np.float32,0x806894f6,0xffc00000,4
+np.float32,0x80555a76,0xffc00000,4
+np.float32,0x804e1fb8,0xffc00000,4
+np.float32,0x80687de9,0xffc00000,4
+np.float32,0x807fffff,0xffc00000,4
+np.float32,0x80000001,0xffc00000,4
+## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ##
+np.float32,0x00000000,0xff800000,4
+np.float32,0x80000000,0xff800000,4
+np.float32,0x7f7fffff,0x42b17218,4
+np.float32,0x80800000,0xffc00000,4
+np.float32,0xff7fffff,0xffc00000,4
+## 1.00f + 0x00000001 ##
+np.float32,0x3f800000,0x00000000,4
+np.float32,0x3f800001,0x33ffffff,4
+np.float32,0x3f800002,0x347ffffe,4
+np.float32,0x3f7fffff,0xb3800000,4
+np.float32,0x3f7ffffe,0xb4000000,4
+np.float32,0x3f7ffffd,0xb4400001,4
+np.float32,0x402df853,0x3f7ffffe,4
+np.float32,0x402df854,0x3f7fffff,4
+np.float32,0x402df855,0x3f800000,4
+np.float32,0x402df856,0x3f800001,4
+np.float32,0x3ebc5ab0,0xbf800001,4
+np.float32,0x3ebc5ab1,0xbf800000,4
+np.float32,0x3ebc5ab2,0xbf800000,4
+np.float32,0x3ebc5ab3,0xbf7ffffe,4
+np.float32,0x423ef575,0x407768ab,4
+np.float32,0x427b8c61,0x408485dd,4
+np.float32,0x4211e9ee,0x406630b0,4
+np.float32,0x424d5c41,0x407c0fed,4
+np.float32,0x42be722a,0x4091cc91,4
+np.float32,0x42b73d30,0x4090908b,4
+np.float32,0x427e48e2,0x4084de7f,4
+np.float32,0x428f759b,0x4088bba3,4
+np.float32,0x41629069,0x4029a0cc,4
+np.float32,0x4272c99d,0x40836379,4
+np.float32,0x4d1b7458,0x4197463d,4
+np.float32,0x4f10c594,0x41ace2b2,4
+np.float32,0x4ea397c2,0x41a85171,4
+np.float32,0x4fefa9d1,0x41b6769c,4
+np.float32,0x4ebac6ab,0x41a960dc,4
+np.float32,0x4f6efb42,0x41b0e535,4
+np.float32,0x4e9ab8e7,0x41a7df44,4
+np.float32,0x4e81b5d1,0x41a67625,4
+np.float32,0x5014d9f2,0x41b832bd,4
+np.float32,0x4f02175c,0x41ac07b8,4
+np.float32,0x7f034f89,0x42b01c47,4
+np.float32,0x7f56d00e,0x42b11849,4
+np.float32,0x7f1cd5f6,0x42b0773a,4
+np.float32,0x7e979174,0x42af02d7,4
+np.float32,0x7f23369f,0x42b08ba2,4
+np.float32,0x7f0637ae,0x42b0277d,4
+np.float32,0x7efcb6e8,0x42b00897,4
+np.float32,0x7f7907c8,0x42b163f6,4
+np.float32,0x7e95c4c2,0x42aefcba,4
+np.float32,0x7f4577b2,0x42b0ed2d,4
+np.float32,0x3f49c92e,0xbe73ae84,4
+np.float32,0x3f4a23d1,0xbe71e2f8,4
+np.float32,0x3f4abb67,0xbe6ee430,4
+np.float32,0x3f48169a,0xbe7c5532,4
+np.float32,0x3f47f5fa,0xbe7cfc37,4
+np.float32,0x3f488309,0xbe7a2ad8,4
+np.float32,0x3f479df4,0xbe7ebf5f,4
+np.float32,0x3f47cfff,0xbe7dbec9,4
+np.float32,0x3f496704,0xbe75a125,4
+np.float32,0x3f478ee8,0xbe7f0c92,4
+np.float32,0x3f4a763b,0xbe7041ce,4
+np.float32,0x3f47a108,0xbe7eaf94,4
+np.float32,0x3f48136c,0xbe7c6578,4
+np.float32,0x3f481c17,0xbe7c391c,4
+np.float32,0x3f47cd28,0xbe7dcd56,4
+np.float32,0x3f478be8,0xbe7f1bf7,4
+np.float32,0x3f4c1f8e,0xbe67e367,4
+np.float32,0x3f489b0c,0xbe79b03f,4
+np.float32,0x3f4934cf,0xbe76a08a,4
+np.float32,0x3f4954df,0xbe75fd6a,4
+np.float32,0x3f47a3f5,0xbe7ea093,4
+np.float32,0x3f4ba4fc,0xbe6a4b02,4
+np.float32,0x3f47a0e1,0xbe7eb05c,4
+np.float32,0x3f48c30a,0xbe78e42f,4
+np.float32,0x3f48cab8,0xbe78bd05,4
+np.float32,0x3f4b0569,0xbe6d6ea4,4
+np.float32,0x3f47de32,0xbe7d7607,4
+np.float32,0x3f477328,0xbe7f9b00,4
+np.float32,0x3f496dab,0xbe757f52,4
+np.float32,0x3f47662c,0xbe7fddac,4
+np.float32,0x3f48ddd8,0xbe785b80,4
+np.float32,0x3f481866,0xbe7c4bff,4
+np.float32,0x3f48b119,0xbe793fb6,4
+np.float32,0x3f48c7e8,0xbe78cb5c,4
+np.float32,0x3f4985f6,0xbe7503da,4
+np.float32,0x3f483fdf,0xbe7b8212,4
+np.float32,0x3f4b1c76,0xbe6cfa67,4
+np.float32,0x3f480b2e,0xbe7c8fa8,4
+np.float32,0x3f48745f,0xbe7a75bf,4
+np.float32,0x3f485bda,0xbe7af308,4
+np.float32,0x3f47a660,0xbe7e942c,4
+np.float32,0x3f47d4d5,0xbe7da600,4
+np.float32,0x3f4b0a26,0xbe6d56be,4
+np.float32,0x3f4a4883,0xbe712924,4
+np.float32,0x3f4769e7,0xbe7fca84,4
+np.float32,0x3f499702,0xbe74ad3f,4
+np.float32,0x3f494ab1,0xbe763131,4
+np.float32,0x3f476b69,0xbe7fc2c6,4
+np.float32,0x3f4884e8,0xbe7a214a,4
+np.float32,0x3f486945,0xbe7aae76,4
diff --git a/numpy/core/tests/data/umath-validation-set-sin b/numpy/core/tests/data/umath-validation-set-sin
new file mode 100644
index 000000000..a56273195
--- /dev/null
+++ b/numpy/core/tests/data/umath-validation-set-sin
@@ -0,0 +1,707 @@
+dtype,input,output,ulperrortol
+## +ve denormals ##
+np.float32,0x004b4716,0x004b4716,2
+np.float32,0x007b2490,0x007b2490,2
+np.float32,0x007c99fa,0x007c99fa,2
+np.float32,0x00734a0c,0x00734a0c,2
+np.float32,0x0070de24,0x0070de24,2
+np.float32,0x007fffff,0x007fffff,2
+np.float32,0x00000001,0x00000001,2
+## -ve denormals ##
+np.float32,0x80495d65,0x80495d65,2
+np.float32,0x806894f6,0x806894f6,2
+np.float32,0x80555a76,0x80555a76,2
+np.float32,0x804e1fb8,0x804e1fb8,2
+np.float32,0x80687de9,0x80687de9,2
+np.float32,0x807fffff,0x807fffff,2
+np.float32,0x80000001,0x80000001,2
+## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ##
+np.float32,0x00000000,0x00000000,2
+np.float32,0x80000000,0x80000000,2
+np.float32,0x00800000,0x00800000,2
+np.float32,0x7f7fffff,0xbf0599b3,2
+np.float32,0x80800000,0x80800000,2
+np.float32,0xff7fffff,0x3f0599b3,2
+## 1.00f ##
+np.float32,0x3f800000,0x3f576aa4,2
+np.float32,0x3f800001,0x3f576aa6,2
+np.float32,0x3f800002,0x3f576aa7,2
+np.float32,0xc090a8b0,0x3f7b4e48,2
+np.float32,0x41ce3184,0x3f192d43,2
+np.float32,0xc1d85848,0xbf7161cb,2
+np.float32,0x402b8820,0x3ee3f29f,2
+np.float32,0x42b4e454,0x3f1d0151,2
+np.float32,0x42a67a60,0x3f7ffa4c,2
+np.float32,0x41d92388,0x3f67beef,2
+np.float32,0x422dd66c,0xbeffb0c1,2
+np.float32,0xc28f5be6,0xbf0bae79,2
+np.float32,0x41ab2674,0x3f0ffe2b,2
+np.float32,0xd0102756,0x3f227e8a,2
+np.float32,0xcf99405e,0x3f73ad00,2
+np.float32,0xcfd83a12,0xbf7151a7,2
+np.float32,0x4fb54db0,0xbe46354b,2
+np.float32,0xcfcca29d,0xbe9345e6,2
+np.float32,0xceec2ac0,0x3e98dc89,2
+np.float32,0xcfdca97f,0xbf60b2b4,2
+np.float32,0xcfe92b0a,0xbf222705,2
+np.float32,0x5014b0eb,0x3f63e75c,2
+np.float32,0xcfa7ee96,0x3f62ada4,2
+np.float32,0x754c09a0,0xbf617056,2
+np.float32,0x77a731fb,0x3f44472b,2
+np.float32,0x76de2494,0xbe680739,2
+np.float32,0xf74920dc,0xbf193338,2
+np.float32,0x7707a312,0xbf6f51b1,2
+np.float32,0x75bf9790,0xbd0f1a47,2
+np.float32,0xf4ca7c40,0xbf7d45e7,2
+np.float32,0x77e91899,0x3f767181,2
+np.float32,0xf74c9820,0xbd685b75,2
+np.float32,0x7785ca29,0x3f78ee61,2
+np.float32,0x3f490fdb,0x3f3504f3,2
+np.float32,0xbf490fdb,0xbf3504f3,2
+np.float32,0x3fc90fdb,0x3f800000,2
+np.float32,0xbfc90fdb,0xbf800000,2
+np.float32,0x40490fdb,0xb3bbbd2e,2
+np.float32,0xc0490fdb,0x33bbbd2e,2
+np.float32,0x3fc90fdb,0x3f800000,2
+np.float32,0xbfc90fdb,0xbf800000,2
+np.float32,0x40490fdb,0xb3bbbd2e,2
+np.float32,0xc0490fdb,0x33bbbd2e,2
+np.float32,0x40c90fdb,0x343bbd2e,2
+np.float32,0xc0c90fdb,0xb43bbd2e,2
+np.float32,0x4016cbe4,0x3f3504f3,2
+np.float32,0xc016cbe4,0xbf3504f3,2
+np.float32,0x4096cbe4,0xbf800000,2
+np.float32,0xc096cbe4,0x3f800000,2
+np.float32,0x4116cbe4,0xb2ccde2e,2
+np.float32,0xc116cbe4,0x32ccde2e,2
+np.float32,0x40490fdb,0xb3bbbd2e,2
+np.float32,0xc0490fdb,0x33bbbd2e,2
+np.float32,0x40c90fdb,0x343bbd2e,2
+np.float32,0xc0c90fdb,0xb43bbd2e,2
+np.float32,0x41490fdb,0x34bbbd2e,2
+np.float32,0xc1490fdb,0xb4bbbd2e,2
+np.float32,0x407b53d2,0xbf3504f5,2
+np.float32,0xc07b53d2,0x3f3504f5,2
+np.float32,0x40fb53d2,0x3f800000,2
+np.float32,0xc0fb53d2,0xbf800000,2
+np.float32,0x417b53d2,0xb535563d,2
+np.float32,0xc17b53d2,0x3535563d,2
+np.float32,0x4096cbe4,0xbf800000,2
+np.float32,0xc096cbe4,0x3f800000,2
+np.float32,0x4116cbe4,0xb2ccde2e,2
+np.float32,0xc116cbe4,0x32ccde2e,2
+np.float32,0x4196cbe4,0x334cde2e,2
+np.float32,0xc196cbe4,0xb34cde2e,2
+np.float32,0x40afede0,0xbf3504ef,2
+np.float32,0xc0afede0,0x3f3504ef,2
+np.float32,0x412fede0,0xbf800000,2
+np.float32,0xc12fede0,0x3f800000,2
+np.float32,0x41afede0,0xb5b222c4,2
+np.float32,0xc1afede0,0x35b222c4,2
+np.float32,0x40c90fdb,0x343bbd2e,2
+np.float32,0xc0c90fdb,0xb43bbd2e,2
+np.float32,0x41490fdb,0x34bbbd2e,2
+np.float32,0xc1490fdb,0xb4bbbd2e,2
+np.float32,0x41c90fdb,0x353bbd2e,2
+np.float32,0xc1c90fdb,0xb53bbd2e,2
+np.float32,0x40e231d6,0x3f3504f3,2
+np.float32,0xc0e231d6,0xbf3504f3,2
+np.float32,0x416231d6,0x3f800000,2
+np.float32,0xc16231d6,0xbf800000,2
+np.float32,0x41e231d6,0xb399a6a2,2
+np.float32,0xc1e231d6,0x3399a6a2,2
+np.float32,0x40fb53d2,0x3f800000,2
+np.float32,0xc0fb53d2,0xbf800000,2
+np.float32,0x417b53d2,0xb535563d,2
+np.float32,0xc17b53d2,0x3535563d,2
+np.float32,0x41fb53d2,0x35b5563d,2
+np.float32,0xc1fb53d2,0xb5b5563d,2
+np.float32,0x410a3ae7,0x3f3504eb,2
+np.float32,0xc10a3ae7,0xbf3504eb,2
+np.float32,0x418a3ae7,0xbf800000,2
+np.float32,0xc18a3ae7,0x3f800000,2
+np.float32,0x420a3ae7,0xb6308908,2
+np.float32,0xc20a3ae7,0x36308908,2
+np.float32,0x4116cbe4,0xb2ccde2e,2
+np.float32,0xc116cbe4,0x32ccde2e,2
+np.float32,0x4196cbe4,0x334cde2e,2
+np.float32,0xc196cbe4,0xb34cde2e,2
+np.float32,0x4216cbe4,0x33ccde2e,2
+np.float32,0xc216cbe4,0xb3ccde2e,2
+np.float32,0x41235ce2,0xbf3504f7,2
+np.float32,0xc1235ce2,0x3f3504f7,2
+np.float32,0x41a35ce2,0x3f800000,2
+np.float32,0xc1a35ce2,0xbf800000,2
+np.float32,0x42235ce2,0xb5b889b6,2
+np.float32,0xc2235ce2,0x35b889b6,2
+np.float32,0x412fede0,0xbf800000,2
+np.float32,0xc12fede0,0x3f800000,2
+np.float32,0x41afede0,0xb5b222c4,2
+np.float32,0xc1afede0,0x35b222c4,2
+np.float32,0x422fede0,0x363222c4,2
+np.float32,0xc22fede0,0xb63222c4,2
+np.float32,0x413c7edd,0xbf3504f3,2
+np.float32,0xc13c7edd,0x3f3504f3,2
+np.float32,0x41bc7edd,0xbf800000,2
+np.float32,0xc1bc7edd,0x3f800000,2
+np.float32,0x423c7edd,0xb4000add,2
+np.float32,0xc23c7edd,0x34000add,2
+np.float32,0x41490fdb,0x34bbbd2e,2
+np.float32,0xc1490fdb,0xb4bbbd2e,2
+np.float32,0x41c90fdb,0x353bbd2e,2
+np.float32,0xc1c90fdb,0xb53bbd2e,2
+np.float32,0x42490fdb,0x35bbbd2e,2
+np.float32,0xc2490fdb,0xb5bbbd2e,2
+np.float32,0x4155a0d9,0x3f3504fb,2
+np.float32,0xc155a0d9,0xbf3504fb,2
+np.float32,0x41d5a0d9,0x3f800000,2
+np.float32,0xc1d5a0d9,0xbf800000,2
+np.float32,0x4255a0d9,0xb633bc81,2
+np.float32,0xc255a0d9,0x3633bc81,2
+np.float32,0x416231d6,0x3f800000,2
+np.float32,0xc16231d6,0xbf800000,2
+np.float32,0x41e231d6,0xb399a6a2,2
+np.float32,0xc1e231d6,0x3399a6a2,2
+np.float32,0x426231d6,0x3419a6a2,2
+np.float32,0xc26231d6,0xb419a6a2,2
+np.float32,0x416ec2d4,0x3f3504ef,2
+np.float32,0xc16ec2d4,0xbf3504ef,2
+np.float32,0x41eec2d4,0xbf800000,2
+np.float32,0xc1eec2d4,0x3f800000,2
+np.float32,0x426ec2d4,0xb5bef0a7,2
+np.float32,0xc26ec2d4,0x35bef0a7,2
+np.float32,0x417b53d2,0xb535563d,2
+np.float32,0xc17b53d2,0x3535563d,2
+np.float32,0x41fb53d2,0x35b5563d,2
+np.float32,0xc1fb53d2,0xb5b5563d,2
+np.float32,0x427b53d2,0x3635563d,2
+np.float32,0xc27b53d2,0xb635563d,2
+np.float32,0x4183f268,0xbf3504ff,2
+np.float32,0xc183f268,0x3f3504ff,2
+np.float32,0x4203f268,0x3f800000,2
+np.float32,0xc203f268,0xbf800000,2
+np.float32,0x4283f268,0xb6859a13,2
+np.float32,0xc283f268,0x36859a13,2
+np.float32,0x418a3ae7,0xbf800000,2
+np.float32,0xc18a3ae7,0x3f800000,2
+np.float32,0x420a3ae7,0xb6308908,2
+np.float32,0xc20a3ae7,0x36308908,2
+np.float32,0x428a3ae7,0x36b08908,2
+np.float32,0xc28a3ae7,0xb6b08908,2
+np.float32,0x41908365,0xbf3504f6,2
+np.float32,0xc1908365,0x3f3504f6,2
+np.float32,0x42108365,0xbf800000,2
+np.float32,0xc2108365,0x3f800000,2
+np.float32,0x42908365,0x3592200d,2
+np.float32,0xc2908365,0xb592200d,2
+np.float32,0x4196cbe4,0x334cde2e,2
+np.float32,0xc196cbe4,0xb34cde2e,2
+np.float32,0x4216cbe4,0x33ccde2e,2
+np.float32,0xc216cbe4,0xb3ccde2e,2
+np.float32,0x4296cbe4,0x344cde2e,2
+np.float32,0xc296cbe4,0xb44cde2e,2
+np.float32,0x419d1463,0x3f3504f8,2
+np.float32,0xc19d1463,0xbf3504f8,2
+np.float32,0x421d1463,0x3f800000,2
+np.float32,0xc21d1463,0xbf800000,2
+np.float32,0x429d1463,0xb5c55799,2
+np.float32,0xc29d1463,0x35c55799,2
+np.float32,0x41a35ce2,0x3f800000,2
+np.float32,0xc1a35ce2,0xbf800000,2
+np.float32,0x42235ce2,0xb5b889b6,2
+np.float32,0xc2235ce2,0x35b889b6,2
+np.float32,0x42a35ce2,0x363889b6,2
+np.float32,0xc2a35ce2,0xb63889b6,2
+np.float32,0x41a9a561,0x3f3504e7,2
+np.float32,0xc1a9a561,0xbf3504e7,2
+np.float32,0x4229a561,0xbf800000,2
+np.float32,0xc229a561,0x3f800000,2
+np.float32,0x42a9a561,0xb68733d0,2
+np.float32,0xc2a9a561,0x368733d0,2
+np.float32,0x41afede0,0xb5b222c4,2
+np.float32,0xc1afede0,0x35b222c4,2
+np.float32,0x422fede0,0x363222c4,2
+np.float32,0xc22fede0,0xb63222c4,2
+np.float32,0x42afede0,0x36b222c4,2
+np.float32,0xc2afede0,0xb6b222c4,2
+np.float32,0x41b6365e,0xbf3504f0,2
+np.float32,0xc1b6365e,0x3f3504f0,2
+np.float32,0x4236365e,0x3f800000,2
+np.float32,0xc236365e,0xbf800000,2
+np.float32,0x42b6365e,0x358bb91c,2
+np.float32,0xc2b6365e,0xb58bb91c,2
+np.float32,0x41bc7edd,0xbf800000,2
+np.float32,0xc1bc7edd,0x3f800000,2
+np.float32,0x423c7edd,0xb4000add,2
+np.float32,0xc23c7edd,0x34000add,2
+np.float32,0x42bc7edd,0x34800add,2
+np.float32,0xc2bc7edd,0xb4800add,2
+np.float32,0x41c2c75c,0xbf3504ef,2
+np.float32,0xc1c2c75c,0x3f3504ef,2
+np.float32,0x4242c75c,0xbf800000,2
+np.float32,0xc242c75c,0x3f800000,2
+np.float32,0x42c2c75c,0xb5cbbe8a,2
+np.float32,0xc2c2c75c,0x35cbbe8a,2
+np.float32,0x41c90fdb,0x353bbd2e,2
+np.float32,0xc1c90fdb,0xb53bbd2e,2
+np.float32,0x42490fdb,0x35bbbd2e,2
+np.float32,0xc2490fdb,0xb5bbbd2e,2
+np.float32,0x42c90fdb,0x363bbd2e,2
+np.float32,0xc2c90fdb,0xb63bbd2e,2
+np.float32,0x41cf585a,0x3f3504ff,2
+np.float32,0xc1cf585a,0xbf3504ff,2
+np.float32,0x424f585a,0x3f800000,2
+np.float32,0xc24f585a,0xbf800000,2
+np.float32,0x42cf585a,0xb688cd8c,2
+np.float32,0xc2cf585a,0x3688cd8c,2
+np.float32,0x41d5a0d9,0x3f800000,2
+np.float32,0xc1d5a0d9,0xbf800000,2
+np.float32,0x4255a0d9,0xb633bc81,2
+np.float32,0xc255a0d9,0x3633bc81,2
+np.float32,0x42d5a0d9,0x36b3bc81,2
+np.float32,0xc2d5a0d9,0xb6b3bc81,2
+np.float32,0x41dbe958,0x3f3504e0,2
+np.float32,0xc1dbe958,0xbf3504e0,2
+np.float32,0x425be958,0xbf800000,2
+np.float32,0xc25be958,0x3f800000,2
+np.float32,0x42dbe958,0xb6deab75,2
+np.float32,0xc2dbe958,0x36deab75,2
+np.float32,0x41e231d6,0xb399a6a2,2
+np.float32,0xc1e231d6,0x3399a6a2,2
+np.float32,0x426231d6,0x3419a6a2,2
+np.float32,0xc26231d6,0xb419a6a2,2
+np.float32,0x42e231d6,0x3499a6a2,2
+np.float32,0xc2e231d6,0xb499a6a2,2
+np.float32,0x41e87a55,0xbf3504f8,2
+np.float32,0xc1e87a55,0x3f3504f8,2
+np.float32,0x42687a55,0x3f800000,2
+np.float32,0xc2687a55,0xbf800000,2
+np.float32,0x42e87a55,0xb5d2257b,2
+np.float32,0xc2e87a55,0x35d2257b,2
+np.float32,0x41eec2d4,0xbf800000,2
+np.float32,0xc1eec2d4,0x3f800000,2
+np.float32,0x426ec2d4,0xb5bef0a7,2
+np.float32,0xc26ec2d4,0x35bef0a7,2
+np.float32,0x42eec2d4,0x363ef0a7,2
+np.float32,0xc2eec2d4,0xb63ef0a7,2
+np.float32,0x41f50b53,0xbf3504e7,2
+np.float32,0xc1f50b53,0x3f3504e7,2
+np.float32,0x42750b53,0xbf800000,2
+np.float32,0xc2750b53,0x3f800000,2
+np.float32,0x42f50b53,0xb68a6748,2
+np.float32,0xc2f50b53,0x368a6748,2
+np.float32,0x41fb53d2,0x35b5563d,2
+np.float32,0xc1fb53d2,0xb5b5563d,2
+np.float32,0x427b53d2,0x3635563d,2
+np.float32,0xc27b53d2,0xb635563d,2
+np.float32,0x42fb53d2,0x36b5563d,2
+np.float32,0xc2fb53d2,0xb6b5563d,2
+np.float32,0x4200ce28,0x3f3504f0,2
+np.float32,0xc200ce28,0xbf3504f0,2
+np.float32,0x4280ce28,0x3f800000,2
+np.float32,0xc280ce28,0xbf800000,2
+np.float32,0x4300ce28,0x357dd672,2
+np.float32,0xc300ce28,0xb57dd672,2
+np.float32,0x4203f268,0x3f800000,2
+np.float32,0xc203f268,0xbf800000,2
+np.float32,0x4283f268,0xb6859a13,2
+np.float32,0xc283f268,0x36859a13,2
+np.float32,0x4303f268,0x37059a13,2
+np.float32,0xc303f268,0xb7059a13,2
+np.float32,0x420716a7,0x3f3504ee,2
+np.float32,0xc20716a7,0xbf3504ee,2
+np.float32,0x428716a7,0xbf800000,2
+np.float32,0xc28716a7,0x3f800000,2
+np.float32,0x430716a7,0xb5d88c6d,2
+np.float32,0xc30716a7,0x35d88c6d,2
+np.float32,0x420a3ae7,0xb6308908,2
+np.float32,0xc20a3ae7,0x36308908,2
+np.float32,0x428a3ae7,0x36b08908,2
+np.float32,0xc28a3ae7,0xb6b08908,2
+np.float32,0x430a3ae7,0x37308908,2
+np.float32,0xc30a3ae7,0xb7308908,2
+np.float32,0x420d5f26,0xbf350500,2
+np.float32,0xc20d5f26,0x3f350500,2
+np.float32,0x428d5f26,0x3f800000,2
+np.float32,0xc28d5f26,0xbf800000,2
+np.float32,0x430d5f26,0xb68c0105,2
+np.float32,0xc30d5f26,0x368c0105,2
+np.float32,0x42108365,0xbf800000,2
+np.float32,0xc2108365,0x3f800000,2
+np.float32,0x42908365,0x3592200d,2
+np.float32,0xc2908365,0xb592200d,2
+np.float32,0x43108365,0xb612200d,2
+np.float32,0xc3108365,0x3612200d,2
+np.float32,0x4213a7a5,0xbf3504df,2
+np.float32,0xc213a7a5,0x3f3504df,2
+np.float32,0x4293a7a5,0xbf800000,2
+np.float32,0xc293a7a5,0x3f800000,2
+np.float32,0x4313a7a5,0xb6e1deee,2
+np.float32,0xc313a7a5,0x36e1deee,2
+np.float32,0x4216cbe4,0x33ccde2e,2
+np.float32,0xc216cbe4,0xb3ccde2e,2
+np.float32,0x4296cbe4,0x344cde2e,2
+np.float32,0xc296cbe4,0xb44cde2e,2
+np.float32,0x4316cbe4,0x34ccde2e,2
+np.float32,0xc316cbe4,0xb4ccde2e,2
+np.float32,0x4219f024,0x3f35050f,2
+np.float32,0xc219f024,0xbf35050f,2
+np.float32,0x4299f024,0x3f800000,2
+np.float32,0xc299f024,0xbf800000,2
+np.float32,0x4319f024,0xb71bde6c,2
+np.float32,0xc319f024,0x371bde6c,2
+np.float32,0x421d1463,0x3f800000,2
+np.float32,0xc21d1463,0xbf800000,2
+np.float32,0x429d1463,0xb5c55799,2
+np.float32,0xc29d1463,0x35c55799,2
+np.float32,0x431d1463,0x36455799,2
+np.float32,0xc31d1463,0xb6455799,2
+np.float32,0x422038a3,0x3f3504d0,2
+np.float32,0xc22038a3,0xbf3504d0,2
+np.float32,0x42a038a3,0xbf800000,2
+np.float32,0xc2a038a3,0x3f800000,2
+np.float32,0x432038a3,0xb746cd61,2
+np.float32,0xc32038a3,0x3746cd61,2
+np.float32,0x42235ce2,0xb5b889b6,2
+np.float32,0xc2235ce2,0x35b889b6,2
+np.float32,0x42a35ce2,0x363889b6,2
+np.float32,0xc2a35ce2,0xb63889b6,2
+np.float32,0x43235ce2,0x36b889b6,2
+np.float32,0xc3235ce2,0xb6b889b6,2
+np.float32,0x42268121,0xbf3504f1,2
+np.float32,0xc2268121,0x3f3504f1,2
+np.float32,0x42a68121,0x3f800000,2
+np.float32,0xc2a68121,0xbf800000,2
+np.float32,0x43268121,0x35643aac,2
+np.float32,0xc3268121,0xb5643aac,2
+np.float32,0x4229a561,0xbf800000,2
+np.float32,0xc229a561,0x3f800000,2
+np.float32,0x42a9a561,0xb68733d0,2
+np.float32,0xc2a9a561,0x368733d0,2
+np.float32,0x4329a561,0x370733d0,2
+np.float32,0xc329a561,0xb70733d0,2
+np.float32,0x422cc9a0,0xbf3504ee,2
+np.float32,0xc22cc9a0,0x3f3504ee,2
+np.float32,0x42acc9a0,0xbf800000,2
+np.float32,0xc2acc9a0,0x3f800000,2
+np.float32,0x432cc9a0,0xb5e55a50,2
+np.float32,0xc32cc9a0,0x35e55a50,2
+np.float32,0x422fede0,0x363222c4,2
+np.float32,0xc22fede0,0xb63222c4,2
+np.float32,0x42afede0,0x36b222c4,2
+np.float32,0xc2afede0,0xb6b222c4,2
+np.float32,0x432fede0,0x373222c4,2
+np.float32,0xc32fede0,0xb73222c4,2
+np.float32,0x4233121f,0x3f350500,2
+np.float32,0xc233121f,0xbf350500,2
+np.float32,0x42b3121f,0x3f800000,2
+np.float32,0xc2b3121f,0xbf800000,2
+np.float32,0x4333121f,0xb68f347d,2
+np.float32,0xc333121f,0x368f347d,2
+np.float32,0x4236365e,0x3f800000,2
+np.float32,0xc236365e,0xbf800000,2
+np.float32,0x42b6365e,0x358bb91c,2
+np.float32,0xc2b6365e,0xb58bb91c,2
+np.float32,0x4336365e,0xb60bb91c,2
+np.float32,0xc336365e,0x360bb91c,2
+np.float32,0x42395a9e,0x3f3504df,2
+np.float32,0xc2395a9e,0xbf3504df,2
+np.float32,0x42b95a9e,0xbf800000,2
+np.float32,0xc2b95a9e,0x3f800000,2
+np.float32,0x43395a9e,0xb6e51267,2
+np.float32,0xc3395a9e,0x36e51267,2
+np.float32,0x423c7edd,0xb4000add,2
+np.float32,0xc23c7edd,0x34000add,2
+np.float32,0x42bc7edd,0x34800add,2
+np.float32,0xc2bc7edd,0xb4800add,2
+np.float32,0x433c7edd,0x35000add,2
+np.float32,0xc33c7edd,0xb5000add,2
+np.float32,0x423fa31d,0xbf35050f,2
+np.float32,0xc23fa31d,0x3f35050f,2
+np.float32,0x42bfa31d,0x3f800000,2
+np.float32,0xc2bfa31d,0xbf800000,2
+np.float32,0x433fa31d,0xb71d7828,2
+np.float32,0xc33fa31d,0x371d7828,2
+np.float32,0x4242c75c,0xbf800000,2
+np.float32,0xc242c75c,0x3f800000,2
+np.float32,0x42c2c75c,0xb5cbbe8a,2
+np.float32,0xc2c2c75c,0x35cbbe8a,2
+np.float32,0x4342c75c,0x364bbe8a,2
+np.float32,0xc342c75c,0xb64bbe8a,2
+np.float32,0x4245eb9c,0xbf3504d0,2
+np.float32,0xc245eb9c,0x3f3504d0,2
+np.float32,0x42c5eb9c,0xbf800000,2
+np.float32,0xc2c5eb9c,0x3f800000,2
+np.float32,0x4345eb9c,0xb748671d,2
+np.float32,0xc345eb9c,0x3748671d,2
+np.float32,0x42490fdb,0x35bbbd2e,2
+np.float32,0xc2490fdb,0xb5bbbd2e,2
+np.float32,0x42c90fdb,0x363bbd2e,2
+np.float32,0xc2c90fdb,0xb63bbd2e,2
+np.float32,0x43490fdb,0x36bbbd2e,2
+np.float32,0xc3490fdb,0xb6bbbd2e,2
+np.float32,0x424c341a,0x3f3504f1,2
+np.float32,0xc24c341a,0xbf3504f1,2
+np.float32,0x42cc341a,0x3f800000,2
+np.float32,0xc2cc341a,0xbf800000,2
+np.float32,0x434c341a,0x354a9ee6,2
+np.float32,0xc34c341a,0xb54a9ee6,2
+np.float32,0x424f585a,0x3f800000,2
+np.float32,0xc24f585a,0xbf800000,2
+np.float32,0x42cf585a,0xb688cd8c,2
+np.float32,0xc2cf585a,0x3688cd8c,2
+np.float32,0x434f585a,0x3708cd8c,2
+np.float32,0xc34f585a,0xb708cd8c,2
+np.float32,0x42527c99,0x3f3504ee,2
+np.float32,0xc2527c99,0xbf3504ee,2
+np.float32,0x42d27c99,0xbf800000,2
+np.float32,0xc2d27c99,0x3f800000,2
+np.float32,0x43527c99,0xb5f22833,2
+np.float32,0xc3527c99,0x35f22833,2
+np.float32,0x4255a0d9,0xb633bc81,2
+np.float32,0xc255a0d9,0x3633bc81,2
+np.float32,0x42d5a0d9,0x36b3bc81,2
+np.float32,0xc2d5a0d9,0xb6b3bc81,2
+np.float32,0x4355a0d9,0x3733bc81,2
+np.float32,0xc355a0d9,0xb733bc81,2
+np.float32,0x4258c518,0xbf350500,2
+np.float32,0xc258c518,0x3f350500,2
+np.float32,0x42d8c518,0x3f800000,2
+np.float32,0xc2d8c518,0xbf800000,2
+np.float32,0x4358c518,0xb69267f6,2
+np.float32,0xc358c518,0x369267f6,2
+np.float32,0x425be958,0xbf800000,2
+np.float32,0xc25be958,0x3f800000,2
+np.float32,0x42dbe958,0xb6deab75,2
+np.float32,0xc2dbe958,0x36deab75,2
+np.float32,0x435be958,0x375eab75,2
+np.float32,0xc35be958,0xb75eab75,2
+np.float32,0x425f0d97,0xbf3504df,2
+np.float32,0xc25f0d97,0x3f3504df,2
+np.float32,0x42df0d97,0xbf800000,2
+np.float32,0xc2df0d97,0x3f800000,2
+np.float32,0x435f0d97,0xb6e845e0,2
+np.float32,0xc35f0d97,0x36e845e0,2
+np.float32,0x426231d6,0x3419a6a2,2
+np.float32,0xc26231d6,0xb419a6a2,2
+np.float32,0x42e231d6,0x3499a6a2,2
+np.float32,0xc2e231d6,0xb499a6a2,2
+np.float32,0x436231d6,0x3519a6a2,2
+np.float32,0xc36231d6,0xb519a6a2,2
+np.float32,0x42655616,0x3f35050f,2
+np.float32,0xc2655616,0xbf35050f,2
+np.float32,0x42e55616,0x3f800000,2
+np.float32,0xc2e55616,0xbf800000,2
+np.float32,0x43655616,0xb71f11e5,2
+np.float32,0xc3655616,0x371f11e5,2
+np.float32,0x42687a55,0x3f800000,2
+np.float32,0xc2687a55,0xbf800000,2
+np.float32,0x42e87a55,0xb5d2257b,2
+np.float32,0xc2e87a55,0x35d2257b,2
+np.float32,0x43687a55,0x3652257b,2
+np.float32,0xc3687a55,0xb652257b,2
+np.float32,0x426b9e95,0x3f3504cf,2
+np.float32,0xc26b9e95,0xbf3504cf,2
+np.float32,0x42eb9e95,0xbf800000,2
+np.float32,0xc2eb9e95,0x3f800000,2
+np.float32,0x436b9e95,0xb74a00d9,2
+np.float32,0xc36b9e95,0x374a00d9,2
+np.float32,0x426ec2d4,0xb5bef0a7,2
+np.float32,0xc26ec2d4,0x35bef0a7,2
+np.float32,0x42eec2d4,0x363ef0a7,2
+np.float32,0xc2eec2d4,0xb63ef0a7,2
+np.float32,0x436ec2d4,0x36bef0a7,2
+np.float32,0xc36ec2d4,0xb6bef0a7,2
+np.float32,0x4271e713,0xbf3504f1,2
+np.float32,0xc271e713,0x3f3504f1,2
+np.float32,0x42f1e713,0x3f800000,2
+np.float32,0xc2f1e713,0xbf800000,2
+np.float32,0x4371e713,0x35310321,2
+np.float32,0xc371e713,0xb5310321,2
+np.float32,0x42750b53,0xbf800000,2
+np.float32,0xc2750b53,0x3f800000,2
+np.float32,0x42f50b53,0xb68a6748,2
+np.float32,0xc2f50b53,0x368a6748,2
+np.float32,0x43750b53,0x370a6748,2
+np.float32,0xc3750b53,0xb70a6748,2
+np.float32,0x42782f92,0xbf3504ee,2
+np.float32,0xc2782f92,0x3f3504ee,2
+np.float32,0x42f82f92,0xbf800000,2
+np.float32,0xc2f82f92,0x3f800000,2
+np.float32,0x43782f92,0xb5fef616,2
+np.float32,0xc3782f92,0x35fef616,2
+np.float32,0x427b53d2,0x3635563d,2
+np.float32,0xc27b53d2,0xb635563d,2
+np.float32,0x42fb53d2,0x36b5563d,2
+np.float32,0xc2fb53d2,0xb6b5563d,2
+np.float32,0x437b53d2,0x3735563d,2
+np.float32,0xc37b53d2,0xb735563d,2
+np.float32,0x427e7811,0x3f350500,2
+np.float32,0xc27e7811,0xbf350500,2
+np.float32,0x42fe7811,0x3f800000,2
+np.float32,0xc2fe7811,0xbf800000,2
+np.float32,0x437e7811,0xb6959b6f,2
+np.float32,0xc37e7811,0x36959b6f,2
+np.float32,0x4280ce28,0x3f800000,2
+np.float32,0xc280ce28,0xbf800000,2
+np.float32,0x4300ce28,0x357dd672,2
+np.float32,0xc300ce28,0xb57dd672,2
+np.float32,0x4380ce28,0xb5fdd672,2
+np.float32,0xc380ce28,0x35fdd672,2
+np.float32,0x42826048,0x3f3504de,2
+np.float32,0xc2826048,0xbf3504de,2
+np.float32,0x43026048,0xbf800000,2
+np.float32,0xc3026048,0x3f800000,2
+np.float32,0x43826048,0xb6eb7958,2
+np.float32,0xc3826048,0x36eb7958,2
+np.float32,0x4283f268,0xb6859a13,2
+np.float32,0xc283f268,0x36859a13,2
+np.float32,0x4303f268,0x37059a13,2
+np.float32,0xc303f268,0xb7059a13,2
+np.float32,0x4383f268,0x37859a13,2
+np.float32,0xc383f268,0xb7859a13,2
+np.float32,0x42858487,0xbf3504e2,2
+np.float32,0xc2858487,0x3f3504e2,2
+np.float32,0x43058487,0x3f800000,2
+np.float32,0xc3058487,0xbf800000,2
+np.float32,0x43858487,0x36bea8be,2
+np.float32,0xc3858487,0xb6bea8be,2
+np.float32,0x428716a7,0xbf800000,2
+np.float32,0xc28716a7,0x3f800000,2
+np.float32,0x430716a7,0xb5d88c6d,2
+np.float32,0xc30716a7,0x35d88c6d,2
+np.float32,0x438716a7,0x36588c6d,2
+np.float32,0xc38716a7,0xb6588c6d,2
+np.float32,0x4288a8c7,0xbf3504cf,2
+np.float32,0xc288a8c7,0x3f3504cf,2
+np.float32,0x4308a8c7,0xbf800000,2
+np.float32,0xc308a8c7,0x3f800000,2
+np.float32,0x4388a8c7,0xb74b9a96,2
+np.float32,0xc388a8c7,0x374b9a96,2
+np.float32,0x428a3ae7,0x36b08908,2
+np.float32,0xc28a3ae7,0xb6b08908,2
+np.float32,0x430a3ae7,0x37308908,2
+np.float32,0xc30a3ae7,0xb7308908,2
+np.float32,0x438a3ae7,0x37b08908,2
+np.float32,0xc38a3ae7,0xb7b08908,2
+np.float32,0x428bcd06,0x3f3504f2,2
+np.float32,0xc28bcd06,0xbf3504f2,2
+np.float32,0x430bcd06,0x3f800000,2
+np.float32,0xc30bcd06,0xbf800000,2
+np.float32,0x438bcd06,0x3517675b,2
+np.float32,0xc38bcd06,0xb517675b,2
+np.float32,0x428d5f26,0x3f800000,2
+np.float32,0xc28d5f26,0xbf800000,2
+np.float32,0x430d5f26,0xb68c0105,2
+np.float32,0xc30d5f26,0x368c0105,2
+np.float32,0x438d5f26,0x370c0105,2
+np.float32,0xc38d5f26,0xb70c0105,2
+np.float32,0x428ef146,0x3f3504c0,2
+np.float32,0xc28ef146,0xbf3504c0,2
+np.float32,0x430ef146,0xbf800000,2
+np.float32,0xc30ef146,0x3f800000,2
+np.float32,0x438ef146,0xb790bc40,2
+np.float32,0xc38ef146,0x3790bc40,2
+np.float32,0x42908365,0x3592200d,2
+np.float32,0xc2908365,0xb592200d,2
+np.float32,0x43108365,0xb612200d,2
+np.float32,0xc3108365,0x3612200d,2
+np.float32,0x43908365,0xb692200d,2
+np.float32,0xc3908365,0x3692200d,2
+np.float32,0x42921585,0xbf350501,2
+np.float32,0xc2921585,0x3f350501,2
+np.float32,0x43121585,0x3f800000,2
+np.float32,0xc3121585,0xbf800000,2
+np.float32,0x43921585,0xb698cee8,2
+np.float32,0xc3921585,0x3698cee8,2
+np.float32,0x4293a7a5,0xbf800000,2
+np.float32,0xc293a7a5,0x3f800000,2
+np.float32,0x4313a7a5,0xb6e1deee,2
+np.float32,0xc313a7a5,0x36e1deee,2
+np.float32,0x4393a7a5,0x3761deee,2
+np.float32,0xc393a7a5,0xb761deee,2
+np.float32,0x429539c5,0xbf3504b1,2
+np.float32,0xc29539c5,0x3f3504b1,2
+np.float32,0x431539c5,0xbf800000,2
+np.float32,0xc31539c5,0x3f800000,2
+np.float32,0x439539c5,0xb7bbab34,2
+np.float32,0xc39539c5,0x37bbab34,2
+np.float32,0x4296cbe4,0x344cde2e,2
+np.float32,0xc296cbe4,0xb44cde2e,2
+np.float32,0x4316cbe4,0x34ccde2e,2
+np.float32,0xc316cbe4,0xb4ccde2e,2
+np.float32,0x4396cbe4,0x354cde2e,2
+np.float32,0xc396cbe4,0xb54cde2e,2
+np.float32,0x42985e04,0x3f350510,2
+np.float32,0xc2985e04,0xbf350510,2
+np.float32,0x43185e04,0x3f800000,2
+np.float32,0xc3185e04,0xbf800000,2
+np.float32,0x43985e04,0xb722455d,2
+np.float32,0xc3985e04,0x3722455d,2
+np.float32,0x4299f024,0x3f800000,2
+np.float32,0xc299f024,0xbf800000,2
+np.float32,0x4319f024,0xb71bde6c,2
+np.float32,0xc319f024,0x371bde6c,2
+np.float32,0x4399f024,0x379bde6c,2
+np.float32,0xc399f024,0xb79bde6c,2
+np.float32,0x429b8243,0x3f3504fc,2
+np.float32,0xc29b8243,0xbf3504fc,2
+np.float32,0x431b8243,0xbf800000,2
+np.float32,0xc31b8243,0x3f800000,2
+np.float32,0x439b8243,0x364b2eb8,2
+np.float32,0xc39b8243,0xb64b2eb8,2
+np.float32,0x435b2047,0xbf350525,2
+np.float32,0x42a038a2,0xbf800000,2
+np.float32,0x432038a2,0x3664ca7e,2
+np.float32,0x4345eb9b,0x365e638c,2
+np.float32,0x42c5eb9b,0xbf800000,2
+np.float32,0x42eb9e94,0xbf800000,2
+np.float32,0x4350ea79,0x3f800000,2
+np.float32,0x42dbe957,0x3585522a,2
+np.float32,0x425be957,0xbf800000,2
+np.float32,0x435be957,0xb605522a,2
+np.float32,0x487fe5ab,0xbf7ffffd,2
+np.float32,0x497fe5ab,0xbb14017d,2
+np.float32,0x49ffe5ab,0xbb940164,2
+np.float32,0x49ffeb37,0x3f7fff56,2
+np.float32,0x497ff0c3,0x3f7fffd6,2
+np.float32,0x49fff0c3,0x3b930487,2
+np.float32,0x49fff64f,0xbf7fff58,2
+np.float32,0x497ffbdb,0x3b1207c0,2
+np.float32,0x49fffbdb,0xbb9207a9,2
+np.float32,0x48fffbdb,0xbf7ffff6,2
+np.float32,0x4e736e56,0x397fa7f2,2
+np.float32,0x4d4da377,0xb57c64bc,2
+np.float32,0x4ece58c3,0xb80846c8,2
+np.float32,0x4ee0db9c,0x394c4786,2
+np.float32,0x4dee7002,0x381bce96,2
+np.float32,0x4ee86afc,0x3f800000,2
+np.float32,0x4dca4f3f,0xb8e25111,2
+np.float32,0x4ecb48af,0xbf800000,2
+np.float32,0x4e51e33f,0xb8a4fa6f,2
+np.float32,0x4ef5f421,0x387ca7df,2
+np.float32,0x476362a2,0xbd7ff911,2
+np.float32,0x464c99a4,0x3e7f4d41,2
+np.float32,0x4471f73d,0x3e7fe1b0,2
+np.float32,0x445a6752,0x3e7ef367,2
+np.float32,0x474fa400,0x3e7f9fcd,2
+np.float32,0x47c9e70e,0xbb4bba09,2
+np.float32,0x45c1e72f,0xbe7fc7af,2
+np.float32,0x4558c91d,0x3e7e9f31,2
+np.float32,0x43784f94,0xbdff6654,2
+np.float32,0x466e8500,0xbe7ea0a3,2
+np.float32,0x468e1c25,0x3e7e22fb,2
+np.float32,0x47d28adc,0xbe7d5e6b,2
+np.float32,0x44ea6cfc,0x3dff70c3,2
+np.float32,0x4605126c,0x3e7f89ef,2
+np.float32,0x4788b3c6,0xbb87d853,2
+np.float32,0x4531b042,0x3dffd163,2
+np.float32,0x47e46c29,0xbe7def2b,2
+np.float32,0x47c10e07,0xbdff63d4,2
+np.float32,0x43f1f71d,0x3dfff387,2
+np.float32,0x47c3e38c,0x3e7f0b2f,2
+np.float32,0x462c3fa5,0xbd7fe13d,2
+np.float32,0x441c5354,0xbdff76b4,2
+np.float32,0x44908b69,0x3e7dcf0d,2
+np.float32,0x478813ad,0xbe7e9d80,2
+np.float32,0x441c4351,0x3dff937b,2
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
index 9755e7b36..32e2ea537 100644
--- a/numpy/core/tests/test_api.py
+++ b/numpy/core/tests/test_api.py
@@ -3,8 +3,10 @@ from __future__ import division, absolute_import, print_function
import sys
import numpy as np
+import pytest
from numpy.testing import (
- assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT
+ assert_, assert_equal, assert_array_equal, assert_raises, assert_warns,
+ HAS_REFCOUNT
)
# Switch between new behaviour when NPY_RELAXED_STRIDES_CHECKING is set.
@@ -289,6 +291,14 @@ def test_array_astype():
a = np.array(1000, dtype='i4')
assert_raises(TypeError, a.astype, 'U1', casting='safe')
+@pytest.mark.parametrize("t",
+ np.sctypes['uint'] + np.sctypes['int'] + np.sctypes['float']
+)
+def test_array_astype_warning(t):
+ # test ComplexWarning when casting from complex to float or int
+ a = np.array(10, dtype=np.complex)
+ assert_warns(np.ComplexWarning, a.astype, t)
+
def test_copyto_fromscalar():
a = np.arange(6, dtype='f4').reshape(2, 3)
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index 170c52e9e..f99c0f72b 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -9,7 +9,7 @@ from numpy.testing import (
assert_, assert_equal, assert_raises, assert_warns, suppress_warnings,
assert_raises_regex,
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
# Use pytz to test out various time zones if available
try:
@@ -1825,7 +1825,7 @@ class TestDateTime(object):
# NOTE: some of the operations may be supported
# in the future
with assert_raises_regex(TypeError,
- "remainder cannot use operands with types"):
+ "'remainder' cannot use operands with types"):
val1 % val2
def test_timedelta_arange_no_dtype(self):
@@ -2208,6 +2208,27 @@ class TestDateTime(object):
continue
assert_raises(TypeError, np.isnat, np.zeros(10, t))
+ def test_isfinite(self):
+ assert_(not np.isfinite(np.datetime64('NaT', 'ms')))
+ assert_(not np.isfinite(np.datetime64('NaT', 'ns')))
+ assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07')))
+
+ assert_(not np.isfinite(np.timedelta64('NaT', "ms")))
+ assert_(np.isfinite(np.timedelta64(34, "ms")))
+
+ res = np.array([True, True, False])
+ for unit in ['Y', 'M', 'W', 'D',
+ 'h', 'm', 's', 'ms', 'us',
+ 'ns', 'ps', 'fs', 'as']:
+ arr = np.array([123, -321, "NaT"], dtype='<datetime64[%s]' % unit)
+ assert_equal(np.isfinite(arr), res)
+ arr = np.array([123, -321, "NaT"], dtype='>datetime64[%s]' % unit)
+ assert_equal(np.isfinite(arr), res)
+ arr = np.array([123, -321, "NaT"], dtype='<timedelta64[%s]' % unit)
+ assert_equal(np.isfinite(arr), res)
+ arr = np.array([123, -321, "NaT"], dtype='>timedelta64[%s]' % unit)
+ assert_equal(np.isfinite(arr), res)
+
def test_corecursive_input(self):
# construct a co-recursive list
a, b = [], []
@@ -2220,6 +2241,44 @@ class TestDateTime(object):
assert_raises(RecursionError, obj_arr.astype, 'M8')
assert_raises(RecursionError, obj_arr.astype, 'm8')
+ @pytest.mark.parametrize("time_unit", [
+ "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as",
+ # compound units
+ "10D", "2M",
+ ])
+ def test_limit_symmetry(self, time_unit):
+ """
+ Dates should have symmetric limits around the unix epoch at +/-np.int64
+ """
+ epoch = np.datetime64(0, time_unit)
+ latest = np.datetime64(np.iinfo(np.int64).max, time_unit)
+ earliest = np.datetime64(-np.iinfo(np.int64).max, time_unit)
+
+ # above should not have overflowed
+ assert earliest < epoch < latest
+
+ @pytest.mark.parametrize("time_unit", [
+ "Y", "M",
+ pytest.param("W", marks=pytest.mark.xfail(reason="gh-13197")),
+ "D", "h", "m",
+ "s", "ms", "us", "ns", "ps", "fs", "as",
+ pytest.param("10D", marks=pytest.mark.xfail(reason="similar to gh-13197")),
+ ])
+ @pytest.mark.parametrize("sign", [-1, 1])
+ def test_limit_str_roundtrip(self, time_unit, sign):
+ """
+ Limits should roundtrip when converted to strings.
+
+ This tests the conversion to and from npy_datetimestruct.
+ """
+ # TODO: add absolute (gold standard) time span limit strings
+ limit = np.datetime64(np.iinfo(np.int64).max * sign, time_unit)
+
+ # Convert to string and back. Explicit unit needed since the day and
+ # week reprs are not distinguishable.
+ limit_via_str = np.datetime64(str(limit), time_unit)
+ assert limit_via_str == limit
+
class TestDateTimeData(object):
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index edb5d5e46..6d71fcbd6 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -533,3 +533,18 @@ class Test_GetSet_NumericOps(_DeprecationTestCase):
# other tests.
self.assert_deprecated(np.set_numeric_ops, kwargs={})
assert_raises(ValueError, np.set_numeric_ops, add='abc')
+
+
+class TestShape1Fields(_DeprecationTestCase):
+ warning_cls = FutureWarning
+
+ # 2019-05-20, 1.17.0
+ def test_shape_1_fields(self):
+ self.assert_deprecated(np.dtype, args=([('a', int, 1)],))
+
+
+class TestNonZero(_DeprecationTestCase):
+ # 2019-05-26, 1.17.0
+ def test_zerod(self):
+ self.assert_deprecated(lambda: np.nonzero(np.array(0)))
+ self.assert_deprecated(lambda: np.nonzero(np.array(1)))
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index ff0fb9eff..f60eab696 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -10,7 +10,8 @@ import numpy as np
from numpy.core._rational_tests import rational
from numpy.testing import (
assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
+from itertools import permutations
def assert_dtype_equal(a, b):
assert_equal(a, b)
@@ -87,6 +88,36 @@ class TestBuiltin(object):
assert_raises(TypeError, np.dtype, 'q8')
assert_raises(TypeError, np.dtype, 'Q8')
+ @pytest.mark.parametrize(
+ 'value',
+ ['m8', 'M8', 'datetime64', 'timedelta64',
+ 'i4, (2,3)f8, f4', 'a3, 3u8, (3,4)a10',
+ '>f', '<f', '=f', '|f',
+ ])
+ def test_dtype_bytes_str_equivalence(self, value):
+ bytes_value = value.encode('ascii')
+ from_bytes = np.dtype(bytes_value)
+ from_str = np.dtype(value)
+ assert_dtype_equal(from_bytes, from_str)
+
+ def test_dtype_from_bytes(self):
+ # Empty bytes object
+ assert_raises(TypeError, np.dtype, b'')
+ # Byte order indicator, but no type
+ assert_raises(TypeError, np.dtype, b'|')
+
+ # Single character with ordinal < NPY_NTYPES returns
+ # type by index into _builtin_descrs
+ assert_dtype_equal(np.dtype(bytes([0])), np.dtype('bool'))
+ assert_dtype_equal(np.dtype(bytes([17])), np.dtype(object))
+
+ # Single character where value is a valid type code
+ assert_dtype_equal(np.dtype(b'f'), np.dtype('float32'))
+
+ # Bytes with non-ascii values raise errors
+ assert_raises(TypeError, np.dtype, b'\xff')
+ assert_raises(TypeError, np.dtype, b's\xff')
+
def test_bad_param(self):
# Can't give a size that's too small
assert_raises(ValueError, np.dtype,
@@ -328,15 +359,66 @@ class TestRecord(object):
assert_raises(IndexError, lambda: dt[-3])
assert_raises(TypeError, operator.getitem, dt, 3.0)
- assert_raises(TypeError, operator.getitem, dt, [])
assert_equal(dt[1], dt[np.int8(1)])
+ @pytest.mark.parametrize('align_flag',[False, True])
+ def test_multifield_index(self, align_flag):
+ # indexing with a list produces subfields
+ # the align flag should be preserved
+ dt = np.dtype([
+ (('title', 'col1'), '<U20'), ('A', '<f8'), ('B', '<f8')
+ ], align=align_flag)
+
+ dt_sub = dt[['B', 'col1']]
+ assert_equal(
+ dt_sub,
+ np.dtype({
+ 'names': ['B', 'col1'],
+ 'formats': ['<f8', '<U20'],
+ 'offsets': [88, 0],
+ 'titles': [None, 'title'],
+ 'itemsize': 96
+ })
+ )
+ assert_equal(dt_sub.isalignedstruct, align_flag)
+
+ dt_sub = dt[['B']]
+ assert_equal(
+ dt_sub,
+ np.dtype({
+ 'names': ['B'],
+ 'formats': ['<f8'],
+ 'offsets': [88],
+ 'itemsize': 96
+ })
+ )
+ assert_equal(dt_sub.isalignedstruct, align_flag)
+
+ dt_sub = dt[[]]
+ assert_equal(
+ dt_sub,
+ np.dtype({
+ 'names': [],
+ 'formats': [],
+ 'offsets': [],
+ 'itemsize': 96
+ })
+ )
+ assert_equal(dt_sub.isalignedstruct, align_flag)
+
+ assert_raises(TypeError, operator.getitem, dt, ())
+ assert_raises(TypeError, operator.getitem, dt, [1, 2, 3])
+ assert_raises(TypeError, operator.getitem, dt, ['col1', 2])
+ assert_raises(KeyError, operator.getitem, dt, ['fake'])
+ assert_raises(KeyError, operator.getitem, dt, ['title'])
+ assert_raises(ValueError, operator.getitem, dt, ['col1', 'col1'])
+
def test_partial_dict(self):
# 'names' is missing
assert_raises(ValueError, np.dtype,
{'formats': ['i4', 'i4'], 'f0': ('i4', 0), 'f1':('i4', 4)})
-
+
class TestSubarray(object):
def test_single_subarray(self):
@@ -370,7 +452,10 @@ class TestSubarray(object):
def test_shape_equal(self):
"""Test some data types that are equal"""
assert_dtype_equal(np.dtype('f8'), np.dtype(('f8', tuple())))
- assert_dtype_equal(np.dtype('f8'), np.dtype(('f8', 1)))
+ # FutureWarning during deprecation period; after it is passed this
+ # should instead check that "(1)f8" == "1f8" == ("f8", 1).
+ with pytest.warns(FutureWarning):
+ assert_dtype_equal(np.dtype('f8'), np.dtype(('f8', 1)))
assert_dtype_equal(np.dtype((int, 2)), np.dtype((int, (2,))))
assert_dtype_equal(np.dtype(('<f4', (3, 2))), np.dtype(('<f4', (3, 2))))
d = ([('a', 'f4', (1, 2)), ('b', 'f8', (3, 1))], (3, 2))
@@ -459,7 +544,7 @@ class TestSubarray(object):
def test_alignment(self):
#Check that subarrays are aligned
- t1 = np.dtype('1i4', align=True)
+ t1 = np.dtype('(1,)i4', align=True)
t2 = np.dtype('2i4', align=True)
assert_equal(t1.alignment, t2.alignment)
@@ -612,7 +697,7 @@ class TestStructuredDtypeSparseFields(object):
'offsets':[4]}, (2, 3))])
@pytest.mark.xfail(reason="inaccessible data is changed see gh-12686.")
- @pytest.mark.valgrind_error(reason="reads from unitialized buffers.")
+ @pytest.mark.valgrind_error(reason="reads from uninitialized buffers.")
def test_sparse_field_assignment(self):
arr = np.zeros(3, self.dtype)
sparse_arr = arr.view(self.sparse_dtype)
@@ -951,6 +1036,50 @@ def test_invalid_dtype_string():
assert_raises(TypeError, np.dtype, u'Fl\xfcgel')
+class TestFromDTypeAttribute(object):
+ def test_simple(self):
+ class dt:
+ dtype = "f8"
+
+ assert np.dtype(dt) == np.float64
+ assert np.dtype(dt()) == np.float64
+
+ def test_recursion(self):
+ class dt:
+ pass
+
+ dt.dtype = dt
+ with pytest.raises(RecursionError):
+ np.dtype(dt)
+
+ dt_instance = dt()
+ dt_instance.dtype = dt
+ with pytest.raises(RecursionError):
+ np.dtype(dt_instance)
+
+ def test_void_subtype(self):
+ class dt(np.void):
+ # This code path is fully untested before, so it is unclear
+ # what this should be useful for. Note that if np.void is used
+ # numpy will think we are deallocating a base type [1.17, 2019-02].
+ dtype = np.dtype("f,f")
+ pass
+
+ np.dtype(dt)
+ np.dtype(dt(1))
+
+ def test_void_subtype_recursion(self):
+ class dt(np.void):
+ pass
+
+ dt.dtype = dt
+
+ with pytest.raises(RecursionError):
+ np.dtype(dt)
+
+ with pytest.raises(RecursionError):
+ np.dtype(dt(1))
+
class TestFromCTypes(object):
@staticmethod
@@ -1136,3 +1265,18 @@ class TestFromCTypes(object):
self.check(ctypes.c_uint16.__ctype_be__, np.dtype('>u2'))
self.check(ctypes.c_uint8.__ctype_le__, np.dtype('u1'))
self.check(ctypes.c_uint8.__ctype_be__, np.dtype('u1'))
+
+ all_types = set(np.typecodes['All'])
+ all_pairs = permutations(all_types, 2)
+
+ @pytest.mark.parametrize("pair", all_pairs)
+ def test_pairs(self, pair):
+ """
+ Check that np.dtype('x,y') matches [np.dtype('x'), np.dtype('y')]
+ Example: np.dtype('d,I') -> dtype([('f0', '<f8'), ('f1', '<u4')])
+ """
+ # gh-5645: check that np.dtype('i,L') can be used
+ pair_type = np.dtype('{},{}'.format(*pair))
+ expected = np.dtype([('f0', pair[0]), ('f1', pair[1])])
+ assert_equal(pair_type, expected)
+
diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py
index 1b5b4cb26..cfeeb8a90 100644
--- a/numpy/core/tests/test_einsum.py
+++ b/numpy/core/tests/test_einsum.py
@@ -5,7 +5,7 @@ import itertools
import numpy as np
from numpy.testing import (
assert_, assert_equal, assert_array_equal, assert_almost_equal,
- assert_raises, suppress_warnings, assert_raises_regex, assert_allclose
+ assert_raises, suppress_warnings, assert_raises_regex
)
# Setup for optimize einsum
@@ -700,14 +700,6 @@ class TestEinsum(object):
y2 = x[idx[:, None], idx[:, None], idx, idx]
assert_equal(y1, y2)
- def test_einsum_failed_on_p9_and_s390x(self):
- # Issues gh-14692 and gh-12689
- # Bug with signed vs unsigned char errored on power9 and s390x Linux
- tensor = np.random.random_sample((10, 10, 10, 10))
- x = np.einsum('ijij->', tensor)
- y = tensor.trace(axis1=0, axis2=2).trace()
- assert_allclose(x, y)
-
def test_einsum_all_contig_non_contig_output(self):
# Issue gh-5907, tests that the all contiguous special case
# actually checks the contiguity of the output
diff --git a/numpy/core/tests/test_errstate.py b/numpy/core/tests/test_errstate.py
index 670d485c1..0008c4cc8 100644
--- a/numpy/core/tests/test_errstate.py
+++ b/numpy/core/tests/test_errstate.py
@@ -39,3 +39,11 @@ class TestErrstate(object):
with np.errstate(call=None):
assert_(np.geterrcall() is None, 'call is not None')
assert_(np.geterrcall() is olderrcall, 'call is not olderrcall')
+
+ def test_errstate_decorator(self):
+ @np.errstate(all='ignore')
+ def foo():
+ a = -np.arange(3)
+ a // 0
+
+ foo()
diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py
index 770712501..1e1e6d7d9 100644
--- a/numpy/core/tests/test_half.py
+++ b/numpy/core/tests/test_half.py
@@ -104,7 +104,7 @@ class TestHalf(object):
# logic will be necessary, an arbitrarily small offset should cause
# normal up/down rounding always.
- # Calculate the expecte pattern:
+ # Calculate the expected pattern:
cmp_patterns = f16s_patterns[1:-1].copy()
if shift == "down" and offset != "up":
diff --git a/numpy/core/tests/test_item_selection.py b/numpy/core/tests/test_item_selection.py
index 3bc24fc95..9bd246866 100644
--- a/numpy/core/tests/test_item_selection.py
+++ b/numpy/core/tests/test_item_selection.py
@@ -79,9 +79,9 @@ class TestTake(object):
assert_array_equal(a, a_original)
def test_empty_argpartition(self):
- # In reference to github issue #6530
- a = np.array([0, 2, 4, 6, 8, 10])
- a = a.argpartition(np.array([], dtype=np.int16))
+ # In reference to github issue #6530
+ a = np.array([0, 2, 4, 6, 8, 10])
+ a = a.argpartition(np.array([], dtype=np.int16))
- b = np.array([0, 1, 2, 3, 4, 5])
- assert_array_equal(a, b)
+ b = np.array([0, 1, 2, 3, 4, 5])
+ assert_array_equal(a, b)
diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py
index 990d0ae26..d2ae564b2 100644
--- a/numpy/core/tests/test_memmap.py
+++ b/numpy/core/tests/test_memmap.py
@@ -204,3 +204,13 @@ class TestMemmap(object):
self.tmpfp.write(b'a'*16)
mm = memmap(self.tmpfp, dtype='float64')
assert_equal(mm.shape, (2,))
+
+ def test_empty_array(self):
+ # gh-12653
+ with pytest.raises(ValueError, match='empty file'):
+ memmap(self.tmpfp, shape=(0,4), mode='w+')
+
+ self.tmpfp.write(b'\0')
+
+ # ok now the file is not empty
+ memmap(self.tmpfp, shape=(0,4), mode='w+')
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index c55556535..b8ec84824 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -21,7 +21,15 @@ import weakref
import pytest
from contextlib import contextmanager
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
+
+try:
+ import pathlib
+except ImportError:
+ try:
+ import pathlib2 as pathlib
+ except ImportError:
+ pathlib = None
if sys.version_info[0] >= 3:
import builtins
@@ -102,6 +110,39 @@ class TestFlags(object):
self.a[0] = 5
self.a[0] = 0
+ def test_writeable_any_base(self):
+ # Ensure that any base being writeable is sufficient to change flag;
+ # this is especially interesting for arrays from an array interface.
+ arr = np.arange(10)
+
+ class subclass(np.ndarray):
+ pass
+
+ # Create subclass so base will not be collapsed, this is OK to change
+ view1 = arr.view(subclass)
+ view2 = view1[...]
+ arr.flags.writeable = False
+ view2.flags.writeable = False
+ view2.flags.writeable = True # Can be set to True again.
+
+ arr = np.arange(10)
+
+ class frominterface:
+ def __init__(self, arr):
+ self.arr = arr
+ self.__array_interface__ = arr.__array_interface__
+
+ view1 = np.asarray(frominterface)
+ view2 = view1[...]
+ view2.flags.writeable = False
+ view2.flags.writeable = True
+
+ view1.flags.writeable = False
+ view2.flags.writeable = False
+ with assert_raises(ValueError):
+ # Must assume not writeable, since only base is not:
+ view2.flags.writeable = True
+
def test_writeable_from_readonly(self):
# gh-9440 - make sure fromstring, from buffer on readonly buffers
# set writeable False
@@ -183,6 +224,15 @@ class TestFlags(object):
with assert_warns(DeprecationWarning):
arr.flags.writeable = True
+ def test_warnonwrite(self):
+ a = np.arange(10)
+ a.flags._warn_on_write = True
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ a[1] = 10
+ a[2] = 10
+ # only warn once
+ assert_(len(w) == 1)
def test_otherflags(self):
assert_equal(self.a.flags.carray, True)
@@ -1437,10 +1487,10 @@ class TestZeroSizeFlexible(object):
sort_func(zs, kind=kind, **kwargs)
def test_sort(self):
- self._test_sort_partition('sort', kinds='qhm')
+ self._test_sort_partition('sort', kinds='qhs')
def test_argsort(self):
- self._test_sort_partition('argsort', kinds='qhm')
+ self._test_sort_partition('argsort', kinds='qhs')
def test_partition(self):
self._test_sort_partition('partition', kinds=['introselect'], kth=2)
@@ -1465,6 +1515,10 @@ class TestZeroSizeFlexible(object):
# viewing as any non-empty type gives an empty result
assert_equal(zs.view((dt, 1)).shape, (0,))
+ def test_dumps(self):
+ zs = self._zeros(10, int)
+ assert_equal(zs, pickle.loads(zs.dumps()))
+
def test_pickle(self):
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
for dt in [bytes, np.void, unicode]:
@@ -1491,6 +1545,9 @@ class TestZeroSizeFlexible(object):
class TestMethods(object):
+
+ sort_kinds = ['quicksort', 'heapsort', 'stable']
+
def test_compress(self):
tgt = [[5, 6, 7, 8, 9]]
arr = np.arange(10).reshape(2, 5)
@@ -1530,6 +1587,11 @@ class TestMethods(object):
# gh-12031, caused SEGFAULT
assert_raises(TypeError, oned.choose,np.void(0), [oned])
+ # gh-6272 check overlap on out
+ x = np.arange(5)
+ y = np.choose([0,0,0], [x[:3], x[:3], x[:3]], out=x[1:4], mode='wrap')
+ assert_equal(y, np.array([0, 1, 2]))
+
def test_prod(self):
ba = [1, 2, 10, 11, 6, 5, 4]
ba2 = [[1, 2, 3, 4], [5, 6, 7, 9], [10, 3, 4, 5]]
@@ -1649,22 +1711,37 @@ class TestMethods(object):
# of sorted items must be greater than ~50 to check the actual
# algorithm because quick and merge sort fall over to insertion
# sort for small arrays.
- a = np.arange(101)
- b = a[::-1].copy()
- for kind in ['q', 'm', 'h']:
- msg = "scalar sort, kind=%s" % kind
- c = a.copy()
- c.sort(kind=kind)
- assert_equal(c, a, msg)
- c = b.copy()
- c.sort(kind=kind)
- assert_equal(c, a, msg)
+ # Test unsigned dtypes and nonnegative numbers
+ for dtype in [np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64, np.longdouble]:
+ a = np.arange(101, dtype=dtype)
+ b = a[::-1].copy()
+ for kind in self.sort_kinds:
+ msg = "scalar sort, kind=%s, dtype=%s" % (kind, dtype)
+ c = a.copy()
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+ c = b.copy()
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+
+ # Test signed dtypes and negative numbers as well
+ for dtype in [np.int8, np.int16, np.int32, np.int64, np.float16, np.float32, np.float64, np.longdouble]:
+ a = np.arange(-50, 51, dtype=dtype)
+ b = a[::-1].copy()
+ for kind in self.sort_kinds:
+ msg = "scalar sort, kind=%s, dtype=%s" % (kind, dtype)
+ c = a.copy()
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+ c = b.copy()
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
# test complex sorts. These use the same code as the scalars
# but the compare function differs.
ai = a*1j + 1
bi = b*1j + 1
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "complex sort, real part == 1, kind=%s" % kind
c = ai.copy()
c.sort(kind=kind)
@@ -1674,7 +1751,7 @@ class TestMethods(object):
assert_equal(c, ai, msg)
ai = a + 1j
bi = b + 1j
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "complex sort, imag part == 1, kind=%s" % kind
c = ai.copy()
c.sort(kind=kind)
@@ -1696,7 +1773,7 @@ class TestMethods(object):
s = 'aaaaaaaa'
a = np.array([s + chr(i) for i in range(101)])
b = a[::-1].copy()
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "string sort, kind=%s" % kind
c = a.copy()
c.sort(kind=kind)
@@ -1709,7 +1786,7 @@ class TestMethods(object):
s = 'aaaaaaaa'
a = np.array([s + chr(i) for i in range(101)], dtype=np.unicode)
b = a[::-1].copy()
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "unicode sort, kind=%s" % kind
c = a.copy()
c.sort(kind=kind)
@@ -1799,7 +1876,7 @@ class TestMethods(object):
return True
a = np.array([Boom()]*100, dtype=object)
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "bogus comparison object sort, kind=%s" % kind
c.sort(kind=kind)
@@ -1819,7 +1896,7 @@ class TestMethods(object):
def test_sort_raises(self):
#gh-9404
arr = np.array([0, datetime.now(), 1], dtype=object)
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
assert_raises(TypeError, arr.sort, kind=kind)
#gh-3879
class Raiser(object):
@@ -1828,7 +1905,7 @@ class TestMethods(object):
__eq__ = __ne__ = __lt__ = __gt__ = __ge__ = __le__ = raises_anything
arr = np.array([[Raiser(), n] for n in range(10)]).reshape(-1)
np.random.shuffle(arr)
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
assert_raises(TypeError, arr.sort, kind=kind)
def test_sort_degraded(self):
@@ -1914,24 +1991,26 @@ class TestMethods(object):
# of sorted items must be greater than ~50 to check the actual
# algorithm because quick and merge sort fall over to insertion
# sort for small arrays.
- a = np.arange(101)
- b = a[::-1].copy()
- for kind in ['q', 'm', 'h']:
- msg = "scalar argsort, kind=%s" % kind
- assert_equal(a.copy().argsort(kind=kind), a, msg)
- assert_equal(b.copy().argsort(kind=kind), b, msg)
+
+ for dtype in [np.int32, np.uint32, np.float32]:
+ a = np.arange(101, dtype=dtype)
+ b = a[::-1].copy()
+ for kind in self.sort_kinds:
+ msg = "scalar argsort, kind=%s, dtype=%s" % (kind, dtype)
+ assert_equal(a.copy().argsort(kind=kind), a, msg)
+ assert_equal(b.copy().argsort(kind=kind), b, msg)
# test complex argsorts. These use the same code as the scalars
# but the compare function differs.
ai = a*1j + 1
bi = b*1j + 1
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "complex argsort, kind=%s" % kind
assert_equal(ai.copy().argsort(kind=kind), a, msg)
assert_equal(bi.copy().argsort(kind=kind), b, msg)
ai = a + 1j
bi = b + 1j
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "complex argsort, kind=%s" % kind
assert_equal(ai.copy().argsort(kind=kind), a, msg)
assert_equal(bi.copy().argsort(kind=kind), b, msg)
@@ -1950,7 +2029,7 @@ class TestMethods(object):
b = a[::-1].copy()
r = np.arange(101)
rr = r[::-1]
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "string argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
@@ -1961,7 +2040,7 @@ class TestMethods(object):
b = a[::-1]
r = np.arange(101)
rr = r[::-1]
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "unicode argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
@@ -1972,7 +2051,7 @@ class TestMethods(object):
b = a[::-1]
r = np.arange(101)
rr = r[::-1]
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "object argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
@@ -1983,7 +2062,7 @@ class TestMethods(object):
b = a[::-1]
r = np.arange(101)
rr = r[::-1]
- for kind in ['q', 'm', 'h']:
+ for kind in self.sort_kinds:
msg = "structured array argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
@@ -2901,8 +2980,6 @@ class TestMethods(object):
assert_equal(b.diagonal(0, 2, 1), [[0, 3], [4, 7]])
def test_diagonal_view_notwriteable(self):
- # this test is only for 1.9, the diagonal view will be
- # writeable in 1.10.
a = np.eye(3).diagonal()
assert_(not a.flags.writeable)
assert_(not a.flags.owndata)
@@ -3176,8 +3253,8 @@ class TestMethods(object):
assert_equal(ac, np.conjugate(a))
a = np.array([1-1j, 1, 2.0, 'f'], object)
- assert_raises(AttributeError, lambda: a.conj())
- assert_raises(AttributeError, lambda: a.conjugate())
+ assert_raises(TypeError, lambda: a.conj())
+ assert_raises(TypeError, lambda: a.conjugate())
def test__complex__(self):
dtypes = ['i1', 'i2', 'i4', 'i8',
@@ -3718,17 +3795,6 @@ class TestSubscripting(object):
class TestPickling(object):
- def test_highest_available_pickle_protocol(self):
- try:
- import pickle5
- except ImportError:
- pickle5 = None
-
- if sys.version_info[:2] >= (3, 8) or pickle5 is not None:
- assert pickle.HIGHEST_PROTOCOL >= 5
- else:
- assert pickle.HIGHEST_PROTOCOL < 5
-
@pytest.mark.skipif(pickle.HIGHEST_PROTOCOL >= 5,
reason=('this tests the error messages when trying to'
'protocol 5 although it is not available'))
@@ -3884,64 +3950,6 @@ class TestPickling(object):
assert_equal(original.dtype, new.dtype)
- def test_py2_can_load_py3_pickle_with_dtype_field_names(self):
- # gh-2407 and PR #14275
- # Py2 should be able to load a pickle that was created in PY3
- # when the pickle contains a structured dtype with field names
- import numpy as np
-
- expected_dtype = np.dtype([('SPOT', np.float64)])
- expected_data = np.array([(6.0)], dtype=expected_dtype)
- # Pickled under Python 3.6.5 with protocol=2 by the code below:
- # pickle.dumps(expected_data, protocol=2)
- saved_pickle_from_py3 = b'''\
-\x80\x02cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\n\
-q\x01K\x00\x85q\x02c_codecs\nencode\nq\x03X\x01\x00\x00\x00bq\x04X\
-\x06\x00\x00\x00latin1q\x05\x86q\x06Rq\x07\x87q\x08Rq\t(K\x01K\x01\
-\x85q\ncnumpy\ndtype\nq\x0bX\x02\x00\x00\x00V8q\x0cK\x00K\x01\x87q\
-\rRq\x0e(K\x03X\x01\x00\x00\x00|q\x0fNX\x04\x00\x00\x00SPOTq\x10\
-\x85q\x11}q\x12h\x10h\x0bX\x02\x00\x00\x00f8q\x13K\x00K\x01\x87\
-q\x14Rq\x15(K\x03X\x01\x00\x00\x00<q\x16NNNJ\xff\xff\xff\xffJ\xff\
-\xff\xff\xffK\x00tq\x17bK\x00\x86q\x18sK\x08K\x01K\x10tq\x19b\x89h\
-\x03X\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18@q\x1ah\x05\x86q\
-\x1bRq\x1ctq\x1db.\
-'''
-
- if sys.version_info[0] < 3: # PY2
- assert pickle.loads(saved_pickle_from_py3) == expected_data
- else:
- # check that the string above is what we claim on PY3
- py3_pickle_dump = pickle.dumps(expected_data, protocol=2)
- assert py3_pickle_dump == saved_pickle_from_py3
-
- def test_py3_can_load_py2_pickle_with_dtype_field_names(self):
- # gh-2407 and PR #14275
- # Roundtrip: Py3 should load a pickle that was created in PY2
- # after loading the saved_pickle (from PY3) in the test named
- # 'test_py2_can_load_py3_pickle_with_dtype_field_names'
- import numpy as np
-
- expected_dtype = np.dtype([('SPOT', np.float64)])
- expected = np.array([(6.0)], dtype=expected_dtype)
- # Pickled under Python 2.7.16 with protocol=2 after it was loaded
- # by test 'test_py2_can_load_py3_pickle_with_dtype_field_names'
- pickle_from_py2 = b'''\
-\x80\x02cnumpy.core.multiarray\n_reconstruct\nq\x01cnumpy\nndarray\n\
-q\x02K\x00\x85U\x01b\x87Rq\x03(K\x01K\x01\x85cnumpy\ndtype\nq\x04U\x02\
-V8K\x00K\x01\x87Rq\x05(K\x03U\x01|NU\x04SPOTq\x06\x85q\x07}q\x08h\x06h\
-\x04U\x02f8K\x00K\x01\x87Rq\t(K\x03U\x01<NNNJ\xff\xff\xff\xffJ\xff\xff\
-\xff\xffK\x00tbK\x00\x86sK\x08K\x01K\x10tb\x89U\x08\x00\x00\x00\x00\x00\
-\x00\x18@tb.\
-'''
-
- if sys.version_info[0] >= 3: # PY3
- assert pickle.loads(pickle_from_py2) == expected
- else:
- # check that the string above is what we claim on PY2
- if sys.platform.startswith('linux') and not IS_PYPY:
- assert pickle.dumps(expected, protocol=2) == pickle_from_py2
-
-
class TestFancyIndexing(object):
def test_list(self):
@@ -4372,7 +4380,11 @@ class TestClip(object):
x = (np.random.random(1000) * array_max).astype(dtype)
if inplace:
- x.clip(clip_min, clip_max, x)
+ # The tests that call us pass clip_min and clip_max that
+ # might not fit in the destination dtype. They were written
+ # assuming the previous unsafe casting, which now must be
+ # passed explicitly to avoid a warning.
+ x.clip(clip_min, clip_max, x, casting='unsafe')
else:
x = x.clip(clip_min, clip_max)
byteorder = '='
@@ -4391,7 +4403,7 @@ class TestClip(object):
'float', 1024, 0, 0, inplace=inplace)
self._clip_type(
- 'int', 1024, -120, 100.5, inplace=inplace)
+ 'int', 1024, -120, 100, inplace=inplace)
self._clip_type(
'int', 1024, 0, 0, inplace=inplace)
@@ -4485,6 +4497,16 @@ class TestPutmask(object):
assert_array_equal(rec['y'], [11, 4])
assert_array_equal(rec['z'], [3, 3])
+ def test_overlaps(self):
+ # gh-6272 check overlap
+ x = np.array([True, False, True, False])
+ np.putmask(x[1:4], [True, True, True], x[:3])
+ assert_equal(x, np.array([True, True, False, True]))
+
+ x = np.array([True, False, True, False])
+ np.putmask(x[1:4], x[:3], [True, False, True])
+ assert_equal(x, np.array([True, True, True, True]))
+
class TestTake(object):
def tst_basic(self, x):
@@ -4533,6 +4555,11 @@ class TestTake(object):
rec1 = rec.take([1])
assert_(rec1['x'] == 5.0 and rec1['y'] == 4.0)
+ def test_out_overlap(self):
+ # gh-6272 check overlap on out
+ x = np.arange(5)
+ y = np.take(x, [1, 2, 3], out=x[2:5], mode='wrap')
+ assert_equal(y, np.array([1, 2, 3]))
class TestLexsort(object):
def test_basic(self):
@@ -4648,6 +4675,20 @@ class TestIO(object):
y = np.fromfile(self.filename, dtype=self.dtype)
assert_array_equal(y, self.x.flat)
+ @pytest.mark.skipif(pathlib is None, reason="pathlib not found")
+ def test_roundtrip_pathlib(self):
+ p = pathlib.Path(self.filename)
+ self.x.tofile(p)
+ y = np.fromfile(p, dtype=self.dtype)
+ assert_array_equal(y, self.x.flat)
+
+ @pytest.mark.skipif(pathlib is None, reason="pathlib not found")
+ def test_roundtrip_dump_pathlib(self):
+ p = pathlib.Path(self.filename)
+ self.x.dump(p)
+ y = np.load(p, allow_pickle=True)
+ assert_array_equal(y, self.x)
+
def test_roundtrip_binary_str(self):
s = self.x.tobytes()
y = np.frombuffer(s, dtype=self.dtype)
@@ -4780,6 +4821,36 @@ class TestIO(object):
assert_raises_regex(ValueError, "Cannot read into object array",
np.fromfile, self.filename, dtype=object)
+ def test_fromfile_offset(self):
+ with open(self.filename, 'wb') as f:
+ self.x.tofile(f)
+
+ with open(self.filename, 'rb') as f:
+ y = np.fromfile(f, dtype=self.dtype, offset=0)
+ assert_array_equal(y, self.x.flat)
+
+ with open(self.filename, 'rb') as f:
+ count_items = len(self.x.flat) // 8
+ offset_items = len(self.x.flat) // 4
+ offset_bytes = self.dtype.itemsize * offset_items
+ y = np.fromfile(f, dtype=self.dtype, count=count_items, offset=offset_bytes)
+ assert_array_equal(y, self.x.flat[offset_items:offset_items+count_items])
+
+ # subsequent seeks should stack
+ offset_bytes = self.dtype.itemsize
+ z = np.fromfile(f, dtype=self.dtype, offset=offset_bytes)
+ assert_array_equal(z, self.x.flat[offset_items+count_items+1:])
+
+ with open(self.filename, 'wb') as f:
+ self.x.tofile(f, sep=",")
+
+ with open(self.filename, 'rb') as f:
+ assert_raises_regex(
+ TypeError,
+ "'offset' argument only permitted for binary files",
+ np.fromfile, self.filename, dtype=self.dtype,
+ sep=",", offset=1)
+
def _check_from(self, s, value, **kw):
if 'sep' not in kw:
y = np.frombuffer(s, **kw)
@@ -5822,7 +5893,7 @@ class MatmulCommon(object):
"""
# Should work with these types. Will want to add
# "O" at some point
- types = "?bhilqBHILQefdgFDG"
+ types = "?bhilqBHILQefdgFDGO"
def test_exceptions(self):
dims = [
@@ -5873,8 +5944,9 @@ class MatmulCommon(object):
assert_(res.dtype == dt)
# vector vector returns scalars
- res = self.matmul(v, v)
- assert_(type(res) is np.dtype(dt).type)
+ if dt != "O":
+ res = self.matmul(v, v)
+ assert_(type(res) is np.dtype(dt).type)
def test_scalar_output(self):
vec1 = np.array([2])
@@ -6053,7 +6125,7 @@ class TestMatmul(MatmulCommon):
assert_array_equal(out, tgt, err_msg=msg)
# test out with not allowed type cast (safe casting)
- msg = "Cannot cast ufunc matmul output"
+ msg = "Cannot cast ufunc .* output"
out = np.zeros((5, 2), dtype=np.int32)
assert_raises_regex(TypeError, msg, self.matmul, a, b, out=out)
@@ -6125,14 +6197,14 @@ class TestMatmul(MatmulCommon):
r3 = np.matmul(args[0].copy(), args[1].copy())
assert_equal(r1, r3)
-
+
def test_matmul_object(self):
import fractions
f = np.vectorize(fractions.Fraction)
def random_ints():
return np.random.randint(1, 1000, size=(10, 3, 3))
- M1 = f(random_ints(), random_ints())
+ M1 = f(random_ints(), random_ints())
M2 = f(random_ints(), random_ints())
M3 = self.matmul(M1, M2)
@@ -6171,23 +6243,6 @@ class TestMatmul(MatmulCommon):
with assert_raises(TypeError):
b = np.matmul(a, a)
- def test_matmul_bool(self):
- # gh-14439
- a = np.array([[1, 0],[1, 1]], dtype=bool)
- assert np.max(a.view(np.uint8)) == 1
- b = np.matmul(a, a)
- # matmul with boolean output should always be 0, 1
- assert np.max(b.view(np.uint8)) == 1
-
- np.random.seed(42)
- d = np.random.randint(2, size=4*5, dtype=np.int8)
- d = d.reshape(4, 5) > 0
- out1 = np.matmul(d, d.reshape(5, 4))
- out2 = np.dot(d, d.reshape(5, 4))
- assert_equal(out1, out2)
-
- c = np.matmul(np.zeros((2, 0), dtype=bool), np.zeros(0, dtype=bool))
- assert not np.any(c)
if sys.version_info[:2] >= (3, 5):
@@ -7291,14 +7346,10 @@ def test_array_interface_empty_shape():
assert_equal(arr1, arr2)
assert_equal(arr1, arr3)
-@pytest.mark.skipif(IS_PYPY, reason='PyDict_GetItemString(.., "data") segfaults')
def test_array_interface_offset():
arr = np.array([1, 2, 3], dtype='int32')
interface = dict(arr.__array_interface__)
- if sys.version_info[0] < 3:
- interface['data'] = buffer(arr)
- else:
- interface['data'] = memoryview(arr)
+ interface['data'] = memoryview(arr)
interface['shape'] = (2,)
interface['offset'] = 4
@@ -7845,8 +7896,6 @@ class TestFormat(object):
dst = object.__format__(a, '30')
assert_equal(res, dst)
-from numpy.testing import IS_PYPY
-
class TestCTypes(object):
def test_ctypes_is_available(self):
@@ -7913,29 +7962,7 @@ class TestCTypes(object):
# but when the `ctypes_ptr` object dies, so should `arr`
del ctypes_ptr
- if IS_PYPY:
- # Pypy does not recycle arr objects immediately. Trigger gc to
- # release arr. Cpython uses refcounts. An explicit call to gc
- # should not be needed here.
- break_cycles()
- assert_(arr_ref() is None, "unknowable whether ctypes pointer holds a reference")
-
- def test_ctypes_as_parameter_holds_reference(self):
- arr = np.array([None]).copy()
-
- arr_ref = weakref.ref(arr)
-
- ctypes_ptr = arr.ctypes._as_parameter_
-
- # `ctypes_ptr` should hold onto `arr`
- del arr
break_cycles()
- assert_(arr_ref() is not None, "ctypes pointer did not hold onto a reference")
-
- # but when the `ctypes_ptr` object dies, so should `arr`
- del ctypes_ptr
- if IS_PYPY:
- break_cycles()
assert_(arr_ref() is None, "unknowable whether ctypes pointer holds a reference")
@@ -7953,13 +7980,6 @@ class TestWritebackIfCopy(object):
res = np.argmin(mat, 0, out=out)
assert_equal(res, range(5))
- def test_clip_with_out(self):
- mat = np.eye(5)
- out = np.eye(5, dtype='i2')
- res = np.clip(mat, a_min=-10, a_max=0, out=out)
- assert_(res is out)
- assert_equal(np.sum(out), 0)
-
def test_insert_noncontiguous(self):
a = np.arange(6).reshape(2,3).T # force non-c-contiguous
# uses arr_insert
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index 3a24ce55e..cf66751f8 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -2292,7 +2292,7 @@ class TestIterNested(object):
assert_equal(vals, [[0, 1, 2], [3, 4, 5]])
vals = None
- # writebackifcopy - using conext manager
+ # writebackifcopy - using context manager
a = arange(6, dtype='f4').reshape(2, 3)
i, j = np.nested_iters(a, [[0], [1]],
op_flags=['readwrite', 'updateifcopy'],
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index ed02c1561..935b84234 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -13,7 +13,7 @@ from numpy.random import rand, randint, randn
from numpy.testing import (
assert_, assert_equal, assert_raises, assert_raises_regex,
assert_array_equal, assert_almost_equal, assert_array_almost_equal,
- HAS_REFCOUNT
+ assert_warns, HAS_REFCOUNT
)
@@ -43,7 +43,7 @@ class TestResize(object):
def test_reshape_from_zero(self):
# See also gh-6740
- A = np.zeros(0, dtype=[('a', np.float32, 1)])
+ A = np.zeros(0, dtype=[('a', np.float32)])
Ar = np.resize(A, (2, 1))
assert_array_equal(Ar, np.zeros((2, 1), Ar.dtype))
assert_equal(A.dtype, Ar.dtype)
@@ -152,7 +152,15 @@ class TestNonarrayArgs(object):
def test_squeeze(self):
A = [[[1, 1, 1], [2, 2, 2], [3, 3, 3]]]
- assert_(np.squeeze(A).shape == (3, 3))
+ assert_equal(np.squeeze(A).shape, (3, 3))
+ assert_equal(np.squeeze(np.zeros((1, 3, 1))).shape, (3,))
+ assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=0).shape, (3, 1))
+ assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=-1).shape, (1, 3))
+ assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=2).shape, (1, 3))
+ assert_equal(np.squeeze([np.zeros((3, 1))]).shape, (3,))
+ assert_equal(np.squeeze([np.zeros((3, 1))], axis=0).shape, (3, 1))
+ assert_equal(np.squeeze([np.zeros((3, 1))], axis=2).shape, (1, 3))
+ assert_equal(np.squeeze([np.zeros((3, 1))], axis=-1).shape, (1, 3))
def test_std(self):
A = [[1, 2, 3], [4, 5, 6]]
@@ -208,6 +216,9 @@ class TestNonarrayArgs(object):
assert_(np.isnan(np.var([])))
assert_(w[0].category is RuntimeWarning)
+ B = np.array([None, 0])
+ B[0] = 1j
+ assert_almost_equal(np.var(B), 0.25)
class TestIsscalar(object):
def test_isscalar(self):
@@ -1000,12 +1011,24 @@ class TestNonzero(object):
assert_equal(np.count_nonzero(np.array([], dtype='?')), 0)
assert_equal(np.nonzero(np.array([])), ([],))
+ assert_equal(np.count_nonzero(np.array([0])), 0)
+ assert_equal(np.count_nonzero(np.array([0], dtype='?')), 0)
+ assert_equal(np.nonzero(np.array([0])), ([],))
+
+ assert_equal(np.count_nonzero(np.array([1])), 1)
+ assert_equal(np.count_nonzero(np.array([1], dtype='?')), 1)
+ assert_equal(np.nonzero(np.array([1])), ([0],))
+
+ def test_nonzero_zerod(self):
assert_equal(np.count_nonzero(np.array(0)), 0)
assert_equal(np.count_nonzero(np.array(0, dtype='?')), 0)
- assert_equal(np.nonzero(np.array(0)), ([],))
+ with assert_warns(DeprecationWarning):
+ assert_equal(np.nonzero(np.array(0)), ([],))
+
assert_equal(np.count_nonzero(np.array(1)), 1)
assert_equal(np.count_nonzero(np.array(1, dtype='?')), 1)
- assert_equal(np.nonzero(np.array(1)), ([0],))
+ with assert_warns(DeprecationWarning):
+ assert_equal(np.nonzero(np.array(1)), ([0],))
def test_nonzero_onedim(self):
x = np.array([1, 0, 2, -1, 0, 0, 8])
@@ -1199,6 +1222,38 @@ class TestNonzero(object):
assert_raises(ValueError, np.nonzero, np.array([BoolErrors()]))
+ def test_nonzero_sideeffect_safety(self):
+ # gh-13631
+ class FalseThenTrue:
+ _val = False
+ def __bool__(self):
+ try:
+ return self._val
+ finally:
+ self._val = True
+
+ class TrueThenFalse:
+ _val = True
+ def __bool__(self):
+ try:
+ return self._val
+ finally:
+ self._val = False
+
+ # result grows on the second pass
+ a = np.array([True, FalseThenTrue()])
+ assert_raises(RuntimeError, np.nonzero, a)
+
+ a = np.array([[True], [FalseThenTrue()]])
+ assert_raises(RuntimeError, np.nonzero, a)
+
+ # result shrinks on the second pass
+ a = np.array([False, TrueThenFalse()])
+ assert_raises(RuntimeError, np.nonzero, a)
+
+ a = np.array([[False], [TrueThenFalse()]])
+ assert_raises(RuntimeError, np.nonzero, a)
+
class TestIndex(object):
def test_boolean(self):
@@ -1360,11 +1415,17 @@ class TestClip(object):
self.nr = 5
self.nc = 3
- def fastclip(self, a, m, M, out=None):
+ def fastclip(self, a, m, M, out=None, casting=None):
if out is None:
- return a.clip(m, M)
+ if casting is None:
+ return a.clip(m, M)
+ else:
+ return a.clip(m, M, casting=casting)
else:
- return a.clip(m, M, out)
+ if casting is None:
+ return a.clip(m, M, out)
+ else:
+ return a.clip(m, M, out, casting=casting)
def clip(self, a, m, M, out=None):
# use slow-clip
@@ -1402,6 +1463,20 @@ class TestClip(object):
return (10 * rand(n, m)).astype(np.int32)
# Now the real test cases
+
+ @pytest.mark.parametrize("dtype", '?bhilqpBHILQPefdgFDGO')
+ def test_ones_pathological(self, dtype):
+ # for preservation of behavior described in
+ # gh-12519; amin > amax behavior may still change
+ # in the future
+ arr = np.ones(10, dtype=dtype)
+ expected = np.zeros(10, dtype=dtype)
+ actual = np.clip(arr, 1, 0)
+ if dtype == 'O':
+ assert actual.tolist() == expected.tolist()
+ else:
+ assert_equal(actual, expected)
+
def test_simple_double(self):
# Test native double input with scalar min/max.
a = self._generate_data(self.nr, self.nc)
@@ -1500,14 +1575,21 @@ class TestClip(object):
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
- def test_simple_int32_inout(self):
+ @pytest.mark.parametrize("casting", [None, "unsafe"])
+ def test_simple_int32_inout(self, casting):
# Test native int32 input with double min/max and int32 out.
a = self._generate_int32_data(self.nr, self.nc)
m = np.float64(0)
M = np.float64(2)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ if casting is None:
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac, casting=casting)
+ else:
+ # explicitly passing "unsafe" will silence warning
+ self.fastclip(a, m, M, ac, casting=casting)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1529,7 +1611,9 @@ class TestClip(object):
M = np.float64(1)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1540,7 +1624,9 @@ class TestClip(object):
M = 2.0
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1716,7 +1802,9 @@ class TestClip(object):
M = np.float64(2)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1738,7 +1826,9 @@ class TestClip(object):
M = np.float64(1)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1749,7 +1839,9 @@ class TestClip(object):
M = 2.0
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- self.fastclip(a, m, M, ac)
+ with assert_warns(DeprecationWarning):
+ # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ self.fastclip(a, m, M, ac)
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -1802,11 +1894,94 @@ class TestClip(object):
def test_clip_nan(self):
d = np.arange(7.)
- assert_equal(d.clip(min=np.nan), d)
- assert_equal(d.clip(max=np.nan), d)
- assert_equal(d.clip(min=np.nan, max=np.nan), d)
- assert_equal(d.clip(min=-2, max=np.nan), d)
- assert_equal(d.clip(min=np.nan, max=10), d)
+ with assert_warns(DeprecationWarning):
+ assert_equal(d.clip(min=np.nan), d)
+ with assert_warns(DeprecationWarning):
+ assert_equal(d.clip(max=np.nan), d)
+ with assert_warns(DeprecationWarning):
+ assert_equal(d.clip(min=np.nan, max=np.nan), d)
+ with assert_warns(DeprecationWarning):
+ assert_equal(d.clip(min=-2, max=np.nan), d)
+ with assert_warns(DeprecationWarning):
+ assert_equal(d.clip(min=np.nan, max=10), d)
+
+ def test_object_clip(self):
+ a = np.arange(10, dtype=object)
+ actual = np.clip(a, 1, 5)
+ expected = np.array([1, 1, 2, 3, 4, 5, 5, 5, 5, 5])
+ assert actual.tolist() == expected.tolist()
+
+ def test_clip_all_none(self):
+ a = np.arange(10, dtype=object)
+ with assert_raises_regex(ValueError, 'max or min'):
+ np.clip(a, None, None)
+
+ def test_clip_invalid_casting(self):
+ a = np.arange(10, dtype=object)
+ with assert_raises_regex(ValueError,
+ 'casting must be one of'):
+ self.fastclip(a, 1, 8, casting="garbage")
+
+ @pytest.mark.parametrize("amin, amax", [
+ # two scalars
+ (1, 0),
+ # mix scalar and array
+ (1, np.zeros(10)),
+ # two arrays
+ (np.ones(10), np.zeros(10)),
+ ])
+ def test_clip_value_min_max_flip(self, amin, amax):
+ a = np.arange(10, dtype=np.int64)
+ # requirement from ufunc_docstrings.py
+ expected = np.minimum(np.maximum(a, amin), amax)
+ actual = np.clip(a, amin, amax)
+ assert_equal(actual, expected)
+
+ @pytest.mark.parametrize("arr, amin, amax, exp", [
+ # for a bug in npy_ObjectClip, based on a
+ # case produced by hypothesis
+ (np.zeros(10, dtype=np.int64),
+ 0,
+ -2**64+1,
+ np.full(10, -2**64+1, dtype=object)),
+ # for bugs in NPY_TIMEDELTA_MAX, based on a case
+ # produced by hypothesis
+ (np.zeros(10, dtype='m8') - 1,
+ 0,
+ 0,
+ np.zeros(10, dtype='m8')),
+ ])
+ def test_clip_problem_cases(self, arr, amin, amax, exp):
+ actual = np.clip(arr, amin, amax)
+ assert_equal(actual, exp)
+
+ @pytest.mark.xfail(reason="no scalar nan propagation yet")
+ @pytest.mark.parametrize("arr, amin, amax", [
+ # problematic scalar nan case from hypothesis
+ (np.zeros(10, dtype=np.int64),
+ np.array(np.nan),
+ np.zeros(10, dtype=np.int32)),
+ ])
+ def test_clip_scalar_nan_propagation(self, arr, amin, amax):
+ # enforcement of scalar nan propagation for comparisons
+ # called through clip()
+ expected = np.minimum(np.maximum(a, amin), amax)
+ with assert_warns(DeprecationWarning):
+ actual = np.clip(arr, amin, amax)
+ assert_equal(actual, expected)
+
+ @pytest.mark.xfail(reason="propagation doesn't match spec")
+ @pytest.mark.parametrize("arr, amin, amax", [
+ (np.array([1] * 10, dtype='m8'),
+ np.timedelta64('NaT'),
+ np.zeros(10, dtype=np.int32)),
+ ])
+ def test_NaT_propagation(self, arr, amin, amax):
+ # NOTE: the expected function spec doesn't
+ # propagate NaT, but clip() now does
+ expected = np.minimum(np.maximum(a, amin), amax)
+ actual = np.clip(arr, amin, amax)
+ assert_equal(actual, expected)
class TestAllclose(object):
@@ -2181,6 +2356,7 @@ class TestLikeFuncs(object):
(np.arange(24).reshape(2, 3, 4).swapaxes(0, 1), None),
(np.arange(24).reshape(4, 3, 2).swapaxes(0, 1), '?'),
]
+ self.shapes = [(5,), (5,6,), (5,6,7,)]
def compare_array_value(self, dz, value, fill_value):
if value is not None:
@@ -2246,6 +2422,34 @@ class TestLikeFuncs(object):
assert_equal(dz.dtype, np.dtype(dtype))
self.compare_array_value(dz, value, fill_value)
+ # Test the 'shape' parameter
+ for s in self.shapes:
+ for o in 'CFA':
+ sz = like_function(d, dtype=dtype, shape=s, order=o,
+ **fill_kwarg)
+ assert_equal(sz.shape, s)
+ if dtype is None:
+ assert_equal(sz.dtype, d.dtype)
+ else:
+ assert_equal(sz.dtype, np.dtype(dtype))
+ if o == 'C' or (o == 'A' and d.flags.c_contiguous):
+ assert_(sz.flags.c_contiguous)
+ elif o == 'F' or (o == 'A' and d.flags.f_contiguous):
+ assert_(sz.flags.f_contiguous)
+ self.compare_array_value(sz, value, fill_value)
+
+ if (d.ndim != len(s)):
+ assert_equal(np.argsort(like_function(d, dtype=dtype,
+ shape=s, order='K',
+ **fill_kwarg).strides),
+ np.argsort(np.empty(s, dtype=dtype,
+ order='C').strides))
+ else:
+ assert_equal(np.argsort(like_function(d, dtype=dtype,
+ shape=s, order='K',
+ **fill_kwarg).strides),
+ np.argsort(d.strides))
+
# Test the 'subok' parameter
class MyNDArray(np.ndarray):
pass
@@ -2651,6 +2855,47 @@ def test_outer_out_param():
assert_equal(np.outer(arr2, arr3, out2), out2)
+class TestIndices(object):
+
+ def test_simple(self):
+ [x, y] = np.indices((4, 3))
+ assert_array_equal(x, np.array([[0, 0, 0],
+ [1, 1, 1],
+ [2, 2, 2],
+ [3, 3, 3]]))
+ assert_array_equal(y, np.array([[0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]]))
+
+ def test_single_input(self):
+ [x] = np.indices((4,))
+ assert_array_equal(x, np.array([0, 1, 2, 3]))
+
+ [x] = np.indices((4,), sparse=True)
+ assert_array_equal(x, np.array([0, 1, 2, 3]))
+
+ def test_scalar_input(self):
+ assert_array_equal([], np.indices(()))
+ assert_array_equal([], np.indices((), sparse=True))
+ assert_array_equal([[]], np.indices((0,)))
+ assert_array_equal([[]], np.indices((0,), sparse=True))
+
+ def test_sparse(self):
+ [x, y] = np.indices((4,3), sparse=True)
+ assert_array_equal(x, np.array([[0], [1], [2], [3]]))
+ assert_array_equal(y, np.array([[0, 1, 2]]))
+
+ @pytest.mark.parametrize("dtype", [np.int, np.float32, np.float64])
+ @pytest.mark.parametrize("dims", [(), (0,), (4, 3)])
+ def test_return_type(self, dtype, dims):
+ inds = np.indices(dims, dtype=dtype)
+ assert_(inds.dtype == dtype)
+
+ for arr in np.indices(dims, dtype=dtype, sparse=True):
+ assert_(arr.dtype == dtype)
+
+
class TestRequire(object):
flag_names = ['C', 'C_CONTIGUOUS', 'CONTIGUOUS',
'F', 'F_CONTIGUOUS', 'FORTRAN',
@@ -2731,6 +2976,8 @@ class TestBroadcast(object):
arrs = [np.empty((6, 7)), np.empty((5, 6, 1)), np.empty((7,)),
np.empty((5, 1, 7))]
mits = [np.broadcast(*arrs),
+ np.broadcast(np.broadcast(*arrs[:0]), np.broadcast(*arrs[0:])),
+ np.broadcast(np.broadcast(*arrs[:1]), np.broadcast(*arrs[1:])),
np.broadcast(np.broadcast(*arrs[:2]), np.broadcast(*arrs[2:])),
np.broadcast(arrs[0], np.broadcast(*arrs[1:-1]), arrs[-1])]
for mit in mits:
@@ -2755,7 +3002,7 @@ class TestBroadcast(object):
arr = np.empty((5,))
for j in range(35):
arrs = [arr] * j
- if j < 1 or j > 32:
+ if j > 32:
assert_raises(ValueError, np.broadcast, *arrs)
else:
mit = np.broadcast(*arrs)
@@ -2795,3 +3042,9 @@ class TestTensordot(object):
td = np.tensordot(a, b, (1, 0))
assert_array_equal(td, np.dot(a, b))
assert_array_equal(td, np.einsum('ij,jk', a, b))
+
+ def test_zero_dimensional(self):
+ # gh-12130
+ arr_0d = np.array(1)
+ ret = np.tensordot(arr_0d, arr_0d, ([], [])) # contracting no axes is well defined
+ assert_array_equal(ret, arr_0d)
diff --git a/numpy/core/tests/test_overrides.py b/numpy/core/tests/test_overrides.py
index 8f1c16539..63b0e4539 100644
--- a/numpy/core/tests/test_overrides.py
+++ b/numpy/core/tests/test_overrides.py
@@ -2,19 +2,20 @@ from __future__ import division, absolute_import, print_function
import inspect
import sys
+from unittest import mock
import numpy as np
from numpy.testing import (
assert_, assert_equal, assert_raises, assert_raises_regex)
from numpy.core.overrides import (
_get_implementing_args, array_function_dispatch,
- verify_matching_signatures, ENABLE_ARRAY_FUNCTION)
-from numpy.core.numeric import pickle
+ verify_matching_signatures, ARRAY_FUNCTION_ENABLED)
+from numpy.compat import pickle
import pytest
requires_array_function = pytest.mark.skipif(
- not ENABLE_ARRAY_FUNCTION,
+ not ARRAY_FUNCTION_ENABLED,
reason="__array_function__ dispatch not enabled.")
@@ -35,7 +36,6 @@ def dispatched_two_arg(array1, array2):
return 'original'
-@requires_array_function
class TestGetImplementingArgs(object):
def test_ndarray(self):
@@ -147,9 +147,9 @@ class TestGetImplementingArgs(object):
_get_implementing_args(relevant_args)
-@requires_array_function
class TestNDArrayArrayFunction(object):
+ @requires_array_function
def test_method(self):
class Other(object):
@@ -198,11 +198,13 @@ class TestNDArrayArrayFunction(object):
assert_equal(result, expected.view(OverrideSub))
def test_no_wrapper(self):
+ # This shouldn't happen unless a user intentionally calls
+ # __array_function__ with invalid arguments, but check that we raise
+ # an appropriate error all the same.
array = np.array(1)
- func = dispatched_one_arg.__wrapped__
- with assert_raises_regex(AttributeError, '__wrapped__'):
- array.__array_function__(func=func,
- types=(np.ndarray,),
+ func = lambda x: x
+ with assert_raises_regex(AttributeError, '_implementation'):
+ array.__array_function__(func=func, types=(np.ndarray,),
args=(array,), kwargs={})
@@ -376,7 +378,6 @@ class TestNumPyFunctions(object):
assert_equal(np.fft.fft.__module__, 'numpy.fft')
assert_equal(np.linalg.solve.__module__, 'numpy.linalg')
- @pytest.mark.skipif(sys.version_info[0] < 3, reason="Python 3 only")
def test_inspect_sum(self):
signature = inspect.signature(np.sum)
assert_('axis' in signature.parameters)
@@ -390,3 +391,39 @@ class TestNumPyFunctions(object):
return 'yes'
assert_equal(np.sum(MyArray()), 'yes')
+
+ @requires_array_function
+ def test_sum_on_mock_array(self):
+
+ # We need a proxy for mocks because __array_function__ is only looked
+ # up in the class dict
+ class ArrayProxy:
+ def __init__(self, value):
+ self.value = value
+ def __array_function__(self, *args, **kwargs):
+ return self.value.__array_function__(*args, **kwargs)
+ def __array__(self, *args, **kwargs):
+ return self.value.__array__(*args, **kwargs)
+
+ proxy = ArrayProxy(mock.Mock(spec=ArrayProxy))
+ proxy.value.__array_function__.return_value = 1
+ result = np.sum(proxy)
+ assert_equal(result, 1)
+ proxy.value.__array_function__.assert_called_once_with(
+ np.sum, (ArrayProxy,), (proxy,), {})
+ proxy.value.__array__.assert_not_called()
+
+ @requires_array_function
+ def test_sum_forwarding_implementation(self):
+
+ class MyArray(np.ndarray):
+
+ def sum(self, axis, out):
+ return 'summed'
+
+ def __array_function__(self, func, types, args, kwargs):
+ return super().__array_function__(func, types, args, kwargs)
+
+ # note: the internal implementation of np.sum() calls the .sum() method
+ array = np.array(1).view(MyArray)
+ assert_equal(np.sum(array), 'summed')
diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
index 95ed1fa5b..14413224e 100644
--- a/numpy/core/tests/test_records.py
+++ b/numpy/core/tests/test_records.py
@@ -17,7 +17,7 @@ from numpy.testing import (
assert_, assert_equal, assert_array_equal, assert_array_almost_equal,
assert_raises, temppath
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
class TestFromrecords(object):
@@ -435,54 +435,14 @@ class TestRecord(object):
def test_missing_field(self):
# https://github.com/numpy/numpy/issues/4806
arr = np.zeros((3,), dtype=[('x', int), ('y', int)])
- assert_raises(ValueError, lambda: arr[['nofield']])
-
- @pytest.mark.parametrize('nfields', [0, 1, 2])
- def test_assign_dtype_attribute(self, nfields):
- dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
- data = np.zeros(3, dt).view(np.recarray)
-
- # the original and resulting dtypes differ on whether they are records
- assert data.dtype.type == np.record
- assert dt.type != np.record
-
- # ensure that the dtype remains a record even when assigned
- data.dtype = dt
- assert data.dtype.type == np.record
-
- @pytest.mark.parametrize('nfields', [0, 1, 2])
- def test_nested_fields_are_records(self, nfields):
- """ Test that nested structured types are treated as records too """
- dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
- dt_outer = np.dtype([('inner', dt)])
-
- data = np.zeros(3, dt_outer).view(np.recarray)
- assert isinstance(data, np.recarray)
- assert isinstance(data['inner'], np.recarray)
-
- data0 = data[0]
- assert isinstance(data0, np.record)
- assert isinstance(data0['inner'], np.record)
-
- def test_nested_dtype_padding(self):
- """ test that trailing padding is preserved """
- # construct a dtype with padding at the end
- dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)])
- dt_padded_end = np.dtype(dict(
- names=['a', 'b'],
- formats=[np.uint8, np.uint8],
- offsets=[0, 1],
- itemsize=3
- )) # dt[['a', 'b']], but that's not supported in 1.16
- assert dt_padded_end.itemsize == dt.itemsize
-
- dt_outer = np.dtype([('inner', dt_padded_end)])
-
- data = np.zeros(3, dt_outer).view(np.recarray)
- assert_equal(data['inner'].dtype, dt_padded_end)
-
- data0 = data[0]
- assert_equal(data0['inner'].dtype, dt_padded_end)
+ assert_raises(KeyError, lambda: arr[['nofield']])
+
+ def test_fromarrays_nested_structured_arrays(self):
+ arrays = [
+ np.arange(10),
+ np.ones(10, dtype=[('a', '<u2'), ('b', '<f4')]),
+ ]
+ arr = np.rec.fromarrays(arrays) # ValueError?
def test_find_duplicate():
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 8d84b2c12..4e48c82b7 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -16,8 +16,7 @@ from numpy.testing import (
assert_raises_regex, assert_warns, suppress_warnings,
_assert_valid_refcount, HAS_REFCOUNT,
)
-from numpy.compat import asbytes, asunicode, long
-from numpy.core.numeric import pickle
+from numpy.compat import asbytes, asunicode, long, pickle
try:
RecursionError
@@ -469,7 +468,7 @@ class TestRegression(object):
result = pickle.loads(data, encoding='bytes')
assert_equal(result, original)
- if isinstance(result, np.ndarray) and result.dtype.names is not None:
+ if isinstance(result, np.ndarray) and result.dtype.names:
for name in result.dtype.names:
assert_(isinstance(name, str))
@@ -2455,33 +2454,3 @@ class TestRegression(object):
__array_interface__ = {}
np.array([T()])
-
- def test_2d__array__shape(self):
- class T(object):
- def __array__(self):
- return np.ndarray(shape=(0,0))
-
- # Make sure __array__ is used instead of Sequence methods.
- def __iter__(self):
- return iter([])
-
- def __getitem__(self, idx):
- raise AssertionError("__getitem__ was called")
-
- def __len__(self):
- return 0
-
-
- t = T()
- #gh-13659, would raise in broadcasting [x=t for x in result]
- np.array([t])
-
- @pytest.mark.skipif(sys.maxsize < 2 ** 31 + 1, reason='overflows 32-bit python')
- @pytest.mark.skipif(sys.platform == 'win32' and sys.version_info[:2] < (3, 8),
- reason='overflows on windows, fixed in bpo-16865')
- def test_to_ctypes(self):
- #gh-14214
- arr = np.zeros((2 ** 31 + 1,), 'b')
- assert arr.size * arr.itemsize > 2 ** 31
- c_arr = np.ctypeslib.as_ctypes(arr)
- assert_equal(c_arr._length_, arr.size)
diff --git a/numpy/core/tests/test_scalar_methods.py b/numpy/core/tests/test_scalar_methods.py
new file mode 100644
index 000000000..93434dd1b
--- /dev/null
+++ b/numpy/core/tests/test_scalar_methods.py
@@ -0,0 +1,109 @@
+"""
+Test the scalar constructors, which also do type-coercion
+"""
+from __future__ import division, absolute_import, print_function
+
+import os
+import fractions
+import platform
+
+import pytest
+import numpy as np
+
+from numpy.testing import (
+ run_module_suite,
+ assert_equal, assert_almost_equal, assert_raises, assert_warns,
+ dec
+)
+
+class TestAsIntegerRatio(object):
+ # derived in part from the cpython test "test_floatasratio"
+
+ @pytest.mark.parametrize("ftype", [
+ np.half, np.single, np.double, np.longdouble])
+ @pytest.mark.parametrize("f, ratio", [
+ (0.875, (7, 8)),
+ (-0.875, (-7, 8)),
+ (0.0, (0, 1)),
+ (11.5, (23, 2)),
+ ])
+ def test_small(self, ftype, f, ratio):
+ assert_equal(ftype(f).as_integer_ratio(), ratio)
+
+ @pytest.mark.parametrize("ftype", [
+ np.half, np.single, np.double, np.longdouble])
+ def test_simple_fractions(self, ftype):
+ R = fractions.Fraction
+ assert_equal(R(0, 1),
+ R(*ftype(0.0).as_integer_ratio()))
+ assert_equal(R(5, 2),
+ R(*ftype(2.5).as_integer_ratio()))
+ assert_equal(R(1, 2),
+ R(*ftype(0.5).as_integer_ratio()))
+ assert_equal(R(-2100, 1),
+ R(*ftype(-2100.0).as_integer_ratio()))
+
+ @pytest.mark.parametrize("ftype", [
+ np.half, np.single, np.double, np.longdouble])
+ def test_errors(self, ftype):
+ assert_raises(OverflowError, ftype('inf').as_integer_ratio)
+ assert_raises(OverflowError, ftype('-inf').as_integer_ratio)
+ assert_raises(ValueError, ftype('nan').as_integer_ratio)
+
+ def test_against_known_values(self):
+ R = fractions.Fraction
+ assert_equal(R(1075, 512),
+ R(*np.half(2.1).as_integer_ratio()))
+ assert_equal(R(-1075, 512),
+ R(*np.half(-2.1).as_integer_ratio()))
+ assert_equal(R(4404019, 2097152),
+ R(*np.single(2.1).as_integer_ratio()))
+ assert_equal(R(-4404019, 2097152),
+ R(*np.single(-2.1).as_integer_ratio()))
+ assert_equal(R(4728779608739021, 2251799813685248),
+ R(*np.double(2.1).as_integer_ratio()))
+ assert_equal(R(-4728779608739021, 2251799813685248),
+ R(*np.double(-2.1).as_integer_ratio()))
+ # longdouble is platform dependent
+
+ @pytest.mark.parametrize("ftype, frac_vals, exp_vals", [
+ # dtype test cases generated using hypothesis
+ # first five generated cases per dtype
+ (np.half, [0.0, 0.01154830649280303, 0.31082276347447274,
+ 0.527350517124794, 0.8308562335072596],
+ [0, 1, 0, -8, 12]),
+ (np.single, [0.0, 0.09248576989263226, 0.8160498218131407,
+ 0.17389442853722373, 0.7956044195067877],
+ [0, 12, 10, 17, -26]),
+ (np.double, [0.0, 0.031066908499895136, 0.5214135908877832,
+ 0.45780736035689296, 0.5906586745934036],
+ [0, -801, 51, 194, -653]),
+ pytest.param(
+ np.longdouble,
+ [0.0, 0.20492557202724854, 0.4277180662199366, 0.9888085019891495,
+ 0.9620175814461964],
+ [0, -7400, 14266, -7822, -8721],
+ marks=[
+ pytest.mark.skipif(
+ np.finfo(np.double) == np.finfo(np.longdouble),
+ reason="long double is same as double"),
+ pytest.mark.skipif(
+ platform.machine().startswith("ppc"),
+ reason="IBM double double"),
+ ]
+ )
+ ])
+ def test_roundtrip(self, ftype, frac_vals, exp_vals):
+ for frac, exp in zip(frac_vals, exp_vals):
+ f = np.ldexp(frac, exp, dtype=ftype)
+ n, d = f.as_integer_ratio()
+
+ try:
+ # workaround for gh-9968
+ nf = np.longdouble(str(n))
+ df = np.longdouble(str(d))
+ except (OverflowError, RuntimeWarning):
+ # the values may not fit in any float type
+ pytest.skip("longdouble too small on this platform")
+
+ assert_equal(nf / df, f, "{}/{}".format(n, d))
diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py
index cd520d99b..3ded7eecd 100644
--- a/numpy/core/tests/test_scalarbuffer.py
+++ b/numpy/core/tests/test_scalarbuffer.py
@@ -65,7 +65,7 @@ class TestScalarPEP3118(object):
assert_(isinstance(x, np.void))
mv_x = memoryview(x)
expected_size = 16 * np.dtype((np.unicode_, 1)).itemsize
- expected_size += 2 * np.dtype((np.float64, 1)).itemsize
+ expected_size += 2 * np.dtype(np.float64).itemsize
assert_equal(mv_x.itemsize, expected_size)
assert_equal(mv_x.ndim, 0)
assert_equal(mv_x.shape, ())
diff --git a/numpy/core/tests/test_scalarprint.py b/numpy/core/tests/test_scalarprint.py
index cde1355aa..86b0ca199 100644
--- a/numpy/core/tests/test_scalarprint.py
+++ b/numpy/core/tests/test_scalarprint.py
@@ -51,7 +51,7 @@ class TestRealScalars(object):
def test_py2_float_print(self):
# gh-10753
- # In python2, the python float type implements an obsolte method
+ # In python2, the python float type implements an obsolete method
# tp_print, which overrides tp_repr and tp_str when using "print" to
# output to a "real file" (ie, not a StringIO). Make sure we don't
# inherit it.
diff --git a/numpy/core/tests/test_shape_base.py b/numpy/core/tests/test_shape_base.py
index b996321c2..53d272fc5 100644
--- a/numpy/core/tests/test_shape_base.py
+++ b/numpy/core/tests/test_shape_base.py
@@ -224,13 +224,27 @@ class TestConcatenate(object):
assert_raises(ValueError, concatenate, (0,))
assert_raises(ValueError, concatenate, (np.array(0),))
+ # dimensionality must match
+ assert_raises_regex(
+ ValueError,
+ r"all the input arrays must have same number of dimensions, but "
+ r"the array at index 0 has 1 dimension\(s\) and the array at "
+ r"index 1 has 2 dimension\(s\)",
+ np.concatenate, (np.zeros(1), np.zeros((1, 1))))
+
# test shapes must match except for concatenation axis
a = np.ones((1, 2, 3))
b = np.ones((2, 2, 3))
axis = list(range(3))
for i in range(3):
np.concatenate((a, b), axis=axis[0]) # OK
- assert_raises(ValueError, np.concatenate, (a, b), axis=axis[1])
+ assert_raises_regex(
+ ValueError,
+ "all the input array dimensions for the concatenation axis "
+ "must match exactly, but along dimension {}, the array at "
+ "index 0 has size 1 and the array at index 1 has size 2"
+ .format(i),
+ np.concatenate, (a, b), axis=axis[1])
assert_raises(ValueError, np.concatenate, (a, b), axis=axis[2])
a = np.moveaxis(a, -1, 0)
b = np.moveaxis(b, -1, 0)
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index b83b8ccff..707c690dd 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -3,6 +3,8 @@ from __future__ import division, absolute_import, print_function
import warnings
import itertools
+import pytest
+
import numpy as np
import numpy.core._umath_tests as umt
import numpy.linalg._umath_linalg as uml
@@ -13,7 +15,7 @@ from numpy.testing import (
assert_almost_equal, assert_array_almost_equal, assert_no_warnings,
assert_allclose,
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
class TestUfuncKwargs(object):
@@ -42,6 +44,103 @@ class TestUfuncKwargs(object):
assert_raises(TypeError, np.add, 1, 2, extobj=[4096], parrot=True)
+class TestUfuncGenericLoops(object):
+ """Test generic loops.
+
+ The loops to be tested are:
+
+ PyUFunc_ff_f_As_dd_d
+ PyUFunc_ff_f
+ PyUFunc_dd_d
+ PyUFunc_gg_g
+ PyUFunc_FF_F_As_DD_D
+ PyUFunc_DD_D
+ PyUFunc_FF_F
+ PyUFunc_GG_G
+ PyUFunc_OO_O
+ PyUFunc_OO_O_method
+ PyUFunc_f_f_As_d_d
+ PyUFunc_d_d
+ PyUFunc_f_f
+ PyUFunc_g_g
+ PyUFunc_F_F_As_D_D
+ PyUFunc_F_F
+ PyUFunc_D_D
+ PyUFunc_G_G
+ PyUFunc_O_O
+ PyUFunc_O_O_method
+ PyUFunc_On_Om
+
+ Where:
+
+ f -- float
+ d -- double
+ g -- long double
+ F -- complex float
+ D -- complex double
+ G -- complex long double
+ O -- python object
+
+ It is difficult to assure that each of these loops is entered from the
+ Python level as the special cased loops are a moving target and the
+ corresponding types are architecture dependent. We probably need to
+ define C level testing ufuncs to get at them. For the time being, I've
+ just looked at the signatures registered in the build directory to find
+ relevant functions.
+
+ """
+ np_dtypes = [
+ (np.single, np.single), (np.single, np.double),
+ (np.csingle, np.csingle), (np.csingle, np.cdouble),
+ (np.double, np.double), (np.longdouble, np.longdouble),
+ (np.cdouble, np.cdouble), (np.clongdouble, np.clongdouble)]
+
+ @pytest.mark.parametrize('input_dtype,output_dtype', np_dtypes)
+ def test_unary_PyUFunc(self, input_dtype, output_dtype, f=np.exp, x=0, y=1):
+ xs = np.full(10, input_dtype(x), dtype=output_dtype)
+ ys = f(xs)[::2]
+ assert_allclose(ys, y)
+ assert_equal(ys.dtype, output_dtype)
+
+ def f2(x, y):
+ return x**y
+
+ @pytest.mark.parametrize('input_dtype,output_dtype', np_dtypes)
+ def test_binary_PyUFunc(self, input_dtype, output_dtype, f=f2, x=0, y=1):
+ xs = np.full(10, input_dtype(x), dtype=output_dtype)
+ ys = f(xs, xs)[::2]
+ assert_allclose(ys, y)
+ assert_equal(ys.dtype, output_dtype)
+
+ # class to use in testing object method loops
+ class foo(object):
+ def conjugate(self):
+ return np.bool_(1)
+
+ def logical_xor(self, obj):
+ return np.bool_(1)
+
+ def test_unary_PyUFunc_O_O(self):
+ x = np.ones(10, dtype=object)
+ assert_(np.all(np.abs(x) == 1))
+
+ def test_unary_PyUFunc_O_O_method(self, foo=foo):
+ x = np.full(10, foo(), dtype=object)
+ assert_(np.all(np.conjugate(x) == True))
+
+ def test_binary_PyUFunc_OO_O(self):
+ x = np.ones(10, dtype=object)
+ assert_(np.all(np.add(x, x) == 2))
+
+ def test_binary_PyUFunc_OO_O_method(self, foo=foo):
+ x = np.full(10, foo(), dtype=object)
+ assert_(np.all(np.logical_xor(x, x)))
+
+ def test_binary_PyUFunc_On_Om_method(self, foo=foo):
+ x = np.full((10, 2, 3), foo(), dtype=object)
+ assert_(np.all(np.logical_xor(x, x)))
+
+
class TestUfunc(object):
def test_pickle(self):
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
@@ -65,146 +164,6 @@ class TestUfunc(object):
idx = np.array(list(zip(np.arange(L - 2), np.arange(L - 2) + 2))).ravel()
assert_array_equal(np.add.reduceat(x, idx)[::2], [1, 3, 5, 7])
- def test_generic_loops(self):
- """Test generic loops.
-
- The loops to be tested are:
-
- PyUFunc_ff_f_As_dd_d
- PyUFunc_ff_f
- PyUFunc_dd_d
- PyUFunc_gg_g
- PyUFunc_FF_F_As_DD_D
- PyUFunc_DD_D
- PyUFunc_FF_F
- PyUFunc_GG_G
- PyUFunc_OO_O
- PyUFunc_OO_O_method
- PyUFunc_f_f_As_d_d
- PyUFunc_d_d
- PyUFunc_f_f
- PyUFunc_g_g
- PyUFunc_F_F_As_D_D
- PyUFunc_F_F
- PyUFunc_D_D
- PyUFunc_G_G
- PyUFunc_O_O
- PyUFunc_O_O_method
- PyUFunc_On_Om
-
- Where:
-
- f -- float
- d -- double
- g -- long double
- F -- complex float
- D -- complex double
- G -- complex long double
- O -- python object
-
- It is difficult to assure that each of these loops is entered from the
- Python level as the special cased loops are a moving target and the
- corresponding types are architecture dependent. We probably need to
- define C level testing ufuncs to get at them. For the time being, I've
- just looked at the signatures registered in the build directory to find
- relevant functions.
-
- Fixme, currently untested:
-
- PyUFunc_ff_f_As_dd_d
- PyUFunc_FF_F_As_DD_D
- PyUFunc_f_f_As_d_d
- PyUFunc_F_F_As_D_D
- PyUFunc_On_Om
-
- """
- fone = np.exp
- ftwo = lambda x, y: x**y
- fone_val = 1
- ftwo_val = 1
- # check unary PyUFunc_f_f.
- msg = "PyUFunc_f_f"
- x = np.zeros(10, dtype=np.single)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
- # check unary PyUFunc_d_d.
- msg = "PyUFunc_d_d"
- x = np.zeros(10, dtype=np.double)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
- # check unary PyUFunc_g_g.
- msg = "PyUFunc_g_g"
- x = np.zeros(10, dtype=np.longdouble)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
- # check unary PyUFunc_F_F.
- msg = "PyUFunc_F_F"
- x = np.zeros(10, dtype=np.csingle)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
- # check unary PyUFunc_D_D.
- msg = "PyUFunc_D_D"
- x = np.zeros(10, dtype=np.cdouble)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
- # check unary PyUFunc_G_G.
- msg = "PyUFunc_G_G"
- x = np.zeros(10, dtype=np.clongdouble)[0::2]
- assert_almost_equal(fone(x), fone_val, err_msg=msg)
-
- # check binary PyUFunc_ff_f.
- msg = "PyUFunc_ff_f"
- x = np.ones(10, dtype=np.single)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
- # check binary PyUFunc_dd_d.
- msg = "PyUFunc_dd_d"
- x = np.ones(10, dtype=np.double)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
- # check binary PyUFunc_gg_g.
- msg = "PyUFunc_gg_g"
- x = np.ones(10, dtype=np.longdouble)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
- # check binary PyUFunc_FF_F.
- msg = "PyUFunc_FF_F"
- x = np.ones(10, dtype=np.csingle)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
- # check binary PyUFunc_DD_D.
- msg = "PyUFunc_DD_D"
- x = np.ones(10, dtype=np.cdouble)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
- # check binary PyUFunc_GG_G.
- msg = "PyUFunc_GG_G"
- x = np.ones(10, dtype=np.clongdouble)[0::2]
- assert_almost_equal(ftwo(x, x), ftwo_val, err_msg=msg)
-
- # class to use in testing object method loops
- class foo(object):
- def conjugate(self):
- return np.bool_(1)
-
- def logical_xor(self, obj):
- return np.bool_(1)
-
- # check unary PyUFunc_O_O
- msg = "PyUFunc_O_O"
- x = np.ones(10, dtype=object)[0::2]
- assert_(np.all(np.abs(x) == 1), msg)
- # check unary PyUFunc_O_O_method
- msg = "PyUFunc_O_O_method"
- x = np.zeros(10, dtype=object)[0::2]
- for i in range(len(x)):
- x[i] = foo()
- assert_(np.all(np.conjugate(x) == True), msg)
-
- # check binary PyUFunc_OO_O
- msg = "PyUFunc_OO_O"
- x = np.ones(10, dtype=object)[0::2]
- assert_(np.all(np.add(x, x) == 2), msg)
- # check binary PyUFunc_OO_O_method
- msg = "PyUFunc_OO_O_method"
- x = np.zeros(10, dtype=object)[0::2]
- for i in range(len(x)):
- x[i] = foo()
- assert_(np.all(np.logical_xor(x, x)), msg)
-
- # check PyUFunc_On_Om
- # fixme -- I don't know how to do this yet
-
def test_all_ufunc(self):
"""Try to check presence and results of all ufuncs.
@@ -379,45 +338,21 @@ class TestUfunc(object):
assert_equal(flags, (self.can_ignore, self.size_inferred, 0))
assert_equal(sizes, (3, -1, 9))
- def test_signature_failure0(self):
- # in the following calls, a ValueError should be raised because
- # of error in core signature
- # FIXME These should be using assert_raises
+ def test_signature_failure_extra_parenthesis(self):
+ with assert_raises(ValueError):
+ umt.test_signature(2, 1, "((i)),(i)->()")
- # error: extra parenthesis
- msg = "core_sig: extra parenthesis"
- try:
- ret = umt.test_signature(2, 1, "((i)),(i)->()")
- assert_equal(ret, None, err_msg=msg)
- except ValueError:
- pass
-
- def test_signature_failure1(self):
- # error: parenthesis matching
- msg = "core_sig: parenthesis matching"
- try:
- ret = umt.test_signature(2, 1, "(i),)i(->()")
- assert_equal(ret, None, err_msg=msg)
- except ValueError:
- pass
+ def test_signature_failure_mismatching_parenthesis(self):
+ with assert_raises(ValueError):
+ umt.test_signature(2, 1, "(i),)i(->()")
- def test_signature_failure2(self):
- # error: incomplete signature. letters outside of parenthesis are ignored
- msg = "core_sig: incomplete signature"
- try:
- ret = umt.test_signature(2, 1, "(i),->()")
- assert_equal(ret, None, err_msg=msg)
- except ValueError:
- pass
+ def test_signature_failure_signature_missing_input_arg(self):
+ with assert_raises(ValueError):
+ umt.test_signature(2, 1, "(i),->()")
- def test_signature_failure3(self):
- # error: incomplete signature. 2 output arguments are specified
- msg = "core_sig: incomplete signature"
- try:
- ret = umt.test_signature(2, 2, "(i),(i)->()")
- assert_equal(ret, None, err_msg=msg)
- except ValueError:
- pass
+ def test_signature_failure_signature_missing_output_arg(self):
+ with assert_raises(ValueError):
+ umt.test_signature(2, 2, "(i),(i)->()")
def test_get_signature(self):
assert_equal(umt.inner1d.signature, "(i),(i)->()")
@@ -596,6 +531,12 @@ class TestUfunc(object):
assert_equal(np.sum(np.ones((2, 3, 5), dtype=np.int64), axis=(0, 2), initial=2),
[12, 12, 12])
+ def test_sum_where(self):
+ # More extensive tests done in test_reduction_with_where.
+ assert_equal(np.sum([[1., 2.], [3., 4.]], where=[True, False]), 4.)
+ assert_equal(np.sum([[1., 2.], [3., 4.]], axis=0, initial=5.,
+ where=[True, False]), [9., 5.])
+
def test_inner1d(self):
a = np.arange(6).reshape((2, 3))
assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1))
@@ -623,6 +564,18 @@ class TestUfunc(object):
b = np.arange(3).reshape((3, 1, 1))
assert_raises(ValueError, umt.inner1d, a, b)
+ # Writing to a broadcasted array with overlap should warn, gh-2705
+ a = np.arange(2)
+ b = np.arange(4).reshape((2, 2))
+ u, v = np.broadcast_arrays(a, b)
+ assert_equal(u.strides[0], 0)
+ x = u + v
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter("always")
+ u += v
+ assert_equal(len(w), 1)
+ assert_(x[0,0] != u[0, 0])
+
def test_type_cast(self):
msg = "type cast"
a = np.arange(6, dtype='short').reshape((2, 3))
@@ -1162,6 +1115,8 @@ class TestUfunc(object):
assert_equal(np.array([[1]], dtype=object).sum(), 1)
assert_equal(np.array([[[1, 2]]], dtype=object).sum((0, 1)), [1, 2])
assert_equal(np.array([1], dtype=object).sum(initial=1), 2)
+ assert_equal(np.array([[1], [2, 3]], dtype=object)
+ .sum(initial=[0], where=[False, True]), [0, 2, 3])
def test_object_array_accumulate_inplace(self):
# Checks that in-place accumulates work, see also gh-7402
@@ -1396,6 +1351,44 @@ class TestUfunc(object):
res = np.add.reduce(a, initial=5)
assert_equal(res, 15)
+ @pytest.mark.parametrize('axis', (0, 1, None))
+ @pytest.mark.parametrize('where', (np.array([False, True, True]),
+ np.array([[True], [False], [True]]),
+ np.array([[True, False, False],
+ [False, True, False],
+ [False, True, True]])))
+ def test_reduction_with_where(self, axis, where):
+ a = np.arange(9.).reshape(3, 3)
+ a_copy = a.copy()
+ a_check = np.zeros_like(a)
+ np.positive(a, out=a_check, where=where)
+
+ res = np.add.reduce(a, axis=axis, where=where)
+ check = a_check.sum(axis)
+ assert_equal(res, check)
+ # Check we do not overwrite elements of a internally.
+ assert_array_equal(a, a_copy)
+
+ @pytest.mark.parametrize(('axis', 'where'),
+ ((0, np.array([True, False, True])),
+ (1, [True, True, False]),
+ (None, True)))
+ @pytest.mark.parametrize('initial', (-np.inf, 5.))
+ def test_reduction_with_where_and_initial(self, axis, where, initial):
+ a = np.arange(9.).reshape(3, 3)
+ a_copy = a.copy()
+ a_check = np.full(a.shape, -np.inf)
+ np.positive(a, out=a_check, where=where)
+
+ res = np.maximum.reduce(a, axis=axis, where=where, initial=initial)
+ check = a_check.max(axis, initial=initial)
+ assert_equal(res, check)
+
+ def test_reduction_where_initial_needed(self):
+ a = np.arange(9.).reshape(3, 3)
+ m = [False, True, False]
+ assert_raises(ValueError, np.maximum.reduce, a, where=m)
+
def test_identityless_reduction_nonreorderable(self):
a = np.array([[8.0, 2.0, 2.0], [1.0, 0.5, 0.25]])
@@ -1532,6 +1525,7 @@ class TestUfunc(object):
result = struct_ufunc.add_triplet(a, b)
assert_equal(result, np.array([(2, 4, 6)], dtype='u8,u8,u8'))
+ assert_raises(RuntimeError, struct_ufunc.register_fail)
def test_custom_ufunc(self):
a = np.array(
@@ -1749,16 +1743,19 @@ class TestUfunc(object):
assert_equal(f(d, 0, None, None, True), r.reshape((1,) + r.shape))
assert_equal(f(d, 0, None, None, False, 0), r)
assert_equal(f(d, 0, None, None, False, initial=0), r)
+ assert_equal(f(d, 0, None, None, False, 0, True), r)
+ assert_equal(f(d, 0, None, None, False, 0, where=True), r)
# multiple keywords
assert_equal(f(d, axis=0, dtype=None, out=None, keepdims=False), r)
assert_equal(f(d, 0, dtype=None, out=None, keepdims=False), r)
assert_equal(f(d, 0, None, out=None, keepdims=False), r)
- assert_equal(f(d, 0, None, out=None, keepdims=False, initial=0), r)
+ assert_equal(f(d, 0, None, out=None, keepdims=False, initial=0,
+ where=True), r)
# too little
assert_raises(TypeError, f)
# too much
- assert_raises(TypeError, f, d, 0, None, None, False, 0, 1)
+ assert_raises(TypeError, f, d, 0, None, None, False, 0, True, 1)
# invalid axis
assert_raises(TypeError, f, d, "invalid")
assert_raises(TypeError, f, d, axis="invalid")
@@ -1857,3 +1854,96 @@ class TestUfunc(object):
def test_no_doc_string(self):
# gh-9337
assert_('\n' not in umt.inner1d_no_doc.__doc__)
+
+ def test_invalid_args(self):
+ # gh-7961
+ exc = pytest.raises(TypeError, np.sqrt, None)
+ # minimally check the exception text
+ assert exc.match('loop of ufunc does not support')
+
+ @pytest.mark.parametrize('nat', [np.datetime64('nat'), np.timedelta64('nat')])
+ def test_nat_is_not_finite(self, nat):
+ try:
+ assert not np.isfinite(nat)
+ except TypeError:
+ pass # ok, just not implemented
+
+ @pytest.mark.parametrize('nat', [np.datetime64('nat'), np.timedelta64('nat')])
+ def test_nat_is_nan(self, nat):
+ try:
+ assert np.isnan(nat)
+ except TypeError:
+ pass # ok, just not implemented
+
+ @pytest.mark.parametrize('nat', [np.datetime64('nat'), np.timedelta64('nat')])
+ def test_nat_is_not_inf(self, nat):
+ try:
+ assert not np.isinf(nat)
+ except TypeError:
+ pass # ok, just not implemented
+
+
+@pytest.mark.parametrize('ufunc', [getattr(np, x) for x in dir(np)
+ if isinstance(getattr(np, x), np.ufunc)])
+def test_ufunc_types(ufunc):
+ '''
+ Check all ufuncs that the correct type is returned. Avoid
+ object and boolean types since many operations are not defined for
+ for them.
+
+ Choose the shape so even dot and matmul will succeed
+ '''
+ for typ in ufunc.types:
+ # types is a list of strings like ii->i
+ if 'O' in typ or '?' in typ:
+ continue
+ inp, out = typ.split('->')
+ args = [np.ones((3, 3), t) for t in inp]
+ with warnings.catch_warnings(record=True):
+ warnings.filterwarnings("always")
+ res = ufunc(*args)
+ if isinstance(res, tuple):
+ outs = tuple(out)
+ assert len(res) == len(outs)
+ for r, t in zip(res, outs):
+ assert r.dtype == np.dtype(t)
+ else:
+ assert res.dtype == np.dtype(out)
+
+@pytest.mark.parametrize('ufunc', [getattr(np, x) for x in dir(np)
+ if isinstance(getattr(np, x), np.ufunc)])
+def test_ufunc_noncontiguous(ufunc):
+ '''
+ Check that contiguous and non-contiguous calls to ufuncs
+ have the same results for values in range(9)
+ '''
+ for typ in ufunc.types:
+ # types is a list of strings like ii->i
+ if any(set('O?mM') & set(typ)):
+ # bool, object, datetime are too irregular for this simple test
+ continue
+ inp, out = typ.split('->')
+ args_c = [np.empty(6, t) for t in inp]
+ args_n = [np.empty(18, t)[::3] for t in inp]
+ for a in args_c:
+ a.flat = range(1,7)
+ for a in args_n:
+ a.flat = range(1,7)
+ with warnings.catch_warnings(record=True):
+ warnings.filterwarnings("always")
+ res_c = ufunc(*args_c)
+ res_n = ufunc(*args_n)
+ if len(out) == 1:
+ res_c = (res_c,)
+ res_n = (res_n,)
+ for c_ar, n_ar in zip(res_c, res_n):
+ dt = c_ar.dtype
+ if np.issubdtype(dt, np.floating):
+ # for floating point results allow a small fuss in comparisons
+ # since different algorithms (libm vs. intrinsics) can be used
+ # for different input strides
+ res_eps = np.finfo(dt).eps
+ tol = 2*res_eps
+ assert_allclose(res_c, res_n, atol=tol, rtol=tol)
+ else:
+ assert_equal(c_ar, n_ar)
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index eb6a67fa3..cd2034d9c 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -5,6 +5,7 @@ import warnings
import fnmatch
import itertools
import pytest
+from fractions import Fraction
import numpy.core.umath as ncu
from numpy.core import _umath_tests as ncu_tests
@@ -12,11 +13,10 @@ import numpy as np
from numpy.testing import (
assert_, assert_equal, assert_raises, assert_raises_regex,
assert_array_equal, assert_almost_equal, assert_array_almost_equal,
- assert_allclose, assert_no_warnings, suppress_warnings,
+ assert_array_max_ulp, assert_allclose, assert_no_warnings, suppress_warnings,
_gen_alignment_data
)
-
def on_powerpc():
""" True if we are running on a Power PC platform."""
return platform.processor() == 'powerpc' or \
@@ -649,6 +649,59 @@ class TestExp(object):
yf = np.array(y, dtype=dt)*log2_
assert_almost_equal(np.exp(yf), xf)
+class TestSpecialFloats(object):
+ def test_exp_values(self):
+ x = [np.nan, np.nan, np.inf, 0.]
+ y = [np.nan, -np.nan, np.inf, -np.inf]
+ for dt in ['f', 'd', 'g']:
+ xf = np.array(x, dtype=dt)
+ yf = np.array(y, dtype=dt)
+ assert_equal(np.exp(yf), xf)
+
+ with np.errstate(over='raise'):
+ assert_raises(FloatingPointError, np.exp, np.float32(100.))
+ assert_raises(FloatingPointError, np.exp, np.float32(1E19))
+
+ def test_log_values(self):
+ with np.errstate(all='ignore'):
+ x = [np.nan, np.nan, np.inf, np.nan, -np.inf, np.nan]
+ y = [np.nan, -np.nan, np.inf, -np.inf, 0., -1.0]
+ for dt in ['f', 'd', 'g']:
+ xf = np.array(x, dtype=dt)
+ yf = np.array(y, dtype=dt)
+ assert_equal(np.log(yf), xf)
+
+ with np.errstate(divide='raise'):
+ assert_raises(FloatingPointError, np.log, np.float32(0.))
+
+ with np.errstate(invalid='raise'):
+ assert_raises(FloatingPointError, np.log, np.float32(-np.inf))
+ assert_raises(FloatingPointError, np.log, np.float32(-1.0))
+
+class TestExpLogFloat32(object):
+ def test_exp_float32(self):
+ np.random.seed(42)
+ x_f32 = np.float32(np.random.uniform(low=0.0,high=88.1,size=1000000))
+ x_f64 = np.float64(x_f32)
+ assert_array_max_ulp(np.exp(x_f32), np.float32(np.exp(x_f64)), maxulp=2.6)
+
+ def test_log_float32(self):
+ np.random.seed(42)
+ x_f32 = np.float32(np.random.uniform(low=0.0,high=1000,size=1000000))
+ x_f64 = np.float64(x_f32)
+ assert_array_max_ulp(np.log(x_f32), np.float32(np.log(x_f64)), maxulp=3.9)
+
+ def test_strided_exp_log_float32(self):
+ np.random.seed(42)
+ strides = np.random.randint(low=-100, high=100, size=100)
+ sizes = np.random.randint(low=1, high=2000, size=100)
+ for ii in sizes:
+ x_f32 = np.float32(np.random.uniform(low=0.01,high=88.1,size=ii))
+ exp_true = np.exp(x_f32)
+ log_true = np.log(x_f32)
+ for jj in strides:
+ assert_equal(np.exp(x_f32[::jj]), exp_true[::jj])
+ assert_equal(np.log(x_f32[::jj]), log_true[::jj])
class TestLogAddExp(_FilterInvalids):
def test_logaddexp_values(self):
@@ -1900,7 +1953,8 @@ class TestSpecialMethods(object):
# reduce, kwargs
res = np.multiply.reduce(a, axis='axis0', dtype='dtype0', out='out0',
- keepdims='keep0', initial='init0')
+ keepdims='keep0', initial='init0',
+ where='where0')
assert_equal(res[0], a)
assert_equal(res[1], np.multiply)
assert_equal(res[2], 'reduce')
@@ -1909,7 +1963,8 @@ class TestSpecialMethods(object):
'out': ('out0',),
'keepdims': 'keep0',
'axis': 'axis0',
- 'initial': 'init0'})
+ 'initial': 'init0',
+ 'where': 'where0'})
# reduce, output equal to None removed, but not other explicit ones,
# even if they are at their default value.
@@ -1919,14 +1974,18 @@ class TestSpecialMethods(object):
assert_equal(res[4], {'axis': 0, 'keepdims': True})
res = np.multiply.reduce(a, None, out=(None,), dtype=None)
assert_equal(res[4], {'axis': None, 'dtype': None})
- res = np.multiply.reduce(a, 0, None, None, False, 2)
- assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False, 'initial': 2})
- # np._NoValue ignored for initial.
- res = np.multiply.reduce(a, 0, None, None, False, np._NoValue)
- assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False})
- # None kept for initial.
- res = np.multiply.reduce(a, 0, None, None, False, None)
- assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False, 'initial': None})
+ res = np.multiply.reduce(a, 0, None, None, False, 2, True)
+ assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False,
+ 'initial': 2, 'where': True})
+ # np._NoValue ignored for initial
+ res = np.multiply.reduce(a, 0, None, None, False,
+ np._NoValue, True)
+ assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False,
+ 'where': True})
+ # None kept for initial, True for where.
+ res = np.multiply.reduce(a, 0, None, None, False, None, True)
+ assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False,
+ 'initial': None, 'where': True})
# reduce, wrong args
assert_raises(ValueError, np.multiply.reduce, a, out=())
@@ -2454,6 +2513,42 @@ class TestRationalFunctions(object):
assert_equal(np.gcd(2**100, 3**100), 1)
+class TestRoundingFunctions(object):
+
+ def test_object_direct(self):
+ """ test direct implementation of these magic methods """
+ class C:
+ def __floor__(self):
+ return 1
+ def __ceil__(self):
+ return 2
+ def __trunc__(self):
+ return 3
+
+ arr = np.array([C(), C()])
+ assert_equal(np.floor(arr), [1, 1])
+ assert_equal(np.ceil(arr), [2, 2])
+ assert_equal(np.trunc(arr), [3, 3])
+
+ def test_object_indirect(self):
+ """ test implementations via __float__ """
+ class C:
+ def __float__(self):
+ return -2.5
+
+ arr = np.array([C(), C()])
+ assert_equal(np.floor(arr), [-3, -3])
+ assert_equal(np.ceil(arr), [-2, -2])
+ with pytest.raises(TypeError):
+ np.trunc(arr) # consistent with math.trunc
+
+ def test_fraction(self):
+ f = Fraction(-4, 3)
+ assert_equal(np.floor(f), -2)
+ assert_equal(np.ceil(f), -1)
+ assert_equal(np.trunc(f), -1)
+
+
class TestComplexFunctions(object):
funcs = [np.arcsin, np.arccos, np.arctan, np.arcsinh, np.arccosh,
np.arctanh, np.sin, np.cos, np.tan, np.exp,
@@ -2918,3 +3013,14 @@ def test_signaling_nan_exceptions():
with assert_no_warnings():
a = np.ndarray(shape=(), dtype='float32', buffer=b'\x00\xe0\xbf\xff')
np.isnan(a)
+
+@pytest.mark.parametrize("arr", [
+ np.arange(2),
+ np.matrix([0, 1]),
+ np.matrix([[0, 1], [2, 5]]),
+ ])
+def test_outer_subclass_preserve(arr):
+ # for gh-8661
+ class foo(np.ndarray): pass
+ actual = np.multiply.outer(arr.view(foo), arr.view(foo))
+ assert actual.__class__.__name__ == 'foo'
diff --git a/numpy/core/tests/test_umath_accuracy.py b/numpy/core/tests/test_umath_accuracy.py
new file mode 100644
index 000000000..fcbed0dd3
--- /dev/null
+++ b/numpy/core/tests/test_umath_accuracy.py
@@ -0,0 +1,53 @@
+import numpy as np
+import platform
+from os import path
+import sys
+import pytest
+from ctypes import *
+from numpy.testing import assert_array_max_ulp
+
+runtest = sys.platform.startswith('linux') and (platform.machine() == 'x86_64')
+platform_skip = pytest.mark.skipif(not runtest,
+ reason="""
+ stick to x86_64 and linux platforms.
+ test seems to fail on some of ARM and power
+ architectures.
+ """)
+
+# convert string to hex function taken from:
+# https://stackoverflow.com/questions/1592158/convert-hex-to-float #
+def convert(s):
+ i = int(s, 16) # convert from hex to a Python int
+ cp = pointer(c_int(i)) # make this into a c integer
+ fp = cast(cp, POINTER(c_float)) # cast the int pointer to a float pointer
+ return fp.contents.value # dereference the pointer, get the float
+
+str_to_float = np.vectorize(convert)
+files = ['umath-validation-set-exp',
+ 'umath-validation-set-log',
+ 'umath-validation-set-sin',
+ 'umath-validation-set-cos']
+
+class TestAccuracy(object):
+ @pytest.mark.xfail(reason="Fails for MacPython/numpy-wheels builds")
+ def test_validate_transcendentals(self):
+ with np.errstate(all='ignore'):
+ for filename in files:
+ data_dir = path.join(path.dirname(__file__), 'data')
+ filepath = path.join(data_dir, filename)
+ file_without_comments = (r for r in open(filepath) if not r[0] in ('$', '#'))
+ data = np.genfromtxt(file_without_comments,
+ dtype=('|S39','|S39','|S39',np.int),
+ names=('type','input','output','ulperr'),
+ delimiter=',',
+ skip_header=1)
+ npfunc = getattr(np, filename.split('-')[3])
+ for datatype in np.unique(data['type']):
+ data_subset = data[data['type'] == datatype]
+ inval = np.array(str_to_float(data_subset['input'].astype(str)), dtype=eval(datatype))
+ outval = np.array(str_to_float(data_subset['output'].astype(str)), dtype=eval(datatype))
+ perm = np.random.permutation(len(inval))
+ inval = inval[perm]
+ outval = outval[perm]
+ maxulperr = data_subset['ulperr'].max()
+ assert_array_max_ulp(npfunc(inval), outval, maxulperr)
diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py
index 785ae8c57..1f5b4077f 100644
--- a/numpy/core/tests/test_umath_complex.py
+++ b/numpy/core/tests/test_umath_complex.py
@@ -5,7 +5,8 @@ import platform
import pytest
import numpy as np
-import numpy.core.umath as ncu
+# import the c-extension module directly since _arg is not exported via umath
+import numpy.core._multiarray_umath as ncu
from numpy.testing import (
assert_raises, assert_equal, assert_array_equal, assert_almost_equal
)
diff --git a/numpy/core/umath.py b/numpy/core/umath.py
index a0e8ad427..f3b26ab72 100644
--- a/numpy/core/umath.py
+++ b/numpy/core/umath.py
@@ -9,7 +9,7 @@ by importing from the extension module.
from . import _multiarray_umath
from numpy.core._multiarray_umath import *
from numpy.core._multiarray_umath import (
- _UFUNC_API, _add_newdoc_ufunc, _arg, _ones_like
+ _UFUNC_API, _add_newdoc_ufunc, _ones_like
)
__all__ = [
@@ -18,7 +18,7 @@ __all__ = [
'FPE_DIVIDEBYZERO', 'FPE_INVALID', 'FPE_OVERFLOW', 'FPE_UNDERFLOW', 'NAN',
'NINF', 'NZERO', 'PINF', 'PZERO', 'SHIFT_DIVIDEBYZERO', 'SHIFT_INVALID',
'SHIFT_OVERFLOW', 'SHIFT_UNDERFLOW', 'UFUNC_BUFSIZE_DEFAULT',
- 'UFUNC_PYVALS_NAME', '_add_newdoc_ufunc', '_arg', 'absolute', 'add',
+ 'UFUNC_PYVALS_NAME', '_add_newdoc_ufunc', 'absolute', 'add',
'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh',
'bitwise_and', 'bitwise_or', 'bitwise_xor', 'cbrt', 'ceil', 'conj',
'conjugate', 'copysign', 'cos', 'cosh', 'deg2rad', 'degrees', 'divide',
diff --git a/numpy/ctypeslib.py b/numpy/ctypeslib.py
index 8f4715ffd..55b0d721c 100644
--- a/numpy/ctypeslib.py
+++ b/numpy/ctypeslib.py
@@ -51,7 +51,7 @@ Then, we're ready to call ``foo_func``:
"""
from __future__ import division, absolute_import, print_function
-__all__ = ['load_library', 'ndpointer', 'test', 'ctypes_load_library',
+__all__ = ['load_library', 'ndpointer', 'ctypes_load_library',
'c_intp', 'as_ctypes', 'as_array']
import os
@@ -92,11 +92,11 @@ else:
# Adapted from Albert Strasheim
def load_library(libname, loader_path):
"""
- It is possible to load a library using
+ It is possible to load a library using
>>> lib = ctypes.cdll[<full_path_name>] # doctest: +SKIP
But there are cross-platform considerations, such as library file extensions,
- plus the fact Windows will just load the first library it finds with that name.
+ plus the fact Windows will just load the first library it finds with that name.
NumPy supplies the load_library function as a convenience.
Parameters
@@ -110,12 +110,12 @@ else:
Returns
-------
ctypes.cdll[libpath] : library object
- A ctypes library object
+ A ctypes library object
Raises
------
OSError
- If there is no library with the expected extension, or the
+ If there is no library with the expected extension, or the
library is defective and cannot be loaded.
"""
if ctypes.__version__ < '1.0.1':
@@ -321,7 +321,7 @@ def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
# produce a name for the new type
if dtype is None:
name = 'any'
- elif dtype.names is not None:
+ elif dtype.names:
name = str(id(dtype))
else:
name = dtype.str
@@ -535,10 +535,7 @@ if ctypes is not None:
if readonly:
raise TypeError("readonly arrays unsupported")
- # can't use `_dtype((ai["typestr"], ai["shape"]))` here, as it overflows
- # dtype.itemsize (gh-14214)
- ctype_scalar = as_ctypes_type(ai["typestr"])
- result_type = _ctype_ndarray(ctype_scalar, ai["shape"])
- result = result_type.from_address(addr)
+ dtype = _dtype((ai["typestr"], ai["shape"]))
+ result = as_ctypes_type(dtype).from_address(addr)
result.__keep = obj
return result
diff --git a/numpy/distutils/_shell_utils.py b/numpy/distutils/_shell_utils.py
index 5ef874900..82abd5f4e 100644
--- a/numpy/distutils/_shell_utils.py
+++ b/numpy/distutils/_shell_utils.py
@@ -24,12 +24,12 @@ class CommandLineParser:
@staticmethod
def join(argv):
""" Join a list of arguments into a command line string """
- raise NotImplemented
+ raise NotImplementedError
@staticmethod
def split(cmd):
""" Split a command line string into a list of arguments """
- raise NotImplemented
+ raise NotImplementedError
class WindowsParser:
diff --git a/numpy/distutils/command/autodist.py b/numpy/distutils/command/autodist.py
index d5e78963c..9c98b84d8 100644
--- a/numpy/distutils/command/autodist.py
+++ b/numpy/distutils/command/autodist.py
@@ -3,23 +3,24 @@
"""
from __future__ import division, absolute_import, print_function
+import textwrap
# We put them here since they could be easily reused outside numpy.distutils
def check_inline(cmd):
"""Return the inline identifier (may be empty)."""
cmd._check_compiler()
- body = """
-#ifndef __cplusplus
-static %(inline)s int static_func (void)
-{
- return 0;
-}
-%(inline)s int nostatic_func (void)
-{
- return 0;
-}
-#endif"""
+ body = textwrap.dedent("""
+ #ifndef __cplusplus
+ static %(inline)s int static_func (void)
+ {
+ return 0;
+ }
+ %(inline)s int nostatic_func (void)
+ {
+ return 0;
+ }
+ #endif""")
for kw in ['inline', '__inline__', '__inline']:
st = cmd.try_compile(body % {'inline': kw}, None, None)
@@ -28,15 +29,16 @@ static %(inline)s int static_func (void)
return ''
+
def check_restrict(cmd):
"""Return the restrict identifier (may be empty)."""
cmd._check_compiler()
- body = """
-static int static_func (char * %(restrict)s a)
-{
- return 0;
-}
-"""
+ body = textwrap.dedent("""
+ static int static_func (char * %(restrict)s a)
+ {
+ return 0;
+ }
+ """)
for kw in ['restrict', '__restrict__', '__restrict']:
st = cmd.try_compile(body % {'restrict': kw}, None, None)
@@ -45,52 +47,76 @@ static int static_func (char * %(restrict)s a)
return ''
+
def check_compiler_gcc4(cmd):
"""Return True if the C compiler is GCC 4.x."""
cmd._check_compiler()
- body = """
-int
-main()
-{
-#if (! defined __GNUC__) || (__GNUC__ < 4)
-#error gcc >= 4 required
-#endif
- return 0;
-}
-"""
+ body = textwrap.dedent("""
+ int
+ main()
+ {
+ #if (! defined __GNUC__) || (__GNUC__ < 4)
+ #error gcc >= 4 required
+ #endif
+ return 0;
+ }
+ """)
return cmd.try_compile(body, None, None)
def check_gcc_function_attribute(cmd, attribute, name):
"""Return True if the given function attribute is supported."""
cmd._check_compiler()
- body = """
-#pragma GCC diagnostic error "-Wattributes"
-#pragma clang diagnostic error "-Wattributes"
-
-int %s %s(void*);
-
-int
-main()
-{
- return 0;
-}
-""" % (attribute, name)
+ body = textwrap.dedent("""
+ #pragma GCC diagnostic error "-Wattributes"
+ #pragma clang diagnostic error "-Wattributes"
+
+ int %s %s(void*);
+
+ int
+ main()
+ {
+ return 0;
+ }
+ """) % (attribute, name)
return cmd.try_compile(body, None, None) != 0
+
+def check_gcc_function_attribute_with_intrinsics(cmd, attribute, name, code,
+ include):
+ """Return True if the given function attribute is supported with
+ intrinsics."""
+ cmd._check_compiler()
+ body = textwrap.dedent("""
+ #include<%s>
+ int %s %s(void)
+ {
+ %s;
+ return 0;
+ }
+
+ int
+ main()
+ {
+ return 0;
+ }
+ """) % (include, attribute, name, code)
+ return cmd.try_compile(body, None, None) != 0
+
+
def check_gcc_variable_attribute(cmd, attribute):
"""Return True if the given variable attribute is supported."""
cmd._check_compiler()
- body = """
-#pragma GCC diagnostic error "-Wattributes"
-#pragma clang diagnostic error "-Wattributes"
-
-int %s foo;
-
-int
-main()
-{
- return 0;
-}
-""" % (attribute, )
+ body = textwrap.dedent("""
+ #pragma GCC diagnostic error "-Wattributes"
+ #pragma clang diagnostic error "-Wattributes"
+
+ int %s foo;
+
+ int
+ main()
+ {
+ return 0;
+ }
+ """) % (attribute, )
return cmd.try_compile(body, None, None) != 0
diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py
index ab9d585a5..ef54fb25e 100644
--- a/numpy/distutils/command/build_ext.py
+++ b/numpy/distutils/command/build_ext.py
@@ -281,8 +281,8 @@ class build_ext (old_build_ext):
runtime_lib = os.path.join(self.extra_dll_dir, fn)
copy_file(runtime_lib, shared_lib_dir)
- def swig_sources(self, sources):
- # Do nothing. Swig sources have beed handled in build_src command.
+ def swig_sources(self, sources, extensions=None):
+ # Do nothing. Swig sources have been handled in build_src command.
return sources
def build_extension(self, ext):
diff --git a/numpy/distutils/command/build_src.py b/numpy/distutils/command/build_src.py
index 668bc23fe..6d5d305d2 100644
--- a/numpy/distutils/command/build_src.py
+++ b/numpy/distutils/command/build_src.py
@@ -28,20 +28,14 @@ def subst_vars(target, source, d):
"""Substitute any occurrence of @foo@ by d['foo'] from source file into
target."""
var = re.compile('@([a-zA-Z_]+)@')
- fs = open(source, 'r')
- try:
- ft = open(target, 'w')
- try:
+ with open(source, 'r') as fs:
+ with open(target, 'w') as ft:
for l in fs:
m = var.search(l)
if m:
ft.write(l.replace('@%s@' % m.group(1), d[m.group(1)]))
else:
ft.write(l)
- finally:
- ft.close()
- finally:
- fs.close()
class build_src(build_ext.build_ext):
@@ -425,9 +419,8 @@ class build_src(build_ext.build_ext):
else:
log.info("conv_template:> %s" % (target_file))
outstr = process_c_file(source)
- fid = open(target_file, 'w')
- fid.write(outstr)
- fid.close()
+ with open(target_file, 'w') as fid:
+ fid.write(outstr)
if _header_ext_match(target_file):
d = os.path.dirname(target_file)
if d not in include_dirs:
@@ -723,25 +716,23 @@ _has_c_header = re.compile(r'-[*]-\s*c\s*-[*]-', re.I).search
_has_cpp_header = re.compile(r'-[*]-\s*c[+][+]\s*-[*]-', re.I).search
def get_swig_target(source):
- f = open(source, 'r')
- result = None
- line = f.readline()
- if _has_cpp_header(line):
- result = 'c++'
- if _has_c_header(line):
- result = 'c'
- f.close()
+ with open(source, 'r') as f:
+ result = None
+ line = f.readline()
+ if _has_cpp_header(line):
+ result = 'c++'
+ if _has_c_header(line):
+ result = 'c'
return result
def get_swig_modulename(source):
- f = open(source, 'r')
- name = None
- for line in f:
- m = _swig_module_name_match(line)
- if m:
- name = m.group('name')
- break
- f.close()
+ with open(source, 'r') as f:
+ name = None
+ for line in f:
+ m = _swig_module_name_match(line)
+ if m:
+ name = m.group('name')
+ break
return name
def _find_swig_target(target_dir, name):
@@ -760,15 +751,14 @@ _f2py_user_module_name_match = re.compile(r'\s*python\s*module\s*(?P<name>[\w_]*
def get_f2py_modulename(source):
name = None
- f = open(source)
- for line in f:
- m = _f2py_module_name_match(line)
- if m:
- if _f2py_user_module_name_match(line): # skip *__user__* names
- continue
- name = m.group('name')
- break
- f.close()
+ with open(source) as f:
+ for line in f:
+ m = _f2py_module_name_match(line)
+ if m:
+ if _f2py_user_module_name_match(line): # skip *__user__* names
+ continue
+ name = m.group('name')
+ break
return name
##########################################
diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py
index d9b1e8488..e9ca7bea8 100644
--- a/numpy/distutils/command/config.py
+++ b/numpy/distutils/command/config.py
@@ -8,6 +8,7 @@ import os, signal
import warnings
import sys
import subprocess
+import textwrap
from distutils.command.config import config as old_config
from distutils.command.config import LANG_EXT
@@ -18,6 +19,7 @@ import distutils
from numpy.distutils.exec_command import filepath_from_subprocess_output
from numpy.distutils.mingw32ccompiler import generate_manifest
from numpy.distutils.command.autodist import (check_gcc_function_attribute,
+ check_gcc_function_attribute_with_intrinsics,
check_gcc_variable_attribute,
check_inline,
check_restrict,
@@ -52,18 +54,18 @@ class config(old_config):
self.compiler.initialize()
except IOError:
e = get_exception()
- msg = """\
-Could not initialize compiler instance: do you have Visual Studio
-installed? If you are trying to build with MinGW, please use "python setup.py
-build -c mingw32" instead. If you have Visual Studio installed, check it is
-correctly installed, and the right version (VS 2008 for python 2.6, 2.7 and 3.2,
-VS 2010 for >= 3.3).
-
-Original exception was: %s, and the Compiler class was %s
-============================================================================""" \
+ msg = textwrap.dedent("""\
+ Could not initialize compiler instance: do you have Visual Studio
+ installed? If you are trying to build with MinGW, please use "python setup.py
+ build -c mingw32" instead. If you have Visual Studio installed, check it is
+ correctly installed, and the right version (VS 2008 for python 2.6, 2.7 and 3.2,
+ VS 2010 for >= 3.3).
+
+ Original exception was: %s, and the Compiler class was %s
+ ============================================================================""") \
% (e, self.compiler.__class__.__name__)
- print ("""\
-============================================================================""")
+ print(textwrap.dedent("""\
+ ============================================================================"""))
raise distutils.errors.DistutilsPlatformError(msg)
# After MSVC is initialized, add an explicit /MANIFEST to linker
@@ -172,31 +174,31 @@ Original exception was: %s, and the Compiler class was %s
def check_decl(self, symbol,
headers=None, include_dirs=None):
self._check_compiler()
- body = """
-int main(void)
-{
-#ifndef %s
- (void) %s;
-#endif
- ;
- return 0;
-}""" % (symbol, symbol)
+ body = textwrap.dedent("""
+ int main(void)
+ {
+ #ifndef %s
+ (void) %s;
+ #endif
+ ;
+ return 0;
+ }""") % (symbol, symbol)
return self.try_compile(body, headers, include_dirs)
def check_macro_true(self, symbol,
headers=None, include_dirs=None):
self._check_compiler()
- body = """
-int main(void)
-{
-#if %s
-#else
-#error false or undefined macro
-#endif
- ;
- return 0;
-}""" % (symbol,)
+ body = textwrap.dedent("""
+ int main(void)
+ {
+ #if %s
+ #else
+ #error false or undefined macro
+ #endif
+ ;
+ return 0;
+ }""") % (symbol,)
return self.try_compile(body, headers, include_dirs)
@@ -207,14 +209,14 @@ int main(void)
self._check_compiler()
# First check the type can be compiled
- body = r"""
-int main(void) {
- if ((%(name)s *) 0)
- return 0;
- if (sizeof (%(name)s))
- return 0;
-}
-""" % {'name': type_name}
+ body = textwrap.dedent(r"""
+ int main(void) {
+ if ((%(name)s *) 0)
+ return 0;
+ if (sizeof (%(name)s))
+ return 0;
+ }
+ """) % {'name': type_name}
st = False
try:
@@ -234,33 +236,33 @@ int main(void) {
self._check_compiler()
# First check the type can be compiled
- body = r"""
-typedef %(type)s npy_check_sizeof_type;
-int main (void)
-{
- static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) >= 0)];
- test_array [0] = 0
-
- ;
- return 0;
-}
-"""
+ body = textwrap.dedent(r"""
+ typedef %(type)s npy_check_sizeof_type;
+ int main (void)
+ {
+ static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) >= 0)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+ }
+ """)
self._compile(body % {'type': type_name},
headers, include_dirs, 'c')
self._clean()
if expected:
- body = r"""
-typedef %(type)s npy_check_sizeof_type;
-int main (void)
-{
- static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) == %(size)s)];
- test_array [0] = 0
-
- ;
- return 0;
-}
-"""
+ body = textwrap.dedent(r"""
+ typedef %(type)s npy_check_sizeof_type;
+ int main (void)
+ {
+ static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) == %(size)s)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+ }
+ """)
for size in expected:
try:
self._compile(body % {'type': type_name, 'size': size},
@@ -271,17 +273,17 @@ int main (void)
pass
# this fails to *compile* if size > sizeof(type)
- body = r"""
-typedef %(type)s npy_check_sizeof_type;
-int main (void)
-{
- static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) <= %(size)s)];
- test_array [0] = 0
-
- ;
- return 0;
-}
-"""
+ body = textwrap.dedent(r"""
+ typedef %(type)s npy_check_sizeof_type;
+ int main (void)
+ {
+ static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) <= %(size)s)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+ }
+ """)
# The principle is simple: we first find low and high bounds of size
# for the type, where low/high are looked up on a log scale. Then, we
@@ -424,6 +426,11 @@ int main (void)
def check_gcc_function_attribute(self, attribute, name):
return check_gcc_function_attribute(self, attribute, name)
+ def check_gcc_function_attribute_with_intrinsics(self, attribute, name,
+ code, include):
+ return check_gcc_function_attribute_with_intrinsics(self, attribute,
+ name, code, include)
+
def check_gcc_variable_attribute(self, attribute):
return check_gcc_variable_attribute(self, attribute)
diff --git a/numpy/distutils/command/install.py b/numpy/distutils/command/install.py
index a1dd47755..c74ae9446 100644
--- a/numpy/distutils/command/install.py
+++ b/numpy/distutils/command/install.py
@@ -64,16 +64,15 @@ class install(old_install):
# bdist_rpm fails when INSTALLED_FILES contains
# paths with spaces. Such paths must be enclosed
# with double-quotes.
- f = open(self.record, 'r')
- lines = []
- need_rewrite = False
- for l in f:
- l = l.rstrip()
- if ' ' in l:
- need_rewrite = True
- l = '"%s"' % (l)
- lines.append(l)
- f.close()
+ with open(self.record, 'r') as f:
+ lines = []
+ need_rewrite = False
+ for l in f:
+ l = l.rstrip()
+ if ' ' in l:
+ need_rewrite = True
+ l = '"%s"' % (l)
+ lines.append(l)
if need_rewrite:
self.execute(write_file,
(self.record, lines),
diff --git a/numpy/distutils/command/install_clib.py b/numpy/distutils/command/install_clib.py
index 662aa00bd..6a73f7e33 100644
--- a/numpy/distutils/command/install_clib.py
+++ b/numpy/distutils/command/install_clib.py
@@ -19,6 +19,9 @@ class install_clib(Command):
def run (self):
build_clib_cmd = get_cmd("build_clib")
+ if not build_clib_cmd.build_clib:
+ # can happen if the user specified `--skip-build`
+ build_clib_cmd.finalize_options()
build_dir = build_clib_cmd.build_clib
# We need the compiler to get the library name -> filename association
diff --git a/numpy/distutils/conv_template.py b/numpy/distutils/conv_template.py
index b33e315b4..3bcb7b884 100644
--- a/numpy/distutils/conv_template.py
+++ b/numpy/distutils/conv_template.py
@@ -267,22 +267,21 @@ include_src_re = re.compile(r"(\n|\A)#include\s*['\"]"
def resolve_includes(source):
d = os.path.dirname(source)
- fid = open(source)
- lines = []
- for line in fid:
- m = include_src_re.match(line)
- if m:
- fn = m.group('name')
- if not os.path.isabs(fn):
- fn = os.path.join(d, fn)
- if os.path.isfile(fn):
- print('Including file', fn)
- lines.extend(resolve_includes(fn))
+ with open(source) as fid:
+ lines = []
+ for line in fid:
+ m = include_src_re.match(line)
+ if m:
+ fn = m.group('name')
+ if not os.path.isabs(fn):
+ fn = os.path.join(d, fn)
+ if os.path.isfile(fn):
+ print('Including file', fn)
+ lines.extend(resolve_includes(fn))
+ else:
+ lines.append(line)
else:
lines.append(line)
- else:
- lines.append(line)
- fid.close()
return lines
def process_file(source):
@@ -331,6 +330,7 @@ def main():
except ValueError:
e = get_exception()
raise ValueError("In %s loop at %s" % (file, e))
+
outfile.write(writestr)
if __name__ == "__main__":
diff --git a/numpy/distutils/exec_command.py b/numpy/distutils/exec_command.py
index ede347b03..2e7b9e463 100644
--- a/numpy/distutils/exec_command.py
+++ b/numpy/distutils/exec_command.py
@@ -57,6 +57,7 @@ import os
import sys
import subprocess
import locale
+import warnings
from numpy.distutils.misc_util import is_sequence, make_temp_file
from numpy.distutils import log
@@ -105,6 +106,9 @@ def forward_bytes_to_stdout(val):
def temp_file_name():
+ # 2019-01-30, 1.17
+ warnings.warn('temp_file_name is deprecated since NumPy v1.17, use '
+ 'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1)
fo, name = make_temp_file()
fo.close()
return name
@@ -179,24 +183,14 @@ def _update_environment( **env ):
for name, value in env.items():
os.environ[name] = value or ''
-def _supports_fileno(stream):
- """
- Returns True if 'stream' supports the file descriptor and allows fileno().
- """
- if hasattr(stream, 'fileno'):
- try:
- stream.fileno()
- return True
- except IOError:
- return False
- else:
- return False
-
def exec_command(command, execute_in='', use_shell=None, use_tee=None,
_with_python = 1, **env ):
"""
Return (status,output) of executed command.
+ .. deprecated:: 1.17
+ Use subprocess.Popen instead
+
Parameters
----------
command : str
@@ -220,6 +214,9 @@ def exec_command(command, execute_in='', use_shell=None, use_tee=None,
Wild cards will not work for non-posix systems or when use_shell=0.
"""
+ # 2019-01-30, 1.17
+ warnings.warn('exec_command is deprecated since NumPy v1.17, use '
+ 'subprocess.Popen instead', DeprecationWarning, stacklevel=1)
log.debug('exec_command(%r,%s)' % (command,\
','.join(['%s=%r'%kv for kv in env.items()])))
diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py
index bd3739a81..3723470f3 100644
--- a/numpy/distutils/fcompiler/__init__.py
+++ b/numpy/distutils/fcompiler/__init__.py
@@ -362,7 +362,7 @@ class FCompiler(CCompiler):
set_exe('archiver')
set_exe('ranlib')
- def update_executables(elf):
+ def update_executables(self):
"""Called at the beginning of customisation. Subclasses should
override this if they need to set up the executables dictionary.
@@ -484,11 +484,11 @@ class FCompiler(CCompiler):
# XXX Assuming that free format is default for f90 compiler.
fix = self.command_vars.compiler_fix
# NOTE: this and similar examples are probably just
- # exluding --coverage flag when F90 = gfortran --coverage
+ # excluding --coverage flag when F90 = gfortran --coverage
# instead of putting that flag somewhere more appropriate
# this and similar examples where a Fortran compiler
# environment variable has been customized by CI or a user
- # should perhaps eventually be more throughly tested and more
+ # should perhaps eventually be more thoroughly tested and more
# robustly handled
if fix:
fix = _shell_utils.NativeParser.split(fix)
diff --git a/numpy/distutils/fcompiler/ibm.py b/numpy/distutils/fcompiler/ibm.py
index c4cb2fca7..70d2132e1 100644
--- a/numpy/distutils/fcompiler/ibm.py
+++ b/numpy/distutils/fcompiler/ibm.py
@@ -78,15 +78,14 @@ class IBMFCompiler(FCompiler):
xlf_cfg = '/etc/opt/ibmcmp/xlf/%s/xlf.cfg' % version
fo, new_cfg = make_temp_file(suffix='_xlf.cfg')
log.info('Creating '+new_cfg)
- fi = open(xlf_cfg, 'r')
- crt1_match = re.compile(r'\s*crt\s*[=]\s*(?P<path>.*)/crt1.o').match
- for line in fi:
- m = crt1_match(line)
- if m:
- fo.write('crt = %s/bundle1.o\n' % (m.group('path')))
- else:
- fo.write(line)
- fi.close()
+ with open(xlf_cfg, 'r') as fi:
+ crt1_match = re.compile(r'\s*crt\s*[=]\s*(?P<path>.*)/crt1.o').match
+ for line in fi:
+ m = crt1_match(line)
+ if m:
+ fo.write('crt = %s/bundle1.o\n' % (m.group('path')))
+ else:
+ fo.write(line)
fo.close()
opt.append('-F'+new_cfg)
return opt
diff --git a/numpy/distutils/from_template.py b/numpy/distutils/from_template.py
index 65c60c498..c5c1163c6 100644
--- a/numpy/distutils/from_template.py
+++ b/numpy/distutils/from_template.py
@@ -212,22 +212,21 @@ include_src_re = re.compile(r"(\n|\A)\s*include\s*['\"](?P<name>[\w\d./\\]+[.]sr
def resolve_includes(source):
d = os.path.dirname(source)
- fid = open(source)
- lines = []
- for line in fid:
- m = include_src_re.match(line)
- if m:
- fn = m.group('name')
- if not os.path.isabs(fn):
- fn = os.path.join(d, fn)
- if os.path.isfile(fn):
- print('Including file', fn)
- lines.extend(resolve_includes(fn))
+ with open(source) as fid:
+ lines = []
+ for line in fid:
+ m = include_src_re.match(line)
+ if m:
+ fn = m.group('name')
+ if not os.path.isabs(fn):
+ fn = os.path.join(d, fn)
+ if os.path.isfile(fn):
+ print('Including file', fn)
+ lines.extend(resolve_includes(fn))
+ else:
+ lines.append(line)
else:
lines.append(line)
- else:
- lines.append(line)
- fid.close()
return lines
def process_file(source):
@@ -260,5 +259,6 @@ def main():
writestr = process_str(allstr)
outfile.write(writestr)
+
if __name__ == "__main__":
main()
diff --git a/numpy/distutils/line_endings.py b/numpy/distutils/line_endings.py
index 5ecb104ff..fe8fd1b0f 100644
--- a/numpy/distutils/line_endings.py
+++ b/numpy/distutils/line_endings.py
@@ -11,7 +11,8 @@ def dos2unix(file):
print(file, "Directory!")
return
- data = open(file, "rb").read()
+ with open(file, "rb") as fp:
+ data = fp.read()
if '\0' in data:
print(file, "Binary!")
return
@@ -19,9 +20,8 @@ def dos2unix(file):
newdata = re.sub("\r\n", "\n", data)
if newdata != data:
print('dos2unix:', file)
- f = open(file, "wb")
- f.write(newdata)
- f.close()
+ with open(file, "wb") as f:
+ f.write(newdata)
return file
else:
print(file, 'ok')
@@ -45,7 +45,8 @@ def unix2dos(file):
print(file, "Directory!")
return
- data = open(file, "rb").read()
+ with open(file, "rb") as fp:
+ data = fp.read()
if '\0' in data:
print(file, "Binary!")
return
@@ -53,9 +54,8 @@ def unix2dos(file):
newdata = re.sub("\n", "\r\n", newdata)
if newdata != data:
print('unix2dos:', file)
- f = open(file, "wb")
- f.write(newdata)
- f.close()
+ with open(file, "wb") as f:
+ f.write(newdata)
return file
else:
print(file, 'ok')
diff --git a/numpy/distutils/mingw32ccompiler.py b/numpy/distutils/mingw32ccompiler.py
index e6bbe1996..075858cfe 100644
--- a/numpy/distutils/mingw32ccompiler.py
+++ b/numpy/distutils/mingw32ccompiler.py
@@ -13,6 +13,7 @@ import os
import sys
import subprocess
import re
+import textwrap
# Overwrite certain distutils.ccompiler functions:
import numpy.distutils.ccompiler
@@ -29,7 +30,6 @@ else:
import distutils.cygwinccompiler
from distutils.version import StrictVersion
-from numpy.distutils.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler
from distutils.msvccompiler import get_build_version as get_build_msvc_version
from distutils.errors import (DistutilsExecError, CompileError,
@@ -572,21 +572,21 @@ def msvc_manifest_xml(maj, min):
# embedded in the binary...
# This template was copied directly from the python 2.6 binary (using
# strings.exe from mingw on python.exe).
- template = """\
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
- <security>
- <requestedPrivileges>
- <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
- </requestedPrivileges>
- </security>
- </trustInfo>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC%(maj)d%(min)d.CRT" version="%(fullver)s" processorArchitecture="*" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
- </dependentAssembly>
- </dependency>
-</assembly>"""
+ template = textwrap.dedent("""\
+ <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.VC%(maj)d%(min)d.CRT" version="%(fullver)s" processorArchitecture="*" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ </assembly>""")
return template % {'fullver': fullver, 'maj': maj, 'min': min}
diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py
index 42374ac4f..89171eede 100644
--- a/numpy/distutils/misc_util.py
+++ b/numpy/distutils/misc_util.py
@@ -10,6 +10,7 @@ import tempfile
import subprocess
import shutil
import multiprocessing
+import textwrap
import distutils
from distutils.errors import DistutilsError
@@ -218,15 +219,14 @@ def get_mathlibs(path=None):
raise DistutilsError('_numpyconfig.h not found in numpy include '
'dirs %r' % (dirs,))
- fid = open(config_file)
- mathlibs = []
- s = '#define MATHLIB'
- for line in fid:
- if line.startswith(s):
- value = line[len(s):].strip()
- if value:
- mathlibs.extend(value.split(','))
- fid.close()
+ with open(config_file) as fid:
+ mathlibs = []
+ s = '#define MATHLIB'
+ for line in fid:
+ if line.startswith(s):
+ value = line[len(s):].strip()
+ if value:
+ mathlibs.extend(value.split(','))
return mathlibs
def minrelpath(path):
@@ -443,14 +443,13 @@ def _get_f90_modules(source):
if not f90_ext_match(source):
return []
modules = []
- f = open(source, 'r')
- for line in f:
- m = f90_module_name_match(line)
- if m:
- name = m.group('name')
- modules.append(name)
- # break # XXX can we assume that there is one module per file?
- f.close()
+ with open(source, 'r') as f:
+ for line in f:
+ m = f90_module_name_match(line)
+ if m:
+ name = m.group('name')
+ modules.append(name)
+ # break # XXX can we assume that there is one module per file?
return modules
def is_string(s):
@@ -473,7 +472,7 @@ def is_sequence(seq):
return True
def is_glob_pattern(s):
- return is_string(s) and ('*' in s or '?' is s)
+ return is_string(s) and ('*' in s or '?' in s)
def as_list(seq):
if is_sequence(seq):
@@ -1839,7 +1838,7 @@ class Configuration(object):
except (subprocess.CalledProcessError, OSError):
pass
else:
- m = re.match(br'(?P<revision>\d+)', output)
+ m = re.match(rb'(?P<revision>\d+)', output)
if m:
return int(m.group('revision'))
@@ -1848,9 +1847,8 @@ class Configuration(object):
else:
entries = njoin(path, '.svn', 'entries')
if os.path.isfile(entries):
- f = open(entries)
- fstr = f.read()
- f.close()
+ with open(entries) as f:
+ fstr = f.read()
if fstr[:5] == '<?xml': # pre 1.4
m = re.search(r'revision="(?P<revision>\d+)"', fstr)
if m:
@@ -1870,7 +1868,7 @@ class Configuration(object):
except (subprocess.CalledProcessError, OSError):
pass
else:
- m = re.match(br'(?P<revision>\d+)', output)
+ m = re.match(rb'(?P<revision>\d+)', output)
if m:
return int(m.group('revision'))
@@ -1879,9 +1877,8 @@ class Configuration(object):
if os.path.isfile(branch_fn):
branch0 = None
- f = open(branch_fn)
- revision0 = f.read().strip()
- f.close()
+ with open(branch_fn) as f:
+ revision0 = f.read().strip()
branch_map = {}
for line in file(branch_cache_fn, 'r'):
@@ -1994,9 +1991,8 @@ class Configuration(object):
if not os.path.isfile(target):
version = str(revision)
self.info('Creating %s (version=%r)' % (target, version))
- f = open(target, 'w')
- f.write('version = %r\n' % (version))
- f.close()
+ with open(target, 'w') as f:
+ f.write('version = %r\n' % (version))
def rm_file(f=target,p=self.info):
if delete:
@@ -2035,9 +2031,8 @@ class Configuration(object):
if not os.path.isfile(target):
version = str(revision)
self.info('Creating %s (version=%r)' % (target, version))
- f = open(target, 'w')
- f.write('version = %r\n' % (version))
- f.close()
+ with open(target, 'w') as f:
+ f.write('version = %r\n' % (version))
def rm_file(f=target,p=self.info):
if delete:
@@ -2273,46 +2268,44 @@ def generate_config_py(target):
from numpy.distutils.system_info import system_info
from distutils.dir_util import mkpath
mkpath(os.path.dirname(target))
- f = open(target, 'w')
- f.write('# This file is generated by numpy\'s %s\n' % (os.path.basename(sys.argv[0])))
- f.write('# It contains system_info results at the time of building this package.\n')
- f.write('__all__ = ["get_info","show"]\n\n')
-
- # For gfortran+msvc combination, extra shared libraries may exist
- f.write("""
-
-import os
-import sys
+ with open(target, 'w') as f:
+ f.write('# This file is generated by numpy\'s %s\n' % (os.path.basename(sys.argv[0])))
+ f.write('# It contains system_info results at the time of building this package.\n')
+ f.write('__all__ = ["get_info","show"]\n\n')
+
+ # For gfortran+msvc combination, extra shared libraries may exist
+ f.write(textwrap.dedent("""
+ import os
+ import sys
+
+ extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs')
+
+ if sys.platform == 'win32' and os.path.isdir(extra_dll_dir):
+ os.environ.setdefault('PATH', '')
+ os.environ['PATH'] += os.pathsep + extra_dll_dir
+
+ """))
+
+ for k, i in system_info.saved_results.items():
+ f.write('%s=%r\n' % (k, i))
+ f.write(textwrap.dedent(r'''
+ def get_info(name):
+ g = globals()
+ return g.get(name, g.get(name + "_info", {}))
+
+ def show():
+ for name,info_dict in globals().items():
+ if name[0] == "_" or type(info_dict) is not type({}): continue
+ print(name + ":")
+ if not info_dict:
+ print(" NOT AVAILABLE")
+ for k,v in info_dict.items():
+ v = str(v)
+ if k == "sources" and len(v) > 200:
+ v = v[:60] + " ...\n... " + v[-60:]
+ print(" %s = %s" % (k,v))
+ '''))
-extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs')
-
-if sys.platform == 'win32' and os.path.isdir(extra_dll_dir):
- os.environ.setdefault('PATH', '')
- os.environ['PATH'] += os.pathsep + extra_dll_dir
-
-""")
-
- for k, i in system_info.saved_results.items():
- f.write('%s=%r\n' % (k, i))
- f.write(r'''
-def get_info(name):
- g = globals()
- return g.get(name, g.get(name + "_info", {}))
-
-def show():
- for name,info_dict in globals().items():
- if name[0] == "_" or type(info_dict) is not type({}): continue
- print(name + ":")
- if not info_dict:
- print(" NOT AVAILABLE")
- for k,v in info_dict.items():
- v = str(v)
- if k == "sources" and len(v) > 200:
- v = v[:60] + " ...\n... " + v[-60:]
- print(" %s = %s" % (k,v))
- ''')
-
- f.close()
return target
def msvc_version(compiler):
diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py
index 806f4f7d3..ba2b1f46c 100644
--- a/numpy/distutils/system_info.py
+++ b/numpy/distutils/system_info.py
@@ -17,6 +17,7 @@ classes are available:
atlas_3_10_blas_threads_info,
lapack_atlas_3_10_info
lapack_atlas_3_10_threads_info
+ flame_info
blas_info
lapack_info
openblas_info
@@ -92,20 +93,20 @@ src_dirs = /usr/local/src:/opt/src
search_static_first = 0
[fftw]
-fftw_libs = rfftw, fftw
-fftw_opt_libs = rfftw_threaded, fftw_threaded
-# if the above aren't found, look for {s,d}fftw_libs and {s,d}fftw_opt_libs
+libraries = rfftw, fftw
[atlas]
library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas
# for overriding the names of the atlas libraries
-atlas_libs = lapack, f77blas, cblas, atlas
+libraries = lapack, f77blas, cblas, atlas
[x11]
library_dirs = /usr/X11R6/lib
include_dirs = /usr/X11R6/include
----------
+Note that the ``libraries`` key is the default setting for libraries.
+
Authors:
Pearu Peterson <pearu@cens.ioc.ee>, February 2002
David M. Cooke <cookedm@physics.mcmaster.ca>, April 2002
@@ -127,6 +128,7 @@ import re
import copy
import warnings
import subprocess
+import textwrap
from glob import glob
from functools import reduce
@@ -300,26 +302,21 @@ else:
default_x11_include_dirs.extend(['/usr/lib/X11/include',
'/usr/include/X11'])
- tmp = None
- try:
- # Explicitly open/close file to avoid ResourceWarning when
- # tests are run in debug mode Python 3.
- tmp = open(os.devnull, 'w')
- p = subprocess.Popen(["gcc", "-print-multiarch"], stdout=subprocess.PIPE,
- stderr=tmp)
- except (OSError, DistutilsError):
- # OSError if gcc is not installed, or SandboxViolation (DistutilsError
- # subclass) if an old setuptools bug is triggered (see gh-3160).
- pass
- else:
- triplet = str(p.communicate()[0].decode().strip())
- if p.returncode == 0:
- # gcc supports the "-print-multiarch" option
- default_x11_lib_dirs += [os.path.join("/usr/lib/", triplet)]
- default_lib_dirs += [os.path.join("/usr/lib/", triplet)]
- finally:
- if tmp is not None:
- tmp.close()
+ with open(os.devnull, 'w') as tmp:
+ try:
+ p = subprocess.Popen(["gcc", "-print-multiarch"], stdout=subprocess.PIPE,
+ stderr=tmp)
+ except (OSError, DistutilsError):
+ # OSError if gcc is not installed, or SandboxViolation (DistutilsError
+ # subclass) if an old setuptools bug is triggered (see gh-3160).
+ pass
+ else:
+ triplet = str(p.communicate()[0].decode().strip())
+ if p.returncode == 0:
+ # gcc supports the "-print-multiarch" option
+ default_x11_lib_dirs += [os.path.join("/usr/lib/", triplet)]
+ default_lib_dirs += [os.path.join("/usr/lib/", triplet)]
+
if os.path.join(sys.prefix, 'lib') not in default_lib_dirs:
default_lib_dirs.insert(0, os.path.join(sys.prefix, 'lib'))
@@ -389,6 +386,7 @@ def get_info(name, notfound_action=0):
'atlas_3_10_blas_threads': atlas_3_10_blas_threads_info,
'lapack_atlas_3_10': lapack_atlas_3_10_info, # use lapack_opt instead
'lapack_atlas_3_10_threads': lapack_atlas_3_10_threads_info, # ditto
+ 'flame': flame_info, # use lapack_opt instead
'mkl': mkl_info,
# openblas which may or may not have embedded lapack
'openblas': openblas_info, # use blas_opt instead
@@ -450,6 +448,12 @@ class NotFoundError(DistutilsError):
"""Some third-party program or library is not found."""
+class AliasedOptionError(DistutilsError):
+ """
+ Aliases entries in config files should not be existing.
+ In section '{section}' we found multiple appearances of options {options}."""
+
+
class AtlasNotFoundError(NotFoundError):
"""
Atlas (http://math-atlas.sourceforge.net/) libraries not found.
@@ -458,6 +462,13 @@ class AtlasNotFoundError(NotFoundError):
the ATLAS environment variable."""
+class FlameNotFoundError(NotFoundError):
+ """
+ FLAME (http://www.cs.utexas.edu/~flame/web/) libraries not found.
+ Directories to search for the libraries can be specified in the
+ numpy/distutils/site.cfg file (section [flame])."""
+
+
class LapackNotFoundError(NotFoundError):
"""
Lapack (http://www.netlib.org/lapack/) libraries not found.
@@ -474,6 +485,13 @@ class LapackSrcNotFoundError(LapackNotFoundError):
the LAPACK_SRC environment variable."""
+class BlasOptNotFoundError(NotFoundError):
+ """
+ Optimized (vendor) Blas libraries are not found.
+ Falls back to netlib Blas library which has worse performance.
+ A better performance should be easily gained by switching
+ Blas library."""
+
class BlasNotFoundError(NotFoundError):
"""
Blas (http://www.netlib.org/blas/) libraries not found.
@@ -608,6 +626,39 @@ class system_info(object):
dict_append(info, **extra_info)
self.saved_results[self.__class__.__name__] = info
+ def get_option_single(self, *options):
+ """ Ensure that only one of `options` are found in the section
+
+ Parameters
+ ----------
+ *options : list of str
+ a list of options to be found in the section (``self.section``)
+
+ Returns
+ -------
+ str :
+ the option that is uniquely found in the section
+
+ Raises
+ ------
+ AliasedOptionError :
+ in case more than one of the options are found
+ """
+ found = map(lambda opt: self.cp.has_option(self.section, opt), options)
+ found = list(found)
+ if sum(found) == 1:
+ return options[found.index(True)]
+ elif sum(found) == 0:
+ # nothing is found anyways
+ return options[0]
+
+ # Else we have more than 1 key found
+ if AliasedOptionError.__doc__ is None:
+ raise AliasedOptionError()
+ raise AliasedOptionError(AliasedOptionError.__doc__.format(
+ section=self.section, options='[{}]'.format(', '.join(options))))
+
+
def has_info(self):
return self.__class__.__name__ in self.saved_results
@@ -898,7 +949,9 @@ class fftw_info(system_info):
"""Returns True on successful version detection, else False"""
lib_dirs = self.get_lib_dirs()
incl_dirs = self.get_include_dirs()
- libs = self.get_libs(self.section + '_libs', ver_param['libs'])
+
+ opt = self.get_option_single(self.section + '_libs', 'libraries')
+ libs = self.get_libs(opt, ver_param['libs'])
info = self.check_libs(lib_dirs, libs)
if info is not None:
flag = 0
@@ -907,7 +960,6 @@ class fftw_info(system_info):
== len(ver_param['includes']):
dict_append(info, include_dirs=[d])
flag = 1
- incl_dirs = [d]
break
if flag:
dict_append(info, define_macros=ver_param['macros'])
@@ -1059,9 +1111,9 @@ class mkl_info(system_info):
for d in paths:
dirs = glob(os.path.join(d, 'mkl', '*'))
dirs += glob(os.path.join(d, 'mkl*'))
- for d in dirs:
- if os.path.isdir(os.path.join(d, 'lib')):
- return d
+ for sub_dir in dirs:
+ if os.path.isdir(os.path.join(sub_dir, 'lib')):
+ return sub_dir
return None
def __init__(self):
@@ -1084,7 +1136,8 @@ class mkl_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
incl_dirs = self.get_include_dirs()
- mkl_libs = self.get_libs('mkl_libs', self._lib_mkl)
+ opt = self.get_option_single('mkl_libs', 'libraries')
+ mkl_libs = self.get_libs(opt, self._lib_mkl)
info = self.check_libs2(lib_dirs, mkl_libs)
if info is None:
return
@@ -1131,8 +1184,8 @@ class atlas_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names + self._lib_atlas)
+ opt = self.get_option_single('atlas_libs', 'libraries')
+ atlas_libs = self.get_libs(opt, self._lib_names + self._lib_atlas)
lapack_libs = self.get_libs('lapack_libs', self._lib_lapack)
atlas = None
lapack = None
@@ -1172,11 +1225,11 @@ class atlas_info(system_info):
else:
dict_append(info, **atlas)
dict_append(info, define_macros=[('ATLAS_WITHOUT_LAPACK', None)])
- message = """
-*********************************************************************
- Could not find lapack library within the ATLAS installation.
-*********************************************************************
-"""
+ message = textwrap.dedent("""
+ *********************************************************************
+ Could not find lapack library within the ATLAS installation.
+ *********************************************************************
+ """)
warnings.warn(message, stacklevel=2)
self.set_info(**info)
return
@@ -1199,15 +1252,15 @@ class atlas_info(system_info):
if lapack_lib is not None:
sz = os.stat(lapack_lib)[6]
if sz <= 4000 * 1024:
- message = """
-*********************************************************************
- Lapack library (from ATLAS) is probably incomplete:
- size of %s is %sk (expected >4000k)
-
- Follow the instructions in the KNOWN PROBLEMS section of the file
- numpy/INSTALL.txt.
-*********************************************************************
-""" % (lapack_lib, sz / 1024)
+ message = textwrap.dedent("""
+ *********************************************************************
+ Lapack library (from ATLAS) is probably incomplete:
+ size of %s is %sk (expected >4000k)
+
+ Follow the instructions in the KNOWN PROBLEMS section of the file
+ numpy/INSTALL.txt.
+ *********************************************************************
+ """) % (lapack_lib, sz / 1024)
warnings.warn(message, stacklevel=2)
else:
info['language'] = 'f77'
@@ -1224,8 +1277,8 @@ class atlas_blas_info(atlas_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names + self._lib_atlas)
+ opt = self.get_option_single('atlas_libs', 'libraries')
+ atlas_libs = self.get_libs(opt, self._lib_names + self._lib_atlas)
atlas = self.check_libs2(lib_dirs, atlas_libs, [])
if atlas is None:
return
@@ -1277,8 +1330,8 @@ class atlas_3_10_blas_info(atlas_3_10_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
info = {}
- atlas_libs = self.get_libs('atlas_libs',
- self._lib_names)
+ opt = self.get_option_single('atlas_lib', 'libraries')
+ atlas_libs = self.get_libs(opt, self._lib_names)
atlas = self.check_libs2(lib_dirs, atlas_libs, [])
if atlas is None:
return
@@ -1329,7 +1382,8 @@ class lapack_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
- lapack_libs = self.get_libs('lapack_libs', self._lib_names)
+ opt = self.get_option_single('lapack_libs', 'libraries')
+ lapack_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, lapack_libs, [])
if info is None:
return
@@ -1484,16 +1538,16 @@ def get_atlas_version(**config):
library_dirs=library_dirs,
use_tee=(system_info.verbosity > 0))
if not s:
- warnings.warn("""
-*****************************************************
-Linkage with ATLAS requires gfortran. Use
+ warnings.warn(textwrap.dedent("""
+ *****************************************************
+ Linkage with ATLAS requires gfortran. Use
- python setup.py config_fc --fcompiler=gnu95 ...
+ python setup.py config_fc --fcompiler=gnu95 ...
-when building extension libraries that use ATLAS.
-Make sure that -lgfortran is used for C++ extensions.
-*****************************************************
-""", stacklevel=2)
+ when building extension libraries that use ATLAS.
+ Make sure that -lgfortran is used for C++ extensions.
+ *****************************************************
+ """), stacklevel=2)
dict_append(info, language='f90',
define_macros=[('ATLAS_REQUIRES_GFORTRAN', None)])
except Exception: # failed to get version from file -- maybe on Windows
@@ -1541,139 +1595,226 @@ Make sure that -lgfortran is used for C++ extensions.
class lapack_opt_info(system_info):
notfounderror = LapackNotFoundError
+ # Default order of LAPACK checks
+ lapack_order = ['mkl', 'openblas', 'flame', 'atlas', 'accelerate', 'lapack']
- def calc_info(self):
+ def _calc_info_mkl(self):
+ info = get_info('lapack_mkl')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- lapack_mkl_info = get_info('lapack_mkl')
- if lapack_mkl_info:
- self.set_info(**lapack_mkl_info)
- return
+ def _calc_info_openblas(self):
+ info = get_info('openblas_lapack')
+ if info:
+ self.set_info(**info)
+ return True
+ info = get_info('openblas_clapack')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- openblas_info = get_info('openblas_lapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ def _calc_info_flame(self):
+ info = get_info('flame')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- openblas_info = get_info('openblas_clapack')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ def _calc_info_atlas(self):
+ info = get_info('atlas_3_10_threads')
+ if not info:
+ info = get_info('atlas_3_10')
+ if not info:
+ info = get_info('atlas_threads')
+ if not info:
+ info = get_info('atlas')
+ if info:
+ # Figure out if ATLAS has lapack...
+ # If not we need the lapack library, but not BLAS!
+ l = info.get('define_macros', [])
+ if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \
+ or ('ATLAS_WITHOUT_LAPACK', None) in l:
+ # Get LAPACK (with possible warnings)
+ # If not found we don't accept anything
+ # since we can't use ATLAS with LAPACK!
+ lapack_info = self._get_info_lapack()
+ if not lapack_info:
+ return False
+ dict_append(info, **lapack_info)
+ self.set_info(**info)
+ return True
+ return False
- atlas_info = get_info('atlas_3_10_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10')
- if not atlas_info:
- atlas_info = get_info('atlas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas')
-
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
+ def _calc_info_accelerate(self):
+ info = get_info('accelerate')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- need_lapack = 0
- need_blas = 0
- info = {}
- if atlas_info:
- l = atlas_info.get('define_macros', [])
- if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \
- or ('ATLAS_WITHOUT_LAPACK', None) in l:
- need_lapack = 1
- info = atlas_info
+ def _get_info_blas(self):
+ # Default to get the optimized BLAS implementation
+ info = get_info('blas_opt')
+ if not info:
+ warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3)
+ info_src = get_info('blas_src')
+ if not info_src:
+ warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3)
+ return {}
+ dict_append(info, libraries=[('fblas_src', info_src)])
+ return info
- else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- need_lapack = 1
+ def _get_info_lapack(self):
+ info = get_info('lapack')
+ if not info:
+ warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=3)
+ info_src = get_info('lapack_src')
+ if not info_src:
+ warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=3)
+ return {}
+ dict_append(info, libraries=[('flapack_src', info_src)])
+ return info
+
+ def _calc_info_lapack(self):
+ info = self._get_info_lapack()
+ if info:
+ info_blas = self._get_info_blas()
+ dict_append(info, **info_blas)
dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
+ self.set_info(**info)
+ return True
+ return False
- if need_lapack:
- lapack_info = get_info('lapack')
- #lapack_info = {} ## uncomment for testing
- if lapack_info:
- dict_append(info, **lapack_info)
- else:
- warnings.warn(LapackNotFoundError.__doc__, stacklevel=2)
- lapack_src_info = get_info('lapack_src')
- if not lapack_src_info:
- warnings.warn(LapackSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('flapack_src', lapack_src_info)])
-
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
+ def calc_info(self):
+ user_order = os.environ.get('NPY_LAPACK_ORDER', None)
+ if user_order is None:
+ lapack_order = self.lapack_order
+ else:
+ # the user has requested the order of the
+ # check they are all in the available list, a COMMA SEPARATED list
+ user_order = user_order.lower().split(',')
+ non_existing = []
+ lapack_order = []
+ for order in user_order:
+ if order in self.lapack_order:
+ lapack_order.append(order)
+ elif len(order) > 0:
+ non_existing.append(order)
+ if len(non_existing) > 0:
+ raise ValueError("lapack_opt_info user defined "
+ "LAPACK order has unacceptable "
+ "values: {}".format(non_existing))
+
+ for lapack in lapack_order:
+ if getattr(self, '_calc_info_{}'.format(lapack))():
+ return
- self.set_info(**info)
- return
+ if 'lapack' not in lapack_order:
+ # Since the user may request *not* to use any library, we still need
+ # to raise warnings to signal missing packages!
+ warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=2)
+ warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=2)
class blas_opt_info(system_info):
notfounderror = BlasNotFoundError
+ # Default order of BLAS checks
+ blas_order = ['mkl', 'blis', 'openblas', 'atlas', 'accelerate', 'blas']
- def calc_info(self):
+ def _calc_info_mkl(self):
+ info = get_info('blas_mkl')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- blas_mkl_info = get_info('blas_mkl')
- if blas_mkl_info:
- self.set_info(**blas_mkl_info)
- return
+ def _calc_info_blis(self):
+ info = get_info('blis')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- blis_info = get_info('blis')
- if blis_info:
- self.set_info(**blis_info)
- return
+ def _calc_info_openblas(self):
+ info = get_info('openblas')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- openblas_info = get_info('openblas')
- if openblas_info:
- self.set_info(**openblas_info)
- return
+ def _calc_info_atlas(self):
+ info = get_info('atlas_3_10_blas_threads')
+ if not info:
+ info = get_info('atlas_3_10_blas')
+ if not info:
+ info = get_info('atlas_blas_threads')
+ if not info:
+ info = get_info('atlas_blas')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- atlas_info = get_info('atlas_3_10_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_3_10_blas')
- if not atlas_info:
- atlas_info = get_info('atlas_blas_threads')
- if not atlas_info:
- atlas_info = get_info('atlas_blas')
-
- accelerate_info = get_info('accelerate')
- if accelerate_info and not atlas_info:
- self.set_info(**accelerate_info)
- return
+ def _calc_info_accelerate(self):
+ info = get_info('accelerate')
+ if info:
+ self.set_info(**info)
+ return True
+ return False
- need_blas = 0
+ def _calc_info_blas(self):
+ # Warn about a non-optimized BLAS library
+ warnings.warn(BlasOptNotFoundError.__doc__ or '', stacklevel=3)
info = {}
- if atlas_info:
- info = atlas_info
+ dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
+
+ blas = get_info('blas')
+ if blas:
+ dict_append(info, **blas)
else:
- warnings.warn(AtlasNotFoundError.__doc__, stacklevel=2)
- need_blas = 1
- dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)])
+ # Not even BLAS was found!
+ warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3)
- if need_blas:
- blas_info = get_info('blas')
- if blas_info:
- dict_append(info, **blas_info)
- else:
- warnings.warn(BlasNotFoundError.__doc__, stacklevel=2)
- blas_src_info = get_info('blas_src')
- if not blas_src_info:
- warnings.warn(BlasSrcNotFoundError.__doc__, stacklevel=2)
- return
- dict_append(info, libraries=[('fblas_src', blas_src_info)])
+ blas_src = get_info('blas_src')
+ if not blas_src:
+ warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3)
+ return False
+ dict_append(info, libraries=[('fblas_src', blas_src)])
self.set_info(**info)
- return
+ return True
+
+ def calc_info(self):
+ user_order = os.environ.get('NPY_BLAS_ORDER', None)
+ if user_order is None:
+ blas_order = self.blas_order
+ else:
+ # the user has requested the order of the
+ # check they are all in the available list
+ user_order = user_order.lower().split(',')
+ non_existing = []
+ blas_order = []
+ for order in user_order:
+ if order in self.blas_order:
+ blas_order.append(order)
+ elif len(order) > 0:
+ non_existing.append(order)
+ if len(non_existing) > 0:
+ raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(non_existing))
+
+ for blas in blas_order:
+ if getattr(self, '_calc_info_{}'.format(blas))():
+ return
+
+ if 'blas' not in blas_order:
+ # Since the user may request *not* to use any library, we still need
+ # to raise warnings to signal missing packages!
+ warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=2)
+ warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=2)
class blas_info(system_info):
@@ -1684,39 +1825,64 @@ class blas_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
- blas_libs = self.get_libs('blas_libs', self._lib_names)
+ opt = self.get_option_single('blas_libs', 'libraries')
+ blas_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, blas_libs, [])
if info is None:
return
else:
info['include_dirs'] = self.get_include_dirs()
if platform.system() == 'Windows':
- # The check for windows is needed because has_cblas uses the
+ # The check for windows is needed because get_cblas_libs uses the
# same compiler that was used to compile Python and msvc is
# often not installed when mingw is being used. This rough
# treatment is not desirable, but windows is tricky.
info['language'] = 'f77' # XXX: is it generally true?
else:
- lib = self.has_cblas(info)
+ lib = self.get_cblas_libs(info)
if lib is not None:
info['language'] = 'c'
- info['libraries'] = [lib]
+ info['libraries'] = lib
info['define_macros'] = [('HAVE_CBLAS', None)]
self.set_info(**info)
- def has_cblas(self, info):
+ def get_cblas_libs(self, info):
+ """ Check whether we can link with CBLAS interface
+
+ This method will search through several combinations of libraries
+ to check whether CBLAS is present:
+
+ 1. Libraries in ``info['libraries']``, as is
+ 2. As 1. but also explicitly adding ``'cblas'`` as a library
+ 3. As 1. but also explicitly adding ``'blas'`` as a library
+ 4. Check only library ``'cblas'``
+ 5. Check only library ``'blas'``
+
+ Parameters
+ ----------
+ info : dict
+ system information dictionary for compilation and linking
+
+ Returns
+ -------
+ libraries : list of str or None
+ a list of libraries that enables the use of CBLAS interface.
+ Returns None if not found or a compilation error occurs.
+
+ Since 1.17 returns a list.
+ """
# primitive cblas check by looking for the header and trying to link
# cblas or blas
- res = False
c = customized_ccompiler()
tmpdir = tempfile.mkdtemp()
- s = """#include <cblas.h>
- int main(int argc, const char *argv[])
- {
- double a[4] = {1,2,3,4};
- double b[4] = {5,6,7,8};
- return cblas_ddot(4, a, 1, b, 1) > 10;
- }"""
+ s = textwrap.dedent("""\
+ #include <cblas.h>
+ int main(int argc, const char *argv[])
+ {
+ double a[4] = {1,2,3,4};
+ double b[4] = {5,6,7,8};
+ return cblas_ddot(4, a, 1, b, 1) > 10;
+ }""")
src = os.path.join(tmpdir, 'source.c')
try:
with open(src, 'wt') as f:
@@ -1726,27 +1892,26 @@ class blas_info(system_info):
# check we can compile (find headers)
obj = c.compile([src], output_dir=tmpdir,
include_dirs=self.get_include_dirs())
+ except (distutils.ccompiler.CompileError, distutils.ccompiler.LinkError):
+ return None
- # check we can link (find library)
- # some systems have separate cblas and blas libs. First
- # check for cblas lib, and if not present check for blas lib.
+ # check we can link (find library)
+ # some systems have separate cblas and blas libs.
+ for libs in [info['libraries'], ['cblas'] + info['libraries'],
+ ['blas'] + info['libraries'], ['cblas'], ['blas']]:
try:
c.link_executable(obj, os.path.join(tmpdir, "a.out"),
- libraries=["cblas"],
+ libraries=libs,
library_dirs=info['library_dirs'],
extra_postargs=info.get('extra_link_args', []))
- res = "cblas"
+ return libs
+ # This breaks the for loop
+ break
except distutils.ccompiler.LinkError:
- c.link_executable(obj, os.path.join(tmpdir, "a.out"),
- libraries=["blas"],
- library_dirs=info['library_dirs'],
- extra_postargs=info.get('extra_link_args', []))
- res = "blas"
- except distutils.ccompiler.CompileError:
- res = None
+ pass
finally:
shutil.rmtree(tmpdir)
- return res
+ return None
class openblas_info(blas_info):
@@ -1763,9 +1928,9 @@ class openblas_info(blas_info):
lib_dirs = self.get_lib_dirs()
- openblas_libs = self.get_libs('libraries', self._lib_names)
- if openblas_libs == self._lib_names: # backward compat with 1.8.0
- openblas_libs = self.get_libs('openblas_libs', self._lib_names)
+ # Prefer to use libraries over openblas_libs
+ opt = self.get_option_single('openblas_libs', 'libraries')
+ openblas_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, openblas_libs, [])
@@ -1836,12 +2001,13 @@ class openblas_lapack_info(openblas_info):
c = customized_ccompiler()
tmpdir = tempfile.mkdtemp()
- s = """void zungqr_();
- int main(int argc, const char *argv[])
- {
- zungqr_();
- return 0;
- }"""
+ s = textwrap.dedent("""\
+ void zungqr_();
+ int main(int argc, const char *argv[])
+ {
+ zungqr_();
+ return 0;
+ }""")
src = os.path.join(tmpdir, 'source.c')
out = os.path.join(tmpdir, 'a.out')
# Add the additional "extra" arguments
@@ -1877,10 +2043,8 @@ class blis_info(blas_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
- blis_libs = self.get_libs('libraries', self._lib_names)
- if blis_libs == self._lib_names:
- blis_libs = self.get_libs('blis_libs', self._lib_names)
-
+ opt = self.get_option_single('blis_libs', 'libraries')
+ blis_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs2(lib_dirs, blis_libs, [])
if info is None:
return
@@ -1893,8 +2057,86 @@ class blis_info(blas_info):
include_dirs=incl_dirs)
self.set_info(**info)
+
+class flame_info(system_info):
+ """ Usage of libflame for LAPACK operations
+
+ This requires libflame to be compiled with lapack wrappers:
+
+ ./configure --enable-lapack2flame ...
+
+ Be aware that libflame 5.1.0 has some missing names in the shared library, so
+ if you have problems, try the static flame library.
+ """
+ section = 'flame'
+ _lib_names = ['flame']
+ notfounderror = FlameNotFoundError
+
+ def check_embedded_lapack(self, info):
+ """ libflame does not necessarily have a wrapper for fortran LAPACK, we need to check """
+ c = customized_ccompiler()
+
+ tmpdir = tempfile.mkdtemp()
+ s = textwrap.dedent("""\
+ void zungqr_();
+ int main(int argc, const char *argv[])
+ {
+ zungqr_();
+ return 0;
+ }""")
+ src = os.path.join(tmpdir, 'source.c')
+ out = os.path.join(tmpdir, 'a.out')
+ # Add the additional "extra" arguments
+ extra_args = info.get('extra_link_args', [])
+ try:
+ with open(src, 'wt') as f:
+ f.write(s)
+ obj = c.compile([src], output_dir=tmpdir)
+ try:
+ c.link_executable(obj, out, libraries=info['libraries'],
+ library_dirs=info['library_dirs'],
+ extra_postargs=extra_args)
+ return True
+ except distutils.ccompiler.LinkError:
+ return False
+ finally:
+ shutil.rmtree(tmpdir)
+
+ def calc_info(self):
+ lib_dirs = self.get_lib_dirs()
+ flame_libs = self.get_libs('libraries', self._lib_names)
+
+ info = self.check_libs2(lib_dirs, flame_libs, [])
+ if info is None:
+ return
+
+ if self.check_embedded_lapack(info):
+ # check if the user has supplied all information required
+ self.set_info(**info)
+ else:
+ # Try and get the BLAS lib to see if we can get it to work
+ blas_info = get_info('blas_opt')
+ if not blas_info:
+ # since we already failed once, this ain't going to work either
+ return
+
+ # Now we need to merge the two dictionaries
+ for key in blas_info:
+ if isinstance(blas_info[key], list):
+ info[key] = info.get(key, []) + blas_info[key]
+ elif isinstance(blas_info[key], tuple):
+ info[key] = info.get(key, ()) + blas_info[key]
+ else:
+ info[key] = info.get(key, '') + blas_info[key]
+
+ # Now check again
+ if self.check_embedded_lapack(info):
+ self.set_info(**info)
+
+
class accelerate_info(system_info):
section = 'accelerate'
+ _lib_names = ['accelerate', 'veclib']
notfounderror = BlasNotFoundError
def calc_info(self):
@@ -1903,7 +2145,7 @@ class accelerate_info(system_info):
if libraries:
libraries = [libraries]
else:
- libraries = self.get_libs('libraries', ['accelerate', 'veclib'])
+ libraries = self.get_libs('libraries', self._lib_names)
libraries = [lib.strip().lower() for lib in libraries]
if (sys.platform == 'darwin' and
@@ -2001,6 +2243,7 @@ class blas_src_info(system_info):
class x11_info(system_info):
section = 'x11'
notfounderror = X11NotFoundError
+ _lib_names = ['X11']
def __init__(self):
system_info.__init__(self,
@@ -2012,7 +2255,8 @@ class x11_info(system_info):
return
lib_dirs = self.get_lib_dirs()
include_dirs = self.get_include_dirs()
- x11_libs = self.get_libs('x11_libs', ['X11'])
+ opt = self.get_option_single('x11_libs', 'libraries')
+ x11_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, x11_libs, [])
if info is None:
return
@@ -2403,7 +2647,8 @@ class amd_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
- amd_libs = self.get_libs('amd_libs', self._lib_names)
+ opt = self.get_option_single('amd_libs', 'libraries')
+ amd_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, amd_libs, [])
if info is None:
return
@@ -2434,7 +2679,8 @@ class umfpack_info(system_info):
def calc_info(self):
lib_dirs = self.get_lib_dirs()
- umfpack_libs = self.get_libs('umfpack_libs', self._lib_names)
+ opt = self.get_option_single('umfpack_libs', 'libraries')
+ umfpack_libs = self.get_libs(opt, self._lib_names)
info = self.check_libs(lib_dirs, umfpack_libs, [])
if info is None:
return
diff --git a/numpy/distutils/tests/test_exec_command.py b/numpy/distutils/tests/test_exec_command.py
index 8bd265007..37912f5ba 100644
--- a/numpy/distutils/tests/test_exec_command.py
+++ b/numpy/distutils/tests/test_exec_command.py
@@ -6,7 +6,7 @@ from tempfile import TemporaryFile
from numpy.distutils import exec_command
from numpy.distutils.exec_command import get_pythonexe
-from numpy.testing import tempdir, assert_
+from numpy.testing import tempdir, assert_, assert_warns
# In python 3 stdout, stderr are text (unicode compliant) devices, so to
# emulate them import StringIO from the io module.
@@ -71,27 +71,31 @@ def test_exec_command_stdout():
# Test posix version:
with redirect_stdout(StringIO()):
with redirect_stderr(TemporaryFile()):
- exec_command.exec_command("cd '.'")
+ with assert_warns(DeprecationWarning):
+ exec_command.exec_command("cd '.'")
if os.name == 'posix':
# Test general (non-posix) version:
with emulate_nonposix():
with redirect_stdout(StringIO()):
with redirect_stderr(TemporaryFile()):
- exec_command.exec_command("cd '.'")
+ with assert_warns(DeprecationWarning):
+ exec_command.exec_command("cd '.'")
def test_exec_command_stderr():
# Test posix version:
with redirect_stdout(TemporaryFile(mode='w+')):
with redirect_stderr(StringIO()):
- exec_command.exec_command("cd '.'")
+ with assert_warns(DeprecationWarning):
+ exec_command.exec_command("cd '.'")
if os.name == 'posix':
# Test general (non-posix) version:
with emulate_nonposix():
with redirect_stdout(TemporaryFile()):
with redirect_stderr(StringIO()):
- exec_command.exec_command("cd '.'")
+ with assert_warns(DeprecationWarning):
+ exec_command.exec_command("cd '.'")
class TestExecCommand(object):
@@ -205,11 +209,12 @@ class TestExecCommand(object):
def test_basic(self):
with redirect_stdout(StringIO()):
with redirect_stderr(StringIO()):
- if os.name == "posix":
- self.check_posix(use_tee=0)
- self.check_posix(use_tee=1)
- elif os.name == "nt":
- self.check_nt(use_tee=0)
- self.check_nt(use_tee=1)
- self.check_execute_in(use_tee=0)
- self.check_execute_in(use_tee=1)
+ with assert_warns(DeprecationWarning):
+ if os.name == "posix":
+ self.check_posix(use_tee=0)
+ self.check_posix(use_tee=1)
+ elif os.name == "nt":
+ self.check_nt(use_tee=0)
+ self.check_nt(use_tee=1)
+ self.check_execute_in(use_tee=0)
+ self.check_execute_in(use_tee=1)
diff --git a/numpy/distutils/tests/test_system_info.py b/numpy/distutils/tests/test_system_info.py
index f7e275a2e..3c7638960 100644
--- a/numpy/distutils/tests/test_system_info.py
+++ b/numpy/distutils/tests/test_system_info.py
@@ -7,9 +7,10 @@ from tempfile import mkstemp, mkdtemp
from subprocess import Popen, PIPE
from distutils.errors import DistutilsError
+from numpy.testing import assert_, assert_equal, assert_raises
from numpy.distutils import ccompiler, customized_ccompiler
-from numpy.testing import assert_, assert_equal
from numpy.distutils.system_info import system_info, ConfigParser
+from numpy.distutils.system_info import AliasedOptionError
from numpy.distutils.system_info import default_lib_dirs, default_include_dirs
from numpy.distutils import _shell_utils
@@ -22,7 +23,8 @@ def get_class(name, notfound_action=1):
2 - raise error
"""
cl = {'temp1': Temp1Info,
- 'temp2': Temp2Info
+ 'temp2': Temp2Info,
+ 'duplicate_options': DuplicateOptionInfo,
}.get(name.lower(), _system_info)
return cl()
@@ -43,6 +45,10 @@ library_dirs = {dir2:s}
libraries = {lib2:s}
extra_link_args = -Wl,-rpath={lib2_escaped:s}
rpath = {dir2:s}
+
+[duplicate_options]
+mylib_libs = {lib1:s}
+libraries = {lib2:s}
"""
site_cfg = simple_site
@@ -119,6 +125,10 @@ class Temp2Info(_system_info):
"""For testing purposes"""
section = 'temp2'
+class DuplicateOptionInfo(_system_info):
+ """For testing purposes"""
+ section = 'duplicate_options'
+
class TestSystemInfoReading(object):
@@ -160,6 +170,9 @@ class TestSystemInfoReading(object):
self.c_default = site_and_parse(get_class('default'), self._sitecfg)
self.c_temp1 = site_and_parse(get_class('temp1'), self._sitecfg)
self.c_temp2 = site_and_parse(get_class('temp2'), self._sitecfg)
+ self.c_dup_options = site_and_parse(get_class('duplicate_options'),
+ self._sitecfg)
+
def teardown(self):
# Do each removal separately
@@ -202,6 +215,13 @@ class TestSystemInfoReading(object):
extra = tsi.calc_extra_info()
assert_equal(extra['extra_link_args'], ['-Wl,-rpath=' + self._lib2])
+ def test_duplicate_options(self):
+ # Ensure that duplicates are raising an AliasedOptionError
+ tsi = self.c_dup_options
+ assert_raises(AliasedOptionError, tsi.get_option_single, "mylib_libs", "libraries")
+ assert_equal(tsi.get_libs("mylib_libs", [self._lib1]), [self._lib1])
+ assert_equal(tsi.get_libs("libraries", [self._lib2]), [self._lib2])
+
@pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler")
def test_compile1(self):
# Compile source and link the first source
diff --git a/numpy/doc/basics.py b/numpy/doc/basics.py
index c87a40ccd..7946c6432 100644
--- a/numpy/doc/basics.py
+++ b/numpy/doc/basics.py
@@ -260,6 +260,45 @@ identical behaviour between arrays and scalars, irrespective of whether the
value is inside an array or not. NumPy scalars also have many of the same
methods arrays do.
+Overflow Errors
+===============
+
+The fixed size of NumPy numeric types may cause overflow errors when a value
+requires more memory than available in the data type. For example,
+`numpy.power` evaluates ``100 * 10 ** 8`` correctly for 64-bit integers,
+but gives 1874919424 (incorrect) for a 32-bit integer.
+
+ >>> np.power(100, 8, dtype=np.int64)
+ 10000000000000000
+ >>> np.power(100, 8, dtype=np.int32)
+ 1874919424
+
+The behaviour of NumPy and Python integer types differs significantly for
+integer overflows and may confuse users expecting NumPy integers to behave
+similar to Python's ``int``. Unlike NumPy, the size of Python's ``int`` is
+flexible. This means Python integers may expand to accommodate any integer and
+will not overflow.
+
+NumPy provides `numpy.iinfo` and `numpy.finfo` to verify the
+minimum or maximum values of NumPy integer and floating point values
+respectively ::
+
+ >>> np.iinfo(np.int) # Bounds of the default integer on this system.
+ iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)
+ >>> np.iinfo(np.int32) # Bounds of a 32-bit integer
+ iinfo(min=-2147483648, max=2147483647, dtype=int32)
+ >>> np.iinfo(np.int64) # Bounds of a 64-bit integer
+ iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)
+
+If 64-bit integers are still too small the result may be cast to a
+floating point number. Floating point numbers offer a larger, but inexact,
+range of possible values.
+
+ >>> np.power(100, 100, dtype=np.int64) # Incorrect even with 64-bit int
+ 0
+ >>> np.power(100, 100, dtype=np.float64)
+ 1e+200
+
Extended Precision
==================
diff --git a/numpy/doc/byteswapping.py b/numpy/doc/byteswapping.py
index f9491ed43..7a749c8d5 100644
--- a/numpy/doc/byteswapping.py
+++ b/numpy/doc/byteswapping.py
@@ -31,16 +31,16 @@ Let's say the two integers were in fact 1 and 770. Because 770 = 256 *
3 + 2, the 4 bytes in memory would contain respectively: 0, 1, 3, 2.
The bytes I have loaded from the file would have these contents:
->>> big_end_str = chr(0) + chr(1) + chr(3) + chr(2)
->>> big_end_str
-'\\x00\\x01\\x03\\x02'
+>>> big_end_buffer = bytearray([0,1,3,2])
+>>> big_end_buffer
+bytearray(b'\\x00\\x01\\x03\\x02')
We might want to use an ``ndarray`` to access these integers. In that
case, we can create an array around this memory, and tell numpy that
there are two integers, and that they are 16 bit and big-endian:
>>> import numpy as np
->>> big_end_arr = np.ndarray(shape=(2,),dtype='>i2', buffer=big_end_str)
+>>> big_end_arr = np.ndarray(shape=(2,),dtype='>i2', buffer=big_end_buffer)
>>> big_end_arr[0]
1
>>> big_end_arr[1]
@@ -53,7 +53,7 @@ integer, the dtype string would be ``<u4``.
In fact, why don't we try that?
->>> little_end_u4 = np.ndarray(shape=(1,),dtype='<u4', buffer=big_end_str)
+>>> little_end_u4 = np.ndarray(shape=(1,),dtype='<u4', buffer=big_end_buffer)
>>> little_end_u4[0] == 1 * 256**1 + 3 * 256**2 + 2 * 256**3
True
@@ -97,7 +97,7 @@ Data and dtype endianness don't match, change dtype to match data
We make something where they don't match:
->>> wrong_end_dtype_arr = np.ndarray(shape=(2,),dtype='<i2', buffer=big_end_str)
+>>> wrong_end_dtype_arr = np.ndarray(shape=(2,),dtype='<i2', buffer=big_end_buffer)
>>> wrong_end_dtype_arr[0]
256
@@ -110,7 +110,7 @@ the correct endianness:
Note the array has not changed in memory:
->>> fixed_end_dtype_arr.tobytes() == big_end_str
+>>> fixed_end_dtype_arr.tobytes() == big_end_buffer
True
Data and type endianness don't match, change data to match dtype
@@ -126,7 +126,7 @@ that needs a certain byte ordering.
Now the array *has* changed in memory:
->>> fixed_end_mem_arr.tobytes() == big_end_str
+>>> fixed_end_mem_arr.tobytes() == big_end_buffer
False
Data and dtype endianness match, swap data and dtype
@@ -140,7 +140,7 @@ the previous operations:
>>> swapped_end_arr = big_end_arr.byteswap().newbyteorder()
>>> swapped_end_arr[0]
1
->>> swapped_end_arr.tobytes() == big_end_str
+>>> swapped_end_arr.tobytes() == big_end_buffer
False
An easier way of casting the data to a specific dtype and byte ordering
@@ -149,7 +149,7 @@ can be achieved with the ndarray astype method:
>>> swapped_end_arr = big_end_arr.astype('<i2')
>>> swapped_end_arr[0]
1
->>> swapped_end_arr.tobytes() == big_end_str
+>>> swapped_end_arr.tobytes() == big_end_buffer
False
"""
diff --git a/numpy/doc/constants.py b/numpy/doc/constants.py
index 21c7a3c67..72793e44d 100644
--- a/numpy/doc/constants.py
+++ b/numpy/doc/constants.py
@@ -22,53 +22,51 @@ constants = []
def add_newdoc(module, name, doc):
constants.append((name, doc))
-add_newdoc('numpy', 'Inf',
+add_newdoc('numpy', 'pi',
"""
- IEEE 754 floating point representation of (positive) infinity.
-
- Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
- `inf`. For more details, see `inf`.
+ ``pi = 3.1415926535897932384626433...``
- See Also
- --------
- inf
+ References
+ ----------
+ https://en.wikipedia.org/wiki/Pi
""")
-add_newdoc('numpy', 'Infinity',
+add_newdoc('numpy', 'e',
"""
- IEEE 754 floating point representation of (positive) infinity.
+ Euler's constant, base of natural logarithms, Napier's constant.
- Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
- `inf`. For more details, see `inf`.
+ ``e = 2.71828182845904523536028747135266249775724709369995...``
See Also
--------
- inf
+ exp : Exponential function
+ log : Natural logarithm
+
+ References
+ ----------
+ https://en.wikipedia.org/wiki/E_%28mathematical_constant%29
""")
-add_newdoc('numpy', 'NAN',
+add_newdoc('numpy', 'euler_gamma',
"""
- IEEE 754 floating point representation of Not a Number (NaN).
-
- `NaN` and `NAN` are equivalent definitions of `nan`. Please use
- `nan` instead of `NAN`.
+ ``γ = 0.5772156649015328606065120900824024310421...``
- See Also
- --------
- nan
+ References
+ ----------
+ https://en.wikipedia.org/wiki/Euler-Mascheroni_constant
""")
-add_newdoc('numpy', 'NINF',
+add_newdoc('numpy', 'inf',
"""
- IEEE 754 floating point representation of negative infinity.
+ IEEE 754 floating point representation of (positive) infinity.
Returns
-------
y : float
- A floating point representation of negative infinity.
+ A floating point representation of positive infinity.
See Also
--------
@@ -90,12 +88,96 @@ add_newdoc('numpy', 'NINF',
Also that positive infinity is not equivalent to negative infinity. But
infinity is equivalent to positive infinity.
+ `Inf`, `Infinity`, `PINF` and `infty` are aliases for `inf`.
+
Examples
--------
- >>> np.NINF
- -inf
- >>> np.log(0)
- -inf
+ >>> np.inf
+ inf
+ >>> np.array([1]) / 0.
+ array([ Inf])
+
+ """)
+
+add_newdoc('numpy', 'nan',
+ """
+ IEEE 754 floating point representation of Not a Number (NaN).
+
+ Returns
+ -------
+ y : A floating point representation of Not a Number.
+
+ See Also
+ --------
+ isnan : Shows which elements are Not a Number.
+
+ isfinite : Shows which elements are finite (not one of
+ Not a Number, positive infinity and negative infinity)
+
+ Notes
+ -----
+ NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
+ (IEEE 754). This means that Not a Number is not equivalent to infinity.
+
+ `NaN` and `NAN` are aliases of `nan`.
+
+ Examples
+ --------
+ >>> np.nan
+ nan
+ >>> np.log(-1)
+ nan
+ >>> np.log([-1, 1, 2])
+ array([ NaN, 0. , 0.69314718])
+
+ """)
+
+add_newdoc('numpy', 'newaxis',
+ """
+ A convenient alias for None, useful for indexing arrays.
+
+ See Also
+ --------
+ `numpy.doc.indexing`
+
+ Examples
+ --------
+ >>> newaxis is None
+ True
+ >>> x = np.arange(3)
+ >>> x
+ array([0, 1, 2])
+ >>> x[:, newaxis]
+ array([[0],
+ [1],
+ [2]])
+ >>> x[:, newaxis, newaxis]
+ array([[[0]],
+ [[1]],
+ [[2]]])
+ >>> x[:, newaxis] * x
+ array([[0, 0, 0],
+ [0, 1, 2],
+ [0, 2, 4]])
+
+ Outer product, same as ``outer(x, y)``:
+
+ >>> y = np.arange(3, 6)
+ >>> x[:, newaxis] * y
+ array([[ 0, 0, 0],
+ [ 3, 4, 5],
+ [ 6, 8, 10]])
+
+ ``x[newaxis, :]`` is equivalent to ``x[newaxis]`` and ``x[None]``:
+
+ >>> x[newaxis, :].shape
+ (1, 3)
+ >>> x[newaxis].shape
+ (1, 3)
+ >>> x[None].shape
+ (1, 3)
+ >>> x[:, newaxis].shape
+ (3, 1)
""")
@@ -144,32 +226,6 @@ add_newdoc('numpy', 'NZERO',
""")
-add_newdoc('numpy', 'NaN',
- """
- IEEE 754 floating point representation of Not a Number (NaN).
-
- `NaN` and `NAN` are equivalent definitions of `nan`. Please use
- `nan` instead of `NaN`.
-
- See Also
- --------
- nan
-
- """)
-
-add_newdoc('numpy', 'PINF',
- """
- IEEE 754 floating point representation of (positive) infinity.
-
- Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
- `inf`. For more details, see `inf`.
-
- See Also
- --------
- inf
-
- """)
-
add_newdoc('numpy', 'PZERO',
"""
IEEE 754 floating point representation of positive zero.
@@ -215,31 +271,40 @@ add_newdoc('numpy', 'PZERO',
""")
-add_newdoc('numpy', 'e',
+add_newdoc('numpy', 'NAN',
"""
- Euler's constant, base of natural logarithms, Napier's constant.
+ IEEE 754 floating point representation of Not a Number (NaN).
- ``e = 2.71828182845904523536028747135266249775724709369995...``
+ `NaN` and `NAN` are equivalent definitions of `nan`. Please use
+ `nan` instead of `NAN`.
See Also
--------
- exp : Exponential function
- log : Natural logarithm
+ nan
- References
- ----------
- https://en.wikipedia.org/wiki/E_%28mathematical_constant%29
+ """)
+
+add_newdoc('numpy', 'NaN',
+ """
+ IEEE 754 floating point representation of Not a Number (NaN).
+
+ `NaN` and `NAN` are equivalent definitions of `nan`. Please use
+ `nan` instead of `NaN`.
+
+ See Also
+ --------
+ nan
""")
-add_newdoc('numpy', 'inf',
+add_newdoc('numpy', 'NINF',
"""
- IEEE 754 floating point representation of (positive) infinity.
+ IEEE 754 floating point representation of negative infinity.
Returns
-------
y : float
- A floating point representation of positive infinity.
+ A floating point representation of negative infinity.
See Also
--------
@@ -261,18 +326,16 @@ add_newdoc('numpy', 'inf',
Also that positive infinity is not equivalent to negative infinity. But
infinity is equivalent to positive infinity.
- `Inf`, `Infinity`, `PINF` and `infty` are aliases for `inf`.
-
Examples
--------
- >>> np.inf
- inf
- >>> np.array([1]) / 0.
- array([ Inf])
+ >>> np.NINF
+ -inf
+ >>> np.log(0)
+ -inf
""")
-add_newdoc('numpy', 'infty',
+add_newdoc('numpy', 'PINF',
"""
IEEE 754 floating point representation of (positive) infinity.
@@ -285,108 +348,46 @@ add_newdoc('numpy', 'infty',
""")
-add_newdoc('numpy', 'nan',
+add_newdoc('numpy', 'infty',
"""
- IEEE 754 floating point representation of Not a Number (NaN).
+ IEEE 754 floating point representation of (positive) infinity.
- Returns
- -------
- y : A floating point representation of Not a Number.
+ Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
+ `inf`. For more details, see `inf`.
See Also
--------
- isnan : Shows which elements are Not a Number.
-
- isfinite : Shows which elements are finite (not one of
- Not a Number, positive infinity and negative infinity)
-
- Notes
- -----
- NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
- (IEEE 754). This means that Not a Number is not equivalent to infinity.
-
- `NaN` and `NAN` are aliases of `nan`.
-
- Examples
- --------
- >>> np.nan
- nan
- >>> np.log(-1)
- nan
- >>> np.log([-1, 1, 2])
- array([ NaN, 0. , 0.69314718])
+ inf
""")
-add_newdoc('numpy', 'newaxis',
+add_newdoc('numpy', 'Inf',
"""
- A convenient alias for None, useful for indexing arrays.
+ IEEE 754 floating point representation of (positive) infinity.
- See Also
- --------
- `numpy.doc.indexing`
+ Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
+ `inf`. For more details, see `inf`.
- Examples
+ See Also
--------
- >>> newaxis is None
- True
- >>> x = np.arange(3)
- >>> x
- array([0, 1, 2])
- >>> x[:, newaxis]
- array([[0],
- [1],
- [2]])
- >>> x[:, newaxis, newaxis]
- array([[[0]],
- [[1]],
- [[2]]])
- >>> x[:, newaxis] * x
- array([[0, 0, 0],
- [0, 1, 2],
- [0, 2, 4]])
-
- Outer product, same as ``outer(x, y)``:
-
- >>> y = np.arange(3, 6)
- >>> x[:, newaxis] * y
- array([[ 0, 0, 0],
- [ 3, 4, 5],
- [ 6, 8, 10]])
-
- ``x[newaxis, :]`` is equivalent to ``x[newaxis]`` and ``x[None]``:
-
- >>> x[newaxis, :].shape
- (1, 3)
- >>> x[newaxis].shape
- (1, 3)
- >>> x[None].shape
- (1, 3)
- >>> x[:, newaxis].shape
- (3, 1)
+ inf
""")
-add_newdoc('numpy', 'pi',
+add_newdoc('numpy', 'Infinity',
"""
- ``pi = 3.1415926535897932384626433...``
-
- References
- ----------
- https://en.wikipedia.org/wiki/Pi
-
- """)
+ IEEE 754 floating point representation of (positive) infinity.
-add_newdoc('numpy', 'euler_gamma',
- """
- ``γ = 0.5772156649015328606065120900824024310421...``
+ Use `inf` because `Inf`, `Infinity`, `PINF` and `infty` are aliases for
+ `inf`. For more details, see `inf`.
- References
- ----------
- https://en.wikipedia.org/wiki/Euler-Mascheroni_constant
+ See Also
+ --------
+ inf
""")
+
if __doc__:
constants_str = []
constants.sort()
diff --git a/numpy/doc/glossary.py b/numpy/doc/glossary.py
index a3b9423a8..7d1c9a1d5 100644
--- a/numpy/doc/glossary.py
+++ b/numpy/doc/glossary.py
@@ -159,7 +159,7 @@ Glossary
field
In a :term:`structured data type`, each sub-type is called a `field`.
- The `field` has a name (a string), a type (any valid :term:`dtype`, and
+ The `field` has a name (a string), a type (any valid dtype, and
an optional `title`. See :ref:`arrays.dtypes`
Fortran order
@@ -209,6 +209,9 @@ Glossary
Key 1: b
Key 2: c
+ itemsize
+ The size of the dtype element in bytes.
+
list
A Python container that can hold any number of objects or items.
The items do not have to be of the same type, and can even be
@@ -270,13 +273,11 @@ Glossary
masked_array(data = [-- 2.0 --],
mask = [ True False True],
fill_value = 1e+20)
- <BLANKLINE>
>>> x + [1, 2, 3]
masked_array(data = [-- 4.0 --],
mask = [ True False True],
fill_value = 1e+20)
- <BLANKLINE>
Masked arrays are often used when operating on arrays containing
@@ -347,31 +348,31 @@ Glossary
Painting the city red!
slice
- Used to select only certain elements from a sequence::
+ Used to select only certain elements from a sequence:
- >>> x = range(5)
- >>> x
- [0, 1, 2, 3, 4]
+ >>> x = range(5)
+ >>> x
+ [0, 1, 2, 3, 4]
- >>> x[1:3] # slice from 1 to 3 (excluding 3 itself)
- [1, 2]
+ >>> x[1:3] # slice from 1 to 3 (excluding 3 itself)
+ [1, 2]
- >>> x[1:5:2] # slice from 1 to 5, but skipping every second element
- [1, 3]
+ >>> x[1:5:2] # slice from 1 to 5, but skipping every second element
+ [1, 3]
- >>> x[::-1] # slice a sequence in reverse
- [4, 3, 2, 1, 0]
+ >>> x[::-1] # slice a sequence in reverse
+ [4, 3, 2, 1, 0]
Arrays may have more than one dimension, each which can be sliced
- individually::
+ individually:
- >>> x = np.array([[1, 2], [3, 4]])
- >>> x
- array([[1, 2],
- [3, 4]])
+ >>> x = np.array([[1, 2], [3, 4]])
+ >>> x
+ array([[1, 2],
+ [3, 4]])
- >>> x[:, 1]
- array([2, 4])
+ >>> x[:, 1]
+ array([2, 4])
structure
See :term:`structured data type`
@@ -379,6 +380,20 @@ Glossary
structured data type
A data type composed of other datatypes
+ subarray data type
+ A :term:`structured data type` may contain a :term:`ndarray` with its
+ own dtype and shape:
+
+ >>> dt = np.dtype([('a', np.int32), ('b', np.float32, (3,))])
+ >>> np.zeros(3, dtype=dt)
+ array([(0, [0., 0., 0.]), (0, [0., 0., 0.]), (0, [0., 0., 0.])],
+ dtype=[('a', '<i4'), ('b', '<f4', (3,))])
+
+ title
+ In addition to field names, structured array fields may have an
+ associated :ref:`title <titles>` which is an alias to the name and is
+ commonly used for plotting.
+
tuple
A sequence that may contain a variable number of types of any
kind. A tuple is immutable, i.e., once constructed it cannot be
@@ -415,8 +430,19 @@ Glossary
'alpha'
ufunc
- Universal function. A fast element-wise array operation. Examples include
- ``add``, ``sin`` and ``logical_or``.
+ Universal function. A fast element-wise, :term:`vectorized
+ <vectorization>` array operation. Examples include ``add``, ``sin`` and
+ ``logical_or``.
+
+ vectorization
+ Optimizing a looping block by specialized code. In a traditional sense,
+ vectorization performs the same operation on multiple elements with
+ fixed strides between them via specialized hardware. Compilers know how
+ to take advantage of well-constructed loops to implement such
+ optimizations. NumPy uses :ref:`vectorization <whatis-vectorization>`
+ to mean any optimization via specialized code performing the same
+ operations on multiple elements, typically achieving speedups by
+ avoiding some of the overhead in looking up and converting the elements.
view
An array that does not own its data, but refers to another array's
diff --git a/numpy/doc/indexing.py b/numpy/doc/indexing.py
index 087a688bc..676015668 100644
--- a/numpy/doc/indexing.py
+++ b/numpy/doc/indexing.py
@@ -1,4 +1,5 @@
-"""==============
+"""
+==============
Array indexing
==============
@@ -93,7 +94,9 @@ well. A few examples illustrates best: ::
[21, 24, 27]])
Note that slices of arrays do not copy the internal array data but
-only produce new views of the original data.
+only produce new views of the original data. This is different from
+list or tuple slicing and an explicit ``copy()`` is recommended if
+the original data is not required anymore.
It is possible to index arrays with other arrays for the purposes of
selecting lists of values out of arrays into new arrays. There are
@@ -105,7 +108,7 @@ arrays and thus greatly improve performance.
It is possible to use special features to effectively increase the
number of dimensions in an array through indexing so the resulting
-array aquires the shape needed for use in an expression or with a
+array acquires the shape needed for use in an expression or with a
specific function.
Index arrays
@@ -293,6 +296,13 @@ to produce a resultant array of shape (3,2).
Likewise, slicing can be combined with broadcasted boolean indices: ::
+ >>> b = y > 20
+ >>> b
+ array([[False, False, False, False, False, False, False],
+ [False, False, False, False, False, False, False],
+ [False, False, False, False, False, False, False],
+ [ True, True, True, True, True, True, True],
+ [ True, True, True, True, True, True, True]])
>>> y[b[:,5],1:3]
array([[22, 23],
[29, 30]])
diff --git a/numpy/doc/structured_arrays.py b/numpy/doc/structured_arrays.py
index 6d0ce49f9..1343d2adc 100644
--- a/numpy/doc/structured_arrays.py
+++ b/numpy/doc/structured_arrays.py
@@ -13,8 +13,8 @@ datatypes organized as a sequence of named :term:`fields <field>`. For example,
>>> x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
... dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> x
- array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
- dtype=[('name', 'S10'), ('age', '<i4'), ('weight', '<f4')])
+ array([('Rex', 9, 81.), ('Fido', 3, 27.)],
+ dtype=[('name', 'U10'), ('age', '<i4'), ('weight', '<f4')])
Here ``x`` is a one-dimensional array of length two whose datatype is a
structure with three fields: 1. A string of length 10 or less named 'name', 2.
@@ -32,8 +32,8 @@ with the field name::
array([9, 3], dtype=int32)
>>> x['age'] = 5
>>> x
- array([('Rex', 5, 81.0), ('Fido', 5, 27.0)],
- dtype=[('name', 'S10'), ('age', '<i4'), ('weight', '<f4')])
+ array([('Rex', 5, 81.), ('Fido', 5, 27.)],
+ dtype=[('name', 'U10'), ('age', '<i4'), ('weight', '<f4')])
Structured datatypes are designed to be able to mimic 'structs' in the C
language, and share a similar memory layout. They are meant for interfacing with
@@ -57,10 +57,10 @@ A structured datatype can be thought of as a sequence of bytes of a certain
length (the structure's :term:`itemsize`) which is interpreted as a collection
of fields. Each field has a name, a datatype, and a byte offset within the
structure. The datatype of a field may be any numpy datatype including other
-structured datatypes, and it may also be a :term:`sub-array` which behaves like
-an ndarray of a specified shape. The offsets of the fields are arbitrary, and
-fields may even overlap. These offsets are usually determined automatically by
-numpy, but can also be specified.
+structured datatypes, and it may also be a :term:`subarray data type` which
+behaves like an ndarray of a specified shape. The offsets of the fields are
+arbitrary, and fields may even overlap. These offsets are usually determined
+automatically by numpy, but can also be specified.
Structured Datatype Creation
----------------------------
@@ -79,14 +79,14 @@ summary they are:
convertible to a datatype, and ``shape`` is a tuple of integers specifying
subarray shape.
- >>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2,2))])
- dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4', (2, 2))])
+ >>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))])
+ dtype([('x', '<f4'), ('y', '<f4'), ('z', '<f4', (2, 2))])
If ``fieldname`` is the empty string ``''``, the field will be given a
default name of the form ``f#``, where ``#`` is the integer index of the
field, counting from 0 from the left::
- >>> np.dtype([('x', 'f4'),('', 'i4'),('z', 'i8')])
+ >>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')])
dtype([('x', '<f4'), ('f1', '<i4'), ('z', '<i8')])
The byte offsets of the fields within the structure and the total
@@ -100,10 +100,10 @@ summary they are:
automatically, and the field names are given the default names ``f0``,
``f1``, etc. ::
- >>> np.dtype('i8,f4,S3')
+ >>> np.dtype('i8, f4, S3')
dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])
- >>> np.dtype('3int8, float32, (2,3)float64')
- dtype([('f0', 'i1', 3), ('f1', '<f4'), ('f2', '<f8', (2, 3))])
+ >>> np.dtype('3int8, float32, (2, 3)float64')
+ dtype([('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])
3. A dictionary of field parameter arrays
@@ -121,10 +121,10 @@ summary they are:
enough to contain all the fields.
::
- >>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4','f4']})
+ >>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})
dtype([('col1', '<i4'), ('col2', '<f4')])
>>> np.dtype({'names': ['col1', 'col2'],
- ... 'formats': ['i4','f4'],
+ ... 'formats': ['i4', 'f4'],
... 'offsets': [0, 4],
... 'itemsize': 12})
dtype({'names':['col1','col2'], 'formats':['<i4','<f4'], 'offsets':[0,4], 'itemsize':12})
@@ -149,8 +149,8 @@ summary they are:
because older numpy code may use it. The keys of the dictionary are the
field names and the values are tuples specifying type and offset::
- >>> np.dtype=({'col1': ('i1',0), 'col2': ('f4',1)})
- dtype([(('col1'), 'i1'), (('col2'), '>f4')])
+ >>> np.dtype({'col1': ('i1', 0), 'col2': ('f4', 1)})
+ dtype([('col1', 'i1'), ('col2', '<f4')])
This form is discouraged because Python dictionaries do not preserve order
in Python versions before Python 3.6, and the order of the fields in a
@@ -202,7 +202,7 @@ are contiguous in memory. ::
>>> def print_offsets(d):
... print("offsets:", [d.fields[name][1] for name in d.names])
... print("itemsize:", d.itemsize)
- >>> print_offsets(np.dtype('u1,u1,i4,u1,i8,u2'))
+ >>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2'))
offsets: [0, 1, 2, 6, 7, 15]
itemsize: 17
@@ -215,7 +215,7 @@ in bytes for simple datatypes, see :c:member:`PyArray_Descr.alignment`. The
structure will also have trailing padding added so that its itemsize is a
multiple of the largest field's alignment. ::
- >>> print_offsets(np.dtype('u1,u1,i4,u1,i8,u2', align=True))
+ >>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True))
offsets: [0, 1, 4, 8, 16, 24]
itemsize: 32
@@ -231,7 +231,7 @@ each field's offset is a multiple of its size and that the itemsize is a
multiple of the largest field size, and raise an exception if not.
If the offsets of the fields and itemsize of a structured array satisfy the
-alignment conditions, the array will have the ``ALIGNED`` :ref:`flag
+alignment conditions, the array will have the ``ALIGNED`` :attr:`flag
<numpy.ndarray.flags>` set.
A convenience function :func:`numpy.lib.recfunctions.repack_fields` converts an
@@ -255,6 +255,7 @@ string, which will be the field's title and field name respectively. For
example::
>>> np.dtype([(('my title', 'name'), 'f4')])
+ dtype([(('my title', 'name'), '<f4')])
When using the first form of dictionary-based specification, the titles may be
supplied as an extra ``'titles'`` key as described above. When using the second
@@ -263,8 +264,9 @@ providing a 3-element tuple ``(datatype, offset, title)`` instead of the usual
2-element tuple::
>>> np.dtype({'name': ('i4', 0, 'my title')})
+ dtype([(('my title', 'name'), '<i4')])
-The ``dtype.fields`` dictionary will contain :term:`titles` as keys, if any
+The ``dtype.fields`` dictionary will contain titles as keys, if any
titles are used. This means effectively that a field with a title will be
represented twice in the fields dictionary. The tuple values for these fields
will also have a third element, the field title. Because of this, and because
@@ -275,6 +277,8 @@ in::
>>> for name in d.names:
... print(d.fields[name][:2])
+ (dtype('int64'), 0)
+ (dtype('float32'), 8)
Union types
-----------
@@ -305,8 +309,8 @@ in the array, and not a list or array as these will trigger numpy's
broadcasting rules. The tuple's elements are assigned to the successive fields
of the array, from left to right::
- >>> x = np.array([(1,2,3),(4,5,6)], dtype='i8,f4,f8')
- >>> x[1] = (7,8,9)
+ >>> x = np.array([(1, 2, 3), (4, 5, 6)], dtype='i8, f4, f8')
+ >>> x[1] = (7, 8, 9)
>>> x
array([(1, 2., 3.), (7, 8., 9.)],
dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '<f8')])
@@ -318,14 +322,14 @@ A scalar assigned to a structured element will be assigned to all fields. This
happens when a scalar is assigned to a structured array, or when an
unstructured array is assigned to a structured array::
- >>> x = np.zeros(2, dtype='i8,f4,?,S1')
+ >>> x = np.zeros(2, dtype='i8, f4, ?, S1')
>>> x[:] = 3
>>> x
- array([(3, 3.0, True, b'3'), (3, 3.0, True, b'3')],
+ array([(3, 3., True, b'3'), (3, 3., True, b'3')],
dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
>>> x[:] = np.arange(2)
>>> x
- array([(0, 0.0, False, b'0'), (1, 1.0, True, b'1')],
+ array([(0, 0., False, b'0'), (1, 1., True, b'1')],
dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
Structured arrays can also be assigned to unstructured arrays, but only if the
@@ -354,7 +358,7 @@ included in any of the fields are unaffected. ::
>>> b = np.ones(3, dtype=[('x', 'f4'), ('y', 'S3'), ('z', 'O')])
>>> b[:] = a
>>> b
- array([(0.0, b'0.0', b''), (0.0, b'0.0', b''), (0.0, b'0.0', b'')],
+ array([(0., b'0.0', b''), (0., b'0.0', b''), (0., b'0.0', b'')],
dtype=[('x', '<f4'), ('y', 'S3'), ('z', 'O')])
@@ -373,7 +377,7 @@ Accessing Individual Fields
Individual fields of a structured array may be accessed and modified by indexing
the array with the field name. ::
- >>> x = np.array([(1,2),(3,4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
+ >>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> x['foo']
array([1, 3])
>>> x['foo'] = 10
@@ -385,9 +389,9 @@ The resulting array is a view into the original array. It shares the same
memory locations and writing to the view will modify the original array. ::
>>> y = x['bar']
- >>> y[:] = 10
+ >>> y[:] = 11
>>> x
- array([(10, 5.), (10, 5.)],
+ array([(10, 11.), (10, 11.)],
dtype=[('foo', '<i8'), ('bar', '<f4')])
This view has the same dtype and itemsize as the indexed field, so it is
@@ -399,7 +403,7 @@ typically a non-structured array, except in the case of nested structures.
If the accessed field is a subarray, the dimensions of the subarray
are appended to the shape of the result::
- >>> x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))])
+ >>> x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
>>> x['a'].shape
(2, 2)
>>> x['b'].shape
@@ -424,8 +428,9 @@ array, as follows::
Assignment to the view modifies the original array. The view's fields will be
in the order they were indexed. Note that unlike for single-field indexing, the
-view's dtype has the same itemsize as the original array, and has fields at the
-same offsets as in the original array, and unindexed fields are merely missing.
+dtype of the view has the same itemsize as the original array, and has fields
+at the same offsets as in the original array, and unindexed fields are merely
+missing.
.. warning::
In Numpy 1.15, indexing an array with a multi-field index returned a copy of
@@ -437,15 +442,16 @@ same offsets as in the original array, and unindexed fields are merely missing.
code which depends on the data having a "packed" layout. For instance code
such as::
- >>> a = np.zeros(3, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'f4')])
- >>> a[['a','c']].view('i8') # Fails in Numpy 1.16
+ >>> a[['a', 'c']].view('i8') # Fails in Numpy 1.16
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
ValueError: When changing to a smaller dtype, its size must be a divisor of the size of original dtype
will need to be changed. This code has raised a ``FutureWarning`` since
Numpy 1.12, and similar code has raised ``FutureWarning`` since 1.7.
In 1.16 a number of functions have been introduced in the
- :module:`numpy.lib.recfunctions` module to help users account for this
+ :mod:`numpy.lib.recfunctions` module to help users account for this
change. These are
:func:`numpy.lib.recfunctions.repack_fields`.
:func:`numpy.lib.recfunctions.structured_to_unstructured`,
@@ -458,7 +464,8 @@ same offsets as in the original array, and unindexed fields are merely missing.
used to reproduce the old behavior, as it will return a packed copy of the
structured array. The code above, for example, can be replaced with:
- >>> repack_fields(a[['a','c']]).view('i8') # supported in 1.16
+ >>> from numpy.lib.recfunctions import repack_fields
+ >>> repack_fields(a[['a', 'c']]).view('i8') # supported in 1.16
array([0, 0, 0])
Furthermore, numpy now provides a new function
@@ -469,12 +476,14 @@ same offsets as in the original array, and unindexed fields are merely missing.
account padding, often avoids a copy, and also casts the datatypes
as needed, unlike the view. Code such as:
- >>> a = np.zeros(3, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
- >>> a[['x', 'z']].view('f4')
+ >>> b = np.zeros(3, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
+ >>> b[['x', 'z']].view('f4')
+ array([0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)
can be made safer by replacing with:
- >>> structured_to_unstructured(a[['x', 'z']])
+ >>> from numpy.lib.recfunctions import structured_to_unstructured
+ >>> structured_to_unstructured(b[['x', 'z']])
array([0, 0, 0])
@@ -482,8 +491,8 @@ Assignment to an array with a multi-field index modifies the original array::
>>> a[['a', 'c']] = (2, 3)
>>> a
- array([(2, 0, 3.0), (2, 0, 3.0), (2, 0, 3.0)],
- dtype=[('a', '<i8'), ('b', '<i4'), ('c', '<f8')])
+ array([(2, 0, 3.), (2, 0, 3.), (2, 0, 3.)],
+ dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<f4')])
This obeys the structured array assignment rules described above. For example,
this means that one can swap the values of two fields using appropriate
@@ -497,19 +506,19 @@ Indexing with an Integer to get a Structured Scalar
Indexing a single element of a structured array (with an integer index) returns
a structured scalar::
- >>> x = np.array([(1, 2., 3.)], dtype='i,f,f')
+ >>> x = np.array([(1, 2., 3.)], dtype='i, f, f')
>>> scalar = x[0]
>>> scalar
(1, 2., 3.)
>>> type(scalar)
- numpy.void
+ <class 'numpy.void'>
Unlike other numpy scalars, structured scalars are mutable and act like views
into the original array, such that modifying the scalar will modify the
original array. Structured scalars also support access and assignment by field
name::
- >>> x = np.array([(1,2),(3,4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
+ >>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> s = x[0]
>>> s['bar'] = 100
>>> x
@@ -518,7 +527,7 @@ name::
Similarly to tuples, structured scalars can also be indexed with an integer::
- >>> scalar = np.array([(1, 2., 3.)], dtype='i,f,f')[0]
+ >>> scalar = np.array([(1, 2., 3.)], dtype='i, f, f')[0]
>>> scalar[0]
1
>>> scalar[1] = 4
@@ -529,7 +538,7 @@ numpy's integer types. Structured scalars may be converted to a tuple by
calling :func:`ndarray.item`::
>>> scalar.item(), type(scalar.item())
- ((1, 2.0, 3.0), tuple)
+ ((1, 4.0, 3.0), <class 'tuple'>)
Viewing Structured Arrays Containing Objects
--------------------------------------------
@@ -573,24 +582,24 @@ structured scalars obtained from the array.
The simplest way to create a record array is with :func:`numpy.rec.array`::
- >>> recordarr = np.rec.array([(1,2.,'Hello'),(2,3.,"World")],
+ >>> recordarr = np.rec.array([(1, 2., 'Hello'), (2, 3., "World")],
... dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
>>> recordarr.bar
array([ 2., 3.], dtype=float32)
>>> recordarr[1:2]
- rec.array([(2, 3.0, 'World')],
+ rec.array([(2, 3., b'World')],
dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
>>> recordarr[1:2].foo
array([2], dtype=int32)
>>> recordarr.foo[1:2]
array([2], dtype=int32)
>>> recordarr[1].baz
- 'World'
+ b'World'
:func:`numpy.rec.array` can convert a wide variety of arguments into record
arrays, including structured arrays::
- >>> arr = array([(1,2.,'Hello'),(2,3.,"World")],
+ >>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
... dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = np.rec.array(arr)
@@ -599,11 +608,11 @@ creating record arrays, see :ref:`record array creation routines
<routines.array-creation.rec>`.
A record array representation of a structured array can be obtained using the
-appropriate :ref:`view`::
+appropriate `view <numpy-ndarray-view>`_::
- >>> arr = np.array([(1,2.,'Hello'),(2,3.,"World")],
+ >>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
... dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'a10')])
- >>> recordarr = arr.view(dtype=dtype((np.record, arr.dtype)),
+ >>> recordarr = arr.view(dtype=np.dtype((np.record, arr.dtype)),
... type=np.recarray)
For convenience, viewing an ndarray as type :class:`np.recarray` will
@@ -623,12 +632,12 @@ recordarr was not a structured type::
Record array fields accessed by index or by attribute are returned as a record
array if the field has a structured type but as a plain ndarray otherwise. ::
- >>> recordarr = np.rec.array([('Hello', (1,2)),("World", (3,4))],
+ >>> recordarr = np.rec.array([('Hello', (1, 2)), ("World", (3, 4))],
... dtype=[('foo', 'S6'),('bar', [('A', int), ('B', int)])])
>>> type(recordarr.foo)
- <type 'numpy.ndarray'>
+ <class 'numpy.ndarray'>
>>> type(recordarr.bar)
- <class 'numpy.core.records.recarray'>
+ <class 'numpy.recarray'>
Note that if a field has the same name as an ndarray attribute, the ndarray
attribute takes precedence. Such fields will be inaccessible by attribute but
diff --git a/numpy/dual.py b/numpy/dual.py
index 3a16a8ec5..651e845bb 100644
--- a/numpy/dual.py
+++ b/numpy/dual.py
@@ -51,14 +51,14 @@ _restore_dict = {}
def register_func(name, func):
if name not in __all__:
- raise ValueError("%s not a dual function." % name)
+ raise ValueError("{} not a dual function.".format(name))
f = sys._getframe(0).f_globals
_restore_dict[name] = f[name]
f[name] = func
def restore_func(name):
if name not in __all__:
- raise ValueError("%s not a dual function." % name)
+ raise ValueError("{} not a dual function.".format(name))
try:
val = _restore_dict[name]
except KeyError:
diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py
index 47223151f..110337f92 100755
--- a/numpy/f2py/f2py2e.py
+++ b/numpy/f2py/f2py2e.py
@@ -269,7 +269,8 @@ def scaninputline(inputline):
options["f2py_wrapper_output"] = l
elif f == 1:
try:
- open(l).close()
+ with open(l):
+ pass
files.append(l)
except IOError as detail:
errmess('IOError: %s. Skipping file "%s".\n' %
@@ -333,9 +334,8 @@ def callcrackfortran(files, options):
if options['signsfile'][-6:] == 'stdout':
sys.stdout.write(pyf)
else:
- f = open(options['signsfile'], 'w')
- f.write(pyf)
- f.close()
+ with open(options['signsfile'], 'w') as f:
+ f.write(pyf)
if options["coutput"] is None:
for mod in postlist:
mod["coutput"] = "%smodule.c" % mod["name"]
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 23d36b2c2..6769f1b1f 100644
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -1257,82 +1257,77 @@ def buildmodule(m, um):
fn = os.path.join(options['buildpath'], vrd['coutput'])
ret['csrc'] = fn
- f = open(fn, 'w')
- f.write(ar['modulebody'].replace('\t', 2 * ' '))
- f.close()
+ with open(fn, 'w') as f:
+ f.write(ar['modulebody'].replace('\t', 2 * ' '))
outmess('\tWrote C/API module "%s" to file "%s"\n' % (m['name'], fn))
if options['dorestdoc']:
fn = os.path.join(
options['buildpath'], vrd['modulename'] + 'module.rest')
- f = open(fn, 'w')
- f.write('.. -*- rest -*-\n')
- f.write('\n'.join(ar['restdoc']))
- f.close()
+ with open(fn, 'w') as f:
+ f.write('.. -*- rest -*-\n')
+ f.write('\n'.join(ar['restdoc']))
outmess('\tReST Documentation is saved to file "%s/%smodule.rest"\n' %
(options['buildpath'], vrd['modulename']))
if options['dolatexdoc']:
fn = os.path.join(
options['buildpath'], vrd['modulename'] + 'module.tex')
ret['ltx'] = fn
- f = open(fn, 'w')
- f.write(
- '%% This file is auto-generated with f2py (version:%s)\n' % (f2py_version))
- if 'shortlatex' not in options:
+ with open(fn, 'w') as f:
f.write(
- '\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n')
- f.write('\n'.join(ar['latexdoc']))
- if 'shortlatex' not in options:
- f.write('\\end{document}')
- f.close()
+ '%% This file is auto-generated with f2py (version:%s)\n' % (f2py_version))
+ if 'shortlatex' not in options:
+ f.write(
+ '\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n')
+ f.write('\n'.join(ar['latexdoc']))
+ if 'shortlatex' not in options:
+ f.write('\\end{document}')
outmess('\tDocumentation is saved to file "%s/%smodule.tex"\n' %
(options['buildpath'], vrd['modulename']))
if funcwrappers:
wn = os.path.join(options['buildpath'], vrd['f2py_wrapper_output'])
ret['fsrc'] = wn
- f = open(wn, 'w')
- f.write('C -*- fortran -*-\n')
- f.write(
- 'C This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
- f.write(
- 'C It contains Fortran 77 wrappers to fortran functions.\n')
- lines = []
- for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'):
- if l and l[0] == ' ':
- while len(l) >= 66:
- lines.append(l[:66] + '\n &')
- l = l[66:]
- lines.append(l + '\n')
- else:
- lines.append(l + '\n')
- lines = ''.join(lines).replace('\n &\n', '\n')
- f.write(lines)
- f.close()
+ with open(wn, 'w') as f:
+ f.write('C -*- fortran -*-\n')
+ f.write(
+ 'C This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
+ f.write(
+ 'C It contains Fortran 77 wrappers to fortran functions.\n')
+ lines = []
+ for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'):
+ if l and l[0] == ' ':
+ while len(l) >= 66:
+ lines.append(l[:66] + '\n &')
+ l = l[66:]
+ lines.append(l + '\n')
+ else:
+ lines.append(l + '\n')
+ lines = ''.join(lines).replace('\n &\n', '\n')
+ f.write(lines)
outmess('\tFortran 77 wrappers are saved to "%s"\n' % (wn))
if funcwrappers2:
wn = os.path.join(
options['buildpath'], '%s-f2pywrappers2.f90' % (vrd['modulename']))
ret['fsrc'] = wn
- f = open(wn, 'w')
- f.write('! -*- f90 -*-\n')
- f.write(
- '! This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
- f.write(
- '! It contains Fortran 90 wrappers to fortran functions.\n')
- lines = []
- for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'):
- if len(l) > 72 and l[0] == ' ':
- lines.append(l[:72] + '&\n &')
- l = l[72:]
- while len(l) > 66:
- lines.append(l[:66] + '&\n &')
- l = l[66:]
- lines.append(l + '\n')
- else:
- lines.append(l + '\n')
- lines = ''.join(lines).replace('\n &\n', '\n')
- f.write(lines)
- f.close()
+ with open(wn, 'w') as f:
+ f.write('! -*- f90 -*-\n')
+ f.write(
+ '! This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
+ f.write(
+ '! It contains Fortran 90 wrappers to fortran functions.\n')
+ lines = []
+ for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'):
+ if len(l) > 72 and l[0] == ' ':
+ lines.append(l[:72] + '&\n &')
+ l = l[72:]
+ while len(l) > 66:
+ lines.append(l[:66] + '&\n &')
+ l = l[66:]
+ lines.append(l + '\n')
+ else:
+ lines.append(l + '\n')
+ lines = ''.join(lines).replace('\n &\n', '\n')
+ f.write(lines)
outmess('\tFortran 90 wrappers are saved to "%s"\n' % (wn))
return ret
diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py
index 824ef7b0c..21c29ba5f 100644
--- a/numpy/f2py/tests/test_callback.py
+++ b/numpy/f2py/tests/test_callback.py
@@ -68,7 +68,7 @@ cf2py intent(out) a
@pytest.mark.slow
def test_docstring(self):
- expected = """
+ expected = textwrap.dedent("""\
a = t(fun,[fun_extra_args])
Wrapper for ``t``.
@@ -93,8 +93,8 @@ cf2py intent(out) a
def fun(): return a
Return objects:
a : int
- """
- assert_equal(self.module.t.__doc__, textwrap.dedent(expected).lstrip())
+ """)
+ assert_equal(self.module.t.__doc__, expected)
def check_function(self, name):
t = getattr(self.module, name)
diff --git a/numpy/f2py/tests/test_mixed.py b/numpy/f2py/tests/test_mixed.py
index 28268ecc0..0337538ff 100644
--- a/numpy/f2py/tests/test_mixed.py
+++ b/numpy/f2py/tests/test_mixed.py
@@ -25,7 +25,7 @@ class TestMixed(util.F2PyTest):
@pytest.mark.slow
def test_docstring(self):
- expected = """
+ expected = textwrap.dedent("""\
a = bar11()
Wrapper for ``bar11``.
@@ -33,6 +33,5 @@ class TestMixed(util.F2PyTest):
Returns
-------
a : int
- """
- assert_equal(self.module.bar11.__doc__,
- textwrap.dedent(expected).lstrip())
+ """)
+ assert_equal(self.module.bar11.__doc__, expected)
diff --git a/numpy/f2py/tests/util.py b/numpy/f2py/tests/util.py
index 5fa5dadd2..d20dc5908 100644
--- a/numpy/f2py/tests/util.py
+++ b/numpy/f2py/tests/util.py
@@ -180,27 +180,27 @@ def _get_compiler_status():
# XXX: this is really ugly. But I don't know how to invoke Distutils
# in a safer way...
- code = """
-import os
-import sys
-sys.path = %(syspath)s
-
-def configuration(parent_name='',top_path=None):
- global config
- from numpy.distutils.misc_util import Configuration
- config = Configuration('', parent_name, top_path)
- return config
-
-from numpy.distutils.core import setup
-setup(configuration=configuration)
-
-config_cmd = config.get_config_cmd()
-have_c = config_cmd.try_compile('void foo() {}')
-print('COMPILERS:%%d,%%d,%%d' %% (have_c,
- config.have_f77c(),
- config.have_f90c()))
-sys.exit(99)
-"""
+ code = textwrap.dedent("""\
+ import os
+ import sys
+ sys.path = %(syspath)s
+
+ def configuration(parent_name='',top_path=None):
+ global config
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ return config
+
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+
+ config_cmd = config.get_config_cmd()
+ have_c = config_cmd.try_compile('void foo() {}')
+ print('COMPILERS:%%d,%%d,%%d' %% (have_c,
+ config.have_f77c(),
+ config.have_f90c()))
+ sys.exit(99)
+ """)
code = code % dict(syspath=repr(sys.path))
with temppath(suffix='.py') as script:
@@ -259,21 +259,21 @@ def build_module_distutils(source_files, config_code, module_name, **kw):
# Build script
config_code = textwrap.dedent(config_code).replace("\n", "\n ")
- code = """\
-import os
-import sys
-sys.path = %(syspath)s
-
-def configuration(parent_name='',top_path=None):
- from numpy.distutils.misc_util import Configuration
- config = Configuration('', parent_name, top_path)
- %(config_code)s
- return config
-
-if __name__ == "__main__":
- from numpy.distutils.core import setup
- setup(configuration=configuration)
-""" % dict(config_code=config_code, syspath=repr(sys.path))
+ code = textwrap.dedent("""\
+ import os
+ import sys
+ sys.path = %(syspath)s
+
+ def configuration(parent_name='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ %(config_code)s
+ return config
+
+ if __name__ == "__main__":
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+ """) % dict(config_code=config_code, syspath=repr(sys.path))
script = os.path.join(d, get_temp_module_name() + '.py')
dst_sources.append(script)
diff --git a/numpy/fft/README.md b/numpy/fft/README.md
new file mode 100644
index 000000000..7040a2e9b
--- /dev/null
+++ b/numpy/fft/README.md
@@ -0,0 +1,53 @@
+PocketFFT
+---------
+
+This is a heavily modified implementation of FFTPack [1,2], with the following
+advantages:
+
+- strictly C99 compliant
+- more accurate twiddle factor computation
+- very fast plan generation
+- worst case complexity for transform sizes with large prime factors is
+ `N*log(N)`, because Bluestein's algorithm [3] is used for these cases.
+
+License
+-------
+
+3-clause BSD (see LICENSE.md)
+
+
+Some code details
+-----------------
+
+Twiddle factor computation:
+
+- making use of symmetries to reduce number of sin/cos evaluations
+- all angles are reduced to the range `[0; pi/4]` for higher accuracy
+- an adapted implementation of `sincospi()` is used, which actually computes
+ `sin(x)` and `(cos(x)-1)`.
+- if `n` sin/cos pairs are required, the adjusted `sincospi()` is only called
+ `2*sqrt(n)` times; the remaining values are obtained by evaluating the
+ angle addition theorems in a numerically accurate way.
+
+Parallel invocation:
+
+- Plans only contain read-only data; all temporary arrays are allocated and
+ deallocated during an individual FFT execution. This means that a single plan
+ can be used in several threads at the same time.
+
+Efficient codelets are available for the factors:
+
+- 2, 3, 4, 5, 7, 11 for complex-valued FFTs
+- 2, 3, 4, 5 for real-valued FFTs
+
+Larger prime factors are handled by somewhat less efficient, generic routines.
+
+For lengths with very large prime factors, Bluestein's algorithm is used, and
+instead of an FFT of length `n`, a convolution of length `n2 >= 2*n-1`
+is performed, where `n2` is chosen to be highly composite.
+
+
+[1] Swarztrauber, P. 1982, Vectorizing the Fast Fourier Transforms
+ (New York: Academic Press), 51
+[2] https://www.netlib.org/fftpack/
+[3] https://en.wikipedia.org/wiki/Chirp_Z-transform
diff --git a/numpy/fft/__init__.py b/numpy/fft/__init__.py
index 44243b483..64b35bc19 100644
--- a/numpy/fft/__init__.py
+++ b/numpy/fft/__init__.py
@@ -3,7 +3,7 @@ from __future__ import division, absolute_import, print_function
# To get sub-modules
from .info import __doc__
-from .fftpack import *
+from .pocketfft import *
from .helper import *
from numpy._pytesttester import PytestTester
diff --git a/numpy/fft/fftpack.c b/numpy/fft/fftpack.c
deleted file mode 100644
index 07fa2bf4c..000000000
--- a/numpy/fft/fftpack.c
+++ /dev/null
@@ -1,1536 +0,0 @@
-/*
- * fftpack.c : A set of FFT routines in C.
- * Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber (Version 4, 1985).
-*/
-#define NPY_NO_DEPRECATED_API NPY_API_VERSION
-
-#include <Python.h>
-#include <math.h>
-#include <stdio.h>
-#include <numpy/ndarraytypes.h>
-
-#define DOUBLE
-#ifdef DOUBLE
-#define Treal double
-#else
-#define Treal float
-#endif
-
-#define ref(u,a) u[a]
-
-/* Macros for accurate calculation of the twiddle factors. */
-#define TWOPI 6.283185307179586476925286766559005768391
-#define cos2pi(m, n) cos((TWOPI * (m)) / (n))
-#define sin2pi(m, n) sin((TWOPI * (m)) / (n))
-
-#define MAXFAC 13 /* maximum number of factors in factorization of n */
-#define NSPECIAL 4 /* number of factors for which we have special-case routines */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static void sincos2pi(int m, int n, Treal* si, Treal* co)
-/* Calculates sin(2pi * m/n) and cos(2pi * m/n). It is more accurate
- * than the naive calculation as the fraction m/n is reduced to [0, 1/8) first.
- * Due to the symmetry of sin(x) and cos(x) the values for all x can be
- * determined from the function values of the reduced argument in the first
- * octant.
- */
- {
- int n8, m8, octant;
- n8 = 8 * n;
- m8 = (8 * m) % n8;
- octant = m8 / n;
- m8 = m8 % n;
- switch(octant) {
- case 0:
- *co = cos2pi(m8, n8);
- *si = sin2pi(m8, n8);
- break;
- case 1:
- *co = sin2pi(n-m8, n8);
- *si = cos2pi(n-m8, n8);
- break;
- case 2:
- *co = -sin2pi(m8, n8);
- *si = cos2pi(m8, n8);
- break;
- case 3:
- *co = -cos2pi(n-m8, n8);
- *si = sin2pi(n-m8, n8);
- break;
- case 4:
- *co = -cos2pi(m8, n8);
- *si = -sin2pi(m8, n8);
- break;
- case 5:
- *co = -sin2pi(n-m8, n8);
- *si = -cos2pi(n-m8, n8);
- break;
- case 6:
- *co = sin2pi(m8, n8);
- *si = -cos2pi(m8, n8);
- break;
- case 7:
- *co = cos2pi(n-m8, n8);
- *si = -sin2pi(n-m8, n8);
- break;
- }
- }
-
-/* ----------------------------------------------------------------------
- passf2, passf3, passf4, passf5, passf. Complex FFT passes fwd and bwd.
------------------------------------------------------------------------ */
-
-static void passf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[], int isign)
- /* isign==+1 for backward transform */
- {
- int i, k, ah, ac;
- Treal ti2, tr2;
- if (ido <= 2) {
- for (k=0; k<l1; k++) {
- ah = k*ido;
- ac = 2*k*ido;
- ch[ah] = ref(cc,ac) + ref(cc,ac + ido);
- ch[ah + ido*l1] = ref(cc,ac) - ref(cc,ac + ido);
- ch[ah+1] = ref(cc,ac+1) + ref(cc,ac + ido + 1);
- ch[ah + ido*l1 + 1] = ref(cc,ac+1) - ref(cc,ac + ido + 1);
- }
- } else {
- for (k=0; k<l1; k++) {
- for (i=0; i<ido-1; i+=2) {
- ah = i + k*ido;
- ac = i + 2*k*ido;
- ch[ah] = ref(cc,ac) + ref(cc,ac + ido);
- tr2 = ref(cc,ac) - ref(cc,ac + ido);
- ch[ah+1] = ref(cc,ac+1) + ref(cc,ac + 1 + ido);
- ti2 = ref(cc,ac+1) - ref(cc,ac + 1 + ido);
- ch[ah+l1*ido+1] = wa1[i]*ti2 + isign*wa1[i+1]*tr2;
- ch[ah+l1*ido] = wa1[i]*tr2 - isign*wa1[i+1]*ti2;
- }
- }
- }
- } /* passf2 */
-
-
-static void passf3(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], int isign)
- /* isign==+1 for backward transform */
- {
- static const Treal taur = -0.5;
- static const Treal taui = 0.86602540378443864676;
- int i, k, ac, ah;
- Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
- if (ido == 2) {
- for (k=1; k<=l1; k++) {
- ac = (3*k - 2)*ido;
- tr2 = ref(cc,ac) + ref(cc,ac + ido);
- cr2 = ref(cc,ac - ido) + taur*tr2;
- ah = (k - 1)*ido;
- ch[ah] = ref(cc,ac - ido) + tr2;
-
- ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
- ci2 = ref(cc,ac - ido + 1) + taur*ti2;
- ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;
-
- cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
- ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
- ch[ah + l1*ido] = cr2 - ci3;
- ch[ah + 2*l1*ido] = cr2 + ci3;
- ch[ah + l1*ido + 1] = ci2 + cr3;
- ch[ah + 2*l1*ido + 1] = ci2 - cr3;
- }
- } else {
- for (k=1; k<=l1; k++) {
- for (i=0; i<ido-1; i+=2) {
- ac = i + (3*k - 2)*ido;
- tr2 = ref(cc,ac) + ref(cc,ac + ido);
- cr2 = ref(cc,ac - ido) + taur*tr2;
- ah = i + (k-1)*ido;
- ch[ah] = ref(cc,ac - ido) + tr2;
- ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
- ci2 = ref(cc,ac - ido + 1) + taur*ti2;
- ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;
- cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
- ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
- dr2 = cr2 - ci3;
- dr3 = cr2 + ci3;
- di2 = ci2 + cr3;
- di3 = ci2 - cr3;
- ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
- ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
- ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
- ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
- }
- }
- }
- } /* passf3 */
-
-
-static void passf4(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[], int isign)
- /* isign == -1 for forward transform and +1 for backward transform */
- {
- int i, k, ac, ah;
- Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
- if (ido == 2) {
- for (k=0; k<l1; k++) {
- ac = 4*k*ido + 1;
- ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
- ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
- tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
- ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
- tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
- tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
- ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
- tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
- ah = k*ido;
- ch[ah] = tr2 + tr3;
- ch[ah + 2*l1*ido] = tr2 - tr3;
- ch[ah + 1] = ti2 + ti3;
- ch[ah + 2*l1*ido + 1] = ti2 - ti3;
- ch[ah + l1*ido] = tr1 + isign*tr4;
- ch[ah + 3*l1*ido] = tr1 - isign*tr4;
- ch[ah + l1*ido + 1] = ti1 + isign*ti4;
- ch[ah + 3*l1*ido + 1] = ti1 - isign*ti4;
- }
- } else {
- for (k=0; k<l1; k++) {
- for (i=0; i<ido-1; i+=2) {
- ac = i + 1 + 4*k*ido;
- ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
- ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
- ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
- tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
- tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
- tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
- ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
- tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
- ah = i + k*ido;
- ch[ah] = tr2 + tr3;
- cr3 = tr2 - tr3;
- ch[ah + 1] = ti2 + ti3;
- ci3 = ti2 - ti3;
- cr2 = tr1 + isign*tr4;
- cr4 = tr1 - isign*tr4;
- ci2 = ti1 + isign*ti4;
- ci4 = ti1 - isign*ti4;
- ch[ah + l1*ido] = wa1[i]*cr2 - isign*wa1[i + 1]*ci2;
- ch[ah + l1*ido + 1] = wa1[i]*ci2 + isign*wa1[i + 1]*cr2;
- ch[ah + 2*l1*ido] = wa2[i]*cr3 - isign*wa2[i + 1]*ci3;
- ch[ah + 2*l1*ido + 1] = wa2[i]*ci3 + isign*wa2[i + 1]*cr3;
- ch[ah + 3*l1*ido] = wa3[i]*cr4 -isign*wa3[i + 1]*ci4;
- ch[ah + 3*l1*ido + 1] = wa3[i]*ci4 + isign*wa3[i + 1]*cr4;
- }
- }
- }
- } /* passf4 */
-
-
-static void passf5(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[], int isign)
- /* isign == -1 for forward transform and +1 for backward transform */
- {
- static const Treal tr11 = 0.3090169943749474241;
- static const Treal ti11 = 0.95105651629515357212;
- static const Treal tr12 = -0.8090169943749474241;
- static const Treal ti12 = 0.58778525229247312917;
- int i, k, ac, ah;
- Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
- ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
- if (ido == 2) {
- for (k = 1; k <= l1; ++k) {
- ac = (5*k - 4)*ido + 1;
- ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
- ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
- ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
- ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
- tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
- tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
- tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
- tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
- ah = (k - 1)*ido;
- ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
- ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
- cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;
- ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
- cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;
- ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
- cr5 = isign*(ti11*tr5 + ti12*tr4);
- ci5 = isign*(ti11*ti5 + ti12*ti4);
- cr4 = isign*(ti12*tr5 - ti11*tr4);
- ci4 = isign*(ti12*ti5 - ti11*ti4);
- ch[ah + l1*ido] = cr2 - ci5;
- ch[ah + 4*l1*ido] = cr2 + ci5;
- ch[ah + l1*ido + 1] = ci2 + cr5;
- ch[ah + 2*l1*ido + 1] = ci3 + cr4;
- ch[ah + 2*l1*ido] = cr3 - ci4;
- ch[ah + 3*l1*ido] = cr3 + ci4;
- ch[ah + 3*l1*ido + 1] = ci3 - cr4;
- ch[ah + 4*l1*ido + 1] = ci2 - cr5;
- }
- } else {
- for (k=1; k<=l1; k++) {
- for (i=0; i<ido-1; i+=2) {
- ac = i + 1 + (k*5 - 4)*ido;
- ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
- ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
- ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
- ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
- tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
- tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
- tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
- tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
- ah = i + (k - 1)*ido;
- ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
- ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
- cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;
-
- ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
- cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;
-
- ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
- cr5 = isign*(ti11*tr5 + ti12*tr4);
- ci5 = isign*(ti11*ti5 + ti12*ti4);
- cr4 = isign*(ti12*tr5 - ti11*tr4);
- ci4 = isign*(ti12*ti5 - ti11*ti4);
- dr3 = cr3 - ci4;
- dr4 = cr3 + ci4;
- di3 = ci3 + cr4;
- di4 = ci3 - cr4;
- dr5 = cr2 + ci5;
- dr2 = cr2 - ci5;
- di5 = ci2 - cr5;
- di2 = ci2 + cr5;
- ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
- ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
- ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
- ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
- ch[ah + 3*l1*ido] = wa3[i]*dr4 - isign*wa3[i+1]*di4;
- ch[ah + 3*l1*ido + 1] = wa3[i]*di4 + isign*wa3[i+1]*dr4;
- ch[ah + 4*l1*ido] = wa4[i]*dr5 - isign*wa4[i+1]*di5;
- ch[ah + 4*l1*ido + 1] = wa4[i]*di5 + isign*wa4[i+1]*dr5;
- }
- }
- }
- } /* passf5 */
-
-
-static void passf(int *nac, int ido, int ip, int l1, int idl1,
- Treal cc[], Treal ch[],
- const Treal wa[], int isign)
- /* isign is -1 for forward transform and +1 for backward transform */
- {
- int idij, idlj, idot, ipph, i, j, k, l, jc, lc, ik, idj, idl, inc,idp;
- Treal wai, war;
-
- idot = ido / 2;
- /* nt = ip*idl1;*/
- ipph = (ip + 1) / 2;
- idp = ip*ido;
- if (ido >= l1) {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- for (i=0; i<ido; i++) {
- ch[i + (k + j*l1)*ido] =
- ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*ip)*ido);
- ch[i + (k + jc*l1)*ido] =
- ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*ip)*ido);
- }
- }
- }
- for (k=0; k<l1; k++)
- for (i=0; i<ido; i++)
- ch[i + k*ido] = ref(cc,i + k*ip*ido);
- } else {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (i=0; i<ido; i++) {
- for (k=0; k<l1; k++) {
- ch[i + (k + j*l1)*ido] = ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*
- ip)*ido);
- ch[i + (k + jc*l1)*ido] = ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*
- ip)*ido);
- }
- }
- }
- for (i=0; i<ido; i++)
- for (k=0; k<l1; k++)
- ch[i + k*ido] = ref(cc,i + k*ip*ido);
- }
-
- idl = 2 - ido;
- inc = 0;
- for (l=1; l<ipph; l++) {
- lc = ip - l;
- idl += ido;
- for (ik=0; ik<idl1; ik++) {
- cc[ik + l*idl1] = ch[ik] + wa[idl - 2]*ch[ik + idl1];
- cc[ik + lc*idl1] = isign*wa[idl-1]*ch[ik + (ip-1)*idl1];
- }
- idlj = idl;
- inc += ido;
- for (j=2; j<ipph; j++) {
- jc = ip - j;
- idlj += inc;
- if (idlj > idp) idlj -= idp;
- war = wa[idlj - 2];
- wai = wa[idlj-1];
- for (ik=0; ik<idl1; ik++) {
- cc[ik + l*idl1] += war*ch[ik + j*idl1];
- cc[ik + lc*idl1] += isign*wai*ch[ik + jc*idl1];
- }
- }
- }
- for (j=1; j<ipph; j++)
- for (ik=0; ik<idl1; ik++)
- ch[ik] += ch[ik + j*idl1];
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (ik=1; ik<idl1; ik+=2) {
- ch[ik - 1 + j*idl1] = cc[ik - 1 + j*idl1] - cc[ik + jc*idl1];
- ch[ik - 1 + jc*idl1] = cc[ik - 1 + j*idl1] + cc[ik + jc*idl1];
- ch[ik + j*idl1] = cc[ik + j*idl1] + cc[ik - 1 + jc*idl1];
- ch[ik + jc*idl1] = cc[ik + j*idl1] - cc[ik - 1 + jc*idl1];
- }
- }
- *nac = 1;
- if (ido == 2) return;
- *nac = 0;
- for (ik=0; ik<idl1; ik++)
- cc[ik] = ch[ik];
- for (j=1; j<ip; j++) {
- for (k=0; k<l1; k++) {
- cc[(k + j*l1)*ido + 0] = ch[(k + j*l1)*ido + 0];
- cc[(k + j*l1)*ido + 1] = ch[(k + j*l1)*ido + 1];
- }
- }
- if (idot <= l1) {
- idij = 0;
- for (j=1; j<ip; j++) {
- idij += 2;
- for (i=3; i<ido; i+=2) {
- idij += 2;
- for (k=0; k<l1; k++) {
- cc[i - 1 + (k + j*l1)*ido] =
- wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
- isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
- cc[i + (k + j*l1)*ido] =
- wa[idij - 2]*ch[i + (k + j*l1)*ido] +
- isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- } else {
- idj = 2 - ido;
- for (j=1; j<ip; j++) {
- idj += ido;
- for (k = 0; k < l1; k++) {
- idij = idj;
- for (i=3; i<ido; i+=2) {
- idij += 2;
- cc[i - 1 + (k + j*l1)*ido] =
- wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
- isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
- cc[i + (k + j*l1)*ido] =
- wa[idij - 2]*ch[i + (k + j*l1)*ido] +
- isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- }
- } /* passf */
-
-
- /* ----------------------------------------------------------------------
-radf2,radb2, radf3,radb3, radf4,radb4, radf5,radb5, radfg,radbg.
-Treal FFT passes fwd and bwd.
----------------------------------------------------------------------- */
-
-static void radf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
- {
- int i, k, ic;
- Treal ti2, tr2;
- for (k=0; k<l1; k++) {
- ch[2*k*ido] =
- ref(cc,k*ido) + ref(cc,(k + l1)*ido);
- ch[(2*k+1)*ido + ido-1] =
- ref(cc,k*ido) - ref(cc,(k + l1)*ido);
- }
- if (ido < 2) return;
- if (ido != 2) {
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- tr2 = wa1[i - 2]*ref(cc, i-1 + (k + l1)*ido) + wa1[i - 1]*ref(cc, i + (k + l1)*ido);
- ti2 = wa1[i - 2]*ref(cc, i + (k + l1)*ido) - wa1[i - 1]*ref(cc, i-1 + (k + l1)*ido);
- ch[i + 2*k*ido] = ref(cc,i + k*ido) + ti2;
- ch[ic + (2*k+1)*ido] = ti2 - ref(cc,i + k*ido);
- ch[i - 1 + 2*k*ido] = ref(cc,i - 1 + k*ido) + tr2;
- ch[ic - 1 + (2*k+1)*ido] = ref(cc,i - 1 + k*ido) - tr2;
- }
- }
- if (ido % 2 == 1) return;
- }
- for (k=0; k<l1; k++) {
- ch[(2*k+1)*ido] = -ref(cc,ido-1 + (k + l1)*ido);
- ch[ido-1 + 2*k*ido] = ref(cc,ido-1 + k*ido);
- }
- } /* radf2 */
-
-
-static void radb2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
- {
- int i, k, ic;
- Treal ti2, tr2;
- for (k=0; k<l1; k++) {
- ch[k*ido] =
- ref(cc,2*k*ido) + ref(cc,ido-1 + (2*k+1)*ido);
- ch[(k + l1)*ido] =
- ref(cc,2*k*ido) - ref(cc,ido-1 + (2*k+1)*ido);
- }
- if (ido < 2) return;
- if (ido != 2) {
- for (k = 0; k < l1; ++k) {
- for (i = 2; i < ido; i += 2) {
- ic = ido - i;
- ch[i-1 + k*ido] =
- ref(cc,i-1 + 2*k*ido) + ref(cc,ic-1 + (2*k+1)*ido);
- tr2 = ref(cc,i-1 + 2*k*ido) - ref(cc,ic-1 + (2*k+1)*ido);
- ch[i + k*ido] =
- ref(cc,i + 2*k*ido) - ref(cc,ic + (2*k+1)*ido);
- ti2 = ref(cc,i + (2*k)*ido) + ref(cc,ic + (2*k+1)*ido);
- ch[i-1 + (k + l1)*ido] =
- wa1[i - 2]*tr2 - wa1[i - 1]*ti2;
- ch[i + (k + l1)*ido] =
- wa1[i - 2]*ti2 + wa1[i - 1]*tr2;
- }
- }
- if (ido % 2 == 1) return;
- }
- for (k = 0; k < l1; k++) {
- ch[ido-1 + k*ido] = 2*ref(cc,ido-1 + 2*k*ido);
- ch[ido-1 + (k + l1)*ido] = -2*ref(cc,(2*k+1)*ido);
- }
- } /* radb2 */
-
-
-static void radf3(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[])
- {
- static const Treal taur = -0.5;
- static const Treal taui = 0.86602540378443864676;
- int i, k, ic;
- Treal ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
- for (k=0; k<l1; k++) {
- cr2 = ref(cc,(k + l1)*ido) + ref(cc,(k + 2*l1)*ido);
- ch[3*k*ido] = ref(cc,k*ido) + cr2;
- ch[(3*k+2)*ido] = taui*(ref(cc,(k + l1*2)*ido) - ref(cc,(k + l1)*ido));
- ch[ido-1 + (3*k + 1)*ido] = ref(cc,k*ido) + taur*cr2;
- }
- if (ido == 1) return;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) +
- wa1[i - 1]*ref(cc,i + (k + l1)*ido);
- di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
- dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + l1*2)*ido) + wa2[i - 1]*ref(cc,i + (k + l1*2)*ido);
- di3 = wa2[i - 2]*ref(cc,i + (k + l1*2)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + l1*2)*ido);
- cr2 = dr2 + dr3;
- ci2 = di2 + di3;
- ch[i - 1 + 3*k*ido] = ref(cc,i - 1 + k*ido) + cr2;
- ch[i + 3*k*ido] = ref(cc,i + k*ido) + ci2;
- tr2 = ref(cc,i - 1 + k*ido) + taur*cr2;
- ti2 = ref(cc,i + k*ido) + taur*ci2;
- tr3 = taui*(di2 - di3);
- ti3 = taui*(dr3 - dr2);
- ch[i - 1 + (3*k + 2)*ido] = tr2 + tr3;
- ch[ic - 1 + (3*k + 1)*ido] = tr2 - tr3;
- ch[i + (3*k + 2)*ido] = ti2 + ti3;
- ch[ic + (3*k + 1)*ido] = ti3 - ti2;
- }
- }
- } /* radf3 */
-
-
-static void radb3(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[])
- {
- static const Treal taur = -0.5;
- static const Treal taui = 0.86602540378443864676;
- int i, k, ic;
- Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
- for (k=0; k<l1; k++) {
- tr2 = 2*ref(cc,ido-1 + (3*k + 1)*ido);
- cr2 = ref(cc,3*k*ido) + taur*tr2;
- ch[k*ido] = ref(cc,3*k*ido) + tr2;
- ci3 = 2*taui*ref(cc,(3*k + 2)*ido);
- ch[(k + l1)*ido] = cr2 - ci3;
- ch[(k + 2*l1)*ido] = cr2 + ci3;
- }
- if (ido == 1) return;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- tr2 = ref(cc,i - 1 + (3*k + 2)*ido) + ref(cc,ic - 1 + (3*k + 1)*ido);
- cr2 = ref(cc,i - 1 + 3*k*ido) + taur*tr2;
- ch[i - 1 + k*ido] = ref(cc,i - 1 + 3*k*ido) + tr2;
- ti2 = ref(cc,i + (3*k + 2)*ido) - ref(cc,ic + (3*k + 1)*ido);
- ci2 = ref(cc,i + 3*k*ido) + taur*ti2;
- ch[i + k*ido] = ref(cc,i + 3*k*ido) + ti2;
- cr3 = taui*(ref(cc,i - 1 + (3*k + 2)*ido) - ref(cc,ic - 1 + (3*k + 1)*ido));
- ci3 = taui*(ref(cc,i + (3*k + 2)*ido) + ref(cc,ic + (3*k + 1)*ido));
- dr2 = cr2 - ci3;
- dr3 = cr2 + ci3;
- di2 = ci2 + cr3;
- di3 = ci2 - cr3;
- ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
- ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
- ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
- ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
- }
- }
- } /* radb3 */
-
-
-static void radf4(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[])
- {
- static const Treal hsqt2 = 0.70710678118654752440;
- int i, k, ic;
- Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
- for (k=0; k<l1; k++) {
- tr1 = ref(cc,(k + l1)*ido) + ref(cc,(k + 3*l1)*ido);
- tr2 = ref(cc,k*ido) + ref(cc,(k + 2*l1)*ido);
- ch[4*k*ido] = tr1 + tr2;
- ch[ido-1 + (4*k + 3)*ido] = tr2 - tr1;
- ch[ido-1 + (4*k + 1)*ido] = ref(cc,k*ido) - ref(cc,(k + 2*l1)*ido);
- ch[(4*k + 2)*ido] = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + l1)*ido);
- }
- if (ido < 2) return;
- if (ido != 2) {
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i += 2) {
- ic = ido - i;
- cr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
- ci2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
- cr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*
- ido);
- ci3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*
- ido);
- cr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*
- ido);
- ci4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*
- ido);
- tr1 = cr2 + cr4;
- tr4 = cr4 - cr2;
- ti1 = ci2 + ci4;
- ti4 = ci2 - ci4;
- ti2 = ref(cc,i + k*ido) + ci3;
- ti3 = ref(cc,i + k*ido) - ci3;
- tr2 = ref(cc,i - 1 + k*ido) + cr3;
- tr3 = ref(cc,i - 1 + k*ido) - cr3;
- ch[i - 1 + 4*k*ido] = tr1 + tr2;
- ch[ic - 1 + (4*k + 3)*ido] = tr2 - tr1;
- ch[i + 4*k*ido] = ti1 + ti2;
- ch[ic + (4*k + 3)*ido] = ti1 - ti2;
- ch[i - 1 + (4*k + 2)*ido] = ti4 + tr3;
- ch[ic - 1 + (4*k + 1)*ido] = tr3 - ti4;
- ch[i + (4*k + 2)*ido] = tr4 + ti3;
- ch[ic + (4*k + 1)*ido] = tr4 - ti3;
- }
- }
- if (ido % 2 == 1) return;
- }
- for (k=0; k<l1; k++) {
- ti1 = -hsqt2*(ref(cc,ido-1 + (k + l1)*ido) + ref(cc,ido-1 + (k + 3*l1)*ido));
- tr1 = hsqt2*(ref(cc,ido-1 + (k + l1)*ido) - ref(cc,ido-1 + (k + 3*l1)*ido));
- ch[ido-1 + 4*k*ido] = tr1 + ref(cc,ido-1 + k*ido);
- ch[ido-1 + (4*k + 2)*ido] = ref(cc,ido-1 + k*ido) - tr1;
- ch[(4*k + 1)*ido] = ti1 - ref(cc,ido-1 + (k + 2*l1)*ido);
- ch[(4*k + 3)*ido] = ti1 + ref(cc,ido-1 + (k + 2*l1)*ido);
- }
- } /* radf4 */
-
-
-static void radb4(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[])
- {
- static const Treal sqrt2 = 1.41421356237309504880;
- int i, k, ic;
- Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
- for (k = 0; k < l1; k++) {
- tr1 = ref(cc,4*k*ido) - ref(cc,ido-1 + (4*k + 3)*ido);
- tr2 = ref(cc,4*k*ido) + ref(cc,ido-1 + (4*k + 3)*ido);
- tr3 = ref(cc,ido-1 + (4*k + 1)*ido) + ref(cc,ido-1 + (4*k + 1)*ido);
- tr4 = ref(cc,(4*k + 2)*ido) + ref(cc,(4*k + 2)*ido);
- ch[k*ido] = tr2 + tr3;
- ch[(k + l1)*ido] = tr1 - tr4;
- ch[(k + 2*l1)*ido] = tr2 - tr3;
- ch[(k + 3*l1)*ido] = tr1 + tr4;
- }
- if (ido < 2) return;
- if (ido != 2) {
- for (k = 0; k < l1; ++k) {
- for (i = 2; i < ido; i += 2) {
- ic = ido - i;
- ti1 = ref(cc,i + 4*k*ido) + ref(cc,ic + (4*k + 3)*ido);
- ti2 = ref(cc,i + 4*k*ido) - ref(cc,ic + (4*k + 3)*ido);
- ti3 = ref(cc,i + (4*k + 2)*ido) - ref(cc,ic + (4*k + 1)*ido);
- tr4 = ref(cc,i + (4*k + 2)*ido) + ref(cc,ic + (4*k + 1)*ido);
- tr1 = ref(cc,i - 1 + 4*k*ido) - ref(cc,ic - 1 + (4*k + 3)*ido);
- tr2 = ref(cc,i - 1 + 4*k*ido) + ref(cc,ic - 1 + (4*k + 3)*ido);
- ti4 = ref(cc,i - 1 + (4*k + 2)*ido) - ref(cc,ic - 1 + (4*k + 1)*ido);
- tr3 = ref(cc,i - 1 + (4*k + 2)*ido) + ref(cc,ic - 1 + (4*k + 1)*ido);
- ch[i - 1 + k*ido] = tr2 + tr3;
- cr3 = tr2 - tr3;
- ch[i + k*ido] = ti2 + ti3;
- ci3 = ti2 - ti3;
- cr2 = tr1 - tr4;
- cr4 = tr1 + tr4;
- ci2 = ti1 + ti4;
- ci4 = ti1 - ti4;
- ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*cr2 - wa1[i - 1]*ci2;
- ch[i + (k + l1)*ido] = wa1[i - 2]*ci2 + wa1[i - 1]*cr2;
- ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*cr3 - wa2[i - 1]*ci3;
- ch[i + (k + 2*l1)*ido] = wa2[i - 2]*ci3 + wa2[i - 1]*cr3;
- ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*cr4 - wa3[i - 1]*ci4;
- ch[i + (k + 3*l1)*ido] = wa3[i - 2]*ci4 + wa3[i - 1]*cr4;
- }
- }
- if (ido % 2 == 1) return;
- }
- for (k = 0; k < l1; k++) {
- ti1 = ref(cc,(4*k + 1)*ido) + ref(cc,(4*k + 3)*ido);
- ti2 = ref(cc,(4*k + 3)*ido) - ref(cc,(4*k + 1)*ido);
- tr1 = ref(cc,ido-1 + 4*k*ido) - ref(cc,ido-1 + (4*k + 2)*ido);
- tr2 = ref(cc,ido-1 + 4*k*ido) + ref(cc,ido-1 + (4*k + 2)*ido);
- ch[ido-1 + k*ido] = tr2 + tr2;
- ch[ido-1 + (k + l1)*ido] = sqrt2*(tr1 - ti1);
- ch[ido-1 + (k + 2*l1)*ido] = ti2 + ti2;
- ch[ido-1 + (k + 3*l1)*ido] = -sqrt2*(tr1 + ti1);
- }
- } /* radb4 */
-
-
-static void radf5(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
- {
- static const Treal tr11 = 0.3090169943749474241;
- static const Treal ti11 = 0.95105651629515357212;
- static const Treal tr12 = -0.8090169943749474241;
- static const Treal ti12 = 0.58778525229247312917;
- int i, k, ic;
- Treal ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5,
- cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
- for (k = 0; k < l1; k++) {
- cr2 = ref(cc,(k + 4*l1)*ido) + ref(cc,(k + l1)*ido);
- ci5 = ref(cc,(k + 4*l1)*ido) - ref(cc,(k + l1)*ido);
- cr3 = ref(cc,(k + 3*l1)*ido) + ref(cc,(k + 2*l1)*ido);
- ci4 = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + 2*l1)*ido);
- ch[5*k*ido] = ref(cc,k*ido) + cr2 + cr3;
- ch[ido-1 + (5*k + 1)*ido] = ref(cc,k*ido) + tr11*cr2 + tr12*cr3;
- ch[(5*k + 2)*ido] = ti11*ci5 + ti12*ci4;
- ch[ido-1 + (5*k + 3)*ido] = ref(cc,k*ido) + tr12*cr2 + tr11*cr3;
- ch[(5*k + 4)*ido] = ti12*ci5 - ti11*ci4;
- }
- if (ido == 1) return;
- for (k = 0; k < l1; ++k) {
- for (i = 2; i < ido; i += 2) {
- ic = ido - i;
- dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
- di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
- dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*ido);
- di3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*ido);
- dr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*ido);
- di4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*ido);
- dr5 = wa4[i - 2]*ref(cc,i - 1 + (k + 4*l1)*ido) + wa4[i - 1]*ref(cc,i + (k + 4*l1)*ido);
- di5 = wa4[i - 2]*ref(cc,i + (k + 4*l1)*ido) - wa4[i - 1]*ref(cc,i - 1 + (k + 4*l1)*ido);
- cr2 = dr2 + dr5;
- ci5 = dr5 - dr2;
- cr5 = di2 - di5;
- ci2 = di2 + di5;
- cr3 = dr3 + dr4;
- ci4 = dr4 - dr3;
- cr4 = di3 - di4;
- ci3 = di3 + di4;
- ch[i - 1 + 5*k*ido] = ref(cc,i - 1 + k*ido) + cr2 + cr3;
- ch[i + 5*k*ido] = ref(cc,i + k*ido) + ci2 + ci3;
- tr2 = ref(cc,i - 1 + k*ido) + tr11*cr2 + tr12*cr3;
- ti2 = ref(cc,i + k*ido) + tr11*ci2 + tr12*ci3;
- tr3 = ref(cc,i - 1 + k*ido) + tr12*cr2 + tr11*cr3;
- ti3 = ref(cc,i + k*ido) + tr12*ci2 + tr11*ci3;
- tr5 = ti11*cr5 + ti12*cr4;
- ti5 = ti11*ci5 + ti12*ci4;
- tr4 = ti12*cr5 - ti11*cr4;
- ti4 = ti12*ci5 - ti11*ci4;
- ch[i - 1 + (5*k + 2)*ido] = tr2 + tr5;
- ch[ic - 1 + (5*k + 1)*ido] = tr2 - tr5;
- ch[i + (5*k + 2)*ido] = ti2 + ti5;
- ch[ic + (5*k + 1)*ido] = ti5 - ti2;
- ch[i - 1 + (5*k + 4)*ido] = tr3 + tr4;
- ch[ic - 1 + (5*k + 3)*ido] = tr3 - tr4;
- ch[i + (5*k + 4)*ido] = ti3 + ti4;
- ch[ic + (5*k + 3)*ido] = ti4 - ti3;
- }
- }
- } /* radf5 */
-
-
-static void radb5(int ido, int l1, const Treal cc[], Treal ch[],
- const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
- {
- static const Treal tr11 = 0.3090169943749474241;
- static const Treal ti11 = 0.95105651629515357212;
- static const Treal tr12 = -0.8090169943749474241;
- static const Treal ti12 = 0.58778525229247312917;
- int i, k, ic;
- Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
- ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
- for (k = 0; k < l1; k++) {
- ti5 = 2*ref(cc,(5*k + 2)*ido);
- ti4 = 2*ref(cc,(5*k + 4)*ido);
- tr2 = 2*ref(cc,ido-1 + (5*k + 1)*ido);
- tr3 = 2*ref(cc,ido-1 + (5*k + 3)*ido);
- ch[k*ido] = ref(cc,5*k*ido) + tr2 + tr3;
- cr2 = ref(cc,5*k*ido) + tr11*tr2 + tr12*tr3;
- cr3 = ref(cc,5*k*ido) + tr12*tr2 + tr11*tr3;
- ci5 = ti11*ti5 + ti12*ti4;
- ci4 = ti12*ti5 - ti11*ti4;
- ch[(k + l1)*ido] = cr2 - ci5;
- ch[(k + 2*l1)*ido] = cr3 - ci4;
- ch[(k + 3*l1)*ido] = cr3 + ci4;
- ch[(k + 4*l1)*ido] = cr2 + ci5;
- }
- if (ido == 1) return;
- for (k = 0; k < l1; ++k) {
- for (i = 2; i < ido; i += 2) {
- ic = ido - i;
- ti5 = ref(cc,i + (5*k + 2)*ido) + ref(cc,ic + (5*k + 1)*ido);
- ti2 = ref(cc,i + (5*k + 2)*ido) - ref(cc,ic + (5*k + 1)*ido);
- ti4 = ref(cc,i + (5*k + 4)*ido) + ref(cc,ic + (5*k + 3)*ido);
- ti3 = ref(cc,i + (5*k + 4)*ido) - ref(cc,ic + (5*k + 3)*ido);
- tr5 = ref(cc,i - 1 + (5*k + 2)*ido) - ref(cc,ic - 1 + (5*k + 1)*ido);
- tr2 = ref(cc,i - 1 + (5*k + 2)*ido) + ref(cc,ic - 1 + (5*k + 1)*ido);
- tr4 = ref(cc,i - 1 + (5*k + 4)*ido) - ref(cc,ic - 1 + (5*k + 3)*ido);
- tr3 = ref(cc,i - 1 + (5*k + 4)*ido) + ref(cc,ic - 1 + (5*k + 3)*ido);
- ch[i - 1 + k*ido] = ref(cc,i - 1 + 5*k*ido) + tr2 + tr3;
- ch[i + k*ido] = ref(cc,i + 5*k*ido) + ti2 + ti3;
- cr2 = ref(cc,i - 1 + 5*k*ido) + tr11*tr2 + tr12*tr3;
-
- ci2 = ref(cc,i + 5*k*ido) + tr11*ti2 + tr12*ti3;
- cr3 = ref(cc,i - 1 + 5*k*ido) + tr12*tr2 + tr11*tr3;
-
- ci3 = ref(cc,i + 5*k*ido) + tr12*ti2 + tr11*ti3;
- cr5 = ti11*tr5 + ti12*tr4;
- ci5 = ti11*ti5 + ti12*ti4;
- cr4 = ti12*tr5 - ti11*tr4;
- ci4 = ti12*ti5 - ti11*ti4;
- dr3 = cr3 - ci4;
- dr4 = cr3 + ci4;
- di3 = ci3 + cr4;
- di4 = ci3 - cr4;
- dr5 = cr2 + ci5;
- dr2 = cr2 - ci5;
- di5 = ci2 - cr5;
- di2 = ci2 + cr5;
- ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
- ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
- ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
- ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
- ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*dr4 - wa3[i - 1]*di4;
- ch[i + (k + 3*l1)*ido] = wa3[i - 2]*di4 + wa3[i - 1]*dr4;
- ch[i - 1 + (k + 4*l1)*ido] = wa4[i - 2]*dr5 - wa4[i - 1]*di5;
- ch[i + (k + 4*l1)*ido] = wa4[i - 2]*di5 + wa4[i - 1]*dr5;
- }
- }
- } /* radb5 */
-
-
-static void radfg(int ido, int ip, int l1, int idl1,
- Treal cc[], Treal ch[], const Treal wa[])
- {
- int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is, nbd;
- Treal dc2, ai1, ai2, ar1, ar2, ds2, dcp, dsp, ar1h, ar2h;
- sincos2pi(1, ip, &dsp, &dcp);
- ipph = (ip + 1) / 2;
- nbd = (ido - 1) / 2;
- if (ido != 1) {
- for (ik=0; ik<idl1; ik++) ch[ik] = cc[ik];
- for (j=1; j<ip; j++)
- for (k=0; k<l1; k++)
- ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido];
- if (nbd <= l1) {
- is = -ido;
- for (j=1; j<ip; j++) {
- is += ido;
- idij = is-1;
- for (i=2; i<ido; i+=2) {
- idij += 2;
- for (k=0; k<l1; k++) {
- ch[i - 1 + (k + j*l1)*ido] =
- wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
- ch[i + (k + j*l1)*ido] =
- wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- } else {
- is = -ido;
- for (j=1; j<ip; j++) {
- is += ido;
- for (k=0; k<l1; k++) {
- idij = is-1;
- for (i=2; i<ido; i+=2) {
- idij += 2;
- ch[i - 1 + (k + j*l1)*ido] =
- wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
- ch[i + (k + j*l1)*ido] =
- wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- }
- if (nbd >= l1) {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- cc[i - 1 + (k + j*l1)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
- cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
- cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
- cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- } else {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (i=2; i<ido; i+=2) {
- for (k=0; k<l1; k++) {
- cc[i - 1 + (k + j*l1)*ido] =
- ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
- cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
- cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
- cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- }
- } else { /* now ido == 1 */
- for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
- }
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido] + ch[(k + jc*l1)*ido];
- cc[(k + jc*l1)*ido] = ch[(k + jc*l1)*ido] - ch[(k + j*l1)*ido];
- }
- }
-
- ar1 = 1;
- ai1 = 0;
- for (l=1; l<ipph; l++) {
- lc = ip - l;
- ar1h = dcp*ar1 - dsp*ai1;
- ai1 = dcp*ai1 + dsp*ar1;
- ar1 = ar1h;
- for (ik=0; ik<idl1; ik++) {
- ch[ik + l*idl1] = cc[ik] + ar1*cc[ik + idl1];
- ch[ik + lc*idl1] = ai1*cc[ik + (ip-1)*idl1];
- }
- dc2 = ar1;
- ds2 = ai1;
- ar2 = ar1;
- ai2 = ai1;
- for (j=2; j<ipph; j++) {
- jc = ip - j;
- ar2h = dc2*ar2 - ds2*ai2;
- ai2 = dc2*ai2 + ds2*ar2;
- ar2 = ar2h;
- for (ik=0; ik<idl1; ik++) {
- ch[ik + l*idl1] += ar2*cc[ik + j*idl1];
- ch[ik + lc*idl1] += ai2*cc[ik + jc*idl1];
- }
- }
- }
-
- for (j=1; j<ipph; j++)
- for (ik=0; ik<idl1; ik++)
- ch[ik] += cc[ik + j*idl1];
-
- if (ido >= l1) {
- for (k=0; k<l1; k++) {
- for (i=0; i<ido; i++) {
- ref(cc,i + k*ip*ido) = ch[i + k*ido];
- }
- }
- } else {
- for (i=0; i<ido; i++) {
- for (k=0; k<l1; k++) {
- ref(cc,i + k*ip*ido) = ch[i + k*ido];
- }
- }
- }
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- j2 = 2*j;
- for (k=0; k<l1; k++) {
- ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) =
- ch[(k + j*l1)*ido];
- ref(cc,(j2 + k*ip)*ido) =
- ch[(k + jc*l1)*ido];
- }
- }
- if (ido == 1) return;
- if (nbd >= l1) {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- j2 = 2*j;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
- ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
- ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
- ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
- }
- }
- }
- } else {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- j2 = 2*j;
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- for (k=0; k<l1; k++) {
- ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
- ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
- ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
- ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
- }
- }
- }
- }
- } /* radfg */
-
-
-static void radbg(int ido, int ip, int l1, int idl1,
- Treal cc[], Treal ch[], const Treal wa[])
- {
- int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is;
- Treal dc2, ai1, ai2, ar1, ar2, ds2;
- int nbd;
- Treal dcp, dsp, ar1h, ar2h;
- sincos2pi(1, ip, &dsp, &dcp);
- nbd = (ido - 1) / 2;
- ipph = (ip + 1) / 2;
- if (ido >= l1) {
- for (k=0; k<l1; k++) {
- for (i=0; i<ido; i++) {
- ch[i + k*ido] = ref(cc,i + k*ip*ido);
- }
- }
- } else {
- for (i=0; i<ido; i++) {
- for (k=0; k<l1; k++) {
- ch[i + k*ido] = ref(cc,i + k*ip*ido);
- }
- }
- }
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- j2 = 2*j;
- for (k=0; k<l1; k++) {
- ch[(k + j*l1)*ido] = ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) + ref(cc,ido-1 + (j2 - 1 + k*ip)*
- ido);
- ch[(k + jc*l1)*ido] = ref(cc,(j2 + k*ip)*ido) + ref(cc,(j2 + k*ip)*ido);
- }
- }
-
- if (ido != 1) {
- if (nbd >= l1) {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
- ic - 1 + (2*j - 1 + k*ip)*ido);
- ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
- ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
- ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
- + (2*j - 1 + k*ip)*ido);
- ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
- + (2*j - 1 + k*ip)*ido);
- }
- }
- }
- } else {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (i=2; i<ido; i+=2) {
- ic = ido - i;
- for (k=0; k<l1; k++) {
- ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
- ic - 1 + (2*j - 1 + k*ip)*ido);
- ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
- ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
- ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
- + (2*j - 1 + k*ip)*ido);
- ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
- + (2*j - 1 + k*ip)*ido);
- }
- }
- }
- }
- }
-
- ar1 = 1;
- ai1 = 0;
- for (l=1; l<ipph; l++) {
- lc = ip - l;
- ar1h = dcp*ar1 - dsp*ai1;
- ai1 = dcp*ai1 + dsp*ar1;
- ar1 = ar1h;
- for (ik=0; ik<idl1; ik++) {
- cc[ik + l*idl1] = ch[ik] + ar1*ch[ik + idl1];
- cc[ik + lc*idl1] = ai1*ch[ik + (ip-1)*idl1];
- }
- dc2 = ar1;
- ds2 = ai1;
- ar2 = ar1;
- ai2 = ai1;
- for (j=2; j<ipph; j++) {
- jc = ip - j;
- ar2h = dc2*ar2 - ds2*ai2;
- ai2 = dc2*ai2 + ds2*ar2;
- ar2 = ar2h;
- for (ik=0; ik<idl1; ik++) {
- cc[ik + l*idl1] += ar2*ch[ik + j*idl1];
- cc[ik + lc*idl1] += ai2*ch[ik + jc*idl1];
- }
- }
- }
- for (j=1; j<ipph; j++) {
- for (ik=0; ik<idl1; ik++) {
- ch[ik] += ch[ik + j*idl1];
- }
- }
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido] - cc[(k + jc*l1)*ido];
- ch[(k + jc*l1)*ido] = cc[(k + j*l1)*ido] + cc[(k + jc*l1)*ido];
- }
- }
-
- if (ido == 1) return;
- if (nbd >= l1) {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (k=0; k<l1; k++) {
- for (i=2; i<ido; i+=2) {
- ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
- ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] + cc[i + (k + jc*l1)*ido];
- ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
- ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
- }
- }
- }
- } else {
- for (j=1; j<ipph; j++) {
- jc = ip - j;
- for (i=2; i<ido; i+=2) {
- for (k=0; k<l1; k++) {
- ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
- ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j *l1)*ido] + cc[i + (k + jc*l1)*ido];
- ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
- ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
- }
- }
- }
- }
- for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
- for (j=1; j<ip; j++)
- for (k=0; k<l1; k++)
- cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido];
- if (nbd <= l1) {
- is = -ido;
- for (j=1; j<ip; j++) {
- is += ido;
- idij = is-1;
- for (i=2; i<ido; i+=2) {
- idij += 2;
- for (k=0; k<l1; k++) {
- cc[i - 1 + (k + j*l1)*ido] = wa[idij - 1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
- ch[i + (k + j*l1)*ido];
- cc[i + (k + j*l1)*ido] = wa[idij - 1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- } else {
- is = -ido;
- for (j=1; j<ip; j++) {
- is += ido;
- for (k=0; k<l1; k++) {
- idij = is - 1;
- for (i=2; i<ido; i+=2) {
- idij += 2;
- cc[i - 1 + (k + j*l1)*ido] = wa[idij-1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
- ch[i + (k + j*l1)*ido];
- cc[i + (k + j*l1)*ido] = wa[idij-1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
- }
- }
- }
- }
- } /* radbg */
-
- /* ------------------------------------------------------------
-cfftf1, npy_cfftf, npy_cfftb, cffti1, npy_cffti. Complex FFTs.
---------------------------------------------------------------- */
-
-static void cfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2], int isign)
- {
- int idot, i;
- int k1, l1, l2;
- int na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
- Treal *cinput, *coutput;
- nf = ifac[1];
- na = 0;
- l1 = 1;
- iw = 0;
- for (k1=2; k1<=nf+1; k1++) {
- ip = ifac[k1];
- l2 = ip*l1;
- ido = n / l2;
- idot = ido + ido;
- idl1 = idot*l1;
- if (na) {
- cinput = ch;
- coutput = c;
- } else {
- cinput = c;
- coutput = ch;
- }
- switch (ip) {
- case 4:
- ix2 = iw + idot;
- ix3 = ix2 + idot;
- passf4(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], isign);
- na = !na;
- break;
- case 2:
- passf2(idot, l1, cinput, coutput, &wa[iw], isign);
- na = !na;
- break;
- case 3:
- ix2 = iw + idot;
- passf3(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], isign);
- na = !na;
- break;
- case 5:
- ix2 = iw + idot;
- ix3 = ix2 + idot;
- ix4 = ix3 + idot;
- passf5(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
- na = !na;
- break;
- default:
- passf(&nac, idot, ip, l1, idl1, cinput, coutput, &wa[iw], isign);
- if (nac != 0) na = !na;
- }
- l1 = l2;
- iw += (ip - 1)*idot;
- }
- if (na == 0) return;
- for (i=0; i<2*n; i++) c[i] = ch[i];
- } /* cfftf1 */
-
-
-NPY_VISIBILITY_HIDDEN void npy_cfftf(int n, Treal c[], Treal wsave[])
- {
- int iw1, iw2;
- if (n == 1) return;
- iw1 = 2*n;
- iw2 = iw1 + 2*n;
- cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), -1);
- } /* npy_cfftf */
-
-
-NPY_VISIBILITY_HIDDEN void npy_cfftb(int n, Treal c[], Treal wsave[])
- {
- int iw1, iw2;
- if (n == 1) return;
- iw1 = 2*n;
- iw2 = iw1 + 2*n;
- cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), +1);
- } /* npy_cfftb */
-
-
-static void factorize(int n, int ifac[MAXFAC+2], const int ntryh[NSPECIAL])
- /* Factorize n in factors in ntryh and rest. On exit,
-ifac[0] contains n and ifac[1] contains number of factors,
-the factors start from ifac[2]. */
- {
- int ntry=3, i, j=0, ib, nf=0, nl=n, nq, nr;
-startloop:
- if (j < NSPECIAL)
- ntry = ntryh[j];
- else
- ntry+= 2;
- j++;
- do {
- nq = nl / ntry;
- nr = nl - ntry*nq;
- if (nr != 0) goto startloop;
- nf++;
- ifac[nf + 1] = ntry;
- nl = nq;
- if (ntry == 2 && nf != 1) {
- for (i=2; i<=nf; i++) {
- ib = nf - i + 2;
- ifac[ib + 1] = ifac[ib];
- }
- ifac[2] = 2;
- }
- } while (nl != 1);
- ifac[0] = n;
- ifac[1] = nf;
- }
-
-
-static void cffti1(int n, Treal wa[], int ifac[MAXFAC+2])
- {
- int fi, idot, i, j;
- int i1, k1, l1, l2;
- int ld, ii, nf, ip;
- int ido, ipm;
-
- static const int ntryh[NSPECIAL] = {
- 3,4,2,5 }; /* Do not change the order of these. */
-
- factorize(n,ifac,ntryh);
- nf = ifac[1];
- i = 1;
- l1 = 1;
- for (k1=1; k1<=nf; k1++) {
- ip = ifac[k1+1];
- ld = 0;
- l2 = l1*ip;
- ido = n / l2;
- idot = ido + ido + 2;
- ipm = ip - 1;
- for (j=1; j<=ipm; j++) {
- i1 = i;
- wa[i-1] = 1;
- wa[i] = 0;
- ld += l1;
- fi = 0;
- for (ii=4; ii<=idot; ii+=2) {
- i+= 2;
- fi+= 1;
- sincos2pi(fi*ld, n, wa+i, wa+i-1);
- }
- if (ip > 5) {
- wa[i1-1] = wa[i-1];
- wa[i1] = wa[i];
- }
- }
- l1 = l2;
- }
- } /* cffti1 */
-
-
-NPY_VISIBILITY_HIDDEN void npy_cffti(int n, Treal wsave[])
- {
- int iw1, iw2;
- if (n == 1) return;
- iw1 = 2*n;
- iw2 = iw1 + 2*n;
- cffti1(n, wsave+iw1, (int*)(wsave+iw2));
- } /* npy_cffti */
-
- /* -------------------------------------------------------------------
-rfftf1, rfftb1, npy_rfftf, npy_rfftb, rffti1, npy_rffti. Treal FFTs.
----------------------------------------------------------------------- */
-
-static void rfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
- {
- int i;
- int k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
- Treal *cinput, *coutput;
- nf = ifac[1];
- na = 1;
- l2 = n;
- iw = n-1;
- for (k1 = 1; k1 <= nf; ++k1) {
- kh = nf - k1;
- ip = ifac[kh + 2];
- l1 = l2 / ip;
- ido = n / l2;
- idl1 = ido*l1;
- iw -= (ip - 1)*ido;
- na = !na;
- if (na) {
- cinput = ch;
- coutput = c;
- } else {
- cinput = c;
- coutput = ch;
- }
- switch (ip) {
- case 4:
- ix2 = iw + ido;
- ix3 = ix2 + ido;
- radf4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
- break;
- case 2:
- radf2(ido, l1, cinput, coutput, &wa[iw]);
- break;
- case 3:
- ix2 = iw + ido;
- radf3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
- break;
- case 5:
- ix2 = iw + ido;
- ix3 = ix2 + ido;
- ix4 = ix3 + ido;
- radf5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
- break;
- default:
- if (ido == 1)
- na = !na;
- if (na == 0) {
- radfg(ido, ip, l1, idl1, c, ch, &wa[iw]);
- na = 1;
- } else {
- radfg(ido, ip, l1, idl1, ch, c, &wa[iw]);
- na = 0;
- }
- }
- l2 = l1;
- }
- if (na == 1) return;
- for (i = 0; i < n; i++) c[i] = ch[i];
- } /* rfftf1 */
-
-
-static void rfftb1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
- {
- int i;
- int k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
- Treal *cinput, *coutput;
- nf = ifac[1];
- na = 0;
- l1 = 1;
- iw = 0;
- for (k1=1; k1<=nf; k1++) {
- ip = ifac[k1 + 1];
- l2 = ip*l1;
- ido = n / l2;
- idl1 = ido*l1;
- if (na) {
- cinput = ch;
- coutput = c;
- } else {
- cinput = c;
- coutput = ch;
- }
- switch (ip) {
- case 4:
- ix2 = iw + ido;
- ix3 = ix2 + ido;
- radb4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
- na = !na;
- break;
- case 2:
- radb2(ido, l1, cinput, coutput, &wa[iw]);
- na = !na;
- break;
- case 3:
- ix2 = iw + ido;
- radb3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
- na = !na;
- break;
- case 5:
- ix2 = iw + ido;
- ix3 = ix2 + ido;
- ix4 = ix3 + ido;
- radb5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
- na = !na;
- break;
- default:
- radbg(ido, ip, l1, idl1, cinput, coutput, &wa[iw]);
- if (ido == 1) na = !na;
- }
- l1 = l2;
- iw += (ip - 1)*ido;
- }
- if (na == 0) return;
- for (i=0; i<n; i++) c[i] = ch[i];
- } /* rfftb1 */
-
-
-NPY_VISIBILITY_HIDDEN void npy_rfftf(int n, Treal r[], Treal wsave[])
- {
- if (n == 1) return;
- rfftf1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
- } /* npy_rfftf */
-
-
-NPY_VISIBILITY_HIDDEN void npy_rfftb(int n, Treal r[], Treal wsave[])
- {
- if (n == 1) return;
- rfftb1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
- } /* npy_rfftb */
-
-
-static void rffti1(int n, Treal wa[], int ifac[MAXFAC+2])
- {
- int fi, i, j;
- int k1, l1, l2;
- int ld, ii, nf, ip, is;
- int ido, ipm, nfm1;
- static const int ntryh[NSPECIAL] = {
- 4,2,3,5 }; /* Do not change the order of these. */
- factorize(n,ifac,ntryh);
- nf = ifac[1];
- is = 0;
- nfm1 = nf - 1;
- l1 = 1;
- if (nfm1 == 0) return;
- for (k1 = 1; k1 <= nfm1; k1++) {
- ip = ifac[k1 + 1];
- ld = 0;
- l2 = l1*ip;
- ido = n / l2;
- ipm = ip - 1;
- for (j = 1; j <= ipm; ++j) {
- ld += l1;
- i = is;
- fi = 0;
- for (ii = 3; ii <= ido; ii += 2) {
- i += 2;
- fi += 1;
- sincos2pi(fi*ld, n, wa+i-1, wa+i-2);
- }
- is += ido;
- }
- l1 = l2;
- }
- } /* rffti1 */
-
-
-NPY_VISIBILITY_HIDDEN void npy_rffti(int n, Treal wsave[])
- {
- if (n == 1) return;
- rffti1(n, wsave+n, (int*)(wsave+2*n));
- } /* npy_rffti */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/numpy/fft/fftpack.h b/numpy/fft/fftpack.h
deleted file mode 100644
index 5e8f4631c..000000000
--- a/numpy/fft/fftpack.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of tela the Tensor Language.
- * Copyright (c) 1994-1995 Pekka Janhunen
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DOUBLE
-
-#ifdef DOUBLE
-#define Treal double
-#else
-#define Treal float
-#endif
-
-extern NPY_VISIBILITY_HIDDEN void npy_cfftf(int N, Treal data[], const Treal wrk[]);
-extern NPY_VISIBILITY_HIDDEN void npy_cfftb(int N, Treal data[], const Treal wrk[]);
-extern NPY_VISIBILITY_HIDDEN void npy_cffti(int N, Treal wrk[]);
-
-extern NPY_VISIBILITY_HIDDEN void npy_rfftf(int N, Treal data[], const Treal wrk[]);
-extern NPY_VISIBILITY_HIDDEN void npy_rfftb(int N, Treal data[], const Treal wrk[]);
-extern NPY_VISIBILITY_HIDDEN void npy_rffti(int N, Treal wrk[]);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/numpy/fft/fftpack_litemodule.c b/numpy/fft/fftpack_litemodule.c
deleted file mode 100644
index bd6cfc120..000000000
--- a/numpy/fft/fftpack_litemodule.c
+++ /dev/null
@@ -1,366 +0,0 @@
-#define NPY_NO_DEPRECATED_API NPY_API_VERSION
-
-#include "Python.h"
-#include "numpy/arrayobject.h"
-#include "fftpack.h"
-
-static PyObject *ErrorObject;
-
-static const char fftpack_cfftf__doc__[] = "";
-
-static PyObject *
-fftpack_cfftf(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyObject *op1, *op2;
- PyArrayObject *data;
- PyArray_Descr *descr;
- double *wsave, *dptr;
- npy_intp nsave;
- int npts, nrepeats, i;
-
- if(!PyArg_ParseTuple(args, "OO:cfftf", &op1, &op2)) {
- return NULL;
- }
- data = (PyArrayObject *)PyArray_CopyFromObject(op1,
- NPY_CDOUBLE, 1, 0);
- if (data == NULL) {
- return NULL;
- }
- descr = PyArray_DescrFromType(NPY_DOUBLE);
- if (PyArray_AsCArray(&op2, (void *)&wsave, &nsave, 1, descr) == -1) {
- goto fail;
- }
- if (data == NULL) {
- goto fail;
- }
-
- npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
- if (nsave != npts*4 + 15) {
- PyErr_SetString(ErrorObject, "invalid work array for fft size");
- goto fail;
- }
-
- nrepeats = PyArray_SIZE(data)/npts;
- dptr = (double *)PyArray_DATA(data);
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- for (i = 0; i < nrepeats; i++) {
- npy_cfftf(npts, dptr, wsave);
- dptr += npts*2;
- }
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
- PyArray_Free(op2, (char *)wsave);
- return (PyObject *)data;
-
-fail:
- PyArray_Free(op2, (char *)wsave);
- Py_DECREF(data);
- return NULL;
-}
-
-static const char fftpack_cfftb__doc__[] = "";
-
-static PyObject *
-fftpack_cfftb(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyObject *op1, *op2;
- PyArrayObject *data;
- PyArray_Descr *descr;
- double *wsave, *dptr;
- npy_intp nsave;
- int npts, nrepeats, i;
-
- if(!PyArg_ParseTuple(args, "OO:cfftb", &op1, &op2)) {
- return NULL;
- }
- data = (PyArrayObject *)PyArray_CopyFromObject(op1,
- NPY_CDOUBLE, 1, 0);
- if (data == NULL) {
- return NULL;
- }
- descr = PyArray_DescrFromType(NPY_DOUBLE);
- if (PyArray_AsCArray(&op2, (void *)&wsave, &nsave, 1, descr) == -1) {
- goto fail;
- }
- if (data == NULL) {
- goto fail;
- }
-
- npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
- if (nsave != npts*4 + 15) {
- PyErr_SetString(ErrorObject, "invalid work array for fft size");
- goto fail;
- }
-
- nrepeats = PyArray_SIZE(data)/npts;
- dptr = (double *)PyArray_DATA(data);
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- for (i = 0; i < nrepeats; i++) {
- npy_cfftb(npts, dptr, wsave);
- dptr += npts*2;
- }
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
- PyArray_Free(op2, (char *)wsave);
- return (PyObject *)data;
-
-fail:
- PyArray_Free(op2, (char *)wsave);
- Py_DECREF(data);
- return NULL;
-}
-
-static const char fftpack_cffti__doc__[] = "";
-
-static PyObject *
-fftpack_cffti(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyArrayObject *op;
- npy_intp dim;
- long n;
-
- if (!PyArg_ParseTuple(args, "l:cffti", &n)) {
- return NULL;
- }
- /*Magic size needed by npy_cffti*/
- dim = 4*n + 15;
- /*Create a 1 dimensional array of dimensions of type double*/
- op = (PyArrayObject *)PyArray_SimpleNew(1, &dim, NPY_DOUBLE);
- if (op == NULL) {
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- npy_cffti(n, (double *)PyArray_DATA((PyArrayObject*)op));
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
-
- return (PyObject *)op;
-}
-
-static const char fftpack_rfftf__doc__[] = "";
-
-static PyObject *
-fftpack_rfftf(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyObject *op1, *op2;
- PyArrayObject *data, *ret;
- PyArray_Descr *descr;
- double *wsave = NULL, *dptr, *rptr;
- npy_intp nsave;
- int npts, nrepeats, i, rstep;
-
- if(!PyArg_ParseTuple(args, "OO:rfftf", &op1, &op2)) {
- return NULL;
- }
- data = (PyArrayObject *)PyArray_ContiguousFromObject(op1,
- NPY_DOUBLE, 1, 0);
- if (data == NULL) {
- return NULL;
- }
- /* FIXME, direct access changing contents of data->dimensions */
- npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
- PyArray_DIMS(data)[PyArray_NDIM(data) - 1] = npts/2 + 1;
- ret = (PyArrayObject *)PyArray_Zeros(PyArray_NDIM(data),
- PyArray_DIMS(data), PyArray_DescrFromType(NPY_CDOUBLE), 0);
- if (ret == NULL) {
- goto fail;
- }
- PyArray_DIMS(data)[PyArray_NDIM(data) - 1] = npts;
- rstep = PyArray_DIM(ret, PyArray_NDIM(ret) - 1)*2;
-
- descr = PyArray_DescrFromType(NPY_DOUBLE);
- if (PyArray_AsCArray(&op2, (void *)&wsave, &nsave, 1, descr) == -1) {
- goto fail;
- }
- if (data == NULL || ret == NULL) {
- goto fail;
- }
- if (nsave != npts*2+15) {
- PyErr_SetString(ErrorObject, "invalid work array for fft size");
- goto fail;
- }
-
- nrepeats = PyArray_SIZE(data)/npts;
- rptr = (double *)PyArray_DATA(ret);
- dptr = (double *)PyArray_DATA(data);
-
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- for (i = 0; i < nrepeats; i++) {
- memcpy((char *)(rptr+1), dptr, npts*sizeof(double));
- npy_rfftf(npts, rptr+1, wsave);
- rptr[0] = rptr[1];
- rptr[1] = 0.0;
- rptr += rstep;
- dptr += npts;
- }
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
- PyArray_Free(op2, (char *)wsave);
- Py_DECREF(data);
- return (PyObject *)ret;
-
-fail:
- PyArray_Free(op2, (char *)wsave);
- Py_XDECREF(data);
- Py_XDECREF(ret);
- return NULL;
-}
-
-static const char fftpack_rfftb__doc__[] = "";
-
-static PyObject *
-fftpack_rfftb(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyObject *op1, *op2;
- PyArrayObject *data, *ret;
- PyArray_Descr *descr;
- double *wsave, *dptr, *rptr;
- npy_intp nsave;
- int npts, nrepeats, i;
-
- if(!PyArg_ParseTuple(args, "OO:rfftb", &op1, &op2)) {
- return NULL;
- }
- data = (PyArrayObject *)PyArray_ContiguousFromObject(op1,
- NPY_CDOUBLE, 1, 0);
- if (data == NULL) {
- return NULL;
- }
- npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
- ret = (PyArrayObject *)PyArray_Zeros(PyArray_NDIM(data), PyArray_DIMS(data),
- PyArray_DescrFromType(NPY_DOUBLE), 0);
-
- descr = PyArray_DescrFromType(NPY_DOUBLE);
- if (PyArray_AsCArray(&op2, (void *)&wsave, &nsave, 1, descr) == -1) {
- goto fail;
- }
- if (data == NULL || ret == NULL) {
- goto fail;
- }
- if (nsave != npts*2 + 15) {
- PyErr_SetString(ErrorObject, "invalid work array for fft size");
- goto fail;
- }
-
- nrepeats = PyArray_SIZE(ret)/npts;
- rptr = (double *)PyArray_DATA(ret);
- dptr = (double *)PyArray_DATA(data);
-
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- for (i = 0; i < nrepeats; i++) {
- memcpy((char *)(rptr + 1), (dptr + 2), (npts - 1)*sizeof(double));
- rptr[0] = dptr[0];
- npy_rfftb(npts, rptr, wsave);
- rptr += npts;
- dptr += npts*2;
- }
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
- PyArray_Free(op2, (char *)wsave);
- Py_DECREF(data);
- return (PyObject *)ret;
-
-fail:
- PyArray_Free(op2, (char *)wsave);
- Py_XDECREF(data);
- Py_XDECREF(ret);
- return NULL;
-}
-
-static const char fftpack_rffti__doc__[] = "";
-
-static PyObject *
-fftpack_rffti(PyObject *NPY_UNUSED(self), PyObject *args)
-{
- PyArrayObject *op;
- npy_intp dim;
- long n;
-
- if (!PyArg_ParseTuple(args, "l:rffti", &n)) {
- return NULL;
- }
- /*Magic size needed by npy_rffti*/
- dim = 2*n + 15;
- /*Create a 1 dimensional array of dimensions of type double*/
- op = (PyArrayObject *)PyArray_SimpleNew(1, &dim, NPY_DOUBLE);
- if (op == NULL) {
- return NULL;
- }
- Py_BEGIN_ALLOW_THREADS;
- NPY_SIGINT_ON;
- npy_rffti(n, (double *)PyArray_DATA((PyArrayObject*)op));
- NPY_SIGINT_OFF;
- Py_END_ALLOW_THREADS;
-
- return (PyObject *)op;
-}
-
-
-/* List of methods defined in the module */
-
-static struct PyMethodDef fftpack_methods[] = {
- {"cfftf", fftpack_cfftf, 1, fftpack_cfftf__doc__},
- {"cfftb", fftpack_cfftb, 1, fftpack_cfftb__doc__},
- {"cffti", fftpack_cffti, 1, fftpack_cffti__doc__},
- {"rfftf", fftpack_rfftf, 1, fftpack_rfftf__doc__},
- {"rfftb", fftpack_rfftb, 1, fftpack_rfftb__doc__},
- {"rffti", fftpack_rffti, 1, fftpack_rffti__doc__},
- {NULL, NULL, 0, NULL} /* sentinel */
-};
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "fftpack_lite",
- NULL,
- -1,
- fftpack_methods,
- NULL,
- NULL,
- NULL,
- NULL
-};
-#endif
-
-/* Initialization function for the module */
-#if PY_MAJOR_VERSION >= 3
-#define RETVAL(x) x
-PyMODINIT_FUNC PyInit_fftpack_lite(void)
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC
-initfftpack_lite(void)
-#endif
-{
- PyObject *m,*d;
-#if PY_MAJOR_VERSION >= 3
- m = PyModule_Create(&moduledef);
-#else
- static const char fftpack_module_documentation[] = "";
-
- m = Py_InitModule4("fftpack_lite", fftpack_methods,
- fftpack_module_documentation,
- (PyObject*)NULL,PYTHON_API_VERSION);
-#endif
- if (m == NULL) {
- return RETVAL(NULL);
- }
-
- /* Import the array object */
- import_array();
-
- /* Add some symbolic constants to the module */
- d = PyModule_GetDict(m);
- ErrorObject = PyErr_NewException("fftpack.error", NULL, NULL);
- PyDict_SetItemString(d, "error", ErrorObject);
-
- /* XXXX Add constants here */
-
- return RETVAL(m);
-}
diff --git a/numpy/fft/helper.py b/numpy/fft/helper.py
index 864768df5..a920a4ac0 100644
--- a/numpy/fft/helper.py
+++ b/numpy/fft/helper.py
@@ -4,11 +4,6 @@ Discrete Fourier Transforms - helper.py
"""
from __future__ import division, absolute_import, print_function
-import collections
-try:
- import threading
-except ImportError:
- import dummy_threading as threading
from numpy.compat import integer_types
from numpy.core import integer, empty, arange, asarray, roll
from numpy.core.overrides import array_function_dispatch, set_module
@@ -52,7 +47,7 @@ def fftshift(x, axes=None):
--------
>>> freqs = np.fft.fftfreq(10, 0.1)
>>> freqs
- array([ 0., 1., 2., 3., 4., -5., -4., -3., -2., -1.])
+ array([ 0., 1., 2., ..., -3., -2., -1.])
>>> np.fft.fftshift(freqs)
array([-5., -4., -3., -2., -1., 0., 1., 2., 3., 4.])
@@ -162,7 +157,7 @@ def fftfreq(n, d=1.0):
>>> timestep = 0.1
>>> freq = np.fft.fftfreq(n, d=timestep)
>>> freq
- array([ 0. , 1.25, 2.5 , 3.75, -5. , -3.75, -2.5 , -1.25])
+ array([ 0. , 1.25, 2.5 , ..., -3.75, -2.5 , -1.25])
"""
if not isinstance(n, integer_types):
@@ -215,7 +210,7 @@ def rfftfreq(n, d=1.0):
>>> sample_rate = 100
>>> freq = np.fft.fftfreq(n, d=1./sample_rate)
>>> freq
- array([ 0., 10., 20., 30., 40., -50., -40., -30., -20., -10.])
+ array([ 0., 10., 20., ..., -30., -20., -10.])
>>> freq = np.fft.rfftfreq(n, d=1./sample_rate)
>>> freq
array([ 0., 10., 20., 30., 40., 50.])
@@ -227,99 +222,3 @@ def rfftfreq(n, d=1.0):
N = n//2 + 1
results = arange(0, N, dtype=int)
return results * val
-
-
-class _FFTCache(object):
- """
- Cache for the FFT twiddle factors as an LRU (least recently used) cache.
-
- Parameters
- ----------
- max_size_in_mb : int
- Maximum memory usage of the cache before items are being evicted.
- max_item_count : int
- Maximum item count of the cache before items are being evicted.
-
- Notes
- -----
- Items will be evicted if either limit has been reached upon getting and
- setting. The maximum memory usages is not strictly the given
- ``max_size_in_mb`` but rather
- ``max(max_size_in_mb, 1.5 * size_of_largest_item)``. Thus the cache will
- never be completely cleared - at least one item will remain and a single
- large item can cause the cache to retain several smaller items even if the
- given maximum cache size has been exceeded.
- """
- def __init__(self, max_size_in_mb, max_item_count):
- self._max_size_in_bytes = max_size_in_mb * 1024 ** 2
- self._max_item_count = max_item_count
- self._dict = collections.OrderedDict()
- self._lock = threading.Lock()
-
- def put_twiddle_factors(self, n, factors):
- """
- Store twiddle factors for an FFT of length n in the cache.
-
- Putting multiple twiddle factors for a certain n will store it multiple
- times.
-
- Parameters
- ----------
- n : int
- Data length for the FFT.
- factors : ndarray
- The actual twiddle values.
- """
- with self._lock:
- # Pop + later add to move it to the end for LRU behavior.
- # Internally everything is stored in a dictionary whose values are
- # lists.
- try:
- value = self._dict.pop(n)
- except KeyError:
- value = []
- value.append(factors)
- self._dict[n] = value
- self._prune_cache()
-
- def pop_twiddle_factors(self, n):
- """
- Pop twiddle factors for an FFT of length n from the cache.
-
- Will return None if the requested twiddle factors are not available in
- the cache.
-
- Parameters
- ----------
- n : int
- Data length for the FFT.
-
- Returns
- -------
- out : ndarray or None
- The retrieved twiddle factors if available, else None.
- """
- with self._lock:
- if n not in self._dict or not self._dict[n]:
- return None
- # Pop + later add to move it to the end for LRU behavior.
- all_values = self._dict.pop(n)
- value = all_values.pop()
- # Only put pack if there are still some arrays left in the list.
- if all_values:
- self._dict[n] = all_values
- return value
-
- def _prune_cache(self):
- # Always keep at least one item.
- while len(self._dict) > 1 and (
- len(self._dict) > self._max_item_count or self._check_size()):
- self._dict.popitem(last=False)
-
- def _check_size(self):
- item_sizes = [sum(_j.nbytes for _j in _i)
- for _i in self._dict.values() if _i]
- if not item_sizes:
- return False
- max_size = max(self._max_size_in_bytes, 1.5 * max(item_sizes))
- return sum(item_sizes) > max_size
diff --git a/numpy/fft/pocketfft.c b/numpy/fft/pocketfft.c
new file mode 100644
index 000000000..9d1218e6b
--- /dev/null
+++ b/numpy/fft/pocketfft.c
@@ -0,0 +1,2406 @@
+/*
+ * This file is part of pocketfft.
+ * Licensed under a 3-clause BSD style license - see LICENSE.md
+ */
+
+/*
+ * Main implementation file.
+ *
+ * Copyright (C) 2004-2018 Max-Planck-Society
+ * \author Martin Reinecke
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "npy_config.h"
+#define restrict NPY_RESTRICT
+
+#define RALLOC(type,num) \
+ ((type *)malloc((num)*sizeof(type)))
+#define DEALLOC(ptr) \
+ do { free(ptr); (ptr)=NULL; } while(0)
+
+#define SWAP(a,b,type) \
+ do { type tmp_=(a); (a)=(b); (b)=tmp_; } while(0)
+
+#ifdef __GNUC__
+#define NOINLINE __attribute__((noinline))
+#define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+#else
+#define NOINLINE
+#define WARN_UNUSED_RESULT
+#endif
+
+struct cfft_plan_i;
+typedef struct cfft_plan_i * cfft_plan;
+struct rfft_plan_i;
+typedef struct rfft_plan_i * rfft_plan;
+
+// adapted from https://stackoverflow.com/questions/42792939/
+// CAUTION: this function only works for arguments in the range [-0.25; 0.25]!
+static void my_sincosm1pi (double a, double *restrict res)
+ {
+ double s = a * a;
+ /* Approximate cos(pi*x)-1 for x in [-0.25,0.25] */
+ double r = -1.0369917389758117e-4;
+ r = fma (r, s, 1.9294935641298806e-3);
+ r = fma (r, s, -2.5806887942825395e-2);
+ r = fma (r, s, 2.3533063028328211e-1);
+ r = fma (r, s, -1.3352627688538006e+0);
+ r = fma (r, s, 4.0587121264167623e+0);
+ r = fma (r, s, -4.9348022005446790e+0);
+ double c = r*s;
+ /* Approximate sin(pi*x) for x in [-0.25,0.25] */
+ r = 4.6151442520157035e-4;
+ r = fma (r, s, -7.3700183130883555e-3);
+ r = fma (r, s, 8.2145868949323936e-2);
+ r = fma (r, s, -5.9926452893214921e-1);
+ r = fma (r, s, 2.5501640398732688e+0);
+ r = fma (r, s, -5.1677127800499516e+0);
+ s = s * a;
+ r = r * s;
+ s = fma (a, 3.1415926535897931e+0, r);
+ res[0] = c;
+ res[1] = s;
+ }
+
+NOINLINE static void calc_first_octant(size_t den, double * restrict res)
+ {
+ size_t n = (den+4)>>3;
+ if (n==0) return;
+ res[0]=1.; res[1]=0.;
+ if (n==1) return;
+ size_t l1=(size_t)sqrt(n);
+ for (size_t i=1; i<l1; ++i)
+ my_sincosm1pi((2.*i)/den,&res[2*i]);
+ size_t start=l1;
+ while(start<n)
+ {
+ double cs[2];
+ my_sincosm1pi((2.*start)/den,cs);
+ res[2*start] = cs[0]+1.;
+ res[2*start+1] = cs[1];
+ size_t end = l1;
+ if (start+end>n) end = n-start;
+ for (size_t i=1; i<end; ++i)
+ {
+ double csx[2]={res[2*i], res[2*i+1]};
+ res[2*(start+i)] = ((cs[0]*csx[0] - cs[1]*csx[1] + cs[0]) + csx[0]) + 1.;
+ res[2*(start+i)+1] = (cs[0]*csx[1] + cs[1]*csx[0]) + cs[1] + csx[1];
+ }
+ start += l1;
+ }
+ for (size_t i=1; i<l1; ++i)
+ res[2*i] += 1.;
+ }
+
+NOINLINE static void calc_first_quadrant(size_t n, double * restrict res)
+ {
+ double * restrict p = res+n;
+ calc_first_octant(n<<1, p);
+ size_t ndone=(n+2)>>2;
+ size_t i=0, idx1=0, idx2=2*ndone-2;
+ for (; i+1<ndone; i+=2, idx1+=2, idx2-=2)
+ {
+ res[idx1] = p[2*i];
+ res[idx1+1] = p[2*i+1];
+ res[idx2] = p[2*i+3];
+ res[idx2+1] = p[2*i+2];
+ }
+ if (i!=ndone)
+ {
+ res[idx1 ] = p[2*i];
+ res[idx1+1] = p[2*i+1];
+ }
+ }
+
+NOINLINE static void calc_first_half(size_t n, double * restrict res)
+ {
+ int ndone=(n+1)>>1;
+ double * p = res+n-1;
+ calc_first_octant(n<<2, p);
+ int i4=0, in=n, i=0;
+ for (; i4<=in-i4; ++i, i4+=4) // octant 0
+ {
+ res[2*i] = p[2*i4]; res[2*i+1] = p[2*i4+1];
+ }
+ for (; i4-in <= 0; ++i, i4+=4) // octant 1
+ {
+ int xm = in-i4;
+ res[2*i] = p[2*xm+1]; res[2*i+1] = p[2*xm];
+ }
+ for (; i4<=3*in-i4; ++i, i4+=4) // octant 2
+ {
+ int xm = i4-in;
+ res[2*i] = -p[2*xm+1]; res[2*i+1] = p[2*xm];
+ }
+ for (; i<ndone; ++i, i4+=4) // octant 3
+ {
+ int xm = 2*in-i4;
+ res[2*i] = -p[2*xm]; res[2*i+1] = p[2*xm+1];
+ }
+ }
+
+NOINLINE static void fill_first_quadrant(size_t n, double * restrict res)
+ {
+ const double hsqt2 = 0.707106781186547524400844362104849;
+ size_t quart = n>>2;
+ if ((n&7)==0)
+ res[quart] = res[quart+1] = hsqt2;
+ for (size_t i=2, j=2*quart-2; i<quart; i+=2, j-=2)
+ {
+ res[j ] = res[i+1];
+ res[j+1] = res[i ];
+ }
+ }
+
+NOINLINE static void fill_first_half(size_t n, double * restrict res)
+ {
+ size_t half = n>>1;
+ if ((n&3)==0)
+ for (size_t i=0; i<half; i+=2)
+ {
+ res[i+half] = -res[i+1];
+ res[i+half+1] = res[i ];
+ }
+ else
+ for (size_t i=2, j=2*half-2; i<half; i+=2, j-=2)
+ {
+ res[j ] = -res[i ];
+ res[j+1] = res[i+1];
+ }
+ }
+
+NOINLINE static void fill_second_half(size_t n, double * restrict res)
+ {
+ if ((n&1)==0)
+ for (size_t i=0; i<n; ++i)
+ res[i+n] = -res[i];
+ else
+ for (size_t i=2, j=2*n-2; i<n; i+=2, j-=2)
+ {
+ res[j ] = res[i ];
+ res[j+1] = -res[i+1];
+ }
+ }
+
+NOINLINE static void sincos_2pibyn_half(size_t n, double * restrict res)
+ {
+ if ((n&3)==0)
+ {
+ calc_first_octant(n, res);
+ fill_first_quadrant(n, res);
+ fill_first_half(n, res);
+ }
+ else if ((n&1)==0)
+ {
+ calc_first_quadrant(n, res);
+ fill_first_half(n, res);
+ }
+ else
+ calc_first_half(n, res);
+ }
+
+NOINLINE static void sincos_2pibyn(size_t n, double * restrict res)
+ {
+ sincos_2pibyn_half(n, res);
+ fill_second_half(n, res);
+ }
+
+NOINLINE static size_t largest_prime_factor (size_t n)
+ {
+ size_t res=1;
+ size_t tmp;
+ while (((tmp=(n>>1))<<1)==n)
+ { res=2; n=tmp; }
+
+ size_t limit=(size_t)sqrt(n+0.01);
+ for (size_t x=3; x<=limit; x+=2)
+ while (((tmp=(n/x))*x)==n)
+ {
+ res=x;
+ n=tmp;
+ limit=(size_t)sqrt(n+0.01);
+ }
+ if (n>1) res=n;
+
+ return res;
+ }
+
+NOINLINE static double cost_guess (size_t n)
+ {
+ const double lfp=1.1; // penalty for non-hardcoded larger factors
+ size_t ni=n;
+ double result=0.;
+ size_t tmp;
+ while (((tmp=(n>>1))<<1)==n)
+ { result+=2; n=tmp; }
+
+ size_t limit=(size_t)sqrt(n+0.01);
+ for (size_t x=3; x<=limit; x+=2)
+ while ((tmp=(n/x))*x==n)
+ {
+ result+= (x<=5) ? x : lfp*x; // penalize larger prime factors
+ n=tmp;
+ limit=(size_t)sqrt(n+0.01);
+ }
+ if (n>1) result+=(n<=5) ? n : lfp*n;
+
+ return result*ni;
+ }
+
+/* returns the smallest composite of 2, 3, 5, 7 and 11 which is >= n */
+NOINLINE static size_t good_size(size_t n)
+ {
+ if (n<=6) return n;
+
+ size_t bestfac=2*n;
+ for (size_t f2=1; f2<bestfac; f2*=2)
+ for (size_t f23=f2; f23<bestfac; f23*=3)
+ for (size_t f235=f23; f235<bestfac; f235*=5)
+ for (size_t f2357=f235; f2357<bestfac; f2357*=7)
+ for (size_t f235711=f2357; f235711<bestfac; f235711*=11)
+ if (f235711>=n) bestfac=f235711;
+ return bestfac;
+ }
+
+typedef struct cmplx {
+ double r,i;
+} cmplx;
+
+#define NFCT 25
+typedef struct cfftp_fctdata
+ {
+ size_t fct;
+ cmplx *tw, *tws;
+ } cfftp_fctdata;
+
+typedef struct cfftp_plan_i
+ {
+ size_t length, nfct;
+ cmplx *mem;
+ cfftp_fctdata fct[NFCT];
+ } cfftp_plan_i;
+typedef struct cfftp_plan_i * cfftp_plan;
+
+#define PMC(a,b,c,d) { a.r=c.r+d.r; a.i=c.i+d.i; b.r=c.r-d.r; b.i=c.i-d.i; }
+#define ADDC(a,b,c) { a.r=b.r+c.r; a.i=b.i+c.i; }
+#define SCALEC(a,b) { a.r*=b; a.i*=b; }
+#define ROT90(a) { double tmp_=a.r; a.r=-a.i; a.i=tmp_; }
+#define ROTM90(a) { double tmp_=-a.r; a.r=a.i; a.i=tmp_; }
+#define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))]
+#define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))]
+#define WA(x,i) wa[(i)-1+(x)*(ido-1)]
+/* a = b*c */
+#define A_EQ_B_MUL_C(a,b,c) { a.r=b.r*c.r-b.i*c.i; a.i=b.r*c.i+b.i*c.r; }
+/* a = conj(b)*c*/
+#define A_EQ_CB_MUL_C(a,b,c) { a.r=b.r*c.r+b.i*c.i; a.i=b.r*c.i-b.i*c.r; }
+
+#define PMSIGNC(a,b,c,d) { a.r=c.r+sign*d.r; a.i=c.i+sign*d.i; b.r=c.r-sign*d.r; b.i=c.i-sign*d.i; }
+/* a = b*c */
+#define MULPMSIGNC(a,b,c) { a.r=b.r*c.r-sign*b.i*c.i; a.i=b.r*c.i+sign*b.i*c.r; }
+/* a *= b */
+#define MULPMSIGNCEQ(a,b) { double xtmp=a.r; a.r=b.r*a.r-sign*b.i*a.i; a.i=b.r*a.i+sign*b.i*xtmp; }
+
+NOINLINE static void pass2b (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=2;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ PMC (CH(0,k,0),CH(0,k,1),CC(0,0,k),CC(0,1,k))
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ PMC (CH(0,k,0),CH(0,k,1),CC(0,0,k),CC(0,1,k))
+ for (size_t i=1; i<ido; ++i)
+ {
+ cmplx t;
+ PMC (CH(i,k,0),t,CC(i,0,k),CC(i,1,k))
+ A_EQ_B_MUL_C (CH(i,k,1),WA(0,i),t)
+ }
+ }
+ }
+
+NOINLINE static void pass2f (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=2;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ PMC (CH(0,k,0),CH(0,k,1),CC(0,0,k),CC(0,1,k))
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ PMC (CH(0,k,0),CH(0,k,1),CC(0,0,k),CC(0,1,k))
+ for (size_t i=1; i<ido; ++i)
+ {
+ cmplx t;
+ PMC (CH(i,k,0),t,CC(i,0,k),CC(i,1,k))
+ A_EQ_CB_MUL_C (CH(i,k,1),WA(0,i),t)
+ }
+ }
+ }
+
+#define PREP3(idx) \
+ cmplx t0 = CC(idx,0,k), t1, t2; \
+ PMC (t1,t2,CC(idx,1,k),CC(idx,2,k)) \
+ CH(idx,k,0).r=t0.r+t1.r; \
+ CH(idx,k,0).i=t0.i+t1.i;
+#define PARTSTEP3a(u1,u2,twr,twi) \
+ { \
+ cmplx ca,cb; \
+ ca.r=t0.r+twr*t1.r; \
+ ca.i=t0.i+twr*t1.i; \
+ cb.i=twi*t2.r; \
+ cb.r=-(twi*t2.i); \
+ PMC(CH(0,k,u1),CH(0,k,u2),ca,cb) \
+ }
+
+#define PARTSTEP3b(u1,u2,twr,twi) \
+ { \
+ cmplx ca,cb,da,db; \
+ ca.r=t0.r+twr*t1.r; \
+ ca.i=t0.i+twr*t1.i; \
+ cb.i=twi*t2.r; \
+ cb.r=-(twi*t2.i); \
+ PMC(da,db,ca,cb) \
+ A_EQ_B_MUL_C (CH(i,k,u1),WA(u1-1,i),da) \
+ A_EQ_B_MUL_C (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+NOINLINE static void pass3b (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=3;
+ const double tw1r=-0.5, tw1i= 0.86602540378443864676;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP3(0)
+ PARTSTEP3a(1,2,tw1r,tw1i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP3(0)
+ PARTSTEP3a(1,2,tw1r,tw1i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP3(i)
+ PARTSTEP3b(1,2,tw1r,tw1i)
+ }
+ }
+ }
+#define PARTSTEP3f(u1,u2,twr,twi) \
+ { \
+ cmplx ca,cb,da,db; \
+ ca.r=t0.r+twr*t1.r; \
+ ca.i=t0.i+twr*t1.i; \
+ cb.i=twi*t2.r; \
+ cb.r=-(twi*t2.i); \
+ PMC(da,db,ca,cb) \
+ A_EQ_CB_MUL_C (CH(i,k,u1),WA(u1-1,i),da) \
+ A_EQ_CB_MUL_C (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+NOINLINE static void pass3f (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=3;
+ const double tw1r=-0.5, tw1i= -0.86602540378443864676;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP3(0)
+ PARTSTEP3a(1,2,tw1r,tw1i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP3(0)
+ PARTSTEP3a(1,2,tw1r,tw1i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP3(i)
+ PARTSTEP3f(1,2,tw1r,tw1i)
+ }
+ }
+ }
+
+NOINLINE static void pass4b (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=4;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ cmplx t1, t2, t3, t4;
+ PMC(t2,t1,CC(0,0,k),CC(0,2,k))
+ PMC(t3,t4,CC(0,1,k),CC(0,3,k))
+ ROT90(t4)
+ PMC(CH(0,k,0),CH(0,k,2),t2,t3)
+ PMC(CH(0,k,1),CH(0,k,3),t1,t4)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ cmplx t1, t2, t3, t4;
+ PMC(t2,t1,CC(0,0,k),CC(0,2,k))
+ PMC(t3,t4,CC(0,1,k),CC(0,3,k))
+ ROT90(t4)
+ PMC(CH(0,k,0),CH(0,k,2),t2,t3)
+ PMC(CH(0,k,1),CH(0,k,3),t1,t4)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ cmplx c2, c3, c4, t1, t2, t3, t4;
+ cmplx cc0=CC(i,0,k), cc1=CC(i,1,k),cc2=CC(i,2,k),cc3=CC(i,3,k);
+ PMC(t2,t1,cc0,cc2)
+ PMC(t3,t4,cc1,cc3)
+ ROT90(t4)
+ cmplx wa0=WA(0,i), wa1=WA(1,i),wa2=WA(2,i);
+ PMC(CH(i,k,0),c3,t2,t3)
+ PMC(c2,c4,t1,t4)
+ A_EQ_B_MUL_C (CH(i,k,1),wa0,c2)
+ A_EQ_B_MUL_C (CH(i,k,2),wa1,c3)
+ A_EQ_B_MUL_C (CH(i,k,3),wa2,c4)
+ }
+ }
+ }
+NOINLINE static void pass4f (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=4;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ cmplx t1, t2, t3, t4;
+ PMC(t2,t1,CC(0,0,k),CC(0,2,k))
+ PMC(t3,t4,CC(0,1,k),CC(0,3,k))
+ ROTM90(t4)
+ PMC(CH(0,k,0),CH(0,k,2),t2,t3)
+ PMC(CH(0,k,1),CH(0,k,3),t1,t4)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ cmplx t1, t2, t3, t4;
+ PMC(t2,t1,CC(0,0,k),CC(0,2,k))
+ PMC(t3,t4,CC(0,1,k),CC(0,3,k))
+ ROTM90(t4)
+ PMC(CH(0,k,0),CH(0,k,2),t2,t3)
+ PMC (CH(0,k,1),CH(0,k,3),t1,t4)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ cmplx c2, c3, c4, t1, t2, t3, t4;
+ cmplx cc0=CC(i,0,k), cc1=CC(i,1,k),cc2=CC(i,2,k),cc3=CC(i,3,k);
+ PMC(t2,t1,cc0,cc2)
+ PMC(t3,t4,cc1,cc3)
+ ROTM90(t4)
+ cmplx wa0=WA(0,i), wa1=WA(1,i),wa2=WA(2,i);
+ PMC(CH(i,k,0),c3,t2,t3)
+ PMC(c2,c4,t1,t4)
+ A_EQ_CB_MUL_C (CH(i,k,1),wa0,c2)
+ A_EQ_CB_MUL_C (CH(i,k,2),wa1,c3)
+ A_EQ_CB_MUL_C (CH(i,k,3),wa2,c4)
+ }
+ }
+ }
+
+#define PREP5(idx) \
+ cmplx t0 = CC(idx,0,k), t1, t2, t3, t4; \
+ PMC (t1,t4,CC(idx,1,k),CC(idx,4,k)) \
+ PMC (t2,t3,CC(idx,2,k),CC(idx,3,k)) \
+ CH(idx,k,0).r=t0.r+t1.r+t2.r; \
+ CH(idx,k,0).i=t0.i+t1.i+t2.i;
+
+#define PARTSTEP5a(u1,u2,twar,twbr,twai,twbi) \
+ { \
+ cmplx ca,cb; \
+ ca.r=t0.r+twar*t1.r+twbr*t2.r; \
+ ca.i=t0.i+twar*t1.i+twbr*t2.i; \
+ cb.i=twai*t4.r twbi*t3.r; \
+ cb.r=-(twai*t4.i twbi*t3.i); \
+ PMC(CH(0,k,u1),CH(0,k,u2),ca,cb) \
+ }
+
+#define PARTSTEP5b(u1,u2,twar,twbr,twai,twbi) \
+ { \
+ cmplx ca,cb,da,db; \
+ ca.r=t0.r+twar*t1.r+twbr*t2.r; \
+ ca.i=t0.i+twar*t1.i+twbr*t2.i; \
+ cb.i=twai*t4.r twbi*t3.r; \
+ cb.r=-(twai*t4.i twbi*t3.i); \
+ PMC(da,db,ca,cb) \
+ A_EQ_B_MUL_C (CH(i,k,u1),WA(u1-1,i),da) \
+ A_EQ_B_MUL_C (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+NOINLINE static void pass5b (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=5;
+ const double tw1r= 0.3090169943749474241,
+ tw1i= 0.95105651629515357212,
+ tw2r= -0.8090169943749474241,
+ tw2i= 0.58778525229247312917;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP5(0)
+ PARTSTEP5a(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5a(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP5(0)
+ PARTSTEP5a(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5a(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP5(i)
+ PARTSTEP5b(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5b(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ }
+ }
+#define PARTSTEP5f(u1,u2,twar,twbr,twai,twbi) \
+ { \
+ cmplx ca,cb,da,db; \
+ ca.r=t0.r+twar*t1.r+twbr*t2.r; \
+ ca.i=t0.i+twar*t1.i+twbr*t2.i; \
+ cb.i=twai*t4.r twbi*t3.r; \
+ cb.r=-(twai*t4.i twbi*t3.i); \
+ PMC(da,db,ca,cb) \
+ A_EQ_CB_MUL_C (CH(i,k,u1),WA(u1-1,i),da) \
+ A_EQ_CB_MUL_C (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+NOINLINE static void pass5f (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa)
+ {
+ const size_t cdim=5;
+ const double tw1r= 0.3090169943749474241,
+ tw1i= -0.95105651629515357212,
+ tw2r= -0.8090169943749474241,
+ tw2i= -0.58778525229247312917;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP5(0)
+ PARTSTEP5a(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5a(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP5(0)
+ PARTSTEP5a(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5a(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP5(i)
+ PARTSTEP5f(1,4,tw1r,tw2r,+tw1i,+tw2i)
+ PARTSTEP5f(2,3,tw2r,tw1r,+tw2i,-tw1i)
+ }
+ }
+ }
+
+#define PREP7(idx) \
+ cmplx t1 = CC(idx,0,k), t2, t3, t4, t5, t6, t7; \
+ PMC (t2,t7,CC(idx,1,k),CC(idx,6,k)) \
+ PMC (t3,t6,CC(idx,2,k),CC(idx,5,k)) \
+ PMC (t4,t5,CC(idx,3,k),CC(idx,4,k)) \
+ CH(idx,k,0).r=t1.r+t2.r+t3.r+t4.r; \
+ CH(idx,k,0).i=t1.i+t2.i+t3.i+t4.i;
+
+#define PARTSTEP7a0(u1,u2,x1,x2,x3,y1,y2,y3,out1,out2) \
+ { \
+ cmplx ca,cb; \
+ ca.r=t1.r+x1*t2.r+x2*t3.r+x3*t4.r; \
+ ca.i=t1.i+x1*t2.i+x2*t3.i+x3*t4.i; \
+ cb.i=y1*t7.r y2*t6.r y3*t5.r; \
+ cb.r=-(y1*t7.i y2*t6.i y3*t5.i); \
+ PMC(out1,out2,ca,cb) \
+ }
+#define PARTSTEP7a(u1,u2,x1,x2,x3,y1,y2,y3) \
+ PARTSTEP7a0(u1,u2,x1,x2,x3,y1,y2,y3,CH(0,k,u1),CH(0,k,u2))
+#define PARTSTEP7(u1,u2,x1,x2,x3,y1,y2,y3) \
+ { \
+ cmplx da,db; \
+ PARTSTEP7a0(u1,u2,x1,x2,x3,y1,y2,y3,da,db) \
+ MULPMSIGNC (CH(i,k,u1),WA(u1-1,i),da) \
+ MULPMSIGNC (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+
+NOINLINE static void pass7(size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa, const int sign)
+ {
+ const size_t cdim=7;
+ const double tw1r= 0.623489801858733530525,
+ tw1i= sign * 0.7818314824680298087084,
+ tw2r= -0.222520933956314404289,
+ tw2i= sign * 0.9749279121818236070181,
+ tw3r= -0.9009688679024191262361,
+ tw3i= sign * 0.4338837391175581204758;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP7(0)
+ PARTSTEP7a(1,6,tw1r,tw2r,tw3r,+tw1i,+tw2i,+tw3i)
+ PARTSTEP7a(2,5,tw2r,tw3r,tw1r,+tw2i,-tw3i,-tw1i)
+ PARTSTEP7a(3,4,tw3r,tw1r,tw2r,+tw3i,-tw1i,+tw2i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP7(0)
+ PARTSTEP7a(1,6,tw1r,tw2r,tw3r,+tw1i,+tw2i,+tw3i)
+ PARTSTEP7a(2,5,tw2r,tw3r,tw1r,+tw2i,-tw3i,-tw1i)
+ PARTSTEP7a(3,4,tw3r,tw1r,tw2r,+tw3i,-tw1i,+tw2i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP7(i)
+ PARTSTEP7(1,6,tw1r,tw2r,tw3r,+tw1i,+tw2i,+tw3i)
+ PARTSTEP7(2,5,tw2r,tw3r,tw1r,+tw2i,-tw3i,-tw1i)
+ PARTSTEP7(3,4,tw3r,tw1r,tw2r,+tw3i,-tw1i,+tw2i)
+ }
+ }
+ }
+
+#define PREP11(idx) \
+ cmplx t1 = CC(idx,0,k), t2, t3, t4, t5, t6, t7, t8, t9, t10, t11; \
+ PMC (t2,t11,CC(idx,1,k),CC(idx,10,k)) \
+ PMC (t3,t10,CC(idx,2,k),CC(idx, 9,k)) \
+ PMC (t4,t9 ,CC(idx,3,k),CC(idx, 8,k)) \
+ PMC (t5,t8 ,CC(idx,4,k),CC(idx, 7,k)) \
+ PMC (t6,t7 ,CC(idx,5,k),CC(idx, 6,k)) \
+ CH(idx,k,0).r=t1.r+t2.r+t3.r+t4.r+t5.r+t6.r; \
+ CH(idx,k,0).i=t1.i+t2.i+t3.i+t4.i+t5.i+t6.i;
+
+#define PARTSTEP11a0(u1,u2,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,out1,out2) \
+ { \
+ cmplx ca,cb; \
+ ca.r=t1.r+x1*t2.r+x2*t3.r+x3*t4.r+x4*t5.r+x5*t6.r; \
+ ca.i=t1.i+x1*t2.i+x2*t3.i+x3*t4.i+x4*t5.i+x5*t6.i; \
+ cb.i=y1*t11.r y2*t10.r y3*t9.r y4*t8.r y5*t7.r; \
+ cb.r=-(y1*t11.i y2*t10.i y3*t9.i y4*t8.i y5*t7.i ); \
+ PMC(out1,out2,ca,cb) \
+ }
+#define PARTSTEP11a(u1,u2,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5) \
+ PARTSTEP11a0(u1,u2,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,CH(0,k,u1),CH(0,k,u2))
+#define PARTSTEP11(u1,u2,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5) \
+ { \
+ cmplx da,db; \
+ PARTSTEP11a0(u1,u2,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,da,db) \
+ MULPMSIGNC (CH(i,k,u1),WA(u1-1,i),da) \
+ MULPMSIGNC (CH(i,k,u2),WA(u2-1,i),db) \
+ }
+
+NOINLINE static void pass11 (size_t ido, size_t l1, const cmplx * restrict cc,
+ cmplx * restrict ch, const cmplx * restrict wa, const int sign)
+ {
+ const size_t cdim=11;
+ const double tw1r = 0.8412535328311811688618,
+ tw1i = sign * 0.5406408174555975821076,
+ tw2r = 0.4154150130018864255293,
+ tw2i = sign * 0.9096319953545183714117,
+ tw3r = -0.1423148382732851404438,
+ tw3i = sign * 0.9898214418809327323761,
+ tw4r = -0.6548607339452850640569,
+ tw4i = sign * 0.755749574354258283774,
+ tw5r = -0.9594929736144973898904,
+ tw5i = sign * 0.2817325568414296977114;
+
+ if (ido==1)
+ for (size_t k=0; k<l1; ++k)
+ {
+ PREP11(0)
+ PARTSTEP11a(1,10,tw1r,tw2r,tw3r,tw4r,tw5r,+tw1i,+tw2i,+tw3i,+tw4i,+tw5i)
+ PARTSTEP11a(2, 9,tw2r,tw4r,tw5r,tw3r,tw1r,+tw2i,+tw4i,-tw5i,-tw3i,-tw1i)
+ PARTSTEP11a(3, 8,tw3r,tw5r,tw2r,tw1r,tw4r,+tw3i,-tw5i,-tw2i,+tw1i,+tw4i)
+ PARTSTEP11a(4, 7,tw4r,tw3r,tw1r,tw5r,tw2r,+tw4i,-tw3i,+tw1i,+tw5i,-tw2i)
+ PARTSTEP11a(5, 6,tw5r,tw1r,tw4r,tw2r,tw3r,+tw5i,-tw1i,+tw4i,-tw2i,+tw3i)
+ }
+ else
+ for (size_t k=0; k<l1; ++k)
+ {
+ {
+ PREP11(0)
+ PARTSTEP11a(1,10,tw1r,tw2r,tw3r,tw4r,tw5r,+tw1i,+tw2i,+tw3i,+tw4i,+tw5i)
+ PARTSTEP11a(2, 9,tw2r,tw4r,tw5r,tw3r,tw1r,+tw2i,+tw4i,-tw5i,-tw3i,-tw1i)
+ PARTSTEP11a(3, 8,tw3r,tw5r,tw2r,tw1r,tw4r,+tw3i,-tw5i,-tw2i,+tw1i,+tw4i)
+ PARTSTEP11a(4, 7,tw4r,tw3r,tw1r,tw5r,tw2r,+tw4i,-tw3i,+tw1i,+tw5i,-tw2i)
+ PARTSTEP11a(5, 6,tw5r,tw1r,tw4r,tw2r,tw3r,+tw5i,-tw1i,+tw4i,-tw2i,+tw3i)
+ }
+ for (size_t i=1; i<ido; ++i)
+ {
+ PREP11(i)
+ PARTSTEP11(1,10,tw1r,tw2r,tw3r,tw4r,tw5r,+tw1i,+tw2i,+tw3i,+tw4i,+tw5i)
+ PARTSTEP11(2, 9,tw2r,tw4r,tw5r,tw3r,tw1r,+tw2i,+tw4i,-tw5i,-tw3i,-tw1i)
+ PARTSTEP11(3, 8,tw3r,tw5r,tw2r,tw1r,tw4r,+tw3i,-tw5i,-tw2i,+tw1i,+tw4i)
+ PARTSTEP11(4, 7,tw4r,tw3r,tw1r,tw5r,tw2r,+tw4i,-tw3i,+tw1i,+tw5i,-tw2i)
+ PARTSTEP11(5, 6,tw5r,tw1r,tw4r,tw2r,tw3r,+tw5i,-tw1i,+tw4i,-tw2i,+tw3i)
+ }
+ }
+ }
+
+#define CX(a,b,c) cc[(a)+ido*((b)+l1*(c))]
+#define CX2(a,b) cc[(a)+idl1*(b)]
+#define CH2(a,b) ch[(a)+idl1*(b)]
+
+NOINLINE static int passg (size_t ido, size_t ip, size_t l1,
+ cmplx * restrict cc, cmplx * restrict ch, const cmplx * restrict wa,
+ const cmplx * restrict csarr, const int sign)
+ {
+ const size_t cdim=ip;
+ size_t ipph = (ip+1)/2;
+ size_t idl1 = ido*l1;
+
+ cmplx * restrict wal=RALLOC(cmplx,ip);
+ if (!wal) return -1;
+ wal[0]=(cmplx){1.,0.};
+ for (size_t i=1; i<ip; ++i)
+ wal[i]=(cmplx){csarr[i].r,sign*csarr[i].i};
+
+ for (size_t k=0; k<l1; ++k)
+ for (size_t i=0; i<ido; ++i)
+ CH(i,k,0) = CC(i,0,k);
+ for (size_t j=1, jc=ip-1; j<ipph; ++j, --jc)
+ for (size_t k=0; k<l1; ++k)
+ for (size_t i=0; i<ido; ++i)
+ PMC(CH(i,k,j),CH(i,k,jc),CC(i,j,k),CC(i,jc,k))
+ for (size_t k=0; k<l1; ++k)
+ for (size_t i=0; i<ido; ++i)
+ {
+ cmplx tmp = CH(i,k,0);
+ for (size_t j=1; j<ipph; ++j)
+ ADDC(tmp,tmp,CH(i,k,j))
+ CX(i,k,0) = tmp;
+ }
+ for (size_t l=1, lc=ip-1; l<ipph; ++l, --lc)
+ {
+ // j=0
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ CX2(ik,l).r = CH2(ik,0).r+wal[l].r*CH2(ik,1).r+wal[2*l].r*CH2(ik,2).r;
+ CX2(ik,l).i = CH2(ik,0).i+wal[l].r*CH2(ik,1).i+wal[2*l].r*CH2(ik,2).i;
+ CX2(ik,lc).r=-wal[l].i*CH2(ik,ip-1).i-wal[2*l].i*CH2(ik,ip-2).i;
+ CX2(ik,lc).i=wal[l].i*CH2(ik,ip-1).r+wal[2*l].i*CH2(ik,ip-2).r;
+ }
+
+ size_t iwal=2*l;
+ size_t j=3, jc=ip-3;
+ for (; j<ipph-1; j+=2, jc-=2)
+ {
+ iwal+=l; if (iwal>ip) iwal-=ip;
+ cmplx xwal=wal[iwal];
+ iwal+=l; if (iwal>ip) iwal-=ip;
+ cmplx xwal2=wal[iwal];
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ CX2(ik,l).r += CH2(ik,j).r*xwal.r+CH2(ik,j+1).r*xwal2.r;
+ CX2(ik,l).i += CH2(ik,j).i*xwal.r+CH2(ik,j+1).i*xwal2.r;
+ CX2(ik,lc).r -= CH2(ik,jc).i*xwal.i+CH2(ik,jc-1).i*xwal2.i;
+ CX2(ik,lc).i += CH2(ik,jc).r*xwal.i+CH2(ik,jc-1).r*xwal2.i;
+ }
+ }
+ for (; j<ipph; ++j, --jc)
+ {
+ iwal+=l; if (iwal>ip) iwal-=ip;
+ cmplx xwal=wal[iwal];
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ CX2(ik,l).r += CH2(ik,j).r*xwal.r;
+ CX2(ik,l).i += CH2(ik,j).i*xwal.r;
+ CX2(ik,lc).r -= CH2(ik,jc).i*xwal.i;
+ CX2(ik,lc).i += CH2(ik,jc).r*xwal.i;
+ }
+ }
+ }
+ DEALLOC(wal);
+
+ // shuffling and twiddling
+ if (ido==1)
+ for (size_t j=1, jc=ip-1; j<ipph; ++j, --jc)
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ cmplx t1=CX2(ik,j), t2=CX2(ik,jc);
+ PMC(CX2(ik,j),CX2(ik,jc),t1,t2)
+ }
+ else
+ {
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc)
+ for (size_t k=0; k<l1; ++k)
+ {
+ cmplx t1=CX(0,k,j), t2=CX(0,k,jc);
+ PMC(CX(0,k,j),CX(0,k,jc),t1,t2)
+ for (size_t i=1; i<ido; ++i)
+ {
+ cmplx x1, x2;
+ PMC(x1,x2,CX(i,k,j),CX(i,k,jc))
+ size_t idij=(j-1)*(ido-1)+i-1;
+ MULPMSIGNC (CX(i,k,j),wa[idij],x1)
+ idij=(jc-1)*(ido-1)+i-1;
+ MULPMSIGNC (CX(i,k,jc),wa[idij],x2)
+ }
+ }
+ }
+ return 0;
+ }
+
+#undef CH2
+#undef CX2
+#undef CX
+
+NOINLINE WARN_UNUSED_RESULT static int pass_all(cfftp_plan plan, cmplx c[], double fct,
+ const int sign)
+ {
+ if (plan->length==1) return 0;
+ size_t len=plan->length;
+ size_t l1=1, nf=plan->nfct;
+ cmplx *ch = RALLOC(cmplx, len);
+ if (!ch) return -1;
+ cmplx *p1=c, *p2=ch;
+
+ for(size_t k1=0; k1<nf; k1++)
+ {
+ size_t ip=plan->fct[k1].fct;
+ size_t l2=ip*l1;
+ size_t ido = len/l2;
+ if (ip==4)
+ sign>0 ? pass4b (ido, l1, p1, p2, plan->fct[k1].tw)
+ : pass4f (ido, l1, p1, p2, plan->fct[k1].tw);
+ else if(ip==2)
+ sign>0 ? pass2b (ido, l1, p1, p2, plan->fct[k1].tw)
+ : pass2f (ido, l1, p1, p2, plan->fct[k1].tw);
+ else if(ip==3)
+ sign>0 ? pass3b (ido, l1, p1, p2, plan->fct[k1].tw)
+ : pass3f (ido, l1, p1, p2, plan->fct[k1].tw);
+ else if(ip==5)
+ sign>0 ? pass5b (ido, l1, p1, p2, plan->fct[k1].tw)
+ : pass5f (ido, l1, p1, p2, plan->fct[k1].tw);
+ else if(ip==7) pass7 (ido, l1, p1, p2, plan->fct[k1].tw, sign);
+ else if(ip==11) pass11(ido, l1, p1, p2, plan->fct[k1].tw, sign);
+ else
+ {
+ if (passg(ido, ip, l1, p1, p2, plan->fct[k1].tw, plan->fct[k1].tws, sign))
+ { DEALLOC(ch); return -1; }
+ SWAP(p1,p2,cmplx *);
+ }
+ SWAP(p1,p2,cmplx *);
+ l1=l2;
+ }
+ if (p1!=c)
+ {
+ if (fct!=1.)
+ for (size_t i=0; i<len; ++i)
+ {
+ c[i].r = ch[i].r*fct;
+ c[i].i = ch[i].i*fct;
+ }
+ else
+ memcpy (c,p1,len*sizeof(cmplx));
+ }
+ else
+ if (fct!=1.)
+ for (size_t i=0; i<len; ++i)
+ {
+ c[i].r *= fct;
+ c[i].i *= fct;
+ }
+ DEALLOC(ch);
+ return 0;
+ }
+
+#undef PMSIGNC
+#undef A_EQ_B_MUL_C
+#undef A_EQ_CB_MUL_C
+#undef MULPMSIGNC
+#undef MULPMSIGNCEQ
+
+#undef WA
+#undef CC
+#undef CH
+#undef ROT90
+#undef SCALEC
+#undef ADDC
+#undef PMC
+
+NOINLINE WARN_UNUSED_RESULT
+static int cfftp_forward(cfftp_plan plan, double c[], double fct)
+ { return pass_all(plan,(cmplx *)c, fct, -1); }
+
+NOINLINE WARN_UNUSED_RESULT
+static int cfftp_backward(cfftp_plan plan, double c[], double fct)
+ { return pass_all(plan,(cmplx *)c, fct, 1); }
+
+NOINLINE WARN_UNUSED_RESULT
+static int cfftp_factorize (cfftp_plan plan)
+ {
+ size_t length=plan->length;
+ size_t nfct=0;
+ while ((length%4)==0)
+ { if (nfct>=NFCT) return -1; plan->fct[nfct++].fct=4; length>>=2; }
+ if ((length%2)==0)
+ {
+ length>>=1;
+ // factor 2 should be at the front of the factor list
+ if (nfct>=NFCT) return -1;
+ plan->fct[nfct++].fct=2;
+ SWAP(plan->fct[0].fct, plan->fct[nfct-1].fct,size_t);
+ }
+ size_t maxl=(size_t)(sqrt((double)length))+1;
+ for (size_t divisor=3; (length>1)&&(divisor<maxl); divisor+=2)
+ if ((length%divisor)==0)
+ {
+ while ((length%divisor)==0)
+ {
+ if (nfct>=NFCT) return -1;
+ plan->fct[nfct++].fct=divisor;
+ length/=divisor;
+ }
+ maxl=(size_t)(sqrt((double)length))+1;
+ }
+ if (length>1) plan->fct[nfct++].fct=length;
+ plan->nfct=nfct;
+ return 0;
+ }
+
+NOINLINE static size_t cfftp_twsize (cfftp_plan plan)
+ {
+ size_t twsize=0, l1=1;
+ for (size_t k=0; k<plan->nfct; ++k)
+ {
+ size_t ip=plan->fct[k].fct, ido= plan->length/(l1*ip);
+ twsize+=(ip-1)*(ido-1);
+ if (ip>11)
+ twsize+=ip;
+ l1*=ip;
+ }
+ return twsize;
+ }
+
+NOINLINE WARN_UNUSED_RESULT static int cfftp_comp_twiddle (cfftp_plan plan)
+ {
+ size_t length=plan->length;
+ double *twid = RALLOC(double, 2*length);
+ if (!twid) return -1;
+ sincos_2pibyn(length, twid);
+ size_t l1=1;
+ size_t memofs=0;
+ for (size_t k=0; k<plan->nfct; ++k)
+ {
+ size_t ip=plan->fct[k].fct, ido= length/(l1*ip);
+ plan->fct[k].tw=plan->mem+memofs;
+ memofs+=(ip-1)*(ido-1);
+ for (size_t j=1; j<ip; ++j)
+ for (size_t i=1; i<ido; ++i)
+ {
+ plan->fct[k].tw[(j-1)*(ido-1)+i-1].r = twid[2*j*l1*i];
+ plan->fct[k].tw[(j-1)*(ido-1)+i-1].i = twid[2*j*l1*i+1];
+ }
+ if (ip>11)
+ {
+ plan->fct[k].tws=plan->mem+memofs;
+ memofs+=ip;
+ for (size_t j=0; j<ip; ++j)
+ {
+ plan->fct[k].tws[j].r = twid[2*j*l1*ido];
+ plan->fct[k].tws[j].i = twid[2*j*l1*ido+1];
+ }
+ }
+ l1*=ip;
+ }
+ DEALLOC(twid);
+ return 0;
+ }
+
+static cfftp_plan make_cfftp_plan (size_t length)
+ {
+ if (length==0) return NULL;
+ cfftp_plan plan = RALLOC(cfftp_plan_i,1);
+ if (!plan) return NULL;
+ plan->length=length;
+ plan->nfct=0;
+ for (size_t i=0; i<NFCT; ++i)
+ plan->fct[i]=(cfftp_fctdata){0,0,0};
+ plan->mem=0;
+ if (length==1) return plan;
+ if (cfftp_factorize(plan)!=0) { DEALLOC(plan); return NULL; }
+ size_t tws=cfftp_twsize(plan);
+ plan->mem=RALLOC(cmplx,tws);
+ if (!plan->mem) { DEALLOC(plan); return NULL; }
+ if (cfftp_comp_twiddle(plan)!=0)
+ { DEALLOC(plan->mem); DEALLOC(plan); return NULL; }
+ return plan;
+ }
+
+static void destroy_cfftp_plan (cfftp_plan plan)
+ {
+ DEALLOC(plan->mem);
+ DEALLOC(plan);
+ }
+
+typedef struct rfftp_fctdata
+ {
+ size_t fct;
+ double *tw, *tws;
+ } rfftp_fctdata;
+
+typedef struct rfftp_plan_i
+ {
+ size_t length, nfct;
+ double *mem;
+ rfftp_fctdata fct[NFCT];
+ } rfftp_plan_i;
+typedef struct rfftp_plan_i * rfftp_plan;
+
+#define WA(x,i) wa[(i)+(x)*(ido-1)]
+#define PM(a,b,c,d) { a=c+d; b=c-d; }
+/* (a+ib) = conj(c+id) * (e+if) */
+#define MULPM(a,b,c,d,e,f) { a=c*e+d*f; b=c*f-d*e; }
+
+#define CC(a,b,c) cc[(a)+ido*((b)+l1*(c))]
+#define CH(a,b,c) ch[(a)+ido*((b)+cdim*(c))]
+
+NOINLINE static void radf2 (size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=2;
+
+ for (size_t k=0; k<l1; k++)
+ PM (CH(0,0,k),CH(ido-1,1,k),CC(0,k,0),CC(0,k,1))
+ if ((ido&1)==0)
+ for (size_t k=0; k<l1; k++)
+ {
+ CH( 0,1,k) = -CC(ido-1,k,1);
+ CH(ido-1,0,k) = CC(ido-1,k,0);
+ }
+ if (ido<=2) return;
+ for (size_t k=0; k<l1; k++)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double tr2, ti2;
+ MULPM (tr2,ti2,WA(0,i-2),WA(0,i-1),CC(i-1,k,1),CC(i,k,1))
+ PM (CH(i-1,0,k),CH(ic-1,1,k),CC(i-1,k,0),tr2)
+ PM (CH(i ,0,k),CH(ic ,1,k),ti2,CC(i ,k,0))
+ }
+ }
+
+NOINLINE static void radf3(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=3;
+ static const double taur=-0.5, taui=0.86602540378443864676;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double cr2=CC(0,k,1)+CC(0,k,2);
+ CH(0,0,k) = CC(0,k,0)+cr2;
+ CH(0,2,k) = taui*(CC(0,k,2)-CC(0,k,1));
+ CH(ido-1,1,k) = CC(0,k,0)+taur*cr2;
+ }
+ if (ido==1) return;
+ for (size_t k=0; k<l1; k++)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double di2, di3, dr2, dr3;
+ MULPM (dr2,di2,WA(0,i-2),WA(0,i-1),CC(i-1,k,1),CC(i,k,1)) // d2=conj(WA0)*CC1
+ MULPM (dr3,di3,WA(1,i-2),WA(1,i-1),CC(i-1,k,2),CC(i,k,2)) // d3=conj(WA1)*CC2
+ double cr2=dr2+dr3; // c add
+ double ci2=di2+di3;
+ CH(i-1,0,k) = CC(i-1,k,0)+cr2; // c add
+ CH(i ,0,k) = CC(i ,k,0)+ci2;
+ double tr2 = CC(i-1,k,0)+taur*cr2; // c add
+ double ti2 = CC(i ,k,0)+taur*ci2;
+ double tr3 = taui*(di2-di3); // t3 = taui*i*(d3-d2)?
+ double ti3 = taui*(dr3-dr2);
+ PM(CH(i-1,2,k),CH(ic-1,1,k),tr2,tr3) // PM(i) = t2+t3
+ PM(CH(i ,2,k),CH(ic ,1,k),ti3,ti2) // PM(ic) = conj(t2-t3)
+ }
+ }
+
+NOINLINE static void radf4(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=4;
+ static const double hsqt2=0.70710678118654752440;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double tr1,tr2;
+ PM (tr1,CH(0,2,k),CC(0,k,3),CC(0,k,1))
+ PM (tr2,CH(ido-1,1,k),CC(0,k,0),CC(0,k,2))
+ PM (CH(0,0,k),CH(ido-1,3,k),tr2,tr1)
+ }
+ if ((ido&1)==0)
+ for (size_t k=0; k<l1; k++)
+ {
+ double ti1=-hsqt2*(CC(ido-1,k,1)+CC(ido-1,k,3));
+ double tr1= hsqt2*(CC(ido-1,k,1)-CC(ido-1,k,3));
+ PM (CH(ido-1,0,k),CH(ido-1,2,k),CC(ido-1,k,0),tr1)
+ PM (CH( 0,3,k),CH( 0,1,k),ti1,CC(ido-1,k,2))
+ }
+ if (ido<=2) return;
+ for (size_t k=0; k<l1; k++)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
+ MULPM(cr2,ci2,WA(0,i-2),WA(0,i-1),CC(i-1,k,1),CC(i,k,1))
+ MULPM(cr3,ci3,WA(1,i-2),WA(1,i-1),CC(i-1,k,2),CC(i,k,2))
+ MULPM(cr4,ci4,WA(2,i-2),WA(2,i-1),CC(i-1,k,3),CC(i,k,3))
+ PM(tr1,tr4,cr4,cr2)
+ PM(ti1,ti4,ci2,ci4)
+ PM(tr2,tr3,CC(i-1,k,0),cr3)
+ PM(ti2,ti3,CC(i ,k,0),ci3)
+ PM(CH(i-1,0,k),CH(ic-1,3,k),tr2,tr1)
+ PM(CH(i ,0,k),CH(ic ,3,k),ti1,ti2)
+ PM(CH(i-1,2,k),CH(ic-1,1,k),tr3,ti4)
+ PM(CH(i ,2,k),CH(ic ,1,k),tr4,ti3)
+ }
+ }
+
+NOINLINE static void radf5(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=5;
+ static const double tr11= 0.3090169943749474241, ti11=0.95105651629515357212,
+ tr12=-0.8090169943749474241, ti12=0.58778525229247312917;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double cr2, cr3, ci4, ci5;
+ PM (cr2,ci5,CC(0,k,4),CC(0,k,1))
+ PM (cr3,ci4,CC(0,k,3),CC(0,k,2))
+ CH(0,0,k)=CC(0,k,0)+cr2+cr3;
+ CH(ido-1,1,k)=CC(0,k,0)+tr11*cr2+tr12*cr3;
+ CH(0,2,k)=ti11*ci5+ti12*ci4;
+ CH(ido-1,3,k)=CC(0,k,0)+tr12*cr2+tr11*cr3;
+ CH(0,4,k)=ti12*ci5-ti11*ci4;
+ }
+ if (ido==1) return;
+ for (size_t k=0; k<l1;++k)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ double ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3,
+ dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
+ size_t ic=ido-i;
+ MULPM (dr2,di2,WA(0,i-2),WA(0,i-1),CC(i-1,k,1),CC(i,k,1))
+ MULPM (dr3,di3,WA(1,i-2),WA(1,i-1),CC(i-1,k,2),CC(i,k,2))
+ MULPM (dr4,di4,WA(2,i-2),WA(2,i-1),CC(i-1,k,3),CC(i,k,3))
+ MULPM (dr5,di5,WA(3,i-2),WA(3,i-1),CC(i-1,k,4),CC(i,k,4))
+ PM(cr2,ci5,dr5,dr2)
+ PM(ci2,cr5,di2,di5)
+ PM(cr3,ci4,dr4,dr3)
+ PM(ci3,cr4,di3,di4)
+ CH(i-1,0,k)=CC(i-1,k,0)+cr2+cr3;
+ CH(i ,0,k)=CC(i ,k,0)+ci2+ci3;
+ tr2=CC(i-1,k,0)+tr11*cr2+tr12*cr3;
+ ti2=CC(i ,k,0)+tr11*ci2+tr12*ci3;
+ tr3=CC(i-1,k,0)+tr12*cr2+tr11*cr3;
+ ti3=CC(i ,k,0)+tr12*ci2+tr11*ci3;
+ MULPM(tr5,tr4,cr5,cr4,ti11,ti12)
+ MULPM(ti5,ti4,ci5,ci4,ti11,ti12)
+ PM(CH(i-1,2,k),CH(ic-1,1,k),tr2,tr5)
+ PM(CH(i ,2,k),CH(ic ,1,k),ti5,ti2)
+ PM(CH(i-1,4,k),CH(ic-1,3,k),tr3,tr4)
+ PM(CH(i ,4,k),CH(ic ,3,k),ti4,ti3)
+ }
+ }
+
+#undef CC
+#undef CH
+#define C1(a,b,c) cc[(a)+ido*((b)+l1*(c))]
+#define C2(a,b) cc[(a)+idl1*(b)]
+#define CH2(a,b) ch[(a)+idl1*(b)]
+#define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))]
+#define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))]
+NOINLINE static void radfg(size_t ido, size_t ip, size_t l1,
+ double * restrict cc, double * restrict ch, const double * restrict wa,
+ const double * restrict csarr)
+ {
+ const size_t cdim=ip;
+ size_t ipph=(ip+1)/2;
+ size_t idl1 = ido*l1;
+
+ if (ido>1)
+ {
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 114
+ {
+ size_t is=(j-1)*(ido-1),
+ is2=(jc-1)*(ido-1);
+ for (size_t k=0; k<l1; ++k) // 113
+ {
+ size_t idij=is;
+ size_t idij2=is2;
+ for (size_t i=1; i<=ido-2; i+=2) // 112
+ {
+ double t1=C1(i,k,j ), t2=C1(i+1,k,j ),
+ t3=C1(i,k,jc), t4=C1(i+1,k,jc);
+ double x1=wa[idij]*t1 + wa[idij+1]*t2,
+ x2=wa[idij]*t2 - wa[idij+1]*t1,
+ x3=wa[idij2]*t3 + wa[idij2+1]*t4,
+ x4=wa[idij2]*t4 - wa[idij2+1]*t3;
+ C1(i ,k,j ) = x1+x3;
+ C1(i ,k,jc) = x2-x4;
+ C1(i+1,k,j ) = x2+x4;
+ C1(i+1,k,jc) = x3-x1;
+ idij+=2;
+ idij2+=2;
+ }
+ }
+ }
+ }
+
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 123
+ for (size_t k=0; k<l1; ++k) // 122
+ {
+ double t1=C1(0,k,j), t2=C1(0,k,jc);
+ C1(0,k,j ) = t1+t2;
+ C1(0,k,jc) = t2-t1;
+ }
+
+//everything in C
+//memset(ch,0,ip*l1*ido*sizeof(double));
+
+ for (size_t l=1,lc=ip-1; l<ipph; ++l,--lc) // 127
+ {
+ for (size_t ik=0; ik<idl1; ++ik) // 124
+ {
+ CH2(ik,l ) = C2(ik,0)+csarr[2*l]*C2(ik,1)+csarr[4*l]*C2(ik,2);
+ CH2(ik,lc) = csarr[2*l+1]*C2(ik,ip-1)+csarr[4*l+1]*C2(ik,ip-2);
+ }
+ size_t iang = 2*l;
+ size_t j=3, jc=ip-3;
+ for (; j<ipph-3; j+=4,jc-=4) // 126
+ {
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar1=csarr[2*iang], ai1=csarr[2*iang+1];
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar2=csarr[2*iang], ai2=csarr[2*iang+1];
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar3=csarr[2*iang], ai3=csarr[2*iang+1];
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar4=csarr[2*iang], ai4=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik) // 125
+ {
+ CH2(ik,l ) += ar1*C2(ik,j )+ar2*C2(ik,j +1)
+ +ar3*C2(ik,j +2)+ar4*C2(ik,j +3);
+ CH2(ik,lc) += ai1*C2(ik,jc)+ai2*C2(ik,jc-1)
+ +ai3*C2(ik,jc-2)+ai4*C2(ik,jc-3);
+ }
+ }
+ for (; j<ipph-1; j+=2,jc-=2) // 126
+ {
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar1=csarr[2*iang], ai1=csarr[2*iang+1];
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar2=csarr[2*iang], ai2=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik) // 125
+ {
+ CH2(ik,l ) += ar1*C2(ik,j )+ar2*C2(ik,j +1);
+ CH2(ik,lc) += ai1*C2(ik,jc)+ai2*C2(ik,jc-1);
+ }
+ }
+ for (; j<ipph; ++j,--jc) // 126
+ {
+ iang+=l; if (iang>=ip) iang-=ip;
+ double ar=csarr[2*iang], ai=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik) // 125
+ {
+ CH2(ik,l ) += ar*C2(ik,j );
+ CH2(ik,lc) += ai*C2(ik,jc);
+ }
+ }
+ }
+ for (size_t ik=0; ik<idl1; ++ik) // 101
+ CH2(ik,0) = C2(ik,0);
+ for (size_t j=1; j<ipph; ++j) // 129
+ for (size_t ik=0; ik<idl1; ++ik) // 128
+ CH2(ik,0) += C2(ik,j);
+
+// everything in CH at this point!
+//memset(cc,0,ip*l1*ido*sizeof(double));
+
+ for (size_t k=0; k<l1; ++k) // 131
+ for (size_t i=0; i<ido; ++i) // 130
+ CC(i,0,k) = CH(i,k,0);
+
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 137
+ {
+ size_t j2=2*j-1;
+ for (size_t k=0; k<l1; ++k) // 136
+ {
+ CC(ido-1,j2,k) = CH(0,k,j);
+ CC(0,j2+1,k) = CH(0,k,jc);
+ }
+ }
+
+ if (ido==1) return;
+
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 140
+ {
+ size_t j2=2*j-1;
+ for(size_t k=0; k<l1; ++k) // 139
+ for(size_t i=1, ic=ido-i-2; i<=ido-2; i+=2, ic-=2) // 138
+ {
+ CC(i ,j2+1,k) = CH(i ,k,j )+CH(i ,k,jc);
+ CC(ic ,j2 ,k) = CH(i ,k,j )-CH(i ,k,jc);
+ CC(i+1 ,j2+1,k) = CH(i+1,k,j )+CH(i+1,k,jc);
+ CC(ic+1,j2 ,k) = CH(i+1,k,jc)-CH(i+1,k,j );
+ }
+ }
+ }
+#undef C1
+#undef C2
+#undef CH2
+
+#undef CH
+#undef CC
+#define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))]
+#define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))]
+
+NOINLINE static void radb2(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=2;
+
+ for (size_t k=0; k<l1; k++)
+ PM (CH(0,k,0),CH(0,k,1),CC(0,0,k),CC(ido-1,1,k))
+ if ((ido&1)==0)
+ for (size_t k=0; k<l1; k++)
+ {
+ CH(ido-1,k,0) = 2.*CC(ido-1,0,k);
+ CH(ido-1,k,1) =-2.*CC(0 ,1,k);
+ }
+ if (ido<=2) return;
+ for (size_t k=0; k<l1;++k)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double ti2, tr2;
+ PM (CH(i-1,k,0),tr2,CC(i-1,0,k),CC(ic-1,1,k))
+ PM (ti2,CH(i ,k,0),CC(i ,0,k),CC(ic ,1,k))
+ MULPM (CH(i,k,1),CH(i-1,k,1),WA(0,i-2),WA(0,i-1),ti2,tr2)
+ }
+ }
+
+NOINLINE static void radb3(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=3;
+ static const double taur=-0.5, taui=0.86602540378443864676;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double tr2=2.*CC(ido-1,1,k);
+ double cr2=CC(0,0,k)+taur*tr2;
+ CH(0,k,0)=CC(0,0,k)+tr2;
+ double ci3=2.*taui*CC(0,2,k);
+ PM (CH(0,k,2),CH(0,k,1),cr2,ci3);
+ }
+ if (ido==1) return;
+ for (size_t k=0; k<l1; k++)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double tr2=CC(i-1,2,k)+CC(ic-1,1,k); // t2=CC(I) + conj(CC(ic))
+ double ti2=CC(i ,2,k)-CC(ic ,1,k);
+ double cr2=CC(i-1,0,k)+taur*tr2; // c2=CC +taur*t2
+ double ci2=CC(i ,0,k)+taur*ti2;
+ CH(i-1,k,0)=CC(i-1,0,k)+tr2; // CH=CC+t2
+ CH(i ,k,0)=CC(i ,0,k)+ti2;
+ double cr3=taui*(CC(i-1,2,k)-CC(ic-1,1,k));// c3=taui*(CC(i)-conj(CC(ic)))
+ double ci3=taui*(CC(i ,2,k)+CC(ic ,1,k));
+ double di2, di3, dr2, dr3;
+ PM(dr3,dr2,cr2,ci3) // d2= (cr2-ci3, ci2+cr3) = c2+i*c3
+ PM(di2,di3,ci2,cr3) // d3= (cr2+ci3, ci2-cr3) = c2-i*c3
+ MULPM(CH(i,k,1),CH(i-1,k,1),WA(0,i-2),WA(0,i-1),di2,dr2) // ch = WA*d2
+ MULPM(CH(i,k,2),CH(i-1,k,2),WA(1,i-2),WA(1,i-1),di3,dr3)
+ }
+ }
+
+NOINLINE static void radb4(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=4;
+ static const double sqrt2=1.41421356237309504880;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double tr1, tr2;
+ PM (tr2,tr1,CC(0,0,k),CC(ido-1,3,k))
+ double tr3=2.*CC(ido-1,1,k);
+ double tr4=2.*CC(0,2,k);
+ PM (CH(0,k,0),CH(0,k,2),tr2,tr3)
+ PM (CH(0,k,3),CH(0,k,1),tr1,tr4)
+ }
+ if ((ido&1)==0)
+ for (size_t k=0; k<l1; k++)
+ {
+ double tr1,tr2,ti1,ti2;
+ PM (ti1,ti2,CC(0 ,3,k),CC(0 ,1,k))
+ PM (tr2,tr1,CC(ido-1,0,k),CC(ido-1,2,k))
+ CH(ido-1,k,0)=tr2+tr2;
+ CH(ido-1,k,1)=sqrt2*(tr1-ti1);
+ CH(ido-1,k,2)=ti2+ti2;
+ CH(ido-1,k,3)=-sqrt2*(tr1+ti1);
+ }
+ if (ido<=2) return;
+ for (size_t k=0; k<l1;++k)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
+ size_t ic=ido-i;
+ PM (tr2,tr1,CC(i-1,0,k),CC(ic-1,3,k))
+ PM (ti1,ti2,CC(i ,0,k),CC(ic ,3,k))
+ PM (tr4,ti3,CC(i ,2,k),CC(ic ,1,k))
+ PM (tr3,ti4,CC(i-1,2,k),CC(ic-1,1,k))
+ PM (CH(i-1,k,0),cr3,tr2,tr3)
+ PM (CH(i ,k,0),ci3,ti2,ti3)
+ PM (cr4,cr2,tr1,tr4)
+ PM (ci2,ci4,ti1,ti4)
+ MULPM (CH(i,k,1),CH(i-1,k,1),WA(0,i-2),WA(0,i-1),ci2,cr2)
+ MULPM (CH(i,k,2),CH(i-1,k,2),WA(1,i-2),WA(1,i-1),ci3,cr3)
+ MULPM (CH(i,k,3),CH(i-1,k,3),WA(2,i-2),WA(2,i-1),ci4,cr4)
+ }
+ }
+
+NOINLINE static void radb5(size_t ido, size_t l1, const double * restrict cc,
+ double * restrict ch, const double * restrict wa)
+ {
+ const size_t cdim=5;
+ static const double tr11= 0.3090169943749474241, ti11=0.95105651629515357212,
+ tr12=-0.8090169943749474241, ti12=0.58778525229247312917;
+
+ for (size_t k=0; k<l1; k++)
+ {
+ double ti5=CC(0,2,k)+CC(0,2,k);
+ double ti4=CC(0,4,k)+CC(0,4,k);
+ double tr2=CC(ido-1,1,k)+CC(ido-1,1,k);
+ double tr3=CC(ido-1,3,k)+CC(ido-1,3,k);
+ CH(0,k,0)=CC(0,0,k)+tr2+tr3;
+ double cr2=CC(0,0,k)+tr11*tr2+tr12*tr3;
+ double cr3=CC(0,0,k)+tr12*tr2+tr11*tr3;
+ double ci4, ci5;
+ MULPM(ci5,ci4,ti5,ti4,ti11,ti12)
+ PM(CH(0,k,4),CH(0,k,1),cr2,ci5)
+ PM(CH(0,k,3),CH(0,k,2),cr3,ci4)
+ }
+ if (ido==1) return;
+ for (size_t k=0; k<l1;++k)
+ for (size_t i=2; i<ido; i+=2)
+ {
+ size_t ic=ido-i;
+ double tr2, tr3, tr4, tr5, ti2, ti3, ti4, ti5;
+ PM(tr2,tr5,CC(i-1,2,k),CC(ic-1,1,k))
+ PM(ti5,ti2,CC(i ,2,k),CC(ic ,1,k))
+ PM(tr3,tr4,CC(i-1,4,k),CC(ic-1,3,k))
+ PM(ti4,ti3,CC(i ,4,k),CC(ic ,3,k))
+ CH(i-1,k,0)=CC(i-1,0,k)+tr2+tr3;
+ CH(i ,k,0)=CC(i ,0,k)+ti2+ti3;
+ double cr2=CC(i-1,0,k)+tr11*tr2+tr12*tr3;
+ double ci2=CC(i ,0,k)+tr11*ti2+tr12*ti3;
+ double cr3=CC(i-1,0,k)+tr12*tr2+tr11*tr3;
+ double ci3=CC(i ,0,k)+tr12*ti2+tr11*ti3;
+ double ci4, ci5, cr5, cr4;
+ MULPM(cr5,cr4,tr5,tr4,ti11,ti12)
+ MULPM(ci5,ci4,ti5,ti4,ti11,ti12)
+ double dr2, dr3, dr4, dr5, di2, di3, di4, di5;
+ PM(dr4,dr3,cr3,ci4)
+ PM(di3,di4,ci3,cr4)
+ PM(dr5,dr2,cr2,ci5)
+ PM(di2,di5,ci2,cr5)
+ MULPM(CH(i,k,1),CH(i-1,k,1),WA(0,i-2),WA(0,i-1),di2,dr2)
+ MULPM(CH(i,k,2),CH(i-1,k,2),WA(1,i-2),WA(1,i-1),di3,dr3)
+ MULPM(CH(i,k,3),CH(i-1,k,3),WA(2,i-2),WA(2,i-1),di4,dr4)
+ MULPM(CH(i,k,4),CH(i-1,k,4),WA(3,i-2),WA(3,i-1),di5,dr5)
+ }
+ }
+
+#undef CC
+#undef CH
+#define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))]
+#define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))]
+#define C1(a,b,c) cc[(a)+ido*((b)+l1*(c))]
+#define C2(a,b) cc[(a)+idl1*(b)]
+#define CH2(a,b) ch[(a)+idl1*(b)]
+
+NOINLINE static void radbg(size_t ido, size_t ip, size_t l1,
+ double * restrict cc, double * restrict ch, const double * restrict wa,
+ const double * restrict csarr)
+ {
+ const size_t cdim=ip;
+ size_t ipph=(ip+1)/ 2;
+ size_t idl1 = ido*l1;
+
+ for (size_t k=0; k<l1; ++k) // 102
+ for (size_t i=0; i<ido; ++i) // 101
+ CH(i,k,0) = CC(i,0,k);
+ for (size_t j=1, jc=ip-1; j<ipph; ++j, --jc) // 108
+ {
+ size_t j2=2*j-1;
+ for (size_t k=0; k<l1; ++k)
+ {
+ CH(0,k,j ) = 2*CC(ido-1,j2,k);
+ CH(0,k,jc) = 2*CC(0,j2+1,k);
+ }
+ }
+
+ if (ido!=1)
+ {
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 111
+ {
+ size_t j2=2*j-1;
+ for (size_t k=0; k<l1; ++k)
+ for (size_t i=1, ic=ido-i-2; i<=ido-2; i+=2, ic-=2) // 109
+ {
+ CH(i ,k,j ) = CC(i ,j2+1,k)+CC(ic ,j2,k);
+ CH(i ,k,jc) = CC(i ,j2+1,k)-CC(ic ,j2,k);
+ CH(i+1,k,j ) = CC(i+1,j2+1,k)-CC(ic+1,j2,k);
+ CH(i+1,k,jc) = CC(i+1,j2+1,k)+CC(ic+1,j2,k);
+ }
+ }
+ }
+ for (size_t l=1,lc=ip-1; l<ipph; ++l,--lc)
+ {
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ C2(ik,l ) = CH2(ik,0)+csarr[2*l]*CH2(ik,1)+csarr[4*l]*CH2(ik,2);
+ C2(ik,lc) = csarr[2*l+1]*CH2(ik,ip-1)+csarr[4*l+1]*CH2(ik,ip-2);
+ }
+ size_t iang=2*l;
+ size_t j=3,jc=ip-3;
+ for(; j<ipph-3; j+=4,jc-=4)
+ {
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar1=csarr[2*iang], ai1=csarr[2*iang+1];
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar2=csarr[2*iang], ai2=csarr[2*iang+1];
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar3=csarr[2*iang], ai3=csarr[2*iang+1];
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar4=csarr[2*iang], ai4=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ C2(ik,l ) += ar1*CH2(ik,j )+ar2*CH2(ik,j +1)
+ +ar3*CH2(ik,j +2)+ar4*CH2(ik,j +3);
+ C2(ik,lc) += ai1*CH2(ik,jc)+ai2*CH2(ik,jc-1)
+ +ai3*CH2(ik,jc-2)+ai4*CH2(ik,jc-3);
+ }
+ }
+ for(; j<ipph-1; j+=2,jc-=2)
+ {
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar1=csarr[2*iang], ai1=csarr[2*iang+1];
+ iang+=l; if(iang>ip) iang-=ip;
+ double ar2=csarr[2*iang], ai2=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ C2(ik,l ) += ar1*CH2(ik,j )+ar2*CH2(ik,j +1);
+ C2(ik,lc) += ai1*CH2(ik,jc)+ai2*CH2(ik,jc-1);
+ }
+ }
+ for(; j<ipph; ++j,--jc)
+ {
+ iang+=l; if(iang>ip) iang-=ip;
+ double war=csarr[2*iang], wai=csarr[2*iang+1];
+ for (size_t ik=0; ik<idl1; ++ik)
+ {
+ C2(ik,l ) += war*CH2(ik,j );
+ C2(ik,lc) += wai*CH2(ik,jc);
+ }
+ }
+ }
+ for (size_t j=1; j<ipph; ++j)
+ for (size_t ik=0; ik<idl1; ++ik)
+ CH2(ik,0) += CH2(ik,j);
+ for (size_t j=1, jc=ip-1; j<ipph; ++j,--jc) // 124
+ for (size_t k=0; k<l1; ++k)
+ {
+ CH(0,k,j ) = C1(0,k,j)-C1(0,k,jc);
+ CH(0,k,jc) = C1(0,k,j)+C1(0,k,jc);
+ }
+
+ if (ido==1) return;
+
+ for (size_t j=1, jc=ip-1; j<ipph; ++j, --jc) // 127
+ for (size_t k=0; k<l1; ++k)
+ for (size_t i=1; i<=ido-2; i+=2)
+ {
+ CH(i ,k,j ) = C1(i ,k,j)-C1(i+1,k,jc);
+ CH(i ,k,jc) = C1(i ,k,j)+C1(i+1,k,jc);
+ CH(i+1,k,j ) = C1(i+1,k,j)+C1(i ,k,jc);
+ CH(i+1,k,jc) = C1(i+1,k,j)-C1(i ,k,jc);
+ }
+
+// All in CH
+
+ for (size_t j=1; j<ip; ++j)
+ {
+ size_t is = (j-1)*(ido-1);
+ for (size_t k=0; k<l1; ++k)
+ {
+ size_t idij = is;
+ for (size_t i=1; i<=ido-2; i+=2)
+ {
+ double t1=CH(i,k,j), t2=CH(i+1,k,j);
+ CH(i ,k,j) = wa[idij]*t1-wa[idij+1]*t2;
+ CH(i+1,k,j) = wa[idij]*t2+wa[idij+1]*t1;
+ idij+=2;
+ }
+ }
+ }
+ }
+#undef C1
+#undef C2
+#undef CH2
+
+#undef CC
+#undef CH
+#undef PM
+#undef MULPM
+#undef WA
+
+static void copy_and_norm(double *c, double *p1, size_t n, double fct)
+ {
+ if (p1!=c)
+ {
+ if (fct!=1.)
+ for (size_t i=0; i<n; ++i)
+ c[i] = fct*p1[i];
+ else
+ memcpy (c,p1,n*sizeof(double));
+ }
+ else
+ if (fct!=1.)
+ for (size_t i=0; i<n; ++i)
+ c[i] *= fct;
+ }
+
+WARN_UNUSED_RESULT
+static int rfftp_forward(rfftp_plan plan, double c[], double fct)
+ {
+ if (plan->length==1) return 0;
+ size_t n=plan->length;
+ size_t l1=n, nf=plan->nfct;
+ double *ch = RALLOC(double, n);
+ if (!ch) return -1;
+ double *p1=c, *p2=ch;
+
+ for(size_t k1=0; k1<nf;++k1)
+ {
+ size_t k=nf-k1-1;
+ size_t ip=plan->fct[k].fct;
+ size_t ido=n / l1;
+ l1 /= ip;
+ if(ip==4)
+ radf4(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==2)
+ radf2(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==3)
+ radf3(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==5)
+ radf5(ido, l1, p1, p2, plan->fct[k].tw);
+ else
+ {
+ radfg(ido, ip, l1, p1, p2, plan->fct[k].tw, plan->fct[k].tws);
+ SWAP (p1,p2,double *);
+ }
+ SWAP (p1,p2,double *);
+ }
+ copy_and_norm(c,p1,n,fct);
+ DEALLOC(ch);
+ return 0;
+ }
+
+WARN_UNUSED_RESULT
+static int rfftp_backward(rfftp_plan plan, double c[], double fct)
+ {
+ if (plan->length==1) return 0;
+ size_t n=plan->length;
+ size_t l1=1, nf=plan->nfct;
+ double *ch = RALLOC(double, n);
+ if (!ch) return -1;
+ double *p1=c, *p2=ch;
+
+ for(size_t k=0; k<nf; k++)
+ {
+ size_t ip = plan->fct[k].fct,
+ ido= n/(ip*l1);
+ if(ip==4)
+ radb4(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==2)
+ radb2(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==3)
+ radb3(ido, l1, p1, p2, plan->fct[k].tw);
+ else if(ip==5)
+ radb5(ido, l1, p1, p2, plan->fct[k].tw);
+ else
+ radbg(ido, ip, l1, p1, p2, plan->fct[k].tw, plan->fct[k].tws);
+ SWAP (p1,p2,double *);
+ l1*=ip;
+ }
+ copy_and_norm(c,p1,n,fct);
+ DEALLOC(ch);
+ return 0;
+ }
+
+WARN_UNUSED_RESULT
+static int rfftp_factorize (rfftp_plan plan)
+ {
+ size_t length=plan->length;
+ size_t nfct=0;
+ while ((length%4)==0)
+ { if (nfct>=NFCT) return -1; plan->fct[nfct++].fct=4; length>>=2; }
+ if ((length%2)==0)
+ {
+ length>>=1;
+ // factor 2 should be at the front of the factor list
+ if (nfct>=NFCT) return -1;
+ plan->fct[nfct++].fct=2;
+ SWAP(plan->fct[0].fct, plan->fct[nfct-1].fct,size_t);
+ }
+ size_t maxl=(size_t)(sqrt((double)length))+1;
+ for (size_t divisor=3; (length>1)&&(divisor<maxl); divisor+=2)
+ if ((length%divisor)==0)
+ {
+ while ((length%divisor)==0)
+ {
+ if (nfct>=NFCT) return -1;
+ plan->fct[nfct++].fct=divisor;
+ length/=divisor;
+ }
+ maxl=(size_t)(sqrt((double)length))+1;
+ }
+ if (length>1) plan->fct[nfct++].fct=length;
+ plan->nfct=nfct;
+ return 0;
+ }
+
+static size_t rfftp_twsize(rfftp_plan plan)
+ {
+ size_t twsize=0, l1=1;
+ for (size_t k=0; k<plan->nfct; ++k)
+ {
+ size_t ip=plan->fct[k].fct, ido= plan->length/(l1*ip);
+ twsize+=(ip-1)*(ido-1);
+ if (ip>5) twsize+=2*ip;
+ l1*=ip;
+ }
+ return twsize;
+ return 0;
+ }
+
+WARN_UNUSED_RESULT NOINLINE static int rfftp_comp_twiddle (rfftp_plan plan)
+ {
+ size_t length=plan->length;
+ double *twid = RALLOC(double, 2*length);
+ if (!twid) return -1;
+ sincos_2pibyn_half(length, twid);
+ size_t l1=1;
+ double *ptr=plan->mem;
+ for (size_t k=0; k<plan->nfct; ++k)
+ {
+ size_t ip=plan->fct[k].fct, ido=length/(l1*ip);
+ if (k<plan->nfct-1) // last factor doesn't need twiddles
+ {
+ plan->fct[k].tw=ptr; ptr+=(ip-1)*(ido-1);
+ for (size_t j=1; j<ip; ++j)
+ for (size_t i=1; i<=(ido-1)/2; ++i)
+ {
+ plan->fct[k].tw[(j-1)*(ido-1)+2*i-2] = twid[2*j*l1*i];
+ plan->fct[k].tw[(j-1)*(ido-1)+2*i-1] = twid[2*j*l1*i+1];
+ }
+ }
+ if (ip>5) // special factors required by *g functions
+ {
+ plan->fct[k].tws=ptr; ptr+=2*ip;
+ plan->fct[k].tws[0] = 1.;
+ plan->fct[k].tws[1] = 0.;
+ for (size_t i=1; i<=(ip>>1); ++i)
+ {
+ plan->fct[k].tws[2*i ] = twid[2*i*(length/ip)];
+ plan->fct[k].tws[2*i+1] = twid[2*i*(length/ip)+1];
+ plan->fct[k].tws[2*(ip-i) ] = twid[2*i*(length/ip)];
+ plan->fct[k].tws[2*(ip-i)+1] = -twid[2*i*(length/ip)+1];
+ }
+ }
+ l1*=ip;
+ }
+ DEALLOC(twid);
+ return 0;
+ }
+
+NOINLINE static rfftp_plan make_rfftp_plan (size_t length)
+ {
+ if (length==0) return NULL;
+ rfftp_plan plan = RALLOC(rfftp_plan_i,1);
+ if (!plan) return NULL;
+ plan->length=length;
+ plan->nfct=0;
+ plan->mem=NULL;
+ for (size_t i=0; i<NFCT; ++i)
+ plan->fct[i]=(rfftp_fctdata){0,0,0};
+ if (length==1) return plan;
+ if (rfftp_factorize(plan)!=0) { DEALLOC(plan); return NULL; }
+ size_t tws=rfftp_twsize(plan);
+ plan->mem=RALLOC(double,tws);
+ if (!plan->mem) { DEALLOC(plan); return NULL; }
+ if (rfftp_comp_twiddle(plan)!=0)
+ { DEALLOC(plan->mem); DEALLOC(plan); return NULL; }
+ return plan;
+ }
+
+NOINLINE static void destroy_rfftp_plan (rfftp_plan plan)
+ {
+ DEALLOC(plan->mem);
+ DEALLOC(plan);
+ }
+
+typedef struct fftblue_plan_i
+ {
+ size_t n, n2;
+ cfftp_plan plan;
+ double *mem;
+ double *bk, *bkf;
+ } fftblue_plan_i;
+typedef struct fftblue_plan_i * fftblue_plan;
+
+NOINLINE static fftblue_plan make_fftblue_plan (size_t length)
+ {
+ fftblue_plan plan = RALLOC(fftblue_plan_i,1);
+ if (!plan) return NULL;
+ plan->n = length;
+ plan->n2 = good_size(plan->n*2-1);
+ plan->mem = RALLOC(double, 2*plan->n+2*plan->n2);
+ if (!plan->mem) { DEALLOC(plan); return NULL; }
+ plan->bk = plan->mem;
+ plan->bkf = plan->bk+2*plan->n;
+
+/* initialize b_k */
+ double *tmp = RALLOC(double,4*plan->n);
+ if (!tmp) { DEALLOC(plan->mem); DEALLOC(plan); return NULL; }
+ sincos_2pibyn(2*plan->n,tmp);
+ plan->bk[0] = 1;
+ plan->bk[1] = 0;
+
+ size_t coeff=0;
+ for (size_t m=1; m<plan->n; ++m)
+ {
+ coeff+=2*m-1;
+ if (coeff>=2*plan->n) coeff-=2*plan->n;
+ plan->bk[2*m ] = tmp[2*coeff ];
+ plan->bk[2*m+1] = tmp[2*coeff+1];
+ }
+
+ /* initialize the zero-padded, Fourier transformed b_k. Add normalisation. */
+ double xn2 = 1./plan->n2;
+ plan->bkf[0] = plan->bk[0]*xn2;
+ plan->bkf[1] = plan->bk[1]*xn2;
+ for (size_t m=2; m<2*plan->n; m+=2)
+ {
+ plan->bkf[m] = plan->bkf[2*plan->n2-m] = plan->bk[m] *xn2;
+ plan->bkf[m+1] = plan->bkf[2*plan->n2-m+1] = plan->bk[m+1] *xn2;
+ }
+ for (size_t m=2*plan->n;m<=(2*plan->n2-2*plan->n+1);++m)
+ plan->bkf[m]=0.;
+ plan->plan=make_cfftp_plan(plan->n2);
+ if (!plan->plan)
+ { DEALLOC(tmp); DEALLOC(plan->mem); DEALLOC(plan); return NULL; }
+ if (cfftp_forward(plan->plan,plan->bkf,1.)!=0)
+ { DEALLOC(tmp); DEALLOC(plan->mem); DEALLOC(plan); return NULL; }
+ DEALLOC(tmp);
+
+ return plan;
+ }
+
+NOINLINE static void destroy_fftblue_plan (fftblue_plan plan)
+ {
+ DEALLOC(plan->mem);
+ destroy_cfftp_plan(plan->plan);
+ DEALLOC(plan);
+ }
+
+NOINLINE WARN_UNUSED_RESULT
+static int fftblue_fft(fftblue_plan plan, double c[], int isign, double fct)
+ {
+ size_t n=plan->n;
+ size_t n2=plan->n2;
+ double *bk = plan->bk;
+ double *bkf = plan->bkf;
+ double *akf = RALLOC(double, 2*n2);
+ if (!akf) return -1;
+
+/* initialize a_k and FFT it */
+ if (isign>0)
+ for (size_t m=0; m<2*n; m+=2)
+ {
+ akf[m] = c[m]*bk[m] - c[m+1]*bk[m+1];
+ akf[m+1] = c[m]*bk[m+1] + c[m+1]*bk[m];
+ }
+ else
+ for (size_t m=0; m<2*n; m+=2)
+ {
+ akf[m] = c[m]*bk[m] + c[m+1]*bk[m+1];
+ akf[m+1] =-c[m]*bk[m+1] + c[m+1]*bk[m];
+ }
+ for (size_t m=2*n; m<2*n2; ++m)
+ akf[m]=0;
+
+ if (cfftp_forward (plan->plan,akf,fct)!=0)
+ { DEALLOC(akf); return -1; }
+
+/* do the convolution */
+ if (isign>0)
+ for (size_t m=0; m<2*n2; m+=2)
+ {
+ double im = -akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
+ akf[m ] = akf[m]*bkf[m] + akf[m+1]*bkf[m+1];
+ akf[m+1] = im;
+ }
+ else
+ for (size_t m=0; m<2*n2; m+=2)
+ {
+ double im = akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
+ akf[m ] = akf[m]*bkf[m] - akf[m+1]*bkf[m+1];
+ akf[m+1] = im;
+ }
+
+/* inverse FFT */
+ if (cfftp_backward (plan->plan,akf,1.)!=0)
+ { DEALLOC(akf); return -1; }
+
+/* multiply by b_k */
+ if (isign>0)
+ for (size_t m=0; m<2*n; m+=2)
+ {
+ c[m] = bk[m] *akf[m] - bk[m+1]*akf[m+1];
+ c[m+1] = bk[m+1]*akf[m] + bk[m] *akf[m+1];
+ }
+ else
+ for (size_t m=0; m<2*n; m+=2)
+ {
+ c[m] = bk[m] *akf[m] + bk[m+1]*akf[m+1];
+ c[m+1] =-bk[m+1]*akf[m] + bk[m] *akf[m+1];
+ }
+ DEALLOC(akf);
+ return 0;
+ }
+
+WARN_UNUSED_RESULT
+static int cfftblue_backward(fftblue_plan plan, double c[], double fct)
+ { return fftblue_fft(plan,c,1,fct); }
+
+WARN_UNUSED_RESULT
+static int cfftblue_forward(fftblue_plan plan, double c[], double fct)
+ { return fftblue_fft(plan,c,-1,fct); }
+
+WARN_UNUSED_RESULT
+static int rfftblue_backward(fftblue_plan plan, double c[], double fct)
+ {
+ size_t n=plan->n;
+ double *tmp = RALLOC(double,2*n);
+ if (!tmp) return -1;
+ tmp[0]=c[0];
+ tmp[1]=0.;
+ memcpy (tmp+2,c+1, (n-1)*sizeof(double));
+ if ((n&1)==0) tmp[n+1]=0.;
+ for (size_t m=2; m<n; m+=2)
+ {
+ tmp[2*n-m]=tmp[m];
+ tmp[2*n-m+1]=-tmp[m+1];
+ }
+ if (fftblue_fft(plan,tmp,1,fct)!=0)
+ { DEALLOC(tmp); return -1; }
+ for (size_t m=0; m<n; ++m)
+ c[m] = tmp[2*m];
+ DEALLOC(tmp);
+ return 0;
+ }
+
+WARN_UNUSED_RESULT
+static int rfftblue_forward(fftblue_plan plan, double c[], double fct)
+ {
+ size_t n=plan->n;
+ double *tmp = RALLOC(double,2*n);
+ if (!tmp) return -1;
+ for (size_t m=0; m<n; ++m)
+ {
+ tmp[2*m] = c[m];
+ tmp[2*m+1] = 0.;
+ }
+ if (fftblue_fft(plan,tmp,-1,fct)!=0)
+ { DEALLOC(tmp); return -1; }
+ c[0] = tmp[0];
+ memcpy (c+1, tmp+2, (n-1)*sizeof(double));
+ DEALLOC(tmp);
+ return 0;
+ }
+
+typedef struct cfft_plan_i
+ {
+ cfftp_plan packplan;
+ fftblue_plan blueplan;
+ } cfft_plan_i;
+
+static cfft_plan make_cfft_plan (size_t length)
+ {
+ if (length==0) return NULL;
+ cfft_plan plan = RALLOC(cfft_plan_i,1);
+ if (!plan) return NULL;
+ plan->blueplan=0;
+ plan->packplan=0;
+ if ((length<50) || (largest_prime_factor(length)<=sqrt(length)))
+ {
+ plan->packplan=make_cfftp_plan(length);
+ if (!plan->packplan) { DEALLOC(plan); return NULL; }
+ return plan;
+ }
+ double comp1 = cost_guess(length);
+ double comp2 = 2*cost_guess(good_size(2*length-1));
+ comp2*=1.5; /* fudge factor that appears to give good overall performance */
+ if (comp2<comp1) // use Bluestein
+ {
+ plan->blueplan=make_fftblue_plan(length);
+ if (!plan->blueplan) { DEALLOC(plan); return NULL; }
+ }
+ else
+ {
+ plan->packplan=make_cfftp_plan(length);
+ if (!plan->packplan) { DEALLOC(plan); return NULL; }
+ }
+ return plan;
+ }
+
+static void destroy_cfft_plan (cfft_plan plan)
+ {
+ if (plan->blueplan)
+ destroy_fftblue_plan(plan->blueplan);
+ if (plan->packplan)
+ destroy_cfftp_plan(plan->packplan);
+ DEALLOC(plan);
+ }
+
+WARN_UNUSED_RESULT static int cfft_backward(cfft_plan plan, double c[], double fct)
+ {
+ if (plan->packplan)
+ return cfftp_backward(plan->packplan,c,fct);
+ // if (plan->blueplan)
+ return cfftblue_backward(plan->blueplan,c,fct);
+ }
+
+WARN_UNUSED_RESULT static int cfft_forward(cfft_plan plan, double c[], double fct)
+ {
+ if (plan->packplan)
+ return cfftp_forward(plan->packplan,c,fct);
+ // if (plan->blueplan)
+ return cfftblue_forward(plan->blueplan,c,fct);
+ }
+
+typedef struct rfft_plan_i
+ {
+ rfftp_plan packplan;
+ fftblue_plan blueplan;
+ } rfft_plan_i;
+
+static rfft_plan make_rfft_plan (size_t length)
+ {
+ if (length==0) return NULL;
+ rfft_plan plan = RALLOC(rfft_plan_i,1);
+ if (!plan) return NULL;
+ plan->blueplan=0;
+ plan->packplan=0;
+ if ((length<50) || (largest_prime_factor(length)<=sqrt(length)))
+ {
+ plan->packplan=make_rfftp_plan(length);
+ if (!plan->packplan) { DEALLOC(plan); return NULL; }
+ return plan;
+ }
+ double comp1 = 0.5*cost_guess(length);
+ double comp2 = 2*cost_guess(good_size(2*length-1));
+ comp2*=1.5; /* fudge factor that appears to give good overall performance */
+ if (comp2<comp1) // use Bluestein
+ {
+ plan->blueplan=make_fftblue_plan(length);
+ if (!plan->blueplan) { DEALLOC(plan); return NULL; }
+ }
+ else
+ {
+ plan->packplan=make_rfftp_plan(length);
+ if (!plan->packplan) { DEALLOC(plan); return NULL; }
+ }
+ return plan;
+ }
+
+static void destroy_rfft_plan (rfft_plan plan)
+ {
+ if (plan->blueplan)
+ destroy_fftblue_plan(plan->blueplan);
+ if (plan->packplan)
+ destroy_rfftp_plan(plan->packplan);
+ DEALLOC(plan);
+ }
+
+WARN_UNUSED_RESULT static int rfft_backward(rfft_plan plan, double c[], double fct)
+ {
+ if (plan->packplan)
+ return rfftp_backward(plan->packplan,c,fct);
+ else // if (plan->blueplan)
+ return rfftblue_backward(plan->blueplan,c,fct);
+ }
+
+WARN_UNUSED_RESULT static int rfft_forward(rfft_plan plan, double c[], double fct)
+ {
+ if (plan->packplan)
+ return rfftp_forward(plan->packplan,c,fct);
+ else // if (plan->blueplan)
+ return rfftblue_forward(plan->blueplan,c,fct);
+ }
+
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include "Python.h"
+#include "numpy/arrayobject.h"
+
+static PyObject *
+execute_complex(PyObject *a1, int is_forward, double fct)
+{
+ PyArrayObject *data = (PyArrayObject *)PyArray_FromAny(a1,
+ PyArray_DescrFromType(NPY_CDOUBLE), 1, 0,
+ NPY_ARRAY_ENSURECOPY | NPY_ARRAY_DEFAULT |
+ NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST,
+ NULL);
+ if (!data) return NULL;
+
+ int npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
+ cfft_plan plan=NULL;
+
+ int nrepeats = PyArray_SIZE(data)/npts;
+ double *dptr = (double *)PyArray_DATA(data);
+ int fail=0;
+ Py_BEGIN_ALLOW_THREADS;
+ NPY_SIGINT_ON;
+ plan = make_cfft_plan(npts);
+ if (!plan) fail=1;
+ if (!fail)
+ for (int i = 0; i < nrepeats; i++) {
+ int res = is_forward ?
+ cfft_forward(plan, dptr, fct) : cfft_backward(plan, dptr, fct);
+ if (res!=0) { fail=1; break; }
+ dptr += npts*2;
+ }
+ if (plan) destroy_cfft_plan(plan);
+ NPY_SIGINT_OFF;
+ Py_END_ALLOW_THREADS;
+ if (fail) {
+ Py_XDECREF(data);
+ return PyErr_NoMemory();
+ }
+ return (PyObject *)data;
+}
+
+static PyObject *
+execute_real_forward(PyObject *a1, double fct)
+{
+ rfft_plan plan=NULL;
+ int fail = 0;
+ PyArrayObject *data = (PyArrayObject *)PyArray_FromAny(a1,
+ PyArray_DescrFromType(NPY_DOUBLE), 1, 0,
+ NPY_ARRAY_DEFAULT | NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST,
+ NULL);
+ if (!data) return NULL;
+
+ int ndim = PyArray_NDIM(data);
+ const npy_intp *odim = PyArray_DIMS(data);
+ int npts = odim[ndim - 1];
+ npy_intp *tdim=(npy_intp *)malloc(ndim*sizeof(npy_intp));
+ if (!tdim)
+ { Py_XDECREF(data); return NULL; }
+ for (int d=0; d<ndim-1; ++d)
+ tdim[d] = odim[d];
+ tdim[ndim-1] = npts/2 + 1;
+ PyArrayObject *ret = (PyArrayObject *)PyArray_Empty(ndim,
+ tdim, PyArray_DescrFromType(NPY_CDOUBLE), 0);
+ free(tdim);
+ if (!ret) fail=1;
+ if (!fail) {
+ int rstep = PyArray_DIM(ret, PyArray_NDIM(ret) - 1)*2;
+
+ int nrepeats = PyArray_SIZE(data)/npts;
+ double *rptr = (double *)PyArray_DATA(ret),
+ *dptr = (double *)PyArray_DATA(data);
+
+ Py_BEGIN_ALLOW_THREADS;
+ NPY_SIGINT_ON;
+ plan = make_rfft_plan(npts);
+ if (!plan) fail=1;
+ if (!fail)
+ for (int i = 0; i < nrepeats; i++) {
+ rptr[rstep-1] = 0.0;
+ memcpy((char *)(rptr+1), dptr, npts*sizeof(double));
+ if (rfft_forward(plan, rptr+1, fct)!=0) {fail=1; break;}
+ rptr[0] = rptr[1];
+ rptr[1] = 0.0;
+ rptr += rstep;
+ dptr += npts;
+ }
+ if (plan) destroy_rfft_plan(plan);
+ NPY_SIGINT_OFF;
+ Py_END_ALLOW_THREADS;
+ }
+ if (fail) {
+ Py_XDECREF(data);
+ Py_XDECREF(ret);
+ return PyErr_NoMemory();
+ }
+ Py_DECREF(data);
+ return (PyObject *)ret;
+}
+static PyObject *
+execute_real_backward(PyObject *a1, double fct)
+{
+ rfft_plan plan=NULL;
+ PyArrayObject *data = (PyArrayObject *)PyArray_FromAny(a1,
+ PyArray_DescrFromType(NPY_CDOUBLE), 1, 0,
+ NPY_ARRAY_DEFAULT | NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST,
+ NULL);
+ if (!data) return NULL;
+ int npts = PyArray_DIM(data, PyArray_NDIM(data) - 1);
+ PyArrayObject *ret = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(data),
+ PyArray_DIMS(data), PyArray_DescrFromType(NPY_DOUBLE), 0);
+ int fail = 0;
+ if (!ret) fail=1;
+ if (!fail) {
+ int nrepeats = PyArray_SIZE(ret)/npts;
+ double *rptr = (double *)PyArray_DATA(ret),
+ *dptr = (double *)PyArray_DATA(data);
+
+ Py_BEGIN_ALLOW_THREADS;
+ NPY_SIGINT_ON;
+ plan = make_rfft_plan(npts);
+ if (!plan) fail=1;
+ if (!fail) {
+ for (int i = 0; i < nrepeats; i++) {
+ memcpy((char *)(rptr + 1), (dptr + 2), (npts - 1)*sizeof(double));
+ rptr[0] = dptr[0];
+ if (rfft_backward(plan, rptr, fct)!=0) {fail=1; break;}
+ rptr += npts;
+ dptr += npts*2;
+ }
+ }
+ if (plan) destroy_rfft_plan(plan);
+ NPY_SIGINT_OFF;
+ Py_END_ALLOW_THREADS;
+ }
+ if (fail) {
+ Py_XDECREF(data);
+ Py_XDECREF(ret);
+ return PyErr_NoMemory();
+ }
+ Py_DECREF(data);
+ return (PyObject *)ret;
+}
+
+static PyObject *
+execute_real(PyObject *a1, int is_forward, double fct)
+{
+ return is_forward ? execute_real_forward(a1, fct)
+ : execute_real_backward(a1, fct);
+}
+
+static const char execute__doc__[] = "";
+
+static PyObject *
+execute(PyObject *NPY_UNUSED(self), PyObject *args)
+{
+ PyObject *a1;
+ int is_real, is_forward;
+ double fct;
+
+ if(!PyArg_ParseTuple(args, "Oiid:execute", &a1, &is_real, &is_forward, &fct)) {
+ return NULL;
+ }
+
+ return is_real ? execute_real(a1, is_forward, fct)
+ : execute_complex(a1, is_forward, fct);
+}
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef methods[] = {
+ {"execute", execute, 1, execute__doc__},
+ {NULL, NULL, 0, NULL} /* sentinel */
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "pocketfft_internal",
+ NULL,
+ -1,
+ methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+#endif
+
+/* Initialization function for the module */
+#if PY_MAJOR_VERSION >= 3
+#define RETVAL(x) x
+PyMODINIT_FUNC PyInit_pocketfft_internal(void)
+#else
+#define RETVAL(x)
+PyMODINIT_FUNC
+initpocketfft_internal(void)
+#endif
+{
+ PyObject *m;
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
+ static const char module_documentation[] = "";
+
+ m = Py_InitModule4("pocketfft_internal", methods,
+ module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+#endif
+ if (m == NULL) {
+ return RETVAL(NULL);
+ }
+
+ /* Import the array object */
+ import_array();
+
+ /* XXXX Add constants here */
+
+ return RETVAL(m);
+}
diff --git a/numpy/fft/fftpack.py b/numpy/fft/pocketfft.py
index de675936f..45dc162f6 100644
--- a/numpy/fft/fftpack.py
+++ b/numpy/fft/pocketfft.py
@@ -26,9 +26,6 @@ n = n-dimensional transform
(Note: 2D routines are just nD routines with different default
behavior.)
-The underlying code for these functions is an f2c-translated and modified
-version of the FFTPACK routines.
-
"""
from __future__ import division, absolute_import, print_function
@@ -37,26 +34,18 @@ __all__ = ['fft', 'ifft', 'rfft', 'irfft', 'hfft', 'ihfft', 'rfftn',
import functools
-from numpy.core import (array, asarray, zeros, swapaxes, shape, conjugate,
- take, sqrt)
+from numpy.core import asarray, zeros, swapaxes, conjugate, take, sqrt
+from . import pocketfft_internal as pfi
from numpy.core.multiarray import normalize_axis_index
from numpy.core import overrides
-from . import fftpack_lite as fftpack
-from .helper import _FFTCache
-
-_fft_cache = _FFTCache(max_size_in_mb=100, max_item_count=32)
-_real_fft_cache = _FFTCache(max_size_in_mb=100, max_item_count=32)
array_function_dispatch = functools.partial(
overrides.array_function_dispatch, module='numpy.fft')
-def _raw_fft(a, n=None, axis=-1, init_function=fftpack.cffti,
- work_function=fftpack.cfftf, fft_cache=_fft_cache):
- a = asarray(a)
+def _raw_fft(a, n, axis, is_real, is_forward, fct):
axis = normalize_axis_index(axis, a.ndim)
-
if n is None:
n = a.shape[axis]
@@ -64,15 +53,6 @@ def _raw_fft(a, n=None, axis=-1, init_function=fftpack.cffti,
raise ValueError("Invalid number of FFT data points (%d) specified."
% n)
- # We have to ensure that only a single thread can access a wsave array
- # at any given time. Thus we remove it from the cache and insert it
- # again after it has been used. Multiple threads might create multiple
- # copies of the wsave array. This is intentional and a limitation of
- # the current C code.
- wsave = fft_cache.pop_twiddle_factors(n)
- if wsave is None:
- wsave = init_function(n)
-
if a.shape[axis] != n:
s = list(a.shape)
if s[axis] > n:
@@ -87,25 +67,22 @@ def _raw_fft(a, n=None, axis=-1, init_function=fftpack.cffti,
z[tuple(index)] = a
a = z
- if axis != a.ndim - 1:
+ if axis == a.ndim-1:
+ r = pfi.execute(a, is_real, is_forward, fct)
+ else:
a = swapaxes(a, axis, -1)
- r = work_function(a, wsave)
- if axis != a.ndim - 1:
+ r = pfi.execute(a, is_real, is_forward, fct)
r = swapaxes(r, axis, -1)
-
- # As soon as we put wsave back into the cache, another thread could pick it
- # up and start using it, so we must not do this until after we're
- # completely done using it ourselves.
- fft_cache.put_twiddle_factors(n, wsave)
-
return r
def _unitary(norm):
- if norm not in (None, "ortho"):
- raise ValueError("Invalid norm value %s, should be None or \"ortho\"."
- % norm)
- return norm is not None
+ if norm is None:
+ return False
+ if norm=="ortho":
+ return True
+ raise ValueError("Invalid norm value %s, should be None or \"ortho\"."
+ % norm)
def _fft_dispatcher(a, n=None, axis=None, norm=None):
@@ -177,14 +154,10 @@ def fft(a, n=None, axis=-1, norm=None):
Examples
--------
>>> np.fft.fft(np.exp(2j * np.pi * np.arange(8) / 8))
- array([ -3.44505240e-16 +1.14383329e-17j,
- 8.00000000e+00 -5.71092652e-15j,
- 2.33482938e-16 +1.22460635e-16j,
- 1.64863782e-15 +1.77635684e-15j,
- 9.95839695e-17 +2.33482938e-16j,
- 0.00000000e+00 +1.66837030e-15j,
- 1.14383329e-17 +1.22460635e-16j,
- -1.64863782e-15 +1.77635684e-15j])
+ array([-2.33486982e-16+1.14423775e-17j, 8.00000000e+00-1.25557246e-15j,
+ 2.33486982e-16+2.33486982e-16j, 0.00000000e+00+1.22464680e-16j,
+ -1.14423775e-17+2.33486982e-16j, 0.00000000e+00+5.20784380e-16j,
+ 1.14423775e-17+1.14423775e-17j, 0.00000000e+00+1.22464680e-16j])
In this example, real input has an FFT which is Hermitian, i.e., symmetric
in the real part and anti-symmetric in the imaginary part, as described in
@@ -200,12 +173,13 @@ def fft(a, n=None, axis=-1, norm=None):
"""
- a = asarray(a).astype(complex, copy=False)
+ a = asarray(a)
if n is None:
n = a.shape[axis]
- output = _raw_fft(a, n, axis, fftpack.cffti, fftpack.cfftf, _fft_cache)
- if _unitary(norm):
- output *= 1 / sqrt(n)
+ fct = 1
+ if norm is not None and _unitary(norm):
+ fct = 1 / sqrt(n)
+ output = _raw_fft(a, n, axis, False, True, fct)
return output
@@ -278,7 +252,7 @@ def ifft(a, n=None, axis=-1, norm=None):
Examples
--------
>>> np.fft.ifft([0, 4, 0, 0])
- array([ 1.+0.j, 0.+1.j, -1.+0.j, 0.-1.j])
+ array([ 1.+0.j, 0.+1.j, -1.+0.j, 0.-1.j]) # may vary
Create and plot a band-limited signal with random phases:
@@ -288,19 +262,20 @@ def ifft(a, n=None, axis=-1, norm=None):
>>> n[40:60] = np.exp(1j*np.random.uniform(0, 2*np.pi, (20,)))
>>> s = np.fft.ifft(n)
>>> plt.plot(t, s.real, 'b-', t, s.imag, 'r--')
- ...
+ [<matplotlib.lines.Line2D object at ...>, <matplotlib.lines.Line2D object at ...>]
>>> plt.legend(('real', 'imaginary'))
- ...
+ <matplotlib.legend.Legend object at ...>
>>> plt.show()
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=complex)
+ a = asarray(a)
if n is None:
n = a.shape[axis]
- unitary = _unitary(norm)
- output = _raw_fft(a, n, axis, fftpack.cffti, fftpack.cfftb, _fft_cache)
- return output * (1 / (sqrt(n) if unitary else n))
+ fct = 1/n
+ if norm is not None and _unitary(norm):
+ fct = 1/sqrt(n)
+ output = _raw_fft(a, n, axis, False, False, fct)
+ return output
@@ -374,23 +349,22 @@ def rfft(a, n=None, axis=-1, norm=None):
Examples
--------
>>> np.fft.fft([0, 1, 0, 0])
- array([ 1.+0.j, 0.-1.j, -1.+0.j, 0.+1.j])
+ array([ 1.+0.j, 0.-1.j, -1.+0.j, 0.+1.j]) # may vary
>>> np.fft.rfft([0, 1, 0, 0])
- array([ 1.+0.j, 0.-1.j, -1.+0.j])
+ array([ 1.+0.j, 0.-1.j, -1.+0.j]) # may vary
Notice how the final element of the `fft` output is the complex conjugate
of the second element, for real input. For `rfft`, this symmetry is
exploited to compute only the non-negative frequency terms.
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=float)
- output = _raw_fft(a, n, axis, fftpack.rffti, fftpack.rfftf,
- _real_fft_cache)
- if _unitary(norm):
+ a = asarray(a)
+ fct = 1
+ if norm is not None and _unitary(norm):
if n is None:
n = a.shape[axis]
- output *= 1 / sqrt(n)
+ fct = 1/sqrt(n)
+ output = _raw_fft(a, n, axis, True, True, fct)
return output
@@ -465,9 +439,9 @@ def irfft(a, n=None, axis=-1, norm=None):
Examples
--------
>>> np.fft.ifft([1, -1j, -1, 1j])
- array([ 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j])
+ array([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]) # may vary
>>> np.fft.irfft([1, -1j, -1])
- array([ 0., 1., 0., 0.])
+ array([0., 1., 0., 0.])
Notice how the last term in the input to the ordinary `ifft` is the
complex conjugate of the second term, and the output has zero imaginary
@@ -475,14 +449,14 @@ def irfft(a, n=None, axis=-1, norm=None):
specified, and the output array is purely real.
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=complex)
+ a = asarray(a)
if n is None:
n = (a.shape[axis] - 1) * 2
- unitary = _unitary(norm)
- output = _raw_fft(a, n, axis, fftpack.rffti, fftpack.rfftb,
- _real_fft_cache)
- return output * (1 / (sqrt(n) if unitary else n))
+ fct = 1/n
+ if norm is not None and _unitary(norm):
+ fct = 1/sqrt(n)
+ output = _raw_fft(a, n, axis, True, False, fct)
+ return output
@array_function_dispatch(_fft_dispatcher)
@@ -543,16 +517,16 @@ def hfft(a, n=None, axis=-1, norm=None):
--------
>>> signal = np.array([1, 2, 3, 4, 3, 2])
>>> np.fft.fft(signal)
- array([ 15.+0.j, -4.+0.j, 0.+0.j, -1.-0.j, 0.+0.j, -4.+0.j])
+ array([15.+0.j, -4.+0.j, 0.+0.j, -1.-0.j, 0.+0.j, -4.+0.j]) # may vary
>>> np.fft.hfft(signal[:4]) # Input first half of signal
- array([ 15., -4., 0., -1., 0., -4.])
+ array([15., -4., 0., -1., 0., -4.])
>>> np.fft.hfft(signal, 6) # Input entire signal and truncate
- array([ 15., -4., 0., -1., 0., -4.])
+ array([15., -4., 0., -1., 0., -4.])
>>> signal = np.array([[1, 1.j], [-1.j, 2]])
>>> np.conj(signal.T) - signal # check Hermitian symmetry
- array([[ 0.-0.j, 0.+0.j],
+ array([[ 0.-0.j, -0.+0.j], # may vary
[ 0.+0.j, 0.-0.j]])
>>> freq_spectrum = np.fft.hfft(signal)
>>> freq_spectrum
@@ -560,8 +534,7 @@ def hfft(a, n=None, axis=-1, norm=None):
[ 2., -2.]])
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=complex)
+ a = asarray(a)
if n is None:
n = (a.shape[axis] - 1) * 2
unitary = _unitary(norm)
@@ -616,13 +589,12 @@ def ihfft(a, n=None, axis=-1, norm=None):
--------
>>> spectrum = np.array([ 15, -4, 0, -1, 0, -4])
>>> np.fft.ifft(spectrum)
- array([ 1.+0.j, 2.-0.j, 3.+0.j, 4.+0.j, 3.+0.j, 2.-0.j])
+ array([1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 3.+0.j, 2.+0.j]) # may vary
>>> np.fft.ihfft(spectrum)
- array([ 1.-0.j, 2.-0.j, 3.-0.j, 4.-0.j])
+ array([ 1.-0.j, 2.-0.j, 3.-0.j, 4.-0.j]) # may vary
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=float)
+ a = asarray(a)
if n is None:
n = a.shape[axis]
unitary = _unitary(norm)
@@ -732,17 +704,17 @@ def fftn(a, s=None, axes=None, norm=None):
--------
>>> a = np.mgrid[:3, :3, :3][0]
>>> np.fft.fftn(a, axes=(1, 2))
- array([[[ 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j]],
- [[ 9.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j]],
- [[ 18.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j]]])
+ array([[[ 0.+0.j, 0.+0.j, 0.+0.j], # may vary
+ [ 0.+0.j, 0.+0.j, 0.+0.j],
+ [ 0.+0.j, 0.+0.j, 0.+0.j]],
+ [[ 9.+0.j, 0.+0.j, 0.+0.j],
+ [ 0.+0.j, 0.+0.j, 0.+0.j],
+ [ 0.+0.j, 0.+0.j, 0.+0.j]],
+ [[18.+0.j, 0.+0.j, 0.+0.j],
+ [ 0.+0.j, 0.+0.j, 0.+0.j],
+ [ 0.+0.j, 0.+0.j, 0.+0.j]]])
>>> np.fft.fftn(a, (2, 2), axes=(0, 1))
- array([[[ 2.+0.j, 2.+0.j, 2.+0.j],
+ array([[[ 2.+0.j, 2.+0.j, 2.+0.j], # may vary
[ 0.+0.j, 0.+0.j, 0.+0.j]],
[[-2.+0.j, -2.+0.j, -2.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j]]])
@@ -838,10 +810,10 @@ def ifftn(a, s=None, axes=None, norm=None):
--------
>>> a = np.eye(4)
>>> np.fft.ifftn(np.fft.fftn(a, axes=(0,)), axes=(1,))
- array([[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]])
+ array([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], # may vary
+ [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
+ [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
+ [0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]])
Create and plot an image with band-limited frequency content:
@@ -934,16 +906,16 @@ def fft2(a, s=None, axes=(-2, -1), norm=None):
--------
>>> a = np.mgrid[:5, :5][0]
>>> np.fft.fft2(a)
- array([[ 50.0 +0.j , 0.0 +0.j , 0.0 +0.j ,
- 0.0 +0.j , 0.0 +0.j ],
- [-12.5+17.20477401j, 0.0 +0.j , 0.0 +0.j ,
- 0.0 +0.j , 0.0 +0.j ],
- [-12.5 +4.0614962j , 0.0 +0.j , 0.0 +0.j ,
- 0.0 +0.j , 0.0 +0.j ],
- [-12.5 -4.0614962j , 0.0 +0.j , 0.0 +0.j ,
- 0.0 +0.j , 0.0 +0.j ],
- [-12.5-17.20477401j, 0.0 +0.j , 0.0 +0.j ,
- 0.0 +0.j , 0.0 +0.j ]])
+ array([[ 50. +0.j , 0. +0.j , 0. +0.j , # may vary
+ 0. +0.j , 0. +0.j ],
+ [-12.5+17.20477401j, 0. +0.j , 0. +0.j ,
+ 0. +0.j , 0. +0.j ],
+ [-12.5 +4.0614962j , 0. +0.j , 0. +0.j ,
+ 0. +0.j , 0. +0.j ],
+ [-12.5 -4.0614962j , 0. +0.j , 0. +0.j ,
+ 0. +0.j , 0. +0.j ],
+ [-12.5-17.20477401j, 0. +0.j , 0. +0.j ,
+ 0. +0.j , 0. +0.j ]])
"""
@@ -1028,10 +1000,10 @@ def ifft2(a, s=None, axes=(-2, -1), norm=None):
--------
>>> a = 4 * np.eye(4)
>>> np.fft.ifft2(a)
- array([[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
- [ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
- [ 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]])
+ array([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], # may vary
+ [0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
+ [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
+ [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]])
"""
@@ -1110,20 +1082,19 @@ def rfftn(a, s=None, axes=None, norm=None):
--------
>>> a = np.ones((2, 2, 2))
>>> np.fft.rfftn(a)
- array([[[ 8.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j]],
- [[ 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j]]])
+ array([[[8.+0.j, 0.+0.j], # may vary
+ [0.+0.j, 0.+0.j]],
+ [[0.+0.j, 0.+0.j],
+ [0.+0.j, 0.+0.j]]])
>>> np.fft.rfftn(a, axes=(2, 0))
- array([[[ 4.+0.j, 0.+0.j],
- [ 4.+0.j, 0.+0.j]],
- [[ 0.+0.j, 0.+0.j],
- [ 0.+0.j, 0.+0.j]]])
+ array([[[4.+0.j, 0.+0.j], # may vary
+ [4.+0.j, 0.+0.j]],
+ [[0.+0.j, 0.+0.j],
+ [0.+0.j, 0.+0.j]]])
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=float)
+ a = asarray(a)
s, axes = _cook_nd_args(a, s, axes)
a = rfft(a, s[-1], axes[-1], norm)
for ii in range(len(axes)-1):
@@ -1247,16 +1218,15 @@ def irfftn(a, s=None, axes=None, norm=None):
>>> a = np.zeros((3, 2, 2))
>>> a[0, 0, 0] = 3 * 2 * 2
>>> np.fft.irfftn(a)
- array([[[ 1., 1.],
- [ 1., 1.]],
- [[ 1., 1.],
- [ 1., 1.]],
- [[ 1., 1.],
- [ 1., 1.]]])
+ array([[[1., 1.],
+ [1., 1.]],
+ [[1., 1.],
+ [1., 1.]],
+ [[1., 1.],
+ [1., 1.]]])
"""
- # The copy may be required for multithreading.
- a = array(a, copy=True, dtype=complex)
+ a = asarray(a)
s, axes = _cook_nd_args(a, s, axes, invreal=1)
for ii in range(len(axes)-1):
a = ifft(a, s[ii], axes[ii], norm)
diff --git a/numpy/fft/setup.py b/numpy/fft/setup.py
index cd99a82d7..6c3548b65 100644
--- a/numpy/fft/setup.py
+++ b/numpy/fft/setup.py
@@ -7,9 +7,9 @@ def configuration(parent_package='',top_path=None):
config.add_data_dir('tests')
- # Configure fftpack_lite
- config.add_extension('fftpack_lite',
- sources=['fftpack_litemodule.c', 'fftpack.c']
+ # Configure pocketfft_internal
+ config.add_extension('pocketfft_internal',
+ sources=['pocketfft.c']
)
return config
diff --git a/numpy/fft/tests/test_helper.py b/numpy/fft/tests/test_helper.py
index 8d315fa02..6613c8002 100644
--- a/numpy/fft/tests/test_helper.py
+++ b/numpy/fft/tests/test_helper.py
@@ -7,7 +7,6 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from numpy.testing import assert_array_almost_equal, assert_equal
from numpy import fft, pi
-from numpy.fft.helper import _FFTCache
class TestFFTShift(object):
@@ -168,81 +167,3 @@ class TestIRFFTN(object):
# Should not raise error
fft.irfftn(a, axes=axes)
-
-
-class TestFFTCache(object):
-
- def test_basic_behaviour(self):
- c = _FFTCache(max_size_in_mb=1, max_item_count=4)
-
- # Put
- c.put_twiddle_factors(1, np.ones(2, dtype=np.float32))
- c.put_twiddle_factors(2, np.zeros(2, dtype=np.float32))
-
- # Get
- assert_array_almost_equal(c.pop_twiddle_factors(1),
- np.ones(2, dtype=np.float32))
- assert_array_almost_equal(c.pop_twiddle_factors(2),
- np.zeros(2, dtype=np.float32))
-
- # Nothing should be left.
- assert_equal(len(c._dict), 0)
-
- # Now put everything in twice so it can be retrieved once and each will
- # still have one item left.
- for _ in range(2):
- c.put_twiddle_factors(1, np.ones(2, dtype=np.float32))
- c.put_twiddle_factors(2, np.zeros(2, dtype=np.float32))
- assert_array_almost_equal(c.pop_twiddle_factors(1),
- np.ones(2, dtype=np.float32))
- assert_array_almost_equal(c.pop_twiddle_factors(2),
- np.zeros(2, dtype=np.float32))
- assert_equal(len(c._dict), 2)
-
- def test_automatic_pruning(self):
- # That's around 2600 single precision samples.
- c = _FFTCache(max_size_in_mb=0.01, max_item_count=4)
-
- c.put_twiddle_factors(1, np.ones(200, dtype=np.float32))
- c.put_twiddle_factors(2, np.ones(200, dtype=np.float32))
- assert_equal(list(c._dict.keys()), [1, 2])
-
- # This is larger than the limit but should still be kept.
- c.put_twiddle_factors(3, np.ones(3000, dtype=np.float32))
- assert_equal(list(c._dict.keys()), [1, 2, 3])
- # Add one more.
- c.put_twiddle_factors(4, np.ones(3000, dtype=np.float32))
- # The other three should no longer exist.
- assert_equal(list(c._dict.keys()), [4])
-
- # Now test the max item count pruning.
- c = _FFTCache(max_size_in_mb=0.01, max_item_count=2)
- c.put_twiddle_factors(2, np.empty(2))
- c.put_twiddle_factors(1, np.empty(2))
- # Can still be accessed.
- assert_equal(list(c._dict.keys()), [2, 1])
-
- c.put_twiddle_factors(3, np.empty(2))
- # 1 and 3 can still be accessed - c[2] has been touched least recently
- # and is thus evicted.
- assert_equal(list(c._dict.keys()), [1, 3])
-
- # One last test. We will add a single large item that is slightly
- # bigger then the cache size. Some small items can still be added.
- c = _FFTCache(max_size_in_mb=0.01, max_item_count=5)
- c.put_twiddle_factors(1, np.ones(3000, dtype=np.float32))
- c.put_twiddle_factors(2, np.ones(2, dtype=np.float32))
- c.put_twiddle_factors(3, np.ones(2, dtype=np.float32))
- c.put_twiddle_factors(4, np.ones(2, dtype=np.float32))
- assert_equal(list(c._dict.keys()), [1, 2, 3, 4])
-
- # One more big item. This time it is 6 smaller ones but they are
- # counted as one big item.
- for _ in range(6):
- c.put_twiddle_factors(5, np.ones(500, dtype=np.float32))
- # '1' no longer in the cache. Rest still in the cache.
- assert_equal(list(c._dict.keys()), [2, 3, 4, 5])
-
- # Another big item - should now be the only item in the cache.
- c.put_twiddle_factors(6, np.ones(4000, dtype=np.float32))
- assert_equal(list(c._dict.keys()), [6])
diff --git a/numpy/fft/tests/test_fftpack.py b/numpy/fft/tests/test_pocketfft.py
index 8d6cd8407..db185cb21 100644
--- a/numpy/fft/tests/test_fftpack.py
+++ b/numpy/fft/tests/test_pocketfft.py
@@ -1,6 +1,7 @@
from __future__ import division, absolute_import, print_function
import numpy as np
+import pytest
from numpy.random import random
from numpy.testing import (
assert_array_almost_equal, assert_array_equal, assert_raises,
@@ -28,6 +29,16 @@ class TestFFTShift(object):
class TestFFT1D(object):
+ def test_identity(self):
+ maxlen = 512
+ x = random(maxlen) + 1j*random(maxlen)
+ xr = random(maxlen)
+ for i in range(1,maxlen):
+ assert_array_almost_equal(np.fft.ifft(np.fft.fft(x[0:i])), x[0:i],
+ decimal=12)
+ assert_array_almost_equal(np.fft.irfft(np.fft.rfft(xr[0:i]),i),
+ xr[0:i], decimal=12)
+
def test_fft(self):
x = random(30) + 1j*random(30)
assert_array_almost_equal(fft1(x), np.fft.fft(x))
@@ -127,6 +138,16 @@ class TestFFT1D(object):
x_herm, np.fft.ihfft(np.fft.hfft(x_herm, norm="ortho"),
norm="ortho"))
+ @pytest.mark.parametrize("op", [np.fft.fftn, np.fft.ifftn,
+ np.fft.rfftn, np.fft.irfftn])
+ def test_axes(self, op):
+ x = random((30, 20, 10))
+ axes = [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
+ for a in axes:
+ op_tr = op(np.transpose(x, a))
+ tr_op = np.transpose(op(x, axes=a), a)
+ assert_array_almost_equal(op_tr, tr_op)
+
def test_all_1d_norm_preserving(self):
# verify that round-trip transforms are norm-preserving
x = random(30)
@@ -146,6 +167,53 @@ class TestFFT1D(object):
assert_array_almost_equal(x_norm,
np.linalg.norm(tmp))
+ @pytest.mark.parametrize("dtype", [np.half, np.single, np.double,
+ np.longdouble])
+ def test_dtypes(self, dtype):
+ # make sure that all input precisions are accepted and internally
+ # converted to 64bit
+ x = random(30).astype(dtype)
+ assert_array_almost_equal(np.fft.ifft(np.fft.fft(x)), x)
+ assert_array_almost_equal(np.fft.irfft(np.fft.rfft(x)), x)
+
+
+@pytest.mark.parametrize(
+ "dtype",
+ [np.float32, np.float64, np.complex64, np.complex128])
+@pytest.mark.parametrize("order", ["F", 'non-contiguous'])
+@pytest.mark.parametrize(
+ "fft",
+ [np.fft.fft, np.fft.fft2, np.fft.fftn,
+ np.fft.ifft, np.fft.ifft2, np.fft.ifftn])
+def test_fft_with_order(dtype, order, fft):
+ # Check that FFT/IFFT produces identical results for C, Fortran and
+ # non contiguous arrays
+ rng = np.random.RandomState(42)
+ X = rng.rand(8, 7, 13).astype(dtype, copy=False)
+ if order == 'F':
+ Y = np.asfortranarray(X)
+ else:
+ # Make a non contiguous array
+ Y = X[::-1]
+ X = np.ascontiguousarray(X[::-1])
+
+ if fft.__name__.endswith('fft'):
+ for axis in range(3):
+ X_res = fft(X, axis=axis)
+ Y_res = fft(Y, axis=axis)
+ assert_array_almost_equal(X_res, Y_res)
+ elif fft.__name__.endswith(('fft2', 'fftn')):
+ axes = [(0, 1), (1, 2), (0, 2)]
+ if fft.__name__.endswith('fftn'):
+ axes.extend([(0,), (1,), (2,), None])
+ for ax in axes:
+ X_res = fft(X, axes=ax)
+ Y_res = fft(Y, axes=ax)
+ assert_array_almost_equal(X_res, Y_res)
+ else:
+ raise ValueError
+
+
class TestFFTThreadSafe(object):
threads = 16
input_shape = (800, 200)
diff --git a/numpy/lib/_datasource.py b/numpy/lib/_datasource.py
index 463266e28..0d71375c2 100644
--- a/numpy/lib/_datasource.py
+++ b/numpy/lib/_datasource.py
@@ -20,17 +20,18 @@ gzip, bz2 and xz are supported.
Example::
>>> # Create a DataSource, use os.curdir (default) for local storage.
- >>> ds = datasource.DataSource()
+ >>> from numpy import DataSource
+ >>> ds = DataSource()
>>>
>>> # Open a remote file.
>>> # DataSource downloads the file, stores it locally in:
>>> # './www.google.com/index.html'
>>> # opens the file and returns a file object.
- >>> fp = ds.open('http://www.google.com/index.html')
+ >>> fp = ds.open('http://www.google.com/') # doctest: +SKIP
>>>
>>> # Use the file as you normally would
- >>> fp.read()
- >>> fp.close()
+ >>> fp.read() # doctest: +SKIP
+ >>> fp.close() # doctest: +SKIP
"""
from __future__ import division, absolute_import, print_function
@@ -40,6 +41,7 @@ import sys
import warnings
import shutil
import io
+from contextlib import closing
from numpy.core.overrides import set_module
@@ -156,6 +158,7 @@ class _FileOpeners(object):
Examples
--------
+ >>> import gzip
>>> np.lib._datasource._file_openers.keys()
[None, '.bz2', '.gz', '.xz', '.lzma']
>>> np.lib._datasource._file_openers['.gz'] is gzip.open
@@ -290,7 +293,7 @@ class DataSource(object):
URLs require a scheme string (``http://``) to be used, without it they
will fail::
- >>> repos = DataSource()
+ >>> repos = np.DataSource()
>>> repos.exists('www.google.com/index.html')
False
>>> repos.exists('http://www.google.com/index.html')
@@ -302,17 +305,17 @@ class DataSource(object):
--------
::
- >>> ds = DataSource('/home/guido')
- >>> urlname = 'http://www.google.com/index.html'
- >>> gfile = ds.open('http://www.google.com/index.html') # remote file
+ >>> ds = np.DataSource('/home/guido')
+ >>> urlname = 'http://www.google.com/'
+ >>> gfile = ds.open('http://www.google.com/')
>>> ds.abspath(urlname)
- '/home/guido/www.google.com/site/index.html'
+ '/home/guido/www.google.com/index.html'
- >>> ds = DataSource(None) # use with temporary file
+ >>> ds = np.DataSource(None) # use with temporary file
>>> ds.open('/home/guido/foobar.txt')
<open file '/home/guido.foobar.txt', mode 'r' at 0x91d4430>
>>> ds.abspath('/home/guido/foobar.txt')
- '/tmp/tmpy4pgsP/home/guido/foobar.txt'
+ '/tmp/.../home/guido/foobar.txt'
"""
@@ -412,13 +415,9 @@ class DataSource(object):
# TODO: Doesn't handle compressed files!
if self._isurl(path):
try:
- openedurl = urlopen(path)
- f = _open(upath, 'wb')
- try:
- shutil.copyfileobj(openedurl, f)
- finally:
- f.close()
- openedurl.close()
+ with closing(urlopen(path)) as openedurl:
+ with _open(upath, 'wb') as f:
+ shutil.copyfileobj(openedurl, f)
except URLError:
raise URLError("URL not found: %s" % path)
else:
diff --git a/numpy/lib/_iotools.py b/numpy/lib/_iotools.py
index 9713ff8b1..0ebd39b8c 100644
--- a/numpy/lib/_iotools.py
+++ b/numpy/lib/_iotools.py
@@ -121,7 +121,7 @@ def has_nested_fields(ndtype):
"""
for name in ndtype.names or ():
- if ndtype[name].names is not None:
+ if ndtype[name].names:
return True
return False
@@ -146,11 +146,17 @@ def flatten_dtype(ndtype, flatten_base=False):
>>> dt = np.dtype([('name', 'S4'), ('x', float), ('y', float),
... ('block', int, (2, 3))])
>>> np.lib._iotools.flatten_dtype(dt)
- [dtype('|S4'), dtype('float64'), dtype('float64'), dtype('int32')]
+ [dtype('S4'), dtype('float64'), dtype('float64'), dtype('int64')]
>>> np.lib._iotools.flatten_dtype(dt, flatten_base=True)
- [dtype('|S4'), dtype('float64'), dtype('float64'), dtype('int32'),
- dtype('int32'), dtype('int32'), dtype('int32'), dtype('int32'),
- dtype('int32')]
+ [dtype('S4'),
+ dtype('float64'),
+ dtype('float64'),
+ dtype('int64'),
+ dtype('int64'),
+ dtype('int64'),
+ dtype('int64'),
+ dtype('int64'),
+ dtype('int64')]
"""
names = ndtype.names
@@ -309,13 +315,13 @@ class NameValidator(object):
--------
>>> validator = np.lib._iotools.NameValidator()
>>> validator(['file', 'field2', 'with space', 'CaSe'])
- ['file_', 'field2', 'with_space', 'CaSe']
+ ('file_', 'field2', 'with_space', 'CaSe')
>>> validator = np.lib._iotools.NameValidator(excludelist=['excl'],
- deletechars='q',
- case_sensitive='False')
+ ... deletechars='q',
+ ... case_sensitive=False)
>>> validator(['excl', 'field2', 'no_q', 'with space', 'CaSe'])
- ['excl_', 'field2', 'no_', 'with_space', 'case']
+ ('EXCL', 'FIELD2', 'NO_Q', 'WITH_SPACE', 'CASE')
"""
#
@@ -599,7 +605,7 @@ class StringConverter(object):
--------
>>> import dateutil.parser
>>> import datetime
- >>> dateparser = datetustil.parser.parse
+ >>> dateparser = dateutil.parser.parse
>>> defaultdate = datetime.date(2000, 1, 1)
>>> StringConverter.upgrade_mapper(dateparser, default=defaultdate)
"""
@@ -925,27 +931,28 @@ def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs):
names = validate(names, nbfields=nbfields, defaultfmt=defaultfmt)
ndtype = np.dtype(dict(formats=ndtype, names=names))
else:
+ nbtypes = len(ndtype)
# Explicit names
if names is not None:
validate = NameValidator(**validationargs)
if isinstance(names, basestring):
names = names.split(",")
# Simple dtype: repeat to match the nb of names
- if ndtype.names is None:
+ if nbtypes == 0:
formats = tuple([ndtype.type] * len(names))
names = validate(names, defaultfmt=defaultfmt)
ndtype = np.dtype(list(zip(names, formats)))
# Structured dtype: just validate the names as needed
else:
- ndtype.names = validate(names, nbfields=len(ndtype.names),
+ ndtype.names = validate(names, nbfields=nbtypes,
defaultfmt=defaultfmt)
# No implicit names
- elif ndtype.names is not None:
+ elif (nbtypes > 0):
validate = NameValidator(**validationargs)
# Default initial names : should we change the format ?
- if ((ndtype.names == tuple("f%i" % i for i in range(len(ndtype.names)))) and
+ if ((ndtype.names == tuple("f%i" % i for i in range(nbtypes))) and
(defaultfmt != "f%i")):
- ndtype.names = validate([''] * len(ndtype.names), defaultfmt=defaultfmt)
+ ndtype.names = validate([''] * nbtypes, defaultfmt=defaultfmt)
# Explicit initial names : just validate
else:
ndtype.names = validate(ndtype.names, defaultfmt=defaultfmt)
diff --git a/numpy/lib/_version.py b/numpy/lib/_version.py
index c3563a7fa..8aa999fc9 100644
--- a/numpy/lib/_version.py
+++ b/numpy/lib/_version.py
@@ -47,9 +47,12 @@ class NumpyVersion():
>>> from numpy.lib import NumpyVersion
>>> if NumpyVersion(np.__version__) < '1.7.0':
... print('skip')
- skip
+ >>> # skip
>>> NumpyVersion('1.7') # raises ValueError, add ".0"
+ Traceback (most recent call last):
+ ...
+ ValueError: Not a valid numpy version string
"""
diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py
index 8650685a7..f08d425d6 100644
--- a/numpy/lib/arraypad.py
+++ b/numpy/lib/arraypad.py
@@ -7,6 +7,7 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from numpy.core.overrides import array_function_dispatch
+from numpy.lib.index_tricks import ndindex
__all__ = ['pad']
@@ -16,50 +17,67 @@ __all__ = ['pad']
# Private utility functions.
-def _arange_ndarray(arr, shape, axis, reverse=False):
+def _linear_ramp(ndim, axis, start, stop, size, reverse=False):
"""
- Create an ndarray of `shape` with increments along specified `axis`
+ Create a linear ramp of `size` in `axis` with `ndim`.
+
+ This algorithm behaves like a vectorized version of `numpy.linspace`.
+ The resulting linear ramp is broadcastable to any array that matches the
+ ramp in `shape[axis]` and `ndim`.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- shape : tuple of ints
- Shape of desired array. Should be equivalent to `arr.shape` except
- `shape[axis]` which may have any positive value.
+ ndim : int
+ Number of dimensions of the resulting array. All dimensions except
+ the one specified by `axis` will have the size 1.
axis : int
- Axis to increment along.
+ The dimension that contains the linear ramp of `size`.
+ start : int or ndarray
+ The starting value(s) of the linear ramp. If given as an array, its
+ size must match `size`.
+ stop : int or ndarray
+ The stop value(s) (not included!) of the linear ramp. If given as an
+ array, its size must match `size`.
+ size : int
+ The number of elements in the linear ramp. If this argument is 0 the
+ dimensions of `ramp` will all be of length 1 except for the one given
+ by `axis` which will be 0.
reverse : bool
- If False, increment in a positive fashion from 1 to `shape[axis]`,
- inclusive. If True, the bounds are the same but the order reversed.
+ If False, increment in a positive fashion, otherwise decrement.
Returns
-------
- padarr : ndarray
- Output array sized to pad `arr` along `axis`, with linear range from
- 1 to `shape[axis]` along specified `axis`.
-
- Notes
- -----
- The range is deliberately 1-indexed for this specific use case. Think of
- this algorithm as broadcasting `np.arange` to a single `axis` of an
- arbitrarily shaped ndarray.
+ ramp : ndarray
+ Output array of dtype np.float64 that in- or decrements along the given
+ `axis`.
+ Examples
+ --------
+ >>> _linear_ramp(ndim=2, axis=0, start=np.arange(3), stop=10, size=2)
+ array([[0. , 1. , 2. ],
+ [5. , 5.5, 6. ]])
+ >>> _linear_ramp(ndim=3, axis=0, start=2, stop=0, size=0)
+ array([], shape=(0, 1, 1), dtype=float64)
"""
- initshape = tuple(1 if i != axis else shape[axis]
- for (i, x) in enumerate(arr.shape))
- if not reverse:
- padarr = np.arange(1, shape[axis] + 1)
- else:
- padarr = np.arange(shape[axis], 0, -1)
- padarr = padarr.reshape(initshape)
- for i, dim in enumerate(shape):
- if padarr.shape[i] != dim:
- padarr = padarr.repeat(dim, axis=i)
- return padarr
+ # Create initial ramp
+ ramp = np.arange(size, dtype=np.float64)
+ if reverse:
+ ramp = ramp[::-1]
+
+ # Make sure, that ramp is broadcastable
+ init_shape = (1,) * axis + (size,) + (1,) * (ndim - axis - 1)
+ ramp = ramp.reshape(init_shape)
+
+ if size != 0:
+ # And scale to given start and stop values
+ gain = (stop - start) / float(size)
+ ramp = ramp * gain
+ ramp += start
+ return ramp
-def _round_ifneeded(arr, dtype):
+
+def _round_if_needed(arr, dtype):
"""
Rounds arr inplace if destination dtype is integer.
@@ -69,809 +87,418 @@ def _round_ifneeded(arr, dtype):
Input array.
dtype : dtype
The dtype of the destination array.
-
"""
if np.issubdtype(dtype, np.integer):
arr.round(out=arr)
-def _slice_at_axis(shape, sl, axis):
- """
- Construct a slice tuple the length of shape, with sl at the specified axis
- """
- slice_tup = (slice(None),)
- return slice_tup * axis + (sl,) + slice_tup * (len(shape) - axis - 1)
-
-
-def _slice_first(shape, n, axis):
- """ Construct a slice tuple to take the first n elements along axis """
- return _slice_at_axis(shape, slice(0, n), axis=axis)
-
-
-def _slice_last(shape, n, axis):
- """ Construct a slice tuple to take the last n elements along axis """
- dim = shape[axis] # doing this explicitly makes n=0 work
- return _slice_at_axis(shape, slice(dim - n, dim), axis=axis)
-
-
-def _do_prepend(arr, pad_chunk, axis):
- return np.concatenate(
- (pad_chunk.astype(arr.dtype, copy=False), arr), axis=axis)
-
-
-def _do_append(arr, pad_chunk, axis):
- return np.concatenate(
- (arr, pad_chunk.astype(arr.dtype, copy=False)), axis=axis)
-
-
-def _prepend_const(arr, pad_amt, val, axis=-1):
- """
- Prepend constant `val` along `axis` of `arr`.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- val : scalar
- Constant value to use. For best results should be of type `arr.dtype`;
- if not `arr.dtype` will be cast to `arr.dtype`.
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` constant `val` prepended along `axis`.
-
- """
- if pad_amt == 0:
- return arr
- padshape = tuple(x if i != axis else pad_amt
- for (i, x) in enumerate(arr.shape))
- return _do_prepend(arr, np.full(padshape, val, dtype=arr.dtype), axis)
-
-
-def _append_const(arr, pad_amt, val, axis=-1):
+def _slice_at_axis(sl, axis):
"""
- Append constant `val` along `axis` of `arr`.
+ Construct tuple of slices to slice an array in the given dimension.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- val : scalar
- Constant value to use. For best results should be of type `arr.dtype`;
- if not `arr.dtype` will be cast to `arr.dtype`.
+ sl : slice
+ The slice for the given dimension.
axis : int
- Axis along which to pad `arr`.
+ The axis to which `sl` is applied. All other dimensions are left
+ "unsliced".
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt` constant `val` appended along `axis`.
+ sl : tuple of slices
+ A tuple with slices matching `shape` in length.
+ Examples
+ --------
+ >>> _slice_at_axis(slice(None, 3, -1), 1)
+ (slice(None, None, None), slice(None, 3, -1), (...,))
"""
- if pad_amt == 0:
- return arr
- padshape = tuple(x if i != axis else pad_amt
- for (i, x) in enumerate(arr.shape))
- return _do_append(arr, np.full(padshape, val, dtype=arr.dtype), axis)
+ return (slice(None),) * axis + (sl,) + (...,)
-
-def _prepend_edge(arr, pad_amt, axis=-1):
+def _view_roi(array, original_area_slice, axis):
"""
- Prepend `pad_amt` to `arr` along `axis` by extending edge values.
+ Get a view of the current region of interest during iterative padding.
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, extended by `pad_amt` edge values appended along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- edge_slice = _slice_first(arr.shape, 1, axis=axis)
- edge_arr = arr[edge_slice]
- return _do_prepend(arr, edge_arr.repeat(pad_amt, axis=axis), axis)
-
-
-def _append_edge(arr, pad_amt, axis=-1):
- """
- Append `pad_amt` to `arr` along `axis` by extending edge values.
+ When padding multiple dimensions iteratively corner values are
+ unnecessarily overwritten multiple times. This function reduces the
+ working area for the first dimensions so that corners are excluded.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
+ array : ndarray
+ The array with the region of interest.
+ original_area_slice : tuple of slices
+ Denotes the area with original values of the unpadded array.
axis : int
- Axis along which to pad `arr`.
+ The currently padded dimension assuming that `axis` is padded before
+ `axis` + 1.
Returns
-------
- padarr : ndarray
- Output array, extended by `pad_amt` edge values prepended along
- `axis`.
-
+ roi : ndarray
+ The region of interest of the original `array`.
"""
- if pad_amt == 0:
- return arr
+ axis += 1
+ sl = (slice(None),) * axis + original_area_slice[axis:]
+ return array[sl]
- edge_slice = _slice_last(arr.shape, 1, axis=axis)
- edge_arr = arr[edge_slice]
- return _do_append(arr, edge_arr.repeat(pad_amt, axis=axis), axis)
-
-def _prepend_ramp(arr, pad_amt, end, axis=-1):
+def _pad_simple(array, pad_width, fill_value=None):
"""
- Prepend linear ramp along `axis`.
+ Pad array on all sides with either a single value or undefined values.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- end : scalar
- Constal value to use. For best results should be of type `arr.dtype`;
- if not `arr.dtype` will be cast to `arr.dtype`.
- axis : int
- Axis along which to pad `arr`.
+ array : ndarray
+ Array to grow.
+ pad_width : sequence of tuple[int, int]
+ Pad width on both sides for each dimension in `arr`.
+ fill_value : scalar, optional
+ If provided the padded area is filled with this value, otherwise
+ the pad area left undefined.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt` values prepended along `axis`. The
- prepended region ramps linearly from the edge value to `end`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Slice a chunk from the edge to calculate stats on and extract edge
- edge_slice = _slice_first(arr.shape, 1, axis=axis)
- edge = arr[edge_slice]
-
- ramp_arr = np.linspace(
- start=end,
- stop=edge.squeeze(axis),
- num=pad_amt,
- endpoint=False,
- dtype=arr.dtype,
- axis=axis
+ padded : ndarray
+ The padded array with the same dtype as`array`. Its order will default
+ to C-style if `array` is not F-contiguous.
+ original_area_slice : tuple
+ A tuple of slices pointing to the area of the original array.
+ """
+ # Allocate grown array
+ new_shape = tuple(
+ left + size + right
+ for size, (left, right) in zip(array.shape, pad_width)
)
+ order = 'F' if array.flags.fnc else 'C' # Fortran and not also C-order
+ padded = np.empty(new_shape, dtype=array.dtype, order=order)
- return _do_prepend(arr, ramp_arr, axis)
-
+ if fill_value is not None:
+ padded.fill(fill_value)
-def _append_ramp(arr, pad_amt, end, axis=-1):
- """
- Append linear ramp along `axis`.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- end : scalar
- Constal value to use. For best results should be of type `arr.dtype`;
- if not `arr.dtype` will be cast to `arr.dtype`.
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- appended region ramps linearly from the edge value to `end`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Slice a chunk from the edge to calculate stats on and extract edge
- edge_slice = _slice_last(arr.shape, 1, axis=axis)
- edge = arr[edge_slice]
-
- ramp_arr = np.linspace(
- start=end,
- stop=edge.squeeze(axis),
- num=pad_amt,
- endpoint=False,
- dtype=arr.dtype,
- axis=axis
+ # Copy old array into correct space
+ original_area_slice = tuple(
+ slice(left, left + size)
+ for size, (left, right) in zip(array.shape, pad_width)
)
- # Reverse linear space in appropriate dimension
- ramp_arr = ramp_arr[
- _slice_at_axis(ramp_arr.shape, slice(None, None, -1), axis)
- ]
+ padded[original_area_slice] = array
- return _do_append(arr, ramp_arr, axis)
+ return padded, original_area_slice
-def _prepend_max(arr, pad_amt, num, axis=-1):
+def _set_pad_area(padded, axis, width_pair, value_pair):
"""
- Prepend `pad_amt` maximum values along `axis`.
+ Set empty-padded area in given dimension.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- num : int
- Depth into `arr` along `axis` to calculate maximum.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
+ padded : ndarray
+ Array with the pad area which is modified inplace.
axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- prepended region is the maximum of the first `num` values along
- `axis`.
-
+ Dimension with the pad area to set.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
+ value_pair : tuple of scalars or ndarrays
+ Values inserted into the pad area on each side. It must match or be
+ broadcastable to the shape of `arr`.
"""
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _prepend_edge(arr, pad_amt, axis)
+ left_slice = _slice_at_axis(slice(None, width_pair[0]), axis)
+ padded[left_slice] = value_pair[0]
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
+ right_slice = _slice_at_axis(
+ slice(padded.shape[axis] - width_pair[1], None), axis)
+ padded[right_slice] = value_pair[1]
- # Slice a chunk from the edge to calculate stats on
- max_slice = _slice_first(arr.shape, num, axis=axis)
- # Extract slice, calculate max
- max_chunk = arr[max_slice].max(axis=axis, keepdims=True)
-
- # Concatenate `arr` with `max_chunk`, extended along `axis` by `pad_amt`
- return _do_prepend(arr, max_chunk.repeat(pad_amt, axis=axis), axis)
-
-
-def _append_max(arr, pad_amt, num, axis=-1):
+def _get_edges(padded, axis, width_pair):
"""
- Pad one `axis` of `arr` with the maximum of the last `num` elements.
+ Retrieve edge values from empty-padded array in given dimension.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- num : int
- Depth into `arr` along `axis` to calculate maximum.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
+ padded : ndarray
+ Empty-padded array.
axis : int
- Axis along which to pad `arr`.
+ Dimension in which the edges are considered.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- appended region is the maximum of the final `num` values along `axis`.
-
+ left_edge, right_edge : ndarray
+ Edge values of the valid area in `padded` in the given dimension. Its
+ shape will always match `padded` except for the dimension given by
+ `axis` which will have a length of 1.
"""
- if pad_amt == 0:
- return arr
+ left_index = width_pair[0]
+ left_slice = _slice_at_axis(slice(left_index, left_index + 1), axis)
+ left_edge = padded[left_slice]
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _append_edge(arr, pad_amt, axis)
+ right_index = padded.shape[axis] - width_pair[1]
+ right_slice = _slice_at_axis(slice(right_index - 1, right_index), axis)
+ right_edge = padded[right_slice]
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- if num is not None:
- max_slice = _slice_last(arr.shape, num, axis=axis)
- else:
- max_slice = tuple(slice(None) for x in arr.shape)
+ return left_edge, right_edge
- # Extract slice, calculate max
- max_chunk = arr[max_slice].max(axis=axis, keepdims=True)
- # Concatenate `arr` with `max_chunk`, extended along `axis` by `pad_amt`
- return _do_append(arr, max_chunk.repeat(pad_amt, axis=axis), axis)
-
-
-def _prepend_mean(arr, pad_amt, num, axis=-1):
+def _get_linear_ramps(padded, axis, width_pair, end_value_pair):
"""
- Prepend `pad_amt` mean values along `axis`.
+ Construct linear ramps for empty-padded array in given dimension.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- num : int
- Depth into `arr` along `axis` to calculate mean.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
+ padded : ndarray
+ Empty-padded array.
axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values prepended along `axis`. The
- prepended region is the mean of the first `num` values along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _prepend_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- mean_slice = _slice_first(arr.shape, num, axis=axis)
-
- # Extract slice, calculate mean
- mean_chunk = arr[mean_slice].mean(axis, keepdims=True)
- _round_ifneeded(mean_chunk, arr.dtype)
-
- # Concatenate `arr` with `mean_chunk`, extended along `axis` by `pad_amt`
- return _do_prepend(arr, mean_chunk.repeat(pad_amt, axis), axis=axis)
-
-
-def _append_mean(arr, pad_amt, num, axis=-1):
- """
- Append `pad_amt` mean values along `axis`.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- num : int
- Depth into `arr` along `axis` to calculate mean.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
- axis : int
- Axis along which to pad `arr`.
+ Dimension in which the ramps are constructed.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
+ end_value_pair : (scalar, scalar)
+ End values for the linear ramps which form the edge of the fully padded
+ array. These values are included in the linear ramps.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- appended region is the maximum of the final `num` values along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _append_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- if num is not None:
- mean_slice = _slice_last(arr.shape, num, axis=axis)
- else:
- mean_slice = tuple(slice(None) for x in arr.shape)
-
- # Extract slice, calculate mean
- mean_chunk = arr[mean_slice].mean(axis=axis, keepdims=True)
- _round_ifneeded(mean_chunk, arr.dtype)
-
- # Concatenate `arr` with `mean_chunk`, extended along `axis` by `pad_amt`
- return _do_append(arr, mean_chunk.repeat(pad_amt, axis), axis=axis)
-
-
-def _prepend_med(arr, pad_amt, num, axis=-1):
+ left_ramp, right_ramp : ndarray
+ Linear ramps to set on both sides of `padded`.
"""
- Prepend `pad_amt` median values along `axis`.
+ edge_pair = _get_edges(padded, axis, width_pair)
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- num : int
- Depth into `arr` along `axis` to calculate median.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values prepended along `axis`. The
- prepended region is the median of the first `num` values along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _prepend_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- med_slice = _slice_first(arr.shape, num, axis=axis)
+ left_ramp = _linear_ramp(
+ padded.ndim, axis, start=end_value_pair[0], stop=edge_pair[0],
+ size=width_pair[0], reverse=False
+ )
+ _round_if_needed(left_ramp, padded.dtype)
- # Extract slice, calculate median
- med_chunk = np.median(arr[med_slice], axis=axis, keepdims=True)
- _round_ifneeded(med_chunk, arr.dtype)
+ right_ramp = _linear_ramp(
+ padded.ndim, axis, start=end_value_pair[1], stop=edge_pair[1],
+ size=width_pair[1], reverse=True
+ )
+ _round_if_needed(right_ramp, padded.dtype)
- # Concatenate `arr` with `med_chunk`, extended along `axis` by `pad_amt`
- return _do_prepend(arr, med_chunk.repeat(pad_amt, axis), axis=axis)
+ return left_ramp, right_ramp
-def _append_med(arr, pad_amt, num, axis=-1):
+def _get_stats(padded, axis, width_pair, length_pair, stat_func):
"""
- Append `pad_amt` median values along `axis`.
+ Calculate statistic for the empty-padded array in given dimnsion.
Parameters
----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- num : int
- Depth into `arr` along `axis` to calculate median.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
+ padded : ndarray
+ Empty-padded array.
axis : int
- Axis along which to pad `arr`.
+ Dimension in which the statistic is calculated.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
+ length_pair : 2-element sequence of None or int
+ Gives the number of values in valid area from each side that is
+ taken into account when calculating the statistic. If None the entire
+ valid area in `padded` is considered.
+ stat_func : function
+ Function to compute statistic. The expected signature is
+ ``stat_func(x: ndarray, axis: int, keepdims: bool) -> ndarray``.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- appended region is the median of the final `num` values along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _append_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- if num is not None:
- med_slice = _slice_last(arr.shape, num, axis=axis)
- else:
- med_slice = tuple(slice(None) for x in arr.shape)
-
- # Extract slice, calculate median
- med_chunk = np.median(arr[med_slice], axis=axis, keepdims=True)
- _round_ifneeded(med_chunk, arr.dtype)
-
- # Concatenate `arr` with `med_chunk`, extended along `axis` by `pad_amt`
- return _do_append(arr, med_chunk.repeat(pad_amt, axis), axis=axis)
-
-
-def _prepend_min(arr, pad_amt, num, axis=-1):
- """
- Prepend `pad_amt` minimum values along `axis`.
+ left_stat, right_stat : ndarray
+ Calculated statistic for both sides of `padded`.
+ """
+ # Calculate indices of the edges of the area with original values
+ left_index = width_pair[0]
+ right_index = padded.shape[axis] - width_pair[1]
+ # as well as its length
+ max_length = right_index - left_index
+
+ # Limit stat_lengths to max_length
+ left_length, right_length = length_pair
+ if left_length is None or max_length < left_length:
+ left_length = max_length
+ if right_length is None or max_length < right_length:
+ right_length = max_length
+
+ # Calculate statistic for the left side
+ left_slice = _slice_at_axis(
+ slice(left_index, left_index + left_length), axis)
+ left_chunk = padded[left_slice]
+ left_stat = stat_func(left_chunk, axis=axis, keepdims=True)
+ _round_if_needed(left_stat, padded.dtype)
+
+ if left_length == right_length == max_length:
+ # return early as right_stat must be identical to left_stat
+ return left_stat, left_stat
+
+ # Calculate statistic for the right side
+ right_slice = _slice_at_axis(
+ slice(right_index - right_length, right_index), axis)
+ right_chunk = padded[right_slice]
+ right_stat = stat_func(right_chunk, axis=axis, keepdims=True)
+ _round_if_needed(right_stat, padded.dtype)
+ return left_stat, right_stat
+
+
+def _set_reflect_both(padded, axis, width_pair, method, include_edge=False):
+ """
+ Pad `axis` of `arr` with reflection.
Parameters
----------
- arr : ndarray
+ padded : ndarray
Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to prepend.
- num : int
- Depth into `arr` along `axis` to calculate minimum.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
axis : int
Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values prepended along `axis`. The
- prepended region is the minimum of the first `num` values along
- `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _prepend_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- min_slice = _slice_first(arr.shape, num, axis=axis)
-
- # Extract slice, calculate min
- min_chunk = arr[min_slice].min(axis=axis, keepdims=True)
-
- # Concatenate `arr` with `min_chunk`, extended along `axis` by `pad_amt`
- return _do_prepend(arr, min_chunk.repeat(pad_amt, axis), axis=axis)
-
-
-def _append_min(arr, pad_amt, num, axis=-1):
- """
- Append `pad_amt` median values along `axis`.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : int
- Amount of padding to append.
- num : int
- Depth into `arr` along `axis` to calculate minimum.
- Range: [1, `arr.shape[axis]`] or None (entire axis)
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt` values appended along `axis`. The
- appended region is the minimum of the final `num` values along `axis`.
-
- """
- if pad_amt == 0:
- return arr
-
- # Equivalent to edge padding for single value, so do that instead
- if num == 1:
- return _append_edge(arr, pad_amt, axis)
-
- # Use entire array if `num` is too large
- if num is not None:
- if num >= arr.shape[axis]:
- num = None
-
- # Slice a chunk from the edge to calculate stats on
- if num is not None:
- min_slice = _slice_last(arr.shape, num, axis=axis)
- else:
- min_slice = tuple(slice(None) for x in arr.shape)
-
- # Extract slice, calculate min
- min_chunk = arr[min_slice].min(axis=axis, keepdims=True)
-
- # Concatenate `arr` with `min_chunk`, extended along `axis` by `pad_amt`
- return _do_append(arr, min_chunk.repeat(pad_amt, axis), axis=axis)
-
-
-def _pad_ref(arr, pad_amt, method, axis=-1):
- """
- Pad `axis` of `arr` by reflection.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
- pad_amt : tuple of ints, length 2
- Padding to (prepend, append) along `axis`.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
method : str
Controls method of reflection; options are 'even' or 'odd'.
- axis : int
- Axis along which to pad `arr`.
+ include_edge : bool
+ If true, edge value is included in reflection, otherwise the edge
+ value forms the symmetric axis to the reflection.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt[0]` values prepended and `pad_amt[1]`
- values appended along `axis`. Both regions are padded with reflected
- values from the original array.
-
- Notes
- -----
- This algorithm does not pad with repetition, i.e. the edges are not
- repeated in the reflection. For that behavior, use `mode='symmetric'`.
-
- The modes 'reflect', 'symmetric', and 'wrap' must be padded with a
- single function, lest the indexing tricks in non-integer multiples of the
- original shape would violate repetition in the final iteration.
-
- """
- # Implicit booleanness to test for zero (or None) in any scalar type
- if pad_amt[0] == 0 and pad_amt[1] == 0:
- return arr
-
- ##########################################################################
- # Prepended region
-
- # Slice off a reverse indexed chunk from near edge to pad `arr` before
- ref_slice = _slice_at_axis(arr.shape, slice(pad_amt[0], 0, -1), axis=axis)
-
- ref_chunk1 = arr[ref_slice]
-
- # Memory/computationally more expensive, only do this if `method='odd'`
- if 'odd' in method and pad_amt[0] > 0:
- edge_slice1 = _slice_first(arr.shape, 1, axis=axis)
- edge_chunk = arr[edge_slice1]
- ref_chunk1 = 2 * edge_chunk - ref_chunk1
- del edge_chunk
-
- ##########################################################################
- # Appended region
-
- # Slice off a reverse indexed chunk from far edge to pad `arr` after
- start = arr.shape[axis] - pad_amt[1] - 1
- end = arr.shape[axis] - 1
- ref_slice = _slice_at_axis(arr.shape, slice(start, end), axis=axis)
- rev_idx = _slice_at_axis(arr.shape, slice(None, None, -1), axis=axis)
- ref_chunk2 = arr[ref_slice][rev_idx]
-
- if 'odd' in method:
- edge_slice2 = _slice_last(arr.shape, 1, axis=axis)
- edge_chunk = arr[edge_slice2]
- ref_chunk2 = 2 * edge_chunk - ref_chunk2
- del edge_chunk
-
- # Concatenate `arr` with both chunks, extending along `axis`
- return np.concatenate((ref_chunk1, arr, ref_chunk2), axis=axis)
-
-
-def _pad_sym(arr, pad_amt, method, axis=-1):
- """
- Pad `axis` of `arr` by symmetry.
-
- Parameters
- ----------
- arr : ndarray
- Input array of arbitrary shape.
pad_amt : tuple of ints, length 2
- Padding to (prepend, append) along `axis`.
- method : str
- Controls method of symmetry; options are 'even' or 'odd'.
- axis : int
- Axis along which to pad `arr`.
-
- Returns
- -------
- padarr : ndarray
- Output array, with `pad_amt[0]` values prepended and `pad_amt[1]`
- values appended along `axis`. Both regions are padded with symmetric
- values from the original array.
-
- Notes
- -----
- This algorithm DOES pad with repetition, i.e. the edges are repeated.
- For padding without repeated edges, use `mode='reflect'`.
-
- The modes 'reflect', 'symmetric', and 'wrap' must be padded with a
- single function, lest the indexing tricks in non-integer multiples of the
- original shape would violate repetition in the final iteration.
-
+ New index positions of padding to do along the `axis`. If these are
+ both 0, padding is done in this dimension.
"""
- # Implicit booleanness to test for zero (or None) in any scalar type
- if pad_amt[0] == 0 and pad_amt[1] == 0:
- return arr
-
- ##########################################################################
- # Prepended region
-
- # Slice off a reverse indexed chunk from near edge to pad `arr` before
- sym_slice = _slice_first(arr.shape, pad_amt[0], axis=axis)
- rev_idx = _slice_at_axis(arr.shape, slice(None, None, -1), axis=axis)
- sym_chunk1 = arr[sym_slice][rev_idx]
-
- # Memory/computationally more expensive, only do this if `method='odd'`
- if 'odd' in method and pad_amt[0] > 0:
- edge_slice1 = _slice_first(arr.shape, 1, axis=axis)
- edge_chunk = arr[edge_slice1]
- sym_chunk1 = 2 * edge_chunk - sym_chunk1
- del edge_chunk
-
- ##########################################################################
- # Appended region
-
- # Slice off a reverse indexed chunk from far edge to pad `arr` after
- sym_slice = _slice_last(arr.shape, pad_amt[1], axis=axis)
- sym_chunk2 = arr[sym_slice][rev_idx]
-
- if 'odd' in method:
- edge_slice2 = _slice_last(arr.shape, 1, axis=axis)
- edge_chunk = arr[edge_slice2]
- sym_chunk2 = 2 * edge_chunk - sym_chunk2
- del edge_chunk
-
- # Concatenate `arr` with both chunks, extending along `axis`
- return np.concatenate((sym_chunk1, arr, sym_chunk2), axis=axis)
-
+ left_pad, right_pad = width_pair
+ old_length = padded.shape[axis] - right_pad - left_pad
-def _pad_wrap(arr, pad_amt, axis=-1):
- """
- Pad `axis` of `arr` via wrapping.
+ if include_edge:
+ # Edge is included, we need to offset the pad amount by 1
+ edge_offset = 1
+ else:
+ edge_offset = 0 # Edge is not included, no need to offset pad amount
+ old_length -= 1 # but must be omitted from the chunk
+
+ if left_pad > 0:
+ # Pad with reflected values on left side:
+ # First limit chunk size which can't be larger than pad area
+ chunk_length = min(old_length, left_pad)
+ # Slice right to left, stop on or next to edge, start relative to stop
+ stop = left_pad - edge_offset
+ start = stop + chunk_length
+ left_slice = _slice_at_axis(slice(start, stop, -1), axis)
+ left_chunk = padded[left_slice]
+
+ if method == "odd":
+ # Negate chunk and align with edge
+ edge_slice = _slice_at_axis(slice(left_pad, left_pad + 1), axis)
+ left_chunk = 2 * padded[edge_slice] - left_chunk
+
+ # Insert chunk into padded area
+ start = left_pad - chunk_length
+ stop = left_pad
+ pad_area = _slice_at_axis(slice(start, stop), axis)
+ padded[pad_area] = left_chunk
+ # Adjust pointer to left edge for next iteration
+ left_pad -= chunk_length
+
+ if right_pad > 0:
+ # Pad with reflected values on right side:
+ # First limit chunk size which can't be larger than pad area
+ chunk_length = min(old_length, right_pad)
+ # Slice right to left, start on or next to edge, stop relative to start
+ start = -right_pad + edge_offset - 2
+ stop = start - chunk_length
+ right_slice = _slice_at_axis(slice(start, stop, -1), axis)
+ right_chunk = padded[right_slice]
+
+ if method == "odd":
+ # Negate chunk and align with edge
+ edge_slice = _slice_at_axis(
+ slice(-right_pad - 1, -right_pad), axis)
+ right_chunk = 2 * padded[edge_slice] - right_chunk
+
+ # Insert chunk into padded area
+ start = padded.shape[axis] - right_pad
+ stop = start + chunk_length
+ pad_area = _slice_at_axis(slice(start, stop), axis)
+ padded[pad_area] = right_chunk
+ # Adjust pointer to right edge for next iteration
+ right_pad -= chunk_length
+
+ return left_pad, right_pad
+
+
+def _set_wrap_both(padded, axis, width_pair):
+ """
+ Pad `axis` of `arr` with wrapped values.
Parameters
----------
- arr : ndarray
+ padded : ndarray
Input array of arbitrary shape.
- pad_amt : tuple of ints, length 2
- Padding to (prepend, append) along `axis`.
axis : int
Axis along which to pad `arr`.
+ width_pair : (int, int)
+ Pair of widths that mark the pad area on both sides in the given
+ dimension.
Returns
-------
- padarr : ndarray
- Output array, with `pad_amt[0]` values prepended and `pad_amt[1]`
- values appended along `axis`. Both regions are padded wrapped values
- from the opposite end of `axis`.
-
- Notes
- -----
- This method of padding is also known as 'tile' or 'tiling'.
-
- The modes 'reflect', 'symmetric', and 'wrap' must be padded with a
- single function, lest the indexing tricks in non-integer multiples of the
- original shape would violate repetition in the final iteration.
-
- """
- # Implicit booleanness to test for zero (or None) in any scalar type
- if pad_amt[0] == 0 and pad_amt[1] == 0:
- return arr
-
- ##########################################################################
- # Prepended region
-
- # Slice off a reverse indexed chunk from near edge to pad `arr` before
- wrap_slice = _slice_last(arr.shape, pad_amt[0], axis=axis)
- wrap_chunk1 = arr[wrap_slice]
-
- ##########################################################################
- # Appended region
-
- # Slice off a reverse indexed chunk from far edge to pad `arr` after
- wrap_slice = _slice_first(arr.shape, pad_amt[1], axis=axis)
- wrap_chunk2 = arr[wrap_slice]
-
- # Concatenate `arr` with both chunks, extending along `axis`
- return np.concatenate((wrap_chunk1, arr, wrap_chunk2), axis=axis)
+ pad_amt : tuple of ints, length 2
+ New index positions of padding to do along the `axis`. If these are
+ both 0, padding is done in this dimension.
+ """
+ left_pad, right_pad = width_pair
+ period = padded.shape[axis] - right_pad - left_pad
+
+ # If the current dimension of `arr` doesn't contain enough valid values
+ # (not part of the undefined pad area) we need to pad multiple times.
+ # Each time the pad area shrinks on both sides which is communicated with
+ # these variables.
+ new_left_pad = 0
+ new_right_pad = 0
+
+ if left_pad > 0:
+ # Pad with wrapped values on left side
+ # First slice chunk from right side of the non-pad area.
+ # Use min(period, left_pad) to ensure that chunk is not larger than
+ # pad area
+ right_slice = _slice_at_axis(
+ slice(-right_pad - min(period, left_pad),
+ -right_pad if right_pad != 0 else None),
+ axis
+ )
+ right_chunk = padded[right_slice]
+
+ if left_pad > period:
+ # Chunk is smaller than pad area
+ pad_area = _slice_at_axis(slice(left_pad - period, left_pad), axis)
+ new_left_pad = left_pad - period
+ else:
+ # Chunk matches pad area
+ pad_area = _slice_at_axis(slice(None, left_pad), axis)
+ padded[pad_area] = right_chunk
+
+ if right_pad > 0:
+ # Pad with wrapped values on right side
+ # First slice chunk from left side of the non-pad area.
+ # Use min(period, right_pad) to ensure that chunk is not larger than
+ # pad area
+ left_slice = _slice_at_axis(
+ slice(left_pad, left_pad + min(period, right_pad),), axis)
+ left_chunk = padded[left_slice]
+
+ if right_pad > period:
+ # Chunk is smaller than pad area
+ pad_area = _slice_at_axis(
+ slice(-right_pad, -right_pad + period), axis)
+ new_right_pad = right_pad - period
+ else:
+ # Chunk matches pad area
+ pad_area = _slice_at_axis(slice(-right_pad, None), axis)
+ padded[pad_area] = left_chunk
+
+ return new_left_pad, new_right_pad
def _as_pairs(x, ndim, as_index=False):
@@ -941,23 +568,23 @@ def _as_pairs(x, ndim, as_index=False):
return np.broadcast_to(x, (ndim, 2)).tolist()
-###############################################################################
-# Public functions
+def _pad_dispatcher(array, pad_width, mode=None, **kwargs):
+ return (array,)
-def _pad_dispatcher(array, pad_width, mode, **kwargs):
- return (array,)
+###############################################################################
+# Public functions
@array_function_dispatch(_pad_dispatcher, module='numpy')
-def pad(array, pad_width, mode, **kwargs):
+def pad(array, pad_width, mode='constant', **kwargs):
"""
- Pads an array.
+ Pad an array.
Parameters
----------
array : array_like of rank N
- Input array
+ The array to pad.
pad_width : {sequence, array_like, int}
Number of values padded to the edges of each axis.
((before_1, after_1), ... (before_N, after_N)) unique pad widths
@@ -965,10 +592,10 @@ def pad(array, pad_width, mode, **kwargs):
((before, after),) yields same before and after pad for each axis.
(pad,) or int is a shortcut for before = after = pad width for all
axes.
- mode : str or function
+ mode : str or function, optional
One of the following string values or a user supplied function.
- 'constant'
+ 'constant' (default)
Pads with a constant value.
'edge'
Pads with the edge values of array.
@@ -998,6 +625,11 @@ def pad(array, pad_width, mode, **kwargs):
Pads with the wrap of the vector along the axis.
The first values are used to pad the end and the
end values are used to pad the beginning.
+ 'empty'
+ Pads with undefined values.
+
+ .. versionadded:: 1.17
+
<function>
Padding function, see Notes.
stat_length : sequence or int, optional
@@ -1014,31 +646,31 @@ def pad(array, pad_width, mode, **kwargs):
length for all axes.
Default is ``None``, to use the entire axis.
- constant_values : sequence or int, optional
+ constant_values : sequence or scalar, optional
Used in 'constant'. The values to set the padded values for each
axis.
- ((before_1, after_1), ... (before_N, after_N)) unique pad constants
+ ``((before_1, after_1), ... (before_N, after_N))`` unique pad constants
for each axis.
- ((before, after),) yields same before and after constants for each
+ ``((before, after),)`` yields same before and after constants for each
axis.
- (constant,) or int is a shortcut for before = after = constant for
+ ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for
all axes.
Default is 0.
- end_values : sequence or int, optional
+ end_values : sequence or scalar, optional
Used in 'linear_ramp'. The values used for the ending value of the
linear_ramp and that will form the edge of the padded array.
- ((before_1, after_1), ... (before_N, after_N)) unique end values
+ ``((before_1, after_1), ... (before_N, after_N))`` unique end values
for each axis.
- ((before, after),) yields same before and after end values for each
+ ``((before, after),)`` yields same before and after end values for each
axis.
- (constant,) or int is a shortcut for before = after = end value for
+ ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for
all axes.
Default is 0.
@@ -1063,9 +695,8 @@ def pad(array, pad_width, mode, **kwargs):
think about with a rank 2 array where the corners of the padded array
are calculated by using padded values from the first axis.
- The padding function, if used, should return a rank 1 array equal in
- length to the vector argument with padded values replaced. It has the
- following signature::
+ The padding function, if used, should modify a rank 1 array in-place. It
+ has the following signature::
padding_func(vector, iaxis_pad_width, iaxis, kwargs)
@@ -1073,7 +704,7 @@ def pad(array, pad_width, mode, **kwargs):
vector : ndarray
A rank 1 array already padded with zeros. Padded values are
- vector[:pad_tuple[0]] and vector[-pad_tuple[1]:].
+ vector[:iaxis_pad_width[0]] and vector[-iaxis_pad_width[1]:].
iaxis_pad_width : tuple
A 2-tuple of ints, iaxis_pad_width[0] represents the number of
values padded at the beginning of vector where
@@ -1087,11 +718,11 @@ def pad(array, pad_width, mode, **kwargs):
Examples
--------
>>> a = [1, 2, 3, 4, 5]
- >>> np.pad(a, (2,3), 'constant', constant_values=(4, 6))
- array([4, 4, 1, 2, 3, 4, 5, 6, 6, 6])
+ >>> np.pad(a, (2, 3), 'constant', constant_values=(4, 6))
+ array([4, 4, 1, ..., 6, 6, 6])
>>> np.pad(a, (2, 3), 'edge')
- array([1, 1, 1, 2, 3, 4, 5, 5, 5, 5])
+ array([1, 1, 1, ..., 5, 5, 5])
>>> np.pad(a, (2, 3), 'linear_ramp', end_values=(5, -4))
array([ 5, 3, 1, 2, 3, 4, 5, 2, -1, -4])
@@ -1135,7 +766,6 @@ def pad(array, pad_width, mode, **kwargs):
... pad_value = kwargs.get('padder', 10)
... vector[:pad_width[0]] = pad_value
... vector[-pad_width[1]:] = pad_value
- ... return vector
>>> a = np.arange(6)
>>> a = a.reshape((2, 3))
>>> np.pad(a, 2, pad_with)
@@ -1153,15 +783,42 @@ def pad(array, pad_width, mode, **kwargs):
[100, 100, 100, 100, 100, 100, 100],
[100, 100, 100, 100, 100, 100, 100]])
"""
- if not np.asarray(pad_width).dtype.kind == 'i':
+ array = np.asarray(array)
+ pad_width = np.asarray(pad_width)
+
+ if not pad_width.dtype.kind == 'i':
raise TypeError('`pad_width` must be of integral type.')
- narray = np.array(array)
- pad_width = _as_pairs(pad_width, narray.ndim, as_index=True)
+ # Broadcast to shape (array.ndim, 2)
+ pad_width = _as_pairs(pad_width, array.ndim, as_index=True)
+
+ if callable(mode):
+ # Old behavior: Use user-supplied function with np.apply_along_axis
+ function = mode
+ # Create a new zero padded array
+ padded, _ = _pad_simple(array, pad_width, fill_value=0)
+ # And apply along each axis
+
+ for axis in range(padded.ndim):
+ # Iterate using ndindex as in apply_along_axis, but assuming that
+ # function operates inplace on the padded array.
+
+ # view with the iteration axis at the end
+ view = np.moveaxis(padded, axis, -1)
+
+ # compute indices for the iteration axes, and append a trailing
+ # ellipsis to prevent 0d arrays decaying to scalars (gh-8642)
+ inds = ndindex(view.shape[:-1])
+ inds = (ind + (Ellipsis,) for ind in inds)
+ for ind in inds:
+ function(view[ind], pad_width[axis], axis, kwargs)
- allowedkwargs = {
+ return padded
+
+ # Make sure that no unsupported keywords were passed for the current mode
+ allowed_kwargs = {
+ 'empty': [], 'edge': [], 'wrap': [],
'constant': ['constant_values'],
- 'edge': [],
'linear_ramp': ['end_values'],
'maximum': ['stat_length'],
'mean': ['stat_length'],
@@ -1169,175 +826,101 @@ def pad(array, pad_width, mode, **kwargs):
'minimum': ['stat_length'],
'reflect': ['reflect_type'],
'symmetric': ['reflect_type'],
- 'wrap': [],
- }
-
- kwdefaults = {
- 'stat_length': None,
- 'constant_values': 0,
- 'end_values': 0,
- 'reflect_type': 'even',
- }
-
- if isinstance(mode, np.compat.basestring):
- # Make sure have allowed kwargs appropriate for mode
- for key in kwargs:
- if key not in allowedkwargs[mode]:
- raise ValueError('%s keyword not in allowed keywords %s' %
- (key, allowedkwargs[mode]))
-
- # Set kwarg defaults
- for kw in allowedkwargs[mode]:
- kwargs.setdefault(kw, kwdefaults[kw])
-
- # Need to only normalize particular keywords.
- for i in kwargs:
- if i == 'stat_length':
- kwargs[i] = _as_pairs(kwargs[i], narray.ndim, as_index=True)
- if i in ['end_values', 'constant_values']:
- kwargs[i] = _as_pairs(kwargs[i], narray.ndim)
- else:
- # Drop back to old, slower np.apply_along_axis mode for user-supplied
- # vector function
- function = mode
-
- # Create a new padded array
- rank = list(range(narray.ndim))
- total_dim_increase = [np.sum(pad_width[i]) for i in rank]
- offset_slices = tuple(
- slice(pad_width[i][0], pad_width[i][0] + narray.shape[i])
- for i in rank)
- new_shape = np.array(narray.shape) + total_dim_increase
- newmat = np.zeros(new_shape, narray.dtype)
-
- # Insert the original array into the padded array
- newmat[offset_slices] = narray
-
- # This is the core of pad ...
- for iaxis in rank:
- np.apply_along_axis(function,
- iaxis,
- newmat,
- pad_width[iaxis],
- iaxis,
- kwargs)
- return newmat
-
- # If we get here, use new padding method
- newmat = narray.copy()
-
- # API preserved, but completely new algorithm which pads by building the
- # entire block to pad before/after `arr` with in one step, for each axis.
- if mode == 'constant':
- for axis, ((pad_before, pad_after), (before_val, after_val)) \
- in enumerate(zip(pad_width, kwargs['constant_values'])):
- newmat = _prepend_const(newmat, pad_before, before_val, axis)
- newmat = _append_const(newmat, pad_after, after_val, axis)
-
- elif mode == 'edge':
- for axis, (pad_before, pad_after) in enumerate(pad_width):
- newmat = _prepend_edge(newmat, pad_before, axis)
- newmat = _append_edge(newmat, pad_after, axis)
-
- elif mode == 'linear_ramp':
- for axis, ((pad_before, pad_after), (before_val, after_val)) \
- in enumerate(zip(pad_width, kwargs['end_values'])):
- newmat = _prepend_ramp(newmat, pad_before, before_val, axis)
- newmat = _append_ramp(newmat, pad_after, after_val, axis)
-
- elif mode == 'maximum':
- for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \
- in enumerate(zip(pad_width, kwargs['stat_length'])):
- newmat = _prepend_max(newmat, pad_before, chunk_before, axis)
- newmat = _append_max(newmat, pad_after, chunk_after, axis)
-
- elif mode == 'mean':
- for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \
- in enumerate(zip(pad_width, kwargs['stat_length'])):
- newmat = _prepend_mean(newmat, pad_before, chunk_before, axis)
- newmat = _append_mean(newmat, pad_after, chunk_after, axis)
-
- elif mode == 'median':
- for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \
- in enumerate(zip(pad_width, kwargs['stat_length'])):
- newmat = _prepend_med(newmat, pad_before, chunk_before, axis)
- newmat = _append_med(newmat, pad_after, chunk_after, axis)
-
- elif mode == 'minimum':
- for axis, ((pad_before, pad_after), (chunk_before, chunk_after)) \
- in enumerate(zip(pad_width, kwargs['stat_length'])):
- newmat = _prepend_min(newmat, pad_before, chunk_before, axis)
- newmat = _append_min(newmat, pad_after, chunk_after, axis)
-
- elif mode == 'reflect':
- for axis, (pad_before, pad_after) in enumerate(pad_width):
- if narray.shape[axis] == 0:
- # Axes with non-zero padding cannot be empty.
- if pad_before > 0 or pad_after > 0:
- raise ValueError("There aren't any elements to reflect"
- " in axis {} of `array`".format(axis))
- # Skip zero padding on empty axes.
- continue
-
- # Recursive padding along any axis where `pad_amt` is too large
- # for indexing tricks. We can only safely pad the original axis
- # length, to keep the period of the reflections consistent.
- if ((pad_before > 0) or
- (pad_after > 0)) and newmat.shape[axis] == 1:
+ }
+ try:
+ unsupported_kwargs = set(kwargs) - set(allowed_kwargs[mode])
+ except KeyError:
+ raise ValueError("mode '{}' is not supported".format(mode))
+ if unsupported_kwargs:
+ raise ValueError("unsupported keyword arguments for mode '{}': {}"
+ .format(mode, unsupported_kwargs))
+
+ stat_functions = {"maximum": np.max, "minimum": np.min,
+ "mean": np.mean, "median": np.median}
+
+ # Create array with final shape and original values
+ # (padded area is undefined)
+ padded, original_area_slice = _pad_simple(array, pad_width)
+ # And prepare iteration over all dimensions
+ # (zipping may be more readable than using enumerate)
+ axes = range(padded.ndim)
+
+ if mode == "constant":
+ values = kwargs.get("constant_values", 0)
+ values = _as_pairs(values, padded.ndim)
+ for axis, width_pair, value_pair in zip(axes, pad_width, values):
+ roi = _view_roi(padded, original_area_slice, axis)
+ _set_pad_area(roi, axis, width_pair, value_pair)
+
+ elif mode == "empty":
+ pass # Do nothing as _pad_simple already returned the correct result
+
+ elif array.size == 0:
+ # Only modes "constant" and "empty" can extend empty axes, all other
+ # modes depend on `array` not being empty
+ # -> ensure every empty axis is only "padded with 0"
+ for axis, width_pair in zip(axes, pad_width):
+ if array.shape[axis] == 0 and any(width_pair):
+ raise ValueError(
+ "can't extend empty axis {} using modes other than "
+ "'constant' or 'empty'".format(axis)
+ )
+ # passed, don't need to do anything more as _pad_simple already
+ # returned the correct result
+
+ elif mode == "edge":
+ for axis, width_pair in zip(axes, pad_width):
+ roi = _view_roi(padded, original_area_slice, axis)
+ edge_pair = _get_edges(roi, axis, width_pair)
+ _set_pad_area(roi, axis, width_pair, edge_pair)
+
+ elif mode == "linear_ramp":
+ end_values = kwargs.get("end_values", 0)
+ end_values = _as_pairs(end_values, padded.ndim)
+ for axis, width_pair, value_pair in zip(axes, pad_width, end_values):
+ roi = _view_roi(padded, original_area_slice, axis)
+ ramp_pair = _get_linear_ramps(roi, axis, width_pair, value_pair)
+ _set_pad_area(roi, axis, width_pair, ramp_pair)
+
+ elif mode in stat_functions:
+ func = stat_functions[mode]
+ length = kwargs.get("stat_length", None)
+ length = _as_pairs(length, padded.ndim, as_index=True)
+ for axis, width_pair, length_pair in zip(axes, pad_width, length):
+ roi = _view_roi(padded, original_area_slice, axis)
+ stat_pair = _get_stats(roi, axis, width_pair, length_pair, func)
+ _set_pad_area(roi, axis, width_pair, stat_pair)
+
+ elif mode in {"reflect", "symmetric"}:
+ method = kwargs.get("reflect_type", "even")
+ include_edge = True if mode == "symmetric" else False
+ for axis, (left_index, right_index) in zip(axes, pad_width):
+ if array.shape[axis] == 1 and (left_index > 0 or right_index > 0):
# Extending singleton dimension for 'reflect' is legacy
# behavior; it really should raise an error.
- newmat = _prepend_edge(newmat, pad_before, axis)
- newmat = _append_edge(newmat, pad_after, axis)
+ edge_pair = _get_edges(padded, axis, (left_index, right_index))
+ _set_pad_area(
+ padded, axis, (left_index, right_index), edge_pair)
continue
- method = kwargs['reflect_type']
- safe_pad = newmat.shape[axis] - 1
- while ((pad_before > safe_pad) or (pad_after > safe_pad)):
- pad_iter_b = min(safe_pad,
- safe_pad * (pad_before // safe_pad))
- pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad))
- newmat = _pad_ref(newmat, (pad_iter_b,
- pad_iter_a), method, axis)
- pad_before -= pad_iter_b
- pad_after -= pad_iter_a
- safe_pad += pad_iter_b + pad_iter_a
- newmat = _pad_ref(newmat, (pad_before, pad_after), method, axis)
-
- elif mode == 'symmetric':
- for axis, (pad_before, pad_after) in enumerate(pad_width):
- # Recursive padding along any axis where `pad_amt` is too large
- # for indexing tricks. We can only safely pad the original axis
- # length, to keep the period of the reflections consistent.
- method = kwargs['reflect_type']
- safe_pad = newmat.shape[axis]
- while ((pad_before > safe_pad) or
- (pad_after > safe_pad)):
- pad_iter_b = min(safe_pad,
- safe_pad * (pad_before // safe_pad))
- pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad))
- newmat = _pad_sym(newmat, (pad_iter_b,
- pad_iter_a), method, axis)
- pad_before -= pad_iter_b
- pad_after -= pad_iter_a
- safe_pad += pad_iter_b + pad_iter_a
- newmat = _pad_sym(newmat, (pad_before, pad_after), method, axis)
-
- elif mode == 'wrap':
- for axis, (pad_before, pad_after) in enumerate(pad_width):
- # Recursive padding along any axis where `pad_amt` is too large
- # for indexing tricks. We can only safely pad the original axis
- # length, to keep the period of the reflections consistent.
- safe_pad = newmat.shape[axis]
- while ((pad_before > safe_pad) or
- (pad_after > safe_pad)):
- pad_iter_b = min(safe_pad,
- safe_pad * (pad_before // safe_pad))
- pad_iter_a = min(safe_pad, safe_pad * (pad_after // safe_pad))
- newmat = _pad_wrap(newmat, (pad_iter_b, pad_iter_a), axis)
-
- pad_before -= pad_iter_b
- pad_after -= pad_iter_a
- safe_pad += pad_iter_b + pad_iter_a
- newmat = _pad_wrap(newmat, (pad_before, pad_after), axis)
-
- return newmat
+ roi = _view_roi(padded, original_area_slice, axis)
+ while left_index > 0 or right_index > 0:
+ # Iteratively pad until dimension is filled with reflected
+ # values. This is necessary if the pad area is larger than
+ # the length of the original values in the current dimension.
+ left_index, right_index = _set_reflect_both(
+ roi, axis, (left_index, right_index),
+ method, include_edge
+ )
+
+ elif mode == "wrap":
+ for axis, (left_index, right_index) in zip(axes, pad_width):
+ roi = _view_roi(padded, original_area_slice, axis)
+ while left_index > 0 or right_index > 0:
+ # Iteratively pad until dimension is filled with wrapped
+ # values. This is necessary if the pad area is larger than
+ # the length of the original values in the current dimension.
+ left_index, right_index = _set_wrap_both(
+ roi, axis, (left_index, right_index))
+
+ return padded
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index 3356904ab..f3f4bc17e 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -82,7 +82,7 @@ def ediff1d(ary, to_end=None, to_begin=None):
array([ 1, 2, 3, -7])
>>> np.ediff1d(x, to_begin=-99, to_end=np.array([88, 99]))
- array([-99, 1, 2, 3, -7, 88, 99])
+ array([-99, 1, 2, ..., -7, 88, 99])
The returned array is always 1D.
@@ -239,13 +239,11 @@ def unique(ar, return_index=False, return_inverse=False,
>>> a = np.array(['a', 'b', 'b', 'c', 'a'])
>>> u, indices = np.unique(a, return_index=True)
>>> u
- array(['a', 'b', 'c'],
- dtype='|S1')
+ array(['a', 'b', 'c'], dtype='<U1')
>>> indices
array([0, 1, 3])
>>> a[indices]
- array(['a', 'b', 'c'],
- dtype='|S1')
+ array(['a', 'b', 'c'], dtype='<U1')
Reconstruct the input array from the unique values:
@@ -254,9 +252,9 @@ def unique(ar, return_index=False, return_inverse=False,
>>> u
array([1, 2, 3, 4, 6])
>>> indices
- array([0, 1, 4, 3, 1, 2, 1])
+ array([0, 1, 4, ..., 1, 2, 1])
>>> u[indices]
- array([1, 2, 6, 4, 2, 3, 2])
+ array([1, 2, 6, ..., 2, 3, 2])
"""
ar = np.asanyarray(ar)
@@ -385,6 +383,7 @@ def intersect1d(ar1, ar2, assume_unique=False, return_indices=False):
To return the indices of the values common to the input arrays
along with the intersected values:
+
>>> x = np.array([1, 1, 2, 3, 4])
>>> y = np.array([2, 1, 4, 6])
>>> xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True)
@@ -659,8 +658,8 @@ def isin(element, test_elements, assume_unique=False, invert=False):
>>> test_elements = [1, 2, 4, 8]
>>> mask = np.isin(element, test_elements)
>>> mask
- array([[ False, True],
- [ True, False]])
+ array([[False, True],
+ [ True, False]])
>>> element[mask]
array([2, 4])
@@ -674,7 +673,7 @@ def isin(element, test_elements, assume_unique=False, invert=False):
>>> mask = np.isin(element, test_elements, invert=True)
>>> mask
array([[ True, False],
- [ False, True]])
+ [False, True]])
>>> element[mask]
array([0, 6])
@@ -683,14 +682,14 @@ def isin(element, test_elements, assume_unique=False, invert=False):
>>> test_set = {1, 2, 4, 8}
>>> np.isin(element, test_set)
- array([[ False, False],
- [ False, False]])
+ array([[False, False],
+ [False, False]])
Casting the set to a list gives the expected result:
>>> np.isin(element, list(test_set))
- array([[ False, True],
- [ True, False]])
+ array([[False, True],
+ [ True, False]])
"""
element = np.asarray(element)
return in1d(element, test_elements, assume_unique=assume_unique,
diff --git a/numpy/lib/arrayterator.py b/numpy/lib/arrayterator.py
index f2d4fe9fd..c16668582 100644
--- a/numpy/lib/arrayterator.py
+++ b/numpy/lib/arrayterator.py
@@ -80,9 +80,8 @@ class Arrayterator(object):
>>> for subarr in a_itor:
... if not subarr.all():
- ... print(subarr, subarr.shape)
- ...
- [[[[0 1]]]] (1, 1, 1, 2)
+ ... print(subarr, subarr.shape) # doctest: +SKIP
+ >>> # [[[[0 1]]]] (1, 1, 1, 2)
"""
@@ -160,7 +159,7 @@ class Arrayterator(object):
... if not subarr:
... print(subarr, type(subarr))
...
- 0 <type 'numpy.int32'>
+ 0 <class 'numpy.int64'>
"""
for block in self:
diff --git a/numpy/lib/financial.py b/numpy/lib/financial.py
index e1e297492..216687475 100644
--- a/numpy/lib/financial.py
+++ b/numpy/lib/financial.py
@@ -127,7 +127,7 @@ def fv(rate, nper, pmt, pv, when='end'):
>>> a = np.array((0.05, 0.06, 0.07))/12
>>> np.fv(a, 10*12, -100, -100)
- array([ 15692.92889434, 16569.87435405, 17509.44688102])
+ array([ 15692.92889434, 16569.87435405, 17509.44688102]) # may vary
"""
when = _convert_when(when)
@@ -275,7 +275,7 @@ def nper(rate, pmt, pv, fv=0, when='end'):
If you only had $150/month to pay towards the loan, how long would it take
to pay-off a loan of $8,000 at 7% annual interest?
- >>> print(round(np.nper(0.07/12, -150, 8000), 5))
+ >>> print(np.round(np.nper(0.07/12, -150, 8000), 5))
64.07335
So, over 64 months would be required to pay off the loan.
@@ -286,10 +286,10 @@ def nper(rate, pmt, pv, fv=0, when='end'):
>>> np.nper(*(np.ogrid[0.07/12: 0.08/12: 0.01/12,
... -150 : -99 : 50 ,
... 8000 : 9001 : 1000]))
- array([[[ 64.07334877, 74.06368256],
- [ 108.07548412, 127.99022654]],
- [[ 66.12443902, 76.87897353],
- [ 114.70165583, 137.90124779]]])
+ array([[[ 64.07334877, 74.06368256],
+ [108.07548412, 127.99022654]],
+ [[ 66.12443902, 76.87897353],
+ [114.70165583, 137.90124779]]])
"""
when = _convert_when(when)
@@ -539,7 +539,7 @@ def pv(rate, nper, pmt, fv=0, when='end'):
>>> a = np.array((0.05, 0.04, 0.03))/12
>>> np.pv(a, 10*12, -100, 15692.93)
- array([ -100.00067132, -649.26771385, -1273.78633713])
+ array([ -100.00067132, -649.26771385, -1273.78633713]) # may vary
So, to end up with the same $15692.93 under the same $100 per month
"savings plan," for annual interest rates of 4% and 3%, one would
@@ -704,15 +704,15 @@ def irr(values):
Examples
--------
- >>> round(irr([-100, 39, 59, 55, 20]), 5)
+ >>> round(np.irr([-100, 39, 59, 55, 20]), 5)
0.28095
- >>> round(irr([-100, 0, 0, 74]), 5)
+ >>> round(np.irr([-100, 0, 0, 74]), 5)
-0.0955
- >>> round(irr([-100, 100, 0, -7]), 5)
+ >>> round(np.irr([-100, 100, 0, -7]), 5)
-0.0833
- >>> round(irr([-100, 100, 0, 7]), 5)
+ >>> round(np.irr([-100, 100, 0, 7]), 5)
0.06206
- >>> round(irr([-5, 10.5, 1, -8, 1]), 5)
+ >>> round(np.irr([-5, 10.5, 1, -8, 1]), 5)
0.0886
(Compare with the Example given for numpy.lib.financial.npv)
@@ -777,7 +777,7 @@ def npv(rate, values):
Examples
--------
>>> np.npv(0.281,[-100, 39, 59, 55, 20])
- -0.0084785916384548798
+ -0.0084785916384548798 # may vary
(Compare with the Example given for numpy.lib.financial.irr)
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
index 74dfc26d8..93bdbce97 100644
--- a/numpy/lib/format.py
+++ b/numpy/lib/format.py
@@ -146,6 +146,13 @@ The description of the fourth element of the header therefore has become:
"The next 4 bytes form a little-endian unsigned int: the length of the header
data HEADER_LEN."
+Format Version 3.0
+------------------
+
+This version replaces the ASCII string (which in practice was latin1) with
+a utf8-encoded string, so supports structured types with any unicode field
+names.
+
Notes
-----
The ``.npy`` format, including motivation for creating it and a comparison of
@@ -162,9 +169,8 @@ import io
import warnings
from numpy.lib.utils import safe_eval
from numpy.compat import (
- asbytes, asstr, isfileobj, long, os_fspath
+ isfileobj, long, os_fspath, pickle
)
-from numpy.core.numeric import pickle
MAGIC_PREFIX = b'\x93NUMPY'
@@ -174,10 +180,16 @@ BUFFER_SIZE = 2**18 # size of buffer for reading npz files in bytes
# difference between version 1.0 and 2.0 is a 4 byte (I) header length
# instead of 2 bytes (H) allowing storage of large structured arrays
+_header_size_info = {
+ (1, 0): ('<H', 'latin1'),
+ (2, 0): ('<I', 'latin1'),
+ (3, 0): ('<I', 'utf8'),
+}
+
def _check_version(version):
- if version not in [(1, 0), (2, 0), None]:
- msg = "we only support format version (1,0) and (2, 0), not %s"
+ if version not in [(1, 0), (2, 0), (3, 0), None]:
+ msg = "we only support format version (1,0), (2,0), and (3,0), not %s"
raise ValueError(msg % (version,))
def magic(major, minor):
@@ -327,6 +339,56 @@ def header_data_from_array_1_0(array):
d['descr'] = dtype_to_descr(array.dtype)
return d
+
+def _wrap_header(header, version):
+ """
+ Takes a stringified header, and attaches the prefix and padding to it
+ """
+ import struct
+ assert version is not None
+ fmt, encoding = _header_size_info[version]
+ if not isinstance(header, bytes): # always true on python 3
+ header = header.encode(encoding)
+ hlen = len(header) + 1
+ padlen = ARRAY_ALIGN - ((MAGIC_LEN + struct.calcsize(fmt) + hlen) % ARRAY_ALIGN)
+ try:
+ header_prefix = magic(*version) + struct.pack(fmt, hlen + padlen)
+ except struct.error:
+ msg = "Header length {} too big for version={}".format(hlen, version)
+ raise ValueError(msg)
+
+ # Pad the header with spaces and a final newline such that the magic
+ # string, the header-length short and the header are aligned on a
+ # ARRAY_ALIGN byte boundary. This supports memory mapping of dtypes
+ # aligned up to ARRAY_ALIGN on systems like Linux where mmap()
+ # offset must be page-aligned (i.e. the beginning of the file).
+ return header_prefix + header + b' '*padlen + b'\n'
+
+
+def _wrap_header_guess_version(header):
+ """
+ Like `_wrap_header`, but chooses an appropriate version given the contents
+ """
+ try:
+ return _wrap_header(header, (1, 0))
+ except ValueError:
+ pass
+
+ try:
+ ret = _wrap_header(header, (2, 0))
+ except UnicodeEncodeError:
+ pass
+ else:
+ warnings.warn("Stored array in format 2.0. It can only be"
+ "read by NumPy >= 1.9", UserWarning, stacklevel=2)
+ return ret
+
+ header = _wrap_header(header, (3, 0))
+ warnings.warn("Stored array in format 3.0. It can only be"
+ "read by NumPy >= 1.17", UserWarning, stacklevel=2)
+ return header
+
+
def _write_array_header(fp, d, version=None):
""" Write the header for an array and returns the version used
@@ -340,48 +402,19 @@ def _write_array_header(fp, d, version=None):
None means use oldest that works
explicit version will raise a ValueError if the format does not
allow saving this data. Default: None
- Returns
- -------
- version : tuple of int
- the file version which needs to be used to store the data
"""
- import struct
header = ["{"]
for key, value in sorted(d.items()):
# Need to use repr here, since we eval these when reading
header.append("'%s': %s, " % (key, repr(value)))
header.append("}")
header = "".join(header)
- header = asbytes(_filter_header(header))
-
- hlen = len(header) + 1 # 1 for newline
- padlen_v1 = ARRAY_ALIGN - ((MAGIC_LEN + struct.calcsize('<H') + hlen) % ARRAY_ALIGN)
- padlen_v2 = ARRAY_ALIGN - ((MAGIC_LEN + struct.calcsize('<I') + hlen) % ARRAY_ALIGN)
-
- # Which version(s) we write depends on the total header size; v1 has a max of 65535
- if hlen + padlen_v1 < 2**16 and version in (None, (1, 0)):
- version = (1, 0)
- header_prefix = magic(1, 0) + struct.pack('<H', hlen + padlen_v1)
- topad = padlen_v1
- elif hlen + padlen_v2 < 2**32 and version in (None, (2, 0)):
- version = (2, 0)
- header_prefix = magic(2, 0) + struct.pack('<I', hlen + padlen_v2)
- topad = padlen_v2
+ header = _filter_header(header)
+ if version is None:
+ header = _wrap_header_guess_version(header)
else:
- msg = "Header length %s too big for version=%s"
- msg %= (hlen, version)
- raise ValueError(msg)
-
- # Pad the header with spaces and a final newline such that the magic
- # string, the header-length short and the header are aligned on a
- # ARRAY_ALIGN byte boundary. This supports memory mapping of dtypes
- # aligned up to ARRAY_ALIGN on systems like Linux where mmap()
- # offset must be page-aligned (i.e. the beginning of the file).
- header = header + b' '*topad + b'\n'
-
- fp.write(header_prefix)
+ header = _wrap_header(header, version)
fp.write(header)
- return version
def write_array_header_1_0(fp, d):
""" Write the header for an array using the 1.0 format.
@@ -484,7 +517,7 @@ def _filter_header(s):
Parameters
----------
- s : byte string
+ s : string
Npy file header.
Returns
@@ -502,7 +535,7 @@ def _filter_header(s):
tokens = []
last_token_was_number = False
# adding newline as python 2.7.5 workaround
- string = asstr(s) + "\n"
+ string = s + "\n"
for token in tokenize.generate_tokens(StringIO(string).readline):
token_type = token[0]
token_string = token[1]
@@ -524,16 +557,15 @@ def _read_array_header(fp, version):
# Read an unsigned, little-endian short int which has the length of the
# header.
import struct
- if version == (1, 0):
- hlength_type = '<H'
- elif version == (2, 0):
- hlength_type = '<I'
- else:
+ hinfo = _header_size_info.get(version)
+ if hinfo is None:
raise ValueError("Invalid version {!r}".format(version))
+ hlength_type, encoding = hinfo
hlength_str = _read_bytes(fp, struct.calcsize(hlength_type), "array header length")
header_length = struct.unpack(hlength_type, hlength_str)[0]
header = _read_bytes(fp, header_length, "array header")
+ header = header.decode(encoding)
# The header is a pretty-printed string representation of a literal
# Python dictionary with trailing newlines padded to a ARRAY_ALIGN byte
@@ -608,12 +640,7 @@ def write_array(fp, array, version=None, allow_pickle=True, pickle_kwargs=None):
"""
_check_version(version)
- used_ver = _write_array_header(fp, header_data_from_array_1_0(array),
- version)
- # this warning can be removed when 1.9 has aged enough
- if version != (2, 0) and used_ver == (2, 0):
- warnings.warn("Stored array in format 2.0. It can only be"
- "read by NumPy >= 1.9", UserWarning, stacklevel=2)
+ _write_array_header(fp, header_data_from_array_1_0(array), version)
if array.itemsize == 0:
buffersize = 0
@@ -623,14 +650,13 @@ def write_array(fp, array, version=None, allow_pickle=True, pickle_kwargs=None):
if array.dtype.hasobject:
# We contain Python objects so we cannot write out the data
- # directly. Instead, we will pickle it out with version 2 of the
- # pickle protocol.
+ # directly. Instead, we will pickle it out
if not allow_pickle:
raise ValueError("Object arrays cannot be saved when "
"allow_pickle=False")
if pickle_kwargs is None:
pickle_kwargs = {}
- pickle.dump(array, fp, protocol=2, **pickle_kwargs)
+ pickle.dump(array, fp, protocol=3, **pickle_kwargs)
elif array.flags.f_contiguous and not array.flags.c_contiguous:
if isfileobj(fp):
array.T.tofile(fp)
@@ -814,20 +840,12 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None,
shape=shape,
)
# If we got here, then it should be safe to create the file.
- fp = open(os_fspath(filename), mode+'b')
- try:
- used_ver = _write_array_header(fp, d, version)
- # this warning can be removed when 1.9 has aged enough
- if version != (2, 0) and used_ver == (2, 0):
- warnings.warn("Stored array in format 2.0. It can only be"
- "read by NumPy >= 1.9", UserWarning, stacklevel=2)
+ with open(os_fspath(filename), mode+'b') as fp:
+ _write_array_header(fp, d, version)
offset = fp.tell()
- finally:
- fp.close()
else:
# Read the header of the file first.
- fp = open(os_fspath(filename), 'rb')
- try:
+ with open(os_fspath(filename), 'rb') as fp:
version = read_magic(fp)
_check_version(version)
@@ -836,8 +854,6 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None,
msg = "Array can't be memory-mapped: Python objects in dtype."
raise ValueError(msg)
offset = fp.tell()
- finally:
- fp.close()
if fortran_order:
order = 'F'
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index d9ce3f8a4..cf7246402 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1,7 +1,7 @@
from __future__ import division, absolute_import, print_function
try:
- # Accessing collections abstact classes from collections
+ # Accessing collections abstract classes from collections
# has been deprecated since Python 3.3
import collections.abc as collections_abc
except ImportError:
@@ -31,7 +31,6 @@ from numpy.core.overrides import set_module
from numpy.core import overrides
from numpy.core.function_base import add_newdoc
from numpy.lib.twodim_base import diag
-from .utils import deprecate
from numpy.core.multiarray import (
_insert, add_docstring, bincount, normalize_axis_index, _monotonicity,
interp as compiled_interp, interp_complex as compiled_interp_complex
@@ -218,12 +217,12 @@ def flip(m, axis=None):
[2, 3]],
[[4, 5],
[6, 7]]])
- >>> flip(A, 0)
+ >>> np.flip(A, 0)
array([[[4, 5],
[6, 7]],
[[0, 1],
[2, 3]]])
- >>> flip(A, 1)
+ >>> np.flip(A, 1)
array([[[2, 3],
[0, 1]],
[[6, 7],
@@ -239,7 +238,7 @@ def flip(m, axis=None):
[[1, 0],
[3, 2]]])
>>> A = np.random.randn(3,4,5)
- >>> np.all(flip(A,2) == A[:,:,::-1,...])
+ >>> np.all(np.flip(A,2) == A[:,:,::-1,...])
True
"""
if not hasattr(m, 'ndim'):
@@ -359,7 +358,7 @@ def average(a, axis=None, weights=None, returned=False):
Examples
--------
- >>> data = range(1,5)
+ >>> data = list(range(1,5))
>>> data
[1, 2, 3, 4]
>>> np.average(data)
@@ -373,13 +372,12 @@ def average(a, axis=None, weights=None, returned=False):
[2, 3],
[4, 5]])
>>> np.average(data, axis=1, weights=[1./4, 3./4])
- array([ 0.75, 2.75, 4.75])
+ array([0.75, 2.75, 4.75])
>>> np.average(data, weights=[1./4, 3./4])
-
Traceback (most recent call last):
- ...
+ ...
TypeError: Axis must be specified when shapes of a and weights differ.
-
+
>>> a = np.ones(5, dtype=np.float128)
>>> w = np.ones(5, dtype=np.complex64)
>>> avg = np.average(a, weights=w)
@@ -586,7 +584,7 @@ def piecewise(x, condlist, funclist, *args, **kw):
``x >= 0``.
>>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x])
- array([ 2.5, 1.5, 0.5, 0.5, 1.5, 2.5])
+ array([2.5, 1.5, 0.5, 0.5, 1.5, 2.5])
Apply the same function to a scalar value.
@@ -671,7 +669,7 @@ def select(condlist, choicelist, default=0):
>>> condlist = [x<3, x>5]
>>> choicelist = [x, x**2]
>>> np.select(condlist, choicelist)
- array([ 0, 1, 2, 0, 0, 0, 36, 49, 64, 81])
+ array([ 0, 1, 2, ..., 49, 64, 81])
"""
# Check the size of condlist and choicelist are the same, or abort.
@@ -684,7 +682,7 @@ def select(condlist, choicelist, default=0):
# 2014-02-24, 1.9
warnings.warn("select with an empty condition list is not possible"
"and will be deprecated",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
return np.asarray(default)[()]
choicelist = [np.asarray(choice) for choice in choicelist]
@@ -719,7 +717,7 @@ def select(condlist, choicelist, default=0):
msg = "select condlists containing integer ndarrays is deprecated " \
"and will be removed in the future. Use `.astype(bool)` to " \
"convert to bools."
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ warnings.warn(msg, DeprecationWarning, stacklevel=3)
if choicelist[0].ndim == 0:
# This may be common, so avoid the call.
@@ -854,9 +852,9 @@ def gradient(f, *varargs, **kwargs):
--------
>>> f = np.array([1, 2, 4, 7, 11, 16], dtype=float)
>>> np.gradient(f)
- array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ])
+ array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
>>> np.gradient(f, 2)
- array([ 0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ])
+ array([0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ])
Spacing can be also specified with an array that represents the coordinates
of the values F along the dimensions.
@@ -864,13 +862,13 @@ def gradient(f, *varargs, **kwargs):
>>> x = np.arange(f.size)
>>> np.gradient(f, x)
- array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ])
+ array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
Or a non uniform one:
>>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=float)
>>> np.gradient(f, x)
- array([ 1. , 3. , 3.5, 6.7, 6.9, 2.5])
+ array([1. , 3. , 3.5, 6.7, 6.9, 2.5])
For two dimensional arrays, the return will be two arrays ordered by
axis. In this example the first array stands for the gradient in
@@ -878,8 +876,8 @@ def gradient(f, *varargs, **kwargs):
>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float))
[array([[ 2., 2., -1.],
- [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ],
- [ 1. , 1. , 1. ]])]
+ [ 2., 2., -1.]]), array([[1. , 2.5, 4. ],
+ [1. , 1. , 1. ]])]
In this example the spacing is also specified:
uniform for axis=0 and non uniform for axis=1
@@ -888,17 +886,17 @@ def gradient(f, *varargs, **kwargs):
>>> y = [1., 1.5, 3.5]
>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), dx, y)
[array([[ 1. , 1. , -0.5],
- [ 1. , 1. , -0.5]]), array([[ 2. , 2. , 2. ],
- [ 2. , 1.7, 0.5]])]
+ [ 1. , 1. , -0.5]]), array([[2. , 2. , 2. ],
+ [2. , 1.7, 0.5]])]
It is possible to specify how boundaries are treated using `edge_order`
>>> x = np.array([0, 1, 2, 3, 4])
>>> f = x**2
>>> np.gradient(f, edge_order=1)
- array([ 1., 2., 4., 6., 7.])
+ array([1., 2., 4., 6., 7.])
>>> np.gradient(f, edge_order=2)
- array([-0., 2., 4., 6., 8.])
+ array([0., 2., 4., 6., 8.])
The `axis` keyword can be used to specify a subset of axes of which the
gradient is calculated
@@ -1151,7 +1149,7 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
"""
Calculate the n-th discrete difference along the given axis.
- The first difference is given by ``out[n] = a[n+1] - a[n]`` along
+ The first difference is given by ``out[i] = a[i+1] - a[i]`` along
the given axis, higher differences are calculated by using `diff`
recursively.
@@ -1200,7 +1198,7 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
>>> np.diff(u8_arr)
array([255], dtype=uint8)
>>> u8_arr[1,...] - u8_arr[0,...]
- array(255, np.uint8)
+ 255
If this is not desirable, then the array should be cast to a larger
integer type first:
@@ -1237,6 +1235,8 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
a = asanyarray(a)
nd = a.ndim
+ if nd == 0:
+ raise ValueError("diff requires input that is at least one dimensional")
axis = normalize_axis_index(axis, nd)
combined = []
@@ -1340,7 +1340,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
>>> np.interp(2.5, xp, fp)
1.0
>>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp)
- array([ 3. , 3. , 2.5 , 0.56, 0. ])
+ array([3. , 3. , 2.5 , 0.56, 0. ])
>>> UNDEF = -99.0
>>> np.interp(3.14, xp, fp, right=UNDEF)
-99.0
@@ -1364,7 +1364,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
>>> xp = [190, -190, 350, -350]
>>> fp = [5, 10, 3, 4]
>>> np.interp(x, xp, fp, period=360)
- array([7.5, 5., 8.75, 6.25, 3., 3.25, 3.5, 3.75])
+ array([7.5 , 5. , 8.75, 6.25, 3. , 3.25, 3.5 , 3.75])
Complex interpolation:
@@ -1372,7 +1372,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
>>> xp = [2,3,5]
>>> fp = [1.0j, 0, 2+3j]
>>> np.interp(x, xp, fp)
- array([ 0.+1.j , 1.+1.5j])
+ array([0.+1.j , 1.+1.5j])
"""
@@ -1431,9 +1431,9 @@ def angle(z, deg=False):
Returns
-------
angle : ndarray or scalar
- The counterclockwise angle from the positive real axis on
- the complex plane, with dtype as numpy.float64.
-
+ The counterclockwise angle from the positive real axis on the complex
+ plane in the range ``(-pi, pi]``, with dtype as numpy.float64.
+
..versionchanged:: 1.16.0
This function works on subclasses of ndarray like `ma.array`.
@@ -1445,7 +1445,7 @@ def angle(z, deg=False):
Examples
--------
>>> np.angle([1.0, 1.0j, 1+1j]) # in radians
- array([ 0. , 1.57079633, 0.78539816])
+ array([ 0. , 1.57079633, 0.78539816]) # may vary
>>> np.angle(1+1j, deg=True) # in degrees
45.0
@@ -1505,9 +1505,9 @@ def unwrap(p, discont=pi, axis=-1):
>>> phase = np.linspace(0, np.pi, num=5)
>>> phase[3:] += np.pi
>>> phase
- array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531])
+ array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531]) # may vary
>>> np.unwrap(phase)
- array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ])
+ array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ]) # may vary
"""
p = asarray(p)
@@ -1547,10 +1547,10 @@ def sort_complex(a):
Examples
--------
>>> np.sort_complex([5, 3, 6, 2, 1])
- array([ 1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])
+ array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])
>>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j])
- array([ 1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])
+ array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])
"""
b = array(a, copy=True)
@@ -1596,7 +1596,7 @@ def trim_zeros(filt, trim='fb'):
array([1, 2, 3, 0, 2, 1])
>>> np.trim_zeros(a, 'b')
- array([0, 0, 0, 1, 2, 3, 0, 2, 1])
+ array([0, 0, 0, ..., 0, 2, 1])
The input data type is preserved, list/tuple in means list/tuple out.
@@ -1931,6 +1931,30 @@ class vectorize(object):
vectorized : callable
Vectorized function.
+ See Also
+ --------
+ frompyfunc : Takes an arbitrary Python function and returns a ufunc
+
+ Notes
+ -----
+ The `vectorize` function is provided primarily for convenience, not for
+ performance. The implementation is essentially a for loop.
+
+ If `otypes` is not specified, then a call to the function with the
+ first argument will be used to determine the number of outputs. The
+ results of this call will be cached if `cache` is `True` to prevent
+ calling the function twice. However, to implement the cache, the
+ original function must be wrapped which will slow down subsequent
+ calls, so only do this if your function is expensive.
+
+ The new keyword argument interface and `excluded` argument support
+ further degrades performance.
+
+ References
+ ----------
+ .. [1] NumPy Reference, section `Generalized Universal Function API
+ <https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html>`_.
+
Examples
--------
>>> def myfunc(a, b):
@@ -1958,11 +1982,11 @@ class vectorize(object):
>>> out = vfunc([1, 2, 3, 4], 2)
>>> type(out[0])
- <type 'numpy.int32'>
+ <class 'numpy.int64'>
>>> vfunc = np.vectorize(myfunc, otypes=[float])
>>> out = vfunc([1, 2, 3, 4], 2)
>>> type(out[0])
- <type 'numpy.float64'>
+ <class 'numpy.float64'>
The `excluded` argument can be used to prevent vectorizing over certain
arguments. This can be useful for array-like arguments of a fixed length
@@ -1990,7 +2014,7 @@ class vectorize(object):
>>> import scipy.stats
>>> pearsonr = np.vectorize(scipy.stats.pearsonr,
- ... signature='(n),(n)->(),()')
+ ... signature='(n),(n)->(),()')
>>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]])
(array([ 1., -1.]), array([ 0., 0.]))
@@ -1998,36 +2022,12 @@ class vectorize(object):
>>> convolve = np.vectorize(np.convolve, signature='(n),(m)->(k)')
>>> convolve(np.eye(4), [1, 2, 1])
- array([[ 1., 2., 1., 0., 0., 0.],
- [ 0., 1., 2., 1., 0., 0.],
- [ 0., 0., 1., 2., 1., 0.],
- [ 0., 0., 0., 1., 2., 1.]])
-
- See Also
- --------
- frompyfunc : Takes an arbitrary Python function and returns a ufunc
-
- Notes
- -----
- The `vectorize` function is provided primarily for convenience, not for
- performance. The implementation is essentially a for loop.
-
- If `otypes` is not specified, then a call to the function with the
- first argument will be used to determine the number of outputs. The
- results of this call will be cached if `cache` is `True` to prevent
- calling the function twice. However, to implement the cache, the
- original function must be wrapped which will slow down subsequent
- calls, so only do this if your function is expensive.
+ array([[1., 2., 1., 0., 0., 0.],
+ [0., 1., 2., 1., 0., 0.],
+ [0., 0., 1., 2., 1., 0.],
+ [0., 0., 0., 1., 2., 1.]])
- The new keyword argument interface and `excluded` argument support
- further degrades performance.
-
- References
- ----------
- .. [1] NumPy Reference, section `Generalized Universal Function API
- <https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html>`_.
"""
-
def __init__(self, pyfunc, otypes=None, doc=None, excluded=None,
cache=False, signature=None):
self.pyfunc = pyfunc
@@ -2311,10 +2311,14 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
array `m` and let ``f = fweights`` and ``a = aweights`` for brevity. The
steps to compute the weighted covariance are as follows::
+ >>> m = np.arange(10, dtype=np.float64)
+ >>> f = np.arange(10) * 2
+ >>> a = np.arange(10) ** 2.
+ >>> ddof = 9 # N - 1
>>> w = f * a
>>> v1 = np.sum(w)
>>> v2 = np.sum(w * a)
- >>> m -= np.sum(m * w, axis=1, keepdims=True) / v1
+ >>> m -= np.sum(m * w, axis=None, keepdims=True) / v1
>>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2)
Note that when ``a == 1``, the normalization factor
@@ -2346,14 +2350,14 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
>>> x = [-2.1, -1, 4.3]
>>> y = [3, 1.1, 0.12]
>>> X = np.stack((x, y), axis=0)
- >>> print(np.cov(X))
- [[ 11.71 -4.286 ]
- [ -4.286 2.14413333]]
- >>> print(np.cov(x, y))
- [[ 11.71 -4.286 ]
- [ -4.286 2.14413333]]
- >>> print(np.cov(x))
- 11.71
+ >>> np.cov(X)
+ array([[11.71 , -4.286 ], # may vary
+ [-4.286 , 2.144133]])
+ >>> np.cov(x, y)
+ array([[11.71 , -4.286 ], # may vary
+ [-4.286 , 2.144133]])
+ >>> np.cov(x)
+ array(11.71)
"""
# Check inputs
@@ -2439,7 +2443,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
if fact <= 0:
warnings.warn("Degrees of freedom <= 0 for slice",
- RuntimeWarning, stacklevel=2)
+ RuntimeWarning, stacklevel=3)
fact = 0.0
X -= avg[:, None]
@@ -2518,7 +2522,7 @@ def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue):
if bias is not np._NoValue or ddof is not np._NoValue:
# 2015-03-15, 1.10
warnings.warn('bias and ddof have no effect and are deprecated',
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
c = cov(x, y, rowvar)
try:
d = diag(c)
@@ -2592,11 +2596,10 @@ def blackman(M):
--------
>>> import matplotlib.pyplot as plt
>>> np.blackman(12)
- array([ -1.38777878e-17, 3.26064346e-02, 1.59903635e-01,
- 4.14397981e-01, 7.36045180e-01, 9.67046769e-01,
- 9.67046769e-01, 7.36045180e-01, 4.14397981e-01,
- 1.59903635e-01, 3.26064346e-02, -1.38777878e-17])
-
+ array([-1.38777878e-17, 3.26064346e-02, 1.59903635e-01, # may vary
+ 4.14397981e-01, 7.36045180e-01, 9.67046769e-01,
+ 9.67046769e-01, 7.36045180e-01, 4.14397981e-01,
+ 1.59903635e-01, 3.26064346e-02, -1.38777878e-17])
Plot the window and the frequency response:
@@ -2605,30 +2608,31 @@ def blackman(M):
>>> plt.plot(window)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Blackman window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Blackman window')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("Sample")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Sample')
>>> plt.show()
>>> plt.figure()
- <matplotlib.figure.Figure object at 0x...>
+ <Figure size 640x480 with 0 Axes>
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Frequency response of Blackman window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Frequency response of Blackman window')
>>> plt.ylabel("Magnitude [dB]")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Magnitude [dB]')
>>> plt.xlabel("Normalized frequency [cycles per sample]")
- <matplotlib.text.Text object at 0x...>
- >>> plt.axis('tight')
- (-0.5, 0.5, -100.0, ...)
+ Text(0.5, 0, 'Normalized frequency [cycles per sample]')
+ >>> _ = plt.axis('tight')
>>> plt.show()
"""
@@ -2700,8 +2704,9 @@ def bartlett(M):
Examples
--------
+ >>> import matplotlib.pyplot as plt
>>> np.bartlett(12)
- array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273,
+ array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273, # may vary
0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636,
0.18181818, 0. ])
@@ -2712,30 +2717,31 @@ def bartlett(M):
>>> plt.plot(window)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Bartlett window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Bartlett window')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("Sample")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Sample')
>>> plt.show()
>>> plt.figure()
- <matplotlib.figure.Figure object at 0x...>
+ <Figure size 640x480 with 0 Axes>
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Frequency response of Bartlett window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Frequency response of Bartlett window')
>>> plt.ylabel("Magnitude [dB]")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Magnitude [dB]')
>>> plt.xlabel("Normalized frequency [cycles per sample]")
- <matplotlib.text.Text object at 0x...>
- >>> plt.axis('tight')
- (-0.5, 0.5, -100.0, ...)
+ Text(0.5, 0, 'Normalized frequency [cycles per sample]')
+ >>> _ = plt.axis('tight')
>>> plt.show()
"""
@@ -2802,9 +2808,9 @@ def hanning(M):
Examples
--------
>>> np.hanning(12)
- array([ 0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037,
- 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249,
- 0.07937323, 0. ])
+ array([0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037,
+ 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249,
+ 0.07937323, 0. ])
Plot the window and its frequency response:
@@ -2814,30 +2820,32 @@ def hanning(M):
>>> plt.plot(window)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Hann window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Hann window')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("Sample")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Sample')
>>> plt.show()
>>> plt.figure()
- <matplotlib.figure.Figure object at 0x...>
+ <Figure size 640x480 with 0 Axes>
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Frequency response of the Hann window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Frequency response of the Hann window')
>>> plt.ylabel("Magnitude [dB]")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Magnitude [dB]')
>>> plt.xlabel("Normalized frequency [cycles per sample]")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Normalized frequency [cycles per sample]')
>>> plt.axis('tight')
- (-0.5, 0.5, -100.0, ...)
+ ...
>>> plt.show()
"""
@@ -2902,7 +2910,7 @@ def hamming(M):
Examples
--------
>>> np.hamming(12)
- array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594,
+ array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594, # may vary
0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909,
0.15302337, 0.08 ])
@@ -2914,15 +2922,15 @@ def hamming(M):
>>> plt.plot(window)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Hamming window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Hamming window')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("Sample")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Sample')
>>> plt.show()
>>> plt.figure()
- <matplotlib.figure.Figure object at 0x...>
+ <Figure size 640x480 with 0 Axes>
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
@@ -2931,13 +2939,13 @@ def hamming(M):
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Frequency response of Hamming window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Frequency response of Hamming window')
>>> plt.ylabel("Magnitude [dB]")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Magnitude [dB]')
>>> plt.xlabel("Normalized frequency [cycles per sample]")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Normalized frequency [cycles per sample]')
>>> plt.axis('tight')
- (-0.5, 0.5, -100.0, ...)
+ ...
>>> plt.show()
"""
@@ -3062,10 +3070,13 @@ def i0(x):
See Also
--------
- scipy.special.iv, scipy.special.ive
+ scipy.special.i0, scipy.special.iv, scipy.special.ive
Notes
-----
+ The scipy implementation is recommended over this function: it is a
+ proper ufunc written in C, and more than an order of magnitude faster.
+
We use the algorithm published by Clenshaw [1]_ and referenced by
Abramowitz and Stegun [2]_, for which the function domain is
partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
@@ -3085,21 +3096,15 @@ def i0(x):
Examples
--------
- >>> np.i0([0.])
- array(1.0)
+ >>> np.i0(0.)
+ array(1.0) # may vary
>>> np.i0([0., 1. + 2j])
- array([ 1.00000000+0.j , 0.18785373+0.64616944j])
+ array([ 1.00000000+0.j , 0.18785373+0.64616944j]) # may vary
"""
- x = atleast_1d(x).copy()
- y = empty_like(x)
- ind = (x < 0)
- x[ind] = -x[ind]
- ind = (x <= 8.0)
- y[ind] = _i0_1(x[ind])
- ind2 = ~ind
- y[ind2] = _i0_2(x[ind2])
- return y.squeeze()
+ x = np.asanyarray(x)
+ x = np.abs(x)
+ return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
## End of cephes code for i0
@@ -3185,10 +3190,10 @@ def kaiser(M, beta):
--------
>>> import matplotlib.pyplot as plt
>>> np.kaiser(12, 14)
- array([ 7.72686684e-06, 3.46009194e-03, 4.65200189e-02,
- 2.29737120e-01, 5.99885316e-01, 9.45674898e-01,
- 9.45674898e-01, 5.99885316e-01, 2.29737120e-01,
- 4.65200189e-02, 3.46009194e-03, 7.72686684e-06])
+ array([7.72686684e-06, 3.46009194e-03, 4.65200189e-02, # may vary
+ 2.29737120e-01, 5.99885316e-01, 9.45674898e-01,
+ 9.45674898e-01, 5.99885316e-01, 2.29737120e-01,
+ 4.65200189e-02, 3.46009194e-03, 7.72686684e-06])
Plot the window and the frequency response:
@@ -3198,15 +3203,15 @@ def kaiser(M, beta):
>>> plt.plot(window)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Kaiser window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Kaiser window')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("Sample")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Sample')
>>> plt.show()
>>> plt.figure()
- <matplotlib.figure.Figure object at 0x...>
+ <Figure size 640x480 with 0 Axes>
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
@@ -3215,13 +3220,13 @@ def kaiser(M, beta):
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Frequency response of Kaiser window")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Frequency response of Kaiser window')
>>> plt.ylabel("Magnitude [dB]")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Magnitude [dB]')
>>> plt.xlabel("Normalized frequency [cycles per sample]")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'Normalized frequency [cycles per sample]')
>>> plt.axis('tight')
- (-0.5, 0.5, -100.0, ...)
+ (-0.5, 0.5, -100.0, ...) # may vary
>>> plt.show()
"""
@@ -3280,29 +3285,29 @@ def sinc(x):
>>> import matplotlib.pyplot as plt
>>> x = np.linspace(-4, 4, 41)
>>> np.sinc(x)
- array([ -3.89804309e-17, -4.92362781e-02, -8.40918587e-02,
+ array([-3.89804309e-17, -4.92362781e-02, -8.40918587e-02, # may vary
-8.90384387e-02, -5.84680802e-02, 3.89804309e-17,
- 6.68206631e-02, 1.16434881e-01, 1.26137788e-01,
- 8.50444803e-02, -3.89804309e-17, -1.03943254e-01,
+ 6.68206631e-02, 1.16434881e-01, 1.26137788e-01,
+ 8.50444803e-02, -3.89804309e-17, -1.03943254e-01,
-1.89206682e-01, -2.16236208e-01, -1.55914881e-01,
- 3.89804309e-17, 2.33872321e-01, 5.04551152e-01,
- 7.56826729e-01, 9.35489284e-01, 1.00000000e+00,
- 9.35489284e-01, 7.56826729e-01, 5.04551152e-01,
- 2.33872321e-01, 3.89804309e-17, -1.55914881e-01,
- -2.16236208e-01, -1.89206682e-01, -1.03943254e-01,
- -3.89804309e-17, 8.50444803e-02, 1.26137788e-01,
- 1.16434881e-01, 6.68206631e-02, 3.89804309e-17,
+ 3.89804309e-17, 2.33872321e-01, 5.04551152e-01,
+ 7.56826729e-01, 9.35489284e-01, 1.00000000e+00,
+ 9.35489284e-01, 7.56826729e-01, 5.04551152e-01,
+ 2.33872321e-01, 3.89804309e-17, -1.55914881e-01,
+ -2.16236208e-01, -1.89206682e-01, -1.03943254e-01,
+ -3.89804309e-17, 8.50444803e-02, 1.26137788e-01,
+ 1.16434881e-01, 6.68206631e-02, 3.89804309e-17,
-5.84680802e-02, -8.90384387e-02, -8.40918587e-02,
-4.92362781e-02, -3.89804309e-17])
>>> plt.plot(x, np.sinc(x))
[<matplotlib.lines.Line2D object at 0x...>]
>>> plt.title("Sinc Function")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 1.0, 'Sinc Function')
>>> plt.ylabel("Amplitude")
- <matplotlib.text.Text object at 0x...>
+ Text(0, 0.5, 'Amplitude')
>>> plt.xlabel("X")
- <matplotlib.text.Text object at 0x...>
+ Text(0.5, 0, 'X')
>>> plt.show()
It works in 2-D as well:
@@ -3474,18 +3479,18 @@ def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
>>> np.median(a)
3.5
>>> np.median(a, axis=0)
- array([ 6.5, 4.5, 2.5])
+ array([6.5, 4.5, 2.5])
>>> np.median(a, axis=1)
- array([ 7., 2.])
+ array([7., 2.])
>>> m = np.median(a, axis=0)
>>> out = np.zeros_like(m)
>>> np.median(a, axis=0, out=m)
- array([ 6.5, 4.5, 2.5])
+ array([6.5, 4.5, 2.5])
>>> m
- array([ 6.5, 4.5, 2.5])
+ array([6.5, 4.5, 2.5])
>>> b = a.copy()
>>> np.median(b, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a==b)
>>> b = a.copy()
>>> np.median(b, axis=None, overwrite_input=True)
@@ -3652,23 +3657,23 @@ def percentile(a, q, axis=None, out=None,
>>> np.percentile(a, 50)
3.5
>>> np.percentile(a, 50, axis=0)
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> np.percentile(a, 50, axis=1)
- array([ 7., 2.])
+ array([7., 2.])
>>> np.percentile(a, 50, axis=1, keepdims=True)
- array([[ 7.],
- [ 2.]])
+ array([[7.],
+ [2.]])
>>> m = np.percentile(a, 50, axis=0)
>>> out = np.zeros_like(m)
>>> np.percentile(a, 50, axis=0, out=out)
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> m
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> b = a.copy()
>>> np.percentile(b, 50, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a == b)
The different types of interpolation can be visualized graphically:
@@ -3700,7 +3705,8 @@ def percentile(a, q, axis=None, out=None,
plt.show()
"""
- q = np.true_divide(q, 100.0) # handles the asarray for us too
+ q = np.true_divide(q, 100)
+ q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105)
if not _quantile_is_valid(q):
raise ValueError("Percentiles must be in the range [0, 100]")
return _quantile_unchecked(
@@ -3717,7 +3723,8 @@ def quantile(a, q, axis=None, out=None,
overwrite_input=False, interpolation='linear', keepdims=False):
"""
Compute the q-th quantile of the data along the specified axis.
- ..versionadded:: 1.15.0
+
+ .. versionadded:: 1.15.0
Parameters
----------
@@ -3794,21 +3801,21 @@ def quantile(a, q, axis=None, out=None,
>>> np.quantile(a, 0.5)
3.5
>>> np.quantile(a, 0.5, axis=0)
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> np.quantile(a, 0.5, axis=1)
- array([ 7., 2.])
+ array([7., 2.])
>>> np.quantile(a, 0.5, axis=1, keepdims=True)
- array([[ 7.],
- [ 2.]])
+ array([[7.],
+ [2.]])
>>> m = np.quantile(a, 0.5, axis=0)
>>> out = np.zeros_like(m)
>>> np.quantile(a, 0.5, axis=0, out=out)
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> m
- array([[ 6.5, 4.5, 2.5]])
+ array([6.5, 4.5, 2.5])
>>> b = a.copy()
>>> np.quantile(b, 0.5, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a == b)
"""
q = np.asanyarray(q)
@@ -3918,7 +3925,7 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
indices_above = concatenate((indices_above, [-1]))
weights_above = indices - indices_below
- weights_below = 1.0 - weights_above
+ weights_below = 1 - weights_above
weights_shape = [1, ] * ap.ndim
weights_shape[axis] = len(indices)
@@ -3955,8 +3962,6 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
r = add(x1, x2)
if np.any(n):
- warnings.warn("Invalid value encountered in percentile",
- RuntimeWarning, stacklevel=3)
if zerod:
if ap.ndim == 1:
if out is not None:
@@ -4037,9 +4042,9 @@ def trapz(y, x=None, dx=1.0, axis=-1):
array([[0, 1, 2],
[3, 4, 5]])
>>> np.trapz(a, axis=0)
- array([ 1.5, 2.5, 3.5])
+ array([1.5, 2.5, 3.5])
>>> np.trapz(a, axis=1)
- array([ 2., 8.])
+ array([2., 8.])
"""
y = asanyarray(y)
@@ -4157,17 +4162,17 @@ def meshgrid(*xi, **kwargs):
>>> y = np.linspace(0, 1, ny)
>>> xv, yv = np.meshgrid(x, y)
>>> xv
- array([[ 0. , 0.5, 1. ],
- [ 0. , 0.5, 1. ]])
+ array([[0. , 0.5, 1. ],
+ [0. , 0.5, 1. ]])
>>> yv
- array([[ 0., 0., 0.],
- [ 1., 1., 1.]])
+ array([[0., 0., 0.],
+ [1., 1., 1.]])
>>> xv, yv = np.meshgrid(x, y, sparse=True) # make sparse output arrays
>>> xv
- array([[ 0. , 0.5, 1. ]])
+ array([[0. , 0.5, 1. ]])
>>> yv
- array([[ 0.],
- [ 1.]])
+ array([[0.],
+ [1.]])
`meshgrid` is very useful to evaluate functions on a grid.
@@ -4229,7 +4234,7 @@ def delete(arr, obj, axis=None):
arr : array_like
Input array.
obj : slice, int or array of ints
- Indicate which sub-arrays to remove.
+ Indicate indices of sub-arrays to remove along the specified axis.
axis : int, optional
The axis along which to delete the subarray defined by `obj`.
If `axis` is None, `obj` is applied to the flattened array.
@@ -4250,6 +4255,7 @@ def delete(arr, obj, axis=None):
-----
Often it is preferable to use a boolean mask. For example:
+ >>> arr = np.arange(12) + 1
>>> mask = np.ones(len(arr), dtype=bool)
>>> mask[[0,2,4]] = False
>>> result = arr[mask,...]
@@ -4296,7 +4302,7 @@ def delete(arr, obj, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"in the future the special handling of scalars will be removed "
- "from delete and raise an error", DeprecationWarning, stacklevel=2)
+ "from delete and raise an error", DeprecationWarning, stacklevel=3)
if wrap:
return wrap(arr)
else:
@@ -4333,7 +4339,7 @@ def delete(arr, obj, axis=None):
else:
slobj[axis] = slice(None, start)
new[tuple(slobj)] = arr[tuple(slobj)]
- # copy end chunck
+ # copy end chunk
if stop == N:
pass
else:
@@ -4365,7 +4371,7 @@ def delete(arr, obj, axis=None):
if obj.dtype == bool:
warnings.warn("in the future insert will treat boolean arrays and "
"array-likes as boolean index instead of casting it "
- "to integer", FutureWarning, stacklevel=2)
+ "to integer", FutureWarning, stacklevel=3)
obj = obj.astype(intp)
if isinstance(_obj, (int, long, integer)):
# optimization for a single value
@@ -4393,7 +4399,7 @@ def delete(arr, obj, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"using a non-integer array as obj in delete will result in an "
- "error in the future", DeprecationWarning, stacklevel=2)
+ "error in the future", DeprecationWarning, stacklevel=3)
obj = obj.astype(intp)
keep = ones(N, dtype=bool)
@@ -4404,13 +4410,13 @@ def delete(arr, obj, axis=None):
warnings.warn(
"in the future out of bounds indices will raise an error "
"instead of being ignored by `numpy.delete`.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
obj = obj[inside_bounds]
positive_indices = obj >= 0
if not positive_indices.all():
warnings.warn(
"in the future negative indices will not be ignored by "
- "`numpy.delete`.", FutureWarning, stacklevel=2)
+ "`numpy.delete`.", FutureWarning, stacklevel=3)
obj = obj[positive_indices]
keep[obj, ] = False
@@ -4481,7 +4487,7 @@ def insert(arr, obj, values, axis=None):
[2, 2],
[3, 3]])
>>> np.insert(a, 1, 5)
- array([1, 5, 1, 2, 2, 3, 3])
+ array([1, 5, 1, ..., 2, 3, 3])
>>> np.insert(a, 1, 5, axis=1)
array([[1, 5, 1],
[2, 5, 2],
@@ -4501,13 +4507,13 @@ def insert(arr, obj, values, axis=None):
>>> b
array([1, 1, 2, 2, 3, 3])
>>> np.insert(b, [2, 2], [5, 6])
- array([1, 1, 5, 6, 2, 2, 3, 3])
+ array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, slice(2, 4), [5, 6])
- array([1, 1, 5, 2, 6, 2, 3, 3])
+ array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, [2, 2], [7.13, False]) # type casting
- array([1, 1, 7, 0, 2, 2, 3, 3])
+ array([1, 1, 7, ..., 2, 3, 3])
>>> x = np.arange(8).reshape(2, 4)
>>> idx = (1, 3)
@@ -4535,7 +4541,7 @@ def insert(arr, obj, values, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"in the future the special handling of scalars will be removed "
- "from insert and raise an error", DeprecationWarning, stacklevel=2)
+ "from insert and raise an error", DeprecationWarning, stacklevel=3)
arr = arr.copy(order=arrorder)
arr[...] = values
if wrap:
@@ -4559,7 +4565,7 @@ def insert(arr, obj, values, axis=None):
warnings.warn(
"in the future insert will treat boolean arrays and "
"array-likes as a boolean index instead of casting it to "
- "integer", FutureWarning, stacklevel=2)
+ "integer", FutureWarning, stacklevel=3)
indices = indices.astype(intp)
# Code after warning period:
#if obj.ndim != 1:
@@ -4609,7 +4615,7 @@ def insert(arr, obj, values, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"using a non-integer array as obj in insert will result in an "
- "error in the future", DeprecationWarning, stacklevel=2)
+ "error in the future", DeprecationWarning, stacklevel=3)
indices = indices.astype(intp)
indices[indices < 0] += N
@@ -4671,7 +4677,7 @@ def append(arr, values, axis=None):
Examples
--------
>>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
- array([1, 2, 3, 4, 5, 6, 7, 8, 9])
+ array([1, 2, 3, ..., 7, 8, 9])
When `axis` is specified, `values` must have the correct shape.
@@ -4681,8 +4687,8 @@ def append(arr, values, axis=None):
[7, 8, 9]])
>>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
Traceback (most recent call last):
- ...
- ValueError: arrays must have same number of dimensions
+ ...
+ ValueError: all the input arrays must have same number of dimensions
"""
arr = asanyarray(arr)
diff --git a/numpy/lib/histograms.py b/numpy/lib/histograms.py
index bed1f46b0..8474bd5d3 100644
--- a/numpy/lib/histograms.py
+++ b/numpy/lib/histograms.py
@@ -3,6 +3,7 @@ Histogram-related functions
"""
from __future__ import division, absolute_import, print_function
+import contextlib
import functools
import operator
import warnings
@@ -21,16 +22,6 @@ array_function_dispatch = functools.partial(
_range = range
-def _ptp(x):
- """Peak-to-peak value of x.
-
- This implementation avoids the problem of signed integer arrays having a
- peak-to-peak value that cannot be represented with the array's data type.
- This function returns an unsigned value for signed integer arrays.
- """
- return _unsigned_subtract(x.max(), x.min())
-
-
def _hist_bin_sqrt(x, range):
"""
Square root histogram bin estimator.
@@ -49,7 +40,7 @@ def _hist_bin_sqrt(x, range):
h : An estimate of the optimal bin width for the given data.
"""
del range # unused
- return _ptp(x) / np.sqrt(x.size)
+ return x.ptp() / np.sqrt(x.size)
def _hist_bin_sturges(x, range):
@@ -72,7 +63,7 @@ def _hist_bin_sturges(x, range):
h : An estimate of the optimal bin width for the given data.
"""
del range # unused
- return _ptp(x) / (np.log2(x.size) + 1.0)
+ return x.ptp() / (np.log2(x.size) + 1.0)
def _hist_bin_rice(x, range):
@@ -96,7 +87,7 @@ def _hist_bin_rice(x, range):
h : An estimate of the optimal bin width for the given data.
"""
del range # unused
- return _ptp(x) / (2.0 * x.size ** (1.0 / 3))
+ return x.ptp() / (2.0 * x.size ** (1.0 / 3))
def _hist_bin_scott(x, range):
@@ -146,7 +137,7 @@ def _hist_bin_stone(x, range):
"""
n = x.size
- ptp_x = _ptp(x)
+ ptp_x = np.ptp(x)
if n <= 1 or ptp_x == 0:
return 0
@@ -158,7 +149,8 @@ def _hist_bin_stone(x, range):
nbins_upper_bound = max(100, int(np.sqrt(n)))
nbins = min(_range(1, nbins_upper_bound + 1), key=jhat)
if nbins == nbins_upper_bound:
- warnings.warn("The number of bins estimated may be suboptimal.", RuntimeWarning, stacklevel=2)
+ warnings.warn("The number of bins estimated may be suboptimal.",
+ RuntimeWarning, stacklevel=3)
return ptp_x / nbins
@@ -192,7 +184,7 @@ def _hist_bin_doane(x, range):
np.true_divide(temp, sigma, temp)
np.power(temp, 3, temp)
g1 = np.mean(temp)
- return _ptp(x) / (1.0 + np.log2(x.size) +
+ return x.ptp() / (1.0 + np.log2(x.size) +
np.log2(1.0 + np.absolute(g1) / sg1))
return 0.0
@@ -289,7 +281,7 @@ def _ravel_and_check_weights(a, weights):
if a.dtype == np.bool_:
warnings.warn("Converting input from {} to {} for compatibility."
.format(a.dtype, np.uint8),
- RuntimeWarning, stacklevel=2)
+ RuntimeWarning, stacklevel=3)
a = a.astype(np.uint8)
if weights is not None:
@@ -471,7 +463,8 @@ def _histogram_bin_edges_dispatcher(a, bins=None, range=None, weights=None):
@array_function_dispatch(_histogram_bin_edges_dispatcher)
def histogram_bin_edges(a, bins=10, range=None, weights=None):
r"""
- Function to calculate only the edges of the bins used by the `histogram` function.
+ Function to calculate only the edges of the bins used by the `histogram`
+ function.
Parameters
----------
@@ -564,14 +557,14 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
using the `ptp` of the data. The final bin count is obtained from
``np.round(np.ceil(range / h))``.
- 'Auto' (maximum of the 'Sturges' and 'FD' estimators)
+ 'auto' (maximum of the 'sturges' and 'fd' estimators)
A compromise to get a good value. For small datasets the Sturges
value will usually be chosen, while larger datasets will usually
default to FD. Avoids the overly conservative behaviour of FD
and Sturges for small and large datasets respectively.
Switchover point is usually :math:`a.size \approx 1000`.
- 'FD' (Freedman Diaconis Estimator)
+ 'fd' (Freedman Diaconis Estimator)
.. math:: h = 2 \frac{IQR}{n^{1/3}}
The binwidth is proportional to the interquartile range (IQR)
@@ -579,7 +572,7 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
conservative for small datasets, but is quite good for large
datasets. The IQR is very robust to outliers.
- 'Scott'
+ 'scott'
.. math:: h = \sigma \sqrt[3]{\frac{24 * \sqrt{\pi}}{n}}
The binwidth is proportional to the standard deviation of the
@@ -589,14 +582,14 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
outliers. Values are very similar to the Freedman-Diaconis
estimator in the absence of outliers.
- 'Rice'
+ 'rice'
.. math:: n_h = 2n^{1/3}
The number of bins is only proportional to cube root of
``a.size``. It tends to overestimate the number of bins and it
does not take into account data variability.
- 'Sturges'
+ 'sturges'
.. math:: n_h = \log _{2}n+1
The number of bins is the base 2 log of ``a.size``. This
@@ -604,7 +597,7 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
larger, non-normal datasets. This is the default method in R's
``hist`` method.
- 'Doane'
+ 'doane'
.. math:: n_h = 1 + \log_{2}(n) +
\log_{2}(1 + \frac{|g_1|}{\sigma_{g_1}})
@@ -616,8 +609,9 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
estimates for non-normal datasets. This estimator attempts to
account for the skew of the data.
- 'Sqrt'
+ 'sqrt'
.. math:: n_h = \sqrt n
+
The simplest and fastest estimator. Only takes into account the
data size.
@@ -655,7 +649,7 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None):
>>> hist_0, bins_0 = np.histogram(arr[group_id == 0], bins='auto')
>>> hist_1, bins_1 = np.histogram(arr[group_id == 1], bins='auto')
- >>> hist_0; hist1
+ >>> hist_0; hist_1
array([1, 1, 1])
array([2, 1, 1, 2])
>>> bins_0; bins_1
@@ -758,14 +752,14 @@ def histogram(a, bins=10, range=None, normed=None, weights=None,
>>> np.histogram([1, 2, 1], bins=[0, 1, 2, 3])
(array([0, 2, 1]), array([0, 1, 2, 3]))
>>> np.histogram(np.arange(4), bins=np.arange(5), density=True)
- (array([ 0.25, 0.25, 0.25, 0.25]), array([0, 1, 2, 3, 4]))
+ (array([0.25, 0.25, 0.25, 0.25]), array([0, 1, 2, 3, 4]))
>>> np.histogram([[1, 2, 1], [1, 0, 1]], bins=[0,1,2,3])
(array([1, 4, 1]), array([0, 1, 2, 3]))
>>> a = np.arange(5)
>>> hist, bin_edges = np.histogram(a, density=True)
>>> hist
- array([ 0.5, 0. , 0.5, 0. , 0. , 0.5, 0. , 0.5, 0. , 0.5])
+ array([0.5, 0. , 0.5, 0. , 0. , 0.5, 0. , 0.5, 0. , 0.5])
>>> hist.sum()
2.4999999999999996
>>> np.sum(hist * np.diff(bin_edges))
@@ -780,8 +774,9 @@ def histogram(a, bins=10, range=None, normed=None, weights=None,
>>> rng = np.random.RandomState(10) # deterministic random data
>>> a = np.hstack((rng.normal(size=1000),
... rng.normal(loc=5, scale=2, size=1000)))
- >>> plt.hist(a, bins='auto') # arguments are passed to np.histogram
+ >>> _ = plt.hist(a, bins='auto') # arguments are passed to np.histogram
>>> plt.title("Histogram with 'auto' bins")
+ Text(0.5, 1.0, "Histogram with 'auto' bins")
>>> plt.show()
"""
@@ -895,7 +890,7 @@ def histogram(a, bins=10, range=None, normed=None, weights=None,
warnings.warn(
"The normed argument is ignored when density is provided. "
"In future passing both will result in an error.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
normed = None
if density:
@@ -911,7 +906,7 @@ def histogram(a, bins=10, range=None, normed=None, weights=None,
"density=True will produce the same result anyway. "
"The argument will be removed in a future version of "
"numpy.",
- np.VisibleDeprecationWarning, stacklevel=2)
+ np.VisibleDeprecationWarning, stacklevel=3)
# this normalization is incorrect, but
db = np.array(np.diff(bin_edges), float)
@@ -922,7 +917,7 @@ def histogram(a, bins=10, range=None, normed=None, weights=None,
warnings.warn(
"Passing normed=False is deprecated, and has no effect. "
"Consider passing the density argument instead.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
return n, bin_edges
@@ -931,13 +926,9 @@ def _histogramdd_dispatcher(sample, bins=None, range=None, normed=None,
if hasattr(sample, 'shape'): # same condition as used in histogramdd
yield sample
else:
- for s in sample:
- yield s
- try:
- for b in bins:
- yield b
- except TypeError:
- pass
+ yield from sample
+ with contextlib.suppress(TypeError):
+ yield from bins
yield weights
diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py
index 56abe293a..04384854c 100644
--- a/numpy/lib/index_tricks.py
+++ b/numpy/lib/index_tricks.py
@@ -94,12 +94,13 @@ def ix_(*args):
out = []
nd = len(args)
for k, new in enumerate(args):
- new = asarray(new)
+ if not isinstance(new, _nx.ndarray):
+ new = asarray(new)
+ if new.size == 0:
+ # Explicitly type empty arrays to avoid float default
+ new = new.astype(_nx.intp)
if new.ndim != 1:
raise ValueError("Cross index must be 1 dimensional")
- if new.size == 0:
- # Explicitly type empty arrays to avoid float default
- new = new.astype(_nx.intp)
if issubdtype(new.dtype, _nx.bool_):
new, = new.nonzero()
new = new.reshape((1,)*k + (new.size,) + (1,)*(nd-k-1))
@@ -269,8 +270,9 @@ class OGridClass(nd_grid):
the stop value **is inclusive**.
Returns
- ----------
- mesh-grid `ndarrays` with only one dimension :math:`\\neq 1`
+ -------
+ mesh-grid
+ `ndarrays` with only one dimension not equal to 1
See Also
--------
@@ -478,7 +480,7 @@ class RClass(AxisConcatenator):
Examples
--------
>>> np.r_[np.array([1,2,3]), 0, 0, np.array([4,5,6])]
- array([1, 2, 3, 0, 0, 4, 5, 6])
+ array([1, 2, 3, ..., 4, 5, 6])
>>> np.r_[-1:1:6j, [0]*3, 5, 6]
array([-1. , -0.6, -0.2, 0.2, 0.6, 1. , 0. , 0. , 0. , 5. , 6. ])
@@ -538,7 +540,7 @@ class CClass(AxisConcatenator):
[2, 5],
[3, 6]])
>>> np.c_[np.array([[1,2,3]]), 0, 0, np.array([[4,5,6]])]
- array([[1, 2, 3, 0, 0, 4, 5, 6]])
+ array([[1, 2, 3, ..., 4, 5, 6]])
"""
@@ -812,8 +814,8 @@ def fill_diagonal(a, val, wrap=False):
The wrap option affects only tall matrices:
>>> # tall matrices no wrap
- >>> a = np.zeros((5, 3),int)
- >>> fill_diagonal(a, 4)
+ >>> a = np.zeros((5, 3), int)
+ >>> np.fill_diagonal(a, 4)
>>> a
array([[4, 0, 0],
[0, 4, 0],
@@ -822,8 +824,8 @@ def fill_diagonal(a, val, wrap=False):
[0, 0, 0]])
>>> # tall matrices wrap
- >>> a = np.zeros((5, 3),int)
- >>> fill_diagonal(a, 4, wrap=True)
+ >>> a = np.zeros((5, 3), int)
+ >>> np.fill_diagonal(a, 4, wrap=True)
>>> a
array([[4, 0, 0],
[0, 4, 0],
@@ -832,13 +834,30 @@ def fill_diagonal(a, val, wrap=False):
[4, 0, 0]])
>>> # wide matrices
- >>> a = np.zeros((3, 5),int)
- >>> fill_diagonal(a, 4, wrap=True)
+ >>> a = np.zeros((3, 5), int)
+ >>> np.fill_diagonal(a, 4, wrap=True)
>>> a
array([[4, 0, 0, 0, 0],
[0, 4, 0, 0, 0],
[0, 0, 4, 0, 0]])
+ The anti-diagonal can be filled by reversing the order of elements
+ using either `numpy.flipud` or `numpy.fliplr`.
+
+ >>> a = np.zeros((3, 3), int);
+ >>> np.fill_diagonal(np.fliplr(a), [1,2,3]) # Horizontal flip
+ >>> a
+ array([[0, 0, 1],
+ [0, 2, 0],
+ [3, 0, 0]])
+ >>> np.fill_diagonal(np.flipud(a), [1,2,3]) # Vertical flip
+ >>> a
+ array([[0, 0, 3],
+ [0, 2, 0],
+ [1, 0, 0]])
+
+ Note that the order in which the diagonal is filled varies depending
+ on the flip function.
"""
if a.ndim < 2:
raise ValueError("array must be at least 2-d")
diff --git a/numpy/lib/nanfunctions.py b/numpy/lib/nanfunctions.py
index d73d84467..9a03d0b39 100644
--- a/numpy/lib/nanfunctions.py
+++ b/numpy/lib/nanfunctions.py
@@ -40,6 +40,33 @@ __all__ = [
]
+def _nan_mask(a, out=None):
+ """
+ Parameters
+ ----------
+ a : array-like
+ Input array with at least 1 dimension.
+ out : ndarray, optional
+ Alternate output array in which to place the result. The default
+ is ``None``; if provided, it must have the same shape as the
+ expected output and will prevent the allocation of a new array.
+
+ Returns
+ -------
+ y : bool ndarray or True
+ A bool array where ``np.nan`` positions are marked with ``False``
+ and other positions are marked with ``True``. If the type of ``a``
+ is such that it can't possibly contain ``np.nan``, returns ``True``.
+ """
+ # we assume that a is an array for this private function
+
+ if a.dtype.kind not in 'fc':
+ return True
+
+ y = np.isnan(a, out=out)
+ y = np.invert(y, out=y)
+ return y
+
def _replace_nan(a, val):
"""
If `a` is of inexact type, make a copy of `a`, replace NaNs with
@@ -138,7 +165,8 @@ def _remove_nan_1d(arr1d, overwrite_input=False):
c = np.isnan(arr1d)
s = np.nonzero(c)[0]
if s.size == arr1d.size:
- warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=4)
+ warnings.warn("All-NaN slice encountered", RuntimeWarning,
+ stacklevel=5)
return arr1d[:0], True
elif s.size == 0:
return arr1d, overwrite_input
@@ -271,9 +299,9 @@ def nanmin(a, axis=None, out=None, keepdims=np._NoValue):
>>> np.nanmin(a)
1.0
>>> np.nanmin(a, axis=0)
- array([ 1., 2.])
+ array([1., 2.])
>>> np.nanmin(a, axis=1)
- array([ 1., 3.])
+ array([1., 3.])
When positive infinity and negative infinity are present:
@@ -291,7 +319,8 @@ def nanmin(a, axis=None, out=None, keepdims=np._NoValue):
# which do not implement isnan (gh-9009), or fmin correctly (gh-8975)
res = np.fmin.reduce(a, axis=axis, out=out, **kwargs)
if np.isnan(res).any():
- warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=2)
+ warnings.warn("All-NaN slice encountered", RuntimeWarning,
+ stacklevel=3)
else:
# Slow, but safe for subclasses of ndarray
a, mask = _replace_nan(a, +np.inf)
@@ -303,7 +332,8 @@ def nanmin(a, axis=None, out=None, keepdims=np._NoValue):
mask = np.all(mask, axis=axis, **kwargs)
if np.any(mask):
res = _copyto(res, np.nan, mask)
- warnings.warn("All-NaN axis encountered", RuntimeWarning, stacklevel=2)
+ warnings.warn("All-NaN axis encountered", RuntimeWarning,
+ stacklevel=3)
return res
@@ -384,9 +414,9 @@ def nanmax(a, axis=None, out=None, keepdims=np._NoValue):
>>> np.nanmax(a)
3.0
>>> np.nanmax(a, axis=0)
- array([ 3., 2.])
+ array([3., 2.])
>>> np.nanmax(a, axis=1)
- array([ 2., 3.])
+ array([2., 3.])
When positive infinity and negative infinity are present:
@@ -404,7 +434,8 @@ def nanmax(a, axis=None, out=None, keepdims=np._NoValue):
# which do not implement isnan (gh-9009), or fmax correctly (gh-8975)
res = np.fmax.reduce(a, axis=axis, out=out, **kwargs)
if np.isnan(res).any():
- warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=2)
+ warnings.warn("All-NaN slice encountered", RuntimeWarning,
+ stacklevel=3)
else:
# Slow, but safe for subclasses of ndarray
a, mask = _replace_nan(a, -np.inf)
@@ -416,7 +447,8 @@ def nanmax(a, axis=None, out=None, keepdims=np._NoValue):
mask = np.all(mask, axis=axis, **kwargs)
if np.any(mask):
res = _copyto(res, np.nan, mask)
- warnings.warn("All-NaN axis encountered", RuntimeWarning, stacklevel=2)
+ warnings.warn("All-NaN axis encountered", RuntimeWarning,
+ stacklevel=3)
return res
@@ -601,12 +633,15 @@ def nansum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
>>> np.nansum(a)
3.0
>>> np.nansum(a, axis=0)
- array([ 2., 1.])
+ array([2., 1.])
>>> np.nansum([1, np.nan, np.inf])
inf
>>> np.nansum([1, np.nan, np.NINF])
-inf
- >>> np.nansum([1, np.nan, np.inf, -np.inf]) # both +/- infinity present
+ >>> from numpy.testing import suppress_warnings
+ >>> with suppress_warnings() as sup:
+ ... sup.filter(RuntimeWarning)
+ ... np.nansum([1, np.nan, np.inf, -np.inf]) # both +/- infinity present
nan
"""
@@ -677,7 +712,7 @@ def nanprod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
>>> np.nanprod(a)
6.0
>>> np.nanprod(a, axis=0)
- array([ 3., 2.])
+ array([3., 2.])
"""
a, mask = _replace_nan(a, 1)
@@ -738,16 +773,16 @@ def nancumsum(a, axis=None, dtype=None, out=None):
>>> np.nancumsum([1])
array([1])
>>> np.nancumsum([1, np.nan])
- array([ 1., 1.])
+ array([1., 1.])
>>> a = np.array([[1, 2], [3, np.nan]])
>>> np.nancumsum(a)
- array([ 1., 3., 6., 6.])
+ array([1., 3., 6., 6.])
>>> np.nancumsum(a, axis=0)
- array([[ 1., 2.],
- [ 4., 2.]])
+ array([[1., 2.],
+ [4., 2.]])
>>> np.nancumsum(a, axis=1)
- array([[ 1., 3.],
- [ 3., 3.]])
+ array([[1., 3.],
+ [3., 3.]])
"""
a, mask = _replace_nan(a, 0)
@@ -805,16 +840,16 @@ def nancumprod(a, axis=None, dtype=None, out=None):
>>> np.nancumprod([1])
array([1])
>>> np.nancumprod([1, np.nan])
- array([ 1., 1.])
+ array([1., 1.])
>>> a = np.array([[1, 2], [3, np.nan]])
>>> np.nancumprod(a)
- array([ 1., 2., 6., 6.])
+ array([1., 2., 6., 6.])
>>> np.nancumprod(a, axis=0)
- array([[ 1., 2.],
- [ 3., 2.]])
+ array([[1., 2.],
+ [3., 2.]])
>>> np.nancumprod(a, axis=1)
- array([[ 1., 2.],
- [ 3., 3.]])
+ array([[1., 2.],
+ [3., 3.]])
"""
a, mask = _replace_nan(a, 1)
@@ -895,9 +930,9 @@ def nanmean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
>>> np.nanmean(a)
2.6666666666666665
>>> np.nanmean(a, axis=0)
- array([ 2., 4.])
+ array([2., 4.])
>>> np.nanmean(a, axis=1)
- array([ 1., 3.5])
+ array([1., 3.5]) # may vary
"""
arr, mask = _replace_nan(a, 0)
@@ -917,7 +952,7 @@ def nanmean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue):
isbad = (cnt == 0)
if isbad.any():
- warnings.warn("Mean of empty slice", RuntimeWarning, stacklevel=2)
+ warnings.warn("Mean of empty slice", RuntimeWarning, stacklevel=3)
# NaN is the only possible bad value, so no further
# action is needed to handle bad results.
return avg
@@ -929,7 +964,7 @@ def _nanmedian1d(arr1d, overwrite_input=False):
See nanmedian for parameter usage
"""
arr1d, overwrite_input = _remove_nan_1d(arr1d,
- overwrite_input=overwrite_input)
+ overwrite_input=overwrite_input)
if arr1d.size == 0:
return np.nan
@@ -972,7 +1007,8 @@ def _nanmedian_small(a, axis=None, out=None, overwrite_input=False):
a = np.ma.masked_array(a, np.isnan(a))
m = np.ma.median(a, axis=axis, overwrite_input=overwrite_input)
for i in range(np.count_nonzero(m.mask.ravel())):
- warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=3)
+ warnings.warn("All-NaN slice encountered", RuntimeWarning,
+ stacklevel=4)
if out is not None:
out[...] = m.filled(np.nan)
return out
@@ -1049,19 +1085,19 @@ def nanmedian(a, axis=None, out=None, overwrite_input=False, keepdims=np._NoValu
>>> a = np.array([[10.0, 7, 4], [3, 2, 1]])
>>> a[0, 1] = np.nan
>>> a
- array([[ 10., nan, 4.],
- [ 3., 2., 1.]])
+ array([[10., nan, 4.],
+ [ 3., 2., 1.]])
>>> np.median(a)
nan
>>> np.nanmedian(a)
3.0
>>> np.nanmedian(a, axis=0)
- array([ 6.5, 2., 2.5])
+ array([6.5, 2. , 2.5])
>>> np.median(a, axis=1)
- array([ 7., 2.])
+ array([nan, 2.])
>>> b = a.copy()
>>> np.nanmedian(b, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a==b)
>>> b = a.copy()
>>> np.nanmedian(b, axis=None, overwrite_input=True)
@@ -1177,27 +1213,27 @@ def nanpercentile(a, q, axis=None, out=None, overwrite_input=False,
>>> a = np.array([[10., 7., 4.], [3., 2., 1.]])
>>> a[0][1] = np.nan
>>> a
- array([[ 10., nan, 4.],
- [ 3., 2., 1.]])
+ array([[10., nan, 4.],
+ [ 3., 2., 1.]])
>>> np.percentile(a, 50)
nan
>>> np.nanpercentile(a, 50)
- 3.5
+ 3.0
>>> np.nanpercentile(a, 50, axis=0)
- array([ 6.5, 2., 2.5])
+ array([6.5, 2. , 2.5])
>>> np.nanpercentile(a, 50, axis=1, keepdims=True)
- array([[ 7.],
- [ 2.]])
+ array([[7.],
+ [2.]])
>>> m = np.nanpercentile(a, 50, axis=0)
>>> out = np.zeros_like(m)
>>> np.nanpercentile(a, 50, axis=0, out=out)
- array([ 6.5, 2., 2.5])
+ array([6.5, 2. , 2.5])
>>> m
- array([ 6.5, 2. , 2.5])
+ array([6.5, 2. , 2.5])
>>> b = a.copy()
>>> np.nanpercentile(b, 50, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a==b)
"""
@@ -1221,6 +1257,7 @@ def nanquantile(a, q, axis=None, out=None, overwrite_input=False,
Compute the qth quantile of the data along the specified axis,
while ignoring nan values.
Returns the qth quantile(s) of the array elements.
+
.. versionadded:: 1.15.0
Parameters
@@ -1291,26 +1328,26 @@ def nanquantile(a, q, axis=None, out=None, overwrite_input=False,
>>> a = np.array([[10., 7., 4.], [3., 2., 1.]])
>>> a[0][1] = np.nan
>>> a
- array([[ 10., nan, 4.],
- [ 3., 2., 1.]])
+ array([[10., nan, 4.],
+ [ 3., 2., 1.]])
>>> np.quantile(a, 0.5)
nan
>>> np.nanquantile(a, 0.5)
- 3.5
+ 3.0
>>> np.nanquantile(a, 0.5, axis=0)
- array([ 6.5, 2., 2.5])
+ array([6.5, 2. , 2.5])
>>> np.nanquantile(a, 0.5, axis=1, keepdims=True)
- array([[ 7.],
- [ 2.]])
+ array([[7.],
+ [2.]])
>>> m = np.nanquantile(a, 0.5, axis=0)
>>> out = np.zeros_like(m)
>>> np.nanquantile(a, 0.5, axis=0, out=out)
- array([ 6.5, 2., 2.5])
+ array([6.5, 2. , 2.5])
>>> m
- array([ 6.5, 2. , 2.5])
+ array([6.5, 2. , 2.5])
>>> b = a.copy()
>>> np.nanquantile(b, 0.5, axis=1, overwrite_input=True)
- array([ 7., 2.])
+ array([7., 2.])
>>> assert not np.all(a==b)
"""
a = np.asanyarray(a)
@@ -1465,12 +1502,12 @@ def nanvar(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
Examples
--------
>>> a = np.array([[1, np.nan], [3, 4]])
- >>> np.var(a)
+ >>> np.nanvar(a)
1.5555555555555554
>>> np.nanvar(a, axis=0)
- array([ 1., 0.])
+ array([1., 0.])
>>> np.nanvar(a, axis=1)
- array([ 0., 0.25])
+ array([0., 0.25]) # may vary
"""
arr, mask = _replace_nan(a, 0)
@@ -1517,7 +1554,8 @@ def nanvar(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
isbad = (dof <= 0)
if np.any(isbad):
- warnings.warn("Degrees of freedom <= 0 for slice.", RuntimeWarning, stacklevel=2)
+ warnings.warn("Degrees of freedom <= 0 for slice.", RuntimeWarning,
+ stacklevel=3)
# NaN, inf, or negative numbers are all possible bad
# values, so explicitly replace them with NaN.
var = _copyto(var, np.nan, isbad)
@@ -1619,9 +1657,9 @@ def nanstd(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue):
>>> np.nanstd(a)
1.247219128924647
>>> np.nanstd(a, axis=0)
- array([ 1., 0.])
+ array([1., 0.])
>>> np.nanstd(a, axis=1)
- array([ 0., 0.5])
+ array([0., 0.5]) # may vary
"""
var = nanvar(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index fe1e65d5b..b9dc444f8 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -7,6 +7,7 @@ import functools
import itertools
import warnings
import weakref
+import contextlib
from operator import itemgetter, index as opindex
import numpy as np
@@ -23,10 +24,9 @@ from ._iotools import (
)
from numpy.compat import (
- asbytes, asstr, asunicode, asbytes_nested, bytes, basestring, unicode,
- os_fspath, os_PathLike
+ asbytes, asstr, asunicode, bytes, basestring, os_fspath, os_PathLike,
+ pickle, contextlib_nullcontext
)
-from numpy.core.numeric import pickle
if sys.version_info[0] >= 3:
from collections.abc import Mapping
@@ -172,13 +172,13 @@ class NpzFile(Mapping):
>>> x = np.arange(10)
>>> y = np.sin(x)
>>> np.savez(outfile, x=x, y=y)
- >>> outfile.seek(0)
+ >>> _ = outfile.seek(0)
>>> npz = np.load(outfile)
>>> isinstance(npz, np.lib.io.NpzFile)
True
- >>> npz.files
- ['y', 'x']
+ >>> sorted(npz.files)
+ ['x', 'y']
>>> npz['x'] # getitem access
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> npz.f.x # attribute lookup
@@ -294,6 +294,12 @@ def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
"""
Load arrays or pickled objects from ``.npy``, ``.npz`` or pickled files.
+ .. warning:: Loading files that contain object arrays uses the ``pickle``
+ module, which is not secure against erroneous or maliciously
+ constructed data. Consider passing ``allow_pickle=False`` to
+ load data that is known not to contain object arrays for the
+ safer handling of untrusted sources.
+
Parameters
----------
file : file-like object, string, or pathlib.Path
@@ -509,13 +515,13 @@ def save(file, arr, allow_pickle=True, fix_imports=True):
>>> x = np.arange(10)
>>> np.save(outfile, x)
- >>> outfile.seek(0) # Only needed here to simulate closing & reopening file
+ >>> _ = outfile.seek(0) # Only needed here to simulate closing & reopening file
>>> np.load(outfile)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
"""
own_fid = False
- if hasattr(file, 'read'):
+ if hasattr(file, 'write'):
fid = file
else:
file = os_fspath(file)
@@ -604,10 +610,10 @@ def savez(file, *args, **kwds):
Using `savez` with \\*args, the arrays are saved with default names.
>>> np.savez(outfile, x, y)
- >>> outfile.seek(0) # Only needed here to simulate closing & reopening file
+ >>> _ = outfile.seek(0) # Only needed here to simulate closing & reopening file
>>> npzfile = np.load(outfile)
>>> npzfile.files
- ['arr_1', 'arr_0']
+ ['arr_0', 'arr_1']
>>> npzfile['arr_0']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
@@ -615,10 +621,10 @@ def savez(file, *args, **kwds):
>>> outfile = TemporaryFile()
>>> np.savez(outfile, x=x, y=y)
- >>> outfile.seek(0)
+ >>> _ = outfile.seek(0)
>>> npzfile = np.load(outfile)
- >>> npzfile.files
- ['y', 'x']
+ >>> sorted(npzfile.files)
+ ['x', 'y']
>>> npzfile['x']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
@@ -703,7 +709,7 @@ def _savez(file, args, kwds, compress, allow_pickle=True, pickle_kwargs=None):
# component of the so-called standard library.
import zipfile
- if not hasattr(file, 'read'):
+ if not hasattr(file, 'write'):
file = os_fspath(file)
if not file.endswith('.npz'):
file = file + '.npz'
@@ -728,8 +734,8 @@ def _savez(file, args, kwds, compress, allow_pickle=True, pickle_kwargs=None):
for key, val in namedict.items():
fname = key + '.npy'
val = np.asanyarray(val)
- force_zip64 = val.nbytes >= 2**30
- with zipf.open(fname, 'w', force_zip64=force_zip64) as fid:
+ # always force zip64, gh-10776
+ with zipf.open(fname, 'w', force_zip64=True) as fid:
format.write_array(fid, val,
allow_pickle=allow_pickle,
pickle_kwargs=pickle_kwargs)
@@ -836,7 +842,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
`genfromtxt`): ``converters = {3: lambda s: float(s.strip() or 0)}``.
Default: None.
skiprows : int, optional
- Skip the first `skiprows` lines; default: 0.
+ Skip the first `skiprows` lines, including comments; default: 0.
usecols : int or sequence, optional
Which columns to read, with 0 being the first. For example,
``usecols = (1,4,5)`` will extract the 2nd, 5th and 6th columns.
@@ -898,21 +904,21 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
>>> from io import StringIO # StringIO behaves like a file object
>>> c = StringIO(u"0 1\\n2 3")
>>> np.loadtxt(c)
- array([[ 0., 1.],
- [ 2., 3.]])
+ array([[0., 1.],
+ [2., 3.]])
>>> d = StringIO(u"M 21 72\\nF 35 58")
>>> np.loadtxt(d, dtype={'names': ('gender', 'age', 'weight'),
... 'formats': ('S1', 'i4', 'f4')})
- array([('M', 21, 72.0), ('F', 35, 58.0)],
- dtype=[('gender', '|S1'), ('age', '<i4'), ('weight', '<f4')])
+ array([(b'M', 21, 72.), (b'F', 35, 58.)],
+ dtype=[('gender', 'S1'), ('age', '<i4'), ('weight', '<f4')])
>>> c = StringIO(u"1,0,2\\n3,0,4")
>>> x, y = np.loadtxt(c, delimiter=',', usecols=(0, 2), unpack=True)
>>> x
- array([ 1., 3.])
+ array([1., 3.])
>>> y
- array([ 2., 4.])
+ array([2., 4.])
"""
# Type conversions for Py3 convenience
@@ -1125,7 +1131,6 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
if type(x) is bytes:
return conv(x)
return conv(x.encode("latin1"))
- import functools
converters[i] = functools.partial(tobytes_first, conv=conv)
else:
converters[i] = conv
@@ -1394,7 +1399,7 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
if len(fmt) != ncol:
raise AttributeError('fmt has wrong shape. %s' % str(fmt))
format = asstr(delimiter).join(map(asstr, fmt))
- elif isinstance(fmt, str):
+ elif isinstance(fmt, basestring):
n_fmt_chars = fmt.count('%')
error = ValueError('fmt has wrong number of %% formats: %s' % fmt)
if n_fmt_chars == 1:
@@ -1488,17 +1493,17 @@ def fromregex(file, regexp, dtype, encoding=None):
Examples
--------
>>> f = open('test.dat', 'w')
- >>> f.write("1312 foo\\n1534 bar\\n444 qux")
+ >>> _ = f.write("1312 foo\\n1534 bar\\n444 qux")
>>> f.close()
>>> regexp = r"(\\d+)\\s+(...)" # match [digits, whitespace, anything]
>>> output = np.fromregex('test.dat', regexp,
... [('num', np.int64), ('key', 'S3')])
>>> output
- array([(1312L, 'foo'), (1534L, 'bar'), (444L, 'qux')],
- dtype=[('num', '<i8'), ('key', '|S3')])
+ array([(1312, b'foo'), (1534, b'bar'), ( 444, b'qux')],
+ dtype=[('num', '<i8'), ('key', 'S3')])
>>> output['num']
- array([1312, 1534, 444], dtype=int64)
+ array([1312, 1534, 444])
"""
own_fh = False
@@ -1544,7 +1549,8 @@ def fromregex(file, regexp, dtype, encoding=None):
def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
skip_header=0, skip_footer=0, converters=None,
missing_values=None, filling_values=None, usecols=None,
- names=None, excludelist=None, deletechars=None,
+ names=None, excludelist=None,
+ deletechars=''.join(sorted(NameValidator.defaultdeletechars)),
replace_space='_', autostrip=False, case_sensitive=True,
defaultfmt="f%i", unpack=None, usemask=False, loose=True,
invalid_raise=True, max_rows=None, encoding='bytes'):
@@ -1681,26 +1687,26 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
>>> data = np.genfromtxt(s, dtype=[('myint','i8'),('myfloat','f8'),
... ('mystring','S5')], delimiter=",")
>>> data
- array((1, 1.3, 'abcde'),
- dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', '|S5')])
+ array((1, 1.3, b'abcde'),
+ dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', 'S5')])
Using dtype = None
- >>> s.seek(0) # needed for StringIO example only
+ >>> _ = s.seek(0) # needed for StringIO example only
>>> data = np.genfromtxt(s, dtype=None,
... names = ['myint','myfloat','mystring'], delimiter=",")
>>> data
- array((1, 1.3, 'abcde'),
- dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', '|S5')])
+ array((1, 1.3, b'abcde'),
+ dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', 'S5')])
Specifying dtype and names
- >>> s.seek(0)
+ >>> _ = s.seek(0)
>>> data = np.genfromtxt(s, dtype="i8,f8,S5",
... names=['myint','myfloat','mystring'], delimiter=",")
>>> data
- array((1, 1.3, 'abcde'),
- dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', '|S5')])
+ array((1, 1.3, b'abcde'),
+ dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', 'S5')])
An example with fixed-width columns
@@ -1708,8 +1714,18 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
>>> data = np.genfromtxt(s, dtype=None, names=['intvar','fltvar','strvar'],
... delimiter=[1,3,5])
>>> data
- array((1, 1.3, 'abcde'),
- dtype=[('intvar', '<i8'), ('fltvar', '<f8'), ('strvar', '|S5')])
+ array((1, 1.3, b'abcde'),
+ dtype=[('intvar', '<i8'), ('fltvar', '<f8'), ('strvar', 'S5')])
+
+ An example to show comments
+
+ >>> f = StringIO('''
+ ... text,# of chars
+ ... hello world,11
+ ... numpy,5''')
+ >>> np.genfromtxt(f, dtype='S12,S12', delimiter=',')
+ array([(b'text', b''), (b'hello world', b'11'), (b'numpy', b'5')],
+ dtype=[('f0', 'S12'), ('f1', 'S12')])
"""
if max_rows is not None:
@@ -1736,301 +1752,299 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
byte_converters = False
# Initialize the filehandle, the LineSplitter and the NameValidator
- own_fhd = False
try:
if isinstance(fname, os_PathLike):
fname = os_fspath(fname)
if isinstance(fname, basestring):
- fhd = iter(np.lib._datasource.open(fname, 'rt', encoding=encoding))
- own_fhd = True
+ fid = np.lib._datasource.open(fname, 'rt', encoding=encoding)
+ fid_ctx = contextlib.closing(fid)
else:
- fhd = iter(fname)
+ fid = fname
+ fid_ctx = contextlib_nullcontext(fid)
+ fhd = iter(fid)
except TypeError:
raise TypeError(
"fname must be a string, filehandle, list of strings, "
"or generator. Got %s instead." % type(fname))
- split_line = LineSplitter(delimiter=delimiter, comments=comments,
- autostrip=autostrip, encoding=encoding)
- validate_names = NameValidator(excludelist=excludelist,
- deletechars=deletechars,
- case_sensitive=case_sensitive,
- replace_space=replace_space)
+ with fid_ctx:
+ split_line = LineSplitter(delimiter=delimiter, comments=comments,
+ autostrip=autostrip, encoding=encoding)
+ validate_names = NameValidator(excludelist=excludelist,
+ deletechars=deletechars,
+ case_sensitive=case_sensitive,
+ replace_space=replace_space)
- # Skip the first `skip_header` rows
- for i in range(skip_header):
- next(fhd)
+ # Skip the first `skip_header` rows
+ for i in range(skip_header):
+ next(fhd)
- # Keep on until we find the first valid values
- first_values = None
- try:
- while not first_values:
- first_line = _decode_line(next(fhd), encoding)
- if (names is True) and (comments is not None):
- if comments in first_line:
- first_line = (
- ''.join(first_line.split(comments)[1:]))
- first_values = split_line(first_line)
- except StopIteration:
- # return an empty array if the datafile is empty
- first_line = ''
- first_values = []
- warnings.warn('genfromtxt: Empty input file: "%s"' % fname, stacklevel=2)
-
- # Should we take the first values as names ?
- if names is True:
- fval = first_values[0].strip()
- if comments is not None:
- if fval in comments:
- del first_values[0]
-
- # Check the columns to use: make sure `usecols` is a list
- if usecols is not None:
+ # Keep on until we find the first valid values
+ first_values = None
try:
- usecols = [_.strip() for _ in usecols.split(",")]
- except AttributeError:
+ while not first_values:
+ first_line = _decode_line(next(fhd), encoding)
+ if (names is True) and (comments is not None):
+ if comments in first_line:
+ first_line = (
+ ''.join(first_line.split(comments)[1:]))
+ first_values = split_line(first_line)
+ except StopIteration:
+ # return an empty array if the datafile is empty
+ first_line = ''
+ first_values = []
+ warnings.warn('genfromtxt: Empty input file: "%s"' % fname, stacklevel=2)
+
+ # Should we take the first values as names ?
+ if names is True:
+ fval = first_values[0].strip()
+ if comments is not None:
+ if fval in comments:
+ del first_values[0]
+
+ # Check the columns to use: make sure `usecols` is a list
+ if usecols is not None:
try:
- usecols = list(usecols)
- except TypeError:
- usecols = [usecols, ]
- nbcols = len(usecols or first_values)
-
- # Check the names and overwrite the dtype.names if needed
- if names is True:
- names = validate_names([str(_.strip()) for _ in first_values])
- first_line = ''
- elif _is_string_like(names):
- names = validate_names([_.strip() for _ in names.split(',')])
- elif names:
- names = validate_names(names)
- # Get the dtype
- if dtype is not None:
- dtype = easy_dtype(dtype, defaultfmt=defaultfmt, names=names,
- excludelist=excludelist,
- deletechars=deletechars,
- case_sensitive=case_sensitive,
- replace_space=replace_space)
- # Make sure the names is a list (for 2.5)
- if names is not None:
- names = list(names)
-
- if usecols:
- for (i, current) in enumerate(usecols):
- # if usecols is a list of names, convert to a list of indices
- if _is_string_like(current):
- usecols[i] = names.index(current)
- elif current < 0:
- usecols[i] = current + len(first_values)
- # If the dtype is not None, make sure we update it
- if (dtype is not None) and (len(dtype) > nbcols):
- descr = dtype.descr
- dtype = np.dtype([descr[_] for _ in usecols])
- names = list(dtype.names)
- # If `names` is not None, update the names
- elif (names is not None) and (len(names) > nbcols):
- names = [names[_] for _ in usecols]
- elif (names is not None) and (dtype is not None):
- names = list(dtype.names)
-
- # Process the missing values ...............................
- # Rename missing_values for convenience
- user_missing_values = missing_values or ()
- if isinstance(user_missing_values, bytes):
- user_missing_values = user_missing_values.decode('latin1')
-
- # Define the list of missing_values (one column: one list)
- missing_values = [list(['']) for _ in range(nbcols)]
-
- # We have a dictionary: process it field by field
- if isinstance(user_missing_values, dict):
- # Loop on the items
- for (key, val) in user_missing_values.items():
- # Is the key a string ?
- if _is_string_like(key):
- try:
- # Transform it into an integer
- key = names.index(key)
- except ValueError:
- # We couldn't find it: the name must have been dropped
- continue
- # Redefine the key as needed if it's a column number
- if usecols:
+ usecols = [_.strip() for _ in usecols.split(",")]
+ except AttributeError:
try:
- key = usecols.index(key)
- except ValueError:
- pass
- # Transform the value as a list of string
- if isinstance(val, (list, tuple)):
- val = [str(_) for _ in val]
+ usecols = list(usecols)
+ except TypeError:
+ usecols = [usecols, ]
+ nbcols = len(usecols or first_values)
+
+ # Check the names and overwrite the dtype.names if needed
+ if names is True:
+ names = validate_names([str(_.strip()) for _ in first_values])
+ first_line = ''
+ elif _is_string_like(names):
+ names = validate_names([_.strip() for _ in names.split(',')])
+ elif names:
+ names = validate_names(names)
+ # Get the dtype
+ if dtype is not None:
+ dtype = easy_dtype(dtype, defaultfmt=defaultfmt, names=names,
+ excludelist=excludelist,
+ deletechars=deletechars,
+ case_sensitive=case_sensitive,
+ replace_space=replace_space)
+ # Make sure the names is a list (for 2.5)
+ if names is not None:
+ names = list(names)
+
+ if usecols:
+ for (i, current) in enumerate(usecols):
+ # if usecols is a list of names, convert to a list of indices
+ if _is_string_like(current):
+ usecols[i] = names.index(current)
+ elif current < 0:
+ usecols[i] = current + len(first_values)
+ # If the dtype is not None, make sure we update it
+ if (dtype is not None) and (len(dtype) > nbcols):
+ descr = dtype.descr
+ dtype = np.dtype([descr[_] for _ in usecols])
+ names = list(dtype.names)
+ # If `names` is not None, update the names
+ elif (names is not None) and (len(names) > nbcols):
+ names = [names[_] for _ in usecols]
+ elif (names is not None) and (dtype is not None):
+ names = list(dtype.names)
+
+ # Process the missing values ...............................
+ # Rename missing_values for convenience
+ user_missing_values = missing_values or ()
+ if isinstance(user_missing_values, bytes):
+ user_missing_values = user_missing_values.decode('latin1')
+
+ # Define the list of missing_values (one column: one list)
+ missing_values = [list(['']) for _ in range(nbcols)]
+
+ # We have a dictionary: process it field by field
+ if isinstance(user_missing_values, dict):
+ # Loop on the items
+ for (key, val) in user_missing_values.items():
+ # Is the key a string ?
+ if _is_string_like(key):
+ try:
+ # Transform it into an integer
+ key = names.index(key)
+ except ValueError:
+ # We couldn't find it: the name must have been dropped
+ continue
+ # Redefine the key as needed if it's a column number
+ if usecols:
+ try:
+ key = usecols.index(key)
+ except ValueError:
+ pass
+ # Transform the value as a list of string
+ if isinstance(val, (list, tuple)):
+ val = [str(_) for _ in val]
+ else:
+ val = [str(val), ]
+ # Add the value(s) to the current list of missing
+ if key is None:
+ # None acts as default
+ for miss in missing_values:
+ miss.extend(val)
+ else:
+ missing_values[key].extend(val)
+ # We have a sequence : each item matches a column
+ elif isinstance(user_missing_values, (list, tuple)):
+ for (value, entry) in zip(user_missing_values, missing_values):
+ value = str(value)
+ if value not in entry:
+ entry.append(value)
+ # We have a string : apply it to all entries
+ elif isinstance(user_missing_values, basestring):
+ user_value = user_missing_values.split(",")
+ for entry in missing_values:
+ entry.extend(user_value)
+ # We have something else: apply it to all entries
+ else:
+ for entry in missing_values:
+ entry.extend([str(user_missing_values)])
+
+ # Process the filling_values ...............................
+ # Rename the input for convenience
+ user_filling_values = filling_values
+ if user_filling_values is None:
+ user_filling_values = []
+ # Define the default
+ filling_values = [None] * nbcols
+ # We have a dictionary : update each entry individually
+ if isinstance(user_filling_values, dict):
+ for (key, val) in user_filling_values.items():
+ if _is_string_like(key):
+ try:
+ # Transform it into an integer
+ key = names.index(key)
+ except ValueError:
+ # We couldn't find it: the name must have been dropped,
+ continue
+ # Redefine the key if it's a column number and usecols is defined
+ if usecols:
+ try:
+ key = usecols.index(key)
+ except ValueError:
+ pass
+ # Add the value to the list
+ filling_values[key] = val
+ # We have a sequence : update on a one-to-one basis
+ elif isinstance(user_filling_values, (list, tuple)):
+ n = len(user_filling_values)
+ if (n <= nbcols):
+ filling_values[:n] = user_filling_values
else:
- val = [str(val), ]
- # Add the value(s) to the current list of missing
- if key is None:
- # None acts as default
- for miss in missing_values:
- miss.extend(val)
+ filling_values = user_filling_values[:nbcols]
+ # We have something else : use it for all entries
+ else:
+ filling_values = [user_filling_values] * nbcols
+
+ # Initialize the converters ................................
+ if dtype is None:
+ # Note: we can't use a [...]*nbcols, as we would have 3 times the same
+ # ... converter, instead of 3 different converters.
+ converters = [StringConverter(None, missing_values=miss, default=fill)
+ for (miss, fill) in zip(missing_values, filling_values)]
+ else:
+ dtype_flat = flatten_dtype(dtype, flatten_base=True)
+ # Initialize the converters
+ if len(dtype_flat) > 1:
+ # Flexible type : get a converter from each dtype
+ zipit = zip(dtype_flat, missing_values, filling_values)
+ converters = [StringConverter(dt, locked=True,
+ missing_values=miss, default=fill)
+ for (dt, miss, fill) in zipit]
else:
- missing_values[key].extend(val)
- # We have a sequence : each item matches a column
- elif isinstance(user_missing_values, (list, tuple)):
- for (value, entry) in zip(user_missing_values, missing_values):
- value = str(value)
- if value not in entry:
- entry.append(value)
- # We have a string : apply it to all entries
- elif isinstance(user_missing_values, basestring):
- user_value = user_missing_values.split(",")
- for entry in missing_values:
- entry.extend(user_value)
- # We have something else: apply it to all entries
- else:
- for entry in missing_values:
- entry.extend([str(user_missing_values)])
-
- # Process the filling_values ...............................
- # Rename the input for convenience
- user_filling_values = filling_values
- if user_filling_values is None:
- user_filling_values = []
- # Define the default
- filling_values = [None] * nbcols
- # We have a dictionary : update each entry individually
- if isinstance(user_filling_values, dict):
- for (key, val) in user_filling_values.items():
- if _is_string_like(key):
+ # Set to a default converter (but w/ different missing values)
+ zipit = zip(missing_values, filling_values)
+ converters = [StringConverter(dtype, locked=True,
+ missing_values=miss, default=fill)
+ for (miss, fill) in zipit]
+ # Update the converters to use the user-defined ones
+ uc_update = []
+ for (j, conv) in user_converters.items():
+ # If the converter is specified by column names, use the index instead
+ if _is_string_like(j):
try:
- # Transform it into an integer
- key = names.index(key)
+ j = names.index(j)
+ i = j
except ValueError:
- # We couldn't find it: the name must have been dropped,
continue
- # Redefine the key if it's a column number and usecols is defined
- if usecols:
+ elif usecols:
try:
- key = usecols.index(key)
+ i = usecols.index(j)
except ValueError:
- pass
- # Add the value to the list
- filling_values[key] = val
- # We have a sequence : update on a one-to-one basis
- elif isinstance(user_filling_values, (list, tuple)):
- n = len(user_filling_values)
- if (n <= nbcols):
- filling_values[:n] = user_filling_values
- else:
- filling_values = user_filling_values[:nbcols]
- # We have something else : use it for all entries
- else:
- filling_values = [user_filling_values] * nbcols
-
- # Initialize the converters ................................
- if dtype is None:
- # Note: we can't use a [...]*nbcols, as we would have 3 times the same
- # ... converter, instead of 3 different converters.
- converters = [StringConverter(None, missing_values=miss, default=fill)
- for (miss, fill) in zip(missing_values, filling_values)]
- else:
- dtype_flat = flatten_dtype(dtype, flatten_base=True)
- # Initialize the converters
- if len(dtype_flat) > 1:
- # Flexible type : get a converter from each dtype
- zipit = zip(dtype_flat, missing_values, filling_values)
- converters = [StringConverter(dt, locked=True,
- missing_values=miss, default=fill)
- for (dt, miss, fill) in zipit]
- else:
- # Set to a default converter (but w/ different missing values)
- zipit = zip(missing_values, filling_values)
- converters = [StringConverter(dtype, locked=True,
- missing_values=miss, default=fill)
- for (miss, fill) in zipit]
- # Update the converters to use the user-defined ones
- uc_update = []
- for (j, conv) in user_converters.items():
- # If the converter is specified by column names, use the index instead
- if _is_string_like(j):
- try:
- j = names.index(j)
+ # Unused converter specified
+ continue
+ else:
i = j
- except ValueError:
- continue
- elif usecols:
- try:
- i = usecols.index(j)
- except ValueError:
- # Unused converter specified
+ # Find the value to test - first_line is not filtered by usecols:
+ if len(first_line):
+ testing_value = first_values[j]
+ else:
+ testing_value = None
+ if conv is bytes:
+ user_conv = asbytes
+ elif byte_converters:
+ # converters may use decode to workaround numpy's old behaviour,
+ # so encode the string again before passing to the user converter
+ def tobytes_first(x, conv):
+ if type(x) is bytes:
+ return conv(x)
+ return conv(x.encode("latin1"))
+ user_conv = functools.partial(tobytes_first, conv=conv)
+ else:
+ user_conv = conv
+ converters[i].update(user_conv, locked=True,
+ testing_value=testing_value,
+ default=filling_values[i],
+ missing_values=missing_values[i],)
+ uc_update.append((i, user_conv))
+ # Make sure we have the corrected keys in user_converters...
+ user_converters.update(uc_update)
+
+ # Fixme: possible error as following variable never used.
+ # miss_chars = [_.missing_values for _ in converters]
+
+ # Initialize the output lists ...
+ # ... rows
+ rows = []
+ append_to_rows = rows.append
+ # ... masks
+ if usemask:
+ masks = []
+ append_to_masks = masks.append
+ # ... invalid
+ invalid = []
+ append_to_invalid = invalid.append
+
+ # Parse each line
+ for (i, line) in enumerate(itertools.chain([first_line, ], fhd)):
+ values = split_line(line)
+ nbvalues = len(values)
+ # Skip an empty line
+ if nbvalues == 0:
continue
- else:
- i = j
- # Find the value to test - first_line is not filtered by usecols:
- if len(first_line):
- testing_value = first_values[j]
- else:
- testing_value = None
- if conv is bytes:
- user_conv = asbytes
- elif byte_converters:
- # converters may use decode to workaround numpy's old behaviour,
- # so encode the string again before passing to the user converter
- def tobytes_first(x, conv):
- if type(x) is bytes:
- return conv(x)
- return conv(x.encode("latin1"))
- import functools
- user_conv = functools.partial(tobytes_first, conv=conv)
- else:
- user_conv = conv
- converters[i].update(user_conv, locked=True,
- testing_value=testing_value,
- default=filling_values[i],
- missing_values=missing_values[i],)
- uc_update.append((i, user_conv))
- # Make sure we have the corrected keys in user_converters...
- user_converters.update(uc_update)
-
- # Fixme: possible error as following variable never used.
- # miss_chars = [_.missing_values for _ in converters]
-
- # Initialize the output lists ...
- # ... rows
- rows = []
- append_to_rows = rows.append
- # ... masks
- if usemask:
- masks = []
- append_to_masks = masks.append
- # ... invalid
- invalid = []
- append_to_invalid = invalid.append
-
- # Parse each line
- for (i, line) in enumerate(itertools.chain([first_line, ], fhd)):
- values = split_line(line)
- nbvalues = len(values)
- # Skip an empty line
- if nbvalues == 0:
- continue
- if usecols:
- # Select only the columns we need
- try:
- values = [values[_] for _ in usecols]
- except IndexError:
+ if usecols:
+ # Select only the columns we need
+ try:
+ values = [values[_] for _ in usecols]
+ except IndexError:
+ append_to_invalid((i + skip_header + 1, nbvalues))
+ continue
+ elif nbvalues != nbcols:
append_to_invalid((i + skip_header + 1, nbvalues))
continue
- elif nbvalues != nbcols:
- append_to_invalid((i + skip_header + 1, nbvalues))
- continue
- # Store the values
- append_to_rows(tuple(values))
- if usemask:
- append_to_masks(tuple([v.strip() in m
- for (v, m) in zip(values,
- missing_values)]))
- if len(rows) == max_rows:
- break
-
- if own_fhd:
- fhd.close()
+ # Store the values
+ append_to_rows(tuple(values))
+ if usemask:
+ append_to_masks(tuple([v.strip() in m
+ for (v, m) in zip(values,
+ missing_values)]))
+ if len(rows) == max_rows:
+ break
# Upgrade the converters (if needed)
if dtype is None:
@@ -2154,7 +2168,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
outputmask = np.array(masks, dtype=mdtype)
else:
# Overwrite the initial dtype names if needed
- if names and dtype.names is not None:
+ if names and dtype.names:
dtype.names = names
# Case 1. We have a structured type
if len(dtype_flat) > 1:
@@ -2204,7 +2218,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
#
output = np.array(data, dtype)
if usemask:
- if dtype.names is not None:
+ if dtype.names:
mdtype = [(_, bool) for _ in dtype.names]
else:
mdtype = bool
@@ -2230,6 +2244,12 @@ def ndfromtxt(fname, **kwargs):
"""
Load ASCII data stored in a file and return it as a single array.
+ .. deprecated:: 1.17
+ ndfromtxt` is a deprecated alias of `genfromtxt` which
+ overwrites the ``usemask`` argument with `False` even when
+ explicitly called as ``ndfromtxt(..., usemask=True)``.
+ Use `genfromtxt` instead.
+
Parameters
----------
fname, kwargs : For a description of input parameters, see `genfromtxt`.
@@ -2240,6 +2260,11 @@ def ndfromtxt(fname, **kwargs):
"""
kwargs['usemask'] = False
+ # Numpy 1.17
+ warnings.warn(
+ "np.ndfromtxt is a deprecated alias of np.genfromtxt, "
+ "prefer the latter.",
+ DeprecationWarning, stacklevel=2)
return genfromtxt(fname, **kwargs)
@@ -2247,6 +2272,12 @@ def mafromtxt(fname, **kwargs):
"""
Load ASCII data stored in a text file and return a masked array.
+ .. deprecated:: 1.17
+ np.mafromtxt is a deprecated alias of `genfromtxt` which
+ overwrites the ``usemask`` argument with `True` even when
+ explicitly called as ``mafromtxt(..., usemask=False)``.
+ Use `genfromtxt` instead.
+
Parameters
----------
fname, kwargs : For a description of input parameters, see `genfromtxt`.
@@ -2257,6 +2288,11 @@ def mafromtxt(fname, **kwargs):
"""
kwargs['usemask'] = True
+ # Numpy 1.17
+ warnings.warn(
+ "np.mafromtxt is a deprecated alias of np.genfromtxt, "
+ "prefer the latter.",
+ DeprecationWarning, stacklevel=2)
return genfromtxt(fname, **kwargs)
diff --git a/numpy/lib/polynomial.py b/numpy/lib/polynomial.py
index 7c858475a..2c72f623c 100644
--- a/numpy/lib/polynomial.py
+++ b/numpy/lib/polynomial.py
@@ -110,7 +110,7 @@ def poly(seq_of_zeros):
Given a sequence of a polynomial's zeros:
>>> np.poly((0, 0, 0)) # Multiple root example
- array([1, 0, 0, 0])
+ array([1., 0., 0., 0.])
The line above represents z**3 + 0*z**2 + 0*z + 0.
@@ -119,14 +119,14 @@ def poly(seq_of_zeros):
The line above represents z**3 - z/4
- >>> np.poly((np.random.random(1.)[0], 0, np.random.random(1.)[0]))
- array([ 1. , -0.77086955, 0.08618131, 0. ]) #random
+ >>> np.poly((np.random.random(1)[0], 0, np.random.random(1)[0]))
+ array([ 1. , -0.77086955, 0.08618131, 0. ]) # random
Given a square array object:
>>> P = np.array([[0, 1./3], [-1./2, 0]])
>>> np.poly(P)
- array([ 1. , 0. , 0.16666667])
+ array([1. , 0. , 0.16666667])
Note how in all cases the leading coefficient is always 1.
@@ -295,7 +295,7 @@ def polyint(p, m=1, k=None):
>>> p = np.poly1d([1,1,1])
>>> P = np.polyint(p)
>>> P
- poly1d([ 0.33333333, 0.5 , 1. , 0. ])
+ poly1d([ 0.33333333, 0.5 , 1. , 0. ]) # may vary
>>> np.polyder(P) == p
True
@@ -310,7 +310,7 @@ def polyint(p, m=1, k=None):
0.0
>>> P = np.polyint(p, 3, k=[6,5,3])
>>> P
- poly1d([ 0.01666667, 0.04166667, 0.16666667, 3. , 5. , 3. ])
+ poly1d([ 0.01666667, 0.04166667, 0.16666667, 3. , 5. , 3. ]) # may vary
Note that 3 = 6 / 2!, and that the constants are given in the order of
integrations. Constant of the highest-order polynomial term comes first:
@@ -404,7 +404,7 @@ def polyder(p, m=1):
>>> np.polyder(p, 3)
poly1d([6])
>>> np.polyder(p, 4)
- poly1d([ 0.])
+ poly1d([0.])
"""
m = int(m)
@@ -548,32 +548,35 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):
Examples
--------
+ >>> import warnings
>>> x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
>>> y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0])
>>> z = np.polyfit(x, y, 3)
>>> z
- array([ 0.08703704, -0.81349206, 1.69312169, -0.03968254])
+ array([ 0.08703704, -0.81349206, 1.69312169, -0.03968254]) # may vary
It is convenient to use `poly1d` objects for dealing with polynomials:
>>> p = np.poly1d(z)
>>> p(0.5)
- 0.6143849206349179
+ 0.6143849206349179 # may vary
>>> p(3.5)
- -0.34732142857143039
+ -0.34732142857143039 # may vary
>>> p(10)
- 22.579365079365115
+ 22.579365079365115 # may vary
High-order polynomials may oscillate wildly:
- >>> p30 = np.poly1d(np.polyfit(x, y, 30))
- /... RankWarning: Polyfit may be poorly conditioned...
+ >>> with warnings.catch_warnings():
+ ... warnings.simplefilter('ignore', np.RankWarning)
+ ... p30 = np.poly1d(np.polyfit(x, y, 30))
+ ...
>>> p30(4)
- -0.80000000000000204
+ -0.80000000000000204 # may vary
>>> p30(5)
- -0.99999999999999445
+ -0.99999999999999445 # may vary
>>> p30(4.5)
- -0.10547061179440398
+ -0.10547061179440398 # may vary
Illustration:
@@ -631,7 +634,7 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):
# warn on rank reduction, which indicates an ill conditioned matrix
if rank != order and not full:
msg = "Polyfit may be poorly conditioned"
- warnings.warn(msg, RankWarning, stacklevel=2)
+ warnings.warn(msg, RankWarning, stacklevel=4)
if full:
return c, resids, rank, s, rcond
@@ -703,6 +706,8 @@ def polyval(p, x):
for polynomials of high degree the values may be inaccurate due to
rounding errors. Use carefully.
+ If `x` is a subtype of `ndarray` the return value will be of the same type.
+
References
----------
.. [1] I. N. Bronshtein, K. A. Semendyayev, and K. A. Hirsch (Eng.
@@ -714,18 +719,18 @@ def polyval(p, x):
>>> np.polyval([3,0,1], 5) # 3 * 5**2 + 0 * 5**1 + 1
76
>>> np.polyval([3,0,1], np.poly1d(5))
- poly1d([ 76.])
+ poly1d([76.])
>>> np.polyval(np.poly1d([3,0,1]), 5)
76
>>> np.polyval(np.poly1d([3,0,1]), np.poly1d(5))
- poly1d([ 76.])
+ poly1d([76.])
"""
p = NX.asarray(p)
if isinstance(x, poly1d):
y = 0
else:
- x = NX.asarray(x)
+ x = NX.asanyarray(x)
y = NX.zeros_like(x)
for i in range(len(p)):
y = y * x + p[i]
@@ -871,8 +876,7 @@ def polymul(a1, a2):
See Also
--------
poly1d : A one-dimensional polynomial class.
- poly, polyadd, polyder, polydiv, polyfit, polyint, polysub,
- polyval
+ poly, polyadd, polyder, polydiv, polyfit, polyint, polysub, polyval
convolve : Array convolution. Same output as polymul, but has parameter
for overlap mode.
@@ -934,7 +938,7 @@ def polydiv(u, v):
See Also
--------
- poly, polyadd, polyder, polydiv, polyfit, polyint, polymul, polysub,
+ poly, polyadd, polyder, polydiv, polyfit, polyint, polymul, polysub
polyval
Notes
@@ -951,7 +955,7 @@ def polydiv(u, v):
>>> x = np.array([3.0, 5.0, 2.0])
>>> y = np.array([2.0, 1.0])
>>> np.polydiv(x, y)
- (array([ 1.5 , 1.75]), array([ 0.25]))
+ (array([1.5 , 1.75]), array([0.25]))
"""
truepoly = (isinstance(u, poly1d) or isinstance(u, poly1d))
@@ -1046,7 +1050,7 @@ class poly1d(object):
>>> p.r
array([-1.+1.41421356j, -1.-1.41421356j])
>>> p(p.r)
- array([ -4.44089210e-16+0.j, -4.44089210e-16+0.j])
+ array([ -4.44089210e-16+0.j, -4.44089210e-16+0.j]) # may vary
These numbers in the previous line represent (0, 0) to machine precision
@@ -1073,7 +1077,7 @@ class poly1d(object):
poly1d([ 1, 4, 10, 12, 9])
>>> (p**3 + 4) / p
- (poly1d([ 1., 4., 10., 12., 9.]), poly1d([ 4.]))
+ (poly1d([ 1., 4., 10., 12., 9.]), poly1d([4.]))
``asarray(p)`` gives the coefficient array, so polynomials can be
used in all functions that accept arrays:
@@ -1095,7 +1099,7 @@ class poly1d(object):
Construct a polynomial from its roots:
>>> np.poly1d([1, 2], True)
- poly1d([ 1, -3, 2])
+ poly1d([ 1., -3., 2.])
This is the same polynomial as obtained by:
diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py
index 40060b41a..6e257bb3f 100644
--- a/numpy/lib/recfunctions.py
+++ b/numpy/lib/recfunctions.py
@@ -72,7 +72,7 @@ def recursive_fill_fields(input, output):
current = input[field]
except ValueError:
continue
- if current.dtype.names is not None:
+ if current.dtype.names:
recursive_fill_fields(current, output[field])
else:
output[field][:len(current)] = current
@@ -139,11 +139,11 @@ def get_names(adtype):
names = adtype.names
for name in names:
current = adtype[name]
- if current.names is not None:
+ if current.names:
listnames.append((name, tuple(get_names(current))))
else:
listnames.append(name)
- return tuple(listnames)
+ return tuple(listnames) or None
def get_names_flat(adtype):
@@ -176,9 +176,9 @@ def get_names_flat(adtype):
for name in names:
listnames.append(name)
current = adtype[name]
- if current.names is not None:
+ if current.names:
listnames.extend(get_names_flat(current))
- return tuple(listnames)
+ return tuple(listnames) or None
def flatten_descr(ndtype):
@@ -215,8 +215,8 @@ def _zip_dtype(seqarrays, flatten=False):
else:
for a in seqarrays:
current = a.dtype
- if current.names is not None and len(current.names) == 1:
- # special case - dtypes of 1 field are flattened
+ if current.names and len(current.names) <= 1:
+ # special case - dtypes of 0 or 1 field are flattened
newdtype.extend(_get_fieldspec(current))
else:
newdtype.append(('', current))
@@ -268,7 +268,7 @@ def get_fieldstructure(adtype, lastname=None, parents=None,):
names = adtype.names
for name in names:
current = adtype[name]
- if current.names is not None:
+ if current.names:
if lastname:
parents[name] = [lastname, ]
else:
@@ -281,7 +281,7 @@ def get_fieldstructure(adtype, lastname=None, parents=None,):
elif lastname:
lastparent = [lastname, ]
parents[name] = lastparent or []
- return parents
+ return parents or None
def _izip_fields_flat(iterable):
@@ -435,7 +435,7 @@ def merge_arrays(seqarrays, fill_value=-1, flatten=False,
if isinstance(seqarrays, (ndarray, np.void)):
seqdtype = seqarrays.dtype
# Make sure we have named fields
- if seqdtype.names is None:
+ if not seqdtype.names:
seqdtype = np.dtype([('', seqdtype)])
if not flatten or _zip_dtype((seqarrays,), flatten=True) == seqdtype:
# Minimal processing needed: just make sure everythng's a-ok
@@ -653,7 +653,7 @@ def rename_fields(base, namemapper):
for name in ndtype.names:
newname = namemapper.get(name, name)
current = ndtype[name]
- if current.names is not None:
+ if current.names:
newdtype.append(
(newname, _recursive_rename_fields(current, namemapper))
)
@@ -874,35 +874,16 @@ def _get_fields_and_offsets(dt, offset=0):
scalar fields in the dtype "dt", including nested fields, in left
to right order.
"""
-
- # counts up elements in subarrays, including nested subarrays, and returns
- # base dtype and count
- def count_elem(dt):
- count = 1
- while dt.shape != ():
- for size in dt.shape:
- count *= size
- dt = dt.base
- return dt, count
-
fields = []
for name in dt.names:
field = dt.fields[name]
- f_dt, f_offset = field[0], field[1]
- f_dt, n = count_elem(f_dt)
-
- if f_dt.names is None:
- fields.append((np.dtype((f_dt, (n,))), n, f_offset + offset))
+ if field[0].names is None:
+ count = 1
+ for size in field[0].shape:
+ count *= size
+ fields.append((field[0], count, field[1] + offset))
else:
- subfields = _get_fields_and_offsets(f_dt, f_offset + offset)
- size = f_dt.itemsize
-
- for i in range(n):
- if i == 0:
- # optimization: avoid list comprehension if no subarray
- fields.extend(subfields)
- else:
- fields.extend([(d, c, o + i*size) for d, c, o in subfields])
+ fields.extend(_get_fields_and_offsets(field[0], field[1] + offset))
return fields
@@ -967,12 +948,6 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'):
fields = _get_fields_and_offsets(arr.dtype)
n_fields = len(fields)
- if n_fields == 0 and dtype is None:
- raise ValueError("arr has no fields. Unable to guess dtype")
- elif n_fields == 0:
- # too many bugs elsewhere for this to work now
- raise NotImplementedError("arr with no fields is not supported")
-
dts, counts, offsets = zip(*fields)
names = ['f{}'.format(n) for n in range(n_fields)]
@@ -1064,9 +1039,6 @@ def unstructured_to_structured(arr, dtype=None, names=None, align=False,
if arr.shape == ():
raise ValueError('arr must have at least one dimension')
n_elem = arr.shape[-1]
- if n_elem == 0:
- # too many bugs elsewhere for this to work now
- raise NotImplementedError("last axis with size 0 is not supported")
if dtype is None:
if names is None:
@@ -1079,11 +1051,7 @@ def unstructured_to_structured(arr, dtype=None, names=None, align=False,
raise ValueError("don't supply both dtype and names")
# sanity check of the input dtype
fields = _get_fields_and_offsets(dtype)
- if len(fields) == 0:
- dts, counts, offsets = [], [], []
- else:
- dts, counts, offsets = zip(*fields)
-
+ dts, counts, offsets = zip(*fields)
if n_elem != sum(counts):
raise ValueError('The length of the last dimension of arr must '
'be equal to the number of fields in dtype')
diff --git a/numpy/lib/scimath.py b/numpy/lib/scimath.py
index 9ca006841..5ac790ce9 100644
--- a/numpy/lib/scimath.py
+++ b/numpy/lib/scimath.py
@@ -59,7 +59,7 @@ def _tocomplex(arr):
>>> a = np.array([1,2,3],np.short)
>>> ac = np.lib.scimath._tocomplex(a); ac
- array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
+ array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
>>> ac.dtype
dtype('complex64')
@@ -70,7 +70,7 @@ def _tocomplex(arr):
>>> b = np.array([1,2,3],np.double)
>>> bc = np.lib.scimath._tocomplex(b); bc
- array([ 1.+0.j, 2.+0.j, 3.+0.j])
+ array([1.+0.j, 2.+0.j, 3.+0.j])
>>> bc.dtype
dtype('complex128')
@@ -81,13 +81,13 @@ def _tocomplex(arr):
>>> c = np.array([1,2,3],np.csingle)
>>> cc = np.lib.scimath._tocomplex(c); cc
- array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
+ array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
>>> c *= 2; c
- array([ 2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64)
+ array([2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64)
>>> cc
- array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
+ array([1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64)
"""
if issubclass(arr.dtype.type, (nt.single, nt.byte, nt.short, nt.ubyte,
nt.ushort, nt.csingle)):
@@ -170,7 +170,7 @@ def _fix_real_abs_gt_1(x):
array([0, 1])
>>> np.lib.scimath._fix_real_abs_gt_1([0,2])
- array([ 0.+0.j, 2.+0.j])
+ array([0.+0.j, 2.+0.j])
"""
x = asarray(x)
if any(isreal(x) & (abs(x) > 1)):
@@ -212,14 +212,14 @@ def sqrt(x):
>>> np.lib.scimath.sqrt(1)
1.0
>>> np.lib.scimath.sqrt([1, 4])
- array([ 1., 2.])
+ array([1., 2.])
But it automatically handles negative inputs:
>>> np.lib.scimath.sqrt(-1)
- (0.0+1.0j)
+ 1j
>>> np.lib.scimath.sqrt([-1,4])
- array([ 0.+1.j, 2.+0.j])
+ array([0.+1.j, 2.+0.j])
"""
x = _fix_real_lt_zero(x)
@@ -317,7 +317,7 @@ def log10(x):
1.0
>>> np.emath.log10([-10**1, -10**2, 10**2])
- array([ 1.+1.3644j, 2.+1.3644j, 2.+0.j ])
+ array([1.+1.3644j, 2.+1.3644j, 2.+0.j ])
"""
x = _fix_real_lt_zero(x)
@@ -354,9 +354,9 @@ def logn(n, x):
>>> np.set_printoptions(precision=4)
>>> np.lib.scimath.logn(2, [4, 8])
- array([ 2., 3.])
+ array([2., 3.])
>>> np.lib.scimath.logn(2, [-4, -8, 8])
- array([ 2.+4.5324j, 3.+4.5324j, 3.+0.j ])
+ array([2.+4.5324j, 3.+4.5324j, 3.+0.j ])
"""
x = _fix_real_lt_zero(x)
@@ -405,7 +405,7 @@ def log2(x):
>>> np.emath.log2(8)
3.0
>>> np.emath.log2([-4, -8, 8])
- array([ 2.+4.5324j, 3.+4.5324j, 3.+0.j ])
+ array([2.+4.5324j, 3.+4.5324j, 3.+0.j ])
"""
x = _fix_real_lt_zero(x)
@@ -451,9 +451,9 @@ def power(x, p):
>>> np.lib.scimath.power([2, 4], 2)
array([ 4, 16])
>>> np.lib.scimath.power([2, 4], -2)
- array([ 0.25 , 0.0625])
+ array([0.25 , 0.0625])
>>> np.lib.scimath.power([-2, 4], 2)
- array([ 4.+0.j, 16.+0.j])
+ array([ 4.-0.j, 16.+0.j])
"""
x = _fix_real_lt_zero(x)
@@ -499,7 +499,7 @@ def arccos(x):
0.0
>>> np.emath.arccos([1,2])
- array([ 0.-0.j , 0.+1.317j])
+ array([0.-0.j , 0.-1.317j])
"""
x = _fix_real_abs_gt_1(x)
@@ -545,7 +545,7 @@ def arcsin(x):
0.0
>>> np.emath.arcsin([0,1])
- array([ 0. , 1.5708])
+ array([0. , 1.5708])
"""
x = _fix_real_abs_gt_1(x)
@@ -589,11 +589,14 @@ def arctanh(x):
--------
>>> np.set_printoptions(precision=4)
- >>> np.emath.arctanh(np.eye(2))
- array([[ Inf, 0.],
- [ 0., Inf]])
+ >>> from numpy.testing import suppress_warnings
+ >>> with suppress_warnings() as sup:
+ ... sup.filter(RuntimeWarning)
+ ... np.emath.arctanh(np.eye(2))
+ array([[inf, 0.],
+ [ 0., inf]])
>>> np.emath.arctanh([1j])
- array([ 0.+0.7854j])
+ array([0.+0.7854j])
"""
x = _fix_real_abs_gt_1(x)
diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py
index f56c4f4db..a5d0040aa 100644
--- a/numpy/lib/shape_base.py
+++ b/numpy/lib/shape_base.py
@@ -7,12 +7,11 @@ import numpy.core.numeric as _nx
from numpy.core.numeric import (
asarray, zeros, outer, concatenate, array, asanyarray
)
-from numpy.core.fromnumeric import product, reshape, transpose
+from numpy.core.fromnumeric import reshape, transpose
from numpy.core.multiarray import normalize_axis_index
from numpy.core import overrides
from numpy.core import vstack, atleast_3d
-from numpy.core.shape_base import (
- _arrays_for_stack_dispatcher, _warn_for_nonsequence)
+from numpy.core.shape_base import _arrays_for_stack_dispatcher
from numpy.lib.index_tricks import ndindex
from numpy.matrixlib.defmatrix import matrix # this raises all the right alarm bells
@@ -95,7 +94,7 @@ def take_along_axis(arr, indices, axis):
Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:]
J = indices.shape[axis] # Need not equal M
- out = np.empty(Nk + (J,) + Nk)
+ out = np.empty(Ni + (J,) + Nk)
for ii in ndindex(Ni):
for kk in ndindex(Nk):
@@ -129,7 +128,7 @@ def take_along_axis(arr, indices, axis):
[40, 50, 60]])
>>> ai = np.argsort(a, axis=1); ai
array([[0, 2, 1],
- [1, 2, 0]], dtype=int64)
+ [1, 2, 0]])
>>> np.take_along_axis(a, ai, axis=1)
array([[10, 20, 30],
[40, 50, 60]])
@@ -142,7 +141,7 @@ def take_along_axis(arr, indices, axis):
>>> ai = np.expand_dims(np.argmax(a, axis=1), axis=1)
>>> ai
array([[1],
- [0], dtype=int64)
+ [0]])
>>> np.take_along_axis(a, ai, axis=1)
array([[30],
[60]])
@@ -152,10 +151,10 @@ def take_along_axis(arr, indices, axis):
>>> ai_min = np.expand_dims(np.argmin(a, axis=1), axis=1)
>>> ai_max = np.expand_dims(np.argmax(a, axis=1), axis=1)
- >>> ai = np.concatenate([ai_min, ai_max], axis=axis)
- >> ai
+ >>> ai = np.concatenate([ai_min, ai_max], axis=1)
+ >>> ai
array([[0, 1],
- [1, 0]], dtype=int64)
+ [1, 0]])
>>> np.take_along_axis(a, ai, axis=1)
array([[10, 30],
[40, 60]])
@@ -243,7 +242,7 @@ def put_along_axis(arr, indices, values, axis):
>>> ai = np.expand_dims(np.argmax(a, axis=1), axis=1)
>>> ai
array([[1],
- [0]], dtype=int64)
+ [0]])
>>> np.put_along_axis(a, ai, 99, axis=1)
>>> a
array([[10, 99, 20],
@@ -330,9 +329,9 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
... return (a[0] + a[-1]) * 0.5
>>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> np.apply_along_axis(my_func, 0, b)
- array([ 4., 5., 6.])
+ array([4., 5., 6.])
>>> np.apply_along_axis(my_func, 1, b)
- array([ 2., 5., 8.])
+ array([2., 5., 8.])
For a function that returns a 1D array, the number of dimensions in
`outarr` is the same as `arr`.
@@ -533,8 +532,7 @@ def expand_dims(a, axis):
Returns
-------
res : ndarray
- Output array. The number of dimensions is one greater than that of
- the input array.
+ View of `a` with the number of dimensions increased by one.
See Also
--------
@@ -580,7 +578,7 @@ def expand_dims(a, axis):
# 2017-05-17, 1.13.0
warnings.warn("Both axis > a.ndim and axis < -a.ndim - 1 are "
"deprecated and will raise an AxisError in the future.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
# When the deprecation period expires, delete this if block,
if axis < 0:
axis = axis + a.ndim + 1
@@ -630,7 +628,10 @@ def column_stack(tup):
[3, 4]])
"""
- _warn_for_nonsequence(tup)
+ if not overrides.ARRAY_FUNCTION_ENABLED:
+ # raise warning if necessary
+ _arrays_for_stack_dispatcher(tup, stacklevel=2)
+
arrays = []
for v in tup:
arr = array(v, copy=False, subok=True)
@@ -695,8 +696,14 @@ def dstack(tup):
[[3, 4]]])
"""
- _warn_for_nonsequence(tup)
- return _nx.concatenate([atleast_3d(_m) for _m in tup], 2)
+ if not overrides.ARRAY_FUNCTION_ENABLED:
+ # raise warning if necessary
+ _arrays_for_stack_dispatcher(tup, stacklevel=2)
+
+ arrs = atleast_3d(*tup)
+ if not isinstance(arrs, list):
+ arrs = [arrs]
+ return _nx.concatenate(arrs, 2)
def _replace_zero_by_x_arrays(sub_arys):
@@ -732,11 +739,11 @@ def array_split(ary, indices_or_sections, axis=0):
--------
>>> x = np.arange(8.0)
>>> np.array_split(x, 3)
- [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7.])]
+ [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])]
>>> x = np.arange(7.0)
>>> np.array_split(x, 3)
- [array([ 0., 1., 2.]), array([ 3., 4.]), array([ 5., 6.])]
+ [array([0., 1., 2.]), array([3., 4.]), array([5., 6.])]
"""
try:
@@ -828,14 +835,14 @@ def split(ary, indices_or_sections, axis=0):
--------
>>> x = np.arange(9.0)
>>> np.split(x, 3)
- [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7., 8.])]
+ [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]
>>> x = np.arange(8.0)
>>> np.split(x, [3, 5, 6, 10])
- [array([ 0., 1., 2.]),
- array([ 3., 4.]),
- array([ 5.]),
- array([ 6., 7.]),
+ [array([0., 1., 2.]),
+ array([3., 4.]),
+ array([5.]),
+ array([6., 7.]),
array([], dtype=float64)]
"""
@@ -872,43 +879,43 @@ def hsplit(ary, indices_or_sections):
--------
>>> x = np.arange(16.0).reshape(4, 4)
>>> x
- array([[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.],
- [ 8., 9., 10., 11.],
- [ 12., 13., 14., 15.]])
+ array([[ 0., 1., 2., 3.],
+ [ 4., 5., 6., 7.],
+ [ 8., 9., 10., 11.],
+ [12., 13., 14., 15.]])
>>> np.hsplit(x, 2)
[array([[ 0., 1.],
[ 4., 5.],
[ 8., 9.],
- [ 12., 13.]]),
+ [12., 13.]]),
array([[ 2., 3.],
[ 6., 7.],
- [ 10., 11.],
- [ 14., 15.]])]
+ [10., 11.],
+ [14., 15.]])]
>>> np.hsplit(x, np.array([3, 6]))
- [array([[ 0., 1., 2.],
- [ 4., 5., 6.],
- [ 8., 9., 10.],
- [ 12., 13., 14.]]),
- array([[ 3.],
- [ 7.],
- [ 11.],
- [ 15.]]),
- array([], dtype=float64)]
+ [array([[ 0., 1., 2.],
+ [ 4., 5., 6.],
+ [ 8., 9., 10.],
+ [12., 13., 14.]]),
+ array([[ 3.],
+ [ 7.],
+ [11.],
+ [15.]]),
+ array([], shape=(4, 0), dtype=float64)]
With a higher dimensional array the split is still along the second axis.
>>> x = np.arange(8.0).reshape(2, 2, 2)
>>> x
- array([[[ 0., 1.],
- [ 2., 3.]],
- [[ 4., 5.],
- [ 6., 7.]]])
+ array([[[0., 1.],
+ [2., 3.]],
+ [[4., 5.],
+ [6., 7.]]])
>>> np.hsplit(x, 2)
- [array([[[ 0., 1.]],
- [[ 4., 5.]]]),
- array([[[ 2., 3.]],
- [[ 6., 7.]]])]
+ [array([[[0., 1.]],
+ [[4., 5.]]]),
+ array([[[2., 3.]],
+ [[6., 7.]]])]
"""
if _nx.ndim(ary) == 0:
@@ -936,35 +943,31 @@ def vsplit(ary, indices_or_sections):
--------
>>> x = np.arange(16.0).reshape(4, 4)
>>> x
- array([[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.],
- [ 8., 9., 10., 11.],
- [ 12., 13., 14., 15.]])
+ array([[ 0., 1., 2., 3.],
+ [ 4., 5., 6., 7.],
+ [ 8., 9., 10., 11.],
+ [12., 13., 14., 15.]])
>>> np.vsplit(x, 2)
- [array([[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.]]),
- array([[ 8., 9., 10., 11.],
- [ 12., 13., 14., 15.]])]
+ [array([[0., 1., 2., 3.],
+ [4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.],
+ [12., 13., 14., 15.]])]
>>> np.vsplit(x, np.array([3, 6]))
- [array([[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.],
- [ 8., 9., 10., 11.]]),
- array([[ 12., 13., 14., 15.]]),
- array([], dtype=float64)]
+ [array([[ 0., 1., 2., 3.],
+ [ 4., 5., 6., 7.],
+ [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)]
With a higher dimensional array the split is still along the first axis.
>>> x = np.arange(8.0).reshape(2, 2, 2)
>>> x
- array([[[ 0., 1.],
- [ 2., 3.]],
- [[ 4., 5.],
- [ 6., 7.]]])
+ array([[[0., 1.],
+ [2., 3.]],
+ [[4., 5.],
+ [6., 7.]]])
>>> np.vsplit(x, 2)
- [array([[[ 0., 1.],
- [ 2., 3.]]]),
- array([[[ 4., 5.],
- [ 6., 7.]]])]
+ [array([[[0., 1.],
+ [2., 3.]]]), array([[[4., 5.],
+ [6., 7.]]])]
"""
if _nx.ndim(ary) < 2:
@@ -989,30 +992,28 @@ def dsplit(ary, indices_or_sections):
--------
>>> x = np.arange(16.0).reshape(2, 2, 4)
>>> x
- array([[[ 0., 1., 2., 3.],
- [ 4., 5., 6., 7.]],
- [[ 8., 9., 10., 11.],
- [ 12., 13., 14., 15.]]])
+ array([[[ 0., 1., 2., 3.],
+ [ 4., 5., 6., 7.]],
+ [[ 8., 9., 10., 11.],
+ [12., 13., 14., 15.]]])
>>> np.dsplit(x, 2)
- [array([[[ 0., 1.],
- [ 4., 5.]],
- [[ 8., 9.],
- [ 12., 13.]]]),
- array([[[ 2., 3.],
- [ 6., 7.]],
- [[ 10., 11.],
- [ 14., 15.]]])]
+ [array([[[ 0., 1.],
+ [ 4., 5.]],
+ [[ 8., 9.],
+ [12., 13.]]]), array([[[ 2., 3.],
+ [ 6., 7.]],
+ [[10., 11.],
+ [14., 15.]]])]
>>> np.dsplit(x, np.array([3, 6]))
- [array([[[ 0., 1., 2.],
- [ 4., 5., 6.]],
- [[ 8., 9., 10.],
- [ 12., 13., 14.]]]),
- array([[[ 3.],
- [ 7.]],
- [[ 11.],
- [ 15.]]]),
- array([], dtype=float64)]
-
+ [array([[[ 0., 1., 2.],
+ [ 4., 5., 6.]],
+ [[ 8., 9., 10.],
+ [12., 13., 14.]]]),
+ array([[[ 3.],
+ [ 7.]],
+ [[11.],
+ [15.]]]),
+ array([], shape=(2, 2, 0), dtype=float64)]
"""
if _nx.ndim(ary) < 3:
raise ValueError('dsplit only works on arrays of 3 or more dimensions')
@@ -1092,15 +1093,15 @@ def kron(a, b):
Examples
--------
>>> np.kron([1,10,100], [5,6,7])
- array([ 5, 6, 7, 50, 60, 70, 500, 600, 700])
+ array([ 5, 6, 7, ..., 500, 600, 700])
>>> np.kron([5,6,7], [1,10,100])
- array([ 5, 50, 500, 6, 60, 600, 7, 70, 700])
+ array([ 5, 50, 500, ..., 7, 70, 700])
>>> np.kron(np.eye(2), np.ones((2,2)))
- array([[ 1., 1., 0., 0.],
- [ 1., 1., 0., 0.],
- [ 0., 0., 1., 1.],
- [ 0., 0., 1., 1.]])
+ array([[1., 1., 0., 0.],
+ [1., 1., 0., 0.],
+ [0., 0., 1., 1.],
+ [0., 0., 1., 1.]])
>>> a = np.arange(100).reshape((2,5,2,5))
>>> b = np.arange(24).reshape((2,3,4))
diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
index 0dc36e41c..8aafd094b 100644
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -121,18 +121,18 @@ def _broadcast_to(array, shape, subok, readonly):
if any(size < 0 for size in shape):
raise ValueError('all elements of broadcast shape must be non-'
'negative')
- needs_writeable = not readonly and array.flags.writeable
- extras = ['reduce_ok'] if needs_writeable else []
- op_flag = 'readwrite' if needs_writeable else 'readonly'
+ extras = []
it = np.nditer(
(array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'] + extras,
- op_flags=[op_flag], itershape=shape, order='C')
+ op_flags=['readonly'], itershape=shape, order='C')
with it:
# never really has writebackifcopy semantics
broadcast = it.itviews[0]
result = _maybe_view_as_subclass(array, broadcast)
- if needs_writeable and not result.flags.writeable:
+ # In a future version this will go away
+ if not readonly and array.flags._writeable_no_warn:
result.flags.writeable = True
+ result.flags._warn_on_write = True
return result
@@ -186,8 +186,6 @@ def _broadcast_shape(*args):
"""Returns the shape of the arrays that would result from broadcasting the
supplied arrays against each other.
"""
- if not args:
- return ()
# use the old-iterator because np.nditer does not handle size 0 arrays
# consistently
b = np.broadcast(*args[:32])
@@ -224,8 +222,15 @@ def broadcast_arrays(*args, **kwargs):
broadcasted : list of arrays
These arrays are views on the original arrays. They are typically
not contiguous. Furthermore, more than one element of a
- broadcasted array may refer to a single memory location. If you
- need to write to the arrays, make copies first.
+ broadcasted array may refer to a single memory location. If you need
+ to write to the arrays, make copies first. While you can set the
+ ``writable`` flag True, writing to a single output value may end up
+ changing more than one location in the output array.
+
+ .. deprecated:: 1.17
+ The output is currently marked so that if written to, a deprecation
+ warning will be emitted. A future version will set the
+ ``writable`` flag False so writing to it will raise an error.
Examples
--------
@@ -262,7 +267,5 @@ def broadcast_arrays(*args, **kwargs):
# Common case where nothing needs to be broadcasted.
return args
- # TODO: consider making the results of broadcast_arrays readonly to match
- # broadcast_to. This will require a deprecation cycle.
return [_broadcast_to(array, shape, subok=subok, readonly=False)
for array in args]
diff --git a/numpy/lib/tests/test_arraypad.py b/numpy/lib/tests/test_arraypad.py
index 6620db8df..b7630cdcd 100644
--- a/numpy/lib/tests/test_arraypad.py
+++ b/numpy/lib/tests/test_arraypad.py
@@ -2,18 +2,31 @@
"""
from __future__ import division, absolute_import, print_function
+from itertools import chain
import pytest
import numpy as np
-from numpy.testing import (assert_array_equal, assert_raises, assert_allclose,
- assert_equal)
-from numpy.lib import pad
+from numpy.testing import assert_array_equal, assert_allclose, assert_equal
from numpy.lib.arraypad import _as_pairs
-class TestAsPairs(object):
+_all_modes = {
+ 'constant': {'constant_values': 0},
+ 'edge': {},
+ 'linear_ramp': {'end_values': 0},
+ 'maximum': {'stat_length': None},
+ 'mean': {'stat_length': None},
+ 'median': {'stat_length': None},
+ 'minimum': {'stat_length': None},
+ 'reflect': {'reflect_type': 'even'},
+ 'symmetric': {'reflect_type': 'even'},
+ 'wrap': {},
+ 'empty': {}
+}
+
+class TestAsPairs(object):
def test_single_value(self):
"""Test casting for a single value."""
expected = np.array([[3, 3]] * 10)
@@ -97,52 +110,31 @@ class TestAsPairs(object):
class TestConditionalShortcuts(object):
- def test_zero_padding_shortcuts(self):
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_zero_padding_shortcuts(self, mode):
test = np.arange(120).reshape(4, 5, 6)
- pad_amt = [(0, 0) for axis in test.shape]
- modes = ['constant',
- 'edge',
- 'linear_ramp',
- 'maximum',
- 'mean',
- 'median',
- 'minimum',
- 'reflect',
- 'symmetric',
- 'wrap',
- ]
- for mode in modes:
- assert_array_equal(test, pad(test, pad_amt, mode=mode))
-
- def test_shallow_statistic_range(self):
+ pad_amt = [(0, 0) for _ in test.shape]
+ assert_array_equal(test, np.pad(test, pad_amt, mode=mode))
+
+ @pytest.mark.parametrize("mode", ['maximum', 'mean', 'median', 'minimum',])
+ def test_shallow_statistic_range(self, mode):
test = np.arange(120).reshape(4, 5, 6)
- pad_amt = [(1, 1) for axis in test.shape]
- modes = ['maximum',
- 'mean',
- 'median',
- 'minimum',
- ]
- for mode in modes:
- assert_array_equal(pad(test, pad_amt, mode='edge'),
- pad(test, pad_amt, mode=mode, stat_length=1))
-
- def test_clip_statistic_range(self):
+ pad_amt = [(1, 1) for _ in test.shape]
+ assert_array_equal(np.pad(test, pad_amt, mode='edge'),
+ np.pad(test, pad_amt, mode=mode, stat_length=1))
+
+ @pytest.mark.parametrize("mode", ['maximum', 'mean', 'median', 'minimum',])
+ def test_clip_statistic_range(self, mode):
test = np.arange(30).reshape(5, 6)
- pad_amt = [(3, 3) for axis in test.shape]
- modes = ['maximum',
- 'mean',
- 'median',
- 'minimum',
- ]
- for mode in modes:
- assert_array_equal(pad(test, pad_amt, mode=mode),
- pad(test, pad_amt, mode=mode, stat_length=30))
+ pad_amt = [(3, 3) for _ in test.shape]
+ assert_array_equal(np.pad(test, pad_amt, mode=mode),
+ np.pad(test, pad_amt, mode=mode, stat_length=30))
class TestStatistic(object):
def test_check_mean_stat_length(self):
a = np.arange(100).astype('f')
- a = pad(a, ((25, 20), ), 'mean', stat_length=((2, 3), ))
+ a = np.pad(a, ((25, 20), ), 'mean', stat_length=((2, 3), ))
b = np.array(
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
@@ -166,7 +158,7 @@ class TestStatistic(object):
def test_check_maximum_1(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'maximum')
+ a = np.pad(a, (25, 20), 'maximum')
b = np.array(
[99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
@@ -190,7 +182,7 @@ class TestStatistic(object):
def test_check_maximum_2(self):
a = np.arange(100) + 1
- a = pad(a, (25, 20), 'maximum')
+ a = np.pad(a, (25, 20), 'maximum')
b = np.array(
[100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
@@ -214,7 +206,7 @@ class TestStatistic(object):
def test_check_maximum_stat_length(self):
a = np.arange(100) + 1
- a = pad(a, (25, 20), 'maximum', stat_length=10)
+ a = np.pad(a, (25, 20), 'maximum', stat_length=10)
b = np.array(
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
@@ -238,7 +230,7 @@ class TestStatistic(object):
def test_check_minimum_1(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'minimum')
+ a = np.pad(a, (25, 20), 'minimum')
b = np.array(
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -262,7 +254,7 @@ class TestStatistic(object):
def test_check_minimum_2(self):
a = np.arange(100) + 2
- a = pad(a, (25, 20), 'minimum')
+ a = np.pad(a, (25, 20), 'minimum')
b = np.array(
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -286,7 +278,7 @@ class TestStatistic(object):
def test_check_minimum_stat_length(self):
a = np.arange(100) + 1
- a = pad(a, (25, 20), 'minimum', stat_length=10)
+ a = np.pad(a, (25, 20), 'minimum', stat_length=10)
b = np.array(
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -310,7 +302,7 @@ class TestStatistic(object):
def test_check_median(self):
a = np.arange(100).astype('f')
- a = pad(a, (25, 20), 'median')
+ a = np.pad(a, (25, 20), 'median')
b = np.array(
[49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5,
49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5,
@@ -334,7 +326,7 @@ class TestStatistic(object):
def test_check_median_01(self):
a = np.array([[3, 1, 4], [4, 5, 9], [9, 8, 2]])
- a = pad(a, 1, 'median')
+ a = np.pad(a, 1, 'median')
b = np.array(
[[4, 4, 5, 4, 4],
@@ -348,7 +340,7 @@ class TestStatistic(object):
def test_check_median_02(self):
a = np.array([[3, 1, 4], [4, 5, 9], [9, 8, 2]])
- a = pad(a.T, 1, 'median').T
+ a = np.pad(a.T, 1, 'median').T
b = np.array(
[[5, 4, 5, 4, 5],
@@ -364,7 +356,7 @@ class TestStatistic(object):
a = np.arange(100).astype('f')
a[1] = 2.
a[97] = 96.
- a = pad(a, (25, 20), 'median', stat_length=(3, 5))
+ a = np.pad(a, (25, 20), 'median', stat_length=(3, 5))
b = np.array(
[ 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
@@ -388,7 +380,7 @@ class TestStatistic(object):
def test_check_mean_shape_one(self):
a = [[4, 5, 6]]
- a = pad(a, (5, 7), 'mean', stat_length=2)
+ a = np.pad(a, (5, 7), 'mean', stat_length=2)
b = np.array(
[[4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6],
[4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6],
@@ -410,7 +402,7 @@ class TestStatistic(object):
def test_check_mean_2(self):
a = np.arange(100).astype('f')
- a = pad(a, (25, 20), 'mean')
+ a = np.pad(a, (25, 20), 'mean')
b = np.array(
[49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5,
49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5, 49.5,
@@ -433,7 +425,7 @@ class TestStatistic(object):
assert_array_equal(a, b)
@pytest.mark.parametrize("mode", [
- pytest.param("mean", marks=pytest.mark.xfail(reason="gh-11216")),
+ "mean",
"median",
"minimum",
"maximum"
@@ -446,11 +438,42 @@ class TestStatistic(object):
a = np.pad(a, (1, 1), mode)
assert_equal(a[0], a[-1])
+ @pytest.mark.parametrize("mode", ["mean", "median", "minimum", "maximum"])
+ @pytest.mark.parametrize(
+ "stat_length", [-2, (-2,), (3, -1), ((5, 2), (-2, 3)), ((-4,), (2,))]
+ )
+ def test_check_negative_stat_length(self, mode, stat_length):
+ arr = np.arange(30).reshape((6, 5))
+ match = "index can't contain negative values"
+ with pytest.raises(ValueError, match=match):
+ np.pad(arr, 2, mode, stat_length=stat_length)
+
+ def test_simple_stat_length(self):
+ a = np.arange(30)
+ a = np.reshape(a, (6, 5))
+ a = np.pad(a, ((2, 3), (3, 2)), mode='mean', stat_length=(3,))
+ b = np.array(
+ [[6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
+ [6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
+
+ [1, 1, 1, 0, 1, 2, 3, 4, 3, 3],
+ [6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
+ [11, 11, 11, 10, 11, 12, 13, 14, 13, 13],
+ [16, 16, 16, 15, 16, 17, 18, 19, 18, 18],
+ [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
+ [26, 26, 26, 25, 26, 27, 28, 29, 28, 28],
+
+ [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
+ [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
+ [21, 21, 21, 20, 21, 22, 23, 24, 23, 23]]
+ )
+ assert_array_equal(a, b)
+
class TestConstant(object):
def test_check_constant(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'constant', constant_values=(10, 20))
+ a = np.pad(a, (25, 20), 'constant', constant_values=(10, 20))
b = np.array(
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
@@ -474,7 +497,7 @@ class TestConstant(object):
def test_check_constant_zeros(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'constant')
+ a = np.pad(a, (25, 20), 'constant')
b = np.array(
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -500,7 +523,7 @@ class TestConstant(object):
# If input array is int, but constant_values are float, the dtype of
# the array to be padded is kept
arr = np.arange(30).reshape(5, 6)
- test = pad(arr, (1, 2), mode='constant',
+ test = np.pad(arr, (1, 2), mode='constant',
constant_values=1.1)
expected = np.array(
[[ 1, 1, 1, 1, 1, 1, 1, 1, 1],
@@ -521,7 +544,7 @@ class TestConstant(object):
# the array to be padded is kept - here retaining the float constants
arr = np.arange(30).reshape(5, 6)
arr_float = arr.astype(np.float64)
- test = pad(arr_float, ((1, 2), (1, 2)), mode='constant',
+ test = np.pad(arr_float, ((1, 2), (1, 2)), mode='constant',
constant_values=1.1)
expected = np.array(
[[ 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1],
@@ -539,7 +562,7 @@ class TestConstant(object):
def test_check_constant_float3(self):
a = np.arange(100, dtype=float)
- a = pad(a, (25, 20), 'constant', constant_values=(-1.1, -1.2))
+ a = np.pad(a, (25, 20), 'constant', constant_values=(-1.1, -1.2))
b = np.array(
[-1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1,
-1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1, -1.1,
@@ -563,7 +586,7 @@ class TestConstant(object):
def test_check_constant_odd_pad_amount(self):
arr = np.arange(30).reshape(5, 6)
- test = pad(arr, ((1,), (2,)), mode='constant',
+ test = np.pad(arr, ((1,), (2,)), mode='constant',
constant_values=3)
expected = np.array(
[[ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
@@ -620,11 +643,16 @@ class TestConstant(object):
assert_array_equal(arr, expected)
+ def test_pad_empty_dimension(self):
+ arr = np.zeros((3, 0, 2))
+ result = np.pad(arr, [(0,), (2,), (1,)], mode="constant")
+ assert result.shape == (3, 4, 4)
+
class TestLinearRamp(object):
def test_check_simple(self):
a = np.arange(100).astype('f')
- a = pad(a, (25, 20), 'linear_ramp', end_values=(4, 5))
+ a = np.pad(a, (25, 20), 'linear_ramp', end_values=(4, 5))
b = np.array(
[4.00, 3.84, 3.68, 3.52, 3.36, 3.20, 3.04, 2.88, 2.72, 2.56,
2.40, 2.24, 2.08, 1.92, 1.76, 1.60, 1.44, 1.28, 1.12, 0.96,
@@ -648,7 +676,7 @@ class TestLinearRamp(object):
def test_check_2d(self):
arr = np.arange(20).reshape(4, 5).astype(np.float64)
- test = pad(arr, (2, 2), mode='linear_ramp', end_values=(0, 0))
+ test = np.pad(arr, (2, 2), mode='linear_ramp', end_values=(0, 0))
expected = np.array(
[[0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0.5, 1., 1.5, 2., 1., 0.],
@@ -679,35 +707,19 @@ class TestLinearRamp(object):
])
assert_equal(actual, expected)
- @pytest.mark.parametrize("dtype", (
- np.sctypes["uint"]
- + np.sctypes["int"]
- + np.sctypes["float"]
- + np.sctypes["complex"]
- ))
- def test_negative_difference(self, dtype):
- """
- Check correct behavior of unsigned dtypes if there is a negative
- difference between the edge to pad and `end_values`. Check both cases
- to be independent of implementation. Test behavior for all other dtypes
- in case dtype casting interferes with complex dtypes. See gh-14191.
- """
- x = np.array([3], dtype=dtype)
- result = np.pad(x, 3, mode="linear_ramp", end_values=0)
- expected = np.array([0, 1, 2, 3, 2, 1, 0], dtype=dtype)
- assert_equal(result, expected)
-
- x = np.array([0], dtype=dtype)
- result = np.pad(x, 3, mode="linear_ramp", end_values=3)
- expected = np.array([3, 2, 1, 0, 1, 2, 3], dtype=dtype)
- assert_equal(result, expected)
-
+ def test_end_values(self):
+ """Ensure that end values are exact."""
+ a = np.pad(np.ones(10).reshape(2, 5), (223, 123), mode="linear_ramp")
+ assert_equal(a[:, 0], 0.)
+ assert_equal(a[:, -1], 0.)
+ assert_equal(a[0, :], 0.)
+ assert_equal(a[-1, :], 0.)
class TestReflect(object):
def test_check_simple(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'reflect')
+ a = np.pad(a, (25, 20), 'reflect')
b = np.array(
[25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
@@ -731,7 +743,7 @@ class TestReflect(object):
def test_check_odd_method(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'reflect', reflect_type='odd')
+ a = np.pad(a, (25, 20), 'reflect', reflect_type='odd')
b = np.array(
[-25, -24, -23, -22, -21, -20, -19, -18, -17, -16,
-15, -14, -13, -12, -11, -10, -9, -8, -7, -6,
@@ -755,7 +767,7 @@ class TestReflect(object):
def test_check_large_pad(self):
a = [[4, 5, 6], [6, 7, 8]]
- a = pad(a, (5, 7), 'reflect')
+ a = np.pad(a, (5, 7), 'reflect')
b = np.array(
[[7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7, 8, 7, 6, 7],
[5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5],
@@ -778,7 +790,7 @@ class TestReflect(object):
def test_check_shape(self):
a = [[4, 5, 6]]
- a = pad(a, (5, 7), 'reflect')
+ a = np.pad(a, (5, 7), 'reflect')
b = np.array(
[[5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5],
[5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5, 6, 5, 4, 5],
@@ -799,30 +811,49 @@ class TestReflect(object):
assert_array_equal(a, b)
def test_check_01(self):
- a = pad([1, 2, 3], 2, 'reflect')
+ a = np.pad([1, 2, 3], 2, 'reflect')
b = np.array([3, 2, 1, 2, 3, 2, 1])
assert_array_equal(a, b)
def test_check_02(self):
- a = pad([1, 2, 3], 3, 'reflect')
+ a = np.pad([1, 2, 3], 3, 'reflect')
b = np.array([2, 3, 2, 1, 2, 3, 2, 1, 2])
assert_array_equal(a, b)
def test_check_03(self):
- a = pad([1, 2, 3], 4, 'reflect')
+ a = np.pad([1, 2, 3], 4, 'reflect')
b = np.array([1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3])
assert_array_equal(a, b)
- def test_check_padding_an_empty_array(self):
- a = pad(np.zeros((0, 3)), ((0,), (1,)), mode='reflect')
- b = np.zeros((0, 5))
- assert_array_equal(a, b)
+
+class TestEmptyArray(object):
+ """Check how padding behaves on arrays with an empty dimension."""
+
+ @pytest.mark.parametrize(
+ # Keep parametrization ordered, otherwise pytest-xdist might believe
+ # that different tests were collected during parallelization
+ "mode", sorted(_all_modes.keys() - {"constant", "empty"})
+ )
+ def test_pad_empty_dimension(self, mode):
+ match = ("can't extend empty axis 0 using modes other than 'constant' "
+ "or 'empty'")
+ with pytest.raises(ValueError, match=match):
+ np.pad([], 4, mode=mode)
+ with pytest.raises(ValueError, match=match):
+ np.pad(np.ndarray(0), 4, mode=mode)
+ with pytest.raises(ValueError, match=match):
+ np.pad(np.zeros((0, 3)), ((1,), (0,)), mode=mode)
+
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_pad_non_empty_dimension(self, mode):
+ result = np.pad(np.ones((2, 0, 2)), ((3,), (0,), (1,)), mode=mode)
+ assert result.shape == (8, 0, 4)
class TestSymmetric(object):
def test_check_simple(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'symmetric')
+ a = np.pad(a, (25, 20), 'symmetric')
b = np.array(
[24, 23, 22, 21, 20, 19, 18, 17, 16, 15,
14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
@@ -846,7 +877,7 @@ class TestSymmetric(object):
def test_check_odd_method(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'symmetric', reflect_type='odd')
+ a = np.pad(a, (25, 20), 'symmetric', reflect_type='odd')
b = np.array(
[-24, -23, -22, -21, -20, -19, -18, -17, -16, -15,
-14, -13, -12, -11, -10, -9, -8, -7, -6, -5,
@@ -870,7 +901,7 @@ class TestSymmetric(object):
def test_check_large_pad(self):
a = [[4, 5, 6], [6, 7, 8]]
- a = pad(a, (5, 7), 'symmetric')
+ a = np.pad(a, (5, 7), 'symmetric')
b = np.array(
[[5, 6, 6, 5, 4, 4, 5, 6, 6, 5, 4, 4, 5, 6, 6],
[5, 6, 6, 5, 4, 4, 5, 6, 6, 5, 4, 4, 5, 6, 6],
@@ -894,7 +925,7 @@ class TestSymmetric(object):
def test_check_large_pad_odd(self):
a = [[4, 5, 6], [6, 7, 8]]
- a = pad(a, (5, 7), 'symmetric', reflect_type='odd')
+ a = np.pad(a, (5, 7), 'symmetric', reflect_type='odd')
b = np.array(
[[-3, -2, -2, -1, 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6],
[-3, -2, -2, -1, 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6],
@@ -917,7 +948,7 @@ class TestSymmetric(object):
def test_check_shape(self):
a = [[4, 5, 6]]
- a = pad(a, (5, 7), 'symmetric')
+ a = np.pad(a, (5, 7), 'symmetric')
b = np.array(
[[5, 6, 6, 5, 4, 4, 5, 6, 6, 5, 4, 4, 5, 6, 6],
[5, 6, 6, 5, 4, 4, 5, 6, 6, 5, 4, 4, 5, 6, 6],
@@ -938,17 +969,17 @@ class TestSymmetric(object):
assert_array_equal(a, b)
def test_check_01(self):
- a = pad([1, 2, 3], 2, 'symmetric')
+ a = np.pad([1, 2, 3], 2, 'symmetric')
b = np.array([2, 1, 1, 2, 3, 3, 2])
assert_array_equal(a, b)
def test_check_02(self):
- a = pad([1, 2, 3], 3, 'symmetric')
+ a = np.pad([1, 2, 3], 3, 'symmetric')
b = np.array([3, 2, 1, 1, 2, 3, 3, 2, 1])
assert_array_equal(a, b)
def test_check_03(self):
- a = pad([1, 2, 3], 6, 'symmetric')
+ a = np.pad([1, 2, 3], 6, 'symmetric')
b = np.array([1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1, 1, 2, 3])
assert_array_equal(a, b)
@@ -956,7 +987,7 @@ class TestSymmetric(object):
class TestWrap(object):
def test_check_simple(self):
a = np.arange(100)
- a = pad(a, (25, 20), 'wrap')
+ a = np.pad(a, (25, 20), 'wrap')
b = np.array(
[75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
@@ -981,7 +1012,7 @@ class TestWrap(object):
def test_check_large_pad(self):
a = np.arange(12)
a = np.reshape(a, (3, 4))
- a = pad(a, (10, 12), 'wrap')
+ a = np.pad(a, (10, 12), 'wrap')
b = np.array(
[[10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10,
11, 8, 9, 10, 11, 8, 9, 10, 11],
@@ -1039,12 +1070,12 @@ class TestWrap(object):
assert_array_equal(a, b)
def test_check_01(self):
- a = pad([1, 2, 3], 3, 'wrap')
+ a = np.pad([1, 2, 3], 3, 'wrap')
b = np.array([1, 2, 3, 1, 2, 3, 1, 2, 3])
assert_array_equal(a, b)
def test_check_02(self):
- a = pad([1, 2, 3], 4, 'wrap')
+ a = np.pad([1, 2, 3], 4, 'wrap')
b = np.array([3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1])
assert_array_equal(a, b)
@@ -1053,35 +1084,25 @@ class TestWrap(object):
b = np.pad(a, (0, 5), mode="wrap")
assert_array_equal(a, b[:-5, :-5])
+ def test_repeated_wrapping(self):
+ """
+ Check wrapping on each side individually if the wrapped area is longer
+ than the original array.
+ """
+ a = np.arange(5)
+ b = np.pad(a, (12, 0), mode="wrap")
+ assert_array_equal(np.r_[a, a, a, a][3:], b)
-class TestStatLen(object):
- def test_check_simple(self):
- a = np.arange(30)
- a = np.reshape(a, (6, 5))
- a = pad(a, ((2, 3), (3, 2)), mode='mean', stat_length=(3,))
- b = np.array(
- [[6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
- [6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
-
- [1, 1, 1, 0, 1, 2, 3, 4, 3, 3],
- [6, 6, 6, 5, 6, 7, 8, 9, 8, 8],
- [11, 11, 11, 10, 11, 12, 13, 14, 13, 13],
- [16, 16, 16, 15, 16, 17, 18, 19, 18, 18],
- [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
- [26, 26, 26, 25, 26, 27, 28, 29, 28, 28],
-
- [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
- [21, 21, 21, 20, 21, 22, 23, 24, 23, 23],
- [21, 21, 21, 20, 21, 22, 23, 24, 23, 23]]
- )
- assert_array_equal(a, b)
+ a = np.arange(5)
+ b = np.pad(a, (0, 12), mode="wrap")
+ assert_array_equal(np.r_[a, a, a, a][:-3], b)
class TestEdge(object):
def test_check_simple(self):
a = np.arange(12)
a = np.reshape(a, (4, 3))
- a = pad(a, ((2, 3), (3, 2)), 'edge')
+ a = np.pad(a, ((2, 3), (3, 2)), 'edge')
b = np.array(
[[0, 0, 0, 0, 1, 2, 2, 2],
[0, 0, 0, 0, 1, 2, 2, 2],
@@ -1101,56 +1122,123 @@ class TestEdge(object):
# Check a pad_width of the form ((1, 2),).
# Regression test for issue gh-7808.
a = np.array([1, 2, 3])
- padded = pad(a, ((1, 2),), 'edge')
+ padded = np.pad(a, ((1, 2),), 'edge')
expected = np.array([1, 1, 2, 3, 3, 3])
assert_array_equal(padded, expected)
a = np.array([[1, 2, 3], [4, 5, 6]])
- padded = pad(a, ((1, 2),), 'edge')
- expected = pad(a, ((1, 2), (1, 2)), 'edge')
+ padded = np.pad(a, ((1, 2),), 'edge')
+ expected = np.pad(a, ((1, 2), (1, 2)), 'edge')
assert_array_equal(padded, expected)
a = np.arange(24).reshape(2, 3, 4)
- padded = pad(a, ((1, 2),), 'edge')
- expected = pad(a, ((1, 2), (1, 2), (1, 2)), 'edge')
+ padded = np.pad(a, ((1, 2),), 'edge')
+ expected = np.pad(a, ((1, 2), (1, 2), (1, 2)), 'edge')
assert_array_equal(padded, expected)
-class TestZeroPadWidth(object):
- def test_zero_pad_width(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- for pad_width in (0, (0, 0), ((0, 0), (0, 0))):
- assert_array_equal(arr, pad(arr, pad_width, mode='constant'))
+class TestEmpty(object):
+ def test_simple(self):
+ arr = np.arange(24).reshape(4, 6)
+ result = np.pad(arr, [(2, 3), (3, 1)], mode="empty")
+ assert result.shape == (9, 10)
+ assert_equal(arr, result[2:-3, 3:-1])
+ def test_pad_empty_dimension(self):
+ arr = np.zeros((3, 0, 2))
+ result = np.pad(arr, [(0,), (2,), (1,)], mode="empty")
+ assert result.shape == (3, 4, 4)
-class TestLegacyVectorFunction(object):
- def test_legacy_vector_functionality(self):
- def _padwithtens(vector, pad_width, iaxis, kwargs):
- vector[:pad_width[0]] = 10
- vector[-pad_width[1]:] = 10
- return vector
- a = np.arange(6).reshape(2, 3)
- a = pad(a, 2, _padwithtens)
- b = np.array(
- [[10, 10, 10, 10, 10, 10, 10],
- [10, 10, 10, 10, 10, 10, 10],
+def test_legacy_vector_functionality():
+ def _padwithtens(vector, pad_width, iaxis, kwargs):
+ vector[:pad_width[0]] = 10
+ vector[-pad_width[1]:] = 10
- [10, 10, 0, 1, 2, 10, 10],
- [10, 10, 3, 4, 5, 10, 10],
+ a = np.arange(6).reshape(2, 3)
+ a = np.pad(a, 2, _padwithtens)
+ b = np.array(
+ [[10, 10, 10, 10, 10, 10, 10],
+ [10, 10, 10, 10, 10, 10, 10],
- [10, 10, 10, 10, 10, 10, 10],
- [10, 10, 10, 10, 10, 10, 10]]
- )
- assert_array_equal(a, b)
+ [10, 10, 0, 1, 2, 10, 10],
+ [10, 10, 3, 4, 5, 10, 10],
+
+ [10, 10, 10, 10, 10, 10, 10],
+ [10, 10, 10, 10, 10, 10, 10]]
+ )
+ assert_array_equal(a, b)
-class TestNdarrayPadWidth(object):
- def test_check_simple(self):
+def test_unicode_mode():
+ a = np.pad([1], 2, mode=u'constant')
+ b = np.array([0, 0, 1, 0, 0])
+ assert_array_equal(a, b)
+
+
+@pytest.mark.parametrize("mode", ["edge", "symmetric", "reflect", "wrap"])
+def test_object_input(mode):
+ # Regression test for issue gh-11395.
+ a = np.full((4, 3), fill_value=None)
+ pad_amt = ((2, 3), (3, 2))
+ b = np.full((9, 8), fill_value=None)
+ assert_array_equal(np.pad(a, pad_amt, mode=mode), b)
+
+
+class TestPadWidth(object):
+ @pytest.mark.parametrize("pad_width", [
+ (4, 5, 6, 7),
+ ((1,), (2,), (3,)),
+ ((1, 2), (3, 4), (5, 6)),
+ ((3, 4, 5), (0, 1, 2)),
+ ])
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_misshaped_pad_width(self, pad_width, mode):
+ arr = np.arange(30).reshape((6, 5))
+ match = "operands could not be broadcast together"
+ with pytest.raises(ValueError, match=match):
+ np.pad(arr, pad_width, mode)
+
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_misshaped_pad_width_2(self, mode):
+ arr = np.arange(30).reshape((6, 5))
+ match = ("input operand has more dimensions than allowed by the axis "
+ "remapping")
+ with pytest.raises(ValueError, match=match):
+ np.pad(arr, (((3,), (4,), (5,)), ((0,), (1,), (2,))), mode)
+
+ @pytest.mark.parametrize(
+ "pad_width", [-2, (-2,), (3, -1), ((5, 2), (-2, 3)), ((-4,), (2,))])
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_negative_pad_width(self, pad_width, mode):
+ arr = np.arange(30).reshape((6, 5))
+ match = "index can't contain negative values"
+ with pytest.raises(ValueError, match=match):
+ np.pad(arr, pad_width, mode)
+
+ @pytest.mark.parametrize("pad_width", [
+ "3",
+ "word",
+ None,
+ object(),
+ 3.4,
+ ((2, 3, 4), (3, 2)), # dtype=object (tuple)
+ complex(1, -1),
+ ((-2.1, 3), (3, 2)),
+ ])
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_bad_type(self, pad_width, mode):
+ arr = np.arange(30).reshape((6, 5))
+ match = "`pad_width` must be of integral type."
+ with pytest.raises(TypeError, match=match):
+ np.pad(arr, pad_width, mode)
+ with pytest.raises(TypeError, match=match):
+ np.pad(arr, np.array(pad_width), mode)
+
+ def test_pad_width_as_ndarray(self):
a = np.arange(12)
a = np.reshape(a, (4, 3))
- a = pad(a, np.array(((2, 3), (3, 2))), 'edge')
+ a = np.pad(a, np.array(((2, 3), (3, 2))), 'edge')
b = np.array(
[[0, 0, 0, 0, 1, 2, 2, 2],
[0, 0, 0, 0, 1, 2, 2, 2],
@@ -1166,121 +1254,68 @@ class TestNdarrayPadWidth(object):
)
assert_array_equal(a, b)
-
-class TestUnicodeInput(object):
- def test_unicode_mode(self):
- constant_mode = u'constant'
- a = np.pad([1], 2, mode=constant_mode)
- b = np.array([0, 0, 1, 0, 0])
- assert_array_equal(a, b)
-
-
-class TestObjectInput(object):
- def test_object_input(self):
- # Regression test for issue gh-11395.
- a = np.full((4, 3), None)
- pad_amt = ((2, 3), (3, 2))
- b = np.full((9, 8), None)
- modes = ['edge',
- 'symmetric',
- 'reflect',
- 'wrap',
- ]
- for mode in modes:
- assert_array_equal(pad(a, pad_amt, mode=mode), b)
-
-
-class TestValueError1(object):
- def test_check_simple(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- kwargs = dict(mode='mean', stat_length=(3, ))
- assert_raises(ValueError, pad, arr, ((2, 3), (3, 2), (4, 5)),
- **kwargs)
-
- def test_check_negative_stat_length(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- kwargs = dict(mode='mean', stat_length=(-3, ))
- assert_raises(ValueError, pad, arr, ((2, 3), (3, 2)),
- **kwargs)
-
- def test_check_negative_pad_width(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- kwargs = dict(mode='mean', stat_length=(3, ))
- assert_raises(ValueError, pad, arr, ((-2, 3), (3, 2)),
- **kwargs)
-
- def test_check_empty_array(self):
- assert_raises(ValueError, pad, [], 4, mode='reflect')
- assert_raises(ValueError, pad, np.ndarray(0), 4, mode='reflect')
- assert_raises(ValueError, pad, np.zeros((0, 3)), ((1,), (0,)),
- mode='reflect')
-
-
-class TestValueError2(object):
- def test_check_negative_pad_amount(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- kwargs = dict(mode='mean', stat_length=(3, ))
- assert_raises(ValueError, pad, arr, ((-2, 3), (3, 2)),
- **kwargs)
-
-
-class TestValueError3(object):
- def test_check_kwarg_not_allowed(self):
- arr = np.arange(30).reshape(5, 6)
- assert_raises(ValueError, pad, arr, 4, mode='mean',
- reflect_type='odd')
-
- def test_mode_not_set(self):
- arr = np.arange(30).reshape(5, 6)
- assert_raises(TypeError, pad, arr, 4)
-
- def test_malformed_pad_amount(self):
- arr = np.arange(30).reshape(5, 6)
- assert_raises(ValueError, pad, arr, (4, 5, 6, 7), mode='constant')
-
- def test_malformed_pad_amount2(self):
- arr = np.arange(30).reshape(5, 6)
- assert_raises(ValueError, pad, arr, ((3, 4, 5), (0, 1, 2)),
- mode='constant')
-
- def test_pad_too_many_axes(self):
- arr = np.arange(30).reshape(5, 6)
-
- # Attempt to pad using a 3D array equivalent
- bad_shape = (((3,), (4,), (5,)), ((0,), (1,), (2,)))
- assert_raises(ValueError, pad, arr, bad_shape,
- mode='constant')
-
-
-class TestTypeError1(object):
- def test_float(self):
- arr = np.arange(30)
- assert_raises(TypeError, pad, arr, ((-2.1, 3), (3, 2)))
- assert_raises(TypeError, pad, arr, np.array(((-2.1, 3), (3, 2))))
-
- def test_str(self):
- arr = np.arange(30)
- assert_raises(TypeError, pad, arr, 'foo')
- assert_raises(TypeError, pad, arr, np.array('foo'))
-
- def test_object(self):
- class FooBar(object):
- pass
- arr = np.arange(30)
- assert_raises(TypeError, pad, arr, FooBar())
-
- def test_complex(self):
- arr = np.arange(30)
- assert_raises(TypeError, pad, arr, complex(1, -1))
- assert_raises(TypeError, pad, arr, np.array(complex(1, -1)))
-
- def test_check_wrong_pad_amount(self):
- arr = np.arange(30)
- arr = np.reshape(arr, (6, 5))
- kwargs = dict(mode='mean', stat_length=(3, ))
- assert_raises(TypeError, pad, arr, ((2, 3, 4), (3, 2)),
- **kwargs)
+ @pytest.mark.parametrize("pad_width", [0, (0, 0), ((0, 0), (0, 0))])
+ @pytest.mark.parametrize("mode", _all_modes.keys())
+ def test_zero_pad_width(self, pad_width, mode):
+ arr = np.arange(30).reshape(6, 5)
+ assert_array_equal(arr, np.pad(arr, pad_width, mode=mode))
+
+
+@pytest.mark.parametrize("mode", _all_modes.keys())
+def test_kwargs(mode):
+ """Test behavior of pad's kwargs for the given mode."""
+ allowed = _all_modes[mode]
+ not_allowed = {}
+ for kwargs in _all_modes.values():
+ if kwargs != allowed:
+ not_allowed.update(kwargs)
+ # Test if allowed keyword arguments pass
+ np.pad([1, 2, 3], 1, mode, **allowed)
+ # Test if prohibited keyword arguments of other modes raise an error
+ for key, value in not_allowed.items():
+ match = "unsupported keyword arguments for mode '{}'".format(mode)
+ with pytest.raises(ValueError, match=match):
+ np.pad([1, 2, 3], 1, mode, **{key: value})
+
+
+def test_constant_zero_default():
+ arr = np.array([1, 1])
+ assert_array_equal(np.pad(arr, 2), [0, 0, 1, 1, 0, 0])
+
+
+@pytest.mark.parametrize("mode", [1, "const", object(), None, True, False])
+def test_unsupported_mode(mode):
+ match= "mode '{}' is not supported".format(mode)
+ with pytest.raises(ValueError, match=match):
+ np.pad([1, 2, 3], 4, mode=mode)
+
+
+@pytest.mark.parametrize("mode", _all_modes.keys())
+def test_non_contiguous_array(mode):
+ arr = np.arange(24).reshape(4, 6)[::2, ::2]
+ result = np.pad(arr, (2, 3), mode)
+ assert result.shape == (7, 8)
+ assert_equal(result[2:-3, 2:-3], arr)
+
+
+@pytest.mark.parametrize("mode", _all_modes.keys())
+def test_memory_layout_persistence(mode):
+ """Test if C and F order is preserved for all pad modes."""
+ x = np.ones((5, 10), order='C')
+ assert np.pad(x, 5, mode).flags["C_CONTIGUOUS"]
+ x = np.ones((5, 10), order='F')
+ assert np.pad(x, 5, mode).flags["F_CONTIGUOUS"]
+
+
+@pytest.mark.parametrize("dtype", chain(
+ # Skip "other" dtypes as they are not supported by all modes
+ np.sctypes["int"],
+ np.sctypes["uint"],
+ np.sctypes["float"],
+ np.sctypes["complex"]
+))
+@pytest.mark.parametrize("mode", _all_modes.keys())
+def test_dtype_persistence(dtype, mode):
+ arr = np.zeros((3, 2, 1), dtype=dtype)
+ result = np.pad(arr, 1, mode=mode)
+ assert result.dtype == dtype
diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py
index 4a3fbdf57..062c21725 100644
--- a/numpy/lib/tests/test_format.py
+++ b/numpy/lib/tests/test_format.py
@@ -287,6 +287,7 @@ from io import BytesIO
import numpy as np
from numpy.testing import (
assert_, assert_array_equal, assert_raises, assert_raises_regex,
+ assert_warns
)
from numpy.lib import format
@@ -938,3 +939,27 @@ def test_empty_npz():
fname = os.path.join(tempdir, "nothing.npz")
np.savez(fname)
np.load(fname)
+
+
+def test_unicode_field_names():
+ # gh-7391
+ arr = np.array([
+ (1, 3),
+ (1, 2),
+ (1, 3),
+ (1, 2)
+ ], dtype=[
+ ('int', int),
+ (u'\N{CJK UNIFIED IDEOGRAPH-6574}\N{CJK UNIFIED IDEOGRAPH-5F62}', int)
+ ])
+ fname = os.path.join(tempdir, "unicode.npy")
+ with open(fname, 'wb') as f:
+ format.write_array(f, arr, version=(3, 0))
+ with open(fname, 'rb') as f:
+ arr2 = format.read_array(f)
+ assert_array_equal(arr, arr2)
+
+ # notifies the user that 3.0 is selected
+ with open(fname, 'wb') as f:
+ with assert_warns(UserWarning):
+ format.write_array(f, arr, version=None)
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 088ca2bae..3061d3a84 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -4,6 +4,8 @@ import operator
import warnings
import sys
import decimal
+import types
+from fractions import Fraction
import pytest
import numpy as np
@@ -24,6 +26,7 @@ from numpy.lib import (
from numpy.compat import long
+PY2 = sys.version_info[0] == 2
def get_mat(n):
data = np.arange(n)
@@ -31,6 +34,17 @@ def get_mat(n):
return data
+def _make_complex(real, imag):
+ """
+ Like real + 1j * imag, but behaves as expected when imag contains non-finite
+ values
+ """
+ ret = np.zeros(np.broadcast(real, imag).shape, np.complex_)
+ ret.real = real
+ ret.imag = imag
+ return ret
+
+
class TestRot90(object):
def test_basic(self):
assert_raises(ValueError, rot90, np.ones(4))
@@ -353,9 +367,9 @@ class TestAverage(object):
assert_equal(type(np.average(a, weights=w)), subclass)
def test_upcasting(self):
- types = [('i4', 'i4', 'f8'), ('i4', 'f4', 'f8'), ('f4', 'i4', 'f8'),
+ typs = [('i4', 'i4', 'f8'), ('i4', 'f4', 'f8'), ('f4', 'i4', 'f8'),
('f4', 'f4', 'f4'), ('f4', 'f8', 'f8')]
- for at, wt, rt in types:
+ for at, wt, rt in typs:
a = np.array([[1,2],[3,4]], dtype=at)
w = np.array([[1,2],[3,4]], dtype=wt)
assert_equal(np.average(a, weights=w).dtype, np.dtype(rt))
@@ -682,6 +696,9 @@ class TestDiff(object):
assert_raises(np.AxisError, diff, x, axis=3)
assert_raises(np.AxisError, diff, x, axis=-4)
+ x = np.array(1.11111111111, np.float64)
+ assert_raises(ValueError, diff, x)
+
def test_nd(self):
x = 20 * rand(10, 20, 30)
out1 = x[:, :, 1:] - x[:, :, :-1]
@@ -931,7 +948,7 @@ class TestGradient(object):
assert_equal(type(out), type(x))
# And make sure that the output and input don't have aliased mask
# arrays
- assert_(x.mask is not out.mask)
+ assert_(x._mask is not out._mask)
# Also check that edge_order=2 doesn't alter the original mask
x2 = np.ma.arange(5)
x2[2] = np.ma.masked
@@ -1498,6 +1515,49 @@ class TestVectorize(object):
f(x)
+class TestLeaks(object):
+ class A(object):
+ iters = 20
+
+ def bound(self, *args):
+ return 0
+
+ @staticmethod
+ def unbound(*args):
+ return 0
+
+ @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
+ @pytest.mark.parametrize('name, incr', [
+ ('bound', A.iters),
+ ('unbound', 0),
+ ])
+ def test_frompyfunc_leaks(self, name, incr):
+ # exposed in gh-11867 as np.vectorized, but the problem stems from
+ # frompyfunc.
+ # class.attribute = np.frompyfunc(<method>) creates a
+ # reference cycle if <method> is a bound class method. It requires a
+ # gc collection cycle to break the cycle (on CPython 3)
+ import gc
+ A_func = getattr(self.A, name)
+ gc.disable()
+ try:
+ refcount = sys.getrefcount(A_func)
+ for i in range(self.A.iters):
+ a = self.A()
+ a.f = np.frompyfunc(getattr(a, name), 1, 1)
+ out = a.f(np.arange(10))
+ a = None
+ if PY2:
+ assert_equal(sys.getrefcount(A_func), refcount)
+ else:
+ # A.func is part of a reference cycle if incr is non-zero
+ assert_equal(sys.getrefcount(A_func), refcount + incr)
+ for i in range(5):
+ gc.collect()
+ assert_equal(sys.getrefcount(A_func), refcount)
+ finally:
+ gc.enable()
+
class TestDigitize(object):
def test_forward(self):
@@ -1924,9 +1984,9 @@ class Test_I0(object):
np.array(1.0634833707413234))
A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549])
- assert_almost_equal(
- i0(A),
- np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049]))
+ expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049])
+ assert_almost_equal(i0(A), expected)
+ assert_almost_equal(i0(-A), expected)
B = np.array([[0.827002, 0.99959078],
[0.89694769, 0.39298162],
@@ -1940,6 +2000,26 @@ class Test_I0(object):
[1.03633899, 1.00067775],
[1.03352052, 1.13557954],
[1.05884290, 1.06432317]]))
+ # Regression test for gh-11205
+ i0_0 = np.i0([0.])
+ assert_equal(i0_0.shape, (1,))
+ assert_array_equal(np.i0([0.]), np.array([1.]))
+
+ def test_non_array(self):
+ a = np.arange(4)
+
+ class array_like:
+ __array_interface__ = a.__array_interface__
+
+ def __array_wrap__(self, arr):
+ return self
+
+ # E.g. pandas series survive ufunc calls through array-wrap:
+ assert isinstance(np.abs(array_like()), array_like)
+ exp = np.i0(a)
+ res = np.i0(array_like())
+
+ assert_array_equal(exp, res)
class TestKaiser(object):
@@ -2309,7 +2389,7 @@ class TestInterp(object):
x0 = np.nan
assert_almost_equal(np.interp(x0, x, y), x0)
- def test_non_finite_behavior(self):
+ def test_non_finite_behavior_exact_x(self):
x = [1, 2, 2.5, 3, 4]
xp = [1, 2, 3, 4]
fp = [1, 2, np.inf, 4]
@@ -2317,6 +2397,64 @@ class TestInterp(object):
fp = [1, 2, np.nan, 4]
assert_almost_equal(np.interp(x, xp, fp), [1, 2, np.nan, np.nan, 4])
+ @pytest.fixture(params=[
+ lambda x: np.float_(x),
+ lambda x: _make_complex(x, 0),
+ lambda x: _make_complex(0, x),
+ lambda x: _make_complex(x, np.multiply(x, -2))
+ ], ids=[
+ 'real',
+ 'complex-real',
+ 'complex-imag',
+ 'complex-both'
+ ])
+ def sc(self, request):
+ """ scale function used by the below tests """
+ return request.param
+
+ def test_non_finite_any_nan(self, sc):
+ """ test that nans are propagated """
+ assert_equal(np.interp(0.5, [np.nan, 1], sc([ 0, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, np.nan], sc([ 0, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, 1], sc([np.nan, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, 1], sc([ 0, np.nan])), sc(np.nan))
+
+ def test_non_finite_inf(self, sc):
+ """ Test that interp between opposite infs gives nan """
+ assert_equal(np.interp(0.5, [-np.inf, +np.inf], sc([ 0, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, 1], sc([-np.inf, +np.inf])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, 1], sc([+np.inf, -np.inf])), sc(np.nan))
+
+ # unless the y values are equal
+ assert_equal(np.interp(0.5, [-np.inf, +np.inf], sc([ 10, 10])), sc(10))
+
+ def test_non_finite_half_inf_xf(self, sc):
+ """ Test that interp where both axes have a bound at inf gives nan """
+ assert_equal(np.interp(0.5, [-np.inf, 1], sc([-np.inf, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [-np.inf, 1], sc([+np.inf, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [-np.inf, 1], sc([ 0, -np.inf])), sc(np.nan))
+ assert_equal(np.interp(0.5, [-np.inf, 1], sc([ 0, +np.inf])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, +np.inf], sc([-np.inf, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, +np.inf], sc([+np.inf, 10])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, +np.inf], sc([ 0, -np.inf])), sc(np.nan))
+ assert_equal(np.interp(0.5, [ 0, +np.inf], sc([ 0, +np.inf])), sc(np.nan))
+
+ def test_non_finite_half_inf_x(self, sc):
+ """ Test interp where the x axis has a bound at inf """
+ assert_equal(np.interp(0.5, [-np.inf, -np.inf], sc([0, 10])), sc(10))
+ assert_equal(np.interp(0.5, [-np.inf, 1 ], sc([0, 10])), sc(10))
+ assert_equal(np.interp(0.5, [ 0, +np.inf], sc([0, 10])), sc(0))
+ assert_equal(np.interp(0.5, [+np.inf, +np.inf], sc([0, 10])), sc(0))
+
+ def test_non_finite_half_inf_f(self, sc):
+ """ Test interp where the f axis has a bound at inf """
+ assert_equal(np.interp(0.5, [0, 1], sc([ 0, -np.inf])), sc(-np.inf))
+ assert_equal(np.interp(0.5, [0, 1], sc([ 0, +np.inf])), sc(+np.inf))
+ assert_equal(np.interp(0.5, [0, 1], sc([-np.inf, 10])), sc(-np.inf))
+ assert_equal(np.interp(0.5, [0, 1], sc([+np.inf, 10])), sc(+np.inf))
+ assert_equal(np.interp(0.5, [0, 1], sc([-np.inf, -np.inf])), sc(-np.inf))
+ assert_equal(np.interp(0.5, [0, 1], sc([+np.inf, +np.inf])), sc(+np.inf))
+
def test_complex_interp(self):
# test complex interpolation
x = np.linspace(0, 1, 5)
@@ -2391,11 +2529,23 @@ class TestPercentile(object):
assert_equal(np.percentile(x, 100), 3.5)
assert_equal(np.percentile(x, 50), 1.75)
x[1] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(x, 0), np.nan)
- assert_equal(np.percentile(x, 0, interpolation='nearest'), np.nan)
- assert_(w[0].category is RuntimeWarning)
+ assert_equal(np.percentile(x, 0), np.nan)
+ assert_equal(np.percentile(x, 0, interpolation='nearest'), np.nan)
+
+ def test_fraction(self):
+ x = [Fraction(i, 2) for i in np.arange(8)]
+
+ p = np.percentile(x, Fraction(0))
+ assert_equal(p, Fraction(0))
+ assert_equal(type(p), Fraction)
+
+ p = np.percentile(x, Fraction(100))
+ assert_equal(p, Fraction(7, 2))
+ assert_equal(type(p), Fraction)
+
+ p = np.percentile(x, Fraction(50))
+ assert_equal(p, Fraction(7, 4))
+ assert_equal(type(p), Fraction)
def test_api(self):
d = np.ones(5)
@@ -2733,85 +2883,63 @@ class TestPercentile(object):
def test_nan_behavior(self):
a = np.arange(24, dtype=float)
a[2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, 0.3), np.nan)
- assert_equal(np.percentile(a, 0.3, axis=0), np.nan)
- assert_equal(np.percentile(a, [0.3, 0.6], axis=0),
- np.array([np.nan] * 2))
- assert_(w[0].category is RuntimeWarning)
- assert_(w[1].category is RuntimeWarning)
- assert_(w[2].category is RuntimeWarning)
+ assert_equal(np.percentile(a, 0.3), np.nan)
+ assert_equal(np.percentile(a, 0.3, axis=0), np.nan)
+ assert_equal(np.percentile(a, [0.3, 0.6], axis=0),
+ np.array([np.nan] * 2))
a = np.arange(24, dtype=float).reshape(2, 3, 4)
a[1, 2, 3] = np.nan
a[1, 1, 2] = np.nan
# no axis
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, 0.3), np.nan)
- assert_equal(np.percentile(a, 0.3).ndim, 0)
- assert_(w[0].category is RuntimeWarning)
+ assert_equal(np.percentile(a, 0.3), np.nan)
+ assert_equal(np.percentile(a, 0.3).ndim, 0)
# axis0 zerod
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, 0)
b[2, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, 0.3, 0), b)
+ assert_equal(np.percentile(a, 0.3, 0), b)
# axis0 not zerod
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4),
[0.3, 0.6], 0)
b[:, 2, 3] = np.nan
b[:, 1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, [0.3, 0.6], 0), b)
+ assert_equal(np.percentile(a, [0.3, 0.6], 0), b)
# axis1 zerod
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, 1)
b[1, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, 0.3, 1), b)
+ assert_equal(np.percentile(a, 0.3, 1), b)
# axis1 not zerod
b = np.percentile(
np.arange(24, dtype=float).reshape(2, 3, 4), [0.3, 0.6], 1)
b[:, 1, 3] = np.nan
b[:, 1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, [0.3, 0.6], 1), b)
+ assert_equal(np.percentile(a, [0.3, 0.6], 1), b)
# axis02 zerod
b = np.percentile(
np.arange(24, dtype=float).reshape(2, 3, 4), 0.3, (0, 2))
b[1] = np.nan
b[2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, 0.3, (0, 2)), b)
+ assert_equal(np.percentile(a, 0.3, (0, 2)), b)
# axis02 not zerod
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4),
[0.3, 0.6], (0, 2))
b[:, 1] = np.nan
b[:, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(a, [0.3, 0.6], (0, 2)), b)
+ assert_equal(np.percentile(a, [0.3, 0.6], (0, 2)), b)
# axis02 not zerod with nearest interpolation
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4),
[0.3, 0.6], (0, 2), interpolation='nearest')
b[:, 1] = np.nan
b[:, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.percentile(
- a, [0.3, 0.6], (0, 2), interpolation='nearest'), b)
+ assert_equal(np.percentile(
+ a, [0.3, 0.6], (0, 2), interpolation='nearest'), b)
class TestQuantile(object):
@@ -2823,6 +2951,26 @@ class TestQuantile(object):
assert_equal(np.quantile(x, 1), 3.5)
assert_equal(np.quantile(x, 0.5), 1.75)
+ def test_fraction(self):
+ # fractional input, integral quantile
+ x = [Fraction(i, 2) for i in np.arange(8)]
+
+ q = np.quantile(x, 0)
+ assert_equal(q, 0)
+ assert_equal(type(q), Fraction)
+
+ q = np.quantile(x, 1)
+ assert_equal(q, Fraction(7, 2))
+ assert_equal(type(q), Fraction)
+
+ q = np.quantile(x, Fraction(1, 2))
+ assert_equal(q, Fraction(7, 4))
+ assert_equal(type(q), Fraction)
+
+ # repeat with integral input but fractional quantile
+ x = np.arange(8)
+ assert_equal(np.quantile(x, Fraction(1, 2)), Fraction(7, 2))
+
def test_no_p_overwrite(self):
# this is worth retesting, because quantile does not make a copy
p0 = np.array([0, 0.75, 0.25, 0.5, 1.0])
@@ -2858,10 +3006,7 @@ class TestMedian(object):
# check array scalar result
assert_equal(np.median(a).ndim, 0)
a[1] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a).ndim, 0)
- assert_(w[0].category is RuntimeWarning)
+ assert_equal(np.median(a).ndim, 0)
def test_axis_keyword(self):
a3 = np.array([[2, 3],
@@ -2960,58 +3105,43 @@ class TestMedian(object):
def test_nan_behavior(self):
a = np.arange(24, dtype=float)
a[2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a), np.nan)
- assert_equal(np.median(a, axis=0), np.nan)
- assert_(w[0].category is RuntimeWarning)
- assert_(w[1].category is RuntimeWarning)
+ assert_equal(np.median(a), np.nan)
+ assert_equal(np.median(a, axis=0), np.nan)
a = np.arange(24, dtype=float).reshape(2, 3, 4)
a[1, 2, 3] = np.nan
a[1, 1, 2] = np.nan
# no axis
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a), np.nan)
- assert_equal(np.median(a).ndim, 0)
- assert_(w[0].category is RuntimeWarning)
+ assert_equal(np.median(a), np.nan)
+ assert_equal(np.median(a).ndim, 0)
# axis0
b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), 0)
b[2, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a, 0), b)
- assert_equal(len(w), 1)
+ assert_equal(np.median(a, 0), b)
# axis1
b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), 1)
b[1, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a, 1), b)
- assert_equal(len(w), 1)
+ assert_equal(np.median(a, 1), b)
# axis02
b = np.median(np.arange(24, dtype=float).reshape(2, 3, 4), (0, 2))
b[1] = np.nan
b[2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.median(a, (0, 2)), b)
- assert_equal(len(w), 1)
+ assert_equal(np.median(a, (0, 2)), b)
def test_empty(self):
- # empty arrays
+ # mean(empty array) emits two warnings: empty slice and divide by 0
a = np.array([], dtype=float)
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', RuntimeWarning)
assert_equal(np.median(a), np.nan)
assert_(w[0].category is RuntimeWarning)
+ assert_equal(len(w), 2)
# multiple dimensions
a = np.array([], dtype=float, ndmin=3)
diff --git a/numpy/lib/tests/test_histograms.py b/numpy/lib/tests/test_histograms.py
index 594c8e782..4895a722c 100644
--- a/numpy/lib/tests/test_histograms.py
+++ b/numpy/lib/tests/test_histograms.py
@@ -8,7 +8,6 @@ from numpy.testing import (
assert_array_almost_equal, assert_raises, assert_allclose,
assert_array_max_ulp, assert_raises_regex, suppress_warnings,
)
-import pytest
class TestHistogram(object):
@@ -555,15 +554,11 @@ class TestHistogramOptimBinNums(object):
return a / (a + b)
ll = [[nbins_ratio(seed, size) for size in np.geomspace(start=10, stop=100, num=4).round().astype(int)]
- for seed in range(256)]
+ for seed in range(10)]
# the average difference between the two methods decreases as the dataset size increases.
- assert_almost_equal(abs(np.mean(ll, axis=0) - 0.5),
- [0.1065248,
- 0.0968844,
- 0.0331818,
- 0.0178057],
- decimal=3)
+ avg = abs(np.mean(ll, axis=0) - 0.5)
+ assert_almost_equal(avg, [0.15, 0.09, 0.08, 0.03], decimal=2)
def test_simple_range(self):
"""
@@ -596,16 +591,6 @@ class TestHistogramOptimBinNums(object):
msg += " with datasize of {0}".format(testlen)
assert_equal(len(a), numbins, err_msg=msg)
- @pytest.mark.parametrize("bins", ['auto', 'fd', 'doane', 'scott',
- 'stone', 'rice', 'sturges'])
- def test_signed_integer_data(self, bins):
- # Regression test for gh-14379.
- a = np.array([-2, 0, 127], dtype=np.int8)
- hist, edges = np.histogram(a, bins=bins)
- hist32, edges32 = np.histogram(a.astype(np.int32), bins=bins)
- assert_array_equal(hist, hist32)
- assert_array_equal(edges, edges32)
-
def test_simple_weighted(self):
"""
Check that weighted data raises a TypeError
@@ -813,7 +798,7 @@ class TestHistogramdd(object):
hist, edges = histogramdd((y, x), bins=(y_edges, x_edges))
assert_equal(hist, relative_areas)
- # resulting histogram should be uniform, since counts and areas are propotional
+ # resulting histogram should be uniform, since counts and areas are proportional
hist, edges = histogramdd((y, x), bins=(y_edges, x_edges), density=True)
assert_equal(hist, 1 / (8*8))
diff --git a/numpy/lib/tests/test_index_tricks.py b/numpy/lib/tests/test_index_tricks.py
index 3246f68ff..2f7e97831 100644
--- a/numpy/lib/tests/test_index_tricks.py
+++ b/numpy/lib/tests/test_index_tricks.py
@@ -77,6 +77,26 @@ class TestRavelUnravelIndex(object):
[[3, 6, 6], [4, 5, 1]])
assert_equal(np.unravel_index(1621, (6, 7, 8, 9)), [3, 1, 4, 1])
+ def test_empty_indices(self):
+ msg1 = 'indices must be integral: the provided empty sequence was'
+ msg2 = 'only int indices permitted'
+ assert_raises_regex(TypeError, msg1, np.unravel_index, [], (10, 3, 5))
+ assert_raises_regex(TypeError, msg1, np.unravel_index, (), (10, 3, 5))
+ assert_raises_regex(TypeError, msg2, np.unravel_index, np.array([]),
+ (10, 3, 5))
+ assert_equal(np.unravel_index(np.array([],dtype=int), (10, 3, 5)),
+ [[], [], []])
+ assert_raises_regex(TypeError, msg1, np.ravel_multi_index, ([], []),
+ (10, 3))
+ assert_raises_regex(TypeError, msg1, np.ravel_multi_index, ([], ['abc']),
+ (10, 3))
+ assert_raises_regex(TypeError, msg2, np.ravel_multi_index,
+ (np.array([]), np.array([])), (5, 3))
+ assert_equal(np.ravel_multi_index(
+ (np.array([], dtype=int), np.array([], dtype=int)), (5, 3)), [])
+ assert_equal(np.ravel_multi_index(np.array([[], []], dtype=int),
+ (5, 3)), [])
+
def test_big_indices(self):
# ravel_multi_index for big indices (issue #7546)
if np.intp == np.int64:
@@ -86,6 +106,9 @@ class TestRavelUnravelIndex(object):
np.ravel_multi_index(arr, (41, 7, 120, 36, 2706, 8, 6)),
[5627771580, 117259570957])
+ # test unravel_index for big indices (issue #9538)
+ assert_raises(ValueError, np.unravel_index, 1, (2**32-1, 2**31+1))
+
# test overflow checking for too big array (issue #7546)
dummy_arr = ([0],[0])
half_max = np.iinfo(np.intp).max // 2
@@ -272,11 +295,16 @@ class TestIndexExpression(object):
class TestIx_(object):
def test_regression_1(self):
- # Test empty inputs create outputs of indexing type, gh-5804
- # Test both lists and arrays
- for func in (range, np.arange):
- a, = np.ix_(func(0))
- assert_equal(a.dtype, np.intp)
+ # Test empty untyped inputs create outputs of indexing type, gh-5804
+ a, = np.ix_(range(0))
+ assert_equal(a.dtype, np.intp)
+
+ a, = np.ix_([])
+ assert_equal(a.dtype, np.intp)
+
+ # but if the type is specified, don't change it
+ a, = np.ix_(np.array([], dtype=np.float32))
+ assert_equal(a.dtype, np.float32)
def test_shape_and_dtype(self):
sizes = (4, 5, 3, 2)
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index 899e49031..78f9f85f3 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -22,7 +22,7 @@ from numpy.ma.testutils import assert_equal
from numpy.testing import (
assert_warns, assert_, assert_raises_regex, assert_raises,
assert_allclose, assert_array_equal, temppath, tempdir, IS_PYPY,
- HAS_REFCOUNT, suppress_warnings, assert_no_gc_cycles,
+ HAS_REFCOUNT, suppress_warnings, assert_no_gc_cycles, assert_no_warnings
)
@@ -504,8 +504,6 @@ class TestSaveTxt(object):
b' (3.142e+00-2.718e+00j) (3.142e+00-2.718e+00j)\n'])
-
-
def test_custom_writer(self):
class CustomWriter(list):
@@ -561,6 +559,33 @@ class TestSaveTxt(object):
s.seek(0)
assert_equal(s.read(), utf8 + '\n')
+ @pytest.mark.parametrize("fmt", [u"%f", b"%f"])
+ @pytest.mark.parametrize("iotype", [StringIO, BytesIO])
+ def test_unicode_and_bytes_fmt(self, fmt, iotype):
+ # string type of fmt should not matter, see also gh-4053
+ a = np.array([1.])
+ s = iotype()
+ np.savetxt(s, a, fmt=fmt)
+ s.seek(0)
+ if iotype is StringIO:
+ assert_equal(s.read(), u"%f\n" % 1.)
+ else:
+ assert_equal(s.read(), b"%f\n" % 1.)
+
+ @pytest.mark.skipif(sys.platform=='win32',
+ reason="large files cause problems")
+ @pytest.mark.slow
+ def test_large_zip(self):
+ # The test takes at least 6GB of memory, writes a file larger than 4GB
+ try:
+ a = 'a' * 6 * 1024 * 1024 * 1024
+ del a
+ except (MemoryError, OverflowError):
+ pytest.skip("Cannot allocate enough memory for test")
+ test_data = np.asarray([np.random.rand(np.random.randint(50,100),4)
+ for i in range(800000)])
+ with tempdir() as tmpdir:
+ np.savez(os.path.join(tmpdir, 'test.npz'), test_data=test_data)
class LoadTxtBase(object):
def check_compressed(self, fopen, suffixes):
@@ -1202,7 +1227,7 @@ class TestFromTxt(LoadTxtBase):
def test_record(self):
# Test w/ explicit dtype
data = TextIO('1 2\n3 4')
- test = np.ndfromtxt(data, dtype=[('x', np.int32), ('y', np.int32)])
+ test = np.genfromtxt(data, dtype=[('x', np.int32), ('y', np.int32)])
control = np.array([(1, 2), (3, 4)], dtype=[('x', 'i4'), ('y', 'i4')])
assert_equal(test, control)
#
@@ -1211,14 +1236,14 @@ class TestFromTxt(LoadTxtBase):
'formats': ('S1', 'i4', 'f4')}
control = np.array([('M', 64.0, 75.0), ('F', 25.0, 60.0)],
dtype=descriptor)
- test = np.ndfromtxt(data, dtype=descriptor)
+ test = np.genfromtxt(data, dtype=descriptor)
assert_equal(test, control)
def test_array(self):
# Test outputting a standard ndarray
data = TextIO('1 2\n3 4')
control = np.array([[1, 2], [3, 4]], dtype=int)
- test = np.ndfromtxt(data, dtype=int)
+ test = np.genfromtxt(data, dtype=int)
assert_array_equal(test, control)
#
data.seek(0)
@@ -1231,11 +1256,11 @@ class TestFromTxt(LoadTxtBase):
control = np.array([1, 2, 3, 4], int)
#
data = TextIO('1\n2\n3\n4\n')
- test = np.ndfromtxt(data, dtype=int)
+ test = np.genfromtxt(data, dtype=int)
assert_array_equal(test, control)
#
data = TextIO('1,2,3,4\n')
- test = np.ndfromtxt(data, dtype=int, delimiter=',')
+ test = np.genfromtxt(data, dtype=int, delimiter=',')
assert_array_equal(test, control)
def test_comments(self):
@@ -1243,11 +1268,11 @@ class TestFromTxt(LoadTxtBase):
control = np.array([1, 2, 3, 5], int)
# Comment on its own line
data = TextIO('# comment\n1,2,3,5\n')
- test = np.ndfromtxt(data, dtype=int, delimiter=',', comments='#')
+ test = np.genfromtxt(data, dtype=int, delimiter=',', comments='#')
assert_equal(test, control)
# Comment at the end of a line
data = TextIO('1,2,3,5# comment\n')
- test = np.ndfromtxt(data, dtype=int, delimiter=',', comments='#')
+ test = np.genfromtxt(data, dtype=int, delimiter=',', comments='#')
assert_equal(test, control)
def test_skiprows(self):
@@ -1256,7 +1281,7 @@ class TestFromTxt(LoadTxtBase):
kwargs = dict(dtype=int, delimiter=',')
#
data = TextIO('comment\n1,2,3,5\n')
- test = np.ndfromtxt(data, skip_header=1, **kwargs)
+ test = np.genfromtxt(data, skip_header=1, **kwargs)
assert_equal(test, control)
#
data = TextIO('# comment\n1,2,3,5\n')
@@ -1303,7 +1328,7 @@ class TestFromTxt(LoadTxtBase):
data = TextIO('gender age weight\nM 64.0 75.0\nF 25.0 60.0')
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- test = np.ndfromtxt(data, dtype=None, names=True)
+ test = np.genfromtxt(data, dtype=None, names=True)
assert_(w[0].category is np.VisibleDeprecationWarning)
control = {'gender': np.array([b'M', b'F']),
'age': np.array([64.0, 25.0]),
@@ -1317,7 +1342,7 @@ class TestFromTxt(LoadTxtBase):
data = TextIO('A 64 75.0 3+4j True\nBCD 25 60.0 5+6j False')
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- test = np.ndfromtxt(data, dtype=None)
+ test = np.genfromtxt(data, dtype=None)
assert_(w[0].category is np.VisibleDeprecationWarning)
control = [np.array([b'A', b'BCD']),
np.array([64, 25]),
@@ -1331,7 +1356,7 @@ class TestFromTxt(LoadTxtBase):
def test_auto_dtype_uniform(self):
# Tests whether the output dtype can be uniformized
data = TextIO('1 2 3 4\n5 6 7 8\n')
- test = np.ndfromtxt(data, dtype=None)
+ test = np.genfromtxt(data, dtype=None)
control = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
assert_equal(test, control)
@@ -1339,7 +1364,7 @@ class TestFromTxt(LoadTxtBase):
# Check that a nested dtype isn't MIA
data = TextIO('1,2,3.0\n4,5,6.0\n')
fancydtype = np.dtype([('x', int), ('y', [('t', int), ('s', float)])])
- test = np.ndfromtxt(data, dtype=fancydtype, delimiter=',')
+ test = np.genfromtxt(data, dtype=fancydtype, delimiter=',')
control = np.array([(1, (2, 3.0)), (4, (5, 6.0))], dtype=fancydtype)
assert_equal(test, control)
@@ -1349,7 +1374,7 @@ class TestFromTxt(LoadTxtBase):
'formats': ('S1', 'i4', 'f4')}
data = TextIO(b'M 64.0 75.0\nF 25.0 60.0')
names = ('gender', 'age', 'weight')
- test = np.ndfromtxt(data, dtype=descriptor, names=names)
+ test = np.genfromtxt(data, dtype=descriptor, names=names)
descriptor['names'] = names
control = np.array([('M', 64.0, 75.0),
('F', 25.0, 60.0)], dtype=descriptor)
@@ -1391,12 +1416,25 @@ M 33 21.99
control = np.array([(1, 2), (3, 4)], dtype=[('col1', int), ('col2', int)])
assert_equal(test, control)
+ def test_file_is_closed_on_error(self):
+ # gh-13200
+ with tempdir() as tmpdir:
+ fpath = os.path.join(tmpdir, "test.csv")
+ with open(fpath, "wb") as f:
+ f.write(u'\N{GREEK PI SYMBOL}'.encode('utf8'))
+
+ # ResourceWarnings are emitted from a destructor, so won't be
+ # detected by regular propagation to errors.
+ with assert_no_warnings():
+ with pytest.raises(UnicodeDecodeError):
+ np.genfromtxt(fpath, encoding="ascii")
+
def test_autonames_and_usecols(self):
# Tests names and usecols
data = TextIO('A B C D\n aaaa 121 45 9.1')
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- test = np.ndfromtxt(data, usecols=('A', 'C', 'D'),
+ test = np.genfromtxt(data, usecols=('A', 'C', 'D'),
names=True, dtype=None)
assert_(w[0].category is np.VisibleDeprecationWarning)
control = np.array(('aaaa', 45, 9.1),
@@ -1406,7 +1444,7 @@ M 33 21.99
def test_converters_with_usecols(self):
# Test the combination user-defined converters and usecol
data = TextIO('1,2,3,,5\n6,7,8,9,10\n')
- test = np.ndfromtxt(data, dtype=int, delimiter=',',
+ test = np.genfromtxt(data, dtype=int, delimiter=',',
converters={3: lambda s: int(s or - 999)},
usecols=(1, 3,))
control = np.array([[2, -999], [7, 9]], int)
@@ -1417,7 +1455,7 @@ M 33 21.99
data = TextIO('A B C D\n aaaa 121 45 9.1')
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- test = np.ndfromtxt(data, usecols=('A', 'C', 'D'), names=True,
+ test = np.genfromtxt(data, usecols=('A', 'C', 'D'), names=True,
dtype=None,
converters={'C': lambda s: 2 * int(s)})
assert_(w[0].category is np.VisibleDeprecationWarning)
@@ -1430,7 +1468,7 @@ M 33 21.99
converter = {
'date': lambda s: strptime(s, '%Y-%m-%d %H:%M:%SZ')}
data = TextIO('2009-02-03 12:00:00Z, 72214.0')
- test = np.ndfromtxt(data, delimiter=',', dtype=None,
+ test = np.genfromtxt(data, delimiter=',', dtype=None,
names=['date', 'stid'], converters=converter)
control = np.array((datetime(2009, 2, 3), 72214.),
dtype=[('date', np.object_), ('stid', float)])
@@ -1441,7 +1479,7 @@ M 33 21.99
converter = {
'date': lambda s: np.datetime64(strptime(s, '%Y-%m-%d %H:%M:%SZ'))}
data = TextIO('2009-02-03 12:00:00Z, 72214.0')
- test = np.ndfromtxt(data, delimiter=',', dtype=None,
+ test = np.genfromtxt(data, delimiter=',', dtype=None,
names=['date', 'stid'], converters=converter)
control = np.array((datetime(2009, 2, 3), 72214.),
dtype=[('date', 'datetime64[us]'), ('stid', float)])
@@ -1450,12 +1488,12 @@ M 33 21.99
def test_unused_converter(self):
# Test whether unused converters are forgotten
data = TextIO("1 21\n 3 42\n")
- test = np.ndfromtxt(data, usecols=(1,),
+ test = np.genfromtxt(data, usecols=(1,),
converters={0: lambda s: int(s, 16)})
assert_equal(test, [21, 42])
#
data.seek(0)
- test = np.ndfromtxt(data, usecols=(1,),
+ test = np.genfromtxt(data, usecols=(1,),
converters={1: lambda s: int(s, 16)})
assert_equal(test, [33, 66])
@@ -1482,12 +1520,12 @@ M 33 21.99
def test_dtype_with_converters(self):
dstr = "2009; 23; 46"
- test = np.ndfromtxt(TextIO(dstr,),
+ test = np.genfromtxt(TextIO(dstr,),
delimiter=";", dtype=float, converters={0: bytes})
control = np.array([('2009', 23., 46)],
dtype=[('f0', '|S4'), ('f1', float), ('f2', float)])
assert_equal(test, control)
- test = np.ndfromtxt(TextIO(dstr,),
+ test = np.genfromtxt(TextIO(dstr,),
delimiter=";", dtype=float, converters={0: float})
control = np.array([2009., 23., 46],)
assert_equal(test, control)
@@ -1527,13 +1565,6 @@ M 33 21.99
test = np.genfromtxt(TextIO(data), delimiter=";",
dtype=ndtype, converters=converters)
- # nested but empty fields also aren't supported
- ndtype = [('idx', int), ('code', object), ('nest', [])]
- with assert_raises_regex(NotImplementedError,
- 'Nested fields.* not supported.*'):
- test = np.genfromtxt(TextIO(data), delimiter=";",
- dtype=ndtype, converters=converters)
-
def test_userconverters_with_explicit_dtype(self):
# Test user_converters w/ explicit (standard) dtype
data = TextIO('skip,skip,2001-01-01,1.0,skip')
@@ -1558,7 +1589,7 @@ M 33 21.99
def test_spacedelimiter(self):
# Test space delimiter
data = TextIO("1 2 3 4 5\n6 7 8 9 10")
- test = np.ndfromtxt(data)
+ test = np.genfromtxt(data)
control = np.array([[1., 2., 3., 4., 5.],
[6., 7., 8., 9., 10.]])
assert_equal(test, control)
@@ -1572,7 +1603,7 @@ M 33 21.99
def test_missing(self):
data = TextIO('1,2,3,,5\n')
- test = np.ndfromtxt(data, dtype=int, delimiter=',',
+ test = np.genfromtxt(data, dtype=int, delimiter=',',
converters={3: lambda s: int(s or - 999)})
control = np.array([1, 2, 3, -999, 5], int)
assert_equal(test, control)
@@ -1594,18 +1625,18 @@ M 33 21.99
data = TextIO()
np.savetxt(data, control)
data.seek(0)
- test = np.ndfromtxt(data, dtype=float, usecols=(1,))
+ test = np.genfromtxt(data, dtype=float, usecols=(1,))
assert_equal(test, control[:, 1])
#
control = np.array([[1, 2, 3], [3, 4, 5]], float)
data = TextIO()
np.savetxt(data, control)
data.seek(0)
- test = np.ndfromtxt(data, dtype=float, usecols=(1, 2))
+ test = np.genfromtxt(data, dtype=float, usecols=(1, 2))
assert_equal(test, control[:, 1:])
# Testing with arrays instead of tuples.
data.seek(0)
- test = np.ndfromtxt(data, dtype=float, usecols=np.array([1, 2]))
+ test = np.genfromtxt(data, dtype=float, usecols=np.array([1, 2]))
assert_equal(test, control[:, 1:])
def test_usecols_as_css(self):
@@ -1621,7 +1652,7 @@ M 33 21.99
data = TextIO("JOE 70.1 25.3\nBOB 60.5 27.9")
names = ['stid', 'temp']
dtypes = ['S4', 'f8']
- test = np.ndfromtxt(
+ test = np.genfromtxt(
data, usecols=(0, 2), dtype=list(zip(names, dtypes)))
assert_equal(test['stid'], [b"JOE", b"BOB"])
assert_equal(test['temp'], [25.3, 27.9])
@@ -1654,7 +1685,7 @@ M 33 21.99
# Check that a nested dtype isn't MIA
data = TextIO('1,2,3.0\n4,5,6.0\n')
fancydtype = np.dtype([('x', int), ('y', [('t', int), ('s', float)])])
- test = np.mafromtxt(data, dtype=fancydtype, delimiter=',')
+ test = np.genfromtxt(data, dtype=fancydtype, delimiter=',', usemask=True)
control = ma.array([(1, (2, 3.0)), (4, (5, 6.0))], dtype=fancydtype)
assert_equal(test, control)
@@ -1662,7 +1693,7 @@ M 33 21.99
c = TextIO("aaaa 1.0 8.0 1 2 3 4 5 6")
dt = np.dtype([('name', 'S4'), ('x', float), ('y', float),
('block', int, (2, 3))])
- x = np.ndfromtxt(c, dtype=dt)
+ x = np.genfromtxt(c, dtype=dt)
a = np.array([('aaaa', 1.0, 8.0, [[1, 2, 3], [4, 5, 6]])],
dtype=dt)
assert_array_equal(x, a)
@@ -1670,7 +1701,7 @@ M 33 21.99
def test_withmissing(self):
data = TextIO('A,B\n0,1\n2,N/A')
kwargs = dict(delimiter=",", missing_values="N/A", names=True)
- test = np.mafromtxt(data, dtype=None, **kwargs)
+ test = np.genfromtxt(data, dtype=None, usemask=True, **kwargs)
control = ma.array([(0, 1), (2, -1)],
mask=[(False, False), (False, True)],
dtype=[('A', int), ('B', int)])
@@ -1678,7 +1709,7 @@ M 33 21.99
assert_equal(test.mask, control.mask)
#
data.seek(0)
- test = np.mafromtxt(data, **kwargs)
+ test = np.genfromtxt(data, usemask=True, **kwargs)
control = ma.array([(0, 1), (2, -1)],
mask=[(False, False), (False, True)],
dtype=[('A', float), ('B', float)])
@@ -1690,7 +1721,7 @@ M 33 21.99
basekwargs = dict(dtype=None, delimiter=",", names=True,)
mdtype = [('A', int), ('B', float), ('C', complex)]
#
- test = np.mafromtxt(TextIO(data), missing_values="N/A",
+ test = np.genfromtxt(TextIO(data), missing_values="N/A",
**basekwargs)
control = ma.array([(0, 0.0, 0j), (1, -999, 1j),
(-9, 2.2, -999j), (3, -99, 3j)],
@@ -1699,16 +1730,17 @@ M 33 21.99
assert_equal(test, control)
#
basekwargs['dtype'] = mdtype
- test = np.mafromtxt(TextIO(data),
- missing_values={0: -9, 1: -99, 2: -999j}, **basekwargs)
+ test = np.genfromtxt(TextIO(data),
+ missing_values={0: -9, 1: -99, 2: -999j}, usemask=True, **basekwargs)
control = ma.array([(0, 0.0, 0j), (1, -999, 1j),
(-9, 2.2, -999j), (3, -99, 3j)],
mask=[(0, 0, 0), (0, 1, 0), (1, 0, 1), (0, 1, 0)],
dtype=mdtype)
assert_equal(test, control)
#
- test = np.mafromtxt(TextIO(data),
+ test = np.genfromtxt(TextIO(data),
missing_values={0: -9, 'B': -99, 'C': -999j},
+ usemask=True,
**basekwargs)
control = ma.array([(0, 0.0, 0j), (1, -999, 1j),
(-9, 2.2, -999j), (3, -99, 3j)],
@@ -1746,8 +1778,8 @@ M 33 21.99
def test_withmissing_float(self):
data = TextIO('A,B\n0,1.5\n2,-999.00')
- test = np.mafromtxt(data, dtype=None, delimiter=',',
- missing_values='-999.0', names=True,)
+ test = np.genfromtxt(data, dtype=None, delimiter=',',
+ missing_values='-999.0', names=True, usemask=True)
control = ma.array([(0, 1.5), (2, -1.)],
mask=[(False, False), (False, True)],
dtype=[('A', int), ('B', float)])
@@ -1786,14 +1818,14 @@ M 33 21.99
ret = {}
def f(_ret={}):
- _ret['mtest'] = np.ndfromtxt(mdata, invalid_raise=False, **kwargs)
+ _ret['mtest'] = np.genfromtxt(mdata, invalid_raise=False, **kwargs)
assert_warns(ConversionWarning, f, _ret=ret)
mtest = ret['mtest']
assert_equal(len(mtest), 45)
assert_equal(mtest, np.ones(45, dtype=[(_, int) for _ in 'abcde']))
#
mdata.seek(0)
- assert_raises(ValueError, np.ndfromtxt, mdata,
+ assert_raises(ValueError, np.genfromtxt, mdata,
delimiter=",", names=True)
def test_invalid_raise_with_usecols(self):
@@ -1810,14 +1842,14 @@ M 33 21.99
ret = {}
def f(_ret={}):
- _ret['mtest'] = np.ndfromtxt(mdata, usecols=(0, 4), **kwargs)
+ _ret['mtest'] = np.genfromtxt(mdata, usecols=(0, 4), **kwargs)
assert_warns(ConversionWarning, f, _ret=ret)
mtest = ret['mtest']
assert_equal(len(mtest), 45)
assert_equal(mtest, np.ones(45, dtype=[(_, int) for _ in 'ae']))
#
mdata.seek(0)
- mtest = np.ndfromtxt(mdata, usecols=(0, 1), **kwargs)
+ mtest = np.genfromtxt(mdata, usecols=(0, 1), **kwargs)
assert_equal(len(mtest), 50)
control = np.ones(50, dtype=[(_, int) for _ in 'ab'])
control[[10 * _ for _ in range(5)]] = (2, 2)
@@ -1836,7 +1868,7 @@ M 33 21.99
def test_default_field_format(self):
# Test default format
data = "0, 1, 2.3\n4, 5, 6.7"
- mtest = np.ndfromtxt(TextIO(data),
+ mtest = np.genfromtxt(TextIO(data),
delimiter=",", dtype=None, defaultfmt="f%02i")
ctrl = np.array([(0, 1, 2.3), (4, 5, 6.7)],
dtype=[("f00", int), ("f01", int), ("f02", float)])
@@ -1845,7 +1877,7 @@ M 33 21.99
def test_single_dtype_wo_names(self):
# Test single dtype w/o names
data = "0, 1, 2.3\n4, 5, 6.7"
- mtest = np.ndfromtxt(TextIO(data),
+ mtest = np.genfromtxt(TextIO(data),
delimiter=",", dtype=float, defaultfmt="f%02i")
ctrl = np.array([[0., 1., 2.3], [4., 5., 6.7]], dtype=float)
assert_equal(mtest, ctrl)
@@ -1853,7 +1885,7 @@ M 33 21.99
def test_single_dtype_w_explicit_names(self):
# Test single dtype w explicit names
data = "0, 1, 2.3\n4, 5, 6.7"
- mtest = np.ndfromtxt(TextIO(data),
+ mtest = np.genfromtxt(TextIO(data),
delimiter=",", dtype=float, names="a, b, c")
ctrl = np.array([(0., 1., 2.3), (4., 5., 6.7)],
dtype=[(_, float) for _ in "abc"])
@@ -1862,7 +1894,7 @@ M 33 21.99
def test_single_dtype_w_implicit_names(self):
# Test single dtype w implicit names
data = "a, b, c\n0, 1, 2.3\n4, 5, 6.7"
- mtest = np.ndfromtxt(TextIO(data),
+ mtest = np.genfromtxt(TextIO(data),
delimiter=",", dtype=float, names=True)
ctrl = np.array([(0., 1., 2.3), (4., 5., 6.7)],
dtype=[(_, float) for _ in "abc"])
@@ -1871,7 +1903,7 @@ M 33 21.99
def test_easy_structured_dtype(self):
# Test easy structured dtype
data = "0, 1, 2.3\n4, 5, 6.7"
- mtest = np.ndfromtxt(TextIO(data), delimiter=",",
+ mtest = np.genfromtxt(TextIO(data), delimiter=",",
dtype=(int, float, float), defaultfmt="f_%02i")
ctrl = np.array([(0, 1., 2.3), (4, 5., 6.7)],
dtype=[("f_00", int), ("f_01", float), ("f_02", float)])
@@ -1883,14 +1915,14 @@ M 33 21.99
kwargs = dict(delimiter=",", dtype=None)
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- mtest = np.ndfromtxt(TextIO(data), **kwargs)
+ mtest = np.genfromtxt(TextIO(data), **kwargs)
assert_(w[0].category is np.VisibleDeprecationWarning)
ctrl = np.array([('01/01/2003 ', 1.3, ' abcde')],
dtype=[('f0', '|S12'), ('f1', float), ('f2', '|S8')])
assert_equal(mtest, ctrl)
with warnings.catch_warnings(record=True) as w:
warnings.filterwarnings('always', '', np.VisibleDeprecationWarning)
- mtest = np.ndfromtxt(TextIO(data), autostrip=True, **kwargs)
+ mtest = np.genfromtxt(TextIO(data), autostrip=True, **kwargs)
assert_(w[0].category is np.VisibleDeprecationWarning)
ctrl = np.array([('01/01/2003', 1.3, 'abcde')],
dtype=[('f0', '|S10'), ('f1', float), ('f2', '|S5')])
@@ -1951,12 +1983,12 @@ M 33 21.99
# w/ dtype=None
ctrl = np.array([(0, 1, 2), (3, 4, 5)],
dtype=[(_, int) for _ in ('A', 'f0', 'C')])
- test = np.ndfromtxt(TextIO(data), dtype=None, **kwargs)
+ test = np.genfromtxt(TextIO(data), dtype=None, **kwargs)
assert_equal(test, ctrl)
# w/ default dtype
ctrl = np.array([(0, 1, 2), (3, 4, 5)],
dtype=[(_, float) for _ in ('A', 'f0', 'C')])
- test = np.ndfromtxt(TextIO(data), **kwargs)
+ test = np.genfromtxt(TextIO(data), **kwargs)
def test_names_auto_completion(self):
# Make sure that names are properly completed
@@ -1992,13 +2024,13 @@ M 33 21.99
kwargs = dict(delimiter=(5, 5, 4), names=True, dtype=None)
ctrl = np.array([(0, 1, 2.3), (45, 67, 9.)],
dtype=[('A', int), ('B', int), ('C', float)])
- test = np.ndfromtxt(TextIO(data), **kwargs)
+ test = np.genfromtxt(TextIO(data), **kwargs)
assert_equal(test, ctrl)
#
kwargs = dict(delimiter=5, names=True, dtype=None)
ctrl = np.array([(0, 1, 2.3), (45, 67, 9.)],
dtype=[('A', int), ('B', int), ('C', float)])
- test = np.ndfromtxt(TextIO(data), **kwargs)
+ test = np.genfromtxt(TextIO(data), **kwargs)
assert_equal(test, ctrl)
def test_filling_values(self):
@@ -2006,7 +2038,7 @@ M 33 21.99
data = b"1, 2, 3\n1, , 5\n0, 6, \n"
kwargs = dict(delimiter=",", dtype=None, filling_values=-999)
ctrl = np.array([[1, 2, 3], [1, -999, 5], [0, 6, -999]], dtype=int)
- test = np.ndfromtxt(TextIO(data), **kwargs)
+ test = np.genfromtxt(TextIO(data), **kwargs)
assert_equal(test, ctrl)
def test_comments_is_none(self):
@@ -2295,7 +2327,7 @@ M 33 21.99
data = TextIO('73786976294838206464 17179869184 1024')
- test = np.ndfromtxt(data, dtype=None)
+ test = np.genfromtxt(data, dtype=None)
assert_equal(test.dtype.names, ['f0', 'f1', 'f2'])
@@ -2359,7 +2391,7 @@ class TestPathUsage(object):
np.savez(path, lab='place holder')
with np.load(path) as data:
assert_array_equal(data['lab'], 'place holder')
-
+
def test_savez_compressed_load(self):
# Test that pathlib.Path instances can be used with savez.
with temppath(suffix='.npz') as path:
@@ -2385,7 +2417,7 @@ class TestPathUsage(object):
f.write(u'1 2\n3 4')
control = np.array([[1, 2], [3, 4]], dtype=int)
- test = np.ndfromtxt(path, dtype=int)
+ test = np.genfromtxt(path, dtype=int)
assert_array_equal(test, control)
def test_mafromtxt(self):
@@ -2395,7 +2427,7 @@ class TestPathUsage(object):
with path.open('w') as f:
f.write(u'1,2,3.0\n4,5,6.0\n')
- test = np.mafromtxt(path, delimiter=',')
+ test = np.genfromtxt(path, delimiter=',', usemask=True)
control = ma.array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)])
assert_equal(test, control)
@@ -2440,6 +2472,44 @@ def test_gzip_load():
assert_array_equal(np.load(f), a)
+# These next two classes encode the minimal API needed to save()/load() arrays.
+# The `test_ducktyping` ensures they work correctly
+class JustWriter(object):
+ def __init__(self, base):
+ self.base = base
+
+ def write(self, s):
+ return self.base.write(s)
+
+ def flush(self):
+ return self.base.flush()
+
+class JustReader(object):
+ def __init__(self, base):
+ self.base = base
+
+ def read(self, n):
+ return self.base.read(n)
+
+ def seek(self, off, whence=0):
+ return self.base.seek(off, whence)
+
+
+def test_ducktyping():
+ a = np.random.random((5, 5))
+
+ s = BytesIO()
+ f = JustWriter(s)
+
+ np.save(f, a)
+ f.flush()
+ s.seek(0)
+
+ f = JustReader(s)
+ assert_array_equal(np.load(f), a)
+
+
+
def test_gzip_loadtxt():
# Thanks to another windows brokenness, we can't use
# NamedTemporaryFile: a file created from this function cannot be
diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py
index 504372faf..b7261c63f 100644
--- a/numpy/lib/tests/test_nanfunctions.py
+++ b/numpy/lib/tests/test_nanfunctions.py
@@ -1,8 +1,10 @@
from __future__ import division, absolute_import, print_function
import warnings
+import pytest
import numpy as np
+from numpy.lib.nanfunctions import _nan_mask
from numpy.testing import (
assert_, assert_equal, assert_almost_equal, assert_no_warnings,
assert_raises, assert_array_equal, suppress_warnings
@@ -925,3 +927,29 @@ class TestNanFunctions_Quantile(object):
p = p.tolist()
np.nanquantile(np.arange(100.), p, interpolation="midpoint")
assert_array_equal(p, p0)
+
+@pytest.mark.parametrize("arr, expected", [
+ # array of floats with some nans
+ (np.array([np.nan, 5.0, np.nan, np.inf]),
+ np.array([False, True, False, True])),
+ # int64 array that can't possibly have nans
+ (np.array([1, 5, 7, 9], dtype=np.int64),
+ True),
+ # bool array that can't possibly have nans
+ (np.array([False, True, False, True]),
+ True),
+ # 2-D complex array with nans
+ (np.array([[np.nan, 5.0],
+ [np.nan, np.inf]], dtype=np.complex64),
+ np.array([[False, True],
+ [False, True]])),
+ ])
+def test__nan_mask(arr, expected):
+ for out in [None, np.empty(arr.shape, dtype=np.bool_)]:
+ actual = _nan_mask(arr, out=out)
+ assert_equal(actual, expected)
+ # the above won't distinguish between True proper
+ # and an array of True values; we want True proper
+ # for types that can't possibly contain NaN
+ if type(expected) is not np.ndarray:
+ assert actual is True
diff --git a/numpy/lib/tests/test_packbits.py b/numpy/lib/tests/test_packbits.py
index fde5c37f2..95a465c36 100644
--- a/numpy/lib/tests/test_packbits.py
+++ b/numpy/lib/tests/test_packbits.py
@@ -2,7 +2,8 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from numpy.testing import assert_array_equal, assert_equal, assert_raises
-
+import pytest
+from itertools import chain
def test_packbits():
# Copied from the docstring.
@@ -50,8 +51,8 @@ def test_packbits_empty_with_axis():
assert_equal(b.dtype, np.uint8)
assert_equal(b.shape, out_shape)
-
-def test_packbits_large():
+@pytest.mark.parametrize('bitorder', ('little', 'big'))
+def test_packbits_large(bitorder):
# test data large enough for 16 byte vectorization
a = np.array([1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
@@ -71,7 +72,7 @@ def test_packbits_large():
a = a.repeat(3)
for dtype in '?bBhHiIlLqQ':
arr = np.array(a, dtype=dtype)
- b = np.packbits(arr, axis=None)
+ b = np.packbits(arr, axis=None, bitorder=bitorder)
assert_equal(b.dtype, np.uint8)
r = [252, 127, 192, 3, 254, 7, 252, 0, 7, 31, 240, 0, 28, 1, 255, 252,
113, 248, 3, 255, 192, 28, 15, 192, 28, 126, 0, 224, 127, 255,
@@ -81,9 +82,10 @@ def test_packbits_large():
255, 224, 1, 255, 252, 126, 63, 0, 1, 192, 252, 14, 63, 0, 15,
199, 252, 113, 255, 3, 128, 56, 252, 14, 7, 0, 113, 255, 255, 142, 56, 227,
129, 248, 227, 129, 199, 31, 128]
- assert_array_equal(b, r)
+ if bitorder == 'big':
+ assert_array_equal(b, r)
# equal for size being multiple of 8
- assert_array_equal(np.unpackbits(b)[:-4], a)
+ assert_array_equal(np.unpackbits(b, bitorder=bitorder)[:-4], a)
# check last byte of different remainders (16 byte vectorization)
b = [np.packbits(arr[:-i], axis=None)[-1] for i in range(1, 16)]
@@ -229,6 +231,20 @@ def test_unpackbits():
[0, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 0, 1, 1, 1]]))
+def test_pack_unpack_order():
+ a = np.array([[2], [7], [23]], dtype=np.uint8)
+ b = np.unpackbits(a, axis=1)
+ assert_equal(b.dtype, np.uint8)
+ b_little = np.unpackbits(a, axis=1, bitorder='little')
+ b_big = np.unpackbits(a, axis=1, bitorder='big')
+ assert_array_equal(b, b_big)
+ assert_array_equal(a, np.packbits(b_little, axis=1, bitorder='little'))
+ assert_array_equal(b[:,::-1], b_little)
+ assert_array_equal(a, np.packbits(b_big, axis=1, bitorder='big'))
+ assert_raises(ValueError, np.unpackbits, a, bitorder='r')
+ assert_raises(TypeError, np.unpackbits, a, bitorder=10)
+
+
def test_unpackbits_empty():
a = np.empty((0,), dtype=np.uint8)
@@ -266,3 +282,97 @@ def test_unpackbits_large():
assert_array_equal(np.packbits(np.unpackbits(d, axis=1), axis=1), d)
d = d.T.copy()
assert_array_equal(np.packbits(np.unpackbits(d, axis=0), axis=0), d)
+
+
+class TestCount():
+ x = np.array([
+ [1, 0, 1, 0, 0, 1, 0],
+ [0, 1, 1, 1, 0, 0, 0],
+ [0, 0, 1, 0, 0, 1, 1],
+ [1, 1, 0, 0, 0, 1, 1],
+ [1, 0, 1, 0, 1, 0, 1],
+ [0, 0, 1, 1, 1, 0, 0],
+ [0, 1, 0, 1, 0, 1, 0],
+ ], dtype=np.uint8)
+ padded1 = np.zeros(57, dtype=np.uint8)
+ padded1[:49] = x.ravel()
+ padded1b = np.zeros(57, dtype=np.uint8)
+ padded1b[:49] = x[::-1].copy().ravel()
+ padded2 = np.zeros((9, 9), dtype=np.uint8)
+ padded2[:7, :7] = x
+
+ @pytest.mark.parametrize('bitorder', ('little', 'big'))
+ @pytest.mark.parametrize('count', chain(range(58), range(-1, -57, -1)))
+ def test_roundtrip(self, bitorder, count):
+ if count < 0:
+ # one extra zero of padding
+ cutoff = count - 1
+ else:
+ cutoff = count
+ # test complete invertibility of packbits and unpackbits with count
+ packed = np.packbits(self.x, bitorder=bitorder)
+ unpacked = np.unpackbits(packed, count=count, bitorder=bitorder)
+ assert_equal(unpacked.dtype, np.uint8)
+ assert_array_equal(unpacked, self.padded1[:cutoff])
+
+ @pytest.mark.parametrize('kwargs', [
+ {}, {'count': None},
+ ])
+ def test_count(self, kwargs):
+ packed = np.packbits(self.x)
+ unpacked = np.unpackbits(packed, **kwargs)
+ assert_equal(unpacked.dtype, np.uint8)
+ assert_array_equal(unpacked, self.padded1[:-1])
+
+ @pytest.mark.parametrize('bitorder', ('little', 'big'))
+ # delta==-1 when count<0 because one extra zero of padding
+ @pytest.mark.parametrize('count', chain(range(8), range(-1, -9, -1)))
+ def test_roundtrip_axis(self, bitorder, count):
+ if count < 0:
+ # one extra zero of padding
+ cutoff = count - 1
+ else:
+ cutoff = count
+ packed0 = np.packbits(self.x, axis=0, bitorder=bitorder)
+ unpacked0 = np.unpackbits(packed0, axis=0, count=count,
+ bitorder=bitorder)
+ assert_equal(unpacked0.dtype, np.uint8)
+ assert_array_equal(unpacked0, self.padded2[:cutoff, :self.x.shape[1]])
+
+ packed1 = np.packbits(self.x, axis=1, bitorder=bitorder)
+ unpacked1 = np.unpackbits(packed1, axis=1, count=count,
+ bitorder=bitorder)
+ assert_equal(unpacked1.dtype, np.uint8)
+ assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :cutoff])
+
+ @pytest.mark.parametrize('kwargs', [
+ {}, {'count': None},
+ {'bitorder' : 'little'},
+ {'bitorder': 'little', 'count': None},
+ {'bitorder' : 'big'},
+ {'bitorder': 'big', 'count': None},
+ ])
+ def test_axis_count(self, kwargs):
+ packed0 = np.packbits(self.x, axis=0)
+ unpacked0 = np.unpackbits(packed0, axis=0, **kwargs)
+ assert_equal(unpacked0.dtype, np.uint8)
+ if kwargs.get('bitorder', 'big') == 'big':
+ assert_array_equal(unpacked0, self.padded2[:-1, :self.x.shape[1]])
+ else:
+ assert_array_equal(unpacked0[::-1, :], self.padded2[:-1, :self.x.shape[1]])
+
+ packed1 = np.packbits(self.x, axis=1)
+ unpacked1 = np.unpackbits(packed1, axis=1, **kwargs)
+ assert_equal(unpacked1.dtype, np.uint8)
+ if kwargs.get('bitorder', 'big') == 'big':
+ assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :-1])
+ else:
+ assert_array_equal(unpacked1[:, ::-1], self.padded2[:self.x.shape[0], :-1])
+
+ def test_bad_count(self):
+ packed0 = np.packbits(self.x, axis=0)
+ assert_raises(ValueError, np.unpackbits, packed0, axis=0, count=-9)
+ packed1 = np.packbits(self.x, axis=1)
+ assert_raises(ValueError, np.unpackbits, packed1, axis=1, count=-9)
+ packed = np.packbits(self.x)
+ assert_raises(ValueError, np.unpackbits, packed, count=-57)
diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py
index 0c839d486..0126ccaf8 100644
--- a/numpy/lib/tests/test_recfunctions.py
+++ b/numpy/lib/tests/test_recfunctions.py
@@ -115,14 +115,6 @@ class TestRecFunctions(object):
test = get_names(ndtype)
assert_equal(test, ('a', ('b', ('ba', 'bb'))))
- ndtype = np.dtype([('a', int), ('b', [])])
- test = get_names(ndtype)
- assert_equal(test, ('a', ('b', ())))
-
- ndtype = np.dtype([])
- test = get_names(ndtype)
- assert_equal(test, ())
-
def test_get_names_flat(self):
# Test get_names_flat
ndtype = np.dtype([('A', '|S3'), ('B', float)])
@@ -133,14 +125,6 @@ class TestRecFunctions(object):
test = get_names_flat(ndtype)
assert_equal(test, ('a', 'b', 'ba', 'bb'))
- ndtype = np.dtype([('a', int), ('b', [])])
- test = get_names_flat(ndtype)
- assert_equal(test, ('a', 'b'))
-
- ndtype = np.dtype([])
- test = get_names_flat(ndtype)
- assert_equal(test, ())
-
def test_get_fieldstructure(self):
# Test get_fieldstructure
@@ -163,11 +147,6 @@ class TestRecFunctions(object):
'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
assert_equal(test, control)
- # 0 fields
- ndtype = np.dtype([])
- test = get_fieldstructure(ndtype)
- assert_equal(test, {})
-
def test_find_duplicates(self):
# Test find_duplicates
a = ma.array([(2, (2., 'B')), (1, (2., 'B')), (2, (2., 'B')),
@@ -269,8 +248,7 @@ class TestRecFunctions(object):
# including uniform fields with subarrays unpacked
d = np.array([(1, [2, 3], [[ 4, 5], [ 6, 7]]),
(8, [9, 10], [[11, 12], [13, 14]])],
- dtype=[('x0', 'i4'), ('x1', ('i4', 2)),
- ('x2', ('i4', (2, 2)))])
+ dtype=[('x0', 'i4'), ('x1', ('i4', 2)), ('x2', ('i4', (2, 2)))])
dd = structured_to_unstructured(d)
ddd = unstructured_to_structured(dd, d.dtype)
assert_(dd.base is d)
@@ -284,40 +262,6 @@ class TestRecFunctions(object):
assert_equal(res, np.zeros((10, 6), dtype=int))
- # test nested combinations of subarrays and structured arrays, gh-13333
- def subarray(dt, shape):
- return np.dtype((dt, shape))
-
- def structured(*dts):
- return np.dtype([('x{}'.format(i), dt) for i, dt in enumerate(dts)])
-
- def inspect(dt, dtype=None):
- arr = np.zeros((), dt)
- ret = structured_to_unstructured(arr, dtype=dtype)
- backarr = unstructured_to_structured(ret, dt)
- return ret.shape, ret.dtype, backarr.dtype
-
- dt = structured(subarray(structured(np.int32, np.int32), 3))
- assert_equal(inspect(dt), ((6,), np.int32, dt))
-
- dt = structured(subarray(subarray(np.int32, 2), 2))
- assert_equal(inspect(dt), ((4,), np.int32, dt))
-
- dt = structured(np.int32)
- assert_equal(inspect(dt), ((1,), np.int32, dt))
-
- dt = structured(np.int32, subarray(subarray(np.int32, 2), 2))
- assert_equal(inspect(dt), ((5,), np.int32, dt))
-
- dt = structured()
- assert_raises(ValueError, structured_to_unstructured, np.zeros(3, dt))
-
- # these currently don't work, but we may make it work in the future
- assert_raises(NotImplementedError, structured_to_unstructured,
- np.zeros(3, dt), dtype=np.int32)
- assert_raises(NotImplementedError, unstructured_to_structured,
- np.zeros((3,0), dtype=np.int32))
-
def test_field_assignment_by_name(self):
a = np.ones(2, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')])
newdt = [('b', 'f4'), ('c', 'u1')]
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
index b2bd7da3e..85fcceedc 100644
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -4,7 +4,7 @@ import numpy as np
from numpy.core._rational_tests import rational
from numpy.testing import (
assert_equal, assert_array_equal, assert_raises, assert_,
- assert_raises_regex
+ assert_raises_regex, assert_warns,
)
from numpy.lib.stride_tricks import (
as_strided, broadcast_arrays, _broadcast_shape, broadcast_to
@@ -415,12 +415,32 @@ def test_writeable():
assert_equal(result.flags.writeable, False)
assert_raises(ValueError, result.__setitem__, slice(None), 0)
- # but the result of broadcast_arrays needs to be writeable (for now), to
+ # but the result of broadcast_arrays needs to be writeable, to
# preserve backwards compatibility
+ for is_broadcast, results in [(False, broadcast_arrays(original,)),
+ (True, broadcast_arrays(0, original))]:
+ for result in results:
+ # This will change to False in a future version
+ if is_broadcast:
+ with assert_warns(FutureWarning):
+ assert_equal(result.flags.writeable, True)
+ with assert_warns(DeprecationWarning):
+ result[:] = 0
+ # Warning not emitted, writing to the array resets it
+ assert_equal(result.flags.writeable, True)
+ else:
+ # No warning:
+ assert_equal(result.flags.writeable, True)
+
for results in [broadcast_arrays(original),
broadcast_arrays(0, original)]:
for result in results:
+ # resets the warn_on_write DeprecationWarning
+ result.flags.writeable = True
+ # check: no warning emitted
assert_equal(result.flags.writeable, True)
+ result[:] = 0
+
# keep readonly input readonly
original.flags.writeable = False
_, result = broadcast_arrays(0, original)
@@ -435,6 +455,25 @@ def test_writeable():
assert_(first.shape == second.shape)
+def test_writeable_memoryview():
+ # The result of broadcast_arrays exports as a non-writeable memoryview
+ # because otherwise there is no good way to opt in to the new behaviour
+ # (i.e. you would need to set writeable to False explicitly).
+ # See gh-13929.
+ original = np.array([1, 2, 3])
+
+ for is_broadcast, results in [(False, broadcast_arrays(original,)),
+ (True, broadcast_arrays(0, original))]:
+ for result in results:
+ # This will change to False in a future version
+ if is_broadcast:
+ # memoryview(result, writable=True) will give warning but cannot
+ # be tested using the python API.
+ assert memoryview(result).readonly
+ else:
+ assert not memoryview(result).readonly
+
+
def test_reference_types():
input_array = np.array('a', dtype=object)
expected = np.array(['a'] * 3, dtype=object)
diff --git a/numpy/lib/tests/test_twodim_base.py b/numpy/lib/tests/test_twodim_base.py
index fe1348d28..bb844e4bd 100644
--- a/numpy/lib/tests/test_twodim_base.py
+++ b/numpy/lib/tests/test_twodim_base.py
@@ -278,7 +278,7 @@ class TestHistogram2d(object):
@requires_array_function
def test_dispatch(self):
- class ShouldDispatch(object):
+ class ShouldDispatch:
def __array_function__(self, function, types, args, kwargs):
return types, args, kwargs
diff --git a/numpy/lib/tests/test_type_check.py b/numpy/lib/tests/test_type_check.py
index 2982ca31a..b3f114b92 100644
--- a/numpy/lib/tests/test_type_check.py
+++ b/numpy/lib/tests/test_type_check.py
@@ -360,6 +360,14 @@ class TestNanToNum(object):
assert_(vals[1] == 0)
assert_all(vals[2] > 1e10) and assert_all(np.isfinite(vals[2]))
assert_equal(type(vals), np.ndarray)
+
+ # perform the same tests but with nan, posinf and neginf keywords
+ with np.errstate(divide='ignore', invalid='ignore'):
+ vals = nan_to_num(np.array((-1., 0, 1))/0.,
+ nan=10, posinf=20, neginf=30)
+ assert_equal(vals, [30, 10, 20])
+ assert_all(np.isfinite(vals[[0, 2]]))
+ assert_equal(type(vals), np.ndarray)
# perform the same test but in-place
with np.errstate(divide='ignore', invalid='ignore'):
@@ -371,26 +379,48 @@ class TestNanToNum(object):
assert_(vals[1] == 0)
assert_all(vals[2] > 1e10) and assert_all(np.isfinite(vals[2]))
assert_equal(type(vals), np.ndarray)
+
+ # perform the same test but in-place
+ with np.errstate(divide='ignore', invalid='ignore'):
+ vals = np.array((-1., 0, 1))/0.
+ result = nan_to_num(vals, copy=False, nan=10, posinf=20, neginf=30)
+
+ assert_(result is vals)
+ assert_equal(vals, [30, 10, 20])
+ assert_all(np.isfinite(vals[[0, 2]]))
+ assert_equal(type(vals), np.ndarray)
def test_array(self):
vals = nan_to_num([1])
assert_array_equal(vals, np.array([1], int))
assert_equal(type(vals), np.ndarray)
+ vals = nan_to_num([1], nan=10, posinf=20, neginf=30)
+ assert_array_equal(vals, np.array([1], int))
+ assert_equal(type(vals), np.ndarray)
def test_integer(self):
vals = nan_to_num(1)
assert_all(vals == 1)
assert_equal(type(vals), np.int_)
+ vals = nan_to_num(1, nan=10, posinf=20, neginf=30)
+ assert_all(vals == 1)
+ assert_equal(type(vals), np.int_)
def test_float(self):
vals = nan_to_num(1.0)
assert_all(vals == 1.0)
assert_equal(type(vals), np.float_)
+ vals = nan_to_num(1.1, nan=10, posinf=20, neginf=30)
+ assert_all(vals == 1.1)
+ assert_equal(type(vals), np.float_)
def test_complex_good(self):
vals = nan_to_num(1+1j)
assert_all(vals == 1+1j)
assert_equal(type(vals), np.complex_)
+ vals = nan_to_num(1+1j, nan=10, posinf=20, neginf=30)
+ assert_all(vals == 1+1j)
+ assert_equal(type(vals), np.complex_)
def test_complex_bad(self):
with np.errstate(divide='ignore', invalid='ignore'):
@@ -414,6 +444,16 @@ class TestNanToNum(object):
# !! inf. Comment out for now, and see if it
# !! changes
#assert_all(vals.real < -1e10) and assert_all(np.isfinite(vals))
+
+ def test_do_not_rewrite_previous_keyword(self):
+ # This is done to test that when, for instance, nan=np.inf then these
+ # values are not rewritten by posinf keyword to the posinf value.
+ with np.errstate(divide='ignore', invalid='ignore'):
+ vals = nan_to_num(np.array((-1., 0, 1))/0., nan=np.inf, posinf=999)
+ assert_all(np.isfinite(vals[[0, 2]]))
+ assert_all(vals[0] < -1e10)
+ assert_equal(vals[[1, 2]], [np.inf, 999])
+ assert_equal(type(vals), np.ndarray)
class TestRealIfClose(object):
diff --git a/numpy/lib/tests/test_utils.py b/numpy/lib/tests/test_utils.py
index 2723f3440..9673a05fa 100644
--- a/numpy/lib/tests/test_utils.py
+++ b/numpy/lib/tests/test_utils.py
@@ -1,5 +1,6 @@
from __future__ import division, absolute_import, print_function
+import inspect
import sys
import pytest
@@ -38,6 +39,32 @@ def old_func3(self, x):
new_func3 = deprecate(old_func3, old_name="old_func3", new_name="new_func3")
+def old_func4(self, x):
+ """Summary.
+
+ Further info.
+ """
+ return x
+new_func4 = deprecate(old_func4)
+
+
+def old_func5(self, x):
+ """Summary.
+
+ Bizarre indentation.
+ """
+ return x
+new_func5 = deprecate(old_func5)
+
+
+def old_func6(self, x):
+ """
+ Also in PEP-257.
+ """
+ return x
+new_func6 = deprecate(old_func6)
+
+
def test_deprecate_decorator():
assert_('deprecated' in old_func.__doc__)
@@ -51,6 +78,25 @@ def test_deprecate_fn():
assert_('new_func3' in new_func3.__doc__)
+@pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings")
+def test_deprecate_help_indentation():
+ _compare_docs(old_func4, new_func4)
+ _compare_docs(old_func5, new_func5)
+ _compare_docs(old_func6, new_func6)
+
+
+def _compare_docs(old_func, new_func):
+ old_doc = inspect.getdoc(old_func)
+ new_doc = inspect.getdoc(new_func)
+ index = new_doc.index('\n\n') + 2
+ assert_equal(new_doc[index:], old_doc)
+
+
+@pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings")
+def test_deprecate_preserve_whitespace():
+ assert_('\n Bizarre' in new_func5.__doc__)
+
+
def test_safe_eval_nameconstant():
# Test if safe_eval supports Python 3.4 _ast.NameConstant
utils.safe_eval('None')
diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py
index a058070e5..f3dc6c8e1 100644
--- a/numpy/lib/twodim_base.py
+++ b/numpy/lib/twodim_base.py
@@ -77,13 +77,13 @@ def fliplr(m):
--------
>>> A = np.diag([1.,2.,3.])
>>> A
- array([[ 1., 0., 0.],
- [ 0., 2., 0.],
- [ 0., 0., 3.]])
+ array([[1., 0., 0.],
+ [0., 2., 0.],
+ [0., 0., 3.]])
>>> np.fliplr(A)
- array([[ 0., 0., 1.],
- [ 0., 2., 0.],
- [ 3., 0., 0.]])
+ array([[0., 0., 1.],
+ [0., 2., 0.],
+ [3., 0., 0.]])
>>> A = np.random.randn(2,3,5)
>>> np.all(np.fliplr(A) == A[:,::-1,...])
@@ -129,13 +129,13 @@ def flipud(m):
--------
>>> A = np.diag([1.0, 2, 3])
>>> A
- array([[ 1., 0., 0.],
- [ 0., 2., 0.],
- [ 0., 0., 3.]])
+ array([[1., 0., 0.],
+ [0., 2., 0.],
+ [0., 0., 3.]])
>>> np.flipud(A)
- array([[ 0., 0., 3.],
- [ 0., 2., 0.],
- [ 1., 0., 0.]])
+ array([[0., 0., 3.],
+ [0., 2., 0.],
+ [1., 0., 0.]])
>>> A = np.random.randn(2,3,5)
>>> np.all(np.flipud(A) == A[::-1,...])
@@ -191,9 +191,9 @@ def eye(N, M=None, k=0, dtype=float, order='C'):
array([[1, 0],
[0, 1]])
>>> np.eye(3, k=1)
- array([[ 0., 1., 0.],
- [ 0., 0., 1.],
- [ 0., 0., 0.]])
+ array([[0., 1., 0.],
+ [0., 0., 1.],
+ [0., 0., 0.]])
"""
if M is None:
@@ -378,9 +378,9 @@ def tri(N, M=None, k=0, dtype=float):
[1, 1, 1, 1, 1]])
>>> np.tri(3, 5, -1)
- array([[ 0., 0., 0., 0., 0.],
- [ 1., 0., 0., 0., 0.],
- [ 1., 1., 0., 0., 0.]])
+ array([[0., 0., 0., 0., 0.],
+ [1., 0., 0., 0., 0.],
+ [1., 1., 0., 0., 0.]])
"""
if M is None:
@@ -540,7 +540,7 @@ def vander(x, N=None, increasing=False):
of the differences between the values of the input vector:
>>> np.linalg.det(np.vander(x))
- 48.000000000000043
+ 48.000000000000043 # may vary
>>> (5-3)*(5-2)*(5-1)*(3-2)*(3-1)*(2-1)
48
@@ -574,8 +574,7 @@ def _histogram2d_dispatcher(x, y, bins=None, range=None, normed=None,
except TypeError:
N = 1
if N == 2:
- for b in bins:
- yield b
+ yield from bins # bins=[x, y]
else:
yield bins
@@ -680,6 +679,7 @@ def histogram2d(x, y, bins=10, range=None, normed=None, weights=None,
>>> ax = fig.add_subplot(131, title='imshow: square bins')
>>> plt.imshow(H, interpolation='nearest', origin='low',
... extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
+ <matplotlib.image.AxesImage object at 0x...>
:func:`pcolormesh <matplotlib.pyplot.pcolormesh>` can display actual edges:
@@ -687,6 +687,7 @@ def histogram2d(x, y, bins=10, range=None, normed=None, weights=None,
... aspect='equal')
>>> X, Y = np.meshgrid(xedges, yedges)
>>> ax.pcolormesh(X, Y, H)
+ <matplotlib.collections.QuadMesh object at 0x...>
:class:`NonUniformImage <matplotlib.image.NonUniformImage>` can be used to
display actual bin edges with interpolation:
@@ -843,7 +844,7 @@ def tril_indices(n, k=0, m=None):
Both for indexing:
>>> a[il1]
- array([ 0, 4, 5, 8, 9, 10, 12, 13, 14, 15])
+ array([ 0, 4, 5, ..., 13, 14, 15])
And for assigning values:
@@ -958,7 +959,7 @@ def triu_indices(n, k=0, m=None):
Both for indexing:
>>> a[iu1]
- array([ 0, 1, 2, 3, 5, 6, 7, 10, 11, 15])
+ array([ 0, 1, 2, ..., 10, 11, 15])
And for assigning values:
diff --git a/numpy/lib/type_check.py b/numpy/lib/type_check.py
index 90b1e9a6e..ac4b03a6c 100644
--- a/numpy/lib/type_check.py
+++ b/numpy/lib/type_check.py
@@ -105,11 +105,11 @@ def asfarray(a, dtype=_nx.float_):
Examples
--------
>>> np.asfarray([2, 3])
- array([ 2., 3.])
+ array([2., 3.])
>>> np.asfarray([2, 3], dtype='float')
- array([ 2., 3.])
+ array([2., 3.])
>>> np.asfarray([2, 3], dtype='int8')
- array([ 2., 3.])
+ array([2., 3.])
"""
if not _nx.issubdtype(dtype, _nx.inexact):
@@ -146,13 +146,13 @@ def real(val):
--------
>>> a = np.array([1+2j, 3+4j, 5+6j])
>>> a.real
- array([ 1., 3., 5.])
+ array([1., 3., 5.])
>>> a.real = 9
>>> a
- array([ 9.+2.j, 9.+4.j, 9.+6.j])
+ array([9.+2.j, 9.+4.j, 9.+6.j])
>>> a.real = np.array([9, 8, 7])
>>> a
- array([ 9.+2.j, 8.+4.j, 7.+6.j])
+ array([9.+2.j, 8.+4.j, 7.+6.j])
>>> np.real(1 + 1j)
1.0
@@ -192,10 +192,10 @@ def imag(val):
--------
>>> a = np.array([1+2j, 3+4j, 5+6j])
>>> a.imag
- array([ 2., 4., 6.])
+ array([2., 4., 6.])
>>> a.imag = np.array([8, 10, 12])
>>> a
- array([ 1. +8.j, 3.+10.j, 5.+12.j])
+ array([1. +8.j, 3.+10.j, 5.+12.j])
>>> np.imag(1 + 1j)
1.0
@@ -363,18 +363,23 @@ def _getmaxmin(t):
return f.max, f.min
-def _nan_to_num_dispatcher(x, copy=None):
+def _nan_to_num_dispatcher(x, copy=None, nan=None, posinf=None, neginf=None):
return (x,)
@array_function_dispatch(_nan_to_num_dispatcher)
-def nan_to_num(x, copy=True):
+def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None):
"""
- Replace NaN with zero and infinity with large finite numbers.
+ Replace NaN with zero and infinity with large finite numbers (default
+ behaviour) or with the numbers defined by the user using the `nan`,
+ `posinf` and/or `neginf` keywords.
- If `x` is inexact, NaN is replaced by zero, and infinity and -infinity
- replaced by the respectively largest and most negative finite floating
- point values representable by ``x.dtype``.
+ If `x` is inexact, NaN is replaced by zero or by the user defined value in
+ `nan` keyword, infinity is replaced by the largest finite floating point
+ values representable by ``x.dtype`` or by the user defined value in
+ `posinf` keyword and -infinity is replaced by the most negative finite
+ floating point values representable by ``x.dtype`` or by the user defined
+ value in `neginf` keyword.
For complex dtypes, the above is applied to each of the real and
imaginary components of `x` separately.
@@ -390,6 +395,17 @@ def nan_to_num(x, copy=True):
in-place (False). The in-place operation only occurs if
casting to an array does not require a copy.
Default is True.
+ nan : int, float, optional
+ Value to be used to fill NaN values. If no value is passed
+ then NaN values will be replaced with 0.0.
+ posinf : int, float, optional
+ Value to be used to fill positive infinity values. If no value is
+ passed then positive infinity values will be replaced with a very
+ large number.
+ neginf : int, float, optional
+ Value to be used to fill negative infinity values. If no value is
+ passed then negative infinity values will be replaced with a very
+ small (or negative) number.
.. versionadded:: 1.13
@@ -422,13 +438,20 @@ def nan_to_num(x, copy=True):
0.0
>>> x = np.array([np.inf, -np.inf, np.nan, -128, 128])
>>> np.nan_to_num(x)
- array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000,
- -1.28000000e+002, 1.28000000e+002])
+ array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000, # may vary
+ -1.28000000e+002, 1.28000000e+002])
+ >>> np.nan_to_num(x, nan=-9999, posinf=33333333, neginf=33333333)
+ array([ 3.3333333e+07, 3.3333333e+07, -9.9990000e+03,
+ -1.2800000e+02, 1.2800000e+02])
>>> y = np.array([complex(np.inf, np.nan), np.nan, complex(np.nan, np.inf)])
+ array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000, # may vary
+ -1.28000000e+002, 1.28000000e+002])
>>> np.nan_to_num(y)
- array([ 1.79769313e+308 +0.00000000e+000j,
+ array([ 1.79769313e+308 +0.00000000e+000j, # may vary
0.00000000e+000 +0.00000000e+000j,
0.00000000e+000 +1.79769313e+308j])
+ >>> np.nan_to_num(y, nan=111111, posinf=222222)
+ array([222222.+111111.j, 111111. +0.j, 111111.+222222.j])
"""
x = _nx.array(x, subok=True, copy=copy)
xtype = x.dtype.type
@@ -442,10 +465,17 @@ def nan_to_num(x, copy=True):
dest = (x.real, x.imag) if iscomplex else (x,)
maxf, minf = _getmaxmin(x.real.dtype)
+ if posinf is not None:
+ maxf = posinf
+ if neginf is not None:
+ minf = neginf
for d in dest:
- _nx.copyto(d, 0.0, where=isnan(d))
- _nx.copyto(d, maxf, where=isposinf(d))
- _nx.copyto(d, minf, where=isneginf(d))
+ idx_nan = isnan(d)
+ idx_posinf = isposinf(d)
+ idx_neginf = isneginf(d)
+ _nx.copyto(d, nan, where=idx_nan)
+ _nx.copyto(d, maxf, where=idx_posinf)
+ _nx.copyto(d, minf, where=idx_neginf)
return x[()] if isscalar else x
#-----------------------------------------------------------------------------
@@ -490,12 +520,12 @@ def real_if_close(a, tol=100):
Examples
--------
>>> np.finfo(float).eps
- 2.2204460492503131e-16
+ 2.2204460492503131e-16 # may vary
>>> np.real_if_close([2.1 + 4e-14j], tol=1000)
- array([ 2.1])
+ array([2.1])
>>> np.real_if_close([2.1 + 4e-13j], tol=1000)
- array([ 2.1 +4.00000000e-13j])
+ array([2.1+4.e-13j])
"""
a = asanyarray(a)
@@ -511,6 +541,9 @@ def real_if_close(a, tol=100):
def _asscalar_dispatcher(a):
+ # 2018-10-10, 1.16
+ warnings.warn('np.asscalar(a) is deprecated since NumPy v1.16, use '
+ 'a.item() instead', DeprecationWarning, stacklevel=3)
return (a,)
@@ -538,12 +571,7 @@ def asscalar(a):
--------
>>> np.asscalar(np.array([24]))
24
-
"""
-
- # 2018-10-10, 1.16
- warnings.warn('np.asscalar(a) is deprecated since NumPy v1.16, use '
- 'a.item() instead', DeprecationWarning, stacklevel=1)
return a.item()
#-----------------------------------------------------------------------------
@@ -672,11 +700,11 @@ def common_type(*arrays):
Examples
--------
>>> np.common_type(np.arange(2, dtype=np.float32))
- <type 'numpy.float32'>
+ <class 'numpy.float32'>
>>> np.common_type(np.arange(2, dtype=np.float32), np.arange(2))
- <type 'numpy.float64'>
+ <class 'numpy.float64'>
>>> np.common_type(np.arange(4), np.array([45, 6.j]), np.array([45.0]))
- <type 'numpy.complex128'>
+ <class 'numpy.complex128'>
"""
is_complex = False
diff --git a/numpy/lib/ufunclike.py b/numpy/lib/ufunclike.py
index 9a9e6f9dd..96fd5b319 100644
--- a/numpy/lib/ufunclike.py
+++ b/numpy/lib/ufunclike.py
@@ -8,7 +8,9 @@ from __future__ import division, absolute_import, print_function
__all__ = ['fix', 'isneginf', 'isposinf']
import numpy.core.numeric as nx
-from numpy.core.overrides import array_function_dispatch, ENABLE_ARRAY_FUNCTION
+from numpy.core.overrides import (
+ array_function_dispatch, ARRAY_FUNCTION_ENABLED,
+)
import warnings
import functools
@@ -43,7 +45,7 @@ def _fix_out_named_y(f):
Allow the out argument to be passed as the name `y` (deprecated)
This decorator should only be used if _deprecate_out_named_y is used on
- a corresponding dispatcher fucntion.
+ a corresponding dispatcher function.
"""
@functools.wraps(f)
def func(x, out=None, **kwargs):
@@ -55,8 +57,14 @@ def _fix_out_named_y(f):
return func
-if not ENABLE_ARRAY_FUNCTION:
- _fix_out_named_y = _deprecate_out_named_y
+def _fix_and_maybe_deprecate_out_named_y(f):
+ """
+ Use the appropriate decorator, depending upon if dispatching is being used.
+ """
+ if ARRAY_FUNCTION_ENABLED:
+ return _fix_out_named_y(f)
+ else:
+ return _deprecate_out_named_y(f)
@_deprecate_out_named_y
@@ -65,7 +73,7 @@ def _dispatcher(x, out=None):
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
-@_fix_out_named_y
+@_fix_and_maybe_deprecate_out_named_y
def fix(x, out=None):
"""
Round to nearest integer towards zero.
@@ -112,7 +120,7 @@ def fix(x, out=None):
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
-@_fix_out_named_y
+@_fix_and_maybe_deprecate_out_named_y
def isposinf(x, out=None):
"""
Test element-wise for positive infinity, return result as bool array.
@@ -154,11 +162,11 @@ def isposinf(x, out=None):
Examples
--------
>>> np.isposinf(np.PINF)
- array(True, dtype=bool)
+ True
>>> np.isposinf(np.inf)
- array(True, dtype=bool)
+ True
>>> np.isposinf(np.NINF)
- array(False, dtype=bool)
+ False
>>> np.isposinf([-np.inf, 0., np.inf])
array([False, False, True])
@@ -181,7 +189,7 @@ def isposinf(x, out=None):
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
-@_fix_out_named_y
+@_fix_and_maybe_deprecate_out_named_y
def isneginf(x, out=None):
"""
Test element-wise for negative infinity, return result as bool array.
@@ -224,11 +232,11 @@ def isneginf(x, out=None):
Examples
--------
>>> np.isneginf(np.NINF)
- array(True, dtype=bool)
+ True
>>> np.isneginf(np.inf)
- array(False, dtype=bool)
+ False
>>> np.isneginf(np.PINF)
- array(False, dtype=bool)
+ False
>>> np.isneginf([-np.inf, 0., np.inf])
array([ True, False, False])
diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py
index 84edf4021..c7dbcc5f9 100644
--- a/numpy/lib/utils.py
+++ b/numpy/lib/utils.py
@@ -105,6 +105,20 @@ class _Deprecate(object):
if doc is None:
doc = depdoc
else:
+ lines = doc.expandtabs().split('\n')
+ indent = _get_indent(lines[1:])
+ if lines[0].lstrip():
+ # Indent the original first line to let inspect.cleandoc()
+ # dedent the docstring despite the deprecation notice.
+ doc = indent * ' ' + doc
+ else:
+ # Remove the same leading blank lines as cleandoc() would.
+ skip = len(lines[0]) + 1
+ for line in lines[1:]:
+ if len(line) > indent:
+ break
+ skip += len(line) + 1
+ doc = doc[skip:]
doc = '\n\n'.join([depdoc, doc])
newfunc.__doc__ = doc
try:
@@ -115,6 +129,21 @@ class _Deprecate(object):
newfunc.__dict__.update(d)
return newfunc
+
+def _get_indent(lines):
+ """
+ Determines the leading whitespace that could be removed from all the lines.
+ """
+ indent = sys.maxsize
+ for line in lines:
+ content = len(line.lstrip())
+ if content:
+ indent = min(indent, len(line) - content)
+ if indent == sys.maxsize:
+ indent = 0
+ return indent
+
+
def deprecate(*args, **kwargs):
"""
Issues a DeprecationWarning, adds warning to `old_name`'s
@@ -150,10 +179,8 @@ def deprecate(*args, **kwargs):
Warning:
>>> olduint = np.deprecate(np.uint)
+ DeprecationWarning: `uint64` is deprecated! # may vary
>>> olduint(6)
- /usr/lib/python2.5/site-packages/numpy/lib/utils.py:114:
- DeprecationWarning: uint32 is deprecated
- warnings.warn(str1, DeprecationWarning, stacklevel=2)
6
"""
@@ -201,8 +228,8 @@ def byte_bounds(a):
>>> low, high = np.byte_bounds(I)
>>> high - low == I.size*I.itemsize
True
- >>> I = np.eye(2, dtype='G'); I.dtype
- dtype('complex192')
+ >>> I = np.eye(2); I.dtype
+ dtype('float64')
>>> low, high = np.byte_bounds(I)
>>> high - low == I.size*I.itemsize
True
@@ -263,17 +290,17 @@ def who(vardict=None):
>>> np.who()
Name Shape Bytes Type
===========================================================
- a 10 40 int32
+ a 10 80 int64
b 20 160 float64
- Upper bound on total bytes = 200
+ Upper bound on total bytes = 240
>>> d = {'x': np.arange(2.0), 'y': np.arange(3.0), 'txt': 'Some str',
... 'idx':5}
>>> np.who(d)
Name Shape Bytes Type
===========================================================
- y 3 24 float64
x 2 16 float64
+ y 3 24 float64
Upper bound on total bytes = 40
"""
@@ -733,7 +760,7 @@ def lookfor(what, module=None, import_modules=True, regenerate=False,
Examples
--------
- >>> np.lookfor('binary representation')
+ >>> np.lookfor('binary representation') # doctest: +SKIP
Search results for 'binary representation'
------------------------------------------
numpy.binary_repr
@@ -1104,12 +1131,11 @@ def safe_eval(source):
>>> np.safe_eval('open("/home/user/.ssh/id_dsa").read()')
Traceback (most recent call last):
...
- SyntaxError: Unsupported source construct: compiler.ast.CallFunc
+ ValueError: malformed node or string: <_ast.Call object at 0x...>
"""
# Local import to speed up numpy's import time.
import ast
-
return ast.literal_eval(source)
@@ -1142,17 +1168,12 @@ def _median_nancheck(data, result, axis, out):
n = n.filled(False)
if result.ndim == 0:
if n == True:
- warnings.warn("Invalid value encountered in median",
- RuntimeWarning, stacklevel=3)
if out is not None:
out[...] = data.dtype.type(np.nan)
result = out
else:
result = data.dtype.type(np.nan)
elif np.count_nonzero(n.ravel()) > 0:
- warnings.warn("Invalid value encountered in median for" +
- " %d results" % np.count_nonzero(n.ravel()),
- RuntimeWarning, stacklevel=3)
result[n] = np.nan
return result
diff --git a/numpy/linalg/lapack_lite/clapack_scrub.py b/numpy/linalg/lapack_lite/clapack_scrub.py
index e72a39e64..434586113 100644
--- a/numpy/linalg/lapack_lite/clapack_scrub.py
+++ b/numpy/linalg/lapack_lite/clapack_scrub.py
@@ -294,9 +294,8 @@ def scrubSource(source, nsteps=None, verbose=False):
if __name__ == '__main__':
filename = sys.argv[1]
outfilename = os.path.join(sys.argv[2], os.path.basename(filename))
- fo = open(filename, 'r')
- source = fo.read()
- fo.close()
+ with open(filename, 'r') as fo:
+ source = fo.read()
if len(sys.argv) > 3:
nsteps = int(sys.argv[3])
diff --git a/numpy/linalg/lapack_lite/fortran.py b/numpy/linalg/lapack_lite/fortran.py
index 3b6ac70f0..87c27aab9 100644
--- a/numpy/linalg/lapack_lite/fortran.py
+++ b/numpy/linalg/lapack_lite/fortran.py
@@ -110,15 +110,14 @@ def getDependencies(filename):
"""For a Fortran source file, return a list of routines declared as EXTERNAL
in it.
"""
- fo = open(filename)
external_pat = re.compile(r'^\s*EXTERNAL\s', re.I)
routines = []
- for lineno, line in fortranSourceLines(fo):
- m = external_pat.match(line)
- if m:
- names = line = line[m.end():].strip().split(',')
- names = [n.strip().lower() for n in names]
- names = [n for n in names if n]
- routines.extend(names)
- fo.close()
+ with open(filename) as fo:
+ for lineno, line in fortranSourceLines(fo):
+ m = external_pat.match(line)
+ if m:
+ names = line = line[m.end():].strip().split(',')
+ names = [n.strip().lower() for n in names]
+ names = [n for n in names if n]
+ routines.extend(names)
return routines
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py
index 8363d7377..c90e25686 100644
--- a/numpy/linalg/linalg.py
+++ b/numpy/linalg/linalg.py
@@ -26,7 +26,7 @@ from numpy.core import (
add, multiply, sqrt, fastCopyAndTranspose, sum, isfinite,
finfo, errstate, geterrobj, moveaxis, amin, amax, product, abs,
atleast_2d, intp, asanyarray, object_, matmul,
- swapaxes, divide, count_nonzero, isnan
+ swapaxes, divide, count_nonzero, isnan, sign
)
from numpy.core.multiarray import normalize_axis_index
from numpy.core.overrides import set_module
@@ -357,7 +357,7 @@ def solve(a, b):
Broadcasting rules apply, see the `numpy.linalg` documentation for
details.
- The solutions are computed using LAPACK routine _gesv
+ The solutions are computed using LAPACK routine ``_gesv``.
`a` must be square and of full-rank, i.e., all rows (or, equivalently,
columns) must be linearly independent; if either is not true, use
@@ -377,7 +377,7 @@ def solve(a, b):
>>> b = np.array([9,8])
>>> x = np.linalg.solve(a, b)
>>> x
- array([ 2., 3.])
+ array([2., 3.])
Check that the solution is correct:
@@ -535,10 +535,10 @@ def inv(a):
>>> a = np.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]])
>>> inv(a)
- array([[[-2. , 1. ],
- [ 1.5, -0.5]],
- [[-5. , 2. ],
- [ 3. , -1. ]]])
+ array([[[-2. , 1. ],
+ [ 1.5 , -0.5 ]],
+ [[-1.25, 0.75],
+ [ 0.75, -0.25]]])
"""
a, wrap = _makearray(a)
@@ -571,7 +571,7 @@ def matrix_power(a, n):
Parameters
----------
a : (..., M, M) array_like
- Matrix to be "powered."
+ Matrix to be "powered".
n : int
The exponent can be any integer or long integer, positive,
negative, or zero.
@@ -730,21 +730,21 @@ def cholesky(a):
--------
>>> A = np.array([[1,-2j],[2j,5]])
>>> A
- array([[ 1.+0.j, 0.-2.j],
+ array([[ 1.+0.j, -0.-2.j],
[ 0.+2.j, 5.+0.j]])
>>> L = np.linalg.cholesky(A)
>>> L
- array([[ 1.+0.j, 0.+0.j],
- [ 0.+2.j, 1.+0.j]])
+ array([[1.+0.j, 0.+0.j],
+ [0.+2.j, 1.+0.j]])
>>> np.dot(L, L.T.conj()) # verify that L * L.H = A
- array([[ 1.+0.j, 0.-2.j],
- [ 0.+2.j, 5.+0.j]])
+ array([[1.+0.j, 0.-2.j],
+ [0.+2.j, 5.+0.j]])
>>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?
>>> np.linalg.cholesky(A) # an ndarray object is returned
- array([[ 1.+0.j, 0.+0.j],
- [ 0.+2.j, 1.+0.j]])
+ array([[1.+0.j, 0.+0.j],
+ [0.+2.j, 1.+0.j]])
>>> # But a matrix object is returned if A is a matrix object
- >>> LA.cholesky(np.matrix(A))
+ >>> np.linalg.cholesky(np.matrix(A))
matrix([[ 1.+0.j, 0.+0.j],
[ 0.+2.j, 1.+0.j]])
@@ -820,8 +820,8 @@ def qr(a, mode='reduced'):
Notes
-----
- This is an interface to the LAPACK routines dgeqrf, zgeqrf,
- dorgqr, and zungqr.
+ This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``,
+ ``dorgqr``, and ``zungqr``.
For more information on the qr factorization, see for example:
https://en.wikipedia.org/wiki/QR_factorization
@@ -878,9 +878,9 @@ def qr(a, mode='reduced'):
[1, 1],
[2, 1]])
>>> b = np.array([1, 0, 2, 1])
- >>> q, r = LA.qr(A)
+ >>> q, r = np.linalg.qr(A)
>>> p = np.dot(q.T, b)
- >>> np.dot(LA.inv(r), p)
+ >>> np.dot(np.linalg.inv(r), p)
array([ 1.1e-16, 1.0e+00])
"""
@@ -890,12 +890,12 @@ def qr(a, mode='reduced'):
msg = "".join((
"The 'full' option is deprecated in favor of 'reduced'.\n",
"For backward compatibility let mode default."))
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ warnings.warn(msg, DeprecationWarning, stacklevel=3)
mode = 'reduced'
elif mode in ('e', 'economic'):
# 2013-04-01, 1.8
msg = "The 'economic' option is deprecated."
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ warnings.warn(msg, DeprecationWarning, stacklevel=3)
mode = 'economic'
else:
raise ValueError("Unrecognized mode '%s'" % mode)
@@ -1010,7 +1010,7 @@ def eigvals(a):
See Also
--------
eig : eigenvalues and right eigenvectors of general arrays
- eigvalsh : eigenvalues of real symmetric or complex Hermitian
+ eigvalsh : eigenvalues of real symmetric or complex Hermitian
(conjugate symmetric) arrays.
eigh : eigenvalues and eigenvectors of real symmetric or complex
Hermitian (conjugate symmetric) arrays.
@@ -1023,7 +1023,7 @@ def eigvals(a):
Broadcasting rules apply, see the `numpy.linalg` documentation for
details.
- This is implemented using the _geev LAPACK routines which compute
+ This is implemented using the ``_geev`` LAPACK routines which compute
the eigenvalues and eigenvectors of general square arrays.
Examples
@@ -1041,7 +1041,7 @@ def eigvals(a):
>>> LA.norm(Q[0, :]), LA.norm(Q[1, :]), np.dot(Q[0, :],Q[1, :])
(1.0, 1.0, 0.0)
- Now multiply a diagonal matrix by Q on one side and by Q.T on the other:
+ Now multiply a diagonal matrix by ``Q`` on one side and by ``Q.T`` on the other:
>>> D = np.diag((-1,1))
>>> LA.eigvals(D)
@@ -1049,7 +1049,7 @@ def eigvals(a):
>>> A = np.dot(Q, D)
>>> A = np.dot(A, Q.T)
>>> LA.eigvals(A)
- array([ 1., -1.])
+ array([ 1., -1.]) # random
"""
a, wrap = _makearray(a)
@@ -1124,31 +1124,31 @@ def eigvalsh(a, UPLO='L'):
Broadcasting rules apply, see the `numpy.linalg` documentation for
details.
- The eigenvalues are computed using LAPACK routines _syevd, _heevd
+ The eigenvalues are computed using LAPACK routines ``_syevd``, ``_heevd``.
Examples
--------
>>> from numpy import linalg as LA
>>> a = np.array([[1, -2j], [2j, 5]])
>>> LA.eigvalsh(a)
- array([ 0.17157288, 5.82842712])
+ array([ 0.17157288, 5.82842712]) # may vary
>>> # demonstrate the treatment of the imaginary part of the diagonal
>>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]])
>>> a
- array([[ 5.+2.j, 9.-2.j],
- [ 0.+2.j, 2.-1.j]])
+ array([[5.+2.j, 9.-2.j],
+ [0.+2.j, 2.-1.j]])
>>> # with UPLO='L' this is numerically equivalent to using LA.eigvals()
>>> # with:
>>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]])
>>> b
- array([[ 5.+0.j, 0.-2.j],
- [ 0.+2.j, 2.+0.j]])
+ array([[5.+0.j, 0.-2.j],
+ [0.+2.j, 2.+0.j]])
>>> wa = LA.eigvalsh(a)
>>> wb = LA.eigvals(b)
>>> wa; wb
- array([ 1., 6.])
- array([ 6.+0.j, 1.+0.j])
+ array([1., 6.])
+ array([6.+0.j, 1.+0.j])
"""
UPLO = UPLO.upper()
@@ -1214,7 +1214,7 @@ def eig(a):
--------
eigvals : eigenvalues of a non-symmetric array.
- eigh : eigenvalues and eigenvectors of a real symmetric or complex
+ eigh : eigenvalues and eigenvectors of a real symmetric or complex
Hermitian (conjugate symmetric) array.
eigvalsh : eigenvalues of a real symmetric or complex Hermitian
@@ -1228,7 +1228,7 @@ def eig(a):
Broadcasting rules apply, see the `numpy.linalg` documentation for
details.
- This is implemented using the _geev LAPACK routines which compute
+ This is implemented using the ``_geev`` LAPACK routines which compute
the eigenvalues and eigenvectors of general square arrays.
The number `w` is an eigenvalue of `a` if there exists a vector
@@ -1264,29 +1264,29 @@ def eig(a):
>>> w, v = LA.eig(np.diag((1, 2, 3)))
>>> w; v
- array([ 1., 2., 3.])
- array([[ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]])
+ array([1., 2., 3.])
+ array([[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]])
Real matrix possessing complex e-values and e-vectors; note that the
e-values are complex conjugates of each other.
>>> w, v = LA.eig(np.array([[1, -1], [1, 1]]))
>>> w; v
- array([ 1. + 1.j, 1. - 1.j])
- array([[ 0.70710678+0.j , 0.70710678+0.j ],
- [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]])
+ array([1.+1.j, 1.-1.j])
+ array([[0.70710678+0.j , 0.70710678-0.j ],
+ [0. -0.70710678j, 0. +0.70710678j]])
Complex-valued matrix with real e-values (but complex-valued e-vectors);
- note that a.conj().T = a, i.e., a is Hermitian.
+ note that ``a.conj().T == a``, i.e., `a` is Hermitian.
>>> a = np.array([[1, 1j], [-1j, 1]])
>>> w, v = LA.eig(a)
>>> w; v
- array([ 2.00000000e+00+0.j, 5.98651912e-36+0.j]) # i.e., {2, 0}
- array([[ 0.00000000+0.70710678j, 0.70710678+0.j ],
- [ 0.70710678+0.j , 0.00000000+0.70710678j]])
+ array([2.+0.j, 0.+0.j])
+ array([[ 0. +0.70710678j, 0.70710678+0.j ], # may vary
+ [ 0.70710678+0.j , -0. +0.70710678j]])
Be careful about round-off error!
@@ -1294,9 +1294,9 @@ def eig(a):
>>> # Theor. e-values are 1 +/- 1e-9
>>> w, v = LA.eig(a)
>>> w; v
- array([ 1., 1.])
- array([[ 1., 0.],
- [ 0., 1.]])
+ array([1., 1.])
+ array([[1., 0.],
+ [0., 1.]])
"""
a, wrap = _makearray(a)
@@ -1374,8 +1374,8 @@ def eigh(a, UPLO='L'):
Broadcasting rules apply, see the `numpy.linalg` documentation for
details.
- The eigenvalues/eigenvectors are computed using LAPACK routines _syevd,
- _heevd
+ The eigenvalues/eigenvectors are computed using LAPACK routines ``_syevd``,
+ ``_heevd``.
The eigenvalues of real symmetric or complex Hermitian matrices are
always real. [1]_ The array `v` of (column) eigenvectors is unitary
@@ -1392,49 +1392,49 @@ def eigh(a, UPLO='L'):
>>> from numpy import linalg as LA
>>> a = np.array([[1, -2j], [2j, 5]])
>>> a
- array([[ 1.+0.j, 0.-2.j],
+ array([[ 1.+0.j, -0.-2.j],
[ 0.+2.j, 5.+0.j]])
>>> w, v = LA.eigh(a)
>>> w; v
- array([ 0.17157288, 5.82842712])
- array([[-0.92387953+0.j , -0.38268343+0.j ],
- [ 0.00000000+0.38268343j, 0.00000000-0.92387953j]])
+ array([0.17157288, 5.82842712])
+ array([[-0.92387953+0.j , -0.38268343+0.j ], # may vary
+ [ 0. +0.38268343j, 0. -0.92387953j]])
>>> np.dot(a, v[:, 0]) - w[0] * v[:, 0] # verify 1st e-val/vec pair
- array([2.77555756e-17 + 0.j, 0. + 1.38777878e-16j])
+ array([5.55111512e-17+0.0000000e+00j, 0.00000000e+00+1.2490009e-16j])
>>> np.dot(a, v[:, 1]) - w[1] * v[:, 1] # verify 2nd e-val/vec pair
- array([ 0.+0.j, 0.+0.j])
+ array([0.+0.j, 0.+0.j])
>>> A = np.matrix(a) # what happens if input is a matrix object
>>> A
- matrix([[ 1.+0.j, 0.-2.j],
+ matrix([[ 1.+0.j, -0.-2.j],
[ 0.+2.j, 5.+0.j]])
>>> w, v = LA.eigh(A)
>>> w; v
- array([ 0.17157288, 5.82842712])
- matrix([[-0.92387953+0.j , -0.38268343+0.j ],
- [ 0.00000000+0.38268343j, 0.00000000-0.92387953j]])
+ array([0.17157288, 5.82842712])
+ matrix([[-0.92387953+0.j , -0.38268343+0.j ], # may vary
+ [ 0. +0.38268343j, 0. -0.92387953j]])
>>> # demonstrate the treatment of the imaginary part of the diagonal
>>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]])
>>> a
- array([[ 5.+2.j, 9.-2.j],
- [ 0.+2.j, 2.-1.j]])
+ array([[5.+2.j, 9.-2.j],
+ [0.+2.j, 2.-1.j]])
>>> # with UPLO='L' this is numerically equivalent to using LA.eig() with:
>>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]])
>>> b
- array([[ 5.+0.j, 0.-2.j],
- [ 0.+2.j, 2.+0.j]])
+ array([[5.+0.j, 0.-2.j],
+ [0.+2.j, 2.+0.j]])
>>> wa, va = LA.eigh(a)
>>> wb, vb = LA.eig(b)
>>> wa; wb
- array([ 1., 6.])
- array([ 6.+0.j, 1.+0.j])
+ array([1., 6.])
+ array([6.+0.j, 1.+0.j])
>>> va; vb
- array([[-0.44721360-0.j , -0.89442719+0.j ],
- [ 0.00000000+0.89442719j, 0.00000000-0.4472136j ]])
- array([[ 0.89442719+0.j , 0.00000000-0.4472136j],
- [ 0.00000000-0.4472136j, 0.89442719+0.j ]])
+ array([[-0.4472136 +0.j , -0.89442719+0.j ], # may vary
+ [ 0. +0.89442719j, 0. -0.4472136j ]])
+ array([[ 0.89442719+0.j , -0. +0.4472136j],
+ [-0. +0.4472136j, 0.89442719+0.j ]])
"""
UPLO = UPLO.upper()
if UPLO not in ('L', 'U'):
@@ -1461,12 +1461,12 @@ def eigh(a, UPLO='L'):
# Singular value decomposition
-def _svd_dispatcher(a, full_matrices=None, compute_uv=None):
+def _svd_dispatcher(a, full_matrices=None, compute_uv=None, hermitian=None):
return (a,)
@array_function_dispatch(_svd_dispatcher)
-def svd(a, full_matrices=True, compute_uv=True):
+def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
"""
Singular Value Decomposition.
@@ -1504,6 +1504,12 @@ def svd(a, full_matrices=True, compute_uv=True):
size as those of the input `a`. The size of the last two dimensions
depends on the value of `full_matrices`. Only returned when
`compute_uv` is True.
+ hermitian : bool, optional
+ If True, `a` is assumed to be Hermitian (symmetric if real-valued),
+ enabling a more efficient method for finding singular values.
+ Defaults to False.
+
+ .. versionadded:: 1.17.0
Raises
------
@@ -1590,6 +1596,24 @@ def svd(a, full_matrices=True, compute_uv=True):
"""
a, wrap = _makearray(a)
+
+ if hermitian:
+ # note: lapack returns eigenvalues in reverse order to our contract.
+ # reversing is cheap by design in numpy, so we do so to be consistent
+ if compute_uv:
+ s, u = eigh(a)
+ s = s[..., ::-1]
+ u = u[..., ::-1]
+ # singular values are unsigned, move the sign into v
+ vt = transpose(u * sign(s)[..., None, :]).conjugate()
+ s = abs(s)
+ return wrap(u), s, wrap(vt)
+ else:
+ s = eigvalsh(a)
+ s = s[..., ::-1]
+ s = abs(s)
+ return s
+
_assertRankAtLeast2(a)
t, result_t = _commonType(a)
@@ -1705,9 +1729,9 @@ def cond(x, p=None):
>>> LA.cond(a, 2)
1.4142135623730951
>>> LA.cond(a, -2)
- 0.70710678118654746
+ 0.70710678118654746 # may vary
>>> min(LA.svd(a, compute_uv=0))*min(LA.svd(LA.inv(a), compute_uv=0))
- 0.70710678118654746
+ 0.70710678118654746 # may vary
"""
x = asarray(x) # in case we have a matrix
@@ -1766,9 +1790,9 @@ def matrix_rank(M, tol=None, hermitian=False):
Parameters
----------
M : {(M,), (..., M, N)} array_like
- input vector or stack of matrices
+ Input vector or stack of matrices.
tol : (...) array_like, float, optional
- threshold below which SVD values are considered zero. If `tol` is
+ Threshold below which SVD values are considered zero. If `tol` is
None, and ``S`` is an array with singular values for `M`, and
``eps`` is the epsilon value for datatype of ``S``, then `tol` is
set to ``S.max() * max(M.shape) * eps``.
@@ -1782,6 +1806,11 @@ def matrix_rank(M, tol=None, hermitian=False):
.. versionadded:: 1.14
+ Returns
+ -------
+ rank : (...) array_like
+ Rank of M.
+
Notes
-----
The default threshold to detect rank deficiency is a test on the magnitude
@@ -1844,10 +1873,7 @@ def matrix_rank(M, tol=None, hermitian=False):
M = asarray(M)
if M.ndim < 2:
return int(not all(M==0))
- if hermitian:
- S = abs(eigvalsh(M))
- else:
- S = svd(M, compute_uv=False)
+ S = svd(M, compute_uv=False, hermitian=hermitian)
if tol is None:
tol = S.max(axis=-1, keepdims=True) * max(M.shape[-2:]) * finfo(S.dtype).eps
else:
@@ -1857,12 +1883,12 @@ def matrix_rank(M, tol=None, hermitian=False):
# Generalized inverse
-def _pinv_dispatcher(a, rcond=None):
+def _pinv_dispatcher(a, rcond=None, hermitian=None):
return (a,)
@array_function_dispatch(_pinv_dispatcher)
-def pinv(a, rcond=1e-15):
+def pinv(a, rcond=1e-15, hermitian=False):
"""
Compute the (Moore-Penrose) pseudo-inverse of a matrix.
@@ -1879,9 +1905,15 @@ def pinv(a, rcond=1e-15):
Matrix or stack of matrices to be pseudo-inverted.
rcond : (...) array_like of float
Cutoff for small singular values.
- Singular values smaller (in modulus) than
- `rcond` * largest_singular_value (again, in modulus)
- are set to zero. Broadcasts against the stack of matrices
+ Singular values less than or equal to
+ ``rcond * largest_singular_value`` are set to zero.
+ Broadcasts against the stack of matrices.
+ hermitian : bool, optional
+ If True, `a` is assumed to be Hermitian (symmetric if real-valued),
+ enabling a more efficient method for finding singular values.
+ Defaults to False.
+
+ .. versionadded:: 1.17.0
Returns
-------
@@ -1935,7 +1967,7 @@ def pinv(a, rcond=1e-15):
res = empty(a.shape[:-2] + (n, m), dtype=a.dtype)
return wrap(res)
a = a.conjugate()
- u, s, vt = svd(a, full_matrices=False)
+ u, s, vt = svd(a, full_matrices=False, hermitian=hermitian)
# discard small singular values
cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True)
@@ -1992,7 +2024,7 @@ def slogdet(a):
.. versionadded:: 1.6.0
The determinant is computed via LU factorization using the LAPACK
- routine z/dgetrf.
+ routine ``z/dgetrf``.
Examples
@@ -2002,7 +2034,7 @@ def slogdet(a):
>>> a = np.array([[1, 2], [3, 4]])
>>> (sign, logdet) = np.linalg.slogdet(a)
>>> (sign, logdet)
- (-1, 0.69314718055994529)
+ (-1, 0.69314718055994529) # may vary
>>> sign * np.exp(logdet)
-2.0
@@ -2066,7 +2098,7 @@ def det(a):
details.
The determinant is computed via LU factorization using the LAPACK
- routine z/dgetrf.
+ routine ``z/dgetrf``.
Examples
--------
@@ -2074,7 +2106,7 @@ def det(a):
>>> a = np.array([[1, 2], [3, 4]])
>>> np.linalg.det(a)
- -2.0
+ -2.0 # may vary
Computing determinants for a stack of matrices:
@@ -2103,16 +2135,16 @@ def _lstsq_dispatcher(a, b, rcond=None):
@array_function_dispatch(_lstsq_dispatcher)
def lstsq(a, b, rcond="warn"):
- """
+ r"""
Return the least-squares solution to a linear matrix equation.
- Solves the equation `a x = b` by computing a vector `x` that
- minimizes the Euclidean 2-norm `|| b - a x ||^2`. The equation may
- be under-, well-, or over- determined (i.e., the number of
- linearly independent rows of `a` can be less than, equal to, or
- greater than its number of linearly independent columns). If `a`
- is square and of full rank, then `x` (but for round-off error) is
- the "exact" solution of the equation.
+ Solves the equation :math:`a x = b` by computing a vector `x` that
+ minimizes the squared Euclidean 2-norm :math:`\| b - a x \|^2_2`.
+ The equation may be under-, well-, or over-determined (i.e., the
+ number of linearly independent rows of `a` can be less than, equal
+ to, or greater than its number of linearly independent columns).
+ If `a` is square and of full rank, then `x` (but for round-off error)
+ is the "exact" solution of the equation.
Parameters
----------
@@ -2181,15 +2213,15 @@ def lstsq(a, b, rcond="warn"):
[ 3., 1.]])
>>> m, c = np.linalg.lstsq(A, y, rcond=None)[0]
- >>> print(m, c)
- 1.0 -0.95
+ >>> m, c
+ (1.0 -0.95) # may vary
Plot the data along with the fitted line:
>>> import matplotlib.pyplot as plt
- >>> plt.plot(x, y, 'o', label='Original data', markersize=10)
- >>> plt.plot(x, m*x + c, 'r', label='Fitted line')
- >>> plt.legend()
+ >>> _ = plt.plot(x, y, 'o', label='Original data', markersize=10)
+ >>> _ = plt.plot(x, m*x + c, 'r', label='Fitted line')
+ >>> _ = plt.legend()
>>> plt.show()
"""
@@ -2218,7 +2250,7 @@ def lstsq(a, b, rcond="warn"):
"To use the future default and silence this warning "
"we advise to pass `rcond=None`, to keep using the old, "
"explicitly pass `rcond=-1`.",
- FutureWarning, stacklevel=2)
+ FutureWarning, stacklevel=3)
rcond = -1
if rcond is None:
rcond = finfo(t).eps * max(n, m)
@@ -2261,7 +2293,7 @@ def lstsq(a, b, rcond="warn"):
def _multi_svd_norm(x, row_axis, col_axis, op):
"""Compute a function of the singular values of the 2-D matrices in `x`.
- This is a private utility function used by numpy.linalg.norm().
+ This is a private utility function used by `numpy.linalg.norm()`.
Parameters
----------
@@ -2269,7 +2301,7 @@ def _multi_svd_norm(x, row_axis, col_axis, op):
row_axis, col_axis : int
The axes of `x` that hold the 2-D matrices.
op : callable
- This should be either numpy.amin or numpy.amax or numpy.sum.
+ This should be either numpy.amin or `numpy.amax` or `numpy.sum`.
Returns
-------
@@ -2367,7 +2399,7 @@ def norm(x, ord=None, axis=None, keepdims=False):
>>> from numpy import linalg as LA
>>> a = np.arange(9) - 4
>>> a
- array([-4, -3, -2, -1, 0, 1, 2, 3, 4])
+ array([-4, -3, -2, ..., 2, 3, 4])
>>> b = a.reshape((3, 3))
>>> b
array([[-4, -3, -2],
@@ -2403,13 +2435,13 @@ def norm(x, ord=None, axis=None, keepdims=False):
7.3484692283495345
>>> LA.norm(a, -2)
- nan
+ 0.0
>>> LA.norm(b, -2)
- 1.8570331885190563e-016
+ 1.8570331885190563e-016 # may vary
>>> LA.norm(a, 3)
- 5.8480354764257312
+ 5.8480354764257312 # may vary
>>> LA.norm(a, -3)
- nan
+ 0.0
Using the `axis` argument to compute vector norms:
@@ -2584,18 +2616,18 @@ def multi_dot(arrays):
>>> from numpy.linalg import multi_dot
>>> # Prepare some data
- >>> A = np.random.random(10000, 100)
- >>> B = np.random.random(100, 1000)
- >>> C = np.random.random(1000, 5)
- >>> D = np.random.random(5, 333)
+ >>> A = np.random.random((10000, 100))
+ >>> B = np.random.random((100, 1000))
+ >>> C = np.random.random((1000, 5))
+ >>> D = np.random.random((5, 333))
>>> # the actual dot multiplication
- >>> multi_dot([A, B, C, D])
+ >>> _ = multi_dot([A, B, C, D])
instead of::
- >>> np.dot(np.dot(np.dot(A, B), C), D)
+ >>> _ = np.dot(np.dot(np.dot(A, B), C), D)
>>> # or
- >>> A.dot(B).dot(C).dot(D)
+ >>> _ = A.dot(B).dot(C).dot(D)
Notes
-----
@@ -2605,7 +2637,7 @@ def multi_dot(arrays):
def cost(A, B):
return A.shape[0] * A.shape[1] * B.shape[1]
- Let's assume we have three matrices
+ Assume we have three matrices
:math:`A_{10x100}, B_{100x5}, C_{5x50}`.
The costs for the two different parenthesizations are as follows::
diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py
index 235488c6e..831c059d0 100644
--- a/numpy/linalg/tests/test_linalg.py
+++ b/numpy/linalg/tests/test_linalg.py
@@ -633,6 +633,20 @@ class TestEig(EigCases):
assert_(isinstance(a, np.ndarray))
+class SVDBaseTests(object):
+ hermitian = False
+
+ @pytest.mark.parametrize('dtype', [single, double, csingle, cdouble])
+ def test_types(self, dtype):
+ x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
+ u, s, vh = linalg.svd(x)
+ assert_equal(u.dtype, dtype)
+ assert_equal(s.dtype, get_real_dtype(dtype))
+ assert_equal(vh.dtype, dtype)
+ s = linalg.svd(x, compute_uv=False, hermitian=self.hermitian)
+ assert_equal(s.dtype, get_real_dtype(dtype))
+
+
class SVDCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
@@ -644,32 +658,37 @@ class SVDCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(consistent_subclass(vt, a))
-class TestSVD(SVDCases):
- @pytest.mark.parametrize('dtype', [single, double, csingle, cdouble])
- def test_types(self, dtype):
- x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
- u, s, vh = linalg.svd(x)
- assert_equal(u.dtype, dtype)
- assert_equal(s.dtype, get_real_dtype(dtype))
- assert_equal(vh.dtype, dtype)
- s = linalg.svd(x, compute_uv=False)
- assert_equal(s.dtype, get_real_dtype(dtype))
-
+class TestSVD(SVDCases, SVDBaseTests):
def test_empty_identity(self):
""" Empty input should put an identity matrix in u or vh """
x = np.empty((4, 0))
- u, s, vh = linalg.svd(x, compute_uv=True)
+ u, s, vh = linalg.svd(x, compute_uv=True, hermitian=self.hermitian)
assert_equal(u.shape, (4, 4))
assert_equal(vh.shape, (0, 0))
assert_equal(u, np.eye(4))
x = np.empty((0, 4))
- u, s, vh = linalg.svd(x, compute_uv=True)
+ u, s, vh = linalg.svd(x, compute_uv=True, hermitian=self.hermitian)
assert_equal(u.shape, (0, 0))
assert_equal(vh.shape, (4, 4))
assert_equal(vh, np.eye(4))
+class SVDHermitianCases(HermitianTestCase, HermitianGeneralizedTestCase):
+
+ def do(self, a, b, tags):
+ u, s, vt = linalg.svd(a, 0, hermitian=True)
+ assert_allclose(a, dot_generalized(np.asarray(u) * np.asarray(s)[..., None, :],
+ np.asarray(vt)),
+ rtol=get_rtol(u.dtype))
+ assert_(consistent_subclass(u, a))
+ assert_(consistent_subclass(vt, a))
+
+
+class TestSVDHermitian(SVDHermitianCases, SVDBaseTests):
+ hermitian = True
+
+
class CondCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
# cond(x, p) for p in (None, 2, -2)
@@ -797,6 +816,20 @@ class TestPinv(PinvCases):
pass
+class PinvHermitianCases(HermitianTestCase, HermitianGeneralizedTestCase):
+
+ def do(self, a, b, tags):
+ a_ginv = linalg.pinv(a, hermitian=True)
+ # `a @ a_ginv == I` does not hold if a is singular
+ dot = dot_generalized
+ assert_almost_equal(dot(dot(a, a_ginv), a), a, single_decimal=5, double_decimal=11)
+ assert_(consistent_subclass(a_ginv, a))
+
+
+class TestPinvHermitian(PinvHermitianCases):
+ pass
+
+
class DetCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
@@ -1962,3 +1995,10 @@ class TestTensorinv(object):
ainv = linalg.tensorinv(a, ind=1)
b = np.ones(24)
assert_allclose(np.tensordot(ainv, b, 1), np.linalg.tensorsolve(a, b))
+
+
+def test_unsupported_commontype():
+ # linalg gracefully handles unsupported type
+ arr = np.array([[1, -2], [2, 5]], dtype='float16')
+ with assert_raises_regex(TypeError, "unsupported in linalg"):
+ linalg.cholesky(arr)
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 96d7207bd..a23ae4010 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -44,10 +44,9 @@ from numpy.compat import (
getargspec, formatargspec, long, basestring, unicode, bytes
)
from numpy import expand_dims
-from numpy.core.multiarray import normalize_axis_index
from numpy.core.numeric import normalize_axis_tuple
from numpy.core._internal import recursive
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
__all__ = [
@@ -516,18 +515,18 @@ def set_fill_value(a, fill_value):
array([0, 1, 2, 3, 4])
>>> a = ma.masked_where(a < 3, a)
>>> a
- masked_array(data = [-- -- -- 3 4],
- mask = [ True True True False False],
- fill_value=999999)
+ masked_array(data=[--, --, --, 3, 4],
+ mask=[ True, True, True, False, False],
+ fill_value=999999)
>>> ma.set_fill_value(a, -999)
>>> a
- masked_array(data = [-- -- -- 3 4],
- mask = [ True True True False False],
- fill_value=-999)
+ masked_array(data=[--, --, --, 3, 4],
+ mask=[ True, True, True, False, False],
+ fill_value=-999)
Nothing happens if `a` is not a masked array.
- >>> a = range(5)
+ >>> a = list(range(5))
>>> a
[0, 1, 2, 3, 4]
>>> ma.set_fill_value(a, 100)
@@ -689,13 +688,12 @@ def getdata(a, subok=True):
>>> import numpy.ma as ma
>>> a = ma.masked_equal([[1,2],[3,4]], 2)
>>> a
- masked_array(data =
- [[1 --]
- [3 4]],
- mask =
- [[False True]
- [False False]],
- fill_value=999999)
+ masked_array(
+ data=[[1, --],
+ [3, 4]],
+ mask=[[False, True],
+ [False, False]],
+ fill_value=2)
>>> ma.getdata(a)
array([[1, 2],
[3, 4]])
@@ -752,20 +750,19 @@ def fix_invalid(a, mask=nomask, copy=True, fill_value=None):
--------
>>> x = np.ma.array([1., -1, np.nan, np.inf], mask=[1] + [0]*3)
>>> x
- masked_array(data = [-- -1.0 nan inf],
- mask = [ True False False False],
- fill_value = 1e+20)
+ masked_array(data=[--, -1.0, nan, inf],
+ mask=[ True, False, False, False],
+ fill_value=1e+20)
>>> np.ma.fix_invalid(x)
- masked_array(data = [-- -1.0 -- --],
- mask = [ True False True True],
- fill_value = 1e+20)
+ masked_array(data=[--, -1.0, --, --],
+ mask=[ True, False, True, True],
+ fill_value=1e+20)
>>> fixed = np.ma.fix_invalid(x)
>>> fixed.data
- array([ 1.00000000e+00, -1.00000000e+00, 1.00000000e+20,
- 1.00000000e+20])
+ array([ 1.e+00, -1.e+00, 1.e+20, 1.e+20])
>>> x.data
- array([ 1., -1., NaN, Inf])
+ array([ 1., -1., nan, inf])
"""
a = masked_array(a, copy=copy, mask=mask, subok=True)
@@ -1200,7 +1197,6 @@ exp = _MaskedUnaryOperation(umath.exp)
conjugate = _MaskedUnaryOperation(umath.conjugate)
sin = _MaskedUnaryOperation(umath.sin)
cos = _MaskedUnaryOperation(umath.cos)
-tan = _MaskedUnaryOperation(umath.tan)
arctan = _MaskedUnaryOperation(umath.arctan)
arcsinh = _MaskedUnaryOperation(umath.arcsinh)
sinh = _MaskedUnaryOperation(umath.sinh)
@@ -1346,9 +1342,9 @@ def make_mask_descr(ndtype):
--------
>>> import numpy.ma as ma
>>> dtype = np.dtype({'names':['foo', 'bar'],
- 'formats':[np.float32, int]})
+ ... 'formats':[np.float32, np.int64]})
>>> dtype
- dtype([('foo', '<f4'), ('bar', '<i4')])
+ dtype([('foo', '<f4'), ('bar', '<i8')])
>>> ma.make_mask_descr(dtype)
dtype([('foo', '|b1'), ('bar', '|b1')])
>>> ma.make_mask_descr(np.float32)
@@ -1381,13 +1377,12 @@ def getmask(a):
>>> import numpy.ma as ma
>>> a = ma.masked_equal([[1,2],[3,4]], 2)
>>> a
- masked_array(data =
- [[1 --]
- [3 4]],
- mask =
- [[False True]
- [False False]],
- fill_value=999999)
+ masked_array(
+ data=[[1, --],
+ [3, 4]],
+ mask=[[False, True],
+ [False, False]],
+ fill_value=2)
>>> ma.getmask(a)
array([[False, True],
[False, False]])
@@ -1402,12 +1397,11 @@ def getmask(a):
>>> b = ma.masked_array([[1,2],[3,4]])
>>> b
- masked_array(data =
- [[1 2]
- [3 4]],
- mask =
- False,
- fill_value=999999)
+ masked_array(
+ data=[[1, 2],
+ [3, 4]],
+ mask=False,
+ fill_value=999999)
>>> ma.nomask
False
>>> ma.getmask(b) == ma.nomask
@@ -1445,13 +1439,12 @@ def getmaskarray(arr):
>>> import numpy.ma as ma
>>> a = ma.masked_equal([[1,2],[3,4]], 2)
>>> a
- masked_array(data =
- [[1 --]
- [3 4]],
- mask =
- [[False True]
- [False False]],
- fill_value=999999)
+ masked_array(
+ data=[[1, --],
+ [3, 4]],
+ mask=[[False, True],
+ [False, False]],
+ fill_value=2)
>>> ma.getmaskarray(a)
array([[False, True],
[False, False]])
@@ -1460,13 +1453,12 @@ def getmaskarray(arr):
>>> b = ma.masked_array([[1,2],[3,4]])
>>> b
- masked_array(data =
- [[1 2]
- [3 4]],
- mask =
- False,
- fill_value=999999)
- >>> >ma.getmaskarray(b)
+ masked_array(
+ data=[[1, 2],
+ [3, 4]],
+ mask=False,
+ fill_value=999999)
+ >>> ma.getmaskarray(b)
array([[False, False],
[False, False]])
@@ -1504,9 +1496,9 @@ def is_mask(m):
>>> import numpy.ma as ma
>>> m = ma.masked_equal([0, 1, 0, 2, 3], 0)
>>> m
- masked_array(data = [-- 1 -- 2 3],
- mask = [ True False True False False],
- fill_value=999999)
+ masked_array(data=[--, 1, --, 2, 3],
+ mask=[ True, False, True, False, False],
+ fill_value=0)
>>> ma.is_mask(m)
False
>>> ma.is_mask(m.mask)
@@ -1527,14 +1519,14 @@ def is_mask(m):
Arrays with complex dtypes don't return True.
>>> dtype = np.dtype({'names':['monty', 'pithon'],
- 'formats':[bool, bool]})
+ ... 'formats':[bool, bool]})
>>> dtype
dtype([('monty', '|b1'), ('pithon', '|b1')])
>>> m = np.array([(True, False), (False, True), (True, False)],
- dtype=dtype)
+ ... dtype=dtype)
>>> m
- array([(True, False), (False, True), (True, False)],
- dtype=[('monty', '|b1'), ('pithon', '|b1')])
+ array([( True, False), (False, True), ( True, False)],
+ dtype=[('monty', '?'), ('pithon', '?')])
>>> ma.is_mask(m)
False
@@ -1600,7 +1592,7 @@ def make_mask(m, copy=False, shrink=True, dtype=MaskType):
>>> m = np.zeros(4)
>>> m
- array([ 0., 0., 0., 0.])
+ array([0., 0., 0., 0.])
>>> ma.make_mask(m)
False
>>> ma.make_mask(m, shrink=False)
@@ -1616,11 +1608,11 @@ def make_mask(m, copy=False, shrink=True, dtype=MaskType):
>>> arr
[(1, 0), (0, 1), (1, 0), (1, 0)]
>>> dtype = np.dtype({'names':['man', 'mouse'],
- 'formats':[int, int]})
+ ... 'formats':[np.int64, np.int64]})
>>> arr = np.array(arr, dtype=dtype)
>>> arr
array([(1, 0), (0, 1), (1, 0), (1, 0)],
- dtype=[('man', '<i4'), ('mouse', '<i4')])
+ dtype=[('man', '<i8'), ('mouse', '<i8')])
>>> ma.make_mask(arr, dtype=dtype)
array([(True, False), (False, True), (True, False), (True, False)],
dtype=[('man', '|b1'), ('mouse', '|b1')])
@@ -1679,9 +1671,9 @@ def make_mask_none(newshape, dtype=None):
Defining a more complex dtype.
>>> dtype = np.dtype({'names':['foo', 'bar'],
- 'formats':[np.float32, int]})
+ ... 'formats':[np.float32, np.int64]})
>>> dtype
- dtype([('foo', '<f4'), ('bar', '<i4')])
+ dtype([('foo', '<f4'), ('bar', '<i8')])
>>> ma.make_mask_none((3,), dtype=dtype)
array([(False, False), (False, False), (False, False)],
dtype=[('foo', '|b1'), ('bar', '|b1')])
@@ -1779,16 +1771,16 @@ def flatten_mask(mask):
Examples
--------
>>> mask = np.array([0, 0, 1])
- >>> flatten_mask(mask)
+ >>> np.ma.flatten_mask(mask)
array([False, False, True])
>>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)])
- >>> flatten_mask(mask)
+ >>> np.ma.flatten_mask(mask)
array([False, False, False, True])
>>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])]
>>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype)
- >>> flatten_mask(mask)
+ >>> np.ma.flatten_mask(mask)
array([False, False, False, False, False, True])
"""
@@ -1873,38 +1865,39 @@ def masked_where(condition, a, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_where(a <= 2, a)
- masked_array(data = [-- -- -- 3],
- mask = [ True True True False],
- fill_value=999999)
+ masked_array(data=[--, --, --, 3],
+ mask=[ True, True, True, False],
+ fill_value=999999)
Mask array `b` conditional on `a`.
>>> b = ['a', 'b', 'c', 'd']
>>> ma.masked_where(a == 2, b)
- masked_array(data = [a b -- d],
- mask = [False False True False],
- fill_value=N/A)
+ masked_array(data=['a', 'b', --, 'd'],
+ mask=[False, False, True, False],
+ fill_value='N/A',
+ dtype='<U1')
Effect of the `copy` argument.
>>> c = ma.masked_where(a <= 2, a)
>>> c
- masked_array(data = [-- -- -- 3],
- mask = [ True True True False],
- fill_value=999999)
+ masked_array(data=[--, --, --, 3],
+ mask=[ True, True, True, False],
+ fill_value=999999)
>>> c[0] = 99
>>> c
- masked_array(data = [99 -- -- 3],
- mask = [False True True False],
- fill_value=999999)
+ masked_array(data=[99, --, --, 3],
+ mask=[False, True, True, False],
+ fill_value=999999)
>>> a
array([0, 1, 2, 3])
>>> c = ma.masked_where(a <= 2, a, copy=False)
>>> c[0] = 99
>>> c
- masked_array(data = [99 -- -- 3],
- mask = [False True True False],
- fill_value=999999)
+ masked_array(data=[99, --, --, 3],
+ mask=[False, True, True, False],
+ fill_value=999999)
>>> a
array([99, 1, 2, 3])
@@ -1913,19 +1906,19 @@ def masked_where(condition, a, copy=True):
>>> a = np.arange(4)
>>> a = ma.masked_where(a == 2, a)
>>> a
- masked_array(data = [0 1 -- 3],
- mask = [False False True False],
- fill_value=999999)
+ masked_array(data=[0, 1, --, 3],
+ mask=[False, False, True, False],
+ fill_value=999999)
>>> b = np.arange(4)
>>> b = ma.masked_where(b == 0, b)
>>> b
- masked_array(data = [-- 1 2 3],
- mask = [ True False False False],
- fill_value=999999)
+ masked_array(data=[--, 1, 2, 3],
+ mask=[ True, False, False, False],
+ fill_value=999999)
>>> ma.masked_where(a == 3, b)
- masked_array(data = [-- 1 -- --],
- mask = [ True False True True],
- fill_value=999999)
+ masked_array(data=[--, 1, --, --],
+ mask=[ True, False, True, True],
+ fill_value=999999)
"""
# Make sure that condition is a valid standard-type mask.
@@ -1965,9 +1958,9 @@ def masked_greater(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_greater(a, 2)
- masked_array(data = [0 1 2 --],
- mask = [False False False True],
- fill_value=999999)
+ masked_array(data=[0, 1, 2, --],
+ mask=[False, False, False, True],
+ fill_value=999999)
"""
return masked_where(greater(x, value), x, copy=copy)
@@ -1991,9 +1984,9 @@ def masked_greater_equal(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_greater_equal(a, 2)
- masked_array(data = [0 1 -- --],
- mask = [False False True True],
- fill_value=999999)
+ masked_array(data=[0, 1, --, --],
+ mask=[False, False, True, True],
+ fill_value=999999)
"""
return masked_where(greater_equal(x, value), x, copy=copy)
@@ -2017,9 +2010,9 @@ def masked_less(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_less(a, 2)
- masked_array(data = [-- -- 2 3],
- mask = [ True True False False],
- fill_value=999999)
+ masked_array(data=[--, --, 2, 3],
+ mask=[ True, True, False, False],
+ fill_value=999999)
"""
return masked_where(less(x, value), x, copy=copy)
@@ -2043,9 +2036,9 @@ def masked_less_equal(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_less_equal(a, 2)
- masked_array(data = [-- -- -- 3],
- mask = [ True True True False],
- fill_value=999999)
+ masked_array(data=[--, --, --, 3],
+ mask=[ True, True, True, False],
+ fill_value=999999)
"""
return masked_where(less_equal(x, value), x, copy=copy)
@@ -2069,9 +2062,9 @@ def masked_not_equal(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_not_equal(a, 2)
- masked_array(data = [-- -- 2 --],
- mask = [ True True False True],
- fill_value=999999)
+ masked_array(data=[--, --, 2, --],
+ mask=[ True, True, False, True],
+ fill_value=999999)
"""
return masked_where(not_equal(x, value), x, copy=copy)
@@ -2097,9 +2090,9 @@ def masked_equal(x, value, copy=True):
>>> a
array([0, 1, 2, 3])
>>> ma.masked_equal(a, 2)
- masked_array(data = [0 1 -- 3],
- mask = [False False True False],
- fill_value=999999)
+ masked_array(data=[0, 1, --, 3],
+ mask=[False, False, True, False],
+ fill_value=2)
"""
output = masked_where(equal(x, value), x, copy=copy)
@@ -2128,16 +2121,16 @@ def masked_inside(x, v1, v2, copy=True):
>>> import numpy.ma as ma
>>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
>>> ma.masked_inside(x, -0.3, 0.3)
- masked_array(data = [0.31 1.2 -- -- -0.4 -1.1],
- mask = [False False True True False False],
- fill_value=1e+20)
+ masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
+ mask=[False, False, True, True, False, False],
+ fill_value=1e+20)
The order of `v1` and `v2` doesn't matter.
>>> ma.masked_inside(x, 0.3, -0.3)
- masked_array(data = [0.31 1.2 -- -- -0.4 -1.1],
- mask = [False False True True False False],
- fill_value=1e+20)
+ masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
+ mask=[False, False, True, True, False, False],
+ fill_value=1e+20)
"""
if v2 < v1:
@@ -2168,16 +2161,16 @@ def masked_outside(x, v1, v2, copy=True):
>>> import numpy.ma as ma
>>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
>>> ma.masked_outside(x, -0.3, 0.3)
- masked_array(data = [-- -- 0.01 0.2 -- --],
- mask = [ True True False False True True],
- fill_value=1e+20)
+ masked_array(data=[--, --, 0.01, 0.2, --, --],
+ mask=[ True, True, False, False, True, True],
+ fill_value=1e+20)
The order of `v1` and `v2` doesn't matter.
>>> ma.masked_outside(x, 0.3, -0.3)
- masked_array(data = [-- -- 0.01 0.2 -- --],
- mask = [ True True False False True True],
- fill_value=1e+20)
+ masked_array(data=[--, --, 0.01, 0.2, --, --],
+ mask=[ True, True, False, False, True, True],
+ fill_value=1e+20)
"""
if v2 < v1:
@@ -2222,20 +2215,27 @@ def masked_object(x, value, copy=True, shrink=True):
>>> food = np.array(['green_eggs', 'ham'], dtype=object)
>>> # don't eat spoiled food
>>> eat = ma.masked_object(food, 'green_eggs')
- >>> print(eat)
- [-- ham]
+ >>> eat
+ masked_array(data=[--, 'ham'],
+ mask=[ True, False],
+ fill_value='green_eggs',
+ dtype=object)
>>> # plain ol` ham is boring
>>> fresh_food = np.array(['cheese', 'ham', 'pineapple'], dtype=object)
>>> eat = ma.masked_object(fresh_food, 'green_eggs')
- >>> print(eat)
- [cheese ham pineapple]
+ >>> eat
+ masked_array(data=['cheese', 'ham', 'pineapple'],
+ mask=False,
+ fill_value='green_eggs',
+ dtype=object)
Note that `mask` is set to ``nomask`` if possible.
>>> eat
- masked_array(data = [cheese ham pineapple],
- mask = False,
- fill_value=?)
+ masked_array(data=['cheese', 'ham', 'pineapple'],
+ mask=False,
+ fill_value='green_eggs',
+ dtype=object)
"""
if isMaskedArray(x):
@@ -2290,16 +2290,16 @@ def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True):
>>> import numpy.ma as ma
>>> x = np.array([1, 1.1, 2, 1.1, 3])
>>> ma.masked_values(x, 1.1)
- masked_array(data = [1.0 -- 2.0 -- 3.0],
- mask = [False True False True False],
- fill_value=1.1)
+ masked_array(data=[1.0, --, 2.0, --, 3.0],
+ mask=[False, True, False, True, False],
+ fill_value=1.1)
Note that `mask` is set to ``nomask`` if possible.
>>> ma.masked_values(x, 1.5)
- masked_array(data = [ 1. 1.1 2. 1.1 3. ],
- mask = False,
- fill_value=1.5)
+ masked_array(data=[1. , 1.1, 2. , 1.1, 3. ],
+ mask=False,
+ fill_value=1.5)
For integers, the fill value will be different in general to the
result of ``masked_equal``.
@@ -2308,13 +2308,13 @@ def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True):
>>> x
array([0, 1, 2, 3, 4])
>>> ma.masked_values(x, 2)
- masked_array(data = [0 1 -- 3 4],
- mask = [False False True False False],
- fill_value=2)
+ masked_array(data=[0, 1, --, 3, 4],
+ mask=[False, False, True, False, False],
+ fill_value=2)
>>> ma.masked_equal(x, 2)
- masked_array(data = [0 1 -- 3 4],
- mask = [False False True False False],
- fill_value=999999)
+ masked_array(data=[0, 1, --, 3, 4],
+ mask=[False, False, True, False, False],
+ fill_value=2)
"""
xnew = filled(x, value)
@@ -2348,11 +2348,11 @@ def masked_invalid(a, copy=True):
>>> a[2] = np.NaN
>>> a[3] = np.PINF
>>> a
- array([ 0., 1., NaN, Inf, 4.])
+ array([ 0., 1., nan, inf, 4.])
>>> ma.masked_invalid(a)
- masked_array(data = [0.0 1.0 -- -- 4.0],
- mask = [False False True True False],
- fill_value=1e+20)
+ masked_array(data=[0.0, 1.0, --, --, 4.0],
+ mask=[False, False, True, True, False],
+ fill_value=1e+20)
"""
a = np.array(a, copy=copy, subok=True)
@@ -2513,7 +2513,7 @@ def flatten_structured_array(a):
--------
>>> ndtype = [('a', int), ('b', float)]
>>> a = np.array([(1, 1), (2, 2)], dtype=ndtype)
- >>> flatten_structured_array(a)
+ >>> np.ma.flatten_structured_array(a)
array([[1., 1.],
[2., 2.]])
@@ -2684,9 +2684,7 @@ class MaskedIterator(object):
>>> fl.next()
3
>>> fl.next()
- masked_array(data = --,
- mask = True,
- fill_value = 1e+20)
+ masked
>>> fl.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
@@ -3445,39 +3443,43 @@ class MaskedArray(ndarray):
_set_mask = __setmask__
- def _get_mask(self):
- """Return the current mask.
+ @property
+ def mask(self):
+ """ Current mask. """
- """
# We could try to force a reshape, but that wouldn't work in some
# cases.
- return self._mask
+ # Return a view so that the dtype and shape cannot be changed in place
+ # This still preserves nomask by identity
+ return self._mask.view()
- mask = property(fget=_get_mask, fset=__setmask__, doc="Mask")
+ @mask.setter
+ def mask(self, value):
+ self.__setmask__(value)
- def _get_recordmask(self):
+ @property
+ def recordmask(self):
"""
- Return the mask of the records.
-
- A record is masked when all the fields are masked.
+ Get or set the mask of the array if it has no named fields. For
+ structured arrays, returns a ndarray of booleans where entries are
+ ``True`` if **all** the fields are masked, ``False`` otherwise:
+ >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],
+ ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
+ ... dtype=[('a', int), ('b', int)])
+ >>> x.recordmask
+ array([False, False, True, False, False])
"""
+
_mask = self._mask.view(ndarray)
if _mask.dtype.names is None:
return _mask
return np.all(flatten_structured_array(_mask), axis=-1)
- def _set_recordmask(self):
- """
- Return the mask of the records.
-
- A record is masked when all the fields are masked.
-
- """
+ @recordmask.setter
+ def recordmask(self, mask):
raise NotImplementedError("Coming soon: setting the mask per records!")
- recordmask = property(fget=_get_recordmask)
-
def harden_mask(self):
"""
Force the mask to hard.
@@ -3508,8 +3510,10 @@ class MaskedArray(ndarray):
self._hardmask = False
return self
- hardmask = property(fget=lambda self: self._hardmask,
- doc="Hardness of the mask")
+ @property
+ def hardmask(self):
+ """ Hardness of the mask """
+ return self._hardmask
def unshare_mask(self):
"""
@@ -3529,8 +3533,10 @@ class MaskedArray(ndarray):
self._sharedmask = False
return self
- sharedmask = property(fget=lambda self: self._sharedmask,
- doc="Share status of the mask (read-only).")
+ @property
+ def sharedmask(self):
+ """ Share status of the mask (read-only). """
+ return self._sharedmask
def shrink_mask(self):
"""
@@ -3551,6 +3557,11 @@ class MaskedArray(ndarray):
array([[False, False],
[False, False]])
>>> x.shrink_mask()
+ masked_array(
+ data=[[1, 2],
+ [3, 4]],
+ mask=False,
+ fill_value=999999)
>>> x.mask
False
@@ -3558,39 +3569,46 @@ class MaskedArray(ndarray):
self._mask = _shrink_mask(self._mask)
return self
- baseclass = property(fget=lambda self: self._baseclass,
- doc="Class of the underlying data (read-only).")
+ @property
+ def baseclass(self):
+ """ Class of the underlying data (read-only). """
+ return self._baseclass
def _get_data(self):
- """Return the current data, as a view of the original
- underlying data.
+ """
+ Returns the underlying data, as a view of the masked array.
+
+ If the underlying data is a subclass of :class:`numpy.ndarray`, it is
+ returned as such.
+ >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
+ >>> x.data
+ matrix([[1, 2],
+ [3, 4]])
+
+ The type of the data can be accessed through the :attr:`baseclass`
+ attribute.
"""
return ndarray.view(self, self._baseclass)
_data = property(fget=_get_data)
data = property(fget=_get_data)
- def _get_flat(self):
- "Return a flat iterator."
+ @property
+ def flat(self):
+ """ Return a flat iterator, or set a flattened version of self to value. """
return MaskedIterator(self)
- def _set_flat(self, value):
- "Set a flattened version of self to value."
+ @flat.setter
+ def flat(self, value):
y = self.ravel()
y[:] = value
- flat = property(fget=_get_flat, fset=_set_flat,
- doc="Flat version of the array.")
-
- def get_fill_value(self):
+ @property
+ def fill_value(self):
"""
- Return the filling value of the masked array.
-
- Returns
- -------
- fill_value : scalar
- The filling value.
+ The filling value of the masked array is a scalar. When setting, None
+ will set to a default based on the data type.
Examples
--------
@@ -3603,8 +3621,17 @@ class MaskedArray(ndarray):
(1e+20+0j)
>>> x = np.ma.array([0, 1.], fill_value=-np.inf)
- >>> x.get_fill_value()
+ >>> x.fill_value
-inf
+ >>> x.fill_value = np.pi
+ >>> x.fill_value
+ 3.1415926535897931 # may vary
+
+ Reset to default:
+
+ >>> x.fill_value = None
+ >>> x.fill_value
+ 1e+20
"""
if self._fill_value is None:
@@ -3618,36 +3645,8 @@ class MaskedArray(ndarray):
return self._fill_value[()]
return self._fill_value
- def set_fill_value(self, value=None):
- """
- Set the filling value of the masked array.
-
- Parameters
- ----------
- value : scalar, optional
- The new filling value. Default is None, in which case a default
- based on the data type is used.
-
- See Also
- --------
- ma.set_fill_value : Equivalent function.
-
- Examples
- --------
- >>> x = np.ma.array([0, 1.], fill_value=-np.inf)
- >>> x.fill_value
- -inf
- >>> x.set_fill_value(np.pi)
- >>> x.fill_value
- 3.1415926535897931
-
- Reset to default:
-
- >>> x.set_fill_value()
- >>> x.fill_value
- 1e+20
-
- """
+ @fill_value.setter
+ def fill_value(self, value=None):
target = _check_fill_value(value, self.dtype)
_fill_value = self._fill_value
if _fill_value is None:
@@ -3657,8 +3656,9 @@ class MaskedArray(ndarray):
# Don't overwrite the attribute, just fill it (for propagation)
_fill_value[()] = target
- fill_value = property(fget=get_fill_value, fset=set_fill_value,
- doc="Filling value.")
+ # kept for compatibility
+ get_fill_value = fill_value.fget
+ set_fill_value = fill_value.fset
def filled(self, fill_value=None):
"""
@@ -3688,9 +3688,9 @@ class MaskedArray(ndarray):
--------
>>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999)
>>> x.filled()
- array([1, 2, -999, 4, -999])
+ array([ 1, 2, -999, 4, -999])
>>> type(x.filled())
- <type 'numpy.ndarray'>
+ <class 'numpy.ndarray'>
Subclassing is preserved. This means that if, e.g., the data part of
the masked array is a recarray, `filled` returns a recarray:
@@ -3755,7 +3755,7 @@ class MaskedArray(ndarray):
>>> x.compressed()
array([0, 1])
>>> type(x.compressed())
- <type 'numpy.ndarray'>
+ <class 'numpy.ndarray'>
"""
data = ndarray.ravel(self._data)
@@ -3797,25 +3797,29 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
+ >>> x
+ masked_array(
+ data=[[1, --, 3],
+ [--, 5, --],
+ [7, --, 9]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
>>> x.compress([1, 0, 1])
- masked_array(data = [1 3],
- mask = [False False],
- fill_value=999999)
+ masked_array(data=[1, 3],
+ mask=[False, False],
+ fill_value=999999)
>>> x.compress([1, 0, 1], axis=1)
- masked_array(data =
- [[1 3]
- [-- --]
- [7 9]],
- mask =
- [[False False]
- [ True True]
- [False False]],
- fill_value=999999)
+ masked_array(
+ data=[[1, 3],
+ [--, --],
+ [7, 9]],
+ mask=[[False, False],
+ [ True, True],
+ [False, False]],
+ fill_value=999999)
"""
# Get the basic components
@@ -4323,75 +4327,59 @@ class MaskedArray(ndarray):
raise MaskError('Cannot convert masked element to a Python long.')
return long(self.item())
-
- def get_imag(self):
+ @property
+ def imag(self):
"""
- Return the imaginary part of the masked array.
-
- The returned array is a view on the imaginary part of the `MaskedArray`
- whose `get_imag` method is called.
-
- Parameters
- ----------
- None
+ The imaginary part of the masked array.
- Returns
- -------
- result : MaskedArray
- The imaginary part of the masked array.
+ This property is a view on the imaginary part of this `MaskedArray`.
See Also
--------
- get_real, real, imag
+ real
Examples
--------
>>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
- >>> x.get_imag()
- masked_array(data = [1.0 -- 1.6],
- mask = [False True False],
- fill_value = 1e+20)
+ >>> x.imag
+ masked_array(data=[1.0, --, 1.6],
+ mask=[False, True, False],
+ fill_value=1e+20)
"""
result = self._data.imag.view(type(self))
result.__setmask__(self._mask)
return result
- imag = property(fget=get_imag, doc="Imaginary part.")
+ # kept for compatibility
+ get_imag = imag.fget
- def get_real(self):
+ @property
+ def real(self):
"""
- Return the real part of the masked array.
-
- The returned array is a view on the real part of the `MaskedArray`
- whose `get_real` method is called.
-
- Parameters
- ----------
- None
+ The real part of the masked array.
- Returns
- -------
- result : MaskedArray
- The real part of the masked array.
+ This property is a view on the real part of this `MaskedArray`.
See Also
--------
- get_imag, real, imag
+ imag
Examples
--------
>>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
- >>> x.get_real()
- masked_array(data = [1.0 -- 3.45],
- mask = [False True False],
- fill_value = 1e+20)
+ >>> x.real
+ masked_array(data=[1.0, --, 3.45],
+ mask=[False, True, False],
+ fill_value=1e+20)
"""
result = self._data.real.view(type(self))
result.__setmask__(self._mask)
return result
- real = property(fget=get_real, doc="Real part")
+
+ # kept for compatibility
+ get_real = real.fget
def count(self, axis=None, keepdims=np._NoValue):
"""
@@ -4431,13 +4419,12 @@ class MaskedArray(ndarray):
>>> a = ma.arange(6).reshape((2, 3))
>>> a[1, :] = ma.masked
>>> a
- masked_array(data =
- [[0 1 2]
- [-- -- --]],
- mask =
- [[False False False]
- [ True True True]],
- fill_value = 999999)
+ masked_array(
+ data=[[0, 1, 2],
+ [--, --, --]],
+ mask=[[False, False, False],
+ [ True, True, True]],
+ fill_value=999999)
>>> a.count()
3
@@ -4463,7 +4450,7 @@ class MaskedArray(ndarray):
if m is nomask:
# compare to _count_reduce_items in _methods.py
- if self.shape is ():
+ if self.shape == ():
if axis not in (None, 0):
raise np.AxisError(axis=axis, ndim=self.ndim)
return 1
@@ -4522,12 +4509,20 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
- >>> print(x.ravel())
- [1 -- 3 -- 5 -- 7 -- 9]
+ >>> x
+ masked_array(
+ data=[[1, --, 3],
+ [--, 5, --],
+ [7, --, 9]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
+ >>> x.ravel()
+ masked_array(data=[1, --, 3, --, 5, --, 7, --, 9],
+ mask=[False, True, False, True, False, True, False, True,
+ False],
+ fill_value=999999)
"""
r = ndarray.ravel(self._data, order=order).view(type(self))
@@ -4576,15 +4571,25 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1])
- >>> print(x)
- [[-- 2]
- [3 --]]
+ >>> x
+ masked_array(
+ data=[[--, 2],
+ [3, --]],
+ mask=[[ True, False],
+ [False, True]],
+ fill_value=999999)
>>> x = x.reshape((4,1))
- >>> print(x)
- [[--]
- [2]
- [3]
- [--]]
+ >>> x
+ masked_array(
+ data=[[--],
+ [2],
+ [3],
+ [--]],
+ mask=[[ True],
+ [False],
+ [False],
+ [ True]],
+ fill_value=999999)
"""
kwargs.update(order=kwargs.get('order', 'C'))
@@ -4641,21 +4646,36 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
+ >>> x
+ masked_array(
+ data=[[1, --, 3],
+ [--, 5, --],
+ [7, --, 9]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
>>> x.put([0,4,8],[10,20,30])
- >>> print(x)
- [[10 -- 3]
- [-- 20 --]
- [7 -- 30]]
+ >>> x
+ masked_array(
+ data=[[10, --, 3],
+ [--, 20, --],
+ [7, --, 30]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
>>> x.put(4,999)
- >>> print(x)
- [[10 -- 3]
- [-- 999 --]
- [7 -- 30]]
+ >>> x
+ masked_array(
+ data=[[10, --, 3],
+ [--, 999, --],
+ [7, --, 30]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
"""
# Hard mask: Get rid of the values/indices that fall on masked data
@@ -4695,14 +4715,14 @@ class MaskedArray(ndarray):
--------
>>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1])
>>> x.ids()
- (166670640, 166659832)
+ (166670640, 166659832) # may vary
If the array has no mask, the address of `nomask` is returned. This address
is typically not close to the data in memory:
>>> x = np.ma.array([1, 2, 3])
>>> x.ids()
- (166691080, 3083169284L)
+ (166691080, 3083169284L) # may vary
"""
if self._mask is nomask:
@@ -4851,13 +4871,12 @@ class MaskedArray(ndarray):
>>> import numpy.ma as ma
>>> x = ma.array(np.eye(3))
>>> x
- masked_array(data =
- [[ 1. 0. 0.]
- [ 0. 1. 0.]
- [ 0. 0. 1.]],
- mask =
- False,
- fill_value=1e+20)
+ masked_array(
+ data=[[1., 0., 0.],
+ [0., 1., 0.],
+ [0., 0., 1.]],
+ mask=False,
+ fill_value=1e+20)
>>> x.nonzero()
(array([0, 1, 2]), array([0, 1, 2]))
@@ -4865,15 +4884,14 @@ class MaskedArray(ndarray):
>>> x[1, 1] = ma.masked
>>> x
- masked_array(data =
- [[1.0 0.0 0.0]
- [0.0 -- 0.0]
- [0.0 0.0 1.0]],
- mask =
- [[False False False]
- [False True False]
- [False False False]],
- fill_value=1e+20)
+ masked_array(
+ data=[[1.0, 0.0, 0.0],
+ [0.0, --, 0.0],
+ [0.0, 0.0, 1.0]],
+ mask=[[False, False, False],
+ [False, True, False],
+ [False, False, False]],
+ fill_value=1e+20)
>>> x.nonzero()
(array([0, 2]), array([0, 2]))
@@ -4890,13 +4908,12 @@ class MaskedArray(ndarray):
>>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a > 3
- masked_array(data =
- [[False False False]
- [ True True True]
- [ True True True]],
- mask =
- False,
- fill_value=999999)
+ masked_array(
+ data=[[False, False, False],
+ [ True, True, True],
+ [ True, True, True]],
+ mask=False,
+ fill_value=True)
>>> ma.nonzero(a > 3)
(array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
@@ -4978,18 +4995,27 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
- >>> print(x.sum())
+ >>> x
+ masked_array(
+ data=[[1, --, 3],
+ [--, 5, --],
+ [7, --, 9]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
+ >>> x.sum()
25
- >>> print(x.sum(axis=1))
- [4 5 16]
- >>> print(x.sum(axis=0))
- [8 5 12]
+ >>> x.sum(axis=1)
+ masked_array(data=[4, 5, 16],
+ mask=[False, False, False],
+ fill_value=999999)
+ >>> x.sum(axis=0)
+ masked_array(data=[8, 5, 12],
+ mask=[False, False, False],
+ fill_value=999999)
>>> print(type(x.sum(axis=0, dtype=np.int64)[0]))
- <type 'numpy.int64'>
+ <class 'numpy.int64'>
"""
kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
@@ -5040,8 +5066,11 @@ class MaskedArray(ndarray):
Examples
--------
>>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0])
- >>> print(marr.cumsum())
- [0 1 3 -- -- -- 9 16 24 33]
+ >>> marr.cumsum()
+ masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33],
+ mask=[False, False, False, True, True, True, False, False,
+ False, False],
+ fill_value=999999)
"""
result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out)
@@ -5145,9 +5174,9 @@ class MaskedArray(ndarray):
--------
>>> a = np.ma.array([1,2,3], mask=[False, False, True])
>>> a
- masked_array(data = [1 2 --],
- mask = [False False True],
- fill_value = 999999)
+ masked_array(data=[1, 2, --],
+ mask=[False, False, True],
+ fill_value=999999)
>>> a.mean()
1.5
@@ -5200,9 +5229,9 @@ class MaskedArray(ndarray):
--------
>>> a = np.ma.array([1,2,3])
>>> a.anom()
- masked_array(data = [-1. 0. 1.],
- mask = False,
- fill_value = 1e+20)
+ masked_array(data=[-1., 0., 1.],
+ mask=False,
+ fill_value=1e+20)
"""
m = self.mean(axis, dtype)
@@ -5327,7 +5356,7 @@ class MaskedArray(ndarray):
out.__setmask__(self._mask)
return out
- def argsort(self, axis=np._NoValue, kind='quicksort', order=None,
+ def argsort(self, axis=np._NoValue, kind=None, order=None,
endwith=True, fill_value=None):
"""
Return an ndarray of indices that sort the array along the
@@ -5347,7 +5376,7 @@ class MaskedArray(ndarray):
Until then, the axis should be given explicitly when
``arr.ndim > 1``, to avoid a FutureWarning.
kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
- Sorting algorithm.
+ The sorting algorithm used.
order : list, optional
When `a` is an array with fields defined, this argument specifies
which fields to compare first, second, etc. Not all fields need be
@@ -5382,9 +5411,9 @@ class MaskedArray(ndarray):
--------
>>> a = np.ma.array([3,2,1], mask=[False, False, True])
>>> a
- masked_array(data = [3 2 --],
- mask = [False False True],
- fill_value = 999999)
+ masked_array(data=[3, 2, --],
+ mask=[False, False, True],
+ fill_value=999999)
>>> a.argsort()
array([1, 0, 2])
@@ -5432,15 +5461,19 @@ class MaskedArray(ndarray):
Examples
--------
- >>> x = np.ma.array(arange(4), mask=[1,1,0,0])
+ >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0])
>>> x.shape = (2,2)
- >>> print(x)
- [[-- --]
- [2 3]]
- >>> print(x.argmin(axis=0, fill_value=-1))
- [0 0]
- >>> print(x.argmin(axis=0, fill_value=9))
- [1 1]
+ >>> x
+ masked_array(
+ data=[[--, --],
+ [2, 3]],
+ mask=[[ True, True],
+ [False, False]],
+ fill_value=999999)
+ >>> x.argmin(axis=0, fill_value=-1)
+ array([0, 0])
+ >>> x.argmin(axis=0, fill_value=9)
+ array([1, 1])
"""
if fill_value is None:
@@ -5485,7 +5518,7 @@ class MaskedArray(ndarray):
d = self.filled(fill_value).view(ndarray)
return d.argmax(axis, out=out)
- def sort(self, axis=-1, kind='quicksort', order=None,
+ def sort(self, axis=-1, kind=None, order=None,
endwith=True, fill_value=None):
"""
Sort the array, in-place
@@ -5498,7 +5531,7 @@ class MaskedArray(ndarray):
Axis along which to sort. If None, the array is flattened before
sorting. The default is -1, which sorts along the last axis.
kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
- Sorting algorithm. Default is 'quicksort'.
+ The sorting algorithm used.
order : list, optional
When `a` is a structured array, this argument specifies which fields
to compare first, second, and so on. This list does not need to
@@ -5506,7 +5539,7 @@ class MaskedArray(ndarray):
endwith : {True, False}, optional
Whether missing values (if any) should be treated as the largest values
(True) or the smallest values (False)
- When the array contains unmasked values at the same extremes of the
+ When the array contains unmasked values sorting at the same extremes of the
datatype, the ordering of these values and the masked values is
undefined.
fill_value : {var}, optional
@@ -5531,23 +5564,29 @@ class MaskedArray(ndarray):
Examples
--------
- >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
+ >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
>>> # Default
>>> a.sort()
- >>> print(a)
- [1 3 5 -- --]
+ >>> a
+ masked_array(data=[1, 3, 5, --, --],
+ mask=[False, False, False, True, True],
+ fill_value=999999)
- >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
+ >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
>>> # Put missing values in the front
>>> a.sort(endwith=False)
- >>> print(a)
- [-- -- 1 3 5]
+ >>> a
+ masked_array(data=[--, --, 1, 3, 5],
+ mask=[ True, True, False, False, False],
+ fill_value=999999)
- >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
+ >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
>>> # fill_value takes over endwith
>>> a.sort(endwith=False, fill_value=3)
- >>> print(a)
- [1 -- -- 3 5]
+ >>> a
+ masked_array(data=[1, --, --, 3, 5],
+ mask=[False, True, True, False, False],
+ fill_value=999999)
"""
if self._mask is nomask:
@@ -5653,27 +5692,36 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array(np.arange(6), mask=[0 ,1, 0, 0, 0 ,1]).reshape(3, 2)
- >>> print(x)
- [[0 --]
- [2 3]
- [4 --]]
+ >>> x
+ masked_array(
+ data=[[0, --],
+ [2, 3],
+ [4, --]],
+ mask=[[False, True],
+ [False, False],
+ [False, True]],
+ fill_value=999999)
>>> x.mini()
- 0
+ masked_array(data=0,
+ mask=False,
+ fill_value=999999)
>>> x.mini(axis=0)
- masked_array(data = [0 3],
- mask = [False False],
- fill_value = 999999)
- >>> print(x.mini(axis=1))
- [0 2 4]
+ masked_array(data=[0, 3],
+ mask=[False, False],
+ fill_value=999999)
+ >>> x.mini(axis=1)
+ masked_array(data=[0, 2, 4],
+ mask=[False, False, False],
+ fill_value=999999)
There is a small difference between `mini` and `min`:
>>> x[:,1].mini(axis=0)
- masked_array(data = --,
- mask = True,
- fill_value = 999999)
+ masked_array(data=3,
+ mask=False,
+ fill_value=999999)
>>> x[:,1].min(axis=0)
- masked
+ 3
"""
# 2016-04-13, 1.13.0, gh-8764
@@ -5889,7 +5937,7 @@ class MaskedArray(ndarray):
returns bytes not strings.
"""
- return self.tobytes(fill_value, order='C')
+ return self.tobytes(fill_value, order=order)
def tobytes(self, fill_value=None, order='C'):
"""
@@ -5926,7 +5974,7 @@ class MaskedArray(ndarray):
--------
>>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
>>> x.tobytes()
- '\\x01\\x00\\x00\\x00?B\\x0f\\x00?B\\x0f\\x00\\x04\\x00\\x00\\x00'
+ b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
"""
return self.filled(fill_value).tobytes(order=order)
@@ -5974,14 +6022,20 @@ class MaskedArray(ndarray):
Examples
--------
>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
- >>> print(x.toflex())
- [[(1, False) (2, True) (3, False)]
- [(4, True) (5, False) (6, True)]
- [(7, False) (8, True) (9, False)]]
+ >>> x
+ masked_array(
+ data=[[1, --, 3],
+ [--, 5, --],
+ [7, --, 9]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
+ >>> x.toflex()
+ array([[(1, False), (2, True), (3, False)],
+ [(4, True), (5, False), (6, True)],
+ [(7, False), (8, True), (9, False)]],
+ dtype=[('_data', '<i8'), ('_mask', '?')])
"""
# Get the basic dtype.
@@ -6081,12 +6135,11 @@ class mvoid(MaskedArray):
_data.fill_value = fill_value
return _data
- def _get_data(self):
+ @property
+ def _data(self):
# Make sure that the _data part is a np.void
return super(mvoid, self)._data[()]
- _data = property(fget=_get_data)
-
def __getitem__(self, indx):
"""
Get the index.
@@ -6228,15 +6281,14 @@ def isMaskedArray(x):
[ 0., 0., 1.]])
>>> m = ma.masked_values(a, 0)
>>> m
- masked_array(data =
- [[1.0 -- --]
- [-- 1.0 --]
- [-- -- 1.0]],
- mask =
- [[False True True]
- [ True False True]
- [ True True False]],
- fill_value=0.0)
+ masked_array(
+ data=[[1.0, --, --],
+ [--, 1.0, --],
+ [--, --, 1.0]],
+ mask=[[False, True, True],
+ [ True, False, True],
+ [ True, True, False]],
+ fill_value=0.0)
>>> ma.isMaskedArray(a)
False
>>> ma.isMaskedArray(m)
@@ -6400,16 +6452,16 @@ def is_masked(x):
>>> import numpy.ma as ma
>>> x = ma.masked_equal([0, 1, 0, 2, 3], 0)
>>> x
- masked_array(data = [-- 1 -- 2 3],
- mask = [ True False True False False],
- fill_value=999999)
+ masked_array(data=[--, 1, --, 2, 3],
+ mask=[ True, False, True, False, False],
+ fill_value=0)
>>> ma.is_masked(x)
True
>>> x = ma.masked_equal([0, 1, 0, 2, 3], 42)
>>> x
- masked_array(data = [0 1 0 2 3],
- mask = False,
- fill_value=999999)
+ masked_array(data=[0, 1, 0, 2, 3],
+ mask=False,
+ fill_value=42)
>>> ma.is_masked(x)
False
@@ -6684,7 +6736,7 @@ def power(a, b, third=None):
argmin = _frommethod('argmin')
argmax = _frommethod('argmax')
-def argsort(a, axis=np._NoValue, kind='quicksort', order=None, endwith=True, fill_value=None):
+def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None):
"Function version of the eponymous method."
a = np.asanyarray(a)
@@ -6699,7 +6751,7 @@ def argsort(a, axis=np._NoValue, kind='quicksort', order=None, endwith=True, fil
return a.argsort(axis=axis, kind=kind, order=order)
argsort.__doc__ = MaskedArray.argsort.__doc__
-def sort(a, axis=-1, kind='quicksort', order=None, endwith=True, fill_value=None):
+def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None):
"Function version of the eponymous method."
a = np.array(a, copy=True, subok=True)
if axis is None:
@@ -6759,17 +6811,17 @@ def concatenate(arrays, axis=0):
>>> a[1] = ma.masked
>>> b = ma.arange(2, 5)
>>> a
- masked_array(data = [0 -- 2],
- mask = [False True False],
- fill_value = 999999)
+ masked_array(data=[0, --, 2],
+ mask=[False, True, False],
+ fill_value=999999)
>>> b
- masked_array(data = [2 3 4],
- mask = False,
- fill_value = 999999)
+ masked_array(data=[2, 3, 4],
+ mask=False,
+ fill_value=999999)
>>> ma.concatenate([a, b])
- masked_array(data = [0 -- 2 2 3 4],
- mask = [False True False False False False],
- fill_value = 999999)
+ masked_array(data=[0, --, 2, 2, 3, 4],
+ mask=[False, True, False, False, False, False],
+ fill_value=999999)
"""
d = np.concatenate([getdata(a) for a in arrays], axis)
@@ -6924,24 +6976,21 @@ def transpose(a, axes=None):
>>> import numpy.ma as ma
>>> x = ma.arange(4).reshape((2,2))
>>> x[1, 1] = ma.masked
- >>>> x
- masked_array(data =
- [[0 1]
- [2 --]],
- mask =
- [[False False]
- [False True]],
- fill_value = 999999)
+ >>> x
+ masked_array(
+ data=[[0, 1],
+ [2, --]],
+ mask=[[False, False],
+ [False, True]],
+ fill_value=999999)
>>> ma.transpose(x)
- masked_array(data =
- [[0 2]
- [1 --]],
- mask =
- [[False False]
- [False True]],
- fill_value = 999999)
-
+ masked_array(
+ data=[[0, 2],
+ [1, --]],
+ mask=[[False, False],
+ [False, True]],
+ fill_value=999999)
"""
# We can't use 'frommethod', as 'transpose' doesn't take keywords
try:
@@ -6988,39 +7037,39 @@ def resize(x, new_shape):
>>> a = ma.array([[1, 2] ,[3, 4]])
>>> a[0, 1] = ma.masked
>>> a
- masked_array(data =
- [[1 --]
- [3 4]],
- mask =
- [[False True]
- [False False]],
- fill_value = 999999)
+ masked_array(
+ data=[[1, --],
+ [3, 4]],
+ mask=[[False, True],
+ [False, False]],
+ fill_value=999999)
>>> np.resize(a, (3, 3))
- array([[1, 2, 3],
- [4, 1, 2],
- [3, 4, 1]])
+ masked_array(
+ data=[[1, 2, 3],
+ [4, 1, 2],
+ [3, 4, 1]],
+ mask=False,
+ fill_value=999999)
>>> ma.resize(a, (3, 3))
- masked_array(data =
- [[1 -- 3]
- [4 1 --]
- [3 4 1]],
- mask =
- [[False True False]
- [False False True]
- [False False False]],
- fill_value = 999999)
+ masked_array(
+ data=[[1, --, 3],
+ [4, 1, --],
+ [3, 4, 1]],
+ mask=[[False, True, False],
+ [False, False, True],
+ [False, False, False]],
+ fill_value=999999)
A MaskedArray is always returned, regardless of the input type.
>>> a = np.array([[1, 2] ,[3, 4]])
>>> ma.resize(a, (3, 3))
- masked_array(data =
- [[1 2 3]
- [4 1 2]
- [3 4 1]],
- mask =
- False,
- fill_value = 999999)
+ masked_array(
+ data=[[1, 2, 3],
+ [4, 1, 2],
+ [3, 4, 1]],
+ mask=False,
+ fill_value=999999)
"""
# We can't use _frommethods here, as N.resize is notoriously whiny.
@@ -7111,14 +7160,24 @@ def where(condition, x=_NoValue, y=_NoValue):
>>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0],
... [1, 0, 1],
... [0, 1, 0]])
- >>> print(x)
- [[0.0 -- 2.0]
- [-- 4.0 --]
- [6.0 -- 8.0]]
- >>> print(np.ma.where(x > 5, x, -3.1416))
- [[-3.1416 -- -3.1416]
- [-- -3.1416 --]
- [6.0 -- 8.0]]
+ >>> x
+ masked_array(
+ data=[[0.0, --, 2.0],
+ [--, 4.0, --],
+ [6.0, --, 8.0]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=1e+20)
+ >>> np.ma.where(x > 5, x, -3.1416)
+ masked_array(
+ data=[[-3.1416, --, -3.1416],
+ [--, -3.1416, --],
+ [6.0, --, 8.0]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=1e+20)
"""
@@ -7198,9 +7257,9 @@ def choose(indices, choices, out=None, mode='raise'):
>>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]])
>>> a = np.array([2, 1, 0])
>>> np.ma.choose(a, choice)
- masked_array(data = [3 2 1],
- mask = False,
- fill_value=999999)
+ masked_array(data=[3, 2, 1],
+ mask=False,
+ fill_value=999999)
"""
def fmask(x):
@@ -7323,25 +7382,23 @@ def mask_rowcols(a, axis=None):
[0, 0, 0]])
>>> a = ma.masked_equal(a, 1)
>>> a
- masked_array(data =
- [[0 0 0]
- [0 -- 0]
- [0 0 0]],
- mask =
- [[False False False]
- [False True False]
- [False False False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, 0, 0],
+ [0, --, 0],
+ [0, 0, 0]],
+ mask=[[False, False, False],
+ [False, True, False],
+ [False, False, False]],
+ fill_value=1)
>>> ma.mask_rowcols(a)
- masked_array(data =
- [[0 -- 0]
- [-- -- --]
- [0 -- 0]],
- mask =
- [[False True False]
- [ True True True]
- [False True False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, --, 0],
+ [--, --, --],
+ [0, --, 0]],
+ mask=[[False, True, False],
+ [ True, True, True],
+ [False, True, False]],
+ fill_value=1)
"""
a = array(a, subok=False)
@@ -7402,24 +7459,22 @@ def dot(a, b, strict=False, out=None):
Examples
--------
- >>> a = ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]])
- >>> b = ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]])
+ >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]])
+ >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]])
>>> np.ma.dot(a, b)
- masked_array(data =
- [[21 26]
- [45 64]],
- mask =
- [[False False]
- [False False]],
- fill_value = 999999)
+ masked_array(
+ data=[[21, 26],
+ [45, 64]],
+ mask=[[False, False],
+ [False, False]],
+ fill_value=999999)
>>> np.ma.dot(a, b, strict=True)
- masked_array(data =
- [[-- --]
- [-- 64]],
- mask =
- [[ True True]
- [ True False]],
- fill_value = 999999)
+ masked_array(
+ data=[[--, --],
+ [--, 64]],
+ mask=[[ True, True],
+ [ True, False]],
+ fill_value=999999)
"""
# !!!: Works only with 2D arrays. There should be a way to get it to run
@@ -7587,18 +7642,18 @@ def allequal(a, b, fill_value=True):
Examples
--------
- >>> a = ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
+ >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
>>> a
- masked_array(data = [10000000000.0 1e-07 --],
- mask = [False False True],
- fill_value=1e+20)
+ masked_array(data=[10000000000.0, 1e-07, --],
+ mask=[False, False, True],
+ fill_value=1e+20)
- >>> b = array([1e10, 1e-7, -42.0])
+ >>> b = np.array([1e10, 1e-7, -42.0])
>>> b
array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01])
- >>> ma.allequal(a, b, fill_value=False)
+ >>> np.ma.allequal(a, b, fill_value=False)
False
- >>> ma.allequal(a, b)
+ >>> np.ma.allequal(a, b)
True
"""
@@ -7664,29 +7719,29 @@ def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8):
Examples
--------
- >>> a = ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
+ >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
>>> a
- masked_array(data = [10000000000.0 1e-07 --],
- mask = [False False True],
- fill_value = 1e+20)
- >>> b = ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1])
- >>> ma.allclose(a, b)
+ masked_array(data=[10000000000.0, 1e-07, --],
+ mask=[False, False, True],
+ fill_value=1e+20)
+ >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1])
+ >>> np.ma.allclose(a, b)
False
- >>> a = ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
- >>> b = ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1])
- >>> ma.allclose(a, b)
+ >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
+ >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1])
+ >>> np.ma.allclose(a, b)
True
- >>> ma.allclose(a, b, masked_equal=False)
+ >>> np.ma.allclose(a, b, masked_equal=False)
False
Masked values are not compared directly.
- >>> a = ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
- >>> b = ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1])
- >>> ma.allclose(a, b)
+ >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
+ >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1])
+ >>> np.ma.allclose(a, b)
True
- >>> ma.allclose(a, b, masked_equal=False)
+ >>> np.ma.allclose(a, b, masked_equal=False)
False
"""
@@ -7753,15 +7808,14 @@ def asarray(a, dtype=None, order=None):
--------
>>> x = np.arange(10.).reshape(2, 5)
>>> x
- array([[ 0., 1., 2., 3., 4.],
- [ 5., 6., 7., 8., 9.]])
+ array([[0., 1., 2., 3., 4.],
+ [5., 6., 7., 8., 9.]])
>>> np.ma.asarray(x)
- masked_array(data =
- [[ 0. 1. 2. 3. 4.]
- [ 5. 6. 7. 8. 9.]],
- mask =
- False,
- fill_value = 1e+20)
+ masked_array(
+ data=[[0., 1., 2., 3., 4.],
+ [5., 6., 7., 8., 9.]],
+ mask=False,
+ fill_value=1e+20)
>>> type(np.ma.asarray(x))
<class 'numpy.ma.core.MaskedArray'>
@@ -7801,15 +7855,14 @@ def asanyarray(a, dtype=None):
--------
>>> x = np.arange(10.).reshape(2, 5)
>>> x
- array([[ 0., 1., 2., 3., 4.],
- [ 5., 6., 7., 8., 9.]])
+ array([[0., 1., 2., 3., 4.],
+ [5., 6., 7., 8., 9.]])
>>> np.ma.asanyarray(x)
- masked_array(data =
- [[ 0. 1. 2. 3. 4.]
- [ 5. 6. 7. 8. 9.]],
- mask =
- False,
- fill_value = 1e+20)
+ masked_array(
+ data=[[0., 1., 2., 3., 4.],
+ [5., 6., 7., 8., 9.]],
+ mask=False,
+ fill_value=1e+20)
>>> type(np.ma.asanyarray(x))
<class 'numpy.ma.core.MaskedArray'>
@@ -7953,39 +8006,38 @@ def fromflex(fxarray):
>>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4)
>>> rec = x.toflex()
>>> rec
- array([[(0, False), (1, True), (2, False)],
- [(3, True), (4, False), (5, True)],
- [(6, False), (7, True), (8, False)]],
- dtype=[('_data', '<i4'), ('_mask', '|b1')])
+ array([[(0, False), (1, True), (2, False)],
+ [(3, True), (4, False), (5, True)],
+ [(6, False), (7, True), (8, False)]],
+ dtype=[('_data', '<i8'), ('_mask', '?')])
>>> x2 = np.ma.fromflex(rec)
>>> x2
- masked_array(data =
- [[0 -- 2]
- [-- 4 --]
- [6 -- 8]],
- mask =
- [[False True False]
- [ True False True]
- [False True False]],
- fill_value = 999999)
+ masked_array(
+ data=[[0, --, 2],
+ [--, 4, --],
+ [6, --, 8]],
+ mask=[[False, True, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
Extra fields can be present in the structured array but are discarded:
>>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')]
>>> rec2 = np.zeros((2, 2), dtype=dt)
>>> rec2
- array([[(0, False, 0.0), (0, False, 0.0)],
- [(0, False, 0.0), (0, False, 0.0)]],
- dtype=[('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')])
+ array([[(0, False, 0.), (0, False, 0.)],
+ [(0, False, 0.), (0, False, 0.)]],
+ dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')])
>>> y = np.ma.fromflex(rec2)
>>> y
- masked_array(data =
- [[0 0]
- [0 0]],
- mask =
- [[False False]
- [False False]],
- fill_value = 999999)
+ masked_array(
+ data=[[0, 0],
+ [0, 0]],
+ mask=[[False, False],
+ [False, False]],
+ fill_value=999999,
+ dtype=int32)
"""
return masked_array(fxarray['_data'], mask=fxarray['_mask'])
@@ -8086,7 +8138,10 @@ def append(a, b, axis=None):
>>> import numpy.ma as ma
>>> a = ma.masked_values([1, 2, 3], 2)
>>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7)
- >>> print(ma.append(a, b))
- [1 -- 3 4 5 6 -- 8 9]
+ >>> ma.append(a, b)
+ masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9],
+ mask=[False, True, False, False, False, False, True, False,
+ False],
+ fill_value=999999)
"""
return concatenate([a, b], axis)
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 3be4d3625..639b3dd1f 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -81,15 +81,14 @@ def count_masked(arr, axis=None):
>>> a[1, 2] = ma.masked
>>> a[2, 1] = ma.masked
>>> a
- masked_array(data =
- [[0 1 2]
- [-- 4 --]
- [6 -- 8]],
- mask =
- [[False False False]
- [ True False True]
- [False True False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, 1, 2],
+ [--, 4, --],
+ [6, --, 8]],
+ mask=[[False, False, False],
+ [ True, False, True],
+ [False, True, False]],
+ fill_value=999999)
>>> ma.count_masked(a)
3
@@ -132,15 +131,15 @@ def masked_all(shape, dtype=float):
--------
>>> import numpy.ma as ma
>>> ma.masked_all((3, 3))
- masked_array(data =
- [[-- -- --]
- [-- -- --]
- [-- -- --]],
- mask =
- [[ True True True]
- [ True True True]
- [ True True True]],
- fill_value=1e+20)
+ masked_array(
+ data=[[--, --, --],
+ [--, --, --],
+ [--, --, --]],
+ mask=[[ True, True, True],
+ [ True, True, True],
+ [ True, True, True]],
+ fill_value=1e+20,
+ dtype=float64)
The `dtype` parameter defines the underlying data type.
@@ -188,16 +187,16 @@ def masked_all_like(arr):
>>> import numpy.ma as ma
>>> arr = np.zeros((2, 3), dtype=np.float32)
>>> arr
- array([[ 0., 0., 0.],
- [ 0., 0., 0.]], dtype=float32)
+ array([[0., 0., 0.],
+ [0., 0., 0.]], dtype=float32)
>>> ma.masked_all_like(arr)
- masked_array(data =
- [[-- -- --]
- [-- -- --]],
- mask =
- [[ True True True]
- [ True True True]],
- fill_value=1e+20)
+ masked_array(
+ data=[[--, --, --],
+ [--, --, --]],
+ mask=[[ True, True, True],
+ [ True, True, True]],
+ fill_value=1e+20,
+ dtype=float32)
The dtype of the masked array matches the dtype of `arr`.
@@ -391,7 +390,6 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
i[axis] = slice(None, None)
outshape = np.asarray(arr.shape).take(indlist)
i.put(indlist, ind)
- j = i.copy()
res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
# if res is a number, then we have a smaller output array
asscalar = np.isscalar(res)
@@ -492,28 +490,45 @@ if apply_over_axes.__doc__ is not None:
Examples
--------
- >>> a = ma.arange(24).reshape(2,3,4)
- >>> a[:,0,1] = ma.masked
- >>> a[:,1,:] = ma.masked
- >>> print(a)
- [[[0 -- 2 3]
- [-- -- -- --]
- [8 9 10 11]]
-
- [[12 -- 14 15]
- [-- -- -- --]
- [20 21 22 23]]]
- >>> print(ma.apply_over_axes(ma.sum, a, [0,2]))
- [[[46]
- [--]
- [124]]]
+ >>> a = np.ma.arange(24).reshape(2,3,4)
+ >>> a[:,0,1] = np.ma.masked
+ >>> a[:,1,:] = np.ma.masked
+ >>> a
+ masked_array(
+ data=[[[0, --, 2, 3],
+ [--, --, --, --],
+ [8, 9, 10, 11]],
+ [[12, --, 14, 15],
+ [--, --, --, --],
+ [20, 21, 22, 23]]],
+ mask=[[[False, True, False, False],
+ [ True, True, True, True],
+ [False, False, False, False]],
+ [[False, True, False, False],
+ [ True, True, True, True],
+ [False, False, False, False]]],
+ fill_value=999999)
+ >>> np.ma.apply_over_axes(np.ma.sum, a, [0,2])
+ masked_array(
+ data=[[[46],
+ [--],
+ [124]]],
+ mask=[[[False],
+ [ True],
+ [False]]],
+ fill_value=999999)
Tuple axis arguments to ufuncs are equivalent:
- >>> print(ma.sum(a, axis=(0,2)).reshape((1,-1,1)))
- [[[46]
- [--]
- [124]]]
+ >>> np.ma.sum(a, axis=(0,2)).reshape((1,-1,1))
+ masked_array(
+ data=[[[46],
+ [--],
+ [124]]],
+ mask=[[[False],
+ [ True],
+ [False]]],
+ fill_value=999999)
"""
@@ -558,14 +573,19 @@ def average(a, axis=None, weights=None, returned=False):
1.25
>>> x = np.ma.arange(6.).reshape(3, 2)
- >>> print(x)
- [[ 0. 1.]
- [ 2. 3.]
- [ 4. 5.]]
+ >>> x
+ masked_array(
+ data=[[0., 1.],
+ [2., 3.],
+ [4., 5.]],
+ mask=False,
+ fill_value=1e+20)
>>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3],
... returned=True)
- >>> print(avg)
- [2.66666666667 3.66666666667]
+ >>> avg
+ masked_array(data=[2.6666666666666665, 3.6666666666666665],
+ mask=[False, False],
+ fill_value=1e+20)
"""
a = asarray(a)
@@ -676,9 +696,9 @@ def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
>>> np.ma.median(x)
2.5
>>> np.ma.median(x, axis=-1, overwrite_input=True)
- masked_array(data = [ 2. 5.],
- mask = False,
- fill_value = 1e+20)
+ masked_array(data=[2.0, 5.0],
+ mask=[False, False],
+ fill_value=1e+20)
"""
if not hasattr(a, 'mask'):
@@ -856,15 +876,14 @@ def compress_rowcols(x, axis=None):
... [1, 0, 0],
... [0, 0, 0]])
>>> x
- masked_array(data =
- [[-- 1 2]
- [-- 4 5]
- [6 7 8]],
- mask =
- [[ True False False]
- [ True False False]
- [False False False]],
- fill_value = 999999)
+ masked_array(
+ data=[[--, 1, 2],
+ [--, 4, 5],
+ [6, 7, 8]],
+ mask=[[ True, False, False],
+ [ True, False, False],
+ [False, False, False]],
+ fill_value=999999)
>>> np.ma.compress_rowcols(x)
array([[7, 8]])
@@ -937,25 +956,24 @@ def mask_rows(a, axis=None):
[0, 0, 0]])
>>> a = ma.masked_equal(a, 1)
>>> a
- masked_array(data =
- [[0 0 0]
- [0 -- 0]
- [0 0 0]],
- mask =
- [[False False False]
- [False True False]
- [False False False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, 0, 0],
+ [0, --, 0],
+ [0, 0, 0]],
+ mask=[[False, False, False],
+ [False, True, False],
+ [False, False, False]],
+ fill_value=1)
+
>>> ma.mask_rows(a)
- masked_array(data =
- [[0 0 0]
- [-- -- --]
- [0 0 0]],
- mask =
- [[False False False]
- [ True True True]
- [False False False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, 0, 0],
+ [--, --, --],
+ [0, 0, 0]],
+ mask=[[False, False, False],
+ [ True, True, True],
+ [False, False, False]],
+ fill_value=1)
"""
return mask_rowcols(a, 0)
@@ -982,25 +1000,23 @@ def mask_cols(a, axis=None):
[0, 0, 0]])
>>> a = ma.masked_equal(a, 1)
>>> a
- masked_array(data =
- [[0 0 0]
- [0 -- 0]
- [0 0 0]],
- mask =
- [[False False False]
- [False True False]
- [False False False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, 0, 0],
+ [0, --, 0],
+ [0, 0, 0]],
+ mask=[[False, False, False],
+ [False, True, False],
+ [False, False, False]],
+ fill_value=1)
>>> ma.mask_cols(a)
- masked_array(data =
- [[0 -- 0]
- [0 -- 0]
- [0 -- 0]],
- mask =
- [[False True False]
- [False True False]
- [False True False]],
- fill_value=999999)
+ masked_array(
+ data=[[0, --, 0],
+ [0, --, 0],
+ [0, --, 0]],
+ mask=[[False, True, False],
+ [False, True, False],
+ [False, True, False]],
+ fill_value=1)
"""
return mask_rowcols(a, 1)
@@ -1078,12 +1094,12 @@ def intersect1d(ar1, ar2, assume_unique=False):
Examples
--------
- >>> x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
- >>> y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
- >>> intersect1d(x, y)
- masked_array(data = [1 3 --],
- mask = [False False True],
- fill_value = 999999)
+ >>> x = np.ma.array([1, 3, 3, 3], mask=[0, 0, 0, 1])
+ >>> y = np.ma.array([3, 1, 1, 1], mask=[0, 0, 0, 1])
+ >>> np.ma.intersect1d(x, y)
+ masked_array(data=[1, 3, --],
+ mask=[False, False, True],
+ fill_value=999999)
"""
if assume_unique:
@@ -1216,9 +1232,9 @@ def setdiff1d(ar1, ar2, assume_unique=False):
--------
>>> x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1])
>>> np.ma.setdiff1d(x, [1, 2])
- masked_array(data = [3 --],
- mask = [False True],
- fill_value = 999999)
+ masked_array(data=[3, --],
+ mask=[False, True],
+ fill_value=999999)
"""
if assume_unique:
@@ -1483,7 +1499,9 @@ class mr_class(MAxisConcatenator):
Examples
--------
>>> np.ma.mr_[np.ma.array([1,2,3]), 0, 0, np.ma.array([4,5,6])]
- array([1, 2, 3, 0, 0, 4, 5, 6])
+ masked_array(data=[1, 2, 3, ..., 4, 5, 6],
+ mask=False,
+ fill_value=999999)
"""
def __init__(self):
@@ -1514,7 +1532,7 @@ def flatnotmasked_edges(a):
See Also
--------
- flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges,
+ flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges
clump_masked, clump_unmasked
Notes
@@ -1524,19 +1542,19 @@ def flatnotmasked_edges(a):
Examples
--------
>>> a = np.ma.arange(10)
- >>> flatnotmasked_edges(a)
- [0,-1]
+ >>> np.ma.flatnotmasked_edges(a)
+ array([0, 9])
>>> mask = (a < 3) | (a > 8) | (a == 5)
>>> a[mask] = np.ma.masked
>>> np.array(a[~a.mask])
array([3, 4, 6, 7, 8])
- >>> flatnotmasked_edges(a)
+ >>> np.ma.flatnotmasked_edges(a)
array([3, 8])
>>> a[:] = np.ma.masked
- >>> print(flatnotmasked_edges(ma))
+ >>> print(np.ma.flatnotmasked_edges(a))
None
"""
@@ -1575,7 +1593,7 @@ def notmasked_edges(a, axis=None):
See Also
--------
- flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous,
+ flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous
clump_masked, clump_unmasked
Examples
@@ -1588,7 +1606,7 @@ def notmasked_edges(a, axis=None):
>>> np.array(am[~am.mask])
array([0, 1, 2, 3, 6])
- >>> np.ma.notmasked_edges(ma)
+ >>> np.ma.notmasked_edges(am)
array([0, 6])
"""
@@ -1620,7 +1638,7 @@ def flatnotmasked_contiguous(a):
See Also
--------
- flatnotmasked_edges, notmasked_contiguous, notmasked_edges,
+ flatnotmasked_edges, notmasked_contiguous, notmasked_edges
clump_masked, clump_unmasked
Notes
@@ -1680,7 +1698,7 @@ def notmasked_contiguous(a, axis=None):
See Also
--------
- flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
+ flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
clump_masked, clump_unmasked
Notes
@@ -1709,15 +1727,11 @@ def notmasked_contiguous(a, axis=None):
[slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)]
>>> np.ma.notmasked_contiguous(ma, axis=0)
- [[slice(0, 1, None), slice(2, 3, None)], # column broken into two segments
- [], # fully masked column
- [slice(0, 1, None)],
- [slice(0, 3, None)]]
+ [[slice(0, 1, None), slice(2, 3, None)], [], [slice(0, 1, None)], [slice(0, 3, None)]]
>>> np.ma.notmasked_contiguous(ma, axis=1)
- [[slice(0, 1, None), slice(2, 4, None)], # row broken into two segments
- [slice(3, 4, None)],
- [slice(0, 1, None), slice(3, 4, None)]]
+ [[slice(0, 1, None), slice(2, 4, None)], [slice(3, 4, None)], [slice(0, 1, None), slice(3, 4, None)]]
+
"""
a = asarray(a)
nd = a.ndim
@@ -1789,7 +1803,7 @@ def clump_unmasked(a):
See Also
--------
- flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
+ flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
notmasked_contiguous, clump_masked
Examples
@@ -1828,7 +1842,7 @@ def clump_masked(a):
See Also
--------
- flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
+ flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
notmasked_contiguous, clump_unmasked
Examples
diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py
index b16e1670a..931a7e8b9 100644
--- a/numpy/ma/mrecords.py
+++ b/numpy/ma/mrecords.py
@@ -19,7 +19,6 @@ import sys
import warnings
import numpy as np
-import numpy.core.numerictypes as ntypes
from numpy.compat import basestring
from numpy import (
bool_, dtype, ndarray, recarray, array as narray
@@ -167,24 +166,22 @@ class MaskedRecords(MaskedArray, object):
_dict['_baseclass'] = recarray
return
- def _getdata(self):
+ @property
+ def _data(self):
"""
Returns the data as a recarray.
"""
return ndarray.view(self, recarray)
- _data = property(fget=_getdata)
-
- def _getfieldmask(self):
+ @property
+ def _fieldmask(self):
"""
Alias to mask.
"""
return self._mask
- _fieldmask = property(fget=_getfieldmask)
-
def __len__(self):
"""
Returns the length
@@ -211,7 +208,7 @@ class MaskedRecords(MaskedArray, object):
_localdict = ndarray.__getattribute__(self, '__dict__')
_data = ndarray.view(self, _localdict['_baseclass'])
obj = _data.getfield(*res)
- if obj.dtype.names is not None:
+ if obj.dtype.fields:
raise NotImplementedError("MaskedRecords is currently limited to"
"simple records.")
# Get some special attributes
@@ -224,7 +221,8 @@ class MaskedRecords(MaskedArray, object):
except IndexError:
# Couldn't find a mask: use the default (nomask)
pass
- hasmasked = _mask.view((bool, (len(_mask.dtype) or 1))).any()
+ tp_len = len(_mask.dtype)
+ hasmasked = _mask.view((bool, ((tp_len,) if tp_len else ()))).any()
if (obj.shape or hasmasked):
obj = obj.view(MaskedArray)
obj._baseclass = ndarray
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index e0dbf1b1a..fb3f1a810 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -49,7 +49,7 @@ from numpy.ma.core import (
ravel, repeat, reshape, resize, shape, sin, sinh, sometrue, sort, sqrt,
subtract, sum, take, tan, tanh, transpose, where, zeros,
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
pi = np.pi
@@ -374,12 +374,12 @@ class TestMaskedArray(object):
y2a = array(x1, mask=m, copy=1)
assert_(y2a._data.__array_interface__ != x1.__array_interface__)
- #assert_( y2a.mask is not m)
+ #assert_( y2a._mask is not m)
assert_(y2a._mask.__array_interface__ != m.__array_interface__)
assert_(y2a[2] is masked)
y2a[2] = 9
assert_(y2a[2] is not masked)
- #assert_( y2a.mask is not m)
+ #assert_( y2a._mask is not m)
assert_(y2a._mask.__array_interface__ != m.__array_interface__)
assert_(allequal(y2a.mask, 0))
@@ -5203,3 +5203,10 @@ def test_fieldless_void():
mx = np.ma.array(x, mask=x)
assert_equal(mx.dtype, x.dtype)
assert_equal(mx.shape, x.shape)
+
+
+def test_mask_shape_assignment_does_not_break_masked():
+ a = np.ma.masked
+ b = np.ma.array(1, mask=a.mask)
+ b.shape = (1,)
+ assert_equal(a.mask.shape, ())
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index 5243cf714..afcfd126e 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -891,61 +891,51 @@ class TestMedian(object):
expected)
def test_nan(self):
- with suppress_warnings() as w:
- w.record(RuntimeWarning)
- for mask in (False, np.zeros(6, dtype=bool)):
- dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
- dm.mask = mask
-
- # scalar result
- r = np.ma.median(dm, axis=None)
- assert_(np.isscalar(r))
- assert_array_equal(r, np.nan)
- r = np.ma.median(dm.ravel(), axis=0)
- assert_(np.isscalar(r))
- assert_array_equal(r, np.nan)
-
- r = np.ma.median(dm, axis=0)
- assert_equal(type(r), MaskedArray)
- assert_array_equal(r, [1, np.nan, 3])
- r = np.ma.median(dm, axis=1)
- assert_equal(type(r), MaskedArray)
- assert_array_equal(r, [np.nan, 2])
- r = np.ma.median(dm, axis=-1)
- assert_equal(type(r), MaskedArray)
- assert_array_equal(r, [np.nan, 2])
-
+ for mask in (False, np.zeros(6, dtype=bool)):
dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
- dm[:, 2] = np.ma.masked
- assert_array_equal(np.ma.median(dm, axis=None), np.nan)
- assert_array_equal(np.ma.median(dm, axis=0), [1, np.nan, 3])
- assert_array_equal(np.ma.median(dm, axis=1), [np.nan, 1.5])
- assert_equal([x.category is RuntimeWarning for x in w.log],
- [True]*13)
+ dm.mask = mask
+
+ # scalar result
+ r = np.ma.median(dm, axis=None)
+ assert_(np.isscalar(r))
+ assert_array_equal(r, np.nan)
+ r = np.ma.median(dm.ravel(), axis=0)
+ assert_(np.isscalar(r))
+ assert_array_equal(r, np.nan)
+
+ r = np.ma.median(dm, axis=0)
+ assert_equal(type(r), MaskedArray)
+ assert_array_equal(r, [1, np.nan, 3])
+ r = np.ma.median(dm, axis=1)
+ assert_equal(type(r), MaskedArray)
+ assert_array_equal(r, [np.nan, 2])
+ r = np.ma.median(dm, axis=-1)
+ assert_equal(type(r), MaskedArray)
+ assert_array_equal(r, [np.nan, 2])
+
+ dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
+ dm[:, 2] = np.ma.masked
+ assert_array_equal(np.ma.median(dm, axis=None), np.nan)
+ assert_array_equal(np.ma.median(dm, axis=0), [1, np.nan, 3])
+ assert_array_equal(np.ma.median(dm, axis=1), [np.nan, 1.5])
def test_out_nan(self):
- with warnings.catch_warnings(record=True):
- warnings.filterwarnings('always', '', RuntimeWarning)
- o = np.ma.masked_array(np.zeros((4,)))
- d = np.ma.masked_array(np.ones((3, 4)))
- d[2, 1] = np.nan
- d[2, 2] = np.ma.masked
- assert_equal(np.ma.median(d, 0, out=o), o)
- o = np.ma.masked_array(np.zeros((3,)))
- assert_equal(np.ma.median(d, 1, out=o), o)
- o = np.ma.masked_array(np.zeros(()))
- assert_equal(np.ma.median(d, out=o), o)
+ o = np.ma.masked_array(np.zeros((4,)))
+ d = np.ma.masked_array(np.ones((3, 4)))
+ d[2, 1] = np.nan
+ d[2, 2] = np.ma.masked
+ assert_equal(np.ma.median(d, 0, out=o), o)
+ o = np.ma.masked_array(np.zeros((3,)))
+ assert_equal(np.ma.median(d, 1, out=o), o)
+ o = np.ma.masked_array(np.zeros(()))
+ assert_equal(np.ma.median(d, out=o), o)
def test_nan_behavior(self):
a = np.ma.masked_array(np.arange(24, dtype=float))
a[::3] = np.ma.masked
a[2] = np.nan
- with suppress_warnings() as w:
- w.record(RuntimeWarning)
- assert_array_equal(np.ma.median(a), np.nan)
- assert_array_equal(np.ma.median(a, axis=0), np.nan)
- assert_(w.log[0].category is RuntimeWarning)
- assert_(w.log[1].category is RuntimeWarning)
+ assert_array_equal(np.ma.median(a), np.nan)
+ assert_array_equal(np.ma.median(a, axis=0), np.nan)
a = np.ma.masked_array(np.arange(24, dtype=float).reshape(2, 3, 4))
a.mask = np.arange(a.size) % 2 == 1
@@ -954,39 +944,26 @@ class TestMedian(object):
a[1, 1, 2] = np.nan
# no axis
- with suppress_warnings() as w:
- w.record(RuntimeWarning)
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_array_equal(np.ma.median(a), np.nan)
- assert_(np.isscalar(np.ma.median(a)))
- assert_(w.log[0].category is RuntimeWarning)
+ assert_array_equal(np.ma.median(a), np.nan)
+ assert_(np.isscalar(np.ma.median(a)))
# axis0
b = np.ma.median(aorig, axis=0)
b[2, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.ma.median(a, 0), b)
- assert_equal(len(w), 1)
+ assert_equal(np.ma.median(a, 0), b)
# axis1
b = np.ma.median(aorig, axis=1)
b[1, 3] = np.nan
b[1, 2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.ma.median(a, 1), b)
- assert_equal(len(w), 1)
+ assert_equal(np.ma.median(a, 1), b)
# axis02
b = np.ma.median(aorig, axis=(0, 2))
b[1] = np.nan
b[2] = np.nan
- with warnings.catch_warnings(record=True) as w:
- warnings.filterwarnings('always', '', RuntimeWarning)
- assert_equal(np.ma.median(a, (0, 2)), b)
- assert_equal(len(w), 1)
+ assert_equal(np.ma.median(a, (0, 2)), b)
def test_ambigous_fill(self):
# 255 is max value, used as filler for sort
diff --git a/numpy/ma/tests/test_mrecords.py b/numpy/ma/tests/test_mrecords.py
index dbbf1c8a1..94e772d55 100644
--- a/numpy/ma/tests/test_mrecords.py
+++ b/numpy/ma/tests/test_mrecords.py
@@ -23,7 +23,7 @@ from numpy.ma.testutils import (
assert_, assert_equal,
assert_equal_records,
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
class TestMRecords(object):
diff --git a/numpy/ma/tests/test_old_ma.py b/numpy/ma/tests/test_old_ma.py
index 2978be22c..1c523768d 100644
--- a/numpy/ma/tests/test_old_ma.py
+++ b/numpy/ma/tests/test_old_ma.py
@@ -21,7 +21,7 @@ from numpy.ma import (
repeat, resize, shape, sin, sinh, sometrue, sort, sqrt, subtract, sum,
take, tan, tanh, transpose, where, zeros,
)
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
pi = np.pi
@@ -270,7 +270,7 @@ class TestMa(object):
y1 = array(x1, mask=m)
assert_(y1._data is not x1)
assert_(allequal(x1, y1._data))
- assert_(y1.mask is m)
+ assert_(y1._mask is m)
y1a = array(y1, copy=0)
# For copy=False, one might expect that the array would just
@@ -280,19 +280,19 @@ class TestMa(object):
y1._mask.__array_interface__)
y2 = array(x1, mask=m3, copy=0)
- assert_(y2.mask is m3)
+ assert_(y2._mask is m3)
assert_(y2[2] is masked)
y2[2] = 9
assert_(y2[2] is not masked)
- assert_(y2.mask is m3)
+ assert_(y2._mask is m3)
assert_(allequal(y2.mask, 0))
y2a = array(x1, mask=m, copy=1)
- assert_(y2a.mask is not m)
+ assert_(y2a._mask is not m)
assert_(y2a[2] is masked)
y2a[2] = 9
assert_(y2a[2] is not masked)
- assert_(y2a.mask is not m)
+ assert_(y2a._mask is not m)
assert_(allequal(y2a.mask, 0))
y3 = array(x1 * 1.0, mask=m)
@@ -318,14 +318,14 @@ class TestMa(object):
assert_(x[3] is masked)
assert_(x[4] is masked)
x[[1, 4]] = [10, 40]
- assert_(x.mask is m)
+ assert_(x._mask is m)
assert_(x[3] is masked)
assert_(x[4] is not masked)
assert_(eq(x, [0, 10, 2, -1, 40]))
x = array(d, mask=m2, copy=True)
x.put([0, 1, 2], [-1, 100, 200])
- assert_(x.mask is not m2)
+ assert_(x._mask is not m2)
assert_(x[3] is masked)
assert_(x[4] is masked)
assert_(eq(x, [-1, 100, 200, 0, 0]))
diff --git a/numpy/ma/tests/test_regression.py b/numpy/ma/tests/test_regression.py
index 54f1bda7d..b83873a5a 100644
--- a/numpy/ma/tests/test_regression.py
+++ b/numpy/ma/tests/test_regression.py
@@ -87,3 +87,7 @@ class TestRegression(object):
# See gh-12464. Indexing with empty list should give empty result.
ma = np.ma.MaskedArray([(1, 1.), (2, 2.), (3, 3.)], dtype='i4,f4')
assert_array_equal(ma[[]], ma[:0])
+
+ def test_masked_array_tostring_fortran(self):
+ ma = np.ma.arange(4).reshape((2,2))
+ assert_array_equal(ma.tostring(order='F'), ma.T.tostring())
diff --git a/numpy/ma/tests/test_subclassing.py b/numpy/ma/tests/test_subclassing.py
index f8ab52bb9..440b36722 100644
--- a/numpy/ma/tests/test_subclassing.py
+++ b/numpy/ma/tests/test_subclassing.py
@@ -66,11 +66,11 @@ class MSubArray(SubArray, MaskedArray):
_data.info = subarr.info
return _data
- def _get_series(self):
+ @property
+ def _series(self):
_view = self.view(MaskedArray)
_view._sharedmask = False
return _view
- _series = property(fget=_get_series)
msubarray = MSubArray
diff --git a/numpy/ma/timer_comparison.py b/numpy/ma/timer_comparison.py
index 68104ed0a..4ad635e38 100644
--- a/numpy/ma/timer_comparison.py
+++ b/numpy/ma/timer_comparison.py
@@ -430,11 +430,10 @@ if __name__ == '__main__':
setup_cur = "import numpy.ma.core as module\n" + setup_base
(nrepeat, nloop) = (10, 10)
- if 1:
- for i in range(1, 8):
- func = 'tester.test_%i()' % i
- cur = timeit.Timer(func, setup_cur).repeat(nrepeat, nloop*10)
- cur = np.sort(cur)
- print("#%i" % i + 50*'.')
- print(eval("ModuleTester.test_%i.__doc__" % i))
- print("core_current : %.3f - %.3f" % (cur[0], cur[1]))
+ for i in range(1, 8):
+ func = 'tester.test_%i()' % i
+ cur = timeit.Timer(func, setup_cur).repeat(nrepeat, nloop*10)
+ cur = np.sort(cur)
+ print("#%i" % i + 50*'.')
+ print(eval("ModuleTester.test_%i.__doc__" % i))
+ print("core_current : %.3f - %.3f" % (cur[0], cur[1]))
diff --git a/numpy/matlib.py b/numpy/matlib.py
index 004e5f0c8..9e115943a 100644
--- a/numpy/matlib.py
+++ b/numpy/matlib.py
@@ -39,11 +39,11 @@ def empty(shape, dtype=None, order='C'):
--------
>>> import numpy.matlib
>>> np.matlib.empty((2, 2)) # filled with random data
- matrix([[ 6.76425276e-320, 9.79033856e-307],
- [ 7.39337286e-309, 3.22135945e-309]]) #random
+ matrix([[ 6.76425276e-320, 9.79033856e-307], # random
+ [ 7.39337286e-309, 3.22135945e-309]])
>>> np.matlib.empty((2, 2), dtype=int)
- matrix([[ 6600475, 0],
- [ 6586976, 22740995]]) #random
+ matrix([[ 6600475, 0], # random
+ [ 6586976, 22740995]])
"""
return ndarray.__new__(matrix, shape, dtype, order=order)
@@ -82,11 +82,11 @@ def ones(shape, dtype=None, order='C'):
Examples
--------
>>> np.matlib.ones((2,3))
- matrix([[ 1., 1., 1.],
- [ 1., 1., 1.]])
+ matrix([[1., 1., 1.],
+ [1., 1., 1.]])
>>> np.matlib.ones(2)
- matrix([[ 1., 1.]])
+ matrix([[1., 1.]])
"""
a = ndarray.__new__(matrix, shape, dtype, order=order)
@@ -126,11 +126,11 @@ def zeros(shape, dtype=None, order='C'):
--------
>>> import numpy.matlib
>>> np.matlib.zeros((2, 3))
- matrix([[ 0., 0., 0.],
- [ 0., 0., 0.]])
+ matrix([[0., 0., 0.],
+ [0., 0., 0.]])
>>> np.matlib.zeros(2)
- matrix([[ 0., 0.]])
+ matrix([[0., 0.]])
"""
a = ndarray.__new__(matrix, shape, dtype, order=order)
@@ -210,9 +210,9 @@ def eye(n,M=None, k=0, dtype=float, order='C'):
--------
>>> import numpy.matlib
>>> np.matlib.eye(3, k=1, dtype=float)
- matrix([[ 0., 1., 0.],
- [ 0., 0., 1.],
- [ 0., 0., 0.]])
+ matrix([[0., 1., 0.],
+ [0., 0., 1.],
+ [0., 0., 0.]])
"""
return asmatrix(np.eye(n, M=M, k=k, dtype=dtype, order=order))
@@ -243,19 +243,20 @@ def rand(*args):
Examples
--------
+ >>> np.random.seed(123)
>>> import numpy.matlib
>>> np.matlib.rand(2, 3)
- matrix([[ 0.68340382, 0.67926887, 0.83271405],
- [ 0.00793551, 0.20468222, 0.95253525]]) #random
+ matrix([[0.69646919, 0.28613933, 0.22685145],
+ [0.55131477, 0.71946897, 0.42310646]])
>>> np.matlib.rand((2, 3))
- matrix([[ 0.84682055, 0.73626594, 0.11308016],
- [ 0.85429008, 0.3294825 , 0.89139555]]) #random
+ matrix([[0.9807642 , 0.68482974, 0.4809319 ],
+ [0.39211752, 0.34317802, 0.72904971]])
If the first argument is a tuple, other arguments are ignored:
>>> np.matlib.rand((2, 3), 4)
- matrix([[ 0.46898646, 0.15163588, 0.95188261],
- [ 0.59208621, 0.09561818, 0.00583606]]) #random
+ matrix([[0.43857224, 0.0596779 , 0.39804426],
+ [0.73799541, 0.18249173, 0.17545176]])
"""
if isinstance(args[0], tuple):
@@ -294,18 +295,19 @@ def randn(*args):
Examples
--------
+ >>> np.random.seed(123)
>>> import numpy.matlib
>>> np.matlib.randn(1)
- matrix([[-0.09542833]]) #random
+ matrix([[-1.0856306]])
>>> np.matlib.randn(1, 2, 3)
- matrix([[ 0.16198284, 0.0194571 , 0.18312985],
- [-0.7509172 , 1.61055 , 0.45298599]]) #random
+ matrix([[ 0.99734545, 0.2829785 , -1.50629471],
+ [-0.57860025, 1.65143654, -2.42667924]])
Two-by-four matrix of samples from :math:`N(3, 6.25)`:
>>> 2.5 * np.matlib.randn((2, 4)) + 3
- matrix([[ 4.74085004, 8.89381862, 4.09042411, 4.83721922],
- [ 7.52373709, 5.07933944, -2.64043543, 0.45610557]]) #random
+ matrix([[1.92771843, 6.16484065, 0.83314899, 1.30278462],
+ [2.76322758, 6.72847407, 1.40274501, 1.8900451 ]])
"""
if isinstance(args[0], tuple):
diff --git a/numpy/matrixlib/defmatrix.py b/numpy/matrixlib/defmatrix.py
index 93b344cd4..3c7e8ffc2 100644
--- a/numpy/matrixlib/defmatrix.py
+++ b/numpy/matrixlib/defmatrix.py
@@ -104,9 +104,9 @@ class matrix(N.ndarray):
Examples
--------
>>> a = np.matrix('1 2; 3 4')
- >>> print(a)
- [[1 2]
- [3 4]]
+ >>> a
+ matrix([[1, 2],
+ [3, 4]])
>>> np.matrix([[1, 2], [3, 4]])
matrix([[1, 2],
@@ -310,12 +310,12 @@ class matrix(N.ndarray):
matrix([[3],
[7]])
>>> x.sum(axis=1, dtype='float')
- matrix([[ 3.],
- [ 7.]])
- >>> out = np.zeros((1, 2), dtype='float')
- >>> x.sum(axis=1, dtype='float', out=out)
- matrix([[ 3.],
- [ 7.]])
+ matrix([[3.],
+ [7.]])
+ >>> out = np.zeros((2, 1), dtype='float')
+ >>> x.sum(axis=1, dtype='float', out=np.asmatrix(out))
+ matrix([[3.],
+ [7.]])
"""
return N.ndarray.sum(self, axis, dtype, out, keepdims=True)._collapse(axis)
@@ -437,7 +437,7 @@ class matrix(N.ndarray):
>>> x.mean()
5.5
>>> x.mean(0)
- matrix([[ 4., 5., 6., 7.]])
+ matrix([[4., 5., 6., 7.]])
>>> x.mean(1)
matrix([[ 1.5],
[ 5.5],
@@ -469,9 +469,9 @@ class matrix(N.ndarray):
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x.std()
- 3.4520525295346629
+ 3.4520525295346629 # may vary
>>> x.std(0)
- matrix([[ 3.26598632, 3.26598632, 3.26598632, 3.26598632]])
+ matrix([[ 3.26598632, 3.26598632, 3.26598632, 3.26598632]]) # may vary
>>> x.std(1)
matrix([[ 1.11803399],
[ 1.11803399],
@@ -505,11 +505,11 @@ class matrix(N.ndarray):
>>> x.var()
11.916666666666666
>>> x.var(0)
- matrix([[ 10.66666667, 10.66666667, 10.66666667, 10.66666667]])
+ matrix([[ 10.66666667, 10.66666667, 10.66666667, 10.66666667]]) # may vary
>>> x.var(1)
- matrix([[ 1.25],
- [ 1.25],
- [ 1.25]])
+ matrix([[1.25],
+ [1.25],
+ [1.25]])
"""
return N.ndarray.var(self, axis, dtype, out, ddof, keepdims=True)._collapse(axis)
@@ -791,7 +791,8 @@ class matrix(N.ndarray):
"""
return N.ndarray.ptp(self, axis, out)._align(axis)
- def getI(self):
+ @property
+ def I(self):
"""
Returns the (multiplicative) inverse of invertible `self`.
@@ -824,7 +825,7 @@ class matrix(N.ndarray):
matrix([[-2. , 1. ],
[ 1.5, -0.5]])
>>> m.getI() * m
- matrix([[ 1., 0.],
+ matrix([[ 1., 0.], # may vary
[ 0., 1.]])
"""
@@ -835,7 +836,8 @@ class matrix(N.ndarray):
from numpy.dual import pinv as func
return asmatrix(func(self))
- def getA(self):
+ @property
+ def A(self):
"""
Return `self` as an `ndarray` object.
@@ -864,7 +866,8 @@ class matrix(N.ndarray):
"""
return self.__array__()
- def getA1(self):
+ @property
+ def A1(self):
"""
Return `self` as a flattened `ndarray`.
@@ -886,7 +889,8 @@ class matrix(N.ndarray):
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x.getA1()
- array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
+ array([ 0, 1, 2, ..., 9, 10, 11])
+
"""
return self.__array__().ravel()
@@ -930,8 +934,8 @@ class matrix(N.ndarray):
"""
return N.ndarray.ravel(self, order=order)
-
- def getT(self):
+ @property
+ def T(self):
"""
Returns the transpose of the matrix.
@@ -963,7 +967,8 @@ class matrix(N.ndarray):
"""
return self.transpose()
- def getH(self):
+ @property
+ def H(self):
"""
Returns the (complex) conjugate transpose of `self`.
@@ -986,10 +991,10 @@ class matrix(N.ndarray):
[ 4. -4.j, 5. -5.j, 6. -6.j, 7. -7.j],
[ 8. -8.j, 9. -9.j, 10.-10.j, 11.-11.j]])
>>> z.getH()
- matrix([[ 0. +0.j, 4. +4.j, 8. +8.j],
- [ 1. +1.j, 5. +5.j, 9. +9.j],
- [ 2. +2.j, 6. +6.j, 10.+10.j],
- [ 3. +3.j, 7. +7.j, 11.+11.j]])
+ matrix([[ 0. -0.j, 4. +4.j, 8. +8.j],
+ [ 1. +1.j, 5. +5.j, 9. +9.j],
+ [ 2. +2.j, 6. +6.j, 10.+10.j],
+ [ 3. +3.j, 7. +7.j, 11.+11.j]])
"""
if issubclass(self.dtype.type, N.complexfloating):
@@ -997,11 +1002,12 @@ class matrix(N.ndarray):
else:
return self.transpose()
- T = property(getT, None)
- A = property(getA, None)
- A1 = property(getA1, None)
- H = property(getH, None)
- I = property(getI, None)
+ # kept for compatibility
+ getT = T.fget
+ getA = A.fget
+ getA1 = A1.fget
+ getH = H.fget
+ getI = I.fget
def _from_string(str, gdict, ldict):
rows = str.split(';')
diff --git a/numpy/matrixlib/tests/test_masked_matrix.py b/numpy/matrixlib/tests/test_masked_matrix.py
index 52fd18577..d3911d2e1 100644
--- a/numpy/matrixlib/tests/test_masked_matrix.py
+++ b/numpy/matrixlib/tests/test_masked_matrix.py
@@ -7,7 +7,7 @@ from numpy.ma.core import (masked_array, masked_values, masked, allequal,
MaskType, getmask, MaskedArray, nomask,
log, add, hypot, divide)
from numpy.ma.extras import mr_
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
class MMatrix(MaskedArray, np.matrix,):
@@ -22,11 +22,11 @@ class MMatrix(MaskedArray, np.matrix,):
MaskedArray.__array_finalize__(self, obj)
return
- def _get_series(self):
+ @property
+ def _series(self):
_view = self.view(MaskedArray)
_view._sharedmask = False
return _view
- _series = property(fget=_get_series)
class TestMaskedMatrix(object):
diff --git a/numpy/polynomial/_polybase.py b/numpy/polynomial/_polybase.py
index c28e77e69..bfa030714 100644
--- a/numpy/polynomial/_polybase.py
+++ b/numpy/polynomial/_polybase.py
@@ -8,7 +8,7 @@ abc module from the stdlib, hence it is only available for Python >= 2.6.
"""
from __future__ import division, absolute_import, print_function
-from abc import ABCMeta, abstractmethod, abstractproperty
+import abc
import numbers
import numpy as np
@@ -16,7 +16,7 @@ from . import polyutils as pu
__all__ = ['ABCPolyBase']
-class ABCPolyBase(object):
+class ABCPolyBase(abc.ABC):
"""An abstract base class for immutable series classes.
ABCPolyBase provides the standard Python numerical methods
@@ -59,7 +59,6 @@ class ABCPolyBase(object):
Default window of the class.
"""
- __metaclass__ = ABCMeta
# Not hashable
__hash__ = None
@@ -70,68 +69,84 @@ class ABCPolyBase(object):
# Limit runaway size. T_n^m has degree n*m
maxpower = 100
- @abstractproperty
+ @property
+ @abc.abstractmethod
def domain(self):
pass
- @abstractproperty
+ @property
+ @abc.abstractmethod
def window(self):
pass
- @abstractproperty
+ @property
+ @abc.abstractmethod
def nickname(self):
pass
- @abstractproperty
+ @property
+ @abc.abstractmethod
def basis_name(self):
pass
- @abstractmethod
- def _add(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _add(c1, c2):
pass
- @abstractmethod
- def _sub(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _sub(c1, c2):
pass
- @abstractmethod
- def _mul(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _mul(c1, c2):
pass
- @abstractmethod
- def _div(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _div(c1, c2):
pass
- @abstractmethod
- def _pow(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _pow(c, pow, maxpower=None):
pass
- @abstractmethod
- def _val(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _val(x, c):
pass
- @abstractmethod
- def _int(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _int(c, m, k, lbnd, scl):
pass
- @abstractmethod
- def _der(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _der(c, m, scl):
pass
- @abstractmethod
- def _fit(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _fit(x, y, deg, rcond, full):
pass
- @abstractmethod
- def _line(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _line(off, scl):
pass
- @abstractmethod
- def _roots(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _roots(c):
pass
- @abstractmethod
- def _fromroots(self):
+ @staticmethod
+ @abc.abstractmethod
+ def _fromroots(r):
pass
def has_samecoef(self, other):
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py
index 92cdb18d2..e4d10bcb8 100644
--- a/numpy/polynomial/chebyshev.py
+++ b/numpy/polynomial/chebyshev.py
@@ -225,15 +225,15 @@ def _zseries_div(z1, z2):
"""
z1 = z1.copy()
z2 = z2.copy()
- len1 = len(z1)
- len2 = len(z2)
- if len2 == 1:
+ lc1 = len(z1)
+ lc2 = len(z2)
+ if lc2 == 1:
z1 /= z2
return z1, z1[:1]*0
- elif len1 < len2:
+ elif lc1 < lc2:
return z1[:1]*0, z1
else:
- dlen = len1 - len2
+ dlen = lc1 - lc2
scl = z2[0]
z2 /= scl
quo = np.empty(dlen + 1, dtype=z1.dtype)
@@ -244,16 +244,16 @@ def _zseries_div(z1, z2):
quo[i] = z1[i]
quo[dlen - i] = r
tmp = r*z2
- z1[i:i+len2] -= tmp
- z1[j:j+len2] -= tmp
+ z1[i:i+lc2] -= tmp
+ z1[j:j+lc2] -= tmp
i += 1
j -= 1
r = z1[i]
quo[i] = r
tmp = r*z2
- z1[i:i+len2] -= tmp
+ z1[i:i+lc2] -= tmp
quo /= scl
- rem = z1[i+1:i-1+len2].copy()
+ rem = z1[i+1:i-1+lc2].copy()
return quo, rem
@@ -361,12 +361,12 @@ def poly2cheb(pol):
>>> from numpy import polynomial as P
>>> p = P.Polynomial(range(4))
>>> p
- Polynomial([ 0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
>>> c = p.convert(kind=P.Chebyshev)
>>> c
- Chebyshev([ 1. , 3.25, 1. , 0.75], domain=[-1, 1], window=[-1, 1])
+ Chebyshev([1. , 3.25, 1. , 0.75], domain=[-1., 1.], window=[-1., 1.])
>>> P.chebyshev.poly2cheb(range(4))
- array([ 1. , 3.25, 1. , 0.75])
+ array([1. , 3.25, 1. , 0.75])
"""
[pol] = pu.as_series([pol])
@@ -413,12 +413,12 @@ def cheb2poly(c):
>>> from numpy import polynomial as P
>>> c = P.Chebyshev(range(4))
>>> c
- Chebyshev([ 0., 1., 2., 3.], [-1., 1.])
+ Chebyshev([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
>>> p = c.convert(kind=P.Polynomial)
>>> p
- Polynomial([ -2., -8., 4., 12.], [-1., 1.])
+ Polynomial([-2., -8., 4., 12.], domain=[-1., 1.], window=[-1., 1.])
>>> P.chebyshev.cheb2poly(range(4))
- array([ -2., -8., 4., 12.])
+ array([-2., -8., 4., 12.])
"""
from .polynomial import polyadd, polysub, polymulx
@@ -528,8 +528,7 @@ def chebfromroots(roots):
See Also
--------
- polyfromroots, legfromroots, lagfromroots, hermfromroots,
- hermefromroots.
+ polyfromroots, legfromroots, lagfromroots, hermfromroots, hermefromroots
Examples
--------
@@ -538,24 +537,10 @@ def chebfromroots(roots):
array([ 0. , -0.25, 0. , 0.25])
>>> j = complex(0,1)
>>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
- array([ 1.5+0.j, 0.0+0.j, 0.5+0.j])
+ array([1.5+0.j, 0. +0.j, 0.5+0.j])
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [chebline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [chebmul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = chebmul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(chebline, chebmul, roots)
def chebadd(c1, c2):
@@ -594,18 +579,10 @@ def chebadd(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> C.chebadd(c1,c2)
- array([ 4., 4., 4.])
+ array([4., 4., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def chebsub(c1, c2):
@@ -649,16 +626,7 @@ def chebsub(c1, c2):
array([ 2., 0., -2.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def chebmulx(c):
@@ -688,7 +656,7 @@ def chebmulx(c):
--------
>>> from numpy.polynomial import chebyshev as C
>>> C.chebmulx([1,2,3])
- array([ 1., 2.5, 3., 1.5, 2.])
+ array([1. , 2.5, 1. , 1.5])
"""
# c is a trimmed copy
@@ -796,10 +764,10 @@ def chebdiv(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
- (array([ 3.]), array([-8., -4.]))
+ (array([3.]), array([-8., -4.]))
>>> c2 = (0,1,2,3)
>>> C.chebdiv(c2,c1) # neither "intuitive"
- (array([ 0., 2.]), array([-2., -4.]))
+ (array([0., 2.]), array([-2., -4.]))
"""
# c1, c2 are trimmed copies
@@ -807,6 +775,7 @@ def chebdiv(c1, c2):
if c2[-1] == 0:
raise ZeroDivisionError()
+ # note: this is more efficient than `pu._div(chebmul, c1, c2)`
lc1 = len(c1)
lc2 = len(c2)
if lc1 < lc2:
@@ -853,9 +822,12 @@ def chebpow(c, pow, maxpower=16):
--------
>>> from numpy.polynomial import chebyshev as C
>>> C.chebpow([1, 2, 3, 4], 2)
- array([15.5, 22. , 16. , 14. , 12.5, 12. , 8. ])
+ array([15.5, 22. , 16. , ..., 12.5, 12. , 8. ])
"""
+ # note: this is more efficient than `pu._pow(chebmul, c1, c2)`, as it
+ # avoids converting between z and c series repeatedly
+
# c is a trimmed copy
[c] = pu.as_series([c])
power = int(pow)
@@ -928,26 +900,22 @@ def chebder(c, m=1, scl=1, axis=0):
>>> from numpy.polynomial import chebyshev as C
>>> c = (1,2,3,4)
>>> C.chebder(c)
- array([ 14., 12., 24.])
+ array([14., 12., 24.])
>>> C.chebder(c,3)
- array([ 96.])
+ array([96.])
>>> C.chebder(c,scl=-1)
array([-14., -12., -24.])
>>> C.chebder(c,2,-1)
- array([ 12., 96.])
+ array([12., 96.])
"""
c = np.array(c, ndmin=1, copy=1)
if c.dtype.char in '?bBhHiIlLqQpP':
c = c.astype(np.double)
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -1048,8 +1016,8 @@ def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
>>> C.chebint(c)
array([ 0.5, -0.5, 0.5, 0.5])
>>> C.chebint(c,3)
- array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667,
- 0.00625 ])
+ array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667, # may vary
+ 0.00625 ])
>>> C.chebint(c, k=3)
array([ 3.5, -0.5, 0.5, 0.5])
>>> C.chebint(c,lbnd=-2)
@@ -1063,10 +1031,8 @@ def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
c = c.astype(np.double)
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -1075,8 +1041,6 @@ def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -1238,14 +1202,7 @@ def chebval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = chebval(x, c)
- c = chebval(y, c, tensor=False)
- return c
+ return pu._valnd(chebval, c, x, y)
def chebgrid2d(x, y, c):
@@ -1298,9 +1255,7 @@ def chebgrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = chebval(x, c)
- c = chebval(y, c)
- return c
+ return pu._gridnd(chebval, c, x, y)
def chebval3d(x, y, z, c):
@@ -1351,15 +1306,7 @@ def chebval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = chebval(x, c)
- c = chebval(y, c, tensor=False)
- c = chebval(z, c, tensor=False)
- return c
+ return pu._valnd(chebval, c, x, y, z)
def chebgrid3d(x, y, z, c):
@@ -1415,10 +1362,7 @@ def chebgrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = chebval(x, c)
- c = chebval(y, c)
- c = chebval(z, c)
- return c
+ return pu._gridnd(chebval, c, x, y, z)
def chebvander(x, deg):
@@ -1456,9 +1400,7 @@ def chebvander(x, deg):
the converted `x`.
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1518,7 +1460,7 @@ def chebvander2d(x, y, deg):
See Also
--------
- chebvander, chebvander3d. chebval2d, chebval3d
+ chebvander, chebvander3d, chebval2d, chebval3d
Notes
-----
@@ -1526,17 +1468,7 @@ def chebvander2d(x, y, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = chebvander(x, degx)
- vy = chebvander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(chebvander, x, y, deg)
def chebvander3d(x, y, z, deg):
@@ -1582,7 +1514,7 @@ def chebvander3d(x, y, z, deg):
See Also
--------
- chebvander, chebvander3d. chebval2d, chebval3d
+ chebvander, chebvander3d, chebval2d, chebval3d
Notes
-----
@@ -1590,18 +1522,7 @@ def chebvander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = chebvander(x, degx)
- vy = chebvander(y, degy)
- vz = chebvander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(chebvander, x, y, z, deg)
def chebfit(x, y, deg, rcond=None, full=False, w=None):
@@ -1674,7 +1595,7 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None):
warnings can be turned off by
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1723,81 +1644,7 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None):
--------
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = chebvander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = chebvander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim > 0:
- if c.ndim == 2:
- cc = np.zeros((lmax + 1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax + 1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(chebvander, x, y, deg, rcond, full, w)
def chebcompanion(c):
@@ -1885,7 +1732,7 @@ def chebroots(c):
--------
>>> import numpy.polynomial.chebyshev as cheb
>>> cheb.chebroots((-1, 1,-1, 1)) # T3 - T2 + T1 - T0 has real roots
- array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00])
+ array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00]) # may vary
"""
# c is a trimmed copy
@@ -1895,7 +1742,8 @@ def chebroots(c):
if len(c) == 2:
return np.array([-c[0]/c[1]])
- m = chebcompanion(c)
+ # rotated companion matrix reduces error
+ m = chebcompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
@@ -2003,9 +1851,9 @@ def chebgauss(deg):
.. math:: w_i = \\pi / n
"""
- ideg = int(deg)
- if ideg != deg or ideg < 1:
- raise ValueError("deg must be a non-negative integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
x = np.cos(np.pi * np.arange(1, 2*ideg, 2) / (2.0*ideg))
w = np.ones(ideg)*(np.pi/ideg)
diff --git a/numpy/polynomial/hermite.py b/numpy/polynomial/hermite.py
index 4905f366f..4bfd89e52 100644
--- a/numpy/polynomial/hermite.py
+++ b/numpy/polynomial/hermite.py
@@ -114,7 +114,7 @@ def poly2herm(pol):
--------
>>> from numpy.polynomial.hermite import poly2herm
>>> poly2herm(np.arange(4))
- array([ 1. , 2.75 , 0.5 , 0.375])
+ array([1. , 2.75 , 0.5 , 0.375])
"""
[pol] = pu.as_series([pol])
@@ -160,7 +160,7 @@ def herm2poly(c):
--------
>>> from numpy.polynomial.hermite import herm2poly
>>> herm2poly([ 1. , 2.75 , 0.5 , 0.375])
- array([ 0., 1., 2., 3.])
+ array([0., 1., 2., 3.])
"""
from .polynomial import polyadd, polysub, polymulx
@@ -272,35 +272,20 @@ def hermfromroots(roots):
See Also
--------
- polyfromroots, legfromroots, lagfromroots, chebfromroots,
- hermefromroots.
+ polyfromroots, legfromroots, lagfromroots, chebfromroots, hermefromroots
Examples
--------
>>> from numpy.polynomial.hermite import hermfromroots, hermval
>>> coef = hermfromroots((-1, 0, 1))
>>> hermval((-1, 0, 1), coef)
- array([ 0., 0., 0.])
+ array([0., 0., 0.])
>>> coef = hermfromroots((-1j, 1j))
>>> hermval((-1j, 1j), coef)
- array([ 0.+0.j, 0.+0.j])
+ array([0.+0.j, 0.+0.j])
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [hermline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [hermmul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = hermmul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(hermline, hermmul, roots)
def hermadd(c1, c2):
@@ -337,18 +322,10 @@ def hermadd(c1, c2):
--------
>>> from numpy.polynomial.hermite import hermadd
>>> hermadd([1, 2, 3], [1, 2, 3, 4])
- array([ 2., 4., 6., 4.])
+ array([2., 4., 6., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def hermsub(c1, c2):
@@ -385,19 +362,10 @@ def hermsub(c1, c2):
--------
>>> from numpy.polynomial.hermite import hermsub
>>> hermsub([1, 2, 3, 4], [1, 2, 3])
- array([ 0., 0., 0., 4.])
+ array([0., 0., 0., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def hermmulx(c):
@@ -435,7 +403,7 @@ def hermmulx(c):
--------
>>> from numpy.polynomial.hermite import hermmulx
>>> hermmulx([1, 2, 3])
- array([ 2. , 6.5, 1. , 1.5])
+ array([2. , 6.5, 1. , 1.5])
"""
# c is a trimmed copy
@@ -488,7 +456,7 @@ def hermmul(c1, c2):
--------
>>> from numpy.polynomial.hermite import hermmul
>>> hermmul([1, 2, 3], [0, 1, 2])
- array([ 52., 29., 52., 7., 6.])
+ array([52., 29., 52., 7., 6.])
"""
# s1, s2 are trimmed copies
@@ -557,33 +525,14 @@ def hermdiv(c1, c2):
--------
>>> from numpy.polynomial.hermite import hermdiv
>>> hermdiv([ 52., 29., 52., 7., 6.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 0.]))
+ (array([1., 2., 3.]), array([0.]))
>>> hermdiv([ 54., 31., 52., 7., 6.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 2., 2.]))
+ (array([1., 2., 3.]), array([2., 2.]))
>>> hermdiv([ 53., 30., 52., 7., 6.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 1., 1.]))
+ (array([1., 2., 3.]), array([1., 1.]))
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if c2[-1] == 0:
- raise ZeroDivisionError()
-
- lc1 = len(c1)
- lc2 = len(c2)
- if lc1 < lc2:
- return c1[:1]*0, c1
- elif lc2 == 1:
- return c1/c2[-1], c1[:1]*0
- else:
- quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
- rem = c1
- for i in range(lc1 - lc2, - 1, -1):
- p = hermmul([0]*i + [1], c2)
- q = rem[-1]/p[-1]
- rem = rem[:-1] - q*p[:-1]
- quo[i] = q
- return quo, pu.trimseq(rem)
+ return pu._div(hermmul, c1, c2)
def hermpow(c, pow, maxpower=16):
@@ -617,27 +566,10 @@ def hermpow(c, pow, maxpower=16):
--------
>>> from numpy.polynomial.hermite import hermpow
>>> hermpow([1, 2, 3], 2)
- array([ 81., 52., 82., 12., 9.])
+ array([81., 52., 82., 12., 9.])
"""
- # c is a trimmed copy
- [c] = pu.as_series([c])
- power = int(pow)
- if power != pow or power < 0:
- raise ValueError("Power must be a non-negative integer.")
- elif maxpower is not None and power > maxpower:
- raise ValueError("Power is too large")
- elif power == 0:
- return np.array([1], dtype=c.dtype)
- elif power == 1:
- return c
- else:
- # This can be made more efficient by using powers of two
- # in the usual way.
- prd = c
- for i in range(2, power + 1):
- prd = hermmul(prd, c)
- return prd
+ return pu._pow(hermmul, c, pow, maxpower)
def hermder(c, m=1, scl=1, axis=0):
@@ -690,22 +622,18 @@ def hermder(c, m=1, scl=1, axis=0):
--------
>>> from numpy.polynomial.hermite import hermder
>>> hermder([ 1. , 0.5, 0.5, 0.5])
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
>>> hermder([-0.5, 1./2., 1./8., 1./12., 1./16.], m=2)
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
"""
c = np.array(c, ndmin=1, copy=1)
if c.dtype.char in '?bBhHiIlLqQpP':
c = c.astype(np.double)
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -799,15 +727,15 @@ def hermint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
--------
>>> from numpy.polynomial.hermite import hermint
>>> hermint([1,2,3]) # integrate once, value 0 at 0.
- array([ 1. , 0.5, 0.5, 0.5])
+ array([1. , 0.5, 0.5, 0.5])
>>> hermint([1,2,3], m=2) # integrate twice, value & deriv 0 at 0
- array([-0.5 , 0.5 , 0.125 , 0.08333333, 0.0625 ])
+ array([-0.5 , 0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
>>> hermint([1,2,3], k=1) # integrate once, value 1 at 0.
- array([ 2. , 0.5, 0.5, 0.5])
+ array([2. , 0.5, 0.5, 0.5])
>>> hermint([1,2,3], lbnd=-1) # integrate once, value 0 at -1
array([-2. , 0.5, 0.5, 0.5])
>>> hermint([1,2,3], m=2, k=[1,2], lbnd=-1)
- array([ 1.66666667, -0.5 , 0.125 , 0.08333333, 0.0625 ])
+ array([ 1.66666667, -0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
"""
c = np.array(c, ndmin=1, copy=1)
@@ -815,10 +743,8 @@ def hermint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
c = c.astype(np.double)
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -827,8 +753,6 @@ def hermint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -918,8 +842,8 @@ def hermval(x, c, tensor=True):
>>> hermval(1, coef)
11.0
>>> hermval([[1,2],[3,4]], coef)
- array([[ 11., 51.],
- [ 115., 203.]])
+ array([[ 11., 51.],
+ [115., 203.]])
"""
c = np.array(c, ndmin=1, copy=0)
@@ -995,14 +919,7 @@ def hermval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = hermval(x, c)
- c = hermval(y, c, tensor=False)
- return c
+ return pu._valnd(hermval, c, x, y)
def hermgrid2d(x, y, c):
@@ -1055,9 +972,7 @@ def hermgrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = hermval(x, c)
- c = hermval(y, c)
- return c
+ return pu._gridnd(hermval, c, x, y)
def hermval3d(x, y, z, c):
@@ -1108,15 +1023,7 @@ def hermval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = hermval(x, c)
- c = hermval(y, c, tensor=False)
- c = hermval(z, c, tensor=False)
- return c
+ return pu._valnd(hermval, c, x, y, z)
def hermgrid3d(x, y, z, c):
@@ -1172,10 +1079,7 @@ def hermgrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = hermval(x, c)
- c = hermval(y, c)
- c = hermval(z, c)
- return c
+ return pu._gridnd(hermval, c, x, y, z)
def hermvander(x, deg):
@@ -1222,9 +1126,7 @@ def hermvander(x, deg):
[ 1., 2., 2., -4.]])
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1283,7 +1185,7 @@ def hermvander2d(x, y, deg):
See Also
--------
- hermvander, hermvander3d. hermval2d, hermval3d
+ hermvander, hermvander3d, hermval2d, hermval3d
Notes
-----
@@ -1291,17 +1193,7 @@ def hermvander2d(x, y, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = hermvander(x, degx)
- vy = hermvander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(hermvander, x, y, deg)
def hermvander3d(x, y, z, deg):
@@ -1347,7 +1239,7 @@ def hermvander3d(x, y, z, deg):
See Also
--------
- hermvander, hermvander3d. hermval2d, hermval3d
+ hermvander, hermvander3d, hermval2d, hermval3d
Notes
-----
@@ -1355,18 +1247,7 @@ def hermvander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = hermvander(x, degx)
- vy = hermvander(y, degy)
- vz = hermvander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(hermvander, x, y, z, deg)
def hermfit(x, y, deg, rcond=None, full=False, w=None):
@@ -1437,7 +1318,7 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None):
warnings can be turned off by
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1490,84 +1371,10 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None):
>>> err = np.random.randn(len(x))/10
>>> y = hermval(x, [1, 2, 3]) + err
>>> hermfit(x, y, 2)
- array([ 0.97902637, 1.99849131, 3.00006 ])
+ array([1.0218, 1.9986, 2.9999]) # may vary
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = hermvander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = hermvander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim > 0:
- if c.ndim == 2:
- cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax+1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(hermvander, x, y, deg, rcond, full, w)
def hermcompanion(c):
@@ -1656,9 +1463,9 @@ def hermroots(c):
>>> from numpy.polynomial.hermite import hermroots, hermfromroots
>>> coef = hermfromroots([-1, 0, 1])
>>> coef
- array([ 0. , 0.25 , 0. , 0.125])
+ array([0. , 0.25 , 0. , 0.125])
>>> hermroots(coef)
- array([ -1.00000000e+00, -1.38777878e-17, 1.00000000e+00])
+ array([-1.00000000e+00, -1.38777878e-17, 1.00000000e+00])
"""
# c is a trimmed copy
@@ -1668,7 +1475,8 @@ def hermroots(c):
if len(c) == 2:
return np.array([-.5*c[0]/c[1]])
- m = hermcompanion(c)
+ # rotated companion matrix reduces error
+ m = hermcompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
@@ -1753,9 +1561,9 @@ def hermgauss(deg):
the right value when integrating 1.
"""
- ideg = int(deg)
- if ideg != deg or ideg < 1:
- raise ValueError("deg must be a non-negative integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
# first approximation of roots. We use the fact that the companion
# matrix is symmetric in this case in order to obtain better zeros.
diff --git a/numpy/polynomial/hermite_e.py b/numpy/polynomial/hermite_e.py
index 6cb044a55..735d66e6c 100644
--- a/numpy/polynomial/hermite_e.py
+++ b/numpy/polynomial/hermite_e.py
@@ -161,7 +161,7 @@ def herme2poly(c):
--------
>>> from numpy.polynomial.hermite_e import herme2poly
>>> herme2poly([ 2., 10., 2., 3.])
- array([ 0., 1., 2., 3.])
+ array([0., 1., 2., 3.])
"""
from .polynomial import polyadd, polysub, polymulx
@@ -273,35 +273,20 @@ def hermefromroots(roots):
See Also
--------
- polyfromroots, legfromroots, lagfromroots, hermfromroots,
- chebfromroots.
+ polyfromroots, legfromroots, lagfromroots, hermfromroots, chebfromroots
Examples
--------
>>> from numpy.polynomial.hermite_e import hermefromroots, hermeval
>>> coef = hermefromroots((-1, 0, 1))
>>> hermeval((-1, 0, 1), coef)
- array([ 0., 0., 0.])
+ array([0., 0., 0.])
>>> coef = hermefromroots((-1j, 1j))
>>> hermeval((-1j, 1j), coef)
- array([ 0.+0.j, 0.+0.j])
+ array([0.+0.j, 0.+0.j])
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [hermeline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [hermemul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = hermemul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(hermeline, hermemul, roots)
def hermeadd(c1, c2):
@@ -338,18 +323,10 @@ def hermeadd(c1, c2):
--------
>>> from numpy.polynomial.hermite_e import hermeadd
>>> hermeadd([1, 2, 3], [1, 2, 3, 4])
- array([ 2., 4., 6., 4.])
+ array([2., 4., 6., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def hermesub(c1, c2):
@@ -386,19 +363,10 @@ def hermesub(c1, c2):
--------
>>> from numpy.polynomial.hermite_e import hermesub
>>> hermesub([1, 2, 3, 4], [1, 2, 3])
- array([ 0., 0., 0., 4.])
+ array([0., 0., 0., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def hermemulx(c):
@@ -432,7 +400,7 @@ def hermemulx(c):
--------
>>> from numpy.polynomial.hermite_e import hermemulx
>>> hermemulx([1, 2, 3])
- array([ 2., 7., 2., 3.])
+ array([2., 7., 2., 3.])
"""
# c is a trimmed copy
@@ -485,7 +453,7 @@ def hermemul(c1, c2):
--------
>>> from numpy.polynomial.hermite_e import hermemul
>>> hermemul([1, 2, 3], [0, 1, 2])
- array([ 14., 15., 28., 7., 6.])
+ array([14., 15., 28., 7., 6.])
"""
# s1, s2 are trimmed copies
@@ -554,31 +522,12 @@ def hermediv(c1, c2):
--------
>>> from numpy.polynomial.hermite_e import hermediv
>>> hermediv([ 14., 15., 28., 7., 6.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 0.]))
+ (array([1., 2., 3.]), array([0.]))
>>> hermediv([ 15., 17., 28., 7., 6.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 1., 2.]))
+ (array([1., 2., 3.]), array([1., 2.]))
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if c2[-1] == 0:
- raise ZeroDivisionError()
-
- lc1 = len(c1)
- lc2 = len(c2)
- if lc1 < lc2:
- return c1[:1]*0, c1
- elif lc2 == 1:
- return c1/c2[-1], c1[:1]*0
- else:
- quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
- rem = c1
- for i in range(lc1 - lc2, - 1, -1):
- p = hermemul([0]*i + [1], c2)
- q = rem[-1]/p[-1]
- rem = rem[:-1] - q*p[:-1]
- quo[i] = q
- return quo, pu.trimseq(rem)
+ return pu._div(hermemul, c1, c2)
def hermepow(c, pow, maxpower=16):
@@ -612,27 +561,10 @@ def hermepow(c, pow, maxpower=16):
--------
>>> from numpy.polynomial.hermite_e import hermepow
>>> hermepow([1, 2, 3], 2)
- array([ 23., 28., 46., 12., 9.])
+ array([23., 28., 46., 12., 9.])
"""
- # c is a trimmed copy
- [c] = pu.as_series([c])
- power = int(pow)
- if power != pow or power < 0:
- raise ValueError("Power must be a non-negative integer.")
- elif maxpower is not None and power > maxpower:
- raise ValueError("Power is too large")
- elif power == 0:
- return np.array([1], dtype=c.dtype)
- elif power == 1:
- return c
- else:
- # This can be made more efficient by using powers of two
- # in the usual way.
- prd = c
- for i in range(2, power + 1):
- prd = hermemul(prd, c)
- return prd
+ return pu._pow(hermemul, c, pow, maxpower)
def hermeder(c, m=1, scl=1, axis=0):
@@ -685,22 +617,18 @@ def hermeder(c, m=1, scl=1, axis=0):
--------
>>> from numpy.polynomial.hermite_e import hermeder
>>> hermeder([ 1., 1., 1., 1.])
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
>>> hermeder([-0.25, 1., 1./2., 1./3., 1./4 ], m=2)
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
"""
c = np.array(c, ndmin=1, copy=1)
if c.dtype.char in '?bBhHiIlLqQpP':
c = c.astype(np.double)
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -794,15 +722,15 @@ def hermeint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
--------
>>> from numpy.polynomial.hermite_e import hermeint
>>> hermeint([1, 2, 3]) # integrate once, value 0 at 0.
- array([ 1., 1., 1., 1.])
+ array([1., 1., 1., 1.])
>>> hermeint([1, 2, 3], m=2) # integrate twice, value & deriv 0 at 0
- array([-0.25 , 1. , 0.5 , 0.33333333, 0.25 ])
+ array([-0.25 , 1. , 0.5 , 0.33333333, 0.25 ]) # may vary
>>> hermeint([1, 2, 3], k=1) # integrate once, value 1 at 0.
- array([ 2., 1., 1., 1.])
+ array([2., 1., 1., 1.])
>>> hermeint([1, 2, 3], lbnd=-1) # integrate once, value 0 at -1
array([-1., 1., 1., 1.])
>>> hermeint([1, 2, 3], m=2, k=[1, 2], lbnd=-1)
- array([ 1.83333333, 0. , 0.5 , 0.33333333, 0.25 ])
+ array([ 1.83333333, 0. , 0.5 , 0.33333333, 0.25 ]) # may vary
"""
c = np.array(c, ndmin=1, copy=1)
@@ -810,10 +738,8 @@ def hermeint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
c = c.astype(np.double)
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -822,8 +748,6 @@ def hermeint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -913,8 +837,8 @@ def hermeval(x, c, tensor=True):
>>> hermeval(1, coef)
3.0
>>> hermeval([[1,2],[3,4]], coef)
- array([[ 3., 14.],
- [ 31., 54.]])
+ array([[ 3., 14.],
+ [31., 54.]])
"""
c = np.array(c, ndmin=1, copy=0)
@@ -989,14 +913,7 @@ def hermeval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = hermeval(x, c)
- c = hermeval(y, c, tensor=False)
- return c
+ return pu._valnd(hermeval, c, x, y)
def hermegrid2d(x, y, c):
@@ -1049,9 +966,7 @@ def hermegrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = hermeval(x, c)
- c = hermeval(y, c)
- return c
+ return pu._gridnd(hermeval, c, x, y)
def hermeval3d(x, y, z, c):
@@ -1102,15 +1017,7 @@ def hermeval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = hermeval(x, c)
- c = hermeval(y, c, tensor=False)
- c = hermeval(z, c, tensor=False)
- return c
+ return pu._valnd(hermeval, c, x, y, z)
def hermegrid3d(x, y, z, c):
@@ -1166,10 +1073,7 @@ def hermegrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = hermeval(x, c)
- c = hermeval(y, c)
- c = hermeval(z, c)
- return c
+ return pu._gridnd(hermeval, c, x, y, z)
def hermevander(x, deg):
@@ -1216,9 +1120,7 @@ def hermevander(x, deg):
[ 1., 1., 0., -2.]])
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1276,7 +1178,7 @@ def hermevander2d(x, y, deg):
See Also
--------
- hermevander, hermevander3d. hermeval2d, hermeval3d
+ hermevander, hermevander3d, hermeval2d, hermeval3d
Notes
-----
@@ -1284,17 +1186,7 @@ def hermevander2d(x, y, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = hermevander(x, degx)
- vy = hermevander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(hermevander, x, y, deg)
def hermevander3d(x, y, z, deg):
@@ -1340,7 +1232,7 @@ def hermevander3d(x, y, z, deg):
See Also
--------
- hermevander, hermevander3d. hermeval2d, hermeval3d
+ hermevander, hermevander3d, hermeval2d, hermeval3d
Notes
-----
@@ -1348,18 +1240,7 @@ def hermevander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = hermevander(x, degx)
- vy = hermevander(y, degy)
- vz = hermevander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(hermevander, x, y, z, deg)
def hermefit(x, y, deg, rcond=None, full=False, w=None):
@@ -1430,7 +1311,7 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None):
warnings can be turned off by
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1480,87 +1361,14 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None):
--------
>>> from numpy.polynomial.hermite_e import hermefit, hermeval
>>> x = np.linspace(-10, 10)
+ >>> np.random.seed(123)
>>> err = np.random.randn(len(x))/10
>>> y = hermeval(x, [1, 2, 3]) + err
>>> hermefit(x, y, 2)
- array([ 1.01690445, 1.99951418, 2.99948696])
+ array([ 1.01690445, 1.99951418, 2.99948696]) # may vary
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = hermevander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = hermevander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim > 0:
- if c.ndim == 2:
- cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax+1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(hermevander, x, y, deg, rcond, full, w)
def hermecompanion(c):
@@ -1650,9 +1458,9 @@ def hermeroots(c):
>>> from numpy.polynomial.hermite_e import hermeroots, hermefromroots
>>> coef = hermefromroots([-1, 0, 1])
>>> coef
- array([ 0., 2., 0., 1.])
+ array([0., 2., 0., 1.])
>>> hermeroots(coef)
- array([-1., 0., 1.])
+ array([-1., 0., 1.]) # may vary
"""
# c is a trimmed copy
@@ -1662,7 +1470,8 @@ def hermeroots(c):
if len(c) == 2:
return np.array([-c[0]/c[1]])
- m = hermecompanion(c)
+ # rotated companion matrix reduces error
+ m = hermecompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
@@ -1747,9 +1556,9 @@ def hermegauss(deg):
the right value when integrating 1.
"""
- ideg = int(deg)
- if ideg != deg or ideg < 1:
- raise ValueError("deg must be a non-negative integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
# first approximation of roots. We use the fact that the companion
# matrix is symmetric in this case in order to obtain better zeros.
diff --git a/numpy/polynomial/laguerre.py b/numpy/polynomial/laguerre.py
index a116d20a7..025a09929 100644
--- a/numpy/polynomial/laguerre.py
+++ b/numpy/polynomial/laguerre.py
@@ -160,7 +160,7 @@ def lag2poly(c):
--------
>>> from numpy.polynomial.laguerre import lag2poly
>>> lag2poly([ 23., -63., 58., -18.])
- array([ 0., 1., 2., 3.])
+ array([0., 1., 2., 3.])
"""
from .polynomial import polyadd, polysub, polymulx
@@ -269,35 +269,20 @@ def lagfromroots(roots):
See Also
--------
- polyfromroots, legfromroots, chebfromroots, hermfromroots,
- hermefromroots.
+ polyfromroots, legfromroots, chebfromroots, hermfromroots, hermefromroots
Examples
--------
>>> from numpy.polynomial.laguerre import lagfromroots, lagval
>>> coef = lagfromroots((-1, 0, 1))
>>> lagval((-1, 0, 1), coef)
- array([ 0., 0., 0.])
+ array([0., 0., 0.])
>>> coef = lagfromroots((-1j, 1j))
>>> lagval((-1j, 1j), coef)
- array([ 0.+0.j, 0.+0.j])
+ array([0.+0.j, 0.+0.j])
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [lagline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [lagmul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = lagmul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(lagline, lagmul, roots)
def lagadd(c1, c2):
@@ -334,19 +319,11 @@ def lagadd(c1, c2):
--------
>>> from numpy.polynomial.laguerre import lagadd
>>> lagadd([1, 2, 3], [1, 2, 3, 4])
- array([ 2., 4., 6., 4.])
+ array([2., 4., 6., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def lagsub(c1, c2):
@@ -383,19 +360,10 @@ def lagsub(c1, c2):
--------
>>> from numpy.polynomial.laguerre import lagsub
>>> lagsub([1, 2, 3, 4], [1, 2, 3])
- array([ 0., 0., 0., 4.])
+ array([0., 0., 0., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def lagmulx(c):
@@ -433,7 +401,7 @@ def lagmulx(c):
--------
>>> from numpy.polynomial.laguerre import lagmulx
>>> lagmulx([1, 2, 3])
- array([ -1., -1., 11., -9.])
+ array([-1., -1., 11., -9.])
"""
# c is a trimmed copy
@@ -556,31 +524,12 @@ def lagdiv(c1, c2):
--------
>>> from numpy.polynomial.laguerre import lagdiv
>>> lagdiv([ 8., -13., 38., -51., 36.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 0.]))
+ (array([1., 2., 3.]), array([0.]))
>>> lagdiv([ 9., -12., 38., -51., 36.], [0, 1, 2])
- (array([ 1., 2., 3.]), array([ 1., 1.]))
+ (array([1., 2., 3.]), array([1., 1.]))
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if c2[-1] == 0:
- raise ZeroDivisionError()
-
- lc1 = len(c1)
- lc2 = len(c2)
- if lc1 < lc2:
- return c1[:1]*0, c1
- elif lc2 == 1:
- return c1/c2[-1], c1[:1]*0
- else:
- quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
- rem = c1
- for i in range(lc1 - lc2, - 1, -1):
- p = lagmul([0]*i + [1], c2)
- q = rem[-1]/p[-1]
- rem = rem[:-1] - q*p[:-1]
- quo[i] = q
- return quo, pu.trimseq(rem)
+ return pu._div(lagmul, c1, c2)
def lagpow(c, pow, maxpower=16):
@@ -617,24 +566,7 @@ def lagpow(c, pow, maxpower=16):
array([ 14., -16., 56., -72., 54.])
"""
- # c is a trimmed copy
- [c] = pu.as_series([c])
- power = int(pow)
- if power != pow or power < 0:
- raise ValueError("Power must be a non-negative integer.")
- elif maxpower is not None and power > maxpower:
- raise ValueError("Power is too large")
- elif power == 0:
- return np.array([1], dtype=c.dtype)
- elif power == 1:
- return c
- else:
- # This can be made more efficient by using powers of two
- # in the usual way.
- prd = c
- for i in range(2, power + 1):
- prd = lagmul(prd, c)
- return prd
+ return pu._pow(lagmul, c, pow, maxpower)
def lagder(c, m=1, scl=1, axis=0):
@@ -687,22 +619,19 @@ def lagder(c, m=1, scl=1, axis=0):
--------
>>> from numpy.polynomial.laguerre import lagder
>>> lagder([ 1., 1., 1., -3.])
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
>>> lagder([ 1., 0., 0., -4., 3.], m=2)
- array([ 1., 2., 3.])
+ array([1., 2., 3.])
"""
c = np.array(c, ndmin=1, copy=1)
if c.dtype.char in '?bBhHiIlLqQpP':
c = c.astype(np.double)
- cnt, iaxis = [int(t) for t in [m, axis]]
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -805,9 +734,9 @@ def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
>>> lagint([1,2,3], k=1)
array([ 2., 1., 1., -3.])
>>> lagint([1,2,3], lbnd=-1)
- array([ 11.5, 1. , 1. , -3. ])
+ array([11.5, 1. , 1. , -3. ])
>>> lagint([1,2], m=2, k=[1,2], lbnd=-1)
- array([ 11.16666667, -5. , -3. , 2. ])
+ array([ 11.16666667, -5. , -3. , 2. ]) # may vary
"""
c = np.array(c, ndmin=1, copy=1)
@@ -815,10 +744,8 @@ def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
c = c.astype(np.double)
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -827,8 +754,6 @@ def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -995,14 +920,7 @@ def lagval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = lagval(x, c)
- c = lagval(y, c, tensor=False)
- return c
+ return pu._valnd(lagval, c, x, y)
def laggrid2d(x, y, c):
@@ -1055,9 +973,7 @@ def laggrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = lagval(x, c)
- c = lagval(y, c)
- return c
+ return pu._gridnd(lagval, c, x, y)
def lagval3d(x, y, z, c):
@@ -1108,15 +1024,7 @@ def lagval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = lagval(x, c)
- c = lagval(y, c, tensor=False)
- c = lagval(z, c, tensor=False)
- return c
+ return pu._valnd(lagval, c, x, y, z)
def laggrid3d(x, y, z, c):
@@ -1172,10 +1080,7 @@ def laggrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = lagval(x, c)
- c = lagval(y, c)
- c = lagval(z, c)
- return c
+ return pu._gridnd(lagval, c, x, y, z)
def lagvander(x, deg):
@@ -1222,9 +1127,7 @@ def lagvander(x, deg):
[ 1. , -1. , -1. , -0.33333333]])
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1282,7 +1185,7 @@ def lagvander2d(x, y, deg):
See Also
--------
- lagvander, lagvander3d. lagval2d, lagval3d
+ lagvander, lagvander3d, lagval2d, lagval3d
Notes
-----
@@ -1290,17 +1193,7 @@ def lagvander2d(x, y, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = lagvander(x, degx)
- vy = lagvander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(lagvander, x, y, deg)
def lagvander3d(x, y, z, deg):
@@ -1346,7 +1239,7 @@ def lagvander3d(x, y, z, deg):
See Also
--------
- lagvander, lagvander3d. lagval2d, lagval3d
+ lagvander, lagvander3d, lagval2d, lagval3d
Notes
-----
@@ -1354,18 +1247,7 @@ def lagvander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = lagvander(x, degx)
- vy = lagvander(y, degy)
- vz = lagvander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(lagvander, x, y, z, deg)
def lagfit(x, y, deg, rcond=None, full=False, w=None):
@@ -1436,7 +1318,7 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None):
warnings can be turned off by
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1489,84 +1371,10 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None):
>>> err = np.random.randn(len(x))/10
>>> y = lagval(x, [1, 2, 3]) + err
>>> lagfit(x, y, 2)
- array([ 0.96971004, 2.00193749, 3.00288744])
+ array([ 0.96971004, 2.00193749, 3.00288744]) # may vary
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = lagvander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = lagvander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim > 0:
- if c.ndim == 2:
- cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax+1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(lagvander, x, y, deg, rcond, full, w)
def lagcompanion(c):
@@ -1656,7 +1464,7 @@ def lagroots(c):
>>> coef
array([ 2., -8., 12., -6.])
>>> lagroots(coef)
- array([ -4.44089210e-16, 1.00000000e+00, 2.00000000e+00])
+ array([-4.4408921e-16, 1.0000000e+00, 2.0000000e+00])
"""
# c is a trimmed copy
@@ -1666,7 +1474,8 @@ def lagroots(c):
if len(c) == 2:
return np.array([1 + c[0]/c[1]])
- m = lagcompanion(c)
+ # rotated companion matrix reduces error
+ m = lagcompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
@@ -1708,9 +1517,9 @@ def laggauss(deg):
the right value when integrating 1.
"""
- ideg = int(deg)
- if ideg != deg or ideg < 1:
- raise ValueError("deg must be a non-negative integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
# first approximation of roots. We use the fact that the companion
# matrix is symmetric in this case in order to obtain better zeros.
diff --git a/numpy/polynomial/legendre.py b/numpy/polynomial/legendre.py
index e9c24594b..f06b294cf 100644
--- a/numpy/polynomial/legendre.py
+++ b/numpy/polynomial/legendre.py
@@ -136,10 +136,10 @@ def poly2leg(pol):
>>> from numpy import polynomial as P
>>> p = P.Polynomial(np.arange(4))
>>> p
- Polynomial([ 0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
>>> c = P.Legendre(P.legendre.poly2leg(p.coef))
>>> c
- Legendre([ 1. , 3.25, 1. , 0.75], domain=[-1, 1], window=[-1, 1])
+ Legendre([ 1. , 3.25, 1. , 0.75], domain=[-1, 1], window=[-1, 1]) # may vary
"""
[pol] = pu.as_series([pol])
@@ -183,12 +183,13 @@ def leg2poly(c):
Examples
--------
+ >>> from numpy import polynomial as P
>>> c = P.Legendre(range(4))
>>> c
- Legendre([ 0., 1., 2., 3.], [-1., 1.])
+ Legendre([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
>>> p = c.convert(kind=P.Polynomial)
>>> p
- Polynomial([-1. , -3.5, 3. , 7.5], [-1., 1.])
+ Polynomial([-1. , -3.5, 3. , 7.5], domain=[-1., 1.], window=[-1., 1.])
>>> P.leg2poly(range(4))
array([-1. , -3.5, 3. , 7.5])
@@ -300,8 +301,7 @@ def legfromroots(roots):
See Also
--------
- polyfromroots, chebfromroots, lagfromroots, hermfromroots,
- hermefromroots.
+ polyfromroots, chebfromroots, lagfromroots, hermfromroots, hermefromroots
Examples
--------
@@ -310,24 +310,10 @@ def legfromroots(roots):
array([ 0. , -0.4, 0. , 0.4])
>>> j = complex(0,1)
>>> L.legfromroots((-j,j)) # x^2 + 1 relative to the standard basis
- array([ 1.33333333+0.j, 0.00000000+0.j, 0.66666667+0.j])
+ array([ 1.33333333+0.j, 0.00000000+0.j, 0.66666667+0.j]) # may vary
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [legline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [legmul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = legmul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(legline, legmul, roots)
def legadd(c1, c2):
@@ -366,18 +352,10 @@ def legadd(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> L.legadd(c1,c2)
- array([ 4., 4., 4.])
+ array([4., 4., 4.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def legsub(c1, c2):
@@ -421,16 +399,7 @@ def legsub(c1, c2):
array([ 2., 0., -2.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def legmulx(c):
@@ -468,7 +437,7 @@ def legmulx(c):
--------
>>> from numpy.polynomial import legendre as L
>>> L.legmulx([1,2,3])
- array([ 0.66666667, 2.2, 1.33333333, 1.8])
+ array([ 0.66666667, 2.2, 1.33333333, 1.8]) # may vary
"""
# c is a trimmed copy
@@ -525,8 +494,8 @@ def legmul(c1, c2):
>>> from numpy.polynomial import legendre as L
>>> c1 = (1,2,3)
>>> c2 = (3,2)
- >>> P.legmul(c1,c2) # multiplication requires "reprojection"
- array([ 4.33333333, 10.4 , 11.66666667, 3.6 ])
+ >>> L.legmul(c1,c2) # multiplication requires "reprojection"
+ array([ 4.33333333, 10.4 , 11.66666667, 3.6 ]) # may vary
"""
# s1, s2 are trimmed copies
@@ -597,32 +566,13 @@ def legdiv(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> L.legdiv(c1,c2) # quotient "intuitive," remainder not
- (array([ 3.]), array([-8., -4.]))
+ (array([3.]), array([-8., -4.]))
>>> c2 = (0,1,2,3)
>>> L.legdiv(c2,c1) # neither "intuitive"
- (array([-0.07407407, 1.66666667]), array([-1.03703704, -2.51851852]))
+ (array([-0.07407407, 1.66666667]), array([-1.03703704, -2.51851852])) # may vary
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if c2[-1] == 0:
- raise ZeroDivisionError()
-
- lc1 = len(c1)
- lc2 = len(c2)
- if lc1 < lc2:
- return c1[:1]*0, c1
- elif lc2 == 1:
- return c1/c2[-1], c1[:1]*0
- else:
- quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
- rem = c1
- for i in range(lc1 - lc2, - 1, -1):
- p = legmul([0]*i + [1], c2)
- q = rem[-1]/p[-1]
- rem = rem[:-1] - q*p[:-1]
- quo[i] = q
- return quo, pu.trimseq(rem)
+ return pu._div(legmul, c1, c2)
def legpow(c, pow, maxpower=16):
@@ -656,24 +606,7 @@ def legpow(c, pow, maxpower=16):
--------
"""
- # c is a trimmed copy
- [c] = pu.as_series([c])
- power = int(pow)
- if power != pow or power < 0:
- raise ValueError("Power must be a non-negative integer.")
- elif maxpower is not None and power > maxpower:
- raise ValueError("Power is too large")
- elif power == 0:
- return np.array([1], dtype=c.dtype)
- elif power == 1:
- return c
- else:
- # This can be made more efficient by using powers of two
- # in the usual way.
- prd = c
- for i in range(2, power + 1):
- prd = legmul(prd, c)
- return prd
+ return pu._pow(legmul, c, pow, maxpower)
def legder(c, m=1, scl=1, axis=0):
@@ -729,7 +662,7 @@ def legder(c, m=1, scl=1, axis=0):
>>> L.legder(c)
array([ 6., 9., 20.])
>>> L.legder(c, 3)
- array([ 60.])
+ array([60.])
>>> L.legder(c, scl=-1)
array([ -6., -9., -20.])
>>> L.legder(c, 2,-1)
@@ -739,14 +672,10 @@ def legder(c, m=1, scl=1, axis=0):
c = np.array(c, ndmin=1, copy=1)
if c.dtype.char in '?bBhHiIlLqQpP':
c = c.astype(np.double)
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -845,16 +774,16 @@ def legint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
>>> from numpy.polynomial import legendre as L
>>> c = (1,2,3)
>>> L.legint(c)
- array([ 0.33333333, 0.4 , 0.66666667, 0.6 ])
+ array([ 0.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
>>> L.legint(c, 3)
- array([ 1.66666667e-02, -1.78571429e-02, 4.76190476e-02,
- -1.73472348e-18, 1.90476190e-02, 9.52380952e-03])
+ array([ 1.66666667e-02, -1.78571429e-02, 4.76190476e-02, # may vary
+ -1.73472348e-18, 1.90476190e-02, 9.52380952e-03])
>>> L.legint(c, k=3)
- array([ 3.33333333, 0.4 , 0.66666667, 0.6 ])
+ array([ 3.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
>>> L.legint(c, lbnd=-2)
- array([ 7.33333333, 0.4 , 0.66666667, 0.6 ])
+ array([ 7.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
>>> L.legint(c, scl=2)
- array([ 0.66666667, 0.8 , 1.33333333, 1.2 ])
+ array([ 0.66666667, 0.8 , 1.33333333, 1.2 ]) # may vary
"""
c = np.array(c, ndmin=1, copy=1)
@@ -862,10 +791,8 @@ def legint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
c = c.astype(np.double)
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -874,8 +801,6 @@ def legint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -1038,14 +963,7 @@ def legval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = legval(x, c)
- c = legval(y, c, tensor=False)
- return c
+ return pu._valnd(legval, c, x, y)
def leggrid2d(x, y, c):
@@ -1098,9 +1016,7 @@ def leggrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = legval(x, c)
- c = legval(y, c)
- return c
+ return pu._gridnd(legval, c, x, y)
def legval3d(x, y, z, c):
@@ -1151,15 +1067,7 @@ def legval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = legval(x, c)
- c = legval(y, c, tensor=False)
- c = legval(z, c, tensor=False)
- return c
+ return pu._valnd(legval, c, x, y, z)
def leggrid3d(x, y, z, c):
@@ -1215,10 +1123,7 @@ def leggrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = legval(x, c)
- c = legval(y, c)
- c = legval(z, c)
- return c
+ return pu._gridnd(legval, c, x, y, z)
def legvander(x, deg):
@@ -1256,9 +1161,7 @@ def legvander(x, deg):
the converted `x`.
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1318,7 +1221,7 @@ def legvander2d(x, y, deg):
See Also
--------
- legvander, legvander3d. legval2d, legval3d
+ legvander, legvander3d, legval2d, legval3d
Notes
-----
@@ -1326,17 +1229,7 @@ def legvander2d(x, y, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = legvander(x, degx)
- vy = legvander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(legvander, x, y, deg)
def legvander3d(x, y, z, deg):
@@ -1382,7 +1275,7 @@ def legvander3d(x, y, z, deg):
See Also
--------
- legvander, legvander3d. legval2d, legval3d
+ legvander, legvander3d, legval2d, legval3d
Notes
-----
@@ -1390,18 +1283,7 @@ def legvander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = legvander(x, degx)
- vy = legvander(y, degy)
- vz = legvander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(legvander, x, y, z, deg)
def legfit(x, y, deg, rcond=None, full=False, w=None):
@@ -1476,7 +1358,7 @@ def legfit(x, y, deg, rcond=None, full=False, w=None):
warnings can be turned off by
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1525,81 +1407,7 @@ def legfit(x, y, deg, rcond=None, full=False, w=None):
--------
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = legvander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = legvander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim > 0:
- if c.ndim == 2:
- cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax+1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(legvander, x, y, deg, rcond, full, w)
def legcompanion(c):
@@ -1686,7 +1494,7 @@ def legroots(c):
--------
>>> import numpy.polynomial.legendre as leg
>>> leg.legroots((1, 2, 3, 4)) # 4L_3 + 3L_2 + 2L_1 + 1L_0, all real roots
- array([-0.85099543, -0.11407192, 0.51506735])
+ array([-0.85099543, -0.11407192, 0.51506735]) # may vary
"""
# c is a trimmed copy
@@ -1696,7 +1504,8 @@ def legroots(c):
if len(c) == 2:
return np.array([-c[0]/c[1]])
- m = legcompanion(c)
+ # rotated companion matrix reduces error
+ m = legcompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
@@ -1738,9 +1547,9 @@ def leggauss(deg):
the right value when integrating 1.
"""
- ideg = int(deg)
- if ideg != deg or ideg < 1:
- raise ValueError("deg must be a non-negative integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
# first approximation of roots. We use the fact that the companion
# matrix is symmetric in this case in order to obtain better zeros.
diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py
index 259cd31f5..99f9fc2fd 100644
--- a/numpy/polynomial/polynomial.py
+++ b/numpy/polynomial/polynomial.py
@@ -185,24 +185,10 @@ def polyfromroots(roots):
array([ 0., -1., 0., 1.])
>>> j = complex(0,1)
>>> P.polyfromroots((-j,j)) # complex returned, though values are real
- array([ 1.+0.j, 0.+0.j, 1.+0.j])
+ array([1.+0.j, 0.+0.j, 1.+0.j])
"""
- if len(roots) == 0:
- return np.ones(1)
- else:
- [roots] = pu.as_series([roots], trim=False)
- roots.sort()
- p = [polyline(-r, 1) for r in roots]
- n = len(p)
- while n > 1:
- m, r = divmod(n, 2)
- tmp = [polymul(p[i], p[i+m]) for i in range(m)]
- if r:
- tmp[0] = polymul(tmp[0], p[-1])
- p = tmp
- n = m
- return p[0]
+ return pu._fromroots(polyline, polymul, roots)
def polyadd(c1, c2):
@@ -233,20 +219,12 @@ def polyadd(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> sum = P.polyadd(c1,c2); sum
- array([ 4., 4., 4.])
+ array([4., 4., 4.])
>>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
28.0
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] += c2
- ret = c1
- else:
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._add(c1, c2)
def polysub(c1, c2):
@@ -283,16 +261,7 @@ def polysub(c1, c2):
array([ 2., 0., -2.])
"""
- # c1, c2 are trimmed copies
- [c1, c2] = pu.as_series([c1, c2])
- if len(c1) > len(c2):
- c1[:c2.size] -= c2
- ret = c1
- else:
- c2 = -c2
- c2[:c1.size] += c1
- ret = c2
- return pu.trimseq(ret)
+ return pu._sub(c1, c2)
def polymulx(c):
@@ -401,9 +370,9 @@ def polydiv(c1, c2):
>>> c1 = (1,2,3)
>>> c2 = (3,2,1)
>>> P.polydiv(c1,c2)
- (array([ 3.]), array([-8., -4.]))
+ (array([3.]), array([-8., -4.]))
>>> P.polydiv(c2,c1)
- (array([ 0.33333333]), array([ 2.66666667, 1.33333333]))
+ (array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary
"""
# c1, c2 are trimmed copies
@@ -411,18 +380,19 @@ def polydiv(c1, c2):
if c2[-1] == 0:
raise ZeroDivisionError()
- len1 = len(c1)
- len2 = len(c2)
- if len2 == 1:
- return c1/c2[-1], c1[:1]*0
- elif len1 < len2:
+ # note: this is more efficient than `pu._div(polymul, c1, c2)`
+ lc1 = len(c1)
+ lc2 = len(c2)
+ if lc1 < lc2:
return c1[:1]*0, c1
+ elif lc2 == 1:
+ return c1/c2[-1], c1[:1]*0
else:
- dlen = len1 - len2
+ dlen = lc1 - lc2
scl = c2[-1]
c2 = c2[:-1]/scl
i = dlen
- j = len1 - 1
+ j = lc1 - 1
while i >= 0:
c1[i:j] -= c2*c1[j]
i -= 1
@@ -464,24 +434,9 @@ def polypow(c, pow, maxpower=None):
array([ 1., 4., 10., 12., 9.])
"""
- # c is a trimmed copy
- [c] = pu.as_series([c])
- power = int(pow)
- if power != pow or power < 0:
- raise ValueError("Power must be a non-negative integer.")
- elif maxpower is not None and power > maxpower:
- raise ValueError("Power is too large")
- elif power == 0:
- return np.array([1], dtype=c.dtype)
- elif power == 1:
- return c
- else:
- # This can be made more efficient by using powers of two
- # in the usual way.
- prd = c
- for i in range(2, power + 1):
- prd = np.convolve(prd, c)
- return prd
+ # note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it
+ # avoids calling `as_series` repeatedly
+ return pu._pow(np.convolve, c, pow, maxpower)
def polyder(c, m=1, scl=1, axis=0):
@@ -529,7 +484,7 @@ def polyder(c, m=1, scl=1, axis=0):
>>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2
array([ 2., 6., 12.])
>>> P.polyder(c,3) # (d**3/dx**3)(c) = 24
- array([ 24.])
+ array([24.])
>>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2
array([ -2., -6., -12.])
>>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x
@@ -541,14 +496,10 @@ def polyder(c, m=1, scl=1, axis=0):
# astype fails with NA
c = c + 0.0
cdt = c.dtype
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of derivation must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of derivation must be non-negative")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -636,14 +587,14 @@ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
>>> from numpy.polynomial import polynomial as P
>>> c = (1,2,3)
>>> P.polyint(c) # should return array([0, 1, 1, 1])
- array([ 0., 1., 1., 1.])
+ array([0., 1., 1., 1.])
>>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
- array([ 0. , 0. , 0. , 0.16666667, 0.08333333,
- 0.05 ])
+ array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary
+ 0.05 ])
>>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])
- array([ 3., 1., 1., 1.])
+ array([3., 1., 1., 1.])
>>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])
- array([ 6., 1., 1., 1.])
+ array([6., 1., 1., 1.])
>>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])
array([ 0., -2., -2., -2.])
@@ -655,10 +606,8 @@ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
cdt = c.dtype
if not np.iterable(k):
k = [k]
- cnt, iaxis = [int(t) for t in [m, axis]]
-
- if cnt != m:
- raise ValueError("The order of integration must be integer")
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
if cnt < 0:
raise ValueError("The order of integration must be non-negative")
if len(k) > cnt:
@@ -667,8 +616,6 @@ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
raise ValueError("lbnd must be a scalar.")
if np.ndim(scl) != 0:
raise ValueError("scl must be a scalar.")
- if iaxis != axis:
- raise ValueError("The axis must be integer")
iaxis = normalize_axis_index(iaxis, c.ndim)
if cnt == 0:
@@ -761,17 +708,17 @@ def polyval(x, c, tensor=True):
array([[0, 1],
[2, 3]])
>>> polyval(a, [1,2,3])
- array([[ 1., 6.],
- [ 17., 34.]])
+ array([[ 1., 6.],
+ [17., 34.]])
>>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients
>>> coef
array([[0, 1],
[2, 3]])
>>> polyval([1,2], coef, tensor=True)
- array([[ 2., 4.],
- [ 4., 7.]])
+ array([[2., 4.],
+ [4., 7.]])
>>> polyval([1,2], coef, tensor=False)
- array([ 2., 7.])
+ array([2., 7.])
"""
c = np.array(c, ndmin=1, copy=0)
@@ -851,8 +798,8 @@ def polyvalfromroots(x, r, tensor=True):
array([[0, 1],
[2, 3]])
>>> polyvalfromroots(a, [-1, 0, 1])
- array([[ -0., 0.],
- [ 6., 24.]])
+ array([[-0., 0.],
+ [ 6., 24.]])
>>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients
>>> r # each column of r defines one polynomial
array([[-2, -1],
@@ -924,14 +871,7 @@ def polyval2d(x, y, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y = np.array((x, y), copy=0)
- except Exception:
- raise ValueError('x, y are incompatible')
-
- c = polyval(x, c)
- c = polyval(y, c, tensor=False)
- return c
+ return pu._valnd(polyval, c, x, y)
def polygrid2d(x, y, c):
@@ -984,9 +924,7 @@ def polygrid2d(x, y, c):
.. versionadded:: 1.7.0
"""
- c = polyval(x, c)
- c = polyval(y, c)
- return c
+ return pu._gridnd(polyval, c, x, y)
def polyval3d(x, y, z, c):
@@ -1037,15 +975,7 @@ def polyval3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- try:
- x, y, z = np.array((x, y, z), copy=0)
- except Exception:
- raise ValueError('x, y, z are incompatible')
-
- c = polyval(x, c)
- c = polyval(y, c, tensor=False)
- c = polyval(z, c, tensor=False)
- return c
+ return pu._valnd(polyval, c, x, y, z)
def polygrid3d(x, y, z, c):
@@ -1101,10 +1031,7 @@ def polygrid3d(x, y, z, c):
.. versionadded:: 1.7.0
"""
- c = polyval(x, c)
- c = polyval(y, c)
- c = polyval(z, c)
- return c
+ return pu._gridnd(polyval, c, x, y, z)
def polyvander(x, deg):
@@ -1145,9 +1072,7 @@ def polyvander(x, deg):
polyvander2d, polyvander3d
"""
- ideg = int(deg)
- if ideg != deg:
- raise ValueError("deg must be integer")
+ ideg = pu._deprecate_as_int(deg, "deg")
if ideg < 0:
raise ValueError("deg must be non-negative")
@@ -1205,22 +1130,10 @@ def polyvander2d(x, y, deg):
See Also
--------
- polyvander, polyvander3d. polyval2d, polyval3d
+ polyvander, polyvander3d, polyval2d, polyval3d
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy = ideg
- x, y = np.array((x, y), copy=0) + 0.0
-
- vx = polyvander(x, degx)
- vy = polyvander(y, degy)
- v = vx[..., None]*vy[..., None,:]
- # einsum bug
- #v = np.einsum("...i,...j->...ij", vx, vy)
- return v.reshape(v.shape[:-2] + (-1,))
+ return pu._vander2d(polyvander, x, y, deg)
def polyvander3d(x, y, z, deg):
@@ -1266,7 +1179,7 @@ def polyvander3d(x, y, z, deg):
See Also
--------
- polyvander, polyvander3d. polyval2d, polyval3d
+ polyvander, polyvander3d, polyval2d, polyval3d
Notes
-----
@@ -1274,20 +1187,7 @@ def polyvander3d(x, y, z, deg):
.. versionadded:: 1.7.0
"""
- ideg = [int(d) for d in deg]
- is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
- if is_valid != [1, 1, 1]:
- raise ValueError("degrees must be non-negative integers")
- degx, degy, degz = ideg
- x, y, z = np.array((x, y, z), copy=0) + 0.0
-
- vx = polyvander(x, degx)
- vy = polyvander(y, degy)
- vz = polyvander(z, degz)
- v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
- # einsum bug
- #v = np.einsum("...i, ...j, ...k->...ijk", vx, vy, vz)
- return v.reshape(v.shape[:-3] + (-1,))
+ return pu._vander3d(polyvander, x, y, z, deg)
def polyfit(x, y, deg, rcond=None, full=False, w=None):
@@ -1363,7 +1263,7 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None):
be turned off by:
>>> import warnings
- >>> warnings.simplefilter('ignore', RankWarning)
+ >>> warnings.simplefilter('ignore', np.RankWarning)
See Also
--------
@@ -1410,103 +1310,30 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None):
Examples
--------
+ >>> np.random.seed(123)
>>> from numpy.polynomial import polynomial as P
>>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
>>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise"
>>> c, stats = P.polyfit(x,y,3,full=True)
+ >>> np.random.seed(123)
>>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
- array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286])
+ array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary
>>> stats # note the large SSR, explaining the rather poor results
- [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316,
- 0.28853036]), 1.1324274851176597e-014]
+ [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary
+ 0.28853036]), 1.1324274851176597e-014]
Same thing without the added noise
>>> y = x**3 - x
>>> c, stats = P.polyfit(x,y,3,full=True)
>>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
- array([ -1.73362882e-17, -1.00000000e+00, -2.67471909e-16,
- 1.00000000e+00])
+ array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])
>>> stats # note the minuscule SSR
- [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158,
- 0.50443316, 0.28853036]), 1.1324274851176597e-014]
+ [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary
+ 0.50443316, 0.28853036]), 1.1324274851176597e-014]
"""
- x = np.asarray(x) + 0.0
- y = np.asarray(y) + 0.0
- deg = np.asarray(deg)
-
- # check arguments.
- if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
- raise TypeError("deg must be an int or non-empty 1-D array of int")
- if deg.min() < 0:
- raise ValueError("expected deg >= 0")
- if x.ndim != 1:
- raise TypeError("expected 1D vector for x")
- if x.size == 0:
- raise TypeError("expected non-empty vector for x")
- if y.ndim < 1 or y.ndim > 2:
- raise TypeError("expected 1D or 2D array for y")
- if len(x) != len(y):
- raise TypeError("expected x and y to have same length")
-
- if deg.ndim == 0:
- lmax = deg
- order = lmax + 1
- van = polyvander(x, lmax)
- else:
- deg = np.sort(deg)
- lmax = deg[-1]
- order = len(deg)
- van = polyvander(x, lmax)[:, deg]
-
- # set up the least squares matrices in transposed form
- lhs = van.T
- rhs = y.T
- if w is not None:
- w = np.asarray(w) + 0.0
- if w.ndim != 1:
- raise TypeError("expected 1D vector for w")
- if len(x) != len(w):
- raise TypeError("expected x and w to have same length")
- # apply weights. Don't use inplace operations as they
- # can cause problems with NA.
- lhs = lhs * w
- rhs = rhs * w
-
- # set rcond
- if rcond is None:
- rcond = len(x)*np.finfo(x.dtype).eps
-
- # Determine the norms of the design matrix columns.
- if issubclass(lhs.dtype.type, np.complexfloating):
- scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
- else:
- scl = np.sqrt(np.square(lhs).sum(1))
- scl[scl == 0] = 1
-
- # Solve the least squares problem.
- c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
- c = (c.T/scl).T
-
- # Expand c to include non-fitted coefficients which are set to zero
- if deg.ndim == 1:
- if c.ndim == 2:
- cc = np.zeros((lmax + 1, c.shape[1]), dtype=c.dtype)
- else:
- cc = np.zeros(lmax + 1, dtype=c.dtype)
- cc[deg] = c
- c = cc
-
- # warn on rank reduction
- if rank != order and not full:
- msg = "The fit may be poorly conditioned"
- warnings.warn(msg, pu.RankWarning, stacklevel=2)
-
- if full:
- return c, [resids, rank, s, rcond]
- else:
- return c
+ return pu._fit(polyvander, x, y, deg, rcond, full, w)
def polycompanion(c):
@@ -1591,7 +1418,7 @@ def polyroots(c):
dtype('float64')
>>> j = complex(0,1)
>>> poly.polyroots(poly.polyfromroots((-j,0,j)))
- array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j])
+ array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary
"""
# c is a trimmed copy
@@ -1601,7 +1428,8 @@ def polyroots(c):
if len(c) == 2:
return np.array([-c[0]/c[1]])
- m = polycompanion(c)
+ # rotated companion matrix reduces error
+ m = polycompanion(c)[::-1,::-1]
r = la.eigvals(m)
r.sort()
return r
diff --git a/numpy/polynomial/polyutils.py b/numpy/polynomial/polyutils.py
index c1ed0c9b3..841421d0e 100644
--- a/numpy/polynomial/polyutils.py
+++ b/numpy/polynomial/polyutils.py
@@ -45,6 +45,9 @@ Functions
"""
from __future__ import division, absolute_import, print_function
+import operator
+import warnings
+
import numpy as np
__all__ = [
@@ -156,19 +159,19 @@ def as_series(alist, trim=True):
>>> from numpy.polynomial import polyutils as pu
>>> a = np.arange(4)
>>> pu.as_series(a)
- [array([ 0.]), array([ 1.]), array([ 2.]), array([ 3.])]
+ [array([0.]), array([1.]), array([2.]), array([3.])]
>>> b = np.arange(6).reshape((2,3))
>>> pu.as_series(b)
- [array([ 0., 1., 2.]), array([ 3., 4., 5.])]
+ [array([0., 1., 2.]), array([3., 4., 5.])]
>>> pu.as_series((1, np.arange(3), np.arange(2, dtype=np.float16)))
- [array([ 1.]), array([ 0., 1., 2.]), array([ 0., 1.])]
+ [array([1.]), array([0., 1., 2.]), array([0., 1.])]
>>> pu.as_series([2, [1.1, 0.]])
- [array([ 2.]), array([ 1.1])]
+ [array([2.]), array([1.1])]
>>> pu.as_series([2, [1.1, 0.]], trim=False)
- [array([ 2.]), array([ 1.1, 0. ])]
+ [array([2.]), array([1.1, 0. ])]
"""
arrays = [np.array(a, ndmin=1, copy=0) for a in alist]
@@ -233,12 +236,12 @@ def trimcoef(c, tol=0):
--------
>>> from numpy.polynomial import polyutils as pu
>>> pu.trimcoef((0,0,3,0,5,0,0))
- array([ 0., 0., 3., 0., 5.])
+ array([0., 0., 3., 0., 5.])
>>> pu.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed
- array([ 0.])
+ array([0.])
>>> i = complex(0,1) # works for complex
>>> pu.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
- array([ 0.0003+0.j , 0.0010-0.001j])
+ array([0.0003+0.j , 0.001 -0.001j])
"""
if tol < 0:
@@ -332,10 +335,10 @@ def mapparms(old, new):
>>> pu.mapparms((-1,1),(-1,1))
(0.0, 1.0)
>>> pu.mapparms((1,-1),(-1,1))
- (0.0, -1.0)
+ (-0.0, -1.0)
>>> i = complex(0,1)
>>> pu.mapparms((-i,-1),(1,i))
- ((1+1j), (1+0j))
+ ((1+1j), (1-0j))
"""
oldlen = old[1] - old[0]
@@ -390,10 +393,10 @@ def mapdomain(x, old, new):
>>> x = np.linspace(-1,1,6); x
array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ])
>>> x_out = pu.mapdomain(x, old_domain, new_domain); x_out
- array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825,
+ array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825, # may vary
6.28318531])
>>> x - pu.mapdomain(x_out, new_domain, old_domain)
- array([ 0., 0., 0., 0., 0., 0.])
+ array([0., 0., 0., 0., 0., 0.])
Also works for complex numbers (and thus can be used to map any line in
the complex plane to any other line therein).
@@ -402,11 +405,358 @@ def mapdomain(x, old, new):
>>> old = (-1 - i, 1 + i)
>>> new = (-1 + i, 1 - i)
>>> z = np.linspace(old[0], old[1], 6); z
- array([-1.0-1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1.0+1.j ])
- >>> new_z = P.mapdomain(z, old, new); new_z
- array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ])
+ array([-1. -1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1. +1.j ])
+ >>> new_z = pu.mapdomain(z, old, new); new_z
+ array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ]) # may vary
"""
x = np.asanyarray(x)
off, scl = mapparms(old, new)
return off + scl*x
+
+
+def _vander2d(vander_f, x, y, deg):
+ """
+ Helper function used to implement the ``<type>vander2d`` functions.
+
+ Parameters
+ ----------
+ vander_f : function(array_like, int) -> ndarray
+ The 1d vander function, such as ``polyvander``
+ x, y, deg :
+ See the ``<type>vander2d`` functions for more detail
+ """
+ degx, degy = [
+ _deprecate_as_int(d, "degrees")
+ for d in deg
+ ]
+ x, y = np.array((x, y), copy=0) + 0.0
+
+ vx = vander_f(x, degx)
+ vy = vander_f(y, degy)
+ v = vx[..., None]*vy[..., None,:]
+ return v.reshape(v.shape[:-2] + (-1,))
+
+
+def _vander3d(vander_f, x, y, z, deg):
+ """
+ Helper function used to implement the ``<type>vander3d`` functions.
+
+ Parameters
+ ----------
+ vander_f : function(array_like, int) -> ndarray
+ The 1d vander function, such as ``polyvander``
+ x, y, z, deg :
+ See the ``<type>vander3d`` functions for more detail
+ """
+ degx, degy, degz = [
+ _deprecate_as_int(d, "degrees")
+ for d in deg
+ ]
+ x, y, z = np.array((x, y, z), copy=0) + 0.0
+
+ vx = vander_f(x, degx)
+ vy = vander_f(y, degy)
+ vz = vander_f(z, degz)
+ v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
+ return v.reshape(v.shape[:-3] + (-1,))
+
+
+def _fromroots(line_f, mul_f, roots):
+ """
+ Helper function used to implement the ``<type>fromroots`` functions.
+
+ Parameters
+ ----------
+ line_f : function(float, float) -> ndarray
+ The ``<type>line`` function, such as ``polyline``
+ mul_f : function(array_like, array_like) -> ndarray
+ The ``<type>mul`` function, such as ``polymul``
+ roots :
+ See the ``<type>fromroots`` functions for more detail
+ """
+ if len(roots) == 0:
+ return np.ones(1)
+ else:
+ [roots] = as_series([roots], trim=False)
+ roots.sort()
+ p = [line_f(-r, 1) for r in roots]
+ n = len(p)
+ while n > 1:
+ m, r = divmod(n, 2)
+ tmp = [mul_f(p[i], p[i+m]) for i in range(m)]
+ if r:
+ tmp[0] = mul_f(tmp[0], p[-1])
+ p = tmp
+ n = m
+ return p[0]
+
+
+def _valnd(val_f, c, *args):
+ """
+ Helper function used to implement the ``<type>val<n>d`` functions.
+
+ Parameters
+ ----------
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
+ The ``<type>val`` function, such as ``polyval``
+ c, args :
+ See the ``<type>val<n>d`` functions for more detail
+ """
+ try:
+ args = tuple(np.array(args, copy=False))
+ except Exception:
+ # preserve the old error message
+ if len(args) == 2:
+ raise ValueError('x, y, z are incompatible')
+ elif len(args) == 3:
+ raise ValueError('x, y are incompatible')
+ else:
+ raise ValueError('ordinates are incompatible')
+
+ it = iter(args)
+ x0 = next(it)
+
+ # use tensor on only the first
+ c = val_f(x0, c)
+ for xi in it:
+ c = val_f(xi, c, tensor=False)
+ return c
+
+
+def _gridnd(val_f, c, *args):
+ """
+ Helper function used to implement the ``<type>grid<n>d`` functions.
+
+ Parameters
+ ----------
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
+ The ``<type>val`` function, such as ``polyval``
+ c, args :
+ See the ``<type>grid<n>d`` functions for more detail
+ """
+ for xi in args:
+ c = val_f(xi, c)
+ return c
+
+
+def _div(mul_f, c1, c2):
+ """
+ Helper function used to implement the ``<type>div`` functions.
+
+ Implementation uses repeated subtraction of c2 multiplied by the nth basis.
+ For some polynomial types, a more efficient approach may be possible.
+
+ Parameters
+ ----------
+ mul_f : function(array_like, array_like) -> array_like
+ The ``<type>mul`` function, such as ``polymul``
+ c1, c2 :
+ See the ``<type>div`` functions for more detail
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if c2[-1] == 0:
+ raise ZeroDivisionError()
+
+ lc1 = len(c1)
+ lc2 = len(c2)
+ if lc1 < lc2:
+ return c1[:1]*0, c1
+ elif lc2 == 1:
+ return c1/c2[-1], c1[:1]*0
+ else:
+ quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
+ rem = c1
+ for i in range(lc1 - lc2, - 1, -1):
+ p = mul_f([0]*i + [1], c2)
+ q = rem[-1]/p[-1]
+ rem = rem[:-1] - q*p[:-1]
+ quo[i] = q
+ return quo, trimseq(rem)
+
+
+def _add(c1, c2):
+ """ Helper function used to implement the ``<type>add`` functions. """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if len(c1) > len(c2):
+ c1[:c2.size] += c2
+ ret = c1
+ else:
+ c2[:c1.size] += c1
+ ret = c2
+ return trimseq(ret)
+
+
+def _sub(c1, c2):
+ """ Helper function used to implement the ``<type>sub`` functions. """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if len(c1) > len(c2):
+ c1[:c2.size] -= c2
+ ret = c1
+ else:
+ c2 = -c2
+ c2[:c1.size] += c1
+ ret = c2
+ return trimseq(ret)
+
+
+def _fit(vander_f, x, y, deg, rcond=None, full=False, w=None):
+ """
+ Helper function used to implement the ``<type>fit`` functions.
+
+ Parameters
+ ----------
+ vander_f : function(array_like, int) -> ndarray
+ The 1d vander function, such as ``polyvander``
+ c1, c2 :
+ See the ``<type>fit`` functions for more detail
+ """
+ x = np.asarray(x) + 0.0
+ y = np.asarray(y) + 0.0
+ deg = np.asarray(deg)
+
+ # check arguments.
+ if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
+ raise TypeError("deg must be an int or non-empty 1-D array of int")
+ if deg.min() < 0:
+ raise ValueError("expected deg >= 0")
+ if x.ndim != 1:
+ raise TypeError("expected 1D vector for x")
+ if x.size == 0:
+ raise TypeError("expected non-empty vector for x")
+ if y.ndim < 1 or y.ndim > 2:
+ raise TypeError("expected 1D or 2D array for y")
+ if len(x) != len(y):
+ raise TypeError("expected x and y to have same length")
+
+ if deg.ndim == 0:
+ lmax = deg
+ order = lmax + 1
+ van = vander_f(x, lmax)
+ else:
+ deg = np.sort(deg)
+ lmax = deg[-1]
+ order = len(deg)
+ van = vander_f(x, lmax)[:, deg]
+
+ # set up the least squares matrices in transposed form
+ lhs = van.T
+ rhs = y.T
+ if w is not None:
+ w = np.asarray(w) + 0.0
+ if w.ndim != 1:
+ raise TypeError("expected 1D vector for w")
+ if len(x) != len(w):
+ raise TypeError("expected x and w to have same length")
+ # apply weights. Don't use inplace operations as they
+ # can cause problems with NA.
+ lhs = lhs * w
+ rhs = rhs * w
+
+ # set rcond
+ if rcond is None:
+ rcond = len(x)*np.finfo(x.dtype).eps
+
+ # Determine the norms of the design matrix columns.
+ if issubclass(lhs.dtype.type, np.complexfloating):
+ scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
+ else:
+ scl = np.sqrt(np.square(lhs).sum(1))
+ scl[scl == 0] = 1
+
+ # Solve the least squares problem.
+ c, resids, rank, s = np.linalg.lstsq(lhs.T/scl, rhs.T, rcond)
+ c = (c.T/scl).T
+
+ # Expand c to include non-fitted coefficients which are set to zero
+ if deg.ndim > 0:
+ if c.ndim == 2:
+ cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
+ else:
+ cc = np.zeros(lmax+1, dtype=c.dtype)
+ cc[deg] = c
+ c = cc
+
+ # warn on rank reduction
+ if rank != order and not full:
+ msg = "The fit may be poorly conditioned"
+ warnings.warn(msg, RankWarning, stacklevel=2)
+
+ if full:
+ return c, [resids, rank, s, rcond]
+ else:
+ return c
+
+
+def _pow(mul_f, c, pow, maxpower):
+ """
+ Helper function used to implement the ``<type>pow`` functions.
+
+ Parameters
+ ----------
+ vander_f : function(array_like, int) -> ndarray
+ The 1d vander function, such as ``polyvander``
+ pow, maxpower :
+ See the ``<type>pow`` functions for more detail
+ mul_f : function(array_like, array_like) -> ndarray
+ The ``<type>mul`` function, such as ``polymul``
+ """
+ # c is a trimmed copy
+ [c] = as_series([c])
+ power = int(pow)
+ if power != pow or power < 0:
+ raise ValueError("Power must be a non-negative integer.")
+ elif maxpower is not None and power > maxpower:
+ raise ValueError("Power is too large")
+ elif power == 0:
+ return np.array([1], dtype=c.dtype)
+ elif power == 1:
+ return c
+ else:
+ # This can be made more efficient by using powers of two
+ # in the usual way.
+ prd = c
+ for i in range(2, power + 1):
+ prd = mul_f(prd, c)
+ return prd
+
+
+def _deprecate_as_int(x, desc):
+ """
+ Like `operator.index`, but emits a deprecation warning when passed a float
+
+ Parameters
+ ----------
+ x : int-like, or float with integral value
+ Value to interpret as an integer
+ desc : str
+ description to include in any error message
+
+ Raises
+ ------
+ TypeError : if x is a non-integral float or non-numeric
+ DeprecationWarning : if x is an integral float
+ """
+ try:
+ return operator.index(x)
+ except TypeError:
+ # Numpy 1.17.0, 2019-03-11
+ try:
+ ix = int(x)
+ except TypeError:
+ pass
+ else:
+ if ix == x:
+ warnings.warn(
+ "In future, this will raise TypeError, as {} will need to "
+ "be an integer not just an integral float."
+ .format(desc),
+ DeprecationWarning,
+ stacklevel=3
+ )
+ return ix
+
+ raise TypeError("{} must be an integer".format(desc))
diff --git a/numpy/polynomial/tests/test_chebyshev.py b/numpy/polynomial/tests/test_chebyshev.py
index 7fb7492c6..c8d2d6dba 100644
--- a/numpy/polynomial/tests/test_chebyshev.py
+++ b/numpy/polynomial/tests/test_chebyshev.py
@@ -221,12 +221,12 @@ class TestIntegral(object):
def test_chebint(self):
# check exceptions
- assert_raises(ValueError, cheb.chebint, [0], .5)
+ assert_raises(TypeError, cheb.chebint, [0], .5)
assert_raises(ValueError, cheb.chebint, [0], -1)
assert_raises(ValueError, cheb.chebint, [0], 1, [0, 0])
assert_raises(ValueError, cheb.chebint, [0], lbnd=[0])
assert_raises(ValueError, cheb.chebint, [0], scl=[0])
- assert_raises(ValueError, cheb.chebint, [0], axis=.5)
+ assert_raises(TypeError, cheb.chebint, [0], axis=.5)
# test integration of zero polynomial
for i in range(2, 5):
@@ -323,7 +323,7 @@ class TestDerivative(object):
def test_chebder(self):
# check exceptions
- assert_raises(ValueError, cheb.chebder, [0], .5)
+ assert_raises(TypeError, cheb.chebder, [0], .5)
assert_raises(ValueError, cheb.chebder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/polynomial/tests/test_classes.py b/numpy/polynomial/tests/test_classes.py
index 15e24f92b..2261f960b 100644
--- a/numpy/polynomial/tests/test_classes.py
+++ b/numpy/polynomial/tests/test_classes.py
@@ -16,7 +16,7 @@ from numpy.testing import (
assert_almost_equal, assert_raises, assert_equal, assert_,
)
from numpy.compat import long
-
+from numpy.polynomial.polyutils import RankWarning
#
# fixtures
@@ -133,6 +133,17 @@ def test_fromroots(Poly):
assert_almost_equal(p2.coef[-1], 1)
+def test_bad_conditioned_fit(Poly):
+
+ x = [0., 0., 1.]
+ y = [1., 2., 3.]
+
+ # check RankWarning is raised
+ with pytest.warns(RankWarning) as record:
+ Poly.fit(x, y, 2)
+ assert record[0].message.args[0] == "The fit may be poorly conditioned"
+
+
def test_fit(Poly):
def f(x):
diff --git a/numpy/polynomial/tests/test_hermite.py b/numpy/polynomial/tests/test_hermite.py
index 1287ef3fe..271c1964b 100644
--- a/numpy/polynomial/tests/test_hermite.py
+++ b/numpy/polynomial/tests/test_hermite.py
@@ -209,12 +209,12 @@ class TestIntegral(object):
def test_hermint(self):
# check exceptions
- assert_raises(ValueError, herm.hermint, [0], .5)
+ assert_raises(TypeError, herm.hermint, [0], .5)
assert_raises(ValueError, herm.hermint, [0], -1)
assert_raises(ValueError, herm.hermint, [0], 1, [0, 0])
assert_raises(ValueError, herm.hermint, [0], lbnd=[0])
assert_raises(ValueError, herm.hermint, [0], scl=[0])
- assert_raises(ValueError, herm.hermint, [0], axis=.5)
+ assert_raises(TypeError, herm.hermint, [0], axis=.5)
# test integration of zero polynomial
for i in range(2, 5):
@@ -311,7 +311,7 @@ class TestDerivative(object):
def test_hermder(self):
# check exceptions
- assert_raises(ValueError, herm.hermder, [0], .5)
+ assert_raises(TypeError, herm.hermder, [0], .5)
assert_raises(ValueError, herm.hermder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/polynomial/tests/test_hermite_e.py b/numpy/polynomial/tests/test_hermite_e.py
index ccb44ad73..434b30e7b 100644
--- a/numpy/polynomial/tests/test_hermite_e.py
+++ b/numpy/polynomial/tests/test_hermite_e.py
@@ -209,12 +209,12 @@ class TestIntegral(object):
def test_hermeint(self):
# check exceptions
- assert_raises(ValueError, herme.hermeint, [0], .5)
+ assert_raises(TypeError, herme.hermeint, [0], .5)
assert_raises(ValueError, herme.hermeint, [0], -1)
assert_raises(ValueError, herme.hermeint, [0], 1, [0, 0])
assert_raises(ValueError, herme.hermeint, [0], lbnd=[0])
assert_raises(ValueError, herme.hermeint, [0], scl=[0])
- assert_raises(ValueError, herme.hermeint, [0], axis=.5)
+ assert_raises(TypeError, herme.hermeint, [0], axis=.5)
# test integration of zero polynomial
for i in range(2, 5):
@@ -311,7 +311,7 @@ class TestDerivative(object):
def test_hermeder(self):
# check exceptions
- assert_raises(ValueError, herme.hermeder, [0], .5)
+ assert_raises(TypeError, herme.hermeder, [0], .5)
assert_raises(ValueError, herme.hermeder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/polynomial/tests/test_laguerre.py b/numpy/polynomial/tests/test_laguerre.py
index 3ababec5e..4b9b28637 100644
--- a/numpy/polynomial/tests/test_laguerre.py
+++ b/numpy/polynomial/tests/test_laguerre.py
@@ -206,12 +206,12 @@ class TestIntegral(object):
def test_lagint(self):
# check exceptions
- assert_raises(ValueError, lag.lagint, [0], .5)
+ assert_raises(TypeError, lag.lagint, [0], .5)
assert_raises(ValueError, lag.lagint, [0], -1)
assert_raises(ValueError, lag.lagint, [0], 1, [0, 0])
assert_raises(ValueError, lag.lagint, [0], lbnd=[0])
assert_raises(ValueError, lag.lagint, [0], scl=[0])
- assert_raises(ValueError, lag.lagint, [0], axis=.5)
+ assert_raises(TypeError, lag.lagint, [0], axis=.5)
# test integration of zero polynomial
for i in range(2, 5):
@@ -308,7 +308,7 @@ class TestDerivative(object):
def test_lagder(self):
# check exceptions
- assert_raises(ValueError, lag.lagder, [0], .5)
+ assert_raises(TypeError, lag.lagder, [0], .5)
assert_raises(ValueError, lag.lagder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/polynomial/tests/test_legendre.py b/numpy/polynomial/tests/test_legendre.py
index a23086d59..917a7e03a 100644
--- a/numpy/polynomial/tests/test_legendre.py
+++ b/numpy/polynomial/tests/test_legendre.py
@@ -210,12 +210,12 @@ class TestIntegral(object):
def test_legint(self):
# check exceptions
- assert_raises(ValueError, leg.legint, [0], .5)
+ assert_raises(TypeError, leg.legint, [0], .5)
assert_raises(ValueError, leg.legint, [0], -1)
assert_raises(ValueError, leg.legint, [0], 1, [0, 0])
assert_raises(ValueError, leg.legint, [0], lbnd=[0])
assert_raises(ValueError, leg.legint, [0], scl=[0])
- assert_raises(ValueError, leg.legint, [0], axis=.5)
+ assert_raises(TypeError, leg.legint, [0], axis=.5)
# test integration of zero polynomial
for i in range(2, 5):
@@ -312,7 +312,7 @@ class TestDerivative(object):
def test_legder(self):
# check exceptions
- assert_raises(ValueError, leg.legder, [0], .5)
+ assert_raises(TypeError, leg.legder, [0], .5)
assert_raises(ValueError, leg.legder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/polynomial/tests/test_polynomial.py b/numpy/polynomial/tests/test_polynomial.py
index 0c93be278..1436963c6 100644
--- a/numpy/polynomial/tests/test_polynomial.py
+++ b/numpy/polynomial/tests/test_polynomial.py
@@ -9,7 +9,7 @@ import numpy as np
import numpy.polynomial.polynomial as poly
from numpy.testing import (
assert_almost_equal, assert_raises, assert_equal, assert_,
- )
+ assert_warns, assert_array_equal)
def trim(x):
@@ -147,6 +147,19 @@ class TestEvaluation(object):
assert_equal(poly.polyval(x, [1, 0]).shape, dims)
assert_equal(poly.polyval(x, [1, 0, 0]).shape, dims)
+ #check masked arrays are processed correctly
+ mask = [False, True, False]
+ mx = np.ma.array([1, 2, 3], mask=mask)
+ res = np.polyval([7, 5, 3], mx)
+ assert_array_equal(res.mask, mask)
+
+ #check subtypes of ndarray are preserved
+ class C(np.ndarray):
+ pass
+
+ cx = np.array([1, 2, 3]).view(C)
+ assert_equal(type(np.polyval([2, 3, 4], cx)), C)
+
def test_polyvalfromroots(self):
# check exception for broadcasting x values over root array with
# too few dimensions
@@ -278,12 +291,14 @@ class TestIntegral(object):
def test_polyint(self):
# check exceptions
- assert_raises(ValueError, poly.polyint, [0], .5)
+ assert_raises(TypeError, poly.polyint, [0], .5)
assert_raises(ValueError, poly.polyint, [0], -1)
assert_raises(ValueError, poly.polyint, [0], 1, [0, 0])
assert_raises(ValueError, poly.polyint, [0], lbnd=[0])
assert_raises(ValueError, poly.polyint, [0], scl=[0])
- assert_raises(ValueError, poly.polyint, [0], axis=.5)
+ assert_raises(TypeError, poly.polyint, [0], axis=.5)
+ with assert_warns(DeprecationWarning):
+ poly.polyint([1, 1], 1.)
# test integration of zero polynomial
for i in range(2, 5):
@@ -375,7 +390,7 @@ class TestDerivative(object):
def test_polyder(self):
# check exceptions
- assert_raises(ValueError, poly.polyder, [0], .5)
+ assert_raises(TypeError, poly.polyder, [0], .5)
assert_raises(ValueError, poly.polyder, [0], -1)
# check that zeroth derivative does nothing
diff --git a/numpy/random/LICENSE.md b/numpy/random/LICENSE.md
new file mode 100644
index 000000000..a6cf1b17e
--- /dev/null
+++ b/numpy/random/LICENSE.md
@@ -0,0 +1,71 @@
+**This software is dual-licensed under the The University of Illinois/NCSA
+Open Source License (NCSA) and The 3-Clause BSD License**
+
+# NCSA Open Source License
+**Copyright (c) 2019 Kevin Sheppard. All rights reserved.**
+
+Developed by: Kevin Sheppard (<kevin.sheppard@economics.ox.ac.uk>,
+<kevin.k.sheppard@gmail.com>)
+[http://www.kevinsheppard.com](http://www.kevinsheppard.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimers.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimers in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of Kevin Sheppard, nor the names of any contributors may be
+used to endorse or promote products derived from this Software without specific
+prior written permission.
+
+**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
+THE SOFTWARE.**
+
+
+# 3-Clause BSD License
+**Copyright (c) 2019 Kevin Sheppard. All rights reserved.**
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+**THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.**
+
+# Components
+
+Many parts of this module have been derived from original sources,
+often the algorithm's designer. Component licenses are located with
+the component code.
diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py
index 965ab5ea9..2d495d67e 100644
--- a/numpy/random/__init__.py
+++ b/numpy/random/__init__.py
@@ -3,32 +3,67 @@
Random Number Generation
========================
+Use ``default_rng()`` to create a `Generator` and call its methods.
+
+=============== =========================================================
+Generator
+--------------- ---------------------------------------------------------
+Generator Class implementing all of the random number distributions
+default_rng Default constructor for ``Generator``
+=============== =========================================================
+
+============================================= ===
+BitGenerator Streams that work with Generator
+--------------------------------------------- ---
+MT19937
+PCG64
+Philox
+SFC64
+============================================= ===
+
+============================================= ===
+Getting entropy to initialize a BitGenerator
+--------------------------------------------- ---
+SeedSequence
+============================================= ===
+
+
+Legacy
+------
+
+For backwards compatibility with previous versions of numpy before 1.17, the
+various aliases to the global `RandomState` methods are left alone and do not
+use the new `Generator` API.
+
==================== =========================================================
Utility functions
-==============================================================================
-random_sample Uniformly distributed floats over ``[0, 1)``.
-random Alias for `random_sample`.
+-------------------- ---------------------------------------------------------
+random Uniformly distributed floats over ``[0, 1)``
bytes Uniformly distributed random bytes.
-random_integers Uniformly distributed integers in a given range.
permutation Randomly permute a sequence / generate a random sequence.
shuffle Randomly permute a sequence in place.
-seed Seed the random number generator.
choice Random sample from 1-D array.
-
==================== =========================================================
==================== =========================================================
-Compatibility functions
-==============================================================================
+Compatibility
+functions - removed
+in the new API
+-------------------- ---------------------------------------------------------
rand Uniformly distributed values.
randn Normally distributed values.
ranf Uniformly distributed floating point numbers.
-randint Uniformly distributed integers in a given range.
+random_integers Uniformly distributed integers in a given range.
+ (deprecated, use ``integers(..., closed=True)`` instead)
+random_sample Alias for `random_sample`
+randint Uniformly distributed integers in a given range
+seed Seed the legacy random number generator.
==================== =========================================================
==================== =========================================================
-Univariate distributions
-==============================================================================
+Univariate
+distributions
+-------------------- ---------------------------------------------------------
beta Beta distribution over ``[0, 1]``.
binomial Binomial distribution.
chisquare :math:`\\chi^2` distribution.
@@ -58,17 +93,19 @@ weibull Weibull distribution.
zipf Zipf's distribution over ranked data.
==================== =========================================================
-==================== =========================================================
-Multivariate distributions
-==============================================================================
+==================== ==========================================================
+Multivariate
+distributions
+-------------------- ----------------------------------------------------------
dirichlet Multivariate generalization of Beta distribution.
multinomial Multivariate generalization of the binomial distribution.
multivariate_normal Multivariate generalization of the normal distribution.
-==================== =========================================================
+==================== ==========================================================
==================== =========================================================
-Standard distributions
-==============================================================================
+Standard
+distributions
+-------------------- ---------------------------------------------------------
standard_cauchy Standard Cauchy-Lorentz distribution.
standard_exponential Standard exponential distribution.
standard_gamma Standard Gamma distribution.
@@ -78,16 +115,15 @@ standard_t Standard Student's t-distribution.
==================== =========================================================
Internal functions
-==============================================================================
+-------------------- ---------------------------------------------------------
get_state Get tuple representing internal state of generator.
set_state Set state of generator.
==================== =========================================================
+
"""
from __future__ import division, absolute_import, print_function
-import warnings
-
__all__ = [
'beta',
'binomial',
@@ -119,9 +155,12 @@ __all__ = [
'rand',
'randint',
'randn',
+ 'random',
'random_integers',
'random_sample',
+ 'ranf',
'rayleigh',
+ 'sample',
'seed',
'set_state',
'shuffle',
@@ -135,32 +174,39 @@ __all__ = [
'vonmises',
'wald',
'weibull',
- 'zipf'
+ 'zipf',
]
-with warnings.catch_warnings():
- warnings.filterwarnings("ignore", message="numpy.ndarray size changed")
- from .mtrand import *
+from . import mtrand
+from .mtrand import *
+from .generator import Generator, default_rng
+from .bit_generator import SeedSequence
+from .mt19937 import MT19937
+from .pcg64 import PCG64
+from .philox import Philox
+from .sfc64 import SFC64
+from .mtrand import RandomState
+
+__all__ += ['Generator', 'RandomState', 'SeedSequence', 'MT19937',
+ 'Philox', 'PCG64', 'SFC64', 'default_rng']
-# Some aliases:
-ranf = random = sample = random_sample
-__all__.extend(['ranf', 'random', 'sample'])
def __RandomState_ctor():
"""Return a RandomState instance.
This function exists solely to assist (un)pickling.
- Note that the state of the RandomState returned here is irrelevant, as this function's
- entire purpose is to return a newly allocated RandomState whose state pickle can set.
- Consequently the RandomState returned by this function is a freshly allocated copy
- with a seed=0.
+ Note that the state of the RandomState returned here is irrelevant, as this
+ function's entire purpose is to return a newly allocated RandomState whose
+ state pickle can set. Consequently the RandomState returned by this function
+ is a freshly allocated copy with a seed=0.
See https://github.com/numpy/numpy/issues/4763 for a detailed discussion
"""
return RandomState(seed=0)
+
from numpy._pytesttester import PytestTester
test = PytestTester(__name__)
del PytestTester
diff --git a/numpy/random/_pickle.py b/numpy/random/_pickle.py
new file mode 100644
index 000000000..d20a91ced
--- /dev/null
+++ b/numpy/random/_pickle.py
@@ -0,0 +1,82 @@
+from .mtrand import RandomState
+from .philox import Philox
+from .pcg64 import PCG64
+from .sfc64 import SFC64
+
+from .generator import Generator
+from .mt19937 import MT19937
+
+BitGenerators = {'MT19937': MT19937,
+ 'PCG64': PCG64,
+ 'Philox': Philox,
+ 'SFC64': SFC64,
+ }
+
+
+def __generator_ctor(bit_generator_name='mt19937'):
+ """
+ Pickling helper function that returns a Generator object
+
+ Parameters
+ ----------
+ bit_generator_name: str
+ String containing the core BitGenerator
+
+ Returns
+ -------
+ rg: Generator
+ Generator using the named core BitGenerator
+ """
+ if bit_generator_name in BitGenerators:
+ bit_generator = BitGenerators[bit_generator_name]
+ else:
+ raise ValueError(str(bit_generator_name) + ' is not a known '
+ 'BitGenerator module.')
+
+ return Generator(bit_generator())
+
+
+def __bit_generator_ctor(bit_generator_name='mt19937'):
+ """
+ Pickling helper function that returns a bit generator object
+
+ Parameters
+ ----------
+ bit_generator_name: str
+ String containing the name of the BitGenerator
+
+ Returns
+ -------
+ bit_generator: BitGenerator
+ BitGenerator instance
+ """
+ if bit_generator_name in BitGenerators:
+ bit_generator = BitGenerators[bit_generator_name]
+ else:
+ raise ValueError(str(bit_generator_name) + ' is not a known '
+ 'BitGenerator module.')
+
+ return bit_generator()
+
+
+def __randomstate_ctor(bit_generator_name='mt19937'):
+ """
+ Pickling helper function that returns a legacy RandomState-like object
+
+ Parameters
+ ----------
+ bit_generator_name: str
+ String containing the core BitGenerator
+
+ Returns
+ -------
+ rs: RandomState
+ Legacy RandomState using the named core BitGenerator
+ """
+ if bit_generator_name in BitGenerators:
+ bit_generator = BitGenerators[bit_generator_name]
+ else:
+ raise ValueError(str(bit_generator_name) + ' is not a known '
+ 'BitGenerator module.')
+
+ return RandomState(bit_generator())
diff --git a/numpy/random/bit_generator.pxd b/numpy/random/bit_generator.pxd
new file mode 100644
index 000000000..79fe69275
--- /dev/null
+++ b/numpy/random/bit_generator.pxd
@@ -0,0 +1,26 @@
+
+from .common cimport bitgen_t
+cimport numpy as np
+
+cdef class BitGenerator():
+ cdef readonly object _seed_seq
+ cdef readonly object lock
+ cdef bitgen_t _bitgen
+ cdef readonly object _ctypes
+ cdef readonly object _cffi
+ cdef readonly object capsule
+
+
+cdef class SeedSequence():
+ cdef readonly object entropy
+ cdef readonly tuple spawn_key
+ cdef readonly int pool_size
+ cdef readonly object pool
+ cdef readonly int n_children_spawned
+
+ cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
+ np.ndarray[np.npy_uint32, ndim=1] entropy_array)
+ cdef get_assembled_entropy(self)
+
+cdef class SeedlessSequence():
+ pass
diff --git a/numpy/random/bit_generator.pyx b/numpy/random/bit_generator.pyx
new file mode 100644
index 000000000..6694e5e4d
--- /dev/null
+++ b/numpy/random/bit_generator.pyx
@@ -0,0 +1,627 @@
+"""
+BitGenerator base class and SeedSequence used to seed the BitGenerators.
+
+SeedSequence is derived from Melissa E. O'Neill's C++11 `std::seed_seq`
+implementation, as it has a lot of nice properties that we want.
+
+https://gist.github.com/imneme/540829265469e673d045
+http://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Melissa E. O'Neill
+Copyright (c) 2019 NumPy Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import abc
+import sys
+from itertools import cycle
+import re
+
+try:
+ from secrets import randbits
+except ImportError:
+ # secrets unavailable on python 3.5 and before
+ from random import SystemRandom
+ randbits = SystemRandom().getrandbits
+
+try:
+ from threading import Lock
+except ImportError:
+ from dummy_threading import Lock
+
+from cpython.pycapsule cimport PyCapsule_New
+
+import numpy as np
+cimport numpy as np
+
+from libc.stdint cimport uint32_t
+from .common cimport (random_raw, benchmark, prepare_ctypes, prepare_cffi)
+from .distributions cimport bitgen_t
+
+__all__ = ['SeedSequence', 'BitGenerator']
+
+np.import_array()
+
+DECIMAL_RE = re.compile(r'[0-9]+')
+
+cdef uint32_t DEFAULT_POOL_SIZE = 4 # Appears also in docstring for pool_size
+cdef uint32_t INIT_A = 0x43b0d7e5
+cdef uint32_t MULT_A = 0x931e8875
+cdef uint32_t INIT_B = 0x8b51f9dd
+cdef uint32_t MULT_B = 0x58f38ded
+cdef uint32_t MIX_MULT_L = 0xca01f9dd
+cdef uint32_t MIX_MULT_R = 0x4973f715
+cdef uint32_t XSHIFT = np.dtype(np.uint32).itemsize * 8 // 2
+cdef uint32_t MASK32 = 0xFFFFFFFF
+
+def _int_to_uint32_array(n):
+ arr = []
+ if n < 0:
+ raise ValueError("expected non-negative integer")
+ if n == 0:
+ arr.append(np.uint32(n))
+ if isinstance(n, np.unsignedinteger):
+ # Cannot do n & MASK32, convert to python int
+ n = int(n)
+ while n > 0:
+ arr.append(np.uint32(n & MASK32))
+ n //= (2**32)
+ return np.array(arr, dtype=np.uint32)
+
+def _coerce_to_uint32_array(x):
+ """ Coerce an input to a uint32 array.
+
+ If a `uint32` array, pass it through directly.
+ If a non-negative integer, then break it up into `uint32` words, lowest
+ bits first.
+ If a string starting with "0x", then interpret as a hex integer, as above.
+ If a string of decimal digits, interpret as a decimal integer, as above.
+ If a sequence of ints or strings, interpret each element as above and
+ concatenate.
+
+ Note that the handling of `int64` or `uint64` arrays are not just
+ straightforward views as `uint32` arrays. If an element is small enough to
+ fit into a `uint32`, then it will only take up one `uint32` element in the
+ output. This is to make sure that the interpretation of a sequence of
+ integers is the same regardless of numpy's default integer type, which
+ differs on different platforms.
+
+ Parameters
+ ----------
+ x : int, str, sequence of int or str
+
+ Returns
+ -------
+ seed_array : uint32 array
+
+ Examples
+ --------
+ >>> import numpy as np
+ >>> from np.random.bit_generator import _coerce_to_uint32_array
+ >>> _coerce_to_uint32_array(12345)
+ array([12345], dtype=uint32)
+ >>> _coerce_to_uint32_array('12345')
+ array([12345], dtype=uint32)
+ >>> _coerce_to_uint32_array('0x12345')
+ array([74565], dtype=uint32)
+ >>> _coerce_to_uint32_array([12345, '67890'])
+ array([12345, 67890], dtype=uint32)
+ >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.uint32))
+ array([12345, 67890], dtype=uint32)
+ >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.int64))
+ array([12345, 67890], dtype=uint32)
+ >>> _coerce_to_uint32_array([12345, 0x10deadbeef, 67890, 0xdeadbeef])
+ array([ 12345, 3735928559, 16, 67890, 3735928559],
+ dtype=uint32)
+ >>> _coerce_to_uint32_array(1234567890123456789012345678901234567890)
+ array([3460238034, 2898026390, 3235640248, 2697535605, 3],
+ dtype=uint32)
+ """
+ if isinstance(x, np.ndarray) and x.dtype == np.dtype(np.uint32):
+ return x.copy()
+ elif isinstance(x, str):
+ if x.startswith('0x'):
+ x = int(x, base=16)
+ elif DECIMAL_RE.match(x):
+ x = int(x)
+ else:
+ raise ValueError("unrecognized seed string")
+ if isinstance(x, (int, np.integer)):
+ return _int_to_uint32_array(x)
+ elif isinstance(x, (float, np.inexact)):
+ raise TypeError('seed must be integer')
+ else:
+ if len(x) == 0:
+ return np.array([], dtype=np.uint32)
+ # Should be a sequence of interpretable-as-ints. Convert each one to
+ # a uint32 array and concatenate.
+ subseqs = [_coerce_to_uint32_array(v) for v in x]
+ return np.concatenate(subseqs)
+
+
+cdef uint32_t hashmix(uint32_t value, uint32_t * hash_const):
+ # We are modifying the multiplier as we go along, so it is input-output
+ value ^= hash_const[0]
+ hash_const[0] *= MULT_A
+ value *= hash_const[0]
+ value ^= value >> XSHIFT
+ return value
+
+cdef uint32_t mix(uint32_t x, uint32_t y):
+ cdef uint32_t result = (MIX_MULT_L * x - MIX_MULT_R * y)
+ result ^= result >> XSHIFT
+ return result
+
+
+class ISeedSequence(abc.ABC):
+ """
+ Abstract base class for seed sequences.
+
+ ``BitGenerator`` implementations should treat any object that adheres to
+ this interface as a seed sequence.
+
+ See Also
+ --------
+ SeedSequence, SeedlessSeedSequence
+ """
+
+ @abc.abstractmethod
+ def generate_state(self, n_words, dtype=np.uint32):
+ """
+ generate_state(n_words, dtype=np.uint32)
+
+ Return the requested number of words for PRNG seeding.
+
+ A BitGenerator should call this method in its constructor with
+ an appropriate `n_words` parameter to properly seed itself.
+
+ Parameters
+ ----------
+ n_words : int
+ dtype : np.uint32 or np.uint64, optional
+ The size of each word. This should only be either `uint32` or
+ `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
+ requesting `uint64` will draw twice as many bits as `uint32` for
+ the same `n_words`. This is a convenience for `BitGenerator`s that
+ express their states as `uint64` arrays.
+
+ Returns
+ -------
+ state : uint32 or uint64 array, shape=(n_words,)
+ """
+
+
+class ISpawnableSeedSequence(ISeedSequence):
+ """
+ Abstract base class for seed sequences that can spawn.
+ """
+
+ @abc.abstractmethod
+ def spawn(self, n_children):
+ """
+ spawn(n_children)
+
+ Spawn a number of child `SeedSequence` s by extending the
+ `spawn_key`.
+
+ Parameters
+ ----------
+ n_children : int
+
+ Returns
+ -------
+ seqs : list of `SeedSequence` s
+ """
+
+
+cdef class SeedlessSeedSequence():
+ """
+ A seed sequence for BitGenerators with no need for seed state.
+
+ See Also
+ --------
+ SeedSequence, ISeedSequence
+ """
+
+ def generate_state(self, n_words, dtype=np.uint32):
+ raise NotImplementedError('seedless SeedSequences cannot generate state')
+
+ def spawn(self, n_children):
+ return [self] * n_children
+
+
+# We cannot directly subclass a `cdef class` type from an `ABC` in Cython, so
+# we must register it after the fact.
+ISpawnableSeedSequence.register(SeedlessSeedSequence)
+
+
+cdef class SeedSequence():
+ """
+ SeedSequence(entropy=None, *, spawn_key=(), pool_size=4)
+
+ SeedSequence mixes sources of entropy in a reproducible way to set the
+ initial state for independent and very probably non-overlapping
+ BitGenerators.
+
+ Once the SeedSequence is instantiated, you can call the `generate_state`
+ method to get an appropriately sized seed. Calling `spawn(n) <spawn>` will
+ create ``n`` SeedSequences that can be used to seed independent
+ BitGenerators, i.e. for different threads.
+
+ Parameters
+ ----------
+ entropy : {None, int, sequence[int]}, optional
+ The entropy for creating a `SeedSequence`.
+ spawn_key : {(), sequence[int]}, optional
+ A third source of entropy, used internally when calling
+ `SeedSequence.spawn`
+ pool_size : {int}, optional
+ Size of the pooled entropy to store. Default is 4 to give a 128-bit
+ entropy pool. 8 (for 256 bits) is another reasonable choice if working
+ with larger PRNGs, but there is very little to be gained by selecting
+ another value.
+ n_children_spawned : {int}, optional
+ The number of children already spawned. Only pass this if
+ reconstructing a `SeedSequence` from a serialized form.
+
+ Notes
+ -----
+
+ Best practice for achieving reproducible bit streams is to use
+ the default ``None`` for the initial entropy, and then use
+ `SeedSequence.entropy` to log/pickle the `entropy` for reproducibility:
+
+ >>> sq1 = np.random.SeedSequence()
+ >>> sq1.entropy
+ 243799254704924441050048792905230269161 # random
+ >>> sq2 = np.random.SeedSequence(sq1.entropy)
+ >>> np.all(sq1.generate_state(10) == sq2.generate_state(10))
+ True
+ """
+
+ def __init__(self, entropy=None, *, spawn_key=(),
+ pool_size=DEFAULT_POOL_SIZE, n_children_spawned=0):
+ if pool_size < DEFAULT_POOL_SIZE:
+ raise ValueError("The size of the entropy pool should be at least "
+ f"{DEFAULT_POOL_SIZE}")
+ if entropy is None:
+ entropy = randbits(pool_size * 32)
+ elif not isinstance(entropy, (int, np.integer, list, tuple, range,
+ np.ndarray)):
+ raise TypeError('SeedSequence expects int or sequence of ints for '
+ 'entropy not {}'.format(entropy))
+ self.entropy = entropy
+ self.spawn_key = tuple(spawn_key)
+ self.pool_size = pool_size
+ self.n_children_spawned = n_children_spawned
+
+ self.pool = np.zeros(pool_size, dtype=np.uint32)
+ self.mix_entropy(self.pool, self.get_assembled_entropy())
+
+ def __repr__(self):
+ lines = [
+ f'{type(self).__name__}(',
+ f' entropy={self.entropy!r},',
+ ]
+ # Omit some entries if they are left as the defaults in order to
+ # simplify things.
+ if self.spawn_key:
+ lines.append(f' spawn_key={self.spawn_key!r},')
+ if self.pool_size != DEFAULT_POOL_SIZE:
+ lines.append(f' pool_size={self.pool_size!r},')
+ if self.n_children_spawned != 0:
+ lines.append(f' n_children_spawned={self.n_children_spawned!r},')
+ lines.append(')')
+ text = '\n'.join(lines)
+ return text
+
+ @property
+ def state(self):
+ return {k:getattr(self, k) for k in
+ ['entropy', 'spawn_key', 'pool_size',
+ 'n_children_spawned']
+ if getattr(self, k) is not None}
+
+ cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
+ np.ndarray[np.npy_uint32, ndim=1] entropy_array):
+ """ Mix in the given entropy to mixer.
+
+ Parameters
+ ----------
+ mixer : 1D uint32 array, modified in-place
+ entropy_array : 1D uint32 array
+ """
+ cdef uint32_t hash_const[1]
+ hash_const[0] = INIT_A
+
+ # Add in the entropy up to the pool size.
+ for i in range(len(mixer)):
+ if i < len(entropy_array):
+ mixer[i] = hashmix(entropy_array[i], hash_const)
+ else:
+ # Our pool size is bigger than our entropy, so just keep
+ # running the hash out.
+ mixer[i] = hashmix(0, hash_const)
+
+ # Mix all bits together so late bits can affect earlier bits.
+ for i_src in range(len(mixer)):
+ for i_dst in range(len(mixer)):
+ if i_src != i_dst:
+ mixer[i_dst] = mix(mixer[i_dst],
+ hashmix(mixer[i_src], hash_const))
+
+ # Add any remaining entropy, mixing each new entropy word with each
+ # pool word.
+ for i_src in range(len(mixer), len(entropy_array)):
+ for i_dst in range(len(mixer)):
+ mixer[i_dst] = mix(mixer[i_dst],
+ hashmix(entropy_array[i_src], hash_const))
+
+ cdef get_assembled_entropy(self):
+ """ Convert and assemble all entropy sources into a uniform uint32
+ array.
+
+ Returns
+ -------
+ entropy_array : 1D uint32 array
+ """
+ # Convert run-entropy, program-entropy, and the spawn key into uint32
+ # arrays and concatenate them.
+
+ # We MUST have at least some run-entropy. The others are optional.
+ assert self.entropy is not None
+ run_entropy = _coerce_to_uint32_array(self.entropy)
+ spawn_entropy = _coerce_to_uint32_array(self.spawn_key)
+ entropy_array = np.concatenate([run_entropy, spawn_entropy])
+ return entropy_array
+
+ @np.errstate(over='ignore')
+ def generate_state(self, n_words, dtype=np.uint32):
+ """
+ generate_state(n_words, dtype=np.uint32)
+
+ Return the requested number of words for PRNG seeding.
+
+ A BitGenerator should call this method in its constructor with
+ an appropriate `n_words` parameter to properly seed itself.
+
+ Parameters
+ ----------
+ n_words : int
+ dtype : np.uint32 or np.uint64, optional
+ The size of each word. This should only be either `uint32` or
+ `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
+ requesting `uint64` will draw twice as many bits as `uint32` for
+ the same `n_words`. This is a convenience for `BitGenerator`s that
+ express their states as `uint64` arrays.
+
+ Returns
+ -------
+ state : uint32 or uint64 array, shape=(n_words,)
+ """
+ cdef uint32_t hash_const = INIT_B
+ cdef uint32_t data_val
+
+ out_dtype = np.dtype(dtype)
+ if out_dtype == np.dtype(np.uint32):
+ pass
+ elif out_dtype == np.dtype(np.uint64):
+ n_words *= 2
+ else:
+ raise ValueError("only support uint32 or uint64")
+ state = np.zeros(n_words, dtype=np.uint32)
+ src_cycle = cycle(self.pool)
+ for i_dst in range(n_words):
+ data_val = next(src_cycle)
+ data_val ^= hash_const
+ hash_const *= MULT_B
+ data_val *= hash_const
+ data_val ^= data_val >> XSHIFT
+ state[i_dst] = data_val
+ if out_dtype == np.dtype(np.uint64):
+ # For consistency across different endiannesses, view first as
+ # little-endian then convert the values to the native endianness.
+ state = state.astype('<u4').view('<u8').astype(np.uint64)
+ return state
+
+ def spawn(self, n_children):
+ """
+ spawn(n_children)
+
+ Spawn a number of child `SeedSequence` s by extending the
+ `spawn_key`.
+
+ Parameters
+ ----------
+ n_children : int
+
+ Returns
+ -------
+ seqs : list of `SeedSequence` s
+ """
+ seqs = []
+ for i in range(self.n_children_spawned,
+ self.n_children_spawned + n_children):
+ seqs.append(type(self)(
+ self.entropy,
+ spawn_key=self.spawn_key + (i,),
+ pool_size=self.pool_size,
+ ))
+ self.n_children_spawned += n_children
+ return seqs
+
+
+ISpawnableSeedSequence.register(SeedSequence)
+
+
+cdef class BitGenerator():
+ """
+ BitGenerator(seed=None)
+
+ Base Class for generic BitGenerators, which provide a stream
+ of random bits based on different algorithms. Must be overridden.
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+
+ Attributes
+ ----------
+ lock : threading.Lock
+ Lock instance that is shared so that the same BitGenerator can
+ be used in multiple Generators without corrupting the state. Code that
+ generates values from a bit generator should hold the bit generator's
+ lock.
+
+ See Also
+ -------
+ SeedSequence
+ """
+
+ def __init__(self, seed=None):
+ self.lock = Lock()
+ self._bitgen.state = <void *>0
+ if type(self) is BitGenerator:
+ raise NotImplementedError('BitGenerator is a base class and cannot be instantized')
+
+ self._ctypes = None
+ self._cffi = None
+
+ cdef const char *name = "BitGenerator"
+ self.capsule = PyCapsule_New(<void *>&self._bitgen, name, NULL)
+ if not isinstance(seed, ISeedSequence):
+ seed = SeedSequence(seed)
+ self._seed_seq = seed
+
+ # Pickling support:
+ def __getstate__(self):
+ return self.state
+
+ def __setstate__(self, state):
+ self.state = state
+
+ def __reduce__(self):
+ from ._pickle import __bit_generator_ctor
+ return __bit_generator_ctor, (self.state['bit_generator'],), self.state
+
+ @property
+ def state(self):
+ """
+ Get or set the PRNG state
+
+ The base BitGenerator.state must be overridden by a subclass
+
+ Returns
+ -------
+ state : dict
+ Dictionary containing the information required to describe the
+ state of the PRNG
+ """
+ raise NotImplementedError('Not implemented in base BitGenerator')
+
+ @state.setter
+ def state(self, value):
+ raise NotImplementedError('Not implemented in base BitGenerator')
+
+ def random_raw(self, size=None, output=True):
+ """
+ random_raw(self, size=None)
+
+ Return randoms as generated by the underlying BitGenerator
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ output : bool, optional
+ Output values. Used for performance testing since the generated
+ values are not returned.
+
+ Returns
+ -------
+ out : uint or ndarray
+ Drawn samples.
+
+ Notes
+ -----
+ This method directly exposes the the raw underlying pseudo-random
+ number generator. All values are returned as unsigned 64-bit
+ values irrespective of the number of bits produced by the PRNG.
+
+ See the class docstring for the number of bits returned.
+ """
+ return random_raw(&self._bitgen, self.lock, size, output)
+
+ def _benchmark(self, Py_ssize_t cnt, method=u'uint64'):
+ '''Used in tests'''
+ return benchmark(&self._bitgen, self.lock, cnt, method)
+
+ @property
+ def ctypes(self):
+ """
+ ctypes interface
+
+ Returns
+ -------
+ interface : namedtuple
+ Named tuple containing ctypes wrapper
+
+ * state_address - Memory address of the state struct
+ * state - pointer to the state struct
+ * next_uint64 - function pointer to produce 64 bit integers
+ * next_uint32 - function pointer to produce 32 bit integers
+ * next_double - function pointer to produce doubles
+ * bitgen - pointer to the bit generator struct
+ """
+ if self._ctypes is None:
+ self._ctypes = prepare_ctypes(&self._bitgen)
+
+ return self._ctypes
+
+ @property
+ def cffi(self):
+ """
+ CFFI interface
+
+ Returns
+ -------
+ interface : namedtuple
+ Named tuple containing CFFI wrapper
+
+ * state_address - Memory address of the state struct
+ * state - pointer to the state struct
+ * next_uint64 - function pointer to produce 64 bit integers
+ * next_uint32 - function pointer to produce 32 bit integers
+ * next_double - function pointer to produce doubles
+ * bitgen - pointer to the bit generator struct
+ """
+ if self._cffi is None:
+ self._cffi = prepare_cffi(&self._bitgen)
+ return self._cffi
diff --git a/numpy/random/bounded_integers.pxd.in b/numpy/random/bounded_integers.pxd.in
new file mode 100644
index 000000000..7a3f224dc
--- /dev/null
+++ b/numpy/random/bounded_integers.pxd.in
@@ -0,0 +1,26 @@
+from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
+ int8_t, int16_t, int32_t, int64_t, intptr_t)
+import numpy as np
+cimport numpy as np
+ctypedef np.npy_bool bool_t
+
+from .common cimport bitgen_t
+
+cdef inline uint64_t _gen_mask(uint64_t max_val) nogil:
+ """Mask generator for use in bounded random numbers"""
+ # Smallest bit mask >= max
+ cdef uint64_t mask = max_val
+ mask |= mask >> 1
+ mask |= mask >> 2
+ mask |= mask >> 4
+ mask |= mask >> 8
+ mask |= mask >> 16
+ mask |= mask >> 32
+ return mask
+{{
+py:
+inttypes = ('uint64','uint32','uint16','uint8','bool','int64','int32','int16','int8')
+}}
+{{for inttype in inttypes}}
+cdef object _rand_{{inttype}}(object low, object high, object size, bint use_masked, bint closed, bitgen_t *state, object lock)
+{{endfor}}
diff --git a/numpy/random/bounded_integers.pyx.in b/numpy/random/bounded_integers.pyx.in
new file mode 100644
index 000000000..411b65a37
--- /dev/null
+++ b/numpy/random/bounded_integers.pyx.in
@@ -0,0 +1,305 @@
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True
+
+import numpy as np
+cimport numpy as np
+
+from .distributions cimport *
+
+__all__ = []
+
+np.import_array()
+
+_integers_types = {'bool': (0, 2),
+ 'int8': (-2**7, 2**7),
+ 'int16': (-2**15, 2**15),
+ 'int32': (-2**31, 2**31),
+ 'int64': (-2**63, 2**63),
+ 'uint8': (0, 2**8),
+ 'uint16': (0, 2**16),
+ 'uint32': (0, 2**32),
+ 'uint64': (0, 2**64)}
+{{
+py:
+type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000ULL'),
+ ('uint16', 'uint16', 'uint32', 'NPY_UINT32', 1, 16, 0, '0X10000UL'),
+ ('uint8', 'uint8', 'uint16', 'NPY_UINT16', 3, 8, 0, '0X100UL'),
+ ('bool','bool', 'uint8', 'NPY_UINT8', 31, 1, 0, '0x2UL'),
+ ('int32', 'uint32', 'uint64', 'NPY_INT64', 0, 0, '-0x80000000LL', '0x80000000LL'),
+ ('int16', 'uint16', 'uint32', 'NPY_INT32', 1, 16, '-0x8000LL', '0x8000LL' ),
+ ('int8', 'uint8', 'uint16', 'NPY_INT16', 3, 8, '-0x80LL', '0x80LL' ),
+)}}
+{{for nptype, utype, nptype_up, npctype, remaining, bitshift, lb, ub in type_info}}
+{{ py: otype = nptype + '_' if nptype == 'bool' else nptype }}
+cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size,
+ bint use_masked, bint closed,
+ bitgen_t *state, object lock):
+ """
+ Array path for smaller integer types
+
+ This path is simpler since the high value in the open interval [low, high)
+ must be in-range for the next larger type, {{nptype_up}}. Here we case to
+ this type for checking and the recast to {{nptype}} when producing the
+ random integers.
+ """
+ cdef {{utype}}_t rng, last_rng, off, val, mask, out_val, is_open
+ cdef uint32_t buf
+ cdef {{utype}}_t *out_data
+ cdef {{nptype_up}}_t low_v, high_v
+ cdef np.ndarray low_arr, high_arr, out_arr
+ cdef np.npy_intp i, cnt
+ cdef np.broadcast it
+ cdef int buf_rem = 0
+
+ # Array path
+ is_open = not closed
+ low_arr = <np.ndarray>low
+ high_arr = <np.ndarray>high
+ if np.any(np.less(low_arr, {{lb}})):
+ raise ValueError('low is out of bounds for {{nptype}}')
+ if closed:
+ high_comp = np.greater_equal
+ low_high_comp = np.greater
+ else:
+ high_comp = np.greater
+ low_high_comp = np.greater_equal
+
+ if np.any(high_comp(high_arr, {{ub}})):
+ raise ValueError('high is out of bounds for {{nptype}}')
+ if np.any(low_high_comp(low_arr, high_arr)):
+ comp = '>' if closed else '>='
+ raise ValueError('low {comp} high'.format(comp=comp))
+
+ low_arr = <np.ndarray>np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
+ high_arr = <np.ndarray>np.PyArray_FROM_OTF(high, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
+
+ if size is not None:
+ out_arr = <np.ndarray>np.empty(size, np.{{otype}})
+ else:
+ it = np.PyArray_MultiIterNew2(low_arr, high_arr)
+ out_arr = <np.ndarray>np.empty(it.shape, np.{{otype}})
+
+ it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr)
+ out_data = <{{utype}}_t *>np.PyArray_DATA(out_arr)
+ cnt = np.PyArray_SIZE(out_arr)
+ mask = last_rng = 0
+ with lock, nogil:
+ for i in range(cnt):
+ low_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
+ high_v = (<{{nptype_up}}_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ # Subtract 1 since generator produces values on the closed int [off, off+rng]
+ rng = <{{utype}}_t>((high_v - is_open) - low_v)
+ off = <{{utype}}_t>(<{{nptype_up}}_t>low_v)
+
+ if rng != last_rng:
+ # Smallest bit mask >= max
+ mask = <{{utype}}_t>_gen_mask(rng)
+
+ out_data[i] = random_buffered_bounded_{{utype}}(state, off, rng, mask, use_masked, &buf_rem, &buf)
+
+ np.PyArray_MultiIter_NEXT(it)
+ return out_arr
+{{endfor}}
+{{
+py:
+big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'),
+ ('int64', 'uint64', 'NPY_INT64', '-0x8000000000000000LL', '0x7FFFFFFFFFFFFFFFLL' )
+)}}
+{{for nptype, utype, npctype, lb, ub in big_type_info}}
+{{ py: otype = nptype}}
+cdef object _rand_{{nptype}}_broadcast(object low, object high, object size,
+ bint use_masked, bint closed,
+ bitgen_t *state, object lock):
+ """
+ Array path for 64-bit integer types
+
+ Requires special treatment since the high value can be out-of-range for
+ the largest (64 bit) integer type since the generator is specified on the
+ interval [low,high).
+
+ The internal generator does not have this issue since it generates from
+ the closes interval [low, high-1] and high-1 is always in range for the
+ 64 bit integer type.
+ """
+
+ cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr
+ cdef np.npy_intp i, cnt, n
+ cdef np.broadcast it
+ cdef object closed_upper
+ cdef uint64_t *out_data
+ cdef {{nptype}}_t *highm1_data
+ cdef {{nptype}}_t low_v, high_v
+ cdef uint64_t rng, last_rng, val, mask, off, out_val
+
+ low_arr = <np.ndarray>low
+ high_arr = <np.ndarray>high
+
+ if np.any(np.less(low_arr, {{lb}})):
+ raise ValueError('low is out of bounds for {{nptype}}')
+ dt = high_arr.dtype
+ if closed or np.issubdtype(dt, np.integer):
+ # Avoid object dtype path if already an integer
+ high_lower_comp = np.less if closed else np.less_equal
+ if np.any(high_lower_comp(high_arr, {{lb}})):
+ comp = '>' if closed else '>='
+ raise ValueError('low {comp} high'.format(comp=comp))
+ high_m1 = high_arr if closed else high_arr - dt.type(1)
+ if np.any(np.greater(high_m1, {{ub}})):
+ raise ValueError('high is out of bounds for {{nptype}}')
+ highm1_arr = <np.ndarray>np.PyArray_FROM_OTF(high_m1, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
+ else:
+ # If input is object or a floating type
+ highm1_arr = <np.ndarray>np.empty_like(high_arr, dtype=np.{{nptype}})
+ highm1_data = <{{nptype}}_t *>np.PyArray_DATA(highm1_arr)
+ cnt = np.PyArray_SIZE(high_arr)
+ flat = high_arr.flat
+ for i in range(cnt):
+ # Subtract 1 since generator produces values on the closed int [off, off+rng]
+ closed_upper = int(flat[i]) - 1
+ if closed_upper > {{ub}}:
+ raise ValueError('high is out of bounds for {{nptype}}')
+ if closed_upper < {{lb}}:
+ comp = '>' if closed else '>='
+ raise ValueError('low {comp} high'.format(comp=comp))
+ highm1_data[i] = <{{nptype}}_t>closed_upper
+
+ if np.any(np.greater(low_arr, highm1_arr)):
+ comp = '>' if closed else '>='
+ raise ValueError('low {comp} high'.format(comp=comp))
+
+ high_arr = highm1_arr
+ low_arr = <np.ndarray>np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST)
+
+ if size is not None:
+ out_arr = <np.ndarray>np.empty(size, np.{{nptype}})
+ else:
+ it = np.PyArray_MultiIterNew2(low_arr, high_arr)
+ out_arr = <np.ndarray>np.empty(it.shape, np.{{nptype}})
+
+ it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr)
+ out_data = <uint64_t *>np.PyArray_DATA(out_arr)
+ n = np.PyArray_SIZE(out_arr)
+ mask = last_rng = 0
+ with lock, nogil:
+ for i in range(n):
+ low_v = (<{{nptype}}_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
+ high_v = (<{{nptype}}_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ # Generator produces values on the closed int [off, off+rng], -1 subtracted above
+ rng = <{{utype}}_t>(high_v - low_v)
+ off = <{{utype}}_t>(<{{nptype}}_t>low_v)
+
+ if rng != last_rng:
+ mask = _gen_mask(rng)
+ out_data[i] = random_bounded_uint64(state, off, rng, mask, use_masked)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return out_arr
+{{endfor}}
+{{
+py:
+type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'),
+ ('uint32', 'uint32', '0x0UL', '0XFFFFFFFFUL'),
+ ('uint16', 'uint16', '0x0UL', '0XFFFFUL'),
+ ('uint8', 'uint8', '0x0UL', '0XFFUL'),
+ ('bool', 'bool', '0x0UL', '0x1UL'),
+ ('int64', 'uint64', '-0x8000000000000000LL', '0x7FFFFFFFFFFFFFFFL'),
+ ('int32', 'uint32', '-0x80000000L', '0x7FFFFFFFL'),
+ ('int16', 'uint16', '-0x8000L', '0x7FFFL' ),
+ ('int8', 'uint8', '-0x80L', '0x7FL' )
+)}}
+{{for nptype, utype, lb, ub in type_info}}
+{{ py: otype = nptype + '_' if nptype == 'bool' else nptype }}
+cdef object _rand_{{nptype}}(object low, object high, object size,
+ bint use_masked, bint closed,
+ bitgen_t *state, object lock):
+ """
+ _rand_{{nptype}}(low, high, size, use_masked, *state, lock)
+
+ Return random np.{{nptype}} integers from `low` (inclusive) to `high` (exclusive).
+
+ Return random integers from the "discrete uniform" distribution in the
+ interval [`low`, `high`). If `high` is None (the default),
+ then results are from [0, `low`). On entry the arguments are presumed
+ to have been validated for size and order for the np.{{nptype}} type.
+
+ Parameters
+ ----------
+ low : int or array-like
+ Lowest (signed) integer to be drawn from the distribution (unless
+ ``high=None``, in which case this parameter is the *highest* such
+ integer).
+ high : int or array-like
+ If provided, one above the largest (signed) integer to be drawn from the
+ distribution (see above for behavior if ``high=None``).
+ size : int or tuple of ints
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ use_masked : bool
+ If True then rejection sampling with a range mask is used else Lemire's algorithm is used.
+ closed : bool
+ If True then sample from [low, high]. If False, sample [low, high)
+ state : bit generator
+ Bit generator state to use in the core random number generators
+ lock : threading.Lock
+ Lock to prevent multiple using a single generator simultaneously
+
+ Returns
+ -------
+ out : python scalar or ndarray of np.{{nptype}}
+ `size`-shaped array of random integers from the appropriate
+ distribution, or a single such random int if `size` not provided.
+
+ Notes
+ -----
+ The internal integer generator produces values from the closed
+ interval [low, high-(not closed)]. This requires some care since
+ high can be out-of-range for {{utype}}. The scalar path leaves
+ integers as Python integers until the 1 has been subtracted to
+ avoid needing to cast to a larger type.
+ """
+ cdef np.ndarray out_arr, low_arr, high_arr
+ cdef {{utype}}_t rng, off, out_val
+ cdef {{utype}}_t *out_data
+ cdef np.npy_intp i, n, cnt
+
+ if size is not None:
+ if (np.prod(size) == 0):
+ return np.empty(size, dtype=np.{{nptype}})
+
+ low_arr = <np.ndarray>np.array(low, copy=False)
+ high_arr = <np.ndarray>np.array(high, copy=False)
+ low_ndim = np.PyArray_NDIM(low_arr)
+ high_ndim = np.PyArray_NDIM(high_arr)
+ if ((low_ndim == 0 or (low_ndim == 1 and low_arr.size == 1 and size is not None)) and
+ (high_ndim == 0 or (high_ndim == 1 and high_arr.size == 1 and size is not None))):
+ low = int(low_arr)
+ high = int(high_arr)
+ # Subtract 1 since internal generator produces on closed interval [low, high]
+ if not closed:
+ high -= 1
+
+ if low < {{lb}}:
+ raise ValueError("low is out of bounds for {{nptype}}")
+ if high > {{ub}}:
+ raise ValueError("high is out of bounds for {{nptype}}")
+ if low > high: # -1 already subtracted, closed interval
+ comp = '>' if closed else '>='
+ raise ValueError('low {comp} high'.format(comp=comp))
+
+ rng = <{{utype}}_t>(high - low)
+ off = <{{utype}}_t>(<{{nptype}}_t>low)
+ if size is None:
+ with lock:
+ random_bounded_{{utype}}_fill(state, off, rng, 1, use_masked, &out_val)
+ return np.{{otype}}(<{{nptype}}_t>out_val)
+ else:
+ out_arr = <np.ndarray>np.empty(size, np.{{nptype}})
+ cnt = np.PyArray_SIZE(out_arr)
+ out_data = <{{utype}}_t *>np.PyArray_DATA(out_arr)
+ with lock, nogil:
+ random_bounded_{{utype}}_fill(state, off, rng, cnt, use_masked, out_data)
+ return out_arr
+ return _rand_{{nptype}}_broadcast(low_arr, high_arr, size, use_masked, closed, state, lock)
+{{endfor}}
diff --git a/numpy/random/common.pxd b/numpy/random/common.pxd
new file mode 100644
index 000000000..2f7baa06e
--- /dev/null
+++ b/numpy/random/common.pxd
@@ -0,0 +1,114 @@
+#cython: language_level=3
+
+from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
+ int8_t, int16_t, int32_t, int64_t, intptr_t,
+ uintptr_t)
+from libc.math cimport sqrt
+
+cdef extern from "numpy/random/bitgen.h":
+ 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
+
+ ctypedef bitgen bitgen_t
+
+import numpy as np
+cimport numpy as np
+
+cdef double POISSON_LAM_MAX
+cdef double LEGACY_POISSON_LAM_MAX
+cdef uint64_t MAXSIZE
+
+cdef enum ConstraintType:
+ CONS_NONE
+ CONS_NON_NEGATIVE
+ CONS_POSITIVE
+ CONS_POSITIVE_NOT_NAN
+ CONS_BOUNDED_0_1
+ CONS_BOUNDED_0_1_NOTNAN
+ CONS_BOUNDED_GT_0_1
+ CONS_GT_1
+ CONS_GTE_1
+ CONS_POISSON
+ LEGACY_CONS_POISSON
+
+ctypedef ConstraintType constraint_type
+
+cdef object benchmark(bitgen_t *bitgen, object lock, Py_ssize_t cnt, object method)
+cdef object random_raw(bitgen_t *bitgen, object lock, object size, object output)
+cdef object prepare_cffi(bitgen_t *bitgen)
+cdef object prepare_ctypes(bitgen_t *bitgen)
+cdef int check_constraint(double val, object name, constraint_type cons) except -1
+cdef int check_array_constraint(np.ndarray val, object name, constraint_type cons) except -1
+
+cdef extern from "src/aligned_malloc/aligned_malloc.h":
+ cdef void *PyArray_realloc_aligned(void *p, size_t n)
+ cdef void *PyArray_malloc_aligned(size_t n)
+ cdef void *PyArray_calloc_aligned(size_t n, size_t s)
+ cdef void PyArray_free_aligned(void *p)
+
+ctypedef double (*random_double_fill)(bitgen_t *state, np.npy_intp count, double* out) nogil
+ctypedef double (*random_double_0)(void *state) nogil
+ctypedef double (*random_double_1)(void *state, double a) nogil
+ctypedef double (*random_double_2)(void *state, double a, double b) nogil
+ctypedef double (*random_double_3)(void *state, double a, double b, double c) nogil
+
+ctypedef float (*random_float_0)(bitgen_t *state) nogil
+ctypedef float (*random_float_1)(bitgen_t *state, float a) nogil
+
+ctypedef int64_t (*random_uint_0)(void *state) nogil
+ctypedef int64_t (*random_uint_d)(void *state, double a) nogil
+ctypedef int64_t (*random_uint_dd)(void *state, double a, double b) nogil
+ctypedef int64_t (*random_uint_di)(void *state, double a, uint64_t b) nogil
+ctypedef int64_t (*random_uint_i)(void *state, int64_t a) nogil
+ctypedef int64_t (*random_uint_iii)(void *state, int64_t a, int64_t b, int64_t c) nogil
+
+ctypedef uint32_t (*random_uint_0_32)(bitgen_t *state) nogil
+ctypedef uint32_t (*random_uint_1_i_32)(bitgen_t *state, uint32_t a) nogil
+
+ctypedef int32_t (*random_int_2_i_32)(bitgen_t *state, int32_t a, int32_t b) nogil
+ctypedef int64_t (*random_int_2_i)(bitgen_t *state, int64_t a, int64_t b) nogil
+
+cdef double kahan_sum(double *darr, np.npy_intp n)
+
+cdef inline double uint64_to_double(uint64_t rnd) nogil:
+ return (rnd >> 11) * (1.0 / 9007199254740992.0)
+
+cdef object double_fill(void *func, bitgen_t *state, object size, object lock, object out)
+
+cdef object float_fill(void *func, bitgen_t *state, object size, object lock, object out)
+
+cdef object float_fill_from_double(void *func, bitgen_t *state, object size, object lock, object out)
+
+cdef object wrap_int(object val, object bits)
+
+cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size)
+
+cdef object cont(void *func, void *state, object size, object lock, int narg,
+ object a, object a_name, constraint_type a_constraint,
+ object b, object b_name, constraint_type b_constraint,
+ object c, object c_name, constraint_type c_constraint,
+ object out)
+
+cdef object disc(void *func, void *state, object size, object lock,
+ int narg_double, int narg_int64,
+ object a, object a_name, constraint_type a_constraint,
+ object b, object b_name, constraint_type b_constraint,
+ object c, object c_name, constraint_type c_constraint)
+
+cdef object cont_f(void *func, bitgen_t *state, object size, object lock,
+ object a, object a_name, constraint_type a_constraint,
+ object out)
+
+cdef object cont_broadcast_3(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint,
+ np.ndarray c_arr, object c_name, constraint_type c_constraint)
+
+cdef object discrete_broadcast_iii(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint,
+ np.ndarray c_arr, object c_name, constraint_type c_constraint)
diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx
new file mode 100644
index 000000000..6ad5f5b21
--- /dev/null
+++ b/numpy/random/common.pyx
@@ -0,0 +1,976 @@
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
+from collections import namedtuple
+from cpython cimport PyFloat_AsDouble
+import sys
+import numpy as np
+cimport numpy as np
+
+from .common cimport *
+
+__all__ = ['interface']
+
+np.import_array()
+
+interface = namedtuple('interface', ['state_address', 'state', 'next_uint64',
+ 'next_uint32', 'next_double',
+ 'bit_generator'])
+
+cdef double LEGACY_POISSON_LAM_MAX = <double>np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10
+cdef double POISSON_LAM_MAX = <double>np.iinfo('int64').max - np.sqrt(np.iinfo('int64').max)*10
+
+cdef uint64_t MAXSIZE = <uint64_t>sys.maxsize
+
+
+cdef object benchmark(bitgen_t *bitgen, object lock, Py_ssize_t cnt, object method):
+ """Benchmark command used by BitGenerator"""
+ cdef Py_ssize_t i
+ if method==u'uint64':
+ with lock, nogil:
+ for i in range(cnt):
+ bitgen.next_uint64(bitgen.state)
+ elif method==u'double':
+ with lock, nogil:
+ for i in range(cnt):
+ bitgen.next_double(bitgen.state)
+ else:
+ raise ValueError('Unknown method')
+
+
+cdef object random_raw(bitgen_t *bitgen, object lock, object size, object output):
+ """
+ random_raw(self, size=None)
+
+ Return randoms as generated by the underlying PRNG
+
+ Parameters
+ ----------
+ bitgen : BitGenerator
+ Address of the bit generator struct
+ lock : Threading.Lock
+ Lock provided by the bit generator
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ output : bool, optional
+ Output values. Used for performance testing since the generated
+ values are not returned.
+
+ Returns
+ -------
+ out : uint or ndarray
+ Drawn samples.
+
+ Notes
+ -----
+ This method directly exposes the the raw underlying pseudo-random
+ number generator. All values are returned as unsigned 64-bit
+ values irrespective of the number of bits produced by the PRNG.
+
+ See the class docstring for the number of bits returned.
+ """
+ cdef np.ndarray randoms
+ cdef uint64_t *randoms_data
+ cdef Py_ssize_t i, n
+
+ if not output:
+ if size is None:
+ with lock:
+ bitgen.next_raw(bitgen.state)
+ return None
+ n = np.asarray(size).sum()
+ with lock, nogil:
+ for i in range(n):
+ bitgen.next_raw(bitgen.state)
+ return None
+
+ if size is None:
+ with lock:
+ return bitgen.next_raw(bitgen.state)
+
+ randoms = <np.ndarray>np.empty(size, np.uint64)
+ randoms_data = <uint64_t*>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ with lock, nogil:
+ for i in range(n):
+ randoms_data[i] = bitgen.next_raw(bitgen.state)
+ return randoms
+
+cdef object prepare_cffi(bitgen_t *bitgen):
+ """
+ Bundles the interfaces to interact with a BitGenerator using cffi
+
+ Parameters
+ ----------
+ bitgen : pointer
+ A pointer to a BitGenerator instance
+
+ Returns
+ -------
+ interface : namedtuple
+ The functions required to interface with the BitGenerator using cffi
+
+ * state_address - Memory address of the state struct
+ * state - pointer to the state struct
+ * next_uint64 - function pointer to produce 64 bit integers
+ * next_uint32 - function pointer to produce 32 bit integers
+ * next_double - function pointer to produce doubles
+ * bit_generator - pointer to the BitGenerator struct
+ """
+ try:
+ import cffi
+ except ImportError:
+ raise ImportError('cffi cannot be imported.')
+
+ ffi = cffi.FFI()
+ _cffi = interface(<uintptr_t>bitgen.state,
+ ffi.cast('void *', <uintptr_t>bitgen.state),
+ ffi.cast('uint64_t (*)(void *)', <uintptr_t>bitgen.next_uint64),
+ ffi.cast('uint32_t (*)(void *)', <uintptr_t>bitgen.next_uint32),
+ ffi.cast('double (*)(void *)', <uintptr_t>bitgen.next_double),
+ ffi.cast('void *', <uintptr_t>bitgen))
+ return _cffi
+
+cdef object prepare_ctypes(bitgen_t *bitgen):
+ """
+ Bundles the interfaces to interact with a BitGenerator using ctypes
+
+ Parameters
+ ----------
+ bitgen : pointer
+ A pointer to a BitGenerator instance
+
+ Returns
+ -------
+ interface : namedtuple
+ The functions required to interface with the BitGenerator using ctypes:
+
+ * state_address - Memory address of the state struct
+ * state - pointer to the state struct
+ * next_uint64 - function pointer to produce 64 bit integers
+ * next_uint32 - function pointer to produce 32 bit integers
+ * next_double - function pointer to produce doubles
+ * bit_generator - pointer to the BitGenerator struct
+ """
+ import ctypes
+
+ _ctypes = interface(<uintptr_t>bitgen.state,
+ ctypes.c_void_p(<uintptr_t>bitgen.state),
+ ctypes.cast(<uintptr_t>bitgen.next_uint64,
+ ctypes.CFUNCTYPE(ctypes.c_uint64,
+ ctypes.c_void_p)),
+ ctypes.cast(<uintptr_t>bitgen.next_uint32,
+ ctypes.CFUNCTYPE(ctypes.c_uint32,
+ ctypes.c_void_p)),
+ ctypes.cast(<uintptr_t>bitgen.next_double,
+ ctypes.CFUNCTYPE(ctypes.c_double,
+ ctypes.c_void_p)),
+ ctypes.c_void_p(<uintptr_t>bitgen))
+ return _ctypes
+
+cdef double kahan_sum(double *darr, np.npy_intp n):
+ cdef double c, y, t, sum
+ cdef np.npy_intp i
+ sum = darr[0]
+ c = 0.0
+ for i in range(1, n):
+ y = darr[i] - c
+ t = sum + y
+ c = (t-sum) - y
+ sum = t
+ return sum
+
+
+cdef object wrap_int(object val, object bits):
+ """Wraparound to place an integer into the interval [0, 2**bits)"""
+ mask = ~(~int(0) << bits)
+ return val & mask
+
+
+cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size):
+ """Convert a large integer to an array of unsigned integers"""
+ len = bits // uint_size
+ value = np.asarray(value)
+ if uint_size == 32:
+ dtype = np.uint32
+ elif uint_size == 64:
+ dtype = np.uint64
+ else:
+ raise ValueError('Unknown uint_size')
+ if value.shape == ():
+ value = int(value)
+ upper = int(2)**int(bits)
+ if value < 0 or value >= upper:
+ raise ValueError('{name} must be positive and '
+ 'less than 2**{bits}.'.format(name=name, bits=bits))
+
+ out = np.empty(len, dtype=dtype)
+ for i in range(len):
+ out[i] = value % 2**int(uint_size)
+ value >>= int(uint_size)
+ else:
+ out = value.astype(dtype)
+ if out.shape != (len,):
+ raise ValueError('{name} must have {len} elements when using '
+ 'array form'.format(name=name, len=len))
+ return out
+
+
+cdef check_output(object out, object dtype, object size):
+ if out is None:
+ return
+ cdef np.ndarray out_array = <np.ndarray>out
+ if not (np.PyArray_CHKFLAGS(out_array, np.NPY_CARRAY) or
+ np.PyArray_CHKFLAGS(out_array, np.NPY_FARRAY)):
+ raise ValueError('Supplied output array is not contiguous, writable or aligned.')
+ if out_array.dtype != dtype:
+ raise TypeError('Supplied output array has the wrong type. '
+ 'Expected {0}, got {0}'.format(dtype, out_array.dtype))
+ if size is not None:
+ try:
+ tup_size = tuple(size)
+ except TypeError:
+ tup_size = tuple([size])
+ if tup_size != out.shape:
+ raise ValueError('size must match out.shape when used together')
+
+
+cdef object double_fill(void *func, bitgen_t *state, object size, object lock, object out):
+ cdef random_double_fill random_func = (<random_double_fill>func)
+ cdef double out_val
+ cdef double *out_array_data
+ cdef np.ndarray out_array
+ cdef np.npy_intp i, n
+
+ if size is None and out is None:
+ with lock:
+ random_func(state, 1, &out_val)
+ return out_val
+
+ if out is not None:
+ check_output(out, np.float64, size)
+ out_array = <np.ndarray>out
+ else:
+ out_array = <np.ndarray>np.empty(size, np.double)
+
+ n = np.PyArray_SIZE(out_array)
+ out_array_data = <double *>np.PyArray_DATA(out_array)
+ with lock, nogil:
+ random_func(state, n, out_array_data)
+ return out_array
+
+cdef object float_fill(void *func, bitgen_t *state, object size, object lock, object out):
+ cdef random_float_0 random_func = (<random_float_0>func)
+ cdef float *out_array_data
+ cdef np.ndarray out_array
+ cdef np.npy_intp i, n
+
+ if size is None and out is None:
+ with lock:
+ return random_func(state)
+
+ if out is not None:
+ check_output(out, np.float32, size)
+ out_array = <np.ndarray>out
+ else:
+ out_array = <np.ndarray>np.empty(size, np.float32)
+
+ n = np.PyArray_SIZE(out_array)
+ out_array_data = <float *>np.PyArray_DATA(out_array)
+ with lock, nogil:
+ for i in range(n):
+ out_array_data[i] = random_func(state)
+ return out_array
+
+cdef object float_fill_from_double(void *func, bitgen_t *state, object size, object lock, object out):
+ cdef random_double_0 random_func = (<random_double_0>func)
+ cdef float *out_array_data
+ cdef np.ndarray out_array
+ cdef np.npy_intp i, n
+
+ if size is None and out is None:
+ with lock:
+ return <float>random_func(state)
+
+ if out is not None:
+ check_output(out, np.float32, size)
+ out_array = <np.ndarray>out
+ else:
+ out_array = <np.ndarray>np.empty(size, np.float32)
+
+ n = np.PyArray_SIZE(out_array)
+ out_array_data = <float *>np.PyArray_DATA(out_array)
+ with lock, nogil:
+ for i in range(n):
+ out_array_data[i] = <float>random_func(state)
+ return out_array
+
+
+cdef int check_array_constraint(np.ndarray val, object name, constraint_type cons) except -1:
+ if cons == CONS_NON_NEGATIVE:
+ if np.any(np.logical_and(np.logical_not(np.isnan(val)), np.signbit(val))):
+ raise ValueError(name + " < 0")
+ elif cons == CONS_POSITIVE or cons == CONS_POSITIVE_NOT_NAN:
+ if cons == CONS_POSITIVE_NOT_NAN and np.any(np.isnan(val)):
+ raise ValueError(name + " must not be NaN")
+ elif np.any(np.less_equal(val, 0)):
+ raise ValueError(name + " <= 0")
+ elif cons == CONS_BOUNDED_0_1:
+ if not np.all(np.greater_equal(val, 0)) or \
+ not np.all(np.less_equal(val, 1)):
+ raise ValueError("{0} < 0, {0} > 1 or {0} contains NaNs".format(name))
+ elif cons == CONS_BOUNDED_GT_0_1:
+ if not np.all(np.greater(val, 0)) or not np.all(np.less_equal(val, 1)):
+ raise ValueError("{0} <= 0, {0} > 1 or {0} contains NaNs".format(name))
+ elif cons == CONS_GT_1:
+ if not np.all(np.greater(val, 1)):
+ raise ValueError("{0} <= 1 or {0} contains NaNs".format(name))
+ elif cons == CONS_GTE_1:
+ if not np.all(np.greater_equal(val, 1)):
+ raise ValueError("{0} < 1 or {0} contains NaNs".format(name))
+ elif cons == CONS_POISSON:
+ if not np.all(np.less_equal(val, POISSON_LAM_MAX)):
+ raise ValueError("{0} value too large".format(name))
+ elif not np.all(np.greater_equal(val, 0.0)):
+ raise ValueError("{0} < 0 or {0} contains NaNs".format(name))
+ elif cons == LEGACY_CONS_POISSON:
+ if not np.all(np.less_equal(val, LEGACY_POISSON_LAM_MAX)):
+ raise ValueError("{0} value too large".format(name))
+ elif not np.all(np.greater_equal(val, 0.0)):
+ raise ValueError("{0} < 0 or {0} contains NaNs".format(name))
+
+ return 0
+
+
+cdef int check_constraint(double val, object name, constraint_type cons) except -1:
+ cdef bint is_nan
+ if cons == CONS_NON_NEGATIVE:
+ if not np.isnan(val) and np.signbit(val):
+ raise ValueError(name + " < 0")
+ elif cons == CONS_POSITIVE or cons == CONS_POSITIVE_NOT_NAN:
+ if cons == CONS_POSITIVE_NOT_NAN and np.isnan(val):
+ raise ValueError(name + " must not be NaN")
+ elif val <= 0:
+ raise ValueError(name + " <= 0")
+ elif cons == CONS_BOUNDED_0_1:
+ if not (val >= 0) or not (val <= 1):
+ raise ValueError("{0} < 0, {0} > 1 or {0} is NaN".format(name))
+ elif cons == CONS_BOUNDED_GT_0_1:
+ if not val >0 or not val <= 1:
+ raise ValueError("{0} <= 0, {0} > 1 or {0} contains NaNs".format(name))
+ elif cons == CONS_GT_1:
+ if not (val > 1):
+ raise ValueError("{0} <= 1 or {0} is NaN".format(name))
+ elif cons == CONS_GTE_1:
+ if not (val >= 1):
+ raise ValueError("{0} < 1 or {0} is NaN".format(name))
+ elif cons == CONS_POISSON:
+ if not (val >= 0):
+ raise ValueError("{0} < 0 or {0} is NaN".format(name))
+ elif not (val <= POISSON_LAM_MAX):
+ raise ValueError(name + " value too large")
+ elif cons == LEGACY_CONS_POISSON:
+ if not (val >= 0):
+ raise ValueError("{0} < 0 or {0} is NaN".format(name))
+ elif not (val <= LEGACY_POISSON_LAM_MAX):
+ raise ValueError(name + " value too large")
+
+ return 0
+
+cdef object cont_broadcast_1(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ object out):
+
+ cdef np.ndarray randoms
+ cdef double a_val
+ cdef double *randoms_data
+ cdef np.broadcast it
+ cdef random_double_1 f = (<random_double_1>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if size is not None and out is None:
+ randoms = <np.ndarray>np.empty(size, np.double)
+ elif out is None:
+ randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_DOUBLE)
+ else:
+ randoms = <np.ndarray>out
+
+ randoms_data = <double *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+ it = np.PyArray_MultiIterNew2(randoms, a_arr)
+
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ randoms_data[i] = f(state, a_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object cont_broadcast_2(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint):
+ cdef np.ndarray randoms
+ cdef double a_val, b_val
+ cdef double *randoms_data
+ cdef np.broadcast it
+ cdef random_double_2 f = (<random_double_2>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if b_constraint != CONS_NONE:
+ check_array_constraint(b_arr, b_name, b_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.double)
+ else:
+ it = np.PyArray_MultiIterNew2(a_arr, b_arr)
+ randoms = <np.ndarray>np.empty(it.shape, np.double)
+ # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_DOUBLE)
+
+ randoms_data = <double *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ b_val = (<double*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ randoms_data[i] = f(state, a_val, b_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object cont_broadcast_3(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint,
+ np.ndarray c_arr, object c_name, constraint_type c_constraint):
+ cdef np.ndarray randoms
+ cdef double a_val, b_val, c_val
+ cdef double *randoms_data
+ cdef np.broadcast it
+ cdef random_double_3 f = (<random_double_3>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if b_constraint != CONS_NONE:
+ check_array_constraint(b_arr, b_name, b_constraint)
+
+ if c_constraint != CONS_NONE:
+ check_array_constraint(c_arr, c_name, c_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.double)
+ else:
+ it = np.PyArray_MultiIterNew3(a_arr, b_arr, c_arr)
+ # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_DOUBLE)
+ randoms = <np.ndarray>np.empty(it.shape, np.double)
+
+ randoms_data = <double *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ b_val = (<double*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ c_val = (<double*>np.PyArray_MultiIter_DATA(it, 3))[0]
+ randoms_data[i] = f(state, a_val, b_val, c_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object cont(void *func, void *state, object size, object lock, int narg,
+ object a, object a_name, constraint_type a_constraint,
+ object b, object b_name, constraint_type b_constraint,
+ object c, object c_name, constraint_type c_constraint,
+ object out):
+
+ cdef np.ndarray a_arr, b_arr, c_arr
+ cdef double _a = 0.0, _b = 0.0, _c = 0.0
+ cdef bint is_scalar = True
+ check_output(out, np.float64, size)
+ if narg > 0:
+ a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
+ if narg > 1:
+ b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
+ if narg == 3:
+ c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0
+
+ if not is_scalar:
+ if narg == 1:
+ return cont_broadcast_1(func, state, size, lock,
+ a_arr, a_name, a_constraint,
+ out)
+ elif narg == 2:
+ return cont_broadcast_2(func, state, size, lock,
+ a_arr, a_name, a_constraint,
+ b_arr, b_name, b_constraint)
+ else:
+ return cont_broadcast_3(func, state, size, lock,
+ a_arr, a_name, a_constraint,
+ b_arr, b_name, b_constraint,
+ c_arr, c_name, c_constraint)
+
+ if narg > 0:
+ _a = PyFloat_AsDouble(a)
+ if a_constraint != CONS_NONE and is_scalar:
+ check_constraint(_a, a_name, a_constraint)
+ if narg > 1:
+ _b = PyFloat_AsDouble(b)
+ if b_constraint != CONS_NONE:
+ check_constraint(_b, b_name, b_constraint)
+ if narg == 3:
+ _c = PyFloat_AsDouble(c)
+ if c_constraint != CONS_NONE and is_scalar:
+ check_constraint(_c, c_name, c_constraint)
+
+ if size is None and out is None:
+ with lock:
+ if narg == 0:
+ return (<random_double_0>func)(state)
+ elif narg == 1:
+ return (<random_double_1>func)(state, _a)
+ elif narg == 2:
+ return (<random_double_2>func)(state, _a, _b)
+ elif narg == 3:
+ return (<random_double_3>func)(state, _a, _b, _c)
+
+ cdef np.npy_intp i, n
+ cdef np.ndarray randoms
+ if out is None:
+ randoms = <np.ndarray>np.empty(size)
+ else:
+ randoms = <np.ndarray>out
+ n = np.PyArray_SIZE(randoms)
+
+ cdef double *randoms_data = <double *>np.PyArray_DATA(randoms)
+ cdef random_double_0 f0
+ cdef random_double_1 f1
+ cdef random_double_2 f2
+ cdef random_double_3 f3
+
+ with lock, nogil:
+ if narg == 0:
+ f0 = (<random_double_0>func)
+ for i in range(n):
+ randoms_data[i] = f0(state)
+ elif narg == 1:
+ f1 = (<random_double_1>func)
+ for i in range(n):
+ randoms_data[i] = f1(state, _a)
+ elif narg == 2:
+ f2 = (<random_double_2>func)
+ for i in range(n):
+ randoms_data[i] = f2(state, _a, _b)
+ elif narg == 3:
+ f3 = (<random_double_3>func)
+ for i in range(n):
+ randoms_data[i] = f3(state, _a, _b, _c)
+
+ if out is None:
+ return randoms
+ else:
+ return out
+
+cdef object discrete_broadcast_d(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint):
+
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+ cdef np.broadcast it
+ cdef random_uint_d f = (<random_uint_d>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if size is not None:
+ randoms = np.empty(size, np.int64)
+ else:
+ # randoms = np.empty(np.shape(a_arr), np.double)
+ randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_INT64)
+
+ randoms_data = <int64_t *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ randoms_data[i] = f(state, a_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object discrete_broadcast_dd(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint):
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+ cdef np.broadcast it
+ cdef random_uint_dd f = (<random_uint_dd>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+ if b_constraint != CONS_NONE:
+ check_array_constraint(b_arr, b_name, b_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ else:
+ it = np.PyArray_MultiIterNew2(a_arr, b_arr)
+ randoms = <np.ndarray>np.empty(it.shape, np.int64)
+ # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_INT64)
+
+ randoms_data = <int64_t *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ b_val = (<double*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ randoms_data[i] = f(state, a_val, b_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object discrete_broadcast_di(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint):
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+ cdef np.broadcast it
+ cdef random_uint_di f = (<random_uint_di>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if b_constraint != CONS_NONE:
+ check_array_constraint(b_arr, b_name, b_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ else:
+ it = np.PyArray_MultiIterNew2(a_arr, b_arr)
+ randoms = <np.ndarray>np.empty(it.shape, np.int64)
+
+ randoms_data = <int64_t *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ b_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ (<int64_t*>np.PyArray_MultiIter_DATA(it, 0))[0] = f(state, a_val, b_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object discrete_broadcast_iii(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ np.ndarray b_arr, object b_name, constraint_type b_constraint,
+ np.ndarray c_arr, object c_name, constraint_type c_constraint):
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+ cdef np.broadcast it
+ cdef random_uint_iii f = (<random_uint_iii>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if b_constraint != CONS_NONE:
+ check_array_constraint(b_arr, b_name, b_constraint)
+
+ if c_constraint != CONS_NONE:
+ check_array_constraint(c_arr, c_name, c_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ else:
+ it = np.PyArray_MultiIterNew3(a_arr, b_arr, c_arr)
+ randoms = <np.ndarray>np.empty(it.shape, np.int64)
+
+ randoms_data = <int64_t *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ b_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ c_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 3))[0]
+ randoms_data[i] = f(state, a_val, b_val, c_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object discrete_broadcast_i(void *func, void *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint):
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+ cdef np.broadcast it
+ cdef random_uint_i f = (<random_uint_i>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ else:
+ randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_INT64)
+
+ randoms_data = <int64_t *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew2(randoms, a_arr)
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ randoms_data[i] = f(state, a_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+# Needs double <vec>, double-double <vec>, double-int64_t<vec>, int64_t <vec>, int64_t-int64_t-int64_t
+cdef object disc(void *func, void *state, object size, object lock,
+ int narg_double, int narg_int64,
+ object a, object a_name, constraint_type a_constraint,
+ object b, object b_name, constraint_type b_constraint,
+ object c, object c_name, constraint_type c_constraint):
+
+ cdef double _da = 0, _db = 0
+ cdef int64_t _ia = 0, _ib = 0, _ic = 0
+ cdef bint is_scalar = True
+ if narg_double > 0:
+ a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
+ if narg_double > 1:
+ b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
+ elif narg_int64 == 1:
+ b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_INT64, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
+ else:
+ if narg_int64 > 0:
+ a_arr = <np.ndarray>np.PyArray_FROM_OTF(a, np.NPY_INT64, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0
+ if narg_int64 > 1:
+ b_arr = <np.ndarray>np.PyArray_FROM_OTF(b, np.NPY_INT64, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0
+ if narg_int64 > 2:
+ c_arr = <np.ndarray>np.PyArray_FROM_OTF(c, np.NPY_INT64, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0
+
+ if not is_scalar:
+ if narg_int64 == 0:
+ if narg_double == 1:
+ return discrete_broadcast_d(func, state, size, lock,
+ a_arr, a_name, a_constraint)
+ elif narg_double == 2:
+ return discrete_broadcast_dd(func, state, size, lock,
+ a_arr, a_name, a_constraint,
+ b_arr, b_name, b_constraint)
+ elif narg_int64 == 1:
+ if narg_double == 0:
+ return discrete_broadcast_i(func, state, size, lock,
+ a_arr, a_name, a_constraint)
+ elif narg_double == 1:
+ return discrete_broadcast_di(func, state, size, lock,
+ a_arr, a_name, a_constraint,
+ b_arr, b_name, b_constraint)
+ else:
+ raise NotImplementedError("No vector path available")
+
+ if narg_double > 0:
+ _da = PyFloat_AsDouble(a)
+ if a_constraint != CONS_NONE and is_scalar:
+ check_constraint(_da, a_name, a_constraint)
+
+ if narg_double > 1:
+ _db = PyFloat_AsDouble(b)
+ if b_constraint != CONS_NONE and is_scalar:
+ check_constraint(_db, b_name, b_constraint)
+ elif narg_int64 == 1:
+ _ib = <int64_t>b
+ if b_constraint != CONS_NONE and is_scalar:
+ check_constraint(<double>_ib, b_name, b_constraint)
+ else:
+ if narg_int64 > 0:
+ _ia = <int64_t>a
+ if a_constraint != CONS_NONE and is_scalar:
+ check_constraint(<double>_ia, a_name, a_constraint)
+ if narg_int64 > 1:
+ _ib = <int64_t>b
+ if b_constraint != CONS_NONE and is_scalar:
+ check_constraint(<double>_ib, b_name, b_constraint)
+ if narg_int64 > 2:
+ _ic = <int64_t>c
+ if c_constraint != CONS_NONE and is_scalar:
+ check_constraint(<double>_ic, c_name, c_constraint)
+
+ if size is None:
+ with lock:
+ if narg_int64 == 0:
+ if narg_double == 0:
+ return (<random_uint_0>func)(state)
+ elif narg_double == 1:
+ return (<random_uint_d>func)(state, _da)
+ elif narg_double == 2:
+ return (<random_uint_dd>func)(state, _da, _db)
+ elif narg_int64 == 1:
+ if narg_double == 0:
+ return (<random_uint_i>func)(state, _ia)
+ if narg_double == 1:
+ return (<random_uint_di>func)(state, _da, _ib)
+ else:
+ return (<random_uint_iii>func)(state, _ia, _ib, _ic)
+
+ cdef np.npy_intp i, n
+ cdef np.ndarray randoms = <np.ndarray>np.empty(size, np.int64)
+ cdef np.int64_t *randoms_data
+ cdef random_uint_0 f0
+ cdef random_uint_d fd
+ cdef random_uint_dd fdd
+ cdef random_uint_di fdi
+ cdef random_uint_i fi
+ cdef random_uint_iii fiii
+
+ n = np.PyArray_SIZE(randoms)
+ randoms_data = <np.int64_t *>np.PyArray_DATA(randoms)
+
+ with lock, nogil:
+ if narg_int64 == 0:
+ if narg_double == 0:
+ f0 = (<random_uint_0>func)
+ for i in range(n):
+ randoms_data[i] = f0(state)
+ elif narg_double == 1:
+ fd = (<random_uint_d>func)
+ for i in range(n):
+ randoms_data[i] = fd(state, _da)
+ elif narg_double == 2:
+ fdd = (<random_uint_dd>func)
+ for i in range(n):
+ randoms_data[i] = fdd(state, _da, _db)
+ elif narg_int64 == 1:
+ if narg_double == 0:
+ fi = (<random_uint_i>func)
+ for i in range(n):
+ randoms_data[i] = fi(state, _ia)
+ if narg_double == 1:
+ fdi = (<random_uint_di>func)
+ for i in range(n):
+ randoms_data[i] = fdi(state, _da, _ib)
+ else:
+ fiii = (<random_uint_iii>func)
+ for i in range(n):
+ randoms_data[i] = fiii(state, _ia, _ib, _ic)
+
+ return randoms
+
+
+cdef object cont_broadcast_1_f(void *func, bitgen_t *state, object size, object lock,
+ np.ndarray a_arr, object a_name, constraint_type a_constraint,
+ object out):
+
+ cdef np.ndarray randoms
+ cdef float a_val
+ cdef float *randoms_data
+ cdef np.broadcast it
+ cdef random_float_1 f = (<random_float_1>func)
+ cdef np.npy_intp i, n
+
+ if a_constraint != CONS_NONE:
+ check_array_constraint(a_arr, a_name, a_constraint)
+
+ if size is not None and out is None:
+ randoms = <np.ndarray>np.empty(size, np.float32)
+ elif out is None:
+ randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr),
+ np.PyArray_DIMS(a_arr),
+ np.NPY_FLOAT32)
+ else:
+ randoms = <np.ndarray>out
+
+ randoms_data = <float *>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+ it = np.PyArray_MultiIterNew2(randoms, a_arr)
+
+ with lock, nogil:
+ for i in range(n):
+ a_val = (<float*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ randoms_data[i] = f(state, a_val)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+cdef object cont_f(void *func, bitgen_t *state, object size, object lock,
+ object a, object a_name, constraint_type a_constraint,
+ object out):
+
+ cdef np.ndarray a_arr, b_arr, c_arr
+ cdef float _a
+ cdef bint is_scalar = True
+ cdef int requirements = np.NPY_ALIGNED | np.NPY_FORCECAST
+ check_output(out, np.float32, size)
+ a_arr = <np.ndarray>np.PyArray_FROMANY(a, np.NPY_FLOAT32, 0, 0, requirements)
+ is_scalar = np.PyArray_NDIM(a_arr) == 0
+
+ if not is_scalar:
+ return cont_broadcast_1_f(func, state, size, lock, a_arr, a_name, a_constraint, out)
+
+ _a = <float>PyFloat_AsDouble(a)
+ if a_constraint != CONS_NONE:
+ check_constraint(_a, a_name, a_constraint)
+
+ if size is None and out is None:
+ with lock:
+ return (<random_float_1>func)(state, _a)
+
+ cdef np.npy_intp i, n
+ cdef np.ndarray randoms
+ if out is None:
+ randoms = <np.ndarray>np.empty(size, np.float32)
+ else:
+ randoms = <np.ndarray>out
+ n = np.PyArray_SIZE(randoms)
+
+ cdef float *randoms_data = <float *>np.PyArray_DATA(randoms)
+ cdef random_float_1 f1 = <random_float_1>func
+
+ with lock, nogil:
+ for i in range(n):
+ randoms_data[i] = f1(state, _a)
+
+ if out is None:
+ return randoms
+ else:
+ return out
diff --git a/numpy/random/distributions.pxd b/numpy/random/distributions.pxd
new file mode 100644
index 000000000..75edaee9d
--- /dev/null
+++ b/numpy/random/distributions.pxd
@@ -0,0 +1,140 @@
+#cython: language_level=3
+
+from .common cimport (uint8_t, uint16_t, uint32_t, uint64_t,
+ int32_t, int64_t, bitgen_t)
+import numpy as np
+cimport numpy as np
+
+cdef extern from "src/distributions/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_double(bitgen_t *bitgen_state) nogil
+ void random_double_fill(bitgen_t* bitgen_state, np.npy_intp cnt, double *out) nogil
+ double random_standard_exponential(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
+ double random_gauss_zig(bitgen_t* bitgen_state) nogil
+ void random_gauss_zig_fill(bitgen_t *bitgen_state, np.npy_intp count, double *out) nogil
+ double random_standard_gamma_zig(bitgen_t *bitgen_state, double shape) nogil
+
+ float random_float(bitgen_t *bitgen_state) nogil
+ float random_standard_exponential_f(bitgen_t *bitgen_state) nogil
+ float random_standard_exponential_zig_f(bitgen_t *bitgen_state) nogil
+ float random_gauss_zig_f(bitgen_t* bitgen_state) nogil
+ float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
+ float random_standard_gamma_zig_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_zig(bitgen_t *bitgen_state, double loc, double scale) nogil
+
+ double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
+ float random_gamma_float(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
+
+ # Generate random uint32 numbers in closed interval [off, off + rng].
+ uint32_t random_buffered_bounded_uint32(bitgen_t *bitgen_state,
+ uint32_t off, uint32_t rng,
+ uint32_t mask, bint use_masked,
+ int *bcnt, uint32_t *buf) nogil
+ uint16_t random_buffered_bounded_uint16(bitgen_t *bitgen_state,
+ uint16_t off, uint16_t rng,
+ uint16_t mask, bint use_masked,
+ int *bcnt, uint32_t *buf) nogil
+ uint8_t random_buffered_bounded_uint8(bitgen_t *bitgen_state,
+ uint8_t off, uint8_t rng,
+ uint8_t mask, bint use_masked,
+ int *bcnt, uint32_t *buf) nogil
+ np.npy_bool random_buffered_bounded_bool(bitgen_t *bitgen_state,
+ np.npy_bool off, np.npy_bool rng,
+ np.npy_bool mask, bint use_masked,
+ int *bcnt, uint32_t *buf) nogil
+
+ void random_bounded_uint64_fill(bitgen_t *bitgen_state,
+ uint64_t off, uint64_t rng, np.npy_intp cnt,
+ bint use_masked,
+ uint64_t *out) nogil
+ void random_bounded_uint32_fill(bitgen_t *bitgen_state,
+ uint32_t off, uint32_t rng, np.npy_intp cnt,
+ bint use_masked,
+ uint32_t *out) nogil
+ void random_bounded_uint16_fill(bitgen_t *bitgen_state,
+ uint16_t off, uint16_t rng, np.npy_intp cnt,
+ bint use_masked,
+ uint16_t *out) nogil
+ void random_bounded_uint8_fill(bitgen_t *bitgen_state,
+ uint8_t off, uint8_t rng, np.npy_intp cnt,
+ bint use_masked,
+ uint8_t *out) nogil
+ void random_bounded_bool_fill(bitgen_t *bitgen_state,
+ np.npy_bool off, np.npy_bool rng, np.npy_intp cnt,
+ bint use_masked,
+ np.npy_bool *out) nogil
+
+ void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
+ double *pix, np.npy_intp d, binomial_t *binomial) nogil
diff --git a/numpy/random/entropy.pyx b/numpy/random/entropy.pyx
new file mode 100644
index 000000000..95bf7c177
--- /dev/null
+++ b/numpy/random/entropy.pyx
@@ -0,0 +1,155 @@
+cimport numpy as np
+import numpy as np
+
+from libc.stdint cimport uint32_t, uint64_t
+
+__all__ = ['random_entropy', 'seed_by_array']
+
+np.import_array()
+
+cdef extern from "src/splitmix64/splitmix64.h":
+ cdef uint64_t splitmix64_next(uint64_t *state) nogil
+
+cdef extern from "src/entropy/entropy.h":
+ cdef bint entropy_getbytes(void* dest, size_t size)
+ cdef bint entropy_fallback_getbytes(void *dest, size_t size)
+
+cdef Py_ssize_t compute_numel(size):
+ cdef Py_ssize_t i, n = 1
+ if isinstance(size, tuple):
+ for i in range(len(size)):
+ n *= size[i]
+ else:
+ n = size
+ return n
+
+
+def seed_by_array(object seed, Py_ssize_t n):
+ """
+ Transforms a seed array into an initial state
+
+ Parameters
+ ----------
+ seed: ndarray, 1d, uint64
+ Array to use. If seed is a scalar, promote to array.
+ n : int
+ Number of 64-bit unsigned integers required
+
+ Notes
+ -----
+ Uses splitmix64 to perform the transformation
+ """
+ cdef uint64_t seed_copy = 0
+ cdef uint64_t[::1] seed_array
+ cdef uint64_t[::1] initial_state
+ cdef Py_ssize_t seed_size, iter_bound
+ cdef int i, loc = 0
+
+ if hasattr(seed, 'squeeze'):
+ seed = seed.squeeze()
+ arr = np.asarray(seed)
+ if arr.shape == ():
+ err_msg = 'Scalar seeds must be integers between 0 and 2**64 - 1'
+ if not np.isreal(arr):
+ raise TypeError(err_msg)
+ int_seed = int(seed)
+ if int_seed != seed:
+ raise TypeError(err_msg)
+ if int_seed < 0 or int_seed > 2**64 - 1:
+ raise ValueError(err_msg)
+ seed_array = np.array([int_seed], dtype=np.uint64)
+ elif issubclass(arr.dtype.type, np.inexact):
+ raise TypeError('seed array must be integers')
+ else:
+ err_msg = "Seed values must be integers between 0 and 2**64 - 1"
+ obj = np.asarray(seed).astype(np.object)
+ if obj.ndim != 1:
+ raise ValueError('Array-valued seeds must be 1-dimensional')
+ if not np.isreal(obj).all():
+ raise TypeError(err_msg)
+ if ((obj > int(2**64 - 1)) | (obj < 0)).any():
+ raise ValueError(err_msg)
+ try:
+ obj_int = obj.astype(np.uint64, casting='unsafe')
+ except ValueError:
+ raise ValueError(err_msg)
+ if not (obj == obj_int).all():
+ raise TypeError(err_msg)
+ seed_array = obj_int
+
+ seed_size = seed_array.shape[0]
+ iter_bound = n if n > seed_size else seed_size
+
+ initial_state = <np.ndarray>np.empty(n, dtype=np.uint64)
+ for i in range(iter_bound):
+ if i < seed_size:
+ seed_copy ^= seed_array[i]
+ initial_state[loc] = splitmix64_next(&seed_copy)
+ loc += 1
+ if loc == n:
+ loc = 0
+
+ return np.array(initial_state)
+
+
+def random_entropy(size=None, source='system'):
+ """
+ random_entropy(size=None, source='system')
+
+ Read entropy from the system cryptographic provider
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ source : str {'system', 'fallback'}
+ Source of entropy. 'system' uses system cryptographic pool.
+ 'fallback' uses a hash of the time and process id.
+
+ Returns
+ -------
+ entropy : scalar or array
+ Entropy bits in 32-bit unsigned integers. A scalar is returned if size
+ is `None`.
+
+ Notes
+ -----
+ On Unix-like machines, reads from ``/dev/urandom``. On Windows machines
+ reads from the RSA algorithm provided by the cryptographic service
+ provider.
+
+ This function reads from the system entropy pool and so samples are
+ not reproducible. In particular, it does *NOT* make use of a
+ BitGenerator, and so ``seed`` and setting ``state`` have no
+ effect.
+
+ Raises RuntimeError if the command fails.
+ """
+ cdef bint success = True
+ cdef Py_ssize_t n = 0
+ cdef uint32_t random = 0
+ cdef uint32_t [:] randoms
+
+ if source not in ('system', 'fallback'):
+ raise ValueError('Unknown value in source.')
+
+ if size is None:
+ if source == 'system':
+ success = entropy_getbytes(<void *>&random, 4)
+ else:
+ success = entropy_fallback_getbytes(<void *>&random, 4)
+ else:
+ n = compute_numel(size)
+ randoms = np.zeros(n, dtype=np.uint32)
+ if source == 'system':
+ success = entropy_getbytes(<void *>(&randoms[0]), 4 * n)
+ else:
+ success = entropy_fallback_getbytes(<void *>(&randoms[0]), 4 * n)
+ if not success:
+ raise RuntimeError('Unable to read from system cryptographic provider')
+
+ if n == 0:
+ return random
+ return np.asarray(randoms).reshape(size)
diff --git a/numpy/random/examples/cython/extending.pyx b/numpy/random/examples/cython/extending.pyx
new file mode 100644
index 000000000..a6a4ba4bf
--- /dev/null
+++ b/numpy/random/examples/cython/extending.pyx
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#cython: language_level=3
+
+from libc.stdint cimport uint32_t
+from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
+
+import numpy as np
+cimport numpy as np
+cimport cython
+
+from numpy.random.common cimport bitgen_t
+from numpy.random import PCG64
+
+np.import_array()
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def uniform_mean(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef double[::1] random_values
+ cdef np.ndarray randoms
+
+ x = PCG64()
+ capsule = x.capsule
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ # Best practice is to acquire the lock whenever generating random values.
+ # This prevents other threads from modifying the state. Acquiring the lock
+ # is only necessary if if the GIL is also released, as in this example.
+ with x.lock, nogil:
+ for i in range(n):
+ random_values[i] = rng.next_double(rng.state)
+ randoms = np.asarray(random_values)
+ return randoms.mean()
+
+
+# This function is declated nogil so it can be used without the GIL below
+cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, bitgen_t *rng) nogil:
+ cdef uint32_t mask, delta, val
+ mask = delta = ub - lb
+ mask |= mask >> 1
+ mask |= mask >> 2
+ mask |= mask >> 4
+ mask |= mask >> 8
+ mask |= mask >> 16
+
+ val = rng.next_uint32(rng.state) & mask
+ while val > delta:
+ val = rng.next_uint32(rng.state) & mask
+
+ return lb + val
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef uint32_t[::1] out
+ cdef const char *capsule_name = "BitGenerator"
+
+ x = PCG64()
+ out = np.empty(n, dtype=np.uint32)
+ capsule = x.capsule
+
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ rng = <bitgen_t *>PyCapsule_GetPointer(capsule, capsule_name)
+
+ with x.lock, nogil:
+ for i in range(n):
+ out[i] = bounded_uint(lb, ub, rng)
+ return np.asarray(out)
diff --git a/numpy/random/examples/cython/extending_distributions.pyx b/numpy/random/examples/cython/extending_distributions.pyx
new file mode 100644
index 000000000..3cefec97e
--- /dev/null
+++ b/numpy/random/examples/cython/extending_distributions.pyx
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#cython: language_level=3
+"""
+This file shows how the distributions that are accessed through
+distributions.pxd can be used Cython code.
+"""
+import numpy as np
+cimport numpy as np
+cimport cython
+from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
+from numpy.random.common cimport *
+from numpy.random.distributions cimport random_gauss_zig
+from numpy.random import PCG64
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def normals_zig(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef double[::1] random_values
+
+ x = PCG64()
+ capsule = x.capsule
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ # Best practice is to release GIL and acquire the lock
+ with x.lock, nogil:
+ for i in range(n):
+ random_values[i] = random_gauss_zig(rng)
+ randoms = np.asarray(random_values)
+ return randoms
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def uniforms(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef double[::1] random_values
+
+ x = PCG64()
+ capsule = x.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)
+ random_values = np.empty(n)
+ with x.lock, nogil:
+ for i in range(n):
+ # Call the function
+ random_values[i] = rng.next_double(rng.state)
+ randoms = np.asarray(random_values)
+ return randoms
diff --git a/numpy/random/examples/cython/setup.py b/numpy/random/examples/cython/setup.py
new file mode 100644
index 000000000..69f057ed5
--- /dev/null
+++ b/numpy/random/examples/cython/setup.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+"""
+Build the demos
+
+Usage: python setup.py build_ext -i
+"""
+
+import numpy as np
+from distutils.core import setup
+from Cython.Build import cythonize
+from setuptools.extension import Extension
+from os.path import join
+
+extending = Extension("extending",
+ sources=['extending.pyx'],
+ include_dirs=[np.get_include()])
+distributions = Extension("extending_distributions",
+ sources=['extending_distributions.pyx',
+ join('..', '..', 'src',
+ 'distributions', 'distributions.c')],
+ include_dirs=[np.get_include()])
+
+extensions = [extending, distributions]
+
+setup(
+ ext_modules=cythonize(extensions)
+)
diff --git a/numpy/random/examples/numba/extending.py b/numpy/random/examples/numba/extending.py
new file mode 100644
index 000000000..d41c2d76f
--- /dev/null
+++ b/numpy/random/examples/numba/extending.py
@@ -0,0 +1,77 @@
+import datetime as dt
+
+import numpy as np
+import numba as nb
+
+from numpy.random import PCG64
+
+x = PCG64()
+f = x.ctypes.next_uint32
+s = x.ctypes.state
+
+
+@nb.jit(nopython=True)
+def bounded_uint(lb, ub, state):
+ mask = delta = ub - lb
+ mask |= mask >> 1
+ mask |= mask >> 2
+ mask |= mask >> 4
+ mask |= mask >> 8
+ mask |= mask >> 16
+
+ val = f(state) & mask
+ while val > delta:
+ val = f(state) & mask
+
+ return lb + val
+
+
+print(bounded_uint(323, 2394691, s.value))
+
+
+@nb.jit(nopython=True)
+def bounded_uints(lb, ub, n, state):
+ out = np.empty(n, dtype=np.uint32)
+ for i in range(n):
+ out[i] = bounded_uint(lb, ub, state)
+
+
+bounded_uints(323, 2394691, 10000000, s.value)
+
+g = x.cffi.next_double
+cffi_state = x.cffi.state
+state_addr = x.cffi.state_address
+
+
+def normals(n, state):
+ out = np.empty(n)
+ for i in range((n + 1) // 2):
+ x1 = 2.0 * g(state) - 1.0
+ x2 = 2.0 * g(state) - 1.0
+ r2 = x1 * x1 + x2 * x2
+ while r2 >= 1.0 or r2 == 0.0:
+ x1 = 2.0 * g(state) - 1.0
+ x2 = 2.0 * g(state) - 1.0
+ r2 = x1 * x1 + x2 * x2
+ f = np.sqrt(-2.0 * np.log(r2) / r2)
+ out[2 * i] = f * x1
+ if 2 * i + 1 < n:
+ out[2 * i + 1] = f * x2
+ return out
+
+
+print(normals(10, cffi_state).var())
+# Warm up
+normalsj = nb.jit(normals, nopython=True)
+normalsj(1, state_addr)
+
+start = dt.datetime.now()
+normalsj(1000000, state_addr)
+ms = 1000 * (dt.datetime.now() - start).total_seconds()
+print('1,000,000 Polar-transform (numba/PCG64) randoms in '
+ '{ms:0.1f}ms'.format(ms=ms))
+
+start = dt.datetime.now()
+np.random.standard_normal(1000000)
+ms = 1000 * (dt.datetime.now() - start).total_seconds()
+print('1,000,000 Polar-transform (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms))
diff --git a/numpy/random/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py
new file mode 100644
index 000000000..9233ccced
--- /dev/null
+++ b/numpy/random/examples/numba/extending_distributions.py
@@ -0,0 +1,61 @@
+r"""
+On *nix, execute in randomgen/src/distributions
+
+export PYTHON_INCLUDE=#path to Python's include folder, usually \
+ ${PYTHON_HOME}/include/python${PYTHON_VERSION}m
+export NUMPY_INCLUDE=#path to numpy's include folder, usually \
+ ${PYTHON_HOME}/lib/python${PYTHON_VERSION}/site-packages/numpy/core/include
+gcc -shared -o libdistributions.so -fPIC distributions.c \
+ -I${NUMPY_INCLUDE} -I${PYTHON_INCLUDE}
+mv libdistributions.so ../../examples/numba/
+
+On Windows
+
+rem PYTHON_HOME is setup dependent, this is an example
+set PYTHON_HOME=c:\Anaconda
+cl.exe /LD .\distributions.c -DDLL_EXPORT \
+ -I%PYTHON_HOME%\lib\site-packages\numpy\core\include \
+ -I%PYTHON_HOME%\include %PYTHON_HOME%\libs\python36.lib
+move distributions.dll ../../examples/numba/
+"""
+import os
+
+import numba as nb
+import numpy as np
+from cffi import FFI
+
+from numpy.random import PCG64
+
+ffi = FFI()
+if os.path.exists('./distributions.dll'):
+ lib = ffi.dlopen('./distributions.dll')
+elif os.path.exists('./libdistributions.so'):
+ lib = ffi.dlopen('./libdistributions.so')
+else:
+ raise RuntimeError('Required DLL/so file was not found.')
+
+ffi.cdef("""
+double random_gauss_zig(void *bitgen_state);
+""")
+x = PCG64()
+xffi = x.cffi
+bit_generator = xffi.bit_generator
+
+random_gauss_zig = lib.random_gauss_zig
+
+
+def normals(n, bit_generator):
+ out = np.empty(n)
+ for i in range(n):
+ out[i] = random_gauss_zig(bit_generator)
+ return out
+
+
+normalsj = nb.jit(normals, nopython=True)
+
+# Numba requires a memory address for void *
+# Can also get address from x.ctypes.bit_generator.value
+bit_generator_address = int(ffi.cast('uintptr_t', bit_generator))
+
+norm = normalsj(1000, bit_generator_address)
+print(norm[:12])
diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx
new file mode 100644
index 000000000..c7432d8c1
--- /dev/null
+++ b/numpy/random/generator.pyx
@@ -0,0 +1,4004 @@
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
+import operator
+import warnings
+
+import numpy as np
+
+from .bounded_integers import _integers_types
+from .pcg64 import PCG64
+
+from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
+from cpython cimport (Py_INCREF, PyFloat_AsDouble)
+from libc cimport string
+
+cimport cython
+cimport numpy as np
+
+from .bounded_integers cimport *
+from .common cimport *
+from .distributions cimport *
+
+
+__all__ = ['Generator', 'beta', 'binomial', 'bytes', 'chisquare', 'choice',
+ 'dirichlet', 'exponential', 'f', 'gamma',
+ 'geometric', 'gumbel', 'hypergeometric', 'integers', 'laplace',
+ 'logistic', 'lognormal', 'logseries', 'multinomial',
+ 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare',
+ 'noncentral_f', 'normal', 'pareto', 'permutation',
+ 'poisson', 'power', 'random', 'rayleigh', 'shuffle',
+ 'standard_cauchy', 'standard_exponential', 'standard_gamma',
+ 'standard_normal', 'standard_t', 'triangular',
+ 'uniform', 'vonmises', 'wald', 'weibull', 'zipf']
+
+np.import_array()
+
+
+cdef bint _check_bit_generator(object bitgen):
+ """Check if an object satisfies the BitGenerator interface.
+ """
+ if not hasattr(bitgen, "capsule"):
+ return False
+ cdef const char *name = "BitGenerator"
+ return PyCapsule_IsValid(bitgen.capsule, name)
+
+
+cdef class Generator:
+ """
+ Generator(bit_generator)
+
+ Container for the BitGenerators.
+
+ ``Generator`` exposes a number of methods for generating random
+ numbers drawn from a variety of probability distributions. In addition to
+ the distribution-specific arguments, each method takes a keyword argument
+ `size` that defaults to ``None``. If `size` is ``None``, then a single
+ value is generated and returned. If `size` is an integer, then a 1-D
+ array filled with generated values is returned. If `size` is a tuple,
+ then an array with that shape is filled and returned.
+
+ The function :func:`numpy.random.default_rng` will instantiate
+ a `Generator` with numpy's default `BitGenerator`.
+
+ **No Compatibility Guarantee**
+
+ ``Generator`` does not provide a version compatibility guarantee. In
+ particular, as better algorithms evolve the bit stream may change.
+
+ Parameters
+ ----------
+ bit_generator : BitGenerator
+ BitGenerator to use as the core generator.
+
+ Notes
+ -----
+ The Python stdlib module `random` contains pseudo-random number generator
+ with a number of methods that are similar to the ones available in
+ ``Generator``. It uses Mersenne Twister, and this bit generator can
+ be accessed using ``MT19937``. ``Generator``, besides being
+ NumPy-aware, has the advantage that it provides a much larger number
+ of probability distributions to choose from.
+
+ Examples
+ --------
+ >>> from numpy.random import Generator, PCG64
+ >>> rg = Generator(PCG64())
+ >>> rg.standard_normal()
+ -0.203 # random
+
+ See Also
+ --------
+ default_rng : Recommended constructor for `Generator`.
+ """
+ cdef public object _bit_generator
+ cdef bitgen_t _bitgen
+ cdef binomial_t _binomial
+ cdef object lock
+ _poisson_lam_max = POISSON_LAM_MAX
+
+ def __init__(self, bit_generator):
+ self._bit_generator = bit_generator
+
+ capsule = bit_generator.capsule
+ cdef const char *name = "BitGenerator"
+ if not PyCapsule_IsValid(capsule, name):
+ raise ValueError("Invalid bit generator'. The bit generator must "
+ "be instantiated.")
+ self._bitgen = (<bitgen_t *> PyCapsule_GetPointer(capsule, name))[0]
+ self.lock = bit_generator.lock
+
+ def __repr__(self):
+ return self.__str__() + ' at 0x{:X}'.format(id(self))
+
+ def __str__(self):
+ _str = self.__class__.__name__
+ _str += '(' + self.bit_generator.__class__.__name__ + ')'
+ return _str
+
+ # Pickling support:
+ def __getstate__(self):
+ return self.bit_generator.state
+
+ def __setstate__(self, state):
+ self.bit_generator.state = state
+
+ def __reduce__(self):
+ from ._pickle import __generator_ctor
+ return __generator_ctor, (self.bit_generator.state['bit_generator'],), self.bit_generator.state
+
+ @property
+ def bit_generator(self):
+ """
+ Gets the bit generator instance used by the generator
+
+ Returns
+ -------
+ bit_generator : BitGenerator
+ The bit generator instance used by the generator
+ """
+ return self._bit_generator
+
+ def random(self, size=None, dtype=np.float64, out=None):
+ """
+ random(size=None, dtype='d', out=None)
+
+ Return random floats in the half-open interval [0.0, 1.0).
+
+ Results are from the "continuous uniform" distribution over the
+ stated interval. To sample :math:`Unif[a, b), b > a` multiply
+ the output of `random` by `(b-a)` and add `a`::
+
+ (b - a) * random() + a
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ dtype : {str, dtype}, optional
+ Desired dtype of the result, either 'd' (or 'float64') or 'f'
+ (or 'float32'). All dtypes are determined by their name. The
+ default value is 'd'.
+ out : ndarray, optional
+ Alternative output array in which to place the result. If size is not None,
+ it must have the same shape as the provided size and must match the type of
+ the output values.
+
+ Returns
+ -------
+ out : float or ndarray of floats
+ Array of random floats of shape `size` (unless ``size=None``, in which
+ case a single float is returned).
+
+ Examples
+ --------
+ >>> rng = np.random.default_rng()
+ >>> rng.random()
+ 0.47108547995356098 # random
+ >>> type(rng.random())
+ <class 'float'>
+ >>> rng.random((5,))
+ array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random
+
+ Three-by-two array of random numbers from [-5, 0):
+
+ >>> 5 * rng.random((3, 2)) - 5
+ array([[-3.99149989, -0.52338984], # random
+ [-2.99091858, -0.79479508],
+ [-1.23204345, -1.75224494]])
+
+ """
+ cdef double temp
+ key = np.dtype(dtype).name
+ if key == 'float64':
+ return double_fill(&random_double_fill, &self._bitgen, size, self.lock, out)
+ elif key == 'float32':
+ return float_fill(&random_float, &self._bitgen, size, self.lock, out)
+ else:
+ raise TypeError('Unsupported dtype "%s" for random' % key)
+
+ def beta(self, a, b, size=None):
+ """
+ beta(a, b, size=None)
+
+ Draw samples from a Beta distribution.
+
+ The Beta distribution is a special case of the Dirichlet distribution,
+ and is related to the Gamma distribution. It has the probability
+ distribution function
+
+ .. math:: f(x; a,b) = \\frac{1}{B(\\alpha, \\beta)} x^{\\alpha - 1}
+ (1 - x)^{\\beta - 1},
+
+ where the normalization, B, is the beta function,
+
+ .. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1}
+ (1 - t)^{\\beta - 1} dt.
+
+ It is often seen in Bayesian inference and order statistics.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Alpha, positive (>0).
+ b : float or array_like of floats
+ Beta, positive (>0).
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` and ``b`` are both scalars.
+ Otherwise, ``np.broadcast(a, b).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized beta distribution.
+
+ """
+ return cont(&random_beta, &self._bitgen, size, self.lock, 2,
+ a, 'a', CONS_POSITIVE,
+ b, 'b', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def exponential(self, scale=1.0, size=None):
+ """
+ exponential(scale=1.0, size=None)
+
+ Draw samples from an exponential distribution.
+
+ Its probability density function is
+
+ .. math:: f(x; \\frac{1}{\\beta}) = \\frac{1}{\\beta} \\exp(-\\frac{x}{\\beta}),
+
+ for ``x > 0`` and 0 elsewhere. :math:`\\beta` is the scale parameter,
+ which is the inverse of the rate parameter :math:`\\lambda = 1/\\beta`.
+ The rate parameter is an alternative, widely used parameterization
+ of the exponential distribution [3]_.
+
+ The exponential distribution is a continuous analogue of the
+ geometric distribution. It describes many common situations, such as
+ the size of raindrops measured over many rainstorms [1]_, or the time
+ between page requests to Wikipedia [2]_.
+
+ Parameters
+ ----------
+ scale : float or array_like of floats
+ The scale parameter, :math:`\\beta = 1/\\lambda`. Must be
+ non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``scale`` is a scalar. Otherwise,
+ ``np.array(scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized exponential distribution.
+
+ References
+ ----------
+ .. [1] Peyton Z. Peebles Jr., "Probability, Random Variables and
+ Random Signal Principles", 4th ed, 2001, p. 57.
+ .. [2] Wikipedia, "Poisson process",
+ https://en.wikipedia.org/wiki/Poisson_process
+ .. [3] Wikipedia, "Exponential distribution",
+ https://en.wikipedia.org/wiki/Exponential_distribution
+
+ """
+ return cont(&random_exponential, &self._bitgen, size, self.lock, 1,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ def standard_exponential(self, size=None, dtype=np.float64, method=u'zig', out=None):
+ """
+ standard_exponential(size=None, dtype='d', method='zig', out=None)
+
+ Draw samples from the standard exponential distribution.
+
+ `standard_exponential` is identical to the exponential distribution
+ with a scale parameter of 1.
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ dtype : dtype, optional
+ Desired dtype of the result, either 'd' (or 'float64') or 'f'
+ (or 'float32'). All dtypes are determined by their name. The
+ default value is 'd'.
+ method : str, optional
+ Either 'inv' or 'zig'. 'inv' uses the default inverse CDF method.
+ 'zig' uses the much faster Ziggurat method of Marsaglia and Tsang.
+ out : ndarray, optional
+ Alternative output array in which to place the result. If size is not None,
+ it must have the same shape as the provided size and must match the type of
+ the output values.
+
+ Returns
+ -------
+ out : float or ndarray
+ Drawn samples.
+
+ Examples
+ --------
+ Output a 3x8000 array:
+
+ >>> n = np.random.default_rng().standard_exponential((3, 8000))
+
+ """
+ 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)
+ elif key == 'float32':
+ if method == u'zig':
+ return float_fill(&random_standard_exponential_zig_f, &self._bitgen, size, self.lock, out)
+ else:
+ return float_fill(&random_standard_exponential_f, &self._bitgen, size, self.lock, out)
+ else:
+ raise TypeError('Unsupported dtype "%s" for standard_exponential'
+ % key)
+
+ def integers(self, low, high=None, size=None, dtype=np.int64, endpoint=False):
+ """
+ integers(low, high=None, size=None, dtype='int64', endpoint=False)
+
+ Return random integers from `low` (inclusive) to `high` (exclusive), or
+ if endpoint=True, `low` (inclusive) to `high` (inclusive). Replaces
+ `RandomState.randint` (with endpoint=False) and
+ `RandomState.random_integers` (with endpoint=True)
+
+ Return random integers from the "discrete uniform" distribution of
+ the specified dtype. If `high` is None (the default), then results are
+ from 0 to `low`.
+
+ Parameters
+ ----------
+ low : int or array-like of ints
+ Lowest (signed) integers to be drawn from the distribution (unless
+ ``high=None``, in which case this parameter is 0 and this value is
+ used for `high`).
+ high : int or array-like of ints, optional
+ If provided, one above the largest (signed) integer to be drawn
+ from the distribution (see above for behavior if ``high=None``).
+ If array-like, must contain integer values
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ dtype : {str, dtype}, optional
+ Desired dtype of the result. All dtypes are determined by their
+ name, i.e., 'int64', 'int', etc, so byteorder is not available
+ and a specific precision may have different C types depending
+ on the platform. The default value is 'np.int'.
+ endpoint : bool, optional
+ If true, sample from the interval [low, high] instead of the
+ default [low, high)
+ Defaults to False
+
+ Returns
+ -------
+ out : int or ndarray of ints
+ `size`-shaped array of random integers from the appropriate
+ distribution, or a single such random int if `size` not provided.
+
+ Notes
+ -----
+ When using broadcasting with uint64 dtypes, the maximum value (2**64)
+ cannot be represented as a standard integer type. The high array (or
+ low if high is None) must have object dtype, e.g., array([2**64]).
+
+ Examples
+ --------
+ >>> rng = np.random.default_rng()
+ >>> rng.integers(2, size=10)
+ array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random
+ >>> rng.integers(1, size=10)
+ array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+ Generate a 2 x 4 array of ints between 0 and 4, inclusive:
+
+ >>> rng.integers(5, size=(2, 4))
+ array([[4, 0, 2, 1],
+ [3, 2, 2, 0]]) # random
+
+ Generate a 1 x 3 array with 3 different upper bounds
+
+ >>> rng.integers(1, [3, 5, 10])
+ array([2, 2, 9]) # random
+
+ Generate a 1 by 3 array with 3 different lower bounds
+
+ >>> rng.integers([1, 5, 7], 10)
+ array([9, 8, 7]) # random
+
+ Generate a 2 by 4 array using broadcasting with dtype of uint8
+
+ >>> rng.integers([1, 3, 5, 7], [[10], [20]], dtype=np.uint8)
+ array([[ 8, 6, 9, 7],
+ [ 1, 16, 9, 12]], dtype=uint8) # random
+
+ References
+ ----------
+ .. [1] Daniel Lemire., "Fast Random Integer Generation in an Interval",
+ ACM Transactions on Modeling and Computer Simulation 29 (1), 2019,
+ http://arxiv.org/abs/1805.10941.
+
+ """
+ if high is None:
+ high = low
+ low = 0
+
+ dt = np.dtype(dtype)
+ key = dt.name
+ if key not in _integers_types:
+ raise TypeError('Unsupported dtype "%s" for integers' % key)
+ if not dt.isnative:
+ raise ValueError('Providing a dtype with a non-native byteorder '
+ 'is not supported. If you require '
+ 'platform-independent byteorder, call byteswap '
+ 'when required.')
+
+ # Implementation detail: the old API used a masked method to generate
+ # bounded uniform integers. Lemire's method is preferable since it is
+ # faster. randomgen allows a choice, we will always use the faster one.
+ cdef bint _masked = False
+
+ if key == 'int32':
+ ret = _rand_int32(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'int64':
+ ret = _rand_int64(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'int16':
+ ret = _rand_int16(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'int8':
+ ret = _rand_int8(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'uint64':
+ ret = _rand_uint64(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'uint32':
+ ret = _rand_uint32(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'uint16':
+ ret = _rand_uint16(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'uint8':
+ ret = _rand_uint8(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+ elif key == 'bool':
+ ret = _rand_bool(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
+
+ if size is None and dtype in (np.bool, np.int, np.long):
+ if np.array(ret).shape == ():
+ return dtype(ret)
+ return ret
+
+ def bytes(self, np.npy_intp length):
+ """
+ bytes(length)
+
+ Return random bytes.
+
+ Parameters
+ ----------
+ length : int
+ Number of random bytes.
+
+ Returns
+ -------
+ out : str
+ String of length `length`.
+
+ Examples
+ --------
+ >>> np.random.default_rng().bytes(10)
+ ' eh\\x85\\x022SZ\\xbf\\xa4' #random
+
+ """
+ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1)
+ # Interpret the uint32s as little-endian to convert them to bytes
+ # consistently.
+ return self.integers(0, 4294967296, size=n_uint32,
+ dtype=np.uint32).astype('<u4').tobytes()[:length]
+
+ @cython.wraparound(True)
+ def choice(self, a, size=None, replace=True, p=None, axis=0, bint shuffle=True):
+ """
+ choice(a, size=None, replace=True, p=None, axis=0):
+
+ Generates a random sample from a given 1-D array
+
+ Parameters
+ ----------
+ a : 1-D array-like or int
+ If an ndarray, a random sample is generated from its elements.
+ If an int, the random sample is generated as if a were np.arange(a)
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn from the 1-d `a`. If `a` has more
+ than one dimension, the `size` shape will be inserted into the
+ `axis` dimension, so the output ``ndim`` will be ``a.ndim - 1 +
+ len(size)``. Default is None, in which case a single value is
+ returned.
+ replace : boolean, optional
+ Whether the sample is with or without replacement
+ p : 1-D array-like, optional
+ The probabilities associated with each entry in a.
+ If not given the sample assumes a uniform distribution over all
+ entries in a.
+ axis : int, optional
+ The axis along which the selection is performed. The default, 0,
+ selects by row.
+ shuffle : boolean, optional
+ Whether the sample is shuffled when sampling without replacement.
+ Default is True, False provides a speedup.
+
+ Returns
+ -------
+ samples : single item or ndarray
+ The generated random samples
+
+ Raises
+ ------
+ ValueError
+ If a is an int and less than zero, if p is not 1-dimensional, if
+ a is array-like with a size 0, if p is not a vector of
+ probabilities, if a and p have different lengths, or if
+ replace=False and the sample size is greater than the population
+ size.
+
+ See Also
+ --------
+ integers, shuffle, permutation
+
+ Examples
+ --------
+ Generate a uniform random sample from np.arange(5) of size 3:
+
+ >>> rng = np.random.default_rng()
+ >>> rng.choice(5, 3)
+ array([0, 3, 4]) # random
+ >>> #This is equivalent to rng.integers(0,5,3)
+
+ Generate a non-uniform random sample from np.arange(5) of size 3:
+
+ >>> rng.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0])
+ array([3, 3, 0]) # random
+
+ Generate a uniform random sample from np.arange(5) of size 3 without
+ replacement:
+
+ >>> rng.choice(5, 3, replace=False)
+ array([3,1,0]) # random
+ >>> #This is equivalent to rng.permutation(np.arange(5))[:3]
+
+ Generate a non-uniform random sample from np.arange(5) of size
+ 3 without replacement:
+
+ >>> rng.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0])
+ array([2, 3, 0]) # random
+
+ Any of the above can be repeated with an arbitrary array-like
+ instead of just integers. For instance:
+
+ >>> aa_milne_arr = ['pooh', 'rabbit', 'piglet', 'Christopher']
+ >>> rng.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3])
+ array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random
+ dtype='<U11')
+
+ """
+
+ cdef int64_t val, t, loc, size_i, pop_size_i
+ cdef int64_t *idx_data
+ cdef np.npy_intp j
+ cdef uint64_t set_size, mask
+ cdef uint64_t[::1] hash_set
+ # Format and Verify input
+ a = np.array(a, copy=False)
+ if a.ndim == 0:
+ try:
+ # __index__ must return an integer by python rules.
+ pop_size = operator.index(a.item())
+ except TypeError:
+ raise ValueError("a must be 1-dimensional or an integer")
+ if pop_size <= 0 and np.prod(size) != 0:
+ raise ValueError("a must be greater than 0 unless no samples are taken")
+ else:
+ pop_size = a.shape[axis]
+ if pop_size == 0 and np.prod(size) != 0:
+ raise ValueError("'a' cannot be empty unless no samples are taken")
+
+ if p is not None:
+ d = len(p)
+
+ atol = np.sqrt(np.finfo(np.float64).eps)
+ if isinstance(p, np.ndarray):
+ if np.issubdtype(p.dtype, np.floating):
+ atol = max(atol, np.sqrt(np.finfo(p.dtype).eps))
+
+ p = <np.ndarray>np.PyArray_FROM_OTF(
+ p, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
+ pix = <double*>np.PyArray_DATA(p)
+
+ if p.ndim != 1:
+ raise ValueError("'p' must be 1-dimensional")
+ if p.size != pop_size:
+ raise ValueError("'a' and 'p' must have same size")
+ p_sum = kahan_sum(pix, d)
+ if np.isnan(p_sum):
+ raise ValueError("probabilities contain NaN")
+ if np.logical_or.reduce(p < 0):
+ raise ValueError("probabilities are not non-negative")
+ if abs(p_sum - 1.) > atol:
+ raise ValueError("probabilities do not sum to 1")
+
+ shape = size
+ if shape is not None:
+ size = np.prod(shape, dtype=np.intp)
+ else:
+ size = 1
+
+ # Actual sampling
+ if replace:
+ if p is not None:
+ cdf = p.cumsum()
+ cdf /= cdf[-1]
+ uniform_samples = self.random(shape)
+ idx = cdf.searchsorted(uniform_samples, side='right')
+ idx = np.array(idx, copy=False, dtype=np.int64) # searchsorted returns a scalar
+ else:
+ idx = self.integers(0, pop_size, size=shape, dtype=np.int64)
+ else:
+ if size > pop_size:
+ raise ValueError("Cannot take a larger sample than "
+ "population when 'replace=False'")
+ elif size < 0:
+ raise ValueError("negative dimensions are not allowed")
+
+ if p is not None:
+ if np.count_nonzero(p > 0) < size:
+ raise ValueError("Fewer non-zero entries in p than size")
+ n_uniq = 0
+ p = p.copy()
+ found = np.zeros(shape, dtype=np.int64)
+ flat_found = found.ravel()
+ while n_uniq < size:
+ x = self.random((size - n_uniq,))
+ if n_uniq > 0:
+ p[flat_found[0:n_uniq]] = 0
+ cdf = np.cumsum(p)
+ cdf /= cdf[-1]
+ new = cdf.searchsorted(x, side='right')
+ _, unique_indices = np.unique(new, return_index=True)
+ unique_indices.sort()
+ new = new.take(unique_indices)
+ flat_found[n_uniq:n_uniq + new.size] = new
+ n_uniq += new.size
+ idx = found
+ else:
+ size_i = size
+ pop_size_i = pop_size
+ # This is a heuristic tuning. should be improvable
+ if shuffle:
+ cutoff = 50
+ else:
+ cutoff = 20
+ if pop_size_i > 10000 and (size_i > (pop_size_i // cutoff)):
+ # Tail shuffle size elements
+ idx = np.PyArray_Arange(0, pop_size_i, 1, np.NPY_INT64)
+ idx_data = <int64_t*>(<np.ndarray>idx).data
+ with self.lock, nogil:
+ self._shuffle_int(pop_size_i, max(pop_size_i - size_i, 1),
+ idx_data)
+ # Copy to allow potentially large array backing idx to be gc
+ idx = idx[(pop_size - size):].copy()
+ else:
+ # Floyd's algorithm
+ idx = np.empty(size, dtype=np.int64)
+ idx_data = <int64_t*>np.PyArray_DATA(<np.ndarray>idx)
+ # smallest power of 2 larger than 1.2 * size
+ set_size = <uint64_t>(1.2 * size_i)
+ mask = _gen_mask(set_size)
+ set_size = 1 + mask
+ hash_set = np.full(set_size, <uint64_t>-1, np.uint64)
+ with self.lock, cython.wraparound(False), nogil:
+ for j in range(pop_size_i - size_i, pop_size_i):
+ val = random_bounded_uint64(&self._bitgen, 0, j, 0, 0)
+ loc = val & mask
+ while hash_set[loc] != <uint64_t>-1 and hash_set[loc] != <uint64_t>val:
+ loc = (loc + 1) & mask
+ if hash_set[loc] == <uint64_t>-1: # then val not in hash_set
+ hash_set[loc] = val
+ idx_data[j - pop_size_i + size_i] = val
+ else: # we need to insert j instead
+ loc = j & mask
+ while hash_set[loc] != <uint64_t>-1:
+ loc = (loc + 1) & mask
+ hash_set[loc] = j
+ idx_data[j - pop_size_i + size_i] = j
+ if shuffle:
+ self._shuffle_int(size_i, 1, idx_data)
+ if shape is not None:
+ idx.shape = shape
+
+ if shape is None and isinstance(idx, np.ndarray):
+ # In most cases a scalar will have been made an array
+ idx = idx.item(0)
+
+ # Use samples as indices for a if a is array-like
+ if a.ndim == 0:
+ return idx
+
+ if shape is not None and idx.ndim == 0:
+ # If size == () then the user requested a 0-d array as opposed to
+ # a scalar object when size is None. However a[idx] is always a
+ # scalar and not an array. So this makes sure the result is an
+ # array, taking into account that np.array(item) may not work
+ # for object arrays.
+ res = np.empty((), dtype=a.dtype)
+ res[()] = a[idx]
+ return res
+
+ # asarray downcasts on 32-bit platforms, always safe
+ # no-op on 64-bit platforms
+ return a.take(np.asarray(idx, dtype=np.intp), axis=axis)
+
+ def uniform(self, low=0.0, high=1.0, size=None):
+ """
+ uniform(low=0.0, high=1.0, size=None)
+
+ Draw samples from a uniform distribution.
+
+ Samples are uniformly distributed over the half-open interval
+ ``[low, high)`` (includes low, but excludes high). In other words,
+ any value within the given interval is equally likely to be drawn
+ by `uniform`.
+
+ Parameters
+ ----------
+ low : float or array_like of floats, optional
+ Lower boundary of the output interval. All values generated will be
+ greater than or equal to low. The default value is 0.
+ high : float or array_like of floats
+ Upper boundary of the output interval. All values generated will be
+ less than high. The default value is 1.0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``low`` and ``high`` are both scalars.
+ Otherwise, ``np.broadcast(low, high).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized uniform distribution.
+
+ See Also
+ --------
+ integers : Discrete uniform distribution, yielding integers.
+ random : Floats uniformly distributed over ``[0, 1)``.
+ random : Alias for `random`.
+
+ Notes
+ -----
+ The probability density function of the uniform distribution is
+
+ .. math:: p(x) = \\frac{1}{b - a}
+
+ anywhere within the interval ``[a, b)``, and zero elsewhere.
+
+ When ``high`` == ``low``, values of ``low`` will be returned.
+ If ``high`` < ``low``, the results are officially undefined
+ and may eventually raise an error, i.e. do not rely on this
+ function to behave when passed arguments satisfying that
+ inequality condition.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> s = np.random.default_rng().uniform(-1,0,1000)
+
+ All values are within the given interval:
+
+ >>> np.all(s >= -1)
+ True
+ >>> np.all(s < 0)
+ True
+
+ Display the histogram of the samples, along with the
+ probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 15, density=True)
+ >>> plt.plot(bins, np.ones_like(bins), linewidth=2, color='r')
+ >>> plt.show()
+
+ """
+ cdef bint is_scalar = True
+ cdef np.ndarray alow, ahigh, arange
+ cdef double _low, _high, range
+ cdef object temp
+
+ alow = <np.ndarray>np.PyArray_FROM_OTF(low, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ ahigh = <np.ndarray>np.PyArray_FROM_OTF(high, np.NPY_DOUBLE, np.NPY_ALIGNED)
+
+ if np.PyArray_NDIM(alow) == np.PyArray_NDIM(ahigh) == 0:
+ _low = PyFloat_AsDouble(low)
+ _high = PyFloat_AsDouble(high)
+ range = _high - _low
+ if not np.isfinite(range):
+ raise OverflowError('Range exceeds valid bounds')
+
+ return cont(&random_uniform, &self._bitgen, size, self.lock, 2,
+ _low, '', CONS_NONE,
+ range, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ temp = np.subtract(ahigh, alow)
+ # needed to get around Pyrex's automatic reference-counting
+ # rules because EnsureArray steals a reference
+ Py_INCREF(temp)
+
+ arange = <np.ndarray>np.PyArray_EnsureArray(temp)
+ if not np.all(np.isfinite(arange)):
+ raise OverflowError('Range exceeds valid bounds')
+ return cont(&random_uniform, &self._bitgen, size, self.lock, 2,
+ alow, '', CONS_NONE,
+ arange, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ # Complicated, continuous distributions:
+ def standard_normal(self, size=None, dtype=np.float64, out=None):
+ """
+ standard_normal(size=None, dtype='d', out=None)
+
+ Draw samples from a standard Normal distribution (mean=0, stdev=1).
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+ dtype : {str, dtype}, optional
+ Desired dtype of the result, either 'd' (or 'float64') or 'f'
+ (or 'float32'). All dtypes are determined by their name. The
+ default value is 'd'.
+ out : ndarray, optional
+ Alternative output array in which to place the result. If size is not None,
+ it must have the same shape as the provided size and must match the type of
+ the output values.
+
+ Returns
+ -------
+ out : float or ndarray
+ A floating-point array of shape ``size`` of drawn samples, or a
+ single sample if ``size`` was not specified.
+
+ Notes
+ -----
+ For random samples from :math:`N(\\mu, \\sigma^2)`, use one of::
+
+ mu + sigma * gen.standard_normal(size=...)
+ gen.normal(mu, sigma, size=...)
+
+ See Also
+ --------
+ normal :
+ Equivalent function with additional ``loc`` and ``scale`` arguments
+ for setting the mean and standard deviation.
+
+ Examples
+ --------
+ >>> rng = np.random.default_rng()
+ >>> rng.standard_normal()
+ 2.1923875335537315 #random
+
+ >>> s = rng.standard_normal(8000)
+ >>> s
+ array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, # random
+ -0.38672696, -0.4685006 ]) # random
+ >>> s.shape
+ (8000,)
+ >>> s = rng.standard_normal(size=(3, 4, 2))
+ >>> s.shape
+ (3, 4, 2)
+
+ Two-by-four array of samples from :math:`N(3, 6.25)`:
+
+ >>> 3 + 2.5 * rng.standard_normal(size=(2, 4))
+ array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
+ [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
+
+ """
+ key = np.dtype(dtype).name
+ if key == 'float64':
+ return double_fill(&random_gauss_zig_fill, &self._bitgen, size, self.lock, out)
+ elif key == 'float32':
+ return float_fill(&random_gauss_zig_f, &self._bitgen, size, self.lock, out)
+
+ else:
+ raise TypeError('Unsupported dtype "%s" for standard_normal' % key)
+
+ def normal(self, loc=0.0, scale=1.0, size=None):
+ """
+ normal(loc=0.0, scale=1.0, size=None)
+
+ Draw random samples from a normal (Gaussian) distribution.
+
+ The probability density function of the normal distribution, first
+ derived by De Moivre and 200 years later by both Gauss and Laplace
+ independently [2]_, is often called the bell curve because of
+ its characteristic shape (see the example below).
+
+ The normal distributions occurs often in nature. For example, it
+ describes the commonly occurring distribution of samples influenced
+ by a large number of tiny, random disturbances, each with its own
+ unique distribution [2]_.
+
+ Parameters
+ ----------
+ loc : float or array_like of floats
+ Mean ("centre") of the distribution.
+ scale : float or array_like of floats
+ Standard deviation (spread or "width") of the distribution. Must be
+ non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``loc`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(loc, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized normal distribution.
+
+ See Also
+ --------
+ scipy.stats.norm : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Gaussian distribution is
+
+ .. math:: p(x) = \\frac{1}{\\sqrt{ 2 \\pi \\sigma^2 }}
+ e^{ - \\frac{ (x - \\mu)^2 } {2 \\sigma^2} },
+
+ where :math:`\\mu` is the mean and :math:`\\sigma` the standard
+ deviation. The square of the standard deviation, :math:`\\sigma^2`,
+ is called the variance.
+
+ The function has its peak at the mean, and its "spread" increases with
+ the standard deviation (the function reaches 0.607 times its maximum at
+ :math:`x + \\sigma` and :math:`x - \\sigma` [2]_). This implies that
+ :meth:`normal` is more likely to return samples lying close to the
+ mean, rather than those far away.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Normal distribution",
+ https://en.wikipedia.org/wiki/Normal_distribution
+ .. [2] P. R. Peebles Jr., "Central Limit Theorem" in "Probability,
+ Random Variables and Random Signal Principles", 4th ed., 2001,
+ pp. 51, 51, 125.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> mu, sigma = 0, 0.1 # mean and standard deviation
+ >>> s = np.random.default_rng().normal(mu, sigma, 1000)
+
+ Verify the mean and the variance:
+
+ >>> abs(mu - np.mean(s))
+ 0.0 # may vary
+
+ >>> abs(sigma - np.std(s, ddof=1))
+ 0.1 # may vary
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 30, density=True)
+ >>> plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *
+ ... np.exp( - (bins - mu)**2 / (2 * sigma**2) ),
+ ... linewidth=2, color='r')
+ >>> plt.show()
+
+ Two-by-four array of samples from N(3, 6.25):
+
+ >>> np.random.default_rng().normal(3, 2.5, size=(2, 4))
+ array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
+ [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
+
+ """
+ return cont(&random_normal_zig, &self._bitgen, size, self.lock, 2,
+ loc, '', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ def standard_gamma(self, shape, size=None, dtype=np.float64, out=None):
+ """
+ standard_gamma(shape, size=None, dtype='d', out=None)
+
+ Draw samples from a standard Gamma distribution.
+
+ Samples are drawn from a Gamma distribution with specified parameters,
+ shape (sometimes designated "k") and scale=1.
+
+ Parameters
+ ----------
+ shape : float or array_like of floats
+ Parameter, must be non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``shape`` is a scalar. Otherwise,
+ ``np.array(shape).size`` samples are drawn.
+ dtype : {str, dtype}, optional
+ Desired dtype of the result, either 'd' (or 'float64') or 'f'
+ (or 'float32'). All dtypes are determined by their name. The
+ default value is 'd'.
+ out : ndarray, optional
+ Alternative output array in which to place the result. If size is
+ not None, it must have the same shape as the provided size and
+ must match the type of the output values.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized standard gamma distribution.
+
+ See Also
+ --------
+ scipy.stats.gamma : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Gamma distribution is
+
+ .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)},
+
+ where :math:`k` is the shape and :math:`\\theta` the scale,
+ and :math:`\\Gamma` is the Gamma function.
+
+ The Gamma distribution is often used to model the times to failure of
+ electronic components, and arises naturally in processes for which the
+ waiting times between Poisson distributed events are relevant.
+
+ References
+ ----------
+ .. [1] Weisstein, Eric W. "Gamma Distribution." From MathWorld--A
+ Wolfram Web Resource.
+ http://mathworld.wolfram.com/GammaDistribution.html
+ .. [2] Wikipedia, "Gamma distribution",
+ https://en.wikipedia.org/wiki/Gamma_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> shape, scale = 2., 1. # mean and width
+ >>> s = np.random.default_rng().standard_gamma(shape, 1000000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> import scipy.special as sps # doctest: +SKIP
+ >>> count, bins, ignored = plt.hist(s, 50, density=True)
+ >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ # doctest: +SKIP
+ ... (sps.gamma(shape) * scale**shape))
+ >>> plt.plot(bins, y, linewidth=2, color='r') # doctest: +SKIP
+ >>> plt.show()
+
+ """
+ cdef void *func
+ key = np.dtype(dtype).name
+ if key == 'float64':
+ return cont(&random_standard_gamma_zig, &self._bitgen, size, self.lock, 1,
+ shape, 'shape', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ out)
+ if key == 'float32':
+ return cont_f(&random_standard_gamma_zig_f, &self._bitgen, size, self.lock,
+ shape, 'shape', CONS_NON_NEGATIVE,
+ out)
+ else:
+ raise TypeError('Unsupported dtype "%s" for standard_gamma' % key)
+
+ def gamma(self, shape, scale=1.0, size=None):
+ """
+ gamma(shape, scale=1.0, size=None)
+
+ Draw samples from a Gamma distribution.
+
+ Samples are drawn from a Gamma distribution with specified parameters,
+ `shape` (sometimes designated "k") and `scale` (sometimes designated
+ "theta"), where both parameters are > 0.
+
+ Parameters
+ ----------
+ shape : float or array_like of floats
+ The shape of the gamma distribution. Must be non-negative.
+ scale : float or array_like of floats, optional
+ The scale of the gamma distribution. Must be non-negative.
+ Default is equal to 1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``shape`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(shape, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized gamma distribution.
+
+ See Also
+ --------
+ scipy.stats.gamma : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Gamma distribution is
+
+ .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)},
+
+ where :math:`k` is the shape and :math:`\\theta` the scale,
+ and :math:`\\Gamma` is the Gamma function.
+
+ The Gamma distribution is often used to model the times to failure of
+ electronic components, and arises naturally in processes for which the
+ waiting times between Poisson distributed events are relevant.
+
+ References
+ ----------
+ .. [1] Weisstein, Eric W. "Gamma Distribution." From MathWorld--A
+ Wolfram Web Resource.
+ http://mathworld.wolfram.com/GammaDistribution.html
+ .. [2] Wikipedia, "Gamma distribution",
+ https://en.wikipedia.org/wiki/Gamma_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> shape, scale = 2., 2. # mean=4, std=2*sqrt(2)
+ >>> s = np.random.default_rng().gamma(shape, scale, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> import scipy.special as sps # doctest: +SKIP
+ >>> count, bins, ignored = plt.hist(s, 50, density=True)
+ >>> y = bins**(shape-1)*(np.exp(-bins/scale) / # doctest: +SKIP
+ ... (sps.gamma(shape)*scale**shape))
+ >>> plt.plot(bins, y, linewidth=2, color='r') # doctest: +SKIP
+ >>> plt.show()
+
+ """
+ return cont(&random_gamma, &self._bitgen, size, self.lock, 2,
+ shape, 'shape', CONS_NON_NEGATIVE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def f(self, dfnum, dfden, size=None):
+ """
+ f(dfnum, dfden, size=None)
+
+ Draw samples from an F distribution.
+
+ Samples are drawn from an F distribution with specified parameters,
+ `dfnum` (degrees of freedom in numerator) and `dfden` (degrees of
+ freedom in denominator), where both parameters must be greater than
+ zero.
+
+ The random variate of the F distribution (also known as the
+ Fisher distribution) is a continuous probability distribution
+ that arises in ANOVA tests, and is the ratio of two chi-square
+ variates.
+
+ Parameters
+ ----------
+ dfnum : float or array_like of floats
+ Degrees of freedom in numerator, must be > 0.
+ dfden : float or array_like of float
+ Degrees of freedom in denominator, must be > 0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``dfnum`` and ``dfden`` are both scalars.
+ Otherwise, ``np.broadcast(dfnum, dfden).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Fisher distribution.
+
+ See Also
+ --------
+ scipy.stats.f : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The F statistic is used to compare in-group variances to between-group
+ variances. Calculating the distribution depends on the sampling, and
+ so it is a function of the respective degrees of freedom in the
+ problem. The variable `dfnum` is the number of samples minus one, the
+ between-groups degrees of freedom, while `dfden` is the within-groups
+ degrees of freedom, the sum of the number of samples in each group
+ minus the number of groups.
+
+ References
+ ----------
+ .. [1] Glantz, Stanton A. "Primer of Biostatistics.", McGraw-Hill,
+ Fifth Edition, 2002.
+ .. [2] Wikipedia, "F-distribution",
+ https://en.wikipedia.org/wiki/F-distribution
+
+ Examples
+ --------
+ An example from Glantz[1], pp 47-40:
+
+ Two groups, children of diabetics (25 people) and children from people
+ without diabetes (25 controls). Fasting blood glucose was measured,
+ case group had a mean value of 86.1, controls had a mean value of
+ 82.2. Standard deviations were 2.09 and 2.49 respectively. Are these
+ data consistent with the null hypothesis that the parents diabetic
+ status does not affect their children's blood glucose levels?
+ Calculating the F statistic from the data gives a value of 36.01.
+
+ Draw samples from the distribution:
+
+ >>> dfnum = 1. # between group degrees of freedom
+ >>> dfden = 48. # within groups degrees of freedom
+ >>> s = np.random.default_rng().f(dfnum, dfden, 1000)
+
+ The lower bound for the top 1% of the samples is :
+
+ >>> np.sort(s)[-10]
+ 7.61988120985 # random
+
+ So there is about a 1% chance that the F statistic will exceed 7.62,
+ the measured value is 36, so the null hypothesis is rejected at the 1%
+ level.
+
+ """
+ return cont(&random_f, &self._bitgen, size, self.lock, 2,
+ dfnum, 'dfnum', CONS_POSITIVE,
+ dfden, 'dfden', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def noncentral_f(self, dfnum, dfden, nonc, size=None):
+ """
+ noncentral_f(dfnum, dfden, nonc, size=None)
+
+ Draw samples from the noncentral F distribution.
+
+ Samples are drawn from an F distribution with specified parameters,
+ `dfnum` (degrees of freedom in numerator) and `dfden` (degrees of
+ freedom in denominator), where both parameters > 1.
+ `nonc` is the non-centrality parameter.
+
+ Parameters
+ ----------
+ dfnum : float or array_like of floats
+ Numerator degrees of freedom, must be > 0.
+
+ .. versionchanged:: 1.14.0
+ Earlier NumPy versions required dfnum > 1.
+ dfden : float or array_like of floats
+ Denominator degrees of freedom, must be > 0.
+ nonc : float or array_like of floats
+ Non-centrality parameter, the sum of the squares of the numerator
+ means, must be >= 0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``dfnum``, ``dfden``, and ``nonc``
+ are all scalars. Otherwise, ``np.broadcast(dfnum, dfden, nonc).size``
+ samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized noncentral Fisher distribution.
+
+ Notes
+ -----
+ When calculating the power of an experiment (power = probability of
+ rejecting the null hypothesis when a specific alternative is true) the
+ non-central F statistic becomes important. When the null hypothesis is
+ true, the F statistic follows a central F distribution. When the null
+ hypothesis is not true, then it follows a non-central F statistic.
+
+ References
+ ----------
+ .. [1] Weisstein, Eric W. "Noncentral F-Distribution."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/NoncentralF-Distribution.html
+ .. [2] Wikipedia, "Noncentral F-distribution",
+ https://en.wikipedia.org/wiki/Noncentral_F-distribution
+
+ Examples
+ --------
+ In a study, testing for a specific alternative to the null hypothesis
+ requires use of the Noncentral F distribution. We need to calculate the
+ area in the tail of the distribution that exceeds the value of the F
+ distribution for the null hypothesis. We'll plot the two probability
+ distributions for comparison.
+
+ >>> rng = np.random.default_rng()
+ >>> dfnum = 3 # between group deg of freedom
+ >>> dfden = 20 # within groups degrees of freedom
+ >>> nonc = 3.0
+ >>> nc_vals = rng.noncentral_f(dfnum, dfden, nonc, 1000000)
+ >>> NF = np.histogram(nc_vals, bins=50, density=True)
+ >>> c_vals = rng.f(dfnum, dfden, 1000000)
+ >>> F = np.histogram(c_vals, bins=50, density=True)
+ >>> import matplotlib.pyplot as plt
+ >>> plt.plot(F[1][1:], F[0])
+ >>> plt.plot(NF[1][1:], NF[0])
+ >>> plt.show()
+
+ """
+ return cont(&random_noncentral_f, &self._bitgen, size, self.lock, 3,
+ dfnum, 'dfnum', CONS_POSITIVE,
+ dfden, 'dfden', CONS_POSITIVE,
+ nonc, 'nonc', CONS_NON_NEGATIVE, None)
+
+ def chisquare(self, df, size=None):
+ """
+ chisquare(df, size=None)
+
+ Draw samples from a chi-square distribution.
+
+ When `df` independent random variables, each with standard normal
+ distributions (mean 0, variance 1), are squared and summed, the
+ resulting distribution is chi-square (see Notes). This distribution
+ is often used in hypothesis testing.
+
+ Parameters
+ ----------
+ df : float or array_like of floats
+ Number of degrees of freedom, must be > 0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``df`` is a scalar. Otherwise,
+ ``np.array(df).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized chi-square distribution.
+
+ Raises
+ ------
+ ValueError
+ When `df` <= 0 or when an inappropriate `size` (e.g. ``size=-1``)
+ is given.
+
+ Notes
+ -----
+ The variable obtained by summing the squares of `df` independent,
+ standard normally distributed random variables:
+
+ .. math:: Q = \\sum_{i=0}^{\\mathtt{df}} X^2_i
+
+ is chi-square distributed, denoted
+
+ .. math:: Q \\sim \\chi^2_k.
+
+ The probability density function of the chi-squared distribution is
+
+ .. math:: p(x) = \\frac{(1/2)^{k/2}}{\\Gamma(k/2)}
+ x^{k/2 - 1} e^{-x/2},
+
+ where :math:`\\Gamma` is the gamma function,
+
+ .. math:: \\Gamma(x) = \\int_0^{-\\infty} t^{x - 1} e^{-t} dt.
+
+ References
+ ----------
+ .. [1] NIST "Engineering Statistics Handbook"
+ https://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm
+
+ Examples
+ --------
+ >>> np.random.default_rng().chisquare(2,4)
+ array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random
+
+ """
+ return cont(&random_chisquare, &self._bitgen, size, self.lock, 1,
+ df, 'df', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
+
+ def noncentral_chisquare(self, df, nonc, size=None):
+ """
+ noncentral_chisquare(df, nonc, size=None)
+
+ Draw samples from a noncentral chi-square distribution.
+
+ The noncentral :math:`\\chi^2` distribution is a generalization of
+ the :math:`\\chi^2` distribution.
+
+ Parameters
+ ----------
+ df : float or array_like of floats
+ Degrees of freedom, must be > 0.
+
+ .. versionchanged:: 1.10.0
+ Earlier NumPy versions required dfnum > 1.
+ nonc : float or array_like of floats
+ Non-centrality, must be non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``df`` and ``nonc`` are both scalars.
+ Otherwise, ``np.broadcast(df, nonc).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized noncentral chi-square distribution.
+
+ Notes
+ -----
+ The probability density function for the noncentral Chi-square
+ distribution is
+
+ .. math:: P(x;df,nonc) = \\sum^{\\infty}_{i=0}
+ \\frac{e^{-nonc/2}(nonc/2)^{i}}{i!}
+ P_{Y_{df+2i}}(x),
+
+ where :math:`Y_{q}` is the Chi-square with q degrees of freedom.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Noncentral chi-squared distribution"
+ https://en.wikipedia.org/wiki/Noncentral_chi-squared_distribution
+
+ Examples
+ --------
+ Draw values from the distribution and plot the histogram
+
+ >>> rng = np.random.default_rng()
+ >>> import matplotlib.pyplot as plt
+ >>> values = plt.hist(rng.noncentral_chisquare(3, 20, 100000),
+ ... bins=200, density=True)
+ >>> plt.show()
+
+ Draw values from a noncentral chisquare with very small noncentrality,
+ and compare to a chisquare.
+
+ >>> plt.figure()
+ >>> values = plt.hist(rng.noncentral_chisquare(3, .0000001, 100000),
+ ... bins=np.arange(0., 25, .1), density=True)
+ >>> values2 = plt.hist(rng.chisquare(3, 100000),
+ ... bins=np.arange(0., 25, .1), density=True)
+ >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob')
+ >>> plt.show()
+
+ Demonstrate how large values of non-centrality lead to a more symmetric
+ distribution.
+
+ >>> plt.figure()
+ >>> values = plt.hist(rng.noncentral_chisquare(3, 20, 100000),
+ ... bins=200, density=True)
+ >>> plt.show()
+
+ """
+ return cont(&random_noncentral_chisquare, &self._bitgen, size, self.lock, 2,
+ df, 'df', CONS_POSITIVE,
+ nonc, 'nonc', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def standard_cauchy(self, size=None):
+ """
+ standard_cauchy(size=None)
+
+ Draw samples from a standard Cauchy distribution with mode = 0.
+
+ Also known as the Lorentz distribution.
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+
+ Returns
+ -------
+ samples : ndarray or scalar
+ The drawn samples.
+
+ Notes
+ -----
+ The probability density function for the full Cauchy distribution is
+
+ .. math:: P(x; x_0, \\gamma) = \\frac{1}{\\pi \\gamma \\bigl[ 1+
+ (\\frac{x-x_0}{\\gamma})^2 \\bigr] }
+
+ and the Standard Cauchy distribution just sets :math:`x_0=0` and
+ :math:`\\gamma=1`
+
+ The Cauchy distribution arises in the solution to the driven harmonic
+ oscillator problem, and also describes spectral line broadening. It
+ also describes the distribution of values at which a line tilted at
+ a random angle will cut the x axis.
+
+ When studying hypothesis tests that assume normality, seeing how the
+ tests perform on data from a Cauchy distribution is a good indicator of
+ their sensitivity to a heavy-tailed distribution, since the Cauchy looks
+ very much like a Gaussian distribution, but with heavier tails.
+
+ References
+ ----------
+ .. [1] NIST/SEMATECH e-Handbook of Statistical Methods, "Cauchy
+ Distribution",
+ https://www.itl.nist.gov/div898/handbook/eda/section3/eda3663.htm
+ .. [2] Weisstein, Eric W. "Cauchy Distribution." From MathWorld--A
+ Wolfram Web Resource.
+ http://mathworld.wolfram.com/CauchyDistribution.html
+ .. [3] Wikipedia, "Cauchy distribution"
+ https://en.wikipedia.org/wiki/Cauchy_distribution
+
+ Examples
+ --------
+ Draw samples and plot the distribution:
+
+ >>> import matplotlib.pyplot as plt
+ >>> s = np.random.default_rng().standard_cauchy(1000000)
+ >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well
+ >>> plt.hist(s, bins=100)
+ >>> plt.show()
+
+ """
+ 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):
+ """
+ standard_t(df, size=None)
+
+ Draw samples from a standard Student's t distribution with `df` degrees
+ of freedom.
+
+ A special case of the hyperbolic distribution. As `df` gets
+ large, the result resembles that of the standard normal
+ distribution (`standard_normal`).
+
+ Parameters
+ ----------
+ df : float or array_like of floats
+ Degrees of freedom, must be > 0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``df`` is a scalar. Otherwise,
+ ``np.array(df).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized standard Student's t distribution.
+
+ Notes
+ -----
+ The probability density function for the t distribution is
+
+ .. math:: P(x, df) = \\frac{\\Gamma(\\frac{df+1}{2})}{\\sqrt{\\pi df}
+ \\Gamma(\\frac{df}{2})}\\Bigl( 1+\\frac{x^2}{df} \\Bigr)^{-(df+1)/2}
+
+ The t test is based on an assumption that the data come from a
+ Normal distribution. The t test provides a way to test whether
+ the sample mean (that is the mean calculated from the data) is
+ a good estimate of the true mean.
+
+ The derivation of the t-distribution was first published in
+ 1908 by William Gosset while working for the Guinness Brewery
+ in Dublin. Due to proprietary issues, he had to publish under
+ a pseudonym, and so he used the name Student.
+
+ References
+ ----------
+ .. [1] Dalgaard, Peter, "Introductory Statistics With R",
+ Springer, 2002.
+ .. [2] Wikipedia, "Student's t-distribution"
+ https://en.wikipedia.org/wiki/Student's_t-distribution
+
+ Examples
+ --------
+ From Dalgaard page 83 [1]_, suppose the daily energy intake for 11
+ women in kilojoules (kJ) is:
+
+ >>> intake = np.array([5260., 5470, 5640, 6180, 6390, 6515, 6805, 7515, \\
+ ... 7515, 8230, 8770])
+
+ Does their energy intake deviate systematically from the recommended
+ value of 7725 kJ?
+
+ We have 10 degrees of freedom, so is the sample mean within 95% of the
+ recommended value?
+
+ >>> s = np.random.default_rng().standard_t(10, size=100000)
+ >>> np.mean(intake)
+ 6753.636363636364
+ >>> intake.std(ddof=1)
+ 1142.1232221373727
+
+ Calculate the t statistic, setting the ddof parameter to the unbiased
+ value so the divisor in the standard deviation will be degrees of
+ freedom, N-1.
+
+ >>> t = (np.mean(intake)-7725)/(intake.std(ddof=1)/np.sqrt(len(intake)))
+ >>> import matplotlib.pyplot as plt
+ >>> h = plt.hist(s, bins=100, density=True)
+
+ For a one-sided t-test, how far out in the distribution does the t
+ statistic appear?
+
+ >>> np.sum(s<t) / float(len(s))
+ 0.0090699999999999999 #random
+
+ So the p-value is about 0.009, which says the null hypothesis has a
+ probability of about 99% of being true.
+
+ """
+ return cont(&random_standard_t, &self._bitgen, size, self.lock, 1,
+ df, 'df', CONS_POSITIVE,
+ 0, '', CONS_NONE,
+ 0, '', CONS_NONE,
+ None)
+
+ def vonmises(self, mu, kappa, size=None):
+ """
+ vonmises(mu, kappa, size=None)
+
+ Draw samples from a von Mises distribution.
+
+ Samples are drawn from a von Mises distribution with specified mode
+ (mu) and dispersion (kappa), on the interval [-pi, pi].
+
+ The von Mises distribution (also known as the circular normal
+ distribution) is a continuous probability distribution on the unit
+ circle. It may be thought of as the circular analogue of the normal
+ distribution.
+
+ Parameters
+ ----------
+ mu : float or array_like of floats
+ Mode ("center") of the distribution.
+ kappa : float or array_like of floats
+ Dispersion of the distribution, has to be >=0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``mu`` and ``kappa`` are both scalars.
+ Otherwise, ``np.broadcast(mu, kappa).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized von Mises distribution.
+
+ See Also
+ --------
+ scipy.stats.vonmises : probability density function, distribution, or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the von Mises distribution is
+
+ .. math:: p(x) = \\frac{e^{\\kappa cos(x-\\mu)}}{2\\pi I_0(\\kappa)},
+
+ where :math:`\\mu` is the mode and :math:`\\kappa` the dispersion,
+ and :math:`I_0(\\kappa)` is the modified Bessel function of order 0.
+
+ The von Mises is named for Richard Edler von Mises, who was born in
+ Austria-Hungary, in what is now the Ukraine. He fled to the United
+ States in 1939 and became a professor at Harvard. He worked in
+ probability theory, aerodynamics, fluid mechanics, and philosophy of
+ science.
+
+ References
+ ----------
+ .. [1] Abramowitz, M. and Stegun, I. A. (Eds.). "Handbook of
+ Mathematical Functions with Formulas, Graphs, and Mathematical
+ Tables, 9th printing," New York: Dover, 1972.
+ .. [2] von Mises, R., "Mathematical Theory of Probability
+ and Statistics", New York: Academic Press, 1964.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> mu, kappa = 0.0, 4.0 # mean and dispersion
+ >>> s = np.random.default_rng().vonmises(mu, kappa, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> from scipy.special import i0 # doctest: +SKIP
+ >>> plt.hist(s, 50, density=True)
+ >>> x = np.linspace(-np.pi, np.pi, num=51)
+ >>> y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa)) # doctest: +SKIP
+ >>> plt.plot(x, y, linewidth=2, color='r') # doctest: +SKIP
+ >>> plt.show()
+
+ """
+ return cont(&random_vonmises, &self._bitgen, size, self.lock, 2,
+ mu, 'mu', CONS_NONE,
+ kappa, 'kappa', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def pareto(self, a, size=None):
+ """
+ pareto(a, size=None)
+
+ Draw samples from a Pareto II or Lomax distribution with
+ specified shape.
+
+ The Lomax or Pareto II distribution is a shifted Pareto
+ distribution. The classical Pareto distribution can be
+ obtained from the Lomax distribution by adding 1 and
+ multiplying by the scale parameter ``m`` (see Notes). The
+ smallest value of the Lomax distribution is zero while for the
+ classical Pareto distribution it is ``mu``, where the standard
+ Pareto distribution has location ``mu = 1``. Lomax can also
+ be considered as a simplified version of the Generalized
+ Pareto distribution (available in SciPy), with the scale set
+ to one and the location set to zero.
+
+ The Pareto distribution must be greater than zero, and is
+ unbounded above. It is also known as the "80-20 rule". In
+ this distribution, 80 percent of the weights are in the lowest
+ 20 percent of the range, while the other 20 percent fill the
+ remaining 80 percent of the range.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Shape of the distribution. Must be positive.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` is a scalar. Otherwise,
+ ``np.array(a).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Pareto distribution.
+
+ See Also
+ --------
+ scipy.stats.lomax : probability density function, distribution or
+ cumulative density function, etc.
+ scipy.stats.genpareto : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Pareto distribution is
+
+ .. math:: p(x) = \\frac{am^a}{x^{a+1}}
+
+ where :math:`a` is the shape and :math:`m` the scale.
+
+ The Pareto distribution, named after the Italian economist
+ Vilfredo Pareto, is a power law probability distribution
+ useful in many real world problems. Outside the field of
+ economics it is generally referred to as the Bradford
+ distribution. Pareto developed the distribution to describe
+ the distribution of wealth in an economy. It has also found
+ use in insurance, web page access statistics, oil field sizes,
+ and many other problems, including the download frequency for
+ projects in Sourceforge [1]_. It is one of the so-called
+ "fat-tailed" distributions.
+
+
+ References
+ ----------
+ .. [1] Francis Hunt and Paul Johnson, On the Pareto Distribution of
+ Sourceforge projects.
+ .. [2] Pareto, V. (1896). Course of Political Economy. Lausanne.
+ .. [3] Reiss, R.D., Thomas, M.(2001), Statistical Analysis of Extreme
+ Values, Birkhauser Verlag, Basel, pp 23-30.
+ .. [4] Wikipedia, "Pareto distribution",
+ https://en.wikipedia.org/wiki/Pareto_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> a, m = 3., 2. # shape and mode
+ >>> s = (np.random.default_rng().pareto(a, 1000) + 1) * m
+
+ Display the histogram of the samples, along with the probability
+ density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, _ = plt.hist(s, 100, density=True)
+ >>> fit = a*m**a / bins**(a+1)
+ >>> plt.plot(bins, max(count)*fit/max(fit), linewidth=2, color='r')
+ >>> plt.show()
+
+ """
+ return cont(&random_pareto, &self._bitgen, size, self.lock, 1,
+ a, 'a', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
+
+ def weibull(self, a, size=None):
+ """
+ weibull(a, size=None)
+
+ Draw samples from a Weibull distribution.
+
+ Draw samples from a 1-parameter Weibull distribution with the given
+ shape parameter `a`.
+
+ .. math:: X = (-ln(U))^{1/a}
+
+ Here, U is drawn from the uniform distribution over (0,1].
+
+ The more common 2-parameter Weibull, including a scale parameter
+ :math:`\\lambda` is just :math:`X = \\lambda(-ln(U))^{1/a}`.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Shape parameter of the distribution. Must be nonnegative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` is a scalar. Otherwise,
+ ``np.array(a).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Weibull distribution.
+
+ See Also
+ --------
+ scipy.stats.weibull_max
+ scipy.stats.weibull_min
+ scipy.stats.genextreme
+ gumbel
+
+ Notes
+ -----
+ The Weibull (or Type III asymptotic extreme value distribution
+ for smallest values, SEV Type III, or Rosin-Rammler
+ distribution) is one of a class of Generalized Extreme Value
+ (GEV) distributions used in modeling extreme value problems.
+ This class includes the Gumbel and Frechet distributions.
+
+ The probability density for the Weibull distribution is
+
+ .. math:: p(x) = \\frac{a}
+ {\\lambda}(\\frac{x}{\\lambda})^{a-1}e^{-(x/\\lambda)^a},
+
+ where :math:`a` is the shape and :math:`\\lambda` the scale.
+
+ The function has its peak (the mode) at
+ :math:`\\lambda(\\frac{a-1}{a})^{1/a}`.
+
+ When ``a = 1``, the Weibull distribution reduces to the exponential
+ distribution.
+
+ References
+ ----------
+ .. [1] Waloddi Weibull, Royal Technical University, Stockholm,
+ 1939 "A Statistical Theory Of The Strength Of Materials",
+ Ingeniorsvetenskapsakademiens Handlingar Nr 151, 1939,
+ Generalstabens Litografiska Anstalts Forlag, Stockholm.
+ .. [2] Waloddi Weibull, "A Statistical Distribution Function of
+ Wide Applicability", Journal Of Applied Mechanics ASME Paper
+ 1951.
+ .. [3] Wikipedia, "Weibull distribution",
+ https://en.wikipedia.org/wiki/Weibull_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> a = 5. # shape
+ >>> s = rng.weibull(a, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> x = np.arange(1,100.)/50.
+ >>> def weib(x,n,a):
+ ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a)
+
+ >>> count, bins, ignored = plt.hist(rng.weibull(5.,1000))
+ >>> x = np.arange(1,100.)/50.
+ >>> scale = count.max()/weib(x, 1., 5.).max()
+ >>> plt.plot(x, weib(x, 1., 5.)*scale)
+ >>> plt.show()
+
+ """
+ return cont(&random_weibull, &self._bitgen, size, self.lock, 1,
+ a, 'a', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
+
+ def power(self, a, size=None):
+ """
+ power(a, size=None)
+
+ Draws samples in [0, 1] from a power distribution with positive
+ exponent a - 1.
+
+ Also known as the power function distribution.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Parameter of the distribution. Must be non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` is a scalar. Otherwise,
+ ``np.array(a).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized power distribution.
+
+ Raises
+ ------
+ ValueError
+ If a < 1.
+
+ Notes
+ -----
+ The probability density function is
+
+ .. math:: P(x; a) = ax^{a-1}, 0 \\le x \\le 1, a>0.
+
+ The power function distribution is just the inverse of the Pareto
+ distribution. It may also be seen as a special case of the Beta
+ distribution.
+
+ It is used, for example, in modeling the over-reporting of insurance
+ claims.
+
+ References
+ ----------
+ .. [1] Christian Kleiber, Samuel Kotz, "Statistical size distributions
+ in economics and actuarial sciences", Wiley, 2003.
+ .. [2] Heckert, N. A. and Filliben, James J. "NIST Handbook 148:
+ Dataplot Reference Manual, Volume 2: Let Subcommands and Library
+ Functions", National Institute of Standards and Technology
+ Handbook Series, June 2003.
+ https://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> a = 5. # shape
+ >>> samples = 1000
+ >>> s = rng.power(a, samples)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, bins=30)
+ >>> x = np.linspace(0, 1, 100)
+ >>> y = a*x**(a-1.)
+ >>> normed_y = samples*np.diff(bins)[0]*y
+ >>> plt.plot(x, normed_y)
+ >>> plt.show()
+
+ Compare the power function distribution to the inverse of the Pareto.
+
+ >>> from scipy import stats # doctest: +SKIP
+ >>> rvs = rng.power(5, 1000000)
+ >>> rvsp = rng.pareto(5, 1000000)
+ >>> xx = np.linspace(0,1,100)
+ >>> powpdf = stats.powerlaw.pdf(xx,5) # doctest: +SKIP
+
+ >>> plt.figure()
+ >>> plt.hist(rvs, bins=50, density=True)
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
+ >>> plt.title('power(5)')
+
+ >>> plt.figure()
+ >>> plt.hist(1./(1.+rvsp), bins=50, density=True)
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
+ >>> plt.title('inverse of 1 + Generator.pareto(5)')
+
+ >>> plt.figure()
+ >>> plt.hist(1./(1.+rvsp), bins=50, density=True)
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
+ >>> plt.title('inverse of stats.pareto(5)')
+
+ """
+ return cont(&random_power, &self._bitgen, size, self.lock, 1,
+ a, 'a', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
+
+ def laplace(self, loc=0.0, scale=1.0, size=None):
+ """
+ laplace(loc=0.0, scale=1.0, size=None)
+
+ Draw samples from the Laplace or double exponential distribution with
+ specified location (or mean) and scale (decay).
+
+ The Laplace distribution is similar to the Gaussian/normal distribution,
+ but is sharper at the peak and has fatter tails. It represents the
+ difference between two independent, identically distributed exponential
+ random variables.
+
+ Parameters
+ ----------
+ loc : float or array_like of floats, optional
+ The position, :math:`\\mu`, of the distribution peak. Default is 0.
+ scale : float or array_like of floats, optional
+ :math:`\\lambda`, the exponential decay. Default is 1. Must be non-
+ negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``loc`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(loc, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Laplace distribution.
+
+ Notes
+ -----
+ It has the probability density function
+
+ .. math:: f(x; \\mu, \\lambda) = \\frac{1}{2\\lambda}
+ \\exp\\left(-\\frac{|x - \\mu|}{\\lambda}\\right).
+
+ The first law of Laplace, from 1774, states that the frequency
+ of an error can be expressed as an exponential function of the
+ absolute magnitude of the error, which leads to the Laplace
+ distribution. For many problems in economics and health
+ sciences, this distribution seems to model the data better
+ than the standard Gaussian distribution.
+
+ References
+ ----------
+ .. [1] Abramowitz, M. and Stegun, I. A. (Eds.). "Handbook of
+ Mathematical Functions with Formulas, Graphs, and Mathematical
+ Tables, 9th printing," New York: Dover, 1972.
+ .. [2] Kotz, Samuel, et. al. "The Laplace Distribution and
+ Generalizations, " Birkhauser, 2001.
+ .. [3] Weisstein, Eric W. "Laplace Distribution."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/LaplaceDistribution.html
+ .. [4] Wikipedia, "Laplace distribution",
+ https://en.wikipedia.org/wiki/Laplace_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution
+
+ >>> loc, scale = 0., 1.
+ >>> s = np.random.default_rng().laplace(loc, scale, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 30, density=True)
+ >>> x = np.arange(-8., 8., .01)
+ >>> pdf = np.exp(-abs(x-loc)/scale)/(2.*scale)
+ >>> plt.plot(x, pdf)
+
+ Plot Gaussian for comparison:
+
+ >>> g = (1/(scale * np.sqrt(2 * np.pi)) *
+ ... np.exp(-(x - loc)**2 / (2 * scale**2)))
+ >>> plt.plot(x,g)
+
+ """
+ return cont(&random_laplace, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def gumbel(self, loc=0.0, scale=1.0, size=None):
+ """
+ gumbel(loc=0.0, scale=1.0, size=None)
+
+ Draw samples from a Gumbel distribution.
+
+ Draw samples from a Gumbel distribution with specified location and
+ scale. For more information on the Gumbel distribution, see
+ Notes and References below.
+
+ Parameters
+ ----------
+ loc : float or array_like of floats, optional
+ The location of the mode of the distribution. Default is 0.
+ scale : float or array_like of floats, optional
+ The scale parameter of the distribution. Default is 1. Must be non-
+ negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``loc`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(loc, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Gumbel distribution.
+
+ See Also
+ --------
+ scipy.stats.gumbel_l
+ scipy.stats.gumbel_r
+ scipy.stats.genextreme
+ weibull
+
+ Notes
+ -----
+ The Gumbel (or Smallest Extreme Value (SEV) or the Smallest Extreme
+ Value Type I) distribution is one of a class of Generalized Extreme
+ Value (GEV) distributions used in modeling extreme value problems.
+ The Gumbel is a special case of the Extreme Value Type I distribution
+ for maximums from distributions with "exponential-like" tails.
+
+ The probability density for the Gumbel distribution is
+
+ .. math:: p(x) = \\frac{e^{-(x - \\mu)/ \\beta}}{\\beta} e^{ -e^{-(x - \\mu)/
+ \\beta}},
+
+ where :math:`\\mu` is the mode, a location parameter, and
+ :math:`\\beta` is the scale parameter.
+
+ The Gumbel (named for German mathematician Emil Julius Gumbel) was used
+ very early in the hydrology literature, for modeling the occurrence of
+ flood events. It is also used for modeling maximum wind speed and
+ rainfall rates. It is a "fat-tailed" distribution - the probability of
+ an event in the tail of the distribution is larger than if one used a
+ Gaussian, hence the surprisingly frequent occurrence of 100-year
+ floods. Floods were initially modeled as a Gaussian process, which
+ underestimated the frequency of extreme events.
+
+ It is one of a class of extreme value distributions, the Generalized
+ Extreme Value (GEV) distributions, which also includes the Weibull and
+ Frechet.
+
+ The function has a mean of :math:`\\mu + 0.57721\\beta` and a variance
+ of :math:`\\frac{\\pi^2}{6}\\beta^2`.
+
+ References
+ ----------
+ .. [1] Gumbel, E. J., "Statistics of Extremes,"
+ New York: Columbia University Press, 1958.
+ .. [2] Reiss, R.-D. and Thomas, M., "Statistical Analysis of Extreme
+ Values from Insurance, Finance, Hydrology and Other Fields,"
+ Basel: Birkhauser Verlag, 2001.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> mu, beta = 0, 0.1 # location and scale
+ >>> s = rng.gumbel(mu, beta, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 30, density=True)
+ >>> plt.plot(bins, (1/beta)*np.exp(-(bins - mu)/beta)
+ ... * np.exp( -np.exp( -(bins - mu) /beta) ),
+ ... linewidth=2, color='r')
+ >>> plt.show()
+
+ Show how an extreme value distribution can arise from a Gaussian process
+ and compare to a Gaussian:
+
+ >>> means = []
+ >>> maxima = []
+ >>> for i in range(0,1000) :
+ ... a = rng.normal(mu, beta, 1000)
+ ... means.append(a.mean())
+ ... maxima.append(a.max())
+ >>> count, bins, ignored = plt.hist(maxima, 30, density=True)
+ >>> beta = np.std(maxima) * np.sqrt(6) / np.pi
+ >>> mu = np.mean(maxima) - 0.57721*beta
+ >>> plt.plot(bins, (1/beta)*np.exp(-(bins - mu)/beta)
+ ... * np.exp(-np.exp(-(bins - mu)/beta)),
+ ... linewidth=2, color='r')
+ >>> plt.plot(bins, 1/(beta * np.sqrt(2 * np.pi))
+ ... * np.exp(-(bins - mu)**2 / (2 * beta**2)),
+ ... linewidth=2, color='g')
+ >>> plt.show()
+
+ """
+ return cont(&random_gumbel, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def logistic(self, loc=0.0, scale=1.0, size=None):
+ """
+ logistic(loc=0.0, scale=1.0, size=None)
+
+ Draw samples from a logistic distribution.
+
+ Samples are drawn from a logistic distribution with specified
+ parameters, loc (location or mean, also median), and scale (>0).
+
+ Parameters
+ ----------
+ loc : float or array_like of floats, optional
+ Parameter of the distribution. Default is 0.
+ scale : float or array_like of floats, optional
+ Parameter of the distribution. Must be non-negative.
+ Default is 1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``loc`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(loc, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized logistic distribution.
+
+ See Also
+ --------
+ scipy.stats.logistic : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Logistic distribution is
+
+ .. math:: P(x) = P(x) = \\frac{e^{-(x-\\mu)/s}}{s(1+e^{-(x-\\mu)/s})^2},
+
+ where :math:`\\mu` = location and :math:`s` = scale.
+
+ The Logistic distribution is used in Extreme Value problems where it
+ can act as a mixture of Gumbel distributions, in Epidemiology, and by
+ the World Chess Federation (FIDE) where it is used in the Elo ranking
+ system, assuming the performance of each player is a logistically
+ distributed random variable.
+
+ References
+ ----------
+ .. [1] Reiss, R.-D. and Thomas M. (2001), "Statistical Analysis of
+ Extreme Values, from Insurance, Finance, Hydrology and Other
+ Fields," Birkhauser Verlag, Basel, pp 132-133.
+ .. [2] Weisstein, Eric W. "Logistic Distribution." From
+ MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/LogisticDistribution.html
+ .. [3] Wikipedia, "Logistic-distribution",
+ https://en.wikipedia.org/wiki/Logistic_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> loc, scale = 10, 1
+ >>> s = np.random.default_rng().logistic(loc, scale, 10000)
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, bins=50)
+
+ # plot against distribution
+
+ >>> def logist(x, loc, scale):
+ ... return np.exp((loc-x)/scale)/(scale*(1+np.exp((loc-x)/scale))**2)
+ >>> lgst_val = logist(bins, loc, scale)
+ >>> plt.plot(bins, lgst_val * count.max() / lgst_val.max())
+ >>> plt.show()
+
+ """
+ return cont(&random_logistic, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def lognormal(self, mean=0.0, sigma=1.0, size=None):
+ """
+ lognormal(mean=0.0, sigma=1.0, size=None)
+
+ Draw samples from a log-normal distribution.
+
+ Draw samples from a log-normal distribution with specified mean,
+ standard deviation, and array shape. Note that the mean and standard
+ deviation are not the values for the distribution itself, but of the
+ underlying normal distribution it is derived from.
+
+ Parameters
+ ----------
+ mean : float or array_like of floats, optional
+ Mean value of the underlying normal distribution. Default is 0.
+ sigma : float or array_like of floats, optional
+ Standard deviation of the underlying normal distribution. Must be
+ non-negative. Default is 1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``mean`` and ``sigma`` are both scalars.
+ Otherwise, ``np.broadcast(mean, sigma).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized log-normal distribution.
+
+ See Also
+ --------
+ scipy.stats.lognorm : probability density function, distribution,
+ cumulative density function, etc.
+
+ Notes
+ -----
+ A variable `x` has a log-normal distribution if `log(x)` is normally
+ distributed. The probability density function for the log-normal
+ distribution is:
+
+ .. math:: p(x) = \\frac{1}{\\sigma x \\sqrt{2\\pi}}
+ e^{(-\\frac{(ln(x)-\\mu)^2}{2\\sigma^2})}
+
+ where :math:`\\mu` is the mean and :math:`\\sigma` is the standard
+ deviation of the normally distributed logarithm of the variable.
+ A log-normal distribution results if a random variable is the *product*
+ of a large number of independent, identically-distributed variables in
+ the same way that a normal distribution results if the variable is the
+ *sum* of a large number of independent, identically-distributed
+ variables.
+
+ References
+ ----------
+ .. [1] Limpert, E., Stahel, W. A., and Abbt, M., "Log-normal
+ Distributions across the Sciences: Keys and Clues,"
+ BioScience, Vol. 51, No. 5, May, 2001.
+ https://stat.ethz.ch/~stahel/lognormal/bioscience.pdf
+ .. [2] Reiss, R.D. and Thomas, M., "Statistical Analysis of Extreme
+ Values," Basel: Birkhauser Verlag, 2001, pp. 31-32.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> mu, sigma = 3., 1. # mean and standard deviation
+ >>> s = rng.lognormal(mu, sigma, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 100, density=True, align='mid')
+
+ >>> x = np.linspace(min(bins), max(bins), 10000)
+ >>> pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2))
+ ... / (x * sigma * np.sqrt(2 * np.pi)))
+
+ >>> plt.plot(x, pdf, linewidth=2, color='r')
+ >>> plt.axis('tight')
+ >>> plt.show()
+
+ Demonstrate that taking the products of random samples from a uniform
+ distribution can be fit well by a log-normal probability density
+ function.
+
+ >>> # Generate a thousand samples: each is the product of 100 random
+ >>> # values, drawn from a normal distribution.
+ >>> rng = rng
+ >>> b = []
+ >>> for i in range(1000):
+ ... a = 10. + rng.standard_normal(100)
+ ... b.append(np.product(a))
+
+ >>> b = np.array(b) / np.min(b) # scale values to be positive
+ >>> count, bins, ignored = plt.hist(b, 100, density=True, align='mid')
+ >>> sigma = np.std(np.log(b))
+ >>> mu = np.mean(np.log(b))
+
+ >>> x = np.linspace(min(bins), max(bins), 10000)
+ >>> pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2))
+ ... / (x * sigma * np.sqrt(2 * np.pi)))
+
+ >>> plt.plot(x, pdf, color='r', linewidth=2)
+ >>> plt.show()
+
+ """
+ return cont(&random_lognormal, &self._bitgen, size, self.lock, 2,
+ mean, 'mean', CONS_NONE,
+ sigma, 'sigma', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def rayleigh(self, scale=1.0, size=None):
+ """
+ rayleigh(scale=1.0, size=None)
+
+ Draw samples from a Rayleigh distribution.
+
+ The :math:`\\chi` and Weibull distributions are generalizations of the
+ Rayleigh.
+
+ Parameters
+ ----------
+ scale : float or array_like of floats, optional
+ Scale, also equals the mode. Must be non-negative. Default is 1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``scale`` is a scalar. Otherwise,
+ ``np.array(scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Rayleigh distribution.
+
+ Notes
+ -----
+ The probability density function for the Rayleigh distribution is
+
+ .. math:: P(x;scale) = \\frac{x}{scale^2}e^{\\frac{-x^2}{2 \\cdotp scale^2}}
+
+ The Rayleigh distribution would arise, for example, if the East
+ and North components of the wind velocity had identical zero-mean
+ Gaussian distributions. Then the wind speed would have a Rayleigh
+ distribution.
+
+ References
+ ----------
+ .. [1] Brighton Webs Ltd., "Rayleigh Distribution,"
+ https://web.archive.org/web/20090514091424/http://brighton-webs.co.uk:80/distributions/rayleigh.asp
+ .. [2] Wikipedia, "Rayleigh distribution"
+ https://en.wikipedia.org/wiki/Rayleigh_distribution
+
+ Examples
+ --------
+ Draw values from the distribution and plot the histogram
+
+ >>> from matplotlib.pyplot import hist
+ >>> rng = np.random.default_rng()
+ >>> values = hist(rng.rayleigh(3, 100000), bins=200, density=True)
+
+ Wave heights tend to follow a Rayleigh distribution. If the mean wave
+ height is 1 meter, what fraction of waves are likely to be larger than 3
+ meters?
+
+ >>> meanvalue = 1
+ >>> modevalue = np.sqrt(2 / np.pi) * meanvalue
+ >>> s = rng.rayleigh(modevalue, 1000000)
+
+ The percentage of waves larger than 3 meters is:
+
+ >>> 100.*sum(s>3)/1000000.
+ 0.087300000000000003 # random
+
+ """
+ return cont(&random_rayleigh, &self._bitgen, size, self.lock, 1,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
+
+ def wald(self, mean, scale, size=None):
+ """
+ wald(mean, scale, size=None)
+
+ Draw samples from a Wald, or inverse Gaussian, distribution.
+
+ As the scale approaches infinity, the distribution becomes more like a
+ Gaussian. Some references claim that the Wald is an inverse Gaussian
+ with mean equal to 1, but this is by no means universal.
+
+ The inverse Gaussian distribution was first studied in relationship to
+ Brownian motion. In 1956 M.C.K. Tweedie used the name inverse Gaussian
+ because there is an inverse relationship between the time to cover a
+ unit distance and distance covered in unit time.
+
+ Parameters
+ ----------
+ mean : float or array_like of floats
+ Distribution mean, must be > 0.
+ scale : float or array_like of floats
+ Scale parameter, must be > 0.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``mean`` and ``scale`` are both scalars.
+ Otherwise, ``np.broadcast(mean, scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Wald distribution.
+
+ Notes
+ -----
+ The probability density function for the Wald distribution is
+
+ .. math:: P(x;mean,scale) = \\sqrt{\\frac{scale}{2\\pi x^3}}e^
+ \\frac{-scale(x-mean)^2}{2\\cdotp mean^2x}
+
+ As noted above the inverse Gaussian distribution first arise
+ from attempts to model Brownian motion. It is also a
+ competitor to the Weibull for use in reliability modeling and
+ modeling stock returns and interest rate processes.
+
+ References
+ ----------
+ .. [1] Brighton Webs Ltd., Wald Distribution,
+ https://web.archive.org/web/20090423014010/http://www.brighton-webs.co.uk:80/distributions/wald.asp
+ .. [2] Chhikara, Raj S., and Folks, J. Leroy, "The Inverse Gaussian
+ Distribution: Theory : Methodology, and Applications", CRC Press,
+ 1988.
+ .. [3] Wikipedia, "Inverse Gaussian distribution"
+ https://en.wikipedia.org/wiki/Inverse_Gaussian_distribution
+
+ Examples
+ --------
+ Draw values from the distribution and plot the histogram:
+
+ >>> import matplotlib.pyplot as plt
+ >>> h = plt.hist(np.random.default_rng().wald(3, 2, 100000), bins=200, density=True)
+ >>> plt.show()
+
+ """
+ return cont(&random_wald, &self._bitgen, size, self.lock, 2,
+ mean, 'mean', CONS_POSITIVE,
+ scale, 'scale', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def triangular(self, left, mode, right, size=None):
+ """
+ triangular(left, mode, right, size=None)
+
+ Draw samples from the triangular distribution over the
+ interval ``[left, right]``.
+
+ The triangular distribution is a continuous probability
+ distribution with lower limit left, peak at mode, and upper
+ limit right. Unlike the other distributions, these parameters
+ directly define the shape of the pdf.
+
+ Parameters
+ ----------
+ left : float or array_like of floats
+ Lower limit.
+ mode : float or array_like of floats
+ The value where the peak of the distribution occurs.
+ The value must fulfill the condition ``left <= mode <= right``.
+ right : float or array_like of floats
+ Upper limit, must be larger than `left`.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``left``, ``mode``, and ``right``
+ are all scalars. Otherwise, ``np.broadcast(left, mode, right).size``
+ samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized triangular distribution.
+
+ Notes
+ -----
+ The probability density function for the triangular distribution is
+
+ .. math:: P(x;l, m, r) = \\begin{cases}
+ \\frac{2(x-l)}{(r-l)(m-l)}& \\text{for $l \\leq x \\leq m$},\\\\
+ \\frac{2(r-x)}{(r-l)(r-m)}& \\text{for $m \\leq x \\leq r$},\\\\
+ 0& \\text{otherwise}.
+ \\end{cases}
+
+ The triangular distribution is often used in ill-defined
+ problems where the underlying distribution is not known, but
+ some knowledge of the limits and mode exists. Often it is used
+ in simulations.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Triangular distribution"
+ https://en.wikipedia.org/wiki/Triangular_distribution
+
+ Examples
+ --------
+ Draw values from the distribution and plot the histogram:
+
+ >>> import matplotlib.pyplot as plt
+ >>> h = plt.hist(np.random.default_rng().triangular(-3, 0, 8, 100000), bins=200,
+ ... density=True)
+ >>> plt.show()
+
+ """
+ cdef bint is_scalar = True
+ cdef double fleft, fmode, fright
+ cdef np.ndarray oleft, omode, oright
+
+ oleft = <np.ndarray>np.PyArray_FROM_OTF(left, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ omode = <np.ndarray>np.PyArray_FROM_OTF(mode, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ oright = <np.ndarray>np.PyArray_FROM_OTF(right, np.NPY_DOUBLE, np.NPY_ALIGNED)
+
+ if np.PyArray_NDIM(oleft) == np.PyArray_NDIM(omode) == np.PyArray_NDIM(oright) == 0:
+ fleft = PyFloat_AsDouble(left)
+ fright = PyFloat_AsDouble(right)
+ fmode = PyFloat_AsDouble(mode)
+
+ if fleft > fmode:
+ raise ValueError("left > mode")
+ if fmode > fright:
+ raise ValueError("mode > right")
+ if fleft == fright:
+ raise ValueError("left == right")
+ return cont(&random_triangular, &self._bitgen, size, self.lock, 3,
+ fleft, '', CONS_NONE,
+ fmode, '', CONS_NONE,
+ fright, '', CONS_NONE, None)
+
+ if np.any(np.greater(oleft, omode)):
+ raise ValueError("left > mode")
+ if np.any(np.greater(omode, oright)):
+ raise ValueError("mode > right")
+ if np.any(np.equal(oleft, oright)):
+ raise ValueError("left == right")
+
+ return cont_broadcast_3(&random_triangular, &self._bitgen, size, self.lock,
+ oleft, '', CONS_NONE,
+ omode, '', CONS_NONE,
+ oright, '', CONS_NONE)
+
+ # Complicated, discrete distributions:
+ def binomial(self, n, p, size=None):
+ """
+ binomial(n, p, size=None)
+
+ Draw samples from a binomial distribution.
+
+ Samples are drawn from a binomial distribution with specified
+ parameters, n trials and p probability of success where
+ n an integer >= 0 and p is in the interval [0,1]. (n may be
+ input as a float, but it is truncated to an integer in use)
+
+ Parameters
+ ----------
+ n : int or array_like of ints
+ Parameter of the distribution, >= 0. Floats are also accepted,
+ but they will be truncated to integers.
+ p : float or array_like of floats
+ Parameter of the distribution, >= 0 and <=1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``n`` and ``p`` are both scalars.
+ Otherwise, ``np.broadcast(n, p).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized binomial distribution, where
+ each sample is equal to the number of successes over the n trials.
+
+ See Also
+ --------
+ scipy.stats.binom : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the binomial distribution is
+
+ .. math:: P(N) = \\binom{n}{N}p^N(1-p)^{n-N},
+
+ where :math:`n` is the number of trials, :math:`p` is the probability
+ of success, and :math:`N` is the number of successes.
+
+ When estimating the standard error of a proportion in a population by
+ using a random sample, the normal distribution works well unless the
+ product p*n <=5, where p = population proportion estimate, and n =
+ number of samples, in which case the binomial distribution is used
+ instead. For example, a sample of 15 people shows 4 who are left
+ handed, and 11 who are right handed. Then p = 4/15 = 27%. 0.27*15 = 4,
+ so the binomial distribution should be used in this case.
+
+ References
+ ----------
+ .. [1] Dalgaard, Peter, "Introductory Statistics with R",
+ Springer-Verlag, 2002.
+ .. [2] Glantz, Stanton A. "Primer of Biostatistics.", McGraw-Hill,
+ Fifth Edition, 2002.
+ .. [3] Lentner, Marvin, "Elementary Applied Statistics", Bogden
+ and Quigley, 1972.
+ .. [4] Weisstein, Eric W. "Binomial Distribution." From MathWorld--A
+ Wolfram Web Resource.
+ http://mathworld.wolfram.com/BinomialDistribution.html
+ .. [5] Wikipedia, "Binomial distribution",
+ https://en.wikipedia.org/wiki/Binomial_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> n, p = 10, .5 # number of trials, probability of each trial
+ >>> s = rng.binomial(n, p, 1000)
+ # result of flipping a coin 10 times, tested 1000 times.
+
+ A real world example. A company drills 9 wild-cat oil exploration
+ wells, each with an estimated probability of success of 0.1. All nine
+ wells fail. What is the probability of that happening?
+
+ Let's do 20,000 trials of the model, and count the number that
+ generate zero positive results.
+
+ >>> sum(rng.binomial(9, 0.1, 20000) == 0)/20000.
+ # answer = 0.38885, or 38%.
+
+ """
+
+ # Uses a custom implementation since self._binomial is required
+ cdef double _dp = 0
+ cdef int64_t _in = 0
+ cdef bint is_scalar = True
+ cdef np.npy_intp i, cnt
+ cdef np.ndarray randoms
+ cdef np.int64_t *randoms_data
+ cdef np.broadcast it
+
+ p_arr = <np.ndarray>np.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(p_arr) == 0
+ n_arr = <np.ndarray>np.PyArray_FROM_OTF(n, np.NPY_INT64, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(n_arr) == 0
+
+ if not is_scalar:
+ check_array_constraint(p_arr, 'p', CONS_BOUNDED_0_1)
+ check_array_constraint(n_arr, 'n', CONS_NON_NEGATIVE)
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ else:
+ it = np.PyArray_MultiIterNew2(p_arr, n_arr)
+ randoms = <np.ndarray>np.empty(it.shape, np.int64)
+
+ randoms_data = <np.int64_t *>np.PyArray_DATA(randoms)
+ cnt = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew3(randoms, p_arr, n_arr)
+ with self.lock, nogil:
+ for i in range(cnt):
+ _dp = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ _in = (<int64_t*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ (<int64_t*>np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(&self._bitgen, _dp, _in, &self._binomial)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+ _dp = PyFloat_AsDouble(p)
+ _in = <int64_t>n
+ check_constraint(_dp, 'p', CONS_BOUNDED_0_1)
+ check_constraint(<double>_in, 'n', CONS_NON_NEGATIVE)
+
+ if size is None:
+ with self.lock:
+ return random_binomial(&self._bitgen, _dp, _in, &self._binomial)
+
+ randoms = <np.ndarray>np.empty(size, np.int64)
+ cnt = np.PyArray_SIZE(randoms)
+ randoms_data = <np.int64_t *>np.PyArray_DATA(randoms)
+
+ with self.lock, nogil:
+ for i in range(cnt):
+ randoms_data[i] = random_binomial(&self._bitgen, _dp, _in,
+ &self._binomial)
+
+ return randoms
+
+ def negative_binomial(self, n, p, size=None):
+ """
+ negative_binomial(n, p, size=None)
+
+ Draw samples from a negative binomial distribution.
+
+ Samples are drawn from a negative binomial distribution with specified
+ parameters, `n` successes and `p` probability of success where `n`
+ is > 0 and `p` is in the interval [0, 1].
+
+ Parameters
+ ----------
+ n : float or array_like of floats
+ Parameter of the distribution, > 0.
+ p : float or array_like of floats
+ Parameter of the distribution, >= 0 and <=1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``n`` and ``p`` are both scalars.
+ Otherwise, ``np.broadcast(n, p).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized negative binomial distribution,
+ where each sample is equal to N, the number of failures that
+ occurred before a total of n successes was reached.
+
+ Notes
+ -----
+ The probability mass function of the negative binomial distribution is
+
+ .. math:: P(N;n,p) = \\frac{\\Gamma(N+n)}{N!\\Gamma(n)}p^{n}(1-p)^{N},
+
+ where :math:`n` is the number of successes, :math:`p` is the
+ probability of success, :math:`N+n` is the number of trials, and
+ :math:`\\Gamma` is the gamma function. When :math:`n` is an integer,
+ :math:`\\frac{\\Gamma(N+n)}{N!\\Gamma(n)} = \\binom{N+n-1}{N}`, which is
+ the more common form of this term in the the pmf. The negative
+ binomial distribution gives the probability of N failures given n
+ successes, with a success on the last trial.
+
+ If one throws a die repeatedly until the third time a "1" appears,
+ then the probability distribution of the number of non-"1"s that
+ appear before the third "1" is a negative binomial distribution.
+
+ References
+ ----------
+ .. [1] Weisstein, Eric W. "Negative Binomial Distribution." From
+ MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/NegativeBinomialDistribution.html
+ .. [2] Wikipedia, "Negative binomial distribution",
+ https://en.wikipedia.org/wiki/Negative_binomial_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ A real world example. A company drills wild-cat oil
+ exploration wells, each with an estimated probability of
+ success of 0.1. What is the probability of having one success
+ for each successive well, that is what is the probability of a
+ single success after drilling 5 wells, after 6 wells, etc.?
+
+ >>> s = np.random.default_rng().negative_binomial(1, 0.1, 100000)
+ >>> for i in range(1, 11): # doctest: +SKIP
+ ... probability = sum(s<i) / 100000.
+ ... print(i, "wells drilled, probability of one success =", probability)
+
+ """
+ return disc(&random_negative_binomial, &self._bitgen, size, self.lock, 2, 0,
+ n, 'n', CONS_POSITIVE_NOT_NAN,
+ p, 'p', CONS_BOUNDED_0_1,
+ 0.0, '', CONS_NONE)
+
+ def poisson(self, lam=1.0, size=None):
+ """
+ poisson(lam=1.0, size=None)
+
+ Draw samples from a Poisson distribution.
+
+ The Poisson distribution is the limit of the binomial distribution
+ for large N.
+
+ Parameters
+ ----------
+ lam : float or array_like of floats
+ Expectation of interval, must be >= 0. A sequence of expectation
+ intervals must be broadcastable over the requested size.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``lam`` is a scalar. Otherwise,
+ ``np.array(lam).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Poisson distribution.
+
+ Notes
+ -----
+ The Poisson distribution
+
+ .. math:: f(k; \\lambda)=\\frac{\\lambda^k e^{-\\lambda}}{k!}
+
+ For events with an expected separation :math:`\\lambda` the Poisson
+ distribution :math:`f(k; \\lambda)` describes the probability of
+ :math:`k` events occurring within the observed
+ interval :math:`\\lambda`.
+
+ Because the output is limited to the range of the C int64 type, a
+ ValueError is raised when `lam` is within 10 sigma of the maximum
+ representable value.
+
+ References
+ ----------
+ .. [1] Weisstein, Eric W. "Poisson Distribution."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/PoissonDistribution.html
+ .. [2] Wikipedia, "Poisson distribution",
+ https://en.wikipedia.org/wiki/Poisson_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> import numpy as np
+ >>> rng = np.random.default_rng()
+ >>> s = rng.poisson(5, 10000)
+
+ Display histogram of the sample:
+
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s, 14, density=True)
+ >>> plt.show()
+
+ Draw each 100 values for lambda 100 and 500:
+
+ >>> s = rng.poisson(lam=(100., 500.), size=(100, 2))
+
+ """
+ return disc(&random_poisson, &self._bitgen, size, self.lock, 1, 0,
+ lam, 'lam', CONS_POISSON,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+
+ def zipf(self, a, size=None):
+ """
+ zipf(a, size=None)
+
+ Draw samples from a Zipf distribution.
+
+ Samples are drawn from a Zipf distribution with specified parameter
+ `a` > 1.
+
+ The Zipf distribution (also known as the zeta distribution) is a
+ continuous probability distribution that satisfies Zipf's law: the
+ frequency of an item is inversely proportional to its rank in a
+ frequency table.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Distribution parameter. Must be greater than 1.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` is a scalar. Otherwise,
+ ``np.array(a).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized Zipf distribution.
+
+ See Also
+ --------
+ scipy.stats.zipf : probability density function, distribution, or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Zipf distribution is
+
+ .. math:: p(x) = \\frac{x^{-a}}{\\zeta(a)},
+
+ where :math:`\\zeta` is the Riemann Zeta function.
+
+ It is named for the American linguist George Kingsley Zipf, who noted
+ that the frequency of any word in a sample of a language is inversely
+ proportional to its rank in the frequency table.
+
+ References
+ ----------
+ .. [1] Zipf, G. K., "Selected Studies of the Principle of Relative
+ Frequency in Language," Cambridge, MA: Harvard Univ. Press,
+ 1932.
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> a = 2. # parameter
+ >>> s = np.random.default_rng().zipf(a, 1000)
+
+ Display the histogram of the samples, along with
+ the probability density function:
+
+ >>> import matplotlib.pyplot as plt
+ >>> from scipy import special # doctest: +SKIP
+
+ Truncate s values at 50 so plot is interesting:
+
+ >>> count, bins, ignored = plt.hist(s[s<50],
+ ... 50, density=True)
+ >>> x = np.arange(1., 50.)
+ >>> y = x**(-a) / special.zetac(a) # doctest: +SKIP
+ >>> plt.plot(x, y/max(y), linewidth=2, color='r') # doctest: +SKIP
+ >>> plt.show()
+
+ """
+ return disc(&random_zipf, &self._bitgen, size, self.lock, 1, 0,
+ a, 'a', CONS_GT_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+
+ def geometric(self, p, size=None):
+ """
+ geometric(p, size=None)
+
+ Draw samples from the geometric distribution.
+
+ Bernoulli trials are experiments with one of two outcomes:
+ success or failure (an example of such an experiment is flipping
+ a coin). The geometric distribution models the number of trials
+ that must be run in order to achieve success. It is therefore
+ supported on the positive integers, ``k = 1, 2, ...``.
+
+ The probability mass function of the geometric distribution is
+
+ .. math:: f(k) = (1 - p)^{k - 1} p
+
+ where `p` is the probability of success of an individual trial.
+
+ Parameters
+ ----------
+ p : float or array_like of floats
+ The probability of success of an individual trial.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``p`` is a scalar. Otherwise,
+ ``np.array(p).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized geometric distribution.
+
+ Examples
+ --------
+ Draw ten thousand values from the geometric distribution,
+ with the probability of an individual success equal to 0.35:
+
+ >>> z = np.random.default_rng().geometric(p=0.35, size=10000)
+
+ How many trials succeeded after a single run?
+
+ >>> (z == 1).sum() / 10000.
+ 0.34889999999999999 #random
+
+ """
+ return disc(&random_geometric, &self._bitgen, size, self.lock, 1, 0,
+ p, 'p', CONS_BOUNDED_GT_0_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+
+ def hypergeometric(self, ngood, nbad, nsample, size=None):
+ """
+ hypergeometric(ngood, nbad, nsample, size=None)
+
+ Draw samples from a Hypergeometric distribution.
+
+ Samples are drawn from a hypergeometric distribution with specified
+ parameters, `ngood` (ways to make a good selection), `nbad` (ways to make
+ a bad selection), and `nsample` (number of items sampled, which is less
+ than or equal to the sum ``ngood + nbad``).
+
+ Parameters
+ ----------
+ ngood : int or array_like of ints
+ Number of ways to make a good selection. Must be nonnegative and
+ less than 10**9.
+ nbad : int or array_like of ints
+ Number of ways to make a bad selection. Must be nonnegative and
+ less than 10**9.
+ nsample : int or array_like of ints
+ Number of items sampled. Must be nonnegative and less than
+ ``ngood + nbad``.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if `ngood`, `nbad`, and `nsample`
+ are all scalars. Otherwise, ``np.broadcast(ngood, nbad, nsample).size``
+ samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized hypergeometric distribution. Each
+ sample is the number of good items within a randomly selected subset of
+ size `nsample` taken from a set of `ngood` good items and `nbad` bad items.
+
+ See Also
+ --------
+ scipy.stats.hypergeom : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability density for the Hypergeometric distribution is
+
+ .. math:: P(x) = \\frac{\\binom{g}{x}\\binom{b}{n-x}}{\\binom{g+b}{n}},
+
+ where :math:`0 \\le x \\le n` and :math:`n-b \\le x \\le g`
+
+ for P(x) the probability of ``x`` good results in the drawn sample,
+ g = `ngood`, b = `nbad`, and n = `nsample`.
+
+ Consider an urn with black and white marbles in it, `ngood` of them
+ are black and `nbad` are white. If you draw `nsample` balls without
+ replacement, then the hypergeometric distribution describes the
+ distribution of black balls in the drawn sample.
+
+ Note that this distribution is very similar to the binomial
+ distribution, except that in this case, samples are drawn without
+ replacement, whereas in the Binomial case samples are drawn with
+ replacement (or the sample space is infinite). As the sample space
+ becomes large, this distribution approaches the binomial.
+
+ The arguments `ngood` and `nbad` each must be less than `10**9`. For
+ extremely large arguments, the algorithm that is used to compute the
+ samples [4]_ breaks down because of loss of precision in floating point
+ calculations. For such large values, if `nsample` is not also large,
+ the distribution can be approximated with the binomial distribution,
+ `binomial(n=nsample, p=ngood/(ngood + nbad))`.
+
+ References
+ ----------
+ .. [1] Lentner, Marvin, "Elementary Applied Statistics", Bogden
+ and Quigley, 1972.
+ .. [2] Weisstein, Eric W. "Hypergeometric Distribution." From
+ MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/HypergeometricDistribution.html
+ .. [3] Wikipedia, "Hypergeometric distribution",
+ https://en.wikipedia.org/wiki/Hypergeometric_distribution
+ .. [4] Stadlober, Ernst, "The ratio of uniforms approach for generating
+ discrete random variates", Journal of Computational and Applied
+ Mathematics, 31, pp. 181-189 (1990).
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> rng = np.random.default_rng()
+ >>> ngood, nbad, nsamp = 100, 2, 10
+ # number of good, number of bad, and number of samples
+ >>> s = rng.hypergeometric(ngood, nbad, nsamp, 1000)
+ >>> from matplotlib.pyplot import hist
+ >>> hist(s)
+ # note that it is very unlikely to grab both bad items
+
+ Suppose you have an urn with 15 white and 15 black marbles.
+ If you pull 15 marbles at random, how likely is it that
+ 12 or more of them are one color?
+
+ >>> s = rng.hypergeometric(15, 15, 15, 100000)
+ >>> sum(s>=12)/100000. + sum(s<=3)/100000.
+ # answer = 0.003 ... pretty unlikely!
+
+ """
+ DEF HYPERGEOM_MAX = 10**9
+ cdef bint is_scalar = True
+ cdef np.ndarray ongood, onbad, onsample
+ cdef int64_t lngood, lnbad, lnsample
+
+ ongood = <np.ndarray>np.PyArray_FROM_OTF(ngood, np.NPY_INT64, np.NPY_ALIGNED)
+ onbad = <np.ndarray>np.PyArray_FROM_OTF(nbad, np.NPY_INT64, np.NPY_ALIGNED)
+ onsample = <np.ndarray>np.PyArray_FROM_OTF(nsample, np.NPY_INT64, np.NPY_ALIGNED)
+
+ if np.PyArray_NDIM(ongood) == np.PyArray_NDIM(onbad) == np.PyArray_NDIM(onsample) == 0:
+
+ lngood = <int64_t>ngood
+ lnbad = <int64_t>nbad
+ lnsample = <int64_t>nsample
+
+ if lngood >= HYPERGEOM_MAX or lnbad >= HYPERGEOM_MAX:
+ raise ValueError("both ngood and nbad must be less than %d" %
+ HYPERGEOM_MAX)
+ if lngood + lnbad < lnsample:
+ raise ValueError("ngood + nbad < nsample")
+ return disc(&random_hypergeometric, &self._bitgen, size, self.lock, 0, 3,
+ lngood, 'ngood', CONS_NON_NEGATIVE,
+ lnbad, 'nbad', CONS_NON_NEGATIVE,
+ lnsample, 'nsample', CONS_NON_NEGATIVE)
+
+ if np.any(ongood >= HYPERGEOM_MAX) or np.any(onbad >= HYPERGEOM_MAX):
+ raise ValueError("both ngood and nbad must be less than %d" %
+ HYPERGEOM_MAX)
+
+ if np.any(np.less(np.add(ongood, onbad), onsample)):
+ raise ValueError("ngood + nbad < nsample")
+
+ return discrete_broadcast_iii(&random_hypergeometric, &self._bitgen, size, self.lock,
+ ongood, 'ngood', CONS_NON_NEGATIVE,
+ onbad, 'nbad', CONS_NON_NEGATIVE,
+ onsample, 'nsample', CONS_NON_NEGATIVE)
+
+ def logseries(self, p, size=None):
+ """
+ logseries(p, size=None)
+
+ Draw samples from a logarithmic series distribution.
+
+ Samples are drawn from a log series distribution with specified
+ shape parameter, 0 < ``p`` < 1.
+
+ Parameters
+ ----------
+ p : float or array_like of floats
+ Shape parameter for the distribution. Must be in the range (0, 1).
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``p`` is a scalar. Otherwise,
+ ``np.array(p).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized logarithmic series distribution.
+
+ See Also
+ --------
+ scipy.stats.logser : probability density function, distribution or
+ cumulative density function, etc.
+
+ Notes
+ -----
+ The probability mass function for the Log Series distribution is
+
+ .. math:: P(k) = \\frac{-p^k}{k \\ln(1-p)},
+
+ where p = probability.
+
+ The log series distribution is frequently used to represent species
+ richness and occurrence, first proposed by Fisher, Corbet, and
+ Williams in 1943 [2]. It may also be used to model the numbers of
+ occupants seen in cars [3].
+
+ References
+ ----------
+ .. [1] Buzas, Martin A.; Culver, Stephen J., Understanding regional
+ species diversity through the log series distribution of
+ occurrences: BIODIVERSITY RESEARCH Diversity & Distributions,
+ Volume 5, Number 5, September 1999 , pp. 187-195(9).
+ .. [2] Fisher, R.A,, A.S. Corbet, and C.B. Williams. 1943. The
+ relation between the number of species and the number of
+ individuals in a random sample of an animal population.
+ Journal of Animal Ecology, 12:42-58.
+ .. [3] D. J. Hand, F. Daly, D. Lunn, E. Ostrowski, A Handbook of Small
+ Data Sets, CRC Press, 1994.
+ .. [4] Wikipedia, "Logarithmic distribution",
+ https://en.wikipedia.org/wiki/Logarithmic_distribution
+
+ Examples
+ --------
+ Draw samples from the distribution:
+
+ >>> a = .6
+ >>> s = np.random.default_rng().logseries(a, 10000)
+ >>> import matplotlib.pyplot as plt
+ >>> count, bins, ignored = plt.hist(s)
+
+ # plot against distribution
+
+ >>> def logseries(k, p):
+ ... return -p**k/(k*np.log(1-p))
+ >>> plt.plot(bins, logseries(bins, a) * count.max()/
+ ... logseries(bins, a).max(), 'r')
+ >>> plt.show()
+
+ """
+ return disc(&random_logseries, &self._bitgen, size, self.lock, 1, 0,
+ p, 'p', CONS_BOUNDED_0_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+
+ # Multivariate distributions:
+ def multivariate_normal(self, mean, cov, size=None, check_valid='warn',
+ tol=1e-8):
+ """
+ multivariate_normal(mean, cov, size=None, check_valid='warn', tol=1e-8)
+
+ Draw random samples from a multivariate normal distribution.
+
+ The multivariate normal, multinormal or Gaussian distribution is a
+ generalization of the one-dimensional normal distribution to higher
+ dimensions. Such a distribution is specified by its mean and
+ covariance matrix. These parameters are analogous to the mean
+ (average or "center") and variance (standard deviation, or "width,"
+ squared) of the one-dimensional normal distribution.
+
+ Parameters
+ ----------
+ mean : 1-D array_like, of length N
+ Mean of the N-dimensional distribution.
+ cov : 2-D array_like, of shape (N, N)
+ Covariance matrix of the distribution. It must be symmetric and
+ positive-semidefinite for proper sampling.
+ size : int or tuple of ints, optional
+ Given a shape of, for example, ``(m,n,k)``, ``m*n*k`` samples are
+ generated, and packed in an `m`-by-`n`-by-`k` arrangement. Because
+ each sample is `N`-dimensional, the output shape is ``(m,n,k,N)``.
+ If no shape is specified, a single (`N`-D) sample is returned.
+ check_valid : { 'warn', 'raise', 'ignore' }, optional
+ Behavior when the covariance matrix is not positive semidefinite.
+ tol : float, optional
+ Tolerance when checking the singular values in covariance matrix.
+ cov is cast to double before the check.
+
+ Returns
+ -------
+ out : ndarray
+ The drawn samples, of shape *size*, if that was provided. If not,
+ the shape is ``(N,)``.
+
+ In other words, each entry ``out[i,j,...,:]`` is an N-dimensional
+ value drawn from the distribution.
+
+ Notes
+ -----
+ The mean is a coordinate in N-dimensional space, which represents the
+ location where samples are most likely to be generated. This is
+ analogous to the peak of the bell curve for the one-dimensional or
+ univariate normal distribution.
+
+ Covariance indicates the level to which two variables vary together.
+ From the multivariate normal distribution, we draw N-dimensional
+ samples, :math:`X = [x_1, x_2, ... x_N]`. The covariance matrix
+ element :math:`C_{ij}` is the covariance of :math:`x_i` and :math:`x_j`.
+ The element :math:`C_{ii}` is the variance of :math:`x_i` (i.e. its
+ "spread").
+
+ Instead of specifying the full covariance matrix, popular
+ approximations include:
+
+ - Spherical covariance (`cov` is a multiple of the identity matrix)
+ - Diagonal covariance (`cov` has non-negative elements, and only on
+ the diagonal)
+
+ This geometrical property can be seen in two dimensions by plotting
+ generated data-points:
+
+ >>> mean = [0, 0]
+ >>> cov = [[1, 0], [0, 100]] # diagonal covariance
+
+ Diagonal covariance means that points are oriented along x or y-axis:
+
+ >>> import matplotlib.pyplot as plt
+ >>> x, y = np.random.default_rng().multivariate_normal(mean, cov, 5000).T
+ >>> plt.plot(x, y, 'x')
+ >>> plt.axis('equal')
+ >>> plt.show()
+
+ Note that the covariance matrix must be positive semidefinite (a.k.a.
+ nonnegative-definite). Otherwise, the behavior of this method is
+ undefined and backwards compatibility is not guaranteed.
+
+ References
+ ----------
+ .. [1] Papoulis, A., "Probability, Random Variables, and Stochastic
+ Processes," 3rd ed., New York: McGraw-Hill, 1991.
+ .. [2] Duda, R. O., Hart, P. E., and Stork, D. G., "Pattern
+ Classification," 2nd ed., New York: Wiley, 2001.
+
+ Examples
+ --------
+ >>> mean = (1, 2)
+ >>> cov = [[1, 0], [0, 1]]
+ >>> x = np.random.default_rng().multivariate_normal(mean, cov, (3, 3))
+ >>> x.shape
+ (3, 3, 2)
+
+ The following is probably true, given that 0.6 is roughly twice the
+ standard deviation:
+
+ >>> list((x[0,0,:] - mean) < 0.6)
+ [True, True] # random
+
+ """
+ from numpy.dual import svd
+
+ # Check preconditions on arguments
+ mean = np.array(mean)
+ cov = np.array(cov)
+ if size is None:
+ shape = []
+ elif isinstance(size, (int, long, np.integer)):
+ shape = [size]
+ else:
+ shape = size
+
+ if len(mean.shape) != 1:
+ raise ValueError("mean must be 1 dimensional")
+ if (len(cov.shape) != 2) or (cov.shape[0] != cov.shape[1]):
+ raise ValueError("cov must be 2 dimensional and square")
+ if mean.shape[0] != cov.shape[0]:
+ raise ValueError("mean and cov must have same length")
+
+ # Compute shape of output and create a matrix of independent
+ # standard normally distributed random numbers. The matrix has rows
+ # with the same length as mean and as many rows are necessary to
+ # form a matrix of shape final_shape.
+ final_shape = list(shape[:])
+ final_shape.append(mean.shape[0])
+ x = self.standard_normal(final_shape).reshape(-1, mean.shape[0])
+
+ # Transform matrix of standard normals into matrix where each row
+ # contains multivariate normals with the desired covariance.
+ # Compute A such that dot(transpose(A),A) == cov.
+ # Then the matrix products of the rows of x and A has the desired
+ # covariance. Note that sqrt(s)*v where (u,s,v) is the singular value
+ # decomposition of cov is such an A.
+ #
+ # Also check that cov is positive-semidefinite. If so, the u.T and v
+ # matrices should be equal up to roundoff error if cov is
+ # symmetric and the singular value of the corresponding row is
+ # not zero. We continue to use the SVD rather than Cholesky in
+ # order to preserve current outputs. Note that symmetry has not
+ # been checked.
+
+ # GH10839, ensure double to make tol meaningful
+ cov = cov.astype(np.double)
+ (u, s, v) = svd(cov)
+
+ if check_valid != 'ignore':
+ if check_valid != 'warn' and check_valid != 'raise':
+ raise ValueError("check_valid must equal 'warn', 'raise', or 'ignore'")
+
+ psd = np.allclose(np.dot(v.T * s, v), cov, rtol=tol, atol=tol)
+ if not psd:
+ if check_valid == 'warn':
+ warnings.warn("covariance is not positive-semidefinite.",
+ RuntimeWarning)
+ else:
+ raise ValueError("covariance is not positive-semidefinite.")
+
+ x = np.dot(x, np.sqrt(s)[:, None] * v)
+ x += mean
+ x.shape = tuple(final_shape)
+ return x
+
+ def multinomial(self, object n, object pvals, size=None):
+ """
+ multinomial(n, pvals, size=None)
+
+ Draw samples from a multinomial distribution.
+
+ The multinomial distribution is a multivariate generalization of the
+ binomial distribution. Take an experiment with one of ``p``
+ possible outcomes. An example of such an experiment is throwing a dice,
+ where the outcome can be 1 through 6. Each sample drawn from the
+ distribution represents `n` such experiments. Its values,
+ ``X_i = [X_0, X_1, ..., X_p]``, represent the number of times the
+ outcome was ``i``.
+
+ Parameters
+ ----------
+ n : int or array-like of ints
+ Number of experiments.
+ pvals : sequence of floats, length p
+ Probabilities of each of the ``p`` different outcomes. These
+ must sum to 1 (however, the last element is always assumed to
+ account for the remaining probability, as long as
+ ``sum(pvals[:-1]) <= 1)``.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+
+ Returns
+ -------
+ out : ndarray
+ The drawn samples, of shape *size*, if that was provided. If not,
+ the shape is ``(N,)``.
+
+ In other words, each entry ``out[i,j,...,:]`` is an N-dimensional
+ value drawn from the distribution.
+
+ Examples
+ --------
+ Throw a dice 20 times:
+
+ >>> rng = np.random.default_rng()
+ >>> rng.multinomial(20, [1/6.]*6, size=1)
+ array([[4, 1, 7, 5, 2, 1]]) # random
+
+ It landed 4 times on 1, once on 2, etc.
+
+ Now, throw the dice 20 times, and 20 times again:
+
+ >>> rng.multinomial(20, [1/6.]*6, size=2)
+ array([[3, 4, 3, 3, 4, 3],
+ [2, 4, 3, 4, 0, 7]]) # random
+
+ For the first run, we threw 3 times 1, 4 times 2, etc. For the second,
+ we threw 2 times 1, 4 times 2, etc.
+
+ Now, do one experiment throwing the dice 10 time, and 10 times again,
+ and another throwing the dice 20 times, and 20 times again:
+
+ >>> rng.multinomial([[10], [20]], [1/6.]*6, size=2)
+ array([[[2, 4, 0, 1, 2, 1],
+ [1, 3, 0, 3, 1, 2]],
+ [[1, 4, 4, 4, 4, 3],
+ [3, 3, 2, 5, 5, 2]]]) # random
+
+ The first array shows the outcomes of throwing the dice 10 times, and
+ the second shows the outcomes from throwing the dice 20 times.
+
+ A loaded die is more likely to land on number 6:
+
+ >>> rng.multinomial(100, [1/7.]*5 + [2/7.])
+ array([11, 16, 14, 17, 16, 26]) # random
+
+ The probability inputs should be normalized. As an implementation
+ detail, the value of the last entry is ignored and assumed to take
+ up any leftover probability mass, but this should not be relied on.
+ A biased coin which has twice as much weight on one side as on the
+ other should be sampled like so:
+
+ >>> rng.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT
+ array([38, 62]) # random
+
+ not like:
+
+ >>> rng.multinomial(100, [1.0, 2.0]) # WRONG
+ Traceback (most recent call last):
+ ValueError: pvals < 0, pvals > 1 or pvals contains NaNs
+
+ """
+
+ cdef np.npy_intp d, i, sz, offset
+ cdef np.ndarray parr, mnarr, on, temp_arr
+ cdef double *pix
+ cdef int64_t *mnix
+ cdef int64_t ni
+ cdef np.broadcast it
+
+ d = len(pvals)
+ on = <np.ndarray>np.PyArray_FROM_OTF(n, np.NPY_INT64, np.NPY_ALIGNED)
+ parr = <np.ndarray>np.PyArray_FROM_OTF(
+ pvals, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
+ pix = <double*>np.PyArray_DATA(parr)
+ check_array_constraint(parr, 'pvals', CONS_BOUNDED_0_1)
+ if kahan_sum(pix, d-1) > (1.0 + 1e-12):
+ raise ValueError("sum(pvals[:-1]) > 1.0")
+
+ if np.PyArray_NDIM(on) != 0: # vector
+ check_array_constraint(on, 'n', CONS_NON_NEGATIVE)
+ if size is None:
+ it = np.PyArray_MultiIterNew1(on)
+ else:
+ temp = np.empty(size, dtype=np.int8)
+ temp_arr = <np.ndarray>temp
+ it = np.PyArray_MultiIterNew2(on, temp_arr)
+ shape = it.shape + (d,)
+ multin = np.zeros(shape, dtype=np.int64)
+ mnarr = <np.ndarray>multin
+ mnix = <int64_t*>np.PyArray_DATA(mnarr)
+ offset = 0
+ sz = it.size
+ with self.lock, nogil:
+ for i in range(sz):
+ ni = (<int64_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
+ random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial)
+ offset += d
+ np.PyArray_MultiIter_NEXT(it)
+ return multin
+
+ if size is None:
+ shape = (d,)
+ else:
+ try:
+ shape = (operator.index(size), d)
+ except:
+ shape = tuple(size) + (d,)
+
+ multin = np.zeros(shape, dtype=np.int64)
+ mnarr = <np.ndarray>multin
+ mnix = <int64_t*>np.PyArray_DATA(mnarr)
+ sz = np.PyArray_SIZE(mnarr)
+ ni = n
+ check_constraint(ni, 'n', CONS_NON_NEGATIVE)
+ offset = 0
+ with self.lock, nogil:
+ for i in range(sz // d):
+ random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial)
+ offset += d
+
+ return multin
+
+ def dirichlet(self, object alpha, size=None):
+ """
+ dirichlet(alpha, size=None)
+
+ Draw samples from the Dirichlet distribution.
+
+ Draw `size` samples of dimension k from a Dirichlet distribution. A
+ Dirichlet-distributed random variable can be seen as a multivariate
+ generalization of a Beta distribution. The Dirichlet distribution
+ is a conjugate prior of a multinomial distribution in Bayesian
+ inference.
+
+ Parameters
+ ----------
+ alpha : array
+ Parameter of the distribution (k dimension for sample of
+ dimension k).
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+
+ Returns
+ -------
+ samples : ndarray,
+ The drawn samples, of shape (size, alpha.ndim).
+
+ Raises
+ -------
+ ValueError
+ If any value in alpha is less than or equal to zero
+
+ Notes
+ -----
+ The Dirichlet distribution is a distribution over vectors
+ :math:`x` that fulfil the conditions :math:`x_i>0` and
+ :math:`\\sum_{i=1}^k x_i = 1`.
+
+ The probability density function :math:`p` of a
+ Dirichlet-distributed random vector :math:`X` is
+ proportional to
+
+ .. math:: p(x) \\propto \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i},
+
+ where :math:`\\alpha` is a vector containing the positive
+ concentration parameters.
+
+ The method uses the following property for computation: let :math:`Y`
+ be a random vector which has components that follow a standard gamma
+ distribution, then :math:`X = \\frac{1}{\\sum_{i=1}^k{Y_i}} Y`
+ is Dirichlet-distributed
+
+ References
+ ----------
+ .. [1] David McKay, "Information Theory, Inference and Learning
+ Algorithms," chapter 23,
+ http://www.inference.org.uk/mackay/itila/
+ .. [2] Wikipedia, "Dirichlet distribution",
+ https://en.wikipedia.org/wiki/Dirichlet_distribution
+
+ Examples
+ --------
+ Taking an example cited in Wikipedia, this distribution can be used if
+ one wanted to cut strings (each of initial length 1.0) into K pieces
+ with different lengths, where each piece had, on average, a designated
+ average length, but allowing some variation in the relative sizes of
+ the pieces.
+
+ >>> s = np.random.default_rng().dirichlet((10, 5, 3), 20).transpose()
+
+ >>> import matplotlib.pyplot as plt
+ >>> plt.barh(range(20), s[0])
+ >>> plt.barh(range(20), s[1], left=s[0], color='g')
+ >>> plt.barh(range(20), s[2], left=s[0]+s[1], color='r')
+ >>> plt.title("Lengths of Strings")
+
+ """
+
+ # =================
+ # Pure python algo
+ # =================
+ # alpha = N.atleast_1d(alpha)
+ # k = alpha.size
+
+ # if n == 1:
+ # val = N.zeros(k)
+ # for i in range(k):
+ # val[i] = sgamma(alpha[i], n)
+ # val /= N.sum(val)
+ # else:
+ # val = N.zeros((k, n))
+ # for i in range(k):
+ # val[i] = sgamma(alpha[i], n)
+ # val /= N.sum(val, axis = 0)
+ # val = val.T
+ # return val
+
+ cdef np.npy_intp k, totsize, i, j
+ cdef np.ndarray alpha_arr, val_arr
+ cdef double *alpha_data
+ cdef double *val_data
+ cdef double acc, invacc
+
+ k = len(alpha)
+ alpha_arr = <np.ndarray>np.PyArray_FROM_OTF(
+ alpha, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
+ if np.any(np.less_equal(alpha_arr, 0)):
+ raise ValueError('alpha <= 0')
+ alpha_data = <double*>np.PyArray_DATA(alpha_arr)
+
+ if size is None:
+ shape = (k,)
+ else:
+ try:
+ shape = (operator.index(size), k)
+ except:
+ shape = tuple(size) + (k,)
+
+ diric = np.zeros(shape, np.float64)
+ val_arr = <np.ndarray>diric
+ val_data= <double*>np.PyArray_DATA(val_arr)
+
+ i = 0
+ totsize = np.PyArray_SIZE(val_arr)
+ with self.lock, nogil:
+ while i < totsize:
+ acc = 0.0
+ for j in range(k):
+ val_data[i+j] = random_standard_gamma_zig(&self._bitgen,
+ alpha_data[j])
+ acc = acc + val_data[i + j]
+ invacc = 1/acc
+ for j in range(k):
+ val_data[i + j] = val_data[i + j] * invacc
+ i = i + k
+
+ return diric
+
+ # Shuffling and permutations:
+ def shuffle(self, object x):
+ """
+ shuffle(x)
+
+ Modify a sequence in-place by shuffling its contents.
+
+ This function only shuffles the array along the first axis of a
+ multi-dimensional array. The order of sub-arrays is changed but
+ their contents remains the same.
+
+ Parameters
+ ----------
+ x : array_like
+ The array or list to be shuffled.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ >>> rng = np.random.default_rng()
+ >>> arr = np.arange(10)
+ >>> rng.shuffle(arr)
+ >>> arr
+ [1 7 5 2 9 4 3 6 0 8] # random
+
+ Multi-dimensional arrays are only shuffled along the first axis:
+
+ >>> arr = np.arange(9).reshape((3, 3))
+ >>> rng.shuffle(arr)
+ >>> arr
+ array([[3, 4, 5], # random
+ [6, 7, 8],
+ [0, 1, 2]])
+
+ """
+ cdef:
+ np.npy_intp i, j, n = len(x), stride, itemsize
+ char* x_ptr
+ char* buf_ptr
+
+ if type(x) is np.ndarray and x.ndim == 1 and x.size:
+ # Fast, statically typed path: shuffle the underlying buffer.
+ # Only for non-empty, 1d objects of class ndarray (subclasses such
+ # as MaskedArrays may not support this approach).
+ x_ptr = <char*><size_t>x.ctypes.data
+ stride = x.strides[0]
+ itemsize = x.dtype.itemsize
+ # As the array x could contain python objects we use a buffer
+ # of bytes for the swaps to avoid leaving one of the objects
+ # within the buffer and erroneously decrementing it's refcount
+ # when the function exits.
+ buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit
+ buf_ptr = <char*><size_t>buf.ctypes.data
+ with self.lock:
+ # We trick gcc into providing a specialized implementation for
+ # the most common case, yielding a ~33% performance improvement.
+ # Note that apparently, only one branch can ever be specialized.
+ if itemsize == sizeof(np.npy_intp):
+ self._shuffle_raw(n, 1, sizeof(np.npy_intp), stride, x_ptr, buf_ptr)
+ else:
+ self._shuffle_raw(n, 1, itemsize, stride, x_ptr, buf_ptr)
+ elif isinstance(x, np.ndarray) and x.ndim and x.size:
+ buf = np.empty_like(x[0, ...])
+ with self.lock:
+ for i in reversed(range(1, n)):
+ j = random_interval(&self._bitgen, i)
+ if i == j:
+ # i == j is not needed and memcpy is undefined.
+ continue
+ buf[...] = x[j]
+ x[j] = x[i]
+ x[i] = buf
+ else:
+ # Untyped path.
+ with self.lock:
+ for i in reversed(range(1, n)):
+ j = random_interval(&self._bitgen, i)
+ x[i], x[j] = x[j], x[i]
+
+ cdef inline _shuffle_raw(self, np.npy_intp n, np.npy_intp first,
+ np.npy_intp itemsize, np.npy_intp stride,
+ char* data, char* buf):
+ """
+ Parameters
+ ----------
+ n
+ Number of elements in data
+ first
+ First observation to shuffle. Shuffles n-1,
+ n-2, ..., first, so that when first=1 the entire
+ array is shuffled
+ itemsize
+ Size in bytes of item
+ stride
+ Array stride
+ data
+ Location of data
+ buf
+ Location of buffer (itemsize)
+ """
+ cdef np.npy_intp i, j
+ for i in reversed(range(first, n)):
+ j = random_interval(&self._bitgen, i)
+ string.memcpy(buf, data + j * stride, itemsize)
+ string.memcpy(data + j * stride, data + i * stride, itemsize)
+ string.memcpy(data + i * stride, buf, itemsize)
+
+ cdef inline void _shuffle_int(self, np.npy_intp n, np.npy_intp first,
+ int64_t* data) nogil:
+ """
+ Parameters
+ ----------
+ n
+ Number of elements in data
+ first
+ First observation to shuffle. Shuffles n-1,
+ n-2, ..., first, so that when first=1 the entire
+ array is shuffled
+ data
+ Location of data
+ """
+ cdef np.npy_intp i, j
+ cdef int64_t temp
+ for i in reversed(range(first, n)):
+ j = random_bounded_uint64(&self._bitgen, 0, i, 0, 0)
+ temp = data[j]
+ data[j] = data[i]
+ data[i] = temp
+
+ def permutation(self, object x):
+ """
+ permutation(x)
+
+ Randomly permute a sequence, or return a permuted range.
+
+ If `x` is a multi-dimensional array, it is only shuffled along its
+ first index.
+
+ Parameters
+ ----------
+ x : int or array_like
+ If `x` is an integer, randomly permute ``np.arange(x)``.
+ If `x` is an array, make a copy and shuffle the elements
+ randomly.
+
+ Returns
+ -------
+ out : ndarray
+ Permuted sequence or array range.
+
+ Examples
+ --------
+ >>> rng = np.random.default_rng()
+ >>> rng.permutation(10)
+ array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random
+
+ >>> rng.permutation([1, 4, 9, 12, 15])
+ array([15, 1, 9, 4, 12]) # random
+
+ >>> arr = np.arange(9).reshape((3, 3))
+ >>> rng.permutation(arr)
+ array([[6, 7, 8], # random
+ [0, 1, 2],
+ [3, 4, 5]])
+
+ """
+ if isinstance(x, (int, np.integer)):
+ arr = np.arange(x)
+ self.shuffle(arr)
+ return arr
+
+ arr = np.asarray(x)
+
+ # shuffle has fast-path for 1-d
+ if arr.ndim == 1:
+ # Return a copy if same memory
+ if np.may_share_memory(arr, x):
+ arr = np.array(arr)
+ self.shuffle(arr)
+ return arr
+
+ # Shuffle index array, dtype to ensure fast path
+ idx = np.arange(arr.shape[0], dtype=np.intp)
+ self.shuffle(idx)
+ return arr[idx]
+
+
+def default_rng(seed=None):
+ """Construct a new Generator with the default BitGenerator (PCG64).
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence, BitGenerator, Generator}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+ Additionally, when passed a `BitGenerator`, it will be wrapped by
+ `Generator`. If passed a `Generator`, it will be returned unaltered.
+
+ Notes
+ -----
+ When `seed` is omitted or ``None``, a new `BitGenerator` and `Generator` will
+ be instantiated each time. This function does not manage a default global
+ instance.
+ """
+ if _check_bit_generator(seed):
+ # We were passed a BitGenerator, so just wrap it up.
+ return Generator(seed)
+ elif isinstance(seed, Generator):
+ # Pass through a Generator.
+ return seed
+ # Otherwise we need to instantiate a new BitGenerator and Generator as
+ # normal.
+ return Generator(PCG64(seed))
diff --git a/numpy/random/legacy_distributions.pxd b/numpy/random/legacy_distributions.pxd
new file mode 100644
index 000000000..7ba058054
--- /dev/null
+++ b/numpy/random/legacy_distributions.pxd
@@ -0,0 +1,48 @@
+#cython: language_level=3
+
+from libc.stdint cimport int64_t
+
+import numpy as np
+cimport numpy as np
+
+from .distributions cimport bitgen_t, binomial_t
+
+cdef extern from "legacy-distributions.h":
+
+ struct aug_bitgen:
+ bitgen_t *bit_generator
+ int has_gauss
+ double gauss
+
+ ctypedef aug_bitgen aug_bitgen_t
+
+ double legacy_gauss(aug_bitgen_t *aug_state) nogil
+ double legacy_pareto(aug_bitgen_t *aug_state, double a) nogil
+ double legacy_weibull(aug_bitgen_t *aug_state, double a) nogil
+ double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape) nogil
+ double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale) nogil
+ double legacy_standard_t(aug_bitgen_t *aug_state, double df) nogil
+
+ double legacy_standard_exponential(aug_bitgen_t *aug_state) nogil
+ double legacy_power(aug_bitgen_t *aug_state, double a) nogil
+ double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale) nogil
+ double legacy_power(aug_bitgen_t *aug_state, double a) nogil
+ double legacy_chisquare(aug_bitgen_t *aug_state, double df) nogil
+ double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df,
+ double nonc) nogil
+ double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum, double dfden,
+ double nonc) nogil
+ double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale) nogil
+ double legacy_lognormal(aug_bitgen_t *aug_state, double mean, double sigma) nogil
+ int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n, double p) nogil
+ int64_t legacy_random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad, int64_t sample) nogil
+ int64_t legacy_random_logseries(bitgen_t *bitgen_state, double p) nogil
+ int64_t legacy_random_poisson(bitgen_t *bitgen_state, double lam) nogil
+ int64_t legacy_random_zipf(bitgen_t *bitgen_state, double a) nogil
+ int64_t legacy_random_geometric(bitgen_t *bitgen_state, double p) nogil
+ void legacy_random_multinomial(bitgen_t *bitgen_state, long n, long *mnix, double *pix, np.npy_intp d, binomial_t *binomial) nogil
+ double legacy_standard_cauchy(aug_bitgen_t *state) nogil
+ double legacy_beta(aug_bitgen_t *aug_state, double a, double b) nogil
+ double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden) nogil
+ double legacy_exponential(aug_bitgen_t *aug_state, double scale) nogil
+ double legacy_power(aug_bitgen_t *state, double a) nogil
diff --git a/numpy/random/mt19937.pyx b/numpy/random/mt19937.pyx
new file mode 100644
index 000000000..49c3622f5
--- /dev/null
+++ b/numpy/random/mt19937.pyx
@@ -0,0 +1,273 @@
+import operator
+
+import numpy as np
+cimport numpy as np
+
+from .common cimport *
+from .bit_generator cimport BitGenerator, SeedSequence
+from .entropy import random_entropy
+
+__all__ = ['MT19937']
+
+np.import_array()
+
+cdef extern from "src/mt19937/mt19937.h":
+
+ struct s_mt19937_state:
+ uint32_t key[624]
+ int pos
+
+ ctypedef s_mt19937_state mt19937_state
+
+ uint64_t mt19937_next64(mt19937_state *state) nogil
+ uint32_t mt19937_next32(mt19937_state *state) nogil
+ double mt19937_next_double(mt19937_state *state) nogil
+ void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key, int key_length)
+ void mt19937_seed(mt19937_state *state, uint32_t seed)
+ void mt19937_jump(mt19937_state *state)
+
+ enum:
+ RK_STATE_LEN
+
+cdef uint64_t mt19937_uint64(void *st) nogil:
+ return mt19937_next64(<mt19937_state *> st)
+
+cdef uint32_t mt19937_uint32(void *st) nogil:
+ return mt19937_next32(<mt19937_state *> st)
+
+cdef double mt19937_double(void *st) nogil:
+ return mt19937_next_double(<mt19937_state *> st)
+
+cdef uint64_t mt19937_raw(void *st) nogil:
+ return <uint64_t>mt19937_next32(<mt19937_state *> st)
+
+cdef class MT19937(BitGenerator):
+ """
+ MT19937(seed=None)
+
+ Container for the Mersenne Twister pseudo-random number generator.
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+
+ Attributes
+ ----------
+ lock: threading.Lock
+ Lock instance that is shared so that the same bit git generator can
+ be used in multiple Generators without corrupting the state. Code that
+ generates values from a bit generator should hold the bit generator's
+ lock.
+
+ Notes
+ -----
+ ``MT19937`` provides a capsule containing function pointers that produce
+ doubles, and unsigned 32 and 64- bit integers [1]_. These are not
+ directly consumable in Python and must be consumed by a ``Generator``
+ or similar object that supports low-level access.
+
+ The Python stdlib module "random" also contains a Mersenne Twister
+ pseudo-random number generator.
+
+ **State and Seeding**
+
+ The ``MT19937`` state vector consists of a 624-element array of
+ 32-bit unsigned integers plus a single integer value between 0 and 624
+ that indexes the current position within the main array.
+
+ The input seed is processed by `SeedSequence` to fill the whole state. The
+ first element is reset such that only its most significant bit is set.
+
+ **Parallel Features**
+
+ The preferred way to use a BitGenerator in parallel applications is to use
+ the `SeedSequence.spawn` method to obtain entropy values, and to use these
+ to generate new BitGenerators:
+
+ >>> from numpy.random import Generator, MT19937, SeedSequence
+ >>> sg = SeedSequence(1234)
+ >>> rg = [Generator(MT19937(s)) for s in sg.spawn(10)]
+
+ Another method is to use `MT19937.jumped` which advances the state as-if
+ :math:`2^{128}` random numbers have been generated ([1]_, [2]_). This
+ allows the original sequence to be split so that distinct segments can be
+ used in each worker process. All generators should be chained to ensure
+ that the segments come from the same sequence.
+
+ >>> from numpy.random import Generator, MT19937, SeedSequence
+ >>> sg = SeedSequence(1234)
+ >>> bit_generator = MT19937(sg)
+ >>> rg = []
+ >>> for _ in range(10):
+ ... rg.append(Generator(bit_generator))
+ ... # Chain the BitGenerators
+ ... bit_generator = bit_generator.jumped()
+
+ **Compatibility Guarantee**
+
+ ``MT19937`` makes a guarantee that a fixed seed and will always produce
+ the same random integer stream.
+
+ References
+ ----------
+ .. [1] Hiroshi Haramoto, Makoto Matsumoto, and Pierre L\'Ecuyer, "A Fast
+ Jump Ahead Algorithm for Linear Recurrences in a Polynomial Space",
+ Sequences and Their Applications - SETA, 290--298, 2008.
+ .. [2] Hiroshi Haramoto, Makoto Matsumoto, Takuji Nishimura, François
+ Panneton, Pierre L\'Ecuyer, "Efficient Jump Ahead for F2-Linear
+ Random Number Generators", INFORMS JOURNAL ON COMPUTING, Vol. 20,
+ No. 3, Summer 2008, pp. 385-390.
+
+ """
+ cdef mt19937_state rng_state
+
+ def __init__(self, seed=None):
+ BitGenerator.__init__(self, seed)
+ val = self._seed_seq.generate_state(RK_STATE_LEN, np.uint32)
+ # MSB is 1; assuring non-zero initial array
+ self.rng_state.key[0] = 0x80000000UL
+ for i in range(1, RK_STATE_LEN):
+ self.rng_state.key[i] = val[i]
+ self.rng_state.pos = i
+
+ self._bitgen.state = &self.rng_state
+ self._bitgen.next_uint64 = &mt19937_uint64
+ self._bitgen.next_uint32 = &mt19937_uint32
+ self._bitgen.next_double = &mt19937_double
+ self._bitgen.next_raw = &mt19937_raw
+
+ def _legacy_seeding(self, seed):
+ """
+ _legacy_seeding(seed)
+
+ Seed the generator in a backward compatible way. For modern
+ applications, creating a new instance is preferable. Calling this
+ overrides self._seed_seq
+
+ Parameters
+ ----------
+ seed : {None, int, array_like}
+ Random seed initializing the pseudo-random number generator.
+ Can be an integer in [0, 2**32-1], array of integers in
+ [0, 2**32-1], a `SeedSequence, or ``None``. If `seed`
+ is ``None``, then sample entropy for a seed.
+
+ Raises
+ ------
+ ValueError
+ If seed values are out of range for the PRNG.
+ """
+ cdef np.ndarray obj
+ with self.lock:
+ try:
+ if seed is None:
+ val = random_entropy(RK_STATE_LEN)
+ # MSB is 1; assuring non-zero initial array
+ self.rng_state.key[0] = 0x80000000UL
+ for i in range(1, RK_STATE_LEN):
+ self.rng_state.key[i] = val[i]
+ else:
+ if hasattr(seed, 'squeeze'):
+ seed = seed.squeeze()
+ idx = operator.index(seed)
+ if idx > int(2**32 - 1) or idx < 0:
+ raise ValueError("Seed must be between 0 and 2**32 - 1")
+ mt19937_seed(&self.rng_state, seed)
+ except TypeError:
+ obj = np.asarray(seed)
+ if obj.size == 0:
+ raise ValueError("Seed must be non-empty")
+ obj = obj.astype(np.int64, casting='safe')
+ if obj.ndim != 1:
+ raise ValueError("Seed array must be 1-d")
+ if ((obj > int(2**32 - 1)) | (obj < 0)).any():
+ raise ValueError("Seed must be between 0 and 2**32 - 1")
+ obj = obj.astype(np.uint32, casting='unsafe', order='C')
+ mt19937_init_by_array(&self.rng_state, <uint32_t*> obj.data, np.PyArray_DIM(obj, 0))
+ self._seed_seq = None
+
+ cdef jump_inplace(self, iter):
+ """
+ Jump state in-place
+
+ Not part of public API
+
+ Parameters
+ ----------
+ iter : integer, positive
+ Number of times to jump the state of the rng.
+ """
+ cdef np.npy_intp i
+ for i in range(iter):
+ mt19937_jump(&self.rng_state)
+
+
+ def jumped(self, np.npy_intp jumps=1):
+ """
+ jumped(jumps=1)
+
+ Returns a new bit generator with the state jumped
+
+ The state of the returned big generator is jumped as-if
+ 2**(128 * jumps) random numbers have been generated.
+
+ Parameters
+ ----------
+ jumps : integer, positive
+ Number of times to jump the state of the bit generator returned
+
+ Returns
+ -------
+ bit_generator : MT19937
+ New instance of generator jumped iter times
+ """
+ cdef MT19937 bit_generator
+
+ bit_generator = self.__class__()
+ bit_generator.state = self.state
+ bit_generator.jump_inplace(jumps)
+
+ return bit_generator
+
+ @property
+ def state(self):
+ """
+ Get or set the PRNG state
+
+ Returns
+ -------
+ state : dict
+ Dictionary containing the information required to describe the
+ state of the PRNG
+ """
+ key = np.zeros(624, dtype=np.uint32)
+ for i in range(624):
+ key[i] = self.rng_state.key[i]
+
+ return {'bit_generator': self.__class__.__name__,
+ 'state': {'key': key, 'pos': self.rng_state.pos}}
+
+ @state.setter
+ def state(self, value):
+ if isinstance(value, tuple):
+ if value[0] != 'MT19937' or len(value) not in (3, 5):
+ raise ValueError('state is not a legacy MT19937 state')
+ value ={'bit_generator': 'MT19937',
+ 'state': {'key': value[1], 'pos': value[2]}}
+
+ if not isinstance(value, dict):
+ raise TypeError('state must be a dict')
+ bitgen = value.get('bit_generator', '')
+ if bitgen != self.__class__.__name__:
+ raise ValueError('state must be for a {0} '
+ 'PRNG'.format(self.__class__.__name__))
+ key = value['state']['key']
+ for i in range(624):
+ self.rng_state.key[i] = key[i]
+ self.rng_state.pos = value['state']['pos']
diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/mtrand.pyx
index 08312da55..46b6b3388 100644
--- a/numpy/random/mtrand/mtrand.pyx
+++ b/numpy/random/mtrand.pyx
@@ -1,627 +1,76 @@
-# mtrand.pyx -- A Pyrex wrapper of Jean-Sebastien Roy's RandomKit
-#
-# Copyright 2005 Robert Kern (robert.kern@gmail.com)
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-include "Python.pxi"
-include "numpy.pxd"
-include "randint_helpers.pxi"
-include "cpython/pycapsule.pxd"
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
+import operator
+import warnings
-from libc cimport string
+import numpy as np
-cdef extern from "math.h":
- double exp(double x)
- double log(double x)
- double floor(double x)
- double sin(double x)
- double cos(double x)
-
-cdef extern from "numpy/npy_math.h":
- int npy_isfinite(double x)
-
-cdef extern from "mtrand_py_helper.h":
- object empty_py_bytes(npy_intp length, void **bytes)
-
-cdef extern from "randomkit.h":
-
- ctypedef struct rk_state:
- unsigned long key[624]
- int pos
- int has_gauss
- double gauss
-
- ctypedef enum rk_error:
- RK_NOERR = 0
- RK_ENODEV = 1
- RK_ERR_MAX = 2
-
- char *rk_strerror[2]
-
- # 0xFFFFFFFFUL
- unsigned long RK_MAX
-
- void rk_seed(unsigned long seed, rk_state *state)
- rk_error rk_randomseed(rk_state *state)
- unsigned long rk_random(rk_state *state)
- long rk_long(rk_state *state) nogil
- unsigned long rk_ulong(rk_state *state) nogil
- unsigned long rk_interval(unsigned long max, rk_state *state) nogil
- double rk_double(rk_state *state) nogil
- void rk_fill(void *buffer, size_t size, rk_state *state) nogil
- rk_error rk_devfill(void *buffer, size_t size, int strong)
- rk_error rk_altfill(void *buffer, size_t size, int strong,
- rk_state *state) nogil
- double rk_gauss(rk_state *state) nogil
- void rk_random_uint64(npy_uint64 off, npy_uint64 rng, npy_intp cnt,
- npy_uint64 *out, rk_state *state) nogil
- void rk_random_uint32(npy_uint32 off, npy_uint32 rng, npy_intp cnt,
- npy_uint32 *out, rk_state *state) nogil
- void rk_random_uint16(npy_uint16 off, npy_uint16 rng, npy_intp cnt,
- npy_uint16 *out, rk_state *state) nogil
- void rk_random_uint8(npy_uint8 off, npy_uint8 rng, npy_intp cnt,
- npy_uint8 *out, rk_state *state) nogil
- void rk_random_bool(npy_bool off, npy_bool rng, npy_intp cnt,
- npy_bool *out, rk_state *state) nogil
-
-
-cdef extern from "distributions.h":
- # do not need the GIL, but they do need a lock on the state !! */
-
- double rk_normal(rk_state *state, double loc, double scale) nogil
- double rk_standard_exponential(rk_state *state) nogil
- double rk_exponential(rk_state *state, double scale) nogil
- double rk_uniform(rk_state *state, double loc, double scale) nogil
- double rk_standard_gamma(rk_state *state, double shape) nogil
- double rk_gamma(rk_state *state, double shape, double scale) nogil
- double rk_beta(rk_state *state, double a, double b) nogil
- double rk_chisquare(rk_state *state, double df) nogil
- double rk_noncentral_chisquare(rk_state *state, double df, double nonc) nogil
- double rk_f(rk_state *state, double dfnum, double dfden) nogil
- double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc) nogil
- double rk_standard_cauchy(rk_state *state) nogil
- double rk_standard_t(rk_state *state, double df) nogil
- double rk_vonmises(rk_state *state, double mu, double kappa) nogil
- double rk_pareto(rk_state *state, double a) nogil
- double rk_weibull(rk_state *state, double a) nogil
- double rk_power(rk_state *state, double a) nogil
- double rk_laplace(rk_state *state, double loc, double scale) nogil
- double rk_gumbel(rk_state *state, double loc, double scale) nogil
- double rk_logistic(rk_state *state, double loc, double scale) nogil
- double rk_lognormal(rk_state *state, double mode, double sigma) nogil
- double rk_rayleigh(rk_state *state, double mode) nogil
- double rk_wald(rk_state *state, double mean, double scale) nogil
- double rk_triangular(rk_state *state, double left, double mode, double right) nogil
-
- long rk_binomial(rk_state *state, long n, double p) nogil
- long rk_binomial_btpe(rk_state *state, long n, double p) nogil
- long rk_binomial_inversion(rk_state *state, long n, double p) nogil
- long rk_negative_binomial(rk_state *state, double n, double p) nogil
- long rk_poisson(rk_state *state, double lam) nogil
- long rk_poisson_mult(rk_state *state, double lam) nogil
- long rk_poisson_ptrs(rk_state *state, double lam) nogil
- long rk_zipf(rk_state *state, double a) nogil
- long rk_geometric(rk_state *state, double p) nogil
- long rk_hypergeometric(rk_state *state, long good, long bad, long sample) nogil
- long rk_logseries(rk_state *state, double p) nogil
-
-ctypedef double (* rk_cont0)(rk_state *state) nogil
-ctypedef double (* rk_cont1)(rk_state *state, double a) nogil
-ctypedef double (* rk_cont2)(rk_state *state, double a, double b) nogil
-ctypedef double (* rk_cont3)(rk_state *state, double a, double b, double c) nogil
-
-ctypedef long (* rk_disc0)(rk_state *state) nogil
-ctypedef long (* rk_discnp)(rk_state *state, long n, double p) nogil
-ctypedef long (* rk_discdd)(rk_state *state, double n, double p) nogil
-ctypedef long (* rk_discnmN)(rk_state *state, long n, long m, long N) nogil
-ctypedef long (* rk_discd)(rk_state *state, double a) nogil
-
-
-cdef extern from "initarray.h":
- void init_by_array(rk_state *self, unsigned long *init_key,
- npy_intp key_length)
-
-# Initialize numpy
-import_array()
+from .bounded_integers import _integers_types
+from .mt19937 import MT19937 as _MT19937
+from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
+from cpython cimport (Py_INCREF, PyFloat_AsDouble)
+from libc cimport string
cimport cython
-import numpy as np
-import operator
-import warnings
+cimport numpy as np
-try:
- from threading import Lock
-except ImportError:
- from dummy_threading import Lock
-
-cdef object cont0_array(rk_state *state, rk_cont0 func, object size,
- object lock):
- cdef double *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state)
- return rv
- else:
- array = <ndarray>np.empty(size, np.float64)
- length = PyArray_SIZE(array)
- array_data = <double *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state)
- return array
-
-
-cdef object cont1_array_sc(rk_state *state, rk_cont1 func, object size, double a,
- object lock):
- cdef double *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, a)
- return rv
- else:
- array = <ndarray>np.empty(size, np.float64)
- length = PyArray_SIZE(array)
- array_data = <double *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, a)
- return array
-
-cdef object cont1_array(rk_state *state, rk_cont1 func, object size,
- ndarray oa, object lock):
- cdef double *array_data
- cdef double *oa_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
- cdef flatiter itera
- cdef broadcast multi
-
- if size is None:
- array = <ndarray>PyArray_SimpleNew(PyArray_NDIM(oa),
- PyArray_DIMS(oa) , NPY_DOUBLE)
- length = PyArray_SIZE(array)
- array_data = <double *>PyArray_DATA(array)
- itera = <flatiter>PyArray_IterNew(<object>oa)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, (<double *>PyArray_ITER_DATA(itera))[0])
- PyArray_ITER_NEXT(itera)
- else:
- array = <ndarray>np.empty(size, np.float64)
- array_data = <double *>PyArray_DATA(array)
- multi = <broadcast>PyArray_MultiIterNew(2, <void *>array,
- <void *>oa)
- if (multi.size != PyArray_SIZE(array)):
- raise ValueError("size is not compatible with inputs")
- with lock, nogil:
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
- return array
-
-cdef object cont2_array_sc(rk_state *state, rk_cont2 func, object size, double a,
- double b, object lock):
- cdef double *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, a, b)
- return rv
- else:
- array = <ndarray>np.empty(size, np.float64)
- length = PyArray_SIZE(array)
- array_data = <double *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, a, b)
- return array
-
-
-cdef object cont2_array(rk_state *state, rk_cont2 func, object size,
- ndarray oa, ndarray ob, object lock):
- cdef double *array_data
- cdef double *oa_data
- cdef double *ob_data
- cdef ndarray array "arrayObject"
- cdef npy_intp i
- cdef broadcast multi
-
- if size is None:
- multi = <broadcast>np.broadcast(oa, ob)
- array = <ndarray>np.empty(multi.shape, dtype=np.float64)
- else:
- array = <ndarray>np.empty(size, dtype=np.float64)
- multi = <broadcast>np.broadcast(oa, ob, array)
- if multi.shape != array.shape:
- raise ValueError("size is not compatible with inputs")
-
- array_data = <double *>PyArray_DATA(array)
-
- with lock, nogil:
- for i in range(multi.size):
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0], ob_data[0])
- PyArray_MultiIter_NEXT(multi)
-
- return array
-
-cdef object cont3_array_sc(rk_state *state, rk_cont3 func, object size, double a,
- double b, double c, object lock):
-
- cdef double *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, a, b, c)
- return rv
- else:
- array = <ndarray>np.empty(size, np.float64)
- length = PyArray_SIZE(array)
- array_data = <double *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, a, b, c)
- return array
-
-cdef object cont3_array(rk_state *state, rk_cont3 func, object size,
- ndarray oa, ndarray ob, ndarray oc, object lock):
-
- cdef double *array_data
- cdef double *oa_data
- cdef double *ob_data
- cdef double *oc_data
- cdef ndarray array "arrayObject"
- cdef npy_intp i
- cdef broadcast multi
-
- if size is None:
- multi = <broadcast>np.broadcast(oa, ob, oc)
- array = <ndarray>np.empty(multi.shape, dtype=np.float64)
- else:
- array = <ndarray>np.empty(size, dtype=np.float64)
- multi = <broadcast>np.broadcast(oa, ob, oc, array)
- if multi.shape != array.shape:
- raise ValueError("size is not compatible with inputs")
-
- array_data = <double *>PyArray_DATA(array)
-
- with lock, nogil:
- for i in range(multi.size):
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- oc_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, oa_data[0], ob_data[0], oc_data[0])
- PyArray_MultiIter_NEXT(multi)
-
- return array
-
-cdef object disc0_array(rk_state *state, rk_disc0 func, object size, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state)
- return rv
- else:
- array = <ndarray>np.empty(size, int)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state)
- return array
-
-cdef object discnp_array_sc(rk_state *state, rk_discnp func, object size,
- long n, double p, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, n, p)
- return rv
- else:
- array = <ndarray>np.empty(size, int)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, n, p)
- return array
-
-cdef object discnp_array(rk_state *state, rk_discnp func, object size,
- ndarray on, ndarray op, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp i
- cdef double *op_data
- cdef long *on_data
- cdef broadcast multi
-
- if size is None:
- multi = <broadcast>np.broadcast(on, op)
- array = <ndarray>np.empty(multi.shape, dtype=int)
- else:
- array = <ndarray>np.empty(size, dtype=int)
- multi = <broadcast>np.broadcast(on, op, array)
- if multi.shape != array.shape:
- raise ValueError("size is not compatible with inputs")
-
- array_data = <long *>PyArray_DATA(array)
-
- with lock, nogil:
- for i in range(multi.size):
- on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXT(multi)
-
- return array
-
-cdef object discdd_array_sc(rk_state *state, rk_discdd func, object size,
- double n, double p, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, n, p)
- return rv
- else:
- array = <ndarray>np.empty(size, int)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, n, p)
- return array
-
-cdef object discdd_array(rk_state *state, rk_discdd func, object size,
- ndarray on, ndarray op, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp i
- cdef double *op_data
- cdef double *on_data
- cdef broadcast multi
-
- if size is None:
- multi = <broadcast>np.broadcast(on, op)
- array = <ndarray>np.empty(multi.shape, dtype=int)
- else:
- array = <ndarray>np.empty(size, dtype=int)
- multi = <broadcast>np.broadcast(on, op, array)
- if multi.shape != array.shape:
- raise ValueError("size is not compatible with inputs")
-
- array_data = <long *>PyArray_DATA(array)
-
- with lock, nogil:
- for i in range(multi.size):
- on_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXT(multi)
-
- return array
-
-cdef object discnmN_array_sc(rk_state *state, rk_discnmN func, object size,
- long n, long m, long N, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, n, m, N)
- return rv
- else:
- array = <ndarray>np.empty(size, int)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, n, m, N)
- return array
-
-cdef object discnmN_array(rk_state *state, rk_discnmN func, object size,
- ndarray on, ndarray om, ndarray oN, object lock):
- cdef long *array_data
- cdef long *on_data
- cdef long *om_data
- cdef long *oN_data
- cdef ndarray array "arrayObject"
- cdef npy_intp i
- cdef broadcast multi
-
- if size is None:
- multi = <broadcast>np.broadcast(on, om, oN)
- array = <ndarray>np.empty(multi.shape, dtype=int)
- else:
- array = <ndarray>np.empty(size, dtype=int)
- multi = <broadcast>np.broadcast(on, om, oN, array)
- if multi.shape != array.shape:
- raise ValueError("size is not compatible with inputs")
-
- array_data = <long *>PyArray_DATA(array)
-
- with lock, nogil:
- for i in range(multi.size):
- on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
- om_data = <long *>PyArray_MultiIter_DATA(multi, 1)
- oN_data = <long *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, on_data[0], om_data[0], oN_data[0])
- PyArray_MultiIter_NEXT(multi)
-
- return array
-
-cdef object discd_array_sc(rk_state *state, rk_discd func, object size,
- double a, object lock):
- cdef long *array_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
-
- if size is None:
- with lock, nogil:
- rv = func(state, a)
- return rv
- else:
- array = <ndarray>np.empty(size, int)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, a)
- return array
-
-cdef object discd_array(rk_state *state, rk_discd func, object size, ndarray oa,
- object lock):
- cdef long *array_data
- cdef double *oa_data
- cdef ndarray array "arrayObject"
- cdef npy_intp length
- cdef npy_intp i
- cdef broadcast multi
- cdef flatiter itera
-
- if size is None:
- array = <ndarray>PyArray_SimpleNew(PyArray_NDIM(oa),
- PyArray_DIMS(oa), NPY_LONG)
- length = PyArray_SIZE(array)
- array_data = <long *>PyArray_DATA(array)
- itera = <flatiter>PyArray_IterNew(<object>oa)
- with lock, nogil:
- for i from 0 <= i < length:
- array_data[i] = func(state, (<double *>PyArray_ITER_DATA(itera))[0])
- PyArray_ITER_NEXT(itera)
- else:
- array = <ndarray>np.empty(size, int)
- array_data = <long *>PyArray_DATA(array)
- multi = <broadcast>PyArray_MultiIterNew(2, <void *>array, <void *>oa)
- if (multi.size != PyArray_SIZE(array)):
- raise ValueError("size is not compatible with inputs")
- with lock, nogil:
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
- return array
-
-cdef double kahan_sum(double *darr, npy_intp n):
- cdef double c, y, t, sum
- cdef npy_intp i
- sum = darr[0]
- c = 0.0
- for i from 1 <= i < n:
- y = darr[i] - c
- t = sum + y
- c = (t-sum) - y
- sum = t
- return sum
-
-def _shape_from_size(size, d):
- if size is None:
- shape = (d,)
- else:
- try:
- shape = (operator.index(size), d)
- except TypeError:
- shape = tuple(size) + (d,)
- return shape
-
-# Look up table for randint functions keyed by dtype.
-# The stored data is a tuple (lbnd, ubnd, func), where lbnd is the smallest
-# value for the type, ubnd is one greater than the largest value, and func is the
-# function to call.
-_randint_type = {
- np.dtype(np.bool_): (0, 2, _rand_bool),
- np.dtype(np.int8): (-2**7, 2**7, _rand_int8),
- np.dtype(np.int16): (-2**15, 2**15, _rand_int16),
- np.dtype(np.int32): (-2**31, 2**31, _rand_int32),
- np.dtype(np.int64): (-2**63, 2**63, _rand_int64),
- np.dtype(np.uint8): (0, 2**8, _rand_uint8),
- np.dtype(np.uint16): (0, 2**16, _rand_uint16),
- np.dtype(np.uint32): (0, 2**32, _rand_uint32),
- np.dtype(np.uint64): (0, 2**64, _rand_uint64)
-}
+from .bounded_integers cimport *
+from .common cimport *
+from .distributions cimport *
+from .legacy_distributions cimport *
+
+np.import_array()
+
+cdef object int64_to_long(object x):
+ """
+ Convert int64 to long for legacy compatibility, which used long for integer
+ distributions
+ """
+ cdef int64_t x64
+
+ if np.isscalar(x):
+ x64 = x
+ return <long>x64
+ return x.astype('l', casting='unsafe')
cdef class RandomState:
"""
RandomState(seed=None)
- Container for the Mersenne Twister pseudo-random number generator.
-
- `RandomState` exposes a number of methods for generating random numbers
- drawn from a variety of probability distributions. In addition to the
- distribution-specific arguments, each method takes a keyword argument
- `size` that defaults to ``None``. If `size` is ``None``, then a single
- value is generated and returned. If `size` is an integer, then a 1-D
- array filled with generated values is returned. If `size` is a tuple,
- then an array with that shape is filled and returned.
-
- *Compatibility Guarantee*
- A fixed seed and a fixed series of calls to 'RandomState' methods using
- the same parameters will always produce the same results up to roundoff
- error except when the values were incorrect. Incorrect values will be
- fixed and the NumPy version in which the fix was made will be noted in
- the relevant docstring. Extension of existing parameter ranges and the
- addition of new parameters is allowed as long the previous behavior
- remains unchanged.
+ Container for the slow Mersenne Twister pseudo-random number generator.
+ Consider using a different BitGenerator with the Generator container
+ instead.
+
+ `RandomState` and `Generator` expose a number of methods for generating
+ random numbers drawn from a variety of probability distributions. In
+ addition to the distribution-specific arguments, each method takes a
+ keyword argument `size` that defaults to ``None``. If `size` is ``None``,
+ then a single value is generated and returned. If `size` is an integer,
+ then a 1-D array filled with generated values is returned. If `size` is a
+ tuple, then an array with that shape is filled and returned.
+
+ **Compatibility Guarantee**
+
+ A fixed bit generator using a fixed seed and a fixed series of calls to
+ 'RandomState' methods using the same parameters will always produce the
+ same results up to roundoff error except when the values were incorrect.
+ `RandomState` is effectively frozen and will only receive updates that
+ are required by changes in the the internals of Numpy. More substantial
+ changes, including algorithmic improvements, are reserved for
+ `Generator`.
Parameters
----------
- seed : {None, int, array_like}, optional
- Random seed used to initialize the pseudo-random number generator. Can
- be any integer between 0 and 2**32 - 1 inclusive, an array (or other
- sequence) of such integers, or ``None`` (the default). If `seed` is
- ``None``, then `RandomState` will try to read data from
- ``/dev/urandom`` (or the Windows analogue) if available or seed from
- the clock otherwise.
+ seed : {None, int, array_like, BitGenerator}, optional
+ Random seed used to initialize the pseudo-random number generator or
+ an instantized BitGenerator. If an integer or array, used as a seed for
+ the MT19937 BitGenerator. Values can be any integer between 0 and
+ 2**32 - 1 inclusive, an array (or other sequence) of such integers,
+ or ``None`` (the default). If `seed` is ``None``, then the `MT19937`
+ BitGenerator is initialized by reading data from ``/dev/urandom``
+ (or the Windows analogue) if available or seed from the clock
+ otherwise.
Notes
-----
@@ -631,70 +80,90 @@ cdef class RandomState:
NumPy-aware, has the advantage that it provides a much larger number
of probability distributions to choose from.
+ See Also
+ --------
+ Generator
+ mt19937.MT19937
+ Bit_Generators
+
"""
- cdef rk_state *internal_state
+ cdef public object _bit_generator
+ cdef bitgen_t _bitgen
+ cdef aug_bitgen_t _aug_state
+ cdef binomial_t _binomial
cdef object lock
- cdef object state_address
- poisson_lam_max = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10
+ _poisson_lam_max = POISSON_LAM_MAX
def __init__(self, seed=None):
- self.internal_state = <rk_state*>PyMem_Malloc(sizeof(rk_state))
- self.state_address = PyCapsule_New(self.internal_state, NULL, NULL)
- self.lock = Lock()
- self.seed(seed)
+ if seed is None:
+ bit_generator = _MT19937()
+ elif not hasattr(seed, 'capsule'):
+ bit_generator = _MT19937()
+ bit_generator._legacy_seeding(seed)
+ else:
+ bit_generator = seed
+
+ self._bit_generator = bit_generator
+ capsule = bit_generator.capsule
+ cdef const char *name = "BitGenerator"
+ if not PyCapsule_IsValid(capsule, name):
+ raise ValueError("Invalid bit generator. The bit generator must "
+ "be instantized.")
+ self._bitgen = (<bitgen_t *> PyCapsule_GetPointer(capsule, name))[0]
+ self._aug_state.bit_generator = &self._bitgen
+ self._reset_gauss()
+ self.lock = bit_generator.lock
+
+ def __repr__(self):
+ return self.__str__() + ' at 0x{:X}'.format(id(self))
+
+ def __str__(self):
+ _str = self.__class__.__name__
+ _str += '(' + self._bit_generator.__class__.__name__ + ')'
+ return _str
+
+ # Pickling support:
+ def __getstate__(self):
+ return self.get_state(legacy=False)
+
+ def __setstate__(self, state):
+ self.set_state(state)
- def __dealloc__(self):
- if self.internal_state != NULL:
- PyMem_Free(self.internal_state)
- self.internal_state = NULL
+ def __reduce__(self):
+ state = self.get_state(legacy=False)
+ from ._pickle import __randomstate_ctor
+ return __randomstate_ctor, (state['bit_generator'],), state
+
+ cdef _reset_gauss(self):
+ self._aug_state.has_gauss = 0
+ self._aug_state.gauss = 0.0
def seed(self, seed=None):
"""
- seed(seed=None)
+ seed(self, seed=None)
- Seed the generator.
+ Reseed a legacy MT19937 BitGenerator
- This method is called when `RandomState` is initialized. It can be
- called again to re-seed the generator. For details, see `RandomState`.
-
- Parameters
- ----------
- seed : int or 1-d array_like, optional
- Seed for `RandomState`.
- Must be convertible to 32 bit unsigned integers.
+ Notes
+ -----
+ This is a convenience, legacy function.
- See Also
- --------
- RandomState
+ The best practice is to **not** reseed a BitGenerator, rather to
+ recreate a new one. This method is here for legacy reasons.
+ This example demonstrates best practice.
+ >>> from numpy.random import MT19937
+ >>> from numpy.random import RandomState, SeedSequence
+ >>> rs = RandomState(MT19937(SeedSequence(123456789)))
+ # Later, you want to restart the stream
+ >>> rs = RandomState(MT19937(SeedSequence(987654321)))
"""
- cdef rk_error errcode
- cdef ndarray obj "arrayObject_obj"
- try:
- if seed is None:
- with self.lock:
- errcode = rk_randomseed(self.internal_state)
- else:
- idx = operator.index(seed)
- if (idx >= 2**32) or (idx < 0):
- raise ValueError("Seed must be between 0 and 2**32 - 1")
- with self.lock:
- rk_seed(idx, self.internal_state)
- except TypeError:
- obj = np.asarray(seed)
- if obj.size == 0:
- raise ValueError("Seed must be non-empty")
- obj = obj.astype(np.int64, casting='safe')
- if obj.ndim != 1:
- raise ValueError("Seed array must be 1-d")
- if ((obj >= 2**32) | (obj < 0)).any():
- raise ValueError("Seed values must be between 0 and 2**32 - 1")
- obj = obj.astype('L', casting='unsafe')
- with self.lock:
- init_by_array(self.internal_state, <unsigned long *>PyArray_DATA(obj),
- PyArray_DIM(obj, 0))
+ if not isinstance(self._bit_generator, _MT19937):
+ raise TypeError('can only re-seed a MT19937 BitGenerator')
+ self._bit_generator._legacy_seeding(seed)
+ self._reset_gauss()
- def get_state(self):
+ def get_state(self, legacy=True):
"""
get_state()
@@ -704,7 +173,7 @@ cdef class RandomState:
Returns
-------
- out : tuple(str, ndarray of 624 uints, int, int, float)
+ out : {tuple(str, ndarray of 624 uints, int, int, float), dict}
The returned tuple has the following items:
1. the string 'MT19937'.
@@ -713,6 +182,13 @@ cdef class RandomState:
4. an integer ``has_gauss``.
5. a float ``cached_gaussian``.
+ If `legacy` is False, or the BitGenerator is not NT19937, then
+ state is returned as a dictionary.
+
+ legacy : bool
+ Flag indicating the return a legacy tuple state when the BitGenerator
+ is MT19937.
+
See Also
--------
set_state
@@ -724,15 +200,18 @@ cdef class RandomState:
the user should know exactly what he/she is doing.
"""
- cdef ndarray state "arrayObject_state"
- state = <ndarray>np.empty(624, np.uint)
- with self.lock:
- memcpy(<void*>PyArray_DATA(state), <void*>(self.internal_state.key), 624*sizeof(long))
- has_gauss = self.internal_state.has_gauss
- gauss = self.internal_state.gauss
- pos = self.internal_state.pos
- state = <ndarray>np.asarray(state, np.uint32)
- return ('MT19937', state, pos, has_gauss, gauss)
+ st = self._bit_generator.state
+ if st['bit_generator'] != 'MT19937' and legacy:
+ warnings.warn('get_state and legacy can only be used with the '
+ 'MT19937 BitGenerator. To silence this warning, '
+ 'set `legacy` to False.', RuntimeWarning)
+ legacy = False
+ st['has_gauss'] = self._aug_state.has_gauss
+ st['gauss'] = self._aug_state.gauss
+ if legacy:
+ return (st['bit_generator'], st['state']['key'], st['state']['pos'],
+ st['has_gauss'], st['gauss'])
+ return st
def set_state(self, state):
"""
@@ -740,12 +219,14 @@ cdef class RandomState:
Set the internal state of the generator from a tuple.
- For use if one has reason to manually (re-)set the internal state of the
- "Mersenne Twister"[1]_ pseudo-random number generating algorithm.
+ For use if one has reason to manually (re-)set the internal state of
+ the bit generator used by the RandomState instance. By default,
+ RandomState uses the "Mersenne Twister"[1]_ pseudo-random number
+ generating algorithm.
Parameters
----------
- state : tuple(str, ndarray of 624 uints, int, int, float)
+ state : {tuple(str, ndarray of 624 uints, int, int, float), dict}
The `state` tuple has the following items:
1. the string 'MT19937', specifying the Mersenne Twister algorithm.
@@ -754,6 +235,9 @@ cdef class RandomState:
4. an integer ``has_gauss``.
5. a float ``cached_gaussian``.
+ If state is a dictionary, it is directly set using the BitGenerators
+ `state` property.
+
Returns
-------
out : None
@@ -781,41 +265,27 @@ cdef class RandomState:
Vol. 8, No. 1, pp. 3-30, Jan. 1998.
"""
- cdef ndarray obj "arrayObject_obj"
- cdef int pos
- algorithm_name = state[0]
- if algorithm_name != 'MT19937':
- raise ValueError("algorithm must be 'MT19937'")
- key, pos = state[1:3]
- if len(state) == 3:
- has_gauss = 0
- cached_gaussian = 0.0
+ if isinstance(state, dict):
+ if 'bit_generator' not in state or 'state' not in state:
+ raise ValueError('state dictionary is not valid.')
+ st = state
else:
- has_gauss, cached_gaussian = state[3:5]
- try:
- obj = <ndarray>PyArray_ContiguousFromObject(key, NPY_ULONG, 1, 1)
- except TypeError:
- # compatibility -- could be an older pickle
- obj = <ndarray>PyArray_ContiguousFromObject(key, NPY_LONG, 1, 1)
- if PyArray_DIM(obj, 0) != 624:
- raise ValueError("state must be 624 longs")
- with self.lock:
- memcpy(<void*>(self.internal_state.key), <void*>PyArray_DATA(obj), 624*sizeof(long))
- self.internal_state.pos = pos
- self.internal_state.has_gauss = has_gauss
- self.internal_state.gauss = cached_gaussian
-
- # Pickling support:
- def __getstate__(self):
- return self.get_state()
-
- def __setstate__(self, state):
- self.set_state(state)
+ if not isinstance(state, (tuple, list)):
+ raise TypeError('state must be a dict or a tuple.')
+ if state[0] != 'MT19937':
+ raise ValueError('set_state can only be used with legacy MT19937'
+ 'state instances.')
+ st = {'bit_generator': state[0],
+ 'state': {'key': state[1], 'pos': state[2]}}
+ if len(state) > 3:
+ st['has_gauss'] = state[3]
+ st['gauss'] = state[4]
+ value = st
+
+ self._aug_state.gauss = st.get('gauss', 0.0)
+ self._aug_state.has_gauss = st.get('has_gauss', 0)
+ self._bit_generator.state = st
- def __reduce__(self):
- return (np.random.__RandomState_ctor, (), self.get_state())
-
- # Basic distributions:
def random_sample(self, size=None):
"""
random_sample(size=None)
@@ -844,30 +314,168 @@ cdef class RandomState:
Examples
--------
>>> np.random.random_sample()
- 0.47108547995356098
+ 0.47108547995356098 # random
>>> type(np.random.random_sample())
- <type 'float'>
+ <class 'float'>
>>> np.random.random_sample((5,))
- array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428])
+ array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random
Three-by-two array of random numbers from [-5, 0):
>>> 5 * np.random.random_sample((3, 2)) - 5
- array([[-3.99149989, -0.52338984],
+ array([[-3.99149989, -0.52338984], # random
[-2.99091858, -0.79479508],
[-1.23204345, -1.75224494]])
"""
- return cont0_array(self.internal_state, rk_double, size, self.lock)
+ cdef double temp
+ return double_fill(&random_double_fill, &self._bitgen, size, self.lock, None)
+
+ def random(self, size=None):
+ """
+ random(size=None)
+
+ Return random floats in the half-open interval [0.0, 1.0). Alias for
+ `random_sample` to ease forward-porting to the new random API.
+ """
+ return self.random_sample(size=size)
+
+ def beta(self, a, b, size=None):
+ """
+ beta(a, b, size=None)
+
+ Draw samples from a Beta distribution.
+
+ The Beta distribution is a special case of the Dirichlet distribution,
+ and is related to the Gamma distribution. It has the probability
+ distribution function
+
+ .. math:: f(x; a,b) = \\frac{1}{B(\\alpha, \\beta)} x^{\\alpha - 1}
+ (1 - x)^{\\beta - 1},
+
+ where the normalization, B, is the beta function,
+
+ .. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1}
+ (1 - t)^{\\beta - 1} dt.
+
+ It is often seen in Bayesian inference and order statistics.
+
+ Parameters
+ ----------
+ a : float or array_like of floats
+ Alpha, positive (>0).
+ b : float or array_like of floats
+ Beta, positive (>0).
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``a`` and ``b`` are both scalars.
+ Otherwise, ``np.broadcast(a, b).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized beta distribution.
+
+ """
+ return cont(&legacy_beta, &self._aug_state, size, self.lock, 2,
+ a, 'a', CONS_POSITIVE,
+ b, 'b', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
+
+ def exponential(self, scale=1.0, size=None):
+ """
+ exponential(scale=1.0, size=None)
+
+ Draw samples from an exponential distribution.
+
+ Its probability density function is
+
+ .. math:: f(x; \\frac{1}{\\beta}) = \\frac{1}{\\beta} \\exp(-\\frac{x}{\\beta}),
+
+ for ``x > 0`` and 0 elsewhere. :math:`\\beta` is the scale parameter,
+ which is the inverse of the rate parameter :math:`\\lambda = 1/\\beta`.
+ The rate parameter is an alternative, widely used parameterization
+ of the exponential distribution [3]_.
+
+ The exponential distribution is a continuous analogue of the
+ geometric distribution. It describes many common situations, such as
+ the size of raindrops measured over many rainstorms [1]_, or the time
+ between page requests to Wikipedia [2]_.
+
+ Parameters
+ ----------
+ scale : float or array_like of floats
+ The scale parameter, :math:`\\beta = 1/\\lambda`. Must be
+ non-negative.
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. If size is ``None`` (default),
+ a single value is returned if ``scale`` is a scalar. Otherwise,
+ ``np.array(scale).size`` samples are drawn.
+
+ Returns
+ -------
+ out : ndarray or scalar
+ Drawn samples from the parameterized exponential distribution.
+
+ References
+ ----------
+ .. [1] Peyton Z. Peebles Jr., "Probability, Random Variables and
+ Random Signal Principles", 4th ed, 2001, p. 57.
+ .. [2] Wikipedia, "Poisson process",
+ https://en.wikipedia.org/wiki/Poisson_process
+ .. [3] Wikipedia, "Exponential distribution",
+ https://en.wikipedia.org/wiki/Exponential_distribution
+
+ """
+ return cont(&legacy_exponential, &self._aug_state, size, self.lock, 1,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ def standard_exponential(self, size=None):
+ """
+ standard_exponential(size=None)
+
+ Draw samples from the standard exponential distribution.
+
+ `standard_exponential` is identical to the exponential distribution
+ with a scale parameter of 1.
+
+ Parameters
+ ----------
+ size : int or tuple of ints, optional
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
+
+ Returns
+ -------
+ out : float or ndarray
+ Drawn samples.
+
+ Examples
+ --------
+ Output a 3x8000 array:
+
+ >>> n = np.random.standard_exponential((3, 8000))
+
+ """
+ return cont(&legacy_standard_exponential, &self._aug_state, size, self.lock, 0,
+ None, None, CONS_NONE,
+ None, None, CONS_NONE,
+ None, None, CONS_NONE,
+ None)
def tomaxint(self, size=None):
"""
tomaxint(size=None)
- Random integers between 0 and ``sys.maxint``, inclusive.
-
Return a sample of uniformly distributed random integers in the interval
- [0, ``sys.maxint``].
+ [0, ``np.iinfo(np.int).max``]. The np.int type translates to the C long
+ integer type and its precision is platform dependent.
Parameters
----------
@@ -889,23 +497,35 @@ cdef class RandomState:
Examples
--------
- >>> RS = np.random.mtrand.RandomState() # need a RandomState object
- >>> RS.tomaxint((2,2,2))
- array([[[1170048599, 1600360186],
+ >>> rs = np.random.RandomState() # need a RandomState object
+ >>> rs.tomaxint((2,2,2))
+ array([[[1170048599, 1600360186], # random
[ 739731006, 1947757578]],
[[1871712945, 752307660],
[1601631370, 1479324245]]])
- >>> import sys
- >>> sys.maxint
- 2147483647
- >>> RS.tomaxint((2,2,2)) < sys.maxint
+ >>> rs.tomaxint((2,2,2)) < np.iinfo(np.int).max
array([[[ True, True],
[ True, True]],
[[ True, True],
[ True, True]]])
"""
- return disc0_array(self.internal_state, rk_long, size, self.lock)
+ cdef np.npy_intp n
+ cdef np.ndarray randoms
+ cdef int64_t *randoms_data
+
+ if size is None:
+ with self.lock:
+ return random_positive_int(&self._bitgen)
+
+ randoms = <np.ndarray>np.empty(size, dtype=np.int64)
+ randoms_data = <int64_t*>np.PyArray_DATA(randoms)
+ n = np.PyArray_SIZE(randoms)
+
+ for i in range(n):
+ with self.lock, nogil:
+ randoms_data[i] = random_positive_int(&self._bitgen)
+ return randoms
def randint(self, low, high=None, size=None, dtype=int):
"""
@@ -919,13 +539,14 @@ cdef class RandomState:
Parameters
----------
- low : int
- Lowest (signed) integer to be drawn from the distribution (unless
+ low : int or array-like of ints
+ Lowest (signed) integers to be drawn from the distribution (unless
``high=None``, in which case this parameter is one above the
*highest* such integer).
- high : int, optional
+ high : int or array-like of ints, optional
If provided, one above the largest (signed) integer to be drawn
from the distribution (see above for behavior if ``high=None``).
+ If array-like, must contain integer values
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
@@ -948,59 +569,86 @@ cdef class RandomState:
--------
random.random_integers : similar to `randint`, only for the closed
interval [`low`, `high`], and 1 is the lowest value if `high` is
- omitted. In particular, this other one is the one to use to generate
- uniformly distributed discrete non-integers.
+ omitted.
Examples
--------
>>> np.random.randint(2, size=10)
- array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])
+ array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random
>>> np.random.randint(1, size=10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Generate a 2 x 4 array of ints between 0 and 4, inclusive:
>>> np.random.randint(5, size=(2, 4))
- array([[4, 0, 2, 1],
+ array([[4, 0, 2, 1], # random
[3, 2, 2, 0]])
+ Generate a 1 x 3 array with 3 different upper bounds
+
+ >>> np.random.randint(1, [3, 5, 10])
+ array([2, 2, 9]) # random
+
+ Generate a 1 by 3 array with 3 different lower bounds
+
+ >>> np.random.randint([1, 5, 7], 10)
+ array([9, 8, 7]) # random
+
+ Generate a 2 by 4 array using broadcasting with dtype of uint8
+
+ >>> np.random.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8)
+ array([[ 8, 6, 9, 7], # random
+ [ 1, 16, 9, 12]], dtype=uint8)
"""
+
if high is None:
high = low
low = 0
- raw_dtype = dtype
- dtype = np.dtype(dtype)
- try:
- lowbnd, highbnd, randfunc = _randint_type[dtype]
- except KeyError:
- raise TypeError('Unsupported dtype "%s" for randint' % dtype)
-
- # TODO: Do not cast these inputs to Python int
- #
- # This is a workaround until gh-8851 is resolved (bug in NumPy
- # integer comparison and subtraction involving uint64 and non-
- # uint64). Afterwards, remove these two lines.
- ilow = int(low)
- ihigh = int(high)
-
- if ilow < lowbnd:
- raise ValueError("low is out of bounds for %s" % dtype)
- if ihigh > highbnd:
- raise ValueError("high is out of bounds for %s" % dtype)
- if ilow >= ihigh and np.prod(size) != 0:
- raise ValueError("Range cannot be empty (low >= high) unless no samples are taken")
-
- with self.lock:
- ret = randfunc(ilow, ihigh - 1, size, self.state_address)
-
- # back-compat: keep python scalars when a python type is passed
- if size is None and raw_dtype in (bool, int, np.long):
- return raw_dtype(ret)
-
+ dt = np.dtype(dtype)
+ key = dt.name
+ if key not in _integers_types:
+ raise TypeError('Unsupported dtype "%s" for randint' % key)
+ if not dt.isnative:
+ # numpy 1.17.0, 2019-05-28
+ warnings.warn('Providing a dtype with a non-native byteorder is '
+ 'not supported. If you require platform-independent '
+ 'byteorder, call byteswap when required.\nIn future '
+ 'version, providing byteorder will raise a '
+ 'ValueError', DeprecationWarning)
+
+ # Implementation detail: the use a masked method to generate
+ # bounded uniform integers. Lemire's method is preferable since it is
+ # faster. randomgen allows a choice, we will always use the slower but
+ # backward compatible one.
+ cdef bint _masked = True
+ cdef bint _endpoint = False
+
+ if key == 'int32':
+ ret = _rand_int32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'int64':
+ ret = _rand_int64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'int16':
+ ret = _rand_int16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'int8':
+ ret = _rand_int8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'uint64':
+ ret = _rand_uint64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'uint32':
+ ret = _rand_uint32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'uint16':
+ ret = _rand_uint16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'uint8':
+ ret = _rand_uint8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+ elif key == 'bool':
+ ret = _rand_bool(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
+
+ if size is None and dtype in (np.bool, np.int, np.long):
+ if np.array(ret).shape == ():
+ return dtype(ret)
return ret
- def bytes(self, npy_intp length):
+ def bytes(self, np.npy_intp length):
"""
bytes(length)
@@ -1022,13 +670,13 @@ cdef class RandomState:
' eh\\x85\\x022SZ\\xbf\\xa4' #random
"""
- cdef void *bytes
- bytestring = empty_py_bytes(length, &bytes)
- with self.lock, nogil:
- rk_fill(bytes, length, self.internal_state)
- return bytestring
-
+ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1)
+ # Interpret the uint32s as little-endian to convert them to bytes
+ # consistently.
+ return self.randint(0, 4294967296, size=n_uint32,
+ dtype=np.uint32).astype('<u4').tobytes()[:length]
+ @cython.wraparound(True)
def choice(self, a, size=None, replace=True, p=None):
"""
choice(a, size=None, replace=True, p=None)
@@ -1038,7 +686,7 @@ cdef class RandomState:
.. versionadded:: 1.7.0
Parameters
- -----------
+ ----------
a : 1-D array-like or int
If an ndarray, a random sample is generated from its elements.
If an int, the random sample is generated as if a were np.arange(a)
@@ -1054,12 +702,12 @@ cdef class RandomState:
entries in a.
Returns
- --------
+ -------
samples : single item or ndarray
The generated random samples
Raises
- -------
+ ------
ValueError
If a is an int and less than zero, if a or p are not 1-dimensional,
if a is an array-like of size 0, if p is not a vector of
@@ -1068,42 +716,42 @@ cdef class RandomState:
size
See Also
- ---------
+ --------
randint, shuffle, permutation
Examples
- ---------
+ --------
Generate a uniform random sample from np.arange(5) of size 3:
>>> np.random.choice(5, 3)
- array([0, 3, 4])
+ array([0, 3, 4]) # random
>>> #This is equivalent to np.random.randint(0,5,3)
Generate a non-uniform random sample from np.arange(5) of size 3:
>>> np.random.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0])
- array([3, 3, 0])
+ array([3, 3, 0]) # random
Generate a uniform random sample from np.arange(5) of size 3 without
replacement:
>>> np.random.choice(5, 3, replace=False)
- array([3,1,0])
+ array([3,1,0]) # random
>>> #This is equivalent to np.random.permutation(np.arange(5))[:3]
Generate a non-uniform random sample from np.arange(5) of size
3 without replacement:
>>> np.random.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0])
- array([2, 3, 0])
+ array([2, 3, 0]) # random
Any of the above can be repeated with an arbitrary array-like
instead of just integers. For instance:
>>> aa_milne_arr = ['pooh', 'rabbit', 'piglet', 'Christopher']
>>> np.random.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3])
- array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'],
- dtype='|S11')
+ array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random
+ dtype='<U11')
"""
@@ -1114,11 +762,11 @@ cdef class RandomState:
# __index__ must return an integer by python rules.
pop_size = operator.index(a.item())
except TypeError:
- raise ValueError("'a' must be 1-dimensional or an integer")
+ raise ValueError("a must be 1-dimensional or an integer")
if pop_size <= 0 and np.prod(size) != 0:
- raise ValueError("'a' must be greater than 0 unless no samples are taken")
+ raise ValueError("a must be greater than 0 unless no samples are taken")
elif a.ndim != 1:
- raise ValueError("'a' must be 1-dimensional")
+ raise ValueError("a must be 1-dimensional")
else:
pop_size = a.shape[0]
if pop_size is 0 and np.prod(size) != 0:
@@ -1132,8 +780,9 @@ cdef class RandomState:
if np.issubdtype(p.dtype, np.floating):
atol = max(atol, np.sqrt(np.finfo(p.dtype).eps))
- p = <ndarray>PyArray_ContiguousFromObject(p, NPY_DOUBLE, 1, 1)
- pix = <double*>PyArray_DATA(p)
+ p = <np.ndarray>np.PyArray_FROM_OTF(
+ p, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
+ pix = <double*>np.PyArray_DATA(p)
if p.ndim != 1:
raise ValueError("'p' must be 1-dimensional")
@@ -1160,15 +809,16 @@ cdef class RandomState:
cdf /= cdf[-1]
uniform_samples = self.random_sample(shape)
idx = cdf.searchsorted(uniform_samples, side='right')
- idx = np.array(idx, copy=False) # searchsorted returns a scalar
+ # searchsorted returns a scalar
+ # force cast to int for LLP64
+ idx = np.array(idx, copy=False).astype(int, casting='unsafe')
else:
idx = self.randint(0, pop_size, size=shape)
else:
if size > pop_size:
raise ValueError("Cannot take a larger sample than "
"population when 'replace=False'")
-
- if size < 0:
+ elif size < 0:
raise ValueError("negative dimensions are not allowed")
if p is not None:
@@ -1176,7 +826,7 @@ cdef class RandomState:
raise ValueError("Fewer non-zero entries in p than size")
n_uniq = 0
p = p.copy()
- found = np.zeros(shape, dtype=np.int)
+ found = np.zeros(shape, dtype=int)
flat_found = found.ravel()
while n_uniq < size:
x = self.rand(size - n_uniq)
@@ -1200,7 +850,7 @@ cdef class RandomState:
# In most cases a scalar will have been made an array
idx = idx.item(0)
- #Use samples as indices for a if a is array-like
+ # Use samples as indices for a if a is array-like
if a.ndim == 0:
return idx
@@ -1216,7 +866,6 @@ cdef class RandomState:
return a[idx]
-
def uniform(self, low=0.0, high=1.0, size=None):
"""
uniform(low=0.0, high=1.0, size=None)
@@ -1294,34 +943,39 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray olow, ohigh, odiff
- cdef double flow, fhigh, fscale
+ cdef bint is_scalar = True
+ cdef np.ndarray alow, ahigh, arange
+ cdef double _low, _high, range
cdef object temp
- olow = <ndarray>PyArray_FROM_OTF(low, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- ohigh = <ndarray>PyArray_FROM_OTF(high, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
+ alow = <np.ndarray>np.PyArray_FROM_OTF(low, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ ahigh = <np.ndarray>np.PyArray_FROM_OTF(high, np.NPY_DOUBLE, np.NPY_ALIGNED)
- if olow.shape == ohigh.shape == ():
- flow = PyFloat_AsDouble(low)
- fhigh = PyFloat_AsDouble(high)
- fscale = fhigh - flow
-
- if not npy_isfinite(fscale):
+ if np.PyArray_NDIM(alow) == np.PyArray_NDIM(ahigh) == 0:
+ _low = PyFloat_AsDouble(low)
+ _high = PyFloat_AsDouble(high)
+ range = _high - _low
+ if not np.isfinite(range):
raise OverflowError('Range exceeds valid bounds')
- return cont2_array_sc(self.internal_state, rk_uniform, size, flow,
- fscale, self.lock)
-
- temp = np.subtract(ohigh, olow)
- Py_INCREF(temp) # needed to get around Pyrex's automatic reference-counting
- # rules because EnsureArray steals a reference
- odiff = <ndarray>PyArray_EnsureArray(temp)
-
- if not np.all(np.isfinite(odiff)):
+ return cont(&random_uniform, &self._bitgen, size, self.lock, 2,
+ _low, '', CONS_NONE,
+ range, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
+
+ temp = np.subtract(ahigh, alow)
+ Py_INCREF(temp)
+ # needed to get around Pyrex's automatic reference-counting
+ # rules because EnsureArray steals a reference
+ arange = <np.ndarray>np.PyArray_EnsureArray(temp)
+ if not np.all(np.isfinite(arange)):
raise OverflowError('Range exceeds valid bounds')
-
- return cont2_array(self.internal_state, rk_uniform, size, olow, odiff,
- self.lock)
+ return cont(&random_uniform, &self._bitgen, size, self.lock, 2,
+ alow, '', CONS_NONE,
+ arange, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
def rand(self, *args):
"""
@@ -1329,6 +983,12 @@ cdef class RandomState:
Random values in a given shape.
+ .. note::
+ This is a convenience function for users porting code from Matlab,
+ and wraps `numpy.random.random_sample`. That function takes a
+ tuple to specify the size of the output, which is consistent with
+ other NumPy functions like `numpy.zeros` and `numpy.ones`.
+
Create an array of the given shape and populate it with
random samples from a uniform distribution
over ``[0, 1)``.
@@ -1336,7 +996,7 @@ cdef class RandomState:
Parameters
----------
d0, d1, ..., dn : int, optional
- The dimensions of the returned array, should all be positive.
+ The dimensions of the returned array, must be non-negative.
If no argument is given a single Python float is returned.
Returns
@@ -1348,12 +1008,6 @@ cdef class RandomState:
--------
random
- Notes
- -----
- This is a convenience function. If you want an interface that
- takes a shape-tuple as the first argument, refer to
- np.random.random_sample .
-
Examples
--------
>>> np.random.rand(3,2)
@@ -1373,21 +1027,22 @@ cdef class RandomState:
Return a sample (or samples) from the "standard normal" distribution.
- If positive, int_like or int-convertible arguments are provided,
- `randn` generates an array of shape ``(d0, d1, ..., dn)``, filled
- with random floats sampled from a univariate "normal" (Gaussian)
- distribution of mean 0 and variance 1 (if any of the :math:`d_i` are
- floats, they are first converted to integers by truncation). A single
- float randomly sampled from the distribution is returned if no
- argument is provided.
+ .. note::
+ This is a convenience function for users porting code from Matlab,
+ and wraps `numpy.random.standard_normal`. That function takes a
+ tuple to specify the size of the output, which is consistent with
+ other NumPy functions like `numpy.zeros` and `numpy.ones`.
- This is a convenience function. If you want an interface that takes a
- tuple as the first argument, use `numpy.random.standard_normal` instead.
+ If positive int_like arguments are provided, `randn` generates an array
+ of shape ``(d0, d1, ..., dn)``, filled
+ with random floats sampled from a univariate "normal" (Gaussian)
+ distribution of mean 0 and variance 1. A single float randomly sampled
+ from the distribution is returned if no argument is provided.
Parameters
----------
d0, d1, ..., dn : int, optional
- The dimensions of the returned array, should be all positive.
+ The dimensions of the returned array, must be non-negative.
If no argument is given a single Python float is returned.
Returns
@@ -1400,6 +1055,7 @@ cdef class RandomState:
See Also
--------
standard_normal : Similar, but takes a tuple as its argument.
+ normal : Also accepts mu and sigma arguments.
Notes
-----
@@ -1410,19 +1066,19 @@ cdef class RandomState:
Examples
--------
>>> np.random.randn()
- 2.1923875335537315 #random
+ 2.1923875335537315 # random
Two-by-four array of samples from N(3, 6.25):
- >>> 2.5 * np.random.randn(2, 4) + 3
- array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random
- [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random
+ >>> 3 + 2.5 * np.random.randn(2, 4)
+ array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
+ [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
"""
if len(args) == 0:
return self.standard_normal()
else:
- return self.standard_normal(args)
+ return self.standard_normal(size=args)
def random_integers(self, low, high=None, size=None):
"""
@@ -1433,8 +1089,8 @@ cdef class RandomState:
Return random integers of type np.int from the "discrete uniform"
distribution in the closed interval [`low`, `high`]. If `high` is
None (the default), then results are from [1, `low`]. The np.int
- type translates to the C long type used by Python 2 for "short"
- integers and its precision is platform dependent.
+ type translates to the C long integer type and its precision
+ is platform dependent.
This function has been deprecated. Use randint instead.
@@ -1476,11 +1132,11 @@ cdef class RandomState:
Examples
--------
>>> np.random.random_integers(5)
- 4
+ 4 # random
>>> type(np.random.random_integers(5))
- <type 'int'>
+ <class 'numpy.int64'>
>>> np.random.random_integers(5, size=(3,2))
- array([[5, 4],
+ array([[5, 4], # random
[3, 3],
[4, 5]])
@@ -1489,7 +1145,7 @@ cdef class RandomState:
:math:`{0, 5/8, 10/8, 15/8, 20/8}`):
>>> 2.5 * (np.random.random_integers(5, size=(5,)) - 1) / 4.
- array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ])
+ array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) # random
Roll two six sided dice 1000 times and sum the results:
@@ -1513,12 +1169,11 @@ cdef class RandomState:
else:
warnings.warn(("This function is deprecated. Please call "
- "randint({low}, {high} + 1) instead".format(
- low=low, high=high)), DeprecationWarning)
-
- return self.randint(low, high + 1, size=size, dtype='l')
-
+ "randint({low}, {high} + 1) "
+ "instead".format(low=low, high=high)),
+ DeprecationWarning)
+ return self.randint(low, int(high) + 1, size=size, dtype='l')
# Complicated, continuous distributions:
def standard_normal(self, size=None):
@@ -1537,22 +1192,49 @@ cdef class RandomState:
Returns
-------
out : float or ndarray
- Drawn samples.
+ A floating-point array of shape ``size`` of drawn samples, or a
+ single sample if ``size`` was not specified.
+
+ Notes
+ -----
+ For random samples from :math:`N(\\mu, \\sigma^2)`, use one of::
+
+ mu + sigma * np.random.standard_normal(size=...)
+ np.random.normal(mu, sigma, size=...)
+
+ See Also
+ --------
+ normal :
+ Equivalent function with additional ``loc`` and ``scale`` arguments
+ for setting the mean and standard deviation.
Examples
--------
+ >>> np.random.standard_normal()
+ 2.1923875335537315 #random
+
>>> s = np.random.standard_normal(8000)
>>> s
- array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random
- -0.38672696, -0.4685006 ]) #random
+ array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, # random
+ -0.38672696, -0.4685006 ]) # random
>>> s.shape
(8000,)
>>> s = np.random.standard_normal(size=(3, 4, 2))
>>> s.shape
(3, 4, 2)
+ Two-by-four array of samples from :math:`N(3, 6.25)`:
+
+ >>> 3 + 2.5 * np.random.standard_normal(size=(2, 4))
+ array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
+ [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
+
"""
- return cont0_array(self.internal_state, rk_gauss, size, self.lock)
+ return cont(&legacy_gauss, &self._aug_state, size, self.lock, 0,
+ None, None, CONS_NONE,
+ None, None, CONS_NONE,
+ None, None, CONS_NONE,
+ None)
def normal(self, loc=0.0, scale=1.0, size=None):
"""
@@ -1575,7 +1257,8 @@ cdef class RandomState:
loc : float or array_like of floats
Mean ("centre") of the distribution.
scale : float or array_like of floats
- Standard deviation (spread or "width") of the distribution.
+ Standard deviation (spread or "width") of the distribution. Must be
+ non-negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -1626,11 +1309,11 @@ cdef class RandomState:
Verify the mean and the variance:
- >>> abs(mu - np.mean(s)) < 0.01
- True
+ >>> abs(mu - np.mean(s))
+ 0.0 # may vary
- >>> abs(sigma - np.std(s, ddof=1)) < 0.01
- True
+ >>> abs(sigma - np.std(s, ddof=1))
+ 0.1 # may vary
Display the histogram of the samples, along with
the probability density function:
@@ -1642,180 +1325,18 @@ cdef class RandomState:
... linewidth=2, color='r')
>>> plt.show()
- """
- cdef ndarray oloc, oscale
- cdef double floc, fscale
-
- oloc = <ndarray>PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oloc.shape == oscale.shape == ():
- floc = PyFloat_AsDouble(loc)
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont2_array_sc(self.internal_state, rk_normal, size, floc,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont2_array(self.internal_state, rk_normal, size, oloc, oscale,
- self.lock)
-
- def beta(self, a, b, size=None):
- """
- beta(a, b, size=None)
-
- Draw samples from a Beta distribution.
-
- The Beta distribution is a special case of the Dirichlet distribution,
- and is related to the Gamma distribution. It has the probability
- distribution function
-
- .. math:: f(x; a,b) = \\frac{1}{B(\\alpha, \\beta)} x^{\\alpha - 1}
- (1 - x)^{\\beta - 1},
-
- where the normalisation, B, is the beta function,
-
- .. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1}
- (1 - t)^{\\beta - 1} dt.
-
- It is often seen in Bayesian inference and order statistics.
-
- Parameters
- ----------
- a : float or array_like of floats
- Alpha, positive (>0).
- b : float or array_like of floats
- Beta, positive (>0).
- size : int or tuple of ints, optional
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn. If size is ``None`` (default),
- a single value is returned if ``a`` and ``b`` are both scalars.
- Otherwise, ``np.broadcast(a, b).size`` samples are drawn.
-
- Returns
- -------
- out : ndarray or scalar
- Drawn samples from the parameterized beta distribution.
-
- """
- cdef ndarray oa, ob
- cdef double fa, fb
-
- oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- ob = <ndarray>PyArray_FROM_OTF(b, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oa.shape == ob.shape == ():
- fa = PyFloat_AsDouble(a)
- fb = PyFloat_AsDouble(b)
-
- if fa <= 0:
- raise ValueError("a <= 0")
- if fb <= 0:
- raise ValueError("b <= 0")
- return cont2_array_sc(self.internal_state, rk_beta, size, fa, fb,
- self.lock)
-
- if np.any(np.less_equal(oa, 0)):
- raise ValueError("a <= 0")
- if np.any(np.less_equal(ob, 0)):
- raise ValueError("b <= 0")
- return cont2_array(self.internal_state, rk_beta, size, oa, ob,
- self.lock)
-
- def exponential(self, scale=1.0, size=None):
- """
- exponential(scale=1.0, size=None)
-
- Draw samples from an exponential distribution.
-
- Its probability density function is
-
- .. math:: f(x; \\frac{1}{\\beta}) = \\frac{1}{\\beta} \\exp(-\\frac{x}{\\beta}),
-
- for ``x > 0`` and 0 elsewhere. :math:`\\beta` is the scale parameter,
- which is the inverse of the rate parameter :math:`\\lambda = 1/\\beta`.
- The rate parameter is an alternative, widely used parameterization
- of the exponential distribution [3]_.
-
- The exponential distribution is a continuous analogue of the
- geometric distribution. It describes many common situations, such as
- the size of raindrops measured over many rainstorms [1]_, or the time
- between page requests to Wikipedia [2]_.
-
- Parameters
- ----------
- scale : float or array_like of floats
- The scale parameter, :math:`\\beta = 1/\\lambda`.
- size : int or tuple of ints, optional
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn. If size is ``None`` (default),
- a single value is returned if ``scale`` is a scalar. Otherwise,
- ``np.array(scale).size`` samples are drawn.
-
- Returns
- -------
- out : ndarray or scalar
- Drawn samples from the parameterized exponential distribution.
-
- References
- ----------
- .. [1] Peyton Z. Peebles Jr., "Probability, Random Variables and
- Random Signal Principles", 4th ed, 2001, p. 57.
- .. [2] Wikipedia, "Poisson process",
- https://en.wikipedia.org/wiki/Poisson_process
- .. [3] Wikipedia, "Exponential distribution",
- https://en.wikipedia.org/wiki/Exponential_distribution
-
- """
- cdef ndarray oscale
- cdef double fscale
-
- oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oscale.shape == ():
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont1_array_sc(self.internal_state, rk_exponential, size,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont1_array(self.internal_state, rk_exponential, size, oscale,
- self.lock)
-
- def standard_exponential(self, size=None):
- """
- standard_exponential(size=None)
-
- Draw samples from the standard exponential distribution.
-
- `standard_exponential` is identical to the exponential distribution
- with a scale parameter of 1.
-
- Parameters
- ----------
- size : int or tuple of ints, optional
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn. Default is None, in which case a
- single value is returned.
-
- Returns
- -------
- out : float or ndarray
- Drawn samples.
-
- Examples
- --------
- Output a 3x8000 array:
+ Two-by-four array of samples from N(3, 6.25):
- >>> n = np.random.standard_exponential((3, 8000))
+ >>> np.random.normal(3, 2.5, size=(2, 4))
+ array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random
+ [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
"""
- return cont0_array(self.internal_state, rk_standard_exponential, size,
- self.lock)
+ return cont(&legacy_normal, &self._aug_state, size, self.lock, 2,
+ loc, '', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ None)
def standard_gamma(self, shape, size=None):
"""
@@ -1829,7 +1350,7 @@ cdef class RandomState:
Parameters
----------
shape : float or array_like of floats
- Parameter, should be > 0.
+ Parameter, must be non-negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -1878,30 +1399,19 @@ cdef class RandomState:
the probability density function:
>>> import matplotlib.pyplot as plt
- >>> import scipy.special as sps
+ >>> import scipy.special as sps # doctest: +SKIP
>>> count, bins, ignored = plt.hist(s, 50, density=True)
- >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\
+ >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ # doctest: +SKIP
... (sps.gamma(shape) * scale**shape))
- >>> plt.plot(bins, y, linewidth=2, color='r')
+ >>> plt.plot(bins, y, linewidth=2, color='r') # doctest: +SKIP
>>> plt.show()
"""
- cdef ndarray oshape
- cdef double fshape
-
- oshape = <ndarray>PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oshape.shape == ():
- fshape = PyFloat_AsDouble(shape)
- if np.signbit(fshape):
- raise ValueError("shape < 0")
- return cont1_array_sc(self.internal_state, rk_standard_gamma,
- size, fshape, self.lock)
-
- if np.any(np.signbit(oshape)):
- raise ValueError("shape < 0")
- return cont1_array(self.internal_state, rk_standard_gamma, size,
- oshape, self.lock)
+ return cont(&legacy_standard_gamma, &self._aug_state, size, self.lock, 1,
+ shape, 'shape', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE,
+ None)
def gamma(self, shape, scale=1.0, size=None):
"""
@@ -1916,9 +1426,9 @@ cdef class RandomState:
Parameters
----------
shape : float or array_like of floats
- The shape of the gamma distribution. Should be greater than zero.
+ The shape of the gamma distribution. Must be non-negative.
scale : float or array_like of floats, optional
- The scale of the gamma distribution. Should be greater than zero.
+ The scale of the gamma distribution. Must be non-negative.
Default is equal to 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
@@ -1968,36 +1478,18 @@ cdef class RandomState:
the probability density function:
>>> import matplotlib.pyplot as plt
- >>> import scipy.special as sps
+ >>> import scipy.special as sps # doctest: +SKIP
>>> count, bins, ignored = plt.hist(s, 50, density=True)
- >>> y = bins**(shape-1)*(np.exp(-bins/scale) /
+ >>> y = bins**(shape-1)*(np.exp(-bins/scale) / # doctest: +SKIP
... (sps.gamma(shape)*scale**shape))
- >>> plt.plot(bins, y, linewidth=2, color='r')
+ >>> plt.plot(bins, y, linewidth=2, color='r') # doctest: +SKIP
>>> plt.show()
"""
- cdef ndarray oshape, oscale
- cdef double fshape, fscale
-
- oshape = <ndarray>PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oshape.shape == oscale.shape == ():
- fshape = PyFloat_AsDouble(shape)
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fshape):
- raise ValueError("shape < 0")
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont2_array_sc(self.internal_state, rk_gamma, size, fshape,
- fscale, self.lock)
-
- if np.any(np.signbit(oshape)):
- raise ValueError("shape < 0")
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont2_array(self.internal_state, rk_gamma, size, oshape, oscale,
- self.lock)
+ return cont(&legacy_gamma, &self._aug_state, size, self.lock, 2,
+ shape, 'shape', CONS_NON_NEGATIVE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def f(self, dfnum, dfden, size=None):
"""
@@ -2007,7 +1499,7 @@ cdef class RandomState:
Samples are drawn from an F distribution with specified parameters,
`dfnum` (degrees of freedom in numerator) and `dfden` (degrees of
- freedom in denominator), where both parameters should be greater than
+ freedom in denominator), where both parameters must be greater than
zero.
The random variate of the F distribution (also known as the
@@ -2018,9 +1510,9 @@ cdef class RandomState:
Parameters
----------
dfnum : float or array_like of floats
- Degrees of freedom in numerator, should be > 0.
+ Degrees of freedom in numerator, must be > 0.
dfden : float or array_like of float
- Degrees of freedom in denominator, should be > 0.
+ Degrees of freedom in denominator, must be > 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2074,37 +1566,18 @@ cdef class RandomState:
The lower bound for the top 1% of the samples is :
- >>> sort(s)[-10]
- 7.61988120985
+ >>> np.sort(s)[-10]
+ 7.61988120985 # random
So there is about a 1% chance that the F statistic will exceed 7.62,
the measured value is 36, so the null hypothesis is rejected at the 1%
level.
"""
- cdef ndarray odfnum, odfden
- cdef double fdfnum, fdfden
-
- odfnum = <ndarray>PyArray_FROM_OTF(dfnum, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- odfden = <ndarray>PyArray_FROM_OTF(dfden, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if odfnum.shape == odfden.shape == ():
- fdfnum = PyFloat_AsDouble(dfnum)
- fdfden = PyFloat_AsDouble(dfden)
-
- if fdfnum <= 0:
- raise ValueError("dfnum <= 0")
- if fdfden <= 0:
- raise ValueError("dfden <= 0")
- return cont2_array_sc(self.internal_state, rk_f, size, fdfnum,
- fdfden, self.lock)
-
- if np.any(np.less_equal(odfnum, 0.0)):
- raise ValueError("dfnum <= 0")
- if np.any(np.less_equal(odfden, 0.0)):
- raise ValueError("dfden <= 0")
- return cont2_array(self.internal_state, rk_f, size, odfnum, odfden,
- self.lock)
+ return cont(&legacy_f, &self._aug_state, size, self.lock, 2,
+ dfnum, 'dfnum', CONS_POSITIVE,
+ dfden, 'dfden', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
def noncentral_f(self, dfnum, dfden, nonc, size=None):
"""
@@ -2120,15 +1593,15 @@ cdef class RandomState:
Parameters
----------
dfnum : float or array_like of floats
- Numerator degrees of freedom, should be > 0.
+ Numerator degrees of freedom, must be > 0.
.. versionchanged:: 1.14.0
Earlier NumPy versions required dfnum > 1.
dfden : float or array_like of floats
- Denominator degrees of freedom, should be > 0.
+ Denominator degrees of freedom, must be > 0.
nonc : float or array_like of floats
Non-centrality parameter, the sum of the squares of the numerator
- means, should be >= 0.
+ means, must be >= 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2178,35 +1651,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray odfnum, odfden, ononc
- cdef double fdfnum, fdfden, fnonc
-
- odfnum = <ndarray>PyArray_FROM_OTF(dfnum, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- odfden = <ndarray>PyArray_FROM_OTF(dfden, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- ononc = <ndarray>PyArray_FROM_OTF(nonc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if odfnum.shape == odfden.shape == ononc.shape == ():
- fdfnum = PyFloat_AsDouble(dfnum)
- fdfden = PyFloat_AsDouble(dfden)
- fnonc = PyFloat_AsDouble(nonc)
-
- if fdfnum <= 0:
- raise ValueError("dfnum <= 0")
- if fdfden <= 0:
- raise ValueError("dfden <= 0")
- if fnonc < 0:
- raise ValueError("nonc < 0")
- return cont3_array_sc(self.internal_state, rk_noncentral_f, size,
- fdfnum, fdfden, fnonc, self.lock)
-
- if np.any(np.less_equal(odfnum, 0.0)):
- raise ValueError("dfnum <= 0")
- if np.any(np.less_equal(odfden, 0.0)):
- raise ValueError("dfden <= 0")
- if np.any(np.less(ononc, 0.0)):
- raise ValueError("nonc < 0")
- return cont3_array(self.internal_state, rk_noncentral_f, size, odfnum,
- odfden, ononc, self.lock)
+ return cont(&legacy_noncentral_f, &self._aug_state, size, self.lock, 3,
+ dfnum, 'dfnum', CONS_POSITIVE,
+ dfden, 'dfden', CONS_POSITIVE,
+ nonc, 'nonc', CONS_NON_NEGATIVE, None)
def chisquare(self, df, size=None):
"""
@@ -2222,7 +1670,7 @@ cdef class RandomState:
Parameters
----------
df : float or array_like of floats
- Number of degrees of freedom, should be > 0.
+ Number of degrees of freedom, must be > 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2268,26 +1716,13 @@ cdef class RandomState:
Examples
--------
>>> np.random.chisquare(2,4)
- array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272])
+ array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random
"""
- cdef ndarray odf
- cdef double fdf
-
- odf = <ndarray>PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if odf.shape == ():
- fdf = PyFloat_AsDouble(df)
-
- if fdf <= 0:
- raise ValueError("df <= 0")
- return cont1_array_sc(self.internal_state, rk_chisquare, size, fdf,
- self.lock)
-
- if np.any(np.less_equal(odf, 0.0)):
- raise ValueError("df <= 0")
- return cont1_array(self.internal_state, rk_chisquare, size, odf,
- self.lock)
+ return cont(&legacy_chisquare, &self._aug_state, size, self.lock, 1,
+ df, 'df', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
def noncentral_chisquare(self, df, nonc, size=None):
"""
@@ -2295,18 +1730,18 @@ cdef class RandomState:
Draw samples from a noncentral chi-square distribution.
- The noncentral :math:`\\chi^2` distribution is a generalisation of
+ The noncentral :math:`\\chi^2` distribution is a generalization of
the :math:`\\chi^2` distribution.
Parameters
----------
df : float or array_like of floats
- Degrees of freedom, should be > 0.
+ Degrees of freedom, must be > 0.
.. versionchanged:: 1.10.0
Earlier NumPy versions required dfnum > 1.
nonc : float or array_like of floats
- Non-centrality, should be non-negative.
+ Non-centrality, must be non-negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2325,21 +1760,13 @@ cdef class RandomState:
.. math:: P(x;df,nonc) = \\sum^{\\infty}_{i=0}
\\frac{e^{-nonc/2}(nonc/2)^{i}}{i!}
- \\P_{Y_{df+2i}}(x),
+ P_{Y_{df+2i}}(x),
where :math:`Y_{q}` is the Chi-square with q degrees of freedom.
- In Delhi (2007), it is noted that the noncentral chi-square is
- useful in bombing and coverage problems, the probability of
- killing the point target given by the noncentral chi-squared
- distribution.
-
References
----------
- .. [1] Delhi, M.S. Holla, "On a noncentral chi-square distribution in
- the analysis of weapon systems effectiveness", Metrika,
- Volume 15, Number 1 / December, 1970.
- .. [2] Wikipedia, "Noncentral chi-squared distribution"
+ .. [1] Wikipedia, "Noncentral chi-squared distribution"
https://en.wikipedia.org/wiki/Noncentral_chi-squared_distribution
Examples
@@ -2371,29 +1798,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray odf, ononc
- cdef double fdf, fnonc
-
- odf = <ndarray>PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- ononc = <ndarray>PyArray_FROM_OTF(nonc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if odf.shape == ononc.shape == ():
- fdf = PyFloat_AsDouble(df)
- fnonc = PyFloat_AsDouble(nonc)
-
- if fdf <= 0:
- raise ValueError("df <= 0")
- if fnonc < 0:
- raise ValueError("nonc < 0")
- return cont2_array_sc(self.internal_state, rk_noncentral_chisquare,
- size, fdf, fnonc, self.lock)
-
- if np.any(np.less_equal(odf, 0.0)):
- raise ValueError("df <= 0")
- if np.any(np.less(ononc, 0.0)):
- raise ValueError("nonc < 0")
- return cont2_array(self.internal_state, rk_noncentral_chisquare, size,
- odf, ononc, self.lock)
+ return cont(&legacy_noncentral_chisquare, &self._aug_state, size, self.lock, 2,
+ df, 'df', CONS_POSITIVE,
+ nonc, 'nonc', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def standard_cauchy(self, size=None):
"""
@@ -2457,8 +1865,8 @@ cdef class RandomState:
>>> plt.show()
"""
- return cont0_array(self.internal_state, rk_standard_cauchy, size,
- self.lock)
+ return cont(&legacy_standard_cauchy, &self._aug_state, size, self.lock, 0,
+ 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None)
def standard_t(self, df, size=None):
"""
@@ -2474,7 +1882,7 @@ cdef class RandomState:
Parameters
----------
df : float or array_like of floats
- Degrees of freedom, should be > 0.
+ Degrees of freedom, must be > 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2548,23 +1956,11 @@ cdef class RandomState:
probability of about 99% of being true.
"""
- cdef ndarray odf
- cdef double fdf
-
- odf = <ndarray> PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if odf.shape == ():
- fdf = PyFloat_AsDouble(df)
-
- if fdf <= 0:
- raise ValueError("df <= 0")
- return cont1_array_sc(self.internal_state, rk_standard_t, size,
- fdf, self.lock)
-
- if np.any(np.less_equal(odf, 0.0)):
- raise ValueError("df <= 0")
- return cont1_array(self.internal_state, rk_standard_t, size, odf,
- self.lock)
+ return cont(&legacy_standard_t, &self._aug_state, size, self.lock, 1,
+ df, 'df', CONS_POSITIVE,
+ 0, '', CONS_NONE,
+ 0, '', CONS_NONE,
+ None)
def vonmises(self, mu, kappa, size=None):
"""
@@ -2636,33 +2032,18 @@ cdef class RandomState:
the probability density function:
>>> import matplotlib.pyplot as plt
- >>> from scipy.special import i0
+ >>> from scipy.special import i0 # doctest: +SKIP
>>> plt.hist(s, 50, density=True)
>>> x = np.linspace(-np.pi, np.pi, num=51)
- >>> y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa))
- >>> plt.plot(x, y, linewidth=2, color='r')
+ >>> y = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa)) # doctest: +SKIP
+ >>> plt.plot(x, y, linewidth=2, color='r') # doctest: +SKIP
>>> plt.show()
"""
- cdef ndarray omu, okappa
- cdef double fmu, fkappa
-
- omu = <ndarray> PyArray_FROM_OTF(mu, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- okappa = <ndarray> PyArray_FROM_OTF(kappa, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if omu.shape == okappa.shape == ():
- fmu = PyFloat_AsDouble(mu)
- fkappa = PyFloat_AsDouble(kappa)
-
- if fkappa < 0:
- raise ValueError("kappa < 0")
- return cont2_array_sc(self.internal_state, rk_vonmises, size, fmu,
- fkappa, self.lock)
-
- if np.any(np.less(okappa, 0.0)):
- raise ValueError("kappa < 0")
- return cont2_array(self.internal_state, rk_vonmises, size, omu, okappa,
- self.lock)
+ return cont(&random_vonmises, &self._bitgen, size, self.lock, 2,
+ mu, 'mu', CONS_NONE,
+ kappa, 'kappa', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def pareto(self, a, size=None):
"""
@@ -2691,7 +2072,7 @@ cdef class RandomState:
Parameters
----------
a : float or array_like of floats
- Shape of the distribution. Should be greater than zero.
+ Shape of the distribution. Must be positive.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2729,7 +2110,6 @@ cdef class RandomState:
projects in Sourceforge [1]_. It is one of the so-called
"fat-tailed" distributions.
-
References
----------
.. [1] Francis Hunt and Paul Johnson, On the Pareto Distribution of
@@ -2757,22 +2137,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray oa
- cdef double fa
-
- oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oa.shape == ():
- fa = PyFloat_AsDouble(a)
-
- if fa <= 0:
- raise ValueError("a <= 0")
- return cont1_array_sc(self.internal_state, rk_pareto, size, fa,
- self.lock)
-
- if np.any(np.less_equal(oa, 0.0)):
- raise ValueError("a <= 0")
- return cont1_array(self.internal_state, rk_pareto, size, oa, self.lock)
+ return cont(&legacy_pareto, &self._aug_state, size, self.lock, 1,
+ a, 'a', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
def weibull(self, a, size=None):
"""
@@ -2867,22 +2235,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray oa
- cdef double fa
-
- oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oa.shape == ():
- fa = PyFloat_AsDouble(a)
- if np.signbit(fa):
- raise ValueError("a < 0")
- return cont1_array_sc(self.internal_state, rk_weibull, size, fa,
- self.lock)
-
- if np.any(np.signbit(oa)):
- raise ValueError("a < 0")
- return cont1_array(self.internal_state, rk_weibull, size, oa,
- self.lock)
+ return cont(&legacy_weibull, &self._aug_state, size, self.lock, 1,
+ a, 'a', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
def power(self, a, size=None):
"""
@@ -2896,7 +2252,7 @@ cdef class RandomState:
Parameters
----------
a : float or array_like of floats
- Parameter of the distribution. Should be greater than zero.
+ Parameter of the distribution. Must be non-negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2957,43 +2313,32 @@ cdef class RandomState:
Compare the power function distribution to the inverse of the Pareto.
- >>> from scipy import stats
+ >>> from scipy import stats # doctest: +SKIP
>>> rvs = np.random.power(5, 1000000)
>>> rvsp = np.random.pareto(5, 1000000)
>>> xx = np.linspace(0,1,100)
- >>> powpdf = stats.powerlaw.pdf(xx,5)
+ >>> powpdf = stats.powerlaw.pdf(xx,5) # doctest: +SKIP
>>> plt.figure()
>>> plt.hist(rvs, bins=50, density=True)
- >>> plt.plot(xx,powpdf,'r-')
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
>>> plt.title('np.random.power(5)')
>>> plt.figure()
>>> plt.hist(1./(1.+rvsp), bins=50, density=True)
- >>> plt.plot(xx,powpdf,'r-')
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
>>> plt.title('inverse of 1 + np.random.pareto(5)')
>>> plt.figure()
>>> plt.hist(1./(1.+rvsp), bins=50, density=True)
- >>> plt.plot(xx,powpdf,'r-')
+ >>> plt.plot(xx,powpdf,'r-') # doctest: +SKIP
>>> plt.title('inverse of stats.pareto(5)')
"""
- cdef ndarray oa
- cdef double fa
-
- oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oa.shape == ():
- fa = PyFloat_AsDouble(a)
- if np.signbit(fa):
- raise ValueError("a < 0")
- return cont1_array_sc(self.internal_state, rk_power, size, fa,
- self.lock)
-
- if np.any(np.signbit(oa)):
- raise ValueError("a < 0")
- return cont1_array(self.internal_state, rk_power, size, oa, self.lock)
+ return cont(&legacy_power, &self._aug_state, size, self.lock, 1,
+ a, 'a', CONS_POSITIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
def laplace(self, loc=0.0, scale=1.0, size=None):
"""
@@ -3012,7 +2357,8 @@ cdef class RandomState:
loc : float or array_like of floats, optional
The position, :math:`\\mu`, of the distribution peak. Default is 0.
scale : float or array_like of floats, optional
- :math:`\\lambda`, the exponential decay. Default is 1.
+ :math:`\\lambda`, the exponential decay. Default is 1. Must be non-
+ negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3074,24 +2420,10 @@ cdef class RandomState:
>>> plt.plot(x,g)
"""
- cdef ndarray oloc, oscale
- cdef double floc, fscale
-
- oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oloc.shape == oscale.shape == ():
- floc = PyFloat_AsDouble(loc)
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont2_array_sc(self.internal_state, rk_laplace, size, floc,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont2_array(self.internal_state, rk_laplace, size, oloc, oscale,
- self.lock)
+ return cont(&random_laplace, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def gumbel(self, loc=0.0, scale=1.0, size=None):
"""
@@ -3108,7 +2440,8 @@ cdef class RandomState:
loc : float or array_like of floats, optional
The location of the mode of the distribution. Default is 0.
scale : float or array_like of floats, optional
- The scale parameter of the distribution. Default is 1.
+ The scale parameter of the distribution. Default is 1. Must be non-
+ negative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3205,24 +2538,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray oloc, oscale
- cdef double floc, fscale
-
- oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oloc.shape == oscale.shape == ():
- floc = PyFloat_AsDouble(loc)
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont2_array_sc(self.internal_state, rk_gumbel, size, floc,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont2_array(self.internal_state, rk_gumbel, size, oloc, oscale,
- self.lock)
+ return cont(&random_gumbel, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def logistic(self, loc=0.0, scale=1.0, size=None):
"""
@@ -3238,7 +2557,7 @@ cdef class RandomState:
loc : float or array_like of floats, optional
Parameter of the distribution. Default is 0.
scale : float or array_like of floats, optional
- Parameter of the distribution. Should be greater than zero.
+ Parameter of the distribution. Must be non-negative.
Default is 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
@@ -3293,30 +2612,16 @@ cdef class RandomState:
# plot against distribution
>>> def logist(x, loc, scale):
- ... return exp((loc-x)/scale)/(scale*(1+exp((loc-x)/scale))**2)
- >>> plt.plot(bins, logist(bins, loc, scale)*count.max()/\\
- ... logist(bins, loc, scale).max())
+ ... return np.exp((loc-x)/scale)/(scale*(1+np.exp((loc-x)/scale))**2)
+ >>> lgst_val = logist(bins, loc, scale)
+ >>> plt.plot(bins, lgst_val * count.max() / lgst_val.max())
>>> plt.show()
"""
- cdef ndarray oloc, oscale
- cdef double floc, fscale
-
- oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oloc.shape == oscale.shape == ():
- floc = PyFloat_AsDouble(loc)
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont2_array_sc(self.internal_state, rk_logistic, size, floc,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0")
- return cont2_array(self.internal_state, rk_logistic, size, oloc,
- oscale, self.lock)
+ return cont(&random_logistic, &self._bitgen, size, self.lock, 2,
+ loc, 'loc', CONS_NONE,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def lognormal(self, mean=0.0, sigma=1.0, size=None):
"""
@@ -3334,8 +2639,8 @@ cdef class RandomState:
mean : float or array_like of floats, optional
Mean value of the underlying normal distribution. Default is 0.
sigma : float or array_like of floats, optional
- Standard deviation of the underlying normal distribution. Should
- be greater than zero. Default is 1.
+ Standard deviation of the underlying normal distribution. Must be
+ non-negative. Default is 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3407,7 +2712,7 @@ cdef class RandomState:
>>> # values, drawn from a normal distribution.
>>> b = []
>>> for i in range(1000):
- ... a = 10. + np.random.random(100)
+ ... a = 10. + np.random.standard_normal(100)
... b.append(np.product(a))
>>> b = np.array(b) / np.min(b) # scale values to be positive
@@ -3423,24 +2728,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray omean, osigma
- cdef double fmean, fsigma
-
- omean = PyArray_FROM_OTF(mean, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- osigma = PyArray_FROM_OTF(sigma, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if omean.shape == osigma.shape == ():
- fmean = PyFloat_AsDouble(mean)
- fsigma = PyFloat_AsDouble(sigma)
- if np.signbit(fsigma):
- raise ValueError("sigma < 0")
- return cont2_array_sc(self.internal_state, rk_lognormal, size,
- fmean, fsigma, self.lock)
-
- if np.any(np.signbit(osigma)):
- raise ValueError("sigma < 0.0")
- return cont2_array(self.internal_state, rk_lognormal, size, omean,
- osigma, self.lock)
+ return cont(&legacy_lognormal, &self._aug_state, size, self.lock, 2,
+ mean, 'mean', CONS_NONE,
+ sigma, 'sigma', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE, None)
def rayleigh(self, scale=1.0, size=None):
"""
@@ -3454,7 +2745,7 @@ cdef class RandomState:
Parameters
----------
scale : float or array_like of floats, optional
- Scale, also equals the mode. Should be >= 0. Default is 1.
+ Scale, also equals the mode. Must be non-negative. Default is 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3502,25 +2793,13 @@ cdef class RandomState:
The percentage of waves larger than 3 meters is:
>>> 100.*sum(s>3)/1000000.
- 0.087300000000000003
+ 0.087300000000000003 # random
"""
- cdef ndarray oscale
- cdef double fscale
-
- oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oscale.shape == ():
- fscale = PyFloat_AsDouble(scale)
- if np.signbit(fscale):
- raise ValueError("scale < 0")
- return cont1_array_sc(self.internal_state, rk_rayleigh, size,
- fscale, self.lock)
-
- if np.any(np.signbit(oscale)):
- raise ValueError("scale < 0.0")
- return cont1_array(self.internal_state, rk_rayleigh, size, oscale,
- self.lock)
+ return cont(&random_rayleigh, &self._bitgen, size, self.lock, 1,
+ scale, 'scale', CONS_NON_NEGATIVE,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE, None)
def wald(self, mean, scale, size=None):
"""
@@ -3540,9 +2819,9 @@ cdef class RandomState:
Parameters
----------
mean : float or array_like of floats
- Distribution mean, should be > 0.
+ Distribution mean, must be > 0.
scale : float or array_like of floats
- Scale parameter, should be >= 0.
+ Scale parameter, must be > 0.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3585,29 +2864,10 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray omean, oscale
- cdef double fmean, fscale
-
- omean = PyArray_FROM_OTF(mean, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if omean.shape == oscale.shape == ():
- fmean = PyFloat_AsDouble(mean)
- fscale = PyFloat_AsDouble(scale)
-
- if fmean <= 0:
- raise ValueError("mean <= 0")
- if fscale <= 0:
- raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_wald, size, fmean,
- fscale, self.lock)
-
- if np.any(np.less_equal(omean,0.0)):
- raise ValueError("mean <= 0.0")
- elif np.any(np.less_equal(oscale,0.0)):
- raise ValueError("scale <= 0.0")
- return cont2_array(self.internal_state, rk_wald, size, omean, oscale,
- self.lock)
+ return cont(&legacy_wald, &self._aug_state, size, self.lock, 2,
+ mean, 'mean', CONS_POSITIVE,
+ scale, 'scale', CONS_POSITIVE,
+ 0.0, '', CONS_NONE, None)
def triangular(self, left, mode, right, size=None):
"""
@@ -3627,9 +2887,9 @@ cdef class RandomState:
Lower limit.
mode : float or array_like of floats
The value where the peak of the distribution occurs.
- The value should fulfill the condition ``left <= mode <= right``.
+ The value must fulfill the condition ``left <= mode <= right``.
right : float or array_like of floats
- Upper limit, should be larger than `left`.
+ Upper limit, must be larger than `left`.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -3672,14 +2932,15 @@ cdef class RandomState:
>>> plt.show()
"""
- cdef ndarray oleft, omode, oright
+ cdef bint is_scalar = True
cdef double fleft, fmode, fright
+ cdef np.ndarray oleft, omode, oright
- oleft = <ndarray>PyArray_FROM_OTF(left, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- omode = <ndarray>PyArray_FROM_OTF(mode, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- oright = <ndarray>PyArray_FROM_OTF(right, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
+ oleft = <np.ndarray>np.PyArray_FROM_OTF(left, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ omode = <np.ndarray>np.PyArray_FROM_OTF(mode, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ oright = <np.ndarray>np.PyArray_FROM_OTF(right, np.NPY_DOUBLE, np.NPY_ALIGNED)
- if oleft.shape == omode.shape == oright.shape == ():
+ if np.PyArray_NDIM(oleft) == np.PyArray_NDIM(omode) == np.PyArray_NDIM(oright) == 0:
fleft = PyFloat_AsDouble(left)
fright = PyFloat_AsDouble(right)
fmode = PyFloat_AsDouble(mode)
@@ -3690,8 +2951,10 @@ cdef class RandomState:
raise ValueError("mode > right")
if fleft == fright:
raise ValueError("left == right")
- return cont3_array_sc(self.internal_state, rk_triangular, size,
- fleft, fmode, fright, self.lock)
+ return cont(&random_triangular, &self._bitgen, size, self.lock, 3,
+ fleft, '', CONS_NONE,
+ fmode, '', CONS_NONE,
+ fright, '', CONS_NONE, None)
if np.any(np.greater(oleft, omode)):
raise ValueError("left > mode")
@@ -3699,8 +2962,11 @@ cdef class RandomState:
raise ValueError("mode > right")
if np.any(np.equal(oleft, oright)):
raise ValueError("left == right")
- return cont3_array(self.internal_state, rk_triangular, size, oleft,
- omode, oright, self.lock)
+
+ return cont_broadcast_3(&random_triangular, &self._bitgen, size, self.lock,
+ oleft, '', CONS_NONE,
+ omode, '', CONS_NONE,
+ oright, '', CONS_NONE)
# Complicated, discrete distributions:
def binomial(self, n, p, size=None):
@@ -3788,36 +3054,63 @@ cdef class RandomState:
# answer = 0.38885, or 38%.
"""
- cdef ndarray on, op
- cdef long ln
- cdef double fp
-
- on = <ndarray>PyArray_FROM_OTF(n, NPY_LONG, NPY_ARRAY_ALIGNED)
- op = <ndarray>PyArray_FROM_OTF(p, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if on.shape == op.shape == ():
- fp = PyFloat_AsDouble(p)
- ln = PyInt_AsLong(n)
-
- if ln < 0:
- raise ValueError("n < 0")
- if fp < 0:
- raise ValueError("p < 0")
- elif fp > 1:
- raise ValueError("p > 1")
- elif np.isnan(fp):
- raise ValueError("p is nan")
- return discnp_array_sc(self.internal_state, rk_binomial, size, ln,
- fp, self.lock)
-
- if np.any(np.less(n, 0)):
- raise ValueError("n < 0")
- if np.any(np.less(p, 0)):
- raise ValueError("p < 0")
- if np.any(np.greater(p, 1)):
- raise ValueError("p > 1")
- return discnp_array(self.internal_state, rk_binomial, size, on, op,
- self.lock)
+
+ # Uses a custom implementation since self._binomial is required
+ cdef double _dp = 0
+ cdef long _in = 0
+ cdef bint is_scalar = True
+ cdef np.npy_intp i, cnt
+ cdef np.ndarray randoms
+ cdef long *randoms_data
+ cdef np.broadcast it
+
+ p_arr = <np.ndarray>np.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(p_arr) == 0
+ n_arr = <np.ndarray>np.PyArray_FROM_OTF(n, np.NPY_LONG, np.NPY_ALIGNED)
+ is_scalar = is_scalar and np.PyArray_NDIM(n_arr) == 0
+
+ if not is_scalar:
+ check_array_constraint(p_arr, 'p', CONS_BOUNDED_0_1)
+ check_array_constraint(n_arr, 'n', CONS_NON_NEGATIVE)
+ if size is not None:
+ randoms = <np.ndarray>np.empty(size, int)
+ else:
+ it = np.PyArray_MultiIterNew2(p_arr, n_arr)
+ randoms = <np.ndarray>np.empty(it.shape, int)
+
+ randoms_data = <long *>np.PyArray_DATA(randoms)
+ cnt = np.PyArray_SIZE(randoms)
+
+ it = np.PyArray_MultiIterNew3(randoms, p_arr, n_arr)
+ with self.lock, nogil:
+ for i in range(cnt):
+ _dp = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
+ _in = (<long*>np.PyArray_MultiIter_DATA(it, 2))[0]
+ (<long*>np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(&self._bitgen, _dp, _in, &self._binomial)
+
+ np.PyArray_MultiIter_NEXT(it)
+
+ return randoms
+
+ _dp = PyFloat_AsDouble(p)
+ _in = <long>n
+ check_constraint(_dp, 'p', CONS_BOUNDED_0_1)
+ check_constraint(<double>_in, 'n', CONS_NON_NEGATIVE)
+
+ if size is None:
+ with self.lock:
+ return random_binomial(&self._bitgen, _dp, _in, &self._binomial)
+
+ randoms = <np.ndarray>np.empty(size, int)
+ cnt = np.PyArray_SIZE(randoms)
+ randoms_data = <long *>np.PyArray_DATA(randoms)
+
+ with self.lock, nogil:
+ for i in range(cnt):
+ randoms_data[i] = random_binomial(&self._bitgen, _dp, _in,
+ &self._binomial)
+
+ return randoms
def negative_binomial(self, n, p, size=None):
"""
@@ -3826,14 +3119,13 @@ cdef class RandomState:
Draw samples from a negative binomial distribution.
Samples are drawn from a negative binomial distribution with specified
- parameters, `n` successes and `p` probability of success where `n` is an
- integer > 0 and `p` is in the interval [0, 1].
+ parameters, `n` successes and `p` probability of success where `n`
+ is > 0 and `p` is in the interval [0, 1].
Parameters
----------
- n : int or array_like of ints
- Parameter of the distribution, > 0. Floats are also accepted,
- but they will be truncated to integers.
+ n : float or array_like of floats
+ Parameter of the distribution, > 0.
p : float or array_like of floats
Parameter of the distribution, >= 0 and <=1.
size : int or tuple of ints, optional
@@ -3851,14 +3143,17 @@ cdef class RandomState:
Notes
-----
- The probability density for the negative binomial distribution is
+ The probability mass function of the negative binomial distribution is
- .. math:: P(N;n,p) = \\binom{N+n-1}{N}p^{n}(1-p)^{N},
+ .. math:: P(N;n,p) = \\frac{\\Gamma(N+n)}{N!\\Gamma(n)}p^{n}(1-p)^{N},
where :math:`n` is the number of successes, :math:`p` is the
- probability of success, and :math:`N+n` is the number of trials.
- The negative binomial distribution gives the probability of N
- failures given n successes, with a success on the last trial.
+ probability of success, :math:`N+n` is the number of trials, and
+ :math:`\\Gamma` is the gamma function. When :math:`n` is an integer,
+ :math:`\\frac{\\Gamma(N+n)}{N!\\Gamma(n)} = \\binom{N+n-1}{N}`, which is
+ the more common form of this term in the the pmf. The negative
+ binomial distribution gives the probability of N failures given n
+ successes, with a success on the last trial.
If one throws a die repeatedly until the third time a "1" appears,
then the probability distribution of the number of non-"1"s that
@@ -3883,40 +3178,17 @@ cdef class RandomState:
single success after drilling 5 wells, after 6 wells, etc.?
>>> s = np.random.negative_binomial(1, 0.1, 100000)
- >>> for i in range(1, 11):
+ >>> for i in range(1, 11): # doctest: +SKIP
... probability = sum(s<i) / 100000.
- ... print i, "wells drilled, probability of one success =", probability
+ ... print(i, "wells drilled, probability of one success =", probability)
"""
- cdef ndarray on
- cdef ndarray op
- cdef double fn
- cdef double fp
-
- on = <ndarray>PyArray_FROM_OTF(n, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
- op = <ndarray>PyArray_FROM_OTF(p, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if on.shape == op.shape == ():
- fp = PyFloat_AsDouble(p)
- fn = PyFloat_AsDouble(n)
-
- if fn <= 0:
- raise ValueError("n <= 0")
- if fp < 0:
- raise ValueError("p < 0")
- elif fp > 1:
- raise ValueError("p > 1")
- return discdd_array_sc(self.internal_state, rk_negative_binomial,
- size, fn, fp, self.lock)
-
- if np.any(np.less_equal(n, 0)):
- raise ValueError("n <= 0")
- if np.any(np.less(p, 0)):
- raise ValueError("p < 0")
- if np.any(np.greater(p, 1)):
- raise ValueError("p > 1")
- return discdd_array(self.internal_state, rk_negative_binomial, size,
- on, op, self.lock)
+ out = disc(&legacy_negative_binomial, &self._aug_state, size, self.lock, 2, 0,
+ n, 'n', CONS_POSITIVE,
+ p, 'p', CONS_BOUNDED_0_1,
+ 0.0, '', CONS_NONE)
+ # Match historical output type
+ return int64_to_long(out)
def poisson(self, lam=1.0, size=None):
"""
@@ -3930,7 +3202,7 @@ cdef class RandomState:
Parameters
----------
lam : float or array_like of floats
- Expectation of interval, should be >= 0. A sequence of expectation
+ Expectation of interval, must be >= 0. A sequence of expectation
intervals must be broadcastable over the requested size.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
@@ -3954,7 +3226,7 @@ cdef class RandomState:
:math:`k` events occurring within the observed
interval :math:`\\lambda`.
- Because the output is limited to the range of the C long type, a
+ Because the output is limited to the range of the C int64 type, a
ValueError is raised when `lam` is within 10 sigma of the maximum
representable value.
@@ -3984,27 +3256,12 @@ cdef class RandomState:
>>> s = np.random.poisson(lam=(100., 500.), size=(100, 2))
"""
- cdef ndarray olam
- cdef double flam
-
- olam = <ndarray>PyArray_FROM_OTF(lam, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if olam.shape == ():
- flam = PyFloat_AsDouble(lam)
-
- if lam < 0:
- raise ValueError("lam < 0")
- if lam > self.poisson_lam_max:
- raise ValueError("lam value too large")
- return discd_array_sc(self.internal_state, rk_poisson, size, flam,
- self.lock)
-
- if np.any(np.less(olam, 0)):
- raise ValueError("lam < 0")
- if np.any(np.greater(olam, self.poisson_lam_max)):
- raise ValueError("lam value too large.")
- return discd_array(self.internal_state, rk_poisson, size, olam,
- self.lock)
+ out = disc(&legacy_random_poisson, &self._bitgen, size, self.lock, 1, 0,
+ lam, 'lam', LEGACY_CONS_POISSON,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+ # Match historical output type
+ return int64_to_long(out)
def zipf(self, a, size=None):
"""
@@ -4023,7 +3280,7 @@ cdef class RandomState:
Parameters
----------
a : float or array_like of floats
- Distribution parameter. Should be greater than 1.
+ Distribution parameter. Must be greater than 1.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -4069,35 +3326,23 @@ cdef class RandomState:
the probability density function:
>>> import matplotlib.pyplot as plt
- >>> from scipy import special
+ >>> from scipy import special # doctest: +SKIP
Truncate s values at 50 so plot is interesting:
>>> count, bins, ignored = plt.hist(s[s<50], 50, density=True)
>>> x = np.arange(1., 50.)
- >>> y = x**(-a) / special.zetac(a)
- >>> plt.plot(x, y/max(y), linewidth=2, color='r')
+ >>> y = x**(-a) / special.zetac(a) # doctest: +SKIP
+ >>> plt.plot(x, y/max(y), linewidth=2, color='r') # doctest: +SKIP
>>> plt.show()
"""
- cdef ndarray oa
- cdef double fa
-
- oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if oa.shape == ():
- fa = PyFloat_AsDouble(a)
-
- # use logic that ensures NaN is rejected.
- if not fa > 1.0:
- raise ValueError("'a' must be a valid float > 1.0")
- return discd_array_sc(self.internal_state, rk_zipf, size, fa,
- self.lock)
-
- # use logic that ensures NaN is rejected.
- if not np.all(np.greater(oa, 1.0)):
- raise ValueError("'a' must contain valid floats > 1.0")
- return discd_array(self.internal_state, rk_zipf, size, oa, self.lock)
+ out = disc(&legacy_random_zipf, &self._bitgen, size, self.lock, 1, 0,
+ a, 'a', CONS_GT_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+ # Match historical output type
+ return int64_to_long(out)
def geometric(self, p, size=None):
"""
@@ -4145,27 +3390,12 @@ cdef class RandomState:
0.34889999999999999 #random
"""
- cdef ndarray op
- cdef double fp
-
- op = <ndarray>PyArray_FROM_OTF(p, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if op.shape == ():
- fp = PyFloat_AsDouble(p)
-
- if fp <= 0.0:
- raise ValueError("p <= 0.0")
- if fp > 1.0:
- raise ValueError("p > 1.0")
- return discd_array_sc(self.internal_state, rk_geometric, size, fp,
- self.lock)
-
- if np.any(np.less_equal(op, 0.0)):
- raise ValueError("p <= 0.0")
- if np.any(np.greater(op, 1.0)):
- raise ValueError("p > 1.0")
- return discd_array(self.internal_state, rk_geometric, size, op,
- self.lock)
+ out = disc(&legacy_random_geometric, &self._bitgen, size, self.lock, 1, 0,
+ p, 'p', CONS_BOUNDED_GT_0_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+ # Match historical output type
+ return int64_to_long(out)
def hypergeometric(self, ngood, nbad, nsample, size=None):
"""
@@ -4174,9 +3404,9 @@ cdef class RandomState:
Draw samples from a Hypergeometric distribution.
Samples are drawn from a hypergeometric distribution with specified
- parameters, ngood (ways to make a good selection), nbad (ways to make
- a bad selection), and nsample = number of items sampled, which is less
- than or equal to the sum ngood + nbad.
+ parameters, `ngood` (ways to make a good selection), `nbad` (ways to make
+ a bad selection), and `nsample` (number of items sampled, which is less
+ than or equal to the sum ``ngood + nbad``).
Parameters
----------
@@ -4190,14 +3420,16 @@ cdef class RandomState:
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
- a single value is returned if ``ngood``, ``nbad``, and ``nsample``
+ a single value is returned if `ngood`, `nbad`, and `nsample`
are all scalars. Otherwise, ``np.broadcast(ngood, nbad, nsample).size``
samples are drawn.
Returns
-------
out : ndarray or scalar
- Drawn samples from the parameterized hypergeometric distribution.
+ Drawn samples from the parameterized hypergeometric distribution. Each
+ sample is the number of good items within a randomly selected subset of
+ size `nsample` taken from a set of `ngood` good items and `nbad` bad items.
See Also
--------
@@ -4212,11 +3444,11 @@ cdef class RandomState:
where :math:`0 \\le x \\le n` and :math:`n-b \\le x \\le g`
- for P(x) the probability of x successes, g = ngood, b = nbad, and
- n = number of samples.
+ for P(x) the probability of ``x`` good results in the drawn sample,
+ g = `ngood`, b = `nbad`, and n = `nsample`.
- Consider an urn with black and white marbles in it, ngood of them
- black and nbad are white. If you draw nsample balls without
+ Consider an urn with black and white marbles in it, `ngood` of them
+ are black and `nbad` are white. If you draw `nsample` balls without
replacement, then the hypergeometric distribution describes the
distribution of black balls in the drawn sample.
@@ -4256,39 +3488,42 @@ cdef class RandomState:
# answer = 0.003 ... pretty unlikely!
"""
- cdef ndarray ongood, onbad, onsample
- cdef long lngood, lnbad, lnsample
-
- ongood = <ndarray>PyArray_FROM_OTF(ngood, NPY_LONG, NPY_ARRAY_ALIGNED)
- onbad = <ndarray>PyArray_FROM_OTF(nbad, NPY_LONG, NPY_ARRAY_ALIGNED)
- onsample = <ndarray>PyArray_FROM_OTF(nsample, NPY_LONG, NPY_ARRAY_ALIGNED)
-
- if ongood.shape == onbad.shape == onsample.shape == ():
- lngood = PyInt_AsLong(ngood)
- lnbad = PyInt_AsLong(nbad)
- lnsample = PyInt_AsLong(nsample)
-
- if lngood < 0:
- raise ValueError("ngood < 0")
- if lnbad < 0:
- raise ValueError("nbad < 0")
- if lnsample < 1:
- raise ValueError("nsample < 1")
+ cdef bint is_scalar = True
+ cdef np.ndarray ongood, onbad, onsample
+ cdef int64_t lngood, lnbad, lnsample
+
+ # This cast to long is required to ensure that the values are inbounds
+ ongood = <np.ndarray>np.PyArray_FROM_OTF(ngood, np.NPY_LONG, np.NPY_ALIGNED)
+ onbad = <np.ndarray>np.PyArray_FROM_OTF(nbad, np.NPY_LONG, np.NPY_ALIGNED)
+ onsample = <np.ndarray>np.PyArray_FROM_OTF(nsample, np.NPY_LONG, np.NPY_ALIGNED)
+
+ if np.PyArray_NDIM(ongood) == np.PyArray_NDIM(onbad) == np.PyArray_NDIM(onsample) == 0:
+
+ lngood = <int64_t>ngood
+ lnbad = <int64_t>nbad
+ lnsample = <int64_t>nsample
+
if lngood + lnbad < lnsample:
raise ValueError("ngood + nbad < nsample")
- return discnmN_array_sc(self.internal_state, rk_hypergeometric,
- size, lngood, lnbad, lnsample, self.lock)
-
- if np.any(np.less(ongood, 0)):
- raise ValueError("ngood < 0")
- if np.any(np.less(onbad, 0)):
- raise ValueError("nbad < 0")
- if np.any(np.less(onsample, 1)):
- raise ValueError("nsample < 1")
- if np.any(np.less(np.add(ongood, onbad),onsample)):
+ out = disc(&legacy_random_hypergeometric, &self._bitgen, size, self.lock, 0, 3,
+ lngood, 'ngood', CONS_NON_NEGATIVE,
+ lnbad, 'nbad', CONS_NON_NEGATIVE,
+ lnsample, 'nsample', CONS_GTE_1)
+ # Match historical output type
+ return int64_to_long(out)
+
+ if np.any(np.less(np.add(ongood, onbad), onsample)):
raise ValueError("ngood + nbad < nsample")
- return discnmN_array(self.internal_state, rk_hypergeometric, size,
- ongood, onbad, onsample, self.lock)
+ # Convert to int64, if necessary, to use int64 infrastructure
+ ongood = ongood.astype(np.int64)
+ onbad = onbad.astype(np.int64)
+ onbad = onbad.astype(np.int64)
+ out = discrete_broadcast_iii(&legacy_random_hypergeometric,&self._bitgen, size, self.lock,
+ ongood, 'ngood', CONS_NON_NEGATIVE,
+ onbad, 'nbad', CONS_NON_NEGATIVE,
+ onsample, 'nsample', CONS_GTE_1)
+ # Match historical output type
+ return int64_to_long(out)
def logseries(self, p, size=None):
"""
@@ -4359,39 +3594,24 @@ cdef class RandomState:
# plot against distribution
>>> def logseries(k, p):
- ... return -p**k/(k*log(1-p))
+ ... return -p**k/(k*np.log(1-p))
>>> plt.plot(bins, logseries(bins, a)*count.max()/
- logseries(bins, a).max(), 'r')
+ ... logseries(bins, a).max(), 'r')
>>> plt.show()
"""
- cdef ndarray op
- cdef double fp
-
- op = <ndarray>PyArray_FROM_OTF(p, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
-
- if op.shape == ():
- fp = PyFloat_AsDouble(p)
-
- if fp <= 0.0:
- raise ValueError("p <= 0.0")
- if fp >= 1.0:
- raise ValueError("p >= 1.0")
- return discd_array_sc(self.internal_state, rk_logseries, size, fp,
- self.lock)
-
- if np.any(np.less_equal(op, 0.0)):
- raise ValueError("p <= 0.0")
- if np.any(np.greater_equal(op, 1.0)):
- raise ValueError("p >= 1.0")
- return discd_array(self.internal_state, rk_logseries, size, op,
- self.lock)
+ out = disc(&legacy_random_logseries, &self._bitgen, size, self.lock, 1, 0,
+ p, 'p', CONS_BOUNDED_0_1,
+ 0.0, '', CONS_NONE,
+ 0.0, '', CONS_NONE)
+ # Match historical output type
+ return int64_to_long(out)
# Multivariate distributions:
def multivariate_normal(self, mean, cov, size=None, check_valid='warn',
tol=1e-8):
"""
- multivariate_normal(mean, cov[, size, check_valid, tol])
+ multivariate_normal(mean, cov, size=None, check_valid='warn', tol=1e-8)
Draw random samples from a multivariate normal distribution.
@@ -4487,7 +3707,7 @@ cdef class RandomState:
standard deviation:
>>> list((x[0,0,:] - mean) < 0.6)
- [True, True]
+ [True, True] # random
"""
from numpy.dual import svd
@@ -4497,7 +3717,7 @@ cdef class RandomState:
cov = np.array(cov)
if size is None:
shape = []
- elif isinstance(size, (int, long, np.integer)):
+ elif isinstance(size, (int, np.integer)):
shape = [size]
else:
shape = size
@@ -4524,11 +3744,12 @@ cdef class RandomState:
# covariance. Note that sqrt(s)*v where (u,s,v) is the singular value
# decomposition of cov is such an A.
#
- # Also check that cov is symmetric positive-semidefinite. If so, the u.T and v
+ # Also check that cov is positive-semidefinite. If so, the u.T and v
# matrices should be equal up to roundoff error if cov is
# symmetric and the singular value of the corresponding row is
# not zero. We continue to use the SVD rather than Cholesky in
- # order to preserve current outputs.
+ # order to preserve current outputs. Note that symmetry has not
+ # been checked.
# GH10839, ensure double to make tol meaningful
cov = cov.astype(np.double)
@@ -4536,30 +3757,30 @@ cdef class RandomState:
if check_valid != 'ignore':
if check_valid != 'warn' and check_valid != 'raise':
- raise ValueError("check_valid must equal 'warn', 'raise', or 'ignore'")
+ raise ValueError(
+ "check_valid must equal 'warn', 'raise', or 'ignore'")
psd = np.allclose(np.dot(v.T * s, v), cov, rtol=tol, atol=tol)
if not psd:
if check_valid == 'warn':
- warnings.warn(
- "covariance is not symmetric positive-semidefinite.",
+ warnings.warn("covariance is not positive-semidefinite.",
RuntimeWarning)
else:
raise ValueError(
- "covariance is not symmetric positive-semidefinite.")
+ "covariance is not positive-semidefinite.")
x = np.dot(x, np.sqrt(s)[:, None] * v)
x += mean
x.shape = tuple(final_shape)
return x
- def multinomial(self, npy_intp n, object pvals, size=None):
+ def multinomial(self, np.npy_intp n, object pvals, size=None):
"""
multinomial(n, pvals, size=None)
Draw samples from a multinomial distribution.
- The multinomial distribution is a multivariate generalisation of the
+ The multinomial distribution is a multivariate generalization of the
binomial distribution. Take an experiment with one of ``p``
possible outcomes. An example of such an experiment is throwing a dice,
where the outcome can be 1 through 6. Each sample drawn from the
@@ -4573,7 +3794,7 @@ cdef class RandomState:
Number of experiments.
pvals : sequence of floats, length p
Probabilities of each of the ``p`` different outcomes. These
- should sum to 1 (however, the last element is always assumed to
+ must sum to 1 (however, the last element is always assumed to
account for the remaining probability, as long as
``sum(pvals[:-1]) <= 1)``.
size : int or tuple of ints, optional
@@ -4595,14 +3816,14 @@ cdef class RandomState:
Throw a dice 20 times:
>>> np.random.multinomial(20, [1/6.]*6, size=1)
- array([[4, 1, 7, 5, 2, 1]])
+ array([[4, 1, 7, 5, 2, 1]]) # random
It landed 4 times on 1, once on 2, etc.
Now, throw the dice 20 times, and 20 times again:
>>> np.random.multinomial(20, [1/6.]*6, size=2)
- array([[3, 4, 3, 3, 4, 3],
+ array([[3, 4, 3, 3, 4, 3], # random
[2, 4, 3, 4, 0, 7]])
For the first run, we threw 3 times 1, 4 times 2, etc. For the second,
@@ -4611,7 +3832,7 @@ cdef class RandomState:
A loaded die is more likely to land on number 6:
>>> np.random.multinomial(100, [1/7.]*5 + [2/7.])
- array([11, 16, 14, 17, 16, 26])
+ array([11, 16, 14, 17, 16, 26]) # random
The probability inputs should be normalized. As an implementation
detail, the value of the last entry is ignored and assumed to take
@@ -4620,49 +3841,48 @@ cdef class RandomState:
other should be sampled like so:
>>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT
- array([38, 62])
+ array([38, 62]) # random
not like:
>>> np.random.multinomial(100, [1.0, 2.0]) # WRONG
- array([100, 0])
+ Traceback (most recent call last):
+ ValueError: pvals < 0, pvals > 1 or pvals contains NaNs
"""
- cdef npy_intp d
- cdef ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr"
+ cdef np.npy_intp d, i, sz, offset
+ cdef np.ndarray parr, mnarr
cdef double *pix
cdef long *mnix
- cdef npy_intp i, j, dn, sz
- cdef double Sum
+ cdef long ni
d = len(pvals)
- parr = <ndarray>PyArray_ContiguousFromObject(pvals, NPY_DOUBLE, 1, 1)
- pix = <double*>PyArray_DATA(parr)
-
+ parr = <np.ndarray>np.PyArray_FROM_OTF(
+ pvals, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
+ pix = <double*>np.PyArray_DATA(parr)
+ check_array_constraint(parr, 'pvals', CONS_BOUNDED_0_1)
if kahan_sum(pix, d-1) > (1.0 + 1e-12):
raise ValueError("sum(pvals[:-1]) > 1.0")
- shape = _shape_from_size(size, d)
-
- multin = np.zeros(shape, int)
- mnarr = <ndarray>multin
- mnix = <long*>PyArray_DATA(mnarr)
- sz = PyArray_SIZE(mnarr)
- with self.lock, nogil, cython.cdivision(True):
- i = 0
- while i < sz:
- Sum = 1.0
- dn = n
- for j from 0 <= j < d-1:
- mnix[i+j] = rk_binomial(self.internal_state, dn, pix[j]/Sum)
- dn = dn - mnix[i+j]
- if dn <= 0:
- break
- Sum = Sum - pix[j]
- if dn > 0:
- mnix[i+d-1] = dn
-
- i = i + d
+ if size is None:
+ shape = (d,)
+ else:
+ try:
+ shape = (operator.index(size), d)
+ except:
+ shape = tuple(size) + (d,)
+
+ multin = np.zeros(shape, dtype=int)
+ mnarr = <np.ndarray>multin
+ mnix = <long*>np.PyArray_DATA(mnarr)
+ sz = np.PyArray_SIZE(mnarr)
+ ni = n
+ check_constraint(ni, 'n', CONS_NON_NEGATIVE)
+ offset = 0
+ with self.lock, nogil:
+ for i in range(sz // d):
+ legacy_random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial)
+ offset += d
return multin
@@ -4674,8 +3894,9 @@ cdef class RandomState:
Draw `size` samples of dimension k from a Dirichlet distribution. A
Dirichlet-distributed random variable can be seen as a multivariate
- generalization of a Beta distribution. Dirichlet pdf is the conjugate
- prior of a multinomial in Bayesian inference.
+ generalization of a Beta distribution. The Dirichlet distribution
+ is a conjugate prior of a multinomial distribution in Bayesian
+ inference.
Parameters
----------
@@ -4699,13 +3920,23 @@ cdef class RandomState:
Notes
-----
- .. math:: X \\approx \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i}
+ The Dirichlet distribution is a distribution over vectors
+ :math:`x` that fulfil the conditions :math:`x_i>0` and
+ :math:`\\sum_{i=1}^k x_i = 1`.
- Uses the following property for computation: for each dimension,
- draw a random sample y_i from a standard gamma generator of shape
- `alpha_i`, then
- :math:`X = \\frac{1}{\\sum_{i=1}^k{y_i}} (y_1, \\ldots, y_n)` is
- Dirichlet distributed.
+ The probability density function :math:`p` of a
+ Dirichlet-distributed random vector :math:`X` is
+ proportional to
+
+ .. math:: p(x) \\propto \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i},
+
+ where :math:`\\alpha` is a vector containing the positive
+ concentration parameters.
+
+ The method uses the following property for computation: let :math:`Y`
+ be a random vector which has components that follow a standard gamma
+ distribution, then :math:`X = \\frac{1}{\\sum_{i=1}^k{Y_i}} Y`
+ is Dirichlet-distributed
References
----------
@@ -4733,58 +3964,62 @@ cdef class RandomState:
"""
- #=================
+ # =================
# Pure python algo
- #=================
- #alpha = N.atleast_1d(alpha)
- #k = alpha.size
-
- #if n == 1:
- # val = N.zeros(k)
- # for i in range(k):
- # val[i] = sgamma(alpha[i], n)
- # val /= N.sum(val)
- #else:
- # val = N.zeros((k, n))
- # for i in range(k):
- # val[i] = sgamma(alpha[i], n)
- # val /= N.sum(val, axis = 0)
- # val = val.T
-
- #return val
-
- cdef npy_intp k
- cdef npy_intp totsize
- cdef ndarray alpha_arr, val_arr
- cdef double *alpha_data
- cdef double *val_data
- cdef npy_intp i, j
- cdef double acc, invacc
-
- k = len(alpha)
- alpha_arr = <ndarray>PyArray_ContiguousFromObject(alpha, NPY_DOUBLE, 1, 1)
+ # =================
+ # alpha = N.atleast_1d(alpha)
+ # k = alpha.size
+
+ # if n == 1:
+ # val = N.zeros(k)
+ # for i in range(k):
+ # val[i] = sgamma(alpha[i], n)
+ # val /= N.sum(val)
+ # else:
+ # val = N.zeros((k, n))
+ # for i in range(k):
+ # val[i] = sgamma(alpha[i], n)
+ # val /= N.sum(val, axis = 0)
+ # val = val.T
+ # return val
+
+ cdef np.npy_intp k, totsize, i, j
+ cdef np.ndarray alpha_arr, val_arr
+ cdef double *alpha_data
+ cdef double *val_data
+ cdef double acc, invacc
+
+ k = len(alpha)
+ alpha_arr = <np.ndarray>np.PyArray_FROM_OTF(
+ alpha, np.NPY_DOUBLE, np.NPY_ALIGNED | np.NPY_ARRAY_C_CONTIGUOUS)
if np.any(np.less_equal(alpha_arr, 0)):
raise ValueError('alpha <= 0')
- alpha_data = <double*>PyArray_DATA(alpha_arr)
+ alpha_data = <double*>np.PyArray_DATA(alpha_arr)
- shape = _shape_from_size(size, k)
+ if size is None:
+ shape = (k,)
+ else:
+ try:
+ shape = (operator.index(size), k)
+ except:
+ shape = tuple(size) + (k,)
- diric = np.zeros(shape, np.float64)
- val_arr = <ndarray>diric
- val_data= <double*>PyArray_DATA(val_arr)
+ diric = np.zeros(shape, np.float64)
+ val_arr = <np.ndarray>diric
+ val_data = <double*>np.PyArray_DATA(val_arr)
i = 0
- totsize = PyArray_SIZE(val_arr)
+ totsize = np.PyArray_SIZE(val_arr)
with self.lock, nogil:
while i < totsize:
acc = 0.0
- for j from 0 <= j < k:
- val_data[i+j] = rk_standard_gamma(self.internal_state,
- alpha_data[j])
- acc = acc + val_data[i+j]
- invacc = 1/acc
- for j from 0 <= j < k:
- val_data[i+j] = val_data[i+j] * invacc
+ for j in range(k):
+ val_data[i+j] = legacy_standard_gamma(&self._aug_state,
+ alpha_data[j])
+ acc = acc + val_data[i + j]
+ invacc = 1/acc
+ for j in range(k):
+ val_data[i + j] = val_data[i + j] * invacc
i = i + k
return diric
@@ -4814,20 +4049,20 @@ cdef class RandomState:
>>> arr = np.arange(10)
>>> np.random.shuffle(arr)
>>> arr
- [1 7 5 2 9 4 3 6 0 8]
+ [1 7 5 2 9 4 3 6 0 8] # random
Multi-dimensional arrays are only shuffled along the first axis:
>>> arr = np.arange(9).reshape((3, 3))
>>> np.random.shuffle(arr)
>>> arr
- array([[3, 4, 5],
+ array([[3, 4, 5], # random
[6, 7, 8],
[0, 1, 2]])
"""
cdef:
- npy_intp i, j, n = len(x), stride, itemsize
+ np.npy_intp i, j, n = len(x), stride, itemsize
char* x_ptr
char* buf_ptr
@@ -4842,21 +4077,23 @@ cdef class RandomState:
# of bytes for the swaps to avoid leaving one of the objects
# within the buffer and erroneously decrementing it's refcount
# when the function exits.
- buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit
+ buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit
buf_ptr = <char*><size_t>buf.ctypes.data
with self.lock:
# We trick gcc into providing a specialized implementation for
# the most common case, yielding a ~33% performance improvement.
# Note that apparently, only one branch can ever be specialized.
- if itemsize == sizeof(npy_intp):
- self._shuffle_raw(n, sizeof(npy_intp), stride, x_ptr, buf_ptr)
+ if itemsize == sizeof(np.npy_intp):
+ self._shuffle_raw(n, sizeof(np.npy_intp), stride, x_ptr, buf_ptr)
else:
self._shuffle_raw(n, itemsize, stride, x_ptr, buf_ptr)
elif isinstance(x, np.ndarray) and x.ndim and x.size:
- buf = np.empty_like(x[0,...])
+ buf = np.empty_like(x[0, ...])
with self.lock:
for i in reversed(range(1, n)):
- j = rk_interval(i, self.internal_state)
+ j = random_interval(&self._bitgen, i)
+ if i == j:
+ continue # i == j is not needed and memcpy is undefined.
buf[...] = x[j]
x[j] = x[i]
x[i] = buf
@@ -4864,15 +4101,14 @@ cdef class RandomState:
# Untyped path.
with self.lock:
for i in reversed(range(1, n)):
- j = rk_interval(i, self.internal_state)
+ j = random_interval(&self._bitgen, i)
x[i], x[j] = x[j], x[i]
- cdef inline _shuffle_raw(self, npy_intp n, npy_intp itemsize,
- npy_intp stride, char* data, char* buf):
- cdef npy_intp i, j
+ cdef inline _shuffle_raw(self, np.npy_intp n, np.npy_intp itemsize,
+ np.npy_intp stride, char* data, char* buf):
+ cdef np.npy_intp i, j
for i in reversed(range(1, n)):
- j = rk_interval(i, self.internal_state)
- if i == j : continue # i == j is not needed and memcpy is undefined.
+ j = random_interval(&self._bitgen, i)
string.memcpy(buf, data + j * stride, itemsize)
string.memcpy(data + j * stride, data + i * stride, itemsize)
string.memcpy(data + i * stride, buf, itemsize)
@@ -4901,25 +4137,25 @@ cdef class RandomState:
Examples
--------
>>> np.random.permutation(10)
- array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6])
+ array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random
>>> np.random.permutation([1, 4, 9, 12, 15])
- array([15, 1, 9, 4, 12])
+ array([15, 1, 9, 4, 12]) # random
>>> arr = np.arange(9).reshape((3, 3))
>>> np.random.permutation(arr)
- array([[6, 7, 8],
+ array([[6, 7, 8], # random
[0, 1, 2],
[3, 4, 5]])
"""
- if isinstance(x, (int, long, np.integer)):
+ if isinstance(x, (int, np.integer)):
arr = np.arange(x)
self.shuffle(arr)
return arr
arr = np.asarray(x)
-
+
# shuffle has fast-path for 1-d
if arr.ndim == 1:
# Return a copy if same memory
@@ -4932,56 +4168,123 @@ cdef class RandomState:
idx = np.arange(arr.shape[0], dtype=np.intp)
self.shuffle(idx)
return arr[idx]
-
_rand = RandomState()
-seed = _rand.seed
-get_state = _rand.get_state
-set_state = _rand.set_state
-random_sample = _rand.random_sample
-choice = _rand.choice
-randint = _rand.randint
+
+beta = _rand.beta
+binomial = _rand.binomial
bytes = _rand.bytes
-uniform = _rand.uniform
+chisquare = _rand.chisquare
+choice = _rand.choice
+dirichlet = _rand.dirichlet
+exponential = _rand.exponential
+f = _rand.f
+gamma = _rand.gamma
+get_state = _rand.get_state
+geometric = _rand.geometric
+gumbel = _rand.gumbel
+hypergeometric = _rand.hypergeometric
+laplace = _rand.laplace
+logistic = _rand.logistic
+lognormal = _rand.lognormal
+logseries = _rand.logseries
+multinomial = _rand.multinomial
+multivariate_normal = _rand.multivariate_normal
+negative_binomial = _rand.negative_binomial
+noncentral_chisquare = _rand.noncentral_chisquare
+noncentral_f = _rand.noncentral_f
+normal = _rand.normal
+pareto = _rand.pareto
+permutation = _rand.permutation
+poisson = _rand.poisson
+power = _rand.power
rand = _rand.rand
+randint = _rand.randint
randn = _rand.randn
+random = _rand.random
random_integers = _rand.random_integers
-standard_normal = _rand.standard_normal
-normal = _rand.normal
-beta = _rand.beta
-exponential = _rand.exponential
+random_sample = _rand.random_sample
+rayleigh = _rand.rayleigh
+seed = _rand.seed
+set_state = _rand.set_state
+shuffle = _rand.shuffle
+standard_cauchy = _rand.standard_cauchy
standard_exponential = _rand.standard_exponential
standard_gamma = _rand.standard_gamma
-gamma = _rand.gamma
-f = _rand.f
-noncentral_f = _rand.noncentral_f
-chisquare = _rand.chisquare
-noncentral_chisquare = _rand.noncentral_chisquare
-standard_cauchy = _rand.standard_cauchy
+standard_normal = _rand.standard_normal
standard_t = _rand.standard_t
+triangular = _rand.triangular
+uniform = _rand.uniform
vonmises = _rand.vonmises
-pareto = _rand.pareto
-weibull = _rand.weibull
-power = _rand.power
-laplace = _rand.laplace
-gumbel = _rand.gumbel
-logistic = _rand.logistic
-lognormal = _rand.lognormal
-rayleigh = _rand.rayleigh
wald = _rand.wald
-triangular = _rand.triangular
-
-binomial = _rand.binomial
-negative_binomial = _rand.negative_binomial
-poisson = _rand.poisson
+weibull = _rand.weibull
zipf = _rand.zipf
-geometric = _rand.geometric
-hypergeometric = _rand.hypergeometric
-logseries = _rand.logseries
-multivariate_normal = _rand.multivariate_normal
-multinomial = _rand.multinomial
-dirichlet = _rand.dirichlet
+# Old aliases that should not be removed
+def sample(*args, **kwargs):
+ """
+ This is an alias of `random_sample`. See `random_sample` for the complete
+ documentation.
+ """
+ return _rand.random_sample(*args, **kwargs)
-shuffle = _rand.shuffle
-permutation = _rand.permutation
+def ranf(*args, **kwargs):
+ """
+ This is an alias of `random_sample`. See `random_sample` for the complete
+ documentation.
+ """
+ return _rand.random_sample(*args, **kwargs)
+
+__all__ = [
+ 'beta',
+ 'binomial',
+ 'bytes',
+ 'chisquare',
+ 'choice',
+ 'dirichlet',
+ 'exponential',
+ 'f',
+ 'gamma',
+ 'geometric',
+ 'get_state',
+ 'gumbel',
+ 'hypergeometric',
+ 'laplace',
+ 'logistic',
+ 'lognormal',
+ 'logseries',
+ 'multinomial',
+ 'multivariate_normal',
+ 'negative_binomial',
+ 'noncentral_chisquare',
+ 'noncentral_f',
+ 'normal',
+ 'pareto',
+ 'permutation',
+ 'poisson',
+ 'power',
+ 'rand',
+ 'randint',
+ 'randn',
+ 'random',
+ 'random_integers',
+ 'random_sample',
+ 'ranf',
+ 'rayleigh',
+ 'sample',
+ 'seed',
+ 'set_state',
+ 'shuffle',
+ 'standard_cauchy',
+ 'standard_exponential',
+ 'standard_gamma',
+ 'standard_normal',
+ 'standard_t',
+ 'triangular',
+ 'uniform',
+ 'vonmises',
+ 'wald',
+ 'weibull',
+ 'zipf',
+ 'RandomState',
+]
diff --git a/numpy/random/mtrand/Python.pxi b/numpy/random/mtrand/Python.pxi
deleted file mode 100644
index 08aadbaa1..000000000
--- a/numpy/random/mtrand/Python.pxi
+++ /dev/null
@@ -1,43 +0,0 @@
-# :Author: Robert Kern
-# :Copyright: 2004, Enthought, Inc.
-# :License: BSD Style
-
-
-cdef extern from "Python.h":
- # Not part of the Python API, but we might as well define it here.
- # Note that the exact type doesn't actually matter for Pyrex.
- ctypedef int size_t
-
- # String API
- char* PyString_AsString(object string)
- char* PyString_AS_STRING(object string)
- object PyString_FromString(char* c_string)
- object PyString_FromStringAndSize(char* c_string, int length)
-
- # Float API
- double PyFloat_AsDouble(object ob) except? -1.0
- long PyInt_AsLong(object ob) except? -1
-
- # Memory API
- void* PyMem_Malloc(size_t n)
- void* PyMem_Realloc(void* buf, size_t n)
- void PyMem_Free(void* buf)
-
- void Py_DECREF(object obj)
- void Py_XDECREF(object obj)
- void Py_INCREF(object obj)
- void Py_XINCREF(object obj)
-
- # TypeCheck API
- int PyFloat_Check(object obj)
- int PyInt_Check(object obj)
-
- # Error API
- int PyErr_Occurred()
- void PyErr_Clear()
-
-cdef extern from "string.h":
- void *memcpy(void *s1, void *s2, int n)
-
-cdef extern from "math.h":
- double fabs(double x)
diff --git a/numpy/random/mtrand/distributions.c b/numpy/random/mtrand/distributions.c
deleted file mode 100644
index fccdc8476..000000000
--- a/numpy/random/mtrand/distributions.c
+++ /dev/null
@@ -1,942 +0,0 @@
-/* Copyright 2005 Robert Kern (robert.kern@gmail.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* The implementations of rk_hypergeometric_hyp(), rk_hypergeometric_hrua(),
- * and rk_triangular() were adapted from Ivan Frohne's rv.py which has this
- * license:
- *
- * Copyright 1998 by Ivan Frohne; Wasilla, Alaska, U.S.A.
- * All Rights Reserved
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation for any purpose, free of charge, is granted subject to the
- * following conditions:
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the software.
- *
- * THE SOFTWARE AND DOCUMENTATION IS PROVIDED WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR
- * OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM OR DAMAGES IN A CONTRACT
- * ACTION, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR ITS DOCUMENTATION.
- */
-
-#include "distributions.h"
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#ifndef min
-#define min(x,y) ((x<y)?x:y)
-#define max(x,y) ((x>y)?x:y)
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338328
-#endif
-
-/*
- * log-gamma function to support some of these distributions. The
- * algorithm comes from SPECFUN by Shanjie Zhang and Jianming Jin and their
- * book "Computation of Special Functions", 1996, John Wiley & Sons, Inc.
- */
-static double loggam(double x)
-{
- double x0, x2, xp, gl, gl0;
- long k, n;
-
- static double a[10] = {8.333333333333333e-02,-2.777777777777778e-03,
- 7.936507936507937e-04,-5.952380952380952e-04,
- 8.417508417508418e-04,-1.917526917526918e-03,
- 6.410256410256410e-03,-2.955065359477124e-02,
- 1.796443723688307e-01,-1.39243221690590e+00};
- x0 = x;
- n = 0;
- if ((x == 1.0) || (x == 2.0))
- {
- return 0.0;
- }
- else if (x <= 7.0)
- {
- n = (long)(7 - x);
- x0 = x + n;
- }
- x2 = 1.0/(x0*x0);
- xp = 2*M_PI;
- gl0 = a[9];
- for (k=8; k>=0; k--)
- {
- gl0 *= x2;
- gl0 += a[k];
- }
- gl = gl0/x0 + 0.5*log(xp) + (x0-0.5)*log(x0) - x0;
- if (x <= 7.0)
- {
- for (k=1; k<=n; k++)
- {
- gl -= log(x0-1.0);
- x0 -= 1.0;
- }
- }
- return gl;
-}
-
-double rk_normal(rk_state *state, double loc, double scale)
-{
- return loc + scale*rk_gauss(state);
-}
-
-double rk_standard_exponential(rk_state *state)
-{
- /* We use -log(1-U) since U is [0, 1) */
- return -log(1.0 - rk_double(state));
-}
-
-double rk_exponential(rk_state *state, double scale)
-{
- return scale * rk_standard_exponential(state);
-}
-
-double rk_uniform(rk_state *state, double loc, double scale)
-{
- return loc + scale*rk_double(state);
-}
-
-double rk_standard_gamma(rk_state *state, double shape)
-{
- double b, c;
- double U, V, X, Y;
-
- if (shape == 1.0)
- {
- return rk_standard_exponential(state);
- }
- else if (shape < 1.0)
- {
- for (;;)
- {
- U = rk_double(state);
- V = rk_standard_exponential(state);
- if (U <= 1.0 - shape)
- {
- X = pow(U, 1./shape);
- if (X <= V)
- {
- return X;
- }
- }
- else
- {
- Y = -log((1-U)/shape);
- X = pow(1.0 - shape + shape*Y, 1./shape);
- if (X <= (V + Y))
- {
- return X;
- }
- }
- }
- }
- else
- {
- b = shape - 1./3.;
- c = 1./sqrt(9*b);
- for (;;)
- {
- do
- {
- X = rk_gauss(state);
- V = 1.0 + c*X;
- } while (V <= 0.0);
-
- V = V*V*V;
- U = rk_double(state);
- if (U < 1.0 - 0.0331*(X*X)*(X*X)) return (b*V);
- if (log(U) < 0.5*X*X + b*(1. - V + log(V))) return (b*V);
- }
- }
-}
-
-double rk_gamma(rk_state *state, double shape, double scale)
-{
- return scale * rk_standard_gamma(state, shape);
-}
-
-double rk_beta(rk_state *state, double a, double b)
-{
- double Ga, Gb;
-
- if ((a <= 1.0) && (b <= 1.0))
- {
- double U, V, X, Y;
- /* Use Johnk's algorithm */
-
- while (1)
- {
- U = rk_double(state);
- V = rk_double(state);
- X = pow(U, 1.0/a);
- Y = pow(V, 1.0/b);
-
- /* Reject if both U and V are 0.0, which is approx 1 in 10^106 */
- if (((X + Y) <= 1.0) && ((U + V) > 0.0))
- {
- if (X + Y > 0)
- {
- return X / (X + Y);
- }
- else
- {
- double logX = log(U) / a;
- double logY = log(V) / b;
- double logM = logX > logY ? logX : logY;
- logX -= logM;
- logY -= logM;
-
- return exp(logX - log(exp(logX) + exp(logY)));
- }
- }
- }
- }
- else
- {
- Ga = rk_standard_gamma(state, a);
- Gb = rk_standard_gamma(state, b);
- return Ga/(Ga + Gb);
- }
-}
-
-double rk_chisquare(rk_state *state, double df)
-{
- return 2.0*rk_standard_gamma(state, df/2.0);
-}
-
-double rk_noncentral_chisquare(rk_state *state, double df, double nonc)
-{
- if (nonc == 0){
- return rk_chisquare(state, df);
- }
- if(1 < df)
- {
- const double Chi2 = rk_chisquare(state, df - 1);
- const double N = rk_gauss(state) + sqrt(nonc);
- return Chi2 + N*N;
- }
- else
- {
- const long i = rk_poisson(state, nonc / 2.0);
- return rk_chisquare(state, df + 2 * i);
- }
-}
-
-double rk_f(rk_state *state, double dfnum, double dfden)
-{
- return ((rk_chisquare(state, dfnum) * dfden) /
- (rk_chisquare(state, dfden) * dfnum));
-}
-
-double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc)
-{
- double t = rk_noncentral_chisquare(state, dfnum, nonc) * dfden;
- return t / (rk_chisquare(state, dfden) * dfnum);
-}
-
-long rk_binomial_btpe(rk_state *state, long n, double p)
-{
- double r,q,fm,p1,xm,xl,xr,c,laml,lamr,p2,p3,p4;
- double a,u,v,s,F,rho,t,A,nrq,x1,x2,f1,f2,z,z2,w,w2,x;
- long m,y,k,i;
-
- if (!(state->has_binomial) ||
- (state->nsave != n) ||
- (state->psave != p))
- {
- /* initialize */
- state->nsave = n;
- state->psave = p;
- state->has_binomial = 1;
- state->r = r = min(p, 1.0-p);
- state->q = q = 1.0 - r;
- state->fm = fm = n*r+r;
- state->m = m = (long)floor(state->fm);
- state->p1 = p1 = floor(2.195*sqrt(n*r*q)-4.6*q) + 0.5;
- state->xm = xm = m + 0.5;
- state->xl = xl = xm - p1;
- state->xr = xr = xm + p1;
- state->c = c = 0.134 + 20.5/(15.3 + m);
- a = (fm - xl)/(fm-xl*r);
- state->laml = laml = a*(1.0 + a/2.0);
- a = (xr - fm)/(xr*q);
- state->lamr = lamr = a*(1.0 + a/2.0);
- state->p2 = p2 = p1*(1.0 + 2.0*c);
- state->p3 = p3 = p2 + c/laml;
- state->p4 = p4 = p3 + c/lamr;
- }
- else
- {
- r = state->r;
- q = state->q;
- fm = state->fm;
- m = state->m;
- p1 = state->p1;
- xm = state->xm;
- xl = state->xl;
- xr = state->xr;
- c = state->c;
- laml = state->laml;
- lamr = state->lamr;
- p2 = state->p2;
- p3 = state->p3;
- p4 = state->p4;
- }
-
- /* sigh ... */
- Step10:
- nrq = n*r*q;
- u = rk_double(state)*p4;
- v = rk_double(state);
- if (u > p1) goto Step20;
- y = (long)floor(xm - p1*v + u);
- goto Step60;
-
- Step20:
- if (u > p2) goto Step30;
- x = xl + (u - p1)/c;
- v = v*c + 1.0 - fabs(m - x + 0.5)/p1;
- if (v > 1.0) goto Step10;
- y = (long)floor(x);
- goto Step50;
-
- Step30:
- if (u > p3) goto Step40;
- y = (long)floor(xl + log(v)/laml);
- /* Reject if v == 0.0 since cast of inf not well defined */
- if ((y < 0) || (v == 0.0)) goto Step10;
- v = v*(u-p2)*laml;
- goto Step50;
-
- Step40:
- y = (long)floor(xr - log(v)/lamr);
- /* Reject if v == 0.0 since cast of inf not well defined */
- if ((y > n) || (v == 0.0)) goto Step10;
- v = v*(u-p3)*lamr;
-
- Step50:
- k = labs(y - m);
- if ((k > 20) && (k < ((nrq)/2.0 - 1))) goto Step52;
-
- s = r/q;
- a = s*(n+1);
- F = 1.0;
- if (m < y)
- {
- for (i=m+1; i<=y; i++)
- {
- F *= (a/i - s);
- }
- }
- else if (m > y)
- {
- for (i=y+1; i<=m; i++)
- {
- F /= (a/i - s);
- }
- }
- if (v > F) goto Step10;
- goto Step60;
-
- Step52:
- rho = (k/(nrq))*((k*(k/3.0 + 0.625) + 0.16666666666666666)/nrq + 0.5);
- t = -k*k/(2*nrq);
- A = log(v);
- if (A < (t - rho)) goto Step60;
- if (A > (t + rho)) goto Step10;
-
- x1 = y+1;
- f1 = m+1;
- z = n+1-m;
- w = n-y+1;
- x2 = x1*x1;
- f2 = f1*f1;
- z2 = z*z;
- w2 = w*w;
- if (A > (xm*log(f1/x1)
- + (n-m+0.5)*log(z/w)
- + (y-m)*log(w*r/(x1*q))
- + (13680.-(462.-(132.-(99.-140./f2)/f2)/f2)/f2)/f1/166320.
- + (13680.-(462.-(132.-(99.-140./z2)/z2)/z2)/z2)/z/166320.
- + (13680.-(462.-(132.-(99.-140./x2)/x2)/x2)/x2)/x1/166320.
- + (13680.-(462.-(132.-(99.-140./w2)/w2)/w2)/w2)/w/166320.))
- {
- goto Step10;
- }
-
- Step60:
- if (p > 0.5)
- {
- y = n - y;
- }
-
- return y;
-}
-
-long rk_binomial_inversion(rk_state *state, long n, double p)
-{
- double q, qn, np, px, U;
- long X, bound;
-
- if (!(state->has_binomial) ||
- (state->nsave != n) ||
- (state->psave != p))
- {
- state->nsave = n;
- state->psave = p;
- state->has_binomial = 1;
- state->q = q = 1.0 - p;
- state->r = qn = exp(n * log(q));
- state->c = np = n*p;
- state->m = bound = min(n, np + 10.0*sqrt(np*q + 1));
- } else
- {
- q = state->q;
- qn = state->r;
- np = state->c;
- bound = state->m;
- }
- X = 0;
- px = qn;
- U = rk_double(state);
- while (U > px)
- {
- X++;
- if (X > bound)
- {
- X = 0;
- px = qn;
- U = rk_double(state);
- } else
- {
- U -= px;
- px = ((n-X+1) * p * px)/(X*q);
- }
- }
- return X;
-}
-
-long rk_binomial(rk_state *state, long n, double p)
-{
- double q;
-
- if (p <= 0.5)
- {
- if (p*n <= 30.0)
- {
- return rk_binomial_inversion(state, n, p);
- }
- else
- {
- return rk_binomial_btpe(state, n, p);
- }
- }
- else
- {
- q = 1.0-p;
- if (q*n <= 30.0)
- {
- return n - rk_binomial_inversion(state, n, q);
- }
- else
- {
- return n - rk_binomial_btpe(state, n, q);
- }
- }
-
-}
-
-long rk_negative_binomial(rk_state *state, double n, double p)
-{
- double Y;
-
- Y = rk_gamma(state, n, (1-p)/p);
- return rk_poisson(state, Y);
-}
-
-long rk_poisson_mult(rk_state *state, double lam)
-{
- long X;
- double prod, U, enlam;
-
- enlam = exp(-lam);
- X = 0;
- prod = 1.0;
- while (1)
- {
- U = rk_double(state);
- prod *= U;
- if (prod > enlam)
- {
- X += 1;
- }
- else
- {
- return X;
- }
- }
-}
-
-/*
- * The transformed rejection method for generating Poisson random variables
- * W. Hoermann
- * Insurance: Mathematics and Economics 12, 39-45 (1993)
- */
-#define LS2PI 0.91893853320467267
-#define TWELFTH 0.083333333333333333333333
-long rk_poisson_ptrs(rk_state *state, double lam)
-{
- long k;
- double U, V, slam, loglam, a, b, invalpha, vr, us;
-
- slam = sqrt(lam);
- loglam = log(lam);
- b = 0.931 + 2.53*slam;
- a = -0.059 + 0.02483*b;
- invalpha = 1.1239 + 1.1328/(b-3.4);
- vr = 0.9277 - 3.6224/(b-2);
-
- while (1)
- {
- U = rk_double(state) - 0.5;
- V = rk_double(state);
- us = 0.5 - fabs(U);
- k = (long)floor((2*a/us + b)*U + lam + 0.43);
- if ((us >= 0.07) && (V <= vr))
- {
- return k;
- }
- if ((k < 0) ||
- ((us < 0.013) && (V > us)))
- {
- continue;
- }
- if ((log(V) + log(invalpha) - log(a/(us*us)+b)) <=
- (-lam + k*loglam - loggam(k+1)))
- {
- return k;
- }
-
-
- }
-
-}
-
-long rk_poisson(rk_state *state, double lam)
-{
- if (lam >= 10)
- {
- return rk_poisson_ptrs(state, lam);
- }
- else if (lam == 0)
- {
- return 0;
- }
- else
- {
- return rk_poisson_mult(state, lam);
- }
-}
-
-double rk_standard_cauchy(rk_state *state)
-{
- return rk_gauss(state) / rk_gauss(state);
-}
-
-double rk_standard_t(rk_state *state, double df)
-{
- double N, G, X;
-
- N = rk_gauss(state);
- G = rk_standard_gamma(state, df/2);
- X = sqrt(df/2)*N/sqrt(G);
- return X;
-}
-
-/* Uses the rejection algorithm compared against the wrapped Cauchy
- distribution suggested by Best and Fisher and documented in
- Chapter 9 of Luc's Non-Uniform Random Variate Generation.
- http://cg.scs.carleton.ca/~luc/rnbookindex.html
- (but corrected to match the algorithm in R and Python)
-*/
-double rk_vonmises(rk_state *state, double mu, double kappa)
-{
- double s;
- double U, V, W, Y, Z;
- double result, mod;
- int neg;
-
- if (kappa < 1e-8)
- {
- return M_PI * (2*rk_double(state)-1);
- }
- else
- {
- /* with double precision rho is zero until 1.4e-8 */
- if (kappa < 1e-5) {
- /*
- * second order taylor expansion around kappa = 0
- * precise until relatively large kappas as second order is 0
- */
- s = (1./kappa + kappa);
- }
- else {
- double r = 1 + sqrt(1 + 4*kappa*kappa);
- double rho = (r - sqrt(2*r)) / (2*kappa);
- s = (1 + rho*rho)/(2*rho);
- }
-
- while (1)
- {
- U = rk_double(state);
- Z = cos(M_PI*U);
- W = (1 + s*Z)/(s + Z);
- Y = kappa * (s - W);
- V = rk_double(state);
- if ((Y*(2-Y) - V >= 0) || (log(Y/V)+1 - Y >= 0))
- {
- break;
- }
- }
-
- U = rk_double(state);
-
- result = acos(W);
- if (U < 0.5)
- {
- result = -result;
- }
- result += mu;
- neg = (result < 0);
- mod = fabs(result);
- mod = (fmod(mod+M_PI, 2*M_PI)-M_PI);
- if (neg)
- {
- mod *= -1;
- }
-
- return mod;
- }
-}
-
-double rk_pareto(rk_state *state, double a)
-{
- return exp(rk_standard_exponential(state)/a) - 1;
-}
-
-double rk_weibull(rk_state *state, double a)
-{
- if (a == 0.0) {
- return 0.0;
- }
- return pow(rk_standard_exponential(state), 1./a);
-}
-
-double rk_power(rk_state *state, double a)
-{
- return pow(1 - exp(-rk_standard_exponential(state)), 1./a);
-}
-
-double rk_laplace(rk_state *state, double loc, double scale)
-{
- double U;
-
- U = rk_double(state);
- if (U >= 0.5)
- {
- U = loc - scale * log(2.0 - U - U);
-
- } else if (U > 0.0)
- {
- U = loc + scale * log(U + U);
- } else
- {
- /* Reject if U == 0.0 */
- return rk_laplace(state, loc, scale);
- }
- return U;
-}
-
-double rk_gumbel(rk_state *state, double loc, double scale)
-{
- double U;
-
- U = 1.0 - rk_double(state);
- if (U < 1.0)
- return loc - scale * log(-log(U));
- return rk_gumbel(state, loc, scale);
-}
-
-double rk_logistic(rk_state *state, double loc, double scale)
-{
- double U;
-
- U = rk_double(state);
- if (U > 0.0)
- return loc + scale * log(U/(1.0 - U));
- return rk_logistic(state, loc, scale);
-}
-
-double rk_lognormal(rk_state *state, double mean, double sigma)
-{
- return exp(rk_normal(state, mean, sigma));
-}
-
-double rk_rayleigh(rk_state *state, double mode)
-{
- return mode*sqrt(-2.0 * log(1.0 - rk_double(state)));
-}
-
-double rk_wald(rk_state *state, double mean, double scale)
-{
- double U, X, Y;
- double mu_2l;
-
- mu_2l = mean / (2*scale);
- Y = rk_gauss(state);
- Y = mean*Y*Y;
- X = mean + mu_2l*(Y - sqrt(4*scale*Y + Y*Y));
- U = rk_double(state);
- if (U <= mean/(mean+X))
- {
- return X;
- } else
- {
- return mean*mean/X;
- }
-}
-
-long rk_zipf(rk_state *state, double a)
-{
- double am1, b;
-
- am1 = a - 1.0;
- b = pow(2.0, am1);
- while (1) {
- double T, U, V, X;
-
- U = 1.0 - rk_double(state);
- V = rk_double(state);
- X = floor(pow(U, -1.0/am1));
- /*
- * The real result may be above what can be represented in a signed
- * long. Since this is a straightforward rejection algorithm, we can
- * just reject this value. This function then models a Zipf
- * distribution truncated to sys.maxint.
- */
- if (X > LONG_MAX || X < 1.0) {
- continue;
- }
-
- T = pow(1.0 + 1.0/X, am1);
- if (V*X*(T - 1.0)/(b - 1.0) <= T/b) {
- return (long)X;
- }
- }
-}
-
-long rk_geometric_search(rk_state *state, double p)
-{
- double U;
- long X;
- double sum, prod, q;
-
- X = 1;
- sum = prod = p;
- q = 1.0 - p;
- U = rk_double(state);
- while (U > sum)
- {
- prod *= q;
- sum += prod;
- X++;
- }
- return X;
-}
-
-long rk_geometric_inversion(rk_state *state, double p)
-{
- return (long)ceil(log(1.0-rk_double(state))/log(1.0-p));
-}
-
-long rk_geometric(rk_state *state, double p)
-{
- if (p >= 0.333333333333333333333333)
- {
- return rk_geometric_search(state, p);
- } else
- {
- return rk_geometric_inversion(state, p);
- }
-}
-
-long rk_hypergeometric_hyp(rk_state *state, long good, long bad, long sample)
-{
- long d1, K, Z;
- double d2, U, Y;
-
- d1 = bad + good - sample;
- d2 = (double)min(bad, good);
-
- Y = d2;
- K = sample;
- while (Y > 0.0)
- {
- U = rk_double(state);
- Y -= (long)floor(U + Y/(d1 + K));
- K--;
- if (K == 0) break;
- }
- Z = (long)(d2 - Y);
- if (good > bad) Z = sample - Z;
- return Z;
-}
-
-/* D1 = 2*sqrt(2/e) */
-/* D2 = 3 - 2*sqrt(3/e) */
-#define D1 1.7155277699214135
-#define D2 0.8989161620588988
-long rk_hypergeometric_hrua(rk_state *state, long good, long bad, long sample)
-{
- long mingoodbad, maxgoodbad, popsize, m, d9;
- double d4, d5, d6, d7, d8, d10, d11;
- long Z;
- double T, W, X, Y;
-
- mingoodbad = min(good, bad);
- popsize = good + bad;
- maxgoodbad = max(good, bad);
- m = min(sample, popsize - sample);
- d4 = ((double)mingoodbad) / popsize;
- d5 = 1.0 - d4;
- d6 = m*d4 + 0.5;
- d7 = sqrt((double)(popsize - m) * sample * d4 * d5 / (popsize - 1) + 0.5);
- d8 = D1*d7 + D2;
- d9 = (long)floor((double)(m + 1) * (mingoodbad + 1) / (popsize + 2));
- d10 = (loggam(d9+1) + loggam(mingoodbad-d9+1) + loggam(m-d9+1) +
- loggam(maxgoodbad-m+d9+1));
- d11 = min(min(m, mingoodbad)+1.0, floor(d6+16*d7));
- /* 16 for 16-decimal-digit precision in D1 and D2 */
-
- while (1)
- {
- X = rk_double(state);
- Y = rk_double(state);
- W = d6 + d8*(Y- 0.5)/X;
-
- /* fast rejection: */
- if ((W < 0.0) || (W >= d11)) continue;
-
- Z = (long)floor(W);
- T = d10 - (loggam(Z+1) + loggam(mingoodbad-Z+1) + loggam(m-Z+1) +
- loggam(maxgoodbad-m+Z+1));
-
- /* fast acceptance: */
- if ((X*(4.0-X)-3.0) <= T) break;
-
- /* fast rejection: */
- if (X*(X-T) >= 1) continue;
-
- if (2.0*log(X) <= T) break; /* acceptance */
- }
-
- /* this is a correction to HRUA* by Ivan Frohne in rv.py */
- if (good > bad) Z = m - Z;
-
- /* another fix from rv.py to allow sample to exceed popsize/2 */
- if (m < sample) Z = good - Z;
-
- return Z;
-}
-#undef D1
-#undef D2
-
-long rk_hypergeometric(rk_state *state, long good, long bad, long sample)
-{
- if (sample > 10)
- {
- return rk_hypergeometric_hrua(state, good, bad, sample);
- } else
- {
- return rk_hypergeometric_hyp(state, good, bad, sample);
- }
-}
-
-double rk_triangular(rk_state *state, double left, double mode, double right)
-{
- double base, leftbase, ratio, leftprod, rightprod;
- double U;
-
- base = right - left;
- leftbase = mode - left;
- ratio = leftbase / base;
- leftprod = leftbase*base;
- rightprod = (right - mode)*base;
-
- U = rk_double(state);
- if (U <= ratio)
- {
- return left + sqrt(U*leftprod);
- } else
- {
- return right - sqrt((1.0 - U) * rightprod);
- }
-}
-
-long rk_logseries(rk_state *state, double p)
-{
- double q, r, U, V;
- long result;
-
- r = log(1.0 - p);
-
- while (1) {
- V = rk_double(state);
- if (V >= p) {
- return 1;
- }
- U = rk_double(state);
- q = 1.0 - exp(r*U);
- if (V <= q*q) {
- result = (long)floor(1 + log(V)/log(q));
- /* Reject if v == 0.0 since cast of inf not well defined */
- if ((result < 1) || (V == 0.0)) {
- continue;
- }
- else {
- return result;
- }
- }
- if (V >= q) {
- return 1;
- }
- return 2;
- }
-}
diff --git a/numpy/random/mtrand/distributions.h b/numpy/random/mtrand/distributions.h
deleted file mode 100644
index 0b42bc794..000000000
--- a/numpy/random/mtrand/distributions.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Copyright 2005 Robert Kern (robert.kern@gmail.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _RK_DISTR_
-#define _RK_DISTR_
-
-#include "randomkit.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* References:
- *
- * Devroye, Luc. _Non-Uniform Random Variate Generation_.
- * Springer-Verlag, New York, 1986.
- * http://cgm.cs.mcgill.ca/~luc/rnbookindex.html
- *
- * Kachitvichyanukul, V. and Schmeiser, B. W. Binomial Random Variate
- * Generation. Communications of the ACM, 31, 2 (February, 1988) 216.
- *
- * Hoermann, W. The Transformed Rejection Method for Generating Poisson Random
- * Variables. Insurance: Mathematics and Economics, (to appear)
- * http://citeseer.csail.mit.edu/151115.html
- *
- * Marsaglia, G. and Tsang, W. W. A Simple Method for Generating Gamma
- * Variables. ACM Transactions on Mathematical Software, Vol. 26, No. 3,
- * September 2000, Pages 363–372.
- */
-
-/* Normal distribution with mean=loc and standard deviation=scale. */
-extern double rk_normal(rk_state *state, double loc, double scale);
-
-/* Standard exponential distribution (mean=1) computed by inversion of the
- * CDF. */
-extern double rk_standard_exponential(rk_state *state);
-
-/* Exponential distribution with mean=scale. */
-extern double rk_exponential(rk_state *state, double scale);
-
-/* Uniform distribution on interval [loc, loc+scale). */
-extern double rk_uniform(rk_state *state, double loc, double scale);
-
-/* Standard gamma distribution with shape parameter.
- * When shape < 1, the algorithm given by (Devroye p. 304) is used.
- * When shape == 1, a Exponential variate is generated.
- * When shape > 1, the small and fast method of (Marsaglia and Tsang 2000)
- * is used.
- */
-extern double rk_standard_gamma(rk_state *state, double shape);
-
-/* Gamma distribution with shape and scale. */
-extern double rk_gamma(rk_state *state, double shape, double scale);
-
-/* Beta distribution computed by combining two gamma variates (Devroye p. 432).
- */
-extern double rk_beta(rk_state *state, double a, double b);
-
-/* Chi^2 distribution computed by transforming a gamma variate (it being a
- * special case Gamma(df/2, 2)). */
-extern double rk_chisquare(rk_state *state, double df);
-
-/* Noncentral Chi^2 distribution computed by modifying a Chi^2 variate. */
-extern double rk_noncentral_chisquare(rk_state *state, double df, double nonc);
-
-/* F distribution computed by taking the ratio of two Chi^2 variates. */
-extern double rk_f(rk_state *state, double dfnum, double dfden);
-
-/* Noncentral F distribution computed by taking the ratio of a noncentral Chi^2
- * and a Chi^2 variate. */
-extern double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc);
-
-/* Binomial distribution with n Bernoulli trials with success probability p.
- * When n*p <= 30, the "Second waiting time method" given by (Devroye p. 525) is
- * used. Otherwise, the BTPE algorithm of (Kachitvichyanukul and Schmeiser 1988)
- * is used. */
-extern long rk_binomial(rk_state *state, long n, double p);
-
-/* Binomial distribution using BTPE. */
-extern long rk_binomial_btpe(rk_state *state, long n, double p);
-
-/* Binomial distribution using inversion and chop-down */
-extern long rk_binomial_inversion(rk_state *state, long n, double p);
-
-/* Negative binomial distribution computed by generating a Gamma(n, (1-p)/p)
- * variate Y and returning a Poisson(Y) variate (Devroye p. 543). */
-extern long rk_negative_binomial(rk_state *state, double n, double p);
-
-/* Poisson distribution with mean=lam.
- * When lam < 10, a basic algorithm using repeated multiplications of uniform
- * variates is used (Devroye p. 504).
- * When lam >= 10, algorithm PTRS from (Hoermann 1992) is used.
- */
-extern long rk_poisson(rk_state *state, double lam);
-
-/* Poisson distribution computed by repeated multiplication of uniform variates.
- */
-extern long rk_poisson_mult(rk_state *state, double lam);
-
-/* Poisson distribution computer by the PTRS algorithm. */
-extern long rk_poisson_ptrs(rk_state *state, double lam);
-
-/* Standard Cauchy distribution computed by dividing standard gaussians
- * (Devroye p. 451). */
-extern double rk_standard_cauchy(rk_state *state);
-
-/* Standard t-distribution with df degrees of freedom (Devroye p. 445 as
- * corrected in the Errata). */
-extern double rk_standard_t(rk_state *state, double df);
-
-/* von Mises circular distribution with center mu and shape kappa on [-pi,pi]
- * (Devroye p. 476 as corrected in the Errata). */
-extern double rk_vonmises(rk_state *state, double mu, double kappa);
-
-/* Pareto distribution via inversion (Devroye p. 262) */
-extern double rk_pareto(rk_state *state, double a);
-
-/* Weibull distribution via inversion (Devroye p. 262) */
-extern double rk_weibull(rk_state *state, double a);
-
-/* Power distribution via inversion (Devroye p. 262) */
-extern double rk_power(rk_state *state, double a);
-
-/* Laplace distribution */
-extern double rk_laplace(rk_state *state, double loc, double scale);
-
-/* Gumbel distribution */
-extern double rk_gumbel(rk_state *state, double loc, double scale);
-
-/* Logistic distribution */
-extern double rk_logistic(rk_state *state, double loc, double scale);
-
-/* Log-normal distribution */
-extern double rk_lognormal(rk_state *state, double mean, double sigma);
-
-/* Rayleigh distribution */
-extern double rk_rayleigh(rk_state *state, double mode);
-
-/* Wald distribution */
-extern double rk_wald(rk_state *state, double mean, double scale);
-
-/* Zipf distribution */
-extern long rk_zipf(rk_state *state, double a);
-
-/* Geometric distribution */
-extern long rk_geometric(rk_state *state, double p);
-extern long rk_geometric_search(rk_state *state, double p);
-extern long rk_geometric_inversion(rk_state *state, double p);
-
-/* Hypergeometric distribution */
-extern long rk_hypergeometric(rk_state *state, long good, long bad, long sample);
-extern long rk_hypergeometric_hyp(rk_state *state, long good, long bad, long sample);
-extern long rk_hypergeometric_hrua(rk_state *state, long good, long bad, long sample);
-
-/* Triangular distribution */
-extern double rk_triangular(rk_state *state, double left, double mode, double right);
-
-/* Logarithmic series distribution */
-extern long rk_logseries(rk_state *state, double p);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _RK_DISTR_ */
diff --git a/numpy/random/mtrand/generate_mtrand_c.py b/numpy/random/mtrand/generate_mtrand_c.py
deleted file mode 100644
index ec935e6dd..000000000
--- a/numpy/random/mtrand/generate_mtrand_c.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
-import sys
-import re
-import os
-
-unused_internal_funcs = ['__Pyx_PrintItem',
- '__Pyx_PrintNewline',
- '__Pyx_ReRaise',
- #'__Pyx_GetExcValue',
- '__Pyx_ArgTypeTest',
- '__Pyx_SetVtable',
- '__Pyx_GetVtable',
- '__Pyx_CreateClass']
-
-if __name__ == '__main__':
- # Use cython here so that long docstrings are broken up.
- # This is needed for some VC++ compilers.
- os.system('cython mtrand.pyx')
- mtrand_c = open('mtrand.c', 'r')
- processed = open('mtrand_pp.c', 'w')
- unused_funcs_str = '(' + '|'.join(unused_internal_funcs) + ')'
- uifpat = re.compile(r'static \w+ \*?'+unused_funcs_str+r'.*/\*proto\*/')
- linepat = re.compile(r'/\* ".*/mtrand.pyx":')
- for linenum, line in enumerate(mtrand_c):
- m = re.match(r'^(\s+arrayObject\w*\s*=\s*[(])[(]PyObject\s*[*][)]',
- line)
- if m:
- line = '%s(PyArrayObject *)%s' % (m.group(1), line[m.end():])
- m = uifpat.match(line)
- if m:
- line = ''
- m = re.search(unused_funcs_str, line)
- if m:
- print("%s was declared unused, but is used at line %d" % (m.group(),
- linenum+1), file=sys.stderr)
- line = linepat.sub(r'/* "mtrand.pyx":', line)
- processed.write(line)
- mtrand_c.close()
- processed.close()
- os.rename('mtrand_pp.c', 'mtrand.c')
diff --git a/numpy/random/mtrand/initarray.c b/numpy/random/mtrand/initarray.c
deleted file mode 100644
index 21f1dc05a..000000000
--- a/numpy/random/mtrand/initarray.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * These function have been adapted from Python 2.4.1's _randommodule.c
- *
- * The following changes have been made to it in 2005 by Robert Kern:
- *
- * * init_by_array has been declared extern, has a void return, and uses the
- * rk_state structure to hold its data.
- *
- * The original file has the following verbatim comments:
- *
- * ------------------------------------------------------------------
- * The code in this module was based on a download from:
- * http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html
- *
- * It was modified in 2002 by Raymond Hettinger as follows:
- *
- * * the principal computational lines untouched except for tabbing.
- *
- * * renamed genrand_res53() to random_random() and wrapped
- * in python calling/return code.
- *
- * * genrand_int32() and the helper functions, init_genrand()
- * and init_by_array(), were declared static, wrapped in
- * Python calling/return code. also, their global data
- * references were replaced with structure references.
- *
- * * unused functions from the original were deleted.
- * new, original C python code was added to implement the
- * Random() interface.
- *
- * The following are the verbatim comments from the original code:
- *
- * A C-program for MT19937, with initialization improved 2002/1/26.
- * Coded by Takuji Nishimura and Makoto Matsumoto.
- *
- * Before using, initialize the state by using init_genrand(seed)
- * or init_by_array(init_key, key_length).
- *
- * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. The names of its contributors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Any feedback is very welcome.
- * http://www.math.keio.ac.jp/matumoto/emt.html
- * email: matumoto@math.keio.ac.jp
- */
-#define NPY_NO_DEPRECATED_API NPY_API_VERSION
-
-#include "initarray.h"
-
-static void
-init_genrand(rk_state *self, unsigned long s);
-
-/* initializes mt[RK_STATE_LEN] with a seed */
-static void
-init_genrand(rk_state *self, unsigned long s)
-{
- int mti;
- unsigned long *mt = self->key;
-
- mt[0] = s & 0xffffffffUL;
- for (mti = 1; mti < RK_STATE_LEN; mti++) {
- /*
- * See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
- * In the previous versions, MSBs of the seed affect
- * only MSBs of the array mt[].
- * 2002/01/09 modified by Makoto Matsumoto
- */
- mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
- /* for > 32 bit machines */
- mt[mti] &= 0xffffffffUL;
- }
- self->pos = mti;
- return;
-}
-
-
-/*
- * initialize by an array with array-length
- * init_key is the array for initializing keys
- * key_length is its length
- */
-extern void
-init_by_array(rk_state *self, unsigned long init_key[], npy_intp key_length)
-{
- /* was signed in the original code. RDH 12/16/2002 */
- npy_intp i = 1;
- npy_intp j = 0;
- unsigned long *mt = self->key;
- npy_intp k;
-
- init_genrand(self, 19650218UL);
- k = (RK_STATE_LEN > key_length ? RK_STATE_LEN : key_length);
- for (; k; k--) {
- /* non linear */
- mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL))
- + init_key[j] + j;
- /* for > 32 bit machines */
- mt[i] &= 0xffffffffUL;
- i++;
- j++;
- if (i >= RK_STATE_LEN) {
- mt[0] = mt[RK_STATE_LEN - 1];
- i = 1;
- }
- if (j >= key_length) {
- j = 0;
- }
- }
- for (k = RK_STATE_LEN - 1; k; k--) {
- mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- - i; /* non linear */
- mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
- i++;
- if (i >= RK_STATE_LEN) {
- mt[0] = mt[RK_STATE_LEN - 1];
- i = 1;
- }
- }
-
- mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
- self->gauss = 0;
- self->has_gauss = 0;
- self->has_binomial = 0;
-}
diff --git a/numpy/random/mtrand/initarray.h b/numpy/random/mtrand/initarray.h
deleted file mode 100644
index f5e5e5332..000000000
--- a/numpy/random/mtrand/initarray.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Python.h"
-#define NO_IMPORT_ARRAY
-#include "numpy/arrayobject.h"
-#include "randomkit.h"
-
-extern void
-init_by_array(rk_state *self, unsigned long init_key[],
- npy_intp key_length);
diff --git a/numpy/random/mtrand/mtrand_py_helper.h b/numpy/random/mtrand/mtrand_py_helper.h
deleted file mode 100644
index 266847cbe..000000000
--- a/numpy/random/mtrand/mtrand_py_helper.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _MTRAND_PY_HELPER_H_
-#define _MTRAND_PY_HELPER_H_
-
-#include <Python.h>
-
-static PyObject *empty_py_bytes(npy_intp length, void **bytes)
-{
- PyObject *b;
-#if PY_MAJOR_VERSION >= 3
- b = PyBytes_FromStringAndSize(NULL, length);
- if (b) {
- *bytes = PyBytes_AS_STRING(b);
- }
-#else
- b = PyString_FromStringAndSize(NULL, length);
- if (b) {
- *bytes = PyString_AS_STRING(b);
- }
-#endif
- return b;
-}
-
-#endif /* _MTRAND_PY_HELPER_H_ */
diff --git a/numpy/random/mtrand/numpy.pxd b/numpy/random/mtrand/numpy.pxd
deleted file mode 100644
index 9092fa113..000000000
--- a/numpy/random/mtrand/numpy.pxd
+++ /dev/null
@@ -1,163 +0,0 @@
-# :Author: Travis Oliphant
-from cpython.exc cimport PyErr_Print
-
-cdef extern from "numpy/npy_no_deprecated_api.h": pass
-
-cdef extern from "numpy/arrayobject.h":
-
- cdef enum NPY_TYPES:
- NPY_BOOL
- NPY_BYTE
- NPY_UBYTE
- NPY_SHORT
- NPY_USHORT
- NPY_INT
- NPY_UINT
- NPY_LONG
- NPY_ULONG
- NPY_LONGLONG
- NPY_ULONGLONG
- NPY_FLOAT
- NPY_DOUBLE
- NPY_LONGDOUBLE
- NPY_CFLOAT
- NPY_CDOUBLE
- NPY_CLONGDOUBLE
- NPY_OBJECT
- NPY_STRING
- NPY_UNICODE
- NPY_VOID
- NPY_NTYPES
- NPY_NOTYPE
-
- cdef enum requirements:
- NPY_ARRAY_C_CONTIGUOUS
- NPY_ARRAY_F_CONTIGUOUS
- NPY_ARRAY_OWNDATA
- NPY_ARRAY_FORCECAST
- NPY_ARRAY_ENSURECOPY
- NPY_ARRAY_ENSUREARRAY
- NPY_ARRAY_ELEMENTSTRIDES
- NPY_ARRAY_ALIGNED
- NPY_ARRAY_NOTSWAPPED
- NPY_ARRAY_WRITEABLE
- NPY_ARRAY_WRITEBACKIFCOPY
- NPY_ARR_HAS_DESCR
-
- NPY_ARRAY_BEHAVED
- NPY_ARRAY_BEHAVED_NS
- NPY_ARRAY_CARRAY
- NPY_ARRAY_CARRAY_RO
- NPY_ARRAY_FARRAY
- NPY_ARRAY_FARRAY_RO
- NPY_ARRAY_DEFAULT
-
- NPY_ARRAY_IN_ARRAY
- NPY_ARRAY_OUT_ARRAY
- NPY_ARRAY_INOUT_ARRAY
- NPY_ARRAY_IN_FARRAY
- NPY_ARRAY_OUT_FARRAY
- NPY_ARRAY_INOUT_FARRAY
-
- NPY_ARRAY_UPDATE_ALL
-
- cdef enum defines:
- NPY_MAXDIMS
-
- ctypedef struct npy_cdouble:
- double real
- double imag
-
- ctypedef struct npy_cfloat:
- double real
- double imag
-
- ctypedef int npy_int
- ctypedef int npy_intp
- ctypedef int npy_int64
- ctypedef int npy_uint64
- ctypedef int npy_int32
- ctypedef int npy_uint32
- ctypedef int npy_int16
- ctypedef int npy_uint16
- ctypedef int npy_int8
- ctypedef int npy_uint8
- ctypedef int npy_bool
-
- ctypedef extern class numpy.dtype [object PyArray_Descr]: pass
-
- ctypedef extern class numpy.ndarray [object PyArrayObject]: pass
-
- ctypedef extern class numpy.flatiter [object PyArrayIterObject]:
- cdef int nd_m1
- cdef npy_intp index, size
- cdef ndarray ao
- cdef char *dataptr
-
- ctypedef extern class numpy.broadcast [object PyArrayMultiIterObject]:
- cdef int numiter
- cdef npy_intp size, index
- cdef int nd
- cdef npy_intp *dimensions
- cdef void **iters
-
- object PyArray_ZEROS(int ndims, npy_intp* dims, NPY_TYPES type_num, int fortran)
- object PyArray_EMPTY(int ndims, npy_intp* dims, NPY_TYPES type_num, int fortran)
- dtype PyArray_DescrFromTypeNum(NPY_TYPES type_num)
- object PyArray_SimpleNew(int ndims, npy_intp* dims, NPY_TYPES type_num)
- int PyArray_Check(object obj)
- object PyArray_ContiguousFromAny(object obj, NPY_TYPES type,
- int mindim, int maxdim)
- object PyArray_ContiguousFromObject(object obj, NPY_TYPES type,
- int mindim, int maxdim)
- npy_intp PyArray_SIZE(ndarray arr)
- npy_intp PyArray_NBYTES(ndarray arr)
- object PyArray_FromAny(object obj, dtype newtype, int mindim, int maxdim,
- int requirements, object context)
- object PyArray_FROMANY(object obj, NPY_TYPES type_num, int min,
- int max, int requirements)
- object PyArray_NewFromDescr(object subtype, dtype newtype, int nd,
- npy_intp* dims, npy_intp* strides, void* data,
- int flags, object parent)
-
- object PyArray_FROM_OTF(object obj, NPY_TYPES type, int flags)
- object PyArray_EnsureArray(object)
-
- object PyArray_MultiIterNew(int n, ...)
-
- char *PyArray_MultiIter_DATA(broadcast multi, int i) nogil
- void PyArray_MultiIter_NEXTi(broadcast multi, int i) nogil
- void PyArray_MultiIter_NEXT(broadcast multi) nogil
-
- object PyArray_IterNew(object arr)
- void PyArray_ITER_NEXT(flatiter it) nogil
- void* PyArray_ITER_DATA(flatiter it) nogil
-
- dtype PyArray_DescrFromType(int)
-
- int _import_array() except -1
-
-# include functions that were once macros in the new api
-
- int PyArray_NDIM(ndarray arr)
- char * PyArray_DATA(ndarray arr)
- npy_intp * PyArray_DIMS(ndarray arr)
- npy_intp * PyArray_STRIDES(ndarray arr)
- npy_intp PyArray_DIM(ndarray arr, int idim)
- npy_intp PyArray_STRIDE(ndarray arr, int istride)
- object PyArray_BASE(ndarray arr)
- dtype PyArray_DESCR(ndarray arr)
- int PyArray_FLAGS(ndarray arr)
- npy_intp PyArray_ITEMSIZE(ndarray arr)
- int PyArray_TYPE(ndarray arr)
- int PyArray_CHKFLAGS(ndarray arr, int flags)
- object PyArray_GETITEM(ndarray arr, char *itemptr)
-
-
-# copied from cython version with addition of PyErr_Print.
-cdef inline int import_array() except -1:
- try:
- _import_array()
- except Exception:
- PyErr_Print()
- raise ImportError("numpy.core.multiarray failed to import")
diff --git a/numpy/random/mtrand/randint_helpers.pxi.in b/numpy/random/mtrand/randint_helpers.pxi.in
deleted file mode 100644
index 894a25167..000000000
--- a/numpy/random/mtrand/randint_helpers.pxi.in
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-Template for each `dtype` helper function in `np.random.randint`.
-"""
-
-{{py:
-
-dtypes = (
- ('bool', 'bool', 'bool_'),
- ('int8', 'uint8', 'int8'),
- ('int16', 'uint16', 'int16'),
- ('int32', 'uint32', 'int32'),
- ('int64', 'uint64', 'int64'),
- ('uint8', 'uint8', 'uint8'),
- ('uint16', 'uint16', 'uint16'),
- ('uint32', 'uint32', 'uint32'),
- ('uint64', 'uint64', 'uint64'),
-)
-
-def get_dispatch(dtypes):
- for npy_dt, npy_udt, np_dt in dtypes:
- yield npy_dt, npy_udt, np_dt
-}}
-
-{{for npy_dt, npy_udt, np_dt in get_dispatch(dtypes)}}
-
-def _rand_{{npy_dt}}(npy_{{npy_dt}} low, npy_{{npy_dt}} high, size, rngstate):
- """
- _rand_{{npy_dt}}(low, high, size, rngstate)
-
- Return random np.{{np_dt}} integers between ``low`` and ``high``, inclusive.
-
- Return random integers from the "discrete uniform" distribution in the
- closed interval [``low``, ``high``). On entry the arguments are presumed
- to have been validated for size and order for the np.{{np_dt}} type.
-
- Parameters
- ----------
- low : int
- Lowest (signed) integer to be drawn from the distribution.
- high : int
- Highest (signed) integer to be drawn from the distribution.
- size : int or tuple of ints
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn. Default is None, in which case a
- single value is returned.
- rngstate : encapsulated pointer to rk_state
- The specific type depends on the python version. In Python 2 it is
- a PyCObject, in Python 3 a PyCapsule object.
-
- Returns
- -------
- out : python integer or ndarray of np.{{np_dt}}
- `size`-shaped array of random integers from the appropriate
- distribution, or a single such random int if `size` not provided.
-
- """
- cdef npy_{{npy_udt}} off, rng, buf
- cdef npy_{{npy_udt}} *out
- cdef ndarray array "arrayObject"
- cdef npy_intp cnt
- cdef rk_state *state = <rk_state *>PyCapsule_GetPointer(rngstate, NULL)
-
- off = <npy_{{npy_udt}}>(low)
- rng = <npy_{{npy_udt}}>(high) - <npy_{{npy_udt}}>(low)
-
- if size is None:
- rk_random_{{npy_udt}}(off, rng, 1, &buf, state)
- return np.{{np_dt}}(<npy_{{npy_dt}}>buf)
- else:
- array = <ndarray>np.empty(size, np.{{np_dt}})
- cnt = PyArray_SIZE(array)
- array_data = <npy_{{npy_udt}} *>PyArray_DATA(array)
- with nogil:
- rk_random_{{npy_udt}}(off, rng, cnt, array_data, state)
- return array
-
-{{endfor}}
diff --git a/numpy/random/mtrand/randomkit.c b/numpy/random/mtrand/randomkit.c
deleted file mode 100644
index 6371ebe33..000000000
--- a/numpy/random/mtrand/randomkit.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/* Random kit 1.3 */
-
-/*
- * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org)
- *
- * The rk_random and rk_seed functions algorithms and the original design of
- * the Mersenne Twister RNG:
- *
- * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. The names of its contributors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Original algorithm for the implementation of rk_interval function from
- * Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by
- * Magnus Jonsson.
- *
- * Constants used in the rk_double implementation by Isaku Wada.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* static char const rcsid[] =
- "@(#) $Jeannot: randomkit.c,v 1.28 2005/07/21 22:14:09 js Exp $"; */
-
-#ifdef _WIN32
-/*
- * Windows
- * XXX: we have to use this ugly defined(__GNUC__) because it is not easy to
- * detect the compiler used in distutils itself
- */
-#if (defined(__GNUC__) && defined(NPY_NEEDS_MINGW_TIME_WORKAROUND))
-
-/*
- * FIXME: ideally, we should set this to the real version of MSVCRT. We need
- * something higher than 0x601 to enable _ftime64 and co
- */
-#define __MSVCRT_VERSION__ 0x0700
-#include <time.h>
-#include <sys/timeb.h>
-
-/*
- * mingw msvcr lib import wrongly export _ftime, which does not exist in the
- * actual msvc runtime for version >= 8; we make it an alias to _ftime64, which
- * is available in those versions of the runtime
- */
-#define _FTIME(x) _ftime64((x))
-#else
-#include <time.h>
-#include <sys/timeb.h>
-#define _FTIME(x) _ftime((x))
-#endif
-
-#ifndef RK_NO_WINCRYPT
-/* Windows crypto */
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0400
-#endif
-#include <windows.h>
-#include <wincrypt.h>
-#endif
-
-/*
- * Do not move this include. randomkit.h must be included
- * after windows timeb.h is included.
- */
-#include "randomkit.h"
-
-#else
-/* Unix */
-#include "randomkit.h"
-#include <time.h>
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-#include <assert.h>
-
-#ifndef RK_DEV_URANDOM
-#define RK_DEV_URANDOM "/dev/urandom"
-#endif
-
-#ifndef RK_DEV_RANDOM
-#define RK_DEV_RANDOM "/dev/random"
-#endif
-
-char *rk_strerror[RK_ERR_MAX] =
-{
- "no error",
- "random device unvavailable"
-};
-
-/* static functions */
-static unsigned long rk_hash(unsigned long key);
-
-void
-rk_seed(unsigned long seed, rk_state *state)
-{
- int pos;
- seed &= 0xffffffffUL;
-
- /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
- for (pos = 0; pos < RK_STATE_LEN; pos++) {
- state->key[pos] = seed;
- seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
- }
- state->pos = RK_STATE_LEN;
- state->gauss = 0;
- state->has_gauss = 0;
- state->has_binomial = 0;
-}
-
-/* Thomas Wang 32 bits integer hash function */
-unsigned long
-rk_hash(unsigned long key)
-{
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
-}
-
-rk_error
-rk_randomseed(rk_state *state)
-{
-#ifndef _WIN32
- struct timeval tv;
-#else
- struct _timeb tv;
-#endif
- int i;
-
- if (rk_devfill(state->key, sizeof(state->key), 0) == RK_NOERR) {
- /* ensures non-zero key */
- state->key[0] |= 0x80000000UL;
- state->pos = RK_STATE_LEN;
- state->gauss = 0;
- state->has_gauss = 0;
- state->has_binomial = 0;
-
- for (i = 0; i < 624; i++) {
- state->key[i] &= 0xffffffffUL;
- }
- return RK_NOERR;
- }
-
-#ifndef _WIN32
- gettimeofday(&tv, NULL);
- rk_seed(rk_hash(getpid()) ^ rk_hash(tv.tv_sec) ^ rk_hash(tv.tv_usec)
- ^ rk_hash(clock()), state);
-#else
- _FTIME(&tv);
- rk_seed(rk_hash(tv.time) ^ rk_hash(tv.millitm) ^ rk_hash(clock()), state);
-#endif
-
- return RK_ENODEV;
-}
-
-/* Magic Mersenne Twister constants */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0dfUL
-#define UPPER_MASK 0x80000000UL
-#define LOWER_MASK 0x7fffffffUL
-
-/*
- * Slightly optimised reference implementation of the Mersenne Twister
- * Note that regardless of the precision of long, only 32 bit random
- * integers are produced
- */
-unsigned long
-rk_random(rk_state *state)
-{
- unsigned long y;
-
- if (state->pos == RK_STATE_LEN) {
- int i;
-
- for (i = 0; i < N - M; i++) {
- y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
- state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
- }
- for (; i < N - 1; i++) {
- y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
- state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
- }
- y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
- state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
-
- state->pos = 0;
- }
- y = state->key[state->pos++];
-
- /* Tempering */
- y ^= (y >> 11);
- y ^= (y << 7) & 0x9d2c5680UL;
- y ^= (y << 15) & 0xefc60000UL;
- y ^= (y >> 18);
-
- return y;
-}
-
-
-/*
- * Returns an unsigned 64 bit random integer.
- */
-NPY_INLINE static npy_uint64
-rk_uint64(rk_state *state)
-{
- npy_uint64 upper = (npy_uint64)rk_random(state) << 32;
- npy_uint64 lower = (npy_uint64)rk_random(state);
- return upper | lower;
-}
-
-
-/*
- * Returns an unsigned 32 bit random integer.
- */
-NPY_INLINE static npy_uint32
-rk_uint32(rk_state *state)
-{
- return (npy_uint32)rk_random(state);
-}
-
-
-/*
- * Fills an array with cnt random npy_uint64 between off and off + rng
- * inclusive. The numbers wrap if rng is sufficiently large.
- */
-void
-rk_random_uint64(npy_uint64 off, npy_uint64 rng, npy_intp cnt,
- npy_uint64 *out, rk_state *state)
-{
- npy_uint64 val, mask = rng;
- npy_intp i;
-
- if (rng == 0) {
- for (i = 0; i < cnt; i++) {
- out[i] = off;
- }
- return;
- }
-
- /* Smallest bit mask >= max */
- mask |= mask >> 1;
- mask |= mask >> 2;
- mask |= mask >> 4;
- mask |= mask >> 8;
- mask |= mask >> 16;
- mask |= mask >> 32;
-
- for (i = 0; i < cnt; i++) {
- if (rng <= 0xffffffffUL) {
- while ((val = (rk_uint32(state) & mask)) > rng);
- }
- else {
- while ((val = (rk_uint64(state) & mask)) > rng);
- }
- out[i] = off + val;
- }
-}
-
-
-/*
- * Fills an array with cnt random npy_uint32 between off and off + rng
- * inclusive. The numbers wrap if rng is sufficiently large.
- */
-void
-rk_random_uint32(npy_uint32 off, npy_uint32 rng, npy_intp cnt,
- npy_uint32 *out, rk_state *state)
-{
- npy_uint32 val, mask = rng;
- npy_intp i;
-
- if (rng == 0) {
- for (i = 0; i < cnt; i++) {
- out[i] = off;
- }
- return;
- }
-
- /* Smallest bit mask >= max */
- mask |= mask >> 1;
- mask |= mask >> 2;
- mask |= mask >> 4;
- mask |= mask >> 8;
- mask |= mask >> 16;
-
- for (i = 0; i < cnt; i++) {
- while ((val = (rk_uint32(state) & mask)) > rng);
- out[i] = off + val;
- }
-}
-
-
-/*
- * Fills an array with cnt random npy_uint16 between off and off + rng
- * inclusive. The numbers wrap if rng is sufficiently large.
- */
-void
-rk_random_uint16(npy_uint16 off, npy_uint16 rng, npy_intp cnt,
- npy_uint16 *out, rk_state *state)
-{
- npy_uint16 val, mask = rng;
- npy_intp i;
- npy_uint32 buf;
- int bcnt = 0;
-
- if (rng == 0) {
- for (i = 0; i < cnt; i++) {
- out[i] = off;
- }
- return;
- }
-
- /* Smallest bit mask >= max */
- mask |= mask >> 1;
- mask |= mask >> 2;
- mask |= mask >> 4;
- mask |= mask >> 8;
-
- for (i = 0; i < cnt; i++) {
- do {
- if (!bcnt) {
- buf = rk_uint32(state);
- bcnt = 1;
- }
- else {
- buf >>= 16;
- bcnt--;
- }
- val = (npy_uint16)buf & mask;
- } while (val > rng);
- out[i] = off + val;
- }
-}
-
-
-/*
- * Fills an array with cnt random npy_uint8 between off and off + rng
- * inclusive. The numbers wrap if rng is sufficiently large.
- */
-void
-rk_random_uint8(npy_uint8 off, npy_uint8 rng, npy_intp cnt,
- npy_uint8 *out, rk_state *state)
-{
- npy_uint8 val, mask = rng;
- npy_intp i;
- npy_uint32 buf;
- int bcnt = 0;
-
- if (rng == 0) {
- for (i = 0; i < cnt; i++) {
- out[i] = off;
- }
- return;
- }
-
- /* Smallest bit mask >= max */
- mask |= mask >> 1;
- mask |= mask >> 2;
- mask |= mask >> 4;
-
- for (i = 0; i < cnt; i++) {
- do {
- if (!bcnt) {
- buf = rk_uint32(state);
- bcnt = 3;
- }
- else {
- buf >>= 8;
- bcnt--;
- }
- val = (npy_uint8)buf & mask;
- } while (val > rng);
- out[i] = off + val;
- }
-}
-
-
-/*
- * Fills an array with cnt random npy_bool between off and off + rng
- * inclusive.
- */
-void
-rk_random_bool(npy_bool off, npy_bool rng, npy_intp cnt,
- npy_bool *out, rk_state *state)
-{
- npy_intp i;
- npy_uint32 buf;
- int bcnt = 0;
-
- if (rng == 0) {
- for (i = 0; i < cnt; i++) {
- out[i] = off;
- }
- return;
- }
-
- /* If we reach here rng and mask are one and off is zero */
- assert(rng == 1 && off == 0);
- for (i = 0; i < cnt; i++) {
- if (!bcnt) {
- buf = rk_uint32(state);
- bcnt = 31;
- }
- else {
- buf >>= 1;
- bcnt--;
- }
- out[i] = (buf & 0x00000001) != 0;
- }
-}
-
-
-long
-rk_long(rk_state *state)
-{
- return rk_ulong(state) >> 1;
-}
-
-unsigned long
-rk_ulong(rk_state *state)
-{
-#if ULONG_MAX <= 0xffffffffUL
- return rk_random(state);
-#else
- return (rk_random(state) << 32) | (rk_random(state));
-#endif
-}
-
-unsigned long
-rk_interval(unsigned long max, rk_state *state)
-{
- unsigned long mask = max, value;
-
- if (max == 0) {
- return 0;
- }
- /* Smallest bit mask >= max */
- mask |= mask >> 1;
- mask |= mask >> 2;
- mask |= mask >> 4;
- mask |= mask >> 8;
- mask |= mask >> 16;
-#if ULONG_MAX > 0xffffffffUL
- mask |= mask >> 32;
-#endif
-
- /* Search a random value in [0..mask] <= max */
-#if ULONG_MAX > 0xffffffffUL
- if (max <= 0xffffffffUL) {
- while ((value = (rk_random(state) & mask)) > max);
- }
- else {
- while ((value = (rk_ulong(state) & mask)) > max);
- }
-#else
- while ((value = (rk_ulong(state) & mask)) > max);
-#endif
- return value;
-}
-
-double
-rk_double(rk_state *state)
-{
- /* shifts : 67108864 = 0x4000000, 9007199254740992 = 0x20000000000000 */
- long a = rk_random(state) >> 5, b = rk_random(state) >> 6;
- return (a * 67108864.0 + b) / 9007199254740992.0;
-}
-
-void
-rk_fill(void *buffer, size_t size, rk_state *state)
-{
- unsigned long r;
- unsigned char *buf = buffer;
-
- for (; size >= 4; size -= 4) {
- r = rk_random(state);
- *(buf++) = r & 0xFF;
- *(buf++) = (r >> 8) & 0xFF;
- *(buf++) = (r >> 16) & 0xFF;
- *(buf++) = (r >> 24) & 0xFF;
- }
-
- if (!size) {
- return;
- }
- r = rk_random(state);
- for (; size; r >>= 8, size --) {
- *(buf++) = (unsigned char)(r & 0xFF);
- }
-}
-
-rk_error
-rk_devfill(void *buffer, size_t size, int strong)
-{
-#ifndef _WIN32
- FILE *rfile;
- int done;
-
- if (strong) {
- rfile = fopen(RK_DEV_RANDOM, "rb");
- }
- else {
- rfile = fopen(RK_DEV_URANDOM, "rb");
- }
- if (rfile == NULL) {
- return RK_ENODEV;
- }
- done = fread(buffer, size, 1, rfile);
- fclose(rfile);
- if (done) {
- return RK_NOERR;
- }
-#else
-
-#ifndef RK_NO_WINCRYPT
- HCRYPTPROV hCryptProv;
- BOOL done;
-
- if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT) || !hCryptProv) {
- return RK_ENODEV;
- }
- done = CryptGenRandom(hCryptProv, size, (unsigned char *)buffer);
- CryptReleaseContext(hCryptProv, 0);
- if (done) {
- return RK_NOERR;
- }
-#endif
-
-#endif
- return RK_ENODEV;
-}
-
-rk_error
-rk_altfill(void *buffer, size_t size, int strong, rk_state *state)
-{
- rk_error err;
-
- err = rk_devfill(buffer, size, strong);
- if (err) {
- rk_fill(buffer, size, state);
- }
- return err;
-}
-
-double
-rk_gauss(rk_state *state)
-{
- if (state->has_gauss) {
- const double tmp = state->gauss;
- state->gauss = 0;
- state->has_gauss = 0;
- return tmp;
- }
- else {
- double f, x1, x2, r2;
-
- do {
- x1 = 2.0*rk_double(state) - 1.0;
- x2 = 2.0*rk_double(state) - 1.0;
- r2 = x1*x1 + x2*x2;
- }
- while (r2 >= 1.0 || r2 == 0.0);
-
- /* Polar method, a more efficient version of the Box-Muller approach. */
- f = sqrt(-2.0*log(r2)/r2);
- /* Keep for next call */
- state->gauss = f*x1;
- state->has_gauss = 1;
- return f*x2;
- }
-}
diff --git a/numpy/random/pcg64.pyx b/numpy/random/pcg64.pyx
new file mode 100644
index 000000000..585520139
--- /dev/null
+++ b/numpy/random/pcg64.pyx
@@ -0,0 +1,270 @@
+import numpy as np
+cimport numpy as np
+
+from .common cimport *
+from .bit_generator cimport BitGenerator
+
+__all__ = ['PCG64']
+
+cdef extern from "src/pcg64/pcg64.h":
+ # Use int as generic type, actual type read from pcg64.h and is platform dependent
+ ctypedef int pcg64_random_t
+
+ struct s_pcg64_state:
+ pcg64_random_t *pcg_state
+ int has_uint32
+ uint32_t uinteger
+
+ ctypedef s_pcg64_state pcg64_state
+
+ uint64_t pcg64_next64(pcg64_state *state) nogil
+ uint32_t pcg64_next32(pcg64_state *state) nogil
+ void pcg64_jump(pcg64_state *state)
+ void pcg64_advance(pcg64_state *state, uint64_t *step)
+ void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc)
+ void pcg64_get_state(pcg64_state *state, uint64_t *state_arr, int *has_uint32, uint32_t *uinteger)
+ void pcg64_set_state(pcg64_state *state, uint64_t *state_arr, int has_uint32, uint32_t uinteger)
+
+cdef uint64_t pcg64_uint64(void* st) nogil:
+ return pcg64_next64(<pcg64_state *>st)
+
+cdef uint32_t pcg64_uint32(void *st) nogil:
+ return pcg64_next32(<pcg64_state *> st)
+
+cdef double pcg64_double(void* st) nogil:
+ return uint64_to_double(pcg64_next64(<pcg64_state *>st))
+
+
+cdef class PCG64(BitGenerator):
+ """
+ PCG64(seed_seq=None)
+
+ BitGenerator for the PCG-64 pseudo-random number generator.
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+
+ Notes
+ -----
+ PCG-64 is a 128-bit implementation of O'Neill's permutation congruential
+ generator ([1]_, [2]_). PCG-64 has a period of :math:`2^{128}` and supports
+ advancing an arbitrary number of steps as well as :math:`2^{127}` streams.
+ The specific member of the PCG family that we use is PCG XSL RR 128/64
+ as described in the paper ([2]_).
+
+ ``PCG64`` provides a capsule containing function pointers that produce
+ doubles, and unsigned 32 and 64- bit integers. These are not
+ directly consumable in Python and must be consumed by a ``Generator``
+ or similar object that supports low-level access.
+
+ Supports the method :meth:`advance` to advance the RNG an arbitrary number of
+ steps. The state of the PCG-64 RNG is represented by 2 128-bit unsigned
+ integers.
+
+ **State and Seeding**
+
+ The ``PCG64`` state vector consists of 2 unsigned 128-bit values,
+ which are represented externally as Python ints. One is the state of the
+ PRNG, which is advanced by a linear congruential generator (LCG). The
+ second is a fixed odd increment used in the LCG.
+
+ The input seed is processed by `SeedSequence` to generate both values. The
+ increment is not independently settable.
+
+ **Parallel Features**
+
+ The preferred way to use a BitGenerator in parallel applications is to use
+ the `SeedSequence.spawn` method to obtain entropy values, and to use these
+ to generate new BitGenerators:
+
+ >>> from numpy.random import Generator, PCG64, SeedSequence
+ >>> sg = SeedSequence(1234)
+ >>> rg = [Generator(PCG64(s)) for s in sg.spawn(10)]
+
+ **Compatibility Guarantee**
+
+ ``PCG64`` makes a guarantee that a fixed seed and will always produce
+ the same random integer stream.
+
+ References
+ ----------
+ .. [1] `"PCG, A Family of Better Random Number Generators"
+ <http://www.pcg-random.org/>`_
+ .. [2] O'Neill, Melissa E. `"PCG: A Family of Simple Fast Space-Efficient
+ Statistically Good Algorithms for Random Number Generation"
+ <https://www.cs.hmc.edu/tr/hmc-cs-2014-0905.pdf>`_
+ """
+
+ cdef pcg64_state rng_state
+ cdef pcg64_random_t pcg64_random_state
+
+ def __init__(self, seed=None):
+ BitGenerator.__init__(self, seed)
+ self.rng_state.pcg_state = &self.pcg64_random_state
+
+ self._bitgen.state = <void *>&self.rng_state
+ self._bitgen.next_uint64 = &pcg64_uint64
+ self._bitgen.next_uint32 = &pcg64_uint32
+ self._bitgen.next_double = &pcg64_double
+ self._bitgen.next_raw = &pcg64_uint64
+ # Seed the _bitgen
+ val = self._seed_seq.generate_state(4, np.uint64)
+ pcg64_set_seed(&self.rng_state,
+ <uint64_t *>np.PyArray_DATA(val),
+ (<uint64_t *>np.PyArray_DATA(val) + 2))
+ self._reset_state_variables()
+
+ cdef _reset_state_variables(self):
+ self.rng_state.has_uint32 = 0
+ self.rng_state.uinteger = 0
+
+ cdef jump_inplace(self, jumps):
+ """
+ Jump state in-place
+ Not part of public API
+
+ Parameters
+ ----------
+ jumps : integer, positive
+ Number of times to jump the state of the rng.
+
+ Notes
+ -----
+ The step size is phi-1 when multiplied by 2**128 where phi is the
+ golden ratio.
+ """
+ step = 0x9e3779b97f4a7c15f39cc0605cedc835
+ self.advance(step * int(jumps))
+
+ def jumped(self, jumps=1):
+ """
+ jumped(jumps=1)
+
+ Returns a new bit generator with the state jumped.
+
+ Jumps the state as-if jumps * 210306068529402873165736369884012333109
+ random numbers have been generated.
+
+ Parameters
+ ----------
+ jumps : integer, positive
+ Number of times to jump the state of the bit generator returned
+
+ Returns
+ -------
+ bit_generator : PCG64
+ New instance of generator jumped iter times
+
+ Notes
+ -----
+ The step size is phi-1 when multiplied by 2**128 where phi is the
+ golden ratio.
+ """
+ cdef PCG64 bit_generator
+
+ bit_generator = self.__class__()
+ bit_generator.state = self.state
+ bit_generator.jump_inplace(jumps)
+
+ return bit_generator
+
+ @property
+ def state(self):
+ """
+ Get or set the PRNG state
+
+ Returns
+ -------
+ state : dict
+ Dictionary containing the information required to describe the
+ state of the PRNG
+ """
+ cdef np.ndarray state_vec
+ cdef int has_uint32
+ cdef uint32_t uinteger
+
+ # state_vec is state.high, state.low, inc.high, inc.low
+ state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
+ pcg64_get_state(&self.rng_state,
+ <uint64_t *>np.PyArray_DATA(state_vec),
+ &has_uint32, &uinteger)
+ state = int(state_vec[0]) * 2**64 + int(state_vec[1])
+ inc = int(state_vec[2]) * 2**64 + int(state_vec[3])
+ return {'bit_generator': self.__class__.__name__,
+ 'state': {'state': state, 'inc': inc},
+ 'has_uint32': has_uint32,
+ 'uinteger': uinteger}
+
+ @state.setter
+ def state(self, value):
+ cdef np.ndarray state_vec
+ cdef int has_uint32
+ cdef uint32_t uinteger
+ if not isinstance(value, dict):
+ raise TypeError('state must be a dict')
+ bitgen = value.get('bit_generator', '')
+ if bitgen != self.__class__.__name__:
+ raise ValueError('state must be for a {0} '
+ 'RNG'.format(self.__class__.__name__))
+ state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
+ state_vec[0] = value['state']['state'] // 2 ** 64
+ state_vec[1] = value['state']['state'] % 2 ** 64
+ state_vec[2] = value['state']['inc'] // 2 ** 64
+ state_vec[3] = value['state']['inc'] % 2 ** 64
+ has_uint32 = value['has_uint32']
+ uinteger = value['uinteger']
+ pcg64_set_state(&self.rng_state,
+ <uint64_t *>np.PyArray_DATA(state_vec),
+ has_uint32, uinteger)
+
+ def advance(self, delta):
+ """
+ advance(delta)
+
+ Advance the underlying RNG as-if delta draws have occurred.
+
+ Parameters
+ ----------
+ delta : integer, positive
+ Number of draws to advance the RNG. Must be less than the
+ size state variable in the underlying RNG.
+
+ Returns
+ -------
+ self : PCG64
+ RNG advanced delta steps
+
+ Notes
+ -----
+ Advancing a RNG updates the underlying RNG state as-if a given
+ number of calls to the underlying RNG have been made. In general
+ there is not a one-to-one relationship between the number output
+ random values from a particular distribution and the number of
+ draws from the core RNG. This occurs for two reasons:
+
+ * The random values are simulated using a rejection-based method
+ and so, on average, more than one value from the underlying
+ RNG is required to generate an single draw.
+ * The number of bits required to generate a simulated value
+ differs from the number of bits generated by the underlying
+ RNG. For example, two 16-bit integer values can be simulated
+ from a single draw of a 32-bit RNG.
+
+ Advancing the RNG state resets any pre-computed random numbers.
+ This is required to ensure exact reproducibility.
+ """
+ delta = wrap_int(delta, 128)
+
+ cdef np.ndarray d = np.empty(2, dtype=np.uint64)
+ d[0] = delta // 2**64
+ d[1] = delta % 2**64
+ pcg64_advance(&self.rng_state, <uint64_t *>np.PyArray_DATA(d))
+ self._reset_state_variables()
+ return self
diff --git a/numpy/random/philox.pyx b/numpy/random/philox.pyx
new file mode 100644
index 000000000..8b7683017
--- /dev/null
+++ b/numpy/random/philox.pyx
@@ -0,0 +1,336 @@
+from cpython.pycapsule cimport PyCapsule_New
+
+try:
+ from threading import Lock
+except ImportError:
+ from dummy_threading import Lock
+
+import numpy as np
+
+from .common cimport *
+from .bit_generator cimport BitGenerator
+
+__all__ = ['Philox']
+
+np.import_array()
+
+DEF PHILOX_BUFFER_SIZE=4
+
+cdef extern from 'src/philox/philox.h':
+ struct s_r123array2x64:
+ uint64_t v[2]
+
+ struct s_r123array4x64:
+ uint64_t v[4]
+
+ ctypedef s_r123array4x64 r123array4x64
+ ctypedef s_r123array2x64 r123array2x64
+
+ ctypedef r123array4x64 philox4x64_ctr_t
+ ctypedef r123array2x64 philox4x64_key_t
+
+ struct s_philox_state:
+ philox4x64_ctr_t *ctr
+ philox4x64_key_t *key
+ int buffer_pos
+ uint64_t buffer[PHILOX_BUFFER_SIZE]
+ int has_uint32
+ uint32_t uinteger
+
+ ctypedef s_philox_state philox_state
+
+ uint64_t philox_next64(philox_state *state) nogil
+ uint32_t philox_next32(philox_state *state) nogil
+ void philox_jump(philox_state *state)
+ void philox_advance(uint64_t *step, philox_state *state)
+
+
+cdef uint64_t philox_uint64(void*st) nogil:
+ return philox_next64(<philox_state *> st)
+
+cdef uint32_t philox_uint32(void *st) nogil:
+ return philox_next32(<philox_state *> st)
+
+cdef double philox_double(void*st) nogil:
+ return uint64_to_double(philox_next64(<philox_state *> st))
+
+cdef class Philox(BitGenerator):
+ """
+ Philox(seed=None, counter=None, key=None)
+
+ Container for the Philox (4x64) pseudo-random number generator.
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+ counter : {None, int, array_like}, optional
+ Counter to use in the Philox state. Can be either
+ a Python int (long in 2.x) in [0, 2**256) or a 4-element uint64 array.
+ If not provided, the RNG is initialized at 0.
+ key : {None, int, array_like}, optional
+ Key to use in the Philox state. Unlike seed, the value in key is
+ directly set. Can be either a Python int in [0, 2**128) or a 2-element
+ uint64 array. `key` and `seed` cannot both be used.
+
+ Attributes
+ ----------
+ lock: threading.Lock
+ Lock instance that is shared so that the same bit git generator can
+ be used in multiple Generators without corrupting the state. Code that
+ generates values from a bit generator should hold the bit generator's
+ lock.
+
+ Notes
+ -----
+ Philox is a 64-bit PRNG that uses a counter-based design based on weaker
+ (and faster) versions of cryptographic functions [1]_. Instances using
+ different values of the key produce independent sequences. Philox has a
+ period of :math:`2^{256} - 1` and supports arbitrary advancing and jumping
+ the sequence in increments of :math:`2^{128}`. These features allow
+ multiple non-overlapping sequences to be generated.
+
+ ``Philox`` provides a capsule containing function pointers that produce
+ doubles, and unsigned 32 and 64- bit integers. These are not
+ directly consumable in Python and must be consumed by a ``Generator``
+ or similar object that supports low-level access.
+
+ **State and Seeding**
+
+ The ``Philox`` state vector consists of a 256-bit value encoded as
+ a 4-element uint64 array and a 128-bit value encoded as a 2-element uint64
+ array. The former is a counter which is incremented by 1 for every 4 64-bit
+ randoms produced. The second is a key which determined the sequence
+ produced. Using different keys produces independent sequences.
+
+ The input seed is processed by `SeedSequence` to generate the key. The
+ counter is set to 0.
+
+ Alternately, one can omit the seed parameter and set the ``key`` and
+ ``counter`` directly.
+
+ **Parallel Features**
+
+ The preferred way to use a BitGenerator in parallel applications is to use
+ the `SeedSequence.spawn` method to obtain entropy values, and to use these
+ to generate new BitGenerators:
+
+ >>> from numpy.random import Generator, Philox, SeedSequence
+ >>> sg = SeedSequence(1234)
+ >>> rg = [Generator(Philox(s)) for s in sg.spawn(10)]
+
+ ``Philox`` can be used in parallel applications by calling the ``jumped``
+ method to advances the state as-if :math:`2^{128}` random numbers have
+ been generated. Alternatively, ``advance`` can be used to advance the
+ counter for any positive step in [0, 2**256). When using ``jumped``, all
+ generators should be chained to ensure that the segments come from the same
+ sequence.
+
+ >>> from numpy.random import Generator, Philox
+ >>> bit_generator = Philox(1234)
+ >>> rg = []
+ >>> for _ in range(10):
+ ... rg.append(Generator(bit_generator))
+ ... bit_generator = bit_generator.jumped()
+
+ Alternatively, ``Philox`` can be used in parallel applications by using
+ a sequence of distinct keys where each instance uses different key.
+
+ >>> key = 2**96 + 2**33 + 2**17 + 2**9
+ >>> rg = [Generator(Philox(key=key+i)) for i in range(10)]
+
+ **Compatibility Guarantee**
+
+ ``Philox`` makes a guarantee that a fixed seed will always produce
+ the same random integer stream.
+
+ Examples
+ --------
+ >>> from numpy.random import Generator, Philox
+ >>> rg = Generator(Philox(1234))
+ >>> rg.standard_normal()
+ 0.123 # random
+
+ References
+ ----------
+ .. [1] John K. Salmon, Mark A. Moraes, Ron O. Dror, and David E. Shaw,
+ "Parallel Random Numbers: As Easy as 1, 2, 3," Proceedings of
+ the International Conference for High Performance Computing,
+ Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011.
+ """
+ cdef philox_state rng_state
+ cdef philox4x64_key_t philox_key
+ cdef philox4x64_ctr_t philox_ctr
+
+ def __init__(self, seed=None, counter=None, key=None):
+ if seed is not None and key is not None:
+ raise ValueError('seed and key cannot be both used')
+ BitGenerator.__init__(self, seed)
+ self.rng_state.ctr = &self.philox_ctr
+ self.rng_state.key = &self.philox_key
+ if key is not None:
+ key = int_to_array(key, 'key', 128, 64)
+ for i in range(2):
+ self.rng_state.key.v[i] = key[i]
+ # The seed sequence is invalid.
+ self._seed_seq = None
+ else:
+ key = self._seed_seq.generate_state(2, np.uint64)
+ for i in range(2):
+ self.rng_state.key.v[i] = key[i]
+ counter = 0 if counter is None else counter
+ counter = int_to_array(counter, 'counter', 256, 64)
+ for i in range(4):
+ self.rng_state.ctr.v[i] = counter[i]
+
+ self._reset_state_variables()
+
+ self._bitgen.state = <void *>&self.rng_state
+ self._bitgen.next_uint64 = &philox_uint64
+ self._bitgen.next_uint32 = &philox_uint32
+ self._bitgen.next_double = &philox_double
+ self._bitgen.next_raw = &philox_uint64
+
+ cdef _reset_state_variables(self):
+ self.rng_state.has_uint32 = 0
+ self.rng_state.uinteger = 0
+ self.rng_state.buffer_pos = PHILOX_BUFFER_SIZE
+ for i in range(PHILOX_BUFFER_SIZE):
+ self.rng_state.buffer[i] = 0
+
+ @property
+ def state(self):
+ """
+ Get or set the PRNG state
+
+ Returns
+ -------
+ state : dict
+ Dictionary containing the information required to describe the
+ state of the PRNG
+ """
+ ctr = np.empty(4, dtype=np.uint64)
+ key = np.empty(2, dtype=np.uint64)
+ buffer = np.empty(PHILOX_BUFFER_SIZE, dtype=np.uint64)
+ for i in range(4):
+ ctr[i] = self.rng_state.ctr.v[i]
+ if i < 2:
+ key[i] = self.rng_state.key.v[i]
+ for i in range(PHILOX_BUFFER_SIZE):
+ buffer[i] = self.rng_state.buffer[i]
+
+ state = {'counter': ctr, 'key': key}
+ return {'bit_generator': self.__class__.__name__,
+ 'state': state,
+ 'buffer': buffer,
+ 'buffer_pos': self.rng_state.buffer_pos,
+ 'has_uint32': self.rng_state.has_uint32,
+ 'uinteger': self.rng_state.uinteger}
+
+ @state.setter
+ def state(self, value):
+ if not isinstance(value, dict):
+ raise TypeError('state must be a dict')
+ bitgen = value.get('bit_generator', '')
+ if bitgen != self.__class__.__name__:
+ raise ValueError('state must be for a {0} '
+ 'PRNG'.format(self.__class__.__name__))
+ for i in range(4):
+ self.rng_state.ctr.v[i] = <uint64_t> value['state']['counter'][i]
+ if i < 2:
+ self.rng_state.key.v[i] = <uint64_t> value['state']['key'][i]
+ for i in range(PHILOX_BUFFER_SIZE):
+ self.rng_state.buffer[i] = <uint64_t> value['buffer'][i]
+
+ self.rng_state.has_uint32 = value['has_uint32']
+ self.rng_state.uinteger = value['uinteger']
+ self.rng_state.buffer_pos = value['buffer_pos']
+
+ cdef jump_inplace(self, iter):
+ """
+ Jump state in-place
+
+ Not part of public API
+
+ Parameters
+ ----------
+ iter : integer, positive
+ Number of times to jump the state of the rng.
+ """
+ self.advance(iter * int(2 ** 128))
+
+ def jumped(self, jumps=1):
+ """
+ jumped(jumps=1)
+
+ Returns a new bit generator with the state jumped
+
+ The state of the returned big generator is jumped as-if
+ 2**(128 * jumps) random numbers have been generated.
+
+ Parameters
+ ----------
+ jumps : integer, positive
+ Number of times to jump the state of the bit generator returned
+
+ Returns
+ -------
+ bit_generator : Philox
+ New instance of generator jumped iter times
+ """
+ cdef Philox bit_generator
+
+ bit_generator = self.__class__()
+ bit_generator.state = self.state
+ bit_generator.jump_inplace(jumps)
+
+ return bit_generator
+
+ def advance(self, delta):
+ """
+ advance(delta)
+
+ Advance the underlying RNG as-if delta draws have occurred.
+
+ Parameters
+ ----------
+ delta : integer, positive
+ Number of draws to advance the RNG. Must be less than the
+ size state variable in the underlying RNG.
+
+ Returns
+ -------
+ self : Philox
+ RNG advanced delta steps
+
+ Notes
+ -----
+ Advancing a RNG updates the underlying RNG state as-if a given
+ number of calls to the underlying RNG have been made. In general
+ there is not a one-to-one relationship between the number output
+ random values from a particular distribution and the number of
+ draws from the core RNG. This occurs for two reasons:
+
+ * The random values are simulated using a rejection-based method
+ and so, on average, more than one value from the underlying
+ RNG is required to generate an single draw.
+ * The number of bits required to generate a simulated value
+ differs from the number of bits generated by the underlying
+ RNG. For example, two 16-bit integer values can be simulated
+ from a single draw of a 32-bit RNG.
+
+ Advancing the RNG state resets any pre-computed random numbers.
+ This is required to ensure exact reproducibility.
+ """
+ delta = wrap_int(delta, 256)
+
+ cdef np.ndarray delta_a
+ delta_a = int_to_array(delta, 'step', 256, 64)
+ philox_advance(<uint64_t *> delta_a.data, &self.rng_state)
+ self._reset_state_variables()
+ return self
diff --git a/numpy/random/setup.py b/numpy/random/setup.py
index 394a70ead..a1bf3b83c 100644
--- a/numpy/random/setup.py
+++ b/numpy/random/setup.py
@@ -1,22 +1,17 @@
from __future__ import division, print_function
-from os.path import join
+import os
+import platform
import sys
-from distutils.dep_util import newer
-from distutils.msvccompiler import get_build_version as get_msvc_build_version
+from os.path import join
-def needs_mingw_ftime_workaround():
- # We need the mingw workaround for _ftime if the msvc runtime version is
- # 7.1 or above and we build with mingw ...
- # ... but we can't easily detect compiler version outside distutils command
- # context, so we will need to detect in randomkit whether we build with gcc
- msver = get_msvc_build_version()
- if msver and msver >= 8:
- return True
+from numpy.distutils.system_info import platform_bits
- return False
+is_msvc = (platform.platform().startswith('Windows') and
+ platform.python_compiler().startswith('MS'))
-def configuration(parent_package='',top_path=None):
+
+def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration, get_mathlibs
config = Configuration('random', parent_package, top_path)
@@ -24,7 +19,7 @@ def configuration(parent_package='',top_path=None):
config_cmd = config.get_config_cmd()
libs = get_mathlibs()
if sys.platform == 'win32':
- libs.append('Advapi32')
+ libs.extend(['Advapi32', 'Kernel32'])
ext.libraries.extend(libs)
return None
@@ -36,28 +31,119 @@ def configuration(parent_package='',top_path=None):
defs = [('_FILE_OFFSET_BITS', '64'),
('_LARGEFILE_SOURCE', '1'),
('_LARGEFILE64_SOURCE', '1')]
- if needs_mingw_ftime_workaround():
- defs.append(("NPY_NEEDS_MINGW_TIME_WORKAROUND", None))
-
- libs = []
- # Configure mtrand
- config.add_extension('mtrand',
- sources=[join('mtrand', x) for x in
- ['mtrand.c', 'randomkit.c', 'initarray.c',
- 'distributions.c']]+[generate_libraries],
- libraries=libs,
- depends=[join('mtrand', '*.h'),
- join('mtrand', '*.pyx'),
- join('mtrand', '*.pxi'),],
- define_macros=defs,
- )
- config.add_data_files(('.', join('mtrand', 'randomkit.h')))
+ defs.append(('NPY_NO_DEPRECATED_API', 0))
config.add_data_dir('tests')
+ config.add_data_files('common.pxd')
+ config.add_data_files('bit_generator.pxd')
+
+ EXTRA_LINK_ARGS = []
+ # Math lib
+ EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else []
+ # Some bit generators exclude GCC inlining
+ EXTRA_COMPILE_ARGS = ['-U__GNUC_GNU_INLINE__']
+ if is_msvc and platform_bits == 32:
+ # 32-bit windows requires explicit sse2 option
+ EXTRA_COMPILE_ARGS += ['/arch:SSE2']
+ elif not is_msvc:
+ # Some bit generators require c99
+ EXTRA_COMPILE_ARGS += ['-std=c99']
+ INTEL_LIKE = any([val in k.lower() for k in platform.uname()
+ for val in ('x86', 'i686', 'i386', 'amd64')])
+ if INTEL_LIKE:
+ # Assumes GCC or GCC-like compiler
+ EXTRA_COMPILE_ARGS += ['-msse2']
+
+ # Use legacy integer variable sizes
+ LEGACY_DEFS = [('NP_RANDOM_LEGACY', '1')]
+ PCG64_DEFS = []
+ # One can force emulated 128-bit arithmetic if one wants.
+ #PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')]
+
+ config.add_extension('entropy',
+ sources=['entropy.c', 'src/entropy/entropy.c'] +
+ [generate_libraries],
+ libraries=EXTRA_LIBRARIES,
+ extra_compile_args=EXTRA_COMPILE_ARGS,
+ extra_link_args=EXTRA_LINK_ARGS,
+ depends=[join('src', 'splitmix64', 'splitmix.h'),
+ join('src', 'entropy', 'entropy.h'),
+ 'entropy.pyx',
+ ],
+ define_macros=defs,
+ )
+ for gen in ['mt19937']:
+ # gen.pyx, src/gen/gen.c, src/gen/gen-jump.c
+ config.add_extension(gen,
+ sources=['{0}.c'.format(gen),
+ 'src/{0}/{0}.c'.format(gen),
+ 'src/{0}/{0}-jump.c'.format(gen)],
+ 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],
+ 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(gen,
+ sources=['{0}.c'.format(gen),
+ 'src/{0}/{0}.c'.format(gen)],
+ 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'],
+ define_macros=_defs,
+ )
+ for gen in ['common', 'bit_generator']:
+ # gen.pyx
+ config.add_extension(gen,
+ sources=['{0}.c'.format(gen)],
+ 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,],
+ define_macros=defs,
+ )
+ other_srcs = [
+ 'src/distributions/logfactorial.c',
+ 'src/distributions/distributions.c',
+ 'src/distributions/random_hypergeometric.c',
+ ]
+ for gen in ['generator', 'bounded_integers']:
+ # gen.pyx, src/distributions/distributions.c
+ config.add_extension(gen,
+ sources=['{0}.c'.format(gen)] + other_srcs,
+ libraries=EXTRA_LIBRARIES,
+ extra_compile_args=EXTRA_COMPILE_ARGS,
+ include_dirs=['.', 'src'],
+ extra_link_args=EXTRA_LINK_ARGS,
+ depends=['%s.pyx' % gen],
+ define_macros=defs,
+ )
+ config.add_extension('mtrand',
+ # mtrand does not depend on random_hypergeometric.c.
+ sources=['mtrand.c',
+ 'src/legacy/legacy-distributions.c',
+ 'src/distributions/logfactorial.c',
+ 'src/distributions/distributions.c'],
+ include_dirs=['.', 'src', 'src/legacy'],
+ libraries=EXTRA_LIBRARIES,
+ extra_compile_args=EXTRA_COMPILE_ARGS,
+ extra_link_args=EXTRA_LINK_ARGS,
+ depends=['mtrand.pyx'],
+ define_macros=defs + LEGACY_DEFS,
+ )
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
+
setup(configuration=configuration)
diff --git a/numpy/random/sfc64.pyx b/numpy/random/sfc64.pyx
new file mode 100644
index 000000000..a881096e9
--- /dev/null
+++ b/numpy/random/sfc64.pyx
@@ -0,0 +1,144 @@
+import numpy as np
+cimport numpy as np
+
+from .common cimport *
+from .bit_generator cimport BitGenerator
+
+__all__ = ['SFC64']
+
+cdef extern from "src/sfc64/sfc64.h":
+ struct s_sfc64_state:
+ uint64_t s[4]
+ int has_uint32
+ uint32_t uinteger
+
+ ctypedef s_sfc64_state sfc64_state
+ uint64_t sfc64_next64(sfc64_state *state) nogil
+ uint32_t sfc64_next32(sfc64_state *state) nogil
+ void sfc64_set_seed(sfc64_state *state, uint64_t *seed)
+ void sfc64_get_state(sfc64_state *state, uint64_t *state_arr, int *has_uint32, uint32_t *uinteger)
+ void sfc64_set_state(sfc64_state *state, uint64_t *state_arr, int has_uint32, uint32_t uinteger)
+
+
+cdef uint64_t sfc64_uint64(void* st) nogil:
+ return sfc64_next64(<sfc64_state *>st)
+
+cdef uint32_t sfc64_uint32(void *st) nogil:
+ return sfc64_next32(<sfc64_state *> st)
+
+cdef double sfc64_double(void* st) nogil:
+ return uint64_to_double(sfc64_next64(<sfc64_state *>st))
+
+
+cdef class SFC64(BitGenerator):
+ """
+ SFC64(seed=None)
+
+ BitGenerator for Chris Doty-Humphrey's Small Fast Chaotic PRNG.
+
+ Parameters
+ ----------
+ seed : {None, int, array_like[ints], ISeedSequence}, optional
+ A seed to initialize the `BitGenerator`. If None, then fresh,
+ unpredictable entropy will be pulled from the OS. If an ``int`` or
+ ``array_like[ints]`` is passed, then it will be passed to
+ `SeedSequence` to derive the initial `BitGenerator` state. One may also
+ pass in an implementor of the `ISeedSequence` interface like
+ `SeedSequence`.
+
+ Notes
+ -----
+ ``SFC64`` is a 256-bit implementation of Chris Doty-Humphrey's Small Fast
+ Chaotic PRNG ([1]_). ``SFC64`` has a few different cycles that one might be
+ on, depending on the seed; the expected period will be about
+ :math:`2^{255}` ([2]_). ``SFC64`` incorporates a 64-bit counter which means
+ that the absolute minimum cycle length is :math:`2^{64}` and that distinct
+ seeds will not run into each other for at least :math:`2^{64}` iterations.
+
+ ``SFC64`` provides a capsule containing function pointers that produce
+ doubles, and unsigned 32 and 64- bit integers. These are not
+ directly consumable in Python and must be consumed by a ``Generator``
+ or similar object that supports low-level access.
+
+ **State and Seeding**
+
+ The ``SFC64`` state vector consists of 4 unsigned 64-bit values. The last
+ is a 64-bit counter that increments by 1 each iteration.
+
+ The input seed is processed by `SeedSequence` to generate the first
+ 3 values, then the ``SFC64`` algorithm is iterated a small number of times
+ to mix.
+
+ **Compatibility Guarantee**
+
+ ``SFC64`` makes a guarantee that a fixed seed will always produce the same
+ random integer stream.
+
+ References
+ ----------
+ .. [1] `"PractRand"
+ <http://pracrand.sourceforge.net/RNG_engines.txt>`_
+ .. [2] `"Random Invertible Mapping Statistics"
+ <http://www.pcg-random.org/posts/random-invertible-mapping-statistics.html>`_
+ """
+
+ cdef sfc64_state rng_state
+
+ def __init__(self, seed=None):
+ BitGenerator.__init__(self, seed)
+ self._bitgen.state = <void *>&self.rng_state
+ self._bitgen.next_uint64 = &sfc64_uint64
+ self._bitgen.next_uint32 = &sfc64_uint32
+ self._bitgen.next_double = &sfc64_double
+ self._bitgen.next_raw = &sfc64_uint64
+ # Seed the _bitgen
+ val = self._seed_seq.generate_state(3, np.uint64)
+ sfc64_set_seed(&self.rng_state, <uint64_t*>np.PyArray_DATA(val))
+ self._reset_state_variables()
+
+ cdef _reset_state_variables(self):
+ self.rng_state.has_uint32 = 0
+ self.rng_state.uinteger = 0
+
+ @property
+ def state(self):
+ """
+ Get or set the PRNG state
+
+ Returns
+ -------
+ state : dict
+ Dictionary containing the information required to describe the
+ state of the PRNG
+ """
+ cdef np.ndarray state_vec
+ cdef int has_uint32
+ cdef uint32_t uinteger
+
+ state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
+ sfc64_get_state(&self.rng_state,
+ <uint64_t *>np.PyArray_DATA(state_vec),
+ &has_uint32, &uinteger)
+ return {'bit_generator': self.__class__.__name__,
+ 'state': {'state': state_vec},
+ 'has_uint32': has_uint32,
+ 'uinteger': uinteger}
+
+ @state.setter
+ def state(self, value):
+ cdef np.ndarray state_vec
+ cdef int has_uint32
+ cdef uint32_t uinteger
+ if not isinstance(value, dict):
+ raise TypeError('state must be a dict')
+ bitgen = value.get('bit_generator', '')
+ if bitgen != self.__class__.__name__:
+ raise ValueError('state must be for a {0} '
+ 'RNG'.format(self.__class__.__name__))
+ state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
+ state_vec[:] = value['state']['state']
+ has_uint32 = value['has_uint32']
+ uinteger = value['uinteger']
+ sfc64_set_state(&self.rng_state,
+ <uint64_t *>np.PyArray_DATA(state_vec),
+ has_uint32, uinteger)
diff --git a/numpy/random/src/aligned_malloc/aligned_malloc.c b/numpy/random/src/aligned_malloc/aligned_malloc.c
new file mode 100644
index 000000000..6e8192cfb
--- /dev/null
+++ b/numpy/random/src/aligned_malloc/aligned_malloc.c
@@ -0,0 +1,9 @@
+#include "aligned_malloc.h"
+
+static NPY_INLINE void *PyArray_realloc_aligned(void *p, size_t n);
+
+static NPY_INLINE void *PyArray_malloc_aligned(size_t n);
+
+static NPY_INLINE void *PyArray_calloc_aligned(size_t n, size_t s);
+
+static NPY_INLINE void PyArray_free_aligned(void *p); \ No newline at end of file
diff --git a/numpy/random/src/aligned_malloc/aligned_malloc.h b/numpy/random/src/aligned_malloc/aligned_malloc.h
new file mode 100644
index 000000000..ea24f6d23
--- /dev/null
+++ b/numpy/random/src/aligned_malloc/aligned_malloc.h
@@ -0,0 +1,54 @@
+#ifndef _RANDOMDGEN__ALIGNED_MALLOC_H_
+#define _RANDOMDGEN__ALIGNED_MALLOC_H_
+
+#include "Python.h"
+#include "numpy/npy_common.h"
+
+#define NPY_MEMALIGN 16 /* 16 for SSE2, 32 for AVX, 64 for Xeon Phi */
+
+static NPY_INLINE void *PyArray_realloc_aligned(void *p, size_t n)
+{
+ void *p1, **p2, *base;
+ size_t old_offs, offs = NPY_MEMALIGN - 1 + sizeof(void *);
+ if (NPY_UNLIKELY(p != NULL))
+ {
+ base = *(((void **)p) - 1);
+ if (NPY_UNLIKELY((p1 = PyMem_Realloc(base, n + offs)) == NULL))
+ return NULL;
+ if (NPY_LIKELY(p1 == base))
+ return p;
+ p2 = (void **)(((Py_uintptr_t)(p1) + offs) & ~(NPY_MEMALIGN - 1));
+ old_offs = (size_t)((Py_uintptr_t)p - (Py_uintptr_t)base);
+ memmove((void *)p2, ((char *)p1) + old_offs, n);
+ }
+ else
+ {
+ if (NPY_UNLIKELY((p1 = PyMem_Malloc(n + offs)) == NULL))
+ return NULL;
+ p2 = (void **)(((Py_uintptr_t)(p1) + offs) & ~(NPY_MEMALIGN - 1));
+ }
+ *(p2 - 1) = p1;
+ return (void *)p2;
+}
+
+static NPY_INLINE void *PyArray_malloc_aligned(size_t n)
+{
+ return PyArray_realloc_aligned(NULL, n);
+}
+
+static NPY_INLINE void *PyArray_calloc_aligned(size_t n, size_t s)
+{
+ void *p;
+ if (NPY_UNLIKELY((p = PyArray_realloc_aligned(NULL, n * s)) == NULL))
+ return NULL;
+ memset(p, 0, n * s);
+ return p;
+}
+
+static NPY_INLINE void PyArray_free_aligned(void *p)
+{
+ void *base = *(((void **)p) - 1);
+ PyMem_Free(base);
+}
+
+#endif
diff --git a/numpy/random/src/distributions/LICENSE.md b/numpy/random/src/distributions/LICENSE.md
new file mode 100644
index 000000000..31576ba4b
--- /dev/null
+++ b/numpy/random/src/distributions/LICENSE.md
@@ -0,0 +1,61 @@
+## NumPy
+
+Copyright (c) 2005-2017, NumPy Developers.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+* Neither the name of the NumPy Developers nor the names of any
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+## Julia
+
+The ziggurat methods were derived from Julia.
+
+Copyright (c) 2009-2019: Jeff Bezanson, Stefan Karpinski, Viral B. Shah,
+and other contributors:
+
+https://github.com/JuliaLang/julia/contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c
new file mode 100644
index 000000000..65257ecbf
--- /dev/null
+++ b/numpy/random/src/distributions/distributions.c
@@ -0,0 +1,1782 @@
+#include "distributions.h"
+#include "ziggurat_constants.h"
+#include "logfactorial.h"
+
+#if defined(_MSC_VER) && defined(_WIN64)
+#include <intrin.h>
+#endif
+
+/* Random generators for external use */
+float random_float(bitgen_t *bitgen_state) { return next_float(bitgen_state); }
+
+double random_double(bitgen_t *bitgen_state) {
+ return next_double(bitgen_state);
+}
+
+static NPY_INLINE double next_standard_exponential(bitgen_t *bitgen_state) {
+ return -log(1.0 - next_double(bitgen_state));
+}
+
+double random_standard_exponential(bitgen_t *bitgen_state) {
+ return next_standard_exponential(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] = next_standard_exponential(bitgen_state);
+ }
+}
+
+float random_standard_exponential_f(bitgen_t *bitgen_state) {
+ return -logf(1.0f - next_float(bitgen_state));
+}
+
+void random_double_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) {
+ npy_intp i;
+ for (i = 0; i < cnt; i++) {
+ out[i] = next_double(bitgen_state);
+ }
+}
+#if 0
+double random_gauss(bitgen_t *bitgen_state) {
+ if (bitgen_state->has_gauss) {
+ const double temp = bitgen_state->gauss;
+ bitgen_state->has_gauss = false;
+ bitgen_state->gauss = 0.0;
+ return temp;
+ } else {
+ double f, x1, x2, r2;
+
+ do {
+ x1 = 2.0 * next_double(bitgen_state) - 1.0;
+ x2 = 2.0 * next_double(bitgen_state) - 1.0;
+ r2 = x1 * x1 + x2 * x2;
+ } while (r2 >= 1.0 || r2 == 0.0);
+
+ /* Polar method, a more efficient version of the Box-Muller approach. */
+ f = sqrt(-2.0 * log(r2) / r2);
+ /* Keep for next call */
+ bitgen_state->gauss = f * x1;
+ bitgen_state->has_gauss = true;
+ return f * x2;
+ }
+}
+
+float random_gauss_f(bitgen_t *bitgen_state) {
+ if (bitgen_state->has_gauss_f) {
+ const float temp = bitgen_state->gauss_f;
+ bitgen_state->has_gauss_f = false;
+ bitgen_state->gauss_f = 0.0f;
+ return temp;
+ } else {
+ float f, x1, x2, r2;
+
+ do {
+ x1 = 2.0f * next_float(bitgen_state) - 1.0f;
+ x2 = 2.0f * next_float(bitgen_state) - 1.0f;
+ r2 = x1 * x1 + x2 * x2;
+ } while (r2 >= 1.0 || r2 == 0.0);
+
+ /* Polar method, a more efficient version of the Box-Muller approach. */
+ f = sqrtf(-2.0f * logf(r2) / r2);
+ /* Keep for next call */
+ bitgen_state->gauss_f = f * x1;
+ bitgen_state->has_gauss_f = true;
+ return f * x2;
+ }
+}
+#endif
+
+static NPY_INLINE double standard_exponential_zig(bitgen_t *bitgen_state);
+
+static double standard_exponential_zig_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 */
+ return ziggurat_exp_r - log(1.0 - next_double(bitgen_state));
+ } else if ((fe_double[idx - 1] - fe_double[idx]) * next_double(bitgen_state) +
+ fe_double[idx] <
+ exp(-x)) {
+ return x;
+ } else {
+ return standard_exponential_zig(bitgen_state);
+ }
+}
+
+static NPY_INLINE double standard_exponential_zig(bitgen_t *bitgen_state) {
+ uint64_t ri;
+ uint8_t idx;
+ double x;
+ ri = next_uint64(bitgen_state);
+ ri >>= 3;
+ idx = ri & 0xFF;
+ ri >>= 8;
+ x = ri * we_double[idx];
+ 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);
+}
+
+double random_standard_exponential_zig(bitgen_t *bitgen_state) {
+ return standard_exponential_zig(bitgen_state);
+}
+
+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] = standard_exponential_zig(bitgen_state);
+ }
+}
+
+static NPY_INLINE float standard_exponential_zig_f(bitgen_t *bitgen_state);
+
+static float standard_exponential_zig_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 */
+ return ziggurat_exp_r_f - logf(1.0f - next_float(bitgen_state));
+ } else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(bitgen_state) +
+ fe_float[idx] <
+ expf(-x)) {
+ return x;
+ } else {
+ return standard_exponential_zig_f(bitgen_state);
+ }
+}
+
+static NPY_INLINE float standard_exponential_zig_f(bitgen_t *bitgen_state) {
+ uint32_t ri;
+ uint8_t idx;
+ float x;
+ ri = next_uint32(bitgen_state);
+ ri >>= 1;
+ idx = ri & 0xFF;
+ ri >>= 8;
+ x = ri * we_float[idx];
+ 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);
+}
+
+float random_standard_exponential_zig_f(bitgen_t *bitgen_state) {
+ return standard_exponential_zig_f(bitgen_state);
+}
+
+static NPY_INLINE double next_gauss_zig(bitgen_t *bitgen_state) {
+ uint64_t r;
+ int sign;
+ uint64_t rabs;
+ int idx;
+ double x, xx, yy;
+ for (;;) {
+ /* r = e3n52sb8 */
+ r = next_uint64(bitgen_state);
+ idx = r & 0xff;
+ r >>= 8;
+ sign = r & 0x1;
+ rabs = (r >> 1) & 0x000fffffffffffff;
+ x = rabs * wi_double[idx];
+ if (sign & 0x1)
+ x = -x;
+ if (rabs < ki_double[idx])
+ return x; /* 99.3% of the time return here */
+ if (idx == 0) {
+ for (;;) {
+ /* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
+ xx = -ziggurat_nor_inv_r * log(1.0 - next_double(bitgen_state));
+ yy = -log(1.0 - next_double(bitgen_state));
+ if (yy + yy > xx * xx)
+ return ((rabs >> 8) & 0x1) ? -(ziggurat_nor_r + xx)
+ : ziggurat_nor_r + xx;
+ }
+ } else {
+ if (((fi_double[idx - 1] - fi_double[idx]) * next_double(bitgen_state) +
+ fi_double[idx]) < exp(-0.5 * x * x))
+ return x;
+ }
+ }
+}
+
+double random_gauss_zig(bitgen_t *bitgen_state) {
+ return next_gauss_zig(bitgen_state);
+}
+
+void random_gauss_zig_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) {
+ npy_intp i;
+ for (i = 0; i < cnt; i++) {
+ out[i] = next_gauss_zig(bitgen_state);
+ }
+}
+
+float random_gauss_zig_f(bitgen_t *bitgen_state) {
+ uint32_t r;
+ int sign;
+ uint32_t rabs;
+ int idx;
+ float x, xx, yy;
+ for (;;) {
+ /* r = n23sb8 */
+ r = next_uint32(bitgen_state);
+ idx = r & 0xff;
+ sign = (r >> 8) & 0x1;
+ rabs = (r >> 9) & 0x0007fffff;
+ x = rabs * wi_float[idx];
+ if (sign & 0x1)
+ x = -x;
+ if (rabs < ki_float[idx])
+ return x; /* # 99.3% of the time return here */
+ if (idx == 0) {
+ for (;;) {
+ /* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
+ xx = -ziggurat_nor_inv_r_f * logf(1.0f - next_float(bitgen_state));
+ yy = -logf(1.0f - next_float(bitgen_state));
+ if (yy + yy > xx * xx)
+ return ((rabs >> 8) & 0x1) ? -(ziggurat_nor_r_f + xx)
+ : ziggurat_nor_r_f + xx;
+ }
+ } else {
+ if (((fi_float[idx - 1] - fi_float[idx]) * next_float(bitgen_state) +
+ fi_float[idx]) < exp(-0.5 * x * x))
+ return x;
+ }
+ }
+}
+
+/*
+static NPY_INLINE double standard_gamma(bitgen_t *bitgen_state, double shape) {
+ double b, c;
+ double U, V, X, Y;
+
+ if (shape == 1.0) {
+ return random_standard_exponential(bitgen_state);
+ } else if (shape < 1.0) {
+ for (;;) {
+ U = next_double(bitgen_state);
+ V = random_standard_exponential(bitgen_state);
+ if (U <= 1.0 - shape) {
+ X = pow(U, 1. / shape);
+ if (X <= V) {
+ return X;
+ }
+ } else {
+ Y = -log((1 - U) / shape);
+ X = pow(1.0 - shape + shape * Y, 1. / shape);
+ if (X <= (V + Y)) {
+ return X;
+ }
+ }
+ }
+ } else {
+ b = shape - 1. / 3.;
+ c = 1. / sqrt(9 * b);
+ for (;;) {
+ do {
+ X = random_gauss(bitgen_state);
+ V = 1.0 + c * X;
+ } while (V <= 0.0);
+
+ V = V * V * V;
+ U = next_double(bitgen_state);
+ if (U < 1.0 - 0.0331 * (X * X) * (X * X))
+ return (b * V);
+ if (log(U) < 0.5 * X * X + b * (1. - V + log(V)))
+ return (b * V);
+ }
+ }
+}
+
+static NPY_INLINE float standard_gamma_float(bitgen_t *bitgen_state, float
+shape) { float b, c; float U, V, X, Y;
+
+ if (shape == 1.0f) {
+ return random_standard_exponential_f(bitgen_state);
+ } else if (shape < 1.0f) {
+ for (;;) {
+ U = next_float(bitgen_state);
+ V = random_standard_exponential_f(bitgen_state);
+ if (U <= 1.0f - shape) {
+ X = powf(U, 1.0f / shape);
+ if (X <= V) {
+ return X;
+ }
+ } else {
+ Y = -logf((1.0f - U) / shape);
+ X = powf(1.0f - shape + shape * Y, 1.0f / shape);
+ if (X <= (V + Y)) {
+ return X;
+ }
+ }
+ }
+ } else {
+ b = shape - 1.0f / 3.0f;
+ c = 1.0f / sqrtf(9.0f * b);
+ for (;;) {
+ do {
+ X = random_gauss_f(bitgen_state);
+ V = 1.0f + c * X;
+ } while (V <= 0.0f);
+
+ V = V * V * V;
+ U = next_float(bitgen_state);
+ if (U < 1.0f - 0.0331f * (X * X) * (X * X))
+ return (b * V);
+ if (logf(U) < 0.5f * X * X + b * (1.0f - V + logf(V)))
+ return (b * V);
+ }
+ }
+}
+
+
+double random_standard_gamma(bitgen_t *bitgen_state, double shape) {
+ return standard_gamma(bitgen_state, shape);
+}
+
+float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) {
+ return standard_gamma_float(bitgen_state, shape);
+}
+*/
+
+static NPY_INLINE double standard_gamma_zig(bitgen_t *bitgen_state,
+ double shape) {
+ double b, c;
+ double U, V, X, Y;
+
+ if (shape == 1.0) {
+ return random_standard_exponential_zig(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);
+ if (U <= 1.0 - shape) {
+ X = pow(U, 1. / shape);
+ if (X <= V) {
+ return X;
+ }
+ } else {
+ Y = -log((1 - U) / shape);
+ X = pow(1.0 - shape + shape * Y, 1. / shape);
+ if (X <= (V + Y)) {
+ return X;
+ }
+ }
+ }
+ } else {
+ b = shape - 1. / 3.;
+ c = 1. / sqrt(9 * b);
+ for (;;) {
+ do {
+ X = random_gauss_zig(bitgen_state);
+ V = 1.0 + c * X;
+ } while (V <= 0.0);
+
+ V = V * V * V;
+ U = next_double(bitgen_state);
+ if (U < 1.0 - 0.0331 * (X * X) * (X * X))
+ return (b * V);
+ /* log(0.0) ok here */
+ if (log(U) < 0.5 * X * X + b * (1. - V + log(V)))
+ return (b * V);
+ }
+ }
+}
+
+static NPY_INLINE float standard_gamma_zig_f(bitgen_t *bitgen_state,
+ float shape) {
+ float b, c;
+ float U, V, X, Y;
+
+ if (shape == 1.0f) {
+ return random_standard_exponential_zig_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);
+ if (U <= 1.0f - shape) {
+ X = powf(U, 1.0f / shape);
+ if (X <= V) {
+ return X;
+ }
+ } else {
+ Y = -logf((1.0f - U) / shape);
+ X = powf(1.0f - shape + shape * Y, 1.0f / shape);
+ if (X <= (V + Y)) {
+ return X;
+ }
+ }
+ }
+ } else {
+ b = shape - 1.0f / 3.0f;
+ c = 1.0f / sqrtf(9.0f * b);
+ for (;;) {
+ do {
+ X = random_gauss_zig_f(bitgen_state);
+ V = 1.0f + c * X;
+ } while (V <= 0.0f);
+
+ V = V * V * V;
+ U = next_float(bitgen_state);
+ if (U < 1.0f - 0.0331f * (X * X) * (X * X))
+ return (b * V);
+ /* logf(0.0) ok here */
+ if (logf(U) < 0.5f * X * X + b * (1.0f - V + logf(V)))
+ return (b * V);
+ }
+ }
+}
+
+double random_standard_gamma_zig(bitgen_t *bitgen_state, double shape) {
+ return standard_gamma_zig(bitgen_state, shape);
+}
+
+float random_standard_gamma_zig_f(bitgen_t *bitgen_state, float shape) {
+ return standard_gamma_zig_f(bitgen_state, shape);
+}
+
+int64_t random_positive_int64(bitgen_t *bitgen_state) {
+ return next_uint64(bitgen_state) >> 1;
+}
+
+int32_t random_positive_int32(bitgen_t *bitgen_state) {
+ return next_uint32(bitgen_state) >> 1;
+}
+
+int64_t random_positive_int(bitgen_t *bitgen_state) {
+#if ULONG_MAX <= 0xffffffffUL
+ return (int64_t)(next_uint32(bitgen_state) >> 1);
+#else
+ return (int64_t)(next_uint64(bitgen_state) >> 1);
+#endif
+}
+
+uint64_t random_uint(bitgen_t *bitgen_state) {
+#if ULONG_MAX <= 0xffffffffUL
+ return next_uint32(bitgen_state);
+#else
+ return next_uint64(bitgen_state);
+#endif
+}
+
+/*
+ * log-gamma function to support some of these distributions. The
+ * algorithm comes from SPECFUN by Shanjie Zhang and Jianming Jin and their
+ * book "Computation of Special Functions", 1996, John Wiley & Sons, Inc.
+ *
+ * If loggam(k+1) is being used to compute log(k!) for an integer k, consider
+ * using logfactorial(k) instead.
+ */
+double loggam(double x) {
+ double x0, x2, xp, gl, gl0;
+ RAND_INT_TYPE k, n;
+
+ static double a[10] = {8.333333333333333e-02, -2.777777777777778e-03,
+ 7.936507936507937e-04, -5.952380952380952e-04,
+ 8.417508417508418e-04, -1.917526917526918e-03,
+ 6.410256410256410e-03, -2.955065359477124e-02,
+ 1.796443723688307e-01, -1.39243221690590e+00};
+ x0 = x;
+ n = 0;
+ if ((x == 1.0) || (x == 2.0)) {
+ return 0.0;
+ } else if (x <= 7.0) {
+ n = (RAND_INT_TYPE)(7 - x);
+ x0 = x + n;
+ }
+ x2 = 1.0 / (x0 * x0);
+ xp = 2 * M_PI;
+ gl0 = a[9];
+ for (k = 8; k >= 0; k--) {
+ gl0 *= x2;
+ gl0 += a[k];
+ }
+ gl = gl0 / x0 + 0.5 * log(xp) + (x0 - 0.5) * log(x0) - x0;
+ if (x <= 7.0) {
+ for (k = 1; k <= n; k++) {
+ gl -= log(x0 - 1.0);
+ x0 -= 1.0;
+ }
+ }
+ return gl;
+}
+
+/*
+double random_normal(bitgen_t *bitgen_state, double loc, double scale) {
+ return loc + scale * random_gauss(bitgen_state);
+}
+*/
+
+double random_normal_zig(bitgen_t *bitgen_state, double loc, double scale) {
+ return loc + scale * random_gauss_zig(bitgen_state);
+}
+
+double random_exponential(bitgen_t *bitgen_state, double scale) {
+ return scale * standard_exponential_zig(bitgen_state);
+}
+
+double random_uniform(bitgen_t *bitgen_state, double lower, double range) {
+ return lower + range * next_double(bitgen_state);
+}
+
+double random_gamma(bitgen_t *bitgen_state, double shape, double scale) {
+ return scale * random_standard_gamma_zig(bitgen_state, shape);
+}
+
+float random_gamma_float(bitgen_t *bitgen_state, float shape, float scale) {
+ return scale * random_standard_gamma_zig_f(bitgen_state, shape);
+}
+
+double random_beta(bitgen_t *bitgen_state, double a, double b) {
+ double Ga, Gb;
+
+ if ((a <= 1.0) && (b <= 1.0)) {
+ double U, V, X, Y, XpY;
+ /* Use Johnk's algorithm */
+
+ while (1) {
+ U = next_double(bitgen_state);
+ V = next_double(bitgen_state);
+ X = pow(U, 1.0 / a);
+ Y = pow(V, 1.0 / b);
+ XpY = X + Y;
+ /* Reject if both U and V are 0.0, which is approx 1 in 10^106 */
+ if ((XpY <= 1.0) && (XpY > 0.0)) {
+ if (X + Y > 0) {
+ return X / XpY;
+ } else {
+ double logX = log(U) / a;
+ double logY = log(V) / b;
+ double logM = logX > logY ? logX : logY;
+ logX -= logM;
+ logY -= logM;
+
+ return exp(logX - log(exp(logX) + exp(logY)));
+ }
+ }
+ }
+ } else {
+ Ga = random_standard_gamma_zig(bitgen_state, a);
+ Gb = random_standard_gamma_zig(bitgen_state, b);
+ return Ga / (Ga + Gb);
+ }
+}
+
+double random_chisquare(bitgen_t *bitgen_state, double df) {
+ return 2.0 * random_standard_gamma_zig(bitgen_state, df / 2.0);
+}
+
+double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) {
+ return ((random_chisquare(bitgen_state, dfnum) * dfden) /
+ (random_chisquare(bitgen_state, dfden) * dfnum));
+}
+
+double random_standard_cauchy(bitgen_t *bitgen_state) {
+ return random_gauss_zig(bitgen_state) / random_gauss_zig(bitgen_state);
+}
+
+double random_pareto(bitgen_t *bitgen_state, double a) {
+ return exp(standard_exponential_zig(bitgen_state) / a) - 1;
+}
+
+double random_weibull(bitgen_t *bitgen_state, double a) {
+ if (a == 0.0) {
+ return 0.0;
+ }
+ return pow(standard_exponential_zig(bitgen_state), 1. / a);
+}
+
+double random_power(bitgen_t *bitgen_state, double a) {
+ return pow(1 - exp(-standard_exponential_zig(bitgen_state)), 1. / a);
+}
+
+double random_laplace(bitgen_t *bitgen_state, double loc, double scale) {
+ double U;
+
+ U = next_double(bitgen_state);
+ if (U >= 0.5) {
+ U = loc - scale * log(2.0 - U - U);
+ } else if (U > 0.0) {
+ U = loc + scale * log(U + U);
+ } else {
+ /* Reject U == 0.0 and call again to get next value */
+ U = random_laplace(bitgen_state, loc, scale);
+ }
+ return U;
+}
+
+double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) {
+ double U;
+
+ U = 1.0 - next_double(bitgen_state);
+ if (U < 1.0) {
+ return loc - scale * log(-log(U));
+ }
+ /* Reject U == 1.0 and call again to get next value */
+ return random_gumbel(bitgen_state, loc, scale);
+}
+
+double random_logistic(bitgen_t *bitgen_state, double loc, double scale) {
+ double U;
+
+ U = next_double(bitgen_state);
+ if (U > 0.0) {
+ return loc + scale * log(U / (1.0 - U));
+ }
+ /* Reject U == 0.0 and call again to get next value */
+ return random_logistic(bitgen_state, loc, scale);
+}
+
+double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) {
+ return exp(random_normal_zig(bitgen_state, mean, sigma));
+}
+
+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 num, denom;
+
+ num = random_gauss_zig(bitgen_state);
+ denom = random_standard_gamma_zig(bitgen_state, df / 2);
+ return sqrt(df / 2) * num / sqrt(denom);
+}
+
+static RAND_INT_TYPE random_poisson_mult(bitgen_t *bitgen_state, double lam) {
+ RAND_INT_TYPE X;
+ double prod, U, enlam;
+
+ enlam = exp(-lam);
+ X = 0;
+ prod = 1.0;
+ while (1) {
+ U = next_double(bitgen_state);
+ prod *= U;
+ if (prod > enlam) {
+ X += 1;
+ } else {
+ return X;
+ }
+ }
+}
+
+/*
+ * The transformed rejection method for generating Poisson random variables
+ * W. Hoermann
+ * Insurance: Mathematics and Economics 12, 39-45 (1993)
+ */
+#define LS2PI 0.91893853320467267
+#define TWELFTH 0.083333333333333333333333
+static RAND_INT_TYPE random_poisson_ptrs(bitgen_t *bitgen_state, double lam) {
+ RAND_INT_TYPE k;
+ double U, V, slam, loglam, a, b, invalpha, vr, us;
+
+ slam = sqrt(lam);
+ loglam = log(lam);
+ b = 0.931 + 2.53 * slam;
+ a = -0.059 + 0.02483 * b;
+ invalpha = 1.1239 + 1.1328 / (b - 3.4);
+ vr = 0.9277 - 3.6224 / (b - 2);
+
+ while (1) {
+ U = next_double(bitgen_state) - 0.5;
+ V = next_double(bitgen_state);
+ us = 0.5 - fabs(U);
+ k = (RAND_INT_TYPE)floor((2 * a / us + b) * U + lam + 0.43);
+ if ((us >= 0.07) && (V <= vr)) {
+ return k;
+ }
+ if ((k < 0) || ((us < 0.013) && (V > us))) {
+ continue;
+ }
+ /* log(V) == log(0.0) ok here */
+ /* if U==0.0 so that us==0.0, log is ok since always returns */
+ if ((log(V) + log(invalpha) - log(a / (us * us) + b)) <=
+ (-lam + k * loglam - loggam(k + 1))) {
+ return k;
+ }
+ }
+}
+
+RAND_INT_TYPE random_poisson(bitgen_t *bitgen_state, double lam) {
+ if (lam >= 10) {
+ return random_poisson_ptrs(bitgen_state, lam);
+ } else if (lam == 0) {
+ return 0;
+ } else {
+ return random_poisson_mult(bitgen_state, lam);
+ }
+}
+
+RAND_INT_TYPE random_negative_binomial(bitgen_t *bitgen_state, double n,
+ double p) {
+ double Y = random_gamma(bitgen_state, n, (1 - p) / p);
+ return random_poisson(bitgen_state, Y);
+}
+
+RAND_INT_TYPE random_binomial_btpe(bitgen_t *bitgen_state, RAND_INT_TYPE n,
+ double p, binomial_t *binomial) {
+ double r, q, fm, p1, xm, xl, xr, c, laml, lamr, p2, p3, p4;
+ double a, u, v, s, F, rho, t, A, nrq, x1, x2, f1, f2, z, z2, w, w2, x;
+ RAND_INT_TYPE m, y, k, i;
+
+ if (!(binomial->has_binomial) || (binomial->nsave != n) ||
+ (binomial->psave != p)) {
+ /* initialize */
+ binomial->nsave = n;
+ binomial->psave = p;
+ binomial->has_binomial = 1;
+ binomial->r = r = MIN(p, 1.0 - p);
+ binomial->q = q = 1.0 - r;
+ binomial->fm = fm = n * r + r;
+ binomial->m = m = (RAND_INT_TYPE)floor(binomial->fm);
+ binomial->p1 = p1 = floor(2.195 * sqrt(n * r * q) - 4.6 * q) + 0.5;
+ binomial->xm = xm = m + 0.5;
+ binomial->xl = xl = xm - p1;
+ binomial->xr = xr = xm + p1;
+ binomial->c = c = 0.134 + 20.5 / (15.3 + m);
+ a = (fm - xl) / (fm - xl * r);
+ binomial->laml = laml = a * (1.0 + a / 2.0);
+ a = (xr - fm) / (xr * q);
+ binomial->lamr = lamr = a * (1.0 + a / 2.0);
+ binomial->p2 = p2 = p1 * (1.0 + 2.0 * c);
+ binomial->p3 = p3 = p2 + c / laml;
+ binomial->p4 = p4 = p3 + c / lamr;
+ } else {
+ r = binomial->r;
+ q = binomial->q;
+ fm = binomial->fm;
+ m = binomial->m;
+ p1 = binomial->p1;
+ xm = binomial->xm;
+ xl = binomial->xl;
+ xr = binomial->xr;
+ c = binomial->c;
+ laml = binomial->laml;
+ lamr = binomial->lamr;
+ p2 = binomial->p2;
+ p3 = binomial->p3;
+ p4 = binomial->p4;
+ }
+
+/* sigh ... */
+Step10:
+ nrq = n * r * q;
+ u = next_double(bitgen_state) * p4;
+ v = next_double(bitgen_state);
+ if (u > p1)
+ goto Step20;
+ y = (RAND_INT_TYPE)floor(xm - p1 * v + u);
+ goto Step60;
+
+Step20:
+ if (u > p2)
+ goto Step30;
+ x = xl + (u - p1) / c;
+ v = v * c + 1.0 - fabs(m - x + 0.5) / p1;
+ if (v > 1.0)
+ goto Step10;
+ y = (RAND_INT_TYPE)floor(x);
+ goto Step50;
+
+Step30:
+ if (u > p3)
+ goto Step40;
+ y = (RAND_INT_TYPE)floor(xl + log(v) / laml);
+ /* Reject if v==0.0 since previous cast is undefined */
+ if ((y < 0) || (v == 0.0))
+ goto Step10;
+ v = v * (u - p2) * laml;
+ goto Step50;
+
+Step40:
+ y = (RAND_INT_TYPE)floor(xr - log(v) / lamr);
+ /* Reject if v==0.0 since previous cast is undefined */
+ if ((y > n) || (v == 0.0))
+ goto Step10;
+ v = v * (u - p3) * lamr;
+
+Step50:
+ k = llabs(y - m);
+ if ((k > 20) && (k < ((nrq) / 2.0 - 1)))
+ goto Step52;
+
+ s = r / q;
+ a = s * (n + 1);
+ F = 1.0;
+ if (m < y) {
+ for (i = m + 1; i <= y; i++) {
+ F *= (a / i - s);
+ }
+ } else if (m > y) {
+ for (i = y + 1; i <= m; i++) {
+ F /= (a / i - s);
+ }
+ }
+ if (v > F)
+ goto Step10;
+ goto Step60;
+
+Step52:
+ rho =
+ (k / (nrq)) * ((k * (k / 3.0 + 0.625) + 0.16666666666666666) / nrq + 0.5);
+ t = -k * k / (2 * nrq);
+ /* log(0.0) ok here */
+ A = log(v);
+ if (A < (t - rho))
+ goto Step60;
+ if (A > (t + rho))
+ goto Step10;
+
+ x1 = y + 1;
+ f1 = m + 1;
+ z = n + 1 - m;
+ w = n - y + 1;
+ x2 = x1 * x1;
+ f2 = f1 * f1;
+ z2 = z * z;
+ w2 = w * w;
+ if (A > (xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) +
+ (y - m) * log(w * r / (x1 * q)) +
+ (13680. - (462. - (132. - (99. - 140. / f2) / f2) / f2) / f2) / f1 /
+ 166320. +
+ (13680. - (462. - (132. - (99. - 140. / z2) / z2) / z2) / z2) / z /
+ 166320. +
+ (13680. - (462. - (132. - (99. - 140. / x2) / x2) / x2) / x2) / x1 /
+ 166320. +
+ (13680. - (462. - (132. - (99. - 140. / w2) / w2) / w2) / w2) / w /
+ 166320.)) {
+ goto Step10;
+ }
+
+Step60:
+ if (p > 0.5) {
+ y = n - y;
+ }
+
+ return y;
+}
+
+RAND_INT_TYPE random_binomial_inversion(bitgen_t *bitgen_state, RAND_INT_TYPE n,
+ double p, binomial_t *binomial) {
+ double q, qn, np, px, U;
+ RAND_INT_TYPE X, bound;
+
+ if (!(binomial->has_binomial) || (binomial->nsave != n) ||
+ (binomial->psave != p)) {
+ binomial->nsave = n;
+ binomial->psave = p;
+ binomial->has_binomial = 1;
+ binomial->q = q = 1.0 - p;
+ binomial->r = qn = exp(n * log(q));
+ binomial->c = np = n * p;
+ binomial->m = bound = (RAND_INT_TYPE)MIN(n, np + 10.0 * sqrt(np * q + 1));
+ } else {
+ q = binomial->q;
+ qn = binomial->r;
+ np = binomial->c;
+ bound = binomial->m;
+ }
+ X = 0;
+ px = qn;
+ U = next_double(bitgen_state);
+ while (U > px) {
+ X++;
+ if (X > bound) {
+ X = 0;
+ px = qn;
+ U = next_double(bitgen_state);
+ } else {
+ U -= px;
+ px = ((n - X + 1) * p * px) / (X * q);
+ }
+ }
+ return X;
+}
+
+RAND_INT_TYPE random_binomial(bitgen_t *bitgen_state, double p, RAND_INT_TYPE n,
+ binomial_t *binomial) {
+ double q;
+
+ if ((n == 0LL) || (p == 0.0f))
+ return 0;
+
+ if (p <= 0.5) {
+ if (p * n <= 30.0) {
+ return random_binomial_inversion(bitgen_state, n, p, binomial);
+ } else {
+ return random_binomial_btpe(bitgen_state, n, p, binomial);
+ }
+ } else {
+ q = 1.0 - p;
+ if (q * n <= 30.0) {
+ return n - random_binomial_inversion(bitgen_state, n, q, binomial);
+ } else {
+ return n - random_binomial_btpe(bitgen_state, n, q, binomial);
+ }
+ }
+}
+
+double random_noncentral_chisquare(bitgen_t *bitgen_state, double df,
+ double nonc) {
+ if (npy_isnan(nonc)) {
+ return NPY_NAN;
+ }
+ if (nonc == 0) {
+ return random_chisquare(bitgen_state, df);
+ }
+ if (1 < df) {
+ const double Chi2 = random_chisquare(bitgen_state, df - 1);
+ const double n = random_gauss_zig(bitgen_state) + sqrt(nonc);
+ return Chi2 + n * n;
+ } else {
+ const RAND_INT_TYPE i = random_poisson(bitgen_state, nonc / 2.0);
+ return random_chisquare(bitgen_state, df + 2 * i);
+ }
+}
+
+double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden,
+ double nonc) {
+ double t = random_noncentral_chisquare(bitgen_state, dfnum, nonc) * dfden;
+ return t / (random_chisquare(bitgen_state, dfden) * dfnum);
+}
+
+double random_wald(bitgen_t *bitgen_state, double mean, double scale) {
+ double U, X, Y;
+ double mu_2l;
+
+ mu_2l = mean / (2 * scale);
+ Y = random_gauss_zig(bitgen_state);
+ Y = mean * Y * Y;
+ X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y));
+ U = next_double(bitgen_state);
+ if (U <= mean / (mean + X)) {
+ return X;
+ } else {
+ return mean * mean / X;
+ }
+}
+
+double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) {
+ double s;
+ double U, V, W, Y, Z;
+ double result, mod;
+ int neg;
+ if (npy_isnan(kappa)) {
+ return NPY_NAN;
+ }
+ if (kappa < 1e-8) {
+ return M_PI * (2 * next_double(bitgen_state) - 1);
+ } else {
+ /* with double precision rho is zero until 1.4e-8 */
+ if (kappa < 1e-5) {
+ /*
+ * second order taylor expansion around kappa = 0
+ * precise until relatively large kappas as second order is 0
+ */
+ s = (1. / kappa + kappa);
+ } else {
+ double r = 1 + sqrt(1 + 4 * kappa * kappa);
+ double rho = (r - sqrt(2 * r)) / (2 * kappa);
+ s = (1 + rho * rho) / (2 * rho);
+ }
+
+ while (1) {
+ U = next_double(bitgen_state);
+ Z = cos(M_PI * U);
+ W = (1 + s * Z) / (s + Z);
+ Y = kappa * (s - W);
+ V = next_double(bitgen_state);
+ /*
+ * V==0.0 is ok here since Y >= 0 always leads
+ * to accept, while Y < 0 always rejects
+ */
+ if ((Y * (2 - Y) - V >= 0) || (log(Y / V) + 1 - Y >= 0)) {
+ break;
+ }
+ }
+
+ U = next_double(bitgen_state);
+
+ result = acos(W);
+ if (U < 0.5) {
+ result = -result;
+ }
+ result += mu;
+ neg = (result < 0);
+ mod = fabs(result);
+ mod = (fmod(mod + M_PI, 2 * M_PI) - M_PI);
+ if (neg) {
+ mod *= -1;
+ }
+
+ return mod;
+ }
+}
+
+/*
+ * RAND_INT_TYPE is used to share integer generators with RandomState which
+ * used long in place of int64_t. If changing a distribution that uses
+ * RAND_INT_TYPE, then the original unmodified copy must be retained for
+ * use in RandomState by copying to the legacy distributions source file.
+ */
+RAND_INT_TYPE random_logseries(bitgen_t *bitgen_state, double p) {
+ double q, r, U, V;
+ RAND_INT_TYPE result;
+
+ r = log(1.0 - p);
+
+ while (1) {
+ V = next_double(bitgen_state);
+ if (V >= p) {
+ return 1;
+ }
+ U = next_double(bitgen_state);
+ q = 1.0 - exp(r * U);
+ if (V <= q * q) {
+ result = (RAND_INT_TYPE)floor(1 + log(V) / log(q));
+ if ((result < 1) || (V == 0.0)) {
+ continue;
+ } else {
+ return result;
+ }
+ }
+ if (V >= q) {
+ return 1;
+ }
+ return 2;
+ }
+}
+
+RAND_INT_TYPE random_geometric_search(bitgen_t *bitgen_state, double p) {
+ double U;
+ RAND_INT_TYPE X;
+ double sum, prod, q;
+
+ X = 1;
+ sum = prod = p;
+ q = 1.0 - p;
+ U = next_double(bitgen_state);
+ while (U > sum) {
+ prod *= q;
+ sum += prod;
+ X++;
+ }
+ return X;
+}
+
+RAND_INT_TYPE random_geometric_inversion(bitgen_t *bitgen_state, double p) {
+ return (RAND_INT_TYPE)ceil(log(1.0 - next_double(bitgen_state)) / log(1.0 - p));
+}
+
+RAND_INT_TYPE random_geometric(bitgen_t *bitgen_state, double p) {
+ if (p >= 0.333333333333333333333333) {
+ return random_geometric_search(bitgen_state, p);
+ } else {
+ return random_geometric_inversion(bitgen_state, p);
+ }
+}
+
+RAND_INT_TYPE random_zipf(bitgen_t *bitgen_state, double a) {
+ double am1, b;
+
+ am1 = a - 1.0;
+ b = pow(2.0, am1);
+ while (1) {
+ double T, U, V, X;
+
+ U = 1.0 - random_double(bitgen_state);
+ V = random_double(bitgen_state);
+ X = floor(pow(U, -1.0 / am1));
+ /*
+ * The real result may be above what can be represented in a signed
+ * long. Since this is a straightforward rejection algorithm, we can
+ * just reject this value. This function then models a Zipf
+ * distribution truncated to sys.maxint.
+ */
+ if (X > RAND_INT_MAX || X < 1.0) {
+ continue;
+ }
+
+ T = pow(1.0 + 1.0 / X, am1);
+ if (V * X * (T - 1.0) / (b - 1.0) <= T / b) {
+ return (RAND_INT_TYPE)X;
+ }
+ }
+}
+
+double random_triangular(bitgen_t *bitgen_state, double left, double mode,
+ double right) {
+ double base, leftbase, ratio, leftprod, rightprod;
+ double U;
+
+ base = right - left;
+ leftbase = mode - left;
+ ratio = leftbase / base;
+ leftprod = leftbase * base;
+ rightprod = (right - mode) * base;
+
+ U = next_double(bitgen_state);
+ if (U <= ratio) {
+ return left + sqrt(U * leftprod);
+ } else {
+ return right - sqrt((1.0 - U) * rightprod);
+ }
+}
+
+
+uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) {
+ uint64_t mask, value;
+ if (max == 0) {
+ return 0;
+ }
+
+ mask = max;
+
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+ mask |= mask >> 32;
+
+ /* Search a random value in [0..mask] <= max */
+ if (max <= 0xffffffffUL) {
+ while ((value = (next_uint32(bitgen_state) & mask)) > max)
+ ;
+ } else {
+ while ((value = (next_uint64(bitgen_state) & mask)) > max)
+ ;
+ }
+ return value;
+}
+
+/* Bounded generators */
+static NPY_INLINE uint64_t gen_mask(uint64_t max) {
+ uint64_t mask = max;
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+ mask |= mask >> 32;
+ return mask;
+}
+
+/* Generate 16 bit random numbers using a 32 bit buffer. */
+static NPY_INLINE uint16_t buffered_uint16(bitgen_t *bitgen_state, int *bcnt,
+ uint32_t *buf) {
+ if (!(bcnt[0])) {
+ buf[0] = next_uint32(bitgen_state);
+ bcnt[0] = 1;
+ } else {
+ buf[0] >>= 16;
+ bcnt[0] -= 1;
+ }
+
+ return (uint16_t)buf[0];
+}
+
+/* Generate 8 bit random numbers using a 32 bit buffer. */
+static NPY_INLINE uint8_t buffered_uint8(bitgen_t *bitgen_state, int *bcnt,
+ uint32_t *buf) {
+ if (!(bcnt[0])) {
+ buf[0] = next_uint32(bitgen_state);
+ bcnt[0] = 3;
+ } else {
+ buf[0] >>= 8;
+ bcnt[0] -= 1;
+ }
+
+ return (uint8_t)buf[0];
+}
+
+/* Static `masked rejection` function called by random_bounded_uint64(...) */
+static NPY_INLINE uint64_t bounded_masked_uint64(bitgen_t *bitgen_state,
+ uint64_t rng, uint64_t mask) {
+ uint64_t val;
+
+ while ((val = (next_uint64(bitgen_state) & mask)) > rng)
+ ;
+
+ return val;
+}
+
+/* Static `masked rejection` function called by
+ * random_buffered_bounded_uint32(...) */
+static NPY_INLINE uint32_t
+buffered_bounded_masked_uint32(bitgen_t *bitgen_state, uint32_t rng,
+ uint32_t mask, int *bcnt, uint32_t *buf) {
+ /*
+ * The buffer and buffer count are not used here but are included to allow
+ * this function to be templated with the similar uint8 and uint16
+ * functions
+ */
+
+ uint32_t val;
+
+ while ((val = (next_uint32(bitgen_state) & mask)) > rng)
+ ;
+
+ return val;
+}
+
+/* Static `masked rejection` function called by
+ * random_buffered_bounded_uint16(...) */
+static NPY_INLINE uint16_t
+buffered_bounded_masked_uint16(bitgen_t *bitgen_state, uint16_t rng,
+ uint16_t mask, int *bcnt, uint32_t *buf) {
+ uint16_t val;
+
+ while ((val = (buffered_uint16(bitgen_state, bcnt, buf) & mask)) > rng)
+ ;
+
+ return val;
+}
+
+/* Static `masked rejection` function called by
+ * random_buffered_bounded_uint8(...) */
+static NPY_INLINE uint8_t buffered_bounded_masked_uint8(bitgen_t *bitgen_state,
+ uint8_t rng,
+ uint8_t mask, int *bcnt,
+ uint32_t *buf) {
+ uint8_t val;
+
+ while ((val = (buffered_uint8(bitgen_state, bcnt, buf) & mask)) > rng)
+ ;
+
+ return val;
+}
+
+static NPY_INLINE npy_bool buffered_bounded_bool(bitgen_t *bitgen_state,
+ npy_bool off, npy_bool rng,
+ npy_bool mask, int *bcnt,
+ uint32_t *buf) {
+ if (rng == 0)
+ return off;
+ if (!(bcnt[0])) {
+ buf[0] = next_uint32(bitgen_state);
+ bcnt[0] = 31;
+ } else {
+ buf[0] >>= 1;
+ bcnt[0] -= 1;
+ }
+ return (buf[0] & 0x00000001UL) != 0;
+}
+
+/* Static `Lemire rejection` function called by random_bounded_uint64(...) */
+static NPY_INLINE uint64_t bounded_lemire_uint64(bitgen_t *bitgen_state,
+ uint64_t rng) {
+ /*
+ * Uses Lemire's algorithm - https://arxiv.org/abs/1805.10941
+ *
+ * Note: `rng` should not be 0xFFFFFFFFFFFFFFFF. When this happens `rng_excl`
+ * becomes zero.
+ */
+ const uint64_t rng_excl = rng + 1;
+
+#if __SIZEOF_INT128__
+ /* 128-bit uint available (e.g. GCC/clang). `m` is the __uint128_t scaled
+ * integer. */
+ __uint128_t m;
+ uint64_t leftover;
+
+ /* Generate a scaled random number. */
+ m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl;
+
+ /* Rejection sampling to remove any bias. */
+ leftover = m & 0xFFFFFFFFFFFFFFFFULL;
+
+ if (leftover < rng_excl) {
+ /* `rng_excl` is a simple upper bound for `threshold`. */
+
+ const uint64_t threshold = -rng_excl % rng_excl;
+ /* Same as: threshold=((uint64_t)(0x10000000000000000ULLL - rng_excl)) %
+ * rng_excl; */
+
+ while (leftover < threshold) {
+ m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl;
+ leftover = m & 0xFFFFFFFFFFFFFFFFULL;
+ }
+ }
+
+ return (m >> 64);
+#else
+ /* 128-bit uint NOT available (e.g. MSVS). `m1` is the upper 64-bits of the
+ * scaled integer. */
+ uint64_t m1;
+ uint64_t x;
+ uint64_t leftover;
+
+ x = next_uint64(bitgen_state);
+
+ /* Rejection sampling to remove any bias. */
+ leftover = x * rng_excl; /* The lower 64-bits of the mult. */
+
+ if (leftover < rng_excl) {
+ /* `rng_excl` is a simple upper bound for `threshold`. */
+
+ const uint64_t threshold = -rng_excl % rng_excl;
+ /* Same as:threshold=((uint64_t)(0x10000000000000000ULLL - rng_excl)) %
+ * rng_excl; */
+
+ while (leftover < threshold) {
+ x = next_uint64(bitgen_state);
+ leftover = x * rng_excl;
+ }
+ }
+
+#if defined(_MSC_VER) && defined(_WIN64)
+ /* _WIN64 architecture. Use the __umulh intrinsic to calc `m1`. */
+ m1 = __umulh(x, rng_excl);
+#else
+ /* 32-bit architecture. Emulate __umulh to calc `m1`. */
+ {
+ uint64_t x0, x1, rng_excl0, rng_excl1;
+ uint64_t w0, w1, w2, t;
+
+ x0 = x & 0xFFFFFFFFULL;
+ x1 = x >> 32;
+ rng_excl0 = rng_excl & 0xFFFFFFFFULL;
+ rng_excl1 = rng_excl >> 32;
+ w0 = x0 * rng_excl0;
+ t = x1 * rng_excl0 + (w0 >> 32);
+ w1 = t & 0xFFFFFFFFULL;
+ w2 = t >> 32;
+ w1 += x0 * rng_excl1;
+ m1 = x1 * rng_excl1 + w2 + (w1 >> 32);
+ }
+#endif
+
+ return m1;
+#endif
+}
+
+/* Static `Lemire rejection` function called by
+ * random_buffered_bounded_uint32(...) */
+static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(
+ bitgen_t *bitgen_state, uint32_t rng, int *bcnt, uint32_t *buf) {
+ /*
+ * Uses Lemire's algorithm - https://arxiv.org/abs/1805.10941
+ *
+ * The buffer and buffer count are not used here but are included to allow
+ * this function to be templated with the similar uint8 and uint16
+ * functions
+ *
+ * Note: `rng` should not be 0xFFFFFFFF. When this happens `rng_excl` becomes
+ * zero.
+ */
+ const uint32_t rng_excl = rng + 1;
+
+ uint64_t m;
+ uint32_t leftover;
+
+ /* Generate a scaled random number. */
+ m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl;
+
+ /* Rejection sampling to remove any bias */
+ leftover = m & 0xFFFFFFFFUL;
+
+ if (leftover < rng_excl) {
+ /* `rng_excl` is a simple upper bound for `threshold`. */
+ const uint32_t threshold = -rng_excl % rng_excl;
+ /* Same as: threshold=((uint64_t)(0x100000000ULL - rng_excl)) % rng_excl; */
+
+ while (leftover < threshold) {
+ m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl;
+ leftover = m & 0xFFFFFFFFUL;
+ }
+ }
+
+ return (m >> 32);
+}
+
+/* Static `Lemire rejection` function called by
+ * random_buffered_bounded_uint16(...) */
+static NPY_INLINE uint16_t buffered_bounded_lemire_uint16(
+ bitgen_t *bitgen_state, uint16_t rng, int *bcnt, uint32_t *buf) {
+ /*
+ * Uses Lemire's algorithm - https://arxiv.org/abs/1805.10941
+ *
+ * Note: `rng` should not be 0xFFFF. When this happens `rng_excl` becomes
+ * zero.
+ */
+ const uint16_t rng_excl = rng + 1;
+
+ uint32_t m;
+ uint16_t leftover;
+
+ /* Generate a scaled random number. */
+ m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl;
+
+ /* Rejection sampling to remove any bias */
+ leftover = m & 0xFFFFUL;
+
+ if (leftover < rng_excl) {
+ /* `rng_excl` is a simple upper bound for `threshold`. */
+ const uint16_t threshold = -rng_excl % rng_excl;
+ /* Same as: threshold=((uint32_t)(0x10000ULL - rng_excl)) % rng_excl; */
+
+ while (leftover < threshold) {
+ m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl;
+ leftover = m & 0xFFFFUL;
+ }
+ }
+
+ return (m >> 16);
+}
+
+/* Static `Lemire rejection` function called by
+ * random_buffered_bounded_uint8(...) */
+static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(bitgen_t *bitgen_state,
+ uint8_t rng, int *bcnt,
+ uint32_t *buf) {
+ /*
+ * Uses Lemire's algorithm - https://arxiv.org/abs/1805.10941
+ *
+ * Note: `rng` should not be 0xFF. When this happens `rng_excl` becomes
+ * zero.
+ */
+ const uint8_t rng_excl = rng + 1;
+
+ uint16_t m;
+ uint8_t leftover;
+
+ /* Generate a scaled random number. */
+ m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl;
+
+ /* Rejection sampling to remove any bias */
+ leftover = m & 0xFFUL;
+
+ if (leftover < rng_excl) {
+ /* `rng_excl` is a simple upper bound for `threshold`. */
+ const uint8_t threshold = -rng_excl % rng_excl;
+ /* Same as: threshold=((uint16_t)(0x100ULL - rng_excl)) % rng_excl; */
+
+ while (leftover < threshold) {
+ m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl;
+ leftover = m & 0xFFUL;
+ }
+ }
+
+ return (m >> 8);
+}
+
+/*
+ * Returns a single random npy_uint64 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off,
+ uint64_t rng, uint64_t mask, bool use_masked) {
+ if (rng == 0) {
+ return off;
+ } else if (rng < 0xFFFFFFFFUL) {
+ /* Call 32-bit generator if range in 32-bit. */
+ if (use_masked) {
+ return off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, NULL,
+ NULL);
+ } else {
+ return off +
+ buffered_bounded_lemire_uint32(bitgen_state, rng, NULL, NULL);
+ }
+ } else if (rng == 0xFFFFFFFFFFFFFFFFULL) {
+ /* Lemire64 doesn't support inclusive rng = 0xFFFFFFFFFFFFFFFF. */
+ return off + next_uint64(bitgen_state);
+ } else {
+ if (use_masked) {
+ return off + bounded_masked_uint64(bitgen_state, rng, mask);
+ } else {
+ return off + bounded_lemire_uint64(bitgen_state, rng);
+ }
+ }
+}
+
+/*
+ * Returns a single random npy_uint64 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+uint32_t random_buffered_bounded_uint32(bitgen_t *bitgen_state, uint32_t off,
+ uint32_t rng, uint32_t mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf) {
+ /*
+ * Unused bcnt and buf are here only to allow templating with other uint
+ * generators.
+ */
+ if (rng == 0) {
+ return off;
+ } else if (rng == 0xFFFFFFFFUL) {
+ /* Lemire32 doesn't support inclusive rng = 0xFFFFFFFF. */
+ return off + next_uint32(bitgen_state);
+ } else {
+ if (use_masked) {
+ return off +
+ buffered_bounded_masked_uint32(bitgen_state, rng, mask, bcnt, buf);
+ } else {
+ return off + buffered_bounded_lemire_uint32(bitgen_state, rng, bcnt, buf);
+ }
+ }
+}
+
+/*
+ * Returns a single random npy_uint16 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+uint16_t random_buffered_bounded_uint16(bitgen_t *bitgen_state, uint16_t off,
+ uint16_t rng, uint16_t mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf) {
+ if (rng == 0) {
+ return off;
+ } else if (rng == 0xFFFFUL) {
+ /* Lemire16 doesn't support inclusive rng = 0xFFFF. */
+ return off + buffered_uint16(bitgen_state, bcnt, buf);
+ } else {
+ if (use_masked) {
+ return off +
+ buffered_bounded_masked_uint16(bitgen_state, rng, mask, bcnt, buf);
+ } else {
+ return off + buffered_bounded_lemire_uint16(bitgen_state, rng, bcnt, buf);
+ }
+ }
+}
+
+/*
+ * Returns a single random npy_uint8 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+uint8_t random_buffered_bounded_uint8(bitgen_t *bitgen_state, uint8_t off,
+ uint8_t rng, uint8_t mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf) {
+ if (rng == 0) {
+ return off;
+ } else if (rng == 0xFFUL) {
+ /* Lemire8 doesn't support inclusive rng = 0xFF. */
+ return off + buffered_uint8(bitgen_state, bcnt, buf);
+ } else {
+ if (use_masked) {
+ return off +
+ buffered_bounded_masked_uint8(bitgen_state, rng, mask, bcnt, buf);
+ } else {
+ return off + buffered_bounded_lemire_uint8(bitgen_state, rng, bcnt, buf);
+ }
+ }
+}
+
+npy_bool random_buffered_bounded_bool(bitgen_t *bitgen_state, npy_bool off,
+ npy_bool rng, npy_bool mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf) {
+ return buffered_bounded_bool(bitgen_state, off, rng, mask, bcnt, buf);
+}
+
+/*
+ * Fills an array with cnt random npy_uint64 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off,
+ uint64_t rng, npy_intp cnt, bool use_masked,
+ uint64_t *out) {
+ npy_intp i;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ } else if (rng < 0xFFFFFFFFUL) {
+ uint32_t buf = 0;
+ int bcnt = 0;
+
+ /* Call 32-bit generator if range in 32-bit. */
+ if (use_masked) {
+ /* Smallest bit mask >= max */
+ uint64_t mask = gen_mask(rng);
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask,
+ &bcnt, &buf);
+ }
+ } else {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off +
+ buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf);
+ }
+ }
+ } else if (rng == 0xFFFFFFFFFFFFFFFFULL) {
+ /* Lemire64 doesn't support rng = 0xFFFFFFFFFFFFFFFF. */
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + next_uint64(bitgen_state);
+ }
+ } else {
+ if (use_masked) {
+ /* Smallest bit mask >= max */
+ uint64_t mask = gen_mask(rng);
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + bounded_masked_uint64(bitgen_state, rng, mask);
+ }
+ } else {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + bounded_lemire_uint64(bitgen_state, rng);
+ }
+ }
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint32 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void random_bounded_uint32_fill(bitgen_t *bitgen_state, uint32_t off,
+ uint32_t rng, npy_intp cnt, bool use_masked,
+ uint32_t *out) {
+ npy_intp i;
+ uint32_t buf = 0;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ } else if (rng == 0xFFFFFFFFUL) {
+ /* Lemire32 doesn't support rng = 0xFFFFFFFF. */
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + next_uint32(bitgen_state);
+ }
+ } else {
+ if (use_masked) {
+ /* Smallest bit mask >= max */
+ uint32_t mask = (uint32_t)gen_mask(rng);
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_bounded_masked_uint32(bitgen_state, rng, mask,
+ &bcnt, &buf);
+ }
+ } else {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off +
+ buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf);
+ }
+ }
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint16 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void random_bounded_uint16_fill(bitgen_t *bitgen_state, uint16_t off,
+ uint16_t rng, npy_intp cnt, bool use_masked,
+ uint16_t *out) {
+ npy_intp i;
+ uint32_t buf = 0;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ } else if (rng == 0xFFFFUL) {
+ /* Lemire16 doesn't support rng = 0xFFFF. */
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_uint16(bitgen_state, &bcnt, &buf);
+ }
+ } else {
+ if (use_masked) {
+ /* Smallest bit mask >= max */
+ uint16_t mask = (uint16_t)gen_mask(rng);
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_bounded_masked_uint16(bitgen_state, rng, mask,
+ &bcnt, &buf);
+ }
+ } else {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off +
+ buffered_bounded_lemire_uint16(bitgen_state, rng, &bcnt, &buf);
+ }
+ }
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint8 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void random_bounded_uint8_fill(bitgen_t *bitgen_state, uint8_t off, uint8_t rng,
+ npy_intp cnt, bool use_masked, uint8_t *out) {
+ npy_intp i;
+ uint32_t buf = 0;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ } else if (rng == 0xFFUL) {
+ /* Lemire8 doesn't support rng = 0xFF. */
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_uint8(bitgen_state, &bcnt, &buf);
+ }
+ } else {
+ if (use_masked) {
+ /* Smallest bit mask >= max */
+ uint8_t mask = (uint8_t)gen_mask(rng);
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = off + buffered_bounded_masked_uint8(bitgen_state, rng, mask,
+ &bcnt, &buf);
+ }
+ } else {
+ for (i = 0; i < cnt; i++) {
+ out[i] =
+ off + buffered_bounded_lemire_uint8(bitgen_state, rng, &bcnt, &buf);
+ }
+ }
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_bool between off and off + rng
+ * inclusive.
+ */
+void random_bounded_bool_fill(bitgen_t *bitgen_state, npy_bool off,
+ npy_bool rng, npy_intp cnt, bool use_masked,
+ npy_bool *out) {
+ npy_bool mask = 0;
+ npy_intp i;
+ uint32_t buf = 0;
+ int bcnt = 0;
+
+ for (i = 0; i < cnt; i++) {
+ out[i] = buffered_bounded_bool(bitgen_state, off, rng, mask, &bcnt, &buf);
+ }
+}
+
+void random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n,
+ RAND_INT_TYPE *mnix, double *pix, npy_intp d,
+ binomial_t *binomial) {
+ double remaining_p = 1.0;
+ npy_intp j;
+ RAND_INT_TYPE dn = n;
+ for (j = 0; j < (d - 1); j++) {
+ mnix[j] = random_binomial(bitgen_state, pix[j] / remaining_p, dn, binomial);
+ dn = dn - mnix[j];
+ if (dn <= 0) {
+ break;
+ }
+ remaining_p -= pix[j];
+ }
+ if (dn > 0) {
+ mnix[d - 1] = dn;
+ }
+}
diff --git a/numpy/random/src/distributions/distributions.h b/numpy/random/src/distributions/distributions.h
new file mode 100644
index 000000000..c8cdfd20f
--- /dev/null
+++ b/numpy/random/src/distributions/distributions.h
@@ -0,0 +1,205 @@
+#ifndef _RANDOMDGEN__DISTRIBUTIONS_H_
+#define _RANDOMDGEN__DISTRIBUTIONS_H_
+
+#pragma once
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "Python.h"
+#include "numpy/npy_common.h"
+#include "numpy/npy_math.h"
+#include "numpy/random/bitgen.h"
+
+/*
+ * RAND_INT_TYPE is used to share integer generators with RandomState which
+ * used long in place of int64_t. If changing a distribution that uses
+ * RAND_INT_TYPE, then the original unmodified copy must be retained for
+ * use in RandomState by copying to the legacy distributions source file.
+ */
+#ifdef NP_RANDOM_LEGACY
+#define RAND_INT_TYPE long
+#define RAND_INT_MAX LONG_MAX
+#else
+#define RAND_INT_TYPE int64_t
+#define RAND_INT_MAX INT64_MAX
+#endif
+
+#ifdef DLL_EXPORT
+#define DECLDIR __declspec(dllexport)
+#else
+#define DECLDIR extern
+#endif
+
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? x : y)
+#define MAX(x, y) (((x) > (y)) ? x : y)
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338328
+#endif
+
+typedef struct s_binomial_t {
+ int has_binomial; /* !=0: following parameters initialized for 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;
+} binomial_t;
+
+/* Inline generators for internal use */
+static NPY_INLINE uint32_t next_uint32(bitgen_t *bitgen_state) {
+ return bitgen_state->next_uint32(bitgen_state->state);
+}
+
+static NPY_INLINE uint64_t next_uint64(bitgen_t *bitgen_state) {
+ return bitgen_state->next_uint64(bitgen_state->state);
+}
+
+static NPY_INLINE float next_float(bitgen_t *bitgen_state) {
+ return (next_uint32(bitgen_state) >> 9) * (1.0f / 8388608.0f);
+}
+
+static NPY_INLINE double next_double(bitgen_t *bitgen_state) {
+ return bitgen_state->next_double(bitgen_state->state);
+}
+
+DECLDIR double loggam(double x);
+
+DECLDIR float random_float(bitgen_t *bitgen_state);
+DECLDIR double random_double(bitgen_t *bitgen_state);
+DECLDIR void random_double_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out);
+
+DECLDIR int64_t random_positive_int64(bitgen_t *bitgen_state);
+DECLDIR int32_t random_positive_int32(bitgen_t *bitgen_state);
+DECLDIR int64_t random_positive_int(bitgen_t *bitgen_state);
+DECLDIR uint64_t random_uint(bitgen_t *bitgen_state);
+
+DECLDIR double random_standard_exponential(bitgen_t *bitgen_state);
+DECLDIR void random_standard_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt,
+ double *out);
+DECLDIR float random_standard_exponential_f(bitgen_t *bitgen_state);
+DECLDIR double random_standard_exponential_zig(bitgen_t *bitgen_state);
+DECLDIR void random_standard_exponential_zig_fill(bitgen_t *bitgen_state,
+ npy_intp cnt, double *out);
+DECLDIR float random_standard_exponential_zig_f(bitgen_t *bitgen_state);
+
+/*
+DECLDIR double random_gauss(bitgen_t *bitgen_state);
+DECLDIR float random_gauss_f(bitgen_t *bitgen_state);
+*/
+DECLDIR double random_gauss_zig(bitgen_t *bitgen_state);
+DECLDIR float random_gauss_zig_f(bitgen_t *bitgen_state);
+DECLDIR void random_gauss_zig_fill(bitgen_t *bitgen_state, npy_intp cnt,
+ double *out);
+
+/*
+DECLDIR double random_standard_gamma(bitgen_t *bitgen_state, double shape);
+DECLDIR float random_standard_gamma_f(bitgen_t *bitgen_state, float shape);
+*/
+DECLDIR double random_standard_gamma_zig(bitgen_t *bitgen_state, double shape);
+DECLDIR float random_standard_gamma_zig_f(bitgen_t *bitgen_state, float shape);
+
+/*
+DECLDIR double random_normal(bitgen_t *bitgen_state, double loc, double scale);
+*/
+DECLDIR double random_normal_zig(bitgen_t *bitgen_state, double loc, double scale);
+
+DECLDIR double random_gamma(bitgen_t *bitgen_state, double shape, double scale);
+DECLDIR float random_gamma_float(bitgen_t *bitgen_state, float shape, float scale);
+
+DECLDIR double random_exponential(bitgen_t *bitgen_state, double scale);
+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_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);
+DECLDIR double random_laplace(bitgen_t *bitgen_state, double loc, double scale);
+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_noncentral_chisquare(bitgen_t *bitgen_state, double df,
+ double nonc);
+DECLDIR double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
+ double dfden, double nonc);
+DECLDIR double random_wald(bitgen_t *bitgen_state, double mean, double scale);
+DECLDIR double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa);
+DECLDIR double random_triangular(bitgen_t *bitgen_state, double left, double mode,
+ double right);
+
+DECLDIR RAND_INT_TYPE random_poisson(bitgen_t *bitgen_state, double lam);
+DECLDIR RAND_INT_TYPE random_negative_binomial(bitgen_t *bitgen_state, double n,
+ double p);
+DECLDIR RAND_INT_TYPE random_binomial(bitgen_t *bitgen_state, double p, RAND_INT_TYPE n,
+ binomial_t *binomial);
+DECLDIR RAND_INT_TYPE random_logseries(bitgen_t *bitgen_state, double p);
+DECLDIR RAND_INT_TYPE random_geometric_search(bitgen_t *bitgen_state, double p);
+DECLDIR RAND_INT_TYPE random_geometric_inversion(bitgen_t *bitgen_state, double p);
+DECLDIR RAND_INT_TYPE random_geometric(bitgen_t *bitgen_state, double p);
+DECLDIR RAND_INT_TYPE random_zipf(bitgen_t *bitgen_state, double a);
+DECLDIR int64_t random_hypergeometric(bitgen_t *bitgen_state,
+ int64_t good, int64_t bad, int64_t sample);
+
+DECLDIR uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max);
+
+/* Generate random uint64 numbers in closed interval [off, off + rng]. */
+DECLDIR uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off,
+ uint64_t rng, uint64_t mask,
+ bool use_masked);
+
+/* Generate random uint32 numbers in closed interval [off, off + rng]. */
+DECLDIR uint32_t random_buffered_bounded_uint32(bitgen_t *bitgen_state,
+ uint32_t off, uint32_t rng,
+ uint32_t mask, bool use_masked,
+ int *bcnt, uint32_t *buf);
+DECLDIR uint16_t random_buffered_bounded_uint16(bitgen_t *bitgen_state,
+ uint16_t off, uint16_t rng,
+ uint16_t mask, bool use_masked,
+ int *bcnt, uint32_t *buf);
+DECLDIR uint8_t random_buffered_bounded_uint8(bitgen_t *bitgen_state, uint8_t off,
+ uint8_t rng, uint8_t mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf);
+DECLDIR npy_bool random_buffered_bounded_bool(bitgen_t *bitgen_state, npy_bool off,
+ npy_bool rng, npy_bool mask,
+ bool use_masked, int *bcnt,
+ uint32_t *buf);
+
+DECLDIR void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off,
+ uint64_t rng, npy_intp cnt,
+ bool use_masked, uint64_t *out);
+DECLDIR void random_bounded_uint32_fill(bitgen_t *bitgen_state, uint32_t off,
+ uint32_t rng, npy_intp cnt,
+ bool use_masked, uint32_t *out);
+DECLDIR void random_bounded_uint16_fill(bitgen_t *bitgen_state, uint16_t off,
+ uint16_t rng, npy_intp cnt,
+ bool use_masked, uint16_t *out);
+DECLDIR void random_bounded_uint8_fill(bitgen_t *bitgen_state, uint8_t off,
+ uint8_t rng, npy_intp cnt,
+ bool use_masked, uint8_t *out);
+DECLDIR void random_bounded_bool_fill(bitgen_t *bitgen_state, npy_bool off,
+ npy_bool rng, npy_intp cnt,
+ bool use_masked, npy_bool *out);
+
+DECLDIR void random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n, RAND_INT_TYPE *mnix,
+ double *pix, npy_intp d, binomial_t *binomial);
+
+#endif
diff --git a/numpy/random/src/distributions/logfactorial.c b/numpy/random/src/distributions/logfactorial.c
new file mode 100644
index 000000000..130516469
--- /dev/null
+++ b/numpy/random/src/distributions/logfactorial.c
@@ -0,0 +1,158 @@
+
+#include <math.h>
+#include <stdint.h>
+
+/*
+ * logfact[k] holds log(k!) for k = 0, 1, 2, ..., 125.
+ */
+
+static const double logfact[] = {
+ 0,
+ 0,
+ 0.69314718055994529,
+ 1.791759469228055,
+ 3.1780538303479458,
+ 4.7874917427820458,
+ 6.5792512120101012,
+ 8.5251613610654147,
+ 10.604602902745251,
+ 12.801827480081469,
+ 15.104412573075516,
+ 17.502307845873887,
+ 19.987214495661885,
+ 22.552163853123425,
+ 25.19122118273868,
+ 27.89927138384089,
+ 30.671860106080672,
+ 33.505073450136891,
+ 36.395445208033053,
+ 39.339884187199495,
+ 42.335616460753485,
+ 45.380138898476908,
+ 48.471181351835227,
+ 51.606675567764377,
+ 54.784729398112319,
+ 58.003605222980518,
+ 61.261701761002001,
+ 64.557538627006338,
+ 67.88974313718154,
+ 71.257038967168015,
+ 74.658236348830158,
+ 78.092223553315307,
+ 81.557959456115043,
+ 85.054467017581516,
+ 88.580827542197682,
+ 92.136175603687093,
+ 95.719694542143202,
+ 99.330612454787428,
+ 102.96819861451381,
+ 106.63176026064346,
+ 110.32063971475739,
+ 114.03421178146171,
+ 117.77188139974507,
+ 121.53308151543864,
+ 125.3172711493569,
+ 129.12393363912722,
+ 132.95257503561632,
+ 136.80272263732635,
+ 140.67392364823425,
+ 144.5657439463449,
+ 148.47776695177302,
+ 152.40959258449735,
+ 156.3608363030788,
+ 160.3311282166309,
+ 164.32011226319517,
+ 168.32744544842765,
+ 172.35279713916279,
+ 176.39584840699735,
+ 180.45629141754378,
+ 184.53382886144948,
+ 188.6281734236716,
+ 192.7390472878449,
+ 196.86618167289001,
+ 201.00931639928152,
+ 205.1681994826412,
+ 209.34258675253685,
+ 213.53224149456327,
+ 217.73693411395422,
+ 221.95644181913033,
+ 226.1905483237276,
+ 230.43904356577696,
+ 234.70172344281826,
+ 238.97838956183432,
+ 243.26884900298271,
+ 247.57291409618688,
+ 251.89040220972319,
+ 256.22113555000954,
+ 260.56494097186322,
+ 264.92164979855278,
+ 269.29109765101981,
+ 273.67312428569369,
+ 278.06757344036612,
+ 282.4742926876304,
+ 286.89313329542699,
+ 291.32395009427029,
+ 295.76660135076065,
+ 300.22094864701415,
+ 304.68685676566872,
+ 309.1641935801469,
+ 313.65282994987905,
+ 318.1526396202093,
+ 322.66349912672615,
+ 327.1852877037752,
+ 331.71788719692847,
+ 336.26118197919845,
+ 340.81505887079902,
+ 345.37940706226686,
+ 349.95411804077025,
+ 354.53908551944079,
+ 359.1342053695754,
+ 363.73937555556347,
+ 368.35449607240474,
+ 372.97946888568902,
+ 377.61419787391867,
+ 382.25858877306001,
+ 386.91254912321756,
+ 391.57598821732961,
+ 396.24881705179155,
+ 400.93094827891576,
+ 405.6222961611449,
+ 410.32277652693733,
+ 415.03230672824964,
+ 419.75080559954472,
+ 424.47819341825709,
+ 429.21439186665157,
+ 433.95932399501481,
+ 438.71291418612117,
+ 443.47508812091894,
+ 448.24577274538461,
+ 453.02489623849613,
+ 457.81238798127816,
+ 462.60817852687489,
+ 467.4121995716082,
+ 472.22438392698058,
+ 477.04466549258564,
+ 481.87297922988796
+};
+
+/*
+ * Compute log(k!)
+ */
+
+double logfactorial(int64_t k)
+{
+ const double halfln2pi = 0.9189385332046728;
+
+ if (k < (int64_t) (sizeof(logfact)/sizeof(logfact[0]))) {
+ /* Use the lookup table. */
+ return logfact[k];
+ }
+
+ /*
+ * Use the Stirling series, truncated at the 1/k**3 term.
+ * (In a Python implementation of this approximation, the result
+ * was within 2 ULP of the best 64 bit floating point value for
+ * k up to 10000000.)
+ */
+ return (k + 0.5)*log(k) - k + (halfln2pi + (1.0/k)*(1/12.0 - 1/(360.0*k*k)));
+}
diff --git a/numpy/random/src/distributions/logfactorial.h b/numpy/random/src/distributions/logfactorial.h
new file mode 100644
index 000000000..1fedef3f6
--- /dev/null
+++ b/numpy/random/src/distributions/logfactorial.h
@@ -0,0 +1,9 @@
+
+#ifndef LOGFACTORIAL_H
+#define LOGFACTORIAL_H
+
+#include <stdint.h>
+
+double logfactorial(int64_t k);
+
+#endif
diff --git a/numpy/random/src/distributions/random_hypergeometric.c b/numpy/random/src/distributions/random_hypergeometric.c
new file mode 100644
index 000000000..59a3a4b9b
--- /dev/null
+++ b/numpy/random/src/distributions/random_hypergeometric.c
@@ -0,0 +1,260 @@
+#include <stdint.h>
+#include "distributions.h"
+#include "logfactorial.h"
+
+/*
+ * Generate a sample from the hypergeometric distribution.
+ *
+ * Assume sample is not greater than half the total. See below
+ * for how the opposite case is handled.
+ *
+ * We initialize the following:
+ * computed_sample = sample
+ * remaining_good = good
+ * remaining_total = good + bad
+ *
+ * In the loop:
+ * * computed_sample counts down to 0;
+ * * remaining_good is the number of good choices not selected yet;
+ * * remaining_total is the total number of choices not selected yet.
+ *
+ * In the loop, we select items by choosing a random integer in
+ * the interval [0, remaining_total), and if the value is less
+ * than remaining_good, it means we have selected a good one,
+ * so remaining_good is decremented. Then, regardless of that
+ * result, computed_sample is decremented. The loop continues
+ * until either computed_sample is 0, remaining_good is 0, or
+ * remaining_total == remaining_good. In the latter case, it
+ * means there are only good choices left, so we can stop the
+ * loop early and select what is left of computed_sample from
+ * the good choices (i.e. decrease remaining_good by computed_sample).
+ *
+ * When the loop exits, the actual number of good choices is
+ * good - remaining_good.
+ *
+ * If sample is more than half the total, then initially we set
+ * computed_sample = total - sample
+ * and at the end we return remaining_good (i.e. the loop in effect
+ * selects the complement of the result).
+ *
+ * It is assumed that when this function is called:
+ * * good, bad and sample are nonnegative;
+ * * the sum good+bad will not result in overflow;
+ * * sample <= good+bad.
+ */
+
+static int64_t hypergeometric_sample(bitgen_t *bitgen_state,
+ int64_t good, int64_t bad, int64_t sample)
+{
+ int64_t remaining_total, remaining_good, result, computed_sample;
+ int64_t total = good + bad;
+
+ if (sample > total/2) {
+ computed_sample = total - sample;
+ }
+ else {
+ computed_sample = sample;
+ }
+
+ remaining_total = total;
+ remaining_good = good;
+
+ while ((computed_sample > 0) && (remaining_good > 0) &&
+ (remaining_total > remaining_good)) {
+ // random_interval(bitgen_state, max) returns an integer in
+ // [0, max] *inclusive*, so we decrement remaining_total before
+ // passing it to random_interval().
+ --remaining_total;
+ if ((int64_t) random_interval(bitgen_state,
+ remaining_total) < remaining_good) {
+ // Selected a "good" one, so decrement remaining_good.
+ --remaining_good;
+ }
+ --computed_sample;
+ }
+
+ if (remaining_total == remaining_good) {
+ // Only "good" choices are left.
+ remaining_good -= computed_sample;
+ }
+
+ if (sample > total/2) {
+ result = remaining_good;
+ }
+ else {
+ result = good - remaining_good;
+ }
+
+ return result;
+}
+
+
+// D1 = 2*sqrt(2/e)
+// D2 = 3 - 2*sqrt(3/e)
+#define D1 1.7155277699214135
+#define D2 0.8989161620588988
+
+/*
+ * Generate variates from the hypergeometric distribution
+ * using the ratio-of-uniforms method.
+ *
+ * In the code, the variable names a, b, c, g, h, m, p, q, K, T,
+ * U and X match the names used in "Algorithm HRUA" beginning on
+ * page 82 of Stadlober's 1989 thesis.
+ *
+ * It is assumed that when this function is called:
+ * * good, bad and sample are nonnegative;
+ * * the sum good+bad will not result in overflow;
+ * * sample <= good+bad.
+ *
+ * References:
+ * - Ernst Stadlober's thesis "Sampling from Poisson, Binomial and
+ * Hypergeometric Distributions: Ratio of Uniforms as a Simple and
+ * Fast Alternative" (1989)
+ * - Ernst Stadlober, "The ratio of uniforms approach for generating
+ * discrete random variates", Journal of Computational and Applied
+ * Mathematics, 31, pp. 181-189 (1990).
+ */
+
+static int64_t hypergeometric_hrua(bitgen_t *bitgen_state,
+ int64_t good, int64_t bad, int64_t sample)
+{
+ int64_t mingoodbad, maxgoodbad, popsize;
+ int64_t computed_sample;
+ double p, q;
+ double mu, var;
+ double a, c, b, h, g;
+ int64_t m, K;
+
+ popsize = good + bad;
+ computed_sample = MIN(sample, popsize - sample);
+ mingoodbad = MIN(good, bad);
+ maxgoodbad = MAX(good, bad);
+
+ /*
+ * Variables that do not match Stadlober (1989)
+ * Here Stadlober
+ * ---------------- ---------
+ * mingoodbad M
+ * popsize N
+ * computed_sample n
+ */
+
+ p = ((double) mingoodbad) / popsize;
+ q = ((double) maxgoodbad) / popsize;
+
+ // mu is the mean of the distribution.
+ mu = computed_sample * p;
+
+ a = mu + 0.5;
+
+ // var is the variance of the distribution.
+ var = ((double)(popsize - computed_sample) *
+ computed_sample * p * q / (popsize - 1));
+
+ c = sqrt(var + 0.5);
+
+ /*
+ * h is 2*s_hat (See Stadlober's theses (1989), Eq. (5.17); or
+ * Stadlober (1990), Eq. 8). s_hat is the scale of the "table mountain"
+ * function that dominates the scaled hypergeometric PMF ("scaled" means
+ * normalized to have a maximum value of 1).
+ */
+ h = D1*c + D2;
+
+ m = (int64_t) floor((double)(computed_sample + 1) * (mingoodbad + 1) /
+ (popsize + 2));
+
+ g = (logfactorial(m) +
+ logfactorial(mingoodbad - m) +
+ logfactorial(computed_sample - m) +
+ logfactorial(maxgoodbad - computed_sample + m));
+
+ /*
+ * b is the upper bound for random samples:
+ * ... min(computed_sample, mingoodbad) + 1 is the length of the support.
+ * ... floor(a + 16*c) is 16 standard deviations beyond the mean.
+ *
+ * The idea behind the second upper bound is that values that far out in
+ * the tail have negligible probabilities.
+ *
+ * There is a comment in a previous version of this algorithm that says
+ * "16 for 16-decimal-digit precision in D1 and D2",
+ * but there is no documented justification for this value. A lower value
+ * might work just as well, but I've kept the value 16 here.
+ */
+ b = MIN(MIN(computed_sample, mingoodbad) + 1, floor(a + 16*c));
+
+ while (1) {
+ double U, V, X, T;
+ double gp;
+ U = random_double(bitgen_state);
+ V = random_double(bitgen_state); // "U star" in Stadlober (1989)
+ X = a + h*(V - 0.5) / U;
+
+ // fast rejection:
+ if ((X < 0.0) || (X >= b)) {
+ continue;
+ }
+
+ K = (int64_t) floor(X);
+
+ gp = (logfactorial(K) +
+ logfactorial(mingoodbad - K) +
+ logfactorial(computed_sample - K) +
+ logfactorial(maxgoodbad - computed_sample + K));
+
+ T = g - gp;
+
+ // fast acceptance:
+ if ((U*(4.0 - U) - 3.0) <= T) {
+ break;
+ }
+
+ // fast rejection:
+ if (U*(U - T) >= 1) {
+ continue;
+ }
+
+ if (2.0*log(U) <= T) {
+ // acceptance
+ break;
+ }
+ }
+
+ if (good > bad) {
+ K = computed_sample - K;
+ }
+
+ if (computed_sample < sample) {
+ K = good - K;
+ }
+
+ return K;
+}
+
+
+/*
+ * Draw a sample from the hypergeometric distribution.
+ *
+ * It is assumed that when this function is called:
+ * * good, bad and sample are nonnegative;
+ * * the sum good+bad will not result in overflow;
+ * * sample <= good+bad.
+ */
+
+int64_t random_hypergeometric(bitgen_t *bitgen_state,
+ int64_t good, int64_t bad, int64_t sample)
+{
+ int64_t r;
+
+ if ((sample >= 10) && (sample <= good + bad - 10)) {
+ // This will use the ratio-of-uniforms method.
+ r = hypergeometric_hrua(bitgen_state, good, bad, sample);
+ }
+ else {
+ // The simpler implementation is faster for small samples.
+ r = hypergeometric_sample(bitgen_state, good, bad, sample);
+ }
+ return r;
+}
diff --git a/numpy/random/src/distributions/ziggurat_constants.h b/numpy/random/src/distributions/ziggurat_constants.h
new file mode 100644
index 000000000..c254466de
--- /dev/null
+++ b/numpy/random/src/distributions/ziggurat_constants.h
@@ -0,0 +1,1206 @@
+static const uint64_t ki_double[] = {
+ 0x000EF33D8025EF6AULL, 0x0000000000000000ULL, 0x000C08BE98FBC6A8ULL,
+ 0x000DA354FABD8142ULL, 0x000E51F67EC1EEEAULL, 0x000EB255E9D3F77EULL,
+ 0x000EEF4B817ECAB9ULL, 0x000F19470AFA44AAULL, 0x000F37ED61FFCB18ULL,
+ 0x000F4F469561255CULL, 0x000F61A5E41BA396ULL, 0x000F707A755396A4ULL,
+ 0x000F7CB2EC28449AULL, 0x000F86F10C6357D3ULL, 0x000F8FA6578325DEULL,
+ 0x000F9724C74DD0DAULL, 0x000F9DA907DBF509ULL, 0x000FA360F581FA74ULL,
+ 0x000FA86FDE5B4BF8ULL, 0x000FACF160D354DCULL, 0x000FB0FB6718B90FULL,
+ 0x000FB49F8D5374C6ULL, 0x000FB7EC2366FE77ULL, 0x000FBAECE9A1E50EULL,
+ 0x000FBDAB9D040BEDULL, 0x000FC03060FF6C57ULL, 0x000FC2821037A248ULL,
+ 0x000FC4A67AE25BD1ULL, 0x000FC6A2977AEE31ULL, 0x000FC87AA92896A4ULL,
+ 0x000FCA325E4BDE85ULL, 0x000FCBCCE902231AULL, 0x000FCD4D12F839C4ULL,
+ 0x000FCEB54D8FEC99ULL, 0x000FD007BF1DC930ULL, 0x000FD1464DD6C4E6ULL,
+ 0x000FD272A8E2F450ULL, 0x000FD38E4FF0C91EULL, 0x000FD49A9990B478ULL,
+ 0x000FD598B8920F53ULL, 0x000FD689C08E99ECULL, 0x000FD76EA9C8E832ULL,
+ 0x000FD848547B08E8ULL, 0x000FD9178BAD2C8CULL, 0x000FD9DD07A7ADD2ULL,
+ 0x000FDA9970105E8CULL, 0x000FDB4D5DC02E20ULL, 0x000FDBF95C5BFCD0ULL,
+ 0x000FDC9DEBB99A7DULL, 0x000FDD3B8118729DULL, 0x000FDDD288342F90ULL,
+ 0x000FDE6364369F64ULL, 0x000FDEEE708D514EULL, 0x000FDF7401A6B42EULL,
+ 0x000FDFF46599ED40ULL, 0x000FE06FE4BC24F2ULL, 0x000FE0E6C225A258ULL,
+ 0x000FE1593C28B84CULL, 0x000FE1C78CBC3F99ULL, 0x000FE231E9DB1CAAULL,
+ 0x000FE29885DA1B91ULL, 0x000FE2FB8FB54186ULL, 0x000FE35B33558D4AULL,
+ 0x000FE3B799D0002AULL, 0x000FE410E99EAD7FULL, 0x000FE46746D47734ULL,
+ 0x000FE4BAD34C095CULL, 0x000FE50BAED29524ULL, 0x000FE559F74EBC78ULL,
+ 0x000FE5A5C8E41212ULL, 0x000FE5EF3E138689ULL, 0x000FE6366FD91078ULL,
+ 0x000FE67B75C6D578ULL, 0x000FE6BE661E11AAULL, 0x000FE6FF55E5F4F2ULL,
+ 0x000FE73E5900A702ULL, 0x000FE77B823E9E39ULL, 0x000FE7B6E37070A2ULL,
+ 0x000FE7F08D774243ULL, 0x000FE8289053F08CULL, 0x000FE85EFB35173AULL,
+ 0x000FE893DC840864ULL, 0x000FE8C741F0CEBCULL, 0x000FE8F9387D4EF6ULL,
+ 0x000FE929CC879B1DULL, 0x000FE95909D388EAULL, 0x000FE986FB939AA2ULL,
+ 0x000FE9B3AC714866ULL, 0x000FE9DF2694B6D5ULL, 0x000FEA0973ABE67CULL,
+ 0x000FEA329CF166A4ULL, 0x000FEA5AAB32952CULL, 0x000FEA81A6D5741AULL,
+ 0x000FEAA797DE1CF0ULL, 0x000FEACC85F3D920ULL, 0x000FEAF07865E63CULL,
+ 0x000FEB13762FEC13ULL, 0x000FEB3585FE2A4AULL, 0x000FEB56AE3162B4ULL,
+ 0x000FEB76F4E284FAULL, 0x000FEB965FE62014ULL, 0x000FEBB4F4CF9D7CULL,
+ 0x000FEBD2B8F449D0ULL, 0x000FEBEFB16E2E3EULL, 0x000FEC0BE31EBDE8ULL,
+ 0x000FEC2752B15A15ULL, 0x000FEC42049DAFD3ULL, 0x000FEC5BFD29F196ULL,
+ 0x000FEC75406CEEF4ULL, 0x000FEC8DD2500CB4ULL, 0x000FECA5B6911F12ULL,
+ 0x000FECBCF0C427FEULL, 0x000FECD38454FB15ULL, 0x000FECE97488C8B3ULL,
+ 0x000FECFEC47F91B7ULL, 0x000FED1377358528ULL, 0x000FED278F844903ULL,
+ 0x000FED3B10242F4CULL, 0x000FED4DFBAD586EULL, 0x000FED605498C3DDULL,
+ 0x000FED721D414FE8ULL, 0x000FED8357E4A982ULL, 0x000FED9406A42CC8ULL,
+ 0x000FEDA42B85B704ULL, 0x000FEDB3C8746AB4ULL, 0x000FEDC2DF416652ULL,
+ 0x000FEDD171A46E52ULL, 0x000FEDDF813C8AD3ULL, 0x000FEDED0F909980ULL,
+ 0x000FEDFA1E0FD414ULL, 0x000FEE06AE124BC4ULL, 0x000FEE12C0D95A06ULL,
+ 0x000FEE1E579006E0ULL, 0x000FEE29734B6524ULL, 0x000FEE34150AE4BCULL,
+ 0x000FEE3E3DB89B3CULL, 0x000FEE47EE2982F4ULL, 0x000FEE51271DB086ULL,
+ 0x000FEE59E9407F41ULL, 0x000FEE623528B42EULL, 0x000FEE6A0B5897F1ULL,
+ 0x000FEE716C3E077AULL, 0x000FEE7858327B82ULL, 0x000FEE7ECF7B06BAULL,
+ 0x000FEE84D2484AB2ULL, 0x000FEE8A60B66343ULL, 0x000FEE8F7ACCC851ULL,
+ 0x000FEE94207E25DAULL, 0x000FEE9851A829EAULL, 0x000FEE9C0E13485CULL,
+ 0x000FEE9F557273F4ULL, 0x000FEEA22762CCAEULL, 0x000FEEA4836B42ACULL,
+ 0x000FEEA668FC2D71ULL, 0x000FEEA7D76ED6FAULL, 0x000FEEA8CE04FA0AULL,
+ 0x000FEEA94BE8333BULL, 0x000FEEA950296410ULL, 0x000FEEA8D9C0075EULL,
+ 0x000FEEA7E7897654ULL, 0x000FEEA678481D24ULL, 0x000FEEA48AA29E83ULL,
+ 0x000FEEA21D22E4DAULL, 0x000FEE9F2E352024ULL, 0x000FEE9BBC26AF2EULL,
+ 0x000FEE97C524F2E4ULL, 0x000FEE93473C0A3AULL, 0x000FEE8E40557516ULL,
+ 0x000FEE88AE369C7AULL, 0x000FEE828E7F3DFDULL, 0x000FEE7BDEA7B888ULL,
+ 0x000FEE749BFF37FFULL, 0x000FEE6CC3A9BD5EULL, 0x000FEE64529E007EULL,
+ 0x000FEE5B45A32888ULL, 0x000FEE51994E57B6ULL, 0x000FEE474A0006CFULL,
+ 0x000FEE3C53E12C50ULL, 0x000FEE30B2E02AD8ULL, 0x000FEE2462AD8205ULL,
+ 0x000FEE175EB83C5AULL, 0x000FEE09A22A1447ULL, 0x000FEDFB27E349CCULL,
+ 0x000FEDEBEA76216CULL, 0x000FEDDBE422047EULL, 0x000FEDCB0ECE39D3ULL,
+ 0x000FEDB964042CF4ULL, 0x000FEDA6DCE938C9ULL, 0x000FED937237E98DULL,
+ 0x000FED7F1C38A836ULL, 0x000FED69D2B9C02BULL, 0x000FED538D06AE00ULL,
+ 0x000FED3C41DEA422ULL, 0x000FED23E76A2FD8ULL, 0x000FED0A732FE644ULL,
+ 0x000FECEFDA07FE34ULL, 0x000FECD4100EB7B8ULL, 0x000FECB708956EB4ULL,
+ 0x000FEC98B61230C1ULL, 0x000FEC790A0DA978ULL, 0x000FEC57F50F31FEULL,
+ 0x000FEC356686C962ULL, 0x000FEC114CB4B335ULL, 0x000FEBEB948E6FD0ULL,
+ 0x000FEBC429A0B692ULL, 0x000FEB9AF5EE0CDCULL, 0x000FEB6FE1C98542ULL,
+ 0x000FEB42D3AD1F9EULL, 0x000FEB13B00B2D4BULL, 0x000FEAE2591A02E9ULL,
+ 0x000FEAAEAE992257ULL, 0x000FEA788D8EE326ULL, 0x000FEA3FCFFD73E5ULL,
+ 0x000FEA044C8DD9F6ULL, 0x000FE9C5D62F563BULL, 0x000FE9843BA947A4ULL,
+ 0x000FE93F471D4728ULL, 0x000FE8F6BD76C5D6ULL, 0x000FE8AA5DC4E8E6ULL,
+ 0x000FE859E07AB1EAULL, 0x000FE804F690A940ULL, 0x000FE7AB488233C0ULL,
+ 0x000FE74C751F6AA5ULL, 0x000FE6E8102AA202ULL, 0x000FE67DA0B6ABD8ULL,
+ 0x000FE60C9F38307EULL, 0x000FE5947338F742ULL, 0x000FE51470977280ULL,
+ 0x000FE48BD436F458ULL, 0x000FE3F9BFFD1E37ULL, 0x000FE35D35EEB19CULL,
+ 0x000FE2B5122FE4FEULL, 0x000FE20003995557ULL, 0x000FE13C82788314ULL,
+ 0x000FE068C4EE67B0ULL, 0x000FDF82B02B71AAULL, 0x000FDE87C57EFEAAULL,
+ 0x000FDD7509C63BFDULL, 0x000FDC46E529BF13ULL, 0x000FDAF8F82E0282ULL,
+ 0x000FD985E1B2BA75ULL, 0x000FD7E6EF48CF04ULL, 0x000FD613ADBD650BULL,
+ 0x000FD40149E2F012ULL, 0x000FD1A1A7B4C7ACULL, 0x000FCEE204761F9EULL,
+ 0x000FCBA8D85E11B2ULL, 0x000FC7D26ECD2D22ULL, 0x000FC32B2F1E22EDULL,
+ 0x000FBD6581C0B83AULL, 0x000FB606C4005434ULL, 0x000FAC40582A2874ULL,
+ 0x000F9E971E014598ULL, 0x000F89FA48A41DFCULL, 0x000F66C5F7F0302CULL,
+ 0x000F1A5A4B331C4AULL};
+
+static const double wi_double[] = {
+ 8.68362706080130616677e-16, 4.77933017572773682428e-17,
+ 6.35435241740526230246e-17, 7.45487048124769627714e-17,
+ 8.32936681579309972857e-17, 9.06806040505948228243e-17,
+ 9.71486007656776183958e-17, 1.02947503142410192108e-16,
+ 1.08234302884476839838e-16, 1.13114701961090307945e-16,
+ 1.17663594570229211411e-16, 1.21936172787143633280e-16,
+ 1.25974399146370927864e-16, 1.29810998862640315416e-16,
+ 1.33472037368241227547e-16, 1.36978648425712032797e-16,
+ 1.40348230012423820659e-16, 1.43595294520569430270e-16,
+ 1.46732087423644219083e-16, 1.49769046683910367425e-16,
+ 1.52715150035961979750e-16, 1.55578181694607639484e-16,
+ 1.58364940092908853989e-16, 1.61081401752749279325e-16,
+ 1.63732852039698532012e-16, 1.66323990584208352778e-16,
+ 1.68859017086765964015e-16, 1.71341701765596607184e-16,
+ 1.73775443658648593310e-16, 1.76163319230009959832e-16,
+ 1.78508123169767272927e-16, 1.80812402857991522674e-16,
+ 1.83078487648267501776e-16, 1.85308513886180189386e-16,
+ 1.87504446393738816849e-16, 1.89668097007747596212e-16,
+ 1.91801140648386198029e-16, 1.93905129306251037069e-16,
+ 1.95981504266288244037e-16, 1.98031606831281739736e-16,
+ 2.00056687762733300198e-16, 2.02057915620716538808e-16,
+ 2.04036384154802118313e-16, 2.05993118874037063144e-16,
+ 2.07929082904140197311e-16, 2.09845182223703516690e-16,
+ 2.11742270357603418769e-16, 2.13621152594498681022e-16,
+ 2.15482589785814580926e-16, 2.17327301775643674990e-16,
+ 2.19155970504272708519e-16, 2.20969242822353175995e-16,
+ 2.22767733047895534948e-16, 2.24552025294143552381e-16,
+ 2.26322675592856786566e-16, 2.28080213834501706782e-16,
+ 2.29825145544246839061e-16, 2.31557953510408037008e-16,
+ 2.33279099280043561128e-16, 2.34989024534709550938e-16,
+ 2.36688152357916037468e-16, 2.38376888404542434981e-16,
+ 2.40055621981350627349e-16, 2.41724727046750252175e-16,
+ 2.43384563137110286400e-16, 2.45035476226149539878e-16,
+ 2.46677799523270498158e-16, 2.48311854216108767769e-16,
+ 2.49937950162045242375e-16, 2.51556386532965786439e-16,
+ 2.53167452417135826983e-16, 2.54771427381694417303e-16,
+ 2.56368581998939683749e-16, 2.57959178339286723500e-16,
+ 2.59543470433517070146e-16, 2.61121704706701939097e-16,
+ 2.62694120385972564623e-16, 2.64260949884118951286e-16,
+ 2.65822419160830680292e-16, 2.67378748063236329361e-16,
+ 2.68930150647261591777e-16, 2.70476835481199518794e-16,
+ 2.72019005932773206655e-16, 2.73556860440867908686e-16,
+ 2.75090592773016664571e-16, 2.76620392269639032183e-16,
+ 2.78146444075954410103e-16, 2.79668929362423005309e-16,
+ 2.81188025534502074329e-16, 2.82703906432447923059e-16,
+ 2.84216742521840606520e-16, 2.85726701075460149289e-16,
+ 2.87233946347097994381e-16, 2.88738639737848191815e-16,
+ 2.90240939955384233230e-16, 2.91741003166694553259e-16,
+ 2.93238983144718163965e-16, 2.94735031409293489611e-16,
+ 2.96229297362806647792e-16, 2.97721928420902891115e-16,
+ 2.99213070138601307081e-16, 3.00702866332133102993e-16,
+ 3.02191459196806151971e-16, 3.03678989421180184427e-16,
+ 3.05165596297821922381e-16, 3.06651417830895451744e-16,
+ 3.08136590840829717032e-16, 3.09621251066292253306e-16,
+ 3.11105533263689296831e-16, 3.12589571304399892784e-16,
+ 3.14073498269944617203e-16, 3.15557446545280064031e-16,
+ 3.17041547910402852545e-16, 3.18525933630440648871e-16,
+ 3.20010734544401137886e-16, 3.21496081152744704901e-16,
+ 3.22982103703941557538e-16, 3.24468932280169778077e-16,
+ 3.25956696882307838340e-16, 3.27445527514370671802e-16,
+ 3.28935554267536967851e-16, 3.30426907403912838589e-16,
+ 3.31919717440175233652e-16, 3.33414115231237245918e-16,
+ 3.34910232054077845412e-16, 3.36408199691876507948e-16,
+ 3.37908150518594979994e-16, 3.39410217584148914282e-16,
+ 3.40914534700312603713e-16, 3.42421236527501816058e-16,
+ 3.43930458662583133920e-16, 3.45442337727858401604e-16,
+ 3.46957011461378353333e-16, 3.48474618808741370700e-16,
+ 3.49995300016538099813e-16, 3.51519196727607440975e-16,
+ 3.53046452078274009054e-16, 3.54577210797743572160e-16,
+ 3.56111619309838843415e-16, 3.57649825837265051035e-16,
+ 3.59191980508602994994e-16, 3.60738235468235137839e-16,
+ 3.62288744989419151904e-16, 3.63843665590734438546e-16,
+ 3.65403156156136995766e-16, 3.66967378058870090021e-16,
+ 3.68536495289491401456e-16, 3.70110674588289834952e-16,
+ 3.71690085582382297792e-16, 3.73274900927794352614e-16,
+ 3.74865296456848868882e-16, 3.76461451331202869131e-16,
+ 3.78063548200896037651e-16, 3.79671773369794425924e-16,
+ 3.81286316967837738238e-16, 3.82907373130524317507e-16,
+ 3.84535140186095955858e-16, 3.86169820850914927119e-16,
+ 3.87811622433558721164e-16, 3.89460757048192620674e-16,
+ 3.91117441837820542060e-16, 3.92781899208054153270e-16,
+ 3.94454357072087711446e-16, 3.96135049107613542983e-16,
+ 3.97824215026468259474e-16, 3.99522100857856502444e-16,
+ 4.01228959246062907451e-16, 4.02945049763632792393e-16,
+ 4.04670639241074995115e-16, 4.06406002114225038723e-16,
+ 4.08151420790493873480e-16, 4.09907186035326643447e-16,
+ 4.11673597380302570170e-16, 4.13450963554423599878e-16,
+ 4.15239602940268833891e-16, 4.17039844056831587498e-16,
+ 4.18852026071011229572e-16, 4.20676499339901510978e-16,
+ 4.22513625986204937320e-16, 4.24363780509307796137e-16,
+ 4.26227350434779809917e-16, 4.28104737005311666397e-16,
+ 4.29996355916383230161e-16, 4.31902638100262944617e-16,
+ 4.33824030562279080411e-16, 4.35760997273684900553e-16,
+ 4.37714020125858747008e-16, 4.39683599951052137423e-16,
+ 4.41670257615420348435e-16, 4.43674535190656726604e-16,
+ 4.45696997211204306674e-16, 4.47738232024753387312e-16,
+ 4.49798853244554968009e-16, 4.51879501313005876278e-16,
+ 4.53980845187003400947e-16, 4.56103584156742206384e-16,
+ 4.58248449810956667052e-16, 4.60416208163115281428e-16,
+ 4.62607661954784567754e-16, 4.64823653154320737780e-16,
+ 4.67065065671263059081e-16, 4.69332828309332890697e-16,
+ 4.71627917983835129766e-16, 4.73951363232586715165e-16,
+ 4.76304248053313737663e-16, 4.78687716104872284247e-16,
+ 4.81102975314741720538e-16, 4.83551302941152515162e-16,
+ 4.86034051145081195402e-16, 4.88552653135360343280e-16,
+ 4.91108629959526955862e-16, 4.93703598024033454728e-16,
+ 4.96339277440398725619e-16, 4.99017501309182245754e-16,
+ 5.01740226071808946011e-16, 5.04509543081872748637e-16,
+ 5.07327691573354207058e-16, 5.10197073234156184149e-16,
+ 5.13120268630678373200e-16, 5.16100055774322824569e-16,
+ 5.19139431175769859873e-16, 5.22241633800023428760e-16,
+ 5.25410172417759732697e-16, 5.28648856950494511482e-16,
+ 5.31961834533840037535e-16, 5.35353631181649688145e-16,
+ 5.38829200133405320160e-16, 5.42393978220171234073e-16,
+ 5.46053951907478041166e-16, 5.49815735089281410703e-16,
+ 5.53686661246787600374e-16, 5.57674893292657647836e-16,
+ 5.61789555355541665830e-16, 5.66040892008242216739e-16,
+ 5.70440462129138908417e-16, 5.75001376891989523684e-16,
+ 5.79738594572459365014e-16, 5.84669289345547900201e-16,
+ 5.89813317647789942685e-16, 5.95193814964144415532e-16,
+ 6.00837969627190832234e-16, 6.06778040933344851394e-16,
+ 6.13052720872528159123e-16, 6.19708989458162555387e-16,
+ 6.26804696330128439415e-16, 6.34412240712750598627e-16,
+ 6.42623965954805540945e-16, 6.51560331734499356881e-16,
+ 6.61382788509766415145e-16, 6.72315046250558662913e-16,
+ 6.84680341756425875856e-16, 6.98971833638761995415e-16,
+ 7.15999493483066421560e-16, 7.37242430179879890722e-16,
+ 7.65893637080557275482e-16, 8.11384933765648418565e-16};
+
+static const double fi_double[] = {
+ 1.00000000000000000000e+00, 9.77101701267671596263e-01,
+ 9.59879091800106665211e-01, 9.45198953442299649730e-01,
+ 9.32060075959230460718e-01, 9.19991505039347012840e-01,
+ 9.08726440052130879366e-01, 8.98095921898343418910e-01,
+ 8.87984660755833377088e-01, 8.78309655808917399966e-01,
+ 8.69008688036857046555e-01, 8.60033621196331532488e-01,
+ 8.51346258458677951353e-01, 8.42915653112204177333e-01,
+ 8.34716292986883434679e-01, 8.26726833946221373317e-01,
+ 8.18929191603702366642e-01, 8.11307874312656274185e-01,
+ 8.03849483170964274059e-01, 7.96542330422958966274e-01,
+ 7.89376143566024590648e-01, 7.82341832654802504798e-01,
+ 7.75431304981187174974e-01, 7.68637315798486264740e-01,
+ 7.61953346836795386565e-01, 7.55373506507096115214e-01,
+ 7.48892447219156820459e-01, 7.42505296340151055290e-01,
+ 7.36207598126862650112e-01, 7.29995264561476231435e-01,
+ 7.23864533468630222401e-01, 7.17811932630721960535e-01,
+ 7.11834248878248421200e-01, 7.05928501332754310127e-01,
+ 7.00091918136511615067e-01, 6.94321916126116711609e-01,
+ 6.88616083004671808432e-01, 6.82972161644994857355e-01,
+ 6.77388036218773526009e-01, 6.71861719897082099173e-01,
+ 6.66391343908750100056e-01, 6.60975147776663107813e-01,
+ 6.55611470579697264149e-01, 6.50298743110816701574e-01,
+ 6.45035480820822293424e-01, 6.39820277453056585060e-01,
+ 6.34651799287623608059e-01, 6.29528779924836690007e-01,
+ 6.24450015547026504592e-01, 6.19414360605834324325e-01,
+ 6.14420723888913888899e-01, 6.09468064925773433949e-01,
+ 6.04555390697467776029e-01, 5.99681752619125263415e-01,
+ 5.94846243767987448159e-01, 5.90047996332826008015e-01,
+ 5.85286179263371453274e-01, 5.80559996100790898232e-01,
+ 5.75868682972353718164e-01, 5.71211506735253227163e-01,
+ 5.66587763256164445025e-01, 5.61996775814524340831e-01,
+ 5.57437893618765945014e-01, 5.52910490425832290562e-01,
+ 5.48413963255265812791e-01, 5.43947731190026262382e-01,
+ 5.39511234256952132426e-01, 5.35103932380457614215e-01,
+ 5.30725304403662057062e-01, 5.26374847171684479008e-01,
+ 5.22052074672321841931e-01, 5.17756517229756352272e-01,
+ 5.13487720747326958914e-01, 5.09245245995747941592e-01,
+ 5.05028667943468123624e-01, 5.00837575126148681903e-01,
+ 4.96671569052489714213e-01, 4.92530263643868537748e-01,
+ 4.88413284705458028423e-01, 4.84320269426683325253e-01,
+ 4.80250865909046753544e-01, 4.76204732719505863248e-01,
+ 4.72181538467730199660e-01, 4.68180961405693596422e-01,
+ 4.64202689048174355069e-01, 4.60246417812842867345e-01,
+ 4.56311852678716434184e-01, 4.52398706861848520777e-01,
+ 4.48506701507203064949e-01, 4.44635565395739396077e-01,
+ 4.40785034665803987508e-01, 4.36954852547985550526e-01,
+ 4.33144769112652261445e-01, 4.29354541029441427735e-01,
+ 4.25583931338021970170e-01, 4.21832709229495894654e-01,
+ 4.18100649837848226120e-01, 4.14387534040891125642e-01,
+ 4.10693148270188157500e-01, 4.07017284329473372217e-01,
+ 4.03359739221114510510e-01, 3.99720314980197222177e-01,
+ 3.96098818515832451492e-01, 3.92495061459315619512e-01,
+ 3.88908860018788715696e-01, 3.85340034840077283462e-01,
+ 3.81788410873393657674e-01, 3.78253817245619183840e-01,
+ 3.74736087137891138443e-01, 3.71235057668239498696e-01,
+ 3.67750569779032587814e-01, 3.64282468129004055601e-01,
+ 3.60830600989648031529e-01, 3.57394820145780500731e-01,
+ 3.53974980800076777232e-01, 3.50570941481406106455e-01,
+ 3.47182563956793643900e-01, 3.43809713146850715049e-01,
+ 3.40452257044521866547e-01, 3.37110066637006045021e-01,
+ 3.33783015830718454708e-01, 3.30470981379163586400e-01,
+ 3.27173842813601400970e-01, 3.23891482376391093290e-01,
+ 3.20623784956905355514e-01, 3.17370638029913609834e-01,
+ 3.14131931596337177215e-01, 3.10907558126286509559e-01,
+ 3.07697412504292056035e-01, 3.04501391976649993243e-01,
+ 3.01319396100803049698e-01, 2.98151326696685481377e-01,
+ 2.94997087799961810184e-01, 2.91856585617095209972e-01,
+ 2.88729728482182923521e-01, 2.85616426815501756042e-01,
+ 2.82516593083707578948e-01, 2.79430141761637940157e-01,
+ 2.76356989295668320494e-01, 2.73297054068577072172e-01,
+ 2.70250256365875463072e-01, 2.67216518343561471038e-01,
+ 2.64195763997261190426e-01, 2.61187919132721213522e-01,
+ 2.58192911337619235290e-01, 2.55210669954661961700e-01,
+ 2.52241126055942177508e-01, 2.49284212418528522415e-01,
+ 2.46339863501263828249e-01, 2.43408015422750312329e-01,
+ 2.40488605940500588254e-01, 2.37581574431238090606e-01,
+ 2.34686861872330010392e-01, 2.31804410824338724684e-01,
+ 2.28934165414680340644e-01, 2.26076071322380278694e-01,
+ 2.23230075763917484855e-01, 2.20396127480151998723e-01,
+ 2.17574176724331130872e-01, 2.14764175251173583536e-01,
+ 2.11966076307030182324e-01, 2.09179834621125076977e-01,
+ 2.06405406397880797353e-01, 2.03642749310334908452e-01,
+ 2.00891822494656591136e-01, 1.98152586545775138971e-01,
+ 1.95425003514134304483e-01, 1.92709036903589175926e-01,
+ 1.90004651670464985713e-01, 1.87311814223800304768e-01,
+ 1.84630492426799269756e-01, 1.81960655599522513892e-01,
+ 1.79302274522847582272e-01, 1.76655321443734858455e-01,
+ 1.74019770081838553999e-01, 1.71395595637505754327e-01,
+ 1.68782774801211288285e-01, 1.66181285764481906364e-01,
+ 1.63591108232365584074e-01, 1.61012223437511009516e-01,
+ 1.58444614155924284882e-01, 1.55888264724479197465e-01,
+ 1.53343161060262855866e-01, 1.50809290681845675763e-01,
+ 1.48286642732574552861e-01, 1.45775208005994028060e-01,
+ 1.43274978973513461566e-01, 1.40785949814444699690e-01,
+ 1.38308116448550733057e-01, 1.35841476571253755301e-01,
+ 1.33386029691669155683e-01, 1.30941777173644358090e-01,
+ 1.28508722279999570981e-01, 1.26086870220185887081e-01,
+ 1.23676228201596571932e-01, 1.21276805484790306533e-01,
+ 1.18888613442910059947e-01, 1.16511665625610869035e-01,
+ 1.14145977827838487895e-01, 1.11791568163838089811e-01,
+ 1.09448457146811797824e-01, 1.07116667774683801961e-01,
+ 1.04796225622487068629e-01, 1.02487158941935246892e-01,
+ 1.00189498768810017482e-01, 9.79032790388624646338e-02,
+ 9.56285367130089991594e-02, 9.33653119126910124859e-02,
+ 9.11136480663737591268e-02, 8.88735920682758862021e-02,
+ 8.66451944505580717859e-02, 8.44285095703534715916e-02,
+ 8.22235958132029043366e-02, 8.00305158146630696292e-02,
+ 7.78493367020961224423e-02, 7.56801303589271778804e-02,
+ 7.35229737139813238622e-02, 7.13779490588904025339e-02,
+ 6.92451443970067553879e-02, 6.71246538277884968737e-02,
+ 6.50165779712428976156e-02, 6.29210244377581412456e-02,
+ 6.08381083495398780614e-02, 5.87679529209337372930e-02,
+ 5.67106901062029017391e-02, 5.46664613248889208474e-02,
+ 5.26354182767921896513e-02, 5.06177238609477817000e-02,
+ 4.86135532158685421122e-02, 4.66230949019303814174e-02,
+ 4.46465522512944634759e-02, 4.26841449164744590750e-02,
+ 4.07361106559409394401e-02, 3.88027074045261474722e-02,
+ 3.68842156885673053135e-02, 3.49809414617161251737e-02,
+ 3.30932194585785779961e-02, 3.12214171919203004046e-02,
+ 2.93659397581333588001e-02, 2.75272356696031131329e-02,
+ 2.57058040085489103443e-02, 2.39022033057958785407e-02,
+ 2.21170627073088502113e-02, 2.03510962300445102935e-02,
+ 1.86051212757246224594e-02, 1.68800831525431419000e-02,
+ 1.51770883079353092332e-02, 1.34974506017398673818e-02,
+ 1.18427578579078790488e-02, 1.02149714397014590439e-02,
+ 8.61658276939872638800e-03, 7.05087547137322242369e-03,
+ 5.52240329925099155545e-03, 4.03797259336302356153e-03,
+ 2.60907274610215926189e-03, 1.26028593049859797236e-03};
+
+static const uint32_t ki_float[] = {
+ 0x007799ECUL, 0x00000000UL, 0x006045F5UL, 0x006D1AA8UL, 0x00728FB4UL,
+ 0x007592AFUL, 0x00777A5CUL, 0x0078CA38UL, 0x0079BF6BUL, 0x007A7A35UL,
+ 0x007B0D2FUL, 0x007B83D4UL, 0x007BE597UL, 0x007C3788UL, 0x007C7D33UL,
+ 0x007CB926UL, 0x007CED48UL, 0x007D1B08UL, 0x007D437FUL, 0x007D678BUL,
+ 0x007D87DBUL, 0x007DA4FCUL, 0x007DBF61UL, 0x007DD767UL, 0x007DED5DUL,
+ 0x007E0183UL, 0x007E1411UL, 0x007E2534UL, 0x007E3515UL, 0x007E43D5UL,
+ 0x007E5193UL, 0x007E5E67UL, 0x007E6A69UL, 0x007E75AAUL, 0x007E803EUL,
+ 0x007E8A32UL, 0x007E9395UL, 0x007E9C72UL, 0x007EA4D5UL, 0x007EACC6UL,
+ 0x007EB44EUL, 0x007EBB75UL, 0x007EC243UL, 0x007EC8BCUL, 0x007ECEE8UL,
+ 0x007ED4CCUL, 0x007EDA6BUL, 0x007EDFCBUL, 0x007EE4EFUL, 0x007EE9DCUL,
+ 0x007EEE94UL, 0x007EF31BUL, 0x007EF774UL, 0x007EFBA0UL, 0x007EFFA3UL,
+ 0x007F037FUL, 0x007F0736UL, 0x007F0ACAUL, 0x007F0E3CUL, 0x007F118FUL,
+ 0x007F14C4UL, 0x007F17DCUL, 0x007F1ADAUL, 0x007F1DBDUL, 0x007F2087UL,
+ 0x007F233AUL, 0x007F25D7UL, 0x007F285DUL, 0x007F2AD0UL, 0x007F2D2EUL,
+ 0x007F2F7AUL, 0x007F31B3UL, 0x007F33DCUL, 0x007F35F3UL, 0x007F37FBUL,
+ 0x007F39F3UL, 0x007F3BDCUL, 0x007F3DB7UL, 0x007F3F84UL, 0x007F4145UL,
+ 0x007F42F8UL, 0x007F449FUL, 0x007F463AUL, 0x007F47CAUL, 0x007F494EUL,
+ 0x007F4AC8UL, 0x007F4C38UL, 0x007F4D9DUL, 0x007F4EF9UL, 0x007F504CUL,
+ 0x007F5195UL, 0x007F52D5UL, 0x007F540DUL, 0x007F553DUL, 0x007F5664UL,
+ 0x007F5784UL, 0x007F589CUL, 0x007F59ACUL, 0x007F5AB5UL, 0x007F5BB8UL,
+ 0x007F5CB3UL, 0x007F5DA8UL, 0x007F5E96UL, 0x007F5F7EUL, 0x007F605FUL,
+ 0x007F613BUL, 0x007F6210UL, 0x007F62E0UL, 0x007F63AAUL, 0x007F646FUL,
+ 0x007F652EUL, 0x007F65E8UL, 0x007F669CUL, 0x007F674CUL, 0x007F67F6UL,
+ 0x007F689CUL, 0x007F693CUL, 0x007F69D9UL, 0x007F6A70UL, 0x007F6B03UL,
+ 0x007F6B91UL, 0x007F6C1BUL, 0x007F6CA0UL, 0x007F6D21UL, 0x007F6D9EUL,
+ 0x007F6E17UL, 0x007F6E8CUL, 0x007F6EFCUL, 0x007F6F68UL, 0x007F6FD1UL,
+ 0x007F7035UL, 0x007F7096UL, 0x007F70F3UL, 0x007F714CUL, 0x007F71A1UL,
+ 0x007F71F2UL, 0x007F723FUL, 0x007F7289UL, 0x007F72CFUL, 0x007F7312UL,
+ 0x007F7350UL, 0x007F738BUL, 0x007F73C3UL, 0x007F73F6UL, 0x007F7427UL,
+ 0x007F7453UL, 0x007F747CUL, 0x007F74A1UL, 0x007F74C3UL, 0x007F74E0UL,
+ 0x007F74FBUL, 0x007F7511UL, 0x007F7524UL, 0x007F7533UL, 0x007F753FUL,
+ 0x007F7546UL, 0x007F754AUL, 0x007F754BUL, 0x007F7547UL, 0x007F753FUL,
+ 0x007F7534UL, 0x007F7524UL, 0x007F7511UL, 0x007F74F9UL, 0x007F74DEUL,
+ 0x007F74BEUL, 0x007F749AUL, 0x007F7472UL, 0x007F7445UL, 0x007F7414UL,
+ 0x007F73DFUL, 0x007F73A5UL, 0x007F7366UL, 0x007F7323UL, 0x007F72DAUL,
+ 0x007F728DUL, 0x007F723AUL, 0x007F71E3UL, 0x007F7186UL, 0x007F7123UL,
+ 0x007F70BBUL, 0x007F704DUL, 0x007F6FD9UL, 0x007F6F5FUL, 0x007F6EDFUL,
+ 0x007F6E58UL, 0x007F6DCBUL, 0x007F6D37UL, 0x007F6C9CUL, 0x007F6BF9UL,
+ 0x007F6B4FUL, 0x007F6A9CUL, 0x007F69E2UL, 0x007F691FUL, 0x007F6854UL,
+ 0x007F677FUL, 0x007F66A1UL, 0x007F65B8UL, 0x007F64C6UL, 0x007F63C8UL,
+ 0x007F62C0UL, 0x007F61ABUL, 0x007F608AUL, 0x007F5F5DUL, 0x007F5E21UL,
+ 0x007F5CD8UL, 0x007F5B7FUL, 0x007F5A17UL, 0x007F589EUL, 0x007F5713UL,
+ 0x007F5575UL, 0x007F53C4UL, 0x007F51FEUL, 0x007F5022UL, 0x007F4E2FUL,
+ 0x007F4C22UL, 0x007F49FAUL, 0x007F47B6UL, 0x007F4553UL, 0x007F42CFUL,
+ 0x007F4028UL, 0x007F3D5AUL, 0x007F3A64UL, 0x007F3741UL, 0x007F33EDUL,
+ 0x007F3065UL, 0x007F2CA4UL, 0x007F28A4UL, 0x007F245FUL, 0x007F1FCEUL,
+ 0x007F1AEAUL, 0x007F15A9UL, 0x007F1000UL, 0x007F09E4UL, 0x007F0346UL,
+ 0x007EFC16UL, 0x007EF43EUL, 0x007EEBA8UL, 0x007EE237UL, 0x007ED7C8UL,
+ 0x007ECC2FUL, 0x007EBF37UL, 0x007EB09DUL, 0x007EA00AUL, 0x007E8D0DUL,
+ 0x007E7710UL, 0x007E5D47UL, 0x007E3E93UL, 0x007E1959UL, 0x007DEB2CUL,
+ 0x007DB036UL, 0x007D6203UL, 0x007CF4B9UL, 0x007C4FD2UL, 0x007B3630UL,
+ 0x0078D2D2UL};
+
+static const float wi_float[] = {
+ 4.66198677960027669255e-07f, 2.56588335019207033255e-08f,
+ 3.41146697750176784592e-08f, 4.00230311410932959821e-08f,
+ 4.47179475877737745459e-08f, 4.86837785973537366722e-08f,
+ 5.21562578925932412861e-08f, 5.52695199001886257153e-08f,
+ 5.81078488992733116465e-08f, 6.07279932024587421409e-08f,
+ 6.31701613261172047795e-08f, 6.54639842900233842742e-08f,
+ 6.76319905583641815324e-08f, 6.96917493470166688656e-08f,
+ 7.16572544283857476692e-08f, 7.35398519048393832969e-08f,
+ 7.53488822443557479279e-08f, 7.70921367281667127885e-08f,
+ 7.87761895947956022626e-08f, 8.04066446825615346857e-08f,
+ 8.19883218760237408659e-08f, 8.35254002936857088917e-08f,
+ 8.50215298165053411740e-08f, 8.64799190652369040985e-08f,
+ 8.79034055989140110861e-08f, 8.92945125124233511541e-08f,
+ 9.06554945027956262312e-08f, 9.19883756905278607229e-08f,
+ 9.32949809202232869780e-08f, 9.45769618559625849039e-08f,
+ 9.58358188855612866442e-08f, 9.70729196232813152662e-08f,
+ 9.82895146313061088986e-08f, 9.94867508514382224721e-08f,
+ 1.00665683139461669691e-07f, 1.01827284217853923044e-07f,
+ 1.02972453302539369464e-07f, 1.04102023612124921572e-07f,
+ 1.05216768930574060431e-07f, 1.06317409364335657741e-07f,
+ 1.07404616410877866490e-07f, 1.08479017436113134283e-07f,
+ 1.09541199642370962438e-07f, 1.10591713595628691212e-07f,
+ 1.11631076370069356306e-07f, 1.12659774359245895023e-07f,
+ 1.13678265795837113569e-07f, 1.14686983015899673063e-07f,
+ 1.15686334498432158725e-07f, 1.16676706706789039179e-07f,
+ 1.17658465754873988919e-07f, 1.18631958917986203582e-07f,
+ 1.19597516005596215528e-07f, 1.20555450611113917226e-07f,
+ 1.21506061251817163689e-07f, 1.22449632410483948386e-07f,
+ 1.23386435488872536840e-07f, 1.24316729681986364321e-07f,
+ 1.25240762781015530062e-07f, 1.26158771911939892267e-07f,
+ 1.27070984215989333455e-07f, 1.27977617477468922011e-07f,
+ 1.28878880703854958297e-07f, 1.29774974662539874521e-07f,
+ 1.30666092378141980504e-07f, 1.31552419593887221722e-07f,
+ 1.32434135200211397569e-07f, 1.33311411633413359243e-07f,
+ 1.34184415246907777059e-07f, 1.35053306657377859830e-07f,
+ 1.35918241067904315860e-07f, 1.36779368569952053923e-07f,
+ 1.37636834425917531047e-07f, 1.38490779333783508675e-07f,
+ 1.39341339675287344817e-07f, 1.40188647748881762555e-07f,
+ 1.41032831988654882776e-07f, 1.41874017170273235693e-07f,
+ 1.42712324604921442006e-07f, 1.43547872322127921816e-07f,
+ 1.44380775242292721080e-07f, 1.45211145339665544509e-07f,
+ 1.46039091796461362146e-07f, 1.46864721148745476208e-07f,
+ 1.47688137424670065700e-07f, 1.48509442275598857119e-07f,
+ 1.49328735100614641423e-07f, 1.50146113164867617390e-07f,
+ 1.50961671712187416111e-07f, 1.51775504072350982845e-07f,
+ 1.52587701763369746341e-07f, 1.53398354589133671168e-07f,
+ 1.54207550732725568797e-07f, 1.55015376845697999657e-07f,
+ 1.55821918133584372604e-07f, 1.56627258437898192833e-07f,
+ 1.57431480314857468671e-07f, 1.58234665111056041043e-07f,
+ 1.59036893036289199880e-07f, 1.59838243233728855017e-07f,
+ 1.60638793847630850137e-07f, 1.61438622088746393909e-07f,
+ 1.62237804297600106296e-07f, 1.63036416005787357730e-07f,
+ 1.63834531995435479082e-07f, 1.64632226356965902954e-07f,
+ 1.65429572545287097020e-07f, 1.66226643434541294491e-07f,
+ 1.67023511371523209274e-07f, 1.67820248227882200051e-07f,
+ 1.68616925451215588827e-07f, 1.69413614115155757272e-07f,
+ 1.70210384968549673733e-07f, 1.71007308483826142122e-07f,
+ 1.71804454904642543391e-07f, 1.72601894292900061024e-07f,
+ 1.73399696575213681990e-07f, 1.74197931588920988271e-07f,
+ 1.74996669127712165834e-07f, 1.75795978986961275677e-07f,
+ 1.76595931008838063924e-07f, 1.77396595127278238022e-07f,
+ 1.78198041412889183130e-07f, 1.79000340117867431104e-07f,
+ 1.79803561721004406185e-07f, 1.80607776972855859813e-07f,
+ 1.81413056941151359868e-07f, 1.82219473056520464354e-07f,
+ 1.83027097158612474240e-07f, 1.83836001542687613069e-07f,
+ 1.84646259006759307383e-07f, 1.85457942899367347876e-07f,
+ 1.86271127168064649331e-07f, 1.87085886408701333260e-07f,
+ 1.87902295915592424729e-07f, 1.88720431732658022414e-07f,
+ 1.89540370705627262627e-07f, 1.90362190535400839128e-07f,
+ 1.91185969832669990437e-07f, 1.92011788173893651535e-07f,
+ 1.92839726158739913768e-07f, 1.93669865469102145482e-07f,
+ 1.94502288929804890433e-07f, 1.95337080571120616772e-07f,
+ 1.96174325693223683314e-07f, 1.97014110932714374919e-07f,
+ 1.97856524331352952716e-07f, 1.98701655407150388211e-07f,
+ 1.99549595227971635348e-07f, 2.00400436487814600236e-07f,
+ 2.01254273585938820883e-07f, 2.02111202709026498408e-07f,
+ 2.02971321916571014951e-07f, 2.03834731229698846698e-07f,
+ 2.04701532723644121196e-07f, 2.05571830624108885378e-07f,
+ 2.06445731407757185541e-07f, 2.07323343907107312957e-07f,
+ 2.08204779420104330037e-07f, 2.09090151824673600213e-07f,
+ 2.09979577698577670508e-07f, 2.10873176444920111011e-07f,
+ 2.11771070423665379388e-07f, 2.12673385089569268965e-07f,
+ 2.13580249136944118603e-07f, 2.14491794651713402832e-07f,
+ 2.15408157271244625533e-07f, 2.16329476352486921685e-07f,
+ 2.17255895148978920488e-07f, 2.18187560997337924713e-07f,
+ 2.19124625513888206785e-07f, 2.20067244802139479285e-07f,
+ 2.21015579671883851683e-07f, 2.21969795870742159701e-07f,
+ 2.22930064329060010376e-07f, 2.23896561419128954210e-07f,
+ 2.24869469229791575583e-07f, 2.25848975857580322189e-07f,
+ 2.26835275715640744118e-07f, 2.27828569861799901001e-07f,
+ 2.28829066347263833069e-07f, 2.29836980587561823183e-07f,
+ 2.30852535757505260518e-07f, 2.31875963212094114516e-07f,
+ 2.32907502935486642699e-07f, 2.33947404020352726160e-07f,
+ 2.34995925180156140289e-07f, 2.36053335297164516378e-07f,
+ 2.37119914009265667728e-07f, 2.38195952338983970691e-07f,
+ 2.39281753368440712742e-07f, 2.40377632964396957621e-07f,
+ 2.41483920557958384709e-07f, 2.42600959984018662258e-07f,
+ 2.43729110386077326413e-07f, 2.44868747192698939290e-07f,
+ 2.46020263172594533433e-07f, 2.47184069576113545901e-07f,
+ 2.48360597371852893654e-07f, 2.49550298588131851232e-07f,
+ 2.50753647770270890721e-07f, 2.51971143565970967140e-07f,
+ 2.53203310452642767375e-07f, 2.54450700622322097890e-07f,
+ 2.55713896041856770961e-07f, 2.56993510708419870887e-07f,
+ 2.58290193123138874550e-07f, 2.59604629008804833146e-07f,
+ 2.60937544301314385690e-07f, 2.62289708448800566945e-07f,
+ 2.63661938057441759882e-07f, 2.65055100928844238758e-07f,
+ 2.66470120540847889467e-07f, 2.67907981031821866252e-07f,
+ 2.69369732758258246335e-07f, 2.70856498507068313229e-07f,
+ 2.72369480457841388042e-07f, 2.73909968006952220135e-07f,
+ 2.75479346585437289399e-07f, 2.77079107626811561009e-07f,
+ 2.78710859870496796972e-07f, 2.80376342222588603820e-07f,
+ 2.82077438439999912690e-07f, 2.83816193958769527230e-07f,
+ 2.85594835255375795814e-07f, 2.87415792215003905739e-07f,
+ 2.89281724087851835900e-07f, 2.91195549750371467233e-07f,
+ 2.93160483161771875581e-07f, 2.95180075129332912389e-07f,
+ 2.97258262785797916083e-07f, 2.99399428561531794298e-07f,
+ 3.01608470935804138388e-07f, 3.03890889921758510417e-07f,
+ 3.06252891144972267537e-07f, 3.08701513613258141075e-07f,
+ 3.11244787989714509378e-07f, 3.13891934589336184321e-07f,
+ 3.16653613755314681314e-07f, 3.19542246256559459667e-07f,
+ 3.22572428717978242099e-07f, 3.25761480217458181578e-07f,
+ 3.29130173358915628534e-07f, 3.32703730345002116955e-07f,
+ 3.36513208964639108346e-07f, 3.40597478255417943913e-07f,
+ 3.45006114675213401550e-07f, 3.49803789521323211592e-07f,
+ 3.55077180848341416206e-07f, 3.60946392031859609868e-07f,
+ 3.67584959507244041831e-07f, 3.75257645787954431030e-07f,
+ 3.84399301057791926300e-07f, 3.95804015855768440983e-07f,
+ 4.11186015434435801956e-07f, 4.35608969373823260746e-07f};
+
+static const float fi_float[] = {
+ 1.00000000000000000000e+00f, 9.77101701267671596263e-01f,
+ 9.59879091800106665211e-01f, 9.45198953442299649730e-01f,
+ 9.32060075959230460718e-01f, 9.19991505039347012840e-01f,
+ 9.08726440052130879366e-01f, 8.98095921898343418910e-01f,
+ 8.87984660755833377088e-01f, 8.78309655808917399966e-01f,
+ 8.69008688036857046555e-01f, 8.60033621196331532488e-01f,
+ 8.51346258458677951353e-01f, 8.42915653112204177333e-01f,
+ 8.34716292986883434679e-01f, 8.26726833946221373317e-01f,
+ 8.18929191603702366642e-01f, 8.11307874312656274185e-01f,
+ 8.03849483170964274059e-01f, 7.96542330422958966274e-01f,
+ 7.89376143566024590648e-01f, 7.82341832654802504798e-01f,
+ 7.75431304981187174974e-01f, 7.68637315798486264740e-01f,
+ 7.61953346836795386565e-01f, 7.55373506507096115214e-01f,
+ 7.48892447219156820459e-01f, 7.42505296340151055290e-01f,
+ 7.36207598126862650112e-01f, 7.29995264561476231435e-01f,
+ 7.23864533468630222401e-01f, 7.17811932630721960535e-01f,
+ 7.11834248878248421200e-01f, 7.05928501332754310127e-01f,
+ 7.00091918136511615067e-01f, 6.94321916126116711609e-01f,
+ 6.88616083004671808432e-01f, 6.82972161644994857355e-01f,
+ 6.77388036218773526009e-01f, 6.71861719897082099173e-01f,
+ 6.66391343908750100056e-01f, 6.60975147776663107813e-01f,
+ 6.55611470579697264149e-01f, 6.50298743110816701574e-01f,
+ 6.45035480820822293424e-01f, 6.39820277453056585060e-01f,
+ 6.34651799287623608059e-01f, 6.29528779924836690007e-01f,
+ 6.24450015547026504592e-01f, 6.19414360605834324325e-01f,
+ 6.14420723888913888899e-01f, 6.09468064925773433949e-01f,
+ 6.04555390697467776029e-01f, 5.99681752619125263415e-01f,
+ 5.94846243767987448159e-01f, 5.90047996332826008015e-01f,
+ 5.85286179263371453274e-01f, 5.80559996100790898232e-01f,
+ 5.75868682972353718164e-01f, 5.71211506735253227163e-01f,
+ 5.66587763256164445025e-01f, 5.61996775814524340831e-01f,
+ 5.57437893618765945014e-01f, 5.52910490425832290562e-01f,
+ 5.48413963255265812791e-01f, 5.43947731190026262382e-01f,
+ 5.39511234256952132426e-01f, 5.35103932380457614215e-01f,
+ 5.30725304403662057062e-01f, 5.26374847171684479008e-01f,
+ 5.22052074672321841931e-01f, 5.17756517229756352272e-01f,
+ 5.13487720747326958914e-01f, 5.09245245995747941592e-01f,
+ 5.05028667943468123624e-01f, 5.00837575126148681903e-01f,
+ 4.96671569052489714213e-01f, 4.92530263643868537748e-01f,
+ 4.88413284705458028423e-01f, 4.84320269426683325253e-01f,
+ 4.80250865909046753544e-01f, 4.76204732719505863248e-01f,
+ 4.72181538467730199660e-01f, 4.68180961405693596422e-01f,
+ 4.64202689048174355069e-01f, 4.60246417812842867345e-01f,
+ 4.56311852678716434184e-01f, 4.52398706861848520777e-01f,
+ 4.48506701507203064949e-01f, 4.44635565395739396077e-01f,
+ 4.40785034665803987508e-01f, 4.36954852547985550526e-01f,
+ 4.33144769112652261445e-01f, 4.29354541029441427735e-01f,
+ 4.25583931338021970170e-01f, 4.21832709229495894654e-01f,
+ 4.18100649837848226120e-01f, 4.14387534040891125642e-01f,
+ 4.10693148270188157500e-01f, 4.07017284329473372217e-01f,
+ 4.03359739221114510510e-01f, 3.99720314980197222177e-01f,
+ 3.96098818515832451492e-01f, 3.92495061459315619512e-01f,
+ 3.88908860018788715696e-01f, 3.85340034840077283462e-01f,
+ 3.81788410873393657674e-01f, 3.78253817245619183840e-01f,
+ 3.74736087137891138443e-01f, 3.71235057668239498696e-01f,
+ 3.67750569779032587814e-01f, 3.64282468129004055601e-01f,
+ 3.60830600989648031529e-01f, 3.57394820145780500731e-01f,
+ 3.53974980800076777232e-01f, 3.50570941481406106455e-01f,
+ 3.47182563956793643900e-01f, 3.43809713146850715049e-01f,
+ 3.40452257044521866547e-01f, 3.37110066637006045021e-01f,
+ 3.33783015830718454708e-01f, 3.30470981379163586400e-01f,
+ 3.27173842813601400970e-01f, 3.23891482376391093290e-01f,
+ 3.20623784956905355514e-01f, 3.17370638029913609834e-01f,
+ 3.14131931596337177215e-01f, 3.10907558126286509559e-01f,
+ 3.07697412504292056035e-01f, 3.04501391976649993243e-01f,
+ 3.01319396100803049698e-01f, 2.98151326696685481377e-01f,
+ 2.94997087799961810184e-01f, 2.91856585617095209972e-01f,
+ 2.88729728482182923521e-01f, 2.85616426815501756042e-01f,
+ 2.82516593083707578948e-01f, 2.79430141761637940157e-01f,
+ 2.76356989295668320494e-01f, 2.73297054068577072172e-01f,
+ 2.70250256365875463072e-01f, 2.67216518343561471038e-01f,
+ 2.64195763997261190426e-01f, 2.61187919132721213522e-01f,
+ 2.58192911337619235290e-01f, 2.55210669954661961700e-01f,
+ 2.52241126055942177508e-01f, 2.49284212418528522415e-01f,
+ 2.46339863501263828249e-01f, 2.43408015422750312329e-01f,
+ 2.40488605940500588254e-01f, 2.37581574431238090606e-01f,
+ 2.34686861872330010392e-01f, 2.31804410824338724684e-01f,
+ 2.28934165414680340644e-01f, 2.26076071322380278694e-01f,
+ 2.23230075763917484855e-01f, 2.20396127480151998723e-01f,
+ 2.17574176724331130872e-01f, 2.14764175251173583536e-01f,
+ 2.11966076307030182324e-01f, 2.09179834621125076977e-01f,
+ 2.06405406397880797353e-01f, 2.03642749310334908452e-01f,
+ 2.00891822494656591136e-01f, 1.98152586545775138971e-01f,
+ 1.95425003514134304483e-01f, 1.92709036903589175926e-01f,
+ 1.90004651670464985713e-01f, 1.87311814223800304768e-01f,
+ 1.84630492426799269756e-01f, 1.81960655599522513892e-01f,
+ 1.79302274522847582272e-01f, 1.76655321443734858455e-01f,
+ 1.74019770081838553999e-01f, 1.71395595637505754327e-01f,
+ 1.68782774801211288285e-01f, 1.66181285764481906364e-01f,
+ 1.63591108232365584074e-01f, 1.61012223437511009516e-01f,
+ 1.58444614155924284882e-01f, 1.55888264724479197465e-01f,
+ 1.53343161060262855866e-01f, 1.50809290681845675763e-01f,
+ 1.48286642732574552861e-01f, 1.45775208005994028060e-01f,
+ 1.43274978973513461566e-01f, 1.40785949814444699690e-01f,
+ 1.38308116448550733057e-01f, 1.35841476571253755301e-01f,
+ 1.33386029691669155683e-01f, 1.30941777173644358090e-01f,
+ 1.28508722279999570981e-01f, 1.26086870220185887081e-01f,
+ 1.23676228201596571932e-01f, 1.21276805484790306533e-01f,
+ 1.18888613442910059947e-01f, 1.16511665625610869035e-01f,
+ 1.14145977827838487895e-01f, 1.11791568163838089811e-01f,
+ 1.09448457146811797824e-01f, 1.07116667774683801961e-01f,
+ 1.04796225622487068629e-01f, 1.02487158941935246892e-01f,
+ 1.00189498768810017482e-01f, 9.79032790388624646338e-02f,
+ 9.56285367130089991594e-02f, 9.33653119126910124859e-02f,
+ 9.11136480663737591268e-02f, 8.88735920682758862021e-02f,
+ 8.66451944505580717859e-02f, 8.44285095703534715916e-02f,
+ 8.22235958132029043366e-02f, 8.00305158146630696292e-02f,
+ 7.78493367020961224423e-02f, 7.56801303589271778804e-02f,
+ 7.35229737139813238622e-02f, 7.13779490588904025339e-02f,
+ 6.92451443970067553879e-02f, 6.71246538277884968737e-02f,
+ 6.50165779712428976156e-02f, 6.29210244377581412456e-02f,
+ 6.08381083495398780614e-02f, 5.87679529209337372930e-02f,
+ 5.67106901062029017391e-02f, 5.46664613248889208474e-02f,
+ 5.26354182767921896513e-02f, 5.06177238609477817000e-02f,
+ 4.86135532158685421122e-02f, 4.66230949019303814174e-02f,
+ 4.46465522512944634759e-02f, 4.26841449164744590750e-02f,
+ 4.07361106559409394401e-02f, 3.88027074045261474722e-02f,
+ 3.68842156885673053135e-02f, 3.49809414617161251737e-02f,
+ 3.30932194585785779961e-02f, 3.12214171919203004046e-02f,
+ 2.93659397581333588001e-02f, 2.75272356696031131329e-02f,
+ 2.57058040085489103443e-02f, 2.39022033057958785407e-02f,
+ 2.21170627073088502113e-02f, 2.03510962300445102935e-02f,
+ 1.86051212757246224594e-02f, 1.68800831525431419000e-02f,
+ 1.51770883079353092332e-02f, 1.34974506017398673818e-02f,
+ 1.18427578579078790488e-02f, 1.02149714397014590439e-02f,
+ 8.61658276939872638800e-03f, 7.05087547137322242369e-03f,
+ 5.52240329925099155545e-03f, 4.03797259336302356153e-03f,
+ 2.60907274610215926189e-03f, 1.26028593049859797236e-03f};
+
+static const uint64_t ke_double[] = {
+ 0x001C5214272497C6, 0x0000000000000000, 0x00137D5BD79C317E,
+ 0x00186EF58E3F3C10, 0x001A9BB7320EB0AE, 0x001BD127F719447C,
+ 0x001C951D0F88651A, 0x001D1BFE2D5C3972, 0x001D7E5BD56B18B2,
+ 0x001DC934DD172C70, 0x001E0409DFAC9DC8, 0x001E337B71D47836,
+ 0x001E5A8B177CB7A2, 0x001E7B42096F046C, 0x001E970DAF08AE3E,
+ 0x001EAEF5B14EF09E, 0x001EC3BD07B46556, 0x001ED5F6F08799CE,
+ 0x001EE614AE6E5688, 0x001EF46ECA361CD0, 0x001F014B76DDD4A4,
+ 0x001F0CE313A796B6, 0x001F176369F1F77A, 0x001F20F20C452570,
+ 0x001F29AE1951A874, 0x001F31B18FB95532, 0x001F39125157C106,
+ 0x001F3FE2EB6E694C, 0x001F463332D788FA, 0x001F4C10BF1D3A0E,
+ 0x001F51874C5C3322, 0x001F56A109C3ECC0, 0x001F5B66D9099996,
+ 0x001F5FE08210D08C, 0x001F6414DD445772, 0x001F6809F6859678,
+ 0x001F6BC52A2B02E6, 0x001F6F4B3D32E4F4, 0x001F72A07190F13A,
+ 0x001F75C8974D09D6, 0x001F78C71B045CC0, 0x001F7B9F12413FF4,
+ 0x001F7E5346079F8A, 0x001F80E63BE21138, 0x001F835A3DAD9162,
+ 0x001F85B16056B912, 0x001F87ED89B24262, 0x001F8A10759374FA,
+ 0x001F8C1BBA3D39AC, 0x001F8E10CC45D04A, 0x001F8FF102013E16,
+ 0x001F91BD968358E0, 0x001F9377AC47AFD8, 0x001F95204F8B64DA,
+ 0x001F96B878633892, 0x001F98410C968892, 0x001F99BAE146BA80,
+ 0x001F9B26BC697F00, 0x001F9C85561B717A, 0x001F9DD759CFD802,
+ 0x001F9F1D6761A1CE, 0x001FA058140936C0, 0x001FA187EB3A3338,
+ 0x001FA2AD6F6BC4FC, 0x001FA3C91ACE0682, 0x001FA4DB5FEE6AA2,
+ 0x001FA5E4AA4D097C, 0x001FA6E55EE46782, 0x001FA7DDDCA51EC4,
+ 0x001FA8CE7CE6A874, 0x001FA9B793CE5FEE, 0x001FAA9970ADB858,
+ 0x001FAB745E588232, 0x001FAC48A3740584, 0x001FAD1682BF9FE8,
+ 0x001FADDE3B5782C0, 0x001FAEA008F21D6C, 0x001FAF5C2418B07E,
+ 0x001FB012C25B7A12, 0x001FB0C41681DFF4, 0x001FB17050B6F1FA,
+ 0x001FB2179EB2963A, 0x001FB2BA2BDFA84A, 0x001FB358217F4E18,
+ 0x001FB3F1A6C9BE0C, 0x001FB486E10CACD6, 0x001FB517F3C793FC,
+ 0x001FB5A500C5FDAA, 0x001FB62E2837FE58, 0x001FB6B388C9010A,
+ 0x001FB7353FB50798, 0x001FB7B368DC7DA8, 0x001FB82E1ED6BA08,
+ 0x001FB8A57B0347F6, 0x001FB919959A0F74, 0x001FB98A85BA7204,
+ 0x001FB9F861796F26, 0x001FBA633DEEE286, 0x001FBACB2F41EC16,
+ 0x001FBB3048B49144, 0x001FBB929CAEA4E2, 0x001FBBF23CC8029E,
+ 0x001FBC4F39D22994, 0x001FBCA9A3E140D4, 0x001FBD018A548F9E,
+ 0x001FBD56FBDE729C, 0x001FBDAA068BD66A, 0x001FBDFAB7CB3F40,
+ 0x001FBE491C7364DE, 0x001FBE9540C9695E, 0x001FBEDF3086B128,
+ 0x001FBF26F6DE6174, 0x001FBF6C9E828AE2, 0x001FBFB031A904C4,
+ 0x001FBFF1BA0FFDB0, 0x001FC03141024588, 0x001FC06ECF5B54B2,
+ 0x001FC0AA6D8B1426, 0x001FC0E42399698A, 0x001FC11BF9298A64,
+ 0x001FC151F57D1942, 0x001FC1861F770F4A, 0x001FC1B87D9E74B4,
+ 0x001FC1E91620EA42, 0x001FC217EED505DE, 0x001FC2450D3C83FE,
+ 0x001FC27076864FC2, 0x001FC29A2F90630E, 0x001FC2C23CE98046,
+ 0x001FC2E8A2D2C6B4, 0x001FC30D654122EC, 0x001FC33087DE9C0E,
+ 0x001FC3520E0B7EC6, 0x001FC371FADF66F8, 0x001FC390512A2886,
+ 0x001FC3AD137497FA, 0x001FC3C844013348, 0x001FC3E1E4CCAB40,
+ 0x001FC3F9F78E4DA8, 0x001FC4107DB85060, 0x001FC4257877FD68,
+ 0x001FC438E8B5BFC6, 0x001FC44ACF15112A, 0x001FC45B2BF447E8,
+ 0x001FC469FF6C4504, 0x001FC477495001B2, 0x001FC483092BFBB8,
+ 0x001FC48D3E457FF6, 0x001FC495E799D21A, 0x001FC49D03DD30B0,
+ 0x001FC4A29179B432, 0x001FC4A68E8E07FC, 0x001FC4A8F8EBFB8C,
+ 0x001FC4A9CE16EA9E, 0x001FC4A90B41FA34, 0x001FC4A6AD4E28A0,
+ 0x001FC4A2B0C82E74, 0x001FC49D11E62DE2, 0x001FC495CC852DF4,
+ 0x001FC48CDC265EC0, 0x001FC4823BEC237A, 0x001FC475E696DEE6,
+ 0x001FC467D6817E82, 0x001FC458059DC036, 0x001FC4466D702E20,
+ 0x001FC433070BCB98, 0x001FC41DCB0D6E0E, 0x001FC406B196BBF6,
+ 0x001FC3EDB248CB62, 0x001FC3D2C43E593C, 0x001FC3B5DE0591B4,
+ 0x001FC396F599614C, 0x001FC376005A4592, 0x001FC352F3069370,
+ 0x001FC32DC1B22818, 0x001FC3065FBD7888, 0x001FC2DCBFCBF262,
+ 0x001FC2B0D3B99F9E, 0x001FC2828C8FFCF0, 0x001FC251DA79F164,
+ 0x001FC21EACB6D39E, 0x001FC1E8F18C6756, 0x001FC1B09637BB3C,
+ 0x001FC17586DCCD10, 0x001FC137AE74D6B6, 0x001FC0F6F6BB2414,
+ 0x001FC0B348184DA4, 0x001FC06C898BAFF0, 0x001FC022A092F364,
+ 0x001FBFD5710F72B8, 0x001FBF84DD29488E, 0x001FBF30C52FC60A,
+ 0x001FBED907770CC6, 0x001FBE7D80327DDA, 0x001FBE1E094BA614,
+ 0x001FBDBA7A354408, 0x001FBD52A7B9F826, 0x001FBCE663C6201A,
+ 0x001FBC757D2C4DE4, 0x001FBBFFBF63B7AA, 0x001FBB84F23FE6A2,
+ 0x001FBB04D9A0D18C, 0x001FBA7F351A70AC, 0x001FB9F3BF92B618,
+ 0x001FB9622ED4ABFC, 0x001FB8CA33174A16, 0x001FB82B76765B54,
+ 0x001FB7859C5B895C, 0x001FB6D840D55594, 0x001FB622F7D96942,
+ 0x001FB5654C6F37E0, 0x001FB49EBFBF69D2, 0x001FB3CEC803E746,
+ 0x001FB2F4CF539C3E, 0x001FB21032442852, 0x001FB1203E5A9604,
+ 0x001FB0243042E1C2, 0x001FAF1B31C479A6, 0x001FAE045767E104,
+ 0x001FACDE9DBF2D72, 0x001FABA8E640060A, 0x001FAA61F399FF28,
+ 0x001FA908656F66A2, 0x001FA79AB3508D3C, 0x001FA61726D1F214,
+ 0x001FA47BD48BEA00, 0x001FA2C693C5C094, 0x001FA0F4F47DF314,
+ 0x001F9F04336BBE0A, 0x001F9CF12B79F9BC, 0x001F9AB84415ABC4,
+ 0x001F98555B782FB8, 0x001F95C3ABD03F78, 0x001F92FDA9CEF1F2,
+ 0x001F8FFCDA9AE41C, 0x001F8CB99E7385F8, 0x001F892AEC479606,
+ 0x001F8545F904DB8E, 0x001F80FDC336039A, 0x001F7C427839E926,
+ 0x001F7700A3582ACC, 0x001F71200F1A241C, 0x001F6A8234B7352A,
+ 0x001F630000A8E266, 0x001F5A66904FE3C4, 0x001F50724ECE1172,
+ 0x001F44C7665C6FDA, 0x001F36E5A38A59A2, 0x001F26143450340A,
+ 0x001F113E047B0414, 0x001EF6AEFA57CBE6, 0x001ED38CA188151E,
+ 0x001EA2A61E122DB0, 0x001E5961C78B267C, 0x001DDDF62BAC0BB0,
+ 0x001CDB4DD9E4E8C0};
+
+static const double we_double[] = {
+ 9.655740063209182975e-16, 7.089014243955414331e-18,
+ 1.163941249669122378e-17, 1.524391512353216015e-17,
+ 1.833284885723743916e-17, 2.108965109464486630e-17,
+ 2.361128077843138196e-17, 2.595595772310893952e-17,
+ 2.816173554197752338e-17, 3.025504130321382330e-17,
+ 3.225508254836375280e-17, 3.417632340185027033e-17,
+ 3.602996978734452488e-17, 3.782490776869649048e-17,
+ 3.956832198097553231e-17, 4.126611778175946428e-17,
+ 4.292321808442525631e-17, 4.454377743282371417e-17,
+ 4.613133981483185932e-17, 4.768895725264635940e-17,
+ 4.921928043727962847e-17, 5.072462904503147014e-17,
+ 5.220704702792671737e-17, 5.366834661718192181e-17,
+ 5.511014372835094717e-17, 5.653388673239667134e-17,
+ 5.794088004852766616e-17, 5.933230365208943081e-17,
+ 6.070922932847179572e-17, 6.207263431163193485e-17,
+ 6.342341280303076511e-17, 6.476238575956142121e-17,
+ 6.609030925769405241e-17, 6.740788167872722244e-17,
+ 6.871574991183812442e-17, 7.001451473403929616e-17,
+ 7.130473549660643409e-17, 7.258693422414648352e-17,
+ 7.386159921381791997e-17, 7.512918820723728089e-17,
+ 7.639013119550825792e-17, 7.764483290797848102e-17,
+ 7.889367502729790548e-17, 8.013701816675454434e-17,
+ 8.137520364041762206e-17, 8.260855505210038174e-17,
+ 8.383737972539139383e-17, 8.506196999385323132e-17,
+ 8.628260436784112996e-17, 8.749954859216182511e-17,
+ 8.871305660690252281e-17, 8.992337142215357066e-17,
+ 9.113072591597909173e-17, 9.233534356381788123e-17,
+ 9.353743910649128938e-17, 9.473721916312949566e-17,
+ 9.593488279457997317e-17, 9.713062202221521206e-17,
+ 9.832462230649511362e-17, 9.951706298915071878e-17,
+ 1.007081177024294931e-16, 1.018979547484694078e-16,
+ 1.030867374515421954e-16, 1.042746244856188556e-16,
+ 1.054617701794576406e-16, 1.066483248011914702e-16,
+ 1.078344348241948498e-16, 1.090202431758350473e-16,
+ 1.102058894705578110e-16, 1.113915102286197502e-16,
+ 1.125772390816567488e-16, 1.137632069661684705e-16,
+ 1.149495423059009298e-16, 1.161363711840218308e-16,
+ 1.173238175059045788e-16, 1.185120031532669434e-16,
+ 1.197010481303465158e-16, 1.208910707027385520e-16,
+ 1.220821875294706151e-16, 1.232745137888415193e-16,
+ 1.244681632985112523e-16, 1.256632486302898513e-16,
+ 1.268598812200397542e-16, 1.280581714730749379e-16,
+ 1.292582288654119552e-16, 1.304601620412028847e-16,
+ 1.316640789066572582e-16, 1.328700867207380889e-16,
+ 1.340782921828999433e-16, 1.352888015181175458e-16,
+ 1.365017205594397770e-16, 1.377171548282880964e-16,
+ 1.389352096127063919e-16, 1.401559900437571538e-16,
+ 1.413796011702485188e-16, 1.426061480319665444e-16,
+ 1.438357357315790180e-16, 1.450684695053687684e-16,
+ 1.463044547929475721e-16, 1.475437973060951633e-16,
+ 1.487866030968626066e-16, 1.500329786250736949e-16,
+ 1.512830308253539427e-16, 1.525368671738125550e-16,
+ 1.537945957544996933e-16, 1.550563253257577148e-16,
+ 1.563221653865837505e-16, 1.575922262431176140e-16,
+ 1.588666190753684151e-16, 1.601454560042916733e-16,
+ 1.614288501593278662e-16, 1.627169157465130500e-16,
+ 1.640097681172717950e-16, 1.653075238380036909e-16,
+ 1.666103007605742067e-16, 1.679182180938228863e-16,
+ 1.692313964762022267e-16, 1.705499580496629830e-16,
+ 1.718740265349031656e-16, 1.732037273081008369e-16,
+ 1.745391874792533975e-16, 1.758805359722491379e-16,
+ 1.772279036068006489e-16, 1.785814231823732619e-16,
+ 1.799412295642463721e-16, 1.813074597718501559e-16,
+ 1.826802530695252266e-16, 1.840597510598587828e-16,
+ 1.854460977797569461e-16, 1.868394397994192684e-16,
+ 1.882399263243892051e-16, 1.896477093008616722e-16,
+ 1.910629435244376536e-16, 1.924857867525243818e-16,
+ 1.939163998205899420e-16, 1.953549467624909132e-16,
+ 1.968015949351037382e-16, 1.982565151475019047e-16,
+ 1.997198817949342081e-16, 2.011918729978734671e-16,
+ 2.026726707464198289e-16, 2.041624610503588774e-16,
+ 2.056614340951917875e-16, 2.071697844044737034e-16,
+ 2.086877110088159721e-16, 2.102154176219292789e-16,
+ 2.117531128241075913e-16, 2.133010102535779087e-16,
+ 2.148593288061663316e-16, 2.164282928437604723e-16,
+ 2.180081324120784027e-16, 2.195990834682870728e-16,
+ 2.212013881190495942e-16, 2.228152948696180545e-16,
+ 2.244410588846308588e-16, 2.260789422613173739e-16,
+ 2.277292143158621037e-16, 2.293921518837311354e-16,
+ 2.310680396348213318e-16, 2.327571704043534613e-16,
+ 2.344598455404957859e-16, 2.361763752697773994e-16,
+ 2.379070790814276700e-16, 2.396522861318623520e-16,
+ 2.414123356706293277e-16, 2.431875774892255956e-16,
+ 2.449783723943070217e-16, 2.467850927069288738e-16,
+ 2.486081227895851719e-16, 2.504478596029557040e-16,
+ 2.523047132944217013e-16, 2.541791078205812227e-16,
+ 2.560714816061770759e-16, 2.579822882420530896e-16,
+ 2.599119972249746917e-16, 2.618610947423924219e-16,
+ 2.638300845054942823e-16, 2.658194886341845120e-16,
+ 2.678298485979525166e-16, 2.698617262169488933e-16,
+ 2.719157047279818500e-16, 2.739923899205814823e-16,
+ 2.760924113487617126e-16, 2.782164236246436081e-16,
+ 2.803651078006983464e-16, 2.825391728480253184e-16,
+ 2.847393572388174091e-16, 2.869664306419817679e-16,
+ 2.892211957417995598e-16, 2.915044901905293183e-16,
+ 2.938171887070028633e-16, 2.961602053345465687e-16,
+ 2.985344958730045276e-16, 3.009410605012618141e-16,
+ 3.033809466085003416e-16, 3.058552518544860874e-16,
+ 3.083651274815310004e-16, 3.109117819034266344e-16,
+ 3.134964845996663118e-16, 3.161205703467105734e-16,
+ 3.187854438219713117e-16, 3.214925846206797361e-16,
+ 3.242435527309451638e-16, 3.270399945182240440e-16,
+ 3.298836492772283149e-16, 3.327763564171671408e-16,
+ 3.357200633553244075e-16, 3.387168342045505162e-16,
+ 3.417688593525636996e-16, 3.448784660453423890e-16,
+ 3.480481301037442286e-16, 3.512804889222979418e-16,
+ 3.545783559224791863e-16, 3.579447366604276541e-16,
+ 3.613828468219060593e-16, 3.648961323764542545e-16,
+ 3.684882922095621322e-16, 3.721633036080207290e-16,
+ 3.759254510416256532e-16, 3.797793587668874387e-16,
+ 3.837300278789213687e-16, 3.877828785607895292e-16,
+ 3.919437984311428867e-16, 3.962191980786774996e-16,
+ 4.006160751056541688e-16, 4.051420882956573177e-16,
+ 4.098056438903062509e-16, 4.146159964290904582e-16,
+ 4.195833672073398926e-16, 4.247190841824385048e-16,
+ 4.300357481667470702e-16, 4.355474314693952008e-16,
+ 4.412699169036069903e-16, 4.472209874259932285e-16,
+ 4.534207798565834480e-16, 4.598922204905932469e-16,
+ 4.666615664711475780e-16, 4.737590853262492027e-16,
+ 4.812199172829237933e-16, 4.890851827392209900e-16,
+ 4.974034236191939753e-16, 5.062325072144159699e-16,
+ 5.156421828878082953e-16, 5.257175802022274839e-16,
+ 5.365640977112021618e-16, 5.483144034258703912e-16,
+ 5.611387454675159622e-16, 5.752606481503331688e-16,
+ 5.909817641652102998e-16, 6.087231416180907671e-16,
+ 6.290979034877557049e-16, 6.530492053564040799e-16,
+ 6.821393079028928626e-16, 7.192444966089361564e-16,
+ 7.706095350032096755e-16, 8.545517038584027421e-16};
+
+static const double fe_double[] = {
+ 1.000000000000000000e+00, 9.381436808621747003e-01,
+ 9.004699299257464817e-01, 8.717043323812035949e-01,
+ 8.477855006239896074e-01, 8.269932966430503241e-01,
+ 8.084216515230083777e-01, 7.915276369724956185e-01,
+ 7.759568520401155522e-01, 7.614633888498962833e-01,
+ 7.478686219851951034e-01, 7.350380924314234843e-01,
+ 7.228676595935720206e-01, 7.112747608050760117e-01,
+ 7.001926550827881623e-01, 6.895664961170779872e-01,
+ 6.793505722647653622e-01, 6.695063167319247333e-01,
+ 6.600008410789997004e-01, 6.508058334145710999e-01,
+ 6.418967164272660897e-01, 6.332519942143660652e-01,
+ 6.248527387036659775e-01, 6.166821809152076561e-01,
+ 6.087253820796220127e-01, 6.009689663652322267e-01,
+ 5.934009016917334289e-01, 5.860103184772680329e-01,
+ 5.787873586028450257e-01, 5.717230486648258170e-01,
+ 5.648091929124001709e-01, 5.580382822625874484e-01,
+ 5.514034165406412891e-01, 5.448982376724396115e-01,
+ 5.385168720028619127e-01, 5.322538802630433219e-01,
+ 5.261042139836197284e-01, 5.200631773682335979e-01,
+ 5.141263938147485613e-01, 5.082897764106428795e-01,
+ 5.025495018413477233e-01, 4.969019872415495476e-01,
+ 4.913438695940325340e-01, 4.858719873418849144e-01,
+ 4.804833639304542103e-01, 4.751751930373773747e-01,
+ 4.699448252839599771e-01, 4.647897562504261781e-01,
+ 4.597076156421376902e-01, 4.546961574746155033e-01,
+ 4.497532511627549967e-01, 4.448768734145485126e-01,
+ 4.400651008423538957e-01, 4.353161032156365740e-01,
+ 4.306281372884588343e-01, 4.259995411430343437e-01,
+ 4.214287289976165751e-01, 4.169141864330028757e-01,
+ 4.124544659971611793e-01, 4.080481831520323954e-01,
+ 4.036940125305302773e-01, 3.993906844752310725e-01,
+ 3.951369818332901573e-01, 3.909317369847971069e-01,
+ 3.867738290841376547e-01, 3.826621814960098344e-01,
+ 3.785957594095807899e-01, 3.745735676159021588e-01,
+ 3.705946484351460013e-01, 3.666580797815141568e-01,
+ 3.627629733548177748e-01, 3.589084729487497794e-01,
+ 3.550937528667874599e-01, 3.513180164374833381e-01,
+ 3.475804946216369817e-01, 3.438804447045024082e-01,
+ 3.402171490667800224e-01, 3.365899140286776059e-01,
+ 3.329980687618089852e-01, 3.294409642641363267e-01,
+ 3.259179723935561879e-01, 3.224284849560891675e-01,
+ 3.189719128449572394e-01, 3.155476852271289490e-01,
+ 3.121552487741795501e-01, 3.087940669345601852e-01,
+ 3.054636192445902565e-01, 3.021634006756935276e-01,
+ 2.988929210155817917e-01, 2.956517042812611962e-01,
+ 2.924392881618925744e-01, 2.892552234896777485e-01,
+ 2.860990737370768255e-01, 2.829704145387807457e-01,
+ 2.798688332369729248e-01, 2.767939284485173568e-01,
+ 2.737453096528029706e-01, 2.707225967990600224e-01,
+ 2.677254199320447947e-01, 2.647534188350622042e-01,
+ 2.618062426893629779e-01, 2.588835497490162285e-01,
+ 2.559850070304153791e-01, 2.531102900156294577e-01,
+ 2.502590823688622956e-01, 2.474310756653276266e-01,
+ 2.446259691318921070e-01, 2.418434693988772144e-01,
+ 2.390832902624491774e-01, 2.363451524570596429e-01,
+ 2.336287834374333461e-01, 2.309339171696274118e-01,
+ 2.282602939307167011e-01, 2.256076601166840667e-01,
+ 2.229757680581201940e-01, 2.203643758433594946e-01,
+ 2.177732471487005272e-01, 2.152021510753786837e-01,
+ 2.126508619929782795e-01, 2.101191593889882581e-01,
+ 2.076068277242220372e-01, 2.051136562938377095e-01,
+ 2.026394390937090173e-01, 2.001839746919112650e-01,
+ 1.977470661050988732e-01, 1.953285206795632167e-01,
+ 1.929281499767713515e-01, 1.905457696631953912e-01,
+ 1.881811994042543179e-01, 1.858342627621971110e-01,
+ 1.835047870977674633e-01, 1.811926034754962889e-01,
+ 1.788975465724783054e-01, 1.766194545904948843e-01,
+ 1.743581691713534942e-01, 1.721135353153200598e-01,
+ 1.698854013025276610e-01, 1.676736186172501919e-01,
+ 1.654780418749360049e-01, 1.632985287519018169e-01,
+ 1.611349399175920349e-01, 1.589871389693142123e-01,
+ 1.568549923693652315e-01, 1.547383693844680830e-01,
+ 1.526371420274428570e-01, 1.505511850010398944e-01,
+ 1.484803756438667910e-01, 1.464245938783449441e-01,
+ 1.443837221606347754e-01, 1.423576454324722018e-01,
+ 1.403462510748624548e-01, 1.383494288635802039e-01,
+ 1.363670709264288572e-01, 1.343990717022136294e-01,
+ 1.324453279013875218e-01, 1.305057384683307731e-01,
+ 1.285802045452281717e-01, 1.266686294375106714e-01,
+ 1.247709185808309612e-01, 1.228869795095451356e-01,
+ 1.210167218266748335e-01, 1.191600571753276827e-01,
+ 1.173168992115555670e-01, 1.154871635786335338e-01,
+ 1.136707678827443141e-01, 1.118676316700562973e-01,
+ 1.100776764051853845e-01, 1.083008254510337970e-01,
+ 1.065370040500016602e-01, 1.047861393065701724e-01,
+ 1.030481601712577161e-01, 1.013229974259536315e-01,
+ 9.961058367063713170e-02, 9.791085331149219917e-02,
+ 9.622374255043279756e-02, 9.454918937605585882e-02,
+ 9.288713355604354127e-02, 9.123751663104015530e-02,
+ 8.960028191003285847e-02, 8.797537446727021759e-02,
+ 8.636274114075691288e-02, 8.476233053236811865e-02,
+ 8.317409300963238272e-02, 8.159798070923741931e-02,
+ 8.003394754231990538e-02, 7.848194920160642130e-02,
+ 7.694194317048050347e-02, 7.541388873405840965e-02,
+ 7.389774699236474620e-02, 7.239348087570873780e-02,
+ 7.090105516237182881e-02, 6.942043649872875477e-02,
+ 6.795159342193660135e-02, 6.649449638533977414e-02,
+ 6.504911778675374900e-02, 6.361543199980733421e-02,
+ 6.219341540854099459e-02, 6.078304644547963265e-02,
+ 5.938430563342026597e-02, 5.799717563120065922e-02,
+ 5.662164128374287675e-02, 5.525768967669703741e-02,
+ 5.390531019604608703e-02, 5.256449459307169225e-02,
+ 5.123523705512628146e-02, 4.991753428270637172e-02,
+ 4.861138557337949667e-02, 4.731679291318154762e-02,
+ 4.603376107617516977e-02, 4.476229773294328196e-02,
+ 4.350241356888818328e-02, 4.225412241331623353e-02,
+ 4.101744138041481941e-02, 3.979239102337412542e-02,
+ 3.857899550307485742e-02, 3.737728277295936097e-02,
+ 3.618728478193142251e-02, 3.500903769739741045e-02,
+ 3.384258215087432992e-02, 3.268796350895953468e-02,
+ 3.154523217289360859e-02, 3.041444391046660423e-02,
+ 2.929566022463739317e-02, 2.818894876397863569e-02,
+ 2.709438378095579969e-02, 2.601204664513421735e-02,
+ 2.494202641973178314e-02, 2.388442051155817078e-02,
+ 2.283933540638524023e-02, 2.180688750428358066e-02,
+ 2.078720407257811723e-02, 1.978042433800974303e-02,
+ 1.878670074469603046e-02, 1.780620041091136169e-02,
+ 1.683910682603994777e-02, 1.588562183997316302e-02,
+ 1.494596801169114850e-02, 1.402039140318193759e-02,
+ 1.310916493125499106e-02, 1.221259242625538123e-02,
+ 1.133101359783459695e-02, 1.046481018102997894e-02,
+ 9.614413642502209895e-03, 8.780314985808975251e-03,
+ 7.963077438017040002e-03, 7.163353183634983863e-03,
+ 6.381905937319179087e-03, 5.619642207205483020e-03,
+ 4.877655983542392333e-03, 4.157295120833795314e-03,
+ 3.460264777836904049e-03, 2.788798793574076128e-03,
+ 2.145967743718906265e-03, 1.536299780301572356e-03,
+ 9.672692823271745359e-04, 4.541343538414967652e-04};
+
+static const uint32_t ke_float[] = {
+ 0x00714851UL, 0x00000000UL, 0x004DF56FUL, 0x0061BBD6UL, 0x006A6EDDUL,
+ 0x006F44A0UL, 0x00725474UL, 0x00746FF9UL, 0x0075F96FUL, 0x007724D3UL,
+ 0x00781027UL, 0x0078CDEEUL, 0x00796A2CUL, 0x0079ED08UL, 0x007A5C37UL,
+ 0x007ABBD7UL, 0x007B0EF4UL, 0x007B57DCUL, 0x007B9853UL, 0x007BD1BBUL,
+ 0x007C052EUL, 0x007C338CUL, 0x007C5D8EUL, 0x007C83C8UL, 0x007CA6B8UL,
+ 0x007CC6C6UL, 0x007CE449UL, 0x007CFF8CUL, 0x007D18CDUL, 0x007D3043UL,
+ 0x007D461DUL, 0x007D5A84UL, 0x007D6D9BUL, 0x007D7F82UL, 0x007D9053UL,
+ 0x007DA028UL, 0x007DAF15UL, 0x007DBD2DUL, 0x007DCA82UL, 0x007DD722UL,
+ 0x007DE31CUL, 0x007DEE7CUL, 0x007DF94DUL, 0x007E0399UL, 0x007E0D69UL,
+ 0x007E16C6UL, 0x007E1FB6UL, 0x007E2842UL, 0x007E306FUL, 0x007E3843UL,
+ 0x007E3FC4UL, 0x007E46F6UL, 0x007E4DDFUL, 0x007E5481UL, 0x007E5AE2UL,
+ 0x007E6104UL, 0x007E66ECUL, 0x007E6C9BUL, 0x007E7215UL, 0x007E775DUL,
+ 0x007E7C76UL, 0x007E8160UL, 0x007E8620UL, 0x007E8AB6UL, 0x007E8F24UL,
+ 0x007E936DUL, 0x007E9793UL, 0x007E9B95UL, 0x007E9F77UL, 0x007EA33AUL,
+ 0x007EA6DEUL, 0x007EAA66UL, 0x007EADD1UL, 0x007EB123UL, 0x007EB45AUL,
+ 0x007EB779UL, 0x007EBA80UL, 0x007EBD71UL, 0x007EC04BUL, 0x007EC310UL,
+ 0x007EC5C1UL, 0x007EC85EUL, 0x007ECAE9UL, 0x007ECD61UL, 0x007ECFC7UL,
+ 0x007ED21CUL, 0x007ED460UL, 0x007ED694UL, 0x007ED8B9UL, 0x007EDACEUL,
+ 0x007EDCD5UL, 0x007EDECEUL, 0x007EE0B8UL, 0x007EE296UL, 0x007EE466UL,
+ 0x007EE62AUL, 0x007EE7E2UL, 0x007EE98DUL, 0x007EEB2DUL, 0x007EECC1UL,
+ 0x007EEE4AUL, 0x007EEFC9UL, 0x007EF13DUL, 0x007EF2A7UL, 0x007EF406UL,
+ 0x007EF55CUL, 0x007EF6A8UL, 0x007EF7EBUL, 0x007EF924UL, 0x007EFA55UL,
+ 0x007EFB7DUL, 0x007EFC9CUL, 0x007EFDB2UL, 0x007EFEC1UL, 0x007EFFC7UL,
+ 0x007F00C5UL, 0x007F01BBUL, 0x007F02AAUL, 0x007F0391UL, 0x007F0470UL,
+ 0x007F0548UL, 0x007F0618UL, 0x007F06E2UL, 0x007F07A4UL, 0x007F0860UL,
+ 0x007F0914UL, 0x007F09C2UL, 0x007F0A69UL, 0x007F0B09UL, 0x007F0BA3UL,
+ 0x007F0C36UL, 0x007F0CC2UL, 0x007F0D48UL, 0x007F0DC8UL, 0x007F0E41UL,
+ 0x007F0EB4UL, 0x007F0F21UL, 0x007F0F88UL, 0x007F0FE8UL, 0x007F1042UL,
+ 0x007F1096UL, 0x007F10E4UL, 0x007F112BUL, 0x007F116DUL, 0x007F11A8UL,
+ 0x007F11DDUL, 0x007F120CUL, 0x007F1235UL, 0x007F1258UL, 0x007F1274UL,
+ 0x007F128AUL, 0x007F129AUL, 0x007F12A4UL, 0x007F12A7UL, 0x007F12A4UL,
+ 0x007F129BUL, 0x007F128BUL, 0x007F1274UL, 0x007F1257UL, 0x007F1233UL,
+ 0x007F1209UL, 0x007F11D8UL, 0x007F119FUL, 0x007F1160UL, 0x007F111AUL,
+ 0x007F10CCUL, 0x007F1077UL, 0x007F101BUL, 0x007F0FB7UL, 0x007F0F4BUL,
+ 0x007F0ED7UL, 0x007F0E5CUL, 0x007F0DD8UL, 0x007F0D4CUL, 0x007F0CB7UL,
+ 0x007F0C19UL, 0x007F0B73UL, 0x007F0AC3UL, 0x007F0A0AUL, 0x007F0947UL,
+ 0x007F087BUL, 0x007F07A4UL, 0x007F06C2UL, 0x007F05D6UL, 0x007F04DFUL,
+ 0x007F03DCUL, 0x007F02CDUL, 0x007F01B2UL, 0x007F008BUL, 0x007EFF56UL,
+ 0x007EFE13UL, 0x007EFCC3UL, 0x007EFB64UL, 0x007EF9F6UL, 0x007EF878UL,
+ 0x007EF6EAUL, 0x007EF54BUL, 0x007EF39AUL, 0x007EF1D6UL, 0x007EEFFFUL,
+ 0x007EEE14UL, 0x007EEC13UL, 0x007EE9FDUL, 0x007EE7CFUL, 0x007EE589UL,
+ 0x007EE329UL, 0x007EE0AEUL, 0x007EDE16UL, 0x007EDB61UL, 0x007ED88CUL,
+ 0x007ED595UL, 0x007ED27BUL, 0x007ECF3BUL, 0x007ECBD3UL, 0x007EC841UL,
+ 0x007EC481UL, 0x007EC091UL, 0x007EBC6DUL, 0x007EB811UL, 0x007EB37AUL,
+ 0x007EAEA4UL, 0x007EA988UL, 0x007EA422UL, 0x007E9E6BUL, 0x007E985DUL,
+ 0x007E91EFUL, 0x007E8B1AUL, 0x007E83D4UL, 0x007E7C11UL, 0x007E73C5UL,
+ 0x007E6AE1UL, 0x007E6155UL, 0x007E570FUL, 0x007E4BF7UL, 0x007E3FF3UL,
+ 0x007E32E6UL, 0x007E24ACUL, 0x007E1518UL, 0x007E03F7UL, 0x007DF10AUL,
+ 0x007DDC03UL, 0x007DC480UL, 0x007DAA09UL, 0x007D8C00UL, 0x007D699AUL,
+ 0x007D41C9UL, 0x007D131EUL, 0x007CDB97UL, 0x007C9851UL, 0x007C44F8UL,
+ 0x007BDABCUL, 0x007B4E33UL, 0x007A8A98UL, 0x00796587UL, 0x007777D9UL,
+ 0x00736D37UL,
+};
+static const float we_float[] = {
+ 1.03677719e-06F, 7.61177108e-09F, 1.24977240e-08F, 1.63680292e-08F,
+ 1.96847466e-08F, 2.26448404e-08F, 2.53524197e-08F, 2.78699974e-08F,
+ 3.02384333e-08F, 3.24861032e-08F, 3.46336312e-08F, 3.66965478e-08F,
+ 3.86868855e-08F, 4.06141855e-08F, 4.24861622e-08F, 4.43091566e-08F,
+ 4.60884545e-08F, 4.78285168e-08F, 4.95331490e-08F, 5.12056279e-08F,
+ 5.28488000e-08F, 5.44651557e-08F, 5.60568899e-08F, 5.76259484e-08F,
+ 5.91740662e-08F, 6.07027987e-08F, 6.22135462e-08F, 6.37075759e-08F,
+ 6.51860386e-08F, 6.66499836e-08F, 6.81003709e-08F, 6.95380822e-08F,
+ 7.09639292e-08F, 7.23786618e-08F, 7.37829746e-08F, 7.51775128e-08F,
+ 7.65628768e-08F, 7.79396272e-08F, 7.93082883e-08F, 8.06693516e-08F,
+ 8.20232788e-08F, 8.33705045e-08F, 8.47114385e-08F, 8.60464681e-08F,
+ 8.73759596e-08F, 8.87002606e-08F, 9.00197010e-08F, 9.13345948e-08F,
+ 9.26452410e-08F, 9.39519249e-08F, 9.52549192e-08F, 9.65544849e-08F,
+ 9.78508719e-08F, 9.91443202e-08F, 1.00435060e-07F, 1.01723315e-07F,
+ 1.03009296e-07F, 1.04293211e-07F, 1.05575259e-07F, 1.06855633e-07F,
+ 1.08134518e-07F, 1.09412096e-07F, 1.10688542e-07F, 1.11964025e-07F,
+ 1.13238713e-07F, 1.14512767e-07F, 1.15786343e-07F, 1.17059595e-07F,
+ 1.18332673e-07F, 1.19605723e-07F, 1.20878890e-07F, 1.22152313e-07F,
+ 1.23426131e-07F, 1.24700479e-07F, 1.25975490e-07F, 1.27251294e-07F,
+ 1.28528022e-07F, 1.29805799e-07F, 1.31084751e-07F, 1.32365001e-07F,
+ 1.33646673e-07F, 1.34929886e-07F, 1.36214760e-07F, 1.37501415e-07F,
+ 1.38789966e-07F, 1.40080532e-07F, 1.41373228e-07F, 1.42668169e-07F,
+ 1.43965470e-07F, 1.45265245e-07F, 1.46567606e-07F, 1.47872669e-07F,
+ 1.49180545e-07F, 1.50491348e-07F, 1.51805191e-07F, 1.53122186e-07F,
+ 1.54442445e-07F, 1.55766083e-07F, 1.57093212e-07F, 1.58423946e-07F,
+ 1.59758399e-07F, 1.61096684e-07F, 1.62438917e-07F, 1.63785214e-07F,
+ 1.65135690e-07F, 1.66490462e-07F, 1.67849647e-07F, 1.69213364e-07F,
+ 1.70581733e-07F, 1.71954874e-07F, 1.73332908e-07F, 1.74715958e-07F,
+ 1.76104148e-07F, 1.77497602e-07F, 1.78896448e-07F, 1.80300814e-07F,
+ 1.81710828e-07F, 1.83126623e-07F, 1.84548331e-07F, 1.85976086e-07F,
+ 1.87410026e-07F, 1.88850288e-07F, 1.90297012e-07F, 1.91750343e-07F,
+ 1.93210424e-07F, 1.94677403e-07F, 1.96151428e-07F, 1.97632653e-07F,
+ 1.99121231e-07F, 2.00617321e-07F, 2.02121082e-07F, 2.03632677e-07F,
+ 2.05152273e-07F, 2.06680040e-07F, 2.08216149e-07F, 2.09760777e-07F,
+ 2.11314104e-07F, 2.12876312e-07F, 2.14447590e-07F, 2.16028129e-07F,
+ 2.17618123e-07F, 2.19217773e-07F, 2.20827283e-07F, 2.22446862e-07F,
+ 2.24076723e-07F, 2.25717086e-07F, 2.27368174e-07F, 2.29030216e-07F,
+ 2.30703448e-07F, 2.32388110e-07F, 2.34084450e-07F, 2.35792720e-07F,
+ 2.37513182e-07F, 2.39246101e-07F, 2.40991752e-07F, 2.42750416e-07F,
+ 2.44522382e-07F, 2.46307948e-07F, 2.48107418e-07F, 2.49921109e-07F,
+ 2.51749342e-07F, 2.53592452e-07F, 2.55450781e-07F, 2.57324683e-07F,
+ 2.59214522e-07F, 2.61120673e-07F, 2.63043524e-07F, 2.64983476e-07F,
+ 2.66940939e-07F, 2.68916342e-07F, 2.70910123e-07F, 2.72922739e-07F,
+ 2.74954660e-07F, 2.77006373e-07F, 2.79078382e-07F, 2.81171210e-07F,
+ 2.83285396e-07F, 2.85421503e-07F, 2.87580110e-07F, 2.89761822e-07F,
+ 2.91967265e-07F, 2.94197089e-07F, 2.96451969e-07F, 2.98732610e-07F,
+ 3.01039742e-07F, 3.03374127e-07F, 3.05736557e-07F, 3.08127859e-07F,
+ 3.10548894e-07F, 3.13000563e-07F, 3.15483804e-07F, 3.17999599e-07F,
+ 3.20548974e-07F, 3.23133003e-07F, 3.25752811e-07F, 3.28409576e-07F,
+ 3.31104534e-07F, 3.33838984e-07F, 3.36614287e-07F, 3.39431878e-07F,
+ 3.42293264e-07F, 3.45200034e-07F, 3.48153864e-07F, 3.51156520e-07F,
+ 3.54209871e-07F, 3.57315892e-07F, 3.60476673e-07F, 3.63694431e-07F,
+ 3.66971518e-07F, 3.70310433e-07F, 3.73713834e-07F, 3.77184553e-07F,
+ 3.80725611e-07F, 3.84340234e-07F, 3.88031877e-07F, 3.91804239e-07F,
+ 3.95661291e-07F, 3.99607304e-07F, 4.03646879e-07F, 4.07784981e-07F,
+ 4.12026980e-07F, 4.16378695e-07F, 4.20846449e-07F, 4.25437124e-07F,
+ 4.30158235e-07F, 4.35018005e-07F, 4.40025460e-07F, 4.45190536e-07F,
+ 4.50524210e-07F, 4.56038644e-07F, 4.61747369e-07F, 4.67665494e-07F,
+ 4.73809965e-07F, 4.80199879e-07F, 4.86856855e-07F, 4.93805512e-07F,
+ 5.01074042e-07F, 5.08694944e-07F, 5.16705952e-07F, 5.25151216e-07F,
+ 5.34082859e-07F, 5.43563016e-07F, 5.53666578e-07F, 5.64484953e-07F,
+ 5.76131313e-07F, 5.88748108e-07F, 6.02518140e-07F, 6.17681418e-07F,
+ 6.34561837e-07F, 6.53611496e-07F, 6.75488730e-07F, 7.01206245e-07F,
+ 7.32441505e-07F, 7.72282898e-07F, 8.27435688e-07F, 9.17567905e-07F,
+};
+static const float fe_float[] = {
+ 1.00000000e+00F, 9.38143681e-01F, 9.00469930e-01F, 8.71704332e-01F,
+ 8.47785501e-01F, 8.26993297e-01F, 8.08421652e-01F, 7.91527637e-01F,
+ 7.75956852e-01F, 7.61463389e-01F, 7.47868622e-01F, 7.35038092e-01F,
+ 7.22867660e-01F, 7.11274761e-01F, 7.00192655e-01F, 6.89566496e-01F,
+ 6.79350572e-01F, 6.69506317e-01F, 6.60000841e-01F, 6.50805833e-01F,
+ 6.41896716e-01F, 6.33251994e-01F, 6.24852739e-01F, 6.16682181e-01F,
+ 6.08725382e-01F, 6.00968966e-01F, 5.93400902e-01F, 5.86010318e-01F,
+ 5.78787359e-01F, 5.71723049e-01F, 5.64809193e-01F, 5.58038282e-01F,
+ 5.51403417e-01F, 5.44898238e-01F, 5.38516872e-01F, 5.32253880e-01F,
+ 5.26104214e-01F, 5.20063177e-01F, 5.14126394e-01F, 5.08289776e-01F,
+ 5.02549502e-01F, 4.96901987e-01F, 4.91343870e-01F, 4.85871987e-01F,
+ 4.80483364e-01F, 4.75175193e-01F, 4.69944825e-01F, 4.64789756e-01F,
+ 4.59707616e-01F, 4.54696157e-01F, 4.49753251e-01F, 4.44876873e-01F,
+ 4.40065101e-01F, 4.35316103e-01F, 4.30628137e-01F, 4.25999541e-01F,
+ 4.21428729e-01F, 4.16914186e-01F, 4.12454466e-01F, 4.08048183e-01F,
+ 4.03694013e-01F, 3.99390684e-01F, 3.95136982e-01F, 3.90931737e-01F,
+ 3.86773829e-01F, 3.82662181e-01F, 3.78595759e-01F, 3.74573568e-01F,
+ 3.70594648e-01F, 3.66658080e-01F, 3.62762973e-01F, 3.58908473e-01F,
+ 3.55093753e-01F, 3.51318016e-01F, 3.47580495e-01F, 3.43880445e-01F,
+ 3.40217149e-01F, 3.36589914e-01F, 3.32998069e-01F, 3.29440964e-01F,
+ 3.25917972e-01F, 3.22428485e-01F, 3.18971913e-01F, 3.15547685e-01F,
+ 3.12155249e-01F, 3.08794067e-01F, 3.05463619e-01F, 3.02163401e-01F,
+ 2.98892921e-01F, 2.95651704e-01F, 2.92439288e-01F, 2.89255223e-01F,
+ 2.86099074e-01F, 2.82970415e-01F, 2.79868833e-01F, 2.76793928e-01F,
+ 2.73745310e-01F, 2.70722597e-01F, 2.67725420e-01F, 2.64753419e-01F,
+ 2.61806243e-01F, 2.58883550e-01F, 2.55985007e-01F, 2.53110290e-01F,
+ 2.50259082e-01F, 2.47431076e-01F, 2.44625969e-01F, 2.41843469e-01F,
+ 2.39083290e-01F, 2.36345152e-01F, 2.33628783e-01F, 2.30933917e-01F,
+ 2.28260294e-01F, 2.25607660e-01F, 2.22975768e-01F, 2.20364376e-01F,
+ 2.17773247e-01F, 2.15202151e-01F, 2.12650862e-01F, 2.10119159e-01F,
+ 2.07606828e-01F, 2.05113656e-01F, 2.02639439e-01F, 2.00183975e-01F,
+ 1.97747066e-01F, 1.95328521e-01F, 1.92928150e-01F, 1.90545770e-01F,
+ 1.88181199e-01F, 1.85834263e-01F, 1.83504787e-01F, 1.81192603e-01F,
+ 1.78897547e-01F, 1.76619455e-01F, 1.74358169e-01F, 1.72113535e-01F,
+ 1.69885401e-01F, 1.67673619e-01F, 1.65478042e-01F, 1.63298529e-01F,
+ 1.61134940e-01F, 1.58987139e-01F, 1.56854992e-01F, 1.54738369e-01F,
+ 1.52637142e-01F, 1.50551185e-01F, 1.48480376e-01F, 1.46424594e-01F,
+ 1.44383722e-01F, 1.42357645e-01F, 1.40346251e-01F, 1.38349429e-01F,
+ 1.36367071e-01F, 1.34399072e-01F, 1.32445328e-01F, 1.30505738e-01F,
+ 1.28580205e-01F, 1.26668629e-01F, 1.24770919e-01F, 1.22886980e-01F,
+ 1.21016722e-01F, 1.19160057e-01F, 1.17316899e-01F, 1.15487164e-01F,
+ 1.13670768e-01F, 1.11867632e-01F, 1.10077676e-01F, 1.08300825e-01F,
+ 1.06537004e-01F, 1.04786139e-01F, 1.03048160e-01F, 1.01322997e-01F,
+ 9.96105837e-02F, 9.79108533e-02F, 9.62237426e-02F, 9.45491894e-02F,
+ 9.28871336e-02F, 9.12375166e-02F, 8.96002819e-02F, 8.79753745e-02F,
+ 8.63627411e-02F, 8.47623305e-02F, 8.31740930e-02F, 8.15979807e-02F,
+ 8.00339475e-02F, 7.84819492e-02F, 7.69419432e-02F, 7.54138887e-02F,
+ 7.38977470e-02F, 7.23934809e-02F, 7.09010552e-02F, 6.94204365e-02F,
+ 6.79515934e-02F, 6.64944964e-02F, 6.50491178e-02F, 6.36154320e-02F,
+ 6.21934154e-02F, 6.07830464e-02F, 5.93843056e-02F, 5.79971756e-02F,
+ 5.66216413e-02F, 5.52576897e-02F, 5.39053102e-02F, 5.25644946e-02F,
+ 5.12352371e-02F, 4.99175343e-02F, 4.86113856e-02F, 4.73167929e-02F,
+ 4.60337611e-02F, 4.47622977e-02F, 4.35024136e-02F, 4.22541224e-02F,
+ 4.10174414e-02F, 3.97923910e-02F, 3.85789955e-02F, 3.73772828e-02F,
+ 3.61872848e-02F, 3.50090377e-02F, 3.38425822e-02F, 3.26879635e-02F,
+ 3.15452322e-02F, 3.04144439e-02F, 2.92956602e-02F, 2.81889488e-02F,
+ 2.70943838e-02F, 2.60120466e-02F, 2.49420264e-02F, 2.38844205e-02F,
+ 2.28393354e-02F, 2.18068875e-02F, 2.07872041e-02F, 1.97804243e-02F,
+ 1.87867007e-02F, 1.78062004e-02F, 1.68391068e-02F, 1.58856218e-02F,
+ 1.49459680e-02F, 1.40203914e-02F, 1.31091649e-02F, 1.22125924e-02F,
+ 1.13310136e-02F, 1.04648102e-02F, 9.61441364e-03F, 8.78031499e-03F,
+ 7.96307744e-03F, 7.16335318e-03F, 6.38190594e-03F, 5.61964221e-03F,
+ 4.87765598e-03F, 4.15729512e-03F, 3.46026478e-03F, 2.78879879e-03F,
+ 2.14596774e-03F, 1.53629978e-03F, 9.67269282e-04F, 4.54134354e-04F,
+};
+
+
+static const double ziggurat_nor_r = 3.6541528853610087963519472518;
+static const double ziggurat_nor_inv_r =
+ 0.27366123732975827203338247596; // 1.0 / ziggurat_nor_r;
+static const double ziggurat_exp_r = 7.6971174701310497140446280481;
+
+static const float ziggurat_nor_r_f = 3.6541528853610087963519472518f;
+static const float ziggurat_nor_inv_r_f = 0.27366123732975827203338247596f;
+static const float ziggurat_exp_r_f = 7.6971174701310497140446280481f;
diff --git a/numpy/random/src/entropy/entropy.c b/numpy/random/src/entropy/entropy.c
new file mode 100644
index 000000000..eaca37a9c
--- /dev/null
+++ b/numpy/random/src/entropy/entropy.c
@@ -0,0 +1,114 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "entropy.h"
+#ifdef _WIN32
+/* Windows */
+#include <sys/timeb.h>
+#include <time.h>
+#include <windows.h>
+
+#include <wincrypt.h>
+#else
+/* Unix */
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+
+bool entropy_getbytes(void *dest, size_t size) {
+#ifndef _WIN32
+
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return false;
+ ssize_t sz = read(fd, dest, size);
+ if ((sz < 0) || ((size_t)sz < size))
+ return false;
+ return close(fd) == 0;
+
+#else
+
+ HCRYPTPROV hCryptProv;
+ BOOL done;
+
+ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT) ||
+ !hCryptProv) {
+ return true;
+ }
+ done = CryptGenRandom(hCryptProv, (DWORD)size, (unsigned char *)dest);
+ CryptReleaseContext(hCryptProv, 0);
+ if (!done) {
+ return false;
+ }
+
+ return true;
+#endif
+}
+
+/* Thomas Wang 32/64 bits integer hash function */
+uint32_t entropy_hash_32(uint32_t key) {
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+
+uint64_t entropy_hash_64(uint64_t key) {
+ key = (~key) + (key << 21); // key = (key << 21) - key - 1;
+ key = key ^ (key >> 24);
+ key = (key + (key << 3)) + (key << 8); // key * 265
+ key = key ^ (key >> 14);
+ key = (key + (key << 2)) + (key << 4); // key * 21
+ key = key ^ (key >> 28);
+ key = key + (key << 31);
+ return key;
+}
+
+uint32_t entropy_randombytes(void) {
+
+#ifndef _WIN32
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return entropy_hash_32(getpid()) ^ entropy_hash_32(tv.tv_sec) ^
+ entropy_hash_32(tv.tv_usec) ^ entropy_hash_32(clock());
+#else
+ uint32_t out = 0;
+ int64_t counter;
+ struct _timeb tv;
+ _ftime_s(&tv);
+ out = entropy_hash_32(GetCurrentProcessId()) ^
+ entropy_hash_32((uint32_t)tv.time) ^ entropy_hash_32(tv.millitm) ^
+ entropy_hash_32(clock());
+ if (QueryPerformanceCounter((LARGE_INTEGER *)&counter) != 0)
+ out ^= entropy_hash_32((uint32_t)(counter & 0xffffffff));
+ return out;
+#endif
+}
+
+bool entropy_fallback_getbytes(void *dest, size_t size) {
+ int hashes = (int)size;
+ uint32_t *hash = malloc(hashes * sizeof(uint32_t));
+ int i;
+ for (i = 0; i < hashes; i++) {
+ hash[i] = entropy_randombytes();
+ }
+ memcpy(dest, (void *)hash, size);
+ free(hash);
+ return true;
+}
+
+void entropy_fill(void *dest, size_t size) {
+ bool success;
+ success = entropy_getbytes(dest, size);
+ if (!success) {
+ entropy_fallback_getbytes(dest, size);
+ }
+}
diff --git a/numpy/random/src/entropy/entropy.h b/numpy/random/src/entropy/entropy.h
new file mode 100644
index 000000000..f00caf61d
--- /dev/null
+++ b/numpy/random/src/entropy/entropy.h
@@ -0,0 +1,14 @@
+#ifndef _RANDOMDGEN__ENTROPY_H_
+#define _RANDOMDGEN__ENTROPY_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+extern void entropy_fill(void *dest, size_t size);
+
+extern bool entropy_getbytes(void *dest, size_t size);
+
+extern bool entropy_fallback_getbytes(void *dest, size_t size);
+
+#endif
diff --git a/numpy/random/src/legacy/legacy-distributions.c b/numpy/random/src/legacy/legacy-distributions.c
new file mode 100644
index 000000000..4741a0352
--- /dev/null
+++ b/numpy/random/src/legacy/legacy-distributions.c
@@ -0,0 +1,361 @@
+#include "legacy-distributions.h"
+
+
+static NPY_INLINE double legacy_double(aug_bitgen_t *aug_state) {
+ return aug_state->bit_generator->next_double(aug_state->bit_generator->state);
+}
+
+double legacy_gauss(aug_bitgen_t *aug_state) {
+ if (aug_state->has_gauss) {
+ const double temp = aug_state->gauss;
+ aug_state->has_gauss = false;
+ aug_state->gauss = 0.0;
+ return temp;
+ } else {
+ double f, x1, x2, r2;
+
+ do {
+ x1 = 2.0 * legacy_double(aug_state) - 1.0;
+ x2 = 2.0 * legacy_double(aug_state) - 1.0;
+ r2 = x1 * x1 + x2 * x2;
+ } while (r2 >= 1.0 || r2 == 0.0);
+
+ /* Polar method, a more efficient version of the Box-Muller approach. */
+ f = sqrt(-2.0 * log(r2) / r2);
+ /* Keep for next call */
+ aug_state->gauss = f * x1;
+ aug_state->has_gauss = true;
+ return f * x2;
+ }
+}
+
+double legacy_standard_exponential(aug_bitgen_t *aug_state) {
+ /* We use -log(1-U) since U is [0, 1) */
+ return -log(1.0 - legacy_double(aug_state));
+}
+
+double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape) {
+ double b, c;
+ double U, V, X, Y;
+
+ if (shape == 1.0) {
+ return legacy_standard_exponential(aug_state);
+ }
+ else if (shape == 0.0) {
+ return 0.0;
+ } else if (shape < 1.0) {
+ for (;;) {
+ U = legacy_double(aug_state);
+ V = legacy_standard_exponential(aug_state);
+ if (U <= 1.0 - shape) {
+ X = pow(U, 1. / shape);
+ if (X <= V) {
+ return X;
+ }
+ } else {
+ Y = -log((1 - U) / shape);
+ X = pow(1.0 - shape + shape * Y, 1. / shape);
+ if (X <= (V + Y)) {
+ return X;
+ }
+ }
+ }
+ } else {
+ b = shape - 1. / 3.;
+ c = 1. / sqrt(9 * b);
+ for (;;) {
+ do {
+ X = legacy_gauss(aug_state);
+ V = 1.0 + c * X;
+ } while (V <= 0.0);
+
+ V = V * V * V;
+ U = legacy_double(aug_state);
+ if (U < 1.0 - 0.0331 * (X * X) * (X * X))
+ return (b * V);
+ if (log(U) < 0.5 * X * X + b * (1. - V + log(V)))
+ return (b * V);
+ }
+ }
+}
+
+double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale) {
+ return scale * legacy_standard_gamma(aug_state, shape);
+}
+
+double legacy_pareto(aug_bitgen_t *aug_state, double a) {
+ return exp(legacy_standard_exponential(aug_state) / a) - 1;
+}
+
+double legacy_weibull(aug_bitgen_t *aug_state, double a) {
+ if (a == 0.0) {
+ return 0.0;
+ }
+ return pow(legacy_standard_exponential(aug_state), 1. / a);
+}
+
+double legacy_power(aug_bitgen_t *aug_state, double a) {
+ return pow(1 - exp(-legacy_standard_exponential(aug_state)), 1. / a);
+}
+
+double legacy_chisquare(aug_bitgen_t *aug_state, double df) {
+ return 2.0 * legacy_standard_gamma(aug_state, df / 2.0);
+}
+
+double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df,
+ double nonc) {
+ double out;
+ if (nonc == 0) {
+ return legacy_chisquare(aug_state, df);
+ }
+ if (1 < df) {
+ const double Chi2 = legacy_chisquare(aug_state, df - 1);
+ const double n = legacy_gauss(aug_state) + sqrt(nonc);
+ return Chi2 + n * n;
+ } else {
+ const long i = random_poisson(aug_state->bit_generator, nonc / 2.0);
+ out = legacy_chisquare(aug_state, df + 2 * i);
+ /* Insert nan guard here to avoid changing the stream */
+ if (npy_isnan(nonc)){
+ return NPY_NAN;
+ } else {
+ return out;
+ }
+ }
+}
+
+double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum, double dfden,
+ double nonc) {
+ double t = legacy_noncentral_chisquare(aug_state, dfnum, nonc) * dfden;
+ return t / (legacy_chisquare(aug_state, dfden) * dfnum);
+}
+
+double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale) {
+ double U, X, Y;
+ double mu_2l;
+
+ mu_2l = mean / (2 * scale);
+ Y = legacy_gauss(aug_state);
+ Y = mean * Y * Y;
+ X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y));
+ U = legacy_double(aug_state);
+ if (U <= mean / (mean + X)) {
+ return X;
+ } else {
+ return mean * mean / X;
+ }
+}
+
+double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale) {
+ return loc + scale * legacy_gauss(aug_state);
+}
+
+double legacy_lognormal(aug_bitgen_t *aug_state, double mean, double sigma) {
+ return exp(legacy_normal(aug_state, mean, sigma));
+}
+
+double legacy_standard_t(aug_bitgen_t *aug_state, double df) {
+ double num, denom;
+
+ num = legacy_gauss(aug_state);
+ denom = legacy_standard_gamma(aug_state, df / 2);
+ return sqrt(df / 2) * num / sqrt(denom);
+}
+
+int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n, double p) {
+ double Y = legacy_gamma(aug_state, n, (1 - p) / p);
+ return (int64_t)random_poisson(aug_state->bit_generator, Y);
+}
+
+double legacy_standard_cauchy(aug_bitgen_t *aug_state) {
+ return legacy_gauss(aug_state) / legacy_gauss(aug_state);
+}
+
+double legacy_beta(aug_bitgen_t *aug_state, double a, double b) {
+ double Ga, Gb;
+
+ if ((a <= 1.0) && (b <= 1.0)) {
+ double U, V, X, Y;
+ /* Use Johnk's algorithm */
+
+ while (1) {
+ U = legacy_double(aug_state);
+ V = legacy_double(aug_state);
+ X = pow(U, 1.0 / a);
+ Y = pow(V, 1.0 / b);
+
+ if ((X + Y) <= 1.0) {
+ if (X + Y > 0) {
+ return X / (X + Y);
+ } else {
+ double logX = log(U) / a;
+ double logY = log(V) / b;
+ double logM = logX > logY ? logX : logY;
+ logX -= logM;
+ logY -= logM;
+
+ return exp(logX - log(exp(logX) + exp(logY)));
+ }
+ }
+ }
+ } else {
+ Ga = legacy_standard_gamma(aug_state, a);
+ Gb = legacy_standard_gamma(aug_state, b);
+ return Ga / (Ga + Gb);
+ }
+}
+
+double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden) {
+ return ((legacy_chisquare(aug_state, dfnum) * dfden) /
+ (legacy_chisquare(aug_state, dfden) * dfnum));
+}
+
+double legacy_exponential(aug_bitgen_t *aug_state, double scale) {
+ return scale * legacy_standard_exponential(aug_state);
+}
+
+
+static RAND_INT_TYPE random_hypergeometric_hyp(bitgen_t *bitgen_state,
+ RAND_INT_TYPE good,
+ RAND_INT_TYPE bad,
+ RAND_INT_TYPE sample) {
+ RAND_INT_TYPE d1, k, z;
+ double d2, u, y;
+
+ d1 = bad + good - sample;
+ d2 = (double)MIN(bad, good);
+
+ y = d2;
+ k = sample;
+ while (y > 0.0) {
+ u = next_double(bitgen_state);
+ y -= (RAND_INT_TYPE)floor(u + y / (d1 + k));
+ k--;
+ if (k == 0)
+ break;
+ }
+ z = (RAND_INT_TYPE)(d2 - y);
+ if (good > bad)
+ z = sample - z;
+ return z;
+}
+
+/* D1 = 2*sqrt(2/e) */
+/* D2 = 3 - 2*sqrt(3/e) */
+#define D1 1.7155277699214135
+#define D2 0.8989161620588988
+static RAND_INT_TYPE random_hypergeometric_hrua(bitgen_t *bitgen_state,
+ RAND_INT_TYPE good,
+ RAND_INT_TYPE bad,
+ RAND_INT_TYPE sample) {
+ RAND_INT_TYPE mingoodbad, maxgoodbad, popsize, m, d9;
+ double d4, d5, d6, d7, d8, d10, d11;
+ RAND_INT_TYPE Z;
+ double T, W, X, Y;
+
+ mingoodbad = MIN(good, bad);
+ popsize = good + bad;
+ maxgoodbad = MAX(good, bad);
+ m = MIN(sample, popsize - sample);
+ d4 = ((double)mingoodbad) / popsize;
+ d5 = 1.0 - d4;
+ d6 = m * d4 + 0.5;
+ d7 = sqrt((double)(popsize - m) * sample * d4 * d5 / (popsize - 1) + 0.5);
+ d8 = D1 * d7 + D2;
+ d9 = (RAND_INT_TYPE)floor((double)(m + 1) * (mingoodbad + 1) / (popsize + 2));
+ d10 = (loggam(d9 + 1) + loggam(mingoodbad - d9 + 1) + loggam(m - d9 + 1) +
+ loggam(maxgoodbad - m + d9 + 1));
+ d11 = MIN(MIN(m, mingoodbad) + 1.0, floor(d6 + 16 * d7));
+ /* 16 for 16-decimal-digit precision in D1 and D2 */
+
+ while (1) {
+ X = next_double(bitgen_state);
+ Y = next_double(bitgen_state);
+ W = d6 + d8 * (Y - 0.5) / X;
+
+ /* fast rejection: */
+ if ((W < 0.0) || (W >= d11))
+ continue;
+
+ Z = (RAND_INT_TYPE)floor(W);
+ T = d10 - (loggam(Z + 1) + loggam(mingoodbad - Z + 1) + loggam(m - Z + 1) +
+ loggam(maxgoodbad - m + Z + 1));
+
+ /* fast acceptance: */
+ if ((X * (4.0 - X) - 3.0) <= T)
+ break;
+
+ /* fast rejection: */
+ if (X * (X - T) >= 1)
+ continue;
+ /* log(0.0) is ok here, since always accept */
+ if (2.0 * log(X) <= T)
+ break; /* acceptance */
+ }
+
+ /* this is a correction to HRUA* by Ivan Frohne in rv.py */
+ if (good > bad)
+ Z = m - Z;
+
+ /* another fix from rv.py to allow sample to exceed popsize/2 */
+ if (m < sample)
+ Z = good - Z;
+
+ return Z;
+}
+#undef D1
+#undef D2
+
+static RAND_INT_TYPE random_hypergeometric_original(bitgen_t *bitgen_state,
+ RAND_INT_TYPE good,
+ RAND_INT_TYPE bad,
+ RAND_INT_TYPE sample)
+{
+ if (sample > 10) {
+ return random_hypergeometric_hrua(bitgen_state, good, bad, sample);
+ } else if (sample > 0) {
+ return random_hypergeometric_hyp(bitgen_state, good, bad, sample);
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * This is a wrapper function that matches the expected template. In the legacy
+ * generator, all int types are long, so this accepts int64 and then converts
+ * them to longs. These values must be in bounds for long and this is checked
+ * outside this function
+ *
+ * The remaining are included for the return type only
+ */
+int64_t legacy_random_hypergeometric(bitgen_t *bitgen_state, int64_t good,
+ int64_t bad, int64_t sample) {
+ return (int64_t)random_hypergeometric_original(bitgen_state,
+ (RAND_INT_TYPE)good,
+ (RAND_INT_TYPE)bad,
+ (RAND_INT_TYPE)sample);
+}
+
+
+int64_t legacy_random_logseries(bitgen_t *bitgen_state, double p) {
+ return (int64_t)random_logseries(bitgen_state, p);
+}
+
+ int64_t legacy_random_poisson(bitgen_t *bitgen_state, double lam) {
+ return (int64_t)random_poisson(bitgen_state, lam);
+}
+
+ int64_t legacy_random_zipf(bitgen_t *bitgen_state, double a) {
+ return (int64_t)random_zipf(bitgen_state, a);
+}
+
+ int64_t legacy_random_geometric(bitgen_t *bitgen_state, double p) {
+ return (int64_t)random_geometric(bitgen_state, p);
+}
+
+ void legacy_random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n,
+ RAND_INT_TYPE *mnix, double *pix, npy_intp d,
+ binomial_t *binomial) {
+ return random_multinomial(bitgen_state, n, mnix, pix, d, binomial);
+}
diff --git a/numpy/random/src/legacy/legacy-distributions.h b/numpy/random/src/legacy/legacy-distributions.h
new file mode 100644
index 000000000..005c4e5d2
--- /dev/null
+++ b/numpy/random/src/legacy/legacy-distributions.h
@@ -0,0 +1,52 @@
+#ifndef _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_
+#define _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_
+
+
+#include "../distributions/distributions.h"
+
+typedef struct aug_bitgen {
+ bitgen_t *bit_generator;
+ int has_gauss;
+ double gauss;
+} aug_bitgen_t;
+
+extern double legacy_gauss(aug_bitgen_t *aug_state);
+extern double legacy_standard_exponential(aug_bitgen_t *aug_state);
+extern double legacy_pareto(aug_bitgen_t *aug_state, double a);
+extern double legacy_weibull(aug_bitgen_t *aug_state, double a);
+extern double legacy_power(aug_bitgen_t *aug_state, double a);
+extern double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale);
+extern double legacy_pareto(aug_bitgen_t *aug_state, double a);
+extern double legacy_weibull(aug_bitgen_t *aug_state, double a);
+extern double legacy_chisquare(aug_bitgen_t *aug_state, double df);
+extern double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df,
+ double nonc);
+
+extern double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum,
+ double dfden, double nonc);
+extern double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale);
+extern double legacy_lognormal(aug_bitgen_t *aug_state, double mean,
+ double sigma);
+extern double legacy_standard_t(aug_bitgen_t *aug_state, double df);
+extern int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n,
+ double p);
+extern double legacy_standard_cauchy(aug_bitgen_t *state);
+extern double legacy_beta(aug_bitgen_t *aug_state, double a, double b);
+extern double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden);
+extern double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale);
+extern double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape);
+extern double legacy_exponential(aug_bitgen_t *aug_state, double scale);
+extern int64_t legacy_negative_binomial(aug_bitgen_t *aug_state, double n,
+ double p);
+extern int64_t legacy_random_hypergeometric(bitgen_t *bitgen_state,
+ int64_t good, int64_t bad,
+ int64_t sample);
+extern int64_t legacy_random_logseries(bitgen_t *bitgen_state, double p);
+extern int64_t legacy_random_poisson(bitgen_t *bitgen_state, double lam);
+extern int64_t legacy_random_zipf(bitgen_t *bitgen_state, double a);
+extern int64_t legacy_random_geometric(bitgen_t *bitgen_state, double p);
+void legacy_random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n,
+ RAND_INT_TYPE *mnix, double *pix, npy_intp d,
+ binomial_t *binomial);
+
+#endif
diff --git a/numpy/random/src/mt19937/LICENSE.md b/numpy/random/src/mt19937/LICENSE.md
new file mode 100644
index 000000000..f65c3d46e
--- /dev/null
+++ b/numpy/random/src/mt19937/LICENSE.md
@@ -0,0 +1,61 @@
+# MT19937
+
+Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org)
+
+The rk_random and rk_seed functions algorithms and the original design of
+the Mersenne Twister RNG:
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Original algorithm for the implementation of rk_interval function from
+Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by
+Magnus Jonsson.
+
+Constants used in the rk_double implementation by Isaku Wada.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/numpy/random/src/mt19937/mt19937-benchmark.c b/numpy/random/src/mt19937/mt19937-benchmark.c
new file mode 100644
index 000000000..039f8030a
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937-benchmark.c
@@ -0,0 +1,31 @@
+/*
+ * cl mt19937-benchmark.c mt19937.c /Ox
+ * Measure-Command { .\mt19937-benchmark.exe }
+ *
+ * gcc mt19937-benchmark.c mt19937.c -O3 -o mt19937-benchmark
+ * time ./mt19937-benchmark
+ */
+#include "mt19937.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <time.h>
+
+#define Q 1000000000
+
+int main() {
+ int i;
+ uint32_t seed = 0x0;
+ uint64_t sum = 0, count = 0;
+ mt19937_state state;
+ mt19937_seed(&state, seed);
+ clock_t begin = clock();
+ for (i = 0; i < Q; i++) {
+ sum += mt19937_next64(&state);
+ count++;
+ }
+ clock_t end = clock();
+ double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+ printf("0x%" PRIx64 "\ncount: %" PRIu64 "\n", sum, count);
+ printf("%" PRIu64 " randoms per second\n",
+ (uint64_t)(Q / time_spent) / 1000000 * 1000000);
+}
diff --git a/numpy/random/src/mt19937/mt19937-jump.c b/numpy/random/src/mt19937/mt19937-jump.c
new file mode 100644
index 000000000..46b28cf96
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937-jump.c
@@ -0,0 +1,224 @@
+#include "mt19937-jump.h"
+#include "mt19937.h"
+
+/* 32-bits function */
+/* return the i-th coefficient of the polynomial pf */
+unsigned long get_coef(unsigned long *pf, unsigned int deg) {
+ if ((pf[deg >> 5] & (LSB << (deg & 0x1ful))) != 0)
+ return (1);
+ else
+ return (0);
+}
+
+/* 32-bit function */
+/* set the coefficient of the polynomial pf with v */
+void set_coef(unsigned long *pf, unsigned int deg, unsigned long v) {
+ if (v != 0)
+ pf[deg >> 5] ^= (LSB << (deg & 0x1ful));
+ else
+ ;
+}
+
+void gray_code(unsigned long *h) {
+ unsigned int i, j = 1, l = 1, term = LL;
+
+ h[0] = 0;
+
+ for (i = 1; i <= QQ; i++) {
+ l = (l << 1);
+ term = (term >> 1);
+ for (; j < l; j++)
+ h[j] = h[l - j - 1] ^ term;
+ }
+}
+
+void copy_state(mt19937_state *target_state, mt19937_state *state) {
+ int i;
+
+ for (i = 0; i < N; i++)
+ target_state->key[i] = state->key[i];
+
+ target_state->pos = state->pos;
+}
+
+/* next state generating function */
+void gen_next(mt19937_state *state) {
+ int num;
+ unsigned long y;
+ static unsigned long mag02[2] = {0x0ul, MATRIX_A};
+
+ num = state->pos;
+ if (num < N - M) {
+ y = (state->key[num] & UPPER_MASK) | (state->key[num + 1] & LOWER_MASK);
+ state->key[num] = state->key[num + M] ^ (y >> 1) ^ mag02[y % 2];
+ state->pos++;
+ } else if (num < N - 1) {
+ y = (state->key[num] & UPPER_MASK) | (state->key[num + 1] & LOWER_MASK);
+ state->key[num] = state->key[num + (M - N)] ^ (y >> 1) ^ mag02[y % 2];
+ state->pos++;
+ } else if (num == N - 1) {
+ y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
+ state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ mag02[y % 2];
+ state->pos = 0;
+ }
+}
+
+void add_state(mt19937_state *state1, mt19937_state *state2) {
+ int i, pt1 = state1->pos, pt2 = state2->pos;
+
+ if (pt2 - pt1 >= 0) {
+ for (i = 0; i < N - pt2; i++)
+ state1->key[i + pt1] ^= state2->key[i + pt2];
+ for (; i < N - pt1; i++)
+ state1->key[i + pt1] ^= state2->key[i + (pt2 - N)];
+ for (; i < N; i++)
+ state1->key[i + (pt1 - N)] ^= state2->key[i + (pt2 - N)];
+ } else {
+ for (i = 0; i < N - pt1; i++)
+ state1->key[i + pt1] ^= state2->key[i + pt2];
+ for (; i < N - pt2; i++)
+ state1->key[i + (pt1 - N)] ^= state2->key[i + pt2];
+ for (; i < N; i++)
+ state1->key[i + (pt1 - N)] ^= state2->key[i + (pt2 - N)];
+ }
+}
+
+/*
+void gen_vec_h(mt19937_state *state, mt19937_state *vec_h,
+ unsigned long *h) {
+ int i;
+ unsigned long k, g;
+ mt19937_state v;
+
+ gray_code(h);
+
+ copy_state(&vec_h[0], state);
+
+ for (i = 0; i < QQ; i++)
+ gen_next(&vec_h[0]);
+
+ for (i = 1; i < LL; i++) {
+ copy_state(&v, state);
+ g = h[i] ^ h[i - 1];
+ for (k = 1; k < g; k = (k << 1))
+ gen_next(&v);
+ copy_state(&vec_h[h[i]], &vec_h[h[i - 1]]);
+ add_state(&vec_h[h[i]], &v);
+ }
+}
+*/
+
+/* compute pf(ss) using Sliding window algorithm */
+/*
+void calc_state(unsigned long *pf, mt19937_state *state,
+ mt19937_state *vec_h) {
+ mt19937_state *temp1;
+ int i = MEXP - 1, j, digit, skip = 0;
+
+ temp1 = (mt19937_state *)calloc(1, sizeof(mt19937_state));
+
+ while (get_coef(pf, i) == 0)
+ i--;
+
+ for (; i >= QQ; i--) {
+ if (get_coef(pf, i) != 0) {
+ for (j = 0; j < QQ + 1; j++)
+ gen_next(temp1);
+ digit = 0;
+ for (j = 0; j < QQ; j++)
+ digit = (digit << 1) ^ get_coef(pf, i - j - 1);
+ add_state(temp1, &vec_h[digit]);
+ i -= QQ;
+ } else
+ gen_next(temp1);
+ }
+
+ for (; i > -1; i--) {
+ gen_next(temp1);
+ if (get_coef(pf, i) == 1)
+ add_state(temp1, state);
+ else
+ ;
+ }
+
+ copy_state(state, temp1);
+ free(temp1);
+}
+*/
+
+/* compute pf(ss) using standard Horner method */
+void horner1(unsigned long *pf, mt19937_state *state) {
+ int i = MEXP - 1;
+ mt19937_state *temp;
+
+ temp = (mt19937_state *)calloc(1, sizeof(mt19937_state));
+
+ while (get_coef(pf, i) == 0)
+ i--;
+
+ if (i > 0) {
+ copy_state(temp, state);
+ gen_next(temp);
+ i--;
+ for (; i > 0; i--) {
+ if (get_coef(pf, i) != 0)
+ add_state(temp, state);
+ else
+ ;
+ gen_next(temp);
+ }
+ if (get_coef(pf, 0) != 0)
+ add_state(temp, state);
+ else
+ ;
+ } else if (i == 0)
+ copy_state(temp, state);
+ else
+ ;
+
+ copy_state(state, temp);
+ free(temp);
+}
+
+void mt19937_jump_state(mt19937_state *state, const char *jump_str) {
+ unsigned long *pf;
+ int i;
+
+ pf = (unsigned long *)calloc(P_SIZE, sizeof(unsigned long));
+
+ for (i = MEXP - 1; i > -1; i--) {
+ if (jump_str[i] == '1')
+ set_coef(pf, i, 1);
+ }
+ /* TODO: Should generate the next set and start from 0, but doesn't matter ??
+ */
+ if (state->pos >= N) {
+ state->pos = 0;
+ }
+
+ horner1(pf, state);
+
+ free(pf);
+}
+/*
+void mt19937_jump(mt19937_state *state, const char *jump_str)
+{
+ unsigned long h[LL];
+ mt19937_state vec_h[LL];
+ unsigned long *pf;
+ int i;
+
+ pf = (unsigned long *)calloc(P_SIZE, sizeof(unsigned long));
+
+ for (i = MEXP - 1; i > -1; i--)
+ {
+ if (jump_str[i] == '1')
+ set_coef(pf, i, 1);
+ }
+
+ gen_vec_h(state, &vec_h, &h);
+ calc_state(pf, state, &vec_h);
+
+ free(pf);
+}
+*/ \ No newline at end of file
diff --git a/numpy/random/src/mt19937/mt19937-jump.h b/numpy/random/src/mt19937/mt19937-jump.h
new file mode 100644
index 000000000..394c150a0
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937-jump.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "mt19937.h"
+#include <stdlib.h>
+
+/* parameters for computing Jump */
+#define W_SIZE 32 /* size of unsigned long */
+#define MEXP 19937
+#define P_SIZE ((MEXP / W_SIZE) + 1)
+#define LSB 0x00000001UL
+#define QQ 7
+#define LL 128 /* LL = 2^(QQ) */
+
+void mt19937_jump_state(mt19937_state *state, const char *jump_str);
+
+void set_coef(unsigned long *pf, unsigned int deg, unsigned long v); \ No newline at end of file
diff --git a/numpy/random/src/mt19937/mt19937-poly.h b/numpy/random/src/mt19937/mt19937-poly.h
new file mode 100644
index 000000000..b03747881
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937-poly.h
@@ -0,0 +1,207 @@
+static const char * poly =
+"0001000111110111011100100010101111000000010100100101000001110111100010101000110100101001011001010"
+"1110101101100101011100101101011001110011100011110100001000001011100101100010100000010011101110011"
+"0100001001111010000100100101001011100111101101001100000111001000011101100100010000001111110100010"
+"0000111101000101000101101111001011000011001001001011010011001000001000011100100010110101111111101"
+"0010001001100010011011101111101110111010111000010000011010110011111101100000100100101001010000001"
+"1001111000011010011101001101011000111001110010110000011000110101111010110011011000001110110010001"
+"1001101011011101000011001011111111100011001010111100000001111011111101000101000011000011111100101"
+"0100001111101010101100000110100110010010101011011100110011000101100101011110010101110000101011100"
+"0001010100010110100000111001100000011101011001101000001000101101010100010101100000100011110110011"
+"0101100110111101010111100010100110100011111011100111000001110110010000000100000110101010111001111"
+"0011110010000110101101010001110010100111111111100100101010010011101111011000010111101001110110110"
+"1011101101101100110111000100101100111001011111110101001000011111010011000111110011100100001101111"
+"1001010110110001000100001001000010000000001011011100101010010100011000110101001000010101100111101"
+"0011110101100110111100000111001011011001100101111011000101001011011111110110100010001100101001100"
+"1111110011111111110111011011100011000100110011011011011001101011100110010001111100001111100100001"
+"1000100011001010100101010100111110001100111111011111100100011110011101101000110100101110010111111"
+"1001010110000101001110010110001011011010101111111001110001100100011001000010111001011011000111100"
+"1101001011110111111010011000110100001010000000101010101001111101111110101111110101110101010010100"
+"1100100101010110011111001101100110001011000101010001000110011011111101111110001100000010110110101"
+"1111110100001011101011101110111101100001111000011100000110110100100100100101011000111000100110001"
+"0110110001001000111110101111000000100100010100100101101111100011010100111101110010000001011111111"
+"1101010000011001010101111001111110001111100010100010100001011001110001010010100001011111110110111"
+"1100100100001111000111110111000100010101010110100111100001011001101001111101001110010110110011010"
+"1000010011000110000000110110110000111010010000111001100010100101010101111100010111000000011101110"
+"1100011010110001101100110000001010001100111101101011100111110111000110010011011011001101001111100"
+"1011111001100011010110101111100110111101011100000011000010001010001101001011000001111000101000100"
+"0110001011001010110000001101100000011000011110010000101000011010011110001101111111010010101100100"
+"1111010100000011011001111111011011111001101110101010110111110110101000100001011110111010100111100"
+"0000001001111100111111111000100000100100010001011001100001111100100000001111011101100010011000111"
+"0011110110100011011001110011100011011000010000000101101101001010111000010000010101111110000000100"
+"1011010100001001000011001100011000000111100111100101010100000111000000110111011101011111100010101"
+"0011001100110000010101111001000111001001010100011000110010011011101001001100101100000000111000111"
+"0111111000010010010100000101010010000100101011111111111001100101101010011010100010111001011100011"
+"1001001011010000110000111100010110110100000100110010000010010000001000110010101000110101101100100"
+"0001100001100011110110010000100000100010011001010010110111100011011000101011001100001111110110110"
+"0001100110010100011001101000100001110011011111101001101011110011011011111110111110101110010011001"
+"1000000101100000101100100000100000001011000100100001100100101101010111101010111101010001001010110"
+"0011111011001101001110110010100100000011001001111010001001100101110000000010111101000111111101010"
+"0110101110101110001001110000111110100000101101100110010001111101111011001000101110111010110111110"
+"0011001101011010001011000010000111111111101001011100110101011000000001111000101100011101011011100"
+"1111101110000000000110001110011001101100111111010001110000111110100011000100001100110010000110111"
+"1001011011001111011100000000011011000100000011000010010111000111101000011001001100011010001111000"
+"0011110010100010001101011101010011001100000010101001001101111101000111001110110000000010111101001"
+"1110110011101110111010011100101001010101100100011111100110001111011111110010100000011100110110001"
+"1011100000101000010100011101000010111100101111101100110001010001010000101110000000110100010110011"
+"1111110100101010011010100001100110110110011111110010000100001010011110010110001000000100000111000"
+"0111001010011001000010111001100110100110110101111011110111001001000101010010010011000111110010101"
+"1100110001100101001000010001101010011001110011001110001110010100010000000000000110111001010101000"
+"0111111011011101000111011001011011000101110100010001111100101110000100001011111101111101010011001"
+"0010001100011011101100010010101011001000001001010101100110001111001110011100110111111010110010001"
+"1111111101111001001101101001001010011001110000101000110010111110010110111111000100101000101011010"
+"0000101101101100000110101000101000010001111000100000111110011111111110010010001010001111011001100"
+"0011110111000000111111000100001111101110100010101011001010110110011001010010001011100001010110101"
+"0100000010101101000011001101110010000010110011000101100100000111111100011001110011010011001110000"
+"1110011110000000001001001010100000111001010110001110011100011010010010001110010011001010111100000"
+"1110000101101001011010001001010000111000010011010100001010110000101101110110011000011100111100001"
+"1001000011010001110110111001100100001111110010110010011111000010100000001101110100000000101101000"
+"0011000000100011000111110001000011100111110110000110101111101100011110100111111000000011011110110"
+"1101011010111010010001001101000110110010000010101000000001100100100000001111011001001010110100011"
+"1011000010101111010111000001001100111110000010110010011011110011111001000101111011010011010100001"
+"0110011111100001011111101010010100110001001001001000100010101011011000011100111000110101110000001"
+"1100001111100011110010000101011000010101111010001101010101100001100101100000100100000101011001100"
+"0011001000101010101010100111000100100010101000111111101010000000101010101001000101010100100111001"
+"1001100001010001100110111101010001111010011100000001001110100010010011110100001000011111100010001"
+"0010001000100110101011001110100110101110110110100101111000110101101101001000001110011010110011001"
+"0111111101011011101001111001011100001010110111000001100010110110100011010111011000111010100011000"
+"1111010110001001010000110001000101101100010100000000100001111100000010111001000011000101010100001"
+"0001101100011100010100101110010100000010011011010100000111110110000110101011011010010001110000111"
+"0110101000110101110010011100010010100111001101110110010001101001101101010100001010001110111011011"
+"1010011001010111101001011000100111001110011000000001101000001111001100001100000011001110100110011"
+"0011000110001001010111111111110110111111000111100010010101110000101100101000001010001011010100010"
+"1010010100010011101111100111010010010001110101011110110100001000001001000111001110010001001100100"
+"1100100010001010011011110100000101101011101010110110100100010001110000111010111001111011111001011"
+"0000000000011000100100100111001000101111000000110001011110101111110111100000000100101011000111011"
+"1011010011101000001011001001110001111010000100101101010111001010001000100001000111011010000110111"
+"1010110001001110001100001110011000101100000101100000000110101000000110101100100101110001100100100"
+"0110000110101011100001010001010000011101111011111011011000100100101011110101111000001011110010110"
+"0111011011100111101010110001111011010011111000010111110100001001010001011001000110111100000101011"
+"0010111111010100000110111101001100000100001011101010100011010010000001101100100101001000100011000"
+"0101010111111100100000111011101111100000011011111111010001100011001100101101011110101011101100001"
+"0100010011101111111011000111111101001000101101111001111000101110010111001010101011010111000000101"
+"0110010000010010101111100010111110000000011101001000011111001011111100111100100101100101111010110"
+"1010101001110011111100111110100000111100100000111111000010100001111011111110110010001001000000000"
+"1110100110010111100101111111001010001111001101100001011000111011100010100001000010100000011001000"
+"0000111000110111001001100010111010100111111001111101100101000011001001110011100110101110001101110"
+"1110000010110110010110000111001110110000011011100111000101100101000000001110011011001001111001111"
+"0000101100001000000111100110110000110111111001101001111111010000001011110011011011100100110000110"
+"1001011111101100100111111000000010001110111011010011011101001100000011001010000010101111111010110"
+"0001000100101110101101100001001010100110010000110110100110011001000111011110110011001110111110101"
+"0000011111011011001111010010101011000010011101001011100001010001111001000110000010000101010011111"
+"0110011000001111101001110001101011111111001010010110100001101000000011101000101011101000110101111"
+"0000101110011010010000110100000101100011000100101111100011001111011101001010100111001110100001101"
+"0000110111011000000110011001101011110000101100110110000101100000110110100001001001110001110001001"
+"1100110111111100101001100010010110011011110001000111111111001101111110010000011001011010111101001"
+"1101111110101110110100101100110001101101001010111101101000000011111111100101000101110001000011001"
+"1000111110111011010010101011110110110001010001001001100111111010011101111000000111011000011010011"
+"0111010101001110010100101101000110000110001100010101001110101011010100000110110111111111110011110"
+"0100011110100011001000110101111010000001011011110101001100111100010100101100010000010110011001111"
+"0011011110001110010010100100011111110000110011011100010110110101001110011010101111011001010101011"
+"1001001111001000001100100111000001000110110101100111000101011000000100001000100010011000001110011"
+"0000111100000111001101011111010000010001100000010101101000111100001000010011110000001011001001100"
+"0011011011111011100000111101001011101000010010001001111110010101111010110101101110110111010000101"
+"1100011000000000110110100011010100100010001101010101101110110111111011010110011101011010110101011"
+"1101000000010010011111000000101000110001000011100001101111010101100000100000100111111111100000000"
+"0011100011100101110010111100010111110010101110101000011000111111001110111111000001101101011011111"
+"1100110101001000011111001111000000001010001001010101101000001100111010101100010111001001111100000"
+"1110101101110001011100011101101100001001001011100111100110011101111000100010010001111100001010010"
+"1011001001010100101100010010000110010000101010111111001000011100000000101101110010001101110101001"
+"1110000011100101010000011110000010001000001010110001010000100111001100110001111000100100011100110"
+"1100010011110111001001100000100111001010000000000011100011111111101110010101111010100010000100001"
+"0101101001010111111110000110110010100000001011110100010111110111010000001011110110111000000110010"
+"0001100100111110001100010101000010011111100000100010000101110000111001101100100000011111111100010"
+"1001101101001000001111000100100001010110111011110110001001010001110001001100011001001100000000101"
+"1100011110101101011001100001010110001010000111100000011011011001000010101100010101110011001101110"
+"0000101011010001010011111001011000010101010100110110111110101000111110001000010100000000100010100"
+"1000111111000110110010001111000010101011101101111101011110101111100111111100111101000101000010011"
+"0010111010100010011001000000010111100010000101001011001101100011100001001111010100100110101111111"
+"1000010011110101001010011111111011101001110100001001100010000100001001100101101111011100100011001"
+"1111010001011001111101011110101101000111110101001010011101010010010101001000000000011001100110001"
+"0001000010101010101000010100111000001110000111001110001101111111000010101010111001011101001001011"
+"0011001111011010101110101111110001001100100111010001011000010100000100000001001100000011000011101"
+"1100000110000001011001110000101001010111101000110101000011000000111011100101010000111000010010101"
+"1010100101100001011011011110110011000100100101010011111101000000100001001101000011000101010111101"
+"1110111111100010111000111000010110111010010110000000000100101001000111101101100000000110111011001"
+"0100000000100100011110111011101101101101010110001110100001100001001011000000111111110100011110011"
+"0010000010000000010100110011110000000010000011111000111101011110000000000010101101001100000010010"
+"1011001001101110110011100001100011101001101011110011010001011101000100011111001010100000011111111"
+"1010101100000010001000110000110000101000110100110011100000110010110100011111010001000011100001001"
+"1000101000010111111011100010111000111001010100110000000010011011101010101111000110001000110111011"
+"1011100001100011010001101011010100110110011100000010111001011111110010100110100010001100000011100"
+"0001011001011000101011010000001010011010001011000111000011000011110011111001111010001101011010010"
+"0010010001001001101000101001011011101110001100010001010100010111111001100100000010001111100010111"
+"0100001111001100101001011101010010110010100010001100011010100110000100011010111110001011011001000"
+"1001001111011010010011101110100001111100000110101001010111110001101100110010111010111001011111010"
+"1110111011111110000001110010000010011111000111011011000011000010011110011111111101100101111011100"
+"0101101100000110101110000111111111111010110101010100111000011111011001100000100000101011000101110"
+"1011010010100000000100100000010111101110111001000011111011111110100011010010000110001101111101100"
+"1100010111001011011001011001010100100110100101001000111011011001100011001010010101111001100100110"
+"1000110000111011100101110101101000011001010010100011000001111001110110101101010010110110001100100"
+"0100001011101100111001010001111011010110010010110010110111110001001001111001111010010001010001101"
+"1110100110101100011110100100110111000111010110011000100100110110001101111100111110100001000110000"
+"1110011011001101100101100000001010100011101000010100111011111100011010000110000001011100010000101"
+"0100101000010001110010001100010110011111111101111000011001110111011100110010010100100010001000010"
+"0100001110010000011000110001101011101001110100100011011001000111010101110100110011010111001100001"
+"0100001001101010010111110101110111000000010100111101011010101001000001001000001000101101111000000"
+"0110000101110100001111001101110111011110010111101000100101110111010101001101100001110001101101101"
+"0010101100100101000100100100110111000111000111100111000001100001000111101011000110111110001010000"
+"0100110010001101100011010111000111010111000111110000110000101111101110010110111001011000111010001"
+"1011000010010101010010011001000011010110111011010001001010100111001000010110110110101110000110000"
+"1110110010011001011011000100011101001001000111011100100000000000100001101101000101000100000111001"
+"0011100001100110101011011101110111101111000100100011100001010001011001110010101010001110101101110"
+"1011001110111111111010101101000010111111011011011100011100101010001011011100011111011100101011000"
+"1000110100101000011111010011110000000101101110010000101100001000100000000010010110000000000110011"
+"1000000000001111001001000100000111001110111111001111101100001100111000101100011000100111111110011"
+"1110010101011010111100110010110001010000101111111101001010100010001001111010111000010000010010001"
+"1111111101100100001101011011100001010101000111110111111101011010011111111101000111011001011011000"
+"0000101011100011101110110011101111011110011110010000011001111001110111011011111010011011001110111"
+"0101100111110100000100010110010010101001010100010111000101111001011011001001110010100011101111110"
+"1101011110010101101011010010011111110000011010011101000000010000111010100100111110111000001101010"
+"0101100001111001111010101011110001001010000011010110010100011100100100111110100110000010011111001"
+"0100010011001001010101110111111010011101101100000101011110111010011110001111110100111011110011010"
+"0111001010110101010110000011001010000000101101010101001101011000011011010110101010101111101101100"
+"1100100000111101010111011011011110011001100010010000010100101000111111101011100111010101011000111"
+"1100110010101100010011111100000110011111101011100100001110001100001010101001001100010011001000100"
+"1101101000101101110010000001101001001110101111000110111000011101111110100100110111000000101011110"
+"0001100100001010101001101111001000001100000011010000100101100000001110100010010000110110101010111"
+"1100010100000110011100101010111110010110111100000010110011011001011110111001010011011110010001110"
+"1101110000001011101101011111101011111110110110000111110011101100110100010000100000110100010010110"
+"0011000011000110101001110100111010110000100010110101110111100010110001000111100111001011011110010"
+"0001001110101001101101011010111001001101100011101001011011001110011010001010110100111001111100101"
+"1000111001010010000010111010101110001100110111111000011101001000001010010011101000111001100111110"
+"1110100100100110010111111101010011101111011011111011011010011110100101100001011000001001001010010"
+"1100001000000110110011011101010001011110010001001110110100100001101101001011101010001110111111010"
+"1100011100101000011110111110110011111111100010110010110111010010001111101110011011010110000001000"
+"0010110100010101110100001000010011100110001110001110010100010010010110011100100110010100001110011"
+"1100001011010000001101011011011110100000001110100111001000101000001000001001000010000111010000100"
+"0111100000101010110010111010010101100000001100110101001001000110001110111011110001010010010011000"
+"1100001111101101100001111000101100110010001000111001101101011110100110100011101000011111011010101"
+"0101000011111010010110001001100110110111000100100011011101000010001010110001111001111101110001111"
+"0100100000010111010011111110000101001001011110100100010011101110011010100101100001010000001110100"
+"0011111101111000100110011000011001100100001010110011111100111010100011110100010101011110011001000"
+"0000110000100100001011101110111010001001011110010101111100001111101101111011011110001010000100010"
+"1001100100100100110010010101100110000000100000000111110011100111101001010000010000000000101011100"
+"0011101011100110000001100101010101011111111011010011110010011011001010011101010010100010001011010"
+"1100010011101011010111110100001010100011000011001001011011101111110011001110010001100101011001101"
+"0100010001111111100000101000001011010100011100111011010111001100110110001100110101000011010001010"
+"1011100001001010011110001010100100001101110011101011100100101010001100110011110010001100100001000"
+"0110001001110110010111101011101101010111001010011010101110000010100010000111011000010110011000001"
+"1000110010100001110001100010010000001101111110000010010110100000000000001111110010001110111100001"
+"0100111101000011101110010101011011000101011010111100111111001011110001110011110011011010010111101"
+"1010111011101101000001110111001010011001110010100100100100001010001100101010111001110100000110111"
+"1010000111000011101101100101101001100000011100100111100110010110011100101000111110111000110111110"
+"1101100101011101100111011111111001111000011110111110101100000111000101100100110111000010100101000"
+"0110000011011101111101111000110101011000010111010000111011000000100011101010100111001111101010111"
+"0001110100001000100001011101001010001110100000101100001011101111100111101011111001111100101101111"
+"0101100001110011111110110100110010000011011111101101110110000110110011100110111000111101000010111"
+"0111101011100100000000011101111011000100001000111000000111011010101010110000111111101010110001111"
+"0000110100111101111011001010101110000011001101001101000010011001101011111110111101010111010011100"
+"0101010011001111101111001100101000101000111110111001011111100000001101111011000001001100111111111"
+"1010111101000001111011110010001001001110100111110010000011110000011000000101001100011110110011001"
+"1010101001000010001010110000010011110101011110010111010001010111101100001001100011101001111101001"
+"0110110100111001110011100011111010010010100010111000001100001011010010000100100110101010111001001"
+"0110000101011011011100110111111001010000001001011010101010010001011010111100111010101101000101101"
+"0100100001011101110111111001111111110110111011000101010000010000011111001000100101100100100110110"
+"1100000111110010110011010100000100011111110001110010110001000001001111001101110110110101101010111"
+"0000100111101100010001110010110111100011100101100011";
diff --git a/numpy/random/src/mt19937/mt19937-test-data-gen.c b/numpy/random/src/mt19937/mt19937-test-data-gen.c
new file mode 100644
index 000000000..4f4ec1d64
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937-test-data-gen.c
@@ -0,0 +1,59 @@
+/*
+ * Generate testing csv files
+ *
+ * cl mt19937-test-data-gen.c randomkit.c
+ * -IC:\Anaconda\Lib\site-packages\numpy\core\include -IC:\Anaconda\include
+ * Advapi32.lib Kernel32.lib C:\Anaconda\libs\python36.lib -DRK_NO_WINCRYPT=1
+ *
+ */
+#include "randomkit.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#define N 1000
+
+int main() {
+ uint64_t sum = 0;
+ uint32_t seed = 0xDEADBEAF;
+ int i;
+ rk_state state;
+ rk_seed(seed, &state);
+ uint64_t store[N];
+ for (i = 0; i < N; i++) {
+ store[i] = (uint64_t)rk_random(&state);
+ }
+
+ FILE *fp;
+ fp = fopen("mt19937-testset-1.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx32 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+
+ seed = 0;
+ rk_seed(seed, &state);
+ for (i = 0; i < N; i++) {
+ store[i] = (uint64_t)rk_random(&state);
+ }
+ fp = fopen("mt19937-testset-2.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx32 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+}
diff --git a/numpy/random/src/mt19937/mt19937.c b/numpy/random/src/mt19937/mt19937.c
new file mode 100644
index 000000000..e5ca9e0cf
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937.c
@@ -0,0 +1,107 @@
+#include "mt19937.h"
+#include "mt19937-jump.h"
+#include "mt19937-poly.h"
+
+void mt19937_seed(mt19937_state *state, uint32_t seed) {
+ int pos;
+ seed &= 0xffffffffUL;
+
+ /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
+ for (pos = 0; pos < RK_STATE_LEN; pos++) {
+ state->key[pos] = seed;
+ seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
+ }
+ state->pos = RK_STATE_LEN;
+}
+
+/* initializes mt[RK_STATE_LEN] with a seed */
+static void init_genrand(mt19937_state *state, uint32_t s) {
+ int mti;
+ uint32_t *mt = state->key;
+
+ mt[0] = s & 0xffffffffUL;
+ for (mti = 1; mti < RK_STATE_LEN; mti++) {
+ /*
+ * See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
+ * In the previous versions, MSBs of the seed affect
+ * only MSBs of the array mt[].
+ * 2002/01/09 modified by Makoto Matsumoto
+ */
+ mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
+ /* for > 32 bit machines */
+ mt[mti] &= 0xffffffffUL;
+ }
+ state->pos = mti;
+ return;
+}
+
+/*
+ * initialize by an array with array-length
+ * init_key is the array for initializing keys
+ * key_length is its length
+ */
+void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key,
+ int key_length) {
+ /* was signed in the original code. RDH 12/16/2002 */
+ int i = 1;
+ int j = 0;
+ uint32_t *mt = state->key;
+ int k;
+
+ init_genrand(state, 19650218UL);
+ k = (RK_STATE_LEN > key_length ? RK_STATE_LEN : key_length);
+ for (; k; k--) {
+ /* non linear */
+ mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) +
+ init_key[j] + j;
+ /* for > 32 bit machines */
+ mt[i] &= 0xffffffffUL;
+ i++;
+ j++;
+ if (i >= RK_STATE_LEN) {
+ mt[0] = mt[RK_STATE_LEN - 1];
+ i = 1;
+ }
+ if (j >= key_length) {
+ j = 0;
+ }
+ }
+ for (k = RK_STATE_LEN - 1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) -
+ i; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++;
+ if (i >= RK_STATE_LEN) {
+ mt[0] = mt[RK_STATE_LEN - 1];
+ i = 1;
+ }
+ }
+
+ mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+}
+
+void mt19937_gen(mt19937_state *state) {
+ uint32_t y;
+ int i;
+
+ for (i = 0; i < N - M; i++) {
+ y = (state->key[i] & UPPER_MASK) | (state->key[i + 1] & LOWER_MASK);
+ state->key[i] = state->key[i + M] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+ }
+ for (; i < N - 1; i++) {
+ y = (state->key[i] & UPPER_MASK) | (state->key[i + 1] & LOWER_MASK);
+ state->key[i] = state->key[i + (M - N)] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+ }
+ y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
+ state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+
+ state->pos = 0;
+}
+
+extern inline uint64_t mt19937_next64(mt19937_state *state);
+
+extern inline uint32_t mt19937_next32(mt19937_state *state);
+
+extern inline double mt19937_next_double(mt19937_state *state);
+
+void mt19937_jump(mt19937_state *state) { mt19937_jump_state(state, poly); }
diff --git a/numpy/random/src/mt19937/mt19937.h b/numpy/random/src/mt19937/mt19937.h
new file mode 100644
index 000000000..1b39e0b64
--- /dev/null
+++ b/numpy/random/src/mt19937/mt19937.h
@@ -0,0 +1,61 @@
+#pragma once
+#include <math.h>
+#include <stdint.h>
+
+#ifdef _WIN32
+#define inline __forceinline
+#endif
+
+#define RK_STATE_LEN 624
+
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL
+#define UPPER_MASK 0x80000000UL
+#define LOWER_MASK 0x7fffffffUL
+
+typedef struct s_mt19937_state {
+ uint32_t key[RK_STATE_LEN];
+ int pos;
+} mt19937_state;
+
+extern void mt19937_seed(mt19937_state *state, uint32_t seed);
+
+extern void mt19937_gen(mt19937_state *state);
+
+/* Slightly optimized reference implementation of the Mersenne Twister */
+static inline uint32_t mt19937_next(mt19937_state *state) {
+ uint32_t y;
+
+ if (state->pos == RK_STATE_LEN) {
+ // Move to function to help inlining
+ mt19937_gen(state);
+ }
+ y = state->key[state->pos++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+extern void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key,
+ int key_length);
+
+static inline uint64_t mt19937_next64(mt19937_state *state) {
+ return (uint64_t)mt19937_next(state) << 32 | mt19937_next(state);
+}
+
+static inline uint32_t mt19937_next32(mt19937_state *state) {
+ return mt19937_next(state);
+}
+
+static inline double mt19937_next_double(mt19937_state *state) {
+ int32_t a = mt19937_next(state) >> 5, b = mt19937_next(state) >> 6;
+ return (a * 67108864.0 + b) / 9007199254740992.0;
+}
+
+void mt19937_jump(mt19937_state *state);
diff --git a/numpy/random/src/mt19937/randomkit.c b/numpy/random/src/mt19937/randomkit.c
new file mode 100644
index 000000000..f8ed4b49e
--- /dev/null
+++ b/numpy/random/src/mt19937/randomkit.c
@@ -0,0 +1,578 @@
+/* Random kit 1.3 */
+
+/*
+ * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org)
+ *
+ * The rk_random and rk_seed functions algorithms and the original design of
+ * the Mersenne Twister RNG:
+ *
+ * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Original algorithm for the implementation of rk_interval function from
+ * Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by
+ * Magnus Jonsson.
+ *
+ * Constants used in the rk_double implementation by Isaku Wada.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* static char const rcsid[] =
+ "@(#) $Jeannot: randomkit.c,v 1.28 2005/07/21 22:14:09 js Exp $"; */
+
+#ifdef _WIN32
+/*
+ * Windows
+ * XXX: we have to use this ugly defined(__GNUC__) because it is not easy to
+ * detect the compiler used in distutils itself
+ */
+#if (defined(__GNUC__) && defined(NPY_NEEDS_MINGW_TIME_WORKAROUND))
+
+/*
+ * FIXME: ideally, we should set this to the real version of MSVCRT. We need
+ * something higher than 0x601 to enable _ftime64 and co
+ */
+#define __MSVCRT_VERSION__ 0x0700
+#include <sys/timeb.h>
+#include <time.h>
+
+/*
+ * mingw msvcr lib import wrongly export _ftime, which does not exist in the
+ * actual msvc runtime for version >= 8; we make it an alias to _ftime64, which
+ * is available in those versions of the runtime
+ */
+#define _FTIME(x) _ftime64((x))
+#else
+#include <sys/timeb.h>
+#include <time.h>
+
+#define _FTIME(x) _ftime((x))
+#endif
+
+#ifndef RK_NO_WINCRYPT
+/* Windows crypto */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#include <wincrypt.h>
+#include <windows.h>
+
+#endif
+
+/*
+ * Do not move this include. randomkit.h must be included
+ * after windows timeb.h is included.
+ */
+#include "randomkit.h"
+
+#else
+/* Unix */
+#include "randomkit.h"
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef RK_DEV_URANDOM
+#define RK_DEV_URANDOM "/dev/urandom"
+#endif
+
+#ifndef RK_DEV_RANDOM
+#define RK_DEV_RANDOM "/dev/random"
+#endif
+
+char *rk_strerror[RK_ERR_MAX] = {"no error", "random device unvavailable"};
+
+/* static functions */
+static unsigned long rk_hash(unsigned long key);
+
+void rk_seed(unsigned long seed, rk_state *state) {
+ int pos;
+ seed &= 0xffffffffUL;
+
+ /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
+ for (pos = 0; pos < RK_STATE_LEN; pos++) {
+ state->key[pos] = seed;
+ seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
+ }
+ state->pos = RK_STATE_LEN;
+ state->gauss = 0;
+ state->has_gauss = 0;
+ state->has_binomial = 0;
+}
+
+/* Thomas Wang 32 bits integer hash function */
+unsigned long rk_hash(unsigned long key) {
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+
+rk_error rk_randomseed(rk_state *state) {
+#ifndef _WIN32
+ struct timeval tv;
+#else
+ struct _timeb tv;
+#endif
+ int i;
+
+ if (rk_devfill(state->key, sizeof(state->key), 0) == RK_NOERR) {
+ /* ensures non-zero key */
+ state->key[0] |= 0x80000000UL;
+ state->pos = RK_STATE_LEN;
+ state->gauss = 0;
+ state->has_gauss = 0;
+ state->has_binomial = 0;
+
+ for (i = 0; i < 624; i++) {
+ state->key[i] &= 0xffffffffUL;
+ }
+ return RK_NOERR;
+ }
+
+#ifndef _WIN32
+ gettimeofday(&tv, NULL);
+ rk_seed(rk_hash(getpid()) ^ rk_hash(tv.tv_sec) ^ rk_hash(tv.tv_usec) ^
+ rk_hash(clock()),
+ state);
+#else
+ _FTIME(&tv);
+ rk_seed(rk_hash(tv.time) ^ rk_hash(tv.millitm) ^ rk_hash(clock()), state);
+#endif
+
+ return RK_ENODEV;
+}
+
+/* Magic Mersenne Twister constants */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL
+#define UPPER_MASK 0x80000000UL
+#define LOWER_MASK 0x7fffffffUL
+
+/*
+ * Slightly optimised reference implementation of the Mersenne Twister
+ * Note that regardless of the precision of long, only 32 bit random
+ * integers are produced
+ */
+unsigned long rk_random(rk_state *state) {
+ unsigned long y;
+
+ if (state->pos == RK_STATE_LEN) {
+ int i;
+
+ for (i = 0; i < N - M; i++) {
+ y = (state->key[i] & UPPER_MASK) | (state->key[i + 1] & LOWER_MASK);
+ state->key[i] = state->key[i + M] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+ }
+ for (; i < N - 1; i++) {
+ y = (state->key[i] & UPPER_MASK) | (state->key[i + 1] & LOWER_MASK);
+ state->key[i] =
+ state->key[i + (M - N)] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+ }
+ y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
+ state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
+
+ state->pos = 0;
+ }
+ y = state->key[state->pos++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+/*
+ * Returns an unsigned 64 bit random integer.
+ */
+NPY_INLINE static npy_uint64 rk_uint64(rk_state *state) {
+ npy_uint64 upper = (npy_uint64)rk_random(state) << 32;
+ npy_uint64 lower = (npy_uint64)rk_random(state);
+ return upper | lower;
+}
+
+/*
+ * Returns an unsigned 32 bit random integer.
+ */
+NPY_INLINE static npy_uint32 rk_uint32(rk_state *state) {
+ return (npy_uint32)rk_random(state);
+}
+
+/*
+ * Fills an array with cnt random npy_uint64 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void rk_random_uint64(npy_uint64 off, npy_uint64 rng, npy_intp cnt,
+ npy_uint64 *out, rk_state *state) {
+ npy_uint64 val, mask = rng;
+ npy_intp i;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ return;
+ }
+
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+ mask |= mask >> 32;
+
+ for (i = 0; i < cnt; i++) {
+ if (rng <= 0xffffffffUL) {
+ while ((val = (rk_uint32(state) & mask)) > rng)
+ ;
+ } else {
+ while ((val = (rk_uint64(state) & mask)) > rng)
+ ;
+ }
+ out[i] = off + val;
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint32 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void rk_random_uint32(npy_uint32 off, npy_uint32 rng, npy_intp cnt,
+ npy_uint32 *out, rk_state *state) {
+ npy_uint32 val, mask = rng;
+ npy_intp i;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ return;
+ }
+
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+
+ for (i = 0; i < cnt; i++) {
+ while ((val = (rk_uint32(state) & mask)) > rng)
+ ;
+ out[i] = off + val;
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint16 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void rk_random_uint16(npy_uint16 off, npy_uint16 rng, npy_intp cnt,
+ npy_uint16 *out, rk_state *state) {
+ npy_uint16 val, mask = rng;
+ npy_intp i;
+ npy_uint32 buf;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ return;
+ }
+
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+
+ for (i = 0; i < cnt; i++) {
+ do {
+ if (!bcnt) {
+ buf = rk_uint32(state);
+ bcnt = 1;
+ } else {
+ buf >>= 16;
+ bcnt--;
+ }
+ val = (npy_uint16)buf & mask;
+ } while (val > rng);
+ out[i] = off + val;
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_uint8 between off and off + rng
+ * inclusive. The numbers wrap if rng is sufficiently large.
+ */
+void rk_random_uint8(npy_uint8 off, npy_uint8 rng, npy_intp cnt, npy_uint8 *out,
+ rk_state *state) {
+ npy_uint8 val, mask = rng;
+ npy_intp i;
+ npy_uint32 buf;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ return;
+ }
+
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+
+ for (i = 0; i < cnt; i++) {
+ do {
+ if (!bcnt) {
+ buf = rk_uint32(state);
+ bcnt = 3;
+ } else {
+ buf >>= 8;
+ bcnt--;
+ }
+ val = (npy_uint8)buf & mask;
+ } while (val > rng);
+ out[i] = off + val;
+ }
+}
+
+/*
+ * Fills an array with cnt random npy_bool between off and off + rng
+ * inclusive.
+ */
+void rk_random_bool(npy_bool off, npy_bool rng, npy_intp cnt, npy_bool *out,
+ rk_state *state) {
+ npy_intp i;
+ npy_uint32 buf;
+ int bcnt = 0;
+
+ if (rng == 0) {
+ for (i = 0; i < cnt; i++) {
+ out[i] = off;
+ }
+ return;
+ }
+
+ /* If we reach here rng and mask are one and off is zero */
+ assert(rng == 1 && off == 0);
+ for (i = 0; i < cnt; i++) {
+ if (!bcnt) {
+ buf = rk_uint32(state);
+ bcnt = 31;
+ } else {
+ buf >>= 1;
+ bcnt--;
+ }
+ out[i] = (buf & 0x00000001) != 0;
+ }
+}
+
+long rk_long(rk_state *state) { return rk_ulong(state) >> 1; }
+
+unsigned long rk_ulong(rk_state *state) {
+#if ULONG_MAX <= 0xffffffffUL
+ return rk_random(state);
+#else
+ return (rk_random(state) << 32) | (rk_random(state));
+#endif
+}
+
+unsigned long rk_interval(unsigned long max, rk_state *state) {
+ unsigned long mask = max, value;
+
+ if (max == 0) {
+ return 0;
+ }
+ /* Smallest bit mask >= max */
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+#if ULONG_MAX > 0xffffffffUL
+ mask |= mask >> 32;
+#endif
+
+ /* Search a random value in [0..mask] <= max */
+#if ULONG_MAX > 0xffffffffUL
+ if (max <= 0xffffffffUL) {
+ while ((value = (rk_random(state) & mask)) > max)
+ ;
+ } else {
+ while ((value = (rk_ulong(state) & mask)) > max)
+ ;
+ }
+#else
+ while ((value = (rk_ulong(state) & mask)) > max)
+ ;
+#endif
+ return value;
+}
+
+double rk_double(rk_state *state) {
+ /* shifts : 67108864 = 0x4000000, 9007199254740992 = 0x20000000000000 */
+ long a = rk_random(state) >> 5, b = rk_random(state) >> 6;
+ return (a * 67108864.0 + b) / 9007199254740992.0;
+}
+
+void rk_fill(void *buffer, size_t size, rk_state *state) {
+ unsigned long r;
+ unsigned char *buf = buffer;
+
+ for (; size >= 4; size -= 4) {
+ r = rk_random(state);
+ *(buf++) = r & 0xFF;
+ *(buf++) = (r >> 8) & 0xFF;
+ *(buf++) = (r >> 16) & 0xFF;
+ *(buf++) = (r >> 24) & 0xFF;
+ }
+
+ if (!size) {
+ return;
+ }
+ r = rk_random(state);
+ for (; size; r >>= 8, size--) {
+ *(buf++) = (unsigned char)(r & 0xFF);
+ }
+}
+
+rk_error rk_devfill(void *buffer, size_t size, int strong) {
+#ifndef _WIN32
+ FILE *rfile;
+ int done;
+
+ if (strong) {
+ rfile = fopen(RK_DEV_RANDOM, "rb");
+ } else {
+ rfile = fopen(RK_DEV_URANDOM, "rb");
+ }
+ if (rfile == NULL) {
+ return RK_ENODEV;
+ }
+ done = fread(buffer, size, 1, rfile);
+ fclose(rfile);
+ if (done) {
+ return RK_NOERR;
+ }
+#else
+
+#ifndef RK_NO_WINCRYPT
+ HCRYPTPROV hCryptProv;
+ BOOL done;
+
+ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT) ||
+ !hCryptProv) {
+ return RK_ENODEV;
+ }
+ done = CryptGenRandom(hCryptProv, size, (unsigned char *)buffer);
+ CryptReleaseContext(hCryptProv, 0);
+ if (done) {
+ return RK_NOERR;
+ }
+#endif
+
+#endif
+ return RK_ENODEV;
+}
+
+rk_error rk_altfill(void *buffer, size_t size, int strong, rk_state *state) {
+ rk_error err;
+
+ err = rk_devfill(buffer, size, strong);
+ if (err) {
+ rk_fill(buffer, size, state);
+ }
+ return err;
+}
+
+double rk_gauss(rk_state *state) {
+ if (state->has_gauss) {
+ const double tmp = state->gauss;
+ state->gauss = 0;
+ state->has_gauss = 0;
+ return tmp;
+ } else {
+ double f, x1, x2, r2;
+
+ do {
+ x1 = 2.0 * rk_double(state) - 1.0;
+ x2 = 2.0 * rk_double(state) - 1.0;
+ r2 = x1 * x1 + x2 * x2;
+ } while (r2 >= 1.0 || r2 == 0.0);
+
+ /* Polar method, a more efficient version of the Box-Muller approach. */
+ f = sqrt(-2.0 * log(r2) / r2);
+ /* Keep for next call */
+ state->gauss = f * x1;
+ state->has_gauss = 1;
+ return f * x2;
+ }
+}
diff --git a/numpy/random/mtrand/randomkit.h b/numpy/random/src/mt19937/randomkit.h
index a24dabebf..abb082cb2 100644
--- a/numpy/random/mtrand/randomkit.h
+++ b/numpy/random/src/mt19937/randomkit.h
@@ -59,50 +59,47 @@
#ifndef _RANDOMKIT_
#define _RANDOMKIT_
-#include <stddef.h>
#include <numpy/npy_common.h>
-
+#include <stddef.h>
#define RK_STATE_LEN 624
-typedef struct rk_state_
-{
- unsigned long key[RK_STATE_LEN];
- int pos;
- int has_gauss; /* !=0: gauss contains a gaussian deviate */
- double gauss;
-
- /* The rk_state structure has been extended to store the following
- * information for the binomial generator. If the input values of n or p
- * are different than nsave and psave, then the other parameters will be
- * recomputed. RTK 2005-09-02 */
-
- int has_binomial; /* !=0: following parameters initialized for
- binomial */
- double psave;
- long nsave;
- double r;
- double q;
- double fm;
- long m;
- double p1;
- double xm;
- double xl;
- double xr;
- double c;
- double laml;
- double lamr;
- double p2;
- double p3;
- double p4;
-
-}
-rk_state;
+typedef struct rk_state_ {
+ unsigned long key[RK_STATE_LEN];
+ int pos;
+ int has_gauss; /* !=0: gauss contains a gaussian deviate */
+ double gauss;
+
+ /* The rk_state structure has been extended to store the following
+ * information for the binomial generator. If the input values of n or p
+ * are different than nsave and psave, then the other parameters will be
+ * recomputed. RTK 2005-09-02 */
+
+ int has_binomial; /* !=0: following parameters initialized for
+ binomial */
+ double psave;
+ long nsave;
+ double r;
+ double q;
+ double fm;
+ long m;
+ double p1;
+ double xm;
+ double xl;
+ double xr;
+ double c;
+ double laml;
+ double lamr;
+ double p2;
+ double p3;
+ double p4;
+
+} rk_state;
typedef enum {
- RK_NOERR = 0, /* no error */
- RK_ENODEV = 1, /* no RK_DEV_RANDOM device */
- RK_ERR_MAX = 2
+ RK_NOERR = 0, /* no error */
+ RK_ENODEV = 1, /* no RK_DEV_RANDOM device */
+ RK_ERR_MAX = 2
} rk_error;
/* error strings */
@@ -212,7 +209,7 @@ extern rk_error rk_devfill(void *buffer, size_t size, int strong);
* Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is
*/
extern rk_error rk_altfill(void *buffer, size_t size, int strong,
- rk_state *state);
+ rk_state *state);
/*
* return a random gaussian deviate with variance unity and zero mean.
diff --git a/numpy/random/src/pcg64/LICENSE.md b/numpy/random/src/pcg64/LICENSE.md
new file mode 100644
index 000000000..7aac7a51c
--- /dev/null
+++ b/numpy/random/src/pcg64/LICENSE.md
@@ -0,0 +1,22 @@
+# PCG64
+
+## The MIT License
+
+PCG Random Number Generation for C.
+
+Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/numpy/random/src/pcg64/pcg64-benchmark.c b/numpy/random/src/pcg64/pcg64-benchmark.c
new file mode 100644
index 000000000..76f3ec78c
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64-benchmark.c
@@ -0,0 +1,42 @@
+/*
+ * cl pcg64-benchmark.c pcg64.c ../splitmix64/splitmix64.c /Ox
+ * Measure-Command { .\xoroshiro128-benchmark.exe }
+ *
+ * gcc pcg64-benchmark.c pcg64.c ../splitmix64/splitmix64.c -O3 -o
+ * pcg64-benchmark
+ * time ./pcg64-benchmark
+ */
+#include "../splitmix64/splitmix64.h"
+#include "pcg64.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <time.h>
+
+#define N 1000000000
+
+int main() {
+ pcg64_random_t rng;
+ uint64_t sum = 0, count = 0;
+ uint64_t seed = 0xDEADBEAF;
+ int i;
+#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH)
+ rng.state = (__uint128_t)splitmix64_next(&seed) << 64;
+ rng.state |= splitmix64_next(&seed);
+ rng.inc = (__uint128_t)1;
+#else
+ rng.state.high = splitmix64_next(&seed);
+ rng.state.low = splitmix64_next(&seed);
+ rng.inc.high = 0;
+ rng.inc.low = 1;
+#endif
+ clock_t begin = clock();
+ for (i = 0; i < N; i++) {
+ sum += pcg64_random_r(&rng);
+ count++;
+ }
+ clock_t end = clock();
+ double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+ printf("0x%" PRIx64 "\ncount: %" PRIu64 "\n", sum, count);
+ printf("%" PRIu64 " randoms per second\n",
+ (uint64_t)(N / time_spent) / 1000000 * 1000000);
+}
diff --git a/numpy/random/src/pcg64/pcg64-test-data-gen.c b/numpy/random/src/pcg64/pcg64-test-data-gen.c
new file mode 100644
index 000000000..0c2b079a3
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64-test-data-gen.c
@@ -0,0 +1,73 @@
+/*
+ * Generate testing csv files
+ *
+ * GCC only
+ *
+ * gcc pcg64-test-data-gen.c pcg64.orig.c ../splitmix64/splitmix64.c -o
+ * pgc64-test-data-gen
+ */
+
+#include "pcg64.orig.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#define N 1000
+
+int main() {
+ pcg64_random_t rng;
+ uint64_t state, seed = 0xDEADBEAF;
+ state = seed;
+ __uint128_t temp, s, inc;
+ int i;
+ uint64_t store[N];
+ s = (__uint128_t)seed;
+ inc = (__uint128_t)0;
+ pcg64_srandom_r(&rng, s, inc);
+ printf("0x%" PRIx64, (uint64_t)(rng.state >> 64));
+ printf("%" PRIx64 "\n", (uint64_t)rng.state);
+ printf("0x%" PRIx64, (uint64_t)(rng.inc >> 64));
+ printf("%" PRIx64 "\n", (uint64_t)rng.inc);
+ for (i = 0; i < N; i++) {
+ store[i] = pcg64_random_r(&rng);
+ }
+
+ FILE *fp;
+ fp = fopen("pcg64-testset-1.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx64 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+
+ state = seed = 0;
+ s = (__uint128_t)seed;
+ i = (__uint128_t)0;
+ pcg64_srandom_r(&rng, s, i);
+ printf("0x%" PRIx64, (uint64_t)(rng.state >> 64));
+ printf("%" PRIx64 "\n", (uint64_t)rng.state);
+ printf("0x%" PRIx64, (uint64_t)(rng.inc >> 64));
+ printf("%" PRIx64 "\n", (uint64_t)rng.inc);
+ for (i = 0; i < N; i++) {
+ store[i] = pcg64_random_r(&rng);
+ }
+ fp = fopen("pcg64-testset-2.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx64 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+}
diff --git a/numpy/random/src/pcg64/pcg64.c b/numpy/random/src/pcg64/pcg64.c
new file mode 100644
index 000000000..b15973aef
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64.c
@@ -0,0 +1,187 @@
+/*
+ * PCG64 Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ * Copyright 2015 Robert Kern <robert.kern@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ *
+ * Relicensed MIT in May 2019
+ *
+ * The MIT License
+ *
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "pcg64.h"
+
+extern inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng);
+extern inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state);
+extern inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng,
+ pcg128_t initstate,
+ pcg128_t initseq);
+extern inline uint64_t
+pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128 *rng);
+extern inline uint64_t
+pcg_setseq_128_xsl_rr_64_boundedrand_r(pcg_state_setseq_128 *rng,
+ uint64_t bound);
+extern inline void pcg_setseq_128_advance_r(pcg_state_setseq_128 *rng,
+ pcg128_t delta);
+
+/* Multi-step advance functions (jump-ahead, jump-back)
+ *
+ * The method used here is based on Brown, "Random Number Generation
+ * with Arbitrary Stride,", Transactions of the American Nuclear
+ * Society (Nov. 1994). The algorithm is very similar to fast
+ * exponentiation.
+ *
+ * Even though delta is an unsigned integer, we can pass a
+ * signed integer to go backwards, it just goes "the long way round".
+ */
+
+#ifndef PCG_EMULATED_128BIT_MATH
+
+pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult,
+ pcg128_t cur_plus) {
+ pcg128_t acc_mult = 1u;
+ pcg128_t acc_plus = 0u;
+ while (delta > 0) {
+ if (delta & 1) {
+ acc_mult *= cur_mult;
+ acc_plus = acc_plus * cur_mult + cur_plus;
+ }
+ cur_plus = (cur_mult + 1) * cur_plus;
+ cur_mult *= cur_mult;
+ delta /= 2;
+ }
+ return acc_mult * state + acc_plus;
+}
+
+#else
+
+pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult,
+ pcg128_t cur_plus) {
+ pcg128_t acc_mult = PCG_128BIT_CONSTANT(0u, 1u);
+ pcg128_t acc_plus = PCG_128BIT_CONSTANT(0u, 0u);
+ while ((delta.high > 0) || (delta.low > 0)) {
+ if (delta.low & 1) {
+ acc_mult = pcg128_mult(acc_mult, cur_mult);
+ acc_plus = pcg128_add(pcg128_mult(acc_plus, cur_mult), cur_plus);
+ }
+ cur_plus = pcg128_mult(pcg128_add(cur_mult, PCG_128BIT_CONSTANT(0u, 1u)),
+ cur_plus);
+ cur_mult = pcg128_mult(cur_mult, cur_mult);
+ delta.low >>= 1;
+ delta.low += delta.high & 1;
+ delta.high >>= 1;
+ }
+ return pcg128_add(pcg128_mult(acc_mult, state), acc_plus);
+}
+
+#endif
+
+extern inline uint64_t pcg64_next64(pcg64_state *state);
+extern inline uint32_t pcg64_next32(pcg64_state *state);
+
+extern void pcg64_advance(pcg64_state *state, uint64_t *step) {
+ pcg128_t delta;
+#ifndef PCG_EMULATED_128BIT_MATH
+ delta = (((pcg128_t)step[0]) << 64) | step[1];
+#else
+ delta.high = step[0];
+ delta.low = step[1];
+#endif
+ pcg64_advance_r(state->pcg_state, delta);
+}
+
+extern void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc) {
+ pcg128_t s, i;
+#ifndef PCG_EMULATED_128BIT_MATH
+ s = (((pcg128_t)seed[0]) << 64) | seed[1];
+ i = (((pcg128_t)inc[0]) << 64) | inc[1];
+#else
+ s.high = seed[0];
+ s.low = seed[1];
+ i.high = inc[0];
+ i.low = inc[1];
+#endif
+ pcg64_srandom_r(state->pcg_state, s, i);
+}
+
+extern void pcg64_get_state(pcg64_state *state, uint64_t *state_arr,
+ int *has_uint32, uint32_t *uinteger) {
+ /*
+ * state_arr contains state.high, state.low, inc.high, inc.low
+ * which are interpreted as the upper 64 bits (high) or lower
+ * 64 bits of a uint128_t variable
+ *
+ */
+#ifndef PCG_EMULATED_128BIT_MATH
+ state_arr[0] = (uint64_t)(state->pcg_state->state >> 64);
+ state_arr[1] = (uint64_t)(state->pcg_state->state & 0xFFFFFFFFFFFFFFFFULL);
+ state_arr[2] = (uint64_t)(state->pcg_state->inc >> 64);
+ state_arr[3] = (uint64_t)(state->pcg_state->inc & 0xFFFFFFFFFFFFFFFFULL);
+#else
+ state_arr[0] = (uint64_t)state->pcg_state->state.high;
+ state_arr[1] = (uint64_t)state->pcg_state->state.low;
+ state_arr[2] = (uint64_t)state->pcg_state->inc.high;
+ state_arr[3] = (uint64_t)state->pcg_state->inc.low;
+#endif
+ has_uint32[0] = state->has_uint32;
+ uinteger[0] = state->uinteger;
+}
+
+extern void pcg64_set_state(pcg64_state *state, uint64_t *state_arr,
+ int has_uint32, uint32_t uinteger) {
+ /*
+ * state_arr contains state.high, state.low, inc.high, inc.low
+ * which are interpreted as the upper 64 bits (high) or lower
+ * 64 bits of a uint128_t variable
+ *
+ */
+#ifndef PCG_EMULATED_128BIT_MATH
+ state->pcg_state->state = (((pcg128_t)state_arr[0]) << 64) | state_arr[1];
+ state->pcg_state->inc = (((pcg128_t)state_arr[2]) << 64) | state_arr[3];
+#else
+ state->pcg_state->state.high = state_arr[0];
+ state->pcg_state->state.low = state_arr[1];
+ state->pcg_state->inc.high = state_arr[2];
+ state->pcg_state->inc.low = state_arr[3];
+#endif
+ state->has_uint32 = has_uint32;
+ state->uinteger = uinteger;
+}
diff --git a/numpy/random/src/pcg64/pcg64.h b/numpy/random/src/pcg64/pcg64.h
new file mode 100644
index 000000000..2a7217dd9
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64.h
@@ -0,0 +1,294 @@
+/*
+ * PCG64 Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ * Copyright 2015 Robert Kern <robert.kern@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ *
+ * Relicensed MIT in May 2019
+ *
+ * The MIT License
+ *
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PCG64_H_INCLUDED
+#define PCG64_H_INCLUDED 1
+
+#include <inttypes.h>
+
+#ifdef _WIN32
+#include <stdlib.h>
+#define inline __forceinline
+#endif
+
+#if __GNUC_GNU_INLINE__ && !defined(__cplusplus)
+#error Nonstandard GNU inlining semantics. Compile with -std=c99 or better.
+#endif
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#if defined(__SIZEOF_INT128__) && !defined(PCG_FORCE_EMULATED_128BIT_MATH)
+typedef __uint128_t pcg128_t;
+#define PCG_128BIT_CONSTANT(high, low) (((pcg128_t)(high) << 64) + low)
+#else
+typedef struct {
+ uint64_t high;
+ uint64_t low;
+} pcg128_t;
+
+static inline pcg128_t PCG_128BIT_CONSTANT(uint64_t high, uint64_t low) {
+ pcg128_t result;
+ result.high = high;
+ result.low = low;
+ return result;
+}
+
+#define PCG_EMULATED_128BIT_MATH 1
+#endif
+
+typedef struct { pcg128_t state; } pcg_state_128;
+
+typedef struct {
+ pcg128_t state;
+ pcg128_t inc;
+} pcg_state_setseq_128;
+
+#define PCG_DEFAULT_MULTIPLIER_HIGH 2549297995355413924ULL
+#define PCG_DEFAULT_MULTIPLIER_LOW 4865540595714422341ULL
+
+#define PCG_DEFAULT_MULTIPLIER_128 \
+ PCG_128BIT_CONSTANT(PCG_DEFAULT_MULTIPLIER_HIGH, PCG_DEFAULT_MULTIPLIER_LOW)
+#define PCG_DEFAULT_INCREMENT_128 \
+ PCG_128BIT_CONSTANT(6364136223846793005ULL, 1442695040888963407ULL)
+#define PCG_STATE_SETSEQ_128_INITIALIZER \
+ { \
+ PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL) \
+ , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \
+ }
+
+static inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) {
+#ifdef _WIN32
+ return _rotr64(value, rot);
+#else
+ return (value >> rot) | (value << ((-rot) & 63));
+#endif
+}
+
+#ifdef PCG_EMULATED_128BIT_MATH
+
+static inline pcg128_t pcg128_add(pcg128_t a, pcg128_t b) {
+ pcg128_t result;
+
+ result.low = a.low + b.low;
+ result.high = a.high + b.high + (result.low < b.low);
+ return result;
+}
+
+static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1,
+ uint64_t *z0) {
+
+#if defined _WIN32 && _MSC_VER >= 1900 && _M_AMD64
+ z0[0] = _umul128(x, y, z1);
+#else
+ uint64_t x0, x1, y0, y1;
+ uint64_t w0, w1, w2, t;
+ /* Lower 64 bits are straightforward clock-arithmetic. */
+ *z0 = x * y;
+
+ x0 = x & 0xFFFFFFFFULL;
+ x1 = x >> 32;
+ y0 = y & 0xFFFFFFFFULL;
+ y1 = y >> 32;
+ w0 = x0 * y0;
+ t = x1 * y0 + (w0 >> 32);
+ w1 = t & 0xFFFFFFFFULL;
+ w2 = t >> 32;
+ w1 += x0 * y1;
+ *z1 = x1 * y1 + w2 + (w1 >> 32);
+#endif
+}
+
+static inline pcg128_t pcg128_mult(pcg128_t a, pcg128_t b) {
+ uint64_t h1;
+ pcg128_t result;
+
+ h1 = a.high * b.low + a.low * b.high;
+ _pcg_mult64(a.low, b.low, &(result.high), &(result.low));
+ result.high += h1;
+ return result;
+}
+
+static inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) {
+ rng->state = pcg128_add(pcg128_mult(rng->state, PCG_DEFAULT_MULTIPLIER_128),
+ rng->inc);
+}
+
+static inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) {
+ return pcg_rotr_64(state.high ^ state.low, state.high >> 58u);
+}
+
+static inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng,
+ pcg128_t initstate,
+ pcg128_t initseq) {
+ rng->state = PCG_128BIT_CONSTANT(0ULL, 0ULL);
+ rng->inc.high = initseq.high << 1u;
+ rng->inc.high |= initseq.low >> 63u;
+ rng->inc.low = (initseq.low << 1u) | 1u;
+ pcg_setseq_128_step_r(rng);
+ rng->state = pcg128_add(rng->state, initstate);
+ pcg_setseq_128_step_r(rng);
+}
+
+static inline uint64_t
+pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128 *rng) {
+#if defined _WIN32 && _MSC_VER >= 1900 && _M_AMD64
+ uint64_t h1;
+ pcg128_t product;
+
+ /* Manually inline the multiplication and addition using intrinsics */
+ h1 = rng->state.high * PCG_DEFAULT_MULTIPLIER_LOW +
+ rng->state.low * PCG_DEFAULT_MULTIPLIER_HIGH;
+ product.low =
+ _umul128(rng->state.low, PCG_DEFAULT_MULTIPLIER_LOW, &(product.high));
+ product.high += h1;
+ _addcarry_u64(_addcarry_u64(0, product.low, rng->inc.low, &(rng->state.low)),
+ product.high, rng->inc.high, &(rng->state.high));
+ return _rotr64(rng->state.high ^ rng->state.low, rng->state.high >> 58u);
+#else
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+#endif
+}
+
+#else /* PCG_EMULATED_128BIT_MATH */
+
+static inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc;
+}
+
+static inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) {
+ return pcg_rotr_64(((uint64_t)(state >> 64u)) ^ (uint64_t)state,
+ state >> 122u);
+}
+
+static inline uint64_t
+pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128* rng)
+{
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+}
+
+static inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng,
+ pcg128_t initstate,
+ pcg128_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_128_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_128_step_r(rng);
+}
+
+#endif /* PCG_EMULATED_128BIT_MATH */
+
+static inline uint64_t
+pcg_setseq_128_xsl_rr_64_boundedrand_r(pcg_state_setseq_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_128_xsl_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+extern pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta,
+ pcg128_t cur_mult, pcg128_t cur_plus);
+
+static inline void pcg_setseq_128_advance_r(pcg_state_setseq_128 *rng,
+ pcg128_t delta) {
+ rng->state = pcg_advance_lcg_128(rng->state, delta,
+ PCG_DEFAULT_MULTIPLIER_128, rng->inc);
+}
+
+typedef pcg_state_setseq_128 pcg64_random_t;
+#define pcg64_random_r pcg_setseq_128_xsl_rr_64_random_r
+#define pcg64_boundedrand_r pcg_setseq_128_xsl_rr_64_boundedrand_r
+#define pcg64_srandom_r pcg_setseq_128_srandom_r
+#define pcg64_advance_r pcg_setseq_128_advance_r
+#define PCG64_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER
+
+#if __cplusplus
+}
+#endif
+
+typedef struct s_pcg64_state {
+ pcg64_random_t *pcg_state;
+ int has_uint32;
+ uint32_t uinteger;
+} pcg64_state;
+
+static inline uint64_t pcg64_next64(pcg64_state *state) {
+ return pcg64_random_r(state->pcg_state);
+}
+
+static inline uint32_t pcg64_next32(pcg64_state *state) {
+ uint64_t next;
+ if (state->has_uint32) {
+ state->has_uint32 = 0;
+ return state->uinteger;
+ }
+ next = pcg64_random_r(state->pcg_state);
+ state->has_uint32 = 1;
+ state->uinteger = (uint32_t)(next >> 32);
+ return (uint32_t)(next & 0xffffffff);
+}
+
+void pcg64_advance(pcg64_state *state, uint64_t *step);
+
+void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc);
+
+void pcg64_get_state(pcg64_state *state, uint64_t *state_arr, int *has_uint32,
+ uint32_t *uinteger);
+
+void pcg64_set_state(pcg64_state *state, uint64_t *state_arr, int has_uint32,
+ uint32_t uinteger);
+
+#endif /* PCG64_H_INCLUDED */
diff --git a/numpy/random/src/pcg64/pcg64.orig.c b/numpy/random/src/pcg64/pcg64.orig.c
new file mode 100644
index 000000000..07e97e4b6
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64.orig.c
@@ -0,0 +1,11 @@
+#include "pcg64.orig.h"
+
+extern inline void pcg_setseq_128_srandom_r(pcg64_random_t *rng,
+ pcg128_t initstate,
+ pcg128_t initseq);
+
+extern uint64_t pcg_rotr_64(uint64_t value, unsigned int rot);
+extern inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state);
+extern void pcg_setseq_128_step_r(struct pcg_state_setseq_128 *rng);
+extern uint64_t
+pcg_setseq_128_xsl_rr_64_random_r(struct pcg_state_setseq_128 *rng);
diff --git a/numpy/random/src/pcg64/pcg64.orig.h b/numpy/random/src/pcg64/pcg64.orig.h
new file mode 100644
index 000000000..74be91f31
--- /dev/null
+++ b/numpy/random/src/pcg64/pcg64.orig.h
@@ -0,0 +1,2025 @@
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+/*
+ * This code is derived from the canonical C++ PCG implementation, which
+ * has many additional features and is preferable if you can use C++ in
+ * your project.
+ *
+ * Much of the derivation was performed mechanically. In particular, the
+ * output functions were generated by compiling the C++ output functions
+ * into LLVM bitcode and then transforming that using the LLVM C backend
+ * (from https://github.com/draperlaboratory/llvm-cbe), and then
+ * postprocessing and hand editing the output.
+ *
+ * Much of the remaining code was generated by C-preprocessor metaprogramming.
+ */
+
+#ifndef PCG_VARIANTS_H_INCLUDED
+#define PCG_VARIANTS_H_INCLUDED 1
+
+#include <inttypes.h>
+
+#if __SIZEOF_INT128__
+typedef __uint128_t pcg128_t;
+#define PCG_128BIT_CONSTANT(high, low) ((((pcg128_t)high) << 64) + low)
+#define PCG_HAS_128BIT_OPS 1
+#endif
+
+#if __GNUC_GNU_INLINE__ && !defined(__cplusplus)
+#error Nonstandard GNU inlining semantics. Compile with -std=c99 or better.
+// We could instead use macros PCG_INLINE and PCG_EXTERN_INLINE
+// but better to just reject ancient C code.
+#endif
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Rotate helper functions.
+ */
+
+inline uint8_t pcg_rotr_8(uint8_t value, unsigned int rot) {
+/* Unfortunately, clang is kinda pathetic when it comes to properly
+ * recognizing idiomatic rotate code, so for clang we actually provide
+ * assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss.
+ */
+#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__)
+ asm("rorb %%cl, %0" : "=r"(value) : "0"(value), "c"(rot));
+ return value;
+#else
+ return (value >> rot) | (value << ((-rot) & 7));
+#endif
+}
+
+inline uint16_t pcg_rotr_16(uint16_t value, unsigned int rot) {
+#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__)
+ asm("rorw %%cl, %0" : "=r"(value) : "0"(value), "c"(rot));
+ return value;
+#else
+ return (value >> rot) | (value << ((-rot) & 15));
+#endif
+}
+
+inline uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) {
+#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__)
+ asm("rorl %%cl, %0" : "=r"(value) : "0"(value), "c"(rot));
+ return value;
+#else
+ return (value >> rot) | (value << ((-rot) & 31));
+#endif
+}
+
+inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) {
+#if 0 && PCG_USE_INLINE_ASM && __clang__ && __x86_64__
+ // For whatever reason, clang actually *does* generate rotq by
+ // itself, so we don't need this code.
+ asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
+ return value;
+#else
+ return (value >> rot) | (value << ((-rot) & 63));
+#endif
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t pcg_rotr_128(pcg128_t value, unsigned int rot) {
+ return (value >> rot) | (value << ((-rot) & 127));
+}
+#endif
+
+/*
+ * Output functions. These are the core of the PCG generation scheme.
+ */
+
+// XSH RS
+
+inline uint8_t pcg_output_xsh_rs_16_8(uint16_t state) {
+ return (uint8_t)(((state >> 7u) ^ state) >> ((state >> 14u) + 3u));
+}
+
+inline uint16_t pcg_output_xsh_rs_32_16(uint32_t state) {
+ return (uint16_t)(((state >> 11u) ^ state) >> ((state >> 30u) + 11u));
+}
+
+inline uint32_t pcg_output_xsh_rs_64_32(uint64_t state) {
+
+ return (uint32_t)(((state >> 22u) ^ state) >> ((state >> 61u) + 22u));
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_output_xsh_rs_128_64(pcg128_t state) {
+ return (uint64_t)(((state >> 43u) ^ state) >> ((state >> 124u) + 45u));
+}
+#endif
+
+// XSH RR
+
+inline uint8_t pcg_output_xsh_rr_16_8(uint16_t state) {
+ return pcg_rotr_8(((state >> 5u) ^ state) >> 5u, state >> 13u);
+}
+
+inline uint16_t pcg_output_xsh_rr_32_16(uint32_t state) {
+ return pcg_rotr_16(((state >> 10u) ^ state) >> 12u, state >> 28u);
+}
+
+inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) {
+ return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u);
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_output_xsh_rr_128_64(pcg128_t state) {
+ return pcg_rotr_64(((state >> 29u) ^ state) >> 58u, state >> 122u);
+}
+#endif
+
+// RXS M XS
+
+inline uint8_t pcg_output_rxs_m_xs_8_8(uint8_t state) {
+ uint8_t word = ((state >> ((state >> 6u) + 2u)) ^ state) * 217u;
+ return (word >> 6u) ^ word;
+}
+
+inline uint16_t pcg_output_rxs_m_xs_16_16(uint16_t state) {
+ uint16_t word = ((state >> ((state >> 13u) + 3u)) ^ state) * 62169u;
+ return (word >> 11u) ^ word;
+}
+
+inline uint32_t pcg_output_rxs_m_xs_32_32(uint32_t state) {
+ uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
+ return (word >> 22u) ^ word;
+}
+
+inline uint64_t pcg_output_rxs_m_xs_64_64(uint64_t state) {
+ uint64_t word =
+ ((state >> ((state >> 59u) + 5u)) ^ state) * 12605985483714917081ull;
+ return (word >> 43u) ^ word;
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t pcg_output_rxs_m_xs_128_128(pcg128_t state) {
+ pcg128_t word =
+ ((state >> ((state >> 122u) + 6u)) ^ state) *
+ (PCG_128BIT_CONSTANT(17766728186571221404ULL, 12605985483714917081ULL));
+ // 327738287884841127335028083622016905945
+ return (word >> 86u) ^ word;
+}
+#endif
+
+// XSL RR (only defined for >= 64 bits)
+
+inline uint32_t pcg_output_xsl_rr_64_32(uint64_t state) {
+ return pcg_rotr_32(((uint32_t)(state >> 32u)) ^ (uint32_t)state,
+ state >> 59u);
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) {
+ return pcg_rotr_64(((uint64_t)(state >> 64u)) ^ (uint64_t)state,
+ state >> 122u);
+}
+#endif
+
+// XSL RR RR (only defined for >= 64 bits)
+
+inline uint64_t pcg_output_xsl_rr_rr_64_64(uint64_t state) {
+ uint32_t rot1 = (uint32_t)(state >> 59u);
+ uint32_t high = (uint32_t)(state >> 32u);
+ uint32_t low = (uint32_t)state;
+ uint32_t xored = high ^ low;
+ uint32_t newlow = pcg_rotr_32(xored, rot1);
+ uint32_t newhigh = pcg_rotr_32(high, newlow & 31u);
+ return (((uint64_t)newhigh) << 32u) | newlow;
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t pcg_output_xsl_rr_rr_128_128(pcg128_t state) {
+ uint32_t rot1 = (uint32_t)(state >> 122u);
+ uint64_t high = (uint64_t)(state >> 64u);
+ uint64_t low = (uint64_t)state;
+ uint64_t xored = high ^ low;
+ uint64_t newlow = pcg_rotr_64(xored, rot1);
+ uint64_t newhigh = pcg_rotr_64(high, newlow & 63u);
+ return (((pcg128_t)newhigh) << 64u) | newlow;
+}
+#endif
+
+#define PCG_DEFAULT_MULTIPLIER_8 141U
+#define PCG_DEFAULT_MULTIPLIER_16 12829U
+#define PCG_DEFAULT_MULTIPLIER_32 747796405U
+#define PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
+
+#define PCG_DEFAULT_INCREMENT_8 77U
+#define PCG_DEFAULT_INCREMENT_16 47989U
+#define PCG_DEFAULT_INCREMENT_32 2891336453U
+#define PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
+
+#if PCG_HAS_128BIT_OPS
+#define PCG_DEFAULT_MULTIPLIER_128 \
+ PCG_128BIT_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL)
+#define PCG_DEFAULT_INCREMENT_128 \
+ PCG_128BIT_CONSTANT(6364136223846793005ULL, 1442695040888963407ULL)
+#endif
+
+ /*
+ * Static initialization constants (if you can't call srandom for some
+ * bizarre reason).
+ */
+
+#define PCG_STATE_ONESEQ_8_INITIALIZER \
+ { 0xd7U }
+#define PCG_STATE_ONESEQ_16_INITIALIZER \
+ { 0x20dfU }
+#define PCG_STATE_ONESEQ_32_INITIALIZER \
+ { 0x46b56677U }
+#define PCG_STATE_ONESEQ_64_INITIALIZER \
+ { 0x4d595df4d0f33173ULL }
+#if PCG_HAS_128BIT_OPS
+#define PCG_STATE_ONESEQ_128_INITIALIZER \
+ { PCG_128BIT_CONSTANT(0xb8dc10e158a92392ULL, 0x98046df007ec0a53ULL) }
+#endif
+
+#define PCG_STATE_UNIQUE_8_INITIALIZER PCG_STATE_ONESEQ_8_INITIALIZER
+#define PCG_STATE_UNIQUE_16_INITIALIZER PCG_STATE_ONESEQ_16_INITIALIZER
+#define PCG_STATE_UNIQUE_32_INITIALIZER PCG_STATE_ONESEQ_32_INITIALIZER
+#define PCG_STATE_UNIQUE_64_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER
+#if PCG_HAS_128BIT_OPS
+#define PCG_STATE_UNIQUE_128_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER
+#endif
+
+#define PCG_STATE_MCG_8_INITIALIZER \
+ { 0xe5U }
+#define PCG_STATE_MCG_16_INITIALIZER \
+ { 0xa5e5U }
+#define PCG_STATE_MCG_32_INITIALIZER \
+ { 0xd15ea5e5U }
+#define PCG_STATE_MCG_64_INITIALIZER \
+ { 0xcafef00dd15ea5e5ULL }
+#if PCG_HAS_128BIT_OPS
+#define PCG_STATE_MCG_128_INITIALIZER \
+ { PCG_128BIT_CONSTANT(0x0000000000000000ULL, 0xcafef00dd15ea5e5ULL) }
+#endif
+
+#define PCG_STATE_SETSEQ_8_INITIALIZER \
+ { 0x9bU, 0xdbU }
+#define PCG_STATE_SETSEQ_16_INITIALIZER \
+ { 0xe39bU, 0x5bdbU }
+#define PCG_STATE_SETSEQ_32_INITIALIZER \
+ { 0xec02d89bU, 0x94b95bdbU }
+#define PCG_STATE_SETSEQ_64_INITIALIZER \
+ { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
+#if PCG_HAS_128BIT_OPS
+#define PCG_STATE_SETSEQ_128_INITIALIZER \
+ { \
+ PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL) \
+ , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \
+ }
+#endif
+
+/* Representations for the oneseq, mcg, and unique variants */
+
+struct pcg_state_8 {
+ uint8_t state;
+};
+
+struct pcg_state_16 {
+ uint16_t state;
+};
+
+struct pcg_state_32 {
+ uint32_t state;
+};
+
+struct pcg_state_64 {
+ uint64_t state;
+};
+
+#if PCG_HAS_128BIT_OPS
+struct pcg_state_128 {
+ pcg128_t state;
+};
+#endif
+
+/* Representations setseq variants */
+
+struct pcg_state_setseq_8 {
+ uint8_t state;
+ uint8_t inc;
+};
+
+struct pcg_state_setseq_16 {
+ uint16_t state;
+ uint16_t inc;
+};
+
+struct pcg_state_setseq_32 {
+ uint32_t state;
+ uint32_t inc;
+};
+
+struct pcg_state_setseq_64 {
+ uint64_t state;
+ uint64_t inc;
+};
+
+#if PCG_HAS_128BIT_OPS
+struct pcg_state_setseq_128 {
+ pcg128_t state;
+ pcg128_t inc;
+};
+#endif
+
+/* Multi-step advance functions (jump-ahead, jump-back) */
+
+extern uint8_t pcg_advance_lcg_8(uint8_t state, uint8_t delta, uint8_t cur_mult,
+ uint8_t cur_plus);
+extern uint16_t pcg_advance_lcg_16(uint16_t state, uint16_t delta,
+ uint16_t cur_mult, uint16_t cur_plus);
+extern uint32_t pcg_advance_lcg_32(uint32_t state, uint32_t delta,
+ uint32_t cur_mult, uint32_t cur_plus);
+extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta,
+ uint64_t cur_mult, uint64_t cur_plus);
+
+#if PCG_HAS_128BIT_OPS
+extern pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta,
+ pcg128_t cur_mult, pcg128_t cur_plus);
+#endif
+
+/* Functions to advance the underlying LCG, one version for each size and
+ * each style. These functions are considered semi-private. There is rarely
+ * a good reason to call them directly.
+ */
+
+inline void pcg_oneseq_8_step_r(struct pcg_state_8 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8 + PCG_DEFAULT_INCREMENT_8;
+}
+
+inline void pcg_oneseq_8_advance_r(struct pcg_state_8 *rng, uint8_t delta) {
+ rng->state = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8,
+ PCG_DEFAULT_INCREMENT_8);
+}
+
+inline void pcg_mcg_8_step_r(struct pcg_state_8 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8;
+}
+
+inline void pcg_mcg_8_advance_r(struct pcg_state_8 *rng, uint8_t delta) {
+ rng->state =
+ pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, 0u);
+}
+
+inline void pcg_unique_8_step_r(struct pcg_state_8 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_8 + (uint8_t)(((intptr_t)rng) | 1u);
+}
+
+inline void pcg_unique_8_advance_r(struct pcg_state_8 *rng, uint8_t delta) {
+ rng->state = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8,
+ (uint8_t)(((intptr_t)rng) | 1u));
+}
+
+inline void pcg_setseq_8_step_r(struct pcg_state_setseq_8 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8 + rng->inc;
+}
+
+inline void pcg_setseq_8_advance_r(struct pcg_state_setseq_8 *rng,
+ uint8_t delta) {
+ rng->state =
+ pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, rng->inc);
+}
+
+inline void pcg_oneseq_16_step_r(struct pcg_state_16 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_16 + PCG_DEFAULT_INCREMENT_16;
+}
+
+inline void pcg_oneseq_16_advance_r(struct pcg_state_16 *rng, uint16_t delta) {
+ rng->state = pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16,
+ PCG_DEFAULT_INCREMENT_16);
+}
+
+inline void pcg_mcg_16_step_r(struct pcg_state_16 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16;
+}
+
+inline void pcg_mcg_16_advance_r(struct pcg_state_16 *rng, uint16_t delta) {
+ rng->state =
+ pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16, 0u);
+}
+
+inline void pcg_unique_16_step_r(struct pcg_state_16 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_16 + (uint16_t)(((intptr_t)rng) | 1u);
+}
+
+inline void pcg_unique_16_advance_r(struct pcg_state_16 *rng, uint16_t delta) {
+ rng->state = pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16,
+ (uint16_t)(((intptr_t)rng) | 1u));
+}
+
+inline void pcg_setseq_16_step_r(struct pcg_state_setseq_16 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16 + rng->inc;
+}
+
+inline void pcg_setseq_16_advance_r(struct pcg_state_setseq_16 *rng,
+ uint16_t delta) {
+ rng->state = pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16,
+ rng->inc);
+}
+
+inline void pcg_oneseq_32_step_r(struct pcg_state_32 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_32 + PCG_DEFAULT_INCREMENT_32;
+}
+
+inline void pcg_oneseq_32_advance_r(struct pcg_state_32 *rng, uint32_t delta) {
+ rng->state = pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32,
+ PCG_DEFAULT_INCREMENT_32);
+}
+
+inline void pcg_mcg_32_step_r(struct pcg_state_32 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32;
+}
+
+inline void pcg_mcg_32_advance_r(struct pcg_state_32 *rng, uint32_t delta) {
+ rng->state =
+ pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32, 0u);
+}
+
+inline void pcg_unique_32_step_r(struct pcg_state_32 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_32 + (uint32_t)(((intptr_t)rng) | 1u);
+}
+
+inline void pcg_unique_32_advance_r(struct pcg_state_32 *rng, uint32_t delta) {
+ rng->state = pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32,
+ (uint32_t)(((intptr_t)rng) | 1u));
+}
+
+inline void pcg_setseq_32_step_r(struct pcg_state_setseq_32 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32 + rng->inc;
+}
+
+inline void pcg_setseq_32_advance_r(struct pcg_state_setseq_32 *rng,
+ uint32_t delta) {
+ rng->state = pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32,
+ rng->inc);
+}
+
+inline void pcg_oneseq_64_step_r(struct pcg_state_64 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_64 + PCG_DEFAULT_INCREMENT_64;
+}
+
+inline void pcg_oneseq_64_advance_r(struct pcg_state_64 *rng, uint64_t delta) {
+ rng->state = pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64,
+ PCG_DEFAULT_INCREMENT_64);
+}
+
+inline void pcg_mcg_64_step_r(struct pcg_state_64 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64;
+}
+
+inline void pcg_mcg_64_advance_r(struct pcg_state_64 *rng, uint64_t delta) {
+ rng->state =
+ pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64, 0u);
+}
+
+inline void pcg_unique_64_step_r(struct pcg_state_64 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_64 + (uint64_t)(((intptr_t)rng) | 1u);
+}
+
+inline void pcg_unique_64_advance_r(struct pcg_state_64 *rng, uint64_t delta) {
+ rng->state = pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64,
+ (uint64_t)(((intptr_t)rng) | 1u));
+}
+
+inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc;
+}
+
+inline void pcg_setseq_64_advance_r(struct pcg_state_setseq_64 *rng,
+ uint64_t delta) {
+ rng->state = pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64,
+ rng->inc);
+}
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_oneseq_128_step_r(struct pcg_state_128 *rng) {
+ rng->state =
+ rng->state * PCG_DEFAULT_MULTIPLIER_128 + PCG_DEFAULT_INCREMENT_128;
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_oneseq_128_advance_r(struct pcg_state_128 *rng,
+ pcg128_t delta) {
+ rng->state = pcg_advance_lcg_128(
+ rng->state, delta, PCG_DEFAULT_MULTIPLIER_128, PCG_DEFAULT_INCREMENT_128);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_mcg_128_step_r(struct pcg_state_128 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128;
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_mcg_128_advance_r(struct pcg_state_128 *rng, pcg128_t delta) {
+ rng->state =
+ pcg_advance_lcg_128(rng->state, delta, PCG_DEFAULT_MULTIPLIER_128, 0u);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_unique_128_step_r(struct pcg_state_128 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 +
+ (pcg128_t)(((intptr_t)rng) | 1u);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_unique_128_advance_r(struct pcg_state_128 *rng,
+ pcg128_t delta) {
+ rng->state =
+ pcg_advance_lcg_128(rng->state, delta, PCG_DEFAULT_MULTIPLIER_128,
+ (pcg128_t)(((intptr_t)rng) | 1u));
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_setseq_128_step_r(struct pcg_state_setseq_128 *rng) {
+ rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc;
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_setseq_128_advance_r(struct pcg_state_setseq_128 *rng,
+ pcg128_t delta) {
+ rng->state = pcg_advance_lcg_128(rng->state, delta,
+ PCG_DEFAULT_MULTIPLIER_128, rng->inc);
+}
+#endif
+
+/* Functions to seed the RNG state, one version for each size and each
+ * style. Unlike the step functions, regular users can and should call
+ * these functions.
+ */
+
+inline void pcg_oneseq_8_srandom_r(struct pcg_state_8 *rng, uint8_t initstate) {
+ rng->state = 0U;
+ pcg_oneseq_8_step_r(rng);
+ rng->state += initstate;
+ pcg_oneseq_8_step_r(rng);
+}
+
+inline void pcg_mcg_8_srandom_r(struct pcg_state_8 *rng, uint8_t initstate) {
+ rng->state = initstate | 1u;
+}
+
+inline void pcg_unique_8_srandom_r(struct pcg_state_8 *rng, uint8_t initstate) {
+ rng->state = 0U;
+ pcg_unique_8_step_r(rng);
+ rng->state += initstate;
+ pcg_unique_8_step_r(rng);
+}
+
+inline void pcg_setseq_8_srandom_r(struct pcg_state_setseq_8 *rng,
+ uint8_t initstate, uint8_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_8_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_8_step_r(rng);
+}
+
+inline void pcg_oneseq_16_srandom_r(struct pcg_state_16 *rng,
+ uint16_t initstate) {
+ rng->state = 0U;
+ pcg_oneseq_16_step_r(rng);
+ rng->state += initstate;
+ pcg_oneseq_16_step_r(rng);
+}
+
+inline void pcg_mcg_16_srandom_r(struct pcg_state_16 *rng, uint16_t initstate) {
+ rng->state = initstate | 1u;
+}
+
+inline void pcg_unique_16_srandom_r(struct pcg_state_16 *rng,
+ uint16_t initstate) {
+ rng->state = 0U;
+ pcg_unique_16_step_r(rng);
+ rng->state += initstate;
+ pcg_unique_16_step_r(rng);
+}
+
+inline void pcg_setseq_16_srandom_r(struct pcg_state_setseq_16 *rng,
+ uint16_t initstate, uint16_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_16_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_16_step_r(rng);
+}
+
+inline void pcg_oneseq_32_srandom_r(struct pcg_state_32 *rng,
+ uint32_t initstate) {
+ rng->state = 0U;
+ pcg_oneseq_32_step_r(rng);
+ rng->state += initstate;
+ pcg_oneseq_32_step_r(rng);
+}
+
+inline void pcg_mcg_32_srandom_r(struct pcg_state_32 *rng, uint32_t initstate) {
+ rng->state = initstate | 1u;
+}
+
+inline void pcg_unique_32_srandom_r(struct pcg_state_32 *rng,
+ uint32_t initstate) {
+ rng->state = 0U;
+ pcg_unique_32_step_r(rng);
+ rng->state += initstate;
+ pcg_unique_32_step_r(rng);
+}
+
+inline void pcg_setseq_32_srandom_r(struct pcg_state_setseq_32 *rng,
+ uint32_t initstate, uint32_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_32_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_32_step_r(rng);
+}
+
+inline void pcg_oneseq_64_srandom_r(struct pcg_state_64 *rng,
+ uint64_t initstate) {
+ rng->state = 0U;
+ pcg_oneseq_64_step_r(rng);
+ rng->state += initstate;
+ pcg_oneseq_64_step_r(rng);
+}
+
+inline void pcg_mcg_64_srandom_r(struct pcg_state_64 *rng, uint64_t initstate) {
+ rng->state = initstate | 1u;
+}
+
+inline void pcg_unique_64_srandom_r(struct pcg_state_64 *rng,
+ uint64_t initstate) {
+ rng->state = 0U;
+ pcg_unique_64_step_r(rng);
+ rng->state += initstate;
+ pcg_unique_64_step_r(rng);
+}
+
+inline void pcg_setseq_64_srandom_r(struct pcg_state_setseq_64 *rng,
+ uint64_t initstate, uint64_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_64_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_64_step_r(rng);
+}
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_oneseq_128_srandom_r(struct pcg_state_128 *rng,
+ pcg128_t initstate) {
+ rng->state = 0U;
+ pcg_oneseq_128_step_r(rng);
+ rng->state += initstate;
+ pcg_oneseq_128_step_r(rng);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_mcg_128_srandom_r(struct pcg_state_128 *rng,
+ pcg128_t initstate) {
+ rng->state = initstate | 1u;
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_unique_128_srandom_r(struct pcg_state_128 *rng,
+ pcg128_t initstate) {
+ rng->state = 0U;
+ pcg_unique_128_step_r(rng);
+ rng->state += initstate;
+ pcg_unique_128_step_r(rng);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline void pcg_setseq_128_srandom_r(struct pcg_state_setseq_128 *rng,
+ pcg128_t initstate, pcg128_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg_setseq_128_step_r(rng);
+ rng->state += initstate;
+ pcg_setseq_128_step_r(rng);
+}
+#endif
+
+/* Now, finally we create each of the individual generators. We provide
+ * a random_r function that provides a random number of the appropriate
+ * type (using the full range of the type) and a boundedrand_r version
+ * that provides
+ *
+ * Implementation notes for boundedrand_r:
+ *
+ * To avoid bias, we need to make the range of the RNG a multiple of
+ * bound, which we do by dropping output less than a threshold.
+ * Let's consider a 32-bit case... A naive scheme to calculate the
+ * threshold would be to do
+ *
+ * uint32_t threshold = 0x100000000ull % bound;
+ *
+ * but 64-bit div/mod is slower than 32-bit div/mod (especially on
+ * 32-bit platforms). In essence, we do
+ *
+ * uint32_t threshold = (0x100000000ull-bound) % bound;
+ *
+ * because this version will calculate the same modulus, but the LHS
+ * value is less than 2^32.
+ *
+ * (Note that using modulo is only wise for good RNGs, poorer RNGs
+ * such as raw LCGs do better using a technique based on division.)
+ * Empricical tests show that division is preferable to modulus for
+ * reducting the range of an RNG. It's faster, and sometimes it can
+ * even be statistically prefereable.
+ */
+
+/* Generation functions for XSH RS */
+
+inline uint8_t pcg_oneseq_16_xsh_rs_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_oneseq_16_step_r(rng);
+ return pcg_output_xsh_rs_16_8(oldstate);
+}
+
+inline uint8_t pcg_oneseq_16_xsh_rs_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_oneseq_16_xsh_rs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_oneseq_32_xsh_rs_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_oneseq_32_step_r(rng);
+ return pcg_output_xsh_rs_32_16(oldstate);
+}
+
+inline uint16_t pcg_oneseq_32_xsh_rs_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_oneseq_32_xsh_rs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_oneseq_64_xsh_rs_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_oneseq_64_step_r(rng);
+ return pcg_output_xsh_rs_64_32(oldstate);
+}
+
+inline uint32_t pcg_oneseq_64_xsh_rs_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_oneseq_64_xsh_rs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_oneseq_128_xsh_rs_64_random_r(struct pcg_state_128 *rng) {
+ pcg_oneseq_128_step_r(rng);
+ return pcg_output_xsh_rs_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_oneseq_128_xsh_rs_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_oneseq_128_xsh_rs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t pcg_unique_16_xsh_rs_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_unique_16_step_r(rng);
+ return pcg_output_xsh_rs_16_8(oldstate);
+}
+
+inline uint8_t pcg_unique_16_xsh_rs_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_unique_16_xsh_rs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_unique_32_xsh_rs_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_unique_32_step_r(rng);
+ return pcg_output_xsh_rs_32_16(oldstate);
+}
+
+inline uint16_t pcg_unique_32_xsh_rs_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_unique_32_xsh_rs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_unique_64_xsh_rs_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_unique_64_step_r(rng);
+ return pcg_output_xsh_rs_64_32(oldstate);
+}
+
+inline uint32_t pcg_unique_64_xsh_rs_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_unique_64_xsh_rs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_unique_128_xsh_rs_64_random_r(struct pcg_state_128 *rng) {
+ pcg_unique_128_step_r(rng);
+ return pcg_output_xsh_rs_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_unique_128_xsh_rs_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_unique_128_xsh_rs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t
+pcg_setseq_16_xsh_rs_8_random_r(struct pcg_state_setseq_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_setseq_16_step_r(rng);
+ return pcg_output_xsh_rs_16_8(oldstate);
+}
+
+inline uint8_t
+pcg_setseq_16_xsh_rs_8_boundedrand_r(struct pcg_state_setseq_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_setseq_16_xsh_rs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t
+pcg_setseq_32_xsh_rs_16_random_r(struct pcg_state_setseq_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_setseq_32_step_r(rng);
+ return pcg_output_xsh_rs_32_16(oldstate);
+}
+
+inline uint16_t
+pcg_setseq_32_xsh_rs_16_boundedrand_r(struct pcg_state_setseq_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_setseq_32_xsh_rs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t
+pcg_setseq_64_xsh_rs_32_random_r(struct pcg_state_setseq_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_setseq_64_step_r(rng);
+ return pcg_output_xsh_rs_64_32(oldstate);
+}
+
+inline uint32_t
+pcg_setseq_64_xsh_rs_32_boundedrand_r(struct pcg_state_setseq_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_setseq_64_xsh_rs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsh_rs_64_random_r(struct pcg_state_setseq_128 *rng) {
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsh_rs_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsh_rs_64_boundedrand_r(struct pcg_state_setseq_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_128_xsh_rs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t pcg_mcg_16_xsh_rs_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_mcg_16_step_r(rng);
+ return pcg_output_xsh_rs_16_8(oldstate);
+}
+
+inline uint8_t pcg_mcg_16_xsh_rs_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_mcg_16_xsh_rs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_mcg_32_xsh_rs_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_mcg_32_step_r(rng);
+ return pcg_output_xsh_rs_32_16(oldstate);
+}
+
+inline uint16_t pcg_mcg_32_xsh_rs_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_mcg_32_xsh_rs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_mcg_64_xsh_rs_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_mcg_64_step_r(rng);
+ return pcg_output_xsh_rs_64_32(oldstate);
+}
+
+inline uint32_t pcg_mcg_64_xsh_rs_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_mcg_64_xsh_rs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsh_rs_64_random_r(struct pcg_state_128 *rng) {
+ pcg_mcg_128_step_r(rng);
+ return pcg_output_xsh_rs_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsh_rs_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_mcg_128_xsh_rs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+/* Generation functions for XSH RR */
+
+inline uint8_t pcg_oneseq_16_xsh_rr_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_oneseq_16_step_r(rng);
+ return pcg_output_xsh_rr_16_8(oldstate);
+}
+
+inline uint8_t pcg_oneseq_16_xsh_rr_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_oneseq_16_xsh_rr_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_oneseq_32_xsh_rr_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_oneseq_32_step_r(rng);
+ return pcg_output_xsh_rr_32_16(oldstate);
+}
+
+inline uint16_t pcg_oneseq_32_xsh_rr_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_oneseq_32_xsh_rr_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_oneseq_64_xsh_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_oneseq_64_step_r(rng);
+ return pcg_output_xsh_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_oneseq_64_xsh_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_oneseq_64_xsh_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_oneseq_128_xsh_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_oneseq_128_step_r(rng);
+ return pcg_output_xsh_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_oneseq_128_xsh_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_oneseq_128_xsh_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t pcg_unique_16_xsh_rr_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_unique_16_step_r(rng);
+ return pcg_output_xsh_rr_16_8(oldstate);
+}
+
+inline uint8_t pcg_unique_16_xsh_rr_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_unique_16_xsh_rr_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_unique_32_xsh_rr_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_unique_32_step_r(rng);
+ return pcg_output_xsh_rr_32_16(oldstate);
+}
+
+inline uint16_t pcg_unique_32_xsh_rr_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_unique_32_xsh_rr_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_unique_64_xsh_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_unique_64_step_r(rng);
+ return pcg_output_xsh_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_unique_64_xsh_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_unique_64_xsh_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_unique_128_xsh_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_unique_128_step_r(rng);
+ return pcg_output_xsh_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_unique_128_xsh_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_unique_128_xsh_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t
+pcg_setseq_16_xsh_rr_8_random_r(struct pcg_state_setseq_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_setseq_16_step_r(rng);
+ return pcg_output_xsh_rr_16_8(oldstate);
+}
+
+inline uint8_t
+pcg_setseq_16_xsh_rr_8_boundedrand_r(struct pcg_state_setseq_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_setseq_16_xsh_rr_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t
+pcg_setseq_32_xsh_rr_16_random_r(struct pcg_state_setseq_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_setseq_32_step_r(rng);
+ return pcg_output_xsh_rr_32_16(oldstate);
+}
+
+inline uint16_t
+pcg_setseq_32_xsh_rr_16_boundedrand_r(struct pcg_state_setseq_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_setseq_32_xsh_rr_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t
+pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_setseq_64_step_r(rng);
+ return pcg_output_xsh_rr_64_32(oldstate);
+}
+
+inline uint32_t
+pcg_setseq_64_xsh_rr_32_boundedrand_r(struct pcg_state_setseq_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_setseq_64_xsh_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsh_rr_64_random_r(struct pcg_state_setseq_128 *rng) {
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsh_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsh_rr_64_boundedrand_r(struct pcg_state_setseq_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_128_xsh_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t pcg_mcg_16_xsh_rr_8_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_mcg_16_step_r(rng);
+ return pcg_output_xsh_rr_16_8(oldstate);
+}
+
+inline uint8_t pcg_mcg_16_xsh_rr_8_boundedrand_r(struct pcg_state_16 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_mcg_16_xsh_rr_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_mcg_32_xsh_rr_16_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_mcg_32_step_r(rng);
+ return pcg_output_xsh_rr_32_16(oldstate);
+}
+
+inline uint16_t pcg_mcg_32_xsh_rr_16_boundedrand_r(struct pcg_state_32 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_mcg_32_xsh_rr_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_mcg_64_xsh_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_mcg_64_step_r(rng);
+ return pcg_output_xsh_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_mcg_64_xsh_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_mcg_64_xsh_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsh_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_mcg_128_step_r(rng);
+ return pcg_output_xsh_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsh_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_mcg_128_xsh_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+/* Generation functions for RXS M XS (no MCG versions because they
+ * don't make sense when you want to use the entire state)
+ */
+
+inline uint8_t pcg_oneseq_8_rxs_m_xs_8_random_r(struct pcg_state_8 *rng) {
+ uint8_t oldstate = rng->state;
+ pcg_oneseq_8_step_r(rng);
+ return pcg_output_rxs_m_xs_8_8(oldstate);
+}
+
+inline uint8_t pcg_oneseq_8_rxs_m_xs_8_boundedrand_r(struct pcg_state_8 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_oneseq_8_rxs_m_xs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t pcg_oneseq_16_rxs_m_xs_16_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_oneseq_16_step_r(rng);
+ return pcg_output_rxs_m_xs_16_16(oldstate);
+}
+
+inline uint16_t
+pcg_oneseq_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_16 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_oneseq_16_rxs_m_xs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_oneseq_32_rxs_m_xs_32_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_oneseq_32_step_r(rng);
+ return pcg_output_rxs_m_xs_32_32(oldstate);
+}
+
+inline uint32_t
+pcg_oneseq_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_32 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_oneseq_32_rxs_m_xs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint64_t pcg_oneseq_64_rxs_m_xs_64_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_oneseq_64_step_r(rng);
+ return pcg_output_rxs_m_xs_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_oneseq_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_oneseq_64_rxs_m_xs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_oneseq_128_rxs_m_xs_128_random_r(struct pcg_state_128 *rng) {
+ pcg_oneseq_128_step_r(rng);
+ return pcg_output_rxs_m_xs_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_oneseq_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_oneseq_128_rxs_m_xs_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint16_t pcg_unique_16_rxs_m_xs_16_random_r(struct pcg_state_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_unique_16_step_r(rng);
+ return pcg_output_rxs_m_xs_16_16(oldstate);
+}
+
+inline uint16_t
+pcg_unique_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_16 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_unique_16_rxs_m_xs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t pcg_unique_32_rxs_m_xs_32_random_r(struct pcg_state_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_unique_32_step_r(rng);
+ return pcg_output_rxs_m_xs_32_32(oldstate);
+}
+
+inline uint32_t
+pcg_unique_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_32 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_unique_32_rxs_m_xs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint64_t pcg_unique_64_rxs_m_xs_64_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_unique_64_step_r(rng);
+ return pcg_output_rxs_m_xs_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_unique_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_unique_64_rxs_m_xs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_unique_128_rxs_m_xs_128_random_r(struct pcg_state_128 *rng) {
+ pcg_unique_128_step_r(rng);
+ return pcg_output_rxs_m_xs_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_unique_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_unique_128_rxs_m_xs_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint8_t
+pcg_setseq_8_rxs_m_xs_8_random_r(struct pcg_state_setseq_8 *rng) {
+ uint8_t oldstate = rng->state;
+ pcg_setseq_8_step_r(rng);
+ return pcg_output_rxs_m_xs_8_8(oldstate);
+}
+
+inline uint8_t
+pcg_setseq_8_rxs_m_xs_8_boundedrand_r(struct pcg_state_setseq_8 *rng,
+ uint8_t bound) {
+ uint8_t threshold = ((uint8_t)(-bound)) % bound;
+ for (;;) {
+ uint8_t r = pcg_setseq_8_rxs_m_xs_8_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint16_t
+pcg_setseq_16_rxs_m_xs_16_random_r(struct pcg_state_setseq_16 *rng) {
+ uint16_t oldstate = rng->state;
+ pcg_setseq_16_step_r(rng);
+ return pcg_output_rxs_m_xs_16_16(oldstate);
+}
+
+inline uint16_t
+pcg_setseq_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_setseq_16 *rng,
+ uint16_t bound) {
+ uint16_t threshold = ((uint16_t)(-bound)) % bound;
+ for (;;) {
+ uint16_t r = pcg_setseq_16_rxs_m_xs_16_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint32_t
+pcg_setseq_32_rxs_m_xs_32_random_r(struct pcg_state_setseq_32 *rng) {
+ uint32_t oldstate = rng->state;
+ pcg_setseq_32_step_r(rng);
+ return pcg_output_rxs_m_xs_32_32(oldstate);
+}
+
+inline uint32_t
+pcg_setseq_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_setseq_32 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_setseq_32_rxs_m_xs_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+inline uint64_t
+pcg_setseq_64_rxs_m_xs_64_random_r(struct pcg_state_setseq_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_setseq_64_step_r(rng);
+ return pcg_output_rxs_m_xs_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_setseq_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_setseq_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_64_rxs_m_xs_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_setseq_128_rxs_m_xs_128_random_r(struct pcg_state_setseq_128 *rng) {
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_rxs_m_xs_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_setseq_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_setseq_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_setseq_128_rxs_m_xs_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+/* Generation functions for XSL RR (only defined for "large" types) */
+
+inline uint32_t pcg_oneseq_64_xsl_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_oneseq_64_step_r(rng);
+ return pcg_output_xsl_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_oneseq_64_xsl_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_oneseq_64_xsl_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_oneseq_128_xsl_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_oneseq_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_oneseq_128_xsl_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_oneseq_128_xsl_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint32_t pcg_unique_64_xsl_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_unique_64_step_r(rng);
+ return pcg_output_xsl_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_unique_64_xsl_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_unique_64_xsl_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_unique_128_xsl_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_unique_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_unique_128_xsl_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_unique_128_xsl_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint32_t
+pcg_setseq_64_xsl_rr_32_random_r(struct pcg_state_setseq_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_setseq_64_step_r(rng);
+ return pcg_output_xsl_rr_64_32(oldstate);
+}
+
+inline uint32_t
+pcg_setseq_64_xsl_rr_32_boundedrand_r(struct pcg_state_setseq_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_setseq_64_xsl_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsl_rr_64_random_r(struct pcg_state_setseq_128 *rng) {
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t
+pcg_setseq_128_xsl_rr_64_boundedrand_r(struct pcg_state_setseq_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_128_xsl_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint32_t pcg_mcg_64_xsl_rr_32_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_mcg_64_step_r(rng);
+ return pcg_output_xsl_rr_64_32(oldstate);
+}
+
+inline uint32_t pcg_mcg_64_xsl_rr_32_boundedrand_r(struct pcg_state_64 *rng,
+ uint32_t bound) {
+ uint32_t threshold = -bound % bound;
+ for (;;) {
+ uint32_t r = pcg_mcg_64_xsl_rr_32_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsl_rr_64_random_r(struct pcg_state_128 *rng) {
+ pcg_mcg_128_step_r(rng);
+ return pcg_output_xsl_rr_128_64(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline uint64_t pcg_mcg_128_xsl_rr_64_boundedrand_r(struct pcg_state_128 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_mcg_128_xsl_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+/* Generation functions for XSL RR RR (only defined for "large" types) */
+
+inline uint64_t pcg_oneseq_64_xsl_rr_rr_64_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_oneseq_64_step_r(rng);
+ return pcg_output_xsl_rr_rr_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_oneseq_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_oneseq_64_xsl_rr_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_oneseq_128_xsl_rr_rr_128_random_r(struct pcg_state_128 *rng) {
+ pcg_oneseq_128_step_r(rng);
+ return pcg_output_xsl_rr_rr_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_oneseq_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_oneseq_128_xsl_rr_rr_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint64_t pcg_unique_64_xsl_rr_rr_64_random_r(struct pcg_state_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_unique_64_step_r(rng);
+ return pcg_output_xsl_rr_rr_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_unique_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_unique_64_xsl_rr_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_unique_128_xsl_rr_rr_128_random_r(struct pcg_state_128 *rng) {
+ pcg_unique_128_step_r(rng);
+ return pcg_output_xsl_rr_rr_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_unique_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_unique_128_xsl_rr_rr_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+inline uint64_t
+pcg_setseq_64_xsl_rr_rr_64_random_r(struct pcg_state_setseq_64 *rng) {
+ uint64_t oldstate = rng->state;
+ pcg_setseq_64_step_r(rng);
+ return pcg_output_xsl_rr_rr_64_64(oldstate);
+}
+
+inline uint64_t
+pcg_setseq_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_setseq_64 *rng,
+ uint64_t bound) {
+ uint64_t threshold = -bound % bound;
+ for (;;) {
+ uint64_t r = pcg_setseq_64_xsl_rr_rr_64_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_setseq_128_xsl_rr_rr_128_random_r(struct pcg_state_setseq_128 *rng) {
+ pcg_setseq_128_step_r(rng);
+ return pcg_output_xsl_rr_rr_128_128(rng->state);
+}
+#endif
+
+#if PCG_HAS_128BIT_OPS
+inline pcg128_t
+pcg_setseq_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_setseq_128 *rng,
+ pcg128_t bound) {
+ pcg128_t threshold = -bound % bound;
+ for (;;) {
+ pcg128_t r = pcg_setseq_128_xsl_rr_rr_128_random_r(rng);
+ if (r >= threshold)
+ return r % bound;
+ }
+}
+#endif
+
+//// Typedefs
+typedef struct pcg_state_setseq_64 pcg32_random_t;
+typedef struct pcg_state_64 pcg32s_random_t;
+typedef struct pcg_state_64 pcg32u_random_t;
+typedef struct pcg_state_64 pcg32f_random_t;
+//// random_r
+#define pcg32_random_r pcg_setseq_64_xsh_rr_32_random_r
+#define pcg32s_random_r pcg_oneseq_64_xsh_rr_32_random_r
+#define pcg32u_random_r pcg_unique_64_xsh_rr_32_random_r
+#define pcg32f_random_r pcg_mcg_64_xsh_rs_32_random_r
+//// boundedrand_r
+#define pcg32_boundedrand_r pcg_setseq_64_xsh_rr_32_boundedrand_r
+#define pcg32s_boundedrand_r pcg_oneseq_64_xsh_rr_32_boundedrand_r
+#define pcg32u_boundedrand_r pcg_unique_64_xsh_rr_32_boundedrand_r
+#define pcg32f_boundedrand_r pcg_mcg_64_xsh_rs_32_boundedrand_r
+//// srandom_r
+#define pcg32_srandom_r pcg_setseq_64_srandom_r
+#define pcg32s_srandom_r pcg_oneseq_64_srandom_r
+#define pcg32u_srandom_r pcg_unique_64_srandom_r
+#define pcg32f_srandom_r pcg_mcg_64_srandom_r
+//// advance_r
+#define pcg32_advance_r pcg_setseq_64_advance_r
+#define pcg32s_advance_r pcg_oneseq_64_advance_r
+#define pcg32u_advance_r pcg_unique_64_advance_r
+#define pcg32f_advance_r pcg_mcg_64_advance_r
+
+#if PCG_HAS_128BIT_OPS
+//// Typedefs
+typedef struct pcg_state_setseq_128 pcg64_random_t;
+typedef struct pcg_state_128 pcg64s_random_t;
+typedef struct pcg_state_128 pcg64u_random_t;
+typedef struct pcg_state_128 pcg64f_random_t;
+//// random_r
+#define pcg64_random_r pcg_setseq_128_xsl_rr_64_random_r
+#define pcg64s_random_r pcg_oneseq_128_xsl_rr_64_random_r
+#define pcg64u_random_r pcg_unique_128_xsl_rr_64_random_r
+#define pcg64f_random_r pcg_mcg_128_xsl_rr_64_random_r
+//// boundedrand_r
+#define pcg64_boundedrand_r pcg_setseq_128_xsl_rr_64_boundedrand_r
+#define pcg64s_boundedrand_r pcg_oneseq_128_xsl_rr_64_boundedrand_r
+#define pcg64u_boundedrand_r pcg_unique_128_xsl_rr_64_boundedrand_r
+#define pcg64f_boundedrand_r pcg_mcg_128_xsl_rr_64_boundedrand_r
+//// srandom_r
+#define pcg64_srandom_r pcg_setseq_128_srandom_r
+#define pcg64s_srandom_r pcg_oneseq_128_srandom_r
+#define pcg64u_srandom_r pcg_unique_128_srandom_r
+#define pcg64f_srandom_r pcg_mcg_128_srandom_r
+//// advance_r
+#define pcg64_advance_r pcg_setseq_128_advance_r
+#define pcg64s_advance_r pcg_oneseq_128_advance_r
+#define pcg64u_advance_r pcg_unique_128_advance_r
+#define pcg64f_advance_r pcg_mcg_128_advance_r
+#endif
+
+//// Typedefs
+typedef struct pcg_state_8 pcg8si_random_t;
+typedef struct pcg_state_16 pcg16si_random_t;
+typedef struct pcg_state_32 pcg32si_random_t;
+typedef struct pcg_state_64 pcg64si_random_t;
+//// random_r
+#define pcg8si_random_r pcg_oneseq_8_rxs_m_xs_8_random_r
+#define pcg16si_random_r pcg_oneseq_16_rxs_m_xs_16_random_r
+#define pcg32si_random_r pcg_oneseq_32_rxs_m_xs_32_random_r
+#define pcg64si_random_r pcg_oneseq_64_rxs_m_xs_64_random_r
+//// boundedrand_r
+#define pcg8si_boundedrand_r pcg_oneseq_8_rxs_m_xs_8_boundedrand_r
+#define pcg16si_boundedrand_r pcg_oneseq_16_rxs_m_xs_16_boundedrand_r
+#define pcg32si_boundedrand_r pcg_oneseq_32_rxs_m_xs_32_boundedrand_r
+#define pcg64si_boundedrand_r pcg_oneseq_64_rxs_m_xs_64_boundedrand_r
+//// srandom_r
+#define pcg8si_srandom_r pcg_oneseq_8_srandom_r
+#define pcg16si_srandom_r pcg_oneseq_16_srandom_r
+#define pcg32si_srandom_r pcg_oneseq_32_srandom_r
+#define pcg64si_srandom_r pcg_oneseq_64_srandom_r
+//// advance_r
+#define pcg8si_advance_r pcg_oneseq_8_advance_r
+#define pcg16si_advance_r pcg_oneseq_16_advance_r
+#define pcg32si_advance_r pcg_oneseq_32_advance_r
+#define pcg64si_advance_r pcg_oneseq_64_advance_r
+
+#if PCG_HAS_128BIT_OPS
+typedef struct pcg_state_128 pcg128si_random_t;
+#define pcg128si_random_r pcg_oneseq_128_rxs_m_xs_128_random_r
+#define pcg128si_boundedrand_r pcg_oneseq_128_rxs_m_xs_128_boundedrand_r
+#define pcg128si_srandom_r pcg_oneseq_128_srandom_r
+#define pcg128si_advance_r pcg_oneseq_128_advance_r
+#endif
+
+//// Typedefs
+typedef struct pcg_state_setseq_8 pcg8i_random_t;
+typedef struct pcg_state_setseq_16 pcg16i_random_t;
+typedef struct pcg_state_setseq_32 pcg32i_random_t;
+typedef struct pcg_state_setseq_64 pcg64i_random_t;
+//// random_r
+#define pcg8i_random_r pcg_setseq_8_rxs_m_xs_8_random_r
+#define pcg16i_random_r pcg_setseq_16_rxs_m_xs_16_random_r
+#define pcg32i_random_r pcg_setseq_32_rxs_m_xs_32_random_r
+#define pcg64i_random_r pcg_setseq_64_rxs_m_xs_64_random_r
+//// boundedrand_r
+#define pcg8i_boundedrand_r pcg_setseq_8_rxs_m_xs_8_boundedrand_r
+#define pcg16i_boundedrand_r pcg_setseq_16_rxs_m_xs_16_boundedrand_r
+#define pcg32i_boundedrand_r pcg_setseq_32_rxs_m_xs_32_boundedrand_r
+#define pcg64i_boundedrand_r pcg_setseq_64_rxs_m_xs_64_boundedrand_r
+//// srandom_r
+#define pcg8i_srandom_r pcg_setseq_8_srandom_r
+#define pcg16i_srandom_r pcg_setseq_16_srandom_r
+#define pcg32i_srandom_r pcg_setseq_32_srandom_r
+#define pcg64i_srandom_r pcg_setseq_64_srandom_r
+//// advance_r
+#define pcg8i_advance_r pcg_setseq_8_advance_r
+#define pcg16i_advance_r pcg_setseq_16_advance_r
+#define pcg32i_advance_r pcg_setseq_32_advance_r
+#define pcg64i_advance_r pcg_setseq_64_advance_r
+
+#if PCG_HAS_128BIT_OPS
+typedef struct pcg_state_setseq_128 pcg128i_random_t;
+#define pcg128i_random_r pcg_setseq_128_rxs_m_xs_128_random_r
+#define pcg128i_boundedrand_r pcg_setseq_128_rxs_m_xs_128_boundedrand_r
+#define pcg128i_srandom_r pcg_setseq_128_srandom_r
+#define pcg128i_advance_r pcg_setseq_128_advance_r
+#endif
+
+extern uint32_t pcg32_random();
+extern uint32_t pcg32_boundedrand(uint32_t bound);
+extern void pcg32_srandom(uint64_t seed, uint64_t seq);
+extern void pcg32_advance(uint64_t delta);
+
+#if PCG_HAS_128BIT_OPS
+extern uint64_t pcg64_random();
+extern uint64_t pcg64_boundedrand(uint64_t bound);
+extern void pcg64_srandom(pcg128_t seed, pcg128_t seq);
+extern void pcg64_advance(pcg128_t delta);
+#endif
+
+/*
+ * Static initialization constants (if you can't call srandom for some
+ * bizarre reason).
+ */
+
+#define PCG32_INITIALIZER PCG_STATE_SETSEQ_64_INITIALIZER
+#define PCG32U_INITIALIZER PCG_STATE_UNIQUE_64_INITIALIZER
+#define PCG32S_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER
+#define PCG32F_INITIALIZER PCG_STATE_MCG_64_INITIALIZER
+
+#if PCG_HAS_128BIT_OPS
+#define PCG64_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER
+#define PCG64U_INITIALIZER PCG_STATE_UNIQUE_128_INITIALIZER
+#define PCG64S_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER
+#define PCG64F_INITIALIZER PCG_STATE_MCG_128_INITIALIZER
+#endif
+
+#define PCG8SI_INITIALIZER PCG_STATE_ONESEQ_8_INITIALIZER
+#define PCG16SI_INITIALIZER PCG_STATE_ONESEQ_16_INITIALIZER
+#define PCG32SI_INITIALIZER PCG_STATE_ONESEQ_32_INITIALIZER
+#define PCG64SI_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER
+#if PCG_HAS_128BIT_OPS
+#define PCG128SI_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER
+#endif
+
+#define PCG8I_INITIALIZER PCG_STATE_SETSEQ_8_INITIALIZER
+#define PCG16I_INITIALIZER PCG_STATE_SETSEQ_16_INITIALIZER
+#define PCG32I_INITIALIZER PCG_STATE_SETSEQ_32_INITIALIZER
+#define PCG64I_INITIALIZER PCG_STATE_SETSEQ_64_INITIALIZER
+#if PCG_HAS_128BIT_OPS
+#define PCG128I_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER
+#endif
+
+#if __cplusplus
+}
+#endif
+
+#endif // PCG_VARIANTS_H_INCLUDED
diff --git a/numpy/random/src/philox/LICENSE.md b/numpy/random/src/philox/LICENSE.md
new file mode 100644
index 000000000..9738e44de
--- /dev/null
+++ b/numpy/random/src/philox/LICENSE.md
@@ -0,0 +1,31 @@
+# PHILOX
+
+Copyright 2010-2012, D. E. Shaw Research.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions, and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions, and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of D. E. Shaw Research nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/numpy/random/src/philox/philox-benchmark.c b/numpy/random/src/philox/philox-benchmark.c
new file mode 100644
index 000000000..df5814d5f
--- /dev/null
+++ b/numpy/random/src/philox/philox-benchmark.c
@@ -0,0 +1,38 @@
+/*
+ * Simple benchamrk command
+ *
+ * cl philox-benchmark.c /Ox
+ *
+ * gcc philox-benchmark.c -O3 -o philox-benchmark
+ *
+ * Requires the Random123 directory containing header files to be located in the
+ * same directory (not included).
+ */
+#include "Random123/philox.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <time.h>
+
+#define N 1000000000
+
+int main() {
+ philox4x64_ctr_t ctr = {{0, 0, 0, 0}};
+ philox4x64_key_t key = {{0, 0xDEADBEAF}};
+ philox4x64_ctr_t out;
+ uint64_t count = 0, sum = 0;
+ int i, j;
+ clock_t begin = clock();
+ for (i = 0; i < N / 4UL; i++) {
+ ctr.v[0]++;
+ out = philox4x64_R(philox4x64_rounds, ctr, key);
+ for (j = 0; j < 4; j++) {
+ sum += out.v[j];
+ count++;
+ }
+ }
+ clock_t end = clock();
+ double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+ printf("0x%" PRIx64 "\ncount: %" PRIu64 "\n", sum, count);
+ printf("%" PRIu64 " randoms per second\n",
+ (uint64_t)(N / time_spent) / 1000000 * 1000000);
+}
diff --git a/numpy/random/src/philox/philox-test-data-gen.c b/numpy/random/src/philox/philox-test-data-gen.c
new file mode 100644
index 000000000..a5fcaa690
--- /dev/null
+++ b/numpy/random/src/philox/philox-test-data-gen.c
@@ -0,0 +1,82 @@
+/*
+ * Generate testing csv files
+ *
+ * cl philox-test-data-gen.c /Ox
+ * philox-test-data-gen.exe
+ *
+ * gcc philox-test-data-gen.c -o philox-test-data-gen
+ * ./philox-test-data-gen
+ *
+ * Requires the Random123 directory containing header files to be located in the
+ * same directory (not included).
+ *
+ */
+
+#include "../splitmix64/splitmix64.h"
+#include "Random123/philox.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#define N 1000
+
+int main() {
+ philox4x64_ctr_t ctr = {{0, 0, 0, 0}};
+ philox4x64_key_t key = {{0, 0}};
+ uint64_t state, seed = 0xDEADBEAF;
+ philox4x64_ctr_t out;
+ uint64_t store[N];
+ state = seed;
+ int i, j;
+ for (i = 0; i < 2; i++) {
+ key.v[i] = splitmix64_next(&state);
+ }
+ for (i = 0; i < N / 4UL; i++) {
+ ctr.v[0]++;
+ out = philox4x64_R(philox4x64_rounds, ctr, key);
+ for (j = 0; j < 4; j++) {
+ store[i * 4 + j] = out.v[j];
+ }
+ }
+
+ FILE *fp;
+ fp = fopen("philox-testset-1.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx64 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+
+ ctr.v[0] = 0;
+ state = seed = 0;
+ for (i = 0; i < 2; i++) {
+ key.v[i] = splitmix64_next(&state);
+ }
+ for (i = 0; i < N / 4UL; i++) {
+ ctr.v[0]++;
+ out = philox4x64_R(philox4x64_rounds, ctr, key);
+ for (j = 0; j < 4; j++) {
+ store[i * 4 + j] = out.v[j];
+ }
+ }
+
+ fp = fopen("philox-testset-2.csv", "w");
+ if (fp == NULL) {
+ printf("Couldn't open file\n");
+ return -1;
+ }
+ fprintf(fp, "seed, 0x%" PRIx64 "\n", seed);
+ for (i = 0; i < N; i++) {
+ fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]);
+ if (i == 999) {
+ printf("%d, 0x%" PRIx64 "\n", i, store[i]);
+ }
+ }
+ fclose(fp);
+}
diff --git a/numpy/random/src/philox/philox.c b/numpy/random/src/philox/philox.c
new file mode 100644
index 000000000..6f2fad5a4
--- /dev/null
+++ b/numpy/random/src/philox/philox.c
@@ -0,0 +1,29 @@
+#include "philox.h"
+
+extern NPY_INLINE uint64_t philox_next64(philox_state *state);
+
+extern NPY_INLINE uint32_t philox_next32(philox_state *state);
+
+extern void philox_jump(philox_state *state) {
+ /* Advances state as-if 2^128 draws were made */
+ state->ctr->v[2]++;
+ if (state->ctr->v[2] == 0) {
+ state->ctr->v[3]++;
+ }
+}
+
+extern void philox_advance(uint64_t *step, philox_state *state) {
+ int i, carry = 0;
+ uint64_t v_orig;
+ for (i = 0; i < 4; i++) {
+ if (carry == 1) {
+ state->ctr->v[i]++;
+ carry = state->ctr->v[i] == 0 ? 1 : 0;
+ }
+ v_orig = state->ctr->v[i];
+ state->ctr->v[i] += step[i];
+ if (state->ctr->v[i] < v_orig && carry == 0) {
+ carry = 1;
+ }
+ }
+}
diff --git a/numpy/random/src/philox/philox.h b/numpy/random/src/philox/philox.h
new file mode 100644
index 000000000..309d89eae
--- /dev/null
+++ b/numpy/random/src/philox/philox.h
@@ -0,0 +1,248 @@
+#ifndef _RANDOMDGEN__PHILOX_H_
+#define _RANDOMDGEN__PHILOX_H_
+
+#include <inttypes.h>
+#include "numpy/npy_common.h"
+
+#define PHILOX_BUFFER_SIZE 4L
+
+struct r123array2x64 {
+ uint64_t v[2];
+};
+struct r123array4x64 {
+ uint64_t v[4];
+};
+
+enum r123_enum_philox4x64 { philox4x64_rounds = 10 };
+typedef struct r123array4x64 philox4x64_ctr_t;
+typedef struct r123array2x64 philox4x64_key_t;
+typedef struct r123array2x64 philox4x64_ukey_t;
+
+static NPY_INLINE struct r123array2x64
+_philox4x64bumpkey(struct r123array2x64 key) {
+ key.v[0] += (0x9E3779B97F4A7C15ULL);
+ key.v[1] += (0xBB67AE8584CAA73BULL);
+ return key;
+}
+
+/* Prefer uint128 if available: GCC, clang, ICC */
+#ifdef __SIZEOF_INT128__
+static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) {
+ __uint128_t product = ((__uint128_t)a) * ((__uint128_t)b);
+ *hip = product >> 64;
+ return (uint64_t)product;
+}
+#else
+#ifdef _WIN32
+#include <intrin.h>
+#if defined(_WIN64) && defined(_M_AMD64)
+#pragma intrinsic(_umul128)
+#else
+#pragma intrinsic(__emulu)
+static NPY_INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) {
+
+ uint64_t a_lo, a_hi, b_lo, b_hi, a_x_b_hi, a_x_b_mid, a_x_b_lo, b_x_a_mid,
+ carry_bit;
+ a_lo = (uint32_t)a;
+ a_hi = a >> 32;
+ b_lo = (uint32_t)b;
+ b_hi = b >> 32;
+
+ a_x_b_hi = __emulu(a_hi, b_hi);
+ a_x_b_mid = __emulu(a_hi, b_lo);
+ b_x_a_mid = __emulu(b_hi, a_lo);
+ a_x_b_lo = __emulu(a_lo, b_lo);
+
+ carry_bit = ((uint64_t)(uint32_t)a_x_b_mid + (uint64_t)(uint32_t)b_x_a_mid +
+ (a_x_b_lo >> 32)) >>
+ 32;
+
+ *high = a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit;
+
+ return a_x_b_lo + ((a_x_b_mid + b_x_a_mid) << 32);
+}
+#endif
+static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) {
+ return _umul128(a, b, hip);
+}
+#else
+static NPY_INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) {
+
+ uint64_t a_lo, a_hi, b_lo, b_hi, a_x_b_hi, a_x_b_mid, a_x_b_lo, b_x_a_mid,
+ carry_bit;
+ a_lo = (uint32_t)a;
+ a_hi = a >> 32;
+ b_lo = (uint32_t)b;
+ b_hi = b >> 32;
+
+ a_x_b_hi = a_hi * b_hi;
+ a_x_b_mid = a_hi * b_lo;
+ b_x_a_mid = b_hi * a_lo;
+ a_x_b_lo = a_lo * b_lo;
+
+ carry_bit = ((uint64_t)(uint32_t)a_x_b_mid + (uint64_t)(uint32_t)b_x_a_mid +
+ (a_x_b_lo >> 32)) >>
+ 32;
+
+ *high = a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit;
+
+ return a_x_b_lo + ((a_x_b_mid + b_x_a_mid) << 32);
+}
+static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) {
+ return _umul128(a, b, hip);
+}
+#endif
+#endif
+
+static NPY_INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr,
+ struct r123array2x64 key);
+
+static NPY_INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr,
+ struct r123array2x64 key) {
+ uint64_t hi0;
+ uint64_t hi1;
+ uint64_t lo0 = mulhilo64((0xD2E7470EE14C6C93ULL), ctr.v[0], &hi0);
+ uint64_t lo1 = mulhilo64((0xCA5A826395121157ULL), ctr.v[2], &hi1);
+ struct r123array4x64 out = {
+ {hi1 ^ ctr.v[1] ^ key.v[0], lo1, hi0 ^ ctr.v[3] ^ key.v[1], lo0}};
+ return out;
+}
+
+static NPY_INLINE philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) {
+ return uk;
+}
+static NPY_INLINE philox4x64_ctr_t philox4x64_R(unsigned int R,
+ philox4x64_ctr_t ctr,
+ philox4x64_key_t key);
+
+static NPY_INLINE philox4x64_ctr_t philox4x64_R(unsigned int R,
+ philox4x64_ctr_t ctr,
+ philox4x64_key_t key) {
+ if (R > 0) {
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 1) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 2) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 3) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 4) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 5) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 6) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 7) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 8) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 9) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 10) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 11) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 12) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 13) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 14) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ if (R > 15) {
+ key = _philox4x64bumpkey(key);
+ ctr = _philox4x64round(ctr, key);
+ }
+ return ctr;
+}
+
+typedef struct s_philox_state {
+ philox4x64_ctr_t *ctr;
+ philox4x64_key_t *key;
+ int buffer_pos;
+ uint64_t buffer[PHILOX_BUFFER_SIZE];
+ int has_uint32;
+ uint32_t uinteger;
+} philox_state;
+
+static NPY_INLINE uint64_t philox_next(philox_state *state) {
+ uint64_t out;
+ int i;
+ philox4x64_ctr_t ct;
+
+ if (state->buffer_pos < PHILOX_BUFFER_SIZE) {
+ out = state->buffer[state->buffer_pos];
+ state->buffer_pos++;
+ return out;
+ }
+ /* generate 4 new uint64_t */
+ state->ctr->v[0]++;
+ /* Handle carry */
+ if (state->ctr->v[0] == 0) {
+ state->ctr->v[1]++;
+ if (state->ctr->v[1] == 0) {
+ state->ctr->v[2]++;
+ if (state->ctr->v[2] == 0) {
+ state->ctr->v[3]++;
+ }
+ }
+ }
+ ct = philox4x64_R(philox4x64_rounds, *state->ctr, *state->key);
+ for (i = 0; i < 4; i++) {
+ state->buffer[i] = ct.v[i];
+ }
+ state->buffer_pos = 1;
+ return state->buffer[0];
+}
+
+static NPY_INLINE uint64_t philox_next64(philox_state *state) {
+ return philox_next(state);
+}
+
+static NPY_INLINE uint32_t philox_next32(philox_state *state) {
+ uint64_t next;
+
+ if (state->has_uint32) {
+ state->has_uint32 = 0;
+ return state->uinteger;
+ }
+ next = philox_next(state);
+
+ state->has_uint32 = 1;
+ state->uinteger = (uint32_t)(next >> 32);
+ return (uint32_t)(next & 0xffffffff);
+}
+
+extern void philox_jump(philox_state *state);
+
+extern void philox_advance(uint64_t *step, philox_state *state);
+
+#endif
diff --git a/numpy/random/src/sfc64/LICENSE.md b/numpy/random/src/sfc64/LICENSE.md
new file mode 100644
index 000000000..21dd604af
--- /dev/null
+++ b/numpy/random/src/sfc64/LICENSE.md
@@ -0,0 +1,27 @@
+# SFC64
+
+## The MIT License
+
+Adapted from a C++ implementation of Chris Doty-Humphrey's SFC PRNG.
+
+https://gist.github.com/imneme/f1f7821f07cf76504a97f6537c818083
+
+Copyright (c) 2018 Melissa E. O'Neill
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/numpy/random/src/sfc64/sfc64.c b/numpy/random/src/sfc64/sfc64.c
new file mode 100644
index 000000000..5546fff08
--- /dev/null
+++ b/numpy/random/src/sfc64/sfc64.c
@@ -0,0 +1,39 @@
+#include "sfc64.h"
+
+extern void sfc64_set_seed(sfc64_state *state, uint64_t *seed) {
+ /* Conservatively stick with the original formula. With SeedSequence, it
+ * might be fine to just set the state with 4 uint64s and be done.
+ */
+ int i;
+
+ state->s[0] = seed[0];
+ state->s[1] = seed[1];
+ state->s[2] = seed[2];
+ state->s[3] = 1;
+
+ for (i=0; i<12; i++) {
+ (void)sfc64_next(state->s);
+ }
+}
+
+extern void sfc64_get_state(sfc64_state *state, uint64_t *state_arr, int *has_uint32,
+ uint32_t *uinteger) {
+ int i;
+
+ for (i=0; i<4; i++) {
+ state_arr[i] = state->s[i];
+ }
+ has_uint32[0] = state->has_uint32;
+ uinteger[0] = state->uinteger;
+}
+
+extern void sfc64_set_state(sfc64_state *state, uint64_t *state_arr, int has_uint32,
+ uint32_t uinteger) {
+ int i;
+
+ for (i=0; i<4; i++) {
+ state->s[i] = state_arr[i];
+ }
+ state->has_uint32 = has_uint32;
+ state->uinteger = uinteger;
+}
diff --git a/numpy/random/src/sfc64/sfc64.h b/numpy/random/src/sfc64/sfc64.h
new file mode 100644
index 000000000..6674ae69c
--- /dev/null
+++ b/numpy/random/src/sfc64/sfc64.h
@@ -0,0 +1,60 @@
+#ifndef _RANDOMDGEN__SFC64_H_
+#define _RANDOMDGEN__SFC64_H_
+
+#include <inttypes.h>
+#ifdef _WIN32
+#include <stdlib.h>
+#endif
+#include "numpy/npy_common.h"
+
+typedef struct s_sfc64_state {
+ uint64_t s[4];
+ int has_uint32;
+ uint32_t uinteger;
+} sfc64_state;
+
+
+static NPY_INLINE uint64_t rotl(const uint64_t value, unsigned int rot) {
+#ifdef _WIN32
+ return _rotl64(value, rot);
+#else
+ return (value << rot) | (value >> ((-rot) & 63));
+#endif
+}
+
+static NPY_INLINE uint64_t sfc64_next(uint64_t *s) {
+ const uint64_t tmp = s[0] + s[1] + s[3]++;
+
+ s[0] = s[1] ^ (s[1] >> 11);
+ s[1] = s[2] + (s[2] << 3);
+ s[2] = rotl(s[2], 24) + tmp;
+
+ return tmp;
+}
+
+
+static NPY_INLINE uint64_t sfc64_next64(sfc64_state *state) {
+ return sfc64_next(&state->s[0]);
+}
+
+static NPY_INLINE uint32_t sfc64_next32(sfc64_state *state) {
+ uint64_t next;
+ if (state->has_uint32) {
+ state->has_uint32 = 0;
+ return state->uinteger;
+ }
+ next = sfc64_next(&state->s[0]);
+ state->has_uint32 = 1;
+ state->uinteger = (uint32_t)(next >> 32);
+ return (uint32_t)(next & 0xffffffff);
+}
+
+void sfc64_set_seed(sfc64_state *state, uint64_t *seed);
+
+void sfc64_get_state(sfc64_state *state, uint64_t *state_arr, int *has_uint32,
+ uint32_t *uinteger);
+
+void sfc64_set_state(sfc64_state *state, uint64_t *state_arr, int has_uint32,
+ uint32_t uinteger);
+
+#endif
diff --git a/numpy/random/src/splitmix64/LICENSE.md b/numpy/random/src/splitmix64/LICENSE.md
new file mode 100644
index 000000000..3c4d73b92
--- /dev/null
+++ b/numpy/random/src/splitmix64/LICENSE.md
@@ -0,0 +1,9 @@
+# SPLITMIX64
+
+Written in 2015 by Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>. \ No newline at end of file
diff --git a/numpy/random/src/splitmix64/splitmix64.c b/numpy/random/src/splitmix64/splitmix64.c
new file mode 100644
index 000000000..79a845982
--- /dev/null
+++ b/numpy/random/src/splitmix64/splitmix64.c
@@ -0,0 +1,29 @@
+/* Written in 2015 by Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+Modified 2018 by Kevin Sheppard. Modifications licensed under the NCSA
+license.
+*/
+
+/* This is a fixed-increment version of Java 8's SplittableRandom generator
+ See http://dx.doi.org/10.1145/2714064.2660195 and
+ http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
+
+ It is a very fast generator passing BigCrush, and it can be useful if
+ for some reason you absolutely want 64 bits of state; otherwise, we
+ rather suggest to use a xoroshiro128+ (for moderately parallel
+ computations) or xorshift1024* (for massively parallel computations)
+ generator. */
+
+#include "splitmix64.h"
+
+extern inline uint64_t splitmix64_next(uint64_t *state);
+
+extern inline uint64_t splitmix64_next64(splitmix64_state *state);
+
+extern inline uint32_t splitmix64_next32(splitmix64_state *state);
diff --git a/numpy/random/src/splitmix64/splitmix64.h b/numpy/random/src/splitmix64/splitmix64.h
new file mode 100644
index 000000000..d5877905e
--- /dev/null
+++ b/numpy/random/src/splitmix64/splitmix64.h
@@ -0,0 +1,30 @@
+#include <inttypes.h>
+
+typedef struct s_splitmix64_state {
+ uint64_t state;
+ int has_uint32;
+ uint32_t uinteger;
+} splitmix64_state;
+
+static inline uint64_t splitmix64_next(uint64_t *state) {
+ uint64_t z = (state[0] += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
+
+static inline uint64_t splitmix64_next64(splitmix64_state *state) {
+ return splitmix64_next(&state->state);
+}
+
+static inline uint32_t splitmix64_next32(splitmix64_state *state) {
+ uint64_t next;
+ if (state->has_uint32) {
+ state->has_uint32 = 0;
+ return state->uinteger;
+ }
+ next = splitmix64_next64(state);
+ state->has_uint32 = 1;
+ state->uinteger = (uint32_t)(next >> 32);
+ return (uint32_t)(next & 0xffffffff);
+}
diff --git a/numpy/random/src/splitmix64/splitmix64.orig.c b/numpy/random/src/splitmix64/splitmix64.orig.c
new file mode 100644
index 000000000..df6133aab
--- /dev/null
+++ b/numpy/random/src/splitmix64/splitmix64.orig.c
@@ -0,0 +1,28 @@
+/* Written in 2015 by Sebastiano Vigna (vigna@acm.org)
+
+To the extent possible under law, the author has dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+
+See <http://creativecommons.org/publicdomain/zero/1.0/>. */
+
+#include <stdint.h>
+
+/* This is a fixed-increment version of Java 8's SplittableRandom generator
+ See http://dx.doi.org/10.1145/2714064.2660195 and
+ http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
+
+ It is a very fast generator passing BigCrush, and it can be useful if
+ for some reason you absolutely want 64 bits of state; otherwise, we
+ rather suggest to use a xoroshiro128+ (for moderately parallel
+ computations) or xorshift1024* (for massively parallel computations)
+ generator. */
+
+uint64_t x; /* The state can be seeded with any value. */
+
+uint64_t next() {
+ uint64_t z = (x += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
diff --git a/numpy/random/tests/data/__init__.py b/numpy/random/tests/data/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/numpy/random/tests/data/__init__.py
diff --git a/numpy/random/tests/data/mt19937-testset-1.csv b/numpy/random/tests/data/mt19937-testset-1.csv
new file mode 100644
index 000000000..b97bfa66f
--- /dev/null
+++ b/numpy/random/tests/data/mt19937-testset-1.csv
@@ -0,0 +1,1001 @@
+seed, 0xdeadbeaf
+0, 0xc816921f
+1, 0xb3623c6d
+2, 0x5fa391bb
+3, 0x40178d9
+4, 0x7dcc9811
+5, 0x548eb8e6
+6, 0x92ba3125
+7, 0x65fde68d
+8, 0x2f81ec95
+9, 0xbd94f7a2
+10, 0xdc4d9bcc
+11, 0xa672bf13
+12, 0xb41113e
+13, 0xec7e0066
+14, 0x50239372
+15, 0xd9d66b1d
+16, 0xab72a161
+17, 0xddc2e29f
+18, 0x7ea29ab4
+19, 0x80d141ba
+20, 0xb1c7edf1
+21, 0x44d29203
+22, 0xe224d98
+23, 0x5b3e9d26
+24, 0x14fd567c
+25, 0x27d98c96
+26, 0x838779fc
+27, 0x92a138a
+28, 0x5d08965b
+29, 0x531e0ad6
+30, 0x984ee8f4
+31, 0x1ed78539
+32, 0x32bd6d8d
+33, 0xc37c8516
+34, 0x9aef5c6b
+35, 0x3aacd139
+36, 0xd96ed154
+37, 0x489cd1ed
+38, 0x2cba4b3b
+39, 0x76c6ae72
+40, 0x2dae02b9
+41, 0x52ac5fd6
+42, 0xc2b5e265
+43, 0x630e6a28
+44, 0x3f560d5d
+45, 0x9315bdf3
+46, 0xf1055aba
+47, 0x840e42c6
+48, 0xf2099c6b
+49, 0x15ff7696
+50, 0x7948d146
+51, 0x97342961
+52, 0x7a7a21c
+53, 0xc66f4fb1
+54, 0x23c4103e
+55, 0xd7321f98
+56, 0xeb7efb75
+57, 0xe02490b5
+58, 0x2aa02de
+59, 0x8bee0bf7
+60, 0xfc2da059
+61, 0xae835034
+62, 0x678f2075
+63, 0x6d03094b
+64, 0x56455e05
+65, 0x18b32373
+66, 0x8ff0356b
+67, 0x1fe442fb
+68, 0x3f1ab6c3
+69, 0xb6fd21b
+70, 0xfc310eb2
+71, 0xb19e9a4d
+72, 0x17ddee72
+73, 0xfd534251
+74, 0x9e500564
+75, 0x9013a036
+76, 0xcf08f118
+77, 0x6b6d5969
+78, 0x3ccf1977
+79, 0x7cc11497
+80, 0x651c6ac9
+81, 0x4d6b104b
+82, 0x9a28314e
+83, 0x14c237be
+84, 0x9cfc8d52
+85, 0x2947fad5
+86, 0xd71eff49
+87, 0x5188730e
+88, 0x4b894614
+89, 0xf4fa2a34
+90, 0x42f7cc69
+91, 0x4089c9e8
+92, 0xbf0bbfe4
+93, 0x3cea65c
+94, 0xc6221207
+95, 0x1bb71a8f
+96, 0x54843fe7
+97, 0xbc59de4c
+98, 0x79c6ee64
+99, 0x14e57a26
+100, 0x68d88fe
+101, 0x2b86ef64
+102, 0x8ffff3c1
+103, 0x5bdd573f
+104, 0x85671813
+105, 0xefe32ca2
+106, 0x105ded1e
+107, 0x90ca2769
+108, 0xb33963ac
+109, 0x363fbbc3
+110, 0x3b3763ae
+111, 0x1d50ab88
+112, 0xc9ec01eb
+113, 0xc8bbeada
+114, 0x5d704692
+115, 0x5fd9e40
+116, 0xe61c125
+117, 0x2fe05792
+118, 0xda8afb72
+119, 0x4cbaa653
+120, 0xdd2243df
+121, 0x896fd3f5
+122, 0x5bc23db
+123, 0xa1c4e807
+124, 0x57d1a24d
+125, 0x66503ddc
+126, 0xcf7c0838
+127, 0x19e034fc
+128, 0x66807450
+129, 0xfc219b3b
+130, 0xe8a843e7
+131, 0x9ce61f08
+132, 0x92b950d6
+133, 0xce955ec4
+134, 0xda0d1f0d
+135, 0x960c6250
+136, 0x39552432
+137, 0xde845e84
+138, 0xff3b4b11
+139, 0x5d918e6f
+140, 0xbb930df2
+141, 0x7cfb0993
+142, 0x5400e1e9
+143, 0x3bfa0954
+144, 0x7e2605fb
+145, 0x11941591
+146, 0x887e6994
+147, 0xdc8bed45
+148, 0x45b3fb50
+149, 0xfbdf8358
+150, 0x41507468
+151, 0x34c87166
+152, 0x17f64d77
+153, 0x3bbaf4f8
+154, 0x4f26f37e
+155, 0x4a56ebf2
+156, 0x81100f1
+157, 0x96d94eae
+158, 0xca88fda5
+159, 0x2eef3a60
+160, 0x952afbd3
+161, 0x2bec88c7
+162, 0x52335c4b
+163, 0x8296db8e
+164, 0x4da7d00a
+165, 0xc00ac899
+166, 0xadff8c72
+167, 0xbecf26cf
+168, 0x8835c83c
+169, 0x1d13c804
+170, 0xaa940ddc
+171, 0x68222cfe
+172, 0x4569c0e1
+173, 0x29077976
+174, 0x32d4a5af
+175, 0xd31fcdef
+176, 0xdc60682b
+177, 0x7c95c368
+178, 0x75a70213
+179, 0x43021751
+180, 0x5e52e0a6
+181, 0xf7e190b5
+182, 0xee3e4bb
+183, 0x2fe3b150
+184, 0xcf419c07
+185, 0x478a4570
+186, 0xe5c3ea50
+187, 0x417f30a8
+188, 0xf0cfdaa0
+189, 0xd1f7f738
+190, 0x2c70fc23
+191, 0x54fc89f9
+192, 0x444dcf01
+193, 0xec2a002d
+194, 0xef0c3a88
+195, 0xde21be9
+196, 0x88ab3296
+197, 0x3028897c
+198, 0x264b200b
+199, 0xd8ae0706
+200, 0x9eef901a
+201, 0xbd1b96e0
+202, 0xea71366c
+203, 0x1465b694
+204, 0x5a794650
+205, 0x83df52d4
+206, 0x8262413d
+207, 0x5bc148c0
+208, 0xe0ecd80c
+209, 0x40649571
+210, 0xb4d2ee5f
+211, 0xedfd7d09
+212, 0xa082e25f
+213, 0xc62992d1
+214, 0xbc7e65ee
+215, 0x5499cf8a
+216, 0xac28f775
+217, 0x649840fb
+218, 0xd4c54805
+219, 0x1d166ba6
+220, 0xbeb1171f
+221, 0x45b66703
+222, 0x78c03349
+223, 0x38d2a6ff
+224, 0x935cae8b
+225, 0x1d07dc3f
+226, 0x6c1ed365
+227, 0x579fc585
+228, 0x1320c0ec
+229, 0x632757eb
+230, 0xd265a397
+231, 0x70e9b6c2
+232, 0xc81e322c
+233, 0xa27153cf
+234, 0x2118ba19
+235, 0x514ec400
+236, 0x2bd0ecd6
+237, 0xc3e7dae3
+238, 0xfa39355e
+239, 0x48f23cc1
+240, 0xbcf75948
+241, 0x53ccc70c
+242, 0x75346423
+243, 0x951181e0
+244, 0x348e90df
+245, 0x14365d7f
+246, 0xfbc95d7a
+247, 0xdc98a9e6
+248, 0xed202df7
+249, 0xa59ec913
+250, 0x6b6e9ae2
+251, 0x1697f265
+252, 0x15d322d0
+253, 0xa2e7ee0a
+254, 0x88860b7e
+255, 0x455d8b9d
+256, 0x2f5c59cb
+257, 0xac49c9f1
+258, 0xa6a6a039
+259, 0xc057f56b
+260, 0xf1ff1208
+261, 0x5eb8dc9d
+262, 0xe6702509
+263, 0xe238b0ed
+264, 0x5ae32e3d
+265, 0xa88ebbdf
+266, 0xef885ae7
+267, 0xafa6d49b
+268, 0xc94499e0
+269, 0x1a196325
+270, 0x88938da3
+271, 0x14f4345
+272, 0xd8e33637
+273, 0xa3551bd5
+274, 0x73fe35c7
+275, 0x9561e94b
+276, 0xd673bf68
+277, 0x16134872
+278, 0x68c42f9f
+279, 0xdf7574c8
+280, 0x8809bab9
+281, 0x1432cf69
+282, 0xafb66bf1
+283, 0xc184aa7b
+284, 0xedbf2007
+285, 0xbd420ce1
+286, 0x761033a0
+287, 0xff7e351f
+288, 0xd6c3780e
+289, 0x5844416f
+290, 0xc6c0ee1c
+291, 0xd2e147db
+292, 0x92ac601a
+293, 0x393e846b
+294, 0x18196cca
+295, 0x54a22be
+296, 0x32bab1c4
+297, 0x60365183
+298, 0x64fa342
+299, 0xca24a493
+300, 0xd8cc8b83
+301, 0x3faf102b
+302, 0x6e09bb58
+303, 0x812f0ea
+304, 0x592c95d8
+305, 0xe45ea4c5
+306, 0x23aebf83
+307, 0xbd9691d4
+308, 0xf47b4baa
+309, 0x4ac7b487
+310, 0xcce18803
+311, 0x3377556e
+312, 0x3ff8e6b6
+313, 0x99d22063
+314, 0x23250bec
+315, 0x4e1f9861
+316, 0x8554249b
+317, 0x8635c2fc
+318, 0xe8426e8a
+319, 0x966c29d8
+320, 0x270b6082
+321, 0x3180a8a1
+322, 0xe7e1668b
+323, 0x7f868dc
+324, 0xcf4c17cf
+325, 0xe31de4d1
+326, 0xc8c8aff4
+327, 0xae8db704
+328, 0x3c928cc2
+329, 0xe12cd48
+330, 0xb33ecd04
+331, 0xb93d7cbe
+332, 0x49c69d6a
+333, 0x7d3bce64
+334, 0x86bc219
+335, 0x8408233b
+336, 0x44dc7479
+337, 0xdf80d538
+338, 0xf3db02c3
+339, 0xbbbd31d7
+340, 0x121281f
+341, 0x7521e9a3
+342, 0x8859675a
+343, 0x75aa6502
+344, 0x430ed15b
+345, 0xecf0a28d
+346, 0x659774fd
+347, 0xd58a2311
+348, 0x512389a9
+349, 0xff65e1ff
+350, 0xb6ddf222
+351, 0xe3458895
+352, 0x8b13cd6e
+353, 0xd4a22870
+354, 0xe604c50c
+355, 0x27f54f26
+356, 0x8f7f422f
+357, 0x9735b4cf
+358, 0x414072b0
+359, 0x76a1c6d5
+360, 0xa2208c06
+361, 0x83cd0f61
+362, 0x6c4f7ead
+363, 0x6553cf76
+364, 0xeffcf44
+365, 0x7f434a3f
+366, 0x9dc364bd
+367, 0x3cdf52ed
+368, 0xad597594
+369, 0x9c3e211b
+370, 0x6c04a33f
+371, 0x885dafa6
+372, 0xbbdaca71
+373, 0x7ae5dd5c
+374, 0x37675644
+375, 0x251853c6
+376, 0x130b086b
+377, 0x143fa54b
+378, 0x54cdc282
+379, 0x9faff5b3
+380, 0x502a5c8b
+381, 0xd9524550
+382, 0xae221aa6
+383, 0x55cf759b
+384, 0x24782da4
+385, 0xd715d815
+386, 0x250ea09a
+387, 0x4e0744ac
+388, 0x11e15814
+389, 0xabe5f9df
+390, 0xc8146350
+391, 0xfba67d9b
+392, 0x2b82e42f
+393, 0xd4ea96fc
+394, 0x5ffc179e
+395, 0x1598bafe
+396, 0x7fb6d662
+397, 0x1a12a0db
+398, 0x450cee4a
+399, 0x85f8e12
+400, 0xce71b594
+401, 0xd4bb1d19
+402, 0x968f379d
+403, 0x54cc1d52
+404, 0x467e6066
+405, 0x7da5f9a9
+406, 0x70977034
+407, 0x49e65c4b
+408, 0xd08570d1
+409, 0x7acdf60b
+410, 0xdffa038b
+411, 0x9ce14e4c
+412, 0x107cbbf8
+413, 0xdd746ca0
+414, 0xc6370a46
+415, 0xe7f83312
+416, 0x373fa9ce
+417, 0xd822a2c6
+418, 0x1d4efea6
+419, 0xc53dcadb
+420, 0x9b4e898f
+421, 0x71daa6bf
+422, 0x7a0bc78b
+423, 0xd7b86f50
+424, 0x1b8b3286
+425, 0xcf9425dd
+426, 0xd5263220
+427, 0x4ea0b647
+428, 0xc767fe64
+429, 0xcfc5e67
+430, 0xcc6a2942
+431, 0xa51eff00
+432, 0x76092e1b
+433, 0xf606e80f
+434, 0x824b5e20
+435, 0xebb55e14
+436, 0x783d96a6
+437, 0x10696512
+438, 0x17ee510a
+439, 0x3ab70a1f
+440, 0xcce6b210
+441, 0x8f72f0fb
+442, 0xf0610b41
+443, 0x83d01fb5
+444, 0x6b3de36
+445, 0xe4c2e84f
+446, 0x9c43bb15
+447, 0xddf2905
+448, 0x7dd63556
+449, 0x3662ca09
+450, 0xfb81f35b
+451, 0xc2c8a72a
+452, 0x8e93c37
+453, 0xa93da2d4
+454, 0xa03af8f1
+455, 0x8d75159a
+456, 0x15f010b0
+457, 0xa296ab06
+458, 0xe55962ba
+459, 0xeae700a9
+460, 0xe388964a
+461, 0x917f2bec
+462, 0x1c203fea
+463, 0x792a01ba
+464, 0xa93a80ac
+465, 0x9eb8a197
+466, 0x56c0bc73
+467, 0xb8f05799
+468, 0xf429a8c8
+469, 0xb92cee42
+470, 0xf8864ec
+471, 0x62f2518a
+472, 0x3a7bfa3e
+473, 0x12e56e6d
+474, 0xd7a18313
+475, 0x41fa3899
+476, 0xa09c4956
+477, 0xebcfd94a
+478, 0xc485f90b
+479, 0x4391ce40
+480, 0x742a3333
+481, 0xc932f9e5
+482, 0x75c6c263
+483, 0x80937f0
+484, 0xcf21833c
+485, 0x16027520
+486, 0xd42e669f
+487, 0xb0f01fb7
+488, 0xb35896f1
+489, 0x763737a9
+490, 0x1bb20209
+491, 0x3551f189
+492, 0x56bc2602
+493, 0xb6eacf4
+494, 0x42ec4d11
+495, 0x245cc68
+496, 0xc27ac43b
+497, 0x9d903466
+498, 0xce3f0c05
+499, 0xb708c31c
+500, 0xc0fd37eb
+501, 0x95938b2c
+502, 0xf20175a7
+503, 0x4a86ee9b
+504, 0xbe039a58
+505, 0xd41cabe7
+506, 0x83bc99ba
+507, 0x761d60e1
+508, 0x7737cc2e
+509, 0x2b82fc4b
+510, 0x375aa401
+511, 0xfe9597a0
+512, 0x5543806a
+513, 0x44f31238
+514, 0x7df31538
+515, 0x74cfa770
+516, 0x8755d881
+517, 0x1fde665a
+518, 0xda8bf315
+519, 0x973d8e95
+520, 0x72205228
+521, 0x8fe59717
+522, 0x7bb90b34
+523, 0xef6ed945
+524, 0x16fd4a38
+525, 0x5db44de1
+526, 0xf09f93b3
+527, 0xe84824cc
+528, 0x945bb50e
+529, 0xd0be4aa5
+530, 0x47c277c2
+531, 0xd3800c28
+532, 0xac1c33ec
+533, 0xd3dacce
+534, 0x811c8387
+535, 0x6761b36
+536, 0x70d3882f
+537, 0xd6e62e3a
+538, 0xea25daa2
+539, 0xb07f39d1
+540, 0x391d89d7
+541, 0x84b6fb5e
+542, 0x3dda3fca
+543, 0x229e80a4
+544, 0x3d94a4b7
+545, 0x5d3d576a
+546, 0xad7818a0
+547, 0xce23b03a
+548, 0x7aa2079c
+549, 0x9a6be555
+550, 0x83f3b34a
+551, 0x1848f9d9
+552, 0xd8fefc1c
+553, 0x48e6ce48
+554, 0x52e55750
+555, 0xf41a71cf
+556, 0xba08e259
+557, 0xfaf06a15
+558, 0xeaaac0fb
+559, 0x34f90098
+560, 0xb1dfffbb
+561, 0x718daec2
+562, 0xab4dda21
+563, 0xd27cc1ee
+564, 0x4aafbc4c
+565, 0x356dfb4f
+566, 0x83fcdfd6
+567, 0x8f0bcde0
+568, 0x4363f844
+569, 0xadc0f4d5
+570, 0x3bde994e
+571, 0x3884d452
+572, 0x21876b4a
+573, 0x9c985398
+574, 0xca55a226
+575, 0x3a88c583
+576, 0x916dc33c
+577, 0x8f67d1d7
+578, 0x3b26a667
+579, 0xe4ddeb4b
+580, 0x1a9d8c33
+581, 0x81c9b74f
+582, 0x9ed1e9df
+583, 0x6e61aecf
+584, 0x95e95a5d
+585, 0x68864ff5
+586, 0xb8fa5b9
+587, 0x72b1b3de
+588, 0x5e18a86b
+589, 0xd7f2337d
+590, 0xd70e0925
+591, 0xb573a4c1
+592, 0xc77b3f8a
+593, 0x389b20de
+594, 0x16cf6afb
+595, 0xa39bd275
+596, 0xf491cf01
+597, 0x6f88a802
+598, 0x8510af05
+599, 0xe7cd549a
+600, 0x8603179a
+601, 0xef43f191
+602, 0xf9b64c60
+603, 0xb00254a7
+604, 0xd7c06a2d
+605, 0x17e9380b
+606, 0x529e727b
+607, 0xaaa8fe0a
+608, 0xfb64ff4c
+609, 0xcd75af26
+610, 0xfb717c87
+611, 0xa0789899
+612, 0x10391ec9
+613, 0x7e9b40b3
+614, 0x18536554
+615, 0x728c05f7
+616, 0x787dca98
+617, 0xad948d1
+618, 0x44c18def
+619, 0x3303f2ec
+620, 0xa15acb5
+621, 0xb58d38f4
+622, 0xfe041ef8
+623, 0xd151a956
+624, 0x7b9168e8
+625, 0x5ebeca06
+626, 0x90fe95df
+627, 0xf76875aa
+628, 0xb2e0d664
+629, 0x2e3253b7
+630, 0x68e34469
+631, 0x1f0c2d89
+632, 0x13a34ac2
+633, 0x5ffeb841
+634, 0xe381e91c
+635, 0xb8549a92
+636, 0x3f35cf1
+637, 0xda0f9dcb
+638, 0xdd9828a6
+639, 0xe1428f29
+640, 0xf4db80b5
+641, 0xdac30af5
+642, 0x1af1dd17
+643, 0x9a540254
+644, 0xcab68a38
+645, 0x33560361
+646, 0x2fbf3886
+647, 0xbc785923
+648, 0xe081cd10
+649, 0x8e473356
+650, 0xd102c357
+651, 0xeea4fe48
+652, 0x248d3453
+653, 0x1da79ac
+654, 0x815a65ff
+655, 0x27693e76
+656, 0xb7d5af40
+657, 0x6d245d30
+658, 0x9e06fa8f
+659, 0xb0570dcb
+660, 0x469f0005
+661, 0x3e0ca132
+662, 0xd89bbf3
+663, 0xd61ccd47
+664, 0x6383878
+665, 0x62b5956
+666, 0x4dc83675
+667, 0x93fd8492
+668, 0x5a0091f5
+669, 0xc9f9bc3
+670, 0xa26e7778
+671, 0xeabf2d01
+672, 0xe612dc06
+673, 0x85d89ff9
+674, 0xd1763179
+675, 0xcb88947b
+676, 0x9e8757a5
+677, 0xe100e85c
+678, 0x904166eb
+679, 0x4996243d
+680, 0x4038e1cb
+681, 0x2be2c63d
+682, 0x77017e81
+683, 0x3b1f556b
+684, 0x1c785c77
+685, 0x6869b8bd
+686, 0xe1217ed4
+687, 0x4012ab2f
+688, 0xc06c0d8e
+689, 0x2122eb68
+690, 0xad1783fd
+691, 0x5f0c80e3
+692, 0x828f7efa
+693, 0x29328399
+694, 0xeadf1087
+695, 0x85dc0037
+696, 0x9691ef26
+697, 0xc0947a53
+698, 0x2a178d2a
+699, 0x2a2c7e8f
+700, 0x90378380
+701, 0xaad8d326
+702, 0x9cf1c3c8
+703, 0x84eccd44
+704, 0x79e61808
+705, 0x8b3f454e
+706, 0x209e6e1
+707, 0x51f88378
+708, 0xc210226f
+709, 0xd982adb5
+710, 0x55d44a31
+711, 0x9817d443
+712, 0xa328c626
+713, 0x13455966
+714, 0xb8f681d3
+715, 0x2a3c713b
+716, 0xc186959b
+717, 0x814a74b0
+718, 0xed7bc90
+719, 0xa88d3d6d
+720, 0x88a9f561
+721, 0x73aa1c0a
+722, 0xdfeff404
+723, 0xec037e4b
+724, 0xa5c209f0
+725, 0xb3a223b4
+726, 0x24ce3709
+727, 0x3184c790
+728, 0xa1398c62
+729, 0x2f92034e
+730, 0xbb37a79a
+731, 0x605287b4
+732, 0x8faa772c
+733, 0x6ce56c1d
+734, 0xc035fb4c
+735, 0x7cf5b316
+736, 0x6502645
+737, 0xa283d810
+738, 0x778bc2f1
+739, 0xfdf99313
+740, 0x1f513265
+741, 0xbd3837e2
+742, 0x9b84a9a
+743, 0x2139ce91
+744, 0x61a8e890
+745, 0xf9ff12db
+746, 0xb43d2ea7
+747, 0x88532e61
+748, 0x175a6655
+749, 0x7a6c4f72
+750, 0x6dafc1b7
+751, 0x449b1459
+752, 0x514f654f
+753, 0x9a6731e2
+754, 0x8632da43
+755, 0xc81b0422
+756, 0x81fe9005
+757, 0x15b79618
+758, 0xb5fa629f
+759, 0x987a474f
+760, 0x1c74f54e
+761, 0xf9743232
+762, 0xec4b55f
+763, 0x87d761e5
+764, 0xd1ad78b7
+765, 0x453d9350
+766, 0xc7a7d85
+767, 0xb2576ff5
+768, 0xcdde49b7
+769, 0x8e1f763e
+770, 0x1338583e
+771, 0xfd65b9dc
+772, 0x4f19c4f4
+773, 0x3a52d73d
+774, 0xd3509c4c
+775, 0xda24fe31
+776, 0xe2de56ba
+777, 0x2db5e540
+778, 0x23172734
+779, 0x4db572f
+780, 0xeb941718
+781, 0x84c2649a
+782, 0x3b1e5b6a
+783, 0x4c9c61b9
+784, 0x3bccd11
+785, 0xb4d7b78e
+786, 0x48580ae5
+787, 0xd273ab68
+788, 0x25c11615
+789, 0x470b53f6
+790, 0x329c2068
+791, 0x1693721b
+792, 0xf8c9aacf
+793, 0x4c3d5693
+794, 0xd778284e
+795, 0xae1cb24f
+796, 0x3c11d1b3
+797, 0xddd2b0c0
+798, 0x90269fa7
+799, 0x5666e0a2
+800, 0xf9f195a4
+801, 0x61d78eb2
+802, 0xada5a7c0
+803, 0xaa272fbe
+804, 0xba3bae2f
+805, 0xd0b70fc2
+806, 0x529f32b
+807, 0xda7a3e21
+808, 0x9a776a20
+809, 0xb21f9635
+810, 0xb3acc14e
+811, 0xac55f56
+812, 0x29dccf41
+813, 0x32dabdb3
+814, 0xaa032f58
+815, 0xfa406af4
+816, 0xce3c415d
+817, 0xb44fb4d9
+818, 0x32248d1c
+819, 0x680c6440
+820, 0xae2337b
+821, 0x294cb597
+822, 0x5bca48fe
+823, 0xaef19f40
+824, 0xad60406
+825, 0x4781f090
+826, 0xfd691ffc
+827, 0xb6568268
+828, 0xa56c72cb
+829, 0xf8a9e0fc
+830, 0x9af4fd02
+831, 0x2cd30932
+832, 0x776cefd7
+833, 0xe31f476e
+834, 0x6d94a437
+835, 0xb3cab598
+836, 0xf582d13f
+837, 0x3bf8759d
+838, 0xc3777dc
+839, 0x5e425ea8
+840, 0x1c7ff4ed
+841, 0x1c2e97d1
+842, 0xc062d2b4
+843, 0x46dc80e0
+844, 0xbcdb47e6
+845, 0x32282fe0
+846, 0xaba89063
+847, 0x5e94e9bb
+848, 0x3e667f78
+849, 0xea6eb21a
+850, 0xe56e54e8
+851, 0xa0383510
+852, 0x6768fe2b
+853, 0xb53ac3e0
+854, 0x779569a0
+855, 0xeca83c6a
+856, 0x24db4d2d
+857, 0x4585f696
+858, 0xf84748b2
+859, 0xf6a4dd5b
+860, 0x31fb524d
+861, 0x67ab39fe
+862, 0x5882a899
+863, 0x9a05fcf6
+864, 0x712b5674
+865, 0xe8c6958f
+866, 0x4b448bb3
+867, 0x530b9abf
+868, 0xb491f491
+869, 0x98352c62
+870, 0x2d0a50e3
+871, 0xeb4384da
+872, 0x36246f07
+873, 0xcbc5c1a
+874, 0xae24031d
+875, 0x44d11ed6
+876, 0xf07f1608
+877, 0xf296aadd
+878, 0x3bcfe3be
+879, 0x8fa1e7df
+880, 0xfd317a6e
+881, 0xe4975c44
+882, 0x15205892
+883, 0xa762d4df
+884, 0xf1167365
+885, 0x6811cc00
+886, 0x8315f23
+887, 0xe045b4b1
+888, 0xa8496414
+889, 0xbed313ae
+890, 0xcdae3ddb
+891, 0xa9c22c9
+892, 0x275fab1a
+893, 0xedd65fa
+894, 0x4c188229
+895, 0x63a83e58
+896, 0x18aa9207
+897, 0xa41f2e78
+898, 0xd9f63653
+899, 0xbe2be73b
+900, 0xa3364d39
+901, 0x896d5428
+902, 0xc737539e
+903, 0x745a78c6
+904, 0xf0b2b042
+905, 0x510773b4
+906, 0x92ad8e37
+907, 0x27f2f8c4
+908, 0x23704cc8
+909, 0x3d95a77f
+910, 0xf08587a4
+911, 0xbd696a25
+912, 0x948924f3
+913, 0x8cddb634
+914, 0xcd2a4910
+915, 0x8e0e300e
+916, 0x83815a9b
+917, 0x67383510
+918, 0x3c18f0d0
+919, 0xc7a7bccc
+920, 0x7cc2d3a2
+921, 0x52eb2eeb
+922, 0xe4a257e5
+923, 0xec76160e
+924, 0x63f9ad68
+925, 0x36d0bbbf
+926, 0x957bc4e4
+927, 0xc9ed90ff
+928, 0x4cb6059d
+929, 0x2f86eca1
+930, 0x3e3665a3
+931, 0x9b7eb6f4
+932, 0x492e7e18
+933, 0xa098aa51
+934, 0x7eb568b2
+935, 0x3fd639ba
+936, 0x7bebcf1
+937, 0x99c844ad
+938, 0x43cb5ec7
+939, 0x8dfbbef5
+940, 0x5be413ff
+941, 0xd93b976d
+942, 0xc1c7a86d
+943, 0x1f0e93d0
+944, 0x498204a2
+945, 0xe8fe832a
+946, 0x2236bd7
+947, 0x89953769
+948, 0x2acc3491
+949, 0x2c4f22c6
+950, 0xd7996277
+951, 0x3bcdc349
+952, 0xfc286630
+953, 0x5f8909fd
+954, 0x242677c0
+955, 0x4cb34104
+956, 0xa6ff8100
+957, 0x39ea47ec
+958, 0x9bd54140
+959, 0x7502ffe8
+960, 0x7ebef8ae
+961, 0x1ed8abe4
+962, 0xfaba8450
+963, 0xc197b65f
+964, 0x19431455
+965, 0xe229c176
+966, 0xeb2967da
+967, 0xe0c5dc05
+968, 0xa84e3227
+969, 0x10dd9e0f
+970, 0xbdb70b02
+971, 0xce24808a
+972, 0x423edab8
+973, 0x194caf71
+974, 0x144f150d
+975, 0xf811c2d2
+976, 0xc224ee85
+977, 0x2b217a5b
+978, 0xf78a5a79
+979, 0x6554a4b1
+980, 0x769582df
+981, 0xf4b2cf93
+982, 0x89648483
+983, 0xb3283a3e
+984, 0x82b895db
+985, 0x79388ef0
+986, 0x54bc42a6
+987, 0xc4dd39d9
+988, 0x45b33b7d
+989, 0x8703b2c1
+990, 0x1cc94806
+991, 0xe0f43e49
+992, 0xcaa7b6bc
+993, 0x4f88e9af
+994, 0x1477cce5
+995, 0x347dd115
+996, 0x36e335fa
+997, 0xb93c9a31
+998, 0xaac3a175
+999, 0x68a19647
diff --git a/numpy/random/tests/data/mt19937-testset-2.csv b/numpy/random/tests/data/mt19937-testset-2.csv
new file mode 100644
index 000000000..cdb8e4794
--- /dev/null
+++ b/numpy/random/tests/data/mt19937-testset-2.csv
@@ -0,0 +1,1001 @@
+seed, 0x0
+0, 0x7ab4ea94
+1, 0x9b561119
+2, 0x4957d02e
+3, 0x7dd3fdc2
+4, 0x5affe54
+5, 0x5a01741c
+6, 0x8b9e8c1f
+7, 0xda5bf11a
+8, 0x509226
+9, 0x64e2ea17
+10, 0x82c6dab5
+11, 0xe4302515
+12, 0x8198b873
+13, 0xc3ec9a82
+14, 0x829dff28
+15, 0x5278e44f
+16, 0x994a7d2c
+17, 0xf1c89398
+18, 0xaf2fddec
+19, 0x22abc6ee
+20, 0x963dbd43
+21, 0xc29edffb
+22, 0x41c1ce07
+23, 0x9c90034d
+24, 0x1f17a796
+25, 0x3833caa8
+26, 0xb8795528
+27, 0xebc595a2
+28, 0xf8f5b5dd
+29, 0xc2881f72
+30, 0x18e5d3f0
+31, 0x9b19ac7a
+32, 0xb9992436
+33, 0xc00052b3
+34, 0xb63f4475
+35, 0x962642d9
+36, 0x63506c10
+37, 0x2be6b127
+38, 0x569bdbc6
+39, 0x7f185e01
+40, 0xebb55f53
+41, 0x1c30198c
+42, 0x7c8d75c6
+43, 0xd3f2186b
+44, 0xaca5b9b1
+45, 0xbc49ff45
+46, 0xc4a802af
+47, 0x2cecd86f
+48, 0x8e0da529
+49, 0x1f22b00e
+50, 0x4559ea80
+51, 0x60f587d8
+52, 0x7c7460e9
+53, 0x67be0a4a
+54, 0x987a0183
+55, 0x7bd30f1
+56, 0xab18c4ac
+57, 0xffdbfb64
+58, 0x9ea917f9
+59, 0x1239dab7
+60, 0x38efabeb
+61, 0x5da91888
+62, 0x8f49ed62
+63, 0x83f60b1e
+64, 0x5950a3fc
+65, 0xd8911104
+66, 0x19e8859e
+67, 0x1a4d89ec
+68, 0x968ca180
+69, 0x9e1b6da3
+70, 0x3d99c2c
+71, 0x55f76289
+72, 0x8fa28b9e
+73, 0x9fe01d33
+74, 0xdade4e38
+75, 0x1ea04290
+76, 0xa7263313
+77, 0xaafc762e
+78, 0x460476d6
+79, 0x31226e12
+80, 0x451d3f05
+81, 0xd0d2764b
+82, 0xd06e1ab3
+83, 0x1394e3f4
+84, 0x2fc04ea3
+85, 0x5b8401c
+86, 0xebd6c929
+87, 0xe881687c
+88, 0x94bdd66a
+89, 0xabf85983
+90, 0x223ad12d
+91, 0x2aaeeaa3
+92, 0x1f704934
+93, 0x2db2efb6
+94, 0xf49b8dfb
+95, 0x5bdbbb9d
+96, 0xba0cd0db
+97, 0x4ec4674e
+98, 0xad0129e
+99, 0x7a66129b
+100, 0x50d12c5e
+101, 0x85b1d335
+102, 0x3efda58a
+103, 0xecd886fb
+104, 0x8ecadd3d
+105, 0x60ebac0f
+106, 0x5e10fe79
+107, 0xa84f7e5d
+108, 0x43931288
+109, 0xfacf448
+110, 0x4ee01997
+111, 0xcdc0a651
+112, 0x33c87037
+113, 0x8b50fc03
+114, 0xf52aad34
+115, 0xda6cd856
+116, 0x7585bea0
+117, 0xe947c762
+118, 0x4ddff5d8
+119, 0xe0e79b3b
+120, 0xb804cf09
+121, 0x84765c44
+122, 0x3ff666b4
+123, 0xe31621ad
+124, 0x816f2236
+125, 0x228176bc
+126, 0xfdc14904
+127, 0x635f5077
+128, 0x6981a817
+129, 0xfd9a0300
+130, 0xd3fa8a24
+131, 0xd67c1a77
+132, 0x903fe97a
+133, 0xf7c4a4d5
+134, 0x109f2058
+135, 0x48ab87fe
+136, 0xfd6f1928
+137, 0x707e9452
+138, 0xf327db9e
+139, 0x7b80d76d
+140, 0xfb6ba193
+141, 0x454a1ad0
+142, 0xe20b51e
+143, 0xb774d085
+144, 0x6b1ed574
+145, 0xb1e77de4
+146, 0xe2a83b37
+147, 0x33d3176f
+148, 0x2f0ca0fc
+149, 0x17f51e2
+150, 0x7c1fbf55
+151, 0xf09e9cd0
+152, 0xe3d9bacd
+153, 0x4244db0a
+154, 0x876c09fc
+155, 0x9db4fc2f
+156, 0xd3771d60
+157, 0x25fc6a75
+158, 0xb309915c
+159, 0xc50ee027
+160, 0xaa5b7b38
+161, 0x4c650ded
+162, 0x1acb2879
+163, 0x50db5887
+164, 0x90054847
+165, 0xfef23e5b
+166, 0x2dd7b7d5
+167, 0x990b8c2e
+168, 0x6001a601
+169, 0xb5d314c4
+170, 0xfbfb7bf9
+171, 0x1aba997d
+172, 0x814e7304
+173, 0x989d956a
+174, 0x86d5a29c
+175, 0x70a9fa08
+176, 0xc4ccba87
+177, 0x7e9cb366
+178, 0xee18eb0a
+179, 0x44f5be58
+180, 0x91d4af2d
+181, 0x5ab6e593
+182, 0x9fd6bb4d
+183, 0x85894ce
+184, 0x728a2401
+185, 0xf006f6d4
+186, 0xd782741e
+187, 0x842cd5bd
+188, 0xfb5883aa
+189, 0x7e5a471
+190, 0x83ff6965
+191, 0xc9675c6b
+192, 0xb6ced3c7
+193, 0x3de6425b
+194, 0x25e14db4
+195, 0x69ca3dec
+196, 0x81342d13
+197, 0xd7cd8417
+198, 0x88d15e69
+199, 0xefba17c9
+200, 0x43d595e6
+201, 0x89d4cf25
+202, 0x7cae9b9b
+203, 0x2242c621
+204, 0x27fc3598
+205, 0x467b1d84
+206, 0xe84d4622
+207, 0xa26bf980
+208, 0x80411010
+209, 0xe2c2bfea
+210, 0xbc6ca25a
+211, 0x3ddb592a
+212, 0xdd46eb9e
+213, 0xdfe8f657
+214, 0x2cedc974
+215, 0xf0dc546b
+216, 0xd46be68f
+217, 0x26d8a5aa
+218, 0x76e96ba3
+219, 0x7d5b5353
+220, 0xf532237c
+221, 0x6478b79
+222, 0x9b81a5e5
+223, 0x5fc68e5c
+224, 0x68436e70
+225, 0x2a0043f9
+226, 0x108d523c
+227, 0x7a4c32a3
+228, 0x9c84c742
+229, 0x6f813dae
+230, 0xfcc5bbcc
+231, 0x215b6f3a
+232, 0x84cb321d
+233, 0x7913a248
+234, 0xb1e6b585
+235, 0x49376b31
+236, 0x1dc896b0
+237, 0x347051ad
+238, 0x5524c042
+239, 0xda0eef9d
+240, 0xf2e73342
+241, 0xbeee2f9d
+242, 0x7c702874
+243, 0x9eb3bd34
+244, 0x97b09700
+245, 0xcdbab1d4
+246, 0x4a2f6ed1
+247, 0x2047bda5
+248, 0x3ecc7005
+249, 0x8d0d5e67
+250, 0x40876fb5
+251, 0xb5fd2187
+252, 0xe915d8af
+253, 0x9a2351c7
+254, 0xccc658ae
+255, 0xebb1eddc
+256, 0xc4a83671
+257, 0xffb2548f
+258, 0xe4fe387a
+259, 0x477aaab4
+260, 0x8475a4e4
+261, 0xf8823e46
+262, 0xe4130f71
+263, 0xbdb54482
+264, 0x98fe0462
+265, 0xf36b27b8
+266, 0xed7733da
+267, 0x5f428afc
+268, 0x43a3a21a
+269, 0xf8370b55
+270, 0xfade1de1
+271, 0xd9a038ea
+272, 0x3c69af23
+273, 0x24df7dd0
+274, 0xf66d9353
+275, 0x71d811be
+276, 0xcc4d024b
+277, 0xb8c30bf0
+278, 0x4198509d
+279, 0x8b37ba36
+280, 0xa41ae29a
+281, 0x8cf7799e
+282, 0x5cd0136a
+283, 0xa11324ef
+284, 0x2f8b6d4b
+285, 0x3657cf17
+286, 0x35b6873f
+287, 0xee6e5bd7
+288, 0xbeeaa98
+289, 0x9ad3c581
+290, 0xe2376c3f
+291, 0x738027cc
+292, 0x536ac839
+293, 0xf066227
+294, 0x6c9cb0f9
+295, 0x84082ae6
+296, 0xab38ae9d
+297, 0x493eade9
+298, 0xcb630b3a
+299, 0x64d44250
+300, 0xe5efb557
+301, 0xea2424d9
+302, 0x11a690ba
+303, 0x30a48ae4
+304, 0x58987e53
+305, 0x94ec6076
+306, 0x5d3308fa
+307, 0xf1635ebb
+308, 0x56a5ab90
+309, 0x2b2f2ee4
+310, 0x6f9e6483
+311, 0x8b93e327
+312, 0xa7ce140b
+313, 0x4c8aa42
+314, 0x7657bb3f
+315, 0xf250fd75
+316, 0x1edfcb0f
+317, 0xdb42ace3
+318, 0xf8147e16
+319, 0xd1992bd
+320, 0x64bb14d1
+321, 0x423e724d
+322, 0x7b172f7c
+323, 0x17171696
+324, 0x4acaf83b
+325, 0x7a83527e
+326, 0xfc980c60
+327, 0xc8b56bb
+328, 0x2453f77f
+329, 0x85ad1bf9
+330, 0x62a85dfe
+331, 0x48238c4d
+332, 0xbb3ec1eb
+333, 0x4c1c039c
+334, 0x1f37f571
+335, 0x98aecb63
+336, 0xc3b3ddd6
+337, 0xd22dad4
+338, 0xe49671a3
+339, 0xe3baf945
+340, 0xb9e21680
+341, 0xda562856
+342, 0xe8b88ce4
+343, 0x86f88de2
+344, 0x986faf76
+345, 0x6f0025c3
+346, 0x3fe21234
+347, 0xd8d3f729
+348, 0xc2d11c6f
+349, 0xd4f9e8f
+350, 0xf61a0aa
+351, 0xc48bb313
+352, 0xe944e940
+353, 0xf1801b2e
+354, 0x253590be
+355, 0x981f069d
+356, 0x891454d8
+357, 0xa4f824ad
+358, 0x6dd2cc48
+359, 0x3018827e
+360, 0x3fb329e6
+361, 0x65276517
+362, 0x8d2c0dd2
+363, 0xc965b48e
+364, 0x85d14d90
+365, 0x5a51623c
+366, 0xa9573d6a
+367, 0x82d00edf
+368, 0x5ed7ce07
+369, 0x1d946abc
+370, 0x24fa567b
+371, 0x83ef5ecc
+372, 0x9001724a
+373, 0xc4fe48f3
+374, 0x1e07c25c
+375, 0xf4d5e65e
+376, 0xb734f6e9
+377, 0x327a2df8
+378, 0x766d59b7
+379, 0x625e6b61
+380, 0xe82f32d7
+381, 0x1566c638
+382, 0x2e815871
+383, 0x606514aa
+384, 0x36b7386e
+385, 0xcaa8ce08
+386, 0xb453fe9c
+387, 0x48574e23
+388, 0x71f0da06
+389, 0xa8a79463
+390, 0x6b590210
+391, 0x86e989db
+392, 0x42899f4f
+393, 0x7a654ef9
+394, 0x4c4fe932
+395, 0x77b2fd10
+396, 0xb6b4565c
+397, 0xa2e537a3
+398, 0xef5a3dca
+399, 0x41235ea8
+400, 0x95c90541
+401, 0x50ad32c4
+402, 0xc1b8e0a4
+403, 0x498e9aab
+404, 0xffc965f1
+405, 0x72633485
+406, 0x3a731aef
+407, 0x7cfddd0b
+408, 0xb04d4129
+409, 0x184fc28e
+410, 0x424369b0
+411, 0xf9ae13a1
+412, 0xaf357c8d
+413, 0x7a19228e
+414, 0xb46de2a8
+415, 0xeff2ac76
+416, 0xa6c9357b
+417, 0x614f19c1
+418, 0x8ee1a53f
+419, 0xbe1257b1
+420, 0xf72651fe
+421, 0xd347c298
+422, 0x96dd2f23
+423, 0x5bb1d63e
+424, 0x32e10887
+425, 0x36a144da
+426, 0x9d70e791
+427, 0x5e535a25
+428, 0x214253da
+429, 0x2e43dd40
+430, 0xfc0413f4
+431, 0x1f5ea409
+432, 0x1754c126
+433, 0xcdbeebbe
+434, 0x1fb44a14
+435, 0xaec7926
+436, 0xb9d9a1e
+437, 0x9e4a6577
+438, 0x8b1f04c5
+439, 0x19854e8a
+440, 0x531080cd
+441, 0xc0cbd73
+442, 0x20399d77
+443, 0x7d8e9ed5
+444, 0x66177598
+445, 0x4d18a5c2
+446, 0xe08ebf58
+447, 0xb1f9c87b
+448, 0x66bedb10
+449, 0x26670d21
+450, 0x7a7892da
+451, 0x69b69d86
+452, 0xd04f1d1c
+453, 0xaf469625
+454, 0x7946b813
+455, 0x1ee596bd
+456, 0x7f365d85
+457, 0x795b662b
+458, 0x194ad02d
+459, 0x5a9649b5
+460, 0x6085e278
+461, 0x2cf54550
+462, 0x9c77ea0b
+463, 0x3c6ff8b
+464, 0x2141cd34
+465, 0xb90bc671
+466, 0x35037c4b
+467, 0xd04c0d76
+468, 0xc75bff8
+469, 0x8f52003b
+470, 0xfad3d031
+471, 0x667024bc
+472, 0xcb04ea36
+473, 0x3e03d587
+474, 0x2644d3a0
+475, 0xa8fe99ba
+476, 0x2b9a55fc
+477, 0x45c4d44a
+478, 0xd059881
+479, 0xe07fcd20
+480, 0x4e22046c
+481, 0x7c2cbf81
+482, 0xbf7f23de
+483, 0x69d924c3
+484, 0xe53cd01
+485, 0x3879017c
+486, 0xa590e558
+487, 0x263bc076
+488, 0x245465b1
+489, 0x449212c6
+490, 0x249dcb29
+491, 0x703d42d7
+492, 0x140eb9ec
+493, 0xc86c5741
+494, 0x7992aa5b
+495, 0xb8b76a91
+496, 0x771dac3d
+497, 0x4ecd81e3
+498, 0xe5ac30b3
+499, 0xf4d7a5a6
+500, 0xac24b97
+501, 0x63494d78
+502, 0x627ffa89
+503, 0xfa4f330
+504, 0x8098a1aa
+505, 0xcc0c61dc
+506, 0x34749fa0
+507, 0x7f217822
+508, 0x418d6f15
+509, 0xa4b6e51e
+510, 0x1036de68
+511, 0x1436986e
+512, 0x44df961d
+513, 0x368e4651
+514, 0x6a9e5d8c
+515, 0x27d1597e
+516, 0xa1926c62
+517, 0x8d1f2b55
+518, 0x5797eb42
+519, 0xa90f9e81
+520, 0x57547b10
+521, 0xdbbcca8e
+522, 0x9edd2d86
+523, 0xbb0a7527
+524, 0x7662380c
+525, 0xe7c98590
+526, 0x950fbf3f
+527, 0xdc2b76b3
+528, 0x8a945102
+529, 0x3f0a1a85
+530, 0xeb215834
+531, 0xc59f2802
+532, 0xe2a4610
+533, 0x8b5a8665
+534, 0x8b2d9933
+535, 0x40a4f0bc
+536, 0xaab5bc67
+537, 0x1442a69e
+538, 0xdf531193
+539, 0x698d3db4
+540, 0x2d40324e
+541, 0x1a25feb2
+542, 0xe8cc898f
+543, 0xf12e98f5
+544, 0xc03ad34c
+545, 0xf62fceff
+546, 0xdd827e1e
+547, 0x7d8ccb3b
+548, 0xab2d6bc1
+549, 0xc323a124
+550, 0x8184a19a
+551, 0xc3c4e934
+552, 0x5487424d
+553, 0xd6a81a44
+554, 0x90a8689d
+555, 0xe69c4c67
+556, 0xbdae02dd
+557, 0x72a18a79
+558, 0x2a88e907
+559, 0x31cf4b5d
+560, 0xb157772f
+561, 0x206ba601
+562, 0x18529232
+563, 0x7dac90d8
+564, 0x3a5f8a09
+565, 0x9f4b64a3
+566, 0xae373af9
+567, 0x1d79447c
+568, 0x2a23684b
+569, 0x41fb7ba4
+570, 0x55e4bb9e
+571, 0xd7619d3e
+572, 0xc04e4dd8
+573, 0x8418d516
+574, 0x2b2ca585
+575, 0xfa8eedf
+576, 0x5bafd977
+577, 0x31974fb0
+578, 0x9eb6697b
+579, 0xc8be22f5
+580, 0x173b126a
+581, 0x8809becf
+582, 0x3e41efe1
+583, 0x3d6cbbb8
+584, 0x278c81d8
+585, 0xa6f08434
+586, 0xa0e6601d
+587, 0x2fccd88d
+588, 0x3cbc8beb
+589, 0x5f65d864
+590, 0xa1ff8ddf
+591, 0x609dcb7c
+592, 0x4a4e1663
+593, 0xeae5531
+594, 0x962a7c85
+595, 0x1e110607
+596, 0x8c5db5d0
+597, 0xc7f2337e
+598, 0xc94fcc9c
+599, 0xe7f62629
+600, 0x6c9aa9f8
+601, 0x2e27fe0e
+602, 0x4d0dae12
+603, 0x9eecf588
+604, 0x977ba3f2
+605, 0xed0a51af
+606, 0x3f3ec633
+607, 0xc174b2ec
+608, 0x590be8a9
+609, 0x4f630d18
+610, 0xf579e989
+611, 0xe2a55584
+612, 0xee11edcd
+613, 0x150a4833
+614, 0xc0a0535c
+615, 0xb5e00993
+616, 0xb6435700
+617, 0xa98dbff
+618, 0x315716af
+619, 0x94395776
+620, 0x6cbd48d9
+621, 0xab17f8fc
+622, 0xa794ffb7
+623, 0x6b55e231
+624, 0x89ff5783
+625, 0x431dcb26
+626, 0x270f9bf8
+627, 0x2af1b8d0
+628, 0x881745ed
+629, 0x17e1be4e
+630, 0x132a0ec4
+631, 0x5712df17
+632, 0x2dfb3334
+633, 0xf5a35519
+634, 0xcafbdac6
+635, 0x73b6189d
+636, 0x10107cac
+637, 0x18c1045e
+638, 0xbc19bbad
+639, 0x8b4f05ac
+640, 0x5830d038
+641, 0x468cd98a
+642, 0x5b83a201
+643, 0xf0ccdd9c
+644, 0xcb20c4bd
+645, 0x1ff186c9
+646, 0xcdddb47f
+647, 0x5c65ce6
+648, 0xb748c580
+649, 0x23b6f262
+650, 0xe2ba8e5c
+651, 0x9a164a03
+652, 0x62d3322e
+653, 0x918d8b43
+654, 0x45c8b49d
+655, 0xce172c6e
+656, 0x23febc6
+657, 0x84fdc5b7
+658, 0xe7d1fd82
+659, 0xf0ddf3a6
+660, 0x87050436
+661, 0x13d46375
+662, 0x5b191c78
+663, 0x2cbd99c0
+664, 0x7686c7f
+665, 0xcff56c84
+666, 0x7f9b4486
+667, 0xefc997fe
+668, 0x984d4588
+669, 0xfa44f36a
+670, 0x7a5276c1
+671, 0xcfde6176
+672, 0xcacf7b1d
+673, 0xcffae9a7
+674, 0xe98848d5
+675, 0xd4346001
+676, 0xa2196cac
+677, 0x217f07dc
+678, 0x42d5bef
+679, 0x6f2e8838
+680, 0x4677a24
+681, 0x4ad9cd54
+682, 0x43df42af
+683, 0x2dde417
+684, 0xaef5acb1
+685, 0xf377f4b3
+686, 0x7d870d40
+687, 0xe53df1c2
+688, 0xaeb5be50
+689, 0x7c92eac0
+690, 0x4f00838c
+691, 0x91e05e84
+692, 0x23856c80
+693, 0xc4266fa6
+694, 0x912fddb
+695, 0x34d42d22
+696, 0x6c02ffa
+697, 0xe47d093
+698, 0x183c55b3
+699, 0xc161d142
+700, 0x3d43ff5f
+701, 0xc944a36
+702, 0x27bb9fc6
+703, 0x75c91080
+704, 0x2460d0dc
+705, 0xd2174558
+706, 0x68062dbf
+707, 0x778e5c6e
+708, 0xa4dc9a
+709, 0x7a191e69
+710, 0xc084b2ba
+711, 0xbb391d2
+712, 0x88849be
+713, 0x69c02714
+714, 0x69d4a389
+715, 0x8f51854d
+716, 0xaf10bb82
+717, 0x4d5d1c77
+718, 0x53b53109
+719, 0xa0a92aa0
+720, 0x83ecb757
+721, 0x5325752a
+722, 0x114e466e
+723, 0x4b3f2780
+724, 0xa7a6a39c
+725, 0x5e723357
+726, 0xa6b8be9b
+727, 0x157c32ff
+728, 0x8b898012
+729, 0xd7ff2b1e
+730, 0x69cd8444
+731, 0x6ad8030c
+732, 0xa08a49ec
+733, 0xfbc055d3
+734, 0xedf17e46
+735, 0xc9526200
+736, 0x3849b88a
+737, 0x2746860b
+738, 0xae13d0c1
+739, 0x4f15154f
+740, 0xd65c3975
+741, 0x6a377278
+742, 0x54d501f7
+743, 0x81a054ea
+744, 0x143592ba
+745, 0x97714ad6
+746, 0x4f9926d9
+747, 0x4f7ac56d
+748, 0xe87ca939
+749, 0x58b76f6f
+750, 0x60901ad8
+751, 0x3e401bb6
+752, 0xa058468e
+753, 0xc0bb14f6
+754, 0x2cb8f02a
+755, 0x7c2cf756
+756, 0x34c31de5
+757, 0x9b243e83
+758, 0xa5c85ab4
+759, 0x2741e3b3
+760, 0x1249000e
+761, 0x3fc4e72b
+762, 0xa3e038a2
+763, 0x952dd92c
+764, 0x2b821966
+765, 0xfa81b365
+766, 0x530919b9
+767, 0x4486d66f
+768, 0xccf4f3c1
+769, 0xa8bddd1d
+770, 0xcc295eb9
+771, 0xfccbe42f
+772, 0x38bacd8d
+773, 0x2261854f
+774, 0x56068c62
+775, 0x9bdaeb8
+776, 0x555fa5b6
+777, 0x20fe615e
+778, 0x49fb23d3
+779, 0xd093bad6
+780, 0x54919e86
+781, 0x7373eb24
+782, 0xfbaa7a98
+783, 0x5f62fb39
+784, 0xe03bc9ec
+785, 0xa5074d41
+786, 0xa1cefb1
+787, 0x13912d74
+788, 0xf6421b8
+789, 0xfcb48812
+790, 0x8f1db50b
+791, 0xc1654b87
+792, 0x948b43c2
+793, 0xf503ef77
+794, 0x117d891d
+795, 0x5493ffa
+796, 0x171313b1
+797, 0xa4b62e1e
+798, 0x77454ea6
+799, 0xbea0aff0
+800, 0x13c36389
+801, 0xe3b60bac
+802, 0xa176bed3
+803, 0x2863d428
+804, 0xe2314f46
+805, 0xa85cd3d4
+806, 0x7866e57
+807, 0x8f03f5bc
+808, 0x239ae
+809, 0x46f279fb
+810, 0xcca00559
+811, 0xaa07a104
+812, 0x89123d08
+813, 0x2e6856ba
+814, 0x43a9780d
+815, 0x676cff25
+816, 0x6744b87d
+817, 0xee260d4f
+818, 0xb98d8b77
+819, 0x9b0ca455
+820, 0x659f6fe
+821, 0x28d20d1c
+822, 0x601f2657
+823, 0xdec3073e
+824, 0x61263863
+825, 0x1a13435a
+826, 0x27497d1e
+827, 0x17a8458e
+828, 0xdddc407d
+829, 0x4bb2e8ac
+830, 0x16b2aedb
+831, 0x77ccd696
+832, 0x9d108fcd
+833, 0x25ad233e
+834, 0xaa9bc370
+835, 0xa873ab50
+836, 0xaf19c9d9
+837, 0x696e1e6b
+838, 0x1fdc4bf4
+839, 0x4c2ebc81
+840, 0xde4929ed
+841, 0xf4d0c10c
+842, 0xb6595b76
+843, 0x75cbb1b3
+844, 0xbcb6de49
+845, 0xe23157fd
+846, 0x5e596078
+847, 0xa69b0d29
+848, 0x2118a41
+849, 0x7088c16
+850, 0xc75e1e1
+851, 0x6a4af2d6
+852, 0xf19c6521
+853, 0xaff7b3b1
+854, 0x615295c7
+855, 0xbda3a8d7
+856, 0x5b5ca72e
+857, 0xdad9d80f
+858, 0xfa81c084
+859, 0xf4703fa
+860, 0x3ca54540
+861, 0xa8961d51
+862, 0x53d1ecc2
+863, 0x808d83b6
+864, 0x68e8c48e
+865, 0x89be2039
+866, 0x9088ea11
+867, 0xb8665d12
+868, 0x91272f9
+869, 0x53dddff2
+870, 0xb7a54ab
+871, 0xd2b645ca
+872, 0x99fb8590
+873, 0x5315c8e
+874, 0x2a913806
+875, 0x7f15eb2b
+876, 0xa7f1cc5d
+877, 0xbb2ee836
+878, 0xd9fafd60
+879, 0x17448d6f
+880, 0x999ec436
+881, 0x482ec606
+882, 0x9b403c0e
+883, 0x569eb51b
+884, 0xb275d1a6
+885, 0xadd29c31
+886, 0xb7ebdb15
+887, 0xdfef3662
+888, 0x51aba6db
+889, 0x6d41946d
+890, 0x77bf8896
+891, 0xcafa6fab
+892, 0x976ab40f
+893, 0x49a6d86b
+894, 0x56639e55
+895, 0x9945b996
+896, 0x81459b50
+897, 0xbce97542
+898, 0xe397c9c9
+899, 0x247a5955
+900, 0xb72b1573
+901, 0x86306f86
+902, 0x34f65dc5
+903, 0x909360c0
+904, 0xf3f696ef
+905, 0xcb9faae5
+906, 0x93daecd9
+907, 0xde1af7af
+908, 0x43a1f2d
+909, 0x6d75cde5
+910, 0x9e412b6
+911, 0x5673fed
+912, 0x16bb511a
+913, 0x35ef4cca
+914, 0x4e615aca
+915, 0x5cdaf47a
+916, 0x26676047
+917, 0x8c199325
+918, 0x2adf0cb9
+919, 0x84f2e6fd
+920, 0x5e627f64
+921, 0xb7cee354
+922, 0x542ab4a6
+923, 0xe59cd83b
+924, 0x89cc3f10
+925, 0x92b0f5f
+926, 0xc1328370
+927, 0x8208d9f7
+928, 0x68eb00cf
+929, 0xfadd4ac4
+930, 0x2517784f
+931, 0x4042b99
+932, 0x75ce0230
+933, 0x97c5a1b4
+934, 0x1a97f709
+935, 0x4c62781e
+936, 0xf530a83
+937, 0x75776413
+938, 0x321c7240
+939, 0x6afe4e36
+940, 0xad00a2b4
+941, 0xbc05477d
+942, 0xb0911e80
+943, 0x9935b87d
+944, 0xd535eec5
+945, 0x149af45e
+946, 0x786934b0
+947, 0xbc13cdac
+948, 0x208bfa2e
+949, 0xcf4b39cc
+950, 0x6ac6c172
+951, 0xbfa9a37
+952, 0x42d28db6
+953, 0x2bf1ea63
+954, 0xbed6e677
+955, 0x50325d27
+956, 0xa79d3b8b
+957, 0x52448bb1
+958, 0xefaad1bd
+959, 0x833a2e54
+960, 0xd9de549a
+961, 0x9f59672f
+962, 0x9d5f5f16
+963, 0x1c914489
+964, 0xc08fa058
+965, 0xb188698b
+966, 0xdc4672b5
+967, 0x594f720e
+968, 0x56ed428f
+969, 0x9b0898af
+970, 0x8a64d3d5
+971, 0x773308d6
+972, 0x84d62098
+973, 0x46da7cf9
+974, 0x1114eae7
+975, 0xf9f2a092
+976, 0x5363a28
+977, 0xf2db7b3a
+978, 0x102c71a9
+979, 0xe8e76aaf
+980, 0x77a97b3b
+981, 0x77b090d
+982, 0x1099620e
+983, 0xa6daaae6
+984, 0x86ff4713
+985, 0xc0ef85b8
+986, 0xf621d409
+987, 0xfd1561e2
+988, 0x4bcc687d
+989, 0x596f760
+990, 0x7c8819f9
+991, 0x8cb865b8
+992, 0xadea115a
+993, 0x56609348
+994, 0xb321ac14
+995, 0x1bac7db2
+996, 0x5fe6ee2
+997, 0xe9bfe072
+998, 0x15549e74
+999, 0xad8c191b
diff --git a/numpy/random/tests/data/pcg64-testset-1.csv b/numpy/random/tests/data/pcg64-testset-1.csv
new file mode 100644
index 000000000..0c8271fab
--- /dev/null
+++ b/numpy/random/tests/data/pcg64-testset-1.csv
@@ -0,0 +1,1001 @@
+seed, 0xdeadbeaf
+0, 0x60d24054e17a0698
+1, 0xd5e79d89856e4f12
+2, 0xd254972fe64bd782
+3, 0xf1e3072a53c72571
+4, 0xd7c1d7393d4115c9
+5, 0x77b75928b763e1e2
+6, 0xee6dee05190f7909
+7, 0x15f7b1c51d7fa319
+8, 0x27e44105f26ac2d7
+9, 0xcc0d88b29e5b415
+10, 0xe07b1a90c685e361
+11, 0xd2e430240de95e38
+12, 0x3260bca9a24ca9da
+13, 0x9b3cf2e92385adb7
+14, 0x30b5514548271976
+15, 0xa3a1fa16c124faf9
+16, 0xf53e17e918e45bb6
+17, 0x26f19faaeb833bfc
+18, 0x95e1d605730cce1b
+19, 0xa7b520c5c093c1aa
+20, 0x4b68c010c9b106a3
+21, 0x25e19fe91df703f0
+22, 0x898364bb0bf593cb
+23, 0x5bd6ab7dbaa125db
+24, 0xd1fe47f25152045c
+25, 0x3bb11919addf2409
+26, 0x26a8cb7b3f54af8
+27, 0xe6a27ee11200aa24
+28, 0x7cb585ab01e22000
+29, 0x78e60028676d2ef3
+30, 0x5c32535e5a899528
+31, 0x83e8b6f8c4a46fb3
+32, 0xe56ef7668a161246
+33, 0x36dcbc15aeb73055
+34, 0x5ea247f0bd188acb
+35, 0x438b547b84601a80
+36, 0x8acda2a1273e9e3d
+37, 0x2b05e30a4b40c24c
+38, 0xfd87236bd13af032
+39, 0x471df211d8d985ef
+40, 0x18e8a5609a793292
+41, 0x46f0951fab6dc4e3
+42, 0x6c199c4e700f6795
+43, 0xf04aa16bfb7d22cb
+44, 0xd763d269fbaffc89
+45, 0x9991930cefbe5c2b
+46, 0xb2a11b953f824c96
+47, 0x63fd9f52172c44b0
+48, 0x183bdad907b1d848
+49, 0xe17953cddb931c52
+50, 0x515cf16726ec205a
+51, 0x88c327605150711a
+52, 0xc7090dd79cbc8dc3
+53, 0xcb487cedeb00a350
+54, 0xc8abf254d87b657
+55, 0xd43cc4cbfb493d1a
+56, 0x8705452e5d9ed1e
+57, 0xcecd11446769cf43
+58, 0xde72156c8d65bc69
+59, 0x796a8f0f47d52ee8
+60, 0xb4c0da443917d6c3
+61, 0xe07ad7568a8e3dc3
+62, 0xc24a8da39ce6dc21
+63, 0x92b21ea80a8556eb
+64, 0x572f21e531edf3af
+65, 0x9b917ed56bbed198
+66, 0xe65fd8ddc5ab3d7d
+67, 0xf55a80a8ec84fa18
+68, 0x18fc22e1a5227b61
+69, 0x72305dc7eeaa79d3
+70, 0x47ce58a36e7592cf
+71, 0x14c6374340c0f7cc
+72, 0x6f98273d4eb5a2c
+73, 0x59a8702c46fe8f8a
+74, 0xb67cbd8113cfe57f
+75, 0xaa03c5db5f5b7690
+76, 0x3fb0f77ea4568013
+77, 0x756530990398b26e
+78, 0x4c1952b2a3a6a343
+79, 0x1da15c5383074582
+80, 0xb405b21c81c274f7
+81, 0xbe664677a16788b
+82, 0x9d2e37550bcee656
+83, 0x8b4589f0d9defe02
+84, 0x2935f018ee06a59
+85, 0x3834bf88be97ed11
+86, 0xa610d049cea79b6d
+87, 0xd49ffc0d09a59ea9
+88, 0x4073365b76567adf
+89, 0x499eefb9bb7513e2
+90, 0x74a743ee6b0138a9
+91, 0x3bf0880f2d947594
+92, 0x555d1c0498600a99
+93, 0x923b32a88ef2ffa4
+94, 0x7325411065fbedea
+95, 0x9f4129ff8b79d300
+96, 0xab2b0a9b8a3785dc
+97, 0x11734bdfba3a1713
+98, 0xc8333398841ba585
+99, 0xee2409cc234e6742
+100, 0xf6638e700872ecd2
+101, 0x10875300c13cd284
+102, 0x27a9bbed7c15b2d3
+103, 0x3c87f8fef31ce9bd
+104, 0x92be263cd0914a95
+105, 0xa7b0f11bc742307e
+106, 0x4a56f788cc1c1a3c
+107, 0x4a130fa32257a48b
+108, 0x5d4d9eda16e90286
+109, 0x7cc2af564844bedc
+110, 0x2532867bfe7cda1a
+111, 0xb1c504676611fd17
+112, 0xce8e86cfb4189aee
+113, 0x99685898980d1970
+114, 0x8c3b67db23bcf1e
+115, 0x73e14c93905b135f
+116, 0xf0271b64ac2bd4d3
+117, 0xf4beba82f3ec1b2d
+118, 0x1cdbf3ee9f210af
+119, 0x2e938557c09c3ea6
+120, 0x2d314ccfa6ffd81d
+121, 0x31ad47079950ade4
+122, 0x342b27547b900872
+123, 0x171b0e20b9ef1a76
+124, 0xdf10ce6318b03654
+125, 0x1d625df4aa718897
+126, 0x8712715a9f6e02ec
+127, 0xb4a072da725bca3b
+128, 0x19d346cb7734bd42
+129, 0xfd4281d311cb2958
+130, 0x58274c9519fc8789
+131, 0x4cacf29d885fd544
+132, 0x784b14d1c2523b80
+133, 0x2d25242131bb2373
+134, 0xcd2a5e43a7d9abf9
+135, 0x15eda3806e650ecb
+136, 0xdaac5e277d764d96
+137, 0xdc5a5dd59aaa94e0
+138, 0x40d00237a46d5999
+139, 0x6205dd35a692743f
+140, 0xbbd8236740361f09
+141, 0x1625c9f4e7288bf9
+142, 0xb74f12df1479e3ce
+143, 0xb2d72a51b43d7131
+144, 0xf006a324b3707c83
+145, 0x28e8ab4abe7655b8
+146, 0xfb480093ad7ab55
+147, 0x3f8abd0d6ff8d272
+148, 0xc81a94177ac26bb7
+149, 0x3cdc178307751b14
+150, 0x9de84cc2b10ba025
+151, 0x3f8ab5aefcd046e2
+152, 0x43bdb894e1ee83b2
+153, 0xe288a40f3f06ac9d
+154, 0xdab62a7d04b4f30f
+155, 0x49f4e20295e1a805
+156, 0x3643764805e0edef
+157, 0x9449954618b6b
+158, 0x6c87e0d4508e0ce0
+159, 0x3a334be688a9dd7b
+160, 0xb35c39228776e499
+161, 0xc4118bfff938490e
+162, 0x88cbde3dcbb034b2
+163, 0xf91b287793c417c3
+164, 0x42b15f731a59f5b3
+165, 0xffa27104bbe4814d
+166, 0x1b6789d138beccde
+167, 0x542c2c1440d0ceb9
+168, 0x367294504d18fa0d
+169, 0xf918b60e804a1b58
+170, 0xd390964e33a9d0e3
+171, 0x23bb1be7c4030fe8
+172, 0x9731054d039a8afb
+173, 0x1a6205026b9d139b
+174, 0x2fa13b318254a07e
+175, 0x69571de7d8520626
+176, 0x641a13d7c03332b7
+177, 0x76a6237818f7a441
+178, 0x4e77860d0c660d81
+179, 0x4441448a1c1cbdb2
+180, 0xccd7783a042046e5
+181, 0xf620d8e0805e3200
+182, 0x7de02971367fdd0c
+183, 0x539c263c5914cab1
+184, 0x9c3b9ba1a87bbf08
+185, 0x6d95baa34cda215f
+186, 0x2db3f83ace0bac5f
+187, 0x7f5af1da2dc670a4
+188, 0xfcc098d16c891bfb
+189, 0x81a33df1d7a5ab12
+190, 0x767b0f863c8e9882
+191, 0x7a92983830de483d
+192, 0xfa7598c37a79ac25
+193, 0xb89b3ca42ce03053
+194, 0x457a542b8efed4f7
+195, 0x571b7737fd0eeda7
+196, 0xa0f59e524485c0a
+197, 0x82dca766b7901efd
+198, 0xa68243caf6a3bd5d
+199, 0x1bac981c6c740e5e
+200, 0xbcd51bedf9103e44
+201, 0x4e197efd3ae5a7bf
+202, 0x523568efd782268b
+203, 0x5ec4ef1191fef09
+204, 0xed751ed5e31c9ab
+205, 0x44eac24de03e1b29
+206, 0x9237d57c011d3fb3
+207, 0xa8c6da0f7692f235
+208, 0x9f9eb6bc15d6cac7
+209, 0x34bb8e0c93427aad
+210, 0x115febd738eaac4a
+211, 0xa439991ed139d27a
+212, 0x45c7c2633d8710a2
+213, 0x48b7475f3405a3ce
+214, 0x80158497c77bd00b
+215, 0x935c316a5b1657cb
+216, 0x59c5d54440e9695e
+217, 0x337c78c5b3d0ede2
+218, 0x8c46bb956b93790d
+219, 0xbf1dd03e471d71c5
+220, 0x2d375e90a4bef583
+221, 0xd0365428331b3790
+222, 0xfcd3969ac827ecd4
+223, 0x392fb6c580498410
+224, 0x6d6db4ceab5ea6c0
+225, 0x9bf84f1972e24786
+226, 0x798dfd820959dcc5
+227, 0x2e425095e65e8bfb
+228, 0x8c1aa11536b1c9c3
+229, 0xd28e2ef9b12f6f74
+230, 0x86583bc98c8f78d2
+231, 0x489877530e3f93e7
+232, 0xb1d9430631104a15
+233, 0x1814f6098e6263bd
+234, 0x8e2658a4e0d4cd53
+235, 0x5afe20e2531cdb2a
+236, 0x30d02f7c4755c9bf
+237, 0xe1e217cda16ed2d2
+238, 0xccb4913a42e3b791
+239, 0xfff21363ac183226
+240, 0xe788690bbda147a7
+241, 0x76905cf5917bfc6a
+242, 0x2a8fa58f7916f52c
+243, 0xf903c0cc0357815a
+244, 0x15d20f243a4998d2
+245, 0x5b7decee5a86ea44
+246, 0x114f7fc421211185
+247, 0x328eb21715764c50
+248, 0xaffaa3f45c0678fd
+249, 0x2579e6ef50378393
+250, 0x7610ab7743c19795
+251, 0xf9923d2bd101b197
+252, 0x57e42e7a62ba7e53
+253, 0x9f1dc217b4f02901
+254, 0x88a9ebd86509b234
+255, 0x867fc926aecc8591
+256, 0xaf22c1bfef04c718
+257, 0x39f701f0313f4288
+258, 0x6171ad397e6faab2
+259, 0x239bb5b9abdec4fc
+260, 0xd9a591e25dd01c6e
+261, 0x826dc4a75b628e49
+262, 0xf112b152c408f47
+263, 0x6843a06110f86c0
+264, 0x965e56a7185c1332
+265, 0x8d84492edbc71710
+266, 0xeee8ec111cfd1319
+267, 0xf2858e94ad98e458
+268, 0xbc9589fdf5f3a97e
+269, 0xaf0ceef3bc375130
+270, 0x48f4aaf13fa75c1e
+271, 0x111e9db47bee758f
+272, 0xea3171df130164ba
+273, 0x2a7bbe30bf827ab6
+274, 0xc516c3fdbf758c35
+275, 0xec55097754b04be5
+276, 0x374a997d52b6d3e6
+277, 0x487df5456085ffbc
+278, 0x528883b84df8eafe
+279, 0x805f77ab5ba26f86
+280, 0x8eb81477dc04f213
+281, 0x471ea08ec6794d72
+282, 0x69d3667ecc4d2176
+283, 0x98b7b6e295548a66
+284, 0x3877713c173f8f2
+285, 0xa00542570d0e8de3
+286, 0xf534b1bfa4033e50
+287, 0x7e1fedeac8bf6b26
+288, 0x8043f37c89628af4
+289, 0x1dd7039ec295e86d
+290, 0xce9c05b763a40cc4
+291, 0x246926481e61028f
+292, 0xb7cb0f1babf5893b
+293, 0xefe6b777f37fc63e
+294, 0xebbcabb4cb35cdcb
+295, 0x39fa63cd711eeea9
+296, 0xad5d3ba7aaf30c8d
+297, 0x8e9e78fe46021990
+298, 0xc7eaef6e7d5a3c62
+299, 0xefccdd5495d3f386
+300, 0x2179557ee8cfc76a
+301, 0x88a77f621f0885ce
+302, 0xafda62674543d90c
+303, 0xb8e6fbe2e13e56c0
+304, 0x8bfbbe26a14f9b1a
+305, 0x1404f59f5851f8c3
+306, 0x1140c53a0489566d
+307, 0x3edf2d138b5c3f1d
+308, 0x75d6bb275d817dc
+309, 0x8e660ae27107664e
+310, 0x7a8021038ee303e1
+311, 0x2042ef5eefa9079f
+312, 0xe3e7b90bbf6d457a
+313, 0xf3f819d2bb9405b
+314, 0x522e42155cae0c10
+315, 0xf5bfbb975b40e233
+316, 0x2cf82b614dd95cfa
+317, 0x183ef4a96bc40e55
+318, 0x9f6e351c5ba4e752
+319, 0x37c1110683c90846
+320, 0x1d89b7a996d8a977
+321, 0x18a444f77c7cb4d9
+322, 0xd0a8a971b78dc893
+323, 0x860232fb9e6543f1
+324, 0x60b6097f51002555
+325, 0xca1e5214123e3894
+326, 0xe03fe695c95f99bb
+327, 0x2c7c6779d5f03622
+328, 0xafeeee42f63055d1
+329, 0x670dde905515936a
+330, 0x9a922f42b59fb094
+331, 0xddb5ff49af5a651a
+332, 0xe61b04c9e58ebbf8
+333, 0x4e459dcf272e7fc4
+334, 0xd549e92c16adceeb
+335, 0x7a17dba1299d4a9c
+336, 0x825d756109f2b585
+337, 0xba142e61a9cb203e
+338, 0xc2a19f00e9c04a30
+339, 0x2d0f8140d23d0652
+340, 0x8b866d4d4d6caaf4
+341, 0x4f11d90dd91f8217
+342, 0xf6efc37373b9e0d
+343, 0x248493d6cd6a4736
+344, 0xd12b6ae74a951a3e
+345, 0x56e34722070b70a7
+346, 0x22d3f201cc9fa0eb
+347, 0xbfdcc320008291b7
+348, 0x1a7a6922e9204fbd
+349, 0x831421e0c4945ae4
+350, 0x66316feddddf0e11
+351, 0xa8c86a1517456554
+352, 0x14a9049ad989e335
+353, 0x837022259f141ecd
+354, 0xcb71793a06c261f7
+355, 0x4aeefc07ebe09a79
+356, 0x8982f15aa3b6594b
+357, 0x67bccfa7ed9b0d5b
+358, 0xb377463b523e9dec
+359, 0x53d3d594870fecb7
+360, 0xa5274b1caec5a60a
+361, 0xd6316d0cb643db39
+362, 0xabc1a9b536de88ce
+363, 0xed2fdb1383d2a077
+364, 0x12319c6feb97221b
+365, 0x7e0f6cd40ef47403
+366, 0x86135c84fe26dbf8
+367, 0xc96622d3fbbee19b
+368, 0xe3989d8d8511573f
+369, 0x42cc365554d1fdc7
+370, 0x4c1a1eb8bbce8b4f
+371, 0xfc4e30e7ef2034c1
+372, 0xc490444317a91e76
+373, 0x7ccdf469ff5dc81c
+374, 0xf5a0da4110cc09d7
+375, 0x505227baf34c0fb5
+376, 0xbe58737e8a35cc88
+377, 0xd449bee91b3e8c41
+378, 0x3e590e23299d0e6
+379, 0x291a7d9e0a64caf7
+380, 0xdc6fafbdfebd2293
+381, 0x8223f1e259fe8a65
+382, 0x6186fbc9efd9e3df
+383, 0xfda39b07e4007ffb
+384, 0xfc19aea98574dc02
+385, 0xd0e10d354fcacd8c
+386, 0xc9619916544a55a5
+387, 0xd454d50a8c8558cd
+388, 0xcd94a246712d91e
+389, 0x76a771f5d1231cce
+390, 0xdd20cb2b7b370ee5
+391, 0xa6f4f50feca57c49
+392, 0x78c8fb431f17ab9c
+393, 0x1b692b79a59b43cc
+394, 0x4c45045d287da7e6
+395, 0x522132e18bf43928
+396, 0x25c458983138b41c
+397, 0x2a1fb426ef229796
+398, 0x74dc324c74e5dd3d
+399, 0x6df75e3eb6eb5374
+400, 0xb63f2f4f9ca25b61
+401, 0xac72286112ee54d6
+402, 0x5a966f3d0a6863c4
+403, 0x8d7046bc64a46fc2
+404, 0xa7b740fd6e3087eb
+405, 0xcdbcbe0340cfcdf5
+406, 0xcb632613bf312b65
+407, 0xa91b3f2c2aac238b
+408, 0xa06deb3f5ae555a3
+409, 0x29d72e1f8db69
+410, 0x2d004bae09728ea6
+411, 0xc6eee5dce0736cc1
+412, 0xa7493145500ff60f
+413, 0xc4d68c4aa18ab93c
+414, 0x8210c29e79d48d7f
+415, 0xd0999d7889ecbef6
+416, 0x6e3bd61e66e93566
+417, 0xe6cc13d47d7d7b1f
+418, 0x3d6f181f42e03979
+419, 0xbed4e14fd867604a
+420, 0xbe511c84067bd86d
+421, 0x49a876d89e697d38
+422, 0xc04c3dde8f889c98
+423, 0xaf293eeab0f53e3f
+424, 0x9f6291dd65732cd6
+425, 0xd7811ac01de78c01
+426, 0xe385cf0261d50ec2
+427, 0x5a64134b3542bbf
+428, 0xf9d1302bc6f13a68
+429, 0x5d2aabbea37d8c31
+430, 0xd9842e99a5192970
+431, 0x713eadc4cd30e837
+432, 0xb7b002fc72abb413
+433, 0x276cfeea526af1cf
+434, 0x8519fe79b633a0ce
+435, 0x2f0e87363705a3e2
+436, 0x9adbac0be3c371e7
+437, 0xf3f44ba899a6173c
+438, 0x782d6c29618fde2b
+439, 0x7f61062acec408f
+440, 0x6e79cd836359258f
+441, 0x5c8e9b138df5785a
+442, 0xa54359c9f39a9a84
+443, 0xeec3f033135084b0
+444, 0x883ee717787a535c
+445, 0x9a2422b513a73b00
+446, 0x2dd4beddcdd64a58
+447, 0x90c8a13202239c7b
+448, 0x85b352ab759646d9
+449, 0x139f5cb2e46c53aa
+450, 0xe1d3ba6c721c66d1
+451, 0xaa66e0edc4b60a98
+452, 0x3521275c75be29b6
+453, 0x490a5190b3edfa5d
+454, 0xd2abcdd2ccb2f14e
+455, 0x9d9be8bef4a5857d
+456, 0xde19676f13ef7755
+457, 0xdac2fee2e42615f3
+458, 0xf4239801cb02f2ab
+459, 0xaa8bf923ed91875c
+460, 0x61d18a1940e4c7c0
+461, 0x1eb6aa3d5f077a6d
+462, 0xee7374c063bf29d8
+463, 0x2f0a59e34d76268d
+464, 0xc92e80e17d1eb3e9
+465, 0xafd05b3ec3d2ca72
+466, 0x28a61ad8d6c497b8
+467, 0xa7094d6834ad7d47
+468, 0x57d80ea9eccbb4f
+469, 0xb047e0fee6cdaf16
+470, 0x44f41b5eb48c00bb
+471, 0xd6dc8e1eb9c8c9ba
+472, 0x47adfd2c638c7849
+473, 0x365d63db7d526c68
+474, 0xc21cda439016135d
+475, 0x14d10c3f0f98863c
+476, 0xa93e56f74e037602
+477, 0x3b4e9c8915bdc9
+478, 0xb46f5ae155e54aa2
+479, 0x8e470d21ce1943e1
+480, 0x60b96301b5ba2e8d
+481, 0x1b473a41d381f9ff
+482, 0xabcf5a8e3269e73f
+483, 0xd410f6e94fb21fa1
+484, 0x65d1a47eebf87e5e
+485, 0x48eaa201c61cb843
+486, 0x212c1abc2499bfc5
+487, 0x4255ad8377d2d8d
+488, 0x44caeef472010612
+489, 0xffae764524f572f2
+490, 0x78d374d20c9ee550
+491, 0x6e003206c0511cee
+492, 0x7998a159145bfb82
+493, 0x921239650bda1d4d
+494, 0xae05025509bcfdc5
+495, 0xc6430c980be407b4
+496, 0x78524f1744b153f1
+497, 0x84089e6f468181fe
+498, 0x8d0d21d7dfb6c254
+499, 0x90bad90502a33603
+500, 0x3072a403cbd16315
+501, 0xdfadddf3f1c040c2
+502, 0x22f0b0639d9ff975
+503, 0xb49e48a4cad0765b
+504, 0x95a0a04f8239709d
+505, 0x56e147a24a4c481f
+506, 0xacf16ef61dea4c7e
+507, 0x424040afd2700de6
+508, 0xc67e8096a3c717a9
+509, 0x39f164181dd0a399
+510, 0x2449cedc1d62198c
+511, 0x7a53df11a1f1a61c
+512, 0x5596f1d4a3badae3
+513, 0x38ed4c822072b3d0
+514, 0xf07ef346b3fd730a
+515, 0xfd349c35c3ed51fd
+516, 0x2f15c9c7890f8f32
+517, 0x3b470df52b173c29
+518, 0xd31bfc8981281af7
+519, 0xbbcc9bdf561215bb
+520, 0x5782fffea326574f
+521, 0xb0ebdcfcc5e03290
+522, 0x7fd89d93d2b3fbef
+523, 0x280ea1865d9ba2
+524, 0xe726959845b2c100
+525, 0xd0361f032cd7dbb1
+526, 0x3c65ec2028b81a22
+527, 0x5221e9b2188920bf
+528, 0xeb5ab27c4125ec20
+529, 0x80a32dd48b54f0a4
+530, 0x369b5ced1012bebb
+531, 0x582d35d76530bc6f
+532, 0x7b50dc9b48e1e37d
+533, 0x37fdfe8bbacf8dad
+534, 0x7a0cb7e6e93840ea
+535, 0xa1132c870be0b2ce
+536, 0x9d8ac2c68267cd1a
+537, 0x470969b647fa7df4
+538, 0xabcb7d8adf7e2d24
+539, 0xacdebec9bdf9eb1c
+540, 0xe30f4cbf7eb6a59
+541, 0x746673836c4df41d
+542, 0x75120a6b647bb326
+543, 0x2f4eab556c3f6878
+544, 0xd84651ab05405b7a
+545, 0x9e695808b9622284
+546, 0xc93b71e56aa6e1a5
+547, 0x2be7f3be4a7b7050
+548, 0x6497e910b6733241
+549, 0xcf7050dfd08076fc
+550, 0x4e3cc156eca183f7
+551, 0xf801a33d9326c265
+552, 0x6aa293c8a47d40e6
+553, 0x28c429755faa6230
+554, 0x82b818651f54e7bb
+555, 0xa84d726d7acdbead
+556, 0x5cfa535d5774965d
+557, 0x4a34b7b1cb48d53
+558, 0x86a7b5bce426de84
+559, 0xfcd2307cecdb7318
+560, 0x16dbaaa71181a038
+561, 0x88e7e8cd261c2547
+562, 0x3c09ba6d1d5ea913
+563, 0x5dd3d643734ee5b6
+564, 0x326d725fe8cbb33
+565, 0x7bcca9ca2da8e784
+566, 0x482dcf6b11d7f9a4
+567, 0x1291b605b4cd3e04
+568, 0x6988181b50e2f4a8
+569, 0x649e3c37131fc292
+570, 0x4eeb67b9e21eba54
+571, 0xc051d39073dec45f
+572, 0xc99c52e110270d67
+573, 0xcb813d5d77868add
+574, 0x423a5f13573e7ac0
+575, 0x231ac4cc4fe73616
+576, 0x4c22b888a6e600ea
+577, 0x8059a6dc7c9e25c6
+578, 0x49f498a5b8ad22de
+579, 0xf1e812cc6d1826c8
+580, 0xbbaf60abe8b11e00
+581, 0x1d31d7f4d8be9a6a
+582, 0xfeadce70a9a10c14
+583, 0xb47c635bc136996a
+584, 0xd88e694c8da030cb
+585, 0xc41bbe132aff1364
+586, 0x34249ab18a4b0800
+587, 0xf14b5c825aa736cc
+588, 0x2710be6b08df78e
+589, 0x2ab56bcc9bf9e740
+590, 0x9b7f6e591b5f648
+591, 0xfb665c3772f34135
+592, 0x628a0a5d2db5d8d5
+593, 0xb3e3f251e61b5259
+594, 0x82310ae33faf1b23
+595, 0x24af8723a65cbd0b
+596, 0x671c93282fc4ad97
+597, 0x6cabeaac77270cad
+598, 0xef4643fe38b02b7f
+599, 0x7b011549d1ac6653
+600, 0xe2af87b9fccfe89
+601, 0x36b71ad67197ac8a
+602, 0xdbba55d06f2fd93b
+603, 0xf571dbd764b7f7e5
+604, 0x38ea402501cdbd45
+605, 0xb8ab5b5b1bab2913
+606, 0xfab973c4d45f32bd
+607, 0x9364f1717c2636b9
+608, 0xfad00f4d983e00fe
+609, 0xc90c532a11aef75a
+610, 0x64a6eda96e44783c
+611, 0x35891f2eb84520be
+612, 0x28d216080caed43
+613, 0x129629cc5bd206f6
+614, 0x22c3d39822cbb4b3
+615, 0xf1efbf4cce1eaa2b
+616, 0x7070cba12524ed08
+617, 0xa7ed0be9deabf20d
+618, 0x8ddb4cd6b454f76b
+619, 0xb82814b1db37b63
+620, 0x418e83b36de01876
+621, 0x9a538c7f39c6413
+622, 0xee0cd7abf8a2ecb9
+623, 0xa9222b07e95590f3
+624, 0x6296a415d68341e6
+625, 0x981e0a5a8f811929
+626, 0x4bb372d3b0de283d
+627, 0xa9805b5971866e16
+628, 0xaf3b5f5183497657
+629, 0x2152b0fd23c3d9f
+630, 0xb730c325b7173180
+631, 0x1e3439d231608c19
+632, 0x1c5ba6031379823c
+633, 0x87f5d12d6d365cbc
+634, 0xd3bc7f29614bc594
+635, 0x63102214bb391268
+636, 0x482bbd5bba648a44
+637, 0x6a23604690759dc4
+638, 0x4091d41408d3a39e
+639, 0x7cd017f922101b15
+640, 0x7ce9004ac5f9231
+641, 0x978bc3d8ec7f7fdf
+642, 0x5bd0c4d780580c11
+643, 0x4313c068bb040153
+644, 0x3ab7dab7bc38bf80
+645, 0x3aaf9c187728deea
+646, 0x6633a4ce8efb88d9
+647, 0x7263b089878f00fc
+648, 0xd0d767e96fe00eb8
+649, 0x184a7c0c01908028
+650, 0x1ebdf41e6f76e186
+651, 0xeb740ee1d0402083
+652, 0xfccf4974edb1c339
+653, 0x16e2707aa28306d
+654, 0x1684f0bdb018c3a5
+655, 0x887b6b67b88aa862
+656, 0x923d7810a2bea33a
+657, 0x56b3560babef5d6b
+658, 0xb39a14614c54b8c6
+659, 0x33e4dc545a509fc8
+660, 0x26e21f84142da9b
+661, 0xdd07598125756855
+662, 0x572d49a071d7ae0a
+663, 0xba3c7e3baea28760
+664, 0x7ecdb2d714db4b61
+665, 0x1c62b4920e1b2fe2
+666, 0x71bfafb70092834a
+667, 0xd710a4228f60d56a
+668, 0xeb16277d4ce4e95b
+669, 0x968168c90b16d3a1
+670, 0xac3439dfe8ad0062
+671, 0x5a8226f9dd5876ad
+672, 0xb843affe917291b0
+673, 0xd76d1e67051f8259
+674, 0xb73a6638cce8ccde
+675, 0xa0e6afd3c7295f9
+676, 0xff8857b4bbb5f4c6
+677, 0x99becf78938f0426
+678, 0xfcd17edc1e70f004
+679, 0x6223b8b23f2f50
+680, 0xca875f3e84587b4c
+681, 0x7d1e81e589f87fb9
+682, 0x9eb621586aa826fc
+683, 0xf46fb9ef5b9c2086
+684, 0x2882c9b7092725f3
+685, 0x5493f099bbedcd02
+686, 0x90c1ec979ffa811d
+687, 0x963f765025bcc53
+688, 0x56194e3ec3d9d4e9
+689, 0x7ec4720954cac1f0
+690, 0xfab3145171af7f90
+691, 0x52a0b4e41a13b593
+692, 0x740e2d4d5909d126
+693, 0x98f5339c09c94a28
+694, 0x1700e462fe8dec76
+695, 0x3dbffc2aa4695ac3
+696, 0x5763edacabdfe2a1
+697, 0x7b5b623ce49ef21d
+698, 0x30addc66f49860df
+699, 0xcc7511a6c31bceda
+700, 0x1b25b61ca75db43b
+701, 0x416bc4c298e59046
+702, 0x4cd11fe2d74e4649
+703, 0xb54458a9229fc978
+704, 0x8c21a27882b6ca35
+705, 0x57887c8b5e01639b
+706, 0xf4e893da996680bb
+707, 0x8d601297702c9c0d
+708, 0x2a27904a30aa53af
+709, 0x497800f6917ea8d0
+710, 0xe96db3340ada9c00
+711, 0xcc23166f14c010ee
+712, 0x782690d78fa65ec9
+713, 0xf3e00d74a0878eda
+714, 0xa7cbb683decca0a3
+715, 0xdd2e038e683a94aa
+716, 0xe2096ff8da896ca5
+717, 0xf7c83400afdabe11
+718, 0x395b8c6f6a4086a4
+719, 0x4a164ec05bee71d4
+720, 0xe87aa5d1ca0462fe
+721, 0x8dbc5aed6dff9ceb
+722, 0x12120d1e9552707b
+723, 0x877dca6889b3e6cd
+724, 0xbd65605c01e900fb
+725, 0xbd6b82c4157c3115
+726, 0x8b60282732caf78a
+727, 0x279fcf5e5de9e57f
+728, 0x34b34ebfb6a37eae
+729, 0xd258cc1a14e03b7b
+730, 0x9a528ba3db4a13fb
+731, 0xffa0aea59d057746
+732, 0x27fa7f456cd37c4e
+733, 0xe1117a57a6fdce63
+734, 0xdc8fc903970a1551
+735, 0x492dd104f30faf29
+736, 0x110def0959e5652b
+737, 0x7f8d1997636fdd15
+738, 0xfb77b05e538a9b59
+739, 0x2e41fa35b4b01fc6
+740, 0xbc35ae69a3374085
+741, 0x192c2a681c2d9b4b
+742, 0x12566b8866c189d6
+743, 0x9d88ea785c5185c8
+744, 0x30a621ad5f983c4
+745, 0x8b875efe1206f587
+746, 0x224d25c3af6e3423
+747, 0x7503e976a1ac7bcc
+748, 0x3c98aa869e823859
+749, 0x3d8835304b646892
+750, 0xf6353330ff970bc2
+751, 0x8a673f5e2edb8acb
+752, 0xf2fdcc53493838b9
+753, 0x85ddcd526236af16
+754, 0x60afb99814c676c5
+755, 0x32a1c2749e281ca8
+756, 0x2367a92ae3bee9ca
+757, 0x219fe082703743cc
+758, 0x34d8b74dc85182a9
+759, 0xdd04164c72db23f
+760, 0xe293ac28fe2671a9
+761, 0x9ca7d169cbda6f45
+762, 0x705c47972b4240ed
+763, 0xc10eda9eeb536209
+764, 0xc36ddacd0c94e85d
+765, 0x8eb592c27e8cd0d2
+766, 0x3e815991c76e7cc4
+767, 0xac9cfce31acf7580
+768, 0xbf7a4cb31c7aee94
+769, 0x663077444aceecf6
+770, 0xe7f614ff386eb568
+771, 0x79d7a229c66912c0
+772, 0x161ed4311f63e1f3
+773, 0x308a5faeb9982ede
+774, 0x7b38ddb9b7efd10
+775, 0x1e103a2589b27ecf
+776, 0x67b02baf4259f27e
+777, 0x868921c115ea2eee
+778, 0x959791912200f71e
+779, 0x4dd55f36dec10557
+780, 0xe3464d90080cb99d
+781, 0xfb2d4f6accce652f
+782, 0x109900a9257d77ba
+783, 0x3c4bda8e2c83684c
+784, 0xc9ae040fb7f868c6
+785, 0x78098ffe994f4905
+786, 0x7a94c33eca77f0b4
+787, 0xbe6a2a95e9b5c0e8
+788, 0x797d39cf963f4837
+789, 0x8d2e249e4425d06d
+790, 0x6ae2c30cd5da06f4
+791, 0x904489de762b179f
+792, 0x84713e2dfb591e3b
+793, 0x6405a40da3f6f51b
+794, 0x976b560d663a2df1
+795, 0xed1c544784ba1e22
+796, 0xca658e995ed9344c
+797, 0x2b1c6b8e4db49025
+798, 0x52b1513da528bad
+799, 0x3c63406d256d9968
+800, 0x63a31ca3d423f85e
+801, 0xb05a81f55789a720
+802, 0xd04412992c476c8e
+803, 0x828ec2f77a150a3d
+804, 0xee50926671bb60c6
+805, 0x5aa70f93e2df61b4
+806, 0x94d60fa2e8655858
+807, 0x3f5e5b770703cc7d
+808, 0xc62dfb2688ca7784
+809, 0xaaf02e1e8ba89fe4
+810, 0x4ab74e0d8c047405
+811, 0x31ee04fbac6fcead
+812, 0x1203b78b8228f5af
+813, 0x412a70836f9aa71a
+814, 0xab51cf98c03f1819
+815, 0x783a3ce9ce137f65
+816, 0x8897085b0a072cf2
+817, 0x685dd9bde8798cb
+818, 0x9a1fac7b1705e2c1
+819, 0xf3e9ff98de48e9cb
+820, 0x5c2d3eb1a1fbe917
+821, 0x3bda718b6b54d82e
+822, 0x29f2dd18f22f0821
+823, 0xb992da1572ac3597
+824, 0xacb69e7aa14b34f7
+825, 0xcd36e3ad14f088d1
+826, 0x6aaacc96a1ec55e8
+827, 0xf8ac593f154fe68f
+828, 0x18fc9cbff012339f
+829, 0x2f3368ccbbb99899
+830, 0x7cec7d17f37031f7
+831, 0x96e86bfaadcb8fc2
+832, 0x74f9e7ee3d42a752
+833, 0xbd52f6c7d9b0733
+834, 0xa48e6d96bb6ce1c9
+835, 0xaefa058254b82133
+836, 0xb7a19edfd0929107
+837, 0x6160ce9125b26e26
+838, 0x6537dbbde1d2aed
+839, 0xc567f9a6bec52dde
+840, 0xca29fd3f22443342
+841, 0x7732aa6db6a1c476
+842, 0x8f5a4d7df6b11b3
+843, 0x76649262aa7e31e1
+844, 0x60a13eb125fbc829
+845, 0xc81e4d123dd21ac1
+846, 0x643cbb09bb72f86b
+847, 0xf971a98fb25555a6
+848, 0xffa2774c66692d56
+849, 0xcb33c16c50b13ea9
+850, 0xfabf388dffda0e9b
+851, 0x55d41ec12ca24b9f
+852, 0x91cf693a3467e807
+853, 0x6be2c00b2c31d6dd
+854, 0xc5cf513b5251ae28
+855, 0xffc4384212403dec
+856, 0x45d4e1865255a69d
+857, 0xfb1dcf956972086a
+858, 0xcae946a55c4c55b8
+859, 0x7351ac7720e385c1
+860, 0x19aa8ffd86240254
+861, 0x8f515ae78f4040da
+862, 0x1e1ed2058de50fce
+863, 0x22d006dcdb374243
+864, 0x6e0f0ede7c95b441
+865, 0x70e8aa81b53b4d25
+866, 0x998f309ea41e3814
+867, 0x89ed6598fb66f390
+868, 0xb5997dc3278060df
+869, 0xb2a021eac4f7e046
+870, 0x3705b60aa2fd0768
+871, 0xfc415079ab9200e
+872, 0xf2871ac4cf45ecc9
+873, 0x24bf758d2246175f
+874, 0xac503dd6f8141b3
+875, 0x4e879d12d9f03b3
+876, 0x82034af8cf93b644
+877, 0x59899dd7e478a6c7
+878, 0xae90addb6eb11507
+879, 0x1524ddf76730cdef
+880, 0x6fd4afd5456b1c9d
+881, 0xcddb9221ea001cbc
+882, 0x64ff400bbf2e8604
+883, 0x6dda10549b06ed9b
+884, 0xed2c85104c261527
+885, 0xc7e09217d29929a8
+886, 0x56284df611a428b1
+887, 0x1a7608289c0a61
+888, 0x7cb63db15166ff66
+889, 0xc6013c76fcdcdc72
+890, 0x8e5dd566c7a5a676
+891, 0x5a8e8565f40d133b
+892, 0xe465973455848c44
+893, 0xf92eecbfe0f3c2c0
+894, 0x7d64155d4dcc5cac
+895, 0xf17595706f988dad
+896, 0xd590a001a6a19c5c
+897, 0x82a164475758db3d
+898, 0x6b144993ea1bbe32
+899, 0x22a81a7a6e453779
+900, 0x8e8c298df1a68a73
+901, 0x78056afd6d936b4c
+902, 0xaaceef0325faaf62
+903, 0xe78bb7699f82266f
+904, 0x523a2d283c5a5166
+905, 0x7076d87088f6c6db
+906, 0x6087dd54cff5aeb2
+907, 0x7ef82e62cb851680
+908, 0x4e8bcc8ed84d03d8
+909, 0xd12fa0361df3cfd3
+910, 0xefb89c79f8127297
+911, 0xa9af4e2fbce0b1f8
+912, 0x462136685b70331e
+913, 0xe9e74c93da699b77
+914, 0x9ec69215fb11d0c3
+915, 0xc10f229939e3e111
+916, 0x3f67fa79e41d2374
+917, 0xd5e7c1a9a7185162
+918, 0xa1dcce9ec91492fe
+919, 0xd4e61f0727b5d21b
+920, 0xdf6cdce46551800a
+921, 0xa3f256ce906982d3
+922, 0x209742a6b9ffc27
+923, 0x4006c96958526a57
+924, 0x9606aebc75a1967e
+925, 0x91b9f42fb64189df
+926, 0xb27119defcb938bc
+927, 0x128cc7a84ba05597
+928, 0x6c3df613c62d0d30
+929, 0x3adf69d48b629ec7
+930, 0xda42ee493837b128
+931, 0xb8e770480e760bb5
+932, 0x9feb55d57c99c626
+933, 0x29812d80afdae3ed
+934, 0xae4222a64276a8c7
+935, 0xe3897212a5b4ed53
+936, 0x98bedfd13886e669
+937, 0xca858675d7fc0d0e
+938, 0x28a359f665354234
+939, 0xfac2ccabe4128b35
+940, 0x61373cc5d11ca180
+941, 0x7007605a4512a87a
+942, 0xe71f8eade7b30b3d
+943, 0x3a9e77f9b99bd04d
+944, 0x70d3e42488098866
+945, 0xd30fc159c7cd4d99
+946, 0xe4d3f6600d2e2d6f
+947, 0x1088324dfa955c25
+948, 0x516437acd4764623
+949, 0x38a31abe50d0aa03
+950, 0x72e1054e9dc02ba
+951, 0xe6971dd664d1a2e2
+952, 0xf6698cb095d3b702
+953, 0xad995a5a8c19bd92
+954, 0x34e53c6936f656e6
+955, 0x10de240bc07c757a
+956, 0x3e3b9a6861c2bd1c
+957, 0x9c0b0b97d3712ec9
+958, 0xabf1505a75043aed
+959, 0xbdf93d3de3274179
+960, 0x28fa5904d3f62c28
+961, 0xc3b97b39ef6c5133
+962, 0xf2b2219225b8679d
+963, 0x8be4ec0f930c0aaa
+964, 0x47de5a56aa590643
+965, 0xb6f871b304129856
+966, 0x80a61c06233ab0f9
+967, 0x3ce6c3af8101b055
+968, 0x85b911708274e7d1
+969, 0x4cab65d093a488b7
+970, 0xaabc4b10661fe28e
+971, 0x35b16dea64474a68
+972, 0x1d6eb5b093361223
+973, 0xc39107b92f0fe1fb
+974, 0x1d09e048073c4841
+975, 0xc6a02f43aca8cb2f
+976, 0xaf6613dbc7da909c
+977, 0x5ac2a40c230aa756
+978, 0x33afb5e7c01c39a5
+979, 0xc7b0b20ea8b7d0ef
+980, 0xdf7306c8ccb1bbea
+981, 0x9710efc0c188b2a0
+982, 0xd6303eadb72c873e
+983, 0xa38ca609b118f35a
+984, 0x8390613065c6e535
+985, 0xdf9a0106757e431f
+986, 0x8bcf77039788e143
+987, 0x6026806a986b378e
+988, 0x482ff3b1394cb1dc
+989, 0x2a27d0ccac9ede9c
+990, 0x53c77f26e271b3ab
+991, 0x1ba004cf276cf3f
+992, 0xc135b0517dc81f7c
+993, 0x5d137838db75e442
+994, 0x3fe505f93d1dbdd7
+995, 0x351654ae7d598294
+996, 0x173f8d182af9d84d
+997, 0xf97dfcd164fe11c5
+998, 0xcda423e5ad43b290
+999, 0xa5cb380b8de10d10
diff --git a/numpy/random/tests/data/pcg64-testset-2.csv b/numpy/random/tests/data/pcg64-testset-2.csv
new file mode 100644
index 000000000..7c13e3172
--- /dev/null
+++ b/numpy/random/tests/data/pcg64-testset-2.csv
@@ -0,0 +1,1001 @@
+seed, 0x0
+0, 0xa30febcfd9c2825f
+1, 0x4510bdf882d9d721
+2, 0xa7d3da94ecde8b8
+3, 0x43b27b61342f01d
+4, 0xd0327a782cde513b
+5, 0xe9aa5979a6401c4e
+6, 0x9b4c7b7180edb27f
+7, 0xbac0495ff8829a45
+8, 0x8b2b01e7a1dc7fbf
+9, 0xef60e8078f56bfed
+10, 0xd0dbc74d4700374c
+11, 0xb37868abbe90b0
+12, 0xdb7ed8bf64e6f5f0
+13, 0x89910738de7951f
+14, 0xbacab307c3cfd379
+15, 0x2cf7c449d8b927a6
+16, 0xdcf94b3a16db7f0e
+17, 0x8a9d33d905a8792e
+18, 0x4cb9eb2014951238
+19, 0x6c353acf7b26d6f1
+20, 0x73ff53d673aa30c
+21, 0x1fd10760015eca68
+22, 0xabae0aa9021eeba8
+23, 0xa5ae363a868ee2bb
+24, 0x9d89e0f041de6631
+25, 0x6238b133c3991a65
+26, 0xff49267d75fef51a
+27, 0xfb180656ce13c53f
+28, 0xaf7fadf36128712d
+29, 0xa6847fc6f339c63e
+30, 0xb03e0b80d71ea5bc
+31, 0x63905abcb43969af
+32, 0x2295af3ee00a3bba
+33, 0xb8b375b994330415
+34, 0x867d9ef1d8716a3b
+35, 0x4f6c02f5601b4e18
+36, 0x7c5fb4c16c470d18
+37, 0xe3b57986b804b343
+38, 0xef1d79d212aca692
+39, 0x5b98774c8806209c
+40, 0x924fc76bac38a5d1
+41, 0x5266084c412ddeed
+42, 0x98240bf9b831d6a3
+43, 0x5681599e81219442
+44, 0x6441248fc2ba92bc
+45, 0xe3e9051a540349ea
+46, 0x3a2700034390baa3
+47, 0x9f893155b6d402bc
+48, 0x158207910c6d8aef
+49, 0xd5282ab7608c2cbc
+50, 0xc97f4651669dee4f
+51, 0x3d4750d95103ed60
+52, 0xe0614542caac1f04
+53, 0xefe5092144cfc6c
+54, 0x560bc486abd7e9ae
+55, 0x2678b71392daa4b8
+56, 0x734970d3dc2ba416
+57, 0xcbdbe849e51e4aaf
+58, 0x3b0b5e28b491556c
+59, 0xd51449ac45abd88
+60, 0x6790b59991f1b7ab
+61, 0x32d1c039ff2415bc
+62, 0x173b9772f24f72e0
+63, 0x9490a9ca9f883b1b
+64, 0x4c775989e6214222
+65, 0xac07db37e6ee6114
+66, 0x331371b2e3f10aee
+67, 0xf12e5326c21c28e4
+68, 0x5d77dc280c70d614
+69, 0x1b01bd17a2f281ec
+70, 0xa10d3b5882938487
+71, 0xed5a0033c394ae8f
+72, 0x70bc8ea568ea44b4
+73, 0xf4600ae77965e730
+74, 0x7ff92c0b321ce233
+75, 0x6cdbc87d0cc1d670
+76, 0x9ec64f0cf2000eb1
+77, 0xfebea50259800f68
+78, 0xf2edf9019a8fd343
+79, 0x75c584ac042e5468
+80, 0xc1fa8481d5bf9a1d
+81, 0x7f57180168514ac2
+82, 0x878100716b94f81e
+83, 0xc929406e3af17fd2
+84, 0x6a26e2c013e4bf4d
+85, 0xbc071d8848280955
+86, 0xb60d75abbfd1bdac
+87, 0xee9b76afeca9fa69
+88, 0x1d6c399d2f452810
+89, 0xbaa0bc1621e25c83
+90, 0xed6ba792f8671ba5
+91, 0xf7ca02c2ab11d8d7
+92, 0x3c3cadadf0b21e3
+93, 0xdd1784571e864e9c
+94, 0xfb2f992015157509
+95, 0xf50bb9f0d3ced743
+96, 0x261565f75c3e185f
+97, 0xf8fe33b284513e60
+98, 0xe3d2d10b5e024664
+99, 0xd28717566242cf35
+100, 0x7ae07d133ac5b789
+101, 0x3b7ccaaa53ac338e
+102, 0xcd480bace4871650
+103, 0xec6c78f923c080e9
+104, 0x44211d0ff8919d59
+105, 0x89f79af76d2a45fe
+106, 0x71583fd8a837548b
+107, 0xee57269c261511f5
+108, 0xa5ee8f3b128c5d1
+109, 0xbb64c20ed0765a17
+110, 0x9d4790ab2eeaf7e4
+111, 0x742f3db806d9e98
+112, 0xb81ec97aed6a0d1b
+113, 0x41808b34f6a8a23
+114, 0xc20913af175dfd4d
+115, 0x834427db263b22bb
+116, 0xedd9c632e611828a
+117, 0x10eac8524496f571
+118, 0xd76091b97eb00ab7
+119, 0x111298ae9fe95666
+120, 0x5824b2e2a6719c43
+121, 0x6e280ec539e934ed
+122, 0xf74fd832df90083e
+123, 0x8fee6d0f241c2e97
+124, 0x4244f331c2f19c3c
+125, 0x3dde75a845cce97f
+126, 0xe35bb8e635a9915b
+127, 0x39d2943037f7932e
+128, 0x1fe2d134201d0970
+129, 0x49d00b63c749b804
+130, 0x960c2942cd4e4e04
+131, 0x8dd8e009dbc0435f
+132, 0xcf493495c3a055cd
+133, 0x8f7b5a1c0f9fe9cd
+134, 0x49d5f90374641a25
+135, 0x69b3932073d3524c
+136, 0xd170603e7de84ee2
+137, 0xa062ba3ed3539948
+138, 0xf5861cc5b5d56c82
+139, 0x5e914998a30c7e76
+140, 0x8d77f2ad1503c0f1
+141, 0x980b6a9e3b4181fb
+142, 0xd9299cd50694c084
+143, 0x253dc0f8f1cec4c5
+144, 0x68110fb9d1b3e695
+145, 0xe8f3120d0aabc461
+146, 0xb066e7df0dfb042
+147, 0xd29ce0f797e6b60b
+148, 0x6a569bb7ca33bd42
+149, 0xd46e08b2dc2385f8
+150, 0x28c61d11d055767
+151, 0x5d73aa3d1a2bb725
+152, 0x1421191e1c14829a
+153, 0xa711bfb6423df35e
+154, 0x461af97a86308006
+155, 0xb3e1018ff3519367
+156, 0xf19cf866a268ef2b
+157, 0x207715eac9199d1d
+158, 0xdd621c410975b78c
+159, 0xf390aea68683610
+160, 0x617a2d107a0047d9
+161, 0x6e05ac416e5bebf0
+162, 0x7d253e70506c1bed
+163, 0xf9f96f4a7dd53810
+164, 0xc693b29cb1573f73
+165, 0x4f1146b0020ea544
+166, 0x45140608fbd40579
+167, 0xdcf57219828ce6be
+168, 0xe19d58cca37b5b32
+169, 0x82bda95b2a161235
+170, 0x5823c3d8a2b6c9ba
+171, 0xfeb2e74092fdf89a
+172, 0x50e1ad1abc8f869d
+173, 0x2ec63d0c105eb8da
+174, 0xe14e1c4845a3264a
+175, 0xcff53670455eb6aa
+176, 0xaafaccd24619fa3e
+177, 0xf55a988486e2422a
+178, 0xecfba16a90ff4d04
+179, 0xbf8d36c2f644757a
+180, 0xdc56ed75a0dd6249
+181, 0x3f45023eff17c3bb
+182, 0x2428bbfe90023fab
+183, 0xab892c611adcb70c
+184, 0xb6f13d8c0c2b9d74
+185, 0x2ac3fb11d224f2a8
+186, 0x65433dcfae2d9351
+187, 0xe906859ae4b45f82
+188, 0x8fb7f5f093d76a3b
+189, 0x940dd290b5e88d1a
+190, 0x31b27d21bef116e7
+191, 0x86a964e2c83b5296
+192, 0x85ffd17bc079a9e8
+193, 0x16c47c724e7ab7f1
+194, 0xfb6098a9867e7d7f
+195, 0x9246fb69092c6cb2
+196, 0x1a4033572760f32
+197, 0xc5cc568a8b273b84
+198, 0xfa6f9f2fbdd44abc
+199, 0x9701b8e087718ba3
+200, 0x51d6a7dcf73f8f3a
+201, 0x30008172cc6a972d
+202, 0xac2ab49a5ca6ac81
+203, 0x31f28ef79461e54c
+204, 0x93e35a8da8cc6132
+205, 0x9a2c58beeba3d5b9
+206, 0xf6615c1de266ac39
+207, 0x127ff9f8166b766b
+208, 0x7ffe380e80a69556
+209, 0xbe7d2c228e1542f7
+210, 0x2d5ebb4e50ba1746
+211, 0x63585761ae1bf684
+212, 0x1019eb5cee022fea
+213, 0xb9d3540ab58da30d
+214, 0x1677f4cb45620eb9
+215, 0x6524baee51783822
+216, 0xdf9f2ddcfabb0adc
+217, 0x78e8acc43b287935
+218, 0xe9a1974e999222b5
+219, 0xc41324ec2291e780
+220, 0xea52abc9ecdcbc9f
+221, 0x209d7bcd46ec6b04
+222, 0x12d504c09803db2e
+223, 0x1200e6bf21475d81
+224, 0xde6d3c2b35fd2cfc
+225, 0xa2526900ac33bd3c
+226, 0x7f1f5290fc432bc5
+227, 0x29ddfb380a3d69c8
+228, 0xac79cb6942a2909d
+229, 0x516996685b67a92a
+230, 0xb5fc39041cb828bb
+231, 0x75d9d8ca0644a276
+232, 0x81e98b76be92a3e9
+233, 0xca27888fafe12179
+234, 0x17be2ae039925765
+235, 0x9429846c0e6d0342
+236, 0x327dfd50439815e9
+237, 0xcee20cd7bc254aeb
+238, 0x7d250389f453f29e
+239, 0xfd1b232a85c95569
+240, 0x2ed55fac80f3e9e9
+241, 0xf6886c20417a1be7
+242, 0xcd08e61f0b0fdfde
+243, 0x7b33e34da5c27bff
+244, 0xd043c4b7d5603dd5
+245, 0x9a544e4c70a3b686
+246, 0xa7b60398c381f771
+247, 0xe9e7a3487c4bd4f2
+248, 0x10b58fdfe1ff112c
+249, 0xd5c1c9748c0f4ceb
+250, 0x61be9d09159d54ff
+251, 0x5356f51e8239f510
+252, 0xfe7889d9b202ecef
+253, 0xc7fc19ca5d263d5d
+254, 0x7c4c07e61dfd9f69
+255, 0x6c315fe5015f300a
+256, 0xe0a5bc00039747b4
+257, 0x16397fdcf829ee80
+258, 0xb55aee80d16a5169
+259, 0xca0609944d007eea
+260, 0xcc982249f65a02ce
+261, 0x528161feb149c148
+262, 0xcbf08ba49b41c006
+263, 0x39af1ff0b6f14138
+264, 0x5cc036be69799aec
+265, 0x6adde125b1db21c5
+266, 0x8a99d83d6b613b67
+267, 0x1cd43fca9451f74c
+268, 0x682dbb26ecc96365
+269, 0x13b4be2ceb43e3
+270, 0xbe8fbc3b6f4f581e
+271, 0xda148a2f4bda5719
+272, 0x239106ca3319f393
+273, 0xb42b4dde641f0dd5
+274, 0xd233cfdf4cb0af74
+275, 0xfb5919d905589afc
+276, 0xd802a8860c10b66a
+277, 0x6c923e1d00e7b5bc
+278, 0xfacce1134f383b89
+279, 0xf9570abda7a6d553
+280, 0x80f0f9796a208f18
+281, 0xc0e1df5280951c57
+282, 0xe9f143f08257bbe0
+283, 0x79e4c6463123d588
+284, 0xdd2118583f2b1684
+285, 0xb399ff5f2329fa18
+286, 0x4b3e9ebae96f813c
+287, 0xc484dbf247787384
+288, 0x921865eb97603f2c
+289, 0x18063c68e257d300
+290, 0x643181f345e7fc26
+291, 0x12e0b0e8eadf9fa7
+292, 0x79e613fe73dfa354
+293, 0x6db4c59203b7217a
+294, 0x6c7a0e9ba6139eaf
+295, 0x9617c7ac4e3f6d97
+296, 0x1f68a7b4fb1b4b75
+297, 0xef0b7ab24944f466
+298, 0xaf1dee1f4be1bc89
+299, 0xd2e355c959f5fd8d
+300, 0xe594c3fb95d96efc
+301, 0x9554766ca3342906
+302, 0xa4bbdc77d12842c
+303, 0xb62400211ee489a8
+304, 0x91abadaaa3bbe67c
+305, 0xd371eeb91deb42bb
+306, 0x883bab35cbd2b6e5
+307, 0xd030c3d9411a9041
+308, 0xff3c110a858ff000
+309, 0x59bdf5ca47d0bde7
+310, 0x2bc80fa3cdba1853
+311, 0x6444ccb652662cb8
+312, 0xc0c7e256b9e90339
+313, 0x70714ea9c9d72302
+314, 0x96a0142f9d897d27
+315, 0x209a9097c5a91ef7
+316, 0xb9e33afc5171e009
+317, 0x47b37af433a58d40
+318, 0x30cc4ffbfa831d26
+319, 0xdcea4a85ff815466
+320, 0x907d5bd027f2e5cc
+321, 0x7c081f6852e04a4b
+322, 0xe61950749c1d502b
+323, 0x1604e937ee69834a
+324, 0xb2372d952dd25309
+325, 0x53f6a5b834c72577
+326, 0x2ce7a74395e0b694
+327, 0xacbf9ab4fe91f225
+328, 0x5ce1e63d3a2bb90f
+329, 0x54740da3a5ed139b
+330, 0xf194ddb39f29880b
+331, 0x3305374f5d8ec08b
+332, 0x831dd0164927ff4a
+333, 0x625baa78e4458cf
+334, 0x29d27dc0a4a71152
+335, 0xe227bae9a1401034
+336, 0xca0c209831846b2b
+337, 0x8e8cc54b08b5a411
+338, 0x38f2b4acaac27db6
+339, 0x8ec88baac814e86b
+340, 0x31c08e46b007bde
+341, 0xb686c02722794c09
+342, 0xb77cf8fc682e3907
+343, 0xa56334e7f606f4b2
+344, 0x9c80b127bddd5f4f
+345, 0x12df14834cd858bf
+346, 0x3f14762a9cf5fb9f
+347, 0x930a70941ef5779e
+348, 0x64e96c849c30c080
+349, 0xfdf53bfba1300484
+350, 0xec7a9363c21bc616
+351, 0x26e9fd6a115ecb47
+352, 0x9707a84b5bc77fbb
+353, 0xb23b2737b20d5903
+354, 0x22f4825ae80f6501
+355, 0x500644b12be6a01b
+356, 0xb746645b2af082db
+357, 0xe6af051f697892f8
+358, 0x577c724248a1cfc6
+359, 0x3d2b6a434c84eed3
+360, 0xd260f5efd7328314
+361, 0x95c16cc84bb3f55c
+362, 0x7a01b2e4e0e80ca7
+363, 0x41930c3ce70a0935
+364, 0x1299bccf39d4e110
+365, 0x494883ba1a8a87f
+366, 0x9478ecfe2d918e60
+367, 0x30ec9a5670cda8af
+368, 0xf9bc877e833e2b99
+369, 0x1b83a0acfbb4a8db
+370, 0x73bc1740c0d18880
+371, 0x65086ca9773cb3e1
+372, 0x3b78c3ccd63cff2e
+373, 0xbfae748795acfb31
+374, 0xa4c9d5d56a15ba20
+375, 0xb9cb41721e52b71e
+376, 0x1532f15d4dc47748
+377, 0x5a4d647a4b9ee632
+378, 0x8513c7c5a50898d9
+379, 0x6d3d98ccd5461b2e
+380, 0xa65e99be2fe98d6
+381, 0x31abc8855334a0e5
+382, 0xf1ed22a661dca5b8
+383, 0x299e2b63229e03be
+384, 0xda201a06687bce48
+385, 0xd27794b302142c55
+386, 0x642bd3e1c7898a9d
+387, 0x777f1ff00afa1a87
+388, 0xd2f1c84fb3877baa
+389, 0xae417583289191fd
+390, 0xd641f1d88e0e2d55
+391, 0xc1f1d98fb5d18ebf
+392, 0xb0f72aecdadce97b
+393, 0xe9b8abc764f6018a
+394, 0xd2a37cff8e890594
+395, 0x2dd70d631a528771
+396, 0xbf8ba0478c18e336
+397, 0x1630bf47f372ce0a
+398, 0x6d04ea20dc3f46b8
+399, 0x6591881bf34337f2
+400, 0x33c149c7eb5b4103
+401, 0xf01a8c9857c86748
+402, 0x184348cdfc16d215
+403, 0x141168b253d2ed7
+404, 0x52aaf012ef50a6f1
+405, 0xfda1722387e16f4c
+406, 0x43c30f57d6c038fa
+407, 0xd4a8611f5f96d214
+408, 0x2c512ce17e987f2c
+409, 0x961ce450f0fa2822
+410, 0xf55a506ec6cea9cd
+411, 0xb76d694d9c7f5ef6
+412, 0xfb029216dbd8e988
+413, 0x93162501896a0081
+414, 0xfbbbd2c5ab300f5c
+415, 0xd648b6da7387d491
+416, 0xc73b4697471d9d98
+417, 0xe37412bf1c93ee76
+418, 0xa1a96d96570e6637
+419, 0x5b3ab4f82428f65c
+420, 0x873d849b188aa36f
+421, 0x39fbee0ffc9fa9ff
+422, 0xc70d21b744d677fe
+423, 0x2b8a43c23043d209
+424, 0x93c33eaa37370d16
+425, 0x8930ac1880f2b0ef
+426, 0xac01d27707036af0
+427, 0xc2af3fee504343a0
+428, 0x1c1dae2ad5535d97
+429, 0x9ffc21804b76a480
+430, 0x69f903412cc13563
+431, 0x9d3c4e2759a0c47d
+432, 0xb1a8f894be6302b9
+433, 0x95e1fd7951479506
+434, 0xbb9e6c03cd4ae8e3
+435, 0x85206010c9b737cf
+436, 0x767e813694d6238c
+437, 0x4969af329ccbb30a
+438, 0x3aa9af1075aaea5c
+439, 0xb1ff519e8118a993
+440, 0xb21a23a3c91180fe
+441, 0x320b24582ca3fd88
+442, 0xf8ca56415fb4e453
+443, 0xabd0899c07205e77
+444, 0x87fdc7a44b4ad50f
+445, 0xd75744911641a278
+446, 0x7c8c9a65df6fcb95
+447, 0x79d785e3c7a5b695
+448, 0x421e4565ba1f592f
+449, 0x27f87eb2517835cf
+450, 0xb62cc4297441c83e
+451, 0xd817a80ac815ca6d
+452, 0xad84388130df2aa8
+453, 0x5e6b1640452d6ac8
+454, 0x936285e15edce2a3
+455, 0x903bccc4969768e8
+456, 0xefc2cb7b109d3140
+457, 0x633e9dfdda2d903a
+458, 0x2a2f3225925678a1
+459, 0xe07eac91a27f8547
+460, 0xe50ced40eda78cb3
+461, 0xc5b22500e1c7441
+462, 0x32becf61bca3aa72
+463, 0xa2e37c4b30671344
+464, 0xc9f1c1910f45d544
+465, 0x9b50333b2dcdf730
+466, 0x310bfd53a1684b94
+467, 0x1e1dc21e66ac6455
+468, 0x81876c2bfb1ed5a1
+469, 0xd0c54a3e25eadc7b
+470, 0x3791b6fbbd5c7ba0
+471, 0x133be57356c599fc
+472, 0x8d1148eb8e83fdea
+473, 0x311aedba0d8b42cc
+474, 0x1142ae52745f94bb
+475, 0xc5f4ab2fbde8c4a3
+476, 0xd23be827b5b24f6d
+477, 0x65f95194cd122715
+478, 0x4b48969d73125922
+479, 0x46f165052b8ff988
+480, 0x5c689f94b9275ff4
+481, 0x93b03823ff2d536b
+482, 0x871f3775aa4e3523
+483, 0x5af829f7cc0f66a5
+484, 0xa32e05739cbeac8c
+485, 0xacff1856ddace0fe
+486, 0x8eeb5e7f991a5322
+487, 0x6325c2720e0dbdea
+488, 0x9fb817bc4fdf5200
+489, 0x9786f0d850e43d78
+490, 0x571f76dd7f9fb77a
+491, 0x4d9e94e181cbc63f
+492, 0x8bb632d3376c547a
+493, 0x9cc26d9efd1c88b9
+494, 0x9c5d49579df52b0b
+495, 0x6201abf7e1cda07b
+496, 0x90d68f0c6c884963
+497, 0xfc5b66188ef7f561
+498, 0x6d9303cf2e0e0f95
+499, 0xd7cfcff535f5ed07
+500, 0x14d1a1228daa4ac6
+501, 0xe00ef5762f66ae50
+502, 0xf113a79471582978
+503, 0x430985281785dc7a
+504, 0x31914108c206ed5
+505, 0x7ba6707b6419971c
+506, 0x2ec63b033ce112e5
+507, 0xf8bcd36ced3b41e3
+508, 0xe5cf908c8010414b
+509, 0xf5ee224b7c703e30
+510, 0x9a9733af0b12338b
+511, 0x83e18cc00ace34f8
+512, 0xd52cff39e23008b8
+513, 0xa700578136b9c0c5
+514, 0x3fa179d32ac51f99
+515, 0xef2d5eab6d4ad380
+516, 0x709024a5abd032df
+517, 0xc607c7ee349ede87
+518, 0x803d784e9731eb5f
+519, 0x2ef06f4ba769282d
+520, 0x4bc1dca1e9f07eb9
+521, 0x930c958a7a72f94d
+522, 0x249bc8db2cc7a3bf
+523, 0x3845305798f9a5d
+524, 0x6f137eca9ab6f948
+525, 0xc31f5a963d31bd67
+526, 0x9d39693d5383626f
+527, 0x52fb41c335a8b98e
+528, 0xb79d1a29a06006ec
+529, 0x7c0926a7a3eda2cc
+530, 0xffdf5214406fd53e
+531, 0xc6aa02a7e94282b9
+532, 0xd4a4431b4aa301ee
+533, 0x4271cc0f9420d3ab
+534, 0x26fccd7cc7fc2485
+535, 0x330594bb945b8d5a
+536, 0x6ea8eaad12e5cb8c
+537, 0x831c3467726bede3
+538, 0x31d1eb10017eaa61
+539, 0xc7aa75e41508f5cb
+540, 0xde51810f0cadd0b5
+541, 0x50e5b3e73692f80b
+542, 0x82107ec55636e188
+543, 0x9828ef175d843ab4
+544, 0xb8edc6a860dd421e
+545, 0x25c0c138fd537ac3
+546, 0x47e72a771e8eb563
+547, 0xbb0f8c5333f4a2cc
+548, 0x91750d2fb9b2d479
+549, 0xe662d8f6fe38df36
+550, 0x72a6d879fb5619f0
+551, 0x6817c7878dcbf077
+552, 0x4e7741cb484661e8
+553, 0x3b3b3ba0be5711bf
+554, 0xa6989f5d25868765
+555, 0x43c276398997e4e0
+556, 0xdcbe16a94da28870
+557, 0x454936980a699c99
+558, 0xac614bfa8f0266c6
+559, 0x9174841392e213d5
+560, 0xa0e2acffc5fc9d1f
+561, 0xe53a08a7a0e6521a
+562, 0x2b845cf7c24172e0
+563, 0x265a4fc5f7adec0d
+564, 0x1f34fbe5f1e49420
+565, 0x139181f6fb647f20
+566, 0x88c35d46e2fcd05e
+567, 0x2a6d5b55903c0459
+568, 0xcea28eb621ad7bf1
+569, 0x5c9cdc13e7aaa30
+570, 0x5fe63e14746e7103
+571, 0x7923e53d73835db9
+572, 0x376e661210bf1b06
+573, 0x5b1cab85450efdd5
+574, 0x3908dc096c70b452
+575, 0x4825e303cd1f396f
+576, 0xed476bfd702957c3
+577, 0x6acc013aff5db743
+578, 0x62c80b776343d488
+579, 0x9c75edcd5b012697
+580, 0xaa053362a3b9770a
+581, 0xa907e236c7c07e94
+582, 0x15b2c380451692c0
+583, 0x94f79142697bd61f
+584, 0xbc657d31ea98d44f
+585, 0xcbaa5e52517a1f5e
+586, 0x96aa2e44a7c4a03f
+587, 0x216d3c66db2b515d
+588, 0x157001807e3ca88a
+589, 0x52b3a596bdd3859a
+590, 0xed747e7fc5e3adac
+591, 0x78fd765ddb2c448d
+592, 0xe53dc7299ed8614e
+593, 0x75ad41fb1d7a790a
+594, 0xc14f6b944b0e6cb1
+595, 0x7c314b69fce3df1c
+596, 0xb56d82eb740d7abc
+597, 0x5132a93c41251fdb
+598, 0xe3ce35bd2a82f958
+599, 0x440571a981c722f2
+600, 0x194cdfd9f186bc9
+601, 0xb89e522a5db00939
+602, 0xad35f339f68df3c8
+603, 0xa82ab18420322293
+604, 0xaffa6df9b72b27c4
+605, 0x9615694d23beaa2c
+606, 0x1d82ebe563abad91
+607, 0xab50ef65fbd94385
+608, 0x1b070dbd70a9a14
+609, 0x2ececa796abbadf0
+610, 0x6bbeafe9e81ab2a2
+611, 0x60dcd0d2a9b76914
+612, 0x1e748039ef05c33f
+613, 0x6d4d17f2213ccdff
+614, 0x9fa56132957bc987
+615, 0x60a17185de2428eb
+616, 0xb56038ddf306479c
+617, 0x3b1db5df92d06d8b
+618, 0x24d1bba8bdedf580
+619, 0xbfb7e6740ebaa4d9
+620, 0xab31c4473e46f61d
+621, 0x6deb3cdd8fd5869f
+622, 0x23032e47746d72d6
+623, 0xa9e72d734e10f2e8
+624, 0xbffd199b6157bc23
+625, 0x29f8254df273fb62
+626, 0xb076142130ee55ec
+627, 0x5b0b08374126c309
+628, 0xea4536aae979521f
+629, 0xc064e7abec91a174
+630, 0x46133ef80c59d935
+631, 0xf0227e2da1b14160
+632, 0x675a76641e1af5a
+633, 0x2f50a069b33d198c
+634, 0x3ded5a65e1d657eb
+635, 0xbb6999b020694f6b
+636, 0x86b2f2b33487aed7
+637, 0x76e14e85f8bfb4cf
+638, 0x38f7f1e44bd4e0db
+639, 0xc1a7d41b7e80d4ae
+640, 0x1dfaaf80bbceb42e
+641, 0x3f51c11497720c2b
+642, 0xce6da1415ddb8b80
+643, 0x7377d8bcd359b5f3
+644, 0xe077208f3f810aca
+645, 0x9a06a8a2dacbffce
+646, 0xca1f99156b09b735
+647, 0x2ff9a93064d91451
+648, 0x50f3ea93f351a7ef
+649, 0x606fceccb07054de
+650, 0x7e83d6d2f8f6685d
+651, 0x78f3995291c5d407
+652, 0xd28d2460e22d0228
+653, 0x2c5636f68a0054dd
+654, 0xd9fafb1c56c8f6cb
+655, 0xe39889b5f9d74464
+656, 0x1355372bf5db2cc1
+657, 0x26768426b9ac323
+658, 0x4af1dbdc1111fd89
+659, 0x66973587943b927f
+660, 0xf86f5f50684dfb1d
+661, 0x1247d574ff79b534
+662, 0xc8039f3259210fe2
+663, 0x79b573235c92a9f5
+664, 0x213f642d8450e2f0
+665, 0x5db7706973376566
+666, 0x6182c12e69b373d7
+667, 0x3e5ac47300aec07f
+668, 0x4b5b6c57b1574376
+669, 0x6b7fcceefd56b17c
+670, 0xf656c3455cb9d4b8
+671, 0x7577e2e13329721f
+672, 0xf33c0c53ce956e8d
+673, 0x7d0f328ee356174
+674, 0x10ec9a168088686e
+675, 0x71ef1776d062dfa
+676, 0xaa7b590a488a6bc4
+677, 0x38612b6dd8049a1c
+678, 0x939045e36874f731
+679, 0xcb9d1d74c56d5ac9
+680, 0x54f1c1c8fef1d8ff
+681, 0x3ee4b85c8c7e939e
+682, 0xb9b4608e019f352c
+683, 0x79d4701275d12e6a
+684, 0x2632a2d9835c7f19
+685, 0x1662cd9fba293692
+686, 0xbcb70265115ee944
+687, 0xdc43fb9761468604
+688, 0xe3eec4e7d3871352
+689, 0x829531753226989d
+690, 0x2748cc67f540e074
+691, 0x39c4af25d607837d
+692, 0x741a243f4cb5df99
+693, 0xda1353287e18b49a
+694, 0xa6735689d751ea74
+695, 0x46326d587340ce0b
+696, 0xc18531df4550012b
+697, 0x6f7901e05dd4b818
+698, 0xfb966afc4c001d63
+699, 0x6dc10fca67a9cfdb
+700, 0xd6527ffadf0feaae
+701, 0x3b900172045e25d
+702, 0xb7dd594cdded6a46
+703, 0x6602aee7ec1599fc
+704, 0x7fbf12f23747546a
+705, 0x32e63f662bd2de0d
+706, 0xedf47770b67ed641
+707, 0x331bef83481c5c2a
+708, 0x8fc4256fdf05158c
+709, 0x98eba48dabccf5e0
+710, 0xdbc2f2cdb7b1c154
+711, 0x7777755616517ad3
+712, 0xd473c147d2628ac1
+713, 0x861e15d1d760b5a7
+714, 0xf4d25926405ecb07
+715, 0xb7739c69effff86e
+716, 0xe97fbafa6f96830c
+717, 0xf13e8a334e8bede1
+718, 0xcd60010cba4ee4f9
+719, 0x1f537ac2b82e6008
+720, 0x1fda8d781a89140a
+721, 0x9dc204f3f4a463f0
+722, 0x456dcd18eb56a1ab
+723, 0x629957bc87bd16a1
+724, 0x2c8000ddb8c75253
+725, 0xc31dae9ec8449284
+726, 0xdac05c8baa2b691a
+727, 0x21ff7be9ffa3e7ac
+728, 0x844f4b5ed4ee08d0
+729, 0x651f913fd636c994
+730, 0xca3e71a2110b2d49
+731, 0x7709bc42253ed09d
+732, 0xbb164d45b6569d43
+733, 0x90ec2f040c20a112
+734, 0xfa6e77e9166f5be4
+735, 0x6b6d12c1842d587d
+736, 0xfcd7ff8466e25e2a
+737, 0x6a5a2ed8bd971297
+738, 0x2ec35f6bba5adcbc
+739, 0xc83676e16651249a
+740, 0x458f6064cefe10ba
+741, 0x90d54d527e6cd028
+742, 0xa5613e88db27c388
+743, 0x331e0c7d85aa1abc
+744, 0x8cee4977e210358
+745, 0xfcae379aa6cbff8e
+746, 0xd1407afc97a57e86
+747, 0x1fab25c864f094ae
+748, 0xd914864a63004552
+749, 0x4214d226a20f1384
+750, 0x3f4e0d80c488b715
+751, 0xc5ca2f654024b7c8
+752, 0xc1e27a124e7c821c
+753, 0xd890a915ffc7918c
+754, 0x22fba040ce51a9f8
+755, 0xbf61cebd8891617a
+756, 0x7846609ee228e319
+757, 0x536d1854375509b8
+758, 0xbbfb45fc6e666f50
+759, 0xd85b4c0527f9d7d6
+760, 0x528cc9c7fa2a84c8
+761, 0x27a1baece647f2cb
+762, 0xfddf0cb92fe09dc3
+763, 0xeb5008fe965d8d96
+764, 0x4a3307937eb2e5c8
+765, 0xd07d74c240c6c363
+766, 0x16f62290179d1bbf
+767, 0xe99c9bcc9cb1ece7
+768, 0xc64f9be03c8a93be
+769, 0x32659effaf666c1f
+770, 0x4bb228cfb30b6672
+771, 0x98764870842068a5
+772, 0x5b12ef2d2cd8bdcc
+773, 0xbc79d1c1b41f28b8
+774, 0x97a517cf3279fc9a
+775, 0x34ffd46c1d4d6025
+776, 0x9c302307ee25c8f0
+777, 0x399604eed1f18a8
+778, 0x1c9b813c2043142a
+779, 0x2944ea5e55267fe9
+780, 0x5a8a9f5e728ea667
+781, 0x30c8440adb804a0
+782, 0xee0e6b627099a937
+783, 0x3d50757ada3c52da
+784, 0x4548916b32c813ab
+785, 0x602a186fe5bf109b
+786, 0xf0d440a2227ba304
+787, 0x5a10d4e0ca9ea32b
+788, 0x6e5eb90da13ba64c
+789, 0x4c6af8fd04241ab2
+790, 0xf9eb31d26e093006
+791, 0x5d674878839fe3ea
+792, 0x1562b55b2484e47c
+793, 0xa87188c099c1cb61
+794, 0xb7736b8aa02a3392
+795, 0x5f4b301125abb20f
+796, 0x361d566984637f44
+797, 0x68c4b3feac8bd0c3
+798, 0x7066c634dd2503c1
+799, 0xfecbf7c9441eb6ea
+800, 0xdbc26ae0fc81436b
+801, 0x9ef3e2b48252e7a4
+802, 0x31a49b4c339b37c7
+803, 0xb01b2a83cf346cf4
+804, 0xc24dc2347f82fbe3
+805, 0x134cad272dcd410f
+806, 0x61260742823ba59c
+807, 0x53ac4c193a97c730
+808, 0x9207c9833af34b52
+809, 0xa72e7ee77078d1f5
+810, 0x2e6f6e1b05936885
+811, 0x783b99ce5dbf9464
+812, 0xfdfeb6f0d027bb44
+813, 0x40eeb27096f92b0
+814, 0x5ef96ff5d4a4521f
+815, 0x5595806ae873718a
+816, 0x67d449eecf4ca1c3
+817, 0xde837ab611364f3f
+818, 0x7034c24d2b139be9
+819, 0xe21166603e0a9c86
+820, 0x935694435c1f0d51
+821, 0x6cb3bec90c126088
+822, 0x4096ef662b7a9f89
+823, 0xd2d85b8d238d8c15
+824, 0xa4ea533ce3ec59b2
+825, 0x3654729d80a2db29
+826, 0x214c4cc3906d29d4
+827, 0x201c447e7588e373
+828, 0xe8b8f0ae25f683eb
+829, 0x6744aaf5754e38af
+830, 0xd1ffb10d6f27a061
+831, 0xe536733a7b3a6c30
+832, 0x39f0f66e47cbf2c9
+833, 0x856a9593526fde2
+834, 0x2e2a817a0098ea4b
+835, 0xc5e1eeb551a0e3d3
+836, 0x3f21e2f5e2d50b2
+837, 0x906af56c66dd9f8c
+838, 0x30f6dbd70329fac8
+839, 0xc443dfddf3c01a60
+840, 0x7ab85d9aa9675470
+841, 0x8c9080bd39717bfc
+842, 0x4b1ccdb3c3597f6f
+843, 0x74e2542d70ab5d67
+844, 0xbb3d236aad00f74
+845, 0xcf3cadf9a2804774
+846, 0xe851d9750e42bd07
+847, 0xc0ad82029b1c371f
+848, 0x7ee119eb552d6c07
+849, 0xd8024049bd1d784a
+850, 0xfa67a899760363
+851, 0xaa7c2f438b178197
+852, 0xc473674a47ffe064
+853, 0x539fbe3fc674c270
+854, 0xdb48484748a76f3b
+855, 0xc73b2b092060d
+856, 0xa1d2a15345016f5d
+857, 0x4d0fe8599f9bba47
+858, 0xa0edc275e6f8f1d1
+859, 0x40590a8655bc8d72
+860, 0x35b4223161f05f75
+861, 0xa04c0c0f616752dc
+862, 0x7f371ed2ca45432d
+863, 0x2ff1a08f75ac6438
+864, 0xe2dc5c3682282f48
+865, 0xe1e4179fa98d9013
+866, 0x8cb083d6843a73d5
+867, 0xb4c2b5921b706854
+868, 0x738e14c0e7352445
+869, 0xcd2b646f91afd8c7
+870, 0xd5779a5b57a264fd
+871, 0xc39ff855586c7d07
+872, 0x3e3f0098c631a859
+873, 0x644e02fae032110
+874, 0xa8834613c0a45278
+875, 0x69482f2c08e10657
+876, 0xe4ee475bdb87e69a
+877, 0xdc1ef7b25c0d0019
+878, 0x88a3fa2be18d8744
+879, 0x60a02e0b21c5bec7
+880, 0xb6867b88aa19bc1a
+881, 0xb599409affcf10eb
+882, 0xaeaa1778a5e59daa
+883, 0xd7a91a52c16663e3
+884, 0x93cb269affe07b1c
+885, 0x841b6ced3a4ba815
+886, 0x84541768e1540a5c
+887, 0xe3943c84f83b3020
+888, 0x5de366fbd7b45258
+889, 0xd787cc3bde91a661
+890, 0x814071446edecb57
+891, 0x15d8c602a1141514
+892, 0x72f07bc8002d1d0d
+893, 0x4a8bd8dc9a1f0f3e
+894, 0x8723796ae0f20d35
+895, 0xda7283c2051f73b2
+896, 0x2df0cc247f90bd3b
+897, 0x79a8522b968f990a
+898, 0x951ede190c8b9d02
+899, 0xc512f1a5b14b018a
+900, 0xf0e3ddc03b9a4259
+901, 0x8cf4a35ad312e15f
+902, 0xebef28926b11094b
+903, 0x5628ba687325921c
+904, 0xc3aa75e57edc49c3
+905, 0xc38382fa98e762ba
+906, 0x8d209e896285848e
+907, 0x2c7d6adf592b4a3e
+908, 0x62de48e36f8338f3
+909, 0x4a752741e00de30e
+910, 0xf7855b70f1f6ec2b
+911, 0xa505fa4428199e43
+912, 0xe8b6b423b826bbac
+913, 0x4bd1206cf8786d05
+914, 0x6dcf040391fe3bf4
+915, 0x913f500f87e1bba3
+916, 0x5acf775aa180a5d5
+917, 0x74dd28d9432ce739
+918, 0x996c2ff2f0dc2495
+919, 0x73dbfe6c56effe4
+920, 0x56fddd25196f5e40
+921, 0xe87810158f5b7
+922, 0x7b8795e996383f1f
+923, 0x9ba5ee7c777c4c82
+924, 0x17ce3908d270fe1c
+925, 0x3df9e613c1aedfae
+926, 0xcdd26871b32fc8e1
+927, 0xd71cb13afc633979
+928, 0x63427c8ea9b1c79e
+929, 0xd070f7664d3b405d
+930, 0x46f2a9e32d9fb769
+931, 0xb4c3822a45e9fe9b
+932, 0x8ba30b97fe6f5ec7
+933, 0x70aa554ee2fc11f9
+934, 0xa80c99dbe0cfcfaf
+935, 0x36d9250cb2d68ed
+936, 0x2995e4b9e1cd1db4
+937, 0x4b3803ba57fc570f
+938, 0xae3959e7d740eaa5
+939, 0xb4cbd6662adbae08
+940, 0xae46576446e8dbc4
+941, 0xc4828e008a9a8a54
+942, 0x145d7db8e6554b2f
+943, 0x1b1b8916a730c371
+944, 0xdaf84b2bebe31963
+945, 0x5b59b80ef23a2403
+946, 0x9180c7e89cab6fd3
+947, 0x80e58f5411babf34
+948, 0xa06cf55185b9b005
+949, 0x13b2c798424173ad
+950, 0xc510f8e706311d49
+951, 0x1f974b83b6046d3a
+952, 0xae6e8e85e822d1c3
+953, 0x66f2c8dc3274a31a
+954, 0x7e04dbcbf65bd377
+955, 0xabf41ede01ec20a4
+956, 0x5efa0948f6bbb2ea
+957, 0xbc91c99d8592255
+958, 0xf6d6917911d86d75
+959, 0x85ce273d54e9097a
+960, 0xbdfd30f2420fff92
+961, 0x8802f02f610b537c
+962, 0xd1d70037ed543229
+963, 0x908aaf97f9693a46
+964, 0x1f6cfeaa0834d53a
+965, 0xa453fd1648ce04d2
+966, 0x2c38bb85ebc64af9
+967, 0xd2daff551c90c4f8
+968, 0xae5a0d949797d784
+969, 0xf0974c8552ac9593
+970, 0xa10b70499f65c693
+971, 0x39a449ebd594ddff
+972, 0x8ea090f2b17b9b49
+973, 0xc592de318090fd83
+974, 0xb63e4fbc467b6912
+975, 0x57a0c1c5ce0e4dcc
+976, 0xa7c517cf3d436b35
+977, 0xef6dcb0f3fad038b
+978, 0xaf4fb60315b91287
+979, 0x5e0776f67304f331
+980, 0xe927753b8e6f7932
+981, 0xd3df2dd92559e304
+982, 0xdaed52aa6af44413
+983, 0x1b59f4dac1e181f8
+984, 0x4a73c2293877ef39
+985, 0xca45d0d015fe44de
+986, 0x4659c8b7853735a8
+987, 0x12de6466bdf8adeb
+988, 0xaeea857a09bfec15
+989, 0xcc9cf4b3c0b88a23
+990, 0xa44ae52396a5e1bf
+991, 0x5847a724305d137f
+992, 0x8f4d4de223956182
+993, 0x58254dfada867a8
+994, 0x900a98222c2f339e
+995, 0xdb575260935d51d5
+996, 0x13fb4bfbbc0d7b53
+997, 0x62213850186bb92b
+998, 0x2a34823312c00388
+999, 0x6148329042f743b0
diff --git a/numpy/random/tests/data/philox-testset-1.csv b/numpy/random/tests/data/philox-testset-1.csv
new file mode 100644
index 000000000..e448cbf73
--- /dev/null
+++ b/numpy/random/tests/data/philox-testset-1.csv
@@ -0,0 +1,1001 @@
+seed, 0xdeadbeaf
+0, 0xedc95200e2bd66a5
+1, 0x581d4e43b7682352
+2, 0x4be7278f5e373eab
+3, 0xee47f17991a9e7ea
+4, 0x38a7d2ae422f2e2c
+5, 0xe2a6730a3b4a8a15
+6, 0x1588b7a841486442
+7, 0x13ad777246700504
+8, 0x14d157e0f5e18204
+9, 0xd87c22a7ee8c13f1
+10, 0x30cc389ce3542ba1
+11, 0xb8a53348955bb2e9
+12, 0xc08802e3c454f74f
+13, 0xb444f627671a5780
+14, 0x4b6dd42b29cbf567
+15, 0x6109c7dc0bc5f7d5
+16, 0x85c954715d6b5b1e
+17, 0x646178d3d9a3a5d5
+18, 0xebbde42b1cd83465
+19, 0x3d015102f6bc9c1a
+20, 0x720fe2ec3798d5fd
+21, 0x93120961289ceb2e
+22, 0xc9207e960a56fae2
+23, 0xa7f042f31d991b98
+24, 0x5fac117415fae74b
+25, 0xd0a970ba8dddc287
+26, 0x84b4e7e51b43106
+27, 0x6ad02bf525ea265f
+28, 0xcdc7e5992b36ef8f
+29, 0x44d4985209261d60
+30, 0x628c02d50f4b902e
+31, 0xc7b1914922d1e76d
+32, 0xfde99ff895cba51d
+33, 0x175a0be050fa985f
+34, 0x47297d3699e03228
+35, 0xccf1e9aeaa3339cd
+36, 0x9fdd18ebeeaf15b1
+37, 0x7c94c9ab68747011
+38, 0x612d8ef22c1fa80f
+39, 0x13f52b860de89ab5
+40, 0x81f264b8c139c43b
+41, 0x8d017ba4ef1e85ba
+42, 0x6d0556f46219951e
+43, 0x8ee7b85663cf67b6
+44, 0x2432fc707645fe67
+45, 0xaf814046051e5941
+46, 0x4d432a83739ac76f
+47, 0x59e5060d0983ccdd
+48, 0xdd20e828b83d9b53
+49, 0x1b891800d7385f4c
+50, 0x10e86a026c52ff5e
+51, 0xb932f11723f7b90c
+52, 0xb2413d0a1f3582d0
+53, 0xe7cd4edda65fc6b5
+54, 0x6d3808848d56593b
+55, 0x192a727c3c7f47d9
+56, 0x9659d8aea5db8c16
+57, 0x4242c79fe2c77c16
+58, 0x605f90c913827cea
+59, 0x53e153c8bfc2138a
+60, 0xed2158fbdef5910e
+61, 0xae9e6e29d4cb5060
+62, 0x7dd51afaad3b11ce
+63, 0x2b9ba533d01a5453
+64, 0x7e0e9cf2b6c72c8
+65, 0x1cc8b3c7747ed147
+66, 0x9b102651e2e11b48
+67, 0x30b0b53cbaac33ea
+68, 0x70c28aec39b99b85
+69, 0x5f1417ff536fdb75
+70, 0x3a1d91abd53acf58
+71, 0xba116a1772168259
+72, 0xf5369bc9bd284151
+73, 0x67bf11373bf183ca
+74, 0xef0b2d44dbd33dc7
+75, 0xbfd567ee1a2953ed
+76, 0x7d373f2579b5e5c6
+77, 0x756eeae7bcdd99be
+78, 0x75f16eb9faa56f3b
+79, 0x96d55ded2b54b9a5
+80, 0x94495191db692c24
+81, 0x32358bdd56bab38c
+82, 0x3f6b64078576579
+83, 0x7177e7948bc064c9
+84, 0x2cbf23f09ba9bc91
+85, 0x9b97cc31c26645f5
+86, 0x5af2d239ff9028b1
+87, 0x316fa920e0332abe
+88, 0x46535b7d1cae10a0
+89, 0x21f0a6869298022c
+90, 0xf395c623b12deb14
+91, 0x8573995180675aa7
+92, 0xc3076509f4dc42d5
+93, 0x15e11e49760c6066
+94, 0xe8a6d311e67a021d
+95, 0x7482f389c883339b
+96, 0xda6f881573cba403
+97, 0xb110ffb847e42f07
+98, 0x2c3393140605ccf9
+99, 0xba1c8ba37d8bdc33
+100, 0x59adf43db7a86fe0
+101, 0xb4fcbf6aa585ca85
+102, 0xd794a93c18033fa6
+103, 0x6e839c01985f9d4
+104, 0x64065bf28222b2c7
+105, 0x6a6359b293fa0640
+106, 0x5ff610969e383e44
+107, 0xa8172c263f05c7f7
+108, 0x62a0172e8bd75d07
+109, 0x7be66e3c453b65ac
+110, 0x6a3b8d5a14014292
+111, 0xa2583e6087450020
+112, 0xd5d3ecc480c627d2
+113, 0xa24e83f1eec8a27c
+114, 0xa23febd2a99ee75a
+115, 0x9a5fbf91c7310366
+116, 0x5b63156932e039b
+117, 0x942af3c569908505
+118, 0x89a850f71ab6a912
+119, 0xfeadc803ac132fe9
+120, 0x67bf60e758250f3
+121, 0x533c25103466a697
+122, 0xb7deede3482f9769
+123, 0x325e043b53bba915
+124, 0x9e8d9e7fde132006
+125, 0x6bacc6860bbc436e
+126, 0xb3ea0534c42b1c53
+127, 0xb2389334db583172
+128, 0xa74b1bfbf5242ee4
+129, 0x53a487e2dc51d15c
+130, 0xe5a3b538d2c7a82e
+131, 0x7b6c70bb0c4cadaf
+132, 0xae20791b2081df1
+133, 0xc685c12e3c61d32c
+134, 0x60110e6b0286e882
+135, 0x49682119c774045c
+136, 0x53dc11a3bbd072e
+137, 0xbdc87c6e732d9c2d
+138, 0xcc4620861ebac8fd
+139, 0x7e9c3558759350cc
+140, 0x157408dee34891ba
+141, 0x9bcad1855b80651b
+142, 0xd81b29141d636908
+143, 0x1ed041a9f319c69d
+144, 0x805b2f541208b490
+145, 0x484ef3bba2eb7c66
+146, 0xb6b5e37d50a99691
+147, 0xabc26a7d9e97e85f
+148, 0xcba2a3cce0417c2f
+149, 0xa030dfffd701993c
+150, 0x2bf2dc50582ebf33
+151, 0xd9df13dd3eb9993e
+152, 0x31ca28b757232ae5
+153, 0x614562a0ccf37263
+154, 0x44d635b01725afbb
+155, 0x5ae230bc9ca9cd
+156, 0xb23a124eb98705c6
+157, 0x6395675444981b11
+158, 0xd97314c34119f9ca
+159, 0x9de61048327dd980
+160, 0x16bac6bded819707
+161, 0xcea3700e3e84b8c7
+162, 0xaa96955e2ee9c408
+163, 0x95361dcc93b5bc99
+164, 0x306921aed3713287
+165, 0x4df87f3130cd302a
+166, 0x37c451daeb6a4af5
+167, 0x8dbbe35f911d5cc1
+168, 0x518157ce61cb10f9
+169, 0x669f577aebc7b35b
+170, 0x4b0a5824a8786040
+171, 0x519bc3528de379f5
+172, 0x6128012516b54e02
+173, 0x98e4f165e5e6a6dd
+174, 0x6404d03618a9b882
+175, 0x15b6aeb3d9cd8dc5
+176, 0x87ed2c1bae83c35b
+177, 0x8377fc0252d41278
+178, 0x843f89d257a9ba02
+179, 0xcdda696ea95d0180
+180, 0xcfc4b23a50a89def
+181, 0xf37fd270d5e29902
+182, 0xafe14418f76b7efa
+183, 0xf984b81577076842
+184, 0xe8c60649ccb5458d
+185, 0x3b7be8e50f8ff27b
+186, 0xaa7506f25cef1464
+187, 0x5e513da59f106688
+188, 0x3c585e1f21a90d91
+189, 0x1df0e2075af292a
+190, 0x29fdd36d4f72795f
+191, 0xb162fe6c24cb4741
+192, 0x45073a8c02bd12c4
+193, 0xcbaaa395c2106f34
+194, 0x5db3c4c6011bc21c
+195, 0x1b02aac4f752e377
+196, 0xa2dfb583eb7bec5
+197, 0xfe1d728805d34bb1
+198, 0xf647fb78bb4601ec
+199, 0xd17be06f0d1f51ef
+200, 0x39ec97c26e3d18a0
+201, 0xb7117c6037e142c8
+202, 0xe3a6ce6e6c71a028
+203, 0xe70a265e5db90bb2
+204, 0x24da4480530def1e
+205, 0xfd82b28ce11d9a90
+206, 0x5bf61ead55074a1d
+207, 0xbe9899c61dec480d
+208, 0xae7d66d21e51ec9e
+209, 0x384ee62c26a08419
+210, 0x6648dccb7c2f4abf
+211, 0xc72aa0c2c708bdc9
+212, 0x205c5946b2b5ba71
+213, 0xd4d8d0b01890a812
+214, 0x56f185493625378d
+215, 0x92f8072c81d39bd0
+216, 0xa60b3ceecb3e4979
+217, 0xfcf41d88b63b5896
+218, 0xf5a49aa845c14003
+219, 0xffcc7e99eee1e705
+220, 0xdd98312a7a43b32d
+221, 0xa6339bd7730b004
+222, 0xdac7874ba7e30386
+223, 0xadf6f0b0d321c8
+224, 0x126a173ae4ffa39f
+225, 0x5c854b137385c1e7
+226, 0x8173d471b1e69c00
+227, 0x23fa34de43581e27
+228, 0x343b373aef4507b1
+229, 0xa482d262b4ea919c
+230, 0xf7fbef1b6f7fbba
+231, 0xd8ce559487976613
+232, 0xbf3c8dd1e6ebc654
+233, 0xda41ed375451e988
+234, 0xf54906371fd4b9b3
+235, 0x5b6bb41231a04230
+236, 0x866d816482b29c17
+237, 0x11315b96941f27dc
+238, 0xff95c79205c47d50
+239, 0x19c4fff96fbdac98
+240, 0xbfb1ae6e4131d0f4
+241, 0x9d20923f3cdb82c9
+242, 0x282175507c865dff
+243, 0xdfd5e58a40fe29be
+244, 0xedbd906ff40c8e4f
+245, 0x11b04fc82614ccb3
+246, 0xeceb8afda76ae49f
+247, 0xa4856913847c2cdf
+248, 0x6f1425f15a627f2a
+249, 0xdf144ffedf60349e
+250, 0x392d7ecfd77cc65f
+251, 0x72b8e2531049b2c6
+252, 0x5a7eb2bdb0ec9529
+253, 0xdcfd4306443e78c1
+254, 0x89ad67ed86cd7583
+255, 0x276b06c0779a6c8f
+256, 0xb2dbb723196a0ac3
+257, 0x66c86a3b65906016
+258, 0x938348768a730b47
+259, 0x5f5282de938d1a96
+260, 0xa4d4588c4b473b1f
+261, 0x8daed5962be4796f
+262, 0x9dde8d796985a56e
+263, 0x46be06dbd9ed9543
+264, 0xdf98286ceb9c5955
+265, 0xa1da1f52d7a7ca2b
+266, 0x5a7f1449f24bbd62
+267, 0x3aedc4e324e525fd
+268, 0xced62464cd0154e1
+269, 0x148fc035e7d88ce3
+270, 0x82f8878948f40d4c
+271, 0x4c04d9cdd6135c17
+272, 0xdf046948d86b3b93
+273, 0x2f0dec84f403fe40
+274, 0xa61954fb71e63c0d
+275, 0x616d8496f00382e8
+276, 0x162c622472746e27
+277, 0x43bcfe48731d2ceb
+278, 0xff22432f9ff16d85
+279, 0xc033ed32bb0ad5a4
+280, 0x5d3717cc91c0ce09
+281, 0x7a39a4852d251075
+282, 0x61cd73d71d6e6a6
+283, 0xe37e2ea4783ab1a5
+284, 0x60e1882162579ea8
+285, 0x9258ec33f1a88e00
+286, 0x24b32acf029f0407
+287, 0x1410fc9aea6d3fac
+288, 0x6054cf2a3c71d8f7
+289, 0x82f7605157a66183
+290, 0x3b34c1c0dff9eac5
+291, 0xfebe01b6d5c61819
+292, 0x7372187c68b777f2
+293, 0xc6923812cda479f0
+294, 0x386613be41b45156
+295, 0x92cfebe8cc4014b
+296, 0x8e13c4595849828b
+297, 0x90e47390d412291f
+298, 0x6b21a1d93d285138
+299, 0xbf5b1f5922f04b12
+300, 0x21e65d1643b3cb69
+301, 0xf7683b131948ac3c
+302, 0xe5d99fc926196ed2
+303, 0x7b138debbec90116
+304, 0x8a2650a75c2c2a5c
+305, 0x20689a768f9b347b
+306, 0xdfa2900cfb72dc6e
+307, 0x98959c3855611cc2
+308, 0x5fdb71b89596cc7c
+309, 0x1c14ac5c49568c7b
+310, 0x958c4293016091fe
+311, 0x7484522eb0087243
+312, 0xc4018dfb34fc190f
+313, 0xca638567e9888860
+314, 0x102cd4805f0c0e89
+315, 0xcc3bc438e04548f8
+316, 0xb808944bb56ea5be
+317, 0xffd4778dbf945c57
+318, 0xfe42617784c0233b
+319, 0x3eccbfeae9b42d3c
+320, 0xd9f1b585fd0bfa60
+321, 0x5c063d1b2705d5dd
+322, 0x8e8bec3519941b64
+323, 0x9e94c36cbec2a42
+324, 0x1cd19f5b64ffd3ad
+325, 0x9632e3aebfc68e66
+326, 0x98960c2d9da4ae45
+327, 0xb76994b1f2bbfc1f
+328, 0xca184a737d3971cc
+329, 0x964d31b07183adfb
+330, 0xe9e0ff351cd276d4
+331, 0xb5747c860b05bbe4
+332, 0x5549ddc3bd3862e2
+333, 0x495496677b27873b
+334, 0x53910baa26e3ea18
+335, 0xaa07a07ad0a688d3
+336, 0xbb43bd1f09ecdb1e
+337, 0xe2ebc105699dd84
+338, 0x6e815a2729584035
+339, 0x2caab1713b17948a
+340, 0x43d39d209fa41c90
+341, 0xfe3e71089d5d1c3a
+342, 0xa778646c32f81177
+343, 0x8d42bfb86e6e92d5
+344, 0x175571f70b4fcfbe
+345, 0x2a66a6fe10dc3b5b
+346, 0xd9545e85235ca709
+347, 0x5642781c77ced48a
+348, 0x24facc40b72ccd09
+349, 0xa800fbacce33f6f8
+350, 0x675f58a0ff19fba
+351, 0x35aedf57bb5cde1b
+352, 0xe5535a6b63f6d068
+353, 0x84dffd0102aaa85d
+354, 0x621faad65467aaa7
+355, 0x596ad85b556b112f
+356, 0x837545fff8894c7a
+357, 0x3d9a4ae1356bc6a6
+358, 0xcd8b7153205d4ad0
+359, 0x98afdd40f1ed09a6
+360, 0xa38b2dc55a5cf87f
+361, 0x484aecce2b6838bc
+362, 0x6af05c26bdab18d9
+363, 0xf418b7399dcf2e4b
+364, 0x1cfa38789b0d2445
+365, 0xfbed23c34166ee67
+366, 0x38e6820039e4912a
+367, 0x1fe94911e963591e
+368, 0x1291c79aee29ad70
+369, 0x65eccfc89506f963
+370, 0x7d14de3b2f55b1f6
+371, 0x82eb79c36cd2a739
+372, 0x41ffe3b75ea0def5
+373, 0x9eba9156470a51d9
+374, 0xd17c00b981db37d1
+375, 0xf688769a75601aa7
+376, 0xbcf738e9e03d571e
+377, 0x14712e56df8f919b
+378, 0xab14e227d156e310
+379, 0xf53d193e993e351e
+380, 0x857fae46bd312141
+381, 0xc2dd71e41b639966
+382, 0x74f8b987a3d00ad1
+383, 0x5bce8526dc527981
+384, 0x94910926c172a379
+385, 0x503c45557688a9d5
+386, 0x244d03834e05807f
+387, 0x6e014cbab9c7a31f
+388, 0xae544c638530facf
+389, 0x9b853aaaf9cbc22d
+390, 0xfb42ab7024d060ed
+391, 0x74cc3fba0dfd7ff2
+392, 0x24ec9e8f62144ad5
+393, 0x72f082954307bbe7
+394, 0x36feda21bbf67577
+395, 0x3222191611b832f1
+396, 0xd0584e81bcac8b0b
+397, 0xdce8d793ef75e771
+398, 0x978824c6c2578fc
+399, 0x6e8f77503b3c2ee4
+400, 0xc85d2d86fecf5d03
+401, 0x3d35b4a5d4d723c4
+402, 0xd3987dfd4727fff3
+403, 0xd3cde63fb6a31add
+404, 0xf6699e86165bdaeb
+405, 0x9d60ba158ec364c4
+406, 0x920c3c18b346bfc9
+407, 0x770fd1fdfbc236ca
+408, 0x45998cfc5fc12ddd
+409, 0xd74a3454e888834b
+410, 0xbf2aa68081a4a28f
+411, 0xea41b26a6f1da1b3
+412, 0x5560a2d24b9d5903
+413, 0xe3791f652a228d8b
+414, 0x365116d3b5a8520c
+415, 0xb1b2bd46528f8969
+416, 0xfcfe14943ef16ae7
+417, 0xf4d43425e8a535dc
+418, 0xe6cf10a78782a7e0
+419, 0x9c7ac0de46556e3e
+420, 0xc667ae0856eed9ef
+421, 0x47dbb532e16f9c7e
+422, 0xdf4785a5d89ee82e
+423, 0xbd014925ce79dbcf
+424, 0xea0d663fb58fa5be
+425, 0x51af07d5cc3821fb
+426, 0x27a1bdcdc4159a9d
+427, 0x520c986c59b1e140
+428, 0x50b73fd9bacd5b39
+429, 0xae5240641f51e4f3
+430, 0x71faecc164ed9681
+431, 0xda95aa35529a7ee
+432, 0xe25ba29b853c1c6d
+433, 0x9871a925cda53735
+434, 0xde481ad8540e114d
+435, 0xa2997f540e8abca0
+436, 0xc9683c5035e28185
+437, 0x1082471b57182bac
+438, 0xbd3ecf0f0b788988
+439, 0xf479760776fbb342
+440, 0x3730929200d91f44
+441, 0xc1762d79ae72809c
+442, 0xfaa0a4c7b1686cb3
+443, 0xd581e6d55afdafcd
+444, 0x6cf57bdfba2dcf6d
+445, 0xdef79d9fe6a5bcef
+446, 0x13ed376e18132bd3
+447, 0xbe67efd72defa2a
+448, 0x5acc176c468966ea
+449, 0x8b35b626af139187
+450, 0x446de3fac0d973ac
+451, 0xe1d49e06dc890317
+452, 0x817bc3fd21fc09b7
+453, 0xb71c3958a13d5579
+454, 0x8746e010f73d7148
+455, 0x1b61c06009922e83
+456, 0xba17e62e6b092316
+457, 0x1375fa23c4db8290
+458, 0x3f071230f51245a6
+459, 0x51c99a086a61cd13
+460, 0x5f0f2ae78589e1fd
+461, 0x604834e114bbbc27
+462, 0x5eb2a7a34814e9a9
+463, 0x77a6907f386bf11e
+464, 0x99525de2bd407eeb
+465, 0xb818348c57b3b98f
+466, 0x25f5f9e702fbe78d
+467, 0x8f66669e6f884473
+468, 0x1e47d46e2af4f919
+469, 0xf6a19df846476833
+470, 0xff00c67bcd06621f
+471, 0xe3dfe069795d72d8
+472, 0x8affc88b2fea4d73
+473, 0x66df747e5f827168
+474, 0xf368ec338d898a0e
+475, 0x9e1f1a739c5984a2
+476, 0x46a1c90e1ca32cbc
+477, 0xc261bc305ed8d762
+478, 0x754d7949f7da9e72
+479, 0x4c8fbbb14ef47b17
+480, 0xccbdc67a3848d80d
+481, 0x3c25e6f58bae751d
+482, 0x7078b163b936d9b6
+483, 0x440e27463c134ecf
+484, 0x6c83ee39f324db0f
+485, 0x27cf901b22aea535
+486, 0x57262dec79a3f366
+487, 0x91db09f1dbb524fb
+488, 0xd7436eefba865df2
+489, 0x16c86b0a275a3f43
+490, 0x689493e6681deaa9
+491, 0x7e1dc536c1a9ac42
+492, 0x1145beac3ac7f5cc
+493, 0x3d05e211a104b2b0
+494, 0x4f9e77ced3c52f44
+495, 0x53de1369354add72
+496, 0x1fb60f835f47cdeb
+497, 0x6ab36f089e40c106
+498, 0xaabffcb0d3d04c7
+499, 0xaa399686d921bd25
+500, 0x2bf8dd8b6d6fa7f0
+501, 0x1ddbf4e124329613
+502, 0x466a740241466a72
+503, 0x98d7381eb68a761
+504, 0x817691510bc4857a
+505, 0x8837622c0171fe33
+506, 0xcba078873179ee16
+507, 0x13adad1ab7b75af4
+508, 0x3bac3f502428840c
+509, 0xbeb3cce138de9a91
+510, 0x30ef556e40b5f0b4
+511, 0x19c22abdf3bbb108
+512, 0x977e66ea4ddc7cf
+513, 0x9f4a505f223d3bf3
+514, 0x6bc3f42ac79ec87b
+515, 0x31e77712158d6c23
+516, 0x6d8de4295a28af0d
+517, 0xee1807dbda72adb7
+518, 0xda54140179cd038f
+519, 0x715aa5cdac38e062
+520, 0x5a7e55e99a22fa16
+521, 0xf190c36aa8edbe4f
+522, 0xccadd93a82c1d044
+523, 0x7070e6d5012c3f15
+524, 0x50a83341a26c1ba5
+525, 0x11bca7cc634142e5
+526, 0x623a0d27867d8b04
+527, 0x75c18acff54fbf6e
+528, 0x455ae7d933497a6f
+529, 0xf624cf27d030c3d3
+530, 0x7a852716f8758bac
+531, 0xe7a497ac1fa2b5b4
+532, 0xf84f097498f57562
+533, 0xc4bb392f87f65943
+534, 0x618e79a5d499fbfb
+535, 0xb3c0b61d82b48b8
+536, 0x4750a10815c78ea7
+537, 0x9cf09cca3ddece69
+538, 0x2a69f1c94cc901a2
+539, 0x347a0e446e1ce86d
+540, 0xb06f3a5a5ab37bb1
+541, 0x8035bd0713d591db
+542, 0x539c9637042c3a1f
+543, 0xd7ba4dc6b273cbd7
+544, 0x12f3f99933444f85
+545, 0x4a9517b9783fb9a4
+546, 0x6422b2ea95093bc5
+547, 0x3a5ecff0f996c2a6
+548, 0x31de504efc76a723
+549, 0x7ccb7c5233c21a9f
+550, 0xc687d9e6ce4186e8
+551, 0x6e40769d6940376a
+552, 0xf51207314f1f7528
+553, 0x67ee3acb190865e3
+554, 0xe08d586270588761
+555, 0xe387fa489af1a75c
+556, 0x73414a52d29d8375
+557, 0x671a38191cf2a357
+558, 0xe00fb25b1aa54008
+559, 0x11a0610e22cf549b
+560, 0xc90cc865d57c75be
+561, 0x90d0863cc15f2b79
+562, 0x8b3e60d32ebcb856
+563, 0xb28cc55af621e04a
+564, 0xcf60bd3cb2a5ab1d
+565, 0x212cb5d421948f86
+566, 0xee297b96e0a3363f
+567, 0x4e9392ff998760d1
+568, 0x61940c8d0105ba3e
+569, 0x14ebcbae72a59a16
+570, 0xdf0f39a3d10c02af
+571, 0xfc047b2b3c1c549d
+572, 0x91718b5b98e3b286
+573, 0x9ea9539b1547d326
+574, 0x7a5a624a89a165e6
+575, 0x145b37dcaa8c4166
+576, 0x63814bbb90e5616c
+577, 0xc4bc3ca6c38bb739
+578, 0x853c3a61ddc6626c
+579, 0xa7ce8481c433829a
+580, 0x8aff426941cc07b
+581, 0x2dc3347ca68d8b95
+582, 0xce69f44f349e9917
+583, 0x2fa5cb8aca009b11
+584, 0xf26bb012115d9aca
+585, 0xafa01c2f2d27235a
+586, 0xabcba21f1b40305e
+587, 0xfec20c896c0c1128
+588, 0xc5f7a71ebacadfa0
+589, 0xc8479ad14bab4eef
+590, 0xad86ec9a3e7d3dc
+591, 0xbbecd65292b915c5
+592, 0xb1f9e28149e67446
+593, 0x708d081c03dad352
+594, 0xaa8a84dbd1de916c
+595, 0x9aa3efb29ba9480b
+596, 0xd3c63969ff11443e
+597, 0x1e9e9ac861315919
+598, 0x4fe227f91e66b41d
+599, 0xefc0212d43d253ab
+600, 0x98341437727c42d1
+601, 0x5ea85c0fe9008adc
+602, 0x7891b15faa808613
+603, 0x32db2d63989aacfd
+604, 0xc92f7f28e88fd7bc
+605, 0x3513545eb6549475
+606, 0x49abe0082906fbf8
+607, 0xcee1e1a6551e729c
+608, 0x38556672b592a28e
+609, 0xc3e61409c4ec2d45
+610, 0x96c67ce2995a0fd4
+611, 0x9b9b0cada870293
+612, 0x82d6dd5dada48037
+613, 0xeea4f415299f1706
+614, 0x371107895f152ab3
+615, 0x2f6686159f4396bb
+616, 0x61005a2ff3680089
+617, 0x9d2f2cafb595e6b6
+618, 0x4a812a920f011672
+619, 0x317554d3a77385d7
+620, 0x24c01086727eb74b
+621, 0xa15ff76d618a3a9e
+622, 0x2121bfd983859940
+623, 0x384d11577eea8114
+624, 0xab0f4299f3c44d88
+625, 0x136fd4b07cfa14d9
+626, 0x665fe45cbfaa972a
+627, 0x76c5a23398a314e9
+628, 0x5507036357ccda98
+629, 0xd9b8c5ac9dce632b
+630, 0x366bc71781da6e27
+631, 0xdd2b2ba1d6be6d15
+632, 0xf33ed0d50ea6f1a6
+633, 0xf05a9b1900174c18
+634, 0x3947e1419e2787cf
+635, 0x6c742b1e029637d0
+636, 0x32aba12196a0d2e8
+637, 0x1b94aab2e82e7df
+638, 0x68b617db19229d6
+639, 0x6c88a95ac0a33f98
+640, 0xdc9b95fd60c2d23e
+641, 0x999e6971d3afc8b3
+642, 0x7071fc6ad8b60129
+643, 0x41a8184ef62485f6
+644, 0xb68e0605c7d5e713
+645, 0x272b961a1d1bbee
+646, 0x23f04e76446187b0
+647, 0x999a7a8f6d33f260
+648, 0xdbd6318df4f168d
+649, 0x8f5e74c84c40711e
+650, 0x8ccc6b04393a19d6
+651, 0xadcd24b782dd8d3d
+652, 0x1a966b4f80ef9499
+653, 0xcb6d4f9ff5a280f0
+654, 0x8095ff2b8484018a
+655, 0xbfd3389611b8e771
+656, 0x278eb670b7d12d51
+657, 0x31df54ca8d65c20f
+658, 0x121c7fb38af6985e
+659, 0x84fb94f38fe1d0a
+660, 0x15ae8af1a6d48f02
+661, 0x8d51e4a62cba1a28
+662, 0x58e6b6b3ae0f9e42
+663, 0x9365a0a85669cc99
+664, 0xe56e92f65a2106df
+665, 0x68fa299c66b428fc
+666, 0x55e51bb0b0a832c6
+667, 0x48b565293f9bc494
+668, 0x73d8132b1cbabb57
+669, 0x9178ac3926c36cbc
+670, 0xe2f22c7b28ea5e0f
+671, 0x6af45322a99afb12
+672, 0x59072fcb486a46f4
+673, 0x166b717b08d3d8e
+674, 0xd4e627a2dfacc4ab
+675, 0x33dad6f2921dedaa
+676, 0x4b13b806834a6704
+677, 0xe5f7971b398ed54d
+678, 0x20bfae65e3e6899b
+679, 0x881dab45d2b4fc98
+680, 0x6f248126b5b885be
+681, 0x7aeb39e986f9deee
+682, 0xf819f9574b8c3a03
+683, 0xff3d93ed6bd9781a
+684, 0x3a31e2e24a2f6385
+685, 0x7888a88f8944a5e
+686, 0x4faee12f5de95537
+687, 0x7f3e4efccdb2ed67
+688, 0x91e0f2fc12593af5
+689, 0xb5be8a4b886a40d3
+690, 0x998e8288ac3a9b1b
+691, 0x85c48fc8b1349e7b
+692, 0xf03af25222d8fae5
+693, 0x45467e805b242c2e
+694, 0xa2350db793dbebdc
+695, 0xfebe5b61d2174553
+696, 0xa9a331f02c54ad0b
+697, 0xe94e49a0f905aef3
+698, 0xe54b4c812b55e3da
+699, 0xdc454114c6bc0278
+700, 0x99c7765ab476baa2
+701, 0xccd9590e47fdff7c
+702, 0xfa2bcae7afd6cb71
+703, 0x2c1bf1a433a6f0f7
+704, 0x53882c62ff0aab28
+705, 0x80ac900f844dacc
+706, 0x27ba8eb5c4a44d54
+707, 0x78f3dfb072a46004
+708, 0x34e00e6ec629edce
+709, 0x5b88d19b552d1fbd
+710, 0xe4df375dc79df432
+711, 0x37446312ff79c3b4
+712, 0xb72256900a95fa6d
+713, 0x89f3171fbdff0bfc
+714, 0xd37885b048687eba
+715, 0xbb033213b283b60e
+716, 0xcf10b523ee769030
+717, 0xbf8070b6cfd7bafb
+718, 0xb7194da81fd1763b
+719, 0xbfc303de88e68d24
+720, 0xb949c7a5aea8a072
+721, 0x844216e7bae90455
+722, 0xf1e7f20840049a33
+723, 0x96e3263ad0cae794
+724, 0x10772d51f6e9ba49
+725, 0xcea24fccae9d23b3
+726, 0xefd378add9dde040
+727, 0xba0c7c5275805976
+728, 0x2e2a04608f64fa8c
+729, 0xafb42ec43aa0fa7
+730, 0x30444b84241ac465
+731, 0x19ef384bac4493ab
+732, 0xfd1ac615d3ba5ab9
+733, 0x6cc781ba38643aff
+734, 0x30ff27ebed875cfd
+735, 0xee1a261aca97ae62
+736, 0xc5a92715202bc940
+737, 0x9e6ec76f93c657ff
+738, 0x9b9fd55f55191ca5
+739, 0x654b13af008d8f03
+740, 0x1b7f030d9bd0719f
+741, 0x6d622e277550cb7f
+742, 0x3f8ee6b8830d0538
+743, 0x475462bcd0de190f
+744, 0x21380e8a513bdbcd
+745, 0x629bf3771b1bd7a4
+746, 0x3b5fd0b62c353709
+747, 0xf95634006ec3867e
+748, 0x1be8bb584a6653c2
+749, 0x2e2d3cfa85320ce8
+750, 0x5b904b692252d11d
+751, 0x4bfd76631d527990
+752, 0xc019571ca2bec4a0
+753, 0xf2eb730cea4cd751
+754, 0xd4571d709530191a
+755, 0x3b5bd947061f5a7d
+756, 0x56e2322cd2d1d1c0
+757, 0xa8830a5f62019f83
+758, 0x901d130c1b873cf3
+759, 0xb5dd29b363c61299
+760, 0xbb710bec3a17b26d
+761, 0xc0c464daca0f2328
+762, 0x4dc8055df02650f5
+763, 0x3d3cd9bbe8b957af
+764, 0xdb79612c2635b828
+765, 0xe25b3a8ad8fa3040
+766, 0xd5875c563cbf236b
+767, 0x46861c1c3849c9bc
+768, 0xf84bf1a2814dff43
+769, 0x6d8103902e0ad5e6
+770, 0x99f51c9be8af79e5
+771, 0xb0bfa8540ff94a96
+772, 0xaf45109a4e06f7d0
+773, 0x281df3e55aea9bfc
+774, 0x6a1155ca8aa40e60
+775, 0x754d32c5de1f5da
+776, 0xce1eafb1c6ca916f
+777, 0xc4f2185fa8577bd1
+778, 0x4a188e9bdb5501d9
+779, 0xbb14107e99bd5550
+780, 0xf0381d8425ec2962
+781, 0x213dbfffc16ec4f6
+782, 0x7a999c5a28ea65bc
+783, 0x23758c2aba7709ff
+784, 0xea7e4bb205e93b44
+785, 0x9c5a31e53911c658
+786, 0x7f04d0bbdc689ddc
+787, 0xe3ed89ab8d78dcb3
+788, 0x73c38bfb43986210
+789, 0x740c7d787eb8e158
+790, 0x5284fafdfb3fb9ec
+791, 0x2e91a58ac1fb1409
+792, 0xb94a600bf0a09af3
+793, 0x533ea4dbe07d81dd
+794, 0x48c3f1a736b3c5fd
+795, 0x56ae3499fa8720ce
+796, 0x526f2def663ca818
+797, 0x2f085759c65665c4
+798, 0xf715f042c69e0db4
+799, 0x110889c399231e60
+800, 0x64584a244866f3a0
+801, 0xf02ec101a39405d3
+802, 0xe73cd5e9a7f17283
+803, 0xfea64869e7028234
+804, 0x97559974ad877891
+805, 0xc8695aba1dc9f2e5
+806, 0x7b62b76ffc2264ec
+807, 0xf5e1df172ec5ccd
+808, 0xafaeb68765e443bd
+809, 0xd3870eb2e8337623
+810, 0x4f944d684138fb39
+811, 0x6977c575038916ad
+812, 0x8ada1a225df95a56
+813, 0xe4044c6c58d15e54
+814, 0x4e5121366681cf2
+815, 0xcf8640b079357b0d
+816, 0xcd5b157d44106fa3
+817, 0x9d7a5481279e25a1
+818, 0xe10e9db41fb4b34f
+819, 0x1052607be1eadff9
+820, 0x3403d67232fe2265
+821, 0xac9358f498c34afc
+822, 0x820172da0dc39c9
+823, 0xe186e91a3b826b6a
+824, 0x1a838e2a40284445
+825, 0x1870b617ebd7bce6
+826, 0xcb7cba4424be1ed7
+827, 0x6a2e56e40fdf9041
+828, 0xace93bbe108f97ee
+829, 0xfeb9bc74ac41ca08
+830, 0x8cb2d05b0f6a1f51
+831, 0x73792309f3fac0a9
+832, 0x2507343d431308ca
+833, 0xd0ea1197be615412
+834, 0xb1870812f1d2fa94
+835, 0x6d067b6935dcd23e
+836, 0xaf161014e5492c31
+837, 0xd4be0dce97064be4
+838, 0xf8edfe3fc75c20f1
+839, 0x894751dc442d2d9c
+840, 0xb4a95f6a6663456c
+841, 0x74e93162e2d805db
+842, 0x784bc5f3a7a2f645
+843, 0xd234d7c5b0582ea9
+844, 0x491f28d0ab6cb97c
+845, 0xa79419e5cf4336c3
+846, 0x66b00141978c849
+847, 0xa7ddbd64698d563f
+848, 0xefc33a4a5d97d4b2
+849, 0x95075514a65aebdc
+850, 0x40eca5b3e28cd25e
+851, 0x90ec7d00e9c9e35d
+852, 0x63e84104d5af417a
+853, 0xdaca0ea32df5744
+854, 0x7ed54f2587795881
+855, 0x5a73931760af4ee0
+856, 0x857d1a185a3081ec
+857, 0x6eac2aabe67fb463
+858, 0xd1f86155d8bfc55f
+859, 0x6d56398f3e7877ef
+860, 0x7642f61dfc62bc17
+861, 0x1d76b12843246ffa
+862, 0xde7817809b8a31d0
+863, 0xbcca9cd091198f9d
+864, 0xf71ca566dddcdfd4
+865, 0xea4386ee8b61d082
+866, 0xe351729d6010bac4
+867, 0xfd685d8a49910dd6
+868, 0xa7a20ea6c686bd3
+869, 0x1cdaf82f4dbd5536
+870, 0xa3da1d1e77dda3e0
+871, 0x4f723b3818ff8b2a
+872, 0x1290669eca152469
+873, 0xb54158b52d30651b
+874, 0xc06b74f2c7f0fee
+875, 0x7d5840bcbf702379
+876, 0x19fa4c1254a82ed
+877, 0xcf5ce090ad0b38ea
+878, 0xd4edd6ac9437e16d
+879, 0xc6ebf25eb623b426
+880, 0xd2b6dbdf00d8fea2
+881, 0x949cf98391cc59e1
+882, 0x380a0c7d0356f7b3
+883, 0x8ffefe32465473bf
+884, 0x637b6542d27c861e
+885, 0x347d12ffc664ecd9
+886, 0xea66e3a0c75a6b37
+887, 0xc3aff6f34fb537a1
+888, 0x67bdf3579959bf49
+889, 0xa17a348e3a74b723
+890, 0x93c9ef26ddadd569
+891, 0x483909059a5ac0b2
+892, 0x26ec9074b56d5a0d
+893, 0x6216000d9a48403a
+894, 0x79b43909eab1ec05
+895, 0xe4a8e8d03649e0de
+896, 0x1435d666f3ccdc08
+897, 0xb9e22ba902650a0e
+898, 0x44dffcccc68b41f8
+899, 0x23e60dcc7a559a17
+900, 0x6fd1735eacd81266
+901, 0xf6bda0745ea20c8e
+902, 0x85efcaefe271e07c
+903, 0x9be996ee931cef42
+904, 0xe78b41c158611d64
+905, 0xd6201df605839830
+906, 0x702e8e47d2769fd3
+907, 0xb8dcf70e18cf14c
+908, 0xac2690bab1bf5c17
+909, 0x92b166b71205d696
+910, 0xb0e73c795fc6df28
+911, 0x4bf2322c8b6b6f0d
+912, 0xa842fbe67918cea0
+913, 0xb01a8675d9294e54
+914, 0xfbe3c94f03ca5af2
+915, 0x51a5c089600c441f
+916, 0x60f0fd7512d85ded
+917, 0xef3113d3bc2cadb0
+918, 0xe1ea128ade300d60
+919, 0xde413b7f8d92d746
+920, 0xfc32c6d43f47c5d8
+921, 0x69d551d8c2b54c68
+922, 0xb9bc68c175777943
+923, 0xb9c79c687f0dae90
+924, 0xd799421ef883c06e
+925, 0xbff553ca95a29a3e
+926, 0xfc9ffac46bd0aca1
+927, 0x4f6c3a30c80c3e5a
+928, 0x8b7245bc6dc4a0a
+929, 0xaf4e191a4575ff60
+930, 0x41218c4a76b90f0b
+931, 0x986052aa51b8e89b
+932, 0x284b464ed5622f9
+933, 0xba6bded912626b40
+934, 0x43cad3ed7443cb5c
+935, 0x21641fa95725f328
+936, 0x6d99d6d09d755822
+937, 0x8246dfa2d4838492
+938, 0xd2ee70b9056f4726
+939, 0x87db515a786fbb8b
+940, 0x7c63e4c1d7786e7d
+941, 0xd1a9d548f10b3e88
+942, 0xa00856475f3b74c9
+943, 0x7f1964ce67148bf4
+944, 0x446650ec71e6018c
+945, 0xb1805ca07d1b6345
+946, 0x869c0a1625b7271b
+947, 0x79d6da06ce2ecfe2
+948, 0xec7b3cafc5e3c85f
+949, 0x1745ce21e39f2c3d
+950, 0xd9a0a7af6ee97825
+951, 0x680e0e52a6e11d5c
+952, 0xd86b3f344ff7f4cd
+953, 0xab56af117c840b9c
+954, 0x5c5404c7e333a10e
+955, 0x4f1eb462f35d990d
+956, 0xf857605a5644458e
+957, 0x3bb87cdf09262f86
+958, 0xd57295baf6da64b
+959, 0xb5993f48472f2894
+960, 0x7d1a501608c060b2
+961, 0x45fabe2d0e54adf0
+962, 0xbb41c3806afb4efe
+963, 0xbfbc506049424c8
+964, 0xb7dd6b67f2203344
+965, 0x389ce52eff883b81
+966, 0xe259c55c0cf6d000
+967, 0x70fb3e3824f7d213
+968, 0x9f36d5599ed55f4b
+969, 0xd14cf6f12f83c4f7
+970, 0x570a09d56aaa0b66
+971, 0x8accafd527f4598
+972, 0xa42d64c62175adfd
+973, 0xddb9c6a87b6e1558
+974, 0xd80b6c69fa1cde2a
+975, 0x44ebaac10082207b
+976, 0xf99be8889552fa1a
+977, 0x38253cd4b38b5dc5
+978, 0x85356c8b02675791
+979, 0xbf91677b2ecdcf55
+980, 0x2316cb85e93f366e
+981, 0x9abf35954db6b053
+982, 0xf49f7425e086b45a
+983, 0x8f5b625e074afde2
+984, 0xe0d614559791b080
+985, 0xbf7b866afab2a525
+986, 0xde89d7e1641a6412
+987, 0x1d10687d8ae5b86f
+988, 0x1f034caa0e904cbd
+989, 0x2086357aec8a7a2c
+990, 0x22dc476b80c56e1e
+991, 0xbef5a73cc0e3a493
+992, 0xddfa3829b26ed797
+993, 0x8917a87ec3d4dc78
+994, 0xfeabe390628c365e
+995, 0x581b0c4f6fb2d642
+996, 0x1ef8c590adbf5b9a
+997, 0x4d8e13aac0cce879
+998, 0xfe38f71e5977fad0
+999, 0x1f83a32d4adfd2ed
diff --git a/numpy/random/tests/data/philox-testset-2.csv b/numpy/random/tests/data/philox-testset-2.csv
new file mode 100644
index 000000000..69d24c38c
--- /dev/null
+++ b/numpy/random/tests/data/philox-testset-2.csv
@@ -0,0 +1,1001 @@
+seed, 0x0
+0, 0x399e5b222b82fa9
+1, 0x41fd08c1f00f3bc5
+2, 0x78b8824162ee4d04
+3, 0x176747919e02739d
+4, 0xfaa88f002a8d3596
+5, 0x418eb6f592e6c227
+6, 0xef83020b8344dd45
+7, 0x30a74a1a6eaa064b
+8, 0x93d43bf97a490c3
+9, 0xe4ba28b442194cc
+10, 0xc829083a168a8656
+11, 0x73f45d50f8e22849
+12, 0xf912db57352824cc
+13, 0xf524216927b12ada
+14, 0x22b7697473b1dfda
+15, 0x311e2a936414b39f
+16, 0xb905abfdcc425be6
+17, 0x4b14630d031eac9c
+18, 0x1cf0c4ae01222bc8
+19, 0xa6c33efc6e82ef3
+20, 0x43b3576937ba0948
+21, 0x1e483d17cdde108a
+22, 0x6722784cac11ac88
+23, 0xee87569a48fc45d7
+24, 0xb821dcbe74d18661
+25, 0xa5d1876ef3da1a81
+26, 0xe4121c2af72a483
+27, 0x2d747e355a52cf43
+28, 0x609059957bd03725
+29, 0xc3327244b49e16c5
+30, 0xb5ae6cb000dde769
+31, 0x774315003209017
+32, 0xa2013397ba8db605
+33, 0x73b228945dbcd957
+34, 0x801af7190375d3c0
+35, 0xae6dca29f24c9c67
+36, 0xd1cc0bcb1ca26249
+37, 0x1defa62a5bd853be
+38, 0x67c2f5557fa89462
+39, 0xf1729b58122fab02
+40, 0xb67eb71949ec6c42
+41, 0x5456366ec1f8f7d7
+42, 0x44492b32eb7966f5
+43, 0xa801804159f175f1
+44, 0x5a416f23cac70d84
+45, 0x186f55293302303d
+46, 0x7339d5d7b6a43639
+47, 0xfc6df38d6a566121
+48, 0xed2fe018f150b39e
+49, 0x508e0b04a781fa1b
+50, 0x8bee9d50f32eaf50
+51, 0x9870015d37e63cc
+52, 0x93c6b12309c14f2d
+53, 0xb571cf798abe93ff
+54, 0x85c35a297a88ae6e
+55, 0x9b1b79afe497a2ae
+56, 0x1ca02e5b95d96b8d
+57, 0x5bb695a666c0a94a
+58, 0x4e3caf9bbab0b208
+59, 0x44a44be1a89f2dc1
+60, 0x4ff37c33445758d1
+61, 0xd0e02875322f35da
+62, 0xfd449a91fb92646b
+63, 0xbe0b49096b95db4d
+64, 0xffa3647cad13ef5d
+65, 0x75c127a61acd10c8
+66, 0xd65f697756f5f98e
+67, 0x3ced84be93d94434
+68, 0x4da3095c2fc46d68
+69, 0x67564e2a771ee9ac
+70, 0x36944775180644a9
+71, 0xf458db1c177cdb60
+72, 0x5b58406dcd034c8
+73, 0x793301a3fdab2a73
+74, 0x1c2a1a16d6db6128
+75, 0xc2dacd4ddddbe56c
+76, 0x2e7d15be2301a111
+77, 0xd4f4a6341b3bcd18
+78, 0x3622996bbe6a9e3b
+79, 0xaf29aa9a7d6d47da
+80, 0x6d7dbb74a4cd68ae
+81, 0xc260a17e0f39f841
+82, 0xdee0170f2af66f0d
+83, 0xf84ae780d7b5a06e
+84, 0x8326247b73f43c3a
+85, 0xd44eef44b4f98b84
+86, 0x3d10aee62ec895e3
+87, 0x4f23fef01bf703b3
+88, 0xf8e50aa57d888df6
+89, 0x7da67411e3bef261
+90, 0x1d00f2769b2f96d7
+91, 0x7ef9a15b7444b84e
+92, 0xcfa16436cc2b7e21
+93, 0x29ab8cfac00460ff
+94, 0x23613de8608b0e70
+95, 0xb1aa0980625798a8
+96, 0xb9256fd29db7df99
+97, 0xdacf311bf3e7fa18
+98, 0xa013c8f9fada20d8
+99, 0xaf5fd4fe8230fe3e
+100, 0xd3d59ca55102bc5c
+101, 0x9d08e2aa5242767f
+102, 0x40278fe131e83b53
+103, 0x56397d03c7c14c98
+104, 0xe874b77b119359b3
+105, 0x926a1ba4304ab19f
+106, 0x1e115d5aa695a91d
+107, 0xc6a459df441f2fe3
+108, 0x2ca842bc1b0b3c6a
+109, 0x24c804cf8e5eed16
+110, 0x7ca00fc4a4c3ebd3
+111, 0x546af7cecc4a4ba6
+112, 0x8faae1fa18fd6e3
+113, 0x40420b0089641a6a
+114, 0x88175a35d9abcb83
+115, 0xf7d746d1b8b1357c
+116, 0x7dae771a651be970
+117, 0x2f6485247ee4df84
+118, 0x6883702fab2d8ec5
+119, 0xeb7eea829a67f9a6
+120, 0x60d5880b485562ed
+121, 0x7d4ca3d7e41a4e7e
+122, 0xbb7fef961ab8de18
+123, 0x3b92452fb810c164
+124, 0x5f4b4755348b338
+125, 0xca45a715a7539806
+126, 0xc33efd9da5399dd
+127, 0x593d665a51d4aedd
+128, 0x75d6b8636563036b
+129, 0x7b57caa55e262082
+130, 0x4ede7427969e0dd5
+131, 0xc3f19b6f78ea00b
+132, 0xeea7bab9be2181ea
+133, 0x652c45fe9c420c04
+134, 0x14ba9e3d175670ee
+135, 0xd2ad156ba6490474
+136, 0x4d65ae41065f614
+137, 0x6ff911c8afa28eb1
+138, 0xedc2b33588f3cb68
+139, 0x437c8bc324666a2f
+140, 0x828cee25457a3f0
+141, 0x530c986091f31b9b
+142, 0x2f34671e8326ade7
+143, 0x4f686a8f4d77f6da
+144, 0xa4c1987083498895
+145, 0xbce5a88b672b0fb1
+146, 0x8476115a9e6a00cc
+147, 0x16de18a55dd2c238
+148, 0xdf38cf4c416232bc
+149, 0x2cb837924e7559f3
+150, 0xfad4727484e982ed
+151, 0x32a55d4b7801e4f
+152, 0x8b9ef96804bd10a5
+153, 0xa1fd422c9b5cf2a9
+154, 0xf46ddb122eb7e442
+155, 0x6e3842547afa3b33
+156, 0x863dee1c34afe5c4
+157, 0x6a43a1935b6db171
+158, 0x1060a5c2f8145821
+159, 0xf783ec9ed34c4607
+160, 0x1da4a86bf5f8c0b0
+161, 0x4c7714041ba12af8
+162, 0x580da7010be2f192
+163, 0xad682fe795a7ea7a
+164, 0x6687b6cb88a9ed2c
+165, 0x3c8d4b175517cd18
+166, 0xe9247c3a524a6b6b
+167, 0x337ca9cfaa02658
+168, 0xed95399481c6feec
+169, 0x58726a088e606062
+170, 0xfe7588a5b4ee342a
+171, 0xee434c7ed146fdee
+172, 0xe2ade8b60fdc4ba5
+173, 0xd57e4c155de4eaab
+174, 0xdefeae12de1137cb
+175, 0xb7a276a241316ac1
+176, 0xeb838b1b1df4ca15
+177, 0x6f78965edea32f6f
+178, 0x18bebd264d7a5d53
+179, 0x3641c691d77005ec
+180, 0xbe70ed7efea8c24c
+181, 0x33047fa8d03ca560
+182, 0x3bed0d2221ff0f87
+183, 0x23083a6ffbcf38a2
+184, 0xc23eb827073d3fa5
+185, 0xc873bb3415e9fb9b
+186, 0xa4645179e54147fe
+187, 0x2c72fb443f66e207
+188, 0x98084915dd89d8f4
+189, 0x88baa2de12c99037
+190, 0x85c74ab238cb795f
+191, 0xe122186469ea3a26
+192, 0x4c3bba99b3249292
+193, 0x85d6845d9a015234
+194, 0x147ddd69c13e6a31
+195, 0x255f4d678c9a570b
+196, 0x2d7c0c410bf962b4
+197, 0x58eb7649e0aa16ca
+198, 0x9d240bf662fe0783
+199, 0x5f74f6fa32d293cc
+200, 0x4928e52f0f79d9b9
+201, 0xe61c2b87146b706d
+202, 0xcfcd90d100cf5431
+203, 0xf15ea8138e6aa178
+204, 0x6ab8287024f9a819
+205, 0xed8942593db74e01
+206, 0xefc00e4ec2ae36dd
+207, 0xc21429fb9387f334
+208, 0xf9a3389e285a9bce
+209, 0xacdee8c43aae49b3
+210, 0xefc382f02ad55c25
+211, 0x1153b50e8d406b72
+212, 0xb00d39ebcc2f89d8
+213, 0xde62f0b9831c8850
+214, 0xc076994662eef6c7
+215, 0x66f08f4752f1e3ef
+216, 0x283b90619796249a
+217, 0x4e4869bc4227499e
+218, 0xb45ad78a49efd7ed
+219, 0xffe19aa77abf5f4b
+220, 0xfce11a0daf913aef
+221, 0x7e4e64450d5cdceb
+222, 0xe9621997cfd62762
+223, 0x4d2c9e156868081
+224, 0x4e2d96eb7cc9a08
+225, 0xda74849bba6e3bd3
+226, 0x6f4621da935e7fde
+227, 0xb94b914aa0497259
+228, 0xd50d03e8b8db1563
+229, 0x1a45c1ce5dca422e
+230, 0xc8d30d33276f843f
+231, 0xb57245774e4176b4
+232, 0x8d36342c05abbbb1
+233, 0x3591ad893ecf9e78
+234, 0x62f4717239ee0ac8
+235, 0x9b71148a1a1d4200
+236, 0x65f8e0f56dd94463
+237, 0x453b1fcfd4fac8c2
+238, 0x4c25e48e54a55865
+239, 0xa866baa05112ace2
+240, 0x7741d3c69c6e79c5
+241, 0x7deb375e8f4f7a8a
+242, 0xc242087ede42abd8
+243, 0x2fa9d1d488750c4b
+244, 0xe8940137a935d3d3
+245, 0x1dab4918ca24b2f2
+246, 0xe2368c782168fe3e
+247, 0x6e8b2d1d73695909
+248, 0x70455ebea268b33e
+249, 0x656a919202e28da1
+250, 0x5a5a8935647da999
+251, 0x428c6f77e118c13c
+252, 0xa87aee2b675bb083
+253, 0x3873a6412b239969
+254, 0x5f72c1e91cb8a2ee
+255, 0xa25af80a1beb5679
+256, 0x1af65d27c7b4abc3
+257, 0x133437060670e067
+258, 0xb1990fa39a97d32e
+259, 0x724adc89ae10ed17
+260, 0x3f682a3f2363a240
+261, 0x29198f8dbd343499
+262, 0xdfaeeaa42bc51105
+263, 0x5baff3901b9480c2
+264, 0x3f760a67043e77f5
+265, 0x610fa7aa355a43ba
+266, 0x394856ac09c4f7a7
+267, 0x1d9229d058aee82e
+268, 0x19c674804c41aeec
+269, 0x74cf12372012f4aa
+270, 0xa5d89b353fa2f6ca
+271, 0x697e4f672ac363dd
+272, 0xde6f55ba73df5af9
+273, 0x679cf537510bd68f
+274, 0x3dc916114ae9ef7e
+275, 0xd7e31a66ec2ee7ba
+276, 0xc21bebb968728495
+277, 0xc5e0781414e2adfd
+278, 0x71147b5412ddd4bd
+279, 0x3b864b410625cca9
+280, 0x433d67c0036cdc6
+281, 0x48083afa0ae20b1b
+282, 0x2d80beecd64ac4e8
+283, 0x2a753c27c3a3ee3e
+284, 0xb2c5e6afd1fe051a
+285, 0xea677930cd66c46b
+286, 0x4c3960932f92810a
+287, 0xf1b367a9e527eaba
+288, 0xb7d92a8a9a69a98e
+289, 0x9f9ad3210bd6b453
+290, 0x817f2889db2dcbd8
+291, 0x4270a665ac15813c
+292, 0x90b85353bd2be4dd
+293, 0x10c0460f7b2d68d
+294, 0x11cef32b94f947f5
+295, 0x3cf29ed8e7d477e8
+296, 0x793aaa9bd50599ef
+297, 0xbac15d1190014aad
+298, 0x987944ae80b5cb13
+299, 0x460aa51f8d57c484
+300, 0xc77df0385f97c2d3
+301, 0x92e743b7293a3822
+302, 0xbc3458bcfbcbb8c0
+303, 0xe277bcf3d04b4ed7
+304, 0xa537ae5cf1c9a31c
+305, 0x95eb00d30bd8cfb2
+306, 0x6376361c24e4f2dd
+307, 0x374477fe87b9ea8e
+308, 0x8210f1a9a039902e
+309, 0xe7628f7031321f68
+310, 0x8b8e9c0888fc1d3d
+311, 0x306be461fdc9e0ed
+312, 0x510009372f9b56f5
+313, 0xa6e6fa486b7a027a
+314, 0x9d3f002025203b5a
+315, 0x7a46e0e81ecbef86
+316, 0x41e280c611d04df0
+317, 0xedcec10418a99e8a
+318, 0x5c27b6327e0b9dbd
+319, 0xa81ed2035b509f07
+320, 0x3581e855983a4cc4
+321, 0x4744594b25e9809d
+322, 0xc737ac7c27fbd0ed
+323, 0x1b523a307045433a
+324, 0x8b4ce9171076f1d9
+325, 0x2db02d817cd5eec0
+326, 0x24a1f1229af50288
+327, 0x5550c0dcf583ff16
+328, 0x3587baaa122ec422
+329, 0xf9d3dc894229e510
+330, 0xf3100430d5cf8e87
+331, 0xc31af79862f8e2fb
+332, 0xd20582063b9f3537
+333, 0xac5e90ac95fcc7ad
+334, 0x107c4c704d5109d4
+335, 0xebc8628906dbfd70
+336, 0x215242776da8c531
+337, 0xa98002f1dcf08b51
+338, 0xbc3bdc07f3b09718
+339, 0x238677062495b512
+340, 0x53b4796f2a3c49e8
+341, 0x6424286467e22f0e
+342, 0x14d0952a11a71bac
+343, 0x2f97098149b82514
+344, 0x3777f2fdc425ad2
+345, 0xa32f2382938876d4
+346, 0xda8a39a021f20ae3
+347, 0x364361ef0a6ac32c
+348, 0x4413eede008ff05a
+349, 0x8dda8ace851aa327
+350, 0x4303cabbdcecd1ee
+351, 0x2e69f06d74aa549f
+352, 0x4797079cd4d9275c
+353, 0xc7b1890917e98307
+354, 0x34031b0e822a4b4c
+355, 0xfc79f76b566303ea
+356, 0x77014adbe255a930
+357, 0xab6c43dd162f3be5
+358, 0xa430041f3463f6b9
+359, 0x5c191a32ada3f84a
+360, 0xe8674a0781645a31
+361, 0x3a11cb667b8d0916
+362, 0xaedc73e80c39fd8a
+363, 0xfde12c1b42328765
+364, 0x97abb7dcccdc1a0b
+365, 0x52475c14d2167bc8
+366, 0x540e8811196d5aff
+367, 0xa867e4ccdb2b4b77
+368, 0x2be04af61e5bcfb9
+369, 0x81b645102bfc5dfd
+370, 0x96a52c9a66c6450f
+371, 0x632ec2d136889234
+372, 0x4ed530c0b36a6c25
+373, 0x6f4851225546b75
+374, 0x2c065d6ba46a1144
+375, 0xf8a3613ff416551d
+376, 0xb5f0fd60e9c971a9
+377, 0x339011a03bb4be65
+378, 0x9439f72b6995ded6
+379, 0xc1b03f3ef3b2292d
+380, 0xad12fd221daab3ae
+381, 0xf615b770f2cf996f
+382, 0x269d0fdcb764172
+383, 0x67837025e8039256
+384, 0x6402831fc823fafa
+385, 0x22854146a4abb964
+386, 0x7b5ad9b5a1bad7a8
+387, 0x67170e7beb6ac935
+388, 0xfc2d1e8e24adfaaa
+389, 0x7ded4395345ff40d
+390, 0x418981760a80dd07
+391, 0xc03bef38022c1d2
+392, 0x3a11850b26eade29
+393, 0xaa56d02c7175c5f4
+394, 0xd83b7917b9bfbff5
+395, 0x3c1df2f8fa6fced3
+396, 0xf3d6e2999c0bb760
+397, 0xc66d683a59a950e3
+398, 0x8e3972a9d73ffabf
+399, 0x97720a0443edffd9
+400, 0xa85f5d2fe198444a
+401, 0xfc5f0458e1b0de5e
+402, 0xe3973f03df632b87
+403, 0xe151073c84c594b3
+404, 0x68eb4e22e7ff8ecf
+405, 0x274f36eaed7cae27
+406, 0x3b87b1eb60896b13
+407, 0xbe0b2f831442d70a
+408, 0x2782ed7a48a1b328
+409, 0xb3619d890310f704
+410, 0xb03926b11b55921a
+411, 0xdb46fc44aa6a0ce4
+412, 0x4b063e2ef2e9453a
+413, 0xe1584f1aeec60fb5
+414, 0x7092bd6a879c5a49
+415, 0xb84e1e7c7d52b0e6
+416, 0x29d09ca48db64dfb
+417, 0x8f6c4a402066e905
+418, 0x77390795eabc36b
+419, 0xcc2dc2e4141cc69f
+420, 0x2727f83beb9e3c7c
+421, 0x1b29868619331de0
+422, 0xd38c571e192c246f
+423, 0x535327479fe37b6f
+424, 0xaff9ce5758617eb3
+425, 0x5658539e9288a4e4
+426, 0x8df91d87126c4c6d
+427, 0xe931cf8fdba6e255
+428, 0x815dfdf25fbee9e8
+429, 0x5c61f4c7cba91697
+430, 0xdd5f5512fe2313a1
+431, 0x499dd918a92a53cd
+432, 0xa7e969d007c97dfd
+433, 0xb8d39c6fc81ac0bb
+434, 0x1d646983def5746c
+435, 0x44d4b3b17432a60c
+436, 0x65664232a14db1e3
+437, 0xda8fae6433e7500b
+438, 0xbe51b94ff2a3fe94
+439, 0xe9b1bd9a9098ef9f
+440, 0xfe47d54176297ef5
+441, 0xb8ab99bc03bb7135
+442, 0xcfad97f608565b38
+443, 0xf05da71f6760d9c1
+444, 0xef8da40a7c70e7b
+445, 0xe0465d58dbd5d138
+446, 0xb54a2d70eb1a938
+447, 0xfdd50c905958f2d8
+448, 0x3c41933c90a57d43
+449, 0x678f6d894c6ad0bb
+450, 0x403e8f4582274e8
+451, 0x5cbbe975668df6b0
+452, 0x297e6520a7902f03
+453, 0x8f6dded33cd1efd7
+454, 0x8e903c97be8d783b
+455, 0x10bd015577e30f77
+456, 0x3fcd69d1c36eab0c
+457, 0xb45989f3ca198d3
+458, 0x507655ce02b491a9
+459, 0xa92cf99bb78602ce
+460, 0xebfb82055fbc2f0f
+461, 0x3334256279289b7a
+462, 0xc19d2a0f740ee0ac
+463, 0x8bb070dea3934905
+464, 0xa4ab57d3a8d1b3eb
+465, 0xfee1b09bcacf7ff4
+466, 0xccc7fb41ceec41fa
+467, 0xd4da49094eb5a74d
+468, 0xed5c693770af02ed
+469, 0x369dabc9bbfaa8e4
+470, 0x7eab9f360d054199
+471, 0xe36dbebf5ee94076
+472, 0xd30840e499b23d7
+473, 0x8678e6cb545015ff
+474, 0x3a47932ca0b336e
+475, 0xeb7c742b6e93d6fe
+476, 0x1404ea51fe5a62a9
+477, 0xa72cd49db978e288
+478, 0xfd7bada020173dcf
+479, 0xc9e74fc7abe50054
+480, 0x93197847bb66808d
+481, 0x25fd5f053dce5698
+482, 0xe198a9b18cc21f4
+483, 0x5cc27b1689452d5d
+484, 0x8b3657af955a98dc
+485, 0xc17f7584f54aa1c0
+486, 0xe821b088246b1427
+487, 0x32b5a9f6b45b6fa0
+488, 0x2aef7c315c2bae0c
+489, 0xe1af8129846b705a
+490, 0x4123b4c091b34614
+491, 0x6999d61ec341c073
+492, 0x14b9a8fcf86831ea
+493, 0xfd4cff6548f46c9f
+494, 0x350c3b7e6cc8d7d6
+495, 0x202a5047fecafcd5
+496, 0xa82509fe496bb57d
+497, 0x835e4b2608b575fe
+498, 0xf3abe3da919f54ec
+499, 0x8705a21e2c9b8796
+500, 0xfd02d1427005c314
+501, 0xa38458faa637f49b
+502, 0x61622f2360e7622a
+503, 0xe89335a773c2963b
+504, 0x481264b659b0e0d0
+505, 0x1e82ae94ebf62f15
+506, 0x8ea7812de49209d4
+507, 0xff963d764680584
+508, 0x418a68bef717f4af
+509, 0x581f0e7621a8ab91
+510, 0x840337e9a0ec4150
+511, 0x951ef61b344be505
+512, 0xc8b1b899feb61ec2
+513, 0x8b78ca13c56f6ed9
+514, 0x3d2fd793715a946f
+515, 0xf1c04fabcd0f4084
+516, 0x92b602614a9a9fcc
+517, 0x7991bd7a94a65be7
+518, 0x5dead10b06cad2d7
+519, 0xda7719b33f722f06
+520, 0x9d87a722b7bff71e
+521, 0xb038e479071409e9
+522, 0xf4e8bbec48054775
+523, 0x4fec2cd7a28a88ea
+524, 0x839e28526aad3e56
+525, 0xd37ec57852a98bf0
+526, 0xdef2cbbe00f3a02d
+527, 0x1aecfe01a9e4d801
+528, 0x59018d3c8beaf067
+529, 0x892753e6ac8bf3cd
+530, 0xefdd3437023d2d1c
+531, 0x447bfbd148c8cb88
+532, 0x282380221bd442b8
+533, 0xfce8658d1347384a
+534, 0x60b211a7ec6bfa8
+535, 0xd21729cfcc692974
+536, 0x162087ecd5038a47
+537, 0x2b17000c4bce39d2
+538, 0x3a1f75ff6adcdce0
+539, 0x721a411d312f1a2c
+540, 0x9c13b6133f66934d
+541, 0xaa975d14978980e5
+542, 0x9403dbd4754203fa
+543, 0x588c15762fdd643
+544, 0xdd1290f8d0ada73a
+545, 0xd9b77380936103f4
+546, 0xb2e2047a356eb829
+547, 0x7019e5e7f76f7a47
+548, 0x3c29a461f62b001d
+549, 0xa07dc6cfab59c116
+550, 0x9b97e278433f8eb
+551, 0x6affc714e7236588
+552, 0x36170aeb32911a73
+553, 0x4a665104d364a789
+554, 0x4be01464ec276c9c
+555, 0x71bb10271a8b4ecf
+556, 0xbf62e1d068bc018
+557, 0xc9ada5db2cbbb413
+558, 0x2bded75e726650e5
+559, 0x33d5a7af2f34385d
+560, 0x8179c46661d85657
+561, 0x324ebcfd29267359
+562, 0xac4c9311dc9f9110
+563, 0xc14bb6a52f9f9c0
+564, 0xc430abe15e7fb9db
+565, 0xf1cce5c14df91c38
+566, 0x651e3efa2c0750d3
+567, 0x38a33604a8be5c75
+568, 0x7aaf77fe7ff56a49
+569, 0xc0d1cc56bbf27706
+570, 0x887aa47324e156c6
+571, 0x12547c004b085e8d
+572, 0xd86a8d6fbbbfd011
+573, 0x57c860188c92d7b4
+574, 0xcd5d3843d361b8ca
+575, 0x8f586ef05a9cb3ef
+576, 0x174456e1ba6267d5
+577, 0xf5dc302c62fe583c
+578, 0xa349442fabcdb71
+579, 0xe5123c1a8b6fd08e
+580, 0x80681552aa318593
+581, 0xb295396deaef1e31
+582, 0xabb626e0b900e32b
+583, 0xf024db8d3f19c15e
+584, 0x1d04bb9548e2fb6c
+585, 0xd8ed2b2214936c2b
+586, 0x618ca1e430a52bc9
+587, 0xccbca44a6088136b
+588, 0xd0481855c8b9ccbe
+589, 0x3c92a2fade28bdf7
+590, 0x855e9fefc38c0816
+591, 0x1269bbfe55a7b27c
+592, 0x1d6c853d83726d43
+593, 0xc8655511cc7fcafc
+594, 0x301503eb125a9b0e
+595, 0xb3108e4532016b11
+596, 0xbb7ab6245da9cb3d
+597, 0x18004c49116d85eb
+598, 0x3480849c20f61129
+599, 0xe28f45157463937b
+600, 0x8e85e61060f2ce1
+601, 0x1673da4ec589ba5e
+602, 0x74b9a6bd1b194712
+603, 0xed39e147fa8b7601
+604, 0x28ce54019102ca77
+605, 0x42e0347f6d7a2f30
+606, 0xb6a908d1c4814731
+607, 0x16c3435e4e9a126d
+608, 0x8880190514c1ad54
+609, 0xfffd86229a6f773c
+610, 0x4f2420cdb0aa1a93
+611, 0xf8e1acb4120fc1fa
+612, 0x63a8c553ab36a2f2
+613, 0x86b88cf3c0a6a190
+614, 0x44d8b2801622c792
+615, 0xf6eae14e93082ff1
+616, 0xd9ed4f5d1b8fac61
+617, 0x1808ce17f4e1f70
+618, 0x446e83ea336f262f
+619, 0xc7c802b04c0917b7
+620, 0x626f45fd64968b73
+621, 0x9ffa540edc9b2c5c
+622, 0xa96a1e219e486af8
+623, 0x2bb8963884e887a1
+624, 0xba7f68a5d029e3c4
+625, 0xefc45f44392d9ca0
+626, 0x98d77762503c5eab
+627, 0xd89bcf62f2da627c
+628, 0xa3cab8347f833151
+629, 0xa095b7595907d5c7
+630, 0x3b3041274286181
+631, 0xb518db8919eb71fa
+632, 0x187036c14fdc9a36
+633, 0xd06e28301e696f5d
+634, 0xdbc71184e0c56492
+635, 0xfe51e9cae6125bfd
+636, 0x3b12d17cd014df24
+637, 0x3b95e4e2c986ac1a
+638, 0x29c1cce59fb2dea2
+639, 0x58c05793182a49d6
+640, 0xc016477e330d8c00
+641, 0x79ef335133ada5d
+642, 0x168e2cad941203f3
+643, 0xf99d0f219d702ef0
+644, 0x655628068f8f135b
+645, 0xdcdea51910ae3f92
+646, 0x8e4505039c567892
+647, 0x91a9ec7e947c89ae
+648, 0x8717172530f93949
+649, 0x1c80aba9a440171a
+650, 0x9c8f83f6ebe7441e
+651, 0x6c05e1efea4aa7f9
+652, 0x10af696b777c01b
+653, 0x5892e9d9a92fc309
+654, 0xd2ba7da71e709432
+655, 0x46378c7c3269a466
+656, 0x942c63dfe18e772c
+657, 0x6245cf02ef2476f
+658, 0x6f265b2759ea2aea
+659, 0x5aa757f17d17f4a6
+660, 0x1ad6a3c44fa09be6
+661, 0xe861af14e7015fb8
+662, 0x86be2e7db388c77
+663, 0x5c7bba32b519e9a0
+664, 0x3feb314850c4437b
+665, 0x97955add60cfb45b
+666, 0xfdb536230a540bdc
+667, 0xdac9d7bf6e58512e
+668, 0x4894c00e474e8120
+669, 0xa1918a37739da366
+670, 0xa8097f2096532807
+671, 0x592afe50e6c5e643
+672, 0xd69050ee6dcb33dc
+673, 0xa6956b262dd3c561
+674, 0x1a55c815555e63f7
+675, 0x2ec7fd37516de2bb
+676, 0x8ec251d9c70e76ba
+677, 0x9b76e4abafd2689
+678, 0x9ce3f5c751a57df1
+679, 0x915c4818bf287bc7
+680, 0x2293a0d1fe07c735
+681, 0x7627dcd5d5a66d3d
+682, 0xb5e4f92cc49c7138
+683, 0x6fc51298731d268c
+684, 0xd19800aa95441f87
+685, 0x14f70f31162fa115
+686, 0x41a3da3752936f59
+687, 0xbec0652be95652ee
+688, 0x7aa4bdb1020a290f
+689, 0x4382d0d9bee899ef
+690, 0xe6d988ae4277d6ff
+691, 0xe618088ccb2a32d1
+692, 0x411669dfaa899e90
+693, 0x234e2bf4ba76d9f
+694, 0xe109fe4cb7828687
+695, 0x1fb96b5022b0b360
+696, 0x6b24ad76c061a716
+697, 0x7e1781d4d7ecee15
+698, 0xf20c2dbe82ba38ba
+699, 0xeda8e8ae1d943655
+700, 0xa58d196e2a77eaec
+701, 0x44564765a5995a0b
+702, 0x11902fe871ecae21
+703, 0x2ea60279900e675d
+704, 0x38427227c18a9a96
+705, 0xe0af01490a1b1b48
+706, 0x826f91997e057824
+707, 0x1e57308e6e50451
+708, 0xb42d469bbbfdc350
+709, 0xb9734cff1109c49b
+710, 0x98967559bb9d364f
+711, 0xd6be360041907c12
+712, 0xa86a1279122a1e21
+713, 0x26f99a8527bfc698
+714, 0xfa8b85758f28f5d6
+715, 0xe3057429940806ae
+716, 0x4bee2d7e84f93b2b
+717, 0x948350a76ea506f4
+718, 0xa139154488045e74
+719, 0x8893579ba5e78085
+720, 0x5f21c215c6a9e397
+721, 0x456134f3a59641dc
+722, 0x92c0273f8e97a9c6
+723, 0xd2936c9c3f0c6936
+724, 0xcfa4221e752c4735
+725, 0x28cd5a7457355dca
+726, 0xecdfdde23d90999f
+727, 0x60631b2d494d032b
+728, 0xf67289df269a827f
+729, 0xcbe8011ef0f5b7ef
+730, 0x20eea973c70a84f5
+731, 0xbe1fd200398557ce
+732, 0xd2279ee030191bba
+733, 0xf2bd4291dedaf819
+734, 0xfc6d167dbe8c402
+735, 0x39ac298da5d0044b
+736, 0xceac026f5f561ce
+737, 0x10a5b0bdd8ad60e6
+738, 0xdeb3c626df6d4bcb
+739, 0x3c128962e77ff6ca
+740, 0xc786262e9c67a0e5
+741, 0x4332855b3febcdc0
+742, 0x7bda9724d1c0e020
+743, 0x6a8c93399bc4df22
+744, 0xa9b20100ac707396
+745, 0xa11a3458502c4eb5
+746, 0xb185461c60478941
+747, 0x13131d56195b7ff6
+748, 0x8d55875ddbd4aa1c
+749, 0xc09b67425f469aa5
+750, 0x39e33786cc7594c4
+751, 0x75e96db8e4b08b93
+752, 0xda01cd12a3275d1e
+753, 0x2c49e7822344fab5
+754, 0x9bd5f10612514ca7
+755, 0x1c801a5c828e7332
+756, 0x29797d3f4f6c7b4c
+757, 0xac992715e21e4e53
+758, 0xe40e89ee887ddb37
+759, 0x15189a2b265a783b
+760, 0xa854159a52af5c5
+761, 0xb9d8a5a81c12bead
+762, 0x3240cdc9d59e2a58
+763, 0x1d0b872234cf8e23
+764, 0xc01224cf6ce12cff
+765, 0x2601e9f3905c8663
+766, 0xd4ecf9890168d6b4
+767, 0xa45db796d89bfdd5
+768, 0x9f389406dad64ab4
+769, 0xa5a851adce43ffe3
+770, 0xd0962c41c26e5aa9
+771, 0x8a671679e48510a4
+772, 0xc196dc0924a6bfeb
+773, 0x3ead661043b549cb
+774, 0x51af4ca737d405ac
+775, 0xf4425b5c62275fb6
+776, 0x71e69d1f818c10f5
+777, 0xacaf4af2d3c70162
+778, 0x2e1f1d4fd7524244
+779, 0xe54fdd8f388890e8
+780, 0xfda0d33e84eb2b83
+781, 0x53965c5e392b81da
+782, 0x5c92288267263097
+783, 0xcac1b431c878c66c
+784, 0x36c0e1cf417241c6
+785, 0x5cc4d9cd1a36bf2c
+786, 0x32e4257bb5d3e470
+787, 0x4aecff904adb44fb
+788, 0x4d91a8e0d1d60cac
+789, 0xa3b478388385b038
+790, 0x48d955f24eba70be
+791, 0x310e4deb07f24f68
+792, 0x8853e73b1f30a5a
+793, 0x278aee45c2a65c5
+794, 0xf6932eedbd62fb0b
+795, 0xafb95958c82fafad
+796, 0x78e807c18616c16c
+797, 0xd7abadda7488ed9f
+798, 0x2dd72e2572aa2ae6
+799, 0x6ec3791982c2be09
+800, 0x6865bb314fac478f
+801, 0xa14dc0ce09000d1a
+802, 0xb8081ad134da10f2
+803, 0xc4ac1534aa825ef5
+804, 0xd83aeb48ae2d538f
+805, 0x38052027e3074be4
+806, 0xa9833e06ef136582
+807, 0x4f02d790ec9fd78
+808, 0xec2f60bc711c5bdc
+809, 0x9253b0d12268e561
+810, 0xa8ac607fdd62c206
+811, 0x895e28ebc920289f
+812, 0xe2fd42b154243ac7
+813, 0xc69cac2f776eee19
+814, 0xf4d4ac11db56d0dc
+815, 0xa8d37049b9f39833
+816, 0x75abbf8a196c337c
+817, 0xb115bb76750d27b8
+818, 0x39426d187839154
+819, 0xd488423e7f38bf83
+820, 0xbb92e0c76ecb6a62
+821, 0x3055a018ce39f4e3
+822, 0xc93fe0e907729bfb
+823, 0x65985d17c5863340
+824, 0x2088ae081b2028e1
+825, 0x6e628de873314057
+826, 0x864377cccf573f0e
+827, 0xae03f4c9aa63d132
+828, 0xb1db766d6404c66d
+829, 0xdce5a22414a374b
+830, 0x622155b777819997
+831, 0x69fe96e620371f3c
+832, 0xa9c67dbc326d94fc
+833, 0x932a84ae5dd43bab
+834, 0xe2301a20f6c48c3f
+835, 0x795d2e79c6477300
+836, 0xd8e3e631289521e7
+837, 0xae2684979002dfd6
+838, 0xc9c2392377550f89
+839, 0xa1b0c99d508ef7ec
+840, 0x593aef3c5a5272ec
+841, 0xe32e511a4b7162cd
+842, 0xab3b81655f5a2857
+843, 0x1b535e1a0aaf053e
+844, 0x5b33f56c1b6a07e2
+845, 0x782dc8cfcac4ef36
+846, 0xb3d4f256eecfd202
+847, 0xf73a6598f58c4f7e
+848, 0xd5722189524870ae
+849, 0x707878de6b995fc0
+850, 0xc3eb6ba73e3d7e8a
+851, 0xca75c017655b75a7
+852, 0x1b29369ea3541e5f
+853, 0x352e98858bdb58a3
+854, 0x1e4412d184b6b27d
+855, 0x2d375ba0304b2d17
+856, 0x56c30fce69a5d08e
+857, 0x6b8c2b0c06584bda
+858, 0xde4dfff228c8c91f
+859, 0xb7c9edd574e6287f
+860, 0xf6078281c9fca2b2
+861, 0xb9b9a51de02a2f1e
+862, 0xa411bef31c0103b0
+863, 0xc5facd8fc5e1d7a3
+864, 0x54e631c05ddf7359
+865, 0x815b42b3fd06c474
+866, 0xc9ac07566fda18ec
+867, 0xd84ea62957bd8e15
+868, 0x5575f74b5cfd8803
+869, 0x5779a8d460c2e304
+870, 0xfd6e87e264a85587
+871, 0xa1d674daa320b26d
+872, 0x2c3c3ec64b35afc4
+873, 0x393a274ff03e6935
+874, 0x1f40ecbac52c50ea
+875, 0xc3de64fa324ffc0c
+876, 0x56ae828b7f9deb04
+877, 0xe7c1a77b5c1f2cb3
+878, 0xa4c4aab19ea921cc
+879, 0xec164c238825822c
+880, 0xa6a3304770c03b03
+881, 0x3a63641d5b1e8123
+882, 0x42677be3a54617ef
+883, 0xa2680423e3a200c0
+884, 0x8b17cf75f3f37277
+885, 0xe7ce65a49242be3d
+886, 0x7f85934271323e4b
+887, 0xcfb0f431f79a4fab
+888, 0x392e4041a8505b65
+889, 0xd3e5daf0d8b25ea6
+890, 0x9447eff675d80f53
+891, 0xea27a9d53cfaeea8
+892, 0xe3f2335945a83ba
+893, 0x8875a43ce216413b
+894, 0xe49941f9eabce33e
+895, 0x9357c1296683a5b1
+896, 0xf0f16439e81ee701
+897, 0x3181515295ffd79a
+898, 0x9d7150fffd169ed8
+899, 0x2d6a1d281e255a72
+900, 0x81bf1286fb3a92b6
+901, 0x566d3079b499e279
+902, 0xc7939ca8f047341
+903, 0xb1f8050e7c2d59f6
+904, 0x605701045e7be192
+905, 0x51b73360e8e31a1c
+906, 0x9f4ad54483ba9fe0
+907, 0xd3085b8fcf69d1c8
+908, 0xc3e7475026dc5f0b
+909, 0x5800f8554b157354
+910, 0x37dfdf858cfcd963
+911, 0x3a1fce05ce385072
+912, 0xf495c062645c20c3
+913, 0xdcbeec2c3492c773
+914, 0xc38f427589d1d0b4
+915, 0x681ead60216a8184
+916, 0x4bd569c40cc88c41
+917, 0x49b0d442e130b7a2
+918, 0xee349156b7d1fa3f
+919, 0x2bde2d2db055135b
+920, 0xc6a460d2fbcb2378
+921, 0xd0f170494ff3dbb
+922, 0xb294422492528a23
+923, 0xfc95873c854e7b86
+924, 0x6c9c3ad1797bb19c
+925, 0xe0c06f2aab65062d
+926, 0x58e32ce0f11e3a81
+927, 0xa745fcd729ff5036
+928, 0x599b249b2fc2cdb2
+929, 0x78f23b5b0dd5b082
+930, 0x6de3e957f549ecfc
+931, 0x9d0712fa6d878756
+932, 0x9076e8554e4a413a
+933, 0xf3185818c0294de8
+934, 0x5de7cdf4b455b9b6
+935, 0xb15f6908ed703f7d
+936, 0x98c654dfedc6818
+937, 0x120502ab0e93ae42
+938, 0x67966a98a58dc120
+939, 0x1caa0fc628989482
+940, 0xd8b2c3cd480a8625
+941, 0x85c70071b3aed671
+942, 0xff385f8473714662
+943, 0xe2868e4bf3773b63
+944, 0x96cf8019b279298e
+945, 0x8511cc930bd74800
+946, 0x5312e48fdd55f5ab
+947, 0xfcdae564b52df78d
+948, 0x9eee48373e652176
+949, 0x953788f6bcbc56b0
+950, 0xd1a3855dbd2f6b37
+951, 0x3ad32acf77f4d1e9
+952, 0x917c7be81b003e30
+953, 0x9ce817da1e2e9dfb
+954, 0x2968983db162d44d
+955, 0x1e005decef5828ad
+956, 0xc38fe59d1aa4f3d5
+957, 0xf357f1710dc02f1d
+958, 0x2613912a4c83ec67
+959, 0x832a11470b9a17cb
+960, 0x5e85508a611f0dad
+961, 0x2781131677f59d56
+962, 0xa82358d7d4b0237f
+963, 0xfbf8b3cc030c3af6
+964, 0x68b2f68ac8a55adb
+965, 0x3b6fcf353add0ada
+966, 0xd1956049bcd15bd5
+967, 0x95b76f31c7f98b6d
+968, 0x814b6690df971a84
+969, 0xdcf7959cddd819e4
+970, 0xcf8c72c5d804fc88
+971, 0x56883769c8945a22
+972, 0x1f034652f658cf46
+973, 0x41df1324cda235a1
+974, 0xeccd32524504a054
+975, 0x974e0910a04ec02c
+976, 0x72104507b821f6db
+977, 0x791f8d089f273044
+978, 0xe0f79a4f567f73c3
+979, 0x52fe5bea3997f024
+980, 0x5f8b9b446494f78
+981, 0xfd9f511947059190
+982, 0x3aea9dac6063bce3
+983, 0xbfdae4dfc24aee60
+984, 0xa82cdbbf0a280318
+985, 0xf460aae18d70aa9d
+986, 0x997367cb204a57c4
+987, 0x616e21ab95ba05ef
+988, 0x9bfc93bec116769f
+989, 0x2b2ee27c37a3fa5b
+990, 0xb25c6ed54006ee38
+991, 0xab04d4a5c69e69a5
+992, 0x6d2f6b45f2d8438f
+993, 0x4ad2f32afc82f092
+994, 0x513d718908f709c0
+995, 0x5272aadc4fffca51
+996, 0xeb3f87e66156ef5d
+997, 0xf8a3d5a46a86ba85
+998, 0xdb4548a86f27abfd
+999, 0x57c05f47ff62380d
diff --git a/numpy/random/tests/data/sfc64-testset-1.csv b/numpy/random/tests/data/sfc64-testset-1.csv
new file mode 100644
index 000000000..4fffe6959
--- /dev/null
+++ b/numpy/random/tests/data/sfc64-testset-1.csv
@@ -0,0 +1,1001 @@
+seed, 0xdeadbeaf
+0, 0xa475f55fbb6bc638
+1, 0xb2d594b6c29d971c
+2, 0x275bc4ece4484fb1
+3, 0x569be72d9b3492fb
+4, 0x89a5bb9b206a670c
+5, 0xd951bfa06afdc3f9
+6, 0x7ee2e1029d52a265
+7, 0x12ef1d4de0cb4d4c
+8, 0x41658ba8f0ef0280
+9, 0x5b650c82e4fe09c5
+10, 0x638a9f3e30ec4e94
+11, 0x147487fb2ba9233e
+12, 0x89ef035603d2d1fb
+13, 0xe66ca57a190e6cbe
+14, 0x330f673740dd61fc
+15, 0xc71d3dce2f8bb34e
+16, 0x3c07c39ff150b185
+17, 0x5df952b6cae8f099
+18, 0x9f09f2b1f0ceac80
+19, 0x19598eee2d0c4c67
+20, 0x64e06483702e0ebd
+21, 0xda04d1fdb545f7fa
+22, 0xf2cf53b61a0c4f9b
+23, 0xf0bb724ce196f66e
+24, 0x71cefde55d9cf0f
+25, 0x6323f62824a20048
+26, 0x1e93604680f14b4e
+27, 0xd9d8fad1d4654025
+28, 0xf4ee25af2e76ca08
+29, 0x6af3325896befa98
+30, 0xad9e43abf5e04053
+31, 0xbf930e318ce09de3
+32, 0x61f9583b4f9ffe76
+33, 0x9b69d0b3d5ec8958
+34, 0xa608f250f9b2ca41
+35, 0x6fdba7073dc2bb5d
+36, 0xa9d57601efea6d26
+37, 0xc24a88a994954105
+38, 0xc728b1f78d88fe5b
+39, 0x88da88c2b083b3b2
+40, 0xa9e27f7303c76cfd
+41, 0xc4c24608c29176eb
+42, 0x5420b58466b972fd
+43, 0xd2018a661b6756c8
+44, 0x7caed83d9573fc7
+45, 0x562a3d81b849a06a
+46, 0x16588af120c21f2c
+47, 0x658109a7e0eb4837
+48, 0x877aabb14d3822e1
+49, 0x95704c342c3745fe
+50, 0xeeb8a0dc81603616
+51, 0x431bf94889290419
+52, 0xe4a9410ab92a5863
+53, 0xbc6be64ea60f12ba
+54, 0x328a2da920015063
+55, 0x40f6b3bf8271ae07
+56, 0x4068ff00a0e854f8
+57, 0x1b287572ca13fa78
+58, 0xa11624a600490b99
+59, 0x4a04ef29eb7150fa
+60, 0xcc9469ab5ffb739
+61, 0x99a6a9f8d95e782
+62, 0x8e90356573e7a070
+63, 0xa740b8fb415c81c4
+64, 0x47eccef67447f3da
+65, 0x2c720afe3a62a49b
+66, 0xe2a747f0a43eacf4
+67, 0xba063a87ab165576
+68, 0xbc1c78ed27feb5a3
+69, 0x285a19fa3974f9d
+70, 0x489c61e704f5f0e3
+71, 0xf5ab04f6b03f238b
+72, 0x7e25f88138a110dd
+73, 0xc3d1cef3d7c1f1d1
+74, 0xc3de6ec64d0d8e00
+75, 0x73682a15b6cc5088
+76, 0x6fecbeb319163dc5
+77, 0x7e100d5defe570a1
+78, 0xad2af9af076dce57
+79, 0x3c65100e23cd3a9a
+80, 0x4b442cc6cfe521bb
+81, 0xe89dc50f8ab1ef75
+82, 0x8b3c6fdc2496566
+83, 0xdfc50042bc2c308c
+84, 0xe39c5f158b33d2b2
+85, 0x92f6adefdfeb0ac
+86, 0xdf5808a949c85b3e
+87, 0x437384021c9dace9
+88, 0xa7b5ed0d3d67d8f
+89, 0xe1408f8b21da3c34
+90, 0xa1bba125c1e80522
+91, 0x7611dc4710385264
+92, 0xb00a46ea84082917
+93, 0x51bf8002ffa87cef
+94, 0x9bb81013e9810adc
+95, 0xd28f6600013541cd
+96, 0xc2ca3b1fa7791c1f
+97, 0x47f9ad58f099c82c
+98, 0x4d1bb9458469caf9
+99, 0xca0b165b2844257
+100, 0xc3b2e667d075dc66
+101, 0xde22f71136a3dbb1
+102, 0x23b4e3b6f219e4c3
+103, 0x327e0db4c9782f66
+104, 0x9365506a6c7a1807
+105, 0x3e868382dedd3be7
+106, 0xff04fa6534bcaa99
+107, 0x96621a8862995305
+108, 0x81bf39cb5f8e1df7
+109, 0x79b684bb8c37af7a
+110, 0xae3bc073c3cde33c
+111, 0x7805674112c899ac
+112, 0xd95a27995abb20f2
+113, 0x71a503c57b105c40
+114, 0x5ff00d6a73ec8acc
+115, 0x12f96391d91e47c2
+116, 0xd55ca097b3bd4947
+117, 0x794d79d20468b04
+118, 0x35d814efb0d7a07d
+119, 0xfa9ac9bd0aae76d3
+120, 0xa77b8a3711e175cd
+121, 0xe6694fbf421f9489
+122, 0xd8f1756525a1a0aa
+123, 0xe38dfa8426277433
+124, 0x16b640c269bbcd44
+125, 0x2a7a5a67ca24cfeb
+126, 0x669039c28d5344b4
+127, 0x2a445ee81fd596bb
+128, 0x600df94cf25607e0
+129, 0x9358561a7579abff
+130, 0xee1d52ea179fc274
+131, 0x21a8b325e89d31be
+132, 0x36fc0917486eec0a
+133, 0x3d99f40717a6be9f
+134, 0x39ac140051ca55ff
+135, 0xcef7447c26711575
+136, 0xf22666870eff441d
+137, 0x4a53c6134e1c7268
+138, 0xd26de518ad6bdb1b
+139, 0x1a736bf75b8b0e55
+140, 0xef1523f4e6bd0219
+141, 0xb287b32fd615ad92
+142, 0x2583d6af5e841dd5
+143, 0x4b9294aae7ca670c
+144, 0xf5aa4a84174f3ca9
+145, 0x886300f9e0dc6376
+146, 0x3611401e475ef130
+147, 0x69b56432b367e1ac
+148, 0x30c330e9ab36b7c4
+149, 0x1e0e73079a85b8d5
+150, 0x40fdfc7a5bfaecf
+151, 0xd7760f3e8e75a085
+152, 0x1cc1891f7f625313
+153, 0xeece1fe6165b4272
+154, 0xe61111b0c166a3c1
+155, 0x2f1201563312f185
+156, 0xfd10e8ecdd2a57cb
+157, 0x51cdc8c9dd3a89bf
+158, 0xed13cc93938b5496
+159, 0x843816129750526b
+160, 0xd09995cd6819ada
+161, 0x4601e778d40607df
+162, 0xef9df06bd66c2ea0
+163, 0xae0bdecd3db65d69
+164, 0xbb921a3c65a4ae9a
+165, 0xd66698ce8e9361be
+166, 0xacdc91647b6068f4
+167, 0xe505ef68f2a5c1c0
+168, 0xd6e62fd27c6ab137
+169, 0x6a2ba2c6a4641d86
+170, 0x9c89143715c3b81
+171, 0xe408c4e00362601a
+172, 0x986155cbf5d4bd9d
+173, 0xb9e6831728c893a7
+174, 0xb985497c3bf88d8c
+175, 0xd0d729214b727bec
+176, 0x4e557f75fece38a
+177, 0x6572067fdfd623ca
+178, 0x178d49bb4d5cd794
+179, 0xe6baf59f60445d82
+180, 0x5607d53518e3a8d2
+181, 0xba7931adb6ebbd61
+182, 0xe853576172611329
+183, 0xe945daff96000c44
+184, 0x565b9ba3d952a176
+185, 0xcdb54d4f88c584c8
+186, 0x482a7499bee9b5e5
+187, 0x76560dd0affe825b
+188, 0x2a56221faa5ca22c
+189, 0x7729be5b361f5a25
+190, 0xd6f2195795764876
+191, 0x59ef7f8f423f18c5
+192, 0x7ebefed6d02adde1
+193, 0xcfec7265329c73e5
+194, 0x4fd8606a5e59881c
+195, 0x95860982ae370b73
+196, 0xdecfa33b1f902acc
+197, 0xf9b8a57400b7c0a6
+198, 0xd20b822672ec857b
+199, 0x4eb81084096c7364
+200, 0xe535c29a44d9b6ad
+201, 0xdef8b48ebacb2e29
+202, 0x1063bc2b8ba0e915
+203, 0xe4e837fb53d76d02
+204, 0x4df935db53579fb8
+205, 0xa30a0c8053869a89
+206, 0xe891ee58a388a7b5
+207, 0x17931a0c64b8a985
+208, 0xaf2d350b494ce1b3
+209, 0x2ab9345ffbcfed82
+210, 0x7de3fe628a2592f0
+211, 0x85cf54fab8b7e79d
+212, 0x42d221520edab71b
+213, 0x17b695b3af36c233
+214, 0xa4ffe50fe53eb485
+215, 0x1102d242db800e4d
+216, 0xc8dc01f0233b3b6
+217, 0x984a030321053d36
+218, 0x27fa8dc7b7112c0e
+219, 0xba634dd8294e177f
+220, 0xe67ce34b36332eb
+221, 0x8f1351e1894fb41a
+222, 0xb522a3048761fd30
+223, 0xc350ad9bc6729edc
+224, 0xe0ed105bd3c805e1
+225, 0xa14043d2b0825aa7
+226, 0xee7779ce7fc11fdf
+227, 0xc0fa8ba23a60ab25
+228, 0xb596d1ce259afbad
+229, 0xaa9b8445537fdf62
+230, 0x770ab2c700762e13
+231, 0xe812f1183e40cc1
+232, 0x44bc898e57aefbbd
+233, 0xdd8a871df785c996
+234, 0x88836a5e371eb36b
+235, 0xb6081c9152623f27
+236, 0x895acbcd6528ca96
+237, 0xfb67e33ddfbed435
+238, 0xaf7af47d323ce26
+239, 0xe354a510c3c39b2d
+240, 0x5cacdedda0672ba3
+241, 0xa440d9a2c6c22b09
+242, 0x6395099f48d64304
+243, 0xc11cf04c75f655b5
+244, 0x1c4e054d144ddb30
+245, 0x3e0c2db89d336636
+246, 0x127ecf18a5b0b9a7
+247, 0x3b50551a88ea7a73
+248, 0xbd27003e47f1f684
+249, 0xf32d657782baac9b
+250, 0x727f5cabf020bc9
+251, 0x39c1c1c226197dc7
+252, 0x5552c87b35deeb69
+253, 0x64d54067b5ce493f
+254, 0x3494b091fe28dda0
+255, 0xdf0278bc85ee2965
+256, 0xdef16fec25efbd66
+257, 0xe2be09f578c4ce28
+258, 0xd27a9271979d3019
+259, 0x427f6fcd71845e3
+260, 0x26b52c5f81ec142b
+261, 0x98267efc3986ad46
+262, 0x7bf4165ddb7e4374
+263, 0xd05f7996d7941010
+264, 0x3b3991de97b45f14
+265, 0x9068217fb4f27a30
+266, 0xd8fe295160afc7f3
+267, 0x8a159fab4c3bc06f
+268, 0x57855506d19080b6
+269, 0x7636df6b3f2367a4
+270, 0x2844ee3abd1d5ec9
+271, 0xe5788de061f51c16
+272, 0x69e78cc9132a164
+273, 0xacd53cde6d8cd421
+274, 0xb23f3100068e91da
+275, 0x4140070a47f53891
+276, 0xe4a422225a96e53a
+277, 0xb82a8925a272a2ac
+278, 0x7c2f9573590fe3b7
+279, 0xbaf80764db170575
+280, 0x955abffa54358368
+281, 0x355ce7460614a869
+282, 0x3700ede779a4afbf
+283, 0x10a6ec01d92d68cd
+284, 0x3308f5a0a4c0afef
+285, 0x97b892d7601136c9
+286, 0x4955c3b941b8552e
+287, 0xca85aa67e941961d
+288, 0xb1859ae5db28e9d2
+289, 0x305d072ac1521fbd
+290, 0xed52a868996085bb
+291, 0x723bfa6a76358852
+292, 0x78d946ecd97c5fb3
+293, 0x39205b30a8e23e79
+294, 0xb927e3d086baadbe
+295, 0xa18d6946136e1ff5
+296, 0xdab6f0b51c1eb5ff
+297, 0xf0a640bf7a1af60c
+298, 0xf0e81db09004d0d4
+299, 0xfe76cebdbe5a4dde
+300, 0x2dafe9cc3decc376
+301, 0x4c871fdf1af34205
+302, 0xe79617d0c8fa893b
+303, 0xee658aaad3a141f7
+304, 0xfd91aa74863e19f1
+305, 0x841b8f55c103cc22
+306, 0x22766ed65444ad5d
+307, 0x56d03d1beca6c17a
+308, 0x5fd4c112c92036ae
+309, 0x75466ae58a5616dc
+310, 0xfbf98b1081e802a9
+311, 0xdc325e957bf6d8f5
+312, 0xb08da7015ebd19b7
+313, 0xf25a9c0944f0c073
+314, 0xf4625bafa0ced718
+315, 0x4349c9e093a9e692
+316, 0x75a9ccd4dd8935cb
+317, 0x7e6cf9e539361e91
+318, 0x20fdd22fb6edd475
+319, 0x5973021b57c2311f
+320, 0x75392403667edc15
+321, 0xed9b2156ea70d9f1
+322, 0xf40c114db50b64a0
+323, 0xe26bb2c9eef20c62
+324, 0x409c1e3037869f03
+325, 0xcdfd71fdda3b7f91
+326, 0xa0dfae46816777d6
+327, 0xde060a8f61a8deb8
+328, 0x890e082a8b0ca4fc
+329, 0xb9f2958eddf2d0db
+330, 0xd17c148020d20e30
+331, 0xffdc9cc176fe7201
+332, 0xffb83d925b764c1
+333, 0x817ea639e313da8d
+334, 0xa4dd335dd891ca91
+335, 0x1342d25a5e81f488
+336, 0xfa7eb9c3cf466b03
+337, 0xfe0a423d44b185d0
+338, 0x101cfd430ab96049
+339, 0x7b5d3eda9c4504b
+340, 0xe20ccc006e0193f1
+341, 0xf54ccddedebc5df0
+342, 0xc0edd142bd58f1db
+343, 0x3831f40d378d2430
+344, 0x80132353f0a88289
+345, 0x688f23c419d03ef8
+346, 0x4c6837e697884066
+347, 0x699387bb2e9a3a8f
+348, 0x8996f860342448d8
+349, 0xb0f80dff99bfa5cc
+350, 0x3e927a7f9ea12c8e
+351, 0xd7e498d1e5f9dff3
+352, 0x78ecb97bb3f864cc
+353, 0x3c4ffd069a014d38
+354, 0xf8d5073a1e09b4d4
+355, 0x8717e854f9faef23
+356, 0xfbcc5478d8d0ad7
+357, 0xd3cd8b233ca274ff
+358, 0x8bd8f11f79beb265
+359, 0xf64498a832d8fd0e
+360, 0xb01bba75112131ec
+361, 0x55572445a7869781
+362, 0x7b56622f18cb3d7a
+363, 0x7f192c9e075bdb83
+364, 0xd9a112f836b83ff3
+365, 0x68673b37269653dc
+366, 0xe46a9433fb6a0879
+367, 0x127d756ca4779001
+368, 0xc1378e8b1e8eab94
+369, 0x1006edb0f51d078c
+370, 0xc6dd53961232d926
+371, 0x9a4aeef44038256d
+372, 0xd357f4fa652d4f5f
+373, 0x59f3d2cc3378598
+374, 0xe76e6207a824a7fc
+375, 0x5fc5e33712ceffef
+376, 0x77d24aeb0ccb1adc
+377, 0x5be4b2826805659e
+378, 0x257c69d787e64634
+379, 0x58dd52ca6bc727b1
+380, 0x3ab997767235ea33
+381, 0x986a2a7a966fad14
+382, 0xc900f8b27761dcc4
+383, 0x44991bdb13795700
+384, 0xe5c145a4fe733b2
+385, 0x56f041b56bffe0d3
+386, 0x5779c4fef8067996
+387, 0xa0fe8748e829532d
+388, 0x840c1277d78d9dd4
+389, 0x37ebcb315432acbc
+390, 0xf4bc8738433ba3be
+391, 0x8b122993f2e10062
+392, 0xe1fe8481f2681ed5
+393, 0x8e23f1630d9f494a
+394, 0xda24661a01b7d0b3
+395, 0x7a02942a179cee36
+396, 0xf1e08a3c09b71ac
+397, 0x3dec2cc7ee0bd8fd
+398, 0x1f3e480113d805d4
+399, 0xc061b973ad4e3f2c
+400, 0x6bea750f17a66836
+401, 0xbc2add72eac84c25
+402, 0xcff058d3f97934ca
+403, 0x54ccc30987778ec2
+404, 0x93449ec1e1469558
+405, 0xe2ff369eb0c6836
+406, 0x41c2df2d63bf8e55
+407, 0xf9302629b6c71be2
+408, 0xdd30376b8e5ab29a
+409, 0x12db9e04f911d754
+410, 0x8d03d6cd359f1b97
+411, 0xe15956511abf1cee
+412, 0x9b68e10e2c2fd940
+413, 0x2e28de6491c1ce53
+414, 0x52b329b72d0c109d
+415, 0xc2c0b115f9da2a60
+416, 0x6ca084105271bbff
+417, 0x49b92b8676058c1e
+418, 0x767fc92a70f7e5a3
+419, 0x87ba4ed4b65a6aa0
+420, 0xf70b052e0a3975e9
+421, 0x3e925c3306db9eec
+422, 0x43253f1d96ac9513
+423, 0xe3e04f1a1ea454c4
+424, 0x763e3f4cc81ba0c8
+425, 0x2a2721ac69265705
+426, 0xdf3b0ac6416ea214
+427, 0xa6a6b57450f3e000
+428, 0xc3d3b1ac7dbfe6ac
+429, 0xb66e5e6f7d2e4ec0
+430, 0x43c65296f98f0f04
+431, 0xdb0f6e3ff974d842
+432, 0x3d6b48e02ebb203b
+433, 0xd74674ebf09d8f27
+434, 0xbe65243c58fc1200
+435, 0x55eb210a68d42625
+436, 0x87badab097dbe883
+437, 0xada3fda85a53824f
+438, 0xef2791e8f48cd37a
+439, 0x3fe7fceb927a641a
+440, 0xd3bffd3ff031ac78
+441, 0xb94efe03da4d18fb
+442, 0x162a0ad8da65ea68
+443, 0x300f234ef5b7e4a6
+444, 0xa2a8b4c77024e4fb
+445, 0x5950f095ddd7b109
+446, 0xded66dd2b1bb02ba
+447, 0x8ec24b7fa509bcb6
+448, 0x9bede53d924bdad6
+449, 0xa9c3f46423be1930
+450, 0x6dfc90597f8de8b4
+451, 0xb7419ebc65b434f0
+452, 0xa6596949238f58b9
+453, 0x966cbade640829b8
+454, 0x58c74877bdcbf65e
+455, 0xaa103b8f89b0c453
+456, 0x219f0a86e41179a4
+457, 0x90f534fc06ddc57f
+458, 0x8db7cdd644f1affa
+459, 0x38f91de0167127ac
+460, 0xdcd2a65e4df43daa
+461, 0x3e04f34a7e01f834
+462, 0x5b237eea68007768
+463, 0x7ff4d2b015921768
+464, 0xf786b286549d3d51
+465, 0xaefa053fc2c3884c
+466, 0x8e6a8ff381515d36
+467, 0x35b94f3d0a1fce3c
+468, 0x165266d19e9abb64
+469, 0x1deb5caa5f9d8076
+470, 0x13ab91290c7cfe9d
+471, 0x3651ca9856be3e05
+472, 0xe7b705f6e9cccc19
+473, 0xd6e7f79668c127ed
+474, 0xa9faf37154896f92
+475, 0x89fbf190603e0ab1
+476, 0xb34d155a86f942d0
+477, 0xb2d4400a78bfdd76
+478, 0x7c0946aca8cfb3f0
+479, 0x7492771591c9d0e8
+480, 0xd084d95c5ca2eb28
+481, 0xb18d12bd3a6023e
+482, 0xea217ed7b864d80b
+483, 0xe52f69a755dd5c6f
+484, 0x127133993d81c4aa
+485, 0xe07188fcf1670bfb
+486, 0x178fbfe668e4661d
+487, 0x1c9ee14bb0cda154
+488, 0x8d043b96b6668f98
+489, 0xbc858986ec96ca2b
+490, 0x7660f779d528b6b7
+491, 0xd448c6a1f74ae1d3
+492, 0x178e122cfc2a6862
+493, 0x236f000abaf2d23b
+494, 0x171b27f3f0921915
+495, 0x4c3ff07652f50a70
+496, 0x18663e5e7d3a66ca
+497, 0xb38c97946c750cc9
+498, 0xc5031aae6f78f909
+499, 0x4d1514e2925e95c1
+500, 0x4c2184a741dabfbb
+501, 0xfd410364edf77182
+502, 0xc228157f863ee873
+503, 0x9856fdc735cc09fc
+504, 0x660496cd1e41d60e
+505, 0x2edf1d7e01954c32
+506, 0xd32e94639bdd98cf
+507, 0x8e153f48709a77d
+508, 0x89357f332d2d6561
+509, 0x1840d512c97085e6
+510, 0x2f18d035c9e26a85
+511, 0x77b88b1448b26d5b
+512, 0xc1ca6ef4cdae0799
+513, 0xcc203f9e4508165f
+514, 0xeaf762fbc9e0cbbe
+515, 0xc070c687f3c4a290
+516, 0xd49ed321068d5c15
+517, 0x84a55eec17ee64ee
+518, 0x4d8ee685298a8871
+519, 0x9ff5f17d7e029793
+520, 0x791d7d0d62e46302
+521, 0xab218b9114e22bc6
+522, 0x4902b7ab3f7119a7
+523, 0x694930f2e29b049e
+524, 0x1a3c90650848999f
+525, 0x79f1b9d8499c932b
+526, 0xfacb6d3d55e3c92f
+527, 0x8fd8b4f25a5da9f5
+528, 0xd037dcc3a7e62ae7
+529, 0xfecf57300d8f84f4
+530, 0x32079b1e1dc12d48
+531, 0xe5f8f1e62b288f54
+532, 0x97feba3a9c108894
+533, 0xd279a51e1899a9a0
+534, 0xd68eea8e8e363fa8
+535, 0x7394cf2deeca9386
+536, 0x5f70b0c80f1dbf10
+537, 0x8d646916ed40462
+538, 0xd253bb1c8a12bbb6
+539, 0x38f399a821fbd73e
+540, 0x947523a26333ac90
+541, 0xb52e90affbc52a37
+542, 0xcf899cd964654da4
+543, 0xdf66ae9cca8d99e7
+544, 0x6051478e57c21b6a
+545, 0xffa7dc975af3c1da
+546, 0x195c7bff2d1a8f5
+547, 0x64f12b6575cf984d
+548, 0x536034cb842cf9e1
+549, 0x180f247ce5bbfad
+550, 0x8ced45081b134867
+551, 0x532bbfdf426710f3
+552, 0x4747933e74c4f54d
+553, 0x197a890dc4793401
+554, 0x76c7cc2bd42fae2
+555, 0xdabfd67f69675dd0
+556, 0x85c690a68cdb3197
+557, 0xe482cec89ce8f92
+558, 0x20bc9fb7797011b1
+559, 0x76dc85a2185782ad
+560, 0x3df37c164422117a
+561, 0x99211f5d231e0ab0
+562, 0xef7fd794a0a91f4
+563, 0x419577151915f5fe
+564, 0x3ce14a0a7135dae3
+565, 0x389b57598a075d6a
+566, 0x8cc2a9d51b5af9aa
+567, 0xe80a9beffbd13f13
+568, 0x65e96b22ea8a54d8
+569, 0x79f38c4164138ede
+570, 0xd1955846cba03d81
+571, 0x60359fe58e4f26d6
+572, 0x4ea724f585f8d13e
+573, 0x316dfdbadc801a3c
+574, 0x20aa29b7c6dd66fe
+575, 0x65eaf83a6a008caa
+576, 0x407000aff1b9e8cb
+577, 0xb4d49bfb2b268c40
+578, 0xd4e6fe8a7a0f14a9
+579, 0xe34afef924e8f58e
+580, 0xe377b0c891844824
+581, 0x29c2e20c112d30c8
+582, 0x906aad1fe0c18a95
+583, 0x308385f0efbb6474
+584, 0xf23900481bf70445
+585, 0xfdfe3ade7f937a55
+586, 0xf37aae71c33c4f97
+587, 0x1c81e3775a8bed85
+588, 0x7eb5013882ce35ea
+589, 0x37a1c1692495818d
+590, 0x3f90ae118622a0ba
+591, 0x58e4fe6fea29b037
+592, 0xd10ff1d269808825
+593, 0xbce30edb60c21bba
+594, 0x123732329afd6fee
+595, 0x429b4059f797d840
+596, 0x421166568a8c4be1
+597, 0x88f895c424c1bd7f
+598, 0x2adaf7a7b9f781cb
+599, 0xa425644b26cb698
+600, 0x8cc44d2486cc5743
+601, 0xdb9f357a33abf6ba
+602, 0x1a57c4ea77a4d70c
+603, 0x1dea29be75239e44
+604, 0x463141a137121a06
+605, 0x8fecfbbe0b8a9517
+606, 0x92c83984b3566123
+607, 0x3b1c69180ed28665
+608, 0x14a6073425ea8717
+609, 0x71f4c2b3283238d7
+610, 0xb3d491e3152f19f
+611, 0x3a0ba3a11ebac5d2
+612, 0xddb4d1dd4c0f54ac
+613, 0xdb8f36fe02414035
+614, 0x1cf5df5031b1902c
+615, 0x23a20ed12ef95870
+616, 0xf113e573b2dedcbb
+617, 0x308e2395cde0a9fa
+618, 0xd377a22581c3a7da
+619, 0xe0ced97a947a66fb
+620, 0xe44f4de9cd754b00
+621, 0x2344943337d9d1bf
+622, 0x4b5ae5e2ea6e749c
+623, 0x9b8d2e3ef41d1c01
+624, 0x59a5a53ebbd24c6b
+625, 0x4f7611bf9e8a06fb
+626, 0xea38c7b61361cd06
+627, 0xf125a2bfdd2c0c7
+628, 0x2df8dcb5926b9ebb
+629, 0x233e18720cc56988
+630, 0x974c61379b4aa95e
+631, 0xc7fe24c1c868910b
+632, 0x818fd1affc82a842
+633, 0xcee92a952a26d38e
+634, 0x8962f575ebcbf43
+635, 0x7770687e3678c460
+636, 0xdfb1db4ed1298117
+637, 0xb9db54cb03d434d3
+638, 0x34aebbf2244257ad
+639, 0xd836db0cb210c490
+640, 0x935daed7138957cd
+641, 0x3cd914b14e7948fd
+642, 0xd0472e9ed0a0f7f0
+643, 0xa9df33dca697f75e
+644, 0x15e9ea259398721a
+645, 0x23eeba0f970abd60
+646, 0x2217fdf8bbe99a12
+647, 0x5ea490a95717b198
+648, 0xf4e2bfc28280b639
+649, 0x9d19916072d6f05c
+650, 0x5e0387cab1734c6a
+651, 0x93c2c8ac26e5f01e
+652, 0xb0d934354d957eb1
+653, 0xee5099a1eef3188c
+654, 0x8be0abca8edc1115
+655, 0x989a60845dbf5aa3
+656, 0x181c7ed964eee892
+657, 0x49838ea07481288d
+658, 0x17dbc75d66116b2e
+659, 0xa4cafb7a87c0117e
+660, 0xab2d0ae44cdc2e6e
+661, 0xdf802f2457e7da6
+662, 0x4b966c4b9187e124
+663, 0x62de9db6f4811e1a
+664, 0x1e20485968bc62
+665, 0xe9ac288265caca94
+666, 0xc5c694d349aa8c1a
+667, 0x3d67f2083d9bdf10
+668, 0x9a2468e503085486
+669, 0x9d6acd3dc152d1a3
+670, 0xca951e2aeee8df77
+671, 0x2707371af9cdd7b0
+672, 0x2347ae6a4eb5ecbd
+673, 0x16abe5582cb426f
+674, 0x523af4ff980bbccb
+675, 0xb07a0f043e3694aa
+676, 0x14d7c3da81b2de7
+677, 0xf471f1b8ac22305b
+678, 0xdb087ffff9e18520
+679, 0x1a352db3574359e8
+680, 0x48d5431502cc7476
+681, 0x7c9b7e7003dfd1bf
+682, 0x4f43a48aae987169
+683, 0x9a5d3eb66dedb3e9
+684, 0xa7b331af76a9f817
+685, 0xba440154b118ab2d
+686, 0x64d22344ce24c9c6
+687, 0xa22377bd52bd043
+688, 0x9dfa1bb18ca6c5f7
+689, 0xdccf44a92f644c8b
+690, 0xf623d0a49fd18145
+691, 0x556d5c37978e28b3
+692, 0xad96e32ce9d2bb8b
+693, 0x2e479c120be52798
+694, 0x7501cf871af7b2f7
+695, 0xd02536a5d026a5b8
+696, 0x4b37ff53e76ab5a4
+697, 0xdb3a4039caaeab13
+698, 0x6cbd65e3b700c7be
+699, 0x7367abd98761a147
+700, 0xf4f9ba216a35aa77
+701, 0xf88ca25ce921eb86
+702, 0xb211de082ec2cbf2
+703, 0xdd94aa46ec57e12e
+704, 0xa967d74ad8210240
+705, 0xdaa1fada8cfa887
+706, 0x85901d081c4488ee
+707, 0xcf67f79a699ef06
+708, 0x7f2f1f0de921ee14
+709, 0x28bc61e9d3f2328b
+710, 0x3332f2963faf18e5
+711, 0x4167ac71fcf43a6
+712, 0x843c1746b0160b74
+713, 0xd9be80070c578a5e
+714, 0xbd7250c9af1473e7
+715, 0x43f78afaa3647899
+716, 0x91c6b5dd715a75a5
+717, 0x29cc66c8a07bfef3
+718, 0x3f5c667311dc22be
+719, 0x4f49cd47958260cd
+720, 0xbef8be43d920b64e
+721, 0x7a892a5f13061d8b
+722, 0x9532f40125c819b1
+723, 0x924fca3045f8a564
+724, 0x9b2c6442453b0c20
+725, 0x7e21009085b8e793
+726, 0x9b98c17e17af59d2
+727, 0xba61acb73e3ae89a
+728, 0xb9d61a710555c138
+729, 0xc2a425d80978974b
+730, 0xa275e13592da7d67
+731, 0xe962103202d9ad0f
+732, 0xbdf8367a4d6f33fd
+733, 0xe59beb2f8648bdc8
+734, 0xb4c387d8fbc4ac1c
+735, 0x5e3f276b63054b75
+736, 0xf27e616aa54d8464
+737, 0x3f271661d1cd7426
+738, 0x43a69dbee7502c78
+739, 0x8066fcea6df059a1
+740, 0x3c10f19409bdc993
+741, 0x6ba6f43fb21f23e0
+742, 0x9e182d70a5bccf09
+743, 0x1520783d2a63a199
+744, 0xba1dcc0c70b9cace
+745, 0x1009e1e9b1032d8
+746, 0xf632f6a95fb0315
+747, 0x48e711c7114cbfff
+748, 0xef281dcec67debf7
+749, 0x33789894d6abf59b
+750, 0x6c8e541fffbe7f9c
+751, 0x85417f13b08e0a88
+752, 0x9a581e36d589608f
+753, 0x461dca50b1befd35
+754, 0x5a3231680dde6462
+755, 0xcc57acf729780b97
+756, 0x50301efef62e1054
+757, 0x675d042cd4f6bbc9
+758, 0x1652fdd3794384c9
+759, 0x1c93bbeeb763cd4d
+760, 0x44b7240c4b105242
+761, 0x4c6af2a1b606ccfb
+762, 0x18fc43ece2ec1a40
+763, 0x859a5511aeae8acb
+764, 0x2f56826f1996ad2f
+765, 0xa8e95ce8bb363bdf
+766, 0xf4da396054e50e4b
+767, 0x5493865e9895883c
+768, 0x768e4c8b332ac0e3
+769, 0x32195d2aa583fca5
+770, 0xf2f353f21266bc15
+771, 0x43cddf1d021307d
+772, 0x6031e3aa30300e4a
+773, 0x4f1298469ac6088f
+774, 0x4b4d450bafac574e
+775, 0x23e1cf9c0582a22b
+776, 0x2e9036980db49cd0
+777, 0xe4e228b113c411b2
+778, 0x8bddcdb82b51706
+779, 0xd2a7ea8288593629
+780, 0x67fe90e98fdda61
+781, 0x7b63494dba95717b
+782, 0x105625904510d782
+783, 0xdf4aa2242454e50a
+784, 0x32541d6cd7d6c7e3
+785, 0x5661fb432591cf3b
+786, 0xce920a5ed047bce7
+787, 0xed4178a3c96eea8f
+788, 0xe378cd996e39863b
+789, 0x169e1fdc8e2b05e1
+790, 0xaee1812ef7149a96
+791, 0x648571c7453d12c5
+792, 0xb7b6bc9328573c43
+793, 0xe7fb969078e270d7
+794, 0xdfc2b1b8985f6e6f
+795, 0x862b6527ee39a1aa
+796, 0x1ee329aea91d7882
+797, 0x20d25324f2fe704
+798, 0xbfcc47401fc3bbfd
+799, 0x1515cdc8d48b2904
+800, 0xbd6eefe86284261c
+801, 0x9b1f28e3b35f22ee
+802, 0x842a29d35e5aecda
+803, 0xf2346109ad370765
+804, 0x24d68add5a71afd9
+805, 0x4a691421613d91e2
+806, 0x60e3058b3c244051
+807, 0x79194905cdaa5de8
+808, 0xe0e2df35c01e8987
+809, 0xe29b78beffbb5e4a
+810, 0xcdcdbc020218c19e
+811, 0x5ae0af8c16feae43
+812, 0x8109292feeaf14fa
+813, 0x34113f7508dfa521
+814, 0xc062ac163f56730a
+815, 0xf1660e66ec6d4c4c
+816, 0x5966c55f60151c80
+817, 0x3865ae8ec934b17
+818, 0x472a7314afb055ec
+819, 0x7a24277309a44a44
+820, 0x556e02dd35d38baa
+821, 0x9849611a1bc96ec1
+822, 0xd176f5d5a8eb0843
+823, 0x44db12ec60510030
+824, 0x272e3a06a0030078
+825, 0x7c4764dbefc075ea
+826, 0x910712f3735c1183
+827, 0xd49a2da74ae7aff6
+828, 0xcf9b3e6e8f776d71
+829, 0x27789fe3ec481a02
+830, 0x86659f82c6b5912b
+831, 0xe044b3dbf339158c
+832, 0x99d81f6bb62a37b0
+833, 0x5f5830c246fada9a
+834, 0xe68abab1eeb432cb
+835, 0x49c5c5ace04e104
+836, 0x1ac3871b3fc6771b
+837, 0x773b39f32d070652
+838, 0x9c4138c2ae58b1f3
+839, 0xac41c63d7452ac60
+840, 0x9248826b245359e1
+841, 0x99bba1c7a64f1670
+842, 0xe0dc99ff4ebb92f2
+843, 0x113638652740f87c
+844, 0xebf51e94da88cfc
+845, 0x5441c344b81b2585
+846, 0xe1e69e0bc2de652a
+847, 0xe9ab6d64ae42ed1e
+848, 0x879af8730e305f31
+849, 0x36b9ad912c7e00d6
+850, 0x83ef5e9fca853886
+851, 0xda54d48bb20ea974
+852, 0x32c6d93aefa92aa2
+853, 0x4e887b2c3391847d
+854, 0x50966e815f42b1b8
+855, 0x53411ac087832837
+856, 0x46f64fef79df4f29
+857, 0xb34aae3924cd272c
+858, 0xf5ad455869a0adbe
+859, 0x8351ded7144edac8
+860, 0xeb558af089677494
+861, 0x36ed71d69293a8d6
+862, 0x659f90bf5431b254
+863, 0x53349102b7519949
+864, 0x3db83e20b1713610
+865, 0x6d63f96090556254
+866, 0x4cc0467e8f45c645
+867, 0xb8840c4bd5cd4091
+868, 0xbd381463cc93d584
+869, 0x203410d878c2066d
+870, 0x2ebea06213cf71c8
+871, 0x598e8fb75e3fceb4
+872, 0xdcca41ceba0fce02
+873, 0x61bf69212b56aae5
+874, 0x97eed7f70c9114fa
+875, 0xf46f37a8b7a063f9
+876, 0x66c8f4ffe5bd6efa
+877, 0xe43fd6efda2d4e32
+878, 0x12d6c799e5ad01de
+879, 0x9ac83e7f8b709360
+880, 0xbbb7bb3c1957513d
+881, 0x7f87c08d4b3796b0
+882, 0x9a7d1d74b6aa4a5c
+883, 0xa4314530ff741b6f
+884, 0x99a80c6b6f15fca8
+885, 0xd2fec81d6d5fc3ce
+886, 0x15a98be1cc40cea
+887, 0x98693eb7719366f3
+888, 0x36ccdc2a9e9d4de8
+889, 0x3c8208f63d77df25
+890, 0xca2e376e2343df6
+891, 0xcc9b17cbb54420c6
+892, 0x8724c44a64d7dcb8
+893, 0x9d00c6949ff33869
+894, 0xf4f8e584d2699372
+895, 0x88f4748cdd5a2d53
+896, 0xe215072a1205bc6d
+897, 0x190934fe6d740442
+898, 0x7fac5c0ab2af106d
+899, 0x1b86633a0bd84fa1
+900, 0x1293e54318492dfb
+901, 0x433324fd390f34b9
+902, 0x4c5eb2c67a44643b
+903, 0x59a6e281c388b0dd
+904, 0xe78e03f9c44623b7
+905, 0x91307a93c768fc3d
+906, 0xde8867b004d8e3ff
+907, 0xdf52c3f57b7c5862
+908, 0x993f3e1d10358a92
+909, 0x9ccb10bc3e18662d
+910, 0x45093ce48a114c73
+911, 0xd59d05979d26330a
+912, 0x417c0e03300119a9
+913, 0x1c336500f90cde81
+914, 0x1c8ccd29ead9b85b
+915, 0xb76baf3e55d4d950
+916, 0x133ad6196c75fd7e
+917, 0x34200b0cde7ed560
+918, 0x9c7c3dacb213c8d9
+919, 0xd97563c4fd9bf1b6
+920, 0x5d910e871835b6cb
+921, 0x7d46c4733a16bdf9
+922, 0xe41d73194ddc87b2
+923, 0x7d3d8a0855a465a9
+924, 0x70c2a8b5d3f90c0f
+925, 0x9e7565ca5dccfe12
+926, 0x2c0acb4577aa51b1
+927, 0x3d2cd211145b79c7
+928, 0x15a7b17aa6da7732
+929, 0xab44a3730c27d780
+930, 0xf008bd6c802bde3a
+931, 0x82ed86ddf3619f77
+932, 0xaabe982ab15c49f9
+933, 0x9bcad8fa6d8e58a4
+934, 0x8f39ed8243718aa1
+935, 0xe9489340e03e3cb6
+936, 0xc722314f5eefb8d0
+937, 0x870e8869a436df59
+938, 0x4dae75b8087a8204
+939, 0xe1d790f6ec6e425b
+940, 0xafd39ea1b1d0ed09
+941, 0xdf2c99e464ddf08f
+942, 0x74936d859ab9644d
+943, 0x3871302164250e73
+944, 0x764b68921e911886
+945, 0x2a1d024b26bb9d66
+946, 0x797fba43918e75b4
+947, 0x62ec6d24ccca335b
+948, 0xf4bd8b951762b520
+949, 0x9d450dede9119397
+950, 0x5393a26d10f8c124
+951, 0x6b74769392896b57
+952, 0x7f61dbcc0e328581
+953, 0x64e1df3884d0d94
+954, 0xba77dcdf23738c37
+955, 0xf8e288bc0a177475
+956, 0x4a8abfd1702ecb7d
+957, 0x53f22886694736a7
+958, 0x8fc982597ced3e3
+959, 0x1bc46090f820fff7
+960, 0x8bd31f965d02229f
+961, 0x65cd0cb29996ee53
+962, 0x702e0f4fcf8c2e9f
+963, 0x293b77bff307a9a0
+964, 0x125a986b8b305788
+965, 0x416b0eea428ebf3c
+966, 0xeac85421ab0e8469
+967, 0x7f5496095019aa68
+968, 0x1a96d7afbc708e0
+969, 0xb91262e6766e01e1
+970, 0xd0a549cc4ccc6954
+971, 0x75a9a073f50c8a0d
+972, 0xae275d2c1c6cd23c
+973, 0xcf159b5ec5d28fd4
+974, 0x75d0838ce9b92b
+975, 0xd4eddcee6dc4677f
+976, 0x6a0a8ad5df6b75b8
+977, 0x6f3fd0ef0f13ecc4
+978, 0xb75a5826c1a8f8a8
+979, 0xd47098bbc7943766
+980, 0x3d4ddd62d5f23dd1
+981, 0x760a904e4583841c
+982, 0x2afeb5022b4cf1f
+983, 0x66d5f653729f0a13
+984, 0x9a6a5ab62980d30f
+985, 0xc332f5643bbf8d5b
+986, 0x848fb702e4056a90
+987, 0xa057beaf3f9e8c5f
+988, 0x6cc603e4560a6c6a
+989, 0xec761811a7b23211
+990, 0xb14aa4090a82aaa5
+991, 0xe29d9d028a5b2dbb
+992, 0x5564e53738d68f97
+993, 0xfabca36542eaaf3b
+994, 0xb9912fcb782020a2
+995, 0xe865e01b349284fd
+996, 0x540b5ff11c5f9274
+997, 0x3463f64e1e7451dc
+998, 0xe15d3e2f33b735f8
+999, 0xf5433336eadef6e
diff --git a/numpy/random/tests/data/sfc64-testset-2.csv b/numpy/random/tests/data/sfc64-testset-2.csv
new file mode 100644
index 000000000..70aebd5d5
--- /dev/null
+++ b/numpy/random/tests/data/sfc64-testset-2.csv
@@ -0,0 +1,1001 @@
+seed, 0x0
+0, 0x91959e5fb96a6332
+1, 0x3c1dd8a25a7e9f21
+2, 0x657bdffc99798d9e
+3, 0x1a04de320b19e022
+4, 0x65b92af0e5f3c61c
+5, 0x9c84070ce8f743c0
+6, 0xbb10e573693cdb25
+7, 0xd65ea9e76b37fb6b
+8, 0x503efd0e76c8ae66
+9, 0xd711dcd04c26d0f
+10, 0x12f53f435814ac8c
+11, 0xb392cd402cfc82bd
+12, 0x461764550e06c889
+13, 0x716a48b3514e6979
+14, 0xdd0a322213c18ad7
+15, 0x6673a8ca0a05c4d7
+16, 0x2992ef333437f844
+17, 0xc4aaf7e8240b2aad
+18, 0x6ab0a1af1f41474f
+19, 0xb0bae400c226941d
+20, 0xe5f80c2eeeab48c6
+21, 0x3832c6a93a4024bf
+22, 0x280bd824fabe8368
+23, 0x66b626228321e5ff
+24, 0xe0bdfba5325a307e
+25, 0x3a5f65c6ef254e05
+26, 0x99ea12503cb02f94
+27, 0x5d01fd2db77d420b
+28, 0x6959bf5f36b2368d
+29, 0xd856e30c62b5f5be
+30, 0xe33233e1d8140e66
+31, 0xb78be619d415fa8d
+32, 0x4f943bb2cc63d3b
+33, 0x9b1460b290952d81
+34, 0x19205d794826740e
+35, 0x64617bd9d7a6a1ff
+36, 0x30442124b55ea76a
+37, 0xebbbc3b29d0333fc
+38, 0x39235a0fe359751c
+39, 0xf9629768891121aa
+40, 0x32052f53f366e05a
+41, 0x60cc5b412c925bc8
+42, 0xf8b7ecda1c0e5a9
+43, 0x195f036e170a2568
+44, 0xfe06d0381a9ca782
+45, 0x919d89e8b88eebbf
+46, 0xa47fb30148cf0d43
+47, 0x5c983e99d5f9fd56
+48, 0xe7492cdb6a1d42cd
+49, 0xf9cfe5c865b0cfd8
+50, 0x35b653367bbc3b99
+51, 0xb1d92f6f4d4e440b
+52, 0x737e1d5bd87ed9c0
+53, 0x7a880ca1498f8e17
+54, 0x687dae8494f9a3f7
+55, 0x6bae1989f441d5d7
+56, 0x71ad3fa5a9195c2e
+57, 0x16b3969779f5d03
+58, 0xd1bce2ac973f15b3
+59, 0xa114b1ee2ce0dcdd
+60, 0x270d75c11eb1b8d5
+61, 0xc48ffa087c0a7bc
+62, 0xaaf9dc48cda9848d
+63, 0x8111cf10ef6e584d
+64, 0x6736df6af40ee6f4
+65, 0x1a1a111682fbf98d
+66, 0xeb217658e1cb3b5d
+67, 0xcaf58a8b79de9dec
+68, 0x25d0ffd63c88d7a1
+69, 0x4c498cd871b7f176
+70, 0x4069a6156eb0cf3c
+71, 0xdf012f12edcdd867
+72, 0x7734c0ac8edb1689
+73, 0xed6960ac53dbc245
+74, 0x305e20da8868c661
+75, 0x5f0c7a3719956f95
+76, 0x66842bbe3b28895
+77, 0xb608bc9a31eac410
+78, 0xfcb17d5529503abd
+79, 0x829ae5cbc29b92ee
+80, 0x17f2f0027bc24f3a
+81, 0x435926c33d8f44cc
+82, 0x3ab899327098dbec
+83, 0xaf78573b27f8ead8
+84, 0xa8b334fabcf8dc60
+85, 0xcdf3b366a6a303db
+86, 0x8da9379dd62b34c8
+87, 0xb0ba511955f264a7
+88, 0x9d72e21a644f961d
+89, 0xfac28382e2e7e710
+90, 0xd457065f048410aa
+91, 0x1cae57d952563969
+92, 0x5a160a6223253e03
+93, 0x2c45df736d73c8bd
+94, 0x7f651ebc6ad9cec5
+95, 0x77a6be96c7d2e7e7
+96, 0x1721fb1dbfd6546a
+97, 0xf73f433ecff3c997
+98, 0xed1e80f680965bfe
+99, 0x6705ad67a3003b30
+100, 0xac21134efcadb9f7
+101, 0x4d2ba0a91d456ac
+102, 0x59da7b59434eb52b
+103, 0x26c1d070fd414b5f
+104, 0xed7079ddfce83d9a
+105, 0x9277d21f88e0fb7a
+106, 0xfae16b9a8d53d282
+107, 0xb08a0e2e405fdf7d
+108, 0x2ea20df44229d6ec
+109, 0x80e4634cd3612825
+110, 0xbe62e8aeba8f8a1a
+111, 0x4981209769c190fb
+112, 0xcec96ef14c7e1f65
+113, 0x73fe4457b47e7b53
+114, 0x1d66300677315c31
+115, 0xe26821290498c4cc
+116, 0xf6110248fd8fb1c5
+117, 0x30fd7fe32dbd8be3
+118, 0x534ec9b910a2bd72
+119, 0x8f9bfe878bbf7382
+120, 0x4f4eb5295c0c2193
+121, 0xdeb22f03a913be9e
+122, 0x40f716f8e2a8886c
+123, 0xc65007d0e386cdb1
+124, 0x9bdd26d92b143a14
+125, 0xf644b0b77ea44625
+126, 0x75f5a53f6b01993a
+127, 0xfe803e347bf41010
+128, 0x594bff5fa17bc360
+129, 0x3551edfb450373c7
+130, 0x898f9dad433615db
+131, 0x923d2406daa26d49
+132, 0x99e07faccbc33426
+133, 0x7389f9ff4470f807
+134, 0xdc2a25957c6df90b
+135, 0x33c6d8965ef3053f
+136, 0x51a8f07e838f1ab
+137, 0x91c5db369380274f
+138, 0xc37de65ac56b207e
+139, 0xfcc6d2375dde7f14
+140, 0xa4e6418bff505958
+141, 0x4b8b9f78e46953c4
+142, 0x255ab2e0f93cf278
+143, 0xdf650717af3d96ef
+144, 0x2caa21cba3aae2b2
+145, 0xce7e46c6f393daa4
+146, 0x1d5b3573f9997ac7
+147, 0x5280c556e850847d
+148, 0x32edc31bef920ad7
+149, 0xefaa6b0b08cf2c6
+150, 0x5151c99d97b111c5
+151, 0x35ccf4bf53d17590
+152, 0xa210d7bd8697b385
+153, 0xa9419f95738fbe61
+154, 0xdeccf93a1a4fdc90
+155, 0xd0ea3365b18e7a05
+156, 0x84122df6dcd31b9a
+157, 0x33040a2125cea5f5
+158, 0xfe18306a862f6d86
+159, 0xdb97c8392e5c4457
+160, 0xc3e0fa735e80e422
+161, 0x7d106ff36467a0c1
+162, 0xb9825eecc720a76d
+163, 0x7fefc6f771647081
+164, 0xf5df3f5b3977bf13
+165, 0x18fb22736d36f1e0
+166, 0xadc4637b4953abfc
+167, 0x174e66d3e17974bd
+168, 0xf1614c51df4db5db
+169, 0x6664ecde5717b293
+170, 0xd5bc5b6839265c26
+171, 0xf6ca9ce1af3f1832
+172, 0xca696789a9d506ea
+173, 0x7399c246c8f9d53
+174, 0xadf49049626417e2
+175, 0xbcd84af37d09ab91
+176, 0xbb41c177f3a3fa45
+177, 0x592becc814d55302
+178, 0xa88b4e65f6cfe5f7
+179, 0xa0a55e34ff879426
+180, 0x3c2ea6aa725b42b7
+181, 0x65ac4a407b1f9521
+182, 0xde63d53f7e88b556
+183, 0x18bc76696d015f40
+184, 0xd1363f2cd4c116a8
+185, 0x2fe859be19a48e4a
+186, 0x83d6099b1415e656
+187, 0x43f2cbc1a4ee6410
+188, 0xb2eca3d3421c533d
+189, 0xc52b98ea3f031f5d
+190, 0xfe57eb01da07e9d1
+191, 0xf9377883537a6031
+192, 0x364030c05dac7add
+193, 0x6815cb06b35d4404
+194, 0xceae2d4ce31894be
+195, 0xc602bcdf6062bf6a
+196, 0xc8e4bd8dcc6062e3
+197, 0x9c29e87b92a1a791
+198, 0x41e626b871ca9651
+199, 0x325c3d1fb8efbcd8
+200, 0x7dbbacf8e3419fb3
+201, 0x3602e72516bb7319
+202, 0x537a008ebd94d24b
+203, 0xda7714fc9d4d161d
+204, 0x1c8c73700e1b621b
+205, 0x2749b80937d6c939
+206, 0x76ee6abac5b14d33
+207, 0xf18d1e92cb6a8b5c
+208, 0x6ce9579d9291c721
+209, 0x60523c745a40e58
+210, 0x637f837fcc901757
+211, 0x2ff71b19661dc5b3
+212, 0x393ab586326ad16f
+213, 0xa0970ea30fe742b7
+214, 0x570222d7f27fe5ae
+215, 0x3b5806d43fd38629
+216, 0x129a0ad7420180c5
+217, 0x1c4726355778d52c
+218, 0x7c1459cf77656499
+219, 0xfe038a0932132069
+220, 0x4c4cc317a937483a
+221, 0xa333d24067e926ba
+222, 0x401d9b6ab37f6ef2
+223, 0x87ad0e491ebe4a2a
+224, 0xfc02f312e72d121d
+225, 0xfde715b3b99767b2
+226, 0xd111c342ba521c92
+227, 0x83b221b10879c617
+228, 0x6a1bf5c01fdf4277
+229, 0x166bfc0c3f5892ee
+230, 0x4608d556d7c57856
+231, 0x8d786857c95ece49
+232, 0x2d357445a1aca4ac
+233, 0x79620dae28ecd796
+234, 0x90e715dc0f2201c4
+235, 0x173b68b4c9f4b665
+236, 0x4e14d040ebac4eef
+237, 0xbd25960b4b892e
+238, 0x911a199db6f1989d
+239, 0xfe822d7c601fd2e0
+240, 0x9b4c1d58d8223a69
+241, 0x907c1891283843b0
+242, 0xf4868bf54061c4b2
+243, 0x17f8cd1fc24efd85
+244, 0xd44253f9af14c3aa
+245, 0x16d0da0cb911d43c
+246, 0x3c6a46615828e79a
+247, 0x498591c1138e11a5
+248, 0xcc0f26336d0d6141
+249, 0x4d3ebc873212309a
+250, 0x16bad7792d5c2c6a
+251, 0x474215a80b2bbd11
+252, 0x7159848abd8492fc
+253, 0x359341c50973685f
+254, 0x27512ee7bf784a4a
+255, 0x45228ea080f70447
+256, 0x880cab616500d50e
+257, 0x12fae93f9830d56e
+258, 0x6744ee64348d9acd
+259, 0x484dada28cd2a828
+260, 0x98491d0729e41863
+261, 0x2f15aac43c2863b0
+262, 0x5727a34d77a1da0f
+263, 0xa435cebef6a62eed
+264, 0xd211697d57b053b0
+265, 0x65aa757b68bd557
+266, 0xe3a1b7a2d8a3e06a
+267, 0x2adf64e67252a7a9
+268, 0xadadcb75cadee276
+269, 0x7934bc57ac8d97bf
+270, 0xccff0d0f412e0606
+271, 0x101a82aa3e8f3db9
+272, 0xb0f2498094b4575c
+273, 0xba2561d9ef26ed8a
+274, 0xfbcd1268fc3febe1
+275, 0x9aa10bb19eb152e0
+276, 0xf496217a601a6d72
+277, 0xe4be1e4f2fa91363
+278, 0x473a602bf3dd68eb
+279, 0xfe8ed2a48c26f4b5
+280, 0x20e94b1a00159476
+281, 0x93e1cb1c6af86ec7
+282, 0x4fcba3898f7442ba
+283, 0x5150c3a3d94891df
+284, 0x91cfce6c85b033ea
+285, 0x625e8a832a806491
+286, 0x28c97ba72e3ec0b2
+287, 0x8e172de217c71ea1
+288, 0x926b80216c732639
+289, 0x28b19431a649ae3d
+290, 0x57c039a6e95a3795
+291, 0xfbc354182fe52718
+292, 0x819dfd7c7d534cef
+293, 0xabb4093a619ed44f
+294, 0xe785b7ac6f656745
+295, 0xb647b4588b2f942f
+296, 0x64cf870a14c72d27
+297, 0x6d4a4a2a0ba9b37e
+298, 0x78bfb0427d7ce6b0
+299, 0x8dcc72b8bfc79ac6
+300, 0x1c14d915d5e76c99
+301, 0xaf48ddea6f096d79
+302, 0x51b39b67aa130d8
+303, 0x1aeeb39d4def06de
+304, 0xd678092ffedfdd27
+305, 0x8f54787f325111d3
+306, 0xf2ca2e827beaa6bc
+307, 0x339d134099e98545
+308, 0x1f6a8a7b33942e43
+309, 0x952c8065dbef669a
+310, 0xe066aeb6690147f7
+311, 0xed25aa92cf58ebb6
+312, 0x7601edce215ef521
+313, 0xed1c5b396abd9434
+314, 0x4fd1e407535de9d5
+315, 0xccc8315a0d4d1441
+316, 0x85753e250bb86976
+317, 0xf232e469378761c3
+318, 0x81d691b8e9aef3c6
+319, 0x224a2f9cab0ad0e
+320, 0x978f3d3e50007f4e
+321, 0xd3713e6a6c0cbe60
+322, 0xcce8f1eadd41f80d
+323, 0x34bda028a97d469
+324, 0x90e242fdf0f59183
+325, 0x4d749754fbc5f092
+326, 0x4399f5b7851cc87b
+327, 0xcb921a5f25f6c5d7
+328, 0x120bf5d0162101
+329, 0x1304cc2aa352735a
+330, 0xf7236c5d0d5d417b
+331, 0xc31b320fc1654306
+332, 0xb468c6b23f3fb4e7
+333, 0xb5985b5bfaca4166
+334, 0x898285a1cd2f8375
+335, 0xa13493da372aa7c9
+336, 0x15c80c09c12634e7
+337, 0x9b765c5cc9d438bd
+338, 0xee7da816a9201dcb
+339, 0x92e269f73b5a248e
+340, 0xa8086c5de81400ce
+341, 0xe0053901853d42be
+342, 0x821df32c012f433e
+343, 0x17a6d69ca37387c7
+344, 0x2b10044bfba3501f
+345, 0x8dfd262afc2e8515
+346, 0xd68c2c7b60226371
+347, 0xe81ac114e4416774
+348, 0x5896d60061ebc471
+349, 0xa996e3147811dbd1
+350, 0xa819c7b80ecb3661
+351, 0x982ad71b38afbc01
+352, 0xab152b65aa17b7fe
+353, 0x4582bc282ef187ef
+354, 0xab5a17fe8d9bc669
+355, 0x83664fa9cb0284b7
+356, 0x234c4b0091968f52
+357, 0x8ab5f51805688d37
+358, 0xe9e11186e0c53eda
+359, 0x10df37ef1de2eccf
+360, 0x780f1b0d52db968f
+361, 0x50bd4ff292872cd5
+362, 0x51e681c265f5ad0
+363, 0x842c49660a527566
+364, 0x6e56ee026e9eda87
+365, 0x4cf39e40d8c80393
+366, 0x13e466df371f7e1f
+367, 0xf2ce1799f38e028e
+368, 0x833c8db7adc6ff0e
+369, 0xc6e189abc2ec98f
+370, 0xafebb3721283fec5
+371, 0xb49bc1eb5cc17bdc
+372, 0xf1d02e818f5e4488
+373, 0xe5e9d5b41a1dd815
+374, 0xce8aca6573b1bfe5
+375, 0x9b0a5d70e268b1d5
+376, 0xf3c0503a8358f4de
+377, 0x2681605dd755669d
+378, 0xea265ca7601efc70
+379, 0xa93747f0a159439f
+380, 0x62a86ede78a23e50
+381, 0xac8a18935c3d063c
+382, 0x729c0a298f5059f5
+383, 0xbbf195e5b54399f4
+384, 0x38aa9d551f968900
+385, 0x3b3e700c58778caa
+386, 0x68e6e33c4443957a
+387, 0x7c56fc13eb269815
+388, 0xaf7daca39711804a
+389, 0x50fde6d10f9544b3
+390, 0xf3d37159f6f6c03d
+391, 0x82d298f5c1a71685
+392, 0x478661ac54c5002c
+393, 0x6053768e1a324ae0
+394, 0xde8fb4a7e56707ea
+395, 0xaa2809301faa8cf4
+396, 0x690a8d49fedd0722
+397, 0xe17c481b9c217de9
+398, 0x60d1d8a2b57288e3
+399, 0x149adfaadc6b0886
+400, 0xa3c18b6eb79cd5fa
+401, 0x5774e3a091af5f58
+402, 0x2acca57ff30e5712
+403, 0x94454d67367c4b0c
+404, 0x581b2985ac2df5ca
+405, 0x71618e50744f3e70
+406, 0x270a7f3bd9a94ae6
+407, 0x3ef81af9bb36cd7b
+408, 0x8a4a2592875254aa
+409, 0x704ac6086fbb414a
+410, 0xda774d5d3f57414d
+411, 0xe20d3358b918ae9e
+412, 0x934a6b9f7b91e247
+413, 0xf91649cde87ec42c
+414, 0x248cec5f9b6ced30
+415, 0x56791809fd8d64ba
+416, 0xf502b2765c1395f
+417, 0x6b04ec973d75aa7f
+418, 0xb0339f2794bb26f
+419, 0x4c524636efbaea49
+420, 0x6bbf3876e9738748
+421, 0xf686524e754e9e24
+422, 0x8dafa05a42d19cd3
+423, 0xc5f069ab2434008e
+424, 0x4fd64cc713cba76
+425, 0xdbf93450c881ed5f
+426, 0x492e278ebabb59a2
+427, 0x993fddfde4542642
+428, 0xecde68a72c8d4e52
+429, 0xe0760b3074c311fd
+430, 0x68dc0e7e06528707
+431, 0x52b50edf49c0fdc7
+432, 0xb2bd4185c138f412
+433, 0x431496d7e1d86f3
+434, 0xa4e605b037e26c44
+435, 0x58236ae1f0aca2b5
+436, 0x26c72c420fc314d8
+437, 0x20134e982ab99a2b
+438, 0x544b59b8b211374b
+439, 0x1301c42f3a14d993
+440, 0x52a6ea740f763b0f
+441, 0xf209d70c2bebf119
+442, 0xac66a4ebc2aa1be
+443, 0x683713ed35878788
+444, 0x2b5578acec06b80c
+445, 0x86428efa11c45b36
+446, 0xb49010adb17d291e
+447, 0x73b686bd8664b6be
+448, 0x6d28ebf57b6884cc
+449, 0x9712091230ff58d9
+450, 0xc9c91f74c38b286
+451, 0x776310ac41dc008e
+452, 0x2f3739df0bf6a88e
+453, 0x5792dc62b94db675
+454, 0x5715910d024b06af
+455, 0xeb1dd745458da08
+456, 0xfce7b07ccfa851a7
+457, 0xc305f1e983ac368
+458, 0x485aa9519ac00bb0
+459, 0xa5354f6589fb0ea0
+460, 0x32fee02dfdbf4454
+461, 0x4d1ddc304bbefaaa
+462, 0x789a270a1737e57e
+463, 0x9f3072f4b1ed8156
+464, 0x4de3c00e89058120
+465, 0xb00a02529e0a86fa
+466, 0x539f6f0edd845d9a
+467, 0x85e578fe15a8c001
+468, 0xa12c8e1a72cce7d8
+469, 0xc6908abbc2b1828
+470, 0xcf70090774cbb38c
+471, 0x3b636a6977b45d4a
+472, 0xf0a731b220680b57
+473, 0x18973929f51443a8
+474, 0xe93e1fbe7eadabe
+475, 0x8233730f0a6dfa02
+476, 0x66e50b6919b0ab74
+477, 0xb1aba87c97fd08a2
+478, 0xd4dffc1fbc117ad6
+479, 0x6f7fa65724b96e6a
+480, 0x4bd5800dee92e0fa
+481, 0xe18a959db6256da
+482, 0xe53a291bc66df487
+483, 0xb7ec306a08651806
+484, 0x1847a6b80d2821e1
+485, 0xda50391283b14d39
+486, 0xacc4d3cd7cceb97a
+487, 0x57f70185165b7bc6
+488, 0x302b6d597c3aaba7
+489, 0xa47f32d037eab51e
+490, 0xe1509b4408abc559
+491, 0x4f30a1d7c2934157
+492, 0x2ad03e6c60b650b2
+493, 0x334d9c337b0a9064
+494, 0xc7f442821e7aac12
+495, 0xbcdeb09298694cdd
+496, 0xe42402389f8f0fb4
+497, 0xe5de56af539df727
+498, 0x7017f9b2101ee240
+499, 0x1ee5e68d5b10001d
+500, 0x436229051836387a
+501, 0xcd532d6d6ec38fb7
+502, 0x30a66606fdf38272
+503, 0xfdaa2ab9cf798496
+504, 0x4277b4adec70e7df
+505, 0x72cfc30256e0eaef
+506, 0x3c3359fd9bd34917
+507, 0xb7aa89598856efb0
+508, 0xf72226f8bf299ef5
+509, 0x258c499275a4356f
+510, 0x999a56bfc7f20d76
+511, 0x2b3e7432e20c18b
+512, 0x2d1251332f760cb5
+513, 0x7420e0eea62157c5
+514, 0xe85c895aa27cec3d
+515, 0x27a0545c7020d57c
+516, 0xc68638a65b4fff0d
+517, 0xfda473983a4ea747
+518, 0xd19fe65fb4c06062
+519, 0x6b1374e050ee15e4
+520, 0x80065ecd49bc4bef
+521, 0x4ee655954bc838de
+522, 0xe8fb777504a72299
+523, 0x86b652ea70f4bdde
+524, 0xcdc9e0fbde7e4f33
+525, 0x352c0a50cd3ac56
+526, 0x4b8605d368be75dc
+527, 0x1ac9ea8129efbc37
+528, 0x470325faa99f39c5
+529, 0x25dd7ef9adccf7a1
+530, 0x5ae2c7a03e965816
+531, 0xf733d2df59dacc7d
+532, 0xa05bbf0a8a1a7a70
+533, 0xe8aa3f102846ef5f
+534, 0xc9b85ec49ae71789
+535, 0xb904c14ed1cb1936
+536, 0x5ae618230b5f0444
+537, 0x97987fe47b5d7467
+538, 0xabb3aca8865ca761
+539, 0x38bfdf29d4508228
+540, 0x353654f408353330
+541, 0xeb7e92930ae4ef0d
+542, 0xec50f1a7ca526b96
+543, 0xd5e2dc08b5697544
+544, 0x24c7fd69d5ec32df
+545, 0x6f7e1095568b8620
+546, 0x6ed9c16ca13b3c8
+547, 0xe676ef460002130f
+548, 0xa3a01a3992c4b430
+549, 0xe2130406c3b1f202
+550, 0xa8f7263e2aedcd20
+551, 0xc45d71ef2e35f507
+552, 0x37155594021da7ba
+553, 0x22dc94f19de73159
+554, 0x7969fc6bffc5443f
+555, 0x97def7e44faa6bfe
+556, 0x8b940f5e8931d71f
+557, 0xd95b1dd3f1a3fdd5
+558, 0x1c83bfdca615701a
+559, 0xb7fcb56279ceca6b
+560, 0xd84f8950f20dcd0
+561, 0xb03343698de3cbe0
+562, 0xf64565d448d71f71
+563, 0xda52b4676e0ae662
+564, 0xda39c2c05b4ffb91
+565, 0xb35e2560421f6a85
+566, 0x1a7b108d48ac3646
+567, 0xc4e264dc390d79ed
+568, 0xa10727dfd9813256
+569, 0x40d23154e720e4f7
+570, 0xd9fa7cd7e313e119
+571, 0xcbf29107859e6013
+572, 0xc357338553d940b7
+573, 0x2641b7ab0bdfcbaa
+574, 0xd12f2b6060533ae7
+575, 0xd0435aa626411c56
+576, 0x44af4a488a9cec72
+577, 0xb934232ea8fa5696
+578, 0x760a8b12072b572d
+579, 0xfab18f9942cfa9b3
+580, 0x5676834c1fe84d16
+581, 0x9c54e4fddb353236
+582, 0xab49edfc9551f293
+583, 0x567f1fb45a871d
+584, 0x32a967c873998834
+585, 0x99240aad380ef8d1
+586, 0x7f66cbd432859a64
+587, 0x4cdc8a4658166822
+588, 0x984e3984a5766492
+589, 0xa3b2d0a3d64d3d94
+590, 0x177f667172f2affc
+591, 0xb1a90607a73a303f
+592, 0xe600b6c36427f878
+593, 0xf758f9834cb7f466
+594, 0x8ee9fce4a3f36449
+595, 0xcb8f11533e7da347
+596, 0xe7cf647794dabd7c
+597, 0xc9d92cfe6110806
+598, 0xea1335fa9145a1ec
+599, 0xbc6c29821d094552
+600, 0x37b9d6a858cc8bc3
+601, 0xf24e4c694929893e
+602, 0x55d025ce2d7d0004
+603, 0xccdc69acccf4267b
+604, 0xc491c04340c222eb
+605, 0xba50f75ecec9befb
+606, 0x1ec7bd85b8fe3bb9
+607, 0xe4de66498c59ae8a
+608, 0x38aa9e912712c889
+609, 0xcee0e43c5cc31566
+610, 0x72b69aa708fc7ed
+611, 0xdff70b7f6fa96679
+612, 0xd6d71d82112aadc3
+613, 0x365177892cb78531
+614, 0xa54852b39de4f72c
+615, 0x11dd5832bf16dd59
+616, 0x248a0f3369c97097
+617, 0xa14cec0260e26792
+618, 0x3517616ff142bed1
+619, 0x9b693ad39dab7636
+620, 0x739dff825e994434
+621, 0x67711e7356098c9
+622, 0xa81f8515d2fdf458
+623, 0xdac2908113fe568e
+624, 0xe99944ebc6e2806a
+625, 0x671728ca5b030975
+626, 0xfdad20edb2b4a789
+627, 0xedc6e466bd0369d2
+628, 0x88b5d469821f7e1b
+629, 0x2eabf94049a522a5
+630, 0x247794b7a2f5a8e3
+631, 0x278942bdbe02c649
+632, 0xbe5a9a9196ab99c1
+633, 0x75955060866da1b5
+634, 0xdedcfa149273c0b5
+635, 0xdbeb7a57758f3867
+636, 0x7b9053347a2c8d5a
+637, 0xa059b3f2eed338a5
+638, 0x59401a46ded3b79f
+639, 0x38044ba56a6d19fb
+640, 0x72c7221b4e77e779
+641, 0x526df3491a3a34da
+642, 0xc3b31184ba16c0c2
+643, 0xd94c7144488624af
+644, 0xcf966ee4dc373f91
+645, 0x62049e65dd416266
+646, 0x7c2adccb925bf8f
+647, 0xd5fa5c22ed4ef8e1
+648, 0xd00134ebd11f2cd1
+649, 0xfbdf81767bed3634
+650, 0x62e8cc8ff66b6e26
+651, 0x3a72d6bcd4f2dcf7
+652, 0xf1cd45b1b46a86ed
+653, 0x1271f98e0938bb9a
+654, 0x82e6927e83dc31fa
+655, 0x7b9b0e0acb67b92d
+656, 0x6df503e397b2e701
+657, 0x93888f6fb561e0c3
+658, 0x393fb6069a40291
+659, 0x967a7d894cc0754d
+660, 0x6e298996ad866333
+661, 0x5ff3cf5559d6ab46
+662, 0xd0d70508c40349f5
+663, 0xc64c66c0dd426b33
+664, 0x8fea340ee35c64dd
+665, 0xf9cd381eb3060005
+666, 0xfcc37c2799fc0b11
+667, 0x6a37c91d65b489fa
+668, 0x57231000fa0a0c9d
+669, 0x55f6e292c6703f9a
+670, 0xd0508ffbfa55a7a6
+671, 0x885db543276bdac8
+672, 0xc26dbe6a26b0e704
+673, 0x21f884874ebd709e
+674, 0x711f0b6c8f732220
+675, 0x354d0a361eaee195
+676, 0x721344d8d30b006a
+677, 0xa0e090a0d3a56f07
+678, 0x16b3d5d823a4952b
+679, 0x59d7874bc9eae7b6
+680, 0x9bbb32710076455f
+681, 0xd4fb22242ffabafd
+682, 0xe1d4ac6770be1d89
+683, 0xb259cedebc73dc8a
+684, 0x35faaa3b4246ab69
+685, 0x5d26addefdaee89
+686, 0x8e7ec350da0f3545
+687, 0xd0f316eed9f8fc79
+688, 0x98b2a52c9bf291b2
+689, 0xe4d294a8aca6a314
+690, 0x25bd554e6aa7673c
+691, 0xcfde5dcba5be2a6c
+692, 0xb5e01fb48d2d2107
+693, 0xe1caf28948028536
+694, 0xd434aa0a26f3ee9b
+695, 0xd17723381641b8f6
+696, 0xfe73bd1f3f3768a2
+697, 0x1cc6b1abd08d67e9
+698, 0x247e328371a28de0
+699, 0x502e7942e5a9104a
+700, 0x6a030fd242eb4502
+701, 0xa2ffe02744014ce8
+702, 0x59290763b18fe04e
+703, 0xcf14241564271436
+704, 0xb0fb73c3c1503aff
+705, 0x94e27c622f82137a
+706, 0x747a5b406ac3e1f0
+707, 0x9a914e96a732031d
+708, 0x59f68c6c8f078835
+709, 0x809d012c73eb4724
+710, 0x5b3c3b73e1b37d74
+711, 0xdde60ef3ba49cdf7
+712, 0x87a14e1f9c761986
+713, 0x4109b960604522af
+714, 0x122d0e1ed0eb6bb9
+715, 0xadc0d29e80bfe33
+716, 0xa25b1b44f5fc8e4e
+717, 0xbab85d8a9b793f20
+718, 0x825f4cbced0e7d1e
+719, 0x2d6ae8807acb37ea
+720, 0x8234420adce2e39
+721, 0x4a8ad4da6b804807
+722, 0x1e19f9bc215e5245
+723, 0x1d6f4848a916dd5e
+724, 0x9ac40dfcdc2d39cc
+725, 0x9f3524e3086155ec
+726, 0x861fffc43124b2ef
+727, 0xe640e3b756396372
+728, 0x41cb0f0c5e149669
+729, 0xe0bd37e1192e4205
+730, 0x62917d3858f4ce47
+731, 0xa36e7eb4d855820a
+732, 0x204b90255a3bf724
+733, 0x66ee83a0175535bc
+734, 0x2c14ce7c6b0c1423
+735, 0x85d9495fa514f70d
+736, 0x5a4fe45ead874dbc
+737, 0xe72248dcb8cfc863
+738, 0xfc21ff2932ed98cd
+739, 0xcbba1edd735b5cad
+740, 0x91ddc32809679bf5
+741, 0x192cdf2c7631ea1f
+742, 0xbbc451ddf2ea286f
+743, 0xad9e80cae2397a64
+744, 0x6918f0119b95d0e5
+745, 0xa40379017a27d70a
+746, 0x1aaeddb600e61e1
+747, 0x15afd93cbd7adda9
+748, 0x156719bc2b757ff4
+749, 0x13d9a59e2b2df49d
+750, 0x9a490986eaddf0a
+751, 0xef9a350f0b3eb6b4
+752, 0x5de7f6295ba4fa4d
+753, 0x7f37fd087c3fdb49
+754, 0xa9fe3749d6f3f209
+755, 0x50912ac036d9bfb
+756, 0x982cb4d726a441f8
+757, 0x8ca8d8af59b872d0
+758, 0x7f8adfb0ceeade8a
+759, 0xdad390ec742be44
+760, 0xa637944d0045be5b
+761, 0x3569a3b3af807061
+762, 0x9599da8eae14511d
+763, 0xc333e8d19589b01a
+764, 0xfb9b524a20b571e1
+765, 0xbd9dc8b37ce5c3e1
+766, 0x142333005fa389ac
+767, 0x1368bc37cd5bcce1
+768, 0x16094907ad6ecf73
+769, 0xb32c90dbba4c1130
+770, 0x82761d97c1747dd0
+771, 0x599f9f267ae3444d
+772, 0x79ad3382994852e1
+773, 0x2511f06d9ef06e54
+774, 0xb35e6ab7d5bbddae
+775, 0xfca9fa83a2988732
+776, 0x7d4350f0394ac3ba
+777, 0xa52a9527bb176ea3
+778, 0xb49fa0ceb2aa8353
+779, 0x1f62e504d1468cc0
+780, 0xe1a77bfccce6efc3
+781, 0x776cdff4dc0d6797
+782, 0x56612e39b652c1f2
+783, 0x5f096a29294eda04
+784, 0x7978abc3aabd8b23
+785, 0x79dd875e0485b979
+786, 0x8a98aa4d5735d778
+787, 0xcca43940f69d2388
+788, 0xb2d4b156f144f93a
+789, 0xbd528a676e9a862
+790, 0x2a394939c8e7ec5e
+791, 0xb1da900c6efe4abc
+792, 0x9869af479de4c034
+793, 0x78dbdfb88ac7c1db
+794, 0x18cb169143088041
+795, 0xe69e5461c51a3e13
+796, 0x5389fa16ea98183c
+797, 0xed7c80d1be1ea520
+798, 0x87246fc359758ced
+799, 0xab323eba95fae4ed
+800, 0xbc4c0dde7f8a1828
+801, 0xdb739f7955610b1a
+802, 0xecd8c68c3434cc
+803, 0x138c2eb88c477f44
+804, 0x28a65f96727aae41
+805, 0xdee879f2cf5629d
+806, 0x684f0c90ef20070f
+807, 0xa24a819ef5621800
+808, 0x8d0054f870e4fdcb
+809, 0x99e8c6e695b600b
+810, 0x50b705245891f7c3
+811, 0xc02eed3a6e58e51a
+812, 0x443d64e95443606c
+813, 0xca24959cfbd2d120
+814, 0xe072609ea48815bc
+815, 0xbcc715026590315b
+816, 0x3e76df24d7aa5938
+817, 0xd8ff04940d9b79ae
+818, 0x54474ce790059bcd
+819, 0x278390dd6aa70e81
+820, 0xf4df619fe35414e4
+821, 0x757d71270264e615
+822, 0x1e8a373699c11b23
+823, 0xef68c82046e67dd6
+824, 0xe280006599972620
+825, 0x234e095183b0f4d6
+826, 0xe3b7560ed9839749
+827, 0xcd5ec4086572332e
+828, 0xc41c0d4aaa279108
+829, 0x4b9cd6126bc16a6d
+830, 0x4a7252734f3e3dd0
+831, 0xb3132df156cc103a
+832, 0xf9e4abbf7b64464a
+833, 0xf936df27fb3c47b7
+834, 0x9142960873f6d71a
+835, 0x4ba6aa3235cdb10d
+836, 0x3237a2e765ba7766
+837, 0xd62f0b94c8e99e54
+838, 0x26b682f90a3ae41b
+839, 0x40ad5e82072b6f81
+840, 0xd0198101f5484000
+841, 0xe4fac60ba11c332
+842, 0x472d0b0a95ef9d38
+843, 0x8512557aec5a3d8f
+844, 0xef83169d3efd4de9
+845, 0x53fe89283e7a7676
+846, 0x2f50933053d69fc4
+847, 0x76f5e4362e2e53a2
+848, 0x8676fdccce28874a
+849, 0x2737764c1fb1f821
+850, 0x4a6f70afc066ab55
+851, 0x27f8e151e310fca4
+852, 0xd606960ccbe85161
+853, 0xcce51d7ddd270a32
+854, 0xb4235999794875c2
+855, 0x580084e358e884
+856, 0x2159d5e6dc8586d7
+857, 0x87bd54d8599b3ba4
+858, 0x3e9ade6a2181664
+859, 0x5e6e140406d97623
+860, 0x511545d5aa0080a2
+861, 0xf49d78ed219aac57
+862, 0xbece1f9c90b8ea87
+863, 0x1c741cac36a2c514
+864, 0x7453c141047db967
+865, 0xd751832a5037eba2
+866, 0x71370a3f30ada1f7
+867, 0x7c01cf2dcb408631
+868, 0x1052a4fbdccc0fa1
+869, 0x13d525c9df3fb6c
+870, 0xa3aa8dbfee760c55
+871, 0xc0288d200f5155cf
+872, 0x79f4bcd12af567c3
+873, 0x8160d163bb548755
+874, 0x5cf2995fb69fd2df
+875, 0xcc98ed01396639df
+876, 0xad95f1d9cfc8256e
+877, 0xa3df27d9fbdbfb9d
+878, 0x83e5f5dda4d52929
+879, 0x9adc05043009f55b
+880, 0xdfe8329dfde1c001
+881, 0x9980ccdd5298e6a2
+882, 0x636a7bd134f6ef56
+883, 0xef5ff780c4be6ba4
+884, 0x290d71dc77a56d16
+885, 0x6d65db9ff58de1e6
+886, 0x944b063b3805a696
+887, 0xce468ca2cce33008
+888, 0x5ba1ccb840f80f48
+889, 0x28ddce36fc9ad268
+890, 0x4f77ef254d507a21
+891, 0xce9b4057fadf3ab
+892, 0xb518bc68298730e6
+893, 0xd2eb5b8e2ec665b0
+894, 0xe1583303a4f87344
+895, 0x9d5a0df4fbe1bed5
+896, 0x2ba9bc03ec8cfd07
+897, 0x479ed880a96ca669
+898, 0xcedf96338324771a
+899, 0x312f4fc2da41ffaa
+900, 0xa0eb9cf23b5e1ed8
+901, 0xf8f88f975dc3f539
+902, 0x4a37e185d0e96e0f
+903, 0xf829654a5c0b46f9
+904, 0x3909cca7a7f8c7fb
+905, 0x4c2e1d66ceb45105
+906, 0xaffaa19e1db8af87
+907, 0x9ec498246bd18c76
+908, 0x21d51558edc089da
+909, 0xe8984112cd1b1561
+910, 0x7de1d2cf54b0c0e1
+911, 0xa06729aed50bfb9d
+912, 0xcf19f733e5db19e1
+913, 0x70edf2624ab777cd
+914, 0x46685becad10e078
+915, 0x825e0f6add46785
+916, 0x66d4af3b15f70de4
+917, 0xc676614b0666b21
+918, 0x282a916c864f5cb7
+919, 0x2707283a3f512167
+920, 0x37ff3afda7461623
+921, 0xc767eb1205e4ca86
+922, 0x46b359aecc4ea25b
+923, 0x67fbbb797a16dbb1
+924, 0x64fd4ba57122290e
+925, 0x8acc2a8ae59d8fac
+926, 0x64a49298599acc67
+927, 0xedf00de67177ce30
+928, 0x1ea9d8d7e76d2d2c
+929, 0x363fcac323f70eb2
+930, 0x19e6e3ec8a9712eb
+931, 0xca541e96b0961f09
+932, 0x4d8fd34c2822ec46
+933, 0x2fdd56a50b32f705
+934, 0xaac2fcf251e3fd3
+935, 0xb0c600299e57045c
+936, 0xd951ec589e909e38
+937, 0x4dc8414390cae508
+938, 0x537ef9d5e2321344
+939, 0xa57bc21fd31aa2dc
+940, 0xa3a60df564183750
+941, 0xbe69a5ce2e369fb6
+942, 0x7744601f4c053ec8
+943, 0x3838452af42f2612
+944, 0xd4f0dad7115a54e9
+945, 0x629cf68d8009a624
+946, 0x2211c8fa34cb98cb
+947, 0x8040b19e2213db83
+948, 0xb2a86d3ba2384fd
+949, 0x4b85cec4f93f0dab
+950, 0xc8d212d21ea6845d
+951, 0x5b271a03a4fe2be0
+952, 0xff4f671319ad8434
+953, 0x8e615a919d5afa96
+954, 0xea7f47c53161160a
+955, 0x33273930b13c6efc
+956, 0x98eedda27fb59c3c
+957, 0x188dc5e92e939677
+958, 0x9dbd0fa0911430f1
+959, 0x5b3dcf3fa75dfd2b
+960, 0x3f03846febdb275d
+961, 0x20cc24faea9e9cf6
+962, 0x854f3ac66199ff5d
+963, 0x31169ac99d341e6f
+964, 0xa85daed3c0bc1bbe
+965, 0x64633711e71ba5dd
+966, 0x530e79978dc73334
+967, 0x636f2ee6e20aef13
+968, 0xf6220f8b6d9a58fb
+969, 0x425db8fa32141a7b
+970, 0xac7c210f4b02be95
+971, 0x5fe8cfbe197a7754
+972, 0xfff7d40c79420ea
+973, 0x5f8bab9ef4697b77
+974, 0xaf6fe54e45b23fe8
+975, 0xce79456ccc70bbce
+976, 0x645ef680f48f1c00
+977, 0xa4dfac46e2028595
+978, 0x6bece4c41effc5df
+979, 0xd316df886442641f
+980, 0xa4f6ff994edd2a6
+981, 0x30281ae3cc49abe4
+982, 0x39acb7b663dea974
+983, 0x5e8829b01a7c06fb
+984, 0x87bdb08cf027f13e
+985, 0xdfa5ede784e802f6
+986, 0x46d03d55711c38cc
+987, 0xa55a961fc9788306
+988, 0xbf09ded495a2e57a
+989, 0xcd601b29a639cc16
+990, 0x2193ce026bfd1085
+991, 0x25ba27f3f225be13
+992, 0x6f685be82f64f2fe
+993, 0xec8454108229c450
+994, 0x6e79d8d205447a44
+995, 0x9ed7b6a96b9ccd68
+996, 0xae7134b3b7f8ee37
+997, 0x66963de0e5ebcc02
+998, 0x29c8dcd0d17c423f
+999, 0xfb8482c827eb90bc
diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py
new file mode 100644
index 000000000..0f57c4bd4
--- /dev/null
+++ b/numpy/random/tests/test_direct.py
@@ -0,0 +1,418 @@
+import os
+from os.path import join
+
+import numpy as np
+from numpy.testing import (assert_equal, assert_allclose, assert_array_equal,
+ assert_raises)
+import pytest
+
+from numpy.random import (
+ Generator, MT19937, PCG64, Philox, RandomState, SeedSequence, SFC64,
+ default_rng
+)
+from numpy.random.common import interface
+
+try:
+ import cffi # noqa: F401
+
+ MISSING_CFFI = False
+except ImportError:
+ MISSING_CFFI = True
+
+try:
+ import ctypes # noqa: F401
+
+ MISSING_CTYPES = False
+except ImportError:
+ MISSING_CTYPES = False
+
+pwd = os.path.dirname(os.path.abspath(__file__))
+
+
+def assert_state_equal(actual, target):
+ for key in actual:
+ if isinstance(actual[key], dict):
+ assert_state_equal(actual[key], target[key])
+ elif isinstance(actual[key], np.ndarray):
+ assert_array_equal(actual[key], target[key])
+ else:
+ assert actual[key] == target[key]
+
+
+def uniform32_from_uint64(x):
+ x = np.uint64(x)
+ upper = np.array(x >> np.uint64(32), dtype=np.uint32)
+ lower = np.uint64(0xffffffff)
+ lower = np.array(x & lower, dtype=np.uint32)
+ joined = np.column_stack([lower, upper]).ravel()
+ out = (joined >> np.uint32(9)) * (1.0 / 2 ** 23)
+ return out.astype(np.float32)
+
+
+def uniform32_from_uint53(x):
+ x = np.uint64(x) >> np.uint64(16)
+ x = np.uint32(x & np.uint64(0xffffffff))
+ out = (x >> np.uint32(9)) * (1.0 / 2 ** 23)
+ return out.astype(np.float32)
+
+
+def uniform32_from_uint32(x):
+ return (x >> np.uint32(9)) * (1.0 / 2 ** 23)
+
+
+def uniform32_from_uint(x, bits):
+ if bits == 64:
+ return uniform32_from_uint64(x)
+ elif bits == 53:
+ return uniform32_from_uint53(x)
+ elif bits == 32:
+ return uniform32_from_uint32(x)
+ else:
+ raise NotImplementedError
+
+
+def uniform_from_uint(x, bits):
+ if bits in (64, 63, 53):
+ return uniform_from_uint64(x)
+ elif bits == 32:
+ return uniform_from_uint32(x)
+
+
+def uniform_from_uint64(x):
+ return (x >> np.uint64(11)) * (1.0 / 9007199254740992.0)
+
+
+def uniform_from_uint32(x):
+ out = np.empty(len(x) // 2)
+ for i in range(0, len(x), 2):
+ a = x[i] >> 5
+ b = x[i + 1] >> 6
+ out[i // 2] = (a * 67108864.0 + b) / 9007199254740992.0
+ return out
+
+
+def uniform_from_dsfmt(x):
+ return x.view(np.double) - 1.0
+
+
+def gauss_from_uint(x, n, bits):
+ if bits in (64, 63):
+ doubles = uniform_from_uint64(x)
+ elif bits == 32:
+ doubles = uniform_from_uint32(x)
+ else: # bits == 'dsfmt'
+ doubles = uniform_from_dsfmt(x)
+ gauss = []
+ loc = 0
+ x1 = x2 = 0.0
+ while len(gauss) < n:
+ r2 = 2
+ while r2 >= 1.0 or r2 == 0.0:
+ x1 = 2.0 * doubles[loc] - 1.0
+ x2 = 2.0 * doubles[loc + 1] - 1.0
+ r2 = x1 * x1 + x2 * x2
+ loc += 2
+
+ f = np.sqrt(-2.0 * np.log(r2) / r2)
+ gauss.append(f * x2)
+ gauss.append(f * x1)
+
+ return gauss[:n]
+
+def test_seedsequence():
+ from numpy.random.bit_generator import (ISeedSequence,
+ ISpawnableSeedSequence,
+ SeedlessSeedSequence)
+
+ s1 = SeedSequence(range(10), spawn_key=(1, 2), pool_size=6)
+ s1.spawn(10)
+ s2 = SeedSequence(**s1.state)
+ assert_equal(s1.state, s2.state)
+ assert_equal(s1.n_children_spawned, s2.n_children_spawned)
+
+ # The interfaces cannot be instantiated themselves.
+ assert_raises(TypeError, ISeedSequence)
+ assert_raises(TypeError, ISpawnableSeedSequence)
+ dummy = SeedlessSeedSequence()
+ assert_raises(NotImplementedError, dummy.generate_state, 10)
+ assert len(dummy.spawn(10)) == 10
+
+
+class Base(object):
+ dtype = np.uint64
+ data2 = data1 = {}
+
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = PCG64
+ cls.bits = 64
+ cls.dtype = np.uint64
+ cls.seed_error_type = TypeError
+ cls.invalid_init_types = []
+ cls.invalid_init_values = []
+
+ @classmethod
+ def _read_csv(cls, filename):
+ with open(filename) as csv:
+ seed = csv.readline()
+ seed = seed.split(',')
+ seed = [int(s.strip(), 0) for s in seed[1:]]
+ data = []
+ for line in csv:
+ data.append(int(line.split(',')[-1].strip(), 0))
+ return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)}
+
+ def test_raw(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ uints = bit_generator.random_raw(1000)
+ assert_equal(uints, self.data1['data'])
+
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ uints = bit_generator.random_raw()
+ assert_equal(uints, self.data1['data'][0])
+
+ bit_generator = self.bit_generator(*self.data2['seed'])
+ uints = bit_generator.random_raw(1000)
+ assert_equal(uints, self.data2['data'])
+
+ def test_random_raw(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ uints = bit_generator.random_raw(output=False)
+ assert uints is None
+ uints = bit_generator.random_raw(1000, output=False)
+ assert uints is None
+
+ def test_gauss_inv(self):
+ n = 25
+ rs = RandomState(self.bit_generator(*self.data1['seed']))
+ gauss = rs.standard_normal(n)
+ assert_allclose(gauss,
+ gauss_from_uint(self.data1['data'], n, self.bits))
+
+ rs = RandomState(self.bit_generator(*self.data2['seed']))
+ gauss = rs.standard_normal(25)
+ assert_allclose(gauss,
+ gauss_from_uint(self.data2['data'], n, self.bits))
+
+ def test_uniform_double(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ vals = uniform_from_uint(self.data1['data'], self.bits)
+ uniforms = rs.random(len(vals))
+ assert_allclose(uniforms, vals)
+ assert_equal(uniforms.dtype, np.float64)
+
+ rs = Generator(self.bit_generator(*self.data2['seed']))
+ vals = uniform_from_uint(self.data2['data'], self.bits)
+ uniforms = rs.random(len(vals))
+ assert_allclose(uniforms, vals)
+ assert_equal(uniforms.dtype, np.float64)
+
+ def test_uniform_float(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ vals = uniform32_from_uint(self.data1['data'], self.bits)
+ uniforms = rs.random(len(vals), dtype=np.float32)
+ assert_allclose(uniforms, vals)
+ assert_equal(uniforms.dtype, np.float32)
+
+ rs = Generator(self.bit_generator(*self.data2['seed']))
+ vals = uniform32_from_uint(self.data2['data'], self.bits)
+ uniforms = rs.random(len(vals), dtype=np.float32)
+ assert_allclose(uniforms, vals)
+ assert_equal(uniforms.dtype, np.float32)
+
+ def test_repr(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ assert 'Generator' in repr(rs)
+ assert '{:#x}'.format(id(rs)).upper().replace('X', 'x') in repr(rs)
+
+ def test_str(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ assert 'Generator' in str(rs)
+ assert str(self.bit_generator.__name__) in str(rs)
+ assert '{:#x}'.format(id(rs)).upper().replace('X', 'x') not in str(rs)
+
+ def test_pickle(self):
+ import pickle
+
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ state = bit_generator.state
+ bitgen_pkl = pickle.dumps(bit_generator)
+ reloaded = pickle.loads(bitgen_pkl)
+ reloaded_state = reloaded.state
+ assert_array_equal(Generator(bit_generator).standard_normal(1000),
+ Generator(reloaded).standard_normal(1000))
+ assert bit_generator is not reloaded
+ assert_state_equal(reloaded_state, state)
+
+ ss = SeedSequence(100)
+ aa = pickle.loads(pickle.dumps(ss))
+ assert_equal(ss.state, aa.state)
+
+ def test_invalid_state_type(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ with pytest.raises(TypeError):
+ bit_generator.state = {'1'}
+
+ def test_invalid_state_value(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ state = bit_generator.state
+ state['bit_generator'] = 'otherBitGenerator'
+ with pytest.raises(ValueError):
+ bit_generator.state = state
+
+ def test_invalid_init_type(self):
+ bit_generator = self.bit_generator
+ for st in self.invalid_init_types:
+ with pytest.raises(TypeError):
+ bit_generator(*st)
+
+ def test_invalid_init_values(self):
+ bit_generator = self.bit_generator
+ for st in self.invalid_init_values:
+ with pytest.raises((ValueError, OverflowError)):
+ bit_generator(*st)
+
+ def test_benchmark(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ bit_generator._benchmark(1)
+ bit_generator._benchmark(1, 'double')
+ with pytest.raises(ValueError):
+ bit_generator._benchmark(1, 'int32')
+
+ @pytest.mark.skipif(MISSING_CFFI, reason='cffi not available')
+ def test_cffi(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ cffi_interface = bit_generator.cffi
+ assert isinstance(cffi_interface, interface)
+ other_cffi_interface = bit_generator.cffi
+ assert other_cffi_interface is cffi_interface
+
+ @pytest.mark.skipif(MISSING_CTYPES, reason='ctypes not available')
+ def test_ctypes(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ ctypes_interface = bit_generator.ctypes
+ assert isinstance(ctypes_interface, interface)
+ other_ctypes_interface = bit_generator.ctypes
+ assert other_ctypes_interface is ctypes_interface
+
+ def test_getstate(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ state = bit_generator.state
+ alt_state = bit_generator.__getstate__()
+ assert_state_equal(state, alt_state)
+
+
+class TestPhilox(Base):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = Philox
+ cls.bits = 64
+ cls.dtype = np.uint64
+ cls.data1 = cls._read_csv(
+ join(pwd, './data/philox-testset-1.csv'))
+ cls.data2 = cls._read_csv(
+ join(pwd, './data/philox-testset-2.csv'))
+ cls.seed_error_type = TypeError
+ cls.invalid_init_types = []
+ cls.invalid_init_values = [(1, None, 1), (-1,), (None, None, 2 ** 257 + 1)]
+
+ def test_set_key(self):
+ bit_generator = self.bit_generator(*self.data1['seed'])
+ state = bit_generator.state
+ keyed = self.bit_generator(counter=state['state']['counter'],
+ key=state['state']['key'])
+ assert_state_equal(bit_generator.state, keyed.state)
+
+
+class TestPCG64(Base):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = PCG64
+ cls.bits = 64
+ cls.dtype = np.uint64
+ cls.data1 = cls._read_csv(join(pwd, './data/pcg64-testset-1.csv'))
+ cls.data2 = cls._read_csv(join(pwd, './data/pcg64-testset-2.csv'))
+ cls.seed_error_type = (ValueError, TypeError)
+ cls.invalid_init_types = [(3.2,), ([None],), (1, None)]
+ cls.invalid_init_values = [(-1,)]
+
+ def test_advance_symmetry(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ state = rs.bit_generator.state
+ step = -0x9e3779b97f4a7c150000000000000000
+ rs.bit_generator.advance(step)
+ val_neg = rs.integers(10)
+ rs.bit_generator.state = state
+ rs.bit_generator.advance(2**128 + step)
+ val_pos = rs.integers(10)
+ rs.bit_generator.state = state
+ rs.bit_generator.advance(10 * 2**128 + step)
+ val_big = rs.integers(10)
+ assert val_neg == val_pos
+ assert val_big == val_pos
+
+
+class TestMT19937(Base):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = MT19937
+ cls.bits = 32
+ cls.dtype = np.uint32
+ cls.data1 = cls._read_csv(join(pwd, './data/mt19937-testset-1.csv'))
+ cls.data2 = cls._read_csv(join(pwd, './data/mt19937-testset-2.csv'))
+ cls.seed_error_type = ValueError
+ cls.invalid_init_types = []
+ cls.invalid_init_values = [(-1,)]
+
+ def test_seed_float_array(self):
+ assert_raises(TypeError, self.bit_generator, np.array([np.pi]))
+ assert_raises(TypeError, self.bit_generator, np.array([-np.pi]))
+ assert_raises(TypeError, self.bit_generator, np.array([np.pi, -np.pi]))
+ assert_raises(TypeError, self.bit_generator, np.array([0, np.pi]))
+ assert_raises(TypeError, self.bit_generator, [np.pi])
+ assert_raises(TypeError, self.bit_generator, [0, np.pi])
+
+ def test_state_tuple(self):
+ rs = Generator(self.bit_generator(*self.data1['seed']))
+ bit_generator = rs.bit_generator
+ state = bit_generator.state
+ desired = rs.integers(2 ** 16)
+ tup = (state['bit_generator'], state['state']['key'],
+ state['state']['pos'])
+ bit_generator.state = tup
+ actual = rs.integers(2 ** 16)
+ assert_equal(actual, desired)
+ tup = tup + (0, 0.0)
+ bit_generator.state = tup
+ actual = rs.integers(2 ** 16)
+ assert_equal(actual, desired)
+
+
+class TestSFC64(Base):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = SFC64
+ cls.bits = 64
+ cls.dtype = np.uint64
+ cls.data1 = cls._read_csv(
+ join(pwd, './data/sfc64-testset-1.csv'))
+ cls.data2 = cls._read_csv(
+ join(pwd, './data/sfc64-testset-2.csv'))
+ cls.seed_error_type = (ValueError, TypeError)
+ cls.invalid_init_types = [(3.2,), ([None],), (1, None)]
+ cls.invalid_init_values = [(-1,)]
+
+
+class TestDefaultRNG(object):
+ def test_seed(self):
+ for args in [(), (None,), (1234,), ([1234, 5678],)]:
+ rg = default_rng(*args)
+ assert isinstance(rg.bit_generator, PCG64)
+
+ def test_passthrough(self):
+ bg = Philox()
+ rg = default_rng(bg)
+ assert rg.bit_generator is bg
+ rg2 = default_rng(rg)
+ assert rg2 is rg
+ assert rg2.bit_generator is bg
diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py
new file mode 100644
index 000000000..a962fe84e
--- /dev/null
+++ b/numpy/random/tests/test_generator_mt19937.py
@@ -0,0 +1,2018 @@
+import sys
+
+import pytest
+
+import numpy as np
+from numpy.testing import (
+ assert_, assert_raises, assert_equal,
+ assert_warns, assert_no_warnings, assert_array_equal,
+ assert_array_almost_equal, suppress_warnings)
+
+from numpy.random import Generator, MT19937, SeedSequence
+
+random = Generator(MT19937())
+
+
+@pytest.fixture(scope='module', params=[True, False])
+def endpoint(request):
+ return request.param
+
+
+class TestSeed(object):
+ def test_scalar(self):
+ s = Generator(MT19937(0))
+ assert_equal(s.integers(1000), 479)
+ s = Generator(MT19937(4294967295))
+ assert_equal(s.integers(1000), 324)
+
+ def test_array(self):
+ s = Generator(MT19937(range(10)))
+ assert_equal(s.integers(1000), 465)
+ s = Generator(MT19937(np.arange(10)))
+ assert_equal(s.integers(1000), 465)
+ s = Generator(MT19937([0]))
+ assert_equal(s.integers(1000), 479)
+ s = Generator(MT19937([4294967295]))
+ assert_equal(s.integers(1000), 324)
+
+ def test_seedsequence(self):
+ s = MT19937(SeedSequence(0))
+ assert_equal(s.random_raw(1), 2058676884)
+
+ def test_invalid_scalar(self):
+ # seed must be an unsigned 32 bit integer
+ assert_raises(TypeError, MT19937, -0.5)
+ assert_raises(ValueError, MT19937, -1)
+
+ def test_invalid_array(self):
+ # seed must be an unsigned integer
+ assert_raises(TypeError, MT19937, [-0.5])
+ assert_raises(ValueError, MT19937, [-1])
+ assert_raises(ValueError, MT19937, [1, -2, 4294967296])
+
+ def test_noninstantized_bitgen(self):
+ assert_raises(ValueError, Generator, MT19937)
+
+
+class TestBinomial(object):
+ def test_n_zero(self):
+ # Tests the corner case of n == 0 for the binomial distribution.
+ # binomial(0, p) should be zero for any p in [0, 1].
+ # This test addresses issue #3480.
+ zeros = np.zeros(2, dtype='int')
+ for p in [0, .5, 1]:
+ assert_(random.binomial(0, p) == 0)
+ assert_array_equal(random.binomial(zeros, p), zeros)
+
+ def test_p_is_nan(self):
+ # Issue #4571.
+ assert_raises(ValueError, random.binomial, 1, np.nan)
+
+
+class TestMultinomial(object):
+ def test_basic(self):
+ random.multinomial(100, [0.2, 0.8])
+
+ def test_zero_probability(self):
+ random.multinomial(100, [0.2, 0.8, 0.0, 0.0, 0.0])
+
+ def test_int_negative_interval(self):
+ assert_(-5 <= random.integers(-5, -1) < -1)
+ x = random.integers(-5, -1, 5)
+ assert_(np.all(-5 <= x))
+ assert_(np.all(x < -1))
+
+ def test_size(self):
+ # gh-3173
+ p = [0.5, 0.5]
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, [2, 2]).shape, (2, 2, 2))
+ assert_equal(random.multinomial(1, p, (2, 2)).shape, (2, 2, 2))
+ assert_equal(random.multinomial(1, p, np.array((2, 2))).shape,
+ (2, 2, 2))
+
+ assert_raises(TypeError, random.multinomial, 1, p,
+ float(1))
+
+ def test_invalid_prob(self):
+ assert_raises(ValueError, random.multinomial, 100, [1.1, 0.2])
+ assert_raises(ValueError, random.multinomial, 100, [-.1, 0.9])
+
+ def test_invalid_n(self):
+ assert_raises(ValueError, random.multinomial, -1, [0.8, 0.2])
+ assert_raises(ValueError, random.multinomial, [-1] * 10, [0.8, 0.2])
+
+ def test_p_non_contiguous(self):
+ p = np.arange(15.)
+ p /= np.sum(p[1::3])
+ pvals = p[1::3]
+ random = Generator(MT19937(1432985819))
+ non_contig = random.multinomial(100, pvals=pvals)
+ random = Generator(MT19937(1432985819))
+ contig = random.multinomial(100, pvals=np.ascontiguousarray(pvals))
+ assert_array_equal(non_contig, contig)
+
+
+class TestSetState(object):
+ def setup(self):
+ self.seed = 1234567890
+ self.rg = Generator(MT19937(self.seed))
+ self.bit_generator = self.rg.bit_generator
+ self.state = self.bit_generator.state
+ self.legacy_state = (self.state['bit_generator'],
+ self.state['state']['key'],
+ self.state['state']['pos'])
+
+ def test_gaussian_reset(self):
+ # Make sure the cached every-other-Gaussian is reset.
+ old = self.rg.standard_normal(size=3)
+ self.bit_generator.state = self.state
+ new = self.rg.standard_normal(size=3)
+ assert_(np.all(old == new))
+
+ def test_gaussian_reset_in_media_res(self):
+ # When the state is saved with a cached Gaussian, make sure the
+ # cached Gaussian is restored.
+
+ self.rg.standard_normal()
+ state = self.bit_generator.state
+ old = self.rg.standard_normal(size=3)
+ self.bit_generator.state = state
+ new = self.rg.standard_normal(size=3)
+ assert_(np.all(old == new))
+
+ def test_negative_binomial(self):
+ # Ensure that the negative binomial results take floating point
+ # arguments without truncation.
+ self.rg.negative_binomial(0.5, 0.5)
+
+
+class TestIntegers(object):
+ rfunc = random.integers
+
+ # valid integer/boolean types
+ itype = [bool, np.int8, np.uint8, np.int16, np.uint16,
+ np.int32, np.uint32, np.int64, np.uint64]
+
+ def test_unsupported_type(self, endpoint):
+ assert_raises(TypeError, self.rfunc, 1, endpoint=endpoint, dtype=float)
+
+ def test_bounds_checking(self, endpoint):
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+ assert_raises(ValueError, self.rfunc, lbnd - 1, ubnd,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, lbnd, ubnd + 1,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, ubnd, lbnd,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, 1, 0, endpoint=endpoint,
+ dtype=dt)
+
+ assert_raises(ValueError, self.rfunc, [lbnd - 1], ubnd,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, [lbnd], [ubnd + 1],
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, [ubnd], [lbnd],
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, 1, [0],
+ endpoint=endpoint, dtype=dt)
+
+ def test_bounds_checking_array(self, endpoint):
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + (not endpoint)
+
+ assert_raises(ValueError, self.rfunc, [lbnd - 1] * 2, [ubnd] * 2,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, [lbnd] * 2,
+ [ubnd + 1] * 2, endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2,
+ endpoint=endpoint, dtype=dt)
+ assert_raises(ValueError, self.rfunc, [1] * 2, 0,
+ endpoint=endpoint, dtype=dt)
+
+ def test_rng_zero_and_extremes(self, endpoint):
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+ is_open = not endpoint
+
+ tgt = ubnd - 1
+ assert_equal(self.rfunc(tgt, tgt + is_open, size=1000,
+ endpoint=endpoint, dtype=dt), tgt)
+ assert_equal(self.rfunc([tgt], tgt + is_open, size=1000,
+ endpoint=endpoint, dtype=dt), tgt)
+
+ tgt = lbnd
+ assert_equal(self.rfunc(tgt, tgt + is_open, size=1000,
+ endpoint=endpoint, dtype=dt), tgt)
+ assert_equal(self.rfunc(tgt, [tgt + is_open], size=1000,
+ endpoint=endpoint, dtype=dt), tgt)
+
+ tgt = (lbnd + ubnd) // 2
+ assert_equal(self.rfunc(tgt, tgt + is_open, size=1000,
+ endpoint=endpoint, dtype=dt), tgt)
+ assert_equal(self.rfunc([tgt], [tgt + is_open],
+ size=1000, endpoint=endpoint, dtype=dt),
+ tgt)
+
+ def test_rng_zero_and_extremes_array(self, endpoint):
+ size = 1000
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ tgt = ubnd - 1
+ assert_equal(self.rfunc([tgt], [tgt + 1],
+ size=size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, size=size, dtype=dt), tgt)
+
+ tgt = lbnd
+ assert_equal(self.rfunc([tgt], [tgt + 1],
+ size=size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, size=size, dtype=dt), tgt)
+
+ tgt = (lbnd + ubnd) // 2
+ assert_equal(self.rfunc([tgt], [tgt + 1],
+ size=size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, dtype=dt), tgt)
+ assert_equal(self.rfunc(
+ [tgt] * size, [tgt + 1] * size, size=size, dtype=dt), tgt)
+
+ def test_full_range(self, endpoint):
+ # Test for ticket #1690
+
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ try:
+ self.rfunc(lbnd, ubnd, endpoint=endpoint, dtype=dt)
+ except Exception as e:
+ raise AssertionError("No error should have been raised, "
+ "but one was with the following "
+ "message:\n\n%s" % str(e))
+
+ def test_full_range_array(self, endpoint):
+ # Test for ticket #1690
+
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ try:
+ self.rfunc([lbnd] * 2, [ubnd], endpoint=endpoint, dtype=dt)
+ except Exception as e:
+ raise AssertionError("No error should have been raised, "
+ "but one was with the following "
+ "message:\n\n%s" % str(e))
+
+ def test_in_bounds_fuzz(self, endpoint):
+ # Don't use fixed seed
+ random = Generator(MT19937())
+
+ for dt in self.itype[1:]:
+ for ubnd in [4, 8, 16]:
+ vals = self.rfunc(2, ubnd - endpoint, size=2 ** 16,
+ endpoint=endpoint, dtype=dt)
+ assert_(vals.max() < ubnd)
+ assert_(vals.min() >= 2)
+
+ vals = self.rfunc(0, 2 - endpoint, size=2 ** 16, endpoint=endpoint,
+ dtype=bool)
+ assert_(vals.max() < 2)
+ assert_(vals.min() >= 0)
+
+ def test_scalar_array_equiv(self, endpoint):
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ size = 1000
+ random = Generator(MT19937(1234))
+ scalar = random.integers(lbnd, ubnd, size=size, endpoint=endpoint,
+ dtype=dt)
+
+ random = Generator(MT19937(1234))
+ scalar_array = random.integers([lbnd], [ubnd], size=size,
+ endpoint=endpoint, dtype=dt)
+
+ random = Generator(MT19937(1234))
+ array = random.integers([lbnd] * size, [ubnd] *
+ size, size=size, endpoint=endpoint, dtype=dt)
+ assert_array_equal(scalar, scalar_array)
+ assert_array_equal(scalar, array)
+
+ def test_repeatability(self, endpoint):
+ import hashlib
+ # We use a md5 hash of generated sequences of 1000 samples
+ # in the range [0, 6) for all but bool, where the range
+ # is [0, 2). Hashes are for little endian numbers.
+ tgt = {'bool': 'b3300e66d2bb59e493d255d47c3a6cbe',
+ 'int16': '39624ead49ad67e37545744024d2648b',
+ 'int32': '5c4810373f979336c6c0c999996e47a1',
+ 'int64': 'ab126c15edff26f55c50d2b7e37391ac',
+ 'int8': 'd1746364b48a020dab9ef0568e6c0cd2',
+ 'uint16': '39624ead49ad67e37545744024d2648b',
+ 'uint32': '5c4810373f979336c6c0c999996e47a1',
+ 'uint64': 'ab126c15edff26f55c50d2b7e37391ac',
+ 'uint8': 'd1746364b48a020dab9ef0568e6c0cd2'}
+
+ for dt in self.itype[1:]:
+ random = Generator(MT19937(1234))
+
+ # view as little endian for hash
+ if sys.byteorder == 'little':
+ val = random.integers(0, 6 - endpoint, size=1000, endpoint=endpoint,
+ dtype=dt)
+ else:
+ val = random.integers(0, 6 - endpoint, size=1000, endpoint=endpoint,
+ dtype=dt).byteswap()
+
+ res = hashlib.md5(val.view(np.int8)).hexdigest()
+ assert_(tgt[np.dtype(dt).name] == res)
+
+ # bools do not depend on endianness
+ random = Generator(MT19937(1234))
+ val = random.integers(0, 2 - endpoint, size=1000, endpoint=endpoint,
+ dtype=bool).view(np.int8)
+ res = hashlib.md5(val).hexdigest()
+ assert_(tgt[np.dtype(bool).name] == res)
+
+ def test_repeatability_broadcasting(self, endpoint):
+ for dt in self.itype:
+ lbnd = 0 if dt in (np.bool, bool, np.bool_) else np.iinfo(dt).min
+ ubnd = 2 if dt in (
+ np.bool, bool, np.bool_) else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ # view as little endian for hash
+ random = Generator(MT19937(1234))
+ val = random.integers(lbnd, ubnd, size=1000, endpoint=endpoint,
+ dtype=dt)
+
+ random = Generator(MT19937(1234))
+ val_bc = random.integers([lbnd] * 1000, ubnd, endpoint=endpoint,
+ dtype=dt)
+
+ assert_array_equal(val, val_bc)
+
+ random = Generator(MT19937(1234))
+ val_bc = random.integers([lbnd] * 1000, [ubnd] * 1000,
+ endpoint=endpoint, dtype=dt)
+
+ assert_array_equal(val, val_bc)
+
+ def test_int64_uint64_broadcast_exceptions(self, endpoint):
+ configs = {np.uint64: ((0, 2**65), (-1, 2**62), (10, 9), (0, 0)),
+ np.int64: ((0, 2**64), (-(2**64), 2**62), (10, 9), (0, 0),
+ (-2**63-1, -2**63-1))}
+ for dtype in configs:
+ for config in configs[dtype]:
+ low, high = config
+ high = high - endpoint
+ low_a = np.array([[low]*10])
+ high_a = np.array([high] * 10)
+ assert_raises(ValueError, random.integers, low, high,
+ endpoint=endpoint, dtype=dtype)
+ assert_raises(ValueError, random.integers, low_a, high,
+ endpoint=endpoint, dtype=dtype)
+ assert_raises(ValueError, random.integers, low, high_a,
+ endpoint=endpoint, dtype=dtype)
+ assert_raises(ValueError, random.integers, low_a, high_a,
+ endpoint=endpoint, dtype=dtype)
+
+ low_o = np.array([[low]*10], dtype=np.object)
+ high_o = np.array([high] * 10, dtype=np.object)
+ assert_raises(ValueError, random.integers, low_o, high,
+ endpoint=endpoint, dtype=dtype)
+ assert_raises(ValueError, random.integers, low, high_o,
+ endpoint=endpoint, dtype=dtype)
+ assert_raises(ValueError, random.integers, low_o, high_o,
+ endpoint=endpoint, dtype=dtype)
+
+ def test_int64_uint64_corner_case(self, endpoint):
+ # When stored in Numpy arrays, `lbnd` is casted
+ # as np.int64, and `ubnd` is casted as np.uint64.
+ # Checking whether `lbnd` >= `ubnd` used to be
+ # done solely via direct comparison, which is incorrect
+ # because when Numpy tries to compare both numbers,
+ # it casts both to np.float64 because there is
+ # no integer superset of np.int64 and np.uint64. However,
+ # `ubnd` is too large to be represented in np.float64,
+ # causing it be round down to np.iinfo(np.int64).max,
+ # leading to a ValueError because `lbnd` now equals
+ # the new `ubnd`.
+
+ dt = np.int64
+ tgt = np.iinfo(np.int64).max
+ lbnd = np.int64(np.iinfo(np.int64).max)
+ ubnd = np.uint64(np.iinfo(np.int64).max + 1 - endpoint)
+
+ # None of these function calls should
+ # generate a ValueError now.
+ actual = random.integers(lbnd, ubnd, endpoint=endpoint, dtype=dt)
+ assert_equal(actual, tgt)
+
+ def test_respect_dtype_singleton(self, endpoint):
+ # See gh-7203
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+ dt = np.bool_ if dt is bool else dt
+
+ sample = self.rfunc(lbnd, ubnd, endpoint=endpoint, dtype=dt)
+ assert_equal(sample.dtype, dt)
+
+ for dt in (bool, int, np.long):
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+
+ # gh-7284: Ensure that we get Python data types
+ sample = self.rfunc(lbnd, ubnd, endpoint=endpoint, dtype=dt)
+ assert not hasattr(sample, 'dtype')
+ assert_equal(type(sample), dt)
+
+ def test_respect_dtype_array(self, endpoint):
+ # See gh-7203
+ for dt in self.itype:
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+ ubnd = ubnd - 1 if endpoint else ubnd
+ dt = np.bool_ if dt is bool else dt
+
+ sample = self.rfunc([lbnd], [ubnd], endpoint=endpoint, dtype=dt)
+ assert_equal(sample.dtype, dt)
+ sample = self.rfunc([lbnd] * 2, [ubnd] * 2, endpoint=endpoint,
+ dtype=dt)
+ assert_equal(sample.dtype, dt)
+
+ def test_zero_size(self, endpoint):
+ # See gh-7203
+ for dt in self.itype:
+ sample = self.rfunc(0, 0, (3, 0, 4), endpoint=endpoint, dtype=dt)
+ assert sample.shape == (3, 0, 4)
+ assert sample.dtype == dt
+ assert self.rfunc(0, -10, 0, endpoint=endpoint,
+ dtype=dt).shape == (0,)
+ assert_equal(random.integers(0, 0, size=(3, 0, 4)).shape,
+ (3, 0, 4))
+ assert_equal(random.integers(0, -10, size=0).shape, (0,))
+ assert_equal(random.integers(10, 10, size=0).shape, (0,))
+
+ def test_error_byteorder(self):
+ other_byteord_dt = '<i4' if sys.byteorder == 'big' else '>i4'
+ with pytest.raises(ValueError):
+ random.integers(0, 200, size=10, dtype=other_byteord_dt)
+
+
+class TestRandomDist(object):
+ # Make sure the random distribution returns the correct value for a
+ # given seed
+
+ def setup(self):
+ self.seed = 1234567890
+
+ def test_integers(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.integers(-99, 99, size=(3, 2))
+ desired = np.array([[-80, -56], [41, 37], [-83, -16]])
+ assert_array_equal(actual, desired)
+
+ def test_integers_masked(self):
+ # Test masked rejection sampling algorithm to generate array of
+ # uint32 in an interval.
+ random = Generator(MT19937(self.seed))
+ actual = random.integers(0, 99, size=(3, 2), dtype=np.uint32)
+ desired = np.array([[9, 21], [70, 68], [8, 41]], dtype=np.uint32)
+ assert_array_equal(actual, desired)
+
+ def test_integers_closed(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.integers(-99, 99, size=(3, 2), endpoint=True)
+ desired = np.array([[-80, -56], [ 41, 38], [-83, -15]])
+ assert_array_equal(actual, desired)
+
+ def test_integers_max_int(self):
+ # Tests whether integers with closed=True can generate the
+ # maximum allowed Python int that can be converted
+ # into a C long. Previous implementations of this
+ # method have thrown an OverflowError when attempting
+ # to generate this integer.
+ actual = random.integers(np.iinfo('l').max, np.iinfo('l').max,
+ endpoint=True)
+
+ desired = np.iinfo('l').max
+ assert_equal(actual, desired)
+
+ def test_random(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.random((3, 2))
+ desired = np.array([[0.096999199829214, 0.707517457682192],
+ [0.084364834598269, 0.767731206553125],
+ [0.665069021359413, 0.715487190596693]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.random()
+ assert_array_almost_equal(actual, desired[0, 0], decimal=15)
+
+ def test_random_float(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.random((3, 2))
+ desired = np.array([[0.0969992 , 0.70751746],
+ [0.08436483, 0.76773121],
+ [0.66506902, 0.71548719]])
+ assert_array_almost_equal(actual, desired, decimal=7)
+
+ def test_random_float_scalar(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.random(dtype=np.float32)
+ desired = 0.0969992
+ assert_array_almost_equal(actual, desired, decimal=7)
+
+ def test_random_unsupported_type(self):
+ assert_raises(TypeError, random.random, dtype='int32')
+
+ def test_choice_uniform_replace(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(4, 4)
+ desired = np.array([0, 0, 2, 2], dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+ def test_choice_nonuniform_replace(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(4, 4, p=[0.4, 0.4, 0.1, 0.1])
+ desired = np.array([0, 1, 0, 1], dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+ def test_choice_uniform_noreplace(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(4, 3, replace=False)
+ desired = np.array([2, 0, 3], dtype=np.int64)
+ assert_array_equal(actual, desired)
+ actual = random.choice(4, 4, replace=False, shuffle=False)
+ desired = np.arange(4, dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+ def test_choice_nonuniform_noreplace(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(4, 3, replace=False, p=[0.1, 0.3, 0.5, 0.1])
+ desired = np.array([0, 2, 3], dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+ def test_choice_noninteger(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(['a', 'b', 'c', 'd'], 4)
+ desired = np.array(['a', 'a', 'c', 'c'])
+ assert_array_equal(actual, desired)
+
+ def test_choice_multidimensional_default_axis(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice([[0, 1], [2, 3], [4, 5], [6, 7]], 3)
+ desired = np.array([[0, 1], [0, 1], [4, 5]])
+ assert_array_equal(actual, desired)
+
+ def test_choice_multidimensional_custom_axis(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.choice([[0, 1], [2, 3], [4, 5], [6, 7]], 1, axis=1)
+ desired = np.array([[0], [2], [4], [6]])
+ assert_array_equal(actual, desired)
+
+ def test_choice_exceptions(self):
+ sample = random.choice
+ assert_raises(ValueError, sample, -1, 3)
+ assert_raises(ValueError, sample, 3., 3)
+ assert_raises(ValueError, sample, [], 3)
+ assert_raises(ValueError, sample, [1, 2, 3, 4], 3,
+ p=[[0.25, 0.25], [0.25, 0.25]])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[0.4, 0.4, 0.2])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[1.1, -0.1])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[0.4, 0.4])
+ assert_raises(ValueError, sample, [1, 2, 3], 4, replace=False)
+ # gh-13087
+ assert_raises(ValueError, sample, [1, 2, 3], -2, replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], (-1,), replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], (-1, 1), replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], 2,
+ replace=False, p=[1, 0, 0])
+
+ def test_choice_return_shape(self):
+ p = [0.1, 0.9]
+ # Check scalar
+ assert_(np.isscalar(random.choice(2, replace=True)))
+ assert_(np.isscalar(random.choice(2, replace=False)))
+ assert_(np.isscalar(random.choice(2, replace=True, p=p)))
+ assert_(np.isscalar(random.choice(2, replace=False, p=p)))
+ assert_(np.isscalar(random.choice([1, 2], replace=True)))
+ assert_(random.choice([None], replace=True) is None)
+ a = np.array([1, 2])
+ arr = np.empty(1, dtype=object)
+ arr[0] = a
+ assert_(random.choice(arr, replace=True) is a)
+
+ # Check 0-d array
+ s = tuple()
+ assert_(not np.isscalar(random.choice(2, s, replace=True)))
+ assert_(not np.isscalar(random.choice(2, s, replace=False)))
+ assert_(not np.isscalar(random.choice(2, s, replace=True, p=p)))
+ assert_(not np.isscalar(random.choice(2, s, replace=False, p=p)))
+ assert_(not np.isscalar(random.choice([1, 2], s, replace=True)))
+ assert_(random.choice([None], s, replace=True).ndim == 0)
+ a = np.array([1, 2])
+ arr = np.empty(1, dtype=object)
+ arr[0] = a
+ assert_(random.choice(arr, s, replace=True).item() is a)
+
+ # Check multi dimensional array
+ s = (2, 3)
+ p = [0.1, 0.1, 0.1, 0.1, 0.4, 0.2]
+ assert_equal(random.choice(6, s, replace=True).shape, s)
+ assert_equal(random.choice(6, s, replace=False).shape, s)
+ assert_equal(random.choice(6, s, replace=True, p=p).shape, s)
+ assert_equal(random.choice(6, s, replace=False, p=p).shape, s)
+ assert_equal(random.choice(np.arange(6), s, replace=True).shape, s)
+
+ # Check zero-size
+ assert_equal(random.integers(0, 0, size=(3, 0, 4)).shape, (3, 0, 4))
+ assert_equal(random.integers(0, -10, size=0).shape, (0,))
+ assert_equal(random.integers(10, 10, size=0).shape, (0,))
+ assert_equal(random.choice(0, size=0).shape, (0,))
+ assert_equal(random.choice([], size=(0,)).shape, (0,))
+ assert_equal(random.choice(['a', 'b'], size=(3, 0, 4)).shape,
+ (3, 0, 4))
+ assert_raises(ValueError, random.choice, [], 10)
+
+ def test_choice_nan_probabilities(self):
+ a = np.array([42, 1, 2])
+ p = [None, None, None]
+ assert_raises(ValueError, random.choice, a, p=p)
+
+ def test_choice_p_non_contiguous(self):
+ p = np.ones(10) / 5
+ p[1::2] = 3.0
+ random = Generator(MT19937(self.seed))
+ non_contig = random.choice(5, 3, p=p[::2])
+ random = Generator(MT19937(self.seed))
+ contig = random.choice(5, 3, p=np.ascontiguousarray(p[::2]))
+ assert_array_equal(non_contig, contig)
+
+ def test_choice_return_type(self):
+ # gh 9867
+ p = np.ones(4) / 4.
+ actual = random.choice(4, 2)
+ assert actual.dtype == np.int64
+ actual = random.choice(4, 2, replace=False)
+ assert actual.dtype == np.int64
+ actual = random.choice(4, 2, p=p)
+ assert actual.dtype == np.int64
+ actual = random.choice(4, 2, p=p, replace=False)
+ assert actual.dtype == np.int64
+
+ def test_choice_large_sample(self):
+ import hashlib
+
+ choice_hash = 'd44962a0b1e92f4a3373c23222244e21'
+ random = Generator(MT19937(self.seed))
+ actual = random.choice(10000, 5000, replace=False)
+ if sys.byteorder != 'little':
+ actual = actual.byteswap()
+ res = hashlib.md5(actual.view(np.int8)).hexdigest()
+ assert_(choice_hash == res)
+
+ def test_bytes(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.bytes(10)
+ desired = b'\x86\xf0\xd4\x18\xe1\x81\t8%\xdd'
+ assert_equal(actual, desired)
+
+ def test_shuffle(self):
+ # Test lists, arrays (of various dtypes), and multidimensional versions
+ # of both, c-contiguous or not:
+ for conv in [lambda x: np.array([]),
+ lambda x: x,
+ lambda x: np.asarray(x).astype(np.int8),
+ lambda x: np.asarray(x).astype(np.float32),
+ lambda x: np.asarray(x).astype(np.complex64),
+ lambda x: np.asarray(x).astype(object),
+ lambda x: [(i, i) for i in x],
+ lambda x: np.asarray([[i, i] for i in x]),
+ lambda x: np.vstack([x, x]).T,
+ # gh-11442
+ lambda x: (np.asarray([(i, i) for i in x],
+ [("a", int), ("b", int)])
+ .view(np.recarray)),
+ # gh-4270
+ lambda x: np.asarray([(i, i) for i in x],
+ [("a", object, (1,)),
+ ("b", np.int32, (1,))])]:
+ random = Generator(MT19937(self.seed))
+ alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
+ random.shuffle(alist)
+ actual = alist
+ desired = conv([4, 1, 9, 8, 0, 5, 3, 6, 2, 7])
+ assert_array_equal(actual, desired)
+
+ def test_shuffle_masked(self):
+ # gh-3263
+ a = np.ma.masked_values(np.reshape(range(20), (5, 4)) % 3 - 1, -1)
+ b = np.ma.masked_values(np.arange(20) % 3 - 1, -1)
+ a_orig = a.copy()
+ b_orig = b.copy()
+ for i in range(50):
+ random.shuffle(a)
+ assert_equal(
+ sorted(a.data[~a.mask]), sorted(a_orig.data[~a_orig.mask]))
+ random.shuffle(b)
+ assert_equal(
+ sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask]))
+
+ def test_permutation(self):
+ random = Generator(MT19937(self.seed))
+ alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
+ actual = random.permutation(alist)
+ desired = [4, 1, 9, 8, 0, 5, 3, 6, 2, 7]
+ assert_array_equal(actual, desired)
+
+ random = Generator(MT19937(self.seed))
+ arr_2d = np.atleast_2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]).T
+ actual = random.permutation(arr_2d)
+ assert_array_equal(actual, np.atleast_2d(desired).T)
+
+ def test_beta(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.beta(.1, .9, size=(3, 2))
+ desired = np.array(
+ [[1.083029353267698e-10, 2.449965303168024e-11],
+ [2.397085162969853e-02, 3.590779671820755e-08],
+ [2.830254190078299e-04, 1.744709918330393e-01]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_binomial(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.binomial(100.123, .456, size=(3, 2))
+ desired = np.array([[42, 41],
+ [42, 48],
+ [44, 50]])
+ assert_array_equal(actual, desired)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.binomial(100.123, .456)
+ desired = 42
+ assert_array_equal(actual, desired)
+
+ def test_chisquare(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.chisquare(50, size=(3, 2))
+ desired = np.array([[32.9850547060149, 39.0219480493301],
+ [56.2006134779419, 57.3474165711485],
+ [55.4243733880198, 55.4209797925213]])
+ assert_array_almost_equal(actual, desired, decimal=13)
+
+ def test_dirichlet(self):
+ random = Generator(MT19937(self.seed))
+ alpha = np.array([51.72840233779265162, 39.74494232180943953])
+ actual = random.dirichlet(alpha, size=(3, 2))
+ desired = np.array([[[0.5439892869558927, 0.45601071304410745],
+ [0.5588917345860708, 0.4411082654139292 ]],
+ [[0.5632074165063435, 0.43679258349365657],
+ [0.54862581112627, 0.45137418887373015]],
+ [[0.49961831357047226, 0.5003816864295278 ],
+ [0.52374806183482, 0.47625193816517997]]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+ bad_alpha = np.array([5.4e-01, -1.0e-16])
+ assert_raises(ValueError, random.dirichlet, bad_alpha)
+
+ random = Generator(MT19937(self.seed))
+ alpha = np.array([51.72840233779265162, 39.74494232180943953])
+ actual = random.dirichlet(alpha)
+ assert_array_almost_equal(actual, desired[0, 0], decimal=15)
+
+ def test_dirichlet_size(self):
+ # gh-3173
+ p = np.array([51.72840233779265162, 39.74494232180943953])
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, [2, 2]).shape, (2, 2, 2))
+ assert_equal(random.dirichlet(p, (2, 2)).shape, (2, 2, 2))
+ assert_equal(random.dirichlet(p, np.array((2, 2))).shape, (2, 2, 2))
+
+ assert_raises(TypeError, random.dirichlet, p, float(1))
+
+ def test_dirichlet_bad_alpha(self):
+ # gh-2089
+ alpha = np.array([5.4e-01, -1.0e-16])
+ assert_raises(ValueError, random.dirichlet, alpha)
+
+ def test_dirichlet_alpha_non_contiguous(self):
+ a = np.array([51.72840233779265162, -1.0, 39.74494232180943953])
+ alpha = a[::2]
+ random = Generator(MT19937(self.seed))
+ non_contig = random.dirichlet(alpha, size=(3, 2))
+ random = Generator(MT19937(self.seed))
+ contig = random.dirichlet(np.ascontiguousarray(alpha),
+ size=(3, 2))
+ assert_array_almost_equal(non_contig, contig)
+
+ def test_exponential(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.exponential(1.1234, size=(3, 2))
+ desired = np.array([[0.098845481066258, 1.560752510746964],
+ [0.075730916041636, 1.769098974710777],
+ [1.488602544592235, 2.49684815275751 ]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_exponential_0(self):
+ assert_equal(random.exponential(scale=0), 0)
+ assert_raises(ValueError, random.exponential, scale=-0.)
+
+ def test_f(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.f(12, 77, size=(3, 2))
+ desired = np.array([[0.461720027077085, 1.100441958872451],
+ [1.100337455217484, 0.91421736740018 ],
+ [0.500811891303113, 0.826802454552058]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_gamma(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.gamma(5, 3, size=(3, 2))
+ desired = np.array([[ 5.03850858902096, 7.9228656732049 ],
+ [18.73983605132985, 19.57961681699238],
+ [18.17897755150825, 18.17653912505234]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_gamma_0(self):
+ assert_equal(random.gamma(shape=0, scale=0), 0)
+ assert_raises(ValueError, random.gamma, shape=-0., scale=-0.)
+
+ def test_geometric(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.geometric(.123456789, size=(3, 2))
+ desired = np.array([[ 1, 10],
+ [ 1, 12],
+ [ 9, 10]])
+ assert_array_equal(actual, desired)
+
+ def test_geometric_exceptions(self):
+ assert_raises(ValueError, random.geometric, 1.1)
+ assert_raises(ValueError, random.geometric, [1.1] * 10)
+ assert_raises(ValueError, random.geometric, -0.1)
+ assert_raises(ValueError, random.geometric, [-0.1] * 10)
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, random.geometric, np.nan)
+ assert_raises(ValueError, random.geometric, [np.nan] * 10)
+
+ def test_gumbel(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.gumbel(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[ 4.688397515056245, -0.289514845417841],
+ [ 4.981176042584683, -0.633224272589149],
+ [-0.055915275687488, -0.333962478257953]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_gumbel_0(self):
+ assert_equal(random.gumbel(scale=0), 0)
+ assert_raises(ValueError, random.gumbel, scale=-0.)
+
+ def test_hypergeometric(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.hypergeometric(10.1, 5.5, 14, size=(3, 2))
+ desired = np.array([[ 9, 9],
+ [ 9, 9],
+ [10, 9]])
+ assert_array_equal(actual, desired)
+
+ # Test nbad = 0
+ actual = random.hypergeometric(5, 0, 3, size=4)
+ desired = np.array([3, 3, 3, 3])
+ assert_array_equal(actual, desired)
+
+ actual = random.hypergeometric(15, 0, 12, size=4)
+ desired = np.array([12, 12, 12, 12])
+ assert_array_equal(actual, desired)
+
+ # Test ngood = 0
+ actual = random.hypergeometric(0, 5, 3, size=4)
+ desired = np.array([0, 0, 0, 0])
+ assert_array_equal(actual, desired)
+
+ actual = random.hypergeometric(0, 15, 12, size=4)
+ desired = np.array([0, 0, 0, 0])
+ assert_array_equal(actual, desired)
+
+ def test_laplace(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.laplace(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[-3.156353949272393, 1.195863024830054],
+ [-3.435458081645966, 1.656882398925444],
+ [ 0.924824032467446, 1.251116432209336]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_laplace_0(self):
+ assert_equal(random.laplace(scale=0), 0)
+ assert_raises(ValueError, random.laplace, scale=-0.)
+
+ def test_logistic(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.logistic(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[-4.338584631510999, 1.890171436749954],
+ [-4.64547787337966 , 2.514545562919217],
+ [ 1.495389489198666, 1.967827627577474]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_lognormal(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2))
+ desired = np.array([[ 0.0268252166335, 13.9534486483053],
+ [ 0.1204014788936, 2.2422077497792],
+ [ 4.2484199496128, 12.0093343977523]])
+ assert_array_almost_equal(actual, desired, decimal=13)
+
+ def test_lognormal_0(self):
+ assert_equal(random.lognormal(sigma=0), 1)
+ assert_raises(ValueError, random.lognormal, sigma=-0.)
+
+ def test_logseries(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.logseries(p=.923456789, size=(3, 2))
+ desired = np.array([[14, 17],
+ [3, 18],
+ [5, 1]])
+ assert_array_equal(actual, desired)
+
+ def test_logseries_exceptions(self):
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, random.logseries, np.nan)
+ assert_raises(ValueError, random.logseries, [np.nan] * 10)
+
+ def test_multinomial(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.multinomial(20, [1 / 6.] * 6, size=(3, 2))
+ desired = np.array([[[1, 5, 1, 6, 4, 3],
+ [4, 2, 6, 2, 4, 2]],
+ [[5, 3, 2, 6, 3, 1],
+ [4, 4, 0, 2, 3, 7]],
+ [[6, 3, 1, 5, 3, 2],
+ [5, 5, 3, 1, 2, 4]]])
+ assert_array_equal(actual, desired)
+
+ def test_multivariate_normal(self):
+ random = Generator(MT19937(self.seed))
+ mean = (.123456789, 10)
+ cov = [[1, 0], [0, 1]]
+ size = (3, 2)
+ actual = random.multivariate_normal(mean, cov, size)
+ desired = np.array([[[-1.747478062846581, 11.25613495182354 ],
+ [-0.9967333370066214, 10.342002097029821 ]],
+ [[ 0.7850019631242964, 11.181113712443013 ],
+ [ 0.8901349653255224, 8.873825399642492 ]],
+ [[ 0.7130260107430003, 9.551628690083056 ],
+ [ 0.7127098726541128, 11.991709234143173 ]]])
+
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ # Check for default size, was raising deprecation warning
+ actual = random.multivariate_normal(mean, cov)
+ desired = np.array([0.233278563284287, 9.424140804347195])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ # Check that non positive-semidefinite covariance warns with
+ # RuntimeWarning
+ mean = [0, 0]
+ cov = [[1, 2], [2, 1]]
+ assert_warns(RuntimeWarning, random.multivariate_normal, mean, cov)
+
+ # and that it doesn't warn with RuntimeWarning check_valid='ignore'
+ assert_no_warnings(random.multivariate_normal, mean, cov,
+ check_valid='ignore')
+
+ # and that it raises with RuntimeWarning check_valid='raises'
+ assert_raises(ValueError, random.multivariate_normal, mean, cov,
+ check_valid='raise')
+
+ cov = np.array([[1, 0.1], [0.1, 1]], dtype=np.float32)
+ with suppress_warnings() as sup:
+ random.multivariate_normal(mean, cov)
+ w = sup.record(RuntimeWarning)
+ assert len(w) == 0
+
+ mu = np.zeros(2)
+ cov = np.eye(2)
+ assert_raises(ValueError, random.multivariate_normal, mean, cov,
+ check_valid='other')
+ assert_raises(ValueError, random.multivariate_normal,
+ np.zeros((2, 1, 1)), cov)
+ assert_raises(ValueError, random.multivariate_normal,
+ mu, np.empty((3, 2)))
+ assert_raises(ValueError, random.multivariate_normal,
+ mu, np.eye(3))
+
+ def test_negative_binomial(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.negative_binomial(n=100, p=.12345, size=(3, 2))
+ desired = np.array([[543, 727],
+ [775, 760],
+ [600, 674]])
+ assert_array_equal(actual, desired)
+
+ def test_negative_binomial_exceptions(self):
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, random.negative_binomial, 100, np.nan)
+ assert_raises(ValueError, random.negative_binomial, 100,
+ [np.nan] * 10)
+
+ def test_noncentral_chisquare(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2))
+ desired = np.array([[ 1.70561552362133, 15.97378184942111],
+ [13.71483425173724, 20.17859633310629],
+ [11.3615477156643 , 3.67891108738029]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ actual = random.noncentral_chisquare(df=.5, nonc=.2, size=(3, 2))
+ desired = np.array([[9.41427665607629e-04, 1.70473157518850e-04],
+ [1.14554372041263e+00, 1.38187755933435e-03],
+ [1.90659181905387e+00, 1.21772577941822e+00]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.noncentral_chisquare(df=5, nonc=0, size=(3, 2))
+ desired = np.array([[0.82947954590419, 1.80139670767078],
+ [6.58720057417794, 7.00491463609814],
+ [6.31101879073157, 6.30982307753005]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_noncentral_f(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.noncentral_f(dfnum=5, dfden=2, nonc=1,
+ size=(3, 2))
+ desired = np.array([[0.060310671139 , 0.23866058175939],
+ [0.86860246709073, 0.2668510459738 ],
+ [0.23375780078364, 1.88922102885943]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_noncentral_f_nan(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.noncentral_f(dfnum=5, dfden=2, nonc=np.nan)
+ assert np.isnan(actual)
+
+ def test_normal(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.normal(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[-3.618412914693162, 2.635726692647081],
+ [-2.116923463013243, 0.807460983059643],
+ [ 1.446547137248593, 2.485684213886024]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_normal_0(self):
+ assert_equal(random.normal(scale=0), 0)
+ assert_raises(ValueError, random.normal, scale=-0.)
+
+ def test_pareto(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.pareto(a=.123456789, size=(3, 2))
+ desired = np.array([[1.0394926776069018e+00, 7.7142534343505773e+04],
+ [7.2640150889064703e-01, 3.4650454783825594e+05],
+ [4.5852344481994740e+04, 6.5851383009539105e+07]])
+ # For some reason on 32-bit x86 Ubuntu 12.10 the [1, 0] entry in this
+ # matrix differs by 24 nulps. Discussion:
+ # https://mail.python.org/pipermail/numpy-discussion/2012-September/063801.html
+ # Consensus is that this is probably some gcc quirk that affects
+ # rounding but not in any important way, so we just use a looser
+ # tolerance on this test:
+ np.testing.assert_array_almost_equal_nulp(actual, desired, nulp=30)
+
+ def test_poisson(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.poisson(lam=.123456789, size=(3, 2))
+ desired = np.array([[0, 0],
+ [0, 0],
+ [0, 0]])
+ assert_array_equal(actual, desired)
+
+ def test_poisson_exceptions(self):
+ lambig = np.iinfo('int64').max
+ lamneg = -1
+ assert_raises(ValueError, random.poisson, lamneg)
+ assert_raises(ValueError, random.poisson, [lamneg] * 10)
+ assert_raises(ValueError, random.poisson, lambig)
+ assert_raises(ValueError, random.poisson, [lambig] * 10)
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, random.poisson, np.nan)
+ assert_raises(ValueError, random.poisson, [np.nan] * 10)
+
+ def test_power(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.power(a=.123456789, size=(3, 2))
+ desired = np.array([[1.977857368842754e-09, 9.806792196620341e-02],
+ [2.482442984543471e-10, 1.527108843266079e-01],
+ [8.188283434244285e-02, 3.950547209346948e-01]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_rayleigh(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.rayleigh(scale=10, size=(3, 2))
+ desired = np.array([[ 4.51734079831581, 15.6802442485758 ],
+ [ 4.19850651287094, 17.08718809823704],
+ [14.7907457708776 , 15.85545333419775]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_rayleigh_0(self):
+ assert_equal(random.rayleigh(scale=0), 0)
+ assert_raises(ValueError, random.rayleigh, scale=-0.)
+
+ def test_standard_cauchy(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_cauchy(size=(3, 2))
+ desired = np.array([[-1.489437778266206, -3.275389641569784],
+ [ 0.560102864910406, -0.680780916282552],
+ [-1.314912905226277, 0.295852965660225]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_exponential(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_exponential(size=(3, 2), method='inv')
+ desired = np.array([[0.102031839440643, 1.229350298474972],
+ [0.088137284693098, 1.459859985522667],
+ [1.093830802293668, 1.256977002164613]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_expoential_type_error(self):
+ assert_raises(TypeError, random.standard_exponential, dtype=np.int32)
+
+ def test_standard_gamma(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_gamma(shape=3, size=(3, 2))
+ desired = np.array([[0.62970724056362, 1.22379851271008],
+ [3.899412530884 , 4.12479964250139],
+ [3.74994102464584, 3.74929307690815]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_standard_gammma_scalar_float(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_gamma(3, dtype=np.float32)
+ desired = 2.9242148399353027
+ assert_array_almost_equal(actual, desired, decimal=6)
+
+ def test_standard_gamma_float(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_gamma(shape=3, size=(3, 2))
+ desired = np.array([[0.62971, 1.2238 ],
+ [3.89941, 4.1248 ],
+ [3.74994, 3.74929]])
+ assert_array_almost_equal(actual, desired, decimal=5)
+
+ def test_standard_gammma_float_out(self):
+ actual = np.zeros((3, 2), dtype=np.float32)
+ random = Generator(MT19937(self.seed))
+ random.standard_gamma(10.0, out=actual, dtype=np.float32)
+ desired = np.array([[10.14987, 7.87012],
+ [ 9.46284, 12.56832],
+ [13.82495, 7.81533]], dtype=np.float32)
+ assert_array_almost_equal(actual, desired, decimal=5)
+
+ random = Generator(MT19937(self.seed))
+ random.standard_gamma(10.0, out=actual, size=(3, 2), dtype=np.float32)
+ assert_array_almost_equal(actual, desired, decimal=5)
+
+ def test_standard_gamma_unknown_type(self):
+ assert_raises(TypeError, random.standard_gamma, 1.,
+ dtype='int32')
+
+ def test_out_size_mismatch(self):
+ out = np.zeros(10)
+ assert_raises(ValueError, random.standard_gamma, 10.0, size=20,
+ out=out)
+ assert_raises(ValueError, random.standard_gamma, 10.0, size=(10, 1),
+ out=out)
+
+ def test_standard_gamma_0(self):
+ assert_equal(random.standard_gamma(shape=0), 0)
+ assert_raises(ValueError, random.standard_gamma, shape=-0.)
+
+ def test_standard_normal(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_normal(size=(3, 2))
+ desired = np.array([[-1.870934851846581, 1.25613495182354 ],
+ [-1.120190126006621, 0.342002097029821],
+ [ 0.661545174124296, 1.181113712443012]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_normal_unsupported_type(self):
+ assert_raises(TypeError, random.standard_normal, dtype=np.int32)
+
+ def test_standard_t(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_t(df=10, size=(3, 2))
+ desired = np.array([[-1.484666193042647, 0.30597891831161 ],
+ [ 1.056684299648085, -0.407312602088507],
+ [ 0.130704414281157, -2.038053410490321]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_triangular(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.triangular(left=5.12, mode=10.23, right=20.34,
+ size=(3, 2))
+ desired = np.array([[ 7.86664070590917, 13.6313848513185 ],
+ [ 7.68152445215983, 14.36169131136546],
+ [13.16105603911429, 13.72341621856971]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_uniform(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.uniform(low=1.23, high=10.54, size=(3, 2))
+ desired = np.array([[2.13306255040998 , 7.816987531021207],
+ [2.015436610109887, 8.377577533009589],
+ [7.421792588856135, 7.891185744455209]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_uniform_range_bounds(self):
+ fmin = np.finfo('float').min
+ fmax = np.finfo('float').max
+
+ func = random.uniform
+ assert_raises(OverflowError, func, -np.inf, 0)
+ assert_raises(OverflowError, func, 0, np.inf)
+ assert_raises(OverflowError, func, fmin, fmax)
+ assert_raises(OverflowError, func, [-np.inf], [0])
+ assert_raises(OverflowError, func, [0], [np.inf])
+
+ # (fmax / 1e17) - fmin is within range, so this should not throw
+ # account for i386 extended precision DBL_MAX / 1e17 + DBL_MAX >
+ # DBL_MAX by increasing fmin a bit
+ random.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17)
+
+ def test_scalar_exception_propagation(self):
+ # Tests that exceptions are correctly propagated in distributions
+ # when called with objects that throw exceptions when converted to
+ # scalars.
+ #
+ # Regression test for gh: 8865
+
+ class ThrowingFloat(np.ndarray):
+ def __float__(self):
+ raise TypeError
+
+ throwing_float = np.array(1.0).view(ThrowingFloat)
+ assert_raises(TypeError, random.uniform, throwing_float,
+ throwing_float)
+
+ class ThrowingInteger(np.ndarray):
+ def __int__(self):
+ raise TypeError
+
+ throwing_int = np.array(1).view(ThrowingInteger)
+ assert_raises(TypeError, random.hypergeometric, throwing_int, 1, 1)
+
+ def test_vonmises(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.vonmises(mu=1.23, kappa=1.54, size=(3, 2))
+ desired = np.array([[ 1.107972248690106, 2.841536476232361],
+ [ 1.832602376042457, 1.945511926976032],
+ [-0.260147475776542, 2.058047492231698]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_vonmises_small(self):
+ # check infinite loop, gh-4720
+ random = Generator(MT19937(self.seed))
+ r = random.vonmises(mu=0., kappa=1.1e-8, size=10**6)
+ assert_(np.isfinite(r).all())
+
+ def test_vonmises_nan(self):
+ random = Generator(MT19937(self.seed))
+ r = random.vonmises(mu=0., kappa=np.nan)
+ assert_(np.isnan(r))
+
+ def test_wald(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.wald(mean=1.23, scale=1.54, size=(3, 2))
+ desired = np.array([[0.26871721804551, 3.2233942732115 ],
+ [2.20328374987066, 2.40958405189353],
+ [2.07093587449261, 0.73073890064369]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_weibull(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.weibull(a=1.23, size=(3, 2))
+ desired = np.array([[0.138613914769468, 1.306463419753191],
+ [0.111623365934763, 1.446570494646721],
+ [1.257145775276011, 1.914247725027957]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_weibull_0(self):
+ random = Generator(MT19937(self.seed))
+ assert_equal(random.weibull(a=0, size=12), np.zeros(12))
+ assert_raises(ValueError, random.weibull, a=-0.)
+
+ def test_zipf(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.zipf(a=1.23, size=(3, 2))
+ desired = np.array([[ 1, 1],
+ [ 10, 867],
+ [354, 2]])
+ assert_array_equal(actual, desired)
+
+
+class TestBroadcast(object):
+ # tests that functions that broadcast behave
+ # correctly when presented with non-scalar arguments
+ def setup(self):
+ self.seed = 123456789
+
+
+ def test_uniform(self):
+ random = Generator(MT19937(self.seed))
+ low = [0]
+ high = [1]
+ uniform = random.uniform
+ desired = np.array([0.16693771389729, 0.19635129550675, 0.75563050964095])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.uniform(low * 3, high)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.uniform(low, high * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_normal(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ random = Generator(MT19937(self.seed))
+ desired = np.array([-0.38736406738527, 0.79594375042255, 0.0197076236097])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.normal(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.normal, loc * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ normal = random.normal
+ actual = normal(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, normal, loc, bad_scale * 3)
+
+ def test_beta(self):
+ a = [1]
+ b = [2]
+ bad_a = [-1]
+ bad_b = [-2]
+ desired = np.array([0.18719338682602, 0.73234824491364, 0.17928615186455])
+
+ random = Generator(MT19937(self.seed))
+ beta = random.beta
+ actual = beta(a * 3, b)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, beta, bad_a * 3, b)
+ assert_raises(ValueError, beta, a * 3, bad_b)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.beta(a, b * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_exponential(self):
+ scale = [1]
+ bad_scale = [-1]
+ desired = np.array([0.67245993212806, 0.21380495318094, 0.7177848928629])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.exponential(scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.exponential, bad_scale * 3)
+
+ def test_standard_gamma(self):
+ shape = [1]
+ bad_shape = [-1]
+ desired = np.array([0.67245993212806, 0.21380495318094, 0.7177848928629])
+
+ random = Generator(MT19937(self.seed))
+ std_gamma = random.standard_gamma
+ actual = std_gamma(shape * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, std_gamma, bad_shape * 3)
+
+ def test_gamma(self):
+ shape = [1]
+ scale = [2]
+ bad_shape = [-1]
+ bad_scale = [-2]
+ desired = np.array([1.34491986425611, 0.42760990636187, 1.4355697857258])
+
+ random = Generator(MT19937(self.seed))
+ gamma = random.gamma
+ actual = gamma(shape * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gamma, bad_shape * 3, scale)
+ assert_raises(ValueError, gamma, shape * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ gamma = random.gamma
+ actual = gamma(shape, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gamma, bad_shape, scale * 3)
+ assert_raises(ValueError, gamma, shape, bad_scale * 3)
+
+ def test_f(self):
+ dfnum = [1]
+ dfden = [2]
+ bad_dfnum = [-1]
+ bad_dfden = [-2]
+ desired = np.array([0.07765056244107, 7.72951397913186, 0.05786093891763])
+
+ random = Generator(MT19937(self.seed))
+ f = random.f
+ actual = f(dfnum * 3, dfden)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, f, bad_dfnum * 3, dfden)
+ assert_raises(ValueError, f, dfnum * 3, bad_dfden)
+
+ random = Generator(MT19937(self.seed))
+ f = random.f
+ actual = f(dfnum, dfden * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, f, bad_dfnum, dfden * 3)
+ assert_raises(ValueError, f, dfnum, bad_dfden * 3)
+
+ def test_noncentral_f(self):
+ dfnum = [2]
+ dfden = [3]
+ nonc = [4]
+ bad_dfnum = [0]
+ bad_dfden = [-1]
+ bad_nonc = [-2]
+ desired = np.array([2.02434240411421, 12.91838601070124, 1.24395160354629])
+
+ random = Generator(MT19937(self.seed))
+ nonc_f = random.noncentral_f
+ actual = nonc_f(dfnum * 3, dfden, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert np.all(np.isnan(nonc_f(dfnum, dfden, [np.nan] * 3)))
+
+ assert_raises(ValueError, nonc_f, bad_dfnum * 3, dfden, nonc)
+ assert_raises(ValueError, nonc_f, dfnum * 3, bad_dfden, nonc)
+ assert_raises(ValueError, nonc_f, dfnum * 3, dfden, bad_nonc)
+
+ random = Generator(MT19937(self.seed))
+ nonc_f = random.noncentral_f
+ actual = nonc_f(dfnum, dfden * 3, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_f, bad_dfnum, dfden * 3, nonc)
+ assert_raises(ValueError, nonc_f, dfnum, bad_dfden * 3, nonc)
+ assert_raises(ValueError, nonc_f, dfnum, dfden * 3, bad_nonc)
+
+ random = Generator(MT19937(self.seed))
+ nonc_f = random.noncentral_f
+ actual = nonc_f(dfnum, dfden, nonc * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_f, bad_dfnum, dfden, nonc * 3)
+ assert_raises(ValueError, nonc_f, dfnum, bad_dfden, nonc * 3)
+ assert_raises(ValueError, nonc_f, dfnum, dfden, bad_nonc * 3)
+
+ def test_noncentral_f_small_df(self):
+ random = Generator(MT19937(self.seed))
+ desired = np.array([0.04714867120827, 0.1239390327694])
+ actual = random.noncentral_f(0.9, 0.9, 2, size=2)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_chisquare(self):
+ df = [1]
+ bad_df = [-1]
+ desired = np.array([0.05573640064251, 1.47220224353539, 2.9469379318589])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.chisquare(df * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.chisquare, bad_df * 3)
+
+ def test_noncentral_chisquare(self):
+ df = [1]
+ nonc = [2]
+ bad_df = [-1]
+ bad_nonc = [-2]
+ desired = np.array([0.07710766249436, 5.27829115110304, 0.630732147399])
+
+ random = Generator(MT19937(self.seed))
+ nonc_chi = random.noncentral_chisquare
+ actual = nonc_chi(df * 3, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_chi, bad_df * 3, nonc)
+ assert_raises(ValueError, nonc_chi, df * 3, bad_nonc)
+
+ random = Generator(MT19937(self.seed))
+ nonc_chi = random.noncentral_chisquare
+ actual = nonc_chi(df, nonc * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_chi, bad_df, nonc * 3)
+ assert_raises(ValueError, nonc_chi, df, bad_nonc * 3)
+
+ def test_standard_t(self):
+ df = [1]
+ bad_df = [-1]
+ desired = np.array([-1.39498829447098, -1.23058658835223, 0.17207021065983])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.standard_t(df * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.standard_t, bad_df * 3)
+
+ def test_vonmises(self):
+ mu = [2]
+ kappa = [1]
+ bad_kappa = [-1]
+ desired = np.array([2.25935584988528, 2.23326261461399, -2.84152146503326])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.vonmises(mu * 3, kappa)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.vonmises, mu * 3, bad_kappa)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.vonmises(mu, kappa * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.vonmises, mu, bad_kappa * 3)
+
+ def test_pareto(self):
+ a = [1]
+ bad_a = [-1]
+ desired = np.array([0.95905052946317, 0.2383810889437 , 1.04988745750013])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.pareto(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.pareto, bad_a * 3)
+
+ def test_weibull(self):
+ a = [1]
+ bad_a = [-1]
+ desired = np.array([0.67245993212806, 0.21380495318094, 0.7177848928629])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.weibull(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.weibull, bad_a * 3)
+
+ def test_power(self):
+ a = [1]
+ bad_a = [-1]
+ desired = np.array([0.48954864361052, 0.19249412888486, 0.51216834058807])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.power(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.power, bad_a * 3)
+
+ def test_laplace(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ desired = np.array([-1.09698732625119, -0.93470271947368, 0.71592671378202])
+
+ random = Generator(MT19937(self.seed))
+ laplace = random.laplace
+ actual = laplace(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, laplace, loc * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ laplace = random.laplace
+ actual = laplace(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, laplace, loc, bad_scale * 3)
+
+ def test_gumbel(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ desired = np.array([1.70020068231762, 1.52054354273631, -0.34293267607081])
+
+ random = Generator(MT19937(self.seed))
+ gumbel = random.gumbel
+ actual = gumbel(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gumbel, loc * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ gumbel = random.gumbel
+ actual = gumbel(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gumbel, loc, bad_scale * 3)
+
+ def test_logistic(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ desired = np.array([-1.607487640433, -1.40925686003678, 1.12887112820397])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.logistic(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.logistic, loc * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.logistic(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.logistic, loc, bad_scale * 3)
+ assert_equal(random.logistic(1.0, 0.0), 1.0)
+
+ def test_lognormal(self):
+ mean = [0]
+ sigma = [1]
+ bad_sigma = [-1]
+ desired = np.array([0.67884390500697, 2.21653186290321, 1.01990310084276])
+
+ random = Generator(MT19937(self.seed))
+ lognormal = random.lognormal
+ actual = lognormal(mean * 3, sigma)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, lognormal, mean * 3, bad_sigma)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.lognormal(mean, sigma * 3)
+ assert_raises(ValueError, random.lognormal, mean, bad_sigma * 3)
+
+ def test_rayleigh(self):
+ scale = [1]
+ bad_scale = [-1]
+ desired = np.array([0.60439534475066, 0.66120048396359, 1.67873398389499])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.rayleigh(scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.rayleigh, bad_scale * 3)
+
+ def test_wald(self):
+ mean = [0.5]
+ scale = [1]
+ bad_mean = [0]
+ bad_scale = [-2]
+ desired = np.array([0.38052407392905, 0.50701641508592, 0.484935249864])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.wald(mean * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.wald, bad_mean * 3, scale)
+ assert_raises(ValueError, random.wald, mean * 3, bad_scale)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.wald(mean, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, random.wald, bad_mean, scale * 3)
+ assert_raises(ValueError, random.wald, mean, bad_scale * 3)
+
+ def test_triangular(self):
+ left = [1]
+ right = [3]
+ mode = [2]
+ bad_left_one = [3]
+ bad_mode_one = [4]
+ bad_left_two, bad_mode_two = right * 2
+ desired = np.array([1.57781954604754, 1.62665986867957, 2.30090130831326])
+
+ random = Generator(MT19937(self.seed))
+ triangular = random.triangular
+ actual = triangular(left * 3, mode, right)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one * 3, mode, right)
+ assert_raises(ValueError, triangular, left * 3, bad_mode_one, right)
+ assert_raises(ValueError, triangular, bad_left_two * 3, bad_mode_two,
+ right)
+
+ random = Generator(MT19937(self.seed))
+ triangular = random.triangular
+ actual = triangular(left, mode * 3, right)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one, mode * 3, right)
+ assert_raises(ValueError, triangular, left, bad_mode_one * 3, right)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two * 3,
+ right)
+
+ random = Generator(MT19937(self.seed))
+ triangular = random.triangular
+ actual = triangular(left, mode, right * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one, mode, right * 3)
+ assert_raises(ValueError, triangular, left, bad_mode_one, right * 3)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two,
+ right * 3)
+
+ assert_raises(ValueError, triangular, 10., 0., 20.)
+ assert_raises(ValueError, triangular, 10., 25., 20.)
+ assert_raises(ValueError, triangular, 10., 10., 10.)
+
+ def test_binomial(self):
+ n = [1]
+ p = [0.5]
+ bad_n = [-1]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ desired = np.array([0, 0, 1])
+
+ random = Generator(MT19937(self.seed))
+ binom = random.binomial
+ actual = binom(n * 3, p)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, binom, bad_n * 3, p)
+ assert_raises(ValueError, binom, n * 3, bad_p_one)
+ assert_raises(ValueError, binom, n * 3, bad_p_two)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.binomial(n, p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, binom, bad_n, p * 3)
+ assert_raises(ValueError, binom, n, bad_p_one * 3)
+ assert_raises(ValueError, binom, n, bad_p_two * 3)
+
+ def test_negative_binomial(self):
+ n = [1]
+ p = [0.5]
+ bad_n = [-1]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ desired = np.array([0, 2, 1], dtype=np.int64)
+
+ random = Generator(MT19937(self.seed))
+ neg_binom = random.negative_binomial
+ actual = neg_binom(n * 3, p)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, neg_binom, bad_n * 3, p)
+ assert_raises(ValueError, neg_binom, n * 3, bad_p_one)
+ assert_raises(ValueError, neg_binom, n * 3, bad_p_two)
+
+ random = Generator(MT19937(self.seed))
+ neg_binom = random.negative_binomial
+ actual = neg_binom(n, p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, neg_binom, bad_n, p * 3)
+ assert_raises(ValueError, neg_binom, n, bad_p_one * 3)
+ assert_raises(ValueError, neg_binom, n, bad_p_two * 3)
+
+ def test_poisson(self):
+
+ lam = [1]
+ bad_lam_one = [-1]
+ desired = np.array([0, 0, 3])
+
+ random = Generator(MT19937(self.seed))
+ max_lam = random._poisson_lam_max
+ bad_lam_two = [max_lam * 2]
+ poisson = random.poisson
+ actual = poisson(lam * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, poisson, bad_lam_one * 3)
+ assert_raises(ValueError, poisson, bad_lam_two * 3)
+
+ def test_zipf(self):
+ a = [2]
+ bad_a = [0]
+ desired = np.array([1, 8, 1])
+
+ random = Generator(MT19937(self.seed))
+ zipf = random.zipf
+ actual = zipf(a * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, zipf, bad_a * 3)
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, zipf, np.nan)
+ assert_raises(ValueError, zipf, [0, 0, np.nan])
+
+ def test_geometric(self):
+ p = [0.5]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ desired = np.array([1, 1, 3])
+
+ random = Generator(MT19937(self.seed))
+ geometric = random.geometric
+ actual = geometric(p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, geometric, bad_p_one * 3)
+ assert_raises(ValueError, geometric, bad_p_two * 3)
+
+ def test_hypergeometric(self):
+ ngood = [1]
+ nbad = [2]
+ nsample = [2]
+ bad_ngood = [-1]
+ bad_nbad = [-2]
+ bad_nsample_one = [-1]
+ bad_nsample_two = [4]
+ desired = np.array([0, 0, 1])
+
+ random = Generator(MT19937(self.seed))
+ actual = random.hypergeometric(ngood * 3, nbad, nsample)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, random.hypergeometric, bad_ngood * 3, nbad, nsample)
+ assert_raises(ValueError, random.hypergeometric, ngood * 3, bad_nbad, nsample)
+ assert_raises(ValueError, random.hypergeometric, ngood * 3, nbad, bad_nsample_one)
+ assert_raises(ValueError, random.hypergeometric, ngood * 3, nbad, bad_nsample_two)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.hypergeometric(ngood, nbad * 3, nsample)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, random.hypergeometric, bad_ngood, nbad * 3, nsample)
+ assert_raises(ValueError, random.hypergeometric, ngood, bad_nbad * 3, nsample)
+ assert_raises(ValueError, random.hypergeometric, ngood, nbad * 3, bad_nsample_one)
+ assert_raises(ValueError, random.hypergeometric, ngood, nbad * 3, bad_nsample_two)
+
+ random = Generator(MT19937(self.seed))
+ hypergeom = random.hypergeometric
+ actual = hypergeom(ngood, nbad, nsample * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, hypergeom, bad_ngood, nbad, nsample * 3)
+ assert_raises(ValueError, hypergeom, ngood, bad_nbad, nsample * 3)
+ assert_raises(ValueError, hypergeom, ngood, nbad, bad_nsample_one * 3)
+ assert_raises(ValueError, hypergeom, ngood, nbad, bad_nsample_two * 3)
+
+ assert_raises(ValueError, hypergeom, -1, 10, 20)
+ assert_raises(ValueError, hypergeom, 10, -1, 20)
+ assert_raises(ValueError, hypergeom, 10, 10, -1)
+ assert_raises(ValueError, hypergeom, 10, 10, 25)
+
+ # ValueError for arguments that are too big.
+ assert_raises(ValueError, hypergeom, 2**30, 10, 20)
+ assert_raises(ValueError, hypergeom, 999, 2**31, 50)
+ assert_raises(ValueError, hypergeom, 999, [2**29, 2**30], 1000)
+
+ def test_logseries(self):
+ p = [0.5]
+ bad_p_one = [2]
+ bad_p_two = [-1]
+ desired = np.array([1, 1, 1])
+
+ random = Generator(MT19937(self.seed))
+ logseries = random.logseries
+ actual = logseries(p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, logseries, bad_p_one * 3)
+ assert_raises(ValueError, logseries, bad_p_two * 3)
+
+ def test_multinomial(self):
+ random = Generator(MT19937(self.seed))
+ actual = random.multinomial([5, 20], [1 / 6.] * 6, size=(3, 2))
+ desired = np.array([[[0, 0, 2, 1, 2, 0],
+ [2, 3, 6, 4, 2, 3]],
+ [[1, 0, 1, 0, 2, 1],
+ [7, 2, 2, 1, 4, 4]],
+ [[0, 2, 0, 1, 2, 0],
+ [3, 2, 3, 3, 4, 5]]], dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+ random = Generator(MT19937(self.seed))
+ actual = random.multinomial([5, 20], [1 / 6.] * 6)
+ desired = np.array([[0, 0, 2, 1, 2, 0],
+ [2, 3, 6, 4, 2, 3]], dtype=np.int64)
+ assert_array_equal(actual, desired)
+
+
+class TestThread(object):
+ # make sure each state produces the same sequence even in threads
+ def setup(self):
+ self.seeds = range(4)
+
+ def check_function(self, function, sz):
+ from threading import Thread
+
+ out1 = np.empty((len(self.seeds),) + sz)
+ out2 = np.empty((len(self.seeds),) + sz)
+
+ # threaded generation
+ t = [Thread(target=function, args=(Generator(MT19937(s)), o))
+ for s, o in zip(self.seeds, out1)]
+ [x.start() for x in t]
+ [x.join() for x in t]
+
+ # the same serial
+ for s, o in zip(self.seeds, out2):
+ function(Generator(MT19937(s)), o)
+
+ # these platforms change x87 fpu precision mode in threads
+ if np.intp().dtype.itemsize == 4 and sys.platform == "win32":
+ assert_array_almost_equal(out1, out2)
+ else:
+ assert_array_equal(out1, out2)
+
+ def test_normal(self):
+ def gen_random(state, out):
+ out[...] = state.normal(size=10000)
+
+ self.check_function(gen_random, sz=(10000,))
+
+ def test_exp(self):
+ def gen_random(state, out):
+ out[...] = state.exponential(scale=np.ones((100, 1000)))
+
+ self.check_function(gen_random, sz=(100, 1000))
+
+ def test_multinomial(self):
+ def gen_random(state, out):
+ out[...] = state.multinomial(10, [1 / 6.] * 6, size=10000)
+
+ self.check_function(gen_random, sz=(10000, 6))
+
+
+# See Issue #4263
+class TestSingleEltArrayInput(object):
+ def setup(self):
+ self.argOne = np.array([2])
+ self.argTwo = np.array([3])
+ self.argThree = np.array([4])
+ self.tgtShape = (1,)
+
+ def test_one_arg_funcs(self):
+ funcs = (random.exponential, random.standard_gamma,
+ random.chisquare, random.standard_t,
+ random.pareto, random.weibull,
+ random.power, random.rayleigh,
+ random.poisson, random.zipf,
+ random.geometric, random.logseries)
+
+ probfuncs = (random.geometric, random.logseries)
+
+ for func in funcs:
+ if func in probfuncs: # p < 1.0
+ out = func(np.array([0.5]))
+
+ else:
+ out = func(self.argOne)
+
+ assert_equal(out.shape, self.tgtShape)
+
+ def test_two_arg_funcs(self):
+ funcs = (random.uniform, random.normal,
+ random.beta, random.gamma,
+ random.f, random.noncentral_chisquare,
+ random.vonmises, random.laplace,
+ random.gumbel, random.logistic,
+ random.lognormal, random.wald,
+ random.binomial, random.negative_binomial)
+
+ probfuncs = (random.binomial, random.negative_binomial)
+
+ for func in funcs:
+ if func in probfuncs: # p <= 1
+ argTwo = np.array([0.5])
+
+ else:
+ argTwo = self.argTwo
+
+ out = func(self.argOne, argTwo)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne[0], argTwo)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne, argTwo[0])
+ assert_equal(out.shape, self.tgtShape)
+
+ def test_integers(self, endpoint):
+ itype = [np.bool, np.int8, np.uint8, np.int16, np.uint16,
+ np.int32, np.uint32, np.int64, np.uint64]
+ func = random.integers
+ high = np.array([1])
+ low = np.array([0])
+
+ for dt in itype:
+ out = func(low, high, endpoint=endpoint, dtype=dt)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(low[0], high, endpoint=endpoint, dtype=dt)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(low, high[0], endpoint=endpoint, dtype=dt)
+ assert_equal(out.shape, self.tgtShape)
+
+ def test_three_arg_funcs(self):
+ funcs = [random.noncentral_f, random.triangular,
+ random.hypergeometric]
+
+ for func in funcs:
+ out = func(self.argOne, self.argTwo, self.argThree)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne[0], self.argTwo, self.argThree)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne, self.argTwo[0], self.argThree)
+ assert_equal(out.shape, self.tgtShape)
diff --git a/numpy/random/tests/test_generator_mt19937_regressions.py b/numpy/random/tests/test_generator_mt19937_regressions.py
new file mode 100644
index 000000000..3a937f997
--- /dev/null
+++ b/numpy/random/tests/test_generator_mt19937_regressions.py
@@ -0,0 +1,158 @@
+import sys
+from numpy.testing import (assert_, assert_array_equal)
+from numpy.compat import long
+import numpy as np
+import pytest
+from numpy.random import Generator, MT19937
+
+mt19937 = Generator(MT19937())
+
+
+class TestRegression(object):
+
+ def test_VonMises_range(self):
+ # Make sure generated random variables are in [-pi, pi].
+ # Regression test for ticket #986.
+ for mu in np.linspace(-7., 7., 5):
+ r = mt19937.vonmises(mu, 1, 50)
+ assert_(np.all(r > -np.pi) and np.all(r <= np.pi))
+
+ def test_hypergeometric_range(self):
+ # Test for ticket #921
+ assert_(np.all(mt19937.hypergeometric(3, 18, 11, size=10) < 4))
+ assert_(np.all(mt19937.hypergeometric(18, 3, 11, size=10) > 0))
+
+ # Test for ticket #5623
+ args = (2**20 - 2, 2**20 - 2, 2**20 - 2) # Check for 32-bit systems
+ assert_(mt19937.hypergeometric(*args) > 0)
+
+ def test_logseries_convergence(self):
+ # Test for ticket #923
+ N = 1000
+ mt19937 = Generator(MT19937(0))
+ rvsn = mt19937.logseries(0.8, size=N)
+ # these two frequency counts should be close to theoretical
+ # numbers with this large sample
+ # theoretical large N result is 0.49706795
+ freq = np.sum(rvsn == 1) / float(N)
+ msg = "Frequency was %f, should be > 0.45" % freq
+ assert_(freq > 0.45, msg)
+ # theoretical large N result is 0.19882718
+ freq = np.sum(rvsn == 2) / float(N)
+ msg = "Frequency was %f, should be < 0.23" % freq
+ assert_(freq < 0.23, msg)
+
+ def test_permutation_longs(self):
+ mt19937 = Generator(MT19937(1234))
+ a = mt19937.permutation(12)
+ mt19937 = Generator(MT19937(1234))
+ b = mt19937.permutation(long(12))
+ assert_array_equal(a, b)
+
+ def test_shuffle_mixed_dimension(self):
+ # Test for trac ticket #2074
+ for t in [[1, 2, 3, None],
+ [(1, 1), (2, 2), (3, 3), None],
+ [1, (2, 2), (3, 3), None],
+ [(1, 1), 2, 3, None]]:
+ mt19937 = Generator(MT19937(12345))
+ shuffled = list(t)
+ mt19937.shuffle(shuffled)
+ assert_array_equal(shuffled, [t[2], t[0], t[3], t[1]])
+
+ def test_call_within_randomstate(self):
+ # Check that custom BitGenerator does not call into global state
+ res = np.array([1, 8, 0, 1, 5, 3, 3, 8, 1, 4])
+ for i in range(3):
+ mt19937 = Generator(MT19937(i))
+ m = Generator(MT19937(4321))
+ # If m.state is not honored, the result will change
+ assert_array_equal(m.choice(10, size=10, p=np.ones(10)/10.), res)
+
+ def test_multivariate_normal_size_types(self):
+ # Test for multivariate_normal issue with 'size' argument.
+ # Check that the multivariate_normal size argument can be a
+ # numpy integer.
+ mt19937.multivariate_normal([0], [[0]], size=1)
+ mt19937.multivariate_normal([0], [[0]], size=np.int_(1))
+ mt19937.multivariate_normal([0], [[0]], size=np.int64(1))
+
+ def test_beta_small_parameters(self):
+ # Test that beta with small a and b parameters does not produce
+ # NaNs due to roundoff errors causing 0 / 0, gh-5851
+ mt19937 = Generator(MT19937(1234567890))
+ x = mt19937.beta(0.0001, 0.0001, size=100)
+ assert_(not np.any(np.isnan(x)), 'Nans in mt19937.beta')
+
+ def test_choice_sum_of_probs_tolerance(self):
+ # The sum of probs should be 1.0 with some tolerance.
+ # For low precision dtypes the tolerance was too tight.
+ # See numpy github issue 6123.
+ mt19937 = Generator(MT19937(1234))
+ a = [1, 2, 3]
+ counts = [4, 4, 2]
+ for dt in np.float16, np.float32, np.float64:
+ probs = np.array(counts, dtype=dt) / sum(counts)
+ c = mt19937.choice(a, p=probs)
+ assert_(c in a)
+ with pytest.raises(ValueError):
+ mt19937.choice(a, p=probs*0.9)
+
+ def test_shuffle_of_array_of_different_length_strings(self):
+ # Test that permuting an array of different length strings
+ # will not cause a segfault on garbage collection
+ # Tests gh-7710
+ mt19937 = Generator(MT19937(1234))
+
+ a = np.array(['a', 'a' * 1000])
+
+ for _ in range(100):
+ mt19937.shuffle(a)
+
+ # Force Garbage Collection - should not segfault.
+ import gc
+ gc.collect()
+
+ def test_shuffle_of_array_of_objects(self):
+ # Test that permuting an array of objects will not cause
+ # a segfault on garbage collection.
+ # See gh-7719
+ mt19937 = Generator(MT19937(1234))
+ a = np.array([np.arange(1), np.arange(4)])
+
+ for _ in range(1000):
+ mt19937.shuffle(a)
+
+ # Force Garbage Collection - should not segfault.
+ import gc
+ gc.collect()
+
+ def test_permutation_subclass(self):
+ class N(np.ndarray):
+ pass
+
+ mt19937 = Generator(MT19937(1))
+ orig = np.arange(3).view(N)
+ perm = mt19937.permutation(orig)
+ assert_array_equal(perm, np.array([2, 0, 1]))
+ assert_array_equal(orig, np.arange(3).view(N))
+
+ class M(object):
+ a = np.arange(5)
+
+ def __array__(self):
+ return self.a
+
+ mt19937 = Generator(MT19937(1))
+ m = M()
+ perm = mt19937.permutation(m)
+ assert_array_equal(perm, np.array([4, 1, 3, 0, 2]))
+ assert_array_equal(m.__array__(), np.arange(5))
+
+ def test_gamma_0(self):
+ assert mt19937.standard_gamma(0.0) == 0.0
+ assert_array_equal(mt19937.standard_gamma([0.0]), 0.0)
+
+ actual = mt19937.standard_gamma([0.0], dtype='float')
+ expected = np.array([0.], dtype=np.float32)
+ assert_array_equal(actual, expected)
diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py
index 4529b4fbd..37bd121f3 100644
--- a/numpy/random/tests/test_random.py
+++ b/numpy/random/tests/test_random.py
@@ -43,7 +43,8 @@ class TestSeed(object):
def test_invalid_array_shape(self):
# gh-9832
- assert_raises(ValueError, np.random.RandomState, np.array([], dtype=np.int64))
+ assert_raises(ValueError, np.random.RandomState,
+ np.array([], dtype=np.int64))
assert_raises(ValueError, np.random.RandomState, [[1, 2, 3]])
assert_raises(ValueError, np.random.RandomState, [[1, 2, 3],
[4, 5, 6]])
@@ -349,9 +350,9 @@ class TestRandomDist(object):
np.random.random_integers,
np.iinfo('l').max, np.iinfo('l').max)
- def test_random_sample(self):
+ def test_random(self):
np.random.seed(self.seed)
- actual = np.random.random_sample((3, 2))
+ actual = np.random.random((3, 2))
desired = np.array([[0.61879477158567997, 0.59162362775974664],
[0.88868358904449662, 0.89165480011560816],
[0.4575674820298663, 0.7781880808593471]])
@@ -449,7 +450,8 @@ class TestRandomDist(object):
assert_equal(np.random.randint(10, 10, size=0).shape, (0,))
assert_equal(np.random.choice(0, size=0).shape, (0,))
assert_equal(np.random.choice([], size=(0,)).shape, (0,))
- assert_equal(np.random.choice(['a', 'b'], size=(3, 0, 4)).shape, (3, 0, 4))
+ assert_equal(np.random.choice(['a', 'b'], size=(3, 0, 4)).shape,
+ (3, 0, 4))
assert_raises(ValueError, np.random.choice, [], 10)
def test_choice_nan_probabilities(self):
@@ -481,8 +483,7 @@ class TestRandomDist(object):
.view(np.recarray)),
# gh-4270
lambda x: np.asarray([(i, i) for i in x],
- [("a", object, 1),
- ("b", np.int32, 1)])]:
+ [("a", object), ("b", np.int32)])]:
np.random.seed(self.seed)
alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
np.random.shuffle(alist)
@@ -515,7 +516,7 @@ class TestRandomDist(object):
def test_binomial(self):
np.random.seed(self.seed)
- actual = np.random.binomial(100.123, .456, size=(3, 2))
+ actual = np.random.binomial(100, .456, size=(3, 2))
desired = np.array([[37, 43],
[42, 48],
[46, 45]])
@@ -612,7 +613,7 @@ class TestRandomDist(object):
def test_hypergeometric(self):
np.random.seed(self.seed)
- actual = np.random.hypergeometric(10.1, 5.5, 14, size=(3, 2))
+ actual = np.random.hypergeometric(10, 5, 14, size=(3, 2))
desired = np.array([[10, 10],
[10, 10],
[9, 9]])
@@ -693,7 +694,7 @@ class TestRandomDist(object):
cov = [[1, 0], [0, 1]]
size = (3, 2)
actual = np.random.multivariate_normal(mean, cov, size)
- desired = np.array([[[1.463620246718631, 11.73759122771936 ],
+ desired = np.array([[[1.463620246718631, 11.73759122771936],
[1.622445133300628, 9.771356667546383]],
[[2.154490787682787, 12.170324946056553],
[1.719909438201865, 9.230548443648306]],
@@ -721,7 +722,7 @@ class TestRandomDist(object):
assert_raises(ValueError, np.random.multivariate_normal, mean, cov,
check_valid='raise')
- cov = np.array([[1, 0.1],[0.1, 1]], dtype=np.float32)
+ cov = np.array([[1, 0.1], [0.1, 1]], dtype=np.float32)
with suppress_warnings() as sup:
np.random.multivariate_normal(mean, cov)
w = sup.record(RuntimeWarning)
@@ -917,12 +918,15 @@ class TestRandomDist(object):
raise TypeError
throwing_float = np.array(1.0).view(ThrowingFloat)
- assert_raises(TypeError, np.random.uniform, throwing_float, throwing_float)
+ assert_raises(TypeError, np.random.uniform, throwing_float,
+ throwing_float)
class ThrowingInteger(np.ndarray):
def __int__(self):
raise TypeError
+ __index__ = __int__
+
throwing_int = np.array(1).view(ThrowingInteger)
assert_raises(TypeError, np.random.hypergeometric, throwing_int, 1, 1)
@@ -1364,6 +1368,8 @@ class TestBroadcast(object):
assert_array_almost_equal(actual, desired, decimal=14)
assert_raises(ValueError, wald, bad_mean, scale * 3)
assert_raises(ValueError, wald, mean, bad_scale * 3)
+ assert_raises(ValueError, wald, 0.0, 1)
+ assert_raises(ValueError, wald, 0.5, 0.0)
def test_triangular(self):
left = [1]
@@ -1382,21 +1388,24 @@ class TestBroadcast(object):
assert_array_almost_equal(actual, desired, decimal=14)
assert_raises(ValueError, triangular, bad_left_one * 3, mode, right)
assert_raises(ValueError, triangular, left * 3, bad_mode_one, right)
- assert_raises(ValueError, triangular, bad_left_two * 3, bad_mode_two, right)
+ assert_raises(ValueError, triangular, bad_left_two * 3, bad_mode_two,
+ right)
self.setSeed()
actual = triangular(left, mode * 3, right)
assert_array_almost_equal(actual, desired, decimal=14)
assert_raises(ValueError, triangular, bad_left_one, mode * 3, right)
assert_raises(ValueError, triangular, left, bad_mode_one * 3, right)
- assert_raises(ValueError, triangular, bad_left_two, bad_mode_two * 3, right)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two * 3,
+ right)
self.setSeed()
actual = triangular(left, mode, right * 3)
assert_array_almost_equal(actual, desired, decimal=14)
assert_raises(ValueError, triangular, bad_left_one, mode, right * 3)
assert_raises(ValueError, triangular, left, bad_mode_one, right * 3)
- assert_raises(ValueError, triangular, bad_left_two, bad_mode_two, right * 3)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two,
+ right * 3)
def test_binomial(self):
n = [1]
@@ -1445,7 +1454,7 @@ class TestBroadcast(object):
assert_raises(ValueError, neg_binom, n, bad_p_two * 3)
def test_poisson(self):
- max_lam = np.random.RandomState().poisson_lam_max
+ max_lam = np.random.RandomState()._poisson_lam_max
lam = [1]
bad_lam_one = [-1]
@@ -1534,6 +1543,7 @@ class TestBroadcast(object):
assert_raises(ValueError, logseries, bad_p_one * 3)
assert_raises(ValueError, logseries, bad_p_two * 3)
+
class TestThread(object):
# make sure each state produces the same sequence even in threads
def setup(self):
@@ -1576,6 +1586,7 @@ class TestThread(object):
out[...] = state.multinomial(10, [1/6.]*6, size=10000)
self.check_function(gen_random, sz=(10000, 6))
+
# See Issue #4263
class TestSingleEltArrayInput(object):
def setup(self):
diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py
new file mode 100644
index 000000000..3b5a279a3
--- /dev/null
+++ b/numpy/random/tests/test_randomstate.py
@@ -0,0 +1,1951 @@
+import hashlib
+import pickle
+import sys
+import warnings
+
+import numpy as np
+import pytest
+from numpy.testing import (
+ assert_, assert_raises, assert_equal, assert_warns,
+ assert_no_warnings, assert_array_equal, assert_array_almost_equal,
+ suppress_warnings
+ )
+
+from numpy.random import MT19937, PCG64, mtrand as random
+
+INT_FUNCS = {'binomial': (100.0, 0.6),
+ 'geometric': (.5,),
+ 'hypergeometric': (20, 20, 10),
+ 'logseries': (.5,),
+ 'multinomial': (20, np.ones(6) / 6.0),
+ 'negative_binomial': (100, .5),
+ 'poisson': (10.0,),
+ 'zipf': (2,),
+ }
+
+if np.iinfo(int).max < 2**32:
+ # Windows and some 32-bit platforms, e.g., ARM
+ INT_FUNC_HASHES = {'binomial': '670e1c04223ffdbab27e08fbbad7bdba',
+ 'logseries': '6bd0183d2f8030c61b0d6e11aaa60caf',
+ 'geometric': '6e9df886f3e1e15a643168568d5280c0',
+ 'hypergeometric': '7964aa611b046aecd33063b90f4dec06',
+ 'multinomial': '68a0b049c16411ed0aa4aff3572431e4',
+ 'negative_binomial': 'dc265219eec62b4338d39f849cd36d09',
+ 'poisson': '7b4dce8e43552fc82701c2fa8e94dc6e',
+ 'zipf': 'fcd2a2095f34578723ac45e43aca48c5',
+ }
+else:
+ INT_FUNC_HASHES = {'binomial': 'b5f8dcd74f172836536deb3547257b14',
+ 'geometric': '8814571f45c87c59699d62ccd3d6c350',
+ 'hypergeometric': 'bc64ae5976eac452115a16dad2dcf642',
+ 'logseries': '84be924b37485a27c4a98797bc88a7a4',
+ 'multinomial': 'ec3c7f9cf9664044bb0c6fb106934200',
+ 'negative_binomial': '210533b2234943591364d0117a552969',
+ 'poisson': '0536a8850c79da0c78defd742dccc3e0',
+ 'zipf': 'f2841f504dd2525cd67cdcad7561e532',
+ }
+
+
+@pytest.fixture(scope='module', params=INT_FUNCS)
+def int_func(request):
+ return (request.param, INT_FUNCS[request.param],
+ INT_FUNC_HASHES[request.param])
+
+
+def assert_mt19937_state_equal(a, b):
+ assert_equal(a['bit_generator'], b['bit_generator'])
+ assert_array_equal(a['state']['key'], b['state']['key'])
+ assert_array_equal(a['state']['pos'], b['state']['pos'])
+ assert_equal(a['has_gauss'], b['has_gauss'])
+ assert_equal(a['gauss'], b['gauss'])
+
+
+class TestSeed(object):
+ def test_scalar(self):
+ s = random.RandomState(0)
+ assert_equal(s.randint(1000), 684)
+ s = random.RandomState(4294967295)
+ assert_equal(s.randint(1000), 419)
+
+ def test_array(self):
+ s = random.RandomState(range(10))
+ assert_equal(s.randint(1000), 468)
+ s = random.RandomState(np.arange(10))
+ assert_equal(s.randint(1000), 468)
+ s = random.RandomState([0])
+ assert_equal(s.randint(1000), 973)
+ s = random.RandomState([4294967295])
+ assert_equal(s.randint(1000), 265)
+
+ def test_invalid_scalar(self):
+ # seed must be an unsigned 32 bit integer
+ assert_raises(TypeError, random.RandomState, -0.5)
+ assert_raises(ValueError, random.RandomState, -1)
+
+ def test_invalid_array(self):
+ # seed must be an unsigned 32 bit integer
+ assert_raises(TypeError, random.RandomState, [-0.5])
+ assert_raises(ValueError, random.RandomState, [-1])
+ assert_raises(ValueError, random.RandomState, [4294967296])
+ assert_raises(ValueError, random.RandomState, [1, 2, 4294967296])
+ assert_raises(ValueError, random.RandomState, [1, -2, 4294967296])
+
+ def test_invalid_array_shape(self):
+ # gh-9832
+ assert_raises(ValueError, random.RandomState, np.array([],
+ dtype=np.int64))
+ assert_raises(ValueError, random.RandomState, [[1, 2, 3]])
+ assert_raises(ValueError, random.RandomState, [[1, 2, 3],
+ [4, 5, 6]])
+
+ def test_cannot_seed(self):
+ rs = random.RandomState(PCG64(0))
+ with assert_raises(TypeError):
+ rs.seed(1234)
+
+ def test_invalid_initialization(self):
+ assert_raises(ValueError, random.RandomState, MT19937)
+
+
+class TestBinomial(object):
+ def test_n_zero(self):
+ # Tests the corner case of n == 0 for the binomial distribution.
+ # binomial(0, p) should be zero for any p in [0, 1].
+ # This test addresses issue #3480.
+ zeros = np.zeros(2, dtype='int')
+ for p in [0, .5, 1]:
+ assert_(random.binomial(0, p) == 0)
+ assert_array_equal(random.binomial(zeros, p), zeros)
+
+ def test_p_is_nan(self):
+ # Issue #4571.
+ assert_raises(ValueError, random.binomial, 1, np.nan)
+
+
+class TestMultinomial(object):
+ def test_basic(self):
+ random.multinomial(100, [0.2, 0.8])
+
+ def test_zero_probability(self):
+ random.multinomial(100, [0.2, 0.8, 0.0, 0.0, 0.0])
+
+ def test_int_negative_interval(self):
+ assert_(-5 <= random.randint(-5, -1) < -1)
+ x = random.randint(-5, -1, 5)
+ assert_(np.all(-5 <= x))
+ assert_(np.all(x < -1))
+
+ def test_size(self):
+ # gh-3173
+ p = [0.5, 0.5]
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.multinomial(1, p, [2, 2]).shape, (2, 2, 2))
+ assert_equal(random.multinomial(1, p, (2, 2)).shape, (2, 2, 2))
+ assert_equal(random.multinomial(1, p, np.array((2, 2))).shape,
+ (2, 2, 2))
+
+ assert_raises(TypeError, random.multinomial, 1, p,
+ float(1))
+
+ def test_invalid_prob(self):
+ assert_raises(ValueError, random.multinomial, 100, [1.1, 0.2])
+ assert_raises(ValueError, random.multinomial, 100, [-.1, 0.9])
+
+ def test_invalid_n(self):
+ assert_raises(ValueError, random.multinomial, -1, [0.8, 0.2])
+
+ def test_p_non_contiguous(self):
+ p = np.arange(15.)
+ p /= np.sum(p[1::3])
+ pvals = p[1::3]
+ random.seed(1432985819)
+ non_contig = random.multinomial(100, pvals=pvals)
+ random.seed(1432985819)
+ contig = random.multinomial(100, pvals=np.ascontiguousarray(pvals))
+ assert_array_equal(non_contig, contig)
+
+
+class TestSetState(object):
+ def setup(self):
+ self.seed = 1234567890
+ self.random_state = random.RandomState(self.seed)
+ self.state = self.random_state.get_state()
+
+ def test_basic(self):
+ old = self.random_state.tomaxint(16)
+ self.random_state.set_state(self.state)
+ new = self.random_state.tomaxint(16)
+ assert_(np.all(old == new))
+
+ def test_gaussian_reset(self):
+ # Make sure the cached every-other-Gaussian is reset.
+ old = self.random_state.standard_normal(size=3)
+ self.random_state.set_state(self.state)
+ new = self.random_state.standard_normal(size=3)
+ assert_(np.all(old == new))
+
+ def test_gaussian_reset_in_media_res(self):
+ # When the state is saved with a cached Gaussian, make sure the
+ # cached Gaussian is restored.
+
+ self.random_state.standard_normal()
+ state = self.random_state.get_state()
+ old = self.random_state.standard_normal(size=3)
+ self.random_state.set_state(state)
+ new = self.random_state.standard_normal(size=3)
+ assert_(np.all(old == new))
+
+ def test_backwards_compatibility(self):
+ # Make sure we can accept old state tuples that do not have the
+ # cached Gaussian value.
+ old_state = self.state[:-2]
+ x1 = self.random_state.standard_normal(size=16)
+ self.random_state.set_state(old_state)
+ x2 = self.random_state.standard_normal(size=16)
+ self.random_state.set_state(self.state)
+ x3 = self.random_state.standard_normal(size=16)
+ assert_(np.all(x1 == x2))
+ assert_(np.all(x1 == x3))
+
+ def test_negative_binomial(self):
+ # Ensure that the negative binomial results take floating point
+ # arguments without truncation.
+ self.random_state.negative_binomial(0.5, 0.5)
+
+ def test_get_state_warning(self):
+ rs = random.RandomState(PCG64())
+ with suppress_warnings() as sup:
+ w = sup.record(RuntimeWarning)
+ state = rs.get_state()
+ assert_(len(w) == 1)
+ assert isinstance(state, dict)
+ assert state['bit_generator'] == 'PCG64'
+
+ def test_invalid_legacy_state_setting(self):
+ state = self.random_state.get_state()
+ new_state = ('Unknown', ) + state[1:]
+ assert_raises(ValueError, self.random_state.set_state, new_state)
+ assert_raises(TypeError, self.random_state.set_state,
+ np.array(new_state, dtype=np.object))
+ state = self.random_state.get_state(legacy=False)
+ del state['bit_generator']
+ assert_raises(ValueError, self.random_state.set_state, state)
+
+ def test_pickle(self):
+ self.random_state.seed(0)
+ self.random_state.random_sample(100)
+ self.random_state.standard_normal()
+ pickled = self.random_state.get_state(legacy=False)
+ assert_equal(pickled['has_gauss'], 1)
+ rs_unpick = pickle.loads(pickle.dumps(self.random_state))
+ unpickled = rs_unpick.get_state(legacy=False)
+ assert_mt19937_state_equal(pickled, unpickled)
+
+ def test_state_setting(self):
+ attr_state = self.random_state.__getstate__()
+ self.random_state.standard_normal()
+ self.random_state.__setstate__(attr_state)
+ state = self.random_state.get_state(legacy=False)
+ assert_mt19937_state_equal(attr_state, state)
+
+ def test_repr(self):
+ assert repr(self.random_state).startswith('RandomState(MT19937)')
+
+
+class TestRandint(object):
+
+ rfunc = random.randint
+
+ # valid integer/boolean types
+ itype = [np.bool_, np.int8, np.uint8, np.int16, np.uint16,
+ np.int32, np.uint32, np.int64, np.uint64]
+
+ def test_unsupported_type(self):
+ assert_raises(TypeError, self.rfunc, 1, dtype=float)
+
+ def test_bounds_checking(self):
+ for dt in self.itype:
+ lbnd = 0 if dt is np.bool_ else np.iinfo(dt).min
+ ubnd = 2 if dt is np.bool_ else np.iinfo(dt).max + 1
+ assert_raises(ValueError, self.rfunc, lbnd - 1, ubnd, dtype=dt)
+ assert_raises(ValueError, self.rfunc, lbnd, ubnd + 1, dtype=dt)
+ assert_raises(ValueError, self.rfunc, ubnd, lbnd, dtype=dt)
+ assert_raises(ValueError, self.rfunc, 1, 0, dtype=dt)
+
+ def test_rng_zero_and_extremes(self):
+ for dt in self.itype:
+ lbnd = 0 if dt is np.bool_ else np.iinfo(dt).min
+ ubnd = 2 if dt is np.bool_ else np.iinfo(dt).max + 1
+
+ tgt = ubnd - 1
+ assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt)
+
+ tgt = lbnd
+ assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt)
+
+ tgt = (lbnd + ubnd)//2
+ assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt)
+
+ def test_full_range(self):
+ # Test for ticket #1690
+
+ for dt in self.itype:
+ lbnd = 0 if dt is np.bool_ else np.iinfo(dt).min
+ ubnd = 2 if dt is np.bool_ else np.iinfo(dt).max + 1
+
+ try:
+ self.rfunc(lbnd, ubnd, dtype=dt)
+ except Exception as e:
+ raise AssertionError("No error should have been raised, "
+ "but one was with the following "
+ "message:\n\n%s" % str(e))
+
+ def test_in_bounds_fuzz(self):
+ # Don't use fixed seed
+ random.seed()
+
+ for dt in self.itype[1:]:
+ for ubnd in [4, 8, 16]:
+ vals = self.rfunc(2, ubnd, size=2**16, dtype=dt)
+ assert_(vals.max() < ubnd)
+ assert_(vals.min() >= 2)
+
+ vals = self.rfunc(0, 2, size=2**16, dtype=np.bool_)
+
+ assert_(vals.max() < 2)
+ assert_(vals.min() >= 0)
+
+ def test_repeatability(self):
+ # We use a md5 hash of generated sequences of 1000 samples
+ # in the range [0, 6) for all but bool, where the range
+ # is [0, 2). Hashes are for little endian numbers.
+ tgt = {'bool': '7dd3170d7aa461d201a65f8bcf3944b0',
+ 'int16': '1b7741b80964bb190c50d541dca1cac1',
+ 'int32': '4dc9fcc2b395577ebb51793e58ed1a05',
+ 'int64': '17db902806f448331b5a758d7d2ee672',
+ 'int8': '27dd30c4e08a797063dffac2490b0be6',
+ 'uint16': '1b7741b80964bb190c50d541dca1cac1',
+ 'uint32': '4dc9fcc2b395577ebb51793e58ed1a05',
+ 'uint64': '17db902806f448331b5a758d7d2ee672',
+ 'uint8': '27dd30c4e08a797063dffac2490b0be6'}
+
+ for dt in self.itype[1:]:
+ random.seed(1234)
+
+ # view as little endian for hash
+ if sys.byteorder == 'little':
+ val = self.rfunc(0, 6, size=1000, dtype=dt)
+ else:
+ val = self.rfunc(0, 6, size=1000, dtype=dt).byteswap()
+
+ res = hashlib.md5(val.view(np.int8)).hexdigest()
+ assert_(tgt[np.dtype(dt).name] == res)
+
+ # bools do not depend on endianness
+ random.seed(1234)
+ val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8)
+ res = hashlib.md5(val).hexdigest()
+ assert_(tgt[np.dtype(bool).name] == res)
+
+ def test_int64_uint64_corner_case(self):
+ # When stored in Numpy arrays, `lbnd` is casted
+ # as np.int64, and `ubnd` is casted as np.uint64.
+ # Checking whether `lbnd` >= `ubnd` used to be
+ # done solely via direct comparison, which is incorrect
+ # because when Numpy tries to compare both numbers,
+ # it casts both to np.float64 because there is
+ # no integer superset of np.int64 and np.uint64. However,
+ # `ubnd` is too large to be represented in np.float64,
+ # causing it be round down to np.iinfo(np.int64).max,
+ # leading to a ValueError because `lbnd` now equals
+ # the new `ubnd`.
+
+ dt = np.int64
+ tgt = np.iinfo(np.int64).max
+ lbnd = np.int64(np.iinfo(np.int64).max)
+ ubnd = np.uint64(np.iinfo(np.int64).max + 1)
+
+ # None of these function calls should
+ # generate a ValueError now.
+ actual = random.randint(lbnd, ubnd, dtype=dt)
+ assert_equal(actual, tgt)
+
+ def test_respect_dtype_singleton(self):
+ # See gh-7203
+ for dt in self.itype:
+ lbnd = 0 if dt is np.bool_ else np.iinfo(dt).min
+ ubnd = 2 if dt is np.bool_ else np.iinfo(dt).max + 1
+
+ sample = self.rfunc(lbnd, ubnd, dtype=dt)
+ assert_equal(sample.dtype, np.dtype(dt))
+
+ for dt in (bool, int, np.long):
+ lbnd = 0 if dt is bool else np.iinfo(dt).min
+ ubnd = 2 if dt is bool else np.iinfo(dt).max + 1
+
+ # gh-7284: Ensure that we get Python data types
+ sample = self.rfunc(lbnd, ubnd, dtype=dt)
+ assert_(not hasattr(sample, 'dtype'))
+ assert_equal(type(sample), dt)
+
+
+class TestRandomDist(object):
+ # Make sure the random distribution returns the correct value for a
+ # given seed
+
+ def setup(self):
+ self.seed = 1234567890
+
+ def test_rand(self):
+ random.seed(self.seed)
+ actual = random.rand(3, 2)
+ desired = np.array([[0.61879477158567997, 0.59162362775974664],
+ [0.88868358904449662, 0.89165480011560816],
+ [0.4575674820298663, 0.7781880808593471]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_rand_singleton(self):
+ random.seed(self.seed)
+ actual = random.rand()
+ desired = 0.61879477158567997
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_randn(self):
+ random.seed(self.seed)
+ actual = random.randn(3, 2)
+ desired = np.array([[1.34016345771863121, 1.73759122771936081],
+ [1.498988344300628, -0.2286433324536169],
+ [2.031033998682787, 2.17032494605655257]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ random.seed(self.seed)
+ actual = random.randn()
+ assert_array_almost_equal(actual, desired[0, 0], decimal=15)
+
+ def test_randint(self):
+ random.seed(self.seed)
+ actual = random.randint(-99, 99, size=(3, 2))
+ desired = np.array([[31, 3],
+ [-52, 41],
+ [-48, -66]])
+ assert_array_equal(actual, desired)
+
+ def test_random_integers(self):
+ random.seed(self.seed)
+ with suppress_warnings() as sup:
+ w = sup.record(DeprecationWarning)
+ actual = random.random_integers(-99, 99, size=(3, 2))
+ assert_(len(w) == 1)
+ desired = np.array([[31, 3],
+ [-52, 41],
+ [-48, -66]])
+ assert_array_equal(actual, desired)
+
+ random.seed(self.seed)
+ with suppress_warnings() as sup:
+ w = sup.record(DeprecationWarning)
+ actual = random.random_integers(198, size=(3, 2))
+ assert_(len(w) == 1)
+ assert_array_equal(actual, desired + 100)
+
+ def test_tomaxint(self):
+ random.seed(self.seed)
+ rs = random.RandomState(self.seed)
+ actual = rs.tomaxint(size=(3, 2))
+ if np.iinfo(np.int).max == 2147483647:
+ desired = np.array([[1328851649, 731237375],
+ [1270502067, 320041495],
+ [1908433478, 499156889]], dtype=np.int64)
+ else:
+ desired = np.array([[5707374374421908479, 5456764827585442327],
+ [8196659375100692377, 8224063923314595285],
+ [4220315081820346526, 7177518203184491332]],
+ dtype=np.int64)
+
+ assert_equal(actual, desired)
+
+ rs.seed(self.seed)
+ actual = rs.tomaxint()
+ assert_equal(actual, desired[0, 0])
+
+ def test_random_integers_max_int(self):
+ # Tests whether random_integers can generate the
+ # maximum allowed Python int that can be converted
+ # into a C long. Previous implementations of this
+ # method have thrown an OverflowError when attempting
+ # to generate this integer.
+ with suppress_warnings() as sup:
+ w = sup.record(DeprecationWarning)
+ actual = random.random_integers(np.iinfo('l').max,
+ np.iinfo('l').max)
+ assert_(len(w) == 1)
+
+ desired = np.iinfo('l').max
+ assert_equal(actual, desired)
+ with suppress_warnings() as sup:
+ w = sup.record(DeprecationWarning)
+ typer = np.dtype('l').type
+ actual = random.random_integers(typer(np.iinfo('l').max),
+ typer(np.iinfo('l').max))
+ assert_(len(w) == 1)
+ assert_equal(actual, desired)
+
+ def test_random_integers_deprecated(self):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error", DeprecationWarning)
+
+ # DeprecationWarning raised with high == None
+ assert_raises(DeprecationWarning,
+ random.random_integers,
+ np.iinfo('l').max)
+
+ # DeprecationWarning raised with high != None
+ assert_raises(DeprecationWarning,
+ random.random_integers,
+ np.iinfo('l').max, np.iinfo('l').max)
+
+ def test_random_sample(self):
+ random.seed(self.seed)
+ actual = random.random_sample((3, 2))
+ desired = np.array([[0.61879477158567997, 0.59162362775974664],
+ [0.88868358904449662, 0.89165480011560816],
+ [0.4575674820298663, 0.7781880808593471]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ random.seed(self.seed)
+ actual = random.random_sample()
+ assert_array_almost_equal(actual, desired[0, 0], decimal=15)
+
+ def test_choice_uniform_replace(self):
+ random.seed(self.seed)
+ actual = random.choice(4, 4)
+ desired = np.array([2, 3, 2, 3])
+ assert_array_equal(actual, desired)
+
+ def test_choice_nonuniform_replace(self):
+ random.seed(self.seed)
+ actual = random.choice(4, 4, p=[0.4, 0.4, 0.1, 0.1])
+ desired = np.array([1, 1, 2, 2])
+ assert_array_equal(actual, desired)
+
+ def test_choice_uniform_noreplace(self):
+ random.seed(self.seed)
+ actual = random.choice(4, 3, replace=False)
+ desired = np.array([0, 1, 3])
+ assert_array_equal(actual, desired)
+
+ def test_choice_nonuniform_noreplace(self):
+ random.seed(self.seed)
+ actual = random.choice(4, 3, replace=False, p=[0.1, 0.3, 0.5, 0.1])
+ desired = np.array([2, 3, 1])
+ assert_array_equal(actual, desired)
+
+ def test_choice_noninteger(self):
+ random.seed(self.seed)
+ actual = random.choice(['a', 'b', 'c', 'd'], 4)
+ desired = np.array(['c', 'd', 'c', 'd'])
+ assert_array_equal(actual, desired)
+
+ def test_choice_exceptions(self):
+ sample = random.choice
+ assert_raises(ValueError, sample, -1, 3)
+ assert_raises(ValueError, sample, 3., 3)
+ assert_raises(ValueError, sample, [[1, 2], [3, 4]], 3)
+ assert_raises(ValueError, sample, [], 3)
+ assert_raises(ValueError, sample, [1, 2, 3, 4], 3,
+ p=[[0.25, 0.25], [0.25, 0.25]])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[0.4, 0.4, 0.2])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[1.1, -0.1])
+ assert_raises(ValueError, sample, [1, 2], 3, p=[0.4, 0.4])
+ assert_raises(ValueError, sample, [1, 2, 3], 4, replace=False)
+ # gh-13087
+ assert_raises(ValueError, sample, [1, 2, 3], -2, replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], (-1,), replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], (-1, 1), replace=False)
+ assert_raises(ValueError, sample, [1, 2, 3], 2,
+ replace=False, p=[1, 0, 0])
+
+ def test_choice_return_shape(self):
+ p = [0.1, 0.9]
+ # Check scalar
+ assert_(np.isscalar(random.choice(2, replace=True)))
+ assert_(np.isscalar(random.choice(2, replace=False)))
+ assert_(np.isscalar(random.choice(2, replace=True, p=p)))
+ assert_(np.isscalar(random.choice(2, replace=False, p=p)))
+ assert_(np.isscalar(random.choice([1, 2], replace=True)))
+ assert_(random.choice([None], replace=True) is None)
+ a = np.array([1, 2])
+ arr = np.empty(1, dtype=object)
+ arr[0] = a
+ assert_(random.choice(arr, replace=True) is a)
+
+ # Check 0-d array
+ s = tuple()
+ assert_(not np.isscalar(random.choice(2, s, replace=True)))
+ assert_(not np.isscalar(random.choice(2, s, replace=False)))
+ assert_(not np.isscalar(random.choice(2, s, replace=True, p=p)))
+ assert_(not np.isscalar(random.choice(2, s, replace=False, p=p)))
+ assert_(not np.isscalar(random.choice([1, 2], s, replace=True)))
+ assert_(random.choice([None], s, replace=True).ndim == 0)
+ a = np.array([1, 2])
+ arr = np.empty(1, dtype=object)
+ arr[0] = a
+ assert_(random.choice(arr, s, replace=True).item() is a)
+
+ # Check multi dimensional array
+ s = (2, 3)
+ p = [0.1, 0.1, 0.1, 0.1, 0.4, 0.2]
+ assert_equal(random.choice(6, s, replace=True).shape, s)
+ assert_equal(random.choice(6, s, replace=False).shape, s)
+ assert_equal(random.choice(6, s, replace=True, p=p).shape, s)
+ assert_equal(random.choice(6, s, replace=False, p=p).shape, s)
+ assert_equal(random.choice(np.arange(6), s, replace=True).shape, s)
+
+ # Check zero-size
+ assert_equal(random.randint(0, 0, size=(3, 0, 4)).shape, (3, 0, 4))
+ assert_equal(random.randint(0, -10, size=0).shape, (0,))
+ assert_equal(random.randint(10, 10, size=0).shape, (0,))
+ assert_equal(random.choice(0, size=0).shape, (0,))
+ assert_equal(random.choice([], size=(0,)).shape, (0,))
+ assert_equal(random.choice(['a', 'b'], size=(3, 0, 4)).shape,
+ (3, 0, 4))
+ assert_raises(ValueError, random.choice, [], 10)
+
+ def test_choice_nan_probabilities(self):
+ a = np.array([42, 1, 2])
+ p = [None, None, None]
+ assert_raises(ValueError, random.choice, a, p=p)
+
+ def test_choice_p_non_contiguous(self):
+ p = np.ones(10) / 5
+ p[1::2] = 3.0
+ random.seed(self.seed)
+ non_contig = random.choice(5, 3, p=p[::2])
+ random.seed(self.seed)
+ contig = random.choice(5, 3, p=np.ascontiguousarray(p[::2]))
+ assert_array_equal(non_contig, contig)
+
+ def test_bytes(self):
+ random.seed(self.seed)
+ actual = random.bytes(10)
+ desired = b'\x82Ui\x9e\xff\x97+Wf\xa5'
+ assert_equal(actual, desired)
+
+ def test_shuffle(self):
+ # Test lists, arrays (of various dtypes), and multidimensional versions
+ # of both, c-contiguous or not:
+ for conv in [lambda x: np.array([]),
+ lambda x: x,
+ lambda x: np.asarray(x).astype(np.int8),
+ lambda x: np.asarray(x).astype(np.float32),
+ lambda x: np.asarray(x).astype(np.complex64),
+ lambda x: np.asarray(x).astype(object),
+ lambda x: [(i, i) for i in x],
+ lambda x: np.asarray([[i, i] for i in x]),
+ lambda x: np.vstack([x, x]).T,
+ # gh-11442
+ lambda x: (np.asarray([(i, i) for i in x],
+ [("a", int), ("b", int)])
+ .view(np.recarray)),
+ # gh-4270
+ lambda x: np.asarray([(i, i) for i in x],
+ [("a", object, (1,)),
+ ("b", np.int32, (1,))])]:
+ random.seed(self.seed)
+ alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
+ random.shuffle(alist)
+ actual = alist
+ desired = conv([0, 1, 9, 6, 2, 4, 5, 8, 7, 3])
+ assert_array_equal(actual, desired)
+
+ def test_shuffle_masked(self):
+ # gh-3263
+ a = np.ma.masked_values(np.reshape(range(20), (5, 4)) % 3 - 1, -1)
+ b = np.ma.masked_values(np.arange(20) % 3 - 1, -1)
+ a_orig = a.copy()
+ b_orig = b.copy()
+ for i in range(50):
+ random.shuffle(a)
+ assert_equal(
+ sorted(a.data[~a.mask]), sorted(a_orig.data[~a_orig.mask]))
+ random.shuffle(b)
+ assert_equal(
+ sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask]))
+
+ def test_permutation(self):
+ random.seed(self.seed)
+ alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
+ actual = random.permutation(alist)
+ desired = [0, 1, 9, 6, 2, 4, 5, 8, 7, 3]
+ assert_array_equal(actual, desired)
+
+ random.seed(self.seed)
+ arr_2d = np.atleast_2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]).T
+ actual = random.permutation(arr_2d)
+ assert_array_equal(actual, np.atleast_2d(desired).T)
+
+ def test_beta(self):
+ random.seed(self.seed)
+ actual = random.beta(.1, .9, size=(3, 2))
+ desired = np.array(
+ [[1.45341850513746058e-02, 5.31297615662868145e-04],
+ [1.85366619058432324e-06, 4.19214516800110563e-03],
+ [1.58405155108498093e-04, 1.26252891949397652e-04]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_binomial(self):
+ random.seed(self.seed)
+ actual = random.binomial(100.123, .456, size=(3, 2))
+ desired = np.array([[37, 43],
+ [42, 48],
+ [46, 45]])
+ assert_array_equal(actual, desired)
+
+ random.seed(self.seed)
+ actual = random.binomial(100.123, .456)
+ desired = 37
+ assert_array_equal(actual, desired)
+
+ def test_chisquare(self):
+ random.seed(self.seed)
+ actual = random.chisquare(50, size=(3, 2))
+ desired = np.array([[63.87858175501090585, 68.68407748911370447],
+ [65.77116116901505904, 47.09686762438974483],
+ [72.3828403199695174, 74.18408615260374006]])
+ assert_array_almost_equal(actual, desired, decimal=13)
+
+ def test_dirichlet(self):
+ random.seed(self.seed)
+ alpha = np.array([51.72840233779265162, 39.74494232180943953])
+ actual = random.dirichlet(alpha, size=(3, 2))
+ desired = np.array([[[0.54539444573611562, 0.45460555426388438],
+ [0.62345816822039413, 0.37654183177960598]],
+ [[0.55206000085785778, 0.44793999914214233],
+ [0.58964023305154301, 0.41035976694845688]],
+ [[0.59266909280647828, 0.40733090719352177],
+ [0.56974431743975207, 0.43025568256024799]]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+ bad_alpha = np.array([5.4e-01, -1.0e-16])
+ assert_raises(ValueError, random.dirichlet, bad_alpha)
+
+ random.seed(self.seed)
+ alpha = np.array([51.72840233779265162, 39.74494232180943953])
+ actual = random.dirichlet(alpha)
+ assert_array_almost_equal(actual, desired[0, 0], decimal=15)
+
+ def test_dirichlet_size(self):
+ # gh-3173
+ p = np.array([51.72840233779265162, 39.74494232180943953])
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, np.uint32(1)).shape, (1, 2))
+ assert_equal(random.dirichlet(p, [2, 2]).shape, (2, 2, 2))
+ assert_equal(random.dirichlet(p, (2, 2)).shape, (2, 2, 2))
+ assert_equal(random.dirichlet(p, np.array((2, 2))).shape, (2, 2, 2))
+
+ assert_raises(TypeError, random.dirichlet, p, float(1))
+
+ def test_dirichlet_bad_alpha(self):
+ # gh-2089
+ alpha = np.array([5.4e-01, -1.0e-16])
+ assert_raises(ValueError, random.dirichlet, alpha)
+
+ def test_dirichlet_alpha_non_contiguous(self):
+ a = np.array([51.72840233779265162, -1.0, 39.74494232180943953])
+ alpha = a[::2]
+ random.seed(self.seed)
+ non_contig = random.dirichlet(alpha, size=(3, 2))
+ random.seed(self.seed)
+ contig = random.dirichlet(np.ascontiguousarray(alpha),
+ size=(3, 2))
+ assert_array_almost_equal(non_contig, contig)
+
+ def test_exponential(self):
+ random.seed(self.seed)
+ actual = random.exponential(1.1234, size=(3, 2))
+ desired = np.array([[1.08342649775011624, 1.00607889924557314],
+ [2.46628830085216721, 2.49668106809923884],
+ [0.68717433461363442, 1.69175666993575979]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_exponential_0(self):
+ assert_equal(random.exponential(scale=0), 0)
+ assert_raises(ValueError, random.exponential, scale=-0.)
+
+ def test_f(self):
+ random.seed(self.seed)
+ actual = random.f(12, 77, size=(3, 2))
+ desired = np.array([[1.21975394418575878, 1.75135759791559775],
+ [1.44803115017146489, 1.22108959480396262],
+ [1.02176975757740629, 1.34431827623300415]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_gamma(self):
+ random.seed(self.seed)
+ actual = random.gamma(5, 3, size=(3, 2))
+ desired = np.array([[24.60509188649287182, 28.54993563207210627],
+ [26.13476110204064184, 12.56988482927716078],
+ [31.71863275789960568, 33.30143302795922011]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_gamma_0(self):
+ assert_equal(random.gamma(shape=0, scale=0), 0)
+ assert_raises(ValueError, random.gamma, shape=-0., scale=-0.)
+
+ def test_geometric(self):
+ random.seed(self.seed)
+ actual = random.geometric(.123456789, size=(3, 2))
+ desired = np.array([[8, 7],
+ [17, 17],
+ [5, 12]])
+ assert_array_equal(actual, desired)
+
+ def test_geometric_exceptions(self):
+ assert_raises(ValueError, random.geometric, 1.1)
+ assert_raises(ValueError, random.geometric, [1.1] * 10)
+ assert_raises(ValueError, random.geometric, -0.1)
+ assert_raises(ValueError, random.geometric, [-0.1] * 10)
+ with suppress_warnings() as sup:
+ sup.record(RuntimeWarning)
+ assert_raises(ValueError, random.geometric, np.nan)
+ assert_raises(ValueError, random.geometric, [np.nan] * 10)
+
+ def test_gumbel(self):
+ random.seed(self.seed)
+ actual = random.gumbel(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[0.19591898743416816, 0.34405539668096674],
+ [-1.4492522252274278, -1.47374816298446865],
+ [1.10651090478803416, -0.69535848626236174]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_gumbel_0(self):
+ assert_equal(random.gumbel(scale=0), 0)
+ assert_raises(ValueError, random.gumbel, scale=-0.)
+
+ def test_hypergeometric(self):
+ random.seed(self.seed)
+ actual = random.hypergeometric(10.1, 5.5, 14, size=(3, 2))
+ desired = np.array([[10, 10],
+ [10, 10],
+ [9, 9]])
+ assert_array_equal(actual, desired)
+
+ # Test nbad = 0
+ actual = random.hypergeometric(5, 0, 3, size=4)
+ desired = np.array([3, 3, 3, 3])
+ assert_array_equal(actual, desired)
+
+ actual = random.hypergeometric(15, 0, 12, size=4)
+ desired = np.array([12, 12, 12, 12])
+ assert_array_equal(actual, desired)
+
+ # Test ngood = 0
+ actual = random.hypergeometric(0, 5, 3, size=4)
+ desired = np.array([0, 0, 0, 0])
+ assert_array_equal(actual, desired)
+
+ actual = random.hypergeometric(0, 15, 12, size=4)
+ desired = np.array([0, 0, 0, 0])
+ assert_array_equal(actual, desired)
+
+ def test_laplace(self):
+ random.seed(self.seed)
+ actual = random.laplace(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[0.66599721112760157, 0.52829452552221945],
+ [3.12791959514407125, 3.18202813572992005],
+ [-0.05391065675859356, 1.74901336242837324]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_laplace_0(self):
+ assert_equal(random.laplace(scale=0), 0)
+ assert_raises(ValueError, random.laplace, scale=-0.)
+
+ def test_logistic(self):
+ random.seed(self.seed)
+ actual = random.logistic(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[1.09232835305011444, 0.8648196662399954],
+ [4.27818590694950185, 4.33897006346929714],
+ [-0.21682183359214885, 2.63373365386060332]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_lognormal(self):
+ random.seed(self.seed)
+ actual = random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2))
+ desired = np.array([[16.50698631688883822, 36.54846706092654784],
+ [22.67886599981281748, 0.71617561058995771],
+ [65.72798501792723869, 86.84341601437161273]])
+ assert_array_almost_equal(actual, desired, decimal=13)
+
+ def test_lognormal_0(self):
+ assert_equal(random.lognormal(sigma=0), 1)
+ assert_raises(ValueError, random.lognormal, sigma=-0.)
+
+ def test_logseries(self):
+ random.seed(self.seed)
+ actual = random.logseries(p=.923456789, size=(3, 2))
+ desired = np.array([[2, 2],
+ [6, 17],
+ [3, 6]])
+ assert_array_equal(actual, desired)
+
+ def test_logseries_exceptions(self):
+ with suppress_warnings() as sup:
+ sup.record(RuntimeWarning)
+ assert_raises(ValueError, random.logseries, np.nan)
+ assert_raises(ValueError, random.logseries, [np.nan] * 10)
+
+ def test_multinomial(self):
+ random.seed(self.seed)
+ actual = random.multinomial(20, [1 / 6.] * 6, size=(3, 2))
+ desired = np.array([[[4, 3, 5, 4, 2, 2],
+ [5, 2, 8, 2, 2, 1]],
+ [[3, 4, 3, 6, 0, 4],
+ [2, 1, 4, 3, 6, 4]],
+ [[4, 4, 2, 5, 2, 3],
+ [4, 3, 4, 2, 3, 4]]])
+ assert_array_equal(actual, desired)
+
+ def test_multivariate_normal(self):
+ random.seed(self.seed)
+ mean = (.123456789, 10)
+ cov = [[1, 0], [0, 1]]
+ size = (3, 2)
+ actual = random.multivariate_normal(mean, cov, size)
+ desired = np.array([[[1.463620246718631, 11.73759122771936],
+ [1.622445133300628, 9.771356667546383]],
+ [[2.154490787682787, 12.170324946056553],
+ [1.719909438201865, 9.230548443648306]],
+ [[0.689515026297799, 9.880729819607714],
+ [-0.023054015651998, 9.201096623542879]]])
+
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ # Check for default size, was raising deprecation warning
+ actual = random.multivariate_normal(mean, cov)
+ desired = np.array([0.895289569463708, 9.17180864067987])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ # Check that non positive-semidefinite covariance warns with
+ # RuntimeWarning
+ mean = [0, 0]
+ cov = [[1, 2], [2, 1]]
+ assert_warns(RuntimeWarning, random.multivariate_normal, mean, cov)
+
+ # and that it doesn't warn with RuntimeWarning check_valid='ignore'
+ assert_no_warnings(random.multivariate_normal, mean, cov,
+ check_valid='ignore')
+
+ # and that it raises with RuntimeWarning check_valid='raises'
+ assert_raises(ValueError, random.multivariate_normal, mean, cov,
+ check_valid='raise')
+
+ cov = np.array([[1, 0.1], [0.1, 1]], dtype=np.float32)
+ with suppress_warnings() as sup:
+ random.multivariate_normal(mean, cov)
+ w = sup.record(RuntimeWarning)
+ assert len(w) == 0
+
+ mu = np.zeros(2)
+ cov = np.eye(2)
+ assert_raises(ValueError, random.multivariate_normal, mean, cov,
+ check_valid='other')
+ assert_raises(ValueError, random.multivariate_normal,
+ np.zeros((2, 1, 1)), cov)
+ assert_raises(ValueError, random.multivariate_normal,
+ mu, np.empty((3, 2)))
+ assert_raises(ValueError, random.multivariate_normal,
+ mu, np.eye(3))
+
+ def test_negative_binomial(self):
+ random.seed(self.seed)
+ actual = random.negative_binomial(n=100, p=.12345, size=(3, 2))
+ desired = np.array([[848, 841],
+ [892, 611],
+ [779, 647]])
+ assert_array_equal(actual, desired)
+
+ def test_negative_binomial_exceptions(self):
+ with suppress_warnings() as sup:
+ sup.record(RuntimeWarning)
+ assert_raises(ValueError, random.negative_binomial, 100, np.nan)
+ assert_raises(ValueError, random.negative_binomial, 100,
+ [np.nan] * 10)
+
+ def test_noncentral_chisquare(self):
+ random.seed(self.seed)
+ actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2))
+ desired = np.array([[23.91905354498517511, 13.35324692733826346],
+ [31.22452661329736401, 16.60047399466177254],
+ [5.03461598262724586, 17.94973089023519464]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ actual = random.noncentral_chisquare(df=.5, nonc=.2, size=(3, 2))
+ desired = np.array([[1.47145377828516666, 0.15052899268012659],
+ [0.00943803056963588, 1.02647251615666169],
+ [0.332334982684171, 0.15451287602753125]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ random.seed(self.seed)
+ actual = random.noncentral_chisquare(df=5, nonc=0, size=(3, 2))
+ desired = np.array([[9.597154162763948, 11.725484450296079],
+ [10.413711048138335, 3.694475922923986],
+ [13.484222138963087, 14.377255424602957]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_noncentral_f(self):
+ random.seed(self.seed)
+ actual = random.noncentral_f(dfnum=5, dfden=2, nonc=1,
+ size=(3, 2))
+ desired = np.array([[1.40598099674926669, 0.34207973179285761],
+ [3.57715069265772545, 7.92632662577829805],
+ [0.43741599463544162, 1.1774208752428319]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_noncentral_f_nan(self):
+ random.seed(self.seed)
+ actual = random.noncentral_f(dfnum=5, dfden=2, nonc=np.nan)
+ assert np.isnan(actual)
+
+ def test_normal(self):
+ random.seed(self.seed)
+ actual = random.normal(loc=.123456789, scale=2.0, size=(3, 2))
+ desired = np.array([[2.80378370443726244, 3.59863924443872163],
+ [3.121433477601256, -0.33382987590723379],
+ [4.18552478636557357, 4.46410668111310471]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_normal_0(self):
+ assert_equal(random.normal(scale=0), 0)
+ assert_raises(ValueError, random.normal, scale=-0.)
+
+ def test_pareto(self):
+ random.seed(self.seed)
+ actual = random.pareto(a=.123456789, size=(3, 2))
+ desired = np.array(
+ [[2.46852460439034849e+03, 1.41286880810518346e+03],
+ [5.28287797029485181e+07, 6.57720981047328785e+07],
+ [1.40840323350391515e+02, 1.98390255135251704e+05]])
+ # For some reason on 32-bit x86 Ubuntu 12.10 the [1, 0] entry in this
+ # matrix differs by 24 nulps. Discussion:
+ # https://mail.python.org/pipermail/numpy-discussion/2012-September/063801.html
+ # Consensus is that this is probably some gcc quirk that affects
+ # rounding but not in any important way, so we just use a looser
+ # tolerance on this test:
+ np.testing.assert_array_almost_equal_nulp(actual, desired, nulp=30)
+
+ def test_poisson(self):
+ random.seed(self.seed)
+ actual = random.poisson(lam=.123456789, size=(3, 2))
+ desired = np.array([[0, 0],
+ [1, 0],
+ [0, 0]])
+ assert_array_equal(actual, desired)
+
+ def test_poisson_exceptions(self):
+ lambig = np.iinfo('l').max
+ lamneg = -1
+ assert_raises(ValueError, random.poisson, lamneg)
+ assert_raises(ValueError, random.poisson, [lamneg] * 10)
+ assert_raises(ValueError, random.poisson, lambig)
+ assert_raises(ValueError, random.poisson, [lambig] * 10)
+ with suppress_warnings() as sup:
+ sup.record(RuntimeWarning)
+ assert_raises(ValueError, random.poisson, np.nan)
+ assert_raises(ValueError, random.poisson, [np.nan] * 10)
+
+ def test_power(self):
+ random.seed(self.seed)
+ actual = random.power(a=.123456789, size=(3, 2))
+ desired = np.array([[0.02048932883240791, 0.01424192241128213],
+ [0.38446073748535298, 0.39499689943484395],
+ [0.00177699707563439, 0.13115505880863756]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_rayleigh(self):
+ random.seed(self.seed)
+ actual = random.rayleigh(scale=10, size=(3, 2))
+ desired = np.array([[13.8882496494248393, 13.383318339044731],
+ [20.95413364294492098, 21.08285015800712614],
+ [11.06066537006854311, 17.35468505778271009]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_rayleigh_0(self):
+ assert_equal(random.rayleigh(scale=0), 0)
+ assert_raises(ValueError, random.rayleigh, scale=-0.)
+
+ def test_standard_cauchy(self):
+ random.seed(self.seed)
+ actual = random.standard_cauchy(size=(3, 2))
+ desired = np.array([[0.77127660196445336, -6.55601161955910605],
+ [0.93582023391158309, -2.07479293013759447],
+ [-4.74601644297011926, 0.18338989290760804]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_exponential(self):
+ random.seed(self.seed)
+ actual = random.standard_exponential(size=(3, 2))
+ desired = np.array([[0.96441739162374596, 0.89556604882105506],
+ [2.1953785836319808, 2.22243285392490542],
+ [0.6116915921431676, 1.50592546727413201]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_gamma(self):
+ random.seed(self.seed)
+ actual = random.standard_gamma(shape=3, size=(3, 2))
+ desired = np.array([[5.50841531318455058, 6.62953470301903103],
+ [5.93988484943779227, 2.31044849402133989],
+ [7.54838614231317084, 8.012756093271868]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_standard_gamma_0(self):
+ assert_equal(random.standard_gamma(shape=0), 0)
+ assert_raises(ValueError, random.standard_gamma, shape=-0.)
+
+ def test_standard_normal(self):
+ random.seed(self.seed)
+ actual = random.standard_normal(size=(3, 2))
+ desired = np.array([[1.34016345771863121, 1.73759122771936081],
+ [1.498988344300628, -0.2286433324536169],
+ [2.031033998682787, 2.17032494605655257]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_randn_singleton(self):
+ random.seed(self.seed)
+ actual = random.randn()
+ desired = np.array(1.34016345771863121)
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_standard_t(self):
+ random.seed(self.seed)
+ actual = random.standard_t(df=10, size=(3, 2))
+ desired = np.array([[0.97140611862659965, -0.08830486548450577],
+ [1.36311143689505321, -0.55317463909867071],
+ [-0.18473749069684214, 0.61181537341755321]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_triangular(self):
+ random.seed(self.seed)
+ actual = random.triangular(left=5.12, mode=10.23, right=20.34,
+ size=(3, 2))
+ desired = np.array([[12.68117178949215784, 12.4129206149193152],
+ [16.20131377335158263, 16.25692138747600524],
+ [11.20400690911820263, 14.4978144835829923]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_uniform(self):
+ random.seed(self.seed)
+ actual = random.uniform(low=1.23, high=10.54, size=(3, 2))
+ desired = np.array([[6.99097932346268003, 6.73801597444323974],
+ [9.50364421400426274, 9.53130618907631089],
+ [5.48995325769805476, 8.47493103280052118]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_uniform_range_bounds(self):
+ fmin = np.finfo('float').min
+ fmax = np.finfo('float').max
+
+ func = random.uniform
+ assert_raises(OverflowError, func, -np.inf, 0)
+ assert_raises(OverflowError, func, 0, np.inf)
+ assert_raises(OverflowError, func, fmin, fmax)
+ assert_raises(OverflowError, func, [-np.inf], [0])
+ assert_raises(OverflowError, func, [0], [np.inf])
+
+ # (fmax / 1e17) - fmin is within range, so this should not throw
+ # account for i386 extended precision DBL_MAX / 1e17 + DBL_MAX >
+ # DBL_MAX by increasing fmin a bit
+ random.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17)
+
+ def test_scalar_exception_propagation(self):
+ # Tests that exceptions are correctly propagated in distributions
+ # when called with objects that throw exceptions when converted to
+ # scalars.
+ #
+ # Regression test for gh: 8865
+
+ class ThrowingFloat(np.ndarray):
+ def __float__(self):
+ raise TypeError
+
+ throwing_float = np.array(1.0).view(ThrowingFloat)
+ assert_raises(TypeError, random.uniform, throwing_float,
+ throwing_float)
+
+ class ThrowingInteger(np.ndarray):
+ def __int__(self):
+ raise TypeError
+
+ throwing_int = np.array(1).view(ThrowingInteger)
+ assert_raises(TypeError, random.hypergeometric, throwing_int, 1, 1)
+
+ def test_vonmises(self):
+ random.seed(self.seed)
+ actual = random.vonmises(mu=1.23, kappa=1.54, size=(3, 2))
+ desired = np.array([[2.28567572673902042, 2.89163838442285037],
+ [0.38198375564286025, 2.57638023113890746],
+ [1.19153771588353052, 1.83509849681825354]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_vonmises_small(self):
+ # check infinite loop, gh-4720
+ random.seed(self.seed)
+ r = random.vonmises(mu=0., kappa=1.1e-8, size=10**6)
+ assert_(np.isfinite(r).all())
+
+ def test_vonmises_nan(self):
+ random.seed(self.seed)
+ r = random.vonmises(mu=0., kappa=np.nan)
+ assert_(np.isnan(r))
+
+ def test_wald(self):
+ random.seed(self.seed)
+ actual = random.wald(mean=1.23, scale=1.54, size=(3, 2))
+ desired = np.array([[3.82935265715889983, 5.13125249184285526],
+ [0.35045403618358717, 1.50832396872003538],
+ [0.24124319895843183, 0.22031101461955038]])
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_weibull(self):
+ random.seed(self.seed)
+ actual = random.weibull(a=1.23, size=(3, 2))
+ desired = np.array([[0.97097342648766727, 0.91422896443565516],
+ [1.89517770034962929, 1.91414357960479564],
+ [0.67057783752390987, 1.39494046635066793]])
+ assert_array_almost_equal(actual, desired, decimal=15)
+
+ def test_weibull_0(self):
+ random.seed(self.seed)
+ assert_equal(random.weibull(a=0, size=12), np.zeros(12))
+ assert_raises(ValueError, random.weibull, a=-0.)
+
+ def test_zipf(self):
+ random.seed(self.seed)
+ actual = random.zipf(a=1.23, size=(3, 2))
+ desired = np.array([[66, 29],
+ [1, 1],
+ [3, 13]])
+ assert_array_equal(actual, desired)
+
+
+class TestBroadcast(object):
+ # tests that functions that broadcast behave
+ # correctly when presented with non-scalar arguments
+ def setup(self):
+ self.seed = 123456789
+
+ def set_seed(self):
+ random.seed(self.seed)
+
+ def test_uniform(self):
+ low = [0]
+ high = [1]
+ uniform = random.uniform
+ desired = np.array([0.53283302478975902,
+ 0.53413660089041659,
+ 0.50955303552646702])
+
+ self.set_seed()
+ actual = uniform(low * 3, high)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ self.set_seed()
+ actual = uniform(low, high * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_normal(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ normal = random.normal
+ desired = np.array([2.2129019979039612,
+ 2.1283977976520019,
+ 1.8417114045748335])
+
+ self.set_seed()
+ actual = normal(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, normal, loc * 3, bad_scale)
+
+ self.set_seed()
+ actual = normal(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, normal, loc, bad_scale * 3)
+
+ def test_beta(self):
+ a = [1]
+ b = [2]
+ bad_a = [-1]
+ bad_b = [-2]
+ beta = random.beta
+ desired = np.array([0.19843558305989056,
+ 0.075230336409423643,
+ 0.24976865978980844])
+
+ self.set_seed()
+ actual = beta(a * 3, b)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, beta, bad_a * 3, b)
+ assert_raises(ValueError, beta, a * 3, bad_b)
+
+ self.set_seed()
+ actual = beta(a, b * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, beta, bad_a, b * 3)
+ assert_raises(ValueError, beta, a, bad_b * 3)
+
+ def test_exponential(self):
+ scale = [1]
+ bad_scale = [-1]
+ exponential = random.exponential
+ desired = np.array([0.76106853658845242,
+ 0.76386282278691653,
+ 0.71243813125891797])
+
+ self.set_seed()
+ actual = exponential(scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, exponential, bad_scale * 3)
+
+ def test_standard_gamma(self):
+ shape = [1]
+ bad_shape = [-1]
+ std_gamma = random.standard_gamma
+ desired = np.array([0.76106853658845242,
+ 0.76386282278691653,
+ 0.71243813125891797])
+
+ self.set_seed()
+ actual = std_gamma(shape * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, std_gamma, bad_shape * 3)
+
+ def test_gamma(self):
+ shape = [1]
+ scale = [2]
+ bad_shape = [-1]
+ bad_scale = [-2]
+ gamma = random.gamma
+ desired = np.array([1.5221370731769048,
+ 1.5277256455738331,
+ 1.4248762625178359])
+
+ self.set_seed()
+ actual = gamma(shape * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gamma, bad_shape * 3, scale)
+ assert_raises(ValueError, gamma, shape * 3, bad_scale)
+
+ self.set_seed()
+ actual = gamma(shape, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gamma, bad_shape, scale * 3)
+ assert_raises(ValueError, gamma, shape, bad_scale * 3)
+
+ def test_f(self):
+ dfnum = [1]
+ dfden = [2]
+ bad_dfnum = [-1]
+ bad_dfden = [-2]
+ f = random.f
+ desired = np.array([0.80038951638264799,
+ 0.86768719635363512,
+ 2.7251095168386801])
+
+ self.set_seed()
+ actual = f(dfnum * 3, dfden)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, f, bad_dfnum * 3, dfden)
+ assert_raises(ValueError, f, dfnum * 3, bad_dfden)
+
+ self.set_seed()
+ actual = f(dfnum, dfden * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, f, bad_dfnum, dfden * 3)
+ assert_raises(ValueError, f, dfnum, bad_dfden * 3)
+
+ def test_noncentral_f(self):
+ dfnum = [2]
+ dfden = [3]
+ nonc = [4]
+ bad_dfnum = [0]
+ bad_dfden = [-1]
+ bad_nonc = [-2]
+ nonc_f = random.noncentral_f
+ desired = np.array([9.1393943263705211,
+ 13.025456344595602,
+ 8.8018098359100545])
+
+ self.set_seed()
+ actual = nonc_f(dfnum * 3, dfden, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert np.all(np.isnan(nonc_f(dfnum, dfden, [np.nan] * 3)))
+
+ assert_raises(ValueError, nonc_f, bad_dfnum * 3, dfden, nonc)
+ assert_raises(ValueError, nonc_f, dfnum * 3, bad_dfden, nonc)
+ assert_raises(ValueError, nonc_f, dfnum * 3, dfden, bad_nonc)
+
+ self.set_seed()
+ actual = nonc_f(dfnum, dfden * 3, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_f, bad_dfnum, dfden * 3, nonc)
+ assert_raises(ValueError, nonc_f, dfnum, bad_dfden * 3, nonc)
+ assert_raises(ValueError, nonc_f, dfnum, dfden * 3, bad_nonc)
+
+ self.set_seed()
+ actual = nonc_f(dfnum, dfden, nonc * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_f, bad_dfnum, dfden, nonc * 3)
+ assert_raises(ValueError, nonc_f, dfnum, bad_dfden, nonc * 3)
+ assert_raises(ValueError, nonc_f, dfnum, dfden, bad_nonc * 3)
+
+ def test_noncentral_f_small_df(self):
+ self.set_seed()
+ desired = np.array([6.869638627492048, 0.785880199263955])
+ actual = random.noncentral_f(0.9, 0.9, 2, size=2)
+ assert_array_almost_equal(actual, desired, decimal=14)
+
+ def test_chisquare(self):
+ df = [1]
+ bad_df = [-1]
+ chisquare = random.chisquare
+ desired = np.array([0.57022801133088286,
+ 0.51947702108840776,
+ 0.1320969254923558])
+
+ self.set_seed()
+ actual = chisquare(df * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, chisquare, bad_df * 3)
+
+ def test_noncentral_chisquare(self):
+ df = [1]
+ nonc = [2]
+ bad_df = [-1]
+ bad_nonc = [-2]
+ nonc_chi = random.noncentral_chisquare
+ desired = np.array([9.0015599467913763,
+ 4.5804135049718742,
+ 6.0872302432834564])
+
+ self.set_seed()
+ actual = nonc_chi(df * 3, nonc)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_chi, bad_df * 3, nonc)
+ assert_raises(ValueError, nonc_chi, df * 3, bad_nonc)
+
+ self.set_seed()
+ actual = nonc_chi(df, nonc * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, nonc_chi, bad_df, nonc * 3)
+ assert_raises(ValueError, nonc_chi, df, bad_nonc * 3)
+
+ def test_standard_t(self):
+ df = [1]
+ bad_df = [-1]
+ t = random.standard_t
+ desired = np.array([3.0702872575217643,
+ 5.8560725167361607,
+ 1.0274791436474273])
+
+ self.set_seed()
+ actual = t(df * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, t, bad_df * 3)
+ assert_raises(ValueError, random.standard_t, bad_df * 3)
+
+ def test_vonmises(self):
+ mu = [2]
+ kappa = [1]
+ bad_kappa = [-1]
+ vonmises = random.vonmises
+ desired = np.array([2.9883443664201312,
+ -2.7064099483995943,
+ -1.8672476700665914])
+
+ self.set_seed()
+ actual = vonmises(mu * 3, kappa)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, vonmises, mu * 3, bad_kappa)
+
+ self.set_seed()
+ actual = vonmises(mu, kappa * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, vonmises, mu, bad_kappa * 3)
+
+ def test_pareto(self):
+ a = [1]
+ bad_a = [-1]
+ pareto = random.pareto
+ desired = np.array([1.1405622680198362,
+ 1.1465519762044529,
+ 1.0389564467453547])
+
+ self.set_seed()
+ actual = pareto(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, pareto, bad_a * 3)
+ assert_raises(ValueError, random.pareto, bad_a * 3)
+
+ def test_weibull(self):
+ a = [1]
+ bad_a = [-1]
+ weibull = random.weibull
+ desired = np.array([0.76106853658845242,
+ 0.76386282278691653,
+ 0.71243813125891797])
+
+ self.set_seed()
+ actual = weibull(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, weibull, bad_a * 3)
+ assert_raises(ValueError, random.weibull, bad_a * 3)
+
+ def test_power(self):
+ a = [1]
+ bad_a = [-1]
+ power = random.power
+ desired = np.array([0.53283302478975902,
+ 0.53413660089041659,
+ 0.50955303552646702])
+
+ self.set_seed()
+ actual = power(a * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, power, bad_a * 3)
+ assert_raises(ValueError, random.power, bad_a * 3)
+
+ def test_laplace(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ laplace = random.laplace
+ desired = np.array([0.067921356028507157,
+ 0.070715642226971326,
+ 0.019290950698972624])
+
+ self.set_seed()
+ actual = laplace(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, laplace, loc * 3, bad_scale)
+
+ self.set_seed()
+ actual = laplace(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, laplace, loc, bad_scale * 3)
+
+ def test_gumbel(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ gumbel = random.gumbel
+ desired = np.array([0.2730318639556768,
+ 0.26936705726291116,
+ 0.33906220393037939])
+
+ self.set_seed()
+ actual = gumbel(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gumbel, loc * 3, bad_scale)
+
+ self.set_seed()
+ actual = gumbel(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, gumbel, loc, bad_scale * 3)
+
+ def test_logistic(self):
+ loc = [0]
+ scale = [1]
+ bad_scale = [-1]
+ logistic = random.logistic
+ desired = np.array([0.13152135837586171,
+ 0.13675915696285773,
+ 0.038216792802833396])
+
+ self.set_seed()
+ actual = logistic(loc * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, logistic, loc * 3, bad_scale)
+
+ self.set_seed()
+ actual = logistic(loc, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, logistic, loc, bad_scale * 3)
+ assert_equal(random.logistic(1.0, 0.0), 1.0)
+
+ def test_lognormal(self):
+ mean = [0]
+ sigma = [1]
+ bad_sigma = [-1]
+ lognormal = random.lognormal
+ desired = np.array([9.1422086044848427,
+ 8.4013952870126261,
+ 6.3073234116578671])
+
+ self.set_seed()
+ actual = lognormal(mean * 3, sigma)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, lognormal, mean * 3, bad_sigma)
+ assert_raises(ValueError, random.lognormal, mean * 3, bad_sigma)
+
+ self.set_seed()
+ actual = lognormal(mean, sigma * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, lognormal, mean, bad_sigma * 3)
+ assert_raises(ValueError, random.lognormal, mean, bad_sigma * 3)
+
+ def test_rayleigh(self):
+ scale = [1]
+ bad_scale = [-1]
+ rayleigh = random.rayleigh
+ desired = np.array([1.2337491937897689,
+ 1.2360119924878694,
+ 1.1936818095781789])
+
+ self.set_seed()
+ actual = rayleigh(scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, rayleigh, bad_scale * 3)
+
+ def test_wald(self):
+ mean = [0.5]
+ scale = [1]
+ bad_mean = [0]
+ bad_scale = [-2]
+ wald = random.wald
+ desired = np.array([0.11873681120271318,
+ 0.12450084820795027,
+ 0.9096122728408238])
+
+ self.set_seed()
+ actual = wald(mean * 3, scale)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, wald, bad_mean * 3, scale)
+ assert_raises(ValueError, wald, mean * 3, bad_scale)
+ assert_raises(ValueError, random.wald, bad_mean * 3, scale)
+ assert_raises(ValueError, random.wald, mean * 3, bad_scale)
+
+ self.set_seed()
+ actual = wald(mean, scale * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, wald, bad_mean, scale * 3)
+ assert_raises(ValueError, wald, mean, bad_scale * 3)
+ assert_raises(ValueError, wald, 0.0, 1)
+ assert_raises(ValueError, wald, 0.5, 0.0)
+
+ def test_triangular(self):
+ left = [1]
+ right = [3]
+ mode = [2]
+ bad_left_one = [3]
+ bad_mode_one = [4]
+ bad_left_two, bad_mode_two = right * 2
+ triangular = random.triangular
+ desired = np.array([2.03339048710429,
+ 2.0347400359389356,
+ 2.0095991069536208])
+
+ self.set_seed()
+ actual = triangular(left * 3, mode, right)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one * 3, mode, right)
+ assert_raises(ValueError, triangular, left * 3, bad_mode_one, right)
+ assert_raises(ValueError, triangular, bad_left_two * 3, bad_mode_two,
+ right)
+
+ self.set_seed()
+ actual = triangular(left, mode * 3, right)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one, mode * 3, right)
+ assert_raises(ValueError, triangular, left, bad_mode_one * 3, right)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two * 3,
+ right)
+
+ self.set_seed()
+ actual = triangular(left, mode, right * 3)
+ assert_array_almost_equal(actual, desired, decimal=14)
+ assert_raises(ValueError, triangular, bad_left_one, mode, right * 3)
+ assert_raises(ValueError, triangular, left, bad_mode_one, right * 3)
+ assert_raises(ValueError, triangular, bad_left_two, bad_mode_two,
+ right * 3)
+
+ assert_raises(ValueError, triangular, 10., 0., 20.)
+ assert_raises(ValueError, triangular, 10., 25., 20.)
+ assert_raises(ValueError, triangular, 10., 10., 10.)
+
+ def test_binomial(self):
+ n = [1]
+ p = [0.5]
+ bad_n = [-1]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ binom = random.binomial
+ desired = np.array([1, 1, 1])
+
+ self.set_seed()
+ actual = binom(n * 3, p)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, binom, bad_n * 3, p)
+ assert_raises(ValueError, binom, n * 3, bad_p_one)
+ assert_raises(ValueError, binom, n * 3, bad_p_two)
+
+ self.set_seed()
+ actual = binom(n, p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, binom, bad_n, p * 3)
+ assert_raises(ValueError, binom, n, bad_p_one * 3)
+ assert_raises(ValueError, binom, n, bad_p_two * 3)
+
+ def test_negative_binomial(self):
+ n = [1]
+ p = [0.5]
+ bad_n = [-1]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ neg_binom = random.negative_binomial
+ desired = np.array([1, 0, 1])
+
+ self.set_seed()
+ actual = neg_binom(n * 3, p)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, neg_binom, bad_n * 3, p)
+ assert_raises(ValueError, neg_binom, n * 3, bad_p_one)
+ assert_raises(ValueError, neg_binom, n * 3, bad_p_two)
+
+ self.set_seed()
+ actual = neg_binom(n, p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, neg_binom, bad_n, p * 3)
+ assert_raises(ValueError, neg_binom, n, bad_p_one * 3)
+ assert_raises(ValueError, neg_binom, n, bad_p_two * 3)
+
+ def test_poisson(self):
+ max_lam = random.RandomState()._poisson_lam_max
+
+ lam = [1]
+ bad_lam_one = [-1]
+ bad_lam_two = [max_lam * 2]
+ poisson = random.poisson
+ desired = np.array([1, 1, 0])
+
+ self.set_seed()
+ actual = poisson(lam * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, poisson, bad_lam_one * 3)
+ assert_raises(ValueError, poisson, bad_lam_two * 3)
+
+ def test_zipf(self):
+ a = [2]
+ bad_a = [0]
+ zipf = random.zipf
+ desired = np.array([2, 2, 1])
+
+ self.set_seed()
+ actual = zipf(a * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, zipf, bad_a * 3)
+ with np.errstate(invalid='ignore'):
+ assert_raises(ValueError, zipf, np.nan)
+ assert_raises(ValueError, zipf, [0, 0, np.nan])
+
+ def test_geometric(self):
+ p = [0.5]
+ bad_p_one = [-1]
+ bad_p_two = [1.5]
+ geom = random.geometric
+ desired = np.array([2, 2, 2])
+
+ self.set_seed()
+ actual = geom(p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, geom, bad_p_one * 3)
+ assert_raises(ValueError, geom, bad_p_two * 3)
+
+ def test_hypergeometric(self):
+ ngood = [1]
+ nbad = [2]
+ nsample = [2]
+ bad_ngood = [-1]
+ bad_nbad = [-2]
+ bad_nsample_one = [0]
+ bad_nsample_two = [4]
+ hypergeom = random.hypergeometric
+ desired = np.array([1, 1, 1])
+
+ self.set_seed()
+ actual = hypergeom(ngood * 3, nbad, nsample)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, hypergeom, bad_ngood * 3, nbad, nsample)
+ assert_raises(ValueError, hypergeom, ngood * 3, bad_nbad, nsample)
+ assert_raises(ValueError, hypergeom, ngood * 3, nbad, bad_nsample_one)
+ assert_raises(ValueError, hypergeom, ngood * 3, nbad, bad_nsample_two)
+
+ self.set_seed()
+ actual = hypergeom(ngood, nbad * 3, nsample)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, hypergeom, bad_ngood, nbad * 3, nsample)
+ assert_raises(ValueError, hypergeom, ngood, bad_nbad * 3, nsample)
+ assert_raises(ValueError, hypergeom, ngood, nbad * 3, bad_nsample_one)
+ assert_raises(ValueError, hypergeom, ngood, nbad * 3, bad_nsample_two)
+
+ self.set_seed()
+ actual = hypergeom(ngood, nbad, nsample * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, hypergeom, bad_ngood, nbad, nsample * 3)
+ assert_raises(ValueError, hypergeom, ngood, bad_nbad, nsample * 3)
+ assert_raises(ValueError, hypergeom, ngood, nbad, bad_nsample_one * 3)
+ assert_raises(ValueError, hypergeom, ngood, nbad, bad_nsample_two * 3)
+
+ assert_raises(ValueError, hypergeom, -1, 10, 20)
+ assert_raises(ValueError, hypergeom, 10, -1, 20)
+ assert_raises(ValueError, hypergeom, 10, 10, 0)
+ assert_raises(ValueError, hypergeom, 10, 10, 25)
+
+ def test_logseries(self):
+ p = [0.5]
+ bad_p_one = [2]
+ bad_p_two = [-1]
+ logseries = random.logseries
+ desired = np.array([1, 1, 1])
+
+ self.set_seed()
+ actual = logseries(p * 3)
+ assert_array_equal(actual, desired)
+ assert_raises(ValueError, logseries, bad_p_one * 3)
+ assert_raises(ValueError, logseries, bad_p_two * 3)
+
+
+class TestThread(object):
+ # make sure each state produces the same sequence even in threads
+ def setup(self):
+ self.seeds = range(4)
+
+ def check_function(self, function, sz):
+ from threading import Thread
+
+ out1 = np.empty((len(self.seeds),) + sz)
+ out2 = np.empty((len(self.seeds),) + sz)
+
+ # threaded generation
+ t = [Thread(target=function, args=(random.RandomState(s), o))
+ for s, o in zip(self.seeds, out1)]
+ [x.start() for x in t]
+ [x.join() for x in t]
+
+ # the same serial
+ for s, o in zip(self.seeds, out2):
+ function(random.RandomState(s), o)
+
+ # these platforms change x87 fpu precision mode in threads
+ if np.intp().dtype.itemsize == 4 and sys.platform == "win32":
+ assert_array_almost_equal(out1, out2)
+ else:
+ assert_array_equal(out1, out2)
+
+ def test_normal(self):
+ def gen_random(state, out):
+ out[...] = state.normal(size=10000)
+
+ self.check_function(gen_random, sz=(10000,))
+
+ def test_exp(self):
+ def gen_random(state, out):
+ out[...] = state.exponential(scale=np.ones((100, 1000)))
+
+ self.check_function(gen_random, sz=(100, 1000))
+
+ def test_multinomial(self):
+ def gen_random(state, out):
+ out[...] = state.multinomial(10, [1 / 6.] * 6, size=10000)
+
+ self.check_function(gen_random, sz=(10000, 6))
+
+
+# See Issue #4263
+class TestSingleEltArrayInput(object):
+ def setup(self):
+ self.argOne = np.array([2])
+ self.argTwo = np.array([3])
+ self.argThree = np.array([4])
+ self.tgtShape = (1,)
+
+ def test_one_arg_funcs(self):
+ funcs = (random.exponential, random.standard_gamma,
+ random.chisquare, random.standard_t,
+ random.pareto, random.weibull,
+ random.power, random.rayleigh,
+ random.poisson, random.zipf,
+ random.geometric, random.logseries)
+
+ probfuncs = (random.geometric, random.logseries)
+
+ for func in funcs:
+ if func in probfuncs: # p < 1.0
+ out = func(np.array([0.5]))
+
+ else:
+ out = func(self.argOne)
+
+ assert_equal(out.shape, self.tgtShape)
+
+ def test_two_arg_funcs(self):
+ funcs = (random.uniform, random.normal,
+ random.beta, random.gamma,
+ random.f, random.noncentral_chisquare,
+ random.vonmises, random.laplace,
+ random.gumbel, random.logistic,
+ random.lognormal, random.wald,
+ random.binomial, random.negative_binomial)
+
+ probfuncs = (random.binomial, random.negative_binomial)
+
+ for func in funcs:
+ if func in probfuncs: # p <= 1
+ argTwo = np.array([0.5])
+
+ else:
+ argTwo = self.argTwo
+
+ out = func(self.argOne, argTwo)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne[0], argTwo)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne, argTwo[0])
+ assert_equal(out.shape, self.tgtShape)
+
+ def test_three_arg_funcs(self):
+ funcs = [random.noncentral_f, random.triangular,
+ random.hypergeometric]
+
+ for func in funcs:
+ out = func(self.argOne, self.argTwo, self.argThree)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne[0], self.argTwo, self.argThree)
+ assert_equal(out.shape, self.tgtShape)
+
+ out = func(self.argOne, self.argTwo[0], self.argThree)
+ assert_equal(out.shape, self.tgtShape)
+
+
+# Ensure returned array dtype is correct for platform
+def test_integer_dtype(int_func):
+ random.seed(123456789)
+ fname, args, md5 = int_func
+ f = getattr(random, fname)
+ actual = f(*args, size=2)
+ assert_(actual.dtype == np.dtype('l'))
+
+
+def test_integer_repeat(int_func):
+ random.seed(123456789)
+ fname, args, md5 = int_func
+ f = getattr(random, fname)
+ val = f(*args, size=1000000)
+ if sys.byteorder != 'little':
+ val = val.byteswap()
+ res = hashlib.md5(val.view(np.int8)).hexdigest()
+ assert_(res == md5)
diff --git a/numpy/random/tests/test_randomstate_regression.py b/numpy/random/tests/test_randomstate_regression.py
new file mode 100644
index 000000000..29870534a
--- /dev/null
+++ b/numpy/random/tests/test_randomstate_regression.py
@@ -0,0 +1,183 @@
+import sys
+
+import pytest
+
+from numpy.testing import (
+ assert_, assert_array_equal, assert_raises,
+ )
+from numpy.compat import long
+import numpy as np
+
+from numpy.random import mtrand as random
+
+
+class TestRegression(object):
+
+ def test_VonMises_range(self):
+ # Make sure generated random variables are in [-pi, pi].
+ # Regression test for ticket #986.
+ for mu in np.linspace(-7., 7., 5):
+ r = random.vonmises(mu, 1, 50)
+ assert_(np.all(r > -np.pi) and np.all(r <= np.pi))
+
+ def test_hypergeometric_range(self):
+ # Test for ticket #921
+ assert_(np.all(random.hypergeometric(3, 18, 11, size=10) < 4))
+ assert_(np.all(random.hypergeometric(18, 3, 11, size=10) > 0))
+
+ # Test for ticket #5623
+ args = [
+ (2**20 - 2, 2**20 - 2, 2**20 - 2), # Check for 32-bit systems
+ ]
+ is_64bits = sys.maxsize > 2**32
+ if is_64bits and sys.platform != 'win32':
+ # Check for 64-bit systems
+ args.append((2**40 - 2, 2**40 - 2, 2**40 - 2))
+ for arg in args:
+ assert_(random.hypergeometric(*arg) > 0)
+
+ def test_logseries_convergence(self):
+ # Test for ticket #923
+ N = 1000
+ random.seed(0)
+ rvsn = random.logseries(0.8, size=N)
+ # these two frequency counts should be close to theoretical
+ # numbers with this large sample
+ # theoretical large N result is 0.49706795
+ freq = np.sum(rvsn == 1) / float(N)
+ msg = "Frequency was %f, should be > 0.45" % freq
+ assert_(freq > 0.45, msg)
+ # theoretical large N result is 0.19882718
+ freq = np.sum(rvsn == 2) / float(N)
+ msg = "Frequency was %f, should be < 0.23" % freq
+ assert_(freq < 0.23, msg)
+
+ def test_permutation_longs(self):
+ random.seed(1234)
+ a = random.permutation(12)
+ random.seed(1234)
+ b = random.permutation(long(12))
+ assert_array_equal(a, b)
+
+ def test_shuffle_mixed_dimension(self):
+ # Test for trac ticket #2074
+ for t in [[1, 2, 3, None],
+ [(1, 1), (2, 2), (3, 3), None],
+ [1, (2, 2), (3, 3), None],
+ [(1, 1), 2, 3, None]]:
+ random.seed(12345)
+ shuffled = list(t)
+ random.shuffle(shuffled)
+ assert_array_equal(shuffled, [t[0], t[3], t[1], t[2]])
+
+ def test_call_within_randomstate(self):
+ # Check that custom RandomState does not call into global state
+ m = random.RandomState()
+ res = np.array([0, 8, 7, 2, 1, 9, 4, 7, 0, 3])
+ for i in range(3):
+ random.seed(i)
+ m.seed(4321)
+ # If m.state is not honored, the result will change
+ assert_array_equal(m.choice(10, size=10, p=np.ones(10)/10.), res)
+
+ def test_multivariate_normal_size_types(self):
+ # Test for multivariate_normal issue with 'size' argument.
+ # Check that the multivariate_normal size argument can be a
+ # numpy integer.
+ random.multivariate_normal([0], [[0]], size=1)
+ random.multivariate_normal([0], [[0]], size=np.int_(1))
+ random.multivariate_normal([0], [[0]], size=np.int64(1))
+
+ def test_beta_small_parameters(self):
+ # Test that beta with small a and b parameters does not produce
+ # NaNs due to roundoff errors causing 0 / 0, gh-5851
+ random.seed(1234567890)
+ x = random.beta(0.0001, 0.0001, size=100)
+ assert_(not np.any(np.isnan(x)), 'Nans in random.beta')
+
+ def test_choice_sum_of_probs_tolerance(self):
+ # The sum of probs should be 1.0 with some tolerance.
+ # For low precision dtypes the tolerance was too tight.
+ # See numpy github issue 6123.
+ random.seed(1234)
+ a = [1, 2, 3]
+ counts = [4, 4, 2]
+ for dt in np.float16, np.float32, np.float64:
+ probs = np.array(counts, dtype=dt) / sum(counts)
+ c = random.choice(a, p=probs)
+ assert_(c in a)
+ assert_raises(ValueError, random.choice, a, p=probs*0.9)
+
+ def test_shuffle_of_array_of_different_length_strings(self):
+ # Test that permuting an array of different length strings
+ # will not cause a segfault on garbage collection
+ # Tests gh-7710
+ random.seed(1234)
+
+ a = np.array(['a', 'a' * 1000])
+
+ for _ in range(100):
+ random.shuffle(a)
+
+ # Force Garbage Collection - should not segfault.
+ import gc
+ gc.collect()
+
+ def test_shuffle_of_array_of_objects(self):
+ # Test that permuting an array of objects will not cause
+ # a segfault on garbage collection.
+ # See gh-7719
+ random.seed(1234)
+ a = np.array([np.arange(1), np.arange(4)])
+
+ for _ in range(1000):
+ random.shuffle(a)
+
+ # Force Garbage Collection - should not segfault.
+ import gc
+ gc.collect()
+
+ def test_permutation_subclass(self):
+ class N(np.ndarray):
+ pass
+
+ random.seed(1)
+ orig = np.arange(3).view(N)
+ perm = random.permutation(orig)
+ assert_array_equal(perm, np.array([0, 2, 1]))
+ assert_array_equal(orig, np.arange(3).view(N))
+
+ class M(object):
+ a = np.arange(5)
+
+ def __array__(self):
+ return self.a
+
+ random.seed(1)
+ m = M()
+ perm = random.permutation(m)
+ assert_array_equal(perm, np.array([2, 1, 4, 0, 3]))
+ assert_array_equal(m.__array__(), np.arange(5))
+
+ def test_warns_byteorder(self):
+ # GH 13159
+ other_byteord_dt = '<i4' if sys.byteorder == 'big' else '>i4'
+ with pytest.deprecated_call(match='non-native byteorder is not'):
+ random.randint(0, 200, size=10, dtype=other_byteord_dt)
+
+ def test_named_argument_initialization(self):
+ # GH 13669
+ rs1 = np.random.RandomState(123456789)
+ rs2 = np.random.RandomState(seed=123456789)
+ assert rs1.randint(0, 100) == rs2.randint(0, 100)
+
+ def test_choice_retun_dtype(self):
+ # GH 9867
+ c = np.random.choice(10, p=[.1]*10, size=2)
+ assert c.dtype == np.dtype(int)
+ c = np.random.choice(10, p=[.1]*10, replace=False, size=2)
+ assert c.dtype == np.dtype(int)
+ c = np.random.choice(10, size=2)
+ assert c.dtype == np.dtype(int)
+ c = np.random.choice(10, replace=False, size=2)
+ assert c.dtype == np.dtype(int)
diff --git a/numpy/random/tests/test_regression.py b/numpy/random/tests/test_regression.py
index ca9bbbc71..509e2d57f 100644
--- a/numpy/random/tests/test_regression.py
+++ b/numpy/random/tests/test_regression.py
@@ -29,7 +29,8 @@ class TestRegression(object):
]
is_64bits = sys.maxsize > 2**32
if is_64bits and sys.platform != 'win32':
- args.append((2**40 - 2, 2**40 - 2, 2**40 - 2)) # Check for 64-bit systems
+ # Check for 64-bit systems
+ args.append((2**40 - 2, 2**40 - 2, 2**40 - 2))
for arg in args:
assert_(np.random.hypergeometric(*arg) > 0)
diff --git a/numpy/random/tests/test_seed_sequence.py b/numpy/random/tests/test_seed_sequence.py
new file mode 100644
index 000000000..8d6d604a2
--- /dev/null
+++ b/numpy/random/tests/test_seed_sequence.py
@@ -0,0 +1,54 @@
+import numpy as np
+from numpy.testing import assert_array_equal
+
+from numpy.random.bit_generator import SeedSequence
+
+
+def test_reference_data():
+ """ Check that SeedSequence generates data the same as the C++ reference.
+
+ https://gist.github.com/imneme/540829265469e673d045
+ """
+ inputs = [
+ [3735928559, 195939070, 229505742, 305419896],
+ [3668361503, 4165561550, 1661411377, 3634257570],
+ [164546577, 4166754639, 1765190214, 1303880213],
+ [446610472, 3941463886, 522937693, 1882353782],
+ [1864922766, 1719732118, 3882010307, 1776744564],
+ [4141682960, 3310988675, 553637289, 902896340],
+ [1134851934, 2352871630, 3699409824, 2648159817],
+ [1240956131, 3107113773, 1283198141, 1924506131],
+ [2669565031, 579818610, 3042504477, 2774880435],
+ [2766103236, 2883057919, 4029656435, 862374500],
+ ]
+ outputs = [
+ [3914649087, 576849849, 3593928901, 2229911004],
+ [2240804226, 3691353228, 1365957195, 2654016646],
+ [3562296087, 3191708229, 1147942216, 3726991905],
+ [1403443605, 3591372999, 1291086759, 441919183],
+ [1086200464, 2191331643, 560336446, 3658716651],
+ [3249937430, 2346751812, 847844327, 2996632307],
+ [2584285912, 4034195531, 3523502488, 169742686],
+ [959045797, 3875435559, 1886309314, 359682705],
+ [3978441347, 432478529, 3223635119, 138903045],
+ [296367413, 4262059219, 13109864, 3283683422],
+ ]
+ outputs64 = [
+ [2477551240072187391, 9577394838764454085],
+ [15854241394484835714, 11398914698975566411],
+ [13708282465491374871, 16007308345579681096],
+ [15424829579845884309, 1898028439751125927],
+ [9411697742461147792, 15714068361935982142],
+ [10079222287618677782, 12870437757549876199],
+ [17326737873898640088, 729039288628699544],
+ [16644868984619524261, 1544825456798124994],
+ [1857481142255628931, 596584038813451439],
+ [18305404959516669237, 14103312907920476776],
+ ]
+ for seed, expected, expected64 in zip(inputs, outputs, outputs64):
+ expected = np.array(expected, dtype=np.uint32)
+ ss = SeedSequence(seed)
+ state = ss.generate_state(len(expected))
+ assert_array_equal(state, expected)
+ state64 = ss.generate_state(len(expected64), dtype=np.uint64)
+ assert_array_equal(state64, expected64)
diff --git a/numpy/random/tests/test_smoke.py b/numpy/random/tests/test_smoke.py
new file mode 100644
index 000000000..84d261e5e
--- /dev/null
+++ b/numpy/random/tests/test_smoke.py
@@ -0,0 +1,828 @@
+import pickle
+import time
+from functools import partial
+
+import numpy as np
+import pytest
+from numpy.testing import assert_equal, assert_, assert_array_equal
+from numpy.random import (Generator, MT19937, PCG64, Philox, SFC64, entropy)
+
+@pytest.fixture(scope='module',
+ params=(np.bool, np.int8, np.int16, np.int32, np.int64,
+ np.uint8, np.uint16, np.uint32, np.uint64))
+def dtype(request):
+ return request.param
+
+
+def params_0(f):
+ val = f()
+ assert_(np.isscalar(val))
+ val = f(10)
+ assert_(val.shape == (10,))
+ val = f((10, 10))
+ assert_(val.shape == (10, 10))
+ val = f((10, 10, 10))
+ assert_(val.shape == (10, 10, 10))
+ val = f(size=(5, 5))
+ assert_(val.shape == (5, 5))
+
+
+def params_1(f, bounded=False):
+ a = 5.0
+ b = np.arange(2.0, 12.0)
+ c = np.arange(2.0, 102.0).reshape((10, 10))
+ d = np.arange(2.0, 1002.0).reshape((10, 10, 10))
+ e = np.array([2.0, 3.0])
+ g = np.arange(2.0, 12.0).reshape((1, 10, 1))
+ if bounded:
+ a = 0.5
+ b = b / (1.5 * b.max())
+ c = c / (1.5 * c.max())
+ d = d / (1.5 * d.max())
+ e = e / (1.5 * e.max())
+ g = g / (1.5 * g.max())
+
+ # Scalar
+ f(a)
+ # Scalar - size
+ f(a, size=(10, 10))
+ # 1d
+ f(b)
+ # 2d
+ f(c)
+ # 3d
+ f(d)
+ # 1d size
+ f(b, size=10)
+ # 2d - size - broadcast
+ f(e, size=(10, 2))
+ # 3d - size
+ f(g, size=(10, 10, 10))
+
+
+def comp_state(state1, state2):
+ identical = True
+ if isinstance(state1, dict):
+ for key in state1:
+ identical &= comp_state(state1[key], state2[key])
+ elif type(state1) != type(state2):
+ identical &= type(state1) == type(state2)
+ else:
+ if (isinstance(state1, (list, tuple, np.ndarray)) and isinstance(
+ state2, (list, tuple, np.ndarray))):
+ for s1, s2 in zip(state1, state2):
+ identical &= comp_state(s1, s2)
+ else:
+ identical &= state1 == state2
+ return identical
+
+
+def warmup(rg, n=None):
+ if n is None:
+ n = 11 + np.random.randint(0, 20)
+ rg.standard_normal(n)
+ rg.standard_normal(n)
+ rg.standard_normal(n, dtype=np.float32)
+ rg.standard_normal(n, dtype=np.float32)
+ rg.integers(0, 2 ** 24, n, dtype=np.uint64)
+ rg.integers(0, 2 ** 48, n, dtype=np.uint64)
+ rg.standard_gamma(11.0, n)
+ rg.standard_gamma(11.0, n, dtype=np.float32)
+ rg.random(n, dtype=np.float64)
+ rg.random(n, dtype=np.float32)
+
+
+class RNG(object):
+ @classmethod
+ def setup_class(cls):
+ # Overridden in test classes. Place holder to silence IDE noise
+ cls.bit_generator = PCG64
+ cls.advance = None
+ cls.seed = [12345]
+ cls.rg = Generator(cls.bit_generator(*cls.seed))
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 64
+ cls._extra_setup()
+
+ @classmethod
+ def _extra_setup(cls):
+ cls.vec_1d = np.arange(2.0, 102.0)
+ cls.vec_2d = np.arange(2.0, 102.0)[None, :]
+ cls.mat = np.arange(2.0, 102.0, 0.01).reshape((100, 100))
+ cls.seed_error = TypeError
+
+ def _reset_state(self):
+ self.rg.bit_generator.state = self.initial_state
+
+ def test_init(self):
+ rg = Generator(self.bit_generator())
+ state = rg.bit_generator.state
+ rg.standard_normal(1)
+ rg.standard_normal(1)
+ rg.bit_generator.state = state
+ new_state = rg.bit_generator.state
+ assert_(comp_state(state, new_state))
+
+ def test_advance(self):
+ state = self.rg.bit_generator.state
+ if hasattr(self.rg.bit_generator, 'advance'):
+ self.rg.bit_generator.advance(self.advance)
+ assert_(not comp_state(state, self.rg.bit_generator.state))
+ else:
+ bitgen_name = self.rg.bit_generator.__class__.__name__
+ pytest.skip('Advance is not supported by {0}'.format(bitgen_name))
+
+ def test_jump(self):
+ state = self.rg.bit_generator.state
+ if hasattr(self.rg.bit_generator, 'jumped'):
+ bit_gen2 = self.rg.bit_generator.jumped()
+ jumped_state = bit_gen2.state
+ assert_(not comp_state(state, jumped_state))
+ self.rg.random(2 * 3 * 5 * 7 * 11 * 13 * 17)
+ self.rg.bit_generator.state = state
+ bit_gen3 = self.rg.bit_generator.jumped()
+ rejumped_state = bit_gen3.state
+ assert_(comp_state(jumped_state, rejumped_state))
+ else:
+ bitgen_name = self.rg.bit_generator.__class__.__name__
+ if bitgen_name not in ('SFC64',):
+ raise AttributeError('no "jumped" in %s' % bitgen_name)
+ pytest.skip('Jump is not supported by {0}'.format(bitgen_name))
+
+ def test_uniform(self):
+ r = self.rg.uniform(-1.0, 0.0, size=10)
+ assert_(len(r) == 10)
+ assert_((r > -1).all())
+ assert_((r <= 0).all())
+
+ def test_uniform_array(self):
+ r = self.rg.uniform(np.array([-1.0] * 10), 0.0, size=10)
+ assert_(len(r) == 10)
+ assert_((r > -1).all())
+ assert_((r <= 0).all())
+ r = self.rg.uniform(np.array([-1.0] * 10),
+ np.array([0.0] * 10), size=10)
+ assert_(len(r) == 10)
+ assert_((r > -1).all())
+ assert_((r <= 0).all())
+ r = self.rg.uniform(-1.0, np.array([0.0] * 10), size=10)
+ assert_(len(r) == 10)
+ assert_((r > -1).all())
+ assert_((r <= 0).all())
+
+ def test_random(self):
+ assert_(len(self.rg.random(10)) == 10)
+ params_0(self.rg.random)
+
+ def test_standard_normal_zig(self):
+ assert_(len(self.rg.standard_normal(10)) == 10)
+
+ def test_standard_normal(self):
+ assert_(len(self.rg.standard_normal(10)) == 10)
+ params_0(self.rg.standard_normal)
+
+ def test_standard_gamma(self):
+ assert_(len(self.rg.standard_gamma(10, 10)) == 10)
+ assert_(len(self.rg.standard_gamma(np.array([10] * 10), 10)) == 10)
+ params_1(self.rg.standard_gamma)
+
+ def test_standard_exponential(self):
+ assert_(len(self.rg.standard_exponential(10)) == 10)
+ params_0(self.rg.standard_exponential)
+
+ def test_standard_exponential_float(self):
+ randoms = self.rg.standard_exponential(10, dtype='float32')
+ assert_(len(randoms) == 10)
+ assert randoms.dtype == np.float32
+ params_0(partial(self.rg.standard_exponential, dtype='float32'))
+
+ def test_standard_exponential_float_log(self):
+ randoms = self.rg.standard_exponential(10, dtype='float32',
+ method='inv')
+ assert_(len(randoms) == 10)
+ assert randoms.dtype == np.float32
+ params_0(partial(self.rg.standard_exponential, dtype='float32',
+ method='inv'))
+
+ def test_standard_cauchy(self):
+ assert_(len(self.rg.standard_cauchy(10)) == 10)
+ params_0(self.rg.standard_cauchy)
+
+ def test_standard_t(self):
+ assert_(len(self.rg.standard_t(10, 10)) == 10)
+ params_1(self.rg.standard_t)
+
+ def test_binomial(self):
+ assert_(self.rg.binomial(10, .5) >= 0)
+ assert_(self.rg.binomial(1000, .5) >= 0)
+
+ def test_reset_state(self):
+ state = self.rg.bit_generator.state
+ int_1 = self.rg.integers(2**31)
+ self.rg.bit_generator.state = state
+ int_2 = self.rg.integers(2**31)
+ assert_(int_1 == int_2)
+
+ def test_entropy_init(self):
+ rg = Generator(self.bit_generator())
+ rg2 = Generator(self.bit_generator())
+ assert_(not comp_state(rg.bit_generator.state,
+ rg2.bit_generator.state))
+
+ def test_seed(self):
+ rg = Generator(self.bit_generator(*self.seed))
+ rg2 = Generator(self.bit_generator(*self.seed))
+ rg.random()
+ rg2.random()
+ assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state))
+
+ def test_reset_state_gauss(self):
+ rg = Generator(self.bit_generator(*self.seed))
+ rg.standard_normal()
+ state = rg.bit_generator.state
+ n1 = rg.standard_normal(size=10)
+ rg2 = Generator(self.bit_generator())
+ rg2.bit_generator.state = state
+ n2 = rg2.standard_normal(size=10)
+ assert_array_equal(n1, n2)
+
+ def test_reset_state_uint32(self):
+ rg = Generator(self.bit_generator(*self.seed))
+ rg.integers(0, 2 ** 24, 120, dtype=np.uint32)
+ state = rg.bit_generator.state
+ n1 = rg.integers(0, 2 ** 24, 10, dtype=np.uint32)
+ rg2 = Generator(self.bit_generator())
+ rg2.bit_generator.state = state
+ n2 = rg2.integers(0, 2 ** 24, 10, dtype=np.uint32)
+ assert_array_equal(n1, n2)
+
+ def test_reset_state_float(self):
+ rg = Generator(self.bit_generator(*self.seed))
+ rg.random(dtype='float32')
+ state = rg.bit_generator.state
+ n1 = rg.random(size=10, dtype='float32')
+ rg2 = Generator(self.bit_generator())
+ rg2.bit_generator.state = state
+ n2 = rg2.random(size=10, dtype='float32')
+ assert_((n1 == n2).all())
+
+ def test_shuffle(self):
+ original = np.arange(200, 0, -1)
+ permuted = self.rg.permutation(original)
+ assert_((original != permuted).any())
+
+ def test_permutation(self):
+ original = np.arange(200, 0, -1)
+ permuted = self.rg.permutation(original)
+ assert_((original != permuted).any())
+
+ def test_beta(self):
+ vals = self.rg.beta(2.0, 2.0, 10)
+ assert_(len(vals) == 10)
+ vals = self.rg.beta(np.array([2.0] * 10), 2.0)
+ assert_(len(vals) == 10)
+ vals = self.rg.beta(2.0, np.array([2.0] * 10))
+ assert_(len(vals) == 10)
+ vals = self.rg.beta(np.array([2.0] * 10), np.array([2.0] * 10))
+ assert_(len(vals) == 10)
+ vals = self.rg.beta(np.array([2.0] * 10), np.array([[2.0]] * 10))
+ assert_(vals.shape == (10, 10))
+
+ def test_bytes(self):
+ vals = self.rg.bytes(10)
+ assert_(len(vals) == 10)
+
+ def test_chisquare(self):
+ vals = self.rg.chisquare(2.0, 10)
+ assert_(len(vals) == 10)
+ params_1(self.rg.chisquare)
+
+ def test_exponential(self):
+ vals = self.rg.exponential(2.0, 10)
+ assert_(len(vals) == 10)
+ params_1(self.rg.exponential)
+
+ def test_f(self):
+ vals = self.rg.f(3, 1000, 10)
+ assert_(len(vals) == 10)
+
+ def test_gamma(self):
+ vals = self.rg.gamma(3, 2, 10)
+ assert_(len(vals) == 10)
+
+ def test_geometric(self):
+ vals = self.rg.geometric(0.5, 10)
+ assert_(len(vals) == 10)
+ params_1(self.rg.exponential, bounded=True)
+
+ def test_gumbel(self):
+ vals = self.rg.gumbel(2.0, 2.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_laplace(self):
+ vals = self.rg.laplace(2.0, 2.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_logitic(self):
+ vals = self.rg.logistic(2.0, 2.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_logseries(self):
+ vals = self.rg.logseries(0.5, 10)
+ assert_(len(vals) == 10)
+
+ def test_negative_binomial(self):
+ vals = self.rg.negative_binomial(10, 0.2, 10)
+ assert_(len(vals) == 10)
+
+ def test_noncentral_chisquare(self):
+ vals = self.rg.noncentral_chisquare(10, 2, 10)
+ assert_(len(vals) == 10)
+
+ def test_noncentral_f(self):
+ vals = self.rg.noncentral_f(3, 1000, 2, 10)
+ assert_(len(vals) == 10)
+ vals = self.rg.noncentral_f(np.array([3] * 10), 1000, 2)
+ assert_(len(vals) == 10)
+ vals = self.rg.noncentral_f(3, np.array([1000] * 10), 2)
+ assert_(len(vals) == 10)
+ vals = self.rg.noncentral_f(3, 1000, np.array([2] * 10))
+ assert_(len(vals) == 10)
+
+ def test_normal(self):
+ vals = self.rg.normal(10, 0.2, 10)
+ assert_(len(vals) == 10)
+
+ def test_pareto(self):
+ vals = self.rg.pareto(3.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_poisson(self):
+ vals = self.rg.poisson(10, 10)
+ assert_(len(vals) == 10)
+ vals = self.rg.poisson(np.array([10] * 10))
+ assert_(len(vals) == 10)
+ params_1(self.rg.poisson)
+
+ def test_power(self):
+ vals = self.rg.power(0.2, 10)
+ assert_(len(vals) == 10)
+
+ def test_integers(self):
+ vals = self.rg.integers(10, 20, 10)
+ assert_(len(vals) == 10)
+
+ def test_rayleigh(self):
+ vals = self.rg.rayleigh(0.2, 10)
+ assert_(len(vals) == 10)
+ params_1(self.rg.rayleigh, bounded=True)
+
+ def test_vonmises(self):
+ vals = self.rg.vonmises(10, 0.2, 10)
+ assert_(len(vals) == 10)
+
+ def test_wald(self):
+ vals = self.rg.wald(1.0, 1.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_weibull(self):
+ vals = self.rg.weibull(1.0, 10)
+ assert_(len(vals) == 10)
+
+ def test_zipf(self):
+ vals = self.rg.zipf(10, 10)
+ assert_(len(vals) == 10)
+ vals = self.rg.zipf(self.vec_1d)
+ assert_(len(vals) == 100)
+ vals = self.rg.zipf(self.vec_2d)
+ assert_(vals.shape == (1, 100))
+ vals = self.rg.zipf(self.mat)
+ assert_(vals.shape == (100, 100))
+
+ def test_hypergeometric(self):
+ vals = self.rg.hypergeometric(25, 25, 20)
+ assert_(np.isscalar(vals))
+ vals = self.rg.hypergeometric(np.array([25] * 10), 25, 20)
+ assert_(vals.shape == (10,))
+
+ def test_triangular(self):
+ vals = self.rg.triangular(-5, 0, 5)
+ assert_(np.isscalar(vals))
+ vals = self.rg.triangular(-5, np.array([0] * 10), 5)
+ assert_(vals.shape == (10,))
+
+ def test_multivariate_normal(self):
+ mean = [0, 0]
+ cov = [[1, 0], [0, 100]] # diagonal covariance
+ x = self.rg.multivariate_normal(mean, cov, 5000)
+ assert_(x.shape == (5000, 2))
+ x_zig = self.rg.multivariate_normal(mean, cov, 5000)
+ assert_(x.shape == (5000, 2))
+ x_inv = self.rg.multivariate_normal(mean, cov, 5000)
+ assert_(x.shape == (5000, 2))
+ assert_((x_zig != x_inv).any())
+
+ def test_multinomial(self):
+ vals = self.rg.multinomial(100, [1.0 / 3, 2.0 / 3])
+ assert_(vals.shape == (2,))
+ vals = self.rg.multinomial(100, [1.0 / 3, 2.0 / 3], size=10)
+ assert_(vals.shape == (10, 2))
+
+ def test_dirichlet(self):
+ s = self.rg.dirichlet((10, 5, 3), 20)
+ assert_(s.shape == (20, 3))
+
+ def test_pickle(self):
+ pick = pickle.dumps(self.rg)
+ unpick = pickle.loads(pick)
+ assert_((type(self.rg) == type(unpick)))
+ assert_(comp_state(self.rg.bit_generator.state,
+ unpick.bit_generator.state))
+
+ pick = pickle.dumps(self.rg)
+ unpick = pickle.loads(pick)
+ assert_((type(self.rg) == type(unpick)))
+ assert_(comp_state(self.rg.bit_generator.state,
+ unpick.bit_generator.state))
+
+ def test_seed_array(self):
+ if self.seed_vector_bits is None:
+ bitgen_name = self.bit_generator.__name__
+ pytest.skip('Vector seeding is not supported by '
+ '{0}'.format(bitgen_name))
+
+ if self.seed_vector_bits == 32:
+ dtype = np.uint32
+ else:
+ dtype = np.uint64
+ seed = np.array([1], dtype=dtype)
+ bg = self.bit_generator(seed)
+ state1 = bg.state
+ bg = self.bit_generator(1)
+ state2 = bg.state
+ assert_(comp_state(state1, state2))
+
+ seed = np.arange(4, dtype=dtype)
+ bg = self.bit_generator(seed)
+ state1 = bg.state
+ bg = self.bit_generator(seed[0])
+ state2 = bg.state
+ assert_(not comp_state(state1, state2))
+
+ seed = np.arange(1500, dtype=dtype)
+ bg = self.bit_generator(seed)
+ state1 = bg.state
+ bg = self.bit_generator(seed[0])
+ state2 = bg.state
+ assert_(not comp_state(state1, state2))
+
+ seed = 2 ** np.mod(np.arange(1500, dtype=dtype),
+ self.seed_vector_bits - 1) + 1
+ bg = self.bit_generator(seed)
+ state1 = bg.state
+ bg = self.bit_generator(seed[0])
+ state2 = bg.state
+ assert_(not comp_state(state1, state2))
+
+ def test_uniform_float(self):
+ rg = Generator(self.bit_generator(12345))
+ warmup(rg)
+ state = rg.bit_generator.state
+ r1 = rg.random(11, dtype=np.float32)
+ rg2 = Generator(self.bit_generator())
+ warmup(rg2)
+ rg2.bit_generator.state = state
+ r2 = rg2.random(11, dtype=np.float32)
+ assert_array_equal(r1, r2)
+ assert_equal(r1.dtype, np.float32)
+ assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state))
+
+ def test_gamma_floats(self):
+ rg = Generator(self.bit_generator())
+ warmup(rg)
+ state = rg.bit_generator.state
+ r1 = rg.standard_gamma(4.0, 11, dtype=np.float32)
+ rg2 = Generator(self.bit_generator())
+ warmup(rg2)
+ rg2.bit_generator.state = state
+ r2 = rg2.standard_gamma(4.0, 11, dtype=np.float32)
+ assert_array_equal(r1, r2)
+ assert_equal(r1.dtype, np.float32)
+ assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state))
+
+ def test_normal_floats(self):
+ rg = Generator(self.bit_generator())
+ warmup(rg)
+ state = rg.bit_generator.state
+ r1 = rg.standard_normal(11, dtype=np.float32)
+ rg2 = Generator(self.bit_generator())
+ warmup(rg2)
+ rg2.bit_generator.state = state
+ r2 = rg2.standard_normal(11, dtype=np.float32)
+ assert_array_equal(r1, r2)
+ assert_equal(r1.dtype, np.float32)
+ assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state))
+
+ def test_normal_zig_floats(self):
+ rg = Generator(self.bit_generator())
+ warmup(rg)
+ state = rg.bit_generator.state
+ r1 = rg.standard_normal(11, dtype=np.float32)
+ rg2 = Generator(self.bit_generator())
+ warmup(rg2)
+ rg2.bit_generator.state = state
+ r2 = rg2.standard_normal(11, dtype=np.float32)
+ assert_array_equal(r1, r2)
+ assert_equal(r1.dtype, np.float32)
+ assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state))
+
+ def test_output_fill(self):
+ rg = self.rg
+ state = rg.bit_generator.state
+ size = (31, 7, 97)
+ existing = np.empty(size)
+ rg.bit_generator.state = state
+ rg.standard_normal(out=existing)
+ rg.bit_generator.state = state
+ direct = rg.standard_normal(size=size)
+ assert_equal(direct, existing)
+
+ sized = np.empty(size)
+ rg.bit_generator.state = state
+ rg.standard_normal(out=sized, size=sized.shape)
+
+ existing = np.empty(size, dtype=np.float32)
+ rg.bit_generator.state = state
+ rg.standard_normal(out=existing, dtype=np.float32)
+ rg.bit_generator.state = state
+ direct = rg.standard_normal(size=size, dtype=np.float32)
+ assert_equal(direct, existing)
+
+ def test_output_filling_uniform(self):
+ rg = self.rg
+ state = rg.bit_generator.state
+ size = (31, 7, 97)
+ existing = np.empty(size)
+ rg.bit_generator.state = state
+ rg.random(out=existing)
+ rg.bit_generator.state = state
+ direct = rg.random(size=size)
+ assert_equal(direct, existing)
+
+ existing = np.empty(size, dtype=np.float32)
+ rg.bit_generator.state = state
+ rg.random(out=existing, dtype=np.float32)
+ rg.bit_generator.state = state
+ direct = rg.random(size=size, dtype=np.float32)
+ assert_equal(direct, existing)
+
+ def test_output_filling_exponential(self):
+ rg = self.rg
+ state = rg.bit_generator.state
+ size = (31, 7, 97)
+ existing = np.empty(size)
+ rg.bit_generator.state = state
+ rg.standard_exponential(out=existing)
+ rg.bit_generator.state = state
+ direct = rg.standard_exponential(size=size)
+ assert_equal(direct, existing)
+
+ existing = np.empty(size, dtype=np.float32)
+ rg.bit_generator.state = state
+ rg.standard_exponential(out=existing, dtype=np.float32)
+ rg.bit_generator.state = state
+ direct = rg.standard_exponential(size=size, dtype=np.float32)
+ assert_equal(direct, existing)
+
+ def test_output_filling_gamma(self):
+ rg = self.rg
+ state = rg.bit_generator.state
+ size = (31, 7, 97)
+ existing = np.zeros(size)
+ rg.bit_generator.state = state
+ rg.standard_gamma(1.0, out=existing)
+ rg.bit_generator.state = state
+ direct = rg.standard_gamma(1.0, size=size)
+ assert_equal(direct, existing)
+
+ existing = np.zeros(size, dtype=np.float32)
+ rg.bit_generator.state = state
+ rg.standard_gamma(1.0, out=existing, dtype=np.float32)
+ rg.bit_generator.state = state
+ direct = rg.standard_gamma(1.0, size=size, dtype=np.float32)
+ assert_equal(direct, existing)
+
+ def test_output_filling_gamma_broadcast(self):
+ rg = self.rg
+ state = rg.bit_generator.state
+ size = (31, 7, 97)
+ mu = np.arange(97.0) + 1.0
+ existing = np.zeros(size)
+ rg.bit_generator.state = state
+ rg.standard_gamma(mu, out=existing)
+ rg.bit_generator.state = state
+ direct = rg.standard_gamma(mu, size=size)
+ assert_equal(direct, existing)
+
+ existing = np.zeros(size, dtype=np.float32)
+ rg.bit_generator.state = state
+ rg.standard_gamma(mu, out=existing, dtype=np.float32)
+ rg.bit_generator.state = state
+ direct = rg.standard_gamma(mu, size=size, dtype=np.float32)
+ assert_equal(direct, existing)
+
+ def test_output_fill_error(self):
+ rg = self.rg
+ size = (31, 7, 97)
+ existing = np.empty(size)
+ with pytest.raises(TypeError):
+ rg.standard_normal(out=existing, dtype=np.float32)
+ with pytest.raises(ValueError):
+ rg.standard_normal(out=existing[::3])
+ existing = np.empty(size, dtype=np.float32)
+ with pytest.raises(TypeError):
+ rg.standard_normal(out=existing, dtype=np.float64)
+
+ existing = np.zeros(size, dtype=np.float32)
+ with pytest.raises(TypeError):
+ rg.standard_gamma(1.0, out=existing, dtype=np.float64)
+ with pytest.raises(ValueError):
+ rg.standard_gamma(1.0, out=existing[::3], dtype=np.float32)
+ existing = np.zeros(size, dtype=np.float64)
+ with pytest.raises(TypeError):
+ rg.standard_gamma(1.0, out=existing, dtype=np.float32)
+ with pytest.raises(ValueError):
+ rg.standard_gamma(1.0, out=existing[::3])
+
+ def test_integers_broadcast(self, dtype):
+ if dtype == np.bool:
+ upper = 2
+ lower = 0
+ else:
+ info = np.iinfo(dtype)
+ upper = int(info.max) + 1
+ lower = info.min
+ self._reset_state()
+ a = self.rg.integers(lower, [upper] * 10, dtype=dtype)
+ self._reset_state()
+ b = self.rg.integers([lower] * 10, upper, dtype=dtype)
+ assert_equal(a, b)
+ self._reset_state()
+ c = self.rg.integers(lower, upper, size=10, dtype=dtype)
+ assert_equal(a, c)
+ self._reset_state()
+ d = self.rg.integers(np.array(
+ [lower] * 10), np.array([upper], dtype=np.object), size=10,
+ dtype=dtype)
+ assert_equal(a, d)
+ self._reset_state()
+ e = self.rg.integers(
+ np.array([lower] * 10), np.array([upper] * 10), size=10,
+ dtype=dtype)
+ assert_equal(a, e)
+
+ self._reset_state()
+ a = self.rg.integers(0, upper, size=10, dtype=dtype)
+ self._reset_state()
+ b = self.rg.integers([upper] * 10, dtype=dtype)
+ assert_equal(a, b)
+
+ def test_integers_numpy(self, dtype):
+ high = np.array([1])
+ low = np.array([0])
+
+ out = self.rg.integers(low, high, dtype=dtype)
+ assert out.shape == (1,)
+
+ out = self.rg.integers(low[0], high, dtype=dtype)
+ assert out.shape == (1,)
+
+ out = self.rg.integers(low, high[0], dtype=dtype)
+ assert out.shape == (1,)
+
+ def test_integers_broadcast_errors(self, dtype):
+ if dtype == np.bool:
+ upper = 2
+ lower = 0
+ else:
+ info = np.iinfo(dtype)
+ upper = int(info.max) + 1
+ lower = info.min
+ with pytest.raises(ValueError):
+ self.rg.integers(lower, [upper + 1] * 10, dtype=dtype)
+ with pytest.raises(ValueError):
+ self.rg.integers(lower - 1, [upper] * 10, dtype=dtype)
+ with pytest.raises(ValueError):
+ self.rg.integers([lower - 1], [upper] * 10, dtype=dtype)
+ with pytest.raises(ValueError):
+ self.rg.integers([0], [0], dtype=dtype)
+
+
+class TestMT19937(RNG):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = MT19937
+ cls.advance = None
+ cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1]
+ cls.rg = Generator(cls.bit_generator(*cls.seed))
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 32
+ cls._extra_setup()
+ cls.seed_error = ValueError
+
+ def test_numpy_state(self):
+ nprg = np.random.RandomState()
+ nprg.standard_normal(99)
+ state = nprg.get_state()
+ self.rg.bit_generator.state = state
+ state2 = self.rg.bit_generator.state
+ assert_((state[1] == state2['state']['key']).all())
+ assert_((state[2] == state2['state']['pos']))
+
+
+class TestPhilox(RNG):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = Philox
+ cls.advance = 2**63 + 2**31 + 2**15 + 1
+ cls.seed = [12345]
+ cls.rg = Generator(cls.bit_generator(*cls.seed))
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 64
+ cls._extra_setup()
+
+
+class TestSFC64(RNG):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = SFC64
+ cls.advance = None
+ cls.seed = [12345]
+ cls.rg = Generator(cls.bit_generator(*cls.seed))
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 192
+ cls._extra_setup()
+
+
+class TestPCG64(RNG):
+ @classmethod
+ def setup_class(cls):
+ cls.bit_generator = PCG64
+ cls.advance = 2**63 + 2**31 + 2**15 + 1
+ cls.seed = [12345]
+ cls.rg = Generator(cls.bit_generator(*cls.seed))
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 64
+ cls._extra_setup()
+
+
+class TestDefaultRNG(RNG):
+ @classmethod
+ def setup_class(cls):
+ # This will duplicate some tests that directly instantiate a fresh
+ # Generator(), but that's okay.
+ cls.bit_generator = PCG64
+ cls.advance = 2**63 + 2**31 + 2**15 + 1
+ cls.seed = [12345]
+ cls.rg = np.random.default_rng(*cls.seed)
+ cls.initial_state = cls.rg.bit_generator.state
+ cls.seed_vector_bits = 64
+ cls._extra_setup()
+
+ def test_default_is_pcg64(self):
+ # In order to change the default BitGenerator, we'll go through
+ # a deprecation cycle to move to a different function.
+ assert_(isinstance(self.rg.bit_generator, PCG64))
+
+ def test_seed(self):
+ np.random.default_rng()
+ np.random.default_rng(None)
+ np.random.default_rng(12345)
+ np.random.default_rng(0)
+ np.random.default_rng(43660444402423911716352051725018508569)
+ np.random.default_rng([43660444402423911716352051725018508569,
+ 279705150948142787361475340226491943209])
+ with pytest.raises(ValueError):
+ np.random.default_rng(-1)
+ with pytest.raises(ValueError):
+ np.random.default_rng([12345, -1])
+
+
+class TestEntropy(object):
+ def test_entropy(self):
+ e1 = entropy.random_entropy()
+ e2 = entropy.random_entropy()
+ assert_((e1 != e2))
+ e1 = entropy.random_entropy(10)
+ e2 = entropy.random_entropy(10)
+ assert_((e1 != e2).all())
+ e1 = entropy.random_entropy(10, source='system')
+ e2 = entropy.random_entropy(10, source='system')
+ assert_((e1 != e2).all())
+
+ def test_fallback(self):
+ e1 = entropy.random_entropy(source='fallback')
+ time.sleep(0.1)
+ e2 = entropy.random_entropy(source='fallback')
+ assert_((e1 != e2))
+
diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py
index c098e9181..ead5d264d 100644
--- a/numpy/testing/_private/utils.py
+++ b/numpy/testing/_private/utils.py
@@ -301,10 +301,6 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
check that all elements of these objects are equal. An exception is raised
at the first conflicting values.
- When one of `actual` and `desired` is a scalar and the other is array_like,
- the function checks that each element of the array_like object is equal to
- the scalar.
-
This function handles NaN comparisons as if NaN was a "normal" number.
That is, no assertion is raised if both objects have NaNs in the same
positions. This is in contrast to the IEEE standard on NaNs, which says
@@ -395,21 +391,6 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
if isscalar(desired) != isscalar(actual):
raise AssertionError(msg)
- try:
- isdesnat = isnat(desired)
- isactnat = isnat(actual)
- dtypes_match = array(desired).dtype.type == array(actual).dtype.type
- if isdesnat and isactnat:
- # If both are NaT (and have the same dtype -- datetime or
- # timedelta) they are considered equal.
- if dtypes_match:
- return
- else:
- raise AssertionError(msg)
-
- except (TypeError, ValueError, NotImplementedError):
- pass
-
# Inf/nan/negative zero handling
try:
isdesnan = gisnan(desired)
@@ -418,18 +399,6 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
return # both nan, so equal
# handle signed zero specially for floats
- array_actual = array(actual)
- array_desired = array(desired)
- if (array_actual.dtype.char in 'Mm' or
- array_desired.dtype.char in 'Mm'):
- # version 1.18
- # until this version, gisnan failed for datetime64 and timedelta64.
- # Now it succeeds but comparison to scalar with a different type
- # emits a DeprecationWarning.
- # Avoid that by skipping the next check
- raise NotImplementedError('cannot compare to a scalar '
- 'with a different type')
-
if desired == 0 and actual == 0:
if not signbit(desired) == signbit(actual):
raise AssertionError(msg)
@@ -438,6 +407,21 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
pass
try:
+ isdesnat = isnat(desired)
+ isactnat = isnat(actual)
+ dtypes_match = array(desired).dtype.type == array(actual).dtype.type
+ if isdesnat and isactnat:
+ # If both are NaT (and have the same dtype -- datetime or
+ # timedelta) they are considered equal.
+ if dtypes_match:
+ return
+ else:
+ raise AssertionError(msg)
+
+ except (TypeError, ValueError, NotImplementedError):
+ pass
+
+ try:
# Explicitly use __eq__ for comparison, gh-2552
if not (desired == actual):
raise AssertionError(msg)
@@ -719,7 +703,7 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
header='', precision=6, equal_nan=True,
equal_inf=True):
__tracebackhide__ = True # Hide traceback for py.test
- from numpy.core import array, array2string, isnan, inf, bool_, errstate, all, max, object_
+ from numpy.core import array, array2string, isnan, inf, bool_, errstate
x = array(x, copy=False, subok=True)
y = array(y, copy=False, subok=True)
@@ -820,19 +804,15 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
# do not trigger a failure (np.ma.masked != True evaluates as
# np.ma.masked, which is falsy).
if cond != True:
- n_mismatch = reduced.size - reduced.sum(dtype=intp)
- n_elements = flagged.size if flagged.ndim != 0 else reduced.size
- percent_mismatch = 100 * n_mismatch / n_elements
- remarks = [
- 'Mismatched elements: {} / {} ({:.3g}%)'.format(
- n_mismatch, n_elements, percent_mismatch)]
+ mismatch = 100. * (reduced.size - reduced.sum(dtype=intp)) / ox.size
+ remarks = ['Mismatch: {:.3g}%'.format(mismatch)]
with errstate(invalid='ignore', divide='ignore'):
# ignore errors for non-numeric types
- try:
+ with contextlib.suppress(TypeError):
error = abs(x - y)
- max_abs_error = max(error)
- if getattr(error, 'dtype', object_) == object_:
+ max_abs_error = error.max()
+ if error.dtype == 'object':
remarks.append('Max absolute difference: '
+ str(max_abs_error))
else:
@@ -841,20 +821,13 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
# note: this definition of relative error matches that one
# used by assert_allclose (found in np.isclose)
- # Filter values where the divisor would be zero
- nonzero = bool_(y != 0)
- if all(~nonzero):
- max_rel_error = array(inf)
- else:
- max_rel_error = max(error[nonzero] / abs(y[nonzero]))
- if getattr(error, 'dtype', object_) == object_:
+ max_rel_error = (error / abs(y)).max()
+ if error.dtype == 'object':
remarks.append('Max relative difference: '
+ str(max_rel_error))
else:
remarks.append('Max relative difference: '
+ array2string(max_rel_error))
- except TypeError:
- pass
err_msg += '\n' + '\n'.join(remarks)
msg = build_err_msg([ox, oy], err_msg,
@@ -876,11 +849,10 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
Raises an AssertionError if two array_like objects are not equal.
Given two array_like objects, check that the shape is equal and all
- elements of these objects are equal (but see the Notes for the special
- handling of a scalar). An exception is raised at shape mismatch or
- conflicting values. In contrast to the standard usage in numpy, NaNs
- are compared like numbers, no assertion is raised if both objects have
- NaNs in the same positions.
+ elements of these objects are equal. An exception is raised at
+ shape mismatch or conflicting values. In contrast to the standard usage
+ in numpy, NaNs are compared like numbers, no assertion is raised if
+ both objects have NaNs in the same positions.
The usual caution for verifying equality with floating point numbers is
advised.
@@ -907,12 +879,6 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
relative and/or absolute precision.
assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal
- Notes
- -----
- When one of `x` and `y` is a scalar and the other is array_like, the
- function checks that each element of the array_like object is equal to
- the scalar.
-
Examples
--------
The first assert does not raise an exception:
@@ -920,7 +886,7 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
>>> np.testing.assert_array_equal([1.0,2.33333,np.nan],
... [np.exp(0),2.33333, np.nan])
- Assert fails with numerical imprecision with floats:
+ Assert fails with numerical inprecision with floats:
>>> np.testing.assert_array_equal([1.0,np.pi,np.nan],
... [1, np.sqrt(np.pi)**2, np.nan])
@@ -941,12 +907,6 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
... [1, np.sqrt(np.pi)**2, np.nan],
... rtol=1e-10, atol=0)
- As mentioned in the Notes section, `assert_array_equal` has special
- handling for scalars. Here the test checks that each value in `x` is 3:
-
- >>> x = np.full((2, 5), fill_value=3)
- >>> np.testing.assert_array_equal(x, 3)
-
"""
__tracebackhide__ = True # Hide traceback for py.test
assert_array_compare(operator.__eq__, x, y, err_msg=err_msg,
@@ -1185,7 +1145,7 @@ def assert_string_equal(actual, desired):
if desired == actual:
return
- diff = list(difflib.Differ().compare(actual.splitlines(True), desired.splitlines(True)))
+ diff = list(difflib.Differ().compare(actual.splitlines(1), desired.splitlines(1)))
diff_list = []
while diff:
d1 = diff.pop(0)
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index 7f6cbb8fe..bf60772d3 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -17,7 +17,7 @@ from numpy.testing import (
clear_and_catch_warnings, suppress_warnings, assert_string_equal, assert_,
tempdir, temppath, assert_no_gc_cycles, HAS_REFCOUNT
)
-from numpy.core.overrides import ENABLE_ARRAY_FUNCTION
+from numpy.core.overrides import ARRAY_FUNCTION_ENABLED
class _GenericTest(object):
@@ -90,21 +90,6 @@ class TestArrayEqual(_GenericTest):
for t in ['S1', 'U1']:
foo(t)
- def test_0_ndim_array(self):
- x = np.array(473963742225900817127911193656584771)
- y = np.array(18535119325151578301457182298393896)
- assert_raises(AssertionError, self._assert_func, x, y)
-
- y = x
- self._assert_func(x, y)
-
- x = np.array(43)
- y = np.array(10)
- assert_raises(AssertionError, self._assert_func, x, y)
-
- y = x
- self._assert_func(x, y)
-
def test_generic_rank3(self):
"""Test rank 3 array for all dtypes."""
def foo(t):
@@ -196,7 +181,7 @@ class TestArrayEqual(_GenericTest):
self._test_not_equal(b, a)
@pytest.mark.skipif(
- not ENABLE_ARRAY_FUNCTION, reason='requires __array_function__')
+ not ARRAY_FUNCTION_ENABLED, reason='requires __array_function__')
def test_subclass_that_does_not_implement_npall(self):
class MyArray(np.ndarray):
def __array_function__(self, *args, **kwargs):
@@ -535,7 +520,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y, decimal=12)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 3 / 3 (100%)')
+ assert_equal(msgs[3], 'Mismatch: 100%')
assert_equal(msgs[4], 'Max absolute difference: 1.e-05')
assert_equal(msgs[5], 'Max relative difference: 3.33328889e-06')
assert_equal(
@@ -551,7 +536,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 1 / 3 (33.3%)')
+ assert_equal(msgs[3], 'Mismatch: 33.3%')
assert_equal(msgs[4], 'Max absolute difference: 1.e-05')
assert_equal(msgs[5], 'Max relative difference: 3.33328889e-06')
assert_equal(msgs[6], ' x: array([1. , 2. , 3.00003])')
@@ -563,7 +548,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 1 / 2 (50%)')
+ assert_equal(msgs[3], 'Mismatch: 50%')
assert_equal(msgs[4], 'Max absolute difference: 1.')
assert_equal(msgs[5], 'Max relative difference: 1.')
assert_equal(msgs[6], ' x: array([inf, 0.])')
@@ -575,30 +560,10 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 2 / 2 (100%)')
+ assert_equal(msgs[3], 'Mismatch: 100%')
assert_equal(msgs[4], 'Max absolute difference: 2')
assert_equal(msgs[5], 'Max relative difference: inf')
- def test_error_message_2(self):
- """Check the message is formatted correctly when either x or y is a scalar."""
- x = 2
- y = np.ones(20)
- with pytest.raises(AssertionError) as exc_info:
- self._assert_func(x, y)
- msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 20 / 20 (100%)')
- assert_equal(msgs[4], 'Max absolute difference: 1.')
- assert_equal(msgs[5], 'Max relative difference: 1.')
-
- y = 2
- x = np.ones(20)
- with pytest.raises(AssertionError) as exc_info:
- self._assert_func(x, y)
- msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatched elements: 20 / 20 (100%)')
- assert_equal(msgs[4], 'Max absolute difference: 1.')
- assert_equal(msgs[5], 'Max relative difference: 0.5')
-
def test_subclass_that_cannot_be_bool(self):
# While we cannot guarantee testing functions will always work for
# subclasses, the tests should ideally rely only on subclasses having
@@ -623,9 +588,9 @@ class TestApproxEqual(object):
def setup(self):
self._assert_func = assert_approx_equal
- def test_simple_0d_arrays(self):
- x = np.array(1234.22)
- y = np.array(1234.23)
+ def test_simple_arrays(self):
+ x = np.array([1234.22])
+ y = np.array([1234.23])
self._assert_func(x, y, significant=5)
self._assert_func(x, y, significant=6)
@@ -890,8 +855,7 @@ class TestAssertAllclose(object):
with pytest.raises(AssertionError) as exc_info:
assert_allclose(a, b)
msg = str(exc_info.value)
- assert_('Mismatched elements: 1 / 4 (25%)\n'
- 'Max absolute difference: 1\n'
+ assert_('Mismatch: 25%\nMax absolute difference: 1\n'
'Max relative difference: 0.5' in msg)
def test_equal_nan(self):
@@ -916,15 +880,6 @@ class TestAssertAllclose(object):
assert_array_less(a, b)
assert_allclose(a, b)
- def test_report_max_relative_error(self):
- a = np.array([0, 1])
- b = np.array([0, 2])
-
- with pytest.raises(AssertionError) as exc_info:
- assert_allclose(a, b)
- msg = str(exc_info.value)
- assert_('Max relative difference: 0.5' in msg)
-
class TestArrayAlmostEqualNulp(object):
diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py
index 194f8ecbb..807c98652 100644
--- a/numpy/tests/test_public_api.py
+++ b/numpy/tests/test_public_api.py
@@ -43,7 +43,6 @@ def test_numpy_namespace():
'get_include': 'numpy.lib.utils.get_include',
'int_asbuffer': 'numpy.core._multiarray_umath.int_asbuffer',
'mafromtxt': 'numpy.lib.npyio.mafromtxt',
- 'maximum_sctype': 'numpy.core.numerictypes.maximum_sctype',
'ndfromtxt': 'numpy.lib.npyio.ndfromtxt',
'recfromcsv': 'numpy.lib.npyio.recfromcsv',
'recfromtxt': 'numpy.lib.npyio.recfromtxt',
diff --git a/numpy/tests/test_reloading.py b/numpy/tests/test_reloading.py
index a073d691f..e378d1463 100644
--- a/numpy/tests/test_reloading.py
+++ b/numpy/tests/test_reloading.py
@@ -3,7 +3,7 @@ from __future__ import division, absolute_import, print_function
import sys
from numpy.testing import assert_raises, assert_, assert_equal
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
if sys.version_info[:2] >= (3, 4):
from importlib import reload
diff --git a/numpy/tests/test_warnings.py b/numpy/tests/test_warnings.py
index aa6f69f7e..f5560a099 100644
--- a/numpy/tests/test_warnings.py
+++ b/numpy/tests/test_warnings.py
@@ -44,7 +44,7 @@ if sys.version_info >= (3, 4):
if p.ls[-1] == 'warn' and (
len(p.ls) == 1 or p.ls[-2] == 'warnings'):
- if "testing/tests/test_warnings.py" is self.__filename:
+ if "testing/tests/test_warnings.py" == self.__filename:
# This file
return