From 3102fc6a67527cd57831dc156914cc49bb92fda0 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 20 Feb 2018 16:11:43 +0000 Subject: [PATCH 001/138] INIT: Initial commit with basic structure Basic structure of a core PRNG and a generator that consumes the core PRNG CLN: Remove unneeded code Remove unnecessary code and add docstrings --- _randomgen/.gitignore | 5 ++ _randomgen/README.md | 21 ++++++++ _randomgen/core_prng/__init__.py | 0 _randomgen/core_prng/common.c | 0 _randomgen/core_prng/common.h | 0 _randomgen/core_prng/common.pxd | 9 ++++ _randomgen/core_prng/core_prng.pyx | 81 ++++++++++++++++++++++++++++++ _randomgen/core_prng/generator.pyx | 41 +++++++++++++++ _randomgen/setup.py | 33 ++++++++++++ 9 files changed, 190 insertions(+) create mode 100644 _randomgen/.gitignore create mode 100644 _randomgen/README.md create mode 100644 _randomgen/core_prng/__init__.py create mode 100644 _randomgen/core_prng/common.c create mode 100644 _randomgen/core_prng/common.h create mode 100644 _randomgen/core_prng/common.pxd create mode 100644 _randomgen/core_prng/core_prng.pyx create mode 100644 _randomgen/core_prng/generator.pyx create mode 100644 _randomgen/setup.py diff --git a/_randomgen/.gitignore b/_randomgen/.gitignore new file mode 100644 index 000000000000..fd7f147c8885 --- /dev/null +++ b/_randomgen/.gitignore @@ -0,0 +1,5 @@ +.idea/ +build/ +*.egg-info/ +*.pyd +*.html diff --git a/_randomgen/README.md b/_randomgen/README.md new file mode 100644 index 000000000000..f04d423276d0 --- /dev/null +++ b/_randomgen/README.md @@ -0,0 +1,21 @@ +# Core PRNG + +Experimental Core Pseudo Random Number Generator interface for future +NumPy RandomState evolution. + +## Demo + +Basic POC demonstration + +```bash +python setup.py develop +``` + +```ipython +In [13]: import core_prng.generator + +In [14]: rg = core_prng.generator.RandomGenerator() + +In [15]: rg.random_integer() +Out[15]: 872337561037043212 +``` diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/core_prng/common.c b/_randomgen/core_prng/common.c new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/core_prng/common.h b/_randomgen/core_prng/common.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd new file mode 100644 index 000000000000..e9949220f9c6 --- /dev/null +++ b/_randomgen/core_prng/common.pxd @@ -0,0 +1,9 @@ +from libc.stdint cimport uint64_t + +ctypedef uint64_t (*random_uint64_anon)(void* st) + +cdef struct anon_func_state: + void *state + void *f + +ctypedef anon_func_state anon_func_state_t diff --git a/_randomgen/core_prng/core_prng.pyx b/_randomgen/core_prng/core_prng.pyx new file mode 100644 index 000000000000..a43fb9e259db --- /dev/null +++ b/_randomgen/core_prng/core_prng.pyx @@ -0,0 +1,81 @@ +import numpy as np +cimport numpy as np +from libc.stdint cimport uint64_t +from cpython.pycapsule cimport PyCapsule_New +from common cimport * + +np.import_array() + +cdef struct state: + uint64_t state + +ctypedef state state_t + +ctypedef uint64_t (*random_uint64)(state_t *st) + +cdef struct func_state: + state st + random_uint64 f + +ctypedef func_state func_state_t + + +cdef uint64_t _splitmix64(state_t *st): + cdef uint64_t z + # TODO: Use literals -- PyCharm complains + cdef uint64_t c1 = 11400714819323198485 + cdef uint64_t c2 = 13787848793156543929 + cdef uint64_t c3 = 10723151780598845931 + st[0].state += c1 # 0x9E3779B97F4A7C15 + z = st[0].state + z = (z ^ (z >> 30)) * c2 # 0xBF58476D1CE4E5B9 + z = (z ^ (z >> 27)) * c3 # 0x94D049BB133111EB + return z ^ (z >> 31) + +cdef uint64_t _splitmix64_anon(void* st): + return _splitmix64( st) + +cdef class CorePRNG: + """ + Prototype Core PRNG using directly implemented version of SplitMix64. + + Notes + ----- + Exposes no user-facing API except `get_state` and `set_state`. Designed + for use in a `RandomGenerator` object. + """ + cdef state rng_state + cdef anon_func_state anon_func_state + cdef public object _anon_func_state + + def __init__(self): + self.rng_state.state = 17013192669731687406 + + self.anon_func_state.state = &self.rng_state + self.anon_func_state.f = &_splitmix64_anon + cdef const char *anon_name = "Anon CorePRNG func_state" + self._anon_func_state = PyCapsule_New(&self.anon_func_state, + anon_name, NULL) + + def __random_integer(self): + """ + 64-bit Random Integers from the PRNG + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + return _splitmix64(&self.rng_state) + + def get_state(self): + """Get PRNG state""" + return self.rng_state.state + + def set_state(self, uint64_t value): + """Set PRNG state""" + self.rng_state.state = value diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx new file mode 100644 index 000000000000..da96687cdfe7 --- /dev/null +++ b/_randomgen/core_prng/generator.pyx @@ -0,0 +1,41 @@ +import numpy as np +cimport numpy as np +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from common cimport * + +from core_prng.core_prng import CorePRNG + +np.import_array() + +cdef class RandomGenerator: + """ + Prototype Random Generator that consumes randoms from a CorePRNG class + + Parameters + ---------- + prng : CorePRNG, optional + Object exposing a PyCapsule containing state and function pointers + + Examples + -------- + >>> from core_prng.generator import RandomGenerator + >>> rg = RandomGenerator() + >>> rg.random_integer() + """ + cdef public object __core_prng + cdef anon_func_state anon_rng_func_state + + def __init__(self, prng=None): + if prng is None: + prng = CorePRNG() + self.__core_prng = prng + + capsule = prng._anon_func_state + cdef const char *anon_name = "Anon CorePRNG func_state" + if not PyCapsule_IsValid(capsule, anon_name): + raise ValueError("Invalid pointer to anon_func_state") + self.anon_rng_func_state = (PyCapsule_GetPointer(capsule, anon_name))[0] + + def random_integer(self): + cdef random_uint64_anon f = self.anon_rng_func_state.f + return f(self.anon_rng_func_state.state) diff --git a/_randomgen/setup.py b/_randomgen/setup.py new file mode 100644 index 000000000000..9cb861f5048e --- /dev/null +++ b/_randomgen/setup.py @@ -0,0 +1,33 @@ +import numpy as np +from Cython.Build import cythonize +from setuptools import setup, find_packages, Distribution +from setuptools.extension import Extension + +extensions = [Extension("core_prng.core_prng", + ["core_prng/core_prng.pyx"], + include_dirs=[np.get_include()]), + Extension("core_prng.generator", + ["core_prng/generator.pyx"], + include_dirs=[np.get_include()])] + +class BinaryDistribution(Distribution): + def is_pure(self): + return False + + +setup( + ext_modules=cythonize(extensions), + name='core_prng', + packages=find_packages(), + package_dir={'core_prng': './core_prng'}, + package_data={'': ['*.c', '*.h', '*.pxi', '*.pyx', '*.pxd']}, + include_package_data=True, + license='NSCA', + author='Kevin Sheppard', + author_email='kevin.k.sheppard@gmail.com', + distclass=BinaryDistribution, + description='Next-gen RandomState supporting multiple PRNGs', + url='https://github.com/bashtage/core-prng', + keywords=['pseudo random numbers', 'PRNG', 'Python'], + zip_safe=False +) From fa3bef5639b2f3223eeee7c50155824b8df991e0 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 22 Feb 2018 10:10:28 +0000 Subject: [PATCH 002/138] ENH: Add support for xoroshiro128 Clean up splitmix64 to use external functions Add xoroshiro128 to show use of additional PRNG --- _randomgen/README.md | 17 ++++- _randomgen/core_prng/common.c | 0 _randomgen/core_prng/common.h | 0 _randomgen/core_prng/generator.pyx | 14 +++- .../{core_prng.pyx => splitmix64.pyx} | 36 +++------ .../core_prng/src/splitmix64/splitmix64.c | 25 +++++++ .../core_prng/src/splitmix64/splitmix64.h | 12 +++ .../src/splitmix64/splitmix64.orig.c | 28 +++++++ .../core_prng/src/xoroshiro128/xoroshiro128.c | 53 +++++++++++++ .../core_prng/src/xoroshiro128/xoroshiro128.h | 23 ++++++ .../src/xoroshiro128/xoroshiro128plus.orig.c | 74 ++++++++++++++++++ _randomgen/core_prng/xoroshiro128.pyx | 75 +++++++++++++++++++ _randomgen/demo.py | 7 ++ _randomgen/setup.py | 19 ++++- 14 files changed, 347 insertions(+), 36 deletions(-) delete mode 100644 _randomgen/core_prng/common.c delete mode 100644 _randomgen/core_prng/common.h rename _randomgen/core_prng/{core_prng.pyx => splitmix64.pyx} (61%) create mode 100644 _randomgen/core_prng/src/splitmix64/splitmix64.c create mode 100644 _randomgen/core_prng/src/splitmix64/splitmix64.h create mode 100644 _randomgen/core_prng/src/splitmix64/splitmix64.orig.c create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128.c create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128.h create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c create mode 100644 _randomgen/core_prng/xoroshiro128.pyx create mode 100644 _randomgen/demo.py diff --git a/_randomgen/README.md b/_randomgen/README.md index f04d423276d0..0e0bdda72e63 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -12,10 +12,19 @@ python setup.py develop ``` ```ipython -In [13]: import core_prng.generator +In [1]: import core_prng.generator -In [14]: rg = core_prng.generator.RandomGenerator() +# Default generator is Splitmix64 +In [2]: rg = core_prng.generator.RandomGenerator() -In [15]: rg.random_integer() -Out[15]: 872337561037043212 +In [3]: rg.random_integer() +Out[3]: 872337561037043212 + +In [4]: from core_prng.xoroshiro128 import Xoroshiro128 + +# Swap the generator +In [5]: rg = core_prng.generator.RandomGenerator(Xoroshiro128()) + +In [6]: rg.random_integer() +Out[6]: 13370384800127340062 ``` diff --git a/_randomgen/core_prng/common.c b/_randomgen/core_prng/common.c deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/_randomgen/core_prng/common.h b/_randomgen/core_prng/common.h deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index da96687cdfe7..2648f9c0593a 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -3,7 +3,7 @@ cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * -from core_prng.core_prng import CorePRNG +from core_prng.splitmix64 import SplitMix64 np.import_array() @@ -24,10 +24,12 @@ cdef class RandomGenerator: """ cdef public object __core_prng cdef anon_func_state anon_rng_func_state + cdef random_uint64_anon next_uint64 + cdef void *rng_state def __init__(self, prng=None): if prng is None: - prng = CorePRNG() + prng = SplitMix64() self.__core_prng = prng capsule = prng._anon_func_state @@ -35,7 +37,11 @@ cdef class RandomGenerator: if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") self.anon_rng_func_state = (PyCapsule_GetPointer(capsule, anon_name))[0] + self.next_uint64 = self.anon_rng_func_state.f + self.rng_state = self.anon_rng_func_state.state def random_integer(self): - cdef random_uint64_anon f = self.anon_rng_func_state.f - return f(self.anon_rng_func_state.state) + return self.next_uint64(self.rng_state) + + def random_double(self): + return (self.next_uint64(self.rng_state) >> 11) * (1.0 / 9007199254740992.0) diff --git a/_randomgen/core_prng/core_prng.pyx b/_randomgen/core_prng/splitmix64.pyx similarity index 61% rename from _randomgen/core_prng/core_prng.pyx rename to _randomgen/core_prng/splitmix64.pyx index a43fb9e259db..9b26d233b637 100644 --- a/_randomgen/core_prng/core_prng.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -6,36 +6,22 @@ from common cimport * np.import_array() -cdef struct state: - uint64_t state +cdef extern from "src/splitmix64/splitmix64.h": -ctypedef state state_t + cdef struct s_splitmix64_state: + uint64_t state -ctypedef uint64_t (*random_uint64)(state_t *st) + ctypedef s_splitmix64_state splitmix64_state -cdef struct func_state: - state st - random_uint64 f + cdef uint64_t splitmix64_next(splitmix64_state* state) nogil -ctypedef func_state func_state_t +ctypedef uint64_t (*random_uint64)(splitmix64_state* state) -cdef uint64_t _splitmix64(state_t *st): - cdef uint64_t z - # TODO: Use literals -- PyCharm complains - cdef uint64_t c1 = 11400714819323198485 - cdef uint64_t c2 = 13787848793156543929 - cdef uint64_t c3 = 10723151780598845931 - st[0].state += c1 # 0x9E3779B97F4A7C15 - z = st[0].state - z = (z ^ (z >> 30)) * c2 # 0xBF58476D1CE4E5B9 - z = (z ^ (z >> 27)) * c3 # 0x94D049BB133111EB - return z ^ (z >> 31) +cdef uint64_t _splitmix64_anon(void* st) nogil: + return splitmix64_next(st) -cdef uint64_t _splitmix64_anon(void* st): - return _splitmix64( st) - -cdef class CorePRNG: +cdef class SplitMix64: """ Prototype Core PRNG using directly implemented version of SplitMix64. @@ -44,7 +30,7 @@ cdef class CorePRNG: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef state rng_state + cdef splitmix64_state rng_state cdef anon_func_state anon_func_state cdef public object _anon_func_state @@ -70,7 +56,7 @@ cdef class CorePRNG: ----- Testing only """ - return _splitmix64(&self.rng_state) + return splitmix64_next(&self.rng_state) def get_state(self): """Get PRNG state""" diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.c b/_randomgen/core_prng/src/splitmix64/splitmix64.c new file mode 100644 index 000000000000..fa230a99f05d --- /dev/null +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.c @@ -0,0 +1,25 @@ +/* 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 . + +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(splitmix64_state *state); diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/core_prng/src/splitmix64/splitmix64.h new file mode 100644 index 000000000000..8ecd72878135 --- /dev/null +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.h @@ -0,0 +1,12 @@ +#include + +typedef struct s_splitmix64_state { + uint64_t state; +} splitmix64_state; + +static inline uint64_t splitmix64_next(splitmix64_state *state) { + uint64_t z = (state->state += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); +} diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c b/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c new file mode 100644 index 000000000000..d0c1e158fe0c --- /dev/null +++ b/_randomgen/core_prng/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 . */ + +#include + +/* 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/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c new file mode 100644 index 000000000000..b346fd50eee7 --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -0,0 +1,53 @@ +/* Written in 2016 by David Blackman and 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 . */ + +/* This is the successor to xorshift128+. It is the fastest full-period + generator passing BigCrush without systematic failures, but due to the + relatively short period it is acceptable only for applications with a + mild amount of parallelism; otherwise, use a xorshift1024* generator. + + Beside passing BigCrush, this generator passes the PractRand test suite + up to (and included) 16TB, with the exception of binary rank tests, as + the lowest bit of this generator is an LFSR of degree 128. The next bit + can be described by an LFSR of degree 8256, but in the long run it will + fail linearity tests, too. The other bits needs a much higher degree to + be represented as LFSRs. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + Note that the generator uses a simulated rotate operation, which most C + compilers will turn into a single instruction. In Java, you can use + Long.rotateLeft(). In languages that do not make low-level rotation + instructions accessible xorshift128+ could be faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +#include "xoroshiro128.h" + +extern inline uint64_t xoroshiro128_next(xoroshiro128_state *state); + +void xoroshiro128_jump(xoroshiro128_state *state) { + static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; + + uint64_t s0 = 0; + uint64_t s1 = 0; + for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) { + s0 ^= state->s[0]; + s1 ^= state->s[1]; + } + xoroshiro128_next(state); + } + + state->s[0] = s0; + state->s[1] = s1; +} diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h new file mode 100644 index 000000000000..d6c0eefaf251 --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -0,0 +1,23 @@ +#include + +typedef struct s_xoroshiro128_state { + uint64_t s[2]; +} xoroshiro128_state; + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +static inline uint64_t xoroshiro128_next(xoroshiro128_state *state) { + const uint64_t s0 = state->s[0]; + uint64_t s1 = state->s[1]; + const uint64_t result = s0 + s1; + + s1 ^= s0; + state->s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b + state->s[1] = rotl(s1, 36); // c + + return result; +} + +void xoroshiro128_jump(xoroshiro128_state *state); diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c new file mode 100644 index 000000000000..d55a3b3776ca --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c @@ -0,0 +1,74 @@ +/* Written in 2016 by David Blackman and 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 . */ + +#include + +/* This is the successor to xorshift128+. It is the fastest full-period + generator passing BigCrush without systematic failures, but due to the + relatively short period it is acceptable only for applications with a + mild amount of parallelism; otherwise, use a xorshift1024* generator. + + Beside passing BigCrush, this generator passes the PractRand test suite + up to (and included) 16TB, with the exception of binary rank tests, as + the lowest bit of this generator is an LFSR of degree 128. The next bit + can be described by an LFSR of degree 8256, but in the long run it will + fail linearity tests, too. The other bits needs a much higher degree to + be represented as LFSRs. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + Note that the generator uses a simulated rotate operation, which most C + compilers will turn into a single instruction. In Java, you can use + Long.rotateLeft(). In languages that do not make low-level rotation + instructions accessible xorshift128+ could be faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +uint64_t s[2]; + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64_t next(void) { + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; + const uint64_t result = s0 + s1; + + s1 ^= s0; + s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b + s[1] = rotl(s1, 36); // c + + return result; +} + + +/* This is the jump function for the generator. It is equivalent + to 2^64 calls to next(); it can be used to generate 2^64 + non-overlapping subsequences for parallel computations. */ + +void jump(void) { + static const uint64_t JUMP[] = { 0xbeac0467eba5facb, 0xd86b048b86aa9922 }; + + uint64_t s0 = 0; + uint64_t s1 = 0; + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for(int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + } + next(); + } + + s[0] = s0; + s[1] = s1; +} diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx new file mode 100644 index 000000000000..adb94e605691 --- /dev/null +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -0,0 +1,75 @@ +import numpy as np +cimport numpy as np +from libc.stdint cimport uint64_t +from cpython.pycapsule cimport PyCapsule_New +from common cimport * + +np.import_array() + +cdef extern from "src/xoroshiro128/xoroshiro128.h": + + cdef struct s_xoroshiro128_state: + uint64_t s[2] + + ctypedef s_xoroshiro128_state xoroshiro128_state + + cdef uint64_t xoroshiro128_next(xoroshiro128_state* state) nogil + + cdef void xoroshiro128_jump(xoroshiro128_state* state) + + +ctypedef uint64_t (*random_uint64)(xoroshiro128_state* state) + +cdef uint64_t _xoroshiro128_anon(void* st) nogil: + return xoroshiro128_next(st) + +cdef class Xoroshiro128: + """ + Prototype Core PRNG using xoroshiro128 + + Notes + ----- + Exposes no user-facing API except `get_state` and `set_state`. Designed + for use in a `RandomGenerator` object. + """ + cdef xoroshiro128_state rng_state + cdef anon_func_state anon_func_state + cdef public object _anon_func_state + + def __init__(self): + self.rng_state.s[0] = 17013192669731687407 + self.rng_state.s[1] = 14803936204105204271 + + self.anon_func_state.state = &self.rng_state + self.anon_func_state.f = &_xoroshiro128_anon + cdef const char *anon_name = "Anon CorePRNG func_state" + self._anon_func_state = PyCapsule_New(&self.anon_func_state, + anon_name, NULL) + + def __random_integer(self): + """ + 64-bit Random Integers from the PRNG + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + return xoroshiro128_next(&self.rng_state) + + def get_state(self): + """Get PRNG state""" + return np.array(self.rng_state.s,dtype=np.uint64) + + def set_state(self, value): + """Set PRNG state""" + value = np.asarray(value, dtype=np.uint64) + self.rng_state.s[0] = value[0] + self.rng_state.s[1] = value[1] + + def jump(self): + xoroshiro128_jump(&self.rng_state) diff --git a/_randomgen/demo.py b/_randomgen/demo.py new file mode 100644 index 000000000000..78d2bb4606ff --- /dev/null +++ b/_randomgen/demo.py @@ -0,0 +1,7 @@ +from core_prng.generator import RandomGenerator +from core_prng.splitmix64 import SplitMix64 +from core_prng.xoroshiro128 import Xoroshiro128 + +print(RandomGenerator().random_integer()) +print(RandomGenerator(Xoroshiro128()).random_integer()) +print(RandomGenerator(SplitMix64()).random_integer()) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 9cb861f5048e..96f7c7b49e5e 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,15 +1,28 @@ +from os.path import join + import numpy as np from Cython.Build import cythonize from setuptools import setup, find_packages, Distribution from setuptools.extension import Extension -extensions = [Extension("core_prng.core_prng", - ["core_prng/core_prng.pyx"], - include_dirs=[np.get_include()]), +MOD_DIR = './core_prng' + +extensions = [Extension("core_prng.splitmix64", + ["core_prng/splitmix64.pyx", + join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'splitmix64')]), + Extension("core_prng.xoroshiro128", + ["core_prng/xoroshiro128.pyx", + join(MOD_DIR, 'src', 'xoroshiro128', + 'xoroshiro128.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'xoroshiro128')]), Extension("core_prng.generator", ["core_prng/generator.pyx"], include_dirs=[np.get_include()])] + class BinaryDistribution(Distribution): def is_pure(self): return False From d59494c72e9fd5e4aa4c1fceefe39d9e5e319eba Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 23 Feb 2018 09:40:02 +0000 Subject: [PATCH 003/138] ENH: Add entropy initialization to RNGS Port over random entropy from ng-randomstate --- _randomgen/core_prng/__init__.py | 3 + _randomgen/core_prng/entropy.pyx | 78 +++++++ _randomgen/core_prng/splitmix64.pyx | 25 +- _randomgen/core_prng/src/common/stdint.h | 259 +++++++++++++++++++++ _randomgen/core_prng/src/entropy/entropy.c | 174 ++++++++++++++ _randomgen/core_prng/src/entropy/entropy.h | 43 ++++ _randomgen/core_prng/xoroshiro128.pyx | 11 +- _randomgen/setup.py | 13 +- 8 files changed, 591 insertions(+), 15 deletions(-) create mode 100644 _randomgen/core_prng/entropy.pyx create mode 100644 _randomgen/core_prng/src/common/stdint.h create mode 100644 _randomgen/core_prng/src/entropy/entropy.c create mode 100644 _randomgen/core_prng/src/entropy/entropy.h diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index e69de29bb2d1..8bcc8c6f1365 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -0,0 +1,3 @@ +from .generator import RandomGenerator +from .xoroshiro128 import Xoroshiro128 +from .splitmix64 import SplitMix64 \ No newline at end of file diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/core_prng/entropy.pyx new file mode 100644 index 000000000000..0d980fc2ca6d --- /dev/null +++ b/_randomgen/core_prng/entropy.pyx @@ -0,0 +1,78 @@ +cimport numpy as np +import numpy as np + +from libc.stdint cimport uint32_t + +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 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 ndarray + Entropy bits in 32-bit unsigned integers + + 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 + RandomState, and so ``seed``, ``get_state`` and ``set_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(&random, 4) + else: + success = entropy_fallback_getbytes(&random, 4) + else: + n = compute_numel(size) + randoms = np.zeros(n, dtype=np.uint32) + if source == 'system': + success = entropy_getbytes((&randoms[0]), 4 * n) + else: + success = entropy_fallback_getbytes((&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) \ No newline at end of file diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 9b26d233b637..e652465bec6d 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -1,25 +1,24 @@ import numpy as np cimport numpy as np -from libc.stdint cimport uint64_t from cpython.pycapsule cimport PyCapsule_New from common cimport * +from core_prng.entropy import random_entropy np.import_array() cdef extern from "src/splitmix64/splitmix64.h": - cdef struct s_splitmix64_state: uint64_t state ctypedef s_splitmix64_state splitmix64_state - cdef uint64_t splitmix64_next(splitmix64_state* state) nogil + cdef uint64_t splitmix64_next(splitmix64_state*state) nogil -ctypedef uint64_t (*random_uint64)(splitmix64_state* state) +ctypedef uint64_t (*random_uint64)(splitmix64_state*state) -cdef uint64_t _splitmix64_anon(void* st) nogil: - return splitmix64_next(st) +cdef uint64_t _splitmix64_anon(void*st) nogil: + return splitmix64_next( st) cdef class SplitMix64: """ @@ -35,12 +34,16 @@ cdef class SplitMix64: cdef public object _anon_func_state def __init__(self): - self.rng_state.state = 17013192669731687406 - - self.anon_func_state.state = &self.rng_state - self.anon_func_state.f = &_splitmix64_anon + try: + state = random_entropy(2) + except RuntimeError: + state = random_entropy(2, 'fallback') + self.rng_state.state = int(state.view(np.uint64)[0]) + + self.anon_func_state.state = &self.rng_state + self.anon_func_state.f = &_splitmix64_anon cdef const char *anon_name = "Anon CorePRNG func_state" - self._anon_func_state = PyCapsule_New(&self.anon_func_state, + self._anon_func_state = PyCapsule_New( &self.anon_func_state, anon_name, NULL) def __random_integer(self): diff --git a/_randomgen/core_prng/src/common/stdint.h b/_randomgen/core_prng/src/common/stdint.h new file mode 100644 index 000000000000..8941d67c8295 --- /dev/null +++ b/_randomgen/core_prng/src/common/stdint.h @@ -0,0 +1,259 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// 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 product 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 AUTHOR ``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 AUTHOR 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#if _MSC_VER >= 1600 // [ +#include +#else // ] _MSC_VER >= 1600 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] \ No newline at end of file diff --git a/_randomgen/core_prng/src/entropy/entropy.c b/_randomgen/core_prng/src/entropy/entropy.c new file mode 100644 index 000000000000..a5d48bd1418e --- /dev/null +++ b/_randomgen/core_prng/src/entropy/entropy.c @@ -0,0 +1,174 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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 provides a mechanism for getting external randomness for + * seeding purposes. Usually, it's just a wrapper around reading + * /dev/random. + * + * Alas, because not every system provides /dev/random, we need a fallback. + * We also need to try to test whether or not to use the fallback. + */ + +#include +#include +#include +#include + +#include "entropy.h" +#ifdef _WIN32 +/* Windows */ +#include +#include +#include + +#include +#else +/* Unix */ +#include +#include +#include +#endif + +#ifndef IS_UNIX +#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__))) +#define IS_UNIX 1 +#else +#define IS_UNIX 0 +#endif +#endif + +// If HAVE_DEV_RANDOM is set, we use that value, otherwise we guess +#ifndef HAVE_DEV_RANDOM +#define HAVE_DEV_RANDOM IS_UNIX +#endif + +#if HAVE_DEV_RANDOM +#include +#include +#endif + +#if HAVE_DEV_RANDOM +/* entropy_getbytes(dest, size): + * Use /dev/random to get some external entropy for seeding purposes. + * + * Note: + * If reading /dev/random fails (which ought to never happen), it returns + * false, otherwise it returns true. If it fails, you could instead call + * fallback_entropy_getbytes which always succeeds. + */ + +bool entropy_getbytes(void *dest, size_t size) { + 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; +} +#endif + +#ifdef _WIN32 +bool entropy_getbytes(void *dest, size_t size) { + 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(&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)); + // uint32_t hash[hashes]; + 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/_randomgen/core_prng/src/entropy/entropy.h b/_randomgen/core_prng/src/entropy/entropy.h new file mode 100644 index 000000000000..0c33edbe4b5e --- /dev/null +++ b/_randomgen/core_prng/src/entropy/entropy.h @@ -0,0 +1,43 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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 + */ +#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/stdint.h" +typedef int bool; +#define false 0 +#define true 1 +#else +#include +#include +#endif +#else +#include +#include +#endif + +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); diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index adb94e605691..4cd9b2449aab 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -3,7 +3,7 @@ cimport numpy as np from libc.stdint cimport uint64_t from cpython.pycapsule cimport PyCapsule_New from common cimport * - +from core_prng.entropy import random_entropy np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": @@ -37,8 +37,13 @@ cdef class Xoroshiro128: cdef public object _anon_func_state def __init__(self): - self.rng_state.s[0] = 17013192669731687407 - self.rng_state.s[1] = 14803936204105204271 + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + self.rng_state.s[0] = int(state[0]) + self.rng_state.s[1] = int(state[1]) self.anon_func_state.state = &self.rng_state self.anon_func_state.f = &_xoroshiro128_anon diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 96f7c7b49e5e..bd66904cd169 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,3 +1,4 @@ +import os from os.path import join import numpy as np @@ -7,7 +8,17 @@ MOD_DIR = './core_prng' -extensions = [Extension("core_prng.splitmix64", +EXTRA_LINK_ARGS = [] +if os.name == 'nt': + EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] + +extensions = [Extension('core_prng.entropy', + sources=[join(MOD_DIR, 'entropy.pyx'), + join(MOD_DIR, 'src', 'entropy', 'entropy.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'entropy')], + extra_link_args=EXTRA_LINK_ARGS), + Extension("core_prng.splitmix64", ["core_prng/splitmix64.pyx", join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], include_dirs=[np.get_include(), From 8942968bd1c9b2545b208b7bd362dc8c4c010da8 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 23 Feb 2018 18:16:40 +0000 Subject: [PATCH 004/138] ENH: Add seeding to generators Allow generators to be seeded on creation --- _randomgen/core_prng/entropy.pxd | 5 ++ _randomgen/core_prng/entropy.pyx | 68 ++++++++++++++++++- _randomgen/core_prng/splitmix64.pyx | 38 +++++++---- .../core_prng/src/splitmix64/splitmix64.c | 2 +- .../core_prng/src/splitmix64/splitmix64.h | 8 +-- _randomgen/core_prng/xoroshiro128.pyx | 22 ++++-- _randomgen/demo.py | 3 + 7 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 _randomgen/core_prng/entropy.pxd diff --git a/_randomgen/core_prng/entropy.pxd b/_randomgen/core_prng/entropy.pxd new file mode 100644 index 000000000000..c0a1a0e871f7 --- /dev/null +++ b/_randomgen/core_prng/entropy.pxd @@ -0,0 +1,5 @@ + +from libc.stdint cimport uint64_t +cimport numpy as np + +cdef np.ndarray seed_by_array(object seed, Py_ssize_t n) \ No newline at end of file diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/core_prng/entropy.pyx index 0d980fc2ca6d..f1155c605273 100644 --- a/_randomgen/core_prng/entropy.pyx +++ b/_randomgen/core_prng/entropy.pyx @@ -1,7 +1,14 @@ +import operator + cimport numpy as np import numpy as np -from libc.stdint cimport uint32_t +from libc.stdint cimport uint32_t, uint64_t + +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) @@ -16,6 +23,65 @@ cdef Py_ssize_t compute_numel(size): n = size return n +cdef np.ndarray seed_by_array(object seed, Py_ssize_t n): + """ + Transforms a seed array into an initiial state + + Parameters + ---------- + seed: array, 1d, uint64 + Array to use. If seed is a scalar, promote to array. + n : int + Number of 64-bit unsiened 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 + + try: + if hasattr(seed, 'squeeze'): + seed = seed.squeeze() + idx = operator.index(seed) + if idx > int(2**64 - 1) or idx < 0: + raise ValueError("Seed must be between 0 and 2**64 - 1") + seed = [seed] + seed_array = np.array(seed, dtype=np.uint64) + except TypeError: + exc_msg = "Seed values must be integers between 0 and 2**64 - 1" + obj = np.asarray(seed).astype(np.object).ravel() + if obj.ndim != 1: + raise ValueError('Array-valued seeds must be 1-dimensional') + if ((obj > int(2**64 - 1)) | (obj < 0)).any(): + raise ValueError(exc_msg) + try: + obj_int = obj.astype(np.uint64, casting='unsafe') + except ValueError: + raise ValueError(exc_msg) + if not (obj == obj_int).all(): + raise ValueError(exc_msg) + seed_array = obj_int + + seed_size = seed_array.shape[0] + iter_bound = n if n > seed_size else seed_size + + initial_state = 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') diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index e652465bec6d..1a4f3827cae4 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -2,43 +2,51 @@ import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_New from common cimport * + from core_prng.entropy import random_entropy +from core_prng cimport entropy np.import_array() cdef extern from "src/splitmix64/splitmix64.h": - cdef struct s_splitmix64_state: - uint64_t state - - ctypedef s_splitmix64_state splitmix64_state - cdef uint64_t splitmix64_next(splitmix64_state*state) nogil + cdef uint64_t splitmix64_next(uint64_t *state) nogil -ctypedef uint64_t (*random_uint64)(splitmix64_state*state) +ctypedef uint64_t (*random_uint64)(uint64_t *state) -cdef uint64_t _splitmix64_anon(void*st) nogil: - return splitmix64_next( st) +cdef uint64_t _splitmix64_anon(void *st) nogil: + return splitmix64_next( st) cdef class SplitMix64: """ Prototype Core PRNG using directly implemented version of SplitMix64. + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + Notes ----- Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef splitmix64_state rng_state + cdef uint64_t rng_state cdef anon_func_state anon_func_state cdef public object _anon_func_state - def __init__(self): - try: - state = random_entropy(2) - except RuntimeError: - state = random_entropy(2, 'fallback') - self.rng_state.state = int(state.view(np.uint64)[0]) + def __init__(self, seed=None): + if seed is None: + try: + state = random_entropy(2) + except RuntimeError: + state = random_entropy(2, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 1) + + self.rng_state = int(state[0]) self.anon_func_state.state = &self.rng_state self.anon_func_state.f = &_splitmix64_anon diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.c b/_randomgen/core_prng/src/splitmix64/splitmix64.c index fa230a99f05d..1e75f4b9b100 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.c +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.c @@ -22,4 +22,4 @@ license. #include "splitmix64.h" -extern inline uint64_t splitmix64_next(splitmix64_state *state); +extern inline uint64_t splitmix64_next(uint64_t *state); diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/core_prng/src/splitmix64/splitmix64.h index 8ecd72878135..d5d7549d9fad 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.h +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.h @@ -1,11 +1,7 @@ #include -typedef struct s_splitmix64_state { - uint64_t state; -} splitmix64_state; - -static inline uint64_t splitmix64_next(splitmix64_state *state) { - uint64_t z = (state->state += 0x9e3779b97f4a7c15); +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); diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 4cd9b2449aab..1ae7926acb00 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -4,6 +4,7 @@ from libc.stdint cimport uint64_t from cpython.pycapsule cimport PyCapsule_New from common cimport * from core_prng.entropy import random_entropy +from core_prng cimport entropy np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": @@ -27,6 +28,11 @@ cdef class Xoroshiro128: """ Prototype Core PRNG using xoroshiro128 + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + Notes ----- Exposes no user-facing API except `get_state` and `set_state`. Designed @@ -36,12 +42,16 @@ cdef class Xoroshiro128: cdef anon_func_state anon_func_state cdef public object _anon_func_state - def __init__(self): - try: - state = random_entropy(4) - except RuntimeError: - state = random_entropy(4, 'fallback') - state = state.view(np.uint64) + def __init__(self, seed=None): + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + self.rng_state.s[0] = int(state[0]) self.rng_state.s[1] = int(state[1]) diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 78d2bb4606ff..f11ad2b2a91c 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -5,3 +5,6 @@ print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) +print(RandomGenerator(SplitMix64()).random_integer()) +print(RandomGenerator(SplitMix64(1)).random_integer()) +print(RandomGenerator(SplitMix64([1.0,2.0])).random_integer()) From aa9060ce67f90b806b90fae1e445b62c73c0a11d Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 24 Feb 2018 19:18:38 +0000 Subject: [PATCH 005/138] CLN: Simplify xoroshiro state Simplify xoroshiro state --- _randomgen/core_prng/__init__.py | 4 +- .../core_prng/src/xoroshiro128/xoroshiro128.c | 14 +++---- .../core_prng/src/xoroshiro128/xoroshiro128.h | 16 +++----- _randomgen/core_prng/xoroshiro128.pyx | 40 +++++++++---------- _randomgen/demo.py | 4 +- 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 8bcc8c6f1365..d097a9ef158b 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,3 +1,5 @@ from .generator import RandomGenerator from .xoroshiro128 import Xoroshiro128 -from .splitmix64 import SplitMix64 \ No newline at end of file +from .splitmix64 import SplitMix64 + +__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128'] diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c index b346fd50eee7..b9fb5d084309 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -32,9 +32,9 @@ See . */ #include "xoroshiro128.h" -extern inline uint64_t xoroshiro128_next(xoroshiro128_state *state); +extern inline uint64_t xoroshiro128_next(uint64_t *s); -void xoroshiro128_jump(xoroshiro128_state *state) { +void xoroshiro128_jump(uint64_t *s) { static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; uint64_t s0 = 0; @@ -42,12 +42,12 @@ void xoroshiro128_jump(xoroshiro128_state *state) { for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) for (int b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= state->s[0]; - s1 ^= state->s[1]; + s0 ^= s[0]; + s1 ^= s[1]; } - xoroshiro128_next(state); + xoroshiro128_next(s); } - state->s[0] = s0; - state->s[1] = s1; + s[0] = s0; + s[1] = s1; } diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h index d6c0eefaf251..2ececd00e493 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -1,23 +1,19 @@ #include -typedef struct s_xoroshiro128_state { - uint64_t s[2]; -} xoroshiro128_state; - static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -static inline uint64_t xoroshiro128_next(xoroshiro128_state *state) { - const uint64_t s0 = state->s[0]; - uint64_t s1 = state->s[1]; +static inline uint64_t xoroshiro128_next(uint64_t *s) { + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; const uint64_t result = s0 + s1; s1 ^= s0; - state->s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b - state->s[1] = rotl(s1, 36); // c + s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b + s[1] = rotl(s1, 36); // c return result; } -void xoroshiro128_jump(xoroshiro128_state *state); +void xoroshiro128_jump(uint64_t *s); diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 1ae7926acb00..8baf531c6d9e 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -1,6 +1,7 @@ import numpy as np cimport numpy as np from libc.stdint cimport uint64_t +from libc.stdlib cimport malloc from cpython.pycapsule cimport PyCapsule_New from common cimport * from core_prng.entropy import random_entropy @@ -9,20 +10,13 @@ np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": - cdef struct s_xoroshiro128_state: - uint64_t s[2] + cdef uint64_t xoroshiro128_next(uint64_t *s) nogil + cdef void xoroshiro128_jump(uint64_t *s) - ctypedef s_xoroshiro128_state xoroshiro128_state - - cdef uint64_t xoroshiro128_next(xoroshiro128_state* state) nogil - - cdef void xoroshiro128_jump(xoroshiro128_state* state) - - -ctypedef uint64_t (*random_uint64)(xoroshiro128_state* state) +ctypedef uint64_t (*random_uint64)(uint64_t *s) cdef uint64_t _xoroshiro128_anon(void* st) nogil: - return xoroshiro128_next(st) + return xoroshiro128_next(st) cdef class Xoroshiro128: """ @@ -38,10 +32,11 @@ cdef class Xoroshiro128: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef xoroshiro128_state rng_state + cdef uint64_t *rng_state cdef anon_func_state anon_func_state cdef public object _anon_func_state + def __init__(self, seed=None): if seed is None: try: @@ -51,11 +46,11 @@ cdef class Xoroshiro128: state = state.view(np.uint64) else: state = entropy.seed_by_array(seed, 2) + self.rng_state = malloc(2 * sizeof(uint64_t)) + self.rng_state[0] = int(state[0]) + self.rng_state[1] = int(state[1]) - self.rng_state.s[0] = int(state[0]) - self.rng_state.s[1] = int(state[1]) - - self.anon_func_state.state = &self.rng_state + self.anon_func_state.state = self.rng_state self.anon_func_state.f = &_xoroshiro128_anon cdef const char *anon_name = "Anon CorePRNG func_state" self._anon_func_state = PyCapsule_New(&self.anon_func_state, @@ -74,17 +69,20 @@ cdef class Xoroshiro128: ----- Testing only """ - return xoroshiro128_next(&self.rng_state) + return xoroshiro128_next(self.rng_state) def get_state(self): """Get PRNG state""" - return np.array(self.rng_state.s,dtype=np.uint64) + state = np.empty(2, dtype=np.uint64) + state[0] = self.rng_state[0] + state[1] = self.rng_state[1] + return state def set_state(self, value): """Set PRNG state""" value = np.asarray(value, dtype=np.uint64) - self.rng_state.s[0] = value[0] - self.rng_state.s[1] = value[1] + self.rng_state[0] = value[0] + self.rng_state[1] = value[1] def jump(self): - xoroshiro128_jump(&self.rng_state) + xoroshiro128_jump(self.rng_state) diff --git a/_randomgen/demo.py b/_randomgen/demo.py index f11ad2b2a91c..d034d83c5423 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -4,7 +4,9 @@ print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) +x = Xoroshiro128() +print(x.get_state()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64(1)).random_integer()) -print(RandomGenerator(SplitMix64([1.0,2.0])).random_integer()) +print(RandomGenerator(SplitMix64([1.0, 2.0])).random_integer()) From b353f877129f3479b33f112ed6584f871b27f90c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 26 Feb 2018 15:19:16 +0000 Subject: [PATCH 006/138] REF: Add additional state Add state to allow 32 bit generation --- _randomgen/core_prng/common.pxd | 14 ++- _randomgen/core_prng/common.pyx | 42 +++++++++ _randomgen/core_prng/generator.pyx | 80 +++++++++++++++- _randomgen/core_prng/splitmix64.pyx | 63 +++++++++---- .../core_prng/src/splitmix64/splitmix64.c | 6 +- .../core_prng/src/splitmix64/splitmix64.h | 21 +++++ .../core_prng/src/xoroshiro128/xoroshiro128.c | 16 ++-- .../core_prng/src/xoroshiro128/xoroshiro128.h | 23 ++++- _randomgen/core_prng/xoroshiro128.pyx | 91 +++++++++++++------ _randomgen/demo.py | 17 +++- _randomgen/setup.py | 6 +- 11 files changed, 319 insertions(+), 60 deletions(-) create mode 100644 _randomgen/core_prng/common.pyx diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index e9949220f9c6..9b867167967e 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,9 +1,19 @@ + from libc.stdint cimport uint64_t -ctypedef uint64_t (*random_uint64_anon)(void* st) +ctypedef uint64_t (*random_uint64_anon)(void* st) nogil + +ctypedef double (*random_double_anon)(void* st) nogil cdef struct anon_func_state: void *state - void *f + void *next_uint64 + void *next_uint32 + void *next_double ctypedef anon_func_state anon_func_state_t + +cdef inline double uint64_to_double(uint64_t rnd) nogil: + return (rnd >> 11) * (1.0 / 9007199254740992.0) + +cdef object double_fill(random_double_anon *random_double, void *state, object size, object lock, object out) diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx new file mode 100644 index 000000000000..3fb5dd12971e --- /dev/null +++ b/_randomgen/core_prng/common.pyx @@ -0,0 +1,42 @@ +import numpy as np +cimport numpy as np +from common cimport * + +np.import_array() + +cdef check_output(object out, object dtype, object size): + if out is None: + return + cdef np.ndarray out_array = 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: + # TODO: enable this !!! if tuple(size) != out_array.shape: + raise ValueError('size and out cannot be simultaneously used') + + +cdef object double_fill(random_double_anon *random_double, void *state, object size, object lock, object out): + 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: + return random_double[0](state) + + if out is not None: + check_output(out, np.double, size) + out_array = out + else: + out_array = np.empty(size, np.double) + + n = np.PyArray_SIZE(out_array) + out_array_data = np.PyArray_DATA(out_array) + with lock, nogil: + for i in range(n): + out_array_data[i] = random_double[0](state) + return out_array diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 2648f9c0593a..7f31ea9be389 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -2,6 +2,10 @@ import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock from core_prng.splitmix64 import SplitMix64 @@ -25,7 +29,9 @@ cdef class RandomGenerator: cdef public object __core_prng cdef anon_func_state anon_rng_func_state cdef random_uint64_anon next_uint64 + cdef random_double_anon next_double cdef void *rng_state + cdef object lock def __init__(self, prng=None): if prng is None: @@ -37,11 +43,81 @@ cdef class RandomGenerator: if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") self.anon_rng_func_state = (PyCapsule_GetPointer(capsule, anon_name))[0] - self.next_uint64 = self.anon_rng_func_state.f + self.next_uint64 = self.anon_rng_func_state.next_uint64 + self.next_double = self.anon_rng_func_state.next_double self.rng_state = self.anon_rng_func_state.state + self.lock = Lock() + + @property + def state(self): + """Get ot set the underlying PRNG's state""" + return self.__core_prng.state + + @state.setter + def state(self, value): + self.__core_prng.state = value def random_integer(self): return self.next_uint64(self.rng_state) def random_double(self): - return (self.next_uint64(self.rng_state) >> 11) * (1.0 / 9007199254740992.0) + return self.next_double(self.rng_state) + + def random_sample(self, size=None, dtype=np.float64, out=None): + """ + random_sample(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_sample` by `(b-a)` and add `a`:: + + (b - a) * random_sample() + 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 + -------- + >>> np.random.random_sample() + 0.47108547995356098 + >>> type(np.random.random_sample()) + + >>> np.random.random_sample((5,)) + array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) + + Three-by-two array of random numbers from [-5, 0): + + >>> 5 * np.random.random_sample((3, 2)) - 5 + array([[-3.99149989, -0.52338984], + [-2.99091858, -0.79479508], + [-1.23204345, -1.75224494]]) + """ + cdef double temp + key = np.dtype(dtype).name + if key == 'float64': + return double_fill(&self.next_double, self.rng_state, size, self.lock, out) + elif key == 'float32': + raise NotImplementedError + # return float_fill(&self.rng_state, &random_uniform_fill_float, size, self.lock, out) + else: + raise TypeError('Unsupported dtype "%s" for random_sample' % key) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 1a4f3827cae4..5bc8dd8d92f3 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -1,22 +1,34 @@ +from libc.stdint cimport uint32_t, uint64_t +from cpython.pycapsule cimport PyCapsule_New + import numpy as np cimport numpy as np -from cpython.pycapsule cimport PyCapsule_New -from common cimport * +from common cimport * from core_prng.entropy import random_entropy from core_prng cimport entropy np.import_array() cdef extern from "src/splitmix64/splitmix64.h": + cdef struct s_splitmix64_state: + uint64_t state + int has_uint32 + uint32_t uinteger + + ctypedef s_splitmix64_state splitmix64_state - cdef uint64_t splitmix64_next(uint64_t *state) nogil + cdef uint64_t splitmix64_next64(splitmix64_state *state) nogil + cdef uint64_t splitmix64_next32(splitmix64_state *state) nogil +cdef uint64_t splitmix64_uint64(void *st) nogil: + return splitmix64_next64( st) -ctypedef uint64_t (*random_uint64)(uint64_t *state) +cdef uint64_t splitmix64_uint32(void *st) nogil: + return splitmix64_next32( st) -cdef uint64_t _splitmix64_anon(void *st) nogil: - return splitmix64_next( st) +cdef double splitmix64_double(void *st) nogil: + return uint64_to_double(splitmix64_uint64( st)) cdef class SplitMix64: """ @@ -32,7 +44,7 @@ cdef class SplitMix64: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef uint64_t rng_state + cdef splitmix64_state rng_state cdef anon_func_state anon_func_state cdef public object _anon_func_state @@ -46,10 +58,13 @@ cdef class SplitMix64: else: state = entropy.seed_by_array(seed, 1) - self.rng_state = int(state[0]) + self.rng_state.state = int(state[0]) + self.rng_state.has_uint32 = 0 self.anon_func_state.state = &self.rng_state - self.anon_func_state.f = &_splitmix64_anon + self.anon_func_state.next_uint64 = &splitmix64_uint64 + self.anon_func_state.next_uint32 = &splitmix64_uint32 + self.anon_func_state.next_double = &splitmix64_double cdef const char *anon_name = "Anon CorePRNG func_state" self._anon_func_state = PyCapsule_New( &self.anon_func_state, anon_name, NULL) @@ -67,12 +82,24 @@ cdef class SplitMix64: ----- Testing only """ - return splitmix64_next(&self.rng_state) - - def get_state(self): - """Get PRNG state""" - return self.rng_state.state - - def set_state(self, uint64_t value): - """Set PRNG state""" - self.rng_state.state = value + return splitmix64_next64(&self.rng_state) + + @property + def state(self): + """Get or set the PRNG state""" + return {'prng': self.__class__.__name__, + 's': self.rng_state.state, + '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') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + self.rng_state.state = value['s'] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.c b/_randomgen/core_prng/src/splitmix64/splitmix64.c index 1e75f4b9b100..77f0693bac65 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.c +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.c @@ -22,4 +22,8 @@ license. #include "splitmix64.h" -extern inline uint64_t splitmix64_next(uint64_t *state); +static 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/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/core_prng/src/splitmix64/splitmix64.h index d5d7549d9fad..6fbaa1657abf 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.h +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.h @@ -1,8 +1,29 @@ #include +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) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = splitmix64_next64(state); + state->uinteger = next & 0xffffffff; + state->has_uint32 = 1; + return (uint32_t)(next >> 32); +} diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c index b9fb5d084309..244ca28b20d9 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -34,7 +34,11 @@ See . */ extern inline uint64_t xoroshiro128_next(uint64_t *s); -void xoroshiro128_jump(uint64_t *s) { +static inline uint64_t xoroshiro128_next64(xoroshiro128_state *state); + +static inline uint64_t xoroshiro128_next32(xoroshiro128_state *state); + +void xoroshiro128_jump(xoroshiro128_state *state) { static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; uint64_t s0 = 0; @@ -42,12 +46,12 @@ void xoroshiro128_jump(uint64_t *s) { for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) for (int b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= s[0]; - s1 ^= s[1]; + s0 ^= state->s[0]; + s1 ^= state->s[1]; } - xoroshiro128_next(s); + xoroshiro128_next(&state->s); } - s[0] = s0; - s[1] = s1; + state->s[0] = s0; + state->s[1] = s1; } diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h index 2ececd00e493..f575ef7aada3 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -1,5 +1,11 @@ #include +typedef struct s_xoroshiro128_state { + uint64_t s[2]; + int has_uint32; + uint32_t uinteger; +} xoroshiro128_state; + static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } @@ -16,4 +22,19 @@ static inline uint64_t xoroshiro128_next(uint64_t *s) { return result; } -void xoroshiro128_jump(uint64_t *s); +static inline uint64_t xoroshiro128_next64(xoroshiro128_state *state) { + return xoroshiro128_next(&state->s[0]); +} + +static inline uint64_t xoroshiro128_next32(xoroshiro128_state *state) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = xoroshiro128_next(&state->s[0]); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next & 0xffffffff); + return (uint32_t)(next >> 32); +} + +void xoroshiro128_jump(xoroshiro128_state *state); diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 8baf531c6d9e..515bb6a1a753 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -1,22 +1,37 @@ import numpy as np cimport numpy as np -from libc.stdint cimport uint64_t +from libc.stdint cimport uint32_t, uint64_t from libc.stdlib cimport malloc from cpython.pycapsule cimport PyCapsule_New from common cimport * from core_prng.entropy import random_entropy from core_prng cimport entropy + np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": + cdef struct s_xoroshiro128_state: + uint64_t s[2] + int has_uint32 + uint32_t uinteger + + ctypedef s_xoroshiro128_state xoroshiro128_state + cdef uint64_t xoroshiro128_next(uint64_t *s) nogil - cdef void xoroshiro128_jump(uint64_t *s) -ctypedef uint64_t (*random_uint64)(uint64_t *s) + cdef uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil + cdef uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil + cdef void xoroshiro128_jump(xoroshiro128_state *state) -cdef uint64_t _xoroshiro128_anon(void* st) nogil: - return xoroshiro128_next(st) +cdef uint64_t xoroshiro128_uint64(void* st) nogil: + return xoroshiro128_next64(st) + +cdef uint64_t xoroshiro128_uint32(void *st) nogil: + return xoroshiro128_next32( st) + +cdef double xoroshiro128_double(void* st) nogil: + return uint64_to_double(xoroshiro128_next64(st)) cdef class Xoroshiro128: """ @@ -32,7 +47,7 @@ cdef class Xoroshiro128: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef uint64_t *rng_state + cdef xoroshiro128_state rng_state cdef anon_func_state anon_func_state cdef public object _anon_func_state @@ -46,20 +61,26 @@ cdef class Xoroshiro128: state = state.view(np.uint64) else: state = entropy.seed_by_array(seed, 2) - self.rng_state = malloc(2 * sizeof(uint64_t)) - self.rng_state[0] = int(state[0]) - self.rng_state[1] = int(state[1]) + self.rng_state.s[0] = int(state[0]) + self.rng_state.s[1] = int(state[1]) - self.anon_func_state.state = self.rng_state - self.anon_func_state.f = &_xoroshiro128_anon + self.anon_func_state.state = &self.rng_state + self.anon_func_state.next_uint64 = &xoroshiro128_uint64 + self.anon_func_state.next_uint32 = &xoroshiro128_uint32 + self.anon_func_state.next_double = &xoroshiro128_double cdef const char *anon_name = "Anon CorePRNG func_state" self._anon_func_state = PyCapsule_New(&self.anon_func_state, anon_name, NULL) - def __random_integer(self): + def __random_integer(self, bits=64): """ 64-bit Random Integers from the PRNG + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + Returns ------- rv : int @@ -69,20 +90,36 @@ cdef class Xoroshiro128: ----- Testing only """ - return xoroshiro128_next(self.rng_state) - - def get_state(self): - """Get PRNG state""" - state = np.empty(2, dtype=np.uint64) - state[0] = self.rng_state[0] - state[1] = self.rng_state[1] - return state - - def set_state(self, value): - """Set PRNG state""" - value = np.asarray(value, dtype=np.uint64) - self.rng_state[0] = value[0] - self.rng_state[1] = value[1] + if bits == 64: + return xoroshiro128_next64(&self.rng_state) + elif bits == 32: + return xoroshiro128_next32(&self.rng_state) + else: + raise ValueError('bits must be 32 or 64') def jump(self): - xoroshiro128_jump(self.rng_state) + xoroshiro128_jump(&self.rng_state) + + @property + def state(self): + """Get or set the PRNG state""" + state = np.empty(2, dtype=np.uint64) + state[0] = self.rng_state.s[0] + state[1] = self.rng_state.s[1] + return {'prng': self.__class__.__name__, + 's': state, + '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') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + self.rng_state.s[0] = value['s'][0] + self.rng_state.s[1] = value['s'][1] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/demo.py b/_randomgen/demo.py index d034d83c5423..148c36689230 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -4,9 +4,22 @@ print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) -x = Xoroshiro128() -print(x.get_state()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64(1)).random_integer()) print(RandomGenerator(SplitMix64([1.0, 2.0])).random_integer()) + + +print('\n'*3) +print('Check random_sample') +rg = RandomGenerator() +print(rg.random_sample((3))) +print(rg.random_sample((3,1))) + +print('\n'*3) +print('Check set/get state') +state = rg.state +print(rg.state) +print(rg.random_integer()) +rg.state = state +print(rg.random_integer()) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index bd66904cd169..3d0f1c6edd37 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -31,7 +31,11 @@ join(MOD_DIR, 'src', 'xoroshiro128')]), Extension("core_prng.generator", ["core_prng/generator.pyx"], - include_dirs=[np.get_include()])] + include_dirs=[np.get_include()]), + Extension("core_prng.common", + ["core_prng/common.pyx"], + include_dirs=[np.get_include()]), + ] class BinaryDistribution(Distribution): From 15cab3c2f281ed0812e971c05f5af89b2883a7d5 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Feb 2018 15:29:20 +0000 Subject: [PATCH 007/138] REF: Reactor filler to take a function --- _randomgen/core_prng/common.pxd | 4 +++- _randomgen/core_prng/common.pyx | 7 ++++--- _randomgen/core_prng/generator.pyx | 11 ++++++++++- _randomgen/core_prng/splitmix64.pyx | 2 +- _randomgen/core_prng/xoroshiro128.pyx | 2 +- _randomgen/demo.py | 1 + _randomgen/setup.py | 3 +++ 7 files changed, 23 insertions(+), 7 deletions(-) diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 9b867167967e..b3e11a9aa55a 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -5,6 +5,8 @@ ctypedef uint64_t (*random_uint64_anon)(void* st) nogil ctypedef double (*random_double_anon)(void* st) nogil +ctypedef double (*random_0)(void *st) nogil + cdef struct anon_func_state: void *state void *next_uint64 @@ -16,4 +18,4 @@ ctypedef anon_func_state anon_func_state_t cdef inline double uint64_to_double(uint64_t rnd) nogil: return (rnd >> 11) * (1.0 / 9007199254740992.0) -cdef object double_fill(random_double_anon *random_double, void *state, object size, object lock, object out) +cdef object double_fill(void *func, void *state, object size, object lock, object out) diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 3fb5dd12971e..d7b5da8ddc6f 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -19,14 +19,15 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size and out cannot be simultaneously used') -cdef object double_fill(random_double_anon *random_double, void *state, object size, object lock, object out): +cdef object double_fill(void *func, void *state, object size, object lock, object out): + cdef random_0 random_func = (func) 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: - return random_double[0](state) + return random_func(state) if out is not None: check_output(out, np.double, size) @@ -38,5 +39,5 @@ cdef object double_fill(random_double_anon *random_double, void *state, object s out_array_data = np.PyArray_DATA(out_array) with lock, nogil: for i in range(n): - out_array_data[i] = random_double[0](state) + out_array_data[i] = random_func(state) return out_array diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 7f31ea9be389..636d63a63a02 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -2,6 +2,7 @@ import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * +cimport common try: from threading import Lock except ImportError: @@ -11,6 +12,14 @@ from core_prng.splitmix64 import SplitMix64 np.import_array() + +cdef double random_double(void *void_state): + cdef anon_func_state_t *anon_state = void_state + cdef random_double_anon random_double_f = anon_state.next_double + cdef void *state = anon_state.state + return random_double_f(state) + + cdef class RandomGenerator: """ Prototype Random Generator that consumes randoms from a CorePRNG class @@ -115,7 +124,7 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&self.next_double, self.rng_state, size, self.lock, out) + return double_fill(&random_double, &self.anon_rng_func_state, size, self.lock, out) elif key == 'float32': raise NotImplementedError # return float_fill(&self.rng_state, &random_uniform_fill_float, size, self.lock, out) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 5bc8dd8d92f3..0aeda157a139 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -6,7 +6,7 @@ cimport numpy as np from common cimport * from core_prng.entropy import random_entropy -from core_prng cimport entropy +cimport entropy np.import_array() diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 515bb6a1a753..9f6da5355041 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -5,7 +5,7 @@ from libc.stdlib cimport malloc from cpython.pycapsule cimport PyCapsule_New from common cimport * from core_prng.entropy import random_entropy -from core_prng cimport entropy +cimport entropy np.import_array() diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 148c36689230..4eb414bef6a7 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -13,6 +13,7 @@ print('\n'*3) print('Check random_sample') rg = RandomGenerator() +print(rg.random_sample()) print(rg.random_sample((3))) print(rg.random_sample((3,1))) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 3d0f1c6edd37..a95c0e75de59 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -3,9 +3,12 @@ import numpy as np from Cython.Build import cythonize +import Cython.Compiler.Options from setuptools import setup, find_packages, Distribution from setuptools.extension import Extension +Cython.Compiler.Options.annotate = True + MOD_DIR = './core_prng' EXTRA_LINK_ARGS = [] From 83672317aa268176b381f2df5da5c6600d551fbb Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Feb 2018 19:46:02 +0000 Subject: [PATCH 008/138] ENH: Add extra abstraction Abstract various components to allow more flexibility in generating specific distributions --- _randomgen/core_prng/common.pxd | 24 ++++---- _randomgen/core_prng/common.pyx | 25 +++++++- _randomgen/core_prng/generator.pyx | 58 +++++++++++-------- _randomgen/core_prng/splitmix64.pyx | 38 +++++++----- .../src/distributions/distributions.c | 25 ++++++++ .../src/distributions/distributions.h | 33 +++++++++++ _randomgen/core_prng/xoroshiro128.pyx | 16 ++--- _randomgen/demo.py | 18 ++++-- _randomgen/setup.py | 3 +- _randomgen/test.py | 14 +++++ 10 files changed, 190 insertions(+), 64 deletions(-) create mode 100644 _randomgen/core_prng/src/distributions/distributions.c create mode 100644 _randomgen/core_prng/src/distributions/distributions.h create mode 100644 _randomgen/test.py diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index b3e11a9aa55a..8d6df53ba641 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,21 +1,25 @@ +from libc.stdint cimport uint32_t, uint64_t -from libc.stdint cimport uint64_t +cdef extern from "src/distributions/distributions.h": + ctypedef double (*prng_double)(void *st) nogil -ctypedef uint64_t (*random_uint64_anon)(void* st) nogil + ctypedef float (*prng_float)(void *st) nogil -ctypedef double (*random_double_anon)(void* st) nogil + ctypedef uint32_t (*prng_uint32)(void *st) nogil -ctypedef double (*random_0)(void *st) nogil + ctypedef uint64_t (*prng_uint64)(void *st) nogil -cdef struct anon_func_state: - void *state - void *next_uint64 - void *next_uint32 - void *next_double + cdef struct prng: + void *state + void *next_uint64 + void *next_uint32 + void *next_double -ctypedef anon_func_state anon_func_state_t + ctypedef prng prng_t cdef inline double uint64_to_double(uint64_t rnd) nogil: return (rnd >> 11) * (1.0 / 9007199254740992.0) cdef object double_fill(void *func, void *state, object size, object lock, object out) + +cdef object float_fill(void *func, void *state, object size, object lock, object out) \ No newline at end of file diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index d7b5da8ddc6f..9dbd5ea08c2c 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -20,7 +20,7 @@ cdef check_output(object out, object dtype, object size): cdef object double_fill(void *func, void *state, object size, object lock, object out): - cdef random_0 random_func = (func) + cdef prng_double random_func = (func) cdef double *out_array_data cdef np.ndarray out_array cdef np.npy_intp i, n @@ -41,3 +41,26 @@ cdef object double_fill(void *func, void *state, object size, object lock, objec for i in range(n): out_array_data[i] = random_func(state) return out_array + +cdef object float_fill(void *func, void *state, object size, object lock, object out): + cdef prng_float random_func = (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 = out + else: + out_array = np.empty(size, np.float32) + + n = np.PyArray_SIZE(out_array) + out_array_data = np.PyArray_DATA(out_array) + with lock, nogil: + for i in range(n): + out_array_data[i] = random_func(state) + return out_array diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 636d63a63a02..bd213f5bc3ef 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -1,3 +1,4 @@ +from libc.stdint cimport uint64_t, uint32_t import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer @@ -12,13 +13,10 @@ from core_prng.splitmix64 import SplitMix64 np.import_array() - -cdef double random_double(void *void_state): - cdef anon_func_state_t *anon_state = void_state - cdef random_double_anon random_double_f = anon_state.next_double - cdef void *state = anon_state.state - return random_double_f(state) - +cdef extern from "src/distributions/distributions.h": + double random_double(void *void_state) nogil + float random_float(void *void_state) nogil + uint32_t random_uint32(void *void_state) nogil cdef class RandomGenerator: """ @@ -36,9 +34,10 @@ cdef class RandomGenerator: >>> rg.random_integer() """ cdef public object __core_prng - cdef anon_func_state anon_rng_func_state - cdef random_uint64_anon next_uint64 - cdef random_double_anon next_double + cdef prng_t *_prng + cdef prng_uint64 next_uint64 + cdef prng_double next_double + cdef prng_uint32 next_uint32 cdef void *rng_state cdef object lock @@ -47,30 +46,42 @@ cdef class RandomGenerator: prng = SplitMix64() self.__core_prng = prng - capsule = prng._anon_func_state - cdef const char *anon_name = "Anon CorePRNG func_state" + capsule = prng._prng_capsule + cdef const char *anon_name = "CorePRNG" if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") - self.anon_rng_func_state = (PyCapsule_GetPointer(capsule, anon_name))[0] - self.next_uint64 = self.anon_rng_func_state.next_uint64 - self.next_double = self.anon_rng_func_state.next_double - self.rng_state = self.anon_rng_func_state.state + self._prng = PyCapsule_GetPointer(capsule, anon_name) + self.next_uint32 = self._prng.next_uint32 + self.next_uint64 = self._prng.next_uint64 + self.next_double = self._prng.next_double + self.rng_state = self._prng.state self.lock = Lock() @property def state(self): - """Get ot set the underlying PRNG's state""" + """Get or set the underlying PRNG's state""" return self.__core_prng.state @state.setter def state(self, value): self.__core_prng.state = value - def random_integer(self): - return self.next_uint64(self.rng_state) + def random_integer(self, bits=64): + if bits==64: + return self.next_uint64(self.rng_state) + elif bits==32: + return random_uint32(self._prng) # self.next_uint32(self.rng_state) + # return self.next_uint32(self.rng_state) + else: + raise ValueError('bits must be 32 or 64') - def random_double(self): - return self.next_double(self.rng_state) + def random_double(self, bits=64): + if bits==64: + return self.next_double(self.rng_state) + elif bits==32: + return random_float(self._prng) + else: + raise ValueError('bits must be 32 or 64') def random_sample(self, size=None, dtype=np.float64, out=None): """ @@ -124,9 +135,8 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double, &self.anon_rng_func_state, size, self.lock, out) + return double_fill(&random_double, self._prng, size, self.lock, out) elif key == 'float32': - raise NotImplementedError - # return float_fill(&self.rng_state, &random_uniform_fill_float, size, self.lock, out) + return float_fill(&random_float, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 0aeda157a139..d645a1512f46 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -1,6 +1,6 @@ from libc.stdint cimport uint32_t, uint64_t -from cpython.pycapsule cimport PyCapsule_New - +from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer +from libc.stdlib cimport malloc import numpy as np cimport numpy as np @@ -19,13 +19,14 @@ cdef extern from "src/splitmix64/splitmix64.h": ctypedef s_splitmix64_state splitmix64_state cdef uint64_t splitmix64_next64(splitmix64_state *state) nogil - cdef uint64_t splitmix64_next32(splitmix64_state *state) nogil + cdef uint32_t splitmix64_next32(splitmix64_state *state) nogil cdef uint64_t splitmix64_uint64(void *st) nogil: return splitmix64_next64( st) -cdef uint64_t splitmix64_uint32(void *st) nogil: - return splitmix64_next32( st) +cdef uint32_t splitmix64_uint32(void *st): # nogil: TODO + cdef splitmix64_state *state = st + return splitmix64_next32(state) cdef double splitmix64_double(void *st) nogil: return uint64_to_double(splitmix64_uint64( st)) @@ -44,11 +45,14 @@ cdef class SplitMix64: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef splitmix64_state rng_state - cdef anon_func_state anon_func_state - cdef public object _anon_func_state + cdef splitmix64_state *rng_state + cdef prng_t *_prng + cdef prng_t *_prng2 + cdef public object _prng_capsule def __init__(self, seed=None): + self.rng_state = malloc(sizeof(splitmix64_state)) + self._prng = malloc(sizeof(prng_t)) if seed is None: try: state = random_entropy(2) @@ -60,14 +64,16 @@ cdef class SplitMix64: self.rng_state.state = int(state[0]) self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + self._prng.state = self.rng_state + self._prng.next_uint64 = &splitmix64_uint64 + self._prng.next_uint32 = &splitmix64_uint32 + self._prng.next_double = &splitmix64_double + cdef const char *anon_name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, + anon_name, NULL) + self._prng2 = PyCapsule_GetPointer(self._prng_capsule, anon_name) - self.anon_func_state.state = &self.rng_state - self.anon_func_state.next_uint64 = &splitmix64_uint64 - self.anon_func_state.next_uint32 = &splitmix64_uint32 - self.anon_func_state.next_double = &splitmix64_double - cdef const char *anon_name = "Anon CorePRNG func_state" - self._anon_func_state = PyCapsule_New( &self.anon_func_state, - anon_name, NULL) def __random_integer(self): """ @@ -82,7 +88,7 @@ cdef class SplitMix64: ----- Testing only """ - return splitmix64_next64(&self.rng_state) + return splitmix64_next64(self.rng_state) @property def state(self): diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c new file mode 100644 index 000000000000..41613e045727 --- /dev/null +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -0,0 +1,25 @@ +#include "distributions.h" + +uint32_t random_uint32(void *void_state) { + prng_t *prng_state = (prng_t *)void_state; + prng_uint32 next_uint32 = (prng_uint32)prng_state->next_uint32; + return next_uint32(prng_state->state); +} + +float random_float(void *void_state) { + prng_t *prng_state = (prng_t *)void_state; + prng_uint32 next_uint32 = (prng_uint32)(prng_state->next_uint32); + uint32_t next_value = next_uint32(prng_state->state); + return (next_value >> 9) * (1.0f / 8388608.0f); +} + +double random_double(void *void_state) { + prng_t *prng_state = (prng_t *)void_state; + prng_uint64 next_uint64 = (prng_uint64)(prng_state->next_uint64); + uint64_t next_value = next_uint64(prng_state->state); + return (next_value >> 11) * (1.0 / 9007199254740992.0); + // + + //prng_double next_double = (prng_double)prng_state->next_double; + //return next_double(&prng_state->state); +} diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h new file mode 100644 index 000000000000..dbe38492cf06 --- /dev/null +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -0,0 +1,33 @@ +#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/stdint.h" +typedef int bool; +#define false 0 +#define true 1 +#else +#include +#include +#endif +#else +#include +#include +#endif + +typedef double (*prng_double)(void *st); +typedef float (*prng_float)(void *st); +typedef uint32_t (*prng_uint32)(void *st); +typedef uint64_t (*prng_uint64)(void *st); + +typedef struct prng { + void *state; + void *next_uint64; + void *next_uint32; + void *next_double; +} prng_t; + +float random_float(void *void_state); + +double random_double(void *void_state); + +uint32_t random_uint32(void *void_state); diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 9f6da5355041..b6b724f13372 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -48,8 +48,8 @@ cdef class Xoroshiro128: for use in a `RandomGenerator` object. """ cdef xoroshiro128_state rng_state - cdef anon_func_state anon_func_state - cdef public object _anon_func_state + cdef prng_t _prng + cdef public object _prng_capsule def __init__(self, seed=None): @@ -64,12 +64,12 @@ cdef class Xoroshiro128: self.rng_state.s[0] = int(state[0]) self.rng_state.s[1] = int(state[1]) - self.anon_func_state.state = &self.rng_state - self.anon_func_state.next_uint64 = &xoroshiro128_uint64 - self.anon_func_state.next_uint32 = &xoroshiro128_uint32 - self.anon_func_state.next_double = &xoroshiro128_double - cdef const char *anon_name = "Anon CorePRNG func_state" - self._anon_func_state = PyCapsule_New(&self.anon_func_state, + self._prng.state = &self.rng_state + self._prng.next_uint64 = &xoroshiro128_uint64 + self._prng.next_uint32 = &xoroshiro128_uint32 + self._prng.next_double = &xoroshiro128_double + cdef const char *anon_name = "CorePRNG" + self._prng_capsule = PyCapsule_New(&self._prng, anon_name, NULL) def __random_integer(self, bits=64): diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 4eb414bef6a7..b40a2c42843d 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -9,18 +9,28 @@ print(RandomGenerator(SplitMix64(1)).random_integer()) print(RandomGenerator(SplitMix64([1.0, 2.0])).random_integer()) - -print('\n'*3) +print('\n' * 3) print('Check random_sample') rg = RandomGenerator() +print(rg.state) +print(rg.random_sample()) +print(rg.state) print(rg.random_sample()) print(rg.random_sample((3))) -print(rg.random_sample((3,1))) +print(rg.random_sample((3, 1))) +print(rg.state) +import numpy as np + +a = rg.random_sample((1, 1), dtype=np.float32) +print(a) +print(a.dtype) +print(rg.state) -print('\n'*3) +print('\n' * 3) print('Check set/get state') state = rg.state print(rg.state) print(rg.random_integer()) +print(rg.state) rg.state = state print(rg.random_integer()) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index a95c0e75de59..483299a52958 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -33,7 +33,8 @@ include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'xoroshiro128')]), Extension("core_prng.generator", - ["core_prng/generator.pyx"], + ["core_prng/generator.pyx", + join(MOD_DIR, 'src', 'distributions', 'distributions.c')], include_dirs=[np.get_include()]), Extension("core_prng.common", ["core_prng/common.pyx"], diff --git a/_randomgen/test.py b/_randomgen/test.py new file mode 100644 index 000000000000..38ffa02b05c4 --- /dev/null +++ b/_randomgen/test.py @@ -0,0 +1,14 @@ +import core_prng as c +rg = c.RandomGenerator() +print(rg.state) +rg.random_integer(32) +print(rg.state) +rg.random_integer(32) +print(rg.state) + +rg.random_integer(64) +print(rg.state) +rg.random_integer(32) +print(rg.state) +rg.random_integer(64) +print(rg.state) From d5dc57639463ce6fa374b273859512ec05499e47 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Feb 2018 23:59:34 +0000 Subject: [PATCH 009/138] ENH: Add float from double and std exponential Add float fillng from double Add support for log-based exponential --- _randomgen/core_prng/common.pxd | 6 ++- _randomgen/core_prng/common.pyx | 39 +++++++++----- _randomgen/core_prng/generator.pyx | 52 ++++++++++++++++--- _randomgen/core_prng/splitmix64.pyx | 3 -- .../src/distributions/distributions.c | 13 ++--- .../src/distributions/distributions.h | 4 ++ _randomgen/core_prng/xoroshiro128.pyx | 15 +++--- 7 files changed, 94 insertions(+), 38 deletions(-) diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 8d6df53ba641..7e29a4190bf6 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -20,6 +20,8 @@ cdef extern from "src/distributions/distributions.h": cdef inline double uint64_to_double(uint64_t rnd) nogil: return (rnd >> 11) * (1.0 / 9007199254740992.0) -cdef object double_fill(void *func, void *state, object size, object lock, object out) +cdef object double_fill(void *func, void *state, object size, object lock) -cdef object float_fill(void *func, void *state, object size, object lock, object out) \ No newline at end of file +cdef object float_fill(void *func, void *state, object size, object lock) + +cdef object float_fill_from_double(void *func, void *state, object size, object lock) \ No newline at end of file diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 9dbd5ea08c2c..2d09795af180 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -19,21 +19,17 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size and out cannot be simultaneously used') -cdef object double_fill(void *func, void *state, object size, object lock, object out): +cdef object double_fill(void *func, void *state, object size, object lock): cdef prng_double random_func = (func) cdef double *out_array_data cdef np.ndarray out_array cdef np.npy_intp i, n - if size is None and out is None: + if size is None: with lock: return random_func(state) - if out is not None: - check_output(out, np.double, size) - out_array = out - else: - out_array = np.empty(size, np.double) + out_array = np.empty(size, np.double) n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) @@ -42,21 +38,17 @@ cdef object double_fill(void *func, void *state, object size, object lock, objec out_array_data[i] = random_func(state) return out_array -cdef object float_fill(void *func, void *state, object size, object lock, object out): +cdef object float_fill(void *func, void *state, object size, object lock): cdef prng_float random_func = (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: + if size is None: with lock: return random_func(state) - if out is not None: - check_output(out, np.float32, size) - out_array = out - else: - out_array = np.empty(size, np.float32) + out_array = np.empty(size, np.float32) n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) @@ -64,3 +56,22 @@ cdef object float_fill(void *func, void *state, object size, object lock, object for i in range(n): out_array_data[i] = random_func(state) return out_array + +cdef object float_fill_from_double(void *func, void *state, object size, object lock): + cdef prng_double random_func = (func) + cdef float *out_array_data + cdef np.ndarray out_array + cdef np.npy_intp i, n + + if size is None: + with lock: + return random_func(state) + + out_array = np.empty(size, np.float32) + + n = np.PyArray_SIZE(out_array) + out_array_data = np.PyArray_DATA(out_array) + with lock, nogil: + for i in range(n): + out_array_data[i] = random_func(state) + return out_array diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index bd213f5bc3ef..93f44e86dea6 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -17,6 +17,7 @@ cdef extern from "src/distributions/distributions.h": double random_double(void *void_state) nogil float random_float(void *void_state) nogil uint32_t random_uint32(void *void_state) nogil + double random_standard_exponential(void *void_state) nogil cdef class RandomGenerator: """ @@ -83,7 +84,7 @@ cdef class RandomGenerator: else: raise ValueError('bits must be 32 or 64') - def random_sample(self, size=None, dtype=np.float64, out=None): + def random_sample(self, size=None, dtype=np.float64): """ random_sample(size=None, dtype='d', out=None) @@ -105,10 +106,6 @@ cdef class RandomGenerator: 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 ------- @@ -135,8 +132,49 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double, self._prng, size, self.lock, out) + return double_fill(&random_double, self._prng, size, self.lock) elif key == 'float32': - return float_fill(&random_float, self._prng, size, self.lock, out) + return float_fill(&random_float, self._prng, size, self.lock) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) + + + def standard_exponential(self, size=None, dtype=np.float64): + """ + standard_exponential(size=None, dtype='d', method='inv', 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'. + + Returns + ------- + out : float or ndarray + Drawn samples. + + Examples + -------- + Output a 3x8000 array: + + >>> n = np.random.standard_exponential((3, 8000)) + """ + key = np.dtype(dtype).name + if key == 'float64': + return double_fill(&random_standard_exponential, self._prng, size, self.lock) + elif key == 'float32': + return float_fill_from_double(&random_standard_exponential, self._prng, size, self.lock) + else: + raise TypeError('Unsupported dtype "%s" for standard_exponential' + % key) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index d645a1512f46..f953e1c02363 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -47,7 +47,6 @@ cdef class SplitMix64: """ cdef splitmix64_state *rng_state cdef prng_t *_prng - cdef prng_t *_prng2 cdef public object _prng_capsule def __init__(self, seed=None): @@ -72,8 +71,6 @@ cdef class SplitMix64: cdef const char *anon_name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, anon_name, NULL) - self._prng2 = PyCapsule_GetPointer(self._prng_capsule, anon_name) - def __random_integer(self): """ diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 41613e045727..f875b3182d0d 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -15,11 +15,12 @@ float random_float(void *void_state) { double random_double(void *void_state) { prng_t *prng_state = (prng_t *)void_state; - prng_uint64 next_uint64 = (prng_uint64)(prng_state->next_uint64); - uint64_t next_value = next_uint64(prng_state->state); - return (next_value >> 11) * (1.0 / 9007199254740992.0); - // + prng_double next_double = (prng_double)prng_state->next_double; + return next_double(prng_state->state); +} - //prng_double next_double = (prng_double)prng_state->next_double; - //return next_double(&prng_state->state); +double random_standard_exponential(void *void_state) { + prng_t *prng_state = (prng_t *)void_state; + prng_double next_double = (prng_double)prng_state->next_double; + return -log(1.0 - next_double(prng_state->state)); } diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index dbe38492cf06..fa37361cdc09 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -14,6 +14,8 @@ typedef int bool; #include #endif +#include + typedef double (*prng_double)(void *st); typedef float (*prng_float)(void *st); typedef uint32_t (*prng_uint32)(void *st); @@ -31,3 +33,5 @@ float random_float(void *void_state); double random_double(void *void_state); uint32_t random_uint32(void *void_state); + +double random_standard_exponential(void *void_state); \ No newline at end of file diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index b6b724f13372..a44412b997d6 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -47,12 +47,15 @@ cdef class Xoroshiro128: Exposes no user-facing API except `get_state` and `set_state`. Designed for use in a `RandomGenerator` object. """ - cdef xoroshiro128_state rng_state - cdef prng_t _prng + cdef xoroshiro128_state *rng_state + cdef prng_t *_prng cdef public object _prng_capsule def __init__(self, seed=None): + self.rng_state = malloc(sizeof(xoroshiro128_state)) + self._prng = malloc(sizeof(prng_t)) + if seed is None: try: state = random_entropy(4) @@ -64,7 +67,7 @@ cdef class Xoroshiro128: self.rng_state.s[0] = int(state[0]) self.rng_state.s[1] = int(state[1]) - self._prng.state = &self.rng_state + self._prng.state = self.rng_state self._prng.next_uint64 = &xoroshiro128_uint64 self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double @@ -91,14 +94,14 @@ cdef class Xoroshiro128: Testing only """ if bits == 64: - return xoroshiro128_next64(&self.rng_state) + return xoroshiro128_next64(self.rng_state) elif bits == 32: - return xoroshiro128_next32(&self.rng_state) + return xoroshiro128_next32(self.rng_state) else: raise ValueError('bits must be 32 or 64') def jump(self): - xoroshiro128_jump(&self.rng_state) + xoroshiro128_jump(self.rng_state) @property def state(self): From f4575d9f9388624e2724c7f4599bc53526bf3b92 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 1 Mar 2018 08:47:37 +0000 Subject: [PATCH 010/138] BUG: Fix bug in xoroshiro Fix bug which passes reference to state not state --- _randomgen/.gitattributes | 1 + _randomgen/MANIFEST.in | 2 + _randomgen/core_prng/__init__.py | 4 + _randomgen/core_prng/_version.py | 520 +++++++ _randomgen/core_prng/generator.pyx | 4 + _randomgen/core_prng/splitmix64.pyx | 69 +- _randomgen/core_prng/xoroshiro128.pyx | 71 +- _randomgen/setup.cfg | 7 + _randomgen/setup.py | 4 + _randomgen/versioneer.py | 1822 +++++++++++++++++++++++++ 10 files changed, 2467 insertions(+), 37 deletions(-) create mode 100644 _randomgen/.gitattributes create mode 100644 _randomgen/MANIFEST.in create mode 100644 _randomgen/core_prng/_version.py create mode 100644 _randomgen/setup.cfg create mode 100644 _randomgen/versioneer.py diff --git a/_randomgen/.gitattributes b/_randomgen/.gitattributes new file mode 100644 index 000000000000..c5ff9551eda2 --- /dev/null +++ b/_randomgen/.gitattributes @@ -0,0 +1 @@ +core_prng/_version.py export-subst diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in new file mode 100644 index 000000000000..14d24dca926c --- /dev/null +++ b/_randomgen/MANIFEST.in @@ -0,0 +1,2 @@ +include versioneer.py +include core_prng/_version.py diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index d097a9ef158b..539b3fa4d96a 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -3,3 +3,7 @@ from .splitmix64 import SplitMix64 __all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128'] + +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions diff --git a/_randomgen/core_prng/_version.py b/_randomgen/core_prng/_version.py new file mode 100644 index 000000000000..1041669c74ea --- /dev/null +++ b/_randomgen/core_prng/_version.py @@ -0,0 +1,520 @@ + +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (built by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.18 (https://github.com/warner/python-versioneer) + +"""Git implementation of _version.py.""" + +import errno +import os +import re +import subprocess +import sys + + +def get_keywords(): + """Get the keywords needed to look up the version information.""" + # these strings will be replaced by git during git-archive. + # setup.py/versioneer.py will grep for the variable names, so they must + # each be defined on a line of their own. _version.py will just call + # get_keywords(). + git_refnames = "$Format:%d$" + git_full = "$Format:%H$" + git_date = "$Format:%ci$" + keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} + return keywords + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_config(): + """Create, populate and return the VersioneerConfig() object.""" + # these strings are filled in when 'setup.py versioneer' creates + # _version.py + cfg = VersioneerConfig() + cfg.VCS = "git" + cfg.style = "pep440" + cfg.tag_prefix = "" + cfg.parentdir_prefix = "core_prng-" + cfg.versionfile_source = "core_prng/_version.py" + cfg.verbose = False + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % dispcmd) + print("stdout was %s" % stdout) + return None, p.returncode + return stdout, p.returncode + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %s but none started with prefix %s" % + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs - tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %s not under git control" % root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%s*" % tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%s'" + % describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%s' doesn't start with prefix '%s'" + print(fmt % (full_tag, tag_prefix)) + pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" + % (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%d" % pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%d" % pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%s'" % style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +def get_versions(): + """Get version information or return default if unable to do so.""" + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded keywords. + + cfg = get_config() + verbose = cfg.verbose + + try: + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, + verbose) + except NotThisMethod: + pass + + try: + root = os.path.realpath(__file__) + # versionfile_source is the relative path from the top of the source + # tree (where the .git directory might live) to this file. Invert + # this to find the root from __file__. + for i in cfg.versionfile_source.split('/'): + root = os.path.dirname(root) + except NameError: + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None} + + try: + pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) + return render(pieces, cfg.style) + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + except NotThisMethod: + pass + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", "date": None} diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 93f44e86dea6..69aca7a2e83e 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -68,7 +68,11 @@ cdef class RandomGenerator: self.__core_prng.state = value def random_integer(self, bits=64): + #print("In random_integer") if bits==64: + #print("Calling...") + #print(&self.next_uint64) + #print(&self.rng_state) return self.next_uint64(self.rng_state) elif bits==32: return random_uint32(self._prng) # self.next_uint32(self.rng_state) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index f953e1c02363..43f11fc18775 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -1,6 +1,7 @@ from libc.stdint cimport uint32_t, uint64_t -from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer -from libc.stdlib cimport malloc +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + import numpy as np cimport numpy as np @@ -52,25 +53,23 @@ cdef class SplitMix64: def __init__(self, seed=None): self.rng_state = malloc(sizeof(splitmix64_state)) self._prng = malloc(sizeof(prng_t)) - if seed is None: - try: - state = random_entropy(2) - except RuntimeError: - state = random_entropy(2, 'fallback') - state = state.view(np.uint64) - else: - state = entropy.seed_by_array(seed, 1) + self.seed(seed) - self.rng_state.state = int(state[0]) + self._prng.state = self.rng_state + self._prng.next_uint64 = &splitmix64_uint64 + self._prng.next_uint32 = &splitmix64_uint32 + self._prng.next_double = &splitmix64_double + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng) + + def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.state = self.rng_state - self._prng.next_uint64 = &splitmix64_uint64 - self._prng.next_uint32 = &splitmix64_uint32 - self._prng.next_double = &splitmix64_double - cdef const char *anon_name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, - anon_name, NULL) def __random_integer(self): """ @@ -87,6 +86,40 @@ cdef class SplitMix64: """ return splitmix64_next64(self.rng_state) + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(2) + except RuntimeError: + state = random_entropy(2, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 1) + self.rng_state.state = int(state[0]) + self._reset_state_variables() + + @property def state(self): """Get or set the PRNG state""" diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index a44412b997d6..0b6a0453ff54 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -1,8 +1,10 @@ -import numpy as np -cimport numpy as np from libc.stdint cimport uint32_t, uint64_t -from libc.stdlib cimport malloc +from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + from common cimport * from core_prng.entropy import random_entropy cimport entropy @@ -24,7 +26,7 @@ cdef extern from "src/xoroshiro128/xoroshiro128.h": cdef uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil cdef void xoroshiro128_jump(xoroshiro128_state *state) -cdef uint64_t xoroshiro128_uint64(void* st) nogil: +cdef uint64_t xoroshiro128_uint64(void* st):# nogil: return xoroshiro128_next64(st) cdef uint64_t xoroshiro128_uint32(void *st) nogil: @@ -51,29 +53,26 @@ cdef class Xoroshiro128: cdef prng_t *_prng cdef public object _prng_capsule - def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) self._prng = malloc(sizeof(prng_t)) - - if seed is None: - try: - state = random_entropy(4) - except RuntimeError: - state = random_entropy(4, 'fallback') - state = state.view(np.uint64) - else: - state = entropy.seed_by_array(seed, 2) - self.rng_state.s[0] = int(state[0]) - self.rng_state.s[1] = int(state[1]) + self.seed(seed) self._prng.state = self.rng_state self._prng.next_uint64 = &xoroshiro128_uint64 self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double - cdef const char *anon_name = "CorePRNG" - self._prng_capsule = PyCapsule_New(&self._prng, - anon_name, NULL) + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng) + + def _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 def __random_integer(self, bits=64): """ @@ -100,6 +99,40 @@ cdef class Xoroshiro128: else: raise ValueError('bits must be 32 or 64') + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + self.rng_state.s[0] = int(state[0]) + self.rng_state.s[1] = int(state[1]) + self._reset_state_variables() + def jump(self): xoroshiro128_jump(self.rng_state) diff --git a/_randomgen/setup.cfg b/_randomgen/setup.cfg new file mode 100644 index 000000000000..d622db893c08 --- /dev/null +++ b/_randomgen/setup.cfg @@ -0,0 +1,7 @@ +[versioneer] +VCS = git +style = pep440 +versionfile_source = core_prng/_version.py +versionfile_build = core_prng/_version.py +tag_prefix = +parentdir_prefix = core_prng- diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 483299a52958..6aa1aefa7979 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,6 +1,8 @@ import os from os.path import join +import versioneer + import numpy as np from Cython.Build import cythonize import Cython.Compiler.Options @@ -48,6 +50,8 @@ def is_pure(self): setup( + version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), ext_modules=cythonize(extensions), name='core_prng', packages=find_packages(), diff --git a/_randomgen/versioneer.py b/_randomgen/versioneer.py new file mode 100644 index 000000000000..64fea1c89272 --- /dev/null +++ b/_randomgen/versioneer.py @@ -0,0 +1,1822 @@ + +# Version: 0.18 + +"""The Versioneer - like a rocketeer, but for versions. + +The Versioneer +============== + +* like a rocketeer, but for versions! +* https://github.com/warner/python-versioneer +* Brian Warner +* License: Public Domain +* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy +* [![Latest Version] +(https://pypip.in/version/versioneer/badge.svg?style=flat) +](https://pypi.python.org/pypi/versioneer/) +* [![Build Status] +(https://travis-ci.org/warner/python-versioneer.png?branch=master) +](https://travis-ci.org/warner/python-versioneer) + +This is a tool for managing a recorded version number in distutils-based +python projects. The goal is to remove the tedious and error-prone "update +the embedded version string" step from your release process. Making a new +release should be as easy as recording a new tag in your version-control +system, and maybe making new tarballs. + + +## Quick Install + +* `pip install versioneer` to somewhere to your $PATH +* add a `[versioneer]` section to your setup.cfg (see below) +* run `versioneer install` in your source tree, commit the results + +## Version Identifiers + +Source trees come from a variety of places: + +* a version-control system checkout (mostly used by developers) +* a nightly tarball, produced by build automation +* a snapshot tarball, produced by a web-based VCS browser, like github's + "tarball from tag" feature +* a release tarball, produced by "setup.py sdist", distributed through PyPI + +Within each source tree, the version identifier (either a string or a number, +this tool is format-agnostic) can come from a variety of places: + +* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows + about recent "tags" and an absolute revision-id +* the name of the directory into which the tarball was unpacked +* an expanded VCS keyword ($Id$, etc) +* a `_version.py` created by some earlier build step + +For released software, the version identifier is closely related to a VCS +tag. Some projects use tag names that include more than just the version +string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool +needs to strip the tag prefix to extract the version identifier. For +unreleased software (between tags), the version identifier should provide +enough information to help developers recreate the same tree, while also +giving them an idea of roughly how old the tree is (after version 1.2, before +version 1.3). Many VCS systems can report a description that captures this, +for example `git describe --tags --dirty --always` reports things like +"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the +0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has +uncommitted changes. + +The version identifier is used for multiple purposes: + +* to allow the module to self-identify its version: `myproject.__version__` +* to choose a name and prefix for a 'setup.py sdist' tarball + +## Theory of Operation + +Versioneer works by adding a special `_version.py` file into your source +tree, where your `__init__.py` can import it. This `_version.py` knows how to +dynamically ask the VCS tool for version information at import time. + +`_version.py` also contains `$Revision$` markers, and the installation +process marks `_version.py` to have this marker rewritten with a tag name +during the `git archive` command. As a result, generated tarballs will +contain enough information to get the proper version. + +To allow `setup.py` to compute a version too, a `versioneer.py` is added to +the top level of your source tree, next to `setup.py` and the `setup.cfg` +that configures it. This overrides several distutils/setuptools commands to +compute the version when invoked, and changes `setup.py build` and `setup.py +sdist` to replace `_version.py` with a small static file that contains just +the generated version data. + +## Installation + +See [INSTALL.md](./INSTALL.md) for detailed installation instructions. + +## Version-String Flavors + +Code which uses Versioneer can learn about its version string at runtime by +importing `_version` from your main `__init__.py` file and running the +`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can +import the top-level `versioneer.py` and run `get_versions()`. + +Both functions return a dictionary with different flavors of version +information: + +* `['version']`: A condensed version string, rendered using the selected + style. This is the most commonly used value for the project's version + string. The default "pep440" style yields strings like `0.11`, + `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section + below for alternative styles. + +* `['full-revisionid']`: detailed revision identifier. For Git, this is the + full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". + +* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the + commit date in ISO 8601 format. This will be None if the date is not + available. + +* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that + this is only accurate if run in a VCS checkout, otherwise it is likely to + be False or None + +* `['error']`: if the version string could not be computed, this will be set + to a string describing the problem, otherwise it will be None. It may be + useful to throw an exception in setup.py if this is set, to avoid e.g. + creating tarballs with a version string of "unknown". + +Some variants are more useful than others. Including `full-revisionid` in a +bug report should allow developers to reconstruct the exact code being tested +(or indicate the presence of local changes that should be shared with the +developers). `version` is suitable for display in an "about" box or a CLI +`--version` output: it can be easily compared against release notes and lists +of bugs fixed in various releases. + +The installer adds the following text to your `__init__.py` to place a basic +version in `YOURPROJECT.__version__`: + + from ._version import get_versions + __version__ = get_versions()['version'] + del get_versions + +## Styles + +The setup.cfg `style=` configuration controls how the VCS information is +rendered into a version string. + +The default style, "pep440", produces a PEP440-compliant string, equal to the +un-prefixed tag name for actual releases, and containing an additional "local +version" section with more detail for in-between builds. For Git, this is +TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags +--dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the +tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and +that this commit is two revisions ("+2") beyond the "0.11" tag. For released +software (exactly equal to a known tag), the identifier will only contain the +stripped tag, e.g. "0.11". + +Other styles are available. See [details.md](details.md) in the Versioneer +source tree for descriptions. + +## Debugging + +Versioneer tries to avoid fatal errors: if something goes wrong, it will tend +to return a version of "0+unknown". To investigate the problem, run `setup.py +version`, which will run the version-lookup code in a verbose mode, and will +display the full contents of `get_versions()` (including the `error` string, +which may help identify what went wrong). + +## Known Limitations + +Some situations are known to cause problems for Versioneer. This details the +most significant ones. More can be found on Github +[issues page](https://github.com/warner/python-versioneer/issues). + +### Subprojects + +Versioneer has limited support for source trees in which `setup.py` is not in +the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are +two common reasons why `setup.py` might not be in the root: + +* Source trees which contain multiple subprojects, such as + [Buildbot](https://github.com/buildbot/buildbot), which contains both + "master" and "slave" subprojects, each with their own `setup.py`, + `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI + distributions (and upload multiple independently-installable tarballs). +* Source trees whose main purpose is to contain a C library, but which also + provide bindings to Python (and perhaps other langauges) in subdirectories. + +Versioneer will look for `.git` in parent directories, and most operations +should get the right version string. However `pip` and `setuptools` have bugs +and implementation details which frequently cause `pip install .` from a +subproject directory to fail to find a correct version string (so it usually +defaults to `0+unknown`). + +`pip install --editable .` should work correctly. `setup.py install` might +work too. + +Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in +some later version. + +[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking +this issue. The discussion in +[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the +issue from the Versioneer side in more detail. +[pip PR#3176](https://github.com/pypa/pip/pull/3176) and +[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve +pip to let Versioneer work correctly. + +Versioneer-0.16 and earlier only looked for a `.git` directory next to the +`setup.cfg`, so subprojects were completely unsupported with those releases. + +### Editable installs with setuptools <= 18.5 + +`setup.py develop` and `pip install --editable .` allow you to install a +project into a virtualenv once, then continue editing the source code (and +test) without re-installing after every change. + +"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a +convenient way to specify executable scripts that should be installed along +with the python package. + +These both work as expected when using modern setuptools. When using +setuptools-18.5 or earlier, however, certain operations will cause +`pkg_resources.DistributionNotFound` errors when running the entrypoint +script, which must be resolved by re-installing the package. This happens +when the install happens with one version, then the egg_info data is +regenerated while a different version is checked out. Many setup.py commands +cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into +a different virtualenv), so this can be surprising. + +[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes +this one, but upgrading to a newer version of setuptools should probably +resolve it. + +### Unicode version strings + +While Versioneer works (and is continually tested) with both Python 2 and +Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. +Newer releases probably generate unicode version strings on py2. It's not +clear that this is wrong, but it may be surprising for applications when then +write these strings to a network connection or include them in bytes-oriented +APIs like cryptographic checksums. + +[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates +this question. + + +## Updating Versioneer + +To upgrade your project to a new release of Versioneer, do the following: + +* install the new Versioneer (`pip install -U versioneer` or equivalent) +* edit `setup.cfg`, if necessary, to include any new configuration settings + indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. +* re-run `versioneer install` in your source tree, to replace + `SRC/_version.py` +* commit any changed files + +## Future Directions + +This tool is designed to make it easily extended to other version-control +systems: all VCS-specific components are in separate directories like +src/git/ . The top-level `versioneer.py` script is assembled from these +components by running make-versioneer.py . In the future, make-versioneer.py +will take a VCS name as an argument, and will construct a version of +`versioneer.py` that is specific to the given VCS. It might also take the +configuration arguments that are currently provided manually during +installation by editing setup.py . Alternatively, it might go the other +direction and include code from all supported VCS systems, reducing the +number of intermediate scripts. + + +## License + +To make Versioneer easier to embed, all its code is dedicated to the public +domain. The `_version.py` that it creates is also in the public domain. +Specifically, both are released under the Creative Commons "Public Domain +Dedication" license (CC0-1.0), as described in +https://creativecommons.org/publicdomain/zero/1.0/ . + +""" + +from __future__ import print_function +try: + import configparser +except ImportError: + import ConfigParser as configparser +import errno +import json +import os +import re +import subprocess +import sys + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_root(): + """Get the project root directory. + + We require that all commands are run from the project root, i.e. the + directory that contains setup.py, setup.cfg, and versioneer.py . + """ + root = os.path.realpath(os.path.abspath(os.getcwd())) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + # allow 'python path/to/setup.py COMMAND' + root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + err = ("Versioneer was unable to run the project root directory. " + "Versioneer requires setup.py to be executed from " + "its immediate directory (like 'python setup.py COMMAND'), " + "or in a way that lets it use sys.argv[0] to find the root " + "(like 'python path/to/setup.py COMMAND').") + raise VersioneerBadRootError(err) + try: + # Certain runtime workflows (setup.py install/develop in a setuptools + # tree) execute all dependencies in a single python process, so + # "versioneer" may be imported multiple times, and python's shared + # module-import table will cache the first one. So we can't use + # os.path.dirname(__file__), as that will find whichever + # versioneer.py was first imported, even in later projects. + me = os.path.realpath(os.path.abspath(__file__)) + me_dir = os.path.normcase(os.path.splitext(me)[0]) + vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) + if me_dir != vsr_dir: + print("Warning: build in %s is using versioneer.py from %s" + % (os.path.dirname(me), versioneer_py)) + except NameError: + pass + return root + + +def get_config_from_root(root): + """Read the project setup.cfg file to determine Versioneer config.""" + # This might raise EnvironmentError (if setup.cfg is missing), or + # configparser.NoSectionError (if it lacks a [versioneer] section), or + # configparser.NoOptionError (if it lacks "VCS="). See the docstring at + # the top of versioneer.py for instructions on writing your setup.cfg . + setup_cfg = os.path.join(root, "setup.cfg") + parser = configparser.SafeConfigParser() + with open(setup_cfg, "r") as f: + parser.readfp(f) + VCS = parser.get("versioneer", "VCS") # mandatory + + def get(parser, name): + if parser.has_option("versioneer", name): + return parser.get("versioneer", name) + return None + cfg = VersioneerConfig() + cfg.VCS = VCS + cfg.style = get(parser, "style") or "" + cfg.versionfile_source = get(parser, "versionfile_source") + cfg.versionfile_build = get(parser, "versionfile_build") + cfg.tag_prefix = get(parser, "tag_prefix") + if cfg.tag_prefix in ("''", '""'): + cfg.tag_prefix = "" + cfg.parentdir_prefix = get(parser, "parentdir_prefix") + cfg.verbose = get(parser, "verbose") + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +# these dictionaries contain VCS-specific tools +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % dispcmd) + print("stdout was %s" % stdout) + return None, p.returncode + return stdout, p.returncode + + +LONG_VERSION_PY['git'] = ''' +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (built by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.18 (https://github.com/warner/python-versioneer) + +"""Git implementation of _version.py.""" + +import errno +import os +import re +import subprocess +import sys + + +def get_keywords(): + """Get the keywords needed to look up the version information.""" + # these strings will be replaced by git during git-archive. + # setup.py/versioneer.py will grep for the variable names, so they must + # each be defined on a line of their own. _version.py will just call + # get_keywords(). + git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" + git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" + git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" + keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} + return keywords + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_config(): + """Create, populate and return the VersioneerConfig() object.""" + # these strings are filled in when 'setup.py versioneer' creates + # _version.py + cfg = VersioneerConfig() + cfg.VCS = "git" + cfg.style = "%(STYLE)s" + cfg.tag_prefix = "%(TAG_PREFIX)s" + cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" + cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" + cfg.verbose = False + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %%s" %% dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %%s" %% (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %%s (error)" %% dispcmd) + print("stdout was %%s" %% stdout) + return None, p.returncode + return stdout, p.returncode + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %%s but none started with prefix %%s" %% + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %%d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%%s', no digits" %% ",".join(refs - tags)) + if verbose: + print("likely tags: %%s" %% ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %%s" %% r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %%s not under git control" %% root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%%s*" %% tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%%s'" + %% describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%%s' doesn't start with prefix '%%s'" + print(fmt %% (full_tag, tag_prefix)) + pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" + %% (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%%d" %% pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%%d" %% pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%%s" %% pieces["short"] + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%%s" %% pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%%s'" %% style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +def get_versions(): + """Get version information or return default if unable to do so.""" + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded keywords. + + cfg = get_config() + verbose = cfg.verbose + + try: + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, + verbose) + except NotThisMethod: + pass + + try: + root = os.path.realpath(__file__) + # versionfile_source is the relative path from the top of the source + # tree (where the .git directory might live) to this file. Invert + # this to find the root from __file__. + for i in cfg.versionfile_source.split('/'): + root = os.path.dirname(root) + except NameError: + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None} + + try: + pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) + return render(pieces, cfg.style) + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + except NotThisMethod: + pass + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", "date": None} +''' + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs - tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %s not under git control" % root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%s*" % tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%s'" + % describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%s' doesn't start with prefix '%s'" + print(fmt % (full_tag, tag_prefix)) + pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" + % (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def do_vcs_install(manifest_in, versionfile_source, ipy): + """Git-specific installation logic for Versioneer. + + For Git, this means creating/changing .gitattributes to mark _version.py + for export-subst keyword substitution. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + files = [manifest_in, versionfile_source] + if ipy: + files.append(ipy) + try: + me = __file__ + if me.endswith(".pyc") or me.endswith(".pyo"): + me = os.path.splitext(me)[0] + ".py" + versioneer_file = os.path.relpath(me) + except NameError: + versioneer_file = "versioneer.py" + files.append(versioneer_file) + present = False + try: + f = open(".gitattributes", "r") + for line in f.readlines(): + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + f.close() + except EnvironmentError: + pass + if not present: + f = open(".gitattributes", "a+") + f.write("%s export-subst\n" % versionfile_source) + f.close() + files.append(".gitattributes") + run_command(GITS, ["add", "--"] + files) + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %s but none started with prefix %s" % + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +SHORT_VERSION_PY = """ +# This file was generated by 'versioneer.py' (0.18) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +import json + +version_json = ''' +%s +''' # END VERSION_JSON + + +def get_versions(): + return json.loads(version_json) +""" + + +def versions_from_file(filename): + """Try to determine the version from _version.py if present.""" + try: + with open(filename) as f: + contents = f.read() + except EnvironmentError: + raise NotThisMethod("unable to read _version.py") + mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + raise NotThisMethod("no version_json in _version.py") + return json.loads(mo.group(1)) + + +def write_to_version_file(filename, versions): + """Write the given version number to the given _version.py file.""" + os.unlink(filename) + contents = json.dumps(versions, sort_keys=True, + indent=1, separators=(",", ": ")) + with open(filename, "w") as f: + f.write(SHORT_VERSION_PY % contents) + + print("set %s to '%s'" % (filename, versions["version"])) + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%d" % pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%d" % pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%s'" % style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +class VersioneerBadRootError(Exception): + """The project root directory is unknown or missing key files.""" + + +def get_versions(verbose=False): + """Get the project version from whatever source is available. + + Returns dict with two keys: 'version' and 'full'. + """ + if "versioneer" in sys.modules: + # see the discussion in cmdclass.py:get_cmdclass() + del sys.modules["versioneer"] + + root = get_root() + cfg = get_config_from_root(root) + + assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" + handlers = HANDLERS.get(cfg.VCS) + assert handlers, "unrecognized VCS '%s'" % cfg.VCS + verbose = verbose or cfg.verbose + assert cfg.versionfile_source is not None, \ + "please set versioneer.versionfile_source" + assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" + + versionfile_abs = os.path.join(root, cfg.versionfile_source) + + # extract version from first of: _version.py, VCS command (e.g. 'git + # describe'), parentdir. This is meant to work for developers using a + # source checkout, for users of a tarball created by 'setup.py sdist', + # and for users of a tarball/zipball created by 'git archive' or github's + # download-from-tag feature or the equivalent in other VCSes. + + get_keywords_f = handlers.get("get_keywords") + from_keywords_f = handlers.get("keywords") + if get_keywords_f and from_keywords_f: + try: + keywords = get_keywords_f(versionfile_abs) + ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) + if verbose: + print("got version from expanded keyword %s" % ver) + return ver + except NotThisMethod: + pass + + try: + ver = versions_from_file(versionfile_abs) + if verbose: + print("got version from file %s %s" % (versionfile_abs, ver)) + return ver + except NotThisMethod: + pass + + from_vcs_f = handlers.get("pieces_from_vcs") + if from_vcs_f: + try: + pieces = from_vcs_f(cfg.tag_prefix, root, verbose) + ver = render(pieces, cfg.style) + if verbose: + print("got version from VCS %s" % ver) + return ver + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + if verbose: + print("got version from parentdir %s" % ver) + return ver + except NotThisMethod: + pass + + if verbose: + print("unable to compute version") + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, "error": "unable to compute version", + "date": None} + + +def get_version(): + """Get the short version string for this project.""" + return get_versions()["version"] + + +def get_cmdclass(): + """Get the custom setuptools/distutils subclasses used by Versioneer.""" + if "versioneer" in sys.modules: + del sys.modules["versioneer"] + # this fixes the "python setup.py develop" case (also 'install' and + # 'easy_install .'), in which subdependencies of the main project are + # built (using setup.py bdist_egg) in the same python process. Assume + # a main project A and a dependency B, which use different versions + # of Versioneer. A's setup.py imports A's Versioneer, leaving it in + # sys.modules by the time B's setup.py is executed, causing B to run + # with the wrong versioneer. Setuptools wraps the sub-dep builds in a + # sandbox that restores sys.modules to it's pre-build state, so the + # parent is protected against the child's "import versioneer". By + # removing ourselves from sys.modules here, before the child build + # happens, we protect the child from the parent's versioneer too. + # Also see https://github.com/warner/python-versioneer/issues/52 + + cmds = {} + + # we add "version" to both distutils and setuptools + from distutils.core import Command + + class cmd_version(Command): + description = "report generated version string" + user_options = [] + boolean_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + vers = get_versions(verbose=True) + print("Version: %s" % vers["version"]) + print(" full-revisionid: %s" % vers.get("full-revisionid")) + print(" dirty: %s" % vers.get("dirty")) + print(" date: %s" % vers.get("date")) + if vers["error"]: + print(" error: %s" % vers["error"]) + cmds["version"] = cmd_version + + # we override "build_py" in both distutils and setuptools + # + # most invocation pathways end up running build_py: + # distutils/build -> build_py + # distutils/install -> distutils/build ->.. + # setuptools/bdist_wheel -> distutils/install ->.. + # setuptools/bdist_egg -> distutils/install_lib -> build_py + # setuptools/install -> bdist_egg ->.. + # setuptools/develop -> ? + # pip install: + # copies source tree to a tempdir before running egg_info/etc + # if .git isn't copied too, 'git describe' will fail + # then does setup.py bdist_wheel, or sometimes setup.py install + # setup.py egg_info -> ? + + # we override different "build_py" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.build_py import build_py as _build_py + else: + from distutils.command.build_py import build_py as _build_py + + class cmd_build_py(_build_py): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + _build_py.run(self) + # now locate _version.py in the new build/ directory and replace + # it with an updated value + if cfg.versionfile_build: + target_versionfile = os.path.join(self.build_lib, + cfg.versionfile_build) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + cmds["build_py"] = cmd_build_py + + if "cx_Freeze" in sys.modules: # cx_freeze enabled? + from cx_Freeze.dist import build_exe as _build_exe + # nczeczulin reports that py2exe won't like the pep440-style string + # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. + # setup(console=[{ + # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION + # "product_version": versioneer.get_version(), + # ... + + class cmd_build_exe(_build_exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _build_exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["build_exe"] = cmd_build_exe + del cmds["build_py"] + + if 'py2exe' in sys.modules: # py2exe enabled? + try: + from py2exe.distutils_buildexe import py2exe as _py2exe # py3 + except ImportError: + from py2exe.build_exe import py2exe as _py2exe # py2 + + class cmd_py2exe(_py2exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _py2exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["py2exe"] = cmd_py2exe + + # we override different "sdist" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.sdist import sdist as _sdist + else: + from distutils.command.sdist import sdist as _sdist + + class cmd_sdist(_sdist): + def run(self): + versions = get_versions() + self._versioneer_generated_versions = versions + # unless we update this, the command will keep using the old + # version + self.distribution.metadata.version = versions["version"] + return _sdist.run(self) + + def make_release_tree(self, base_dir, files): + root = get_root() + cfg = get_config_from_root(root) + _sdist.make_release_tree(self, base_dir, files) + # now locate _version.py in the new base_dir directory + # (remembering that it may be a hardlink) and replace it with an + # updated value + target_versionfile = os.path.join(base_dir, cfg.versionfile_source) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, + self._versioneer_generated_versions) + cmds["sdist"] = cmd_sdist + + return cmds + + +CONFIG_ERROR = """ +setup.cfg is missing the necessary Versioneer configuration. You need +a section like: + + [versioneer] + VCS = git + style = pep440 + versionfile_source = src/myproject/_version.py + versionfile_build = myproject/_version.py + tag_prefix = + parentdir_prefix = myproject- + +You will also need to edit your setup.py to use the results: + + import versioneer + setup(version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), ...) + +Please read the docstring in ./versioneer.py for configuration instructions, +edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. +""" + +SAMPLE_CONFIG = """ +# See the docstring in versioneer.py for instructions. Note that you must +# re-run 'versioneer.py setup' after changing this section, and commit the +# resulting files. + +[versioneer] +#VCS = git +#style = pep440 +#versionfile_source = +#versionfile_build = +#tag_prefix = +#parentdir_prefix = + +""" + +INIT_PY_SNIPPET = """ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions +""" + + +def do_setup(): + """Main VCS-independent setup function for installing Versioneer.""" + root = get_root() + try: + cfg = get_config_from_root(root) + except (EnvironmentError, configparser.NoSectionError, + configparser.NoOptionError) as e: + if isinstance(e, (EnvironmentError, configparser.NoSectionError)): + print("Adding sample versioneer config to setup.cfg", + file=sys.stderr) + with open(os.path.join(root, "setup.cfg"), "a") as f: + f.write(SAMPLE_CONFIG) + print(CONFIG_ERROR, file=sys.stderr) + return 1 + + print(" creating %s" % cfg.versionfile_source) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + + ipy = os.path.join(os.path.dirname(cfg.versionfile_source), + "__init__.py") + if os.path.exists(ipy): + try: + with open(ipy, "r") as f: + old = f.read() + except EnvironmentError: + old = "" + if INIT_PY_SNIPPET not in old: + print(" appending to %s" % ipy) + with open(ipy, "a") as f: + f.write(INIT_PY_SNIPPET) + else: + print(" %s unmodified" % ipy) + else: + print(" %s doesn't exist, ok" % ipy) + ipy = None + + # Make sure both the top-level "versioneer.py" and versionfile_source + # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so + # they'll be copied into source distributions. Pip won't be able to + # install the package without this. + manifest_in = os.path.join(root, "MANIFEST.in") + simple_includes = set() + try: + with open(manifest_in, "r") as f: + for line in f: + if line.startswith("include "): + for include in line.split()[1:]: + simple_includes.add(include) + except EnvironmentError: + pass + # That doesn't cover everything MANIFEST.in can do + # (http://docs.python.org/2/distutils/sourcedist.html#commands), so + # it might give some false negatives. Appending redundant 'include' + # lines is safe, though. + if "versioneer.py" not in simple_includes: + print(" appending 'versioneer.py' to MANIFEST.in") + with open(manifest_in, "a") as f: + f.write("include versioneer.py\n") + else: + print(" 'versioneer.py' already in MANIFEST.in") + if cfg.versionfile_source not in simple_includes: + print(" appending versionfile_source ('%s') to MANIFEST.in" % + cfg.versionfile_source) + with open(manifest_in, "a") as f: + f.write("include %s\n" % cfg.versionfile_source) + else: + print(" versionfile_source already in MANIFEST.in") + + # Make VCS-specific changes. For git, this means creating/changing + # .gitattributes to mark _version.py for export-subst keyword + # substitution. + do_vcs_install(manifest_in, cfg.versionfile_source, ipy) + return 0 + + +def scan_setup_py(): + """Validate the contents of setup.py against Versioneer's expectations.""" + found = set() + setters = False + errors = 0 + with open("setup.py", "r") as f: + for line in f.readlines(): + if "import versioneer" in line: + found.add("import") + if "versioneer.get_cmdclass()" in line: + found.add("cmdclass") + if "versioneer.get_version()" in line: + found.add("get_version") + if "versioneer.VCS" in line: + setters = True + if "versioneer.versionfile_source" in line: + setters = True + if len(found) != 3: + print("") + print("Your setup.py appears to be missing some important items") + print("(but I might be wrong). Please make sure it has something") + print("roughly like the following:") + print("") + print(" import versioneer") + print(" setup( version=versioneer.get_version(),") + print(" cmdclass=versioneer.get_cmdclass(), ...)") + print("") + errors += 1 + if setters: + print("You should remove lines like 'versioneer.VCS = ' and") + print("'versioneer.versionfile_source = ' . This configuration") + print("now lives in setup.cfg, and should be removed from setup.py") + print("") + errors += 1 + return errors + + +if __name__ == "__main__": + cmd = sys.argv[1] + if cmd == "setup": + errors = do_setup() + errors += scan_setup_py() + if errors: + sys.exit(1) From c687b8450bb63fd01baefc2efbb66966441d4fe4 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 1 Mar 2018 20:00:12 +0000 Subject: [PATCH 011/138] CLN: Fix warning in entropy Use secure time function to avoid compiler warning --- _randomgen/core_prng/src/entropy/entropy.c | 2 +- _randomgen/core_prng/src/xoroshiro128/xoroshiro128.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_randomgen/core_prng/src/entropy/entropy.c b/_randomgen/core_prng/src/entropy/entropy.c index a5d48bd1418e..ead4bef835a3 100644 --- a/_randomgen/core_prng/src/entropy/entropy.c +++ b/_randomgen/core_prng/src/entropy/entropy.c @@ -142,7 +142,7 @@ uint32_t entropy_randombytes(void) { uint32_t out = 0; int64_t counter; struct _timeb tv; - _ftime(&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()); diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c index 244ca28b20d9..743b43f5f8c4 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -49,7 +49,7 @@ void xoroshiro128_jump(xoroshiro128_state *state) { s0 ^= state->s[0]; s1 ^= state->s[1]; } - xoroshiro128_next(&state->s); + xoroshiro128_next(&state->s[0]); } state->s[0] = s0; From 0d4eae3b52877e57dd58ef0a3e1f5e8d52182fc7 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 1 Mar 2018 22:45:43 +0000 Subject: [PATCH 012/138] REF: Add types to prng_t Add function types directly to prng_t to simplify use Clean distributionsto use new syntex Remove unused type definitions Rename type definitions to me more meaningful xref #1 --- _randomgen/core_prng/common.pxd | 14 ++++------ _randomgen/core_prng/common.pyx | 6 ++--- _randomgen/core_prng/generator.pyx | 18 +++---------- _randomgen/core_prng/splitmix64.pyx | 6 ++--- .../src/distributions/distributions.c | 26 +++++++------------ .../src/distributions/distributions.h | 20 +++++++------- _randomgen/core_prng/xoroshiro128.pyx | 8 +++--- 7 files changed, 36 insertions(+), 62 deletions(-) diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 7e29a4190bf6..21bab5df3176 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,19 +1,15 @@ from libc.stdint cimport uint32_t, uint64_t cdef extern from "src/distributions/distributions.h": - ctypedef double (*prng_double)(void *st) nogil + ctypedef double (*random_double_0)(void *st) nogil - ctypedef float (*prng_float)(void *st) nogil - - ctypedef uint32_t (*prng_uint32)(void *st) nogil - - ctypedef uint64_t (*prng_uint64)(void *st) nogil + ctypedef float (*random_float_0)(void *st) nogil cdef struct prng: void *state - void *next_uint64 - void *next_uint32 - void *next_double + uint64_t (*next_uint64)(void *st) + uint32_t (*next_uint32)(void *st) + double (*next_double)(void *st) ctypedef prng prng_t diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 2d09795af180..b6e832c49219 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -20,7 +20,7 @@ cdef check_output(object out, object dtype, object size): cdef object double_fill(void *func, void *state, object size, object lock): - cdef prng_double random_func = (func) + cdef random_double_0 random_func = (func) cdef double *out_array_data cdef np.ndarray out_array cdef np.npy_intp i, n @@ -39,7 +39,7 @@ cdef object double_fill(void *func, void *state, object size, object lock): return out_array cdef object float_fill(void *func, void *state, object size, object lock): - cdef prng_float random_func = (func) + cdef random_float_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array cdef np.npy_intp i, n @@ -58,7 +58,7 @@ cdef object float_fill(void *func, void *state, object size, object lock): return out_array cdef object float_fill_from_double(void *func, void *state, object size, object lock): - cdef prng_double random_func = (func) + cdef random_double_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array cdef np.npy_intp i, n diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 69aca7a2e83e..cfed7778a0a0 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -36,10 +36,6 @@ cdef class RandomGenerator: """ cdef public object __core_prng cdef prng_t *_prng - cdef prng_uint64 next_uint64 - cdef prng_double next_double - cdef prng_uint32 next_uint32 - cdef void *rng_state cdef object lock def __init__(self, prng=None): @@ -52,10 +48,6 @@ cdef class RandomGenerator: if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") self._prng = PyCapsule_GetPointer(capsule, anon_name) - self.next_uint32 = self._prng.next_uint32 - self.next_uint64 = self._prng.next_uint64 - self.next_double = self._prng.next_double - self.rng_state = self._prng.state self.lock = Lock() @property @@ -70,19 +62,15 @@ cdef class RandomGenerator: def random_integer(self, bits=64): #print("In random_integer") if bits==64: - #print("Calling...") - #print(&self.next_uint64) - #print(&self.rng_state) - return self.next_uint64(self.rng_state) + return self._prng.next_uint64(self._prng.state) elif bits==32: - return random_uint32(self._prng) # self.next_uint32(self.rng_state) - # return self.next_uint32(self.rng_state) + return random_uint32(self._prng) else: raise ValueError('bits must be 32 or 64') def random_double(self, bits=64): if bits==64: - return self.next_double(self.rng_state) + return self._prng.next_double(self._prng.state) elif bits==32: return random_float(self._prng) else: diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 43f11fc18775..3e83618bcb9e 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -56,9 +56,9 @@ cdef class SplitMix64: self.seed(seed) self._prng.state = self.rng_state - self._prng.next_uint64 = &splitmix64_uint64 - self._prng.next_uint32 = &splitmix64_uint32 - self._prng.next_double = &splitmix64_double + self._prng.next_uint64 = &splitmix64_uint64 + self._prng.next_uint32 = &splitmix64_uint32 + self._prng.next_double = &splitmix64_double cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index f875b3182d0d..d09c49450295 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -1,26 +1,18 @@ #include "distributions.h" -uint32_t random_uint32(void *void_state) { - prng_t *prng_state = (prng_t *)void_state; - prng_uint32 next_uint32 = (prng_uint32)prng_state->next_uint32; - return next_uint32(prng_state->state); +uint32_t random_uint32(prng_t *prng_state) { + return prng_state->next_uint32(prng_state->state); } -float random_float(void *void_state) { - prng_t *prng_state = (prng_t *)void_state; - prng_uint32 next_uint32 = (prng_uint32)(prng_state->next_uint32); - uint32_t next_value = next_uint32(prng_state->state); - return (next_value >> 9) * (1.0f / 8388608.0f); +float random_float(prng_t *prng_state) { + uint32_t next_32 = prng_state->next_uint32(prng_state->state); + return (next_32 >> 9) * (1.0f / 8388608.0f); } -double random_double(void *void_state) { - prng_t *prng_state = (prng_t *)void_state; - prng_double next_double = (prng_double)prng_state->next_double; - return next_double(prng_state->state); +double random_double(prng_t *prng_state) { + return prng_state->next_double(prng_state->state); } -double random_standard_exponential(void *void_state) { - prng_t *prng_state = (prng_t *)void_state; - prng_double next_double = (prng_double)prng_state->next_double; - return -log(1.0 - next_double(prng_state->state)); +double random_standard_exponential(prng_t *prng_state) { + return -log(1.0 - prng_state->next_double(prng_state->state)); } diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index fa37361cdc09..c5ac4d577f3d 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -16,22 +16,20 @@ typedef int bool; #include -typedef double (*prng_double)(void *st); -typedef float (*prng_float)(void *st); -typedef uint32_t (*prng_uint32)(void *st); -typedef uint64_t (*prng_uint64)(void *st); +typedef double (*random_double_0)(void *st); +typedef float (*random_float_0)(void *st); typedef struct prng { void *state; - void *next_uint64; - void *next_uint32; - void *next_double; + uint64_t (*next_uint64)(void *st); + uint32_t (*next_uint32)(void *st); + double (*next_double)(void *st); } prng_t; -float random_float(void *void_state); +float random_float(prng_t *prng_state); -double random_double(void *void_state); +double random_double(prng_t *prng_state); -uint32_t random_uint32(void *void_state); +uint32_t random_uint32(prng_t *prng_state); -double random_standard_exponential(void *void_state); \ No newline at end of file +double random_standard_exponential(prng_t *prng_state); \ No newline at end of file diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 0b6a0453ff54..d97bc06ad602 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -29,7 +29,7 @@ cdef extern from "src/xoroshiro128/xoroshiro128.h": cdef uint64_t xoroshiro128_uint64(void* st):# nogil: return xoroshiro128_next64(st) -cdef uint64_t xoroshiro128_uint32(void *st) nogil: +cdef uint32_t xoroshiro128_uint32(void *st) nogil: return xoroshiro128_next32( st) cdef double xoroshiro128_double(void* st) nogil: @@ -59,9 +59,9 @@ cdef class Xoroshiro128: self.seed(seed) self._prng.state = self.rng_state - self._prng.next_uint64 = &xoroshiro128_uint64 - self._prng.next_uint32 = &xoroshiro128_uint32 - self._prng.next_double = &xoroshiro128_double + self._prng.next_uint64 = &xoroshiro128_uint64 + self._prng.next_uint32 = &xoroshiro128_uint32 + self._prng.next_double = &xoroshiro128_double cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) From 27a96bbfd2beb60620243046c75c7a5852f350b9 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 2 Mar 2018 12:05:41 +0000 Subject: [PATCH 013/138] ENH: Add Threefry generator Add threefry Clean unused definitions from splitmix and xoroshiro --- _randomgen/core_prng/__init__.py | 5 +- .../core_prng/src/splitmix64/splitmix64.c | 2 +- .../core_prng/src/threefry/threefry-orig.c | 86 +++++++++ _randomgen/core_prng/src/threefry/threefry.c | 38 ++++ _randomgen/core_prng/src/threefry/threefry.h | 107 +++++++++++ .../core_prng/src/xoroshiro128/xoroshiro128.c | 6 +- .../core_prng/src/xoroshiro128/xoroshiro128.h | 2 +- _randomgen/core_prng/threefry.pyx | 174 ++++++++++++++++++ _randomgen/core_prng/xoroshiro128.pyx | 2 - _randomgen/demo.py | 10 +- _randomgen/setup.py | 5 + 11 files changed, 425 insertions(+), 12 deletions(-) create mode 100644 _randomgen/core_prng/src/threefry/threefry-orig.c create mode 100644 _randomgen/core_prng/src/threefry/threefry.c create mode 100644 _randomgen/core_prng/src/threefry/threefry.h create mode 100644 _randomgen/core_prng/threefry.pyx diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 539b3fa4d96a..19890ffb2499 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,8 +1,9 @@ from .generator import RandomGenerator -from .xoroshiro128 import Xoroshiro128 from .splitmix64 import SplitMix64 +from .threefry import ThreeFry +from .xoroshiro128 import Xoroshiro128 -__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128'] +__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128', 'ThreeFry'] from ._version import get_versions __version__ = get_versions()['version'] diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.c b/_randomgen/core_prng/src/splitmix64/splitmix64.c index 77f0693bac65..79a845982c5f 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.c +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.c @@ -22,7 +22,7 @@ license. #include "splitmix64.h" -static inline uint64_t splitmix64_next(uint64_t *state); +extern inline uint64_t splitmix64_next(uint64_t *state); extern inline uint64_t splitmix64_next64(splitmix64_state *state); diff --git a/_randomgen/core_prng/src/threefry/threefry-orig.c b/_randomgen/core_prng/src/threefry/threefry-orig.c new file mode 100644 index 000000000000..1a5094fa6b6d --- /dev/null +++ b/_randomgen/core_prng/src/threefry/threefry-orig.c @@ -0,0 +1,86 @@ +/* +Copyright (c) 2017, Pierre de Buyl + +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. +*/ + + +#include +#include "threefry.h" + +#define N_WORDS 2 +#define KEY_LENGTH 3 +#define C240 0x1BD11BDAA9FC1A22 +#define N_ROUNDS 20 +#define MASK 0xffffffffffffffff +#define DOUBLE_MULT 5.421010862427522e-20 + +static const int ROTATION[] = {16, 42, 12, 31, 16, 32, 24, 21}; + +uint64_t rotl_64(uint64_t x, int d) { + return ((x << d) | (x >> (64-d))); +} + +threefry_t mix(threefry_t x, int R) { + x.c0 += x.c1; + x.c1 = rotl_64(x.c1, R) ^ x.c0; + return x; +} + +threefry_t threefry(threefry_t p, threefry_t k) { + uint64_t K[] = {k.c0, k.c1, C240^k.c0^k.c1}; + int rmod4, rdiv4; + threefry_t x; + x = p; + for (int r=0; rc0++; + return x.c0; +} + +double threefry_double(threefry_t *c, threefry_t *k) { + threefry_t x; + x = threefry(*c, *k); + c->c0++; + return x.c0 * DOUBLE_MULT; +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/core_prng/src/threefry/threefry.c new file mode 100644 index 000000000000..3a2f00d13005 --- /dev/null +++ b/_randomgen/core_prng/src/threefry/threefry.c @@ -0,0 +1,38 @@ +/* +Adapted from https://github.com/pdebuyl/threefry + +Copyright (c) 2017, Pierre de Buyl + +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. +*/ + +#include "threefry.h" + +extern inline uint64_t threefry_next64(threefry_state *state); + +extern inline uint64_t threefry_next32(threefry_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h new file mode 100644 index 000000000000..302f3c9f1c9d --- /dev/null +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -0,0 +1,107 @@ +/* +Adapted from https://github.com/pdebuyl/threefry + +Copyright (c) 2017, Pierre de Buyl + +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. +*/ + + +#include + +#define N_WORDS 2 +#define KEY_LENGTH 3 +#define C240 0x1BD11BDAA9FC1A22 +#define N_ROUNDS 20 +#define MASK 0xffffffffffffffff +#define DOUBLE_MULT 5.421010862427522e-20 + +typedef struct { + uint64_t c0, c1; +} threefry_t; + +typedef struct s_threefry_state { + threefry_t *c; + threefry_t *k; + int has_uint32; + uint32_t uinteger; +} threefry_state; + +static const int ROTATION[] = {16, 42, 12, 31, 16, 32, 24, 21}; + +static inline uint64_t rotl_64(uint64_t x, int d) { + return ((x << d) | (x >> (64 - d))); +} + +static inline threefry_t mix(threefry_t x, int R) { + x.c0 += x.c1; + x.c1 = rotl_64(x.c1, R) ^ x.c0; + return x; +} + +static inline threefry_t threefry(threefry_t p, threefry_t k) { + const uint64_t K[] = {k.c0, k.c1, C240 ^ k.c0 ^ k.c1}; + int rmod4, rdiv4; + threefry_t x; + x = p; + for (int r = 0; r < N_ROUNDS; r++) { + rmod4 = r % 4; + if (rmod4 == 0) { + rdiv4 = r / 4; + x.c0 += K[rdiv4 % KEY_LENGTH]; + x.c1 += K[(rdiv4 + 1) % KEY_LENGTH] + rdiv4; + } + x = mix(x, ROTATION[r % 8]); + } + x.c0 += K[(N_ROUNDS / 4) % KEY_LENGTH]; + x.c1 += K[(N_ROUNDS / 4 + 1) % KEY_LENGTH] + N_ROUNDS / 4; + return x; +} + +static inline uint64_t threefry_next(threefry_t *c, threefry_t *k) { + threefry_t x; + x = threefry(*c, *k); + c->c0++; + return x.c0; +} + +static inline uint64_t threefry_next64(threefry_state *state) { + return threefry_next(state->c, state->k); +} + +static inline uint64_t threefry_next32(threefry_state *state) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = threefry_next(state->c, state->k); + ; + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next & 0xffffffff); + return (uint32_t)(next >> 32); +} diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c index 743b43f5f8c4..928e5c523566 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -32,11 +32,9 @@ See . */ #include "xoroshiro128.h" -extern inline uint64_t xoroshiro128_next(uint64_t *s); +extern inline uint64_t xoroshiro128_next64(xoroshiro128_state *state); -static inline uint64_t xoroshiro128_next64(xoroshiro128_state *state); - -static inline uint64_t xoroshiro128_next32(xoroshiro128_state *state); +extern inline uint32_t xoroshiro128_next32(xoroshiro128_state *state); void xoroshiro128_jump(xoroshiro128_state *state) { static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h index f575ef7aada3..bc6256aa6267 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -26,7 +26,7 @@ static inline uint64_t xoroshiro128_next64(xoroshiro128_state *state) { return xoroshiro128_next(&state->s[0]); } -static inline uint64_t xoroshiro128_next32(xoroshiro128_state *state) { +static inline uint32_t xoroshiro128_next32(xoroshiro128_state *state) { if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx new file mode 100644 index 000000000000..018dfc4165db --- /dev/null +++ b/_randomgen/core_prng/threefry.pyx @@ -0,0 +1,174 @@ +from libc.stdint cimport uint32_t, uint64_t +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy +cimport entropy + +np.import_array() + +cdef extern from "src/threefry/threefry.h": + + cdef struct s_threefry: + uint64_t c0, c1 + + ctypedef s_threefry threefry_t + + cdef struct s_threefry_state: + threefry_t *c + threefry_t *k + int has_uint32 + uint32_t uinteger + + ctypedef s_threefry_state threefry_state + + cdef uint64_t threefry_next64(threefry_state *state) nogil + cdef uint64_t threefry_next32(threefry_state *state) nogil + + +cdef uint64_t threefry_uint64(void* st):# nogil: + return threefry_next64(st) + +cdef uint32_t threefry_uint32(void *st) nogil: + return threefry_next32( st) + +cdef double threefry_double(void* st) nogil: + return uint64_to_double(threefry_next64(st)) + +cdef class ThreeFry: + """ + Prototype Core PRNG using threefry + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `state`. Designed for use in + a `RandomGenerator` object. + """ + cdef threefry_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(threefry_state)) + self.rng_state.c = malloc(sizeof(threefry_t)) + self.rng_state.k = malloc(sizeof(threefry_t)) + self._prng = malloc(sizeof(prng_t)) + self.seed(seed) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &threefry_uint64 + self._prng.next_uint32 = &threefry_uint32 + self._prng.next_double = &threefry_double + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + def __dealloc__(self): + free(self.rng_state.c) + free(self.rng_state.k) + free(self.rng_state) + free(self._prng) + + def _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return threefry_next64(self.rng_state) + elif bits == 32: + return threefry_next32(self.rng_state) + else: + raise ValueError('bits must be 32 or 64') + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + # TODO: Need to be able to set the key and counter directly + self.rng_state.c.c0 = 0 + self.rng_state.c.c1 = 0 + self.rng_state.k.c0 = int(state[0]) + self.rng_state.k.c1 = int(state[1]) + self._reset_state_variables() + + @property + def state(self): + """Get or set the PRNG state""" + c = np.empty(2, dtype=np.uint64) + k = np.empty(2, dtype=np.uint64) + c[0] = self.rng_state.c.c0 + c[1] = self.rng_state.c.c1 + k[0] = self.rng_state.k.c0 + k[1] = self.rng_state.k.c1 + state = {'c':c,'k':k} + return {'prng': self.__class__.__name__, + 'state': state, + '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') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + self.rng_state.c.c0 = value['state']['c'][0] + self.rng_state.c.c1 = value['state']['c'][1] + self.rng_state.k.c0 = value['state']['k'][0] + self.rng_state.k.c1 = value['state']['k'][1] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index d97bc06ad602..0cb53f830426 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -20,8 +20,6 @@ cdef extern from "src/xoroshiro128/xoroshiro128.h": ctypedef s_xoroshiro128_state xoroshiro128_state - cdef uint64_t xoroshiro128_next(uint64_t *s) nogil - cdef uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil cdef uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil cdef void xoroshiro128_jump(xoroshiro128_state *state) diff --git a/_randomgen/demo.py b/_randomgen/demo.py index b40a2c42843d..25b0ea876bcb 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,9 +1,9 @@ from core_prng.generator import RandomGenerator -from core_prng.splitmix64 import SplitMix64 -from core_prng.xoroshiro128 import Xoroshiro128 +from core_prng import SplitMix64, Xoroshiro128, ThreeFry print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) +print(RandomGenerator(ThreeFry()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) print(RandomGenerator(SplitMix64(1)).random_integer()) @@ -34,3 +34,9 @@ print(rg.state) rg.state = state print(rg.random_integer()) + +print(RandomGenerator(Xoroshiro128()).state) +rg = RandomGenerator(ThreeFry()) +print(rg.state) +rg.random_integer() +print(rg.state) \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 6aa1aefa7979..0a9a32b7f912 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -28,6 +28,11 @@ join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'splitmix64')]), + Extension("core_prng.threefry", + ["core_prng/threefry.pyx", + join(MOD_DIR, 'src', 'threefry', 'threefry.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'threefry')]), Extension("core_prng.xoroshiro128", ["core_prng/xoroshiro128.pyx", join(MOD_DIR, 'src', 'xoroshiro128', From a5f17a51f12cae185eec8f736ec1c1c0845a0ae7 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 2 Mar 2018 16:54:06 +0000 Subject: [PATCH 014/138] ENH: Use Random123 threefry Switch to random123 threefry implementation --- _randomgen/core_prng/__init__.py | 4 +- _randomgen/core_prng/entropy.pyx | 4 +- _randomgen/core_prng/mt19937.pyx | 150 +++ _randomgen/core_prng/splitmix64.pyx | 5 +- _randomgen/core_prng/src/mt19937/mt19937.c | 111 +++ _randomgen/core_prng/src/mt19937/mt19937.h | 69 ++ _randomgen/core_prng/src/threefry/threefry.h | 952 +++++++++++++++++-- _randomgen/core_prng/threefry.pyx | 65 +- _randomgen/demo.py | 12 +- _randomgen/setup.py | 5 + 10 files changed, 1265 insertions(+), 112 deletions(-) create mode 100644 _randomgen/core_prng/mt19937.pyx create mode 100644 _randomgen/core_prng/src/mt19937/mt19937.c create mode 100644 _randomgen/core_prng/src/mt19937/mt19937.h diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 19890ffb2499..8ede7e5f5fe9 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -2,8 +2,10 @@ from .splitmix64 import SplitMix64 from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 +from .mt19937 import MT19937 -__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128', 'ThreeFry'] +__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128', 'ThreeFry', + 'MT19937'] from ._version import get_versions __version__ = get_versions()['version'] diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/core_prng/entropy.pyx index f1155c605273..a4747f36b0fd 100644 --- a/_randomgen/core_prng/entropy.pyx +++ b/_randomgen/core_prng/entropy.pyx @@ -25,14 +25,14 @@ cdef Py_ssize_t compute_numel(size): cdef np.ndarray seed_by_array(object seed, Py_ssize_t n): """ - Transforms a seed array into an initiial state + Transforms a seed array into an initial state Parameters ---------- seed: array, 1d, uint64 Array to use. If seed is a scalar, promote to array. n : int - Number of 64-bit unsiened integers required + Number of 64-bit unsigned integers required Notes ----- diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx new file mode 100644 index 000000000000..e6f59aa2e385 --- /dev/null +++ b/_randomgen/core_prng/mt19937.pyx @@ -0,0 +1,150 @@ +import operator + +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy + +np.import_array() + +cdef extern from "src/mt19937/mt19937.h": + + cdef struct s_mt19937_state: + uint32_t key[624] + int pos + + ctypedef s_mt19937_state mt19937_state + + cdef uint64_t mt19937_next64(mt19937_state *state) nogil + cdef uint32_t mt19937_next32(mt19937_state *state) nogil + cdef double mt19937_next_double(mt19937_state *state) nogil + cdef void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key, int key_length) + cdef void mt19937_seed(mt19937_state *state, uint32_t seed) + +cdef uint64_t mt19937_uint64(void *st) nogil: + return mt19937_next64( st) + +cdef uint32_t mt19937_uint32(void *st) nogil: + return mt19937_next32( st) + +cdef double mt19937_double(void *st) nogil: + return mt19937_next_double( st) + +cdef class MT19937: + """ + Prototype Core PRNG using MT19937 + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `state`. Designed for use in a + `RandomGenerator` object. + """ + cdef mt19937_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(mt19937_state)) + self._prng = malloc(sizeof(prng_t)) + self.seed(seed) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &mt19937_uint64 + self._prng.next_uint32 = &mt19937_uint32 + self._prng.next_double = &mt19937_double + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng) + + def __random_integer(self): + """ + 64-bit Random Integers from the PRNG + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + return mt19937_next64(self.rng_state) + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + cdef np.ndarray obj + try: + if seed is None: + try: + seed = random_entropy(1) + except RuntimeError: + seed = random_entropy(1, 'fallback') + mt19937_seed(self.rng_state, seed[0]) + 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).astype(np.int64, casting='safe') + 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, obj.data, np.PyArray_DIM(obj, 0)) + + @property + def state(self): + """Get or set the PRNG state""" + key = np.zeros(624, dtype=np.uint32) + for i in range(624): + key[i] = self.rng_state.key[i] + + return {'prng': self.__class__.__name__, + 'state': {'key':key, 'pos': self.rng_state.pos}} + + @state.setter + def state(self, value): + if not isinstance(value, dict): + raise TypeError('state must be a dict') + prng = value.get('prng', '') + if prng != 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/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 3e83618bcb9e..514e9fed9550 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -25,9 +25,8 @@ cdef extern from "src/splitmix64/splitmix64.h": cdef uint64_t splitmix64_uint64(void *st) nogil: return splitmix64_next64( st) -cdef uint32_t splitmix64_uint32(void *st): # nogil: TODO - cdef splitmix64_state *state = st - return splitmix64_next32(state) +cdef uint32_t splitmix64_uint32(void *st) nogil: + return splitmix64_next32( st) cdef double splitmix64_double(void *st) nogil: return uint64_to_double(splitmix64_uint64( st)) diff --git a/_randomgen/core_prng/src/mt19937/mt19937.c b/_randomgen/core_prng/src/mt19937/mt19937.c new file mode 100644 index 000000000000..06ce7a16f4e8 --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/mt19937.c @@ -0,0 +1,111 @@ +#include "mt19937.h" + +extern inline uint32_t mt19937_random(mt19937_state *state); + +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); \ No newline at end of file diff --git a/_randomgen/core_prng/src/mt19937/mt19937.h b/_randomgen/core_prng/src/mt19937/mt19937.h new file mode 100644 index 000000000000..b9617769a622 --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/mt19937.h @@ -0,0 +1,69 @@ +#pragma once +#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/stdint.h" +#else +#include +#endif +#else +#include +#endif + +#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; +} diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index 302f3c9f1c9d..f6a2ca6bf2cc 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -1,97 +1,894 @@ /* -Adapted from https://github.com/pdebuyl/threefry - -Copyright (c) 2017, Pierre de Buyl - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Adapted from random123's threefry.h +*/ -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. +#include +#include -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. +enum r123_enum_threefry64x4 +{ + /* These are the R_256 constants from the Threefish reference sources + with names changed to R_64x4... */ + R_64x4_0_0 = 14, + R_64x4_0_1 = 16, + R_64x4_1_0 = 52, + R_64x4_1_1 = 57, + R_64x4_2_0 = 23, + R_64x4_2_1 = 40, + R_64x4_3_0 = 5, + R_64x4_3_1 = 37, + R_64x4_4_0 = 25, + R_64x4_4_1 = 33, + R_64x4_5_0 = 46, + R_64x4_5_1 = 12, + R_64x4_6_0 = 58, + R_64x4_6_1 = 22, + R_64x4_7_0 = 32, + R_64x4_7_1 = 32 +}; -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. +struct r123array4x64 +{ + uint64_t v[4]; +}; /* r123array4x64 */ -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. -*/ +typedef struct r123array4x64 threefry4x64_key_t; +typedef struct r123array4x64 threefry4x64_ctr_t; +static __inline _forceinline uint64_t RotL_64(uint64_t x, unsigned int N); +static __inline uint64_t RotL_64(uint64_t x, unsigned int N) +{ + return (x << (N & 63)) | (x >> ((64 - N) & 63)); +} -#include - -#define N_WORDS 2 -#define KEY_LENGTH 3 -#define C240 0x1BD11BDAA9FC1A22 -#define N_ROUNDS 20 -#define MASK 0xffffffffffffffff -#define DOUBLE_MULT 5.421010862427522e-20 -typedef struct { - uint64_t c0, c1; -} threefry_t; +static __inline _forceinline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); +static __inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) +{ + threefry4x64_ctr_t X; + uint64_t ks[4 + 1]; + int i; + (void)((!!(Nrounds <= 72)) || (_wassert(L"Nrounds<=72", L"c:\\temp\\random123-1.09\\include\\random123\\threefry.h", (unsigned)(728)), 0)); + ks[4] = ((0xA9FC1A22) + (((uint64_t)(0x1BD11BDA)) << 32)); + for (i = 0; i < 4; i++) + { + ks[i] = k.v[i]; + X.v[i] = in.v[i]; + ks[4] ^= k.v[i]; + } + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + if (Nrounds > 0) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 1) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 2) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 3) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 3) + { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 1; + } + if (Nrounds > 4) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 5) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 6) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 7) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 7) + { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 2; + } + if (Nrounds > 8) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 9) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 10) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 11) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 11) + { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 3; + } + if (Nrounds > 12) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 13) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 14) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 15) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 15) + { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 4; + } + if (Nrounds > 16) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 17) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 18) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 19) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 19) + { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 5; + } + if (Nrounds > 20) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 21) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 22) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 23) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 23) + { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 6; + } + if (Nrounds > 24) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 25) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 26) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 27) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 27) + { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 7; + } + if (Nrounds > 28) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 29) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 30) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 31) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 31) + { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 8; + } + if (Nrounds > 32) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 33) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 34) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 35) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 35) + { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 9; + } + if (Nrounds > 36) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 37) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 38) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 39) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 39) + { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 10; + } + if (Nrounds > 40) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 41) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 42) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 43) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 43) + { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 11; + } + if (Nrounds > 44) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 45) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 46) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 47) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 47) + { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 12; + } + if (Nrounds > 48) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 49) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 50) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 51) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 51) + { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 13; + } + if (Nrounds > 52) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 53) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 54) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 55) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 55) + { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 14; + } + if (Nrounds > 56) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 57) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 58) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 59) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 59) + { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 15; + } + if (Nrounds > 60) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 61) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 62) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 63) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 63) + { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 16; + } + if (Nrounds > 64) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 65) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 66) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 67) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 67) + { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 17; + } + if (Nrounds > 68) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 69) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 70) + { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 71) + { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 71) + { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 18; + } + return X; +} +enum r123_enum_threefry4x64 +{ + threefry4x64_rounds = 20 +}; typedef struct s_threefry_state { - threefry_t *c; - threefry_t *k; + threefry4x64_key_t *ctr; + threefry4x64_ctr_t *key; + int buffer_pos; + uint64_t buffer[4]; int has_uint32; uint32_t uinteger; } threefry_state; -static const int ROTATION[] = {16, 42, 12, 31, 16, 32, 24, 21}; -static inline uint64_t rotl_64(uint64_t x, int d) { - return ((x << d) | (x >> (64 - d))); -} - -static inline threefry_t mix(threefry_t x, int R) { - x.c0 += x.c1; - x.c1 = rotl_64(x.c1, R) ^ x.c0; - return x; -} - -static inline threefry_t threefry(threefry_t p, threefry_t k) { - const uint64_t K[] = {k.c0, k.c1, C240 ^ k.c0 ^ k.c1}; - int rmod4, rdiv4; - threefry_t x; - x = p; - for (int r = 0; r < N_ROUNDS; r++) { - rmod4 = r % 4; - if (rmod4 == 0) { - rdiv4 = r / 4; - x.c0 += K[rdiv4 % KEY_LENGTH]; - x.c1 += K[(rdiv4 + 1) % KEY_LENGTH] + rdiv4; - } - x = mix(x, ROTATION[r % 8]); +static inline uint64_t threefry_next(threefry_state *state) { + /* TODO: This 4 should be a constant somewhere */ + if (state->buffer_pos >= 4) { + /* generate 4 new uint64_t */ + int i; + threefry4x64_ctr_t ct; + state->ctr->v[0]++; + ct = threefry4x64_R(threefry4x64_rounds, *state->ctr, *state->key); + for (i=0; i<4; i++){ + state->buffer[i] = ct.v[i]; + } + state->buffer_pos = 0; } - x.c0 += K[(N_ROUNDS / 4) % KEY_LENGTH]; - x.c1 += K[(N_ROUNDS / 4 + 1) % KEY_LENGTH] + N_ROUNDS / 4; - return x; -} - -static inline uint64_t threefry_next(threefry_t *c, threefry_t *k) { - threefry_t x; - x = threefry(*c, *k); - c->c0++; - return x.c0; + uint64_t out = state->buffer[state->buffer_pos]; + state->buffer_pos++; + return out; } static inline uint64_t threefry_next64(threefry_state *state) { - return threefry_next(state->c, state->k); + return threefry_next(state); } static inline uint64_t threefry_next32(threefry_state *state) { @@ -99,9 +896,10 @@ static inline uint64_t threefry_next32(threefry_state *state) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = threefry_next(state->c, state->k); - ; + uint64_t next = threefry_next(state); + state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); + return (uint32_t)(next >> 32); } diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 018dfc4165db..961c09f59de5 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -13,14 +13,19 @@ np.import_array() cdef extern from "src/threefry/threefry.h": - cdef struct s_threefry: - uint64_t c0, c1 + cdef struct s_r123array4x64: + uint64_t v[4] - ctypedef s_threefry threefry_t + ctypedef s_r123array4x64 r123array4x64 + + ctypedef r123array4x64 threefry4x64_key_t + ctypedef r123array4x64 threefry4x64_ctr_t cdef struct s_threefry_state: - threefry_t *c - threefry_t *k + threefry4x64_key_t *ctr; + threefry4x64_ctr_t *key; + int buffer_pos; + uint64_t buffer[4]; int has_uint32 uint32_t uinteger @@ -30,7 +35,7 @@ cdef extern from "src/threefry/threefry.h": cdef uint64_t threefry_next32(threefry_state *state) nogil -cdef uint64_t threefry_uint64(void* st):# nogil: +cdef uint64_t threefry_uint64(void* st) nogil: return threefry_next64(st) cdef uint32_t threefry_uint32(void *st) nogil: @@ -59,8 +64,8 @@ cdef class ThreeFry: def __init__(self, seed=None): self.rng_state = malloc(sizeof(threefry_state)) - self.rng_state.c = malloc(sizeof(threefry_t)) - self.rng_state.k = malloc(sizeof(threefry_t)) + self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) + self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) self._prng = malloc(sizeof(prng_t)) self.seed(seed) @@ -73,14 +78,17 @@ cdef class ThreeFry: self._prng_capsule = PyCapsule_New(self._prng, name, NULL) def __dealloc__(self): - free(self.rng_state.c) - free(self.rng_state.k) + free(self.rng_state.ctr) + free(self.rng_state.key) free(self.rng_state) free(self._prng) def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + self.rng_state.buffer_pos = 4 + for i in range(4): + self.rng_state.buffer[i] = 0 def __random_integer(self, bits=64): """ @@ -130,31 +138,33 @@ cdef class ThreeFry: ub = 2 ** 64 if seed is None: try: - state = random_entropy(4) + state = random_entropy(8) except RuntimeError: - state = random_entropy(4, 'fallback') + state = random_entropy(8, 'fallback') state = state.view(np.uint64) else: state = entropy.seed_by_array(seed, 2) # TODO: Need to be able to set the key and counter directly - self.rng_state.c.c0 = 0 - self.rng_state.c.c1 = 0 - self.rng_state.k.c0 = int(state[0]) - self.rng_state.k.c1 = int(state[1]) + for i in range(4): + self.rng_state.ctr.v[i] = 0 + self.rng_state.key.v[i] = state[i] self._reset_state_variables() @property def state(self): """Get or set the PRNG state""" - c = np.empty(2, dtype=np.uint64) - k = np.empty(2, dtype=np.uint64) - c[0] = self.rng_state.c.c0 - c[1] = self.rng_state.c.c1 - k[0] = self.rng_state.k.c0 - k[1] = self.rng_state.k.c1 - state = {'c':c,'k':k} + ctr = np.empty(4, dtype=np.uint64) + key = np.empty(4, dtype=np.uint64) + buffer = np.empty(4, dtype=np.uint64) + for i in range(4): + ctr[i] = self.rng_state.ctr.v[i] + key[i] = self.rng_state.key.v[i] + buffer[i] = self.rng_state.buffer[i] + state = {'ctr':ctr,'k':key} return {'prng': 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} @@ -166,9 +176,10 @@ cdef class ThreeFry: if prng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) - self.rng_state.c.c0 = value['state']['c'][0] - self.rng_state.c.c1 = value['state']['c'][1] - self.rng_state.k.c0 = value['state']['k'][0] - self.rng_state.k.c1 = value['state']['k'][1] + for i in range(4): + self.rng_state.ctr.v[i] = value['state']['ctr'][i] + self.rng_state.key.v[i] = value['state']['key'][i] + self.rng_state.buffer[i] = value['state']['buffer'][i] self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] + self.rng_state.buffer_pos = value['buffer_pos'] diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 25b0ea876bcb..7fe81af01c25 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,5 +1,6 @@ from core_prng.generator import RandomGenerator -from core_prng import SplitMix64, Xoroshiro128, ThreeFry + +from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937 print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) @@ -39,4 +40,11 @@ rg = RandomGenerator(ThreeFry()) print(rg.state) rg.random_integer() -print(rg.state) \ No newline at end of file +print(rg.state) +rg = RandomGenerator(MT19937()) +state = rg.state +print(state) +rg.state = state +print(rg.random_integer()) +print(rg.random_integer(32)) +print(rg.random_sample()) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 0a9a32b7f912..3e06920e8844 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -23,6 +23,11 @@ include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'entropy')], extra_link_args=EXTRA_LINK_ARGS), + Extension("core_prng.mt19937", + ["core_prng/mt19937.pyx", + join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'mt19937')]), Extension("core_prng.splitmix64", ["core_prng/splitmix64.pyx", join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], From 56fd6e7ebefc40813ba2d6e28998a9fc2c07486a Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 2 Mar 2018 17:10:18 +0000 Subject: [PATCH 015/138] CLN: Remove unnecessary code from threefry Remove higher iterations from threefre --- _randomgen/core_prng/src/threefry/threefry.h | 574 +------------------ 1 file changed, 5 insertions(+), 569 deletions(-) diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index f6a2ca6bf2cc..5e0a720ffe1b 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -3,7 +3,6 @@ Adapted from random123's threefry.h */ #include -#include enum r123_enum_threefry64x4 { @@ -35,20 +34,19 @@ struct r123array4x64 typedef struct r123array4x64 threefry4x64_key_t; typedef struct r123array4x64 threefry4x64_ctr_t; -static __inline _forceinline uint64_t RotL_64(uint64_t x, unsigned int N); -static __inline uint64_t RotL_64(uint64_t x, unsigned int N) +static inline uint64_t RotL_64(uint64_t x, unsigned int N); +static inline uint64_t RotL_64(uint64_t x, unsigned int N) { return (x << (N & 63)) | (x >> ((64 - N) & 63)); } -static __inline _forceinline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); -static __inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) +static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); +static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) { threefry4x64_ctr_t X; uint64_t ks[4 + 1]; int i; - (void)((!!(Nrounds <= 72)) || (_wassert(L"Nrounds<=72", L"c:\\temp\\random123-1.09\\include\\random123\\threefry.h", (unsigned)(728)), 0)); ks[4] = ((0xA9FC1A22) + (((uint64_t)(0x1BD11BDA)) << 32)); for (i = 0; i < 4; i++) { @@ -280,6 +278,7 @@ static __inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry X.v[3] += ks[3]; X.v[4 - 1] += 5; } + /* Maximum of 20 rounds */ if (Nrounds > 20) { X.v[0] += X.v[1]; @@ -289,569 +288,6 @@ static __inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry X.v[3] = RotL_64(X.v[3], R_64x4_4_1); X.v[3] ^= X.v[2]; } - if (Nrounds > 21) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 22) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 23) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 23) - { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 6; - } - if (Nrounds > 24) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 25) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 26) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 27) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 27) - { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 7; - } - if (Nrounds > 28) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 29) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 30) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 31) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 31) - { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 8; - } - if (Nrounds > 32) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 33) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 34) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 35) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 35) - { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 9; - } - if (Nrounds > 36) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 37) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 38) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 39) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 39) - { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 10; - } - if (Nrounds > 40) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 41) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 42) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 43) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 43) - { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 11; - } - if (Nrounds > 44) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 45) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 46) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 47) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 47) - { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 12; - } - if (Nrounds > 48) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 49) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 50) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 51) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 51) - { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 13; - } - if (Nrounds > 52) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 53) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 54) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 55) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 55) - { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 14; - } - if (Nrounds > 56) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 57) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 58) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 59) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 59) - { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 15; - } - if (Nrounds > 60) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 61) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 62) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 63) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 63) - { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 16; - } - if (Nrounds > 64) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 65) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 66) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 67) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 67) - { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 17; - } - if (Nrounds > 68) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 69) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 70) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 71) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 71) - { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 18; - } return X; } enum r123_enum_threefry4x64 From 93b7edf6584bab4ea60ef6ea72a009121d604009 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 3 Mar 2018 11:26:08 +0000 Subject: [PATCH 016/138] ENH: Add pickle support Add pickle support for RandomGenerator Add pickle support for other core PRNGs --- _randomgen/core_prng/__init__.py | 4 +- _randomgen/core_prng/generator.pyx | 13 ++++++ _randomgen/core_prng/mt19937.pyx | 13 ++++++ _randomgen/core_prng/pickle.py | 62 +++++++++++++++++++++++++++ _randomgen/core_prng/splitmix64.pyx | 14 ++++++ _randomgen/core_prng/threefry.pyx | 14 ++++++ _randomgen/core_prng/xoroshiro128.pyx | 13 ++++++ 7 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 _randomgen/core_prng/pickle.py diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 8ede7e5f5fe9..6fa8bf8c40c7 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,12 +1,14 @@ from .generator import RandomGenerator +from .mt19937 import MT19937 from .splitmix64 import SplitMix64 from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 -from .mt19937 import MT19937 __all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128', 'ThreeFry', 'MT19937'] from ._version import get_versions + __version__ = get_versions()['version'] del get_versions + diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index cfed7778a0a0..115ae9b2e3f5 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -10,6 +10,7 @@ except ImportError: from dummy_threading import Lock from core_prng.splitmix64 import SplitMix64 +import core_prng.pickle np.import_array() @@ -50,6 +51,18 @@ cdef class RandomGenerator: self._prng = PyCapsule_GetPointer(capsule, anon_name) self.lock = Lock() + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__generator_ctor, + (self.state['prng'],), + self.state) + @property def state(self): """Get or set the underlying PRNG's state""" diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index e6f59aa2e385..2a9be05100eb 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -7,6 +7,7 @@ import numpy as np cimport numpy as np from common cimport * +import core_prng.pickle from core_prng.entropy import random_entropy np.import_array() @@ -69,6 +70,18 @@ cdef class MT19937: free(self.rng_state) free(self._prng) + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + def __random_integer(self): """ 64-bit Random Integers from the PRNG diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/core_prng/pickle.py new file mode 100644 index 000000000000..e3fede9210b4 --- /dev/null +++ b/_randomgen/core_prng/pickle.py @@ -0,0 +1,62 @@ +from .generator import RandomGenerator +from .mt19937 import MT19937 +from .splitmix64 import SplitMix64 +from .threefry import ThreeFry +from .xoroshiro128 import Xoroshiro128 + +PRNGS = {'SplitMix64': SplitMix64, + 'ThreeFry': ThreeFry, + 'MT19937': MT19937, + 'Xoroshiro128': Xoroshiro128} + + +def __generator_ctor(prng_name='mt19937'): + """ + Pickling helper function that returns a mod_name.RandomState object + + Parameters + ---------- + prng_name: str + String containing the core PRNG + + Returns + ------- + rg: RandomGenerator + RandomGenerator using the named core PRNG + """ + try: + prng_name = prng_name.decode('ascii') + except AttributeError: + pass + if prng_name in PRNGS: + prng = PRNGS[prng_name] + else: + raise ValueError(str(prng_name) + ' is not a known PRNG module.') + + return RandomGenerator(prng()) + + +def __prng_ctor(prng_name='mt19937'): + """ + Pickling helper function that returns a mod_name.RandomState object + + Parameters + ---------- + prng_name: str + String containing the core PRNG + + Returns + ------- + prng: CorePRNG + Core PRNG instance + """ + try: + prng_name = prng_name.decode('ascii') + except AttributeError: + pass + if prng_name in PRNGS: + prng = PRNGS[prng_name] + else: + raise ValueError(str(prng_name) + ' is not a known PRNG module.') + + return prng() diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 514e9fed9550..a80fe826aa07 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -7,6 +7,7 @@ cimport numpy as np from common cimport * from core_prng.entropy import random_entropy +import core_prng.pickle cimport entropy np.import_array() @@ -66,6 +67,19 @@ cdef class SplitMix64: free(self.rng_state) free(self._prng) + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 961c09f59de5..ae73cd36fe41 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -7,6 +7,7 @@ cimport numpy as np from common cimport * from core_prng.entropy import random_entropy +import core_prng.pickle cimport entropy np.import_array() @@ -77,6 +78,19 @@ cdef class ThreeFry: cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): free(self.rng_state.ctr) free(self.rng_state.key) diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 0cb53f830426..fc24db07d202 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -7,6 +7,7 @@ cimport numpy as np from common cimport * from core_prng.entropy import random_entropy +import core_prng.pickle cimport entropy np.import_array() @@ -64,6 +65,18 @@ cdef class Xoroshiro128: cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + def __dealloc__(self): free(self.rng_state) free(self._prng) From d6651387549688df188a930e1d24f9df39b6ee35 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 3 Mar 2018 11:56:14 +0000 Subject: [PATCH 017/138] DOC: Add list of TODOs List contains major next steps --- _randomgen/TODO.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 _randomgen/TODO.md diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md new file mode 100644 index 000000000000..a2e48fabc766 --- /dev/null +++ b/_randomgen/TODO.md @@ -0,0 +1,20 @@ +# TODO +0. Use inheritance to simplify CorePRNG structure. The natural base is + xoroshiro128. +1. Add PCG64 +2. Add dSFMT +3. Add xorshift2014 +4. Augment state to include has_gauss and gauss +5. Augment state to have binomial structure +6. Port over 0 parameter distributions + * standard exponential float + * standard exponential ziggurat + * standard exponential ziggurat float + * standard normal + * standard normal float + * standard normal ziggurat + * standard normal ziggurat float + * standard gamma + * standard gamma float +7. Remove SplitMix64 as an external generator +8. Restore ability to use `out` in core distributions From 892d43fb49a82cc7f80df967129ec5496828d90b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 3 Mar 2018 13:06:58 +0000 Subject: [PATCH 018/138] BIG: Fix setting state in threee fry --- _randomgen/TODO.md | 2 ++ _randomgen/core_prng/threefry.pyx | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index a2e48fabc766..dc093f4dca4d 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -18,3 +18,5 @@ * standard gamma float 7. Remove SplitMix64 as an external generator 8. Restore ability to use `out` in core distributions +9. Add correct carry for ThreeFry to allow full set of counters. Important when implmenting jump + diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index ae73cd36fe41..3279c23016a9 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -90,7 +90,6 @@ cdef class ThreeFry: (self.state['prng'],), self.state) - def __dealloc__(self): free(self.rng_state.ctr) free(self.rng_state.key) @@ -174,7 +173,7 @@ cdef class ThreeFry: ctr[i] = self.rng_state.ctr.v[i] key[i] = self.rng_state.key.v[i] buffer[i] = self.rng_state.buffer[i] - state = {'ctr':ctr,'k':key} + state = {'ctr':ctr,'key':key} return {'prng': self.__class__.__name__, 'state': state, 'buffer': buffer, @@ -193,7 +192,7 @@ cdef class ThreeFry: for i in range(4): self.rng_state.ctr.v[i] = value['state']['ctr'][i] self.rng_state.key.v[i] = value['state']['key'][i] - self.rng_state.buffer[i] = value['state']['buffer'][i] + self.rng_state.buffer[i] = 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'] From ad79fe082effca9ec69c34649c42629ced5230c1 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 3 Mar 2018 21:51:23 +0000 Subject: [PATCH 019/138] ENH: Add jump and advance to threefry Add jump (2**128) and advance (arbitrary) to threefry --- _randomgen/TODO.md | 3 +- _randomgen/core_prng/mt19937.pyx | 12 +- _randomgen/core_prng/splitmix64.pyx | 6 +- _randomgen/core_prng/src/threefry/threefry.c | 26 +- _randomgen/core_prng/src/threefry/threefry.h | 559 +++++++++---------- _randomgen/core_prng/threefry.pyx | 28 +- _randomgen/core_prng/xoroshiro128.pyx | 8 +- 7 files changed, 333 insertions(+), 309 deletions(-) diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index dc093f4dca4d..5ba92ab4ef75 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -18,5 +18,6 @@ * standard gamma float 7. Remove SplitMix64 as an external generator 8. Restore ability to use `out` in core distributions -9. Add correct carry for ThreeFry to allow full set of counters. Important when implmenting jump +## Done +9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 2a9be05100eb..6c2f4c5786e2 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -14,17 +14,17 @@ np.import_array() cdef extern from "src/mt19937/mt19937.h": - cdef struct s_mt19937_state: + struct s_mt19937_state: uint32_t key[624] int pos ctypedef s_mt19937_state mt19937_state - cdef uint64_t mt19937_next64(mt19937_state *state) nogil - cdef uint32_t mt19937_next32(mt19937_state *state) nogil - cdef double mt19937_next_double(mt19937_state *state) nogil - cdef void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key, int key_length) - cdef void mt19937_seed(mt19937_state *state, uint32_t seed) + 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) cdef uint64_t mt19937_uint64(void *st) nogil: return mt19937_next64( st) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index a80fe826aa07..515f68884bb8 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -13,15 +13,15 @@ cimport entropy np.import_array() cdef extern from "src/splitmix64/splitmix64.h": - cdef struct s_splitmix64_state: + struct s_splitmix64_state: uint64_t state int has_uint32 uint32_t uinteger ctypedef s_splitmix64_state splitmix64_state - cdef uint64_t splitmix64_next64(splitmix64_state *state) nogil - cdef uint32_t splitmix64_next32(splitmix64_state *state) nogil + uint64_t splitmix64_next64(splitmix64_state *state) nogil + uint32_t splitmix64_next32(splitmix64_state *state) nogil cdef uint64_t splitmix64_uint64(void *st) nogil: return splitmix64_next64( st) diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/core_prng/src/threefry/threefry.c index 3a2f00d13005..069ac5356d9a 100644 --- a/_randomgen/core_prng/src/threefry/threefry.c +++ b/_randomgen/core_prng/src/threefry/threefry.c @@ -35,4 +35,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern inline uint64_t threefry_next64(threefry_state *state); -extern inline uint64_t threefry_next32(threefry_state *state); \ No newline at end of file +extern inline uint64_t threefry_next32(threefry_state *state); + +extern void threefry_jump(threefry_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 threefry_advance(uint64_t *step, threefry_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/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index 5e0a720ffe1b..35a3be53f576 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -4,296 +4,265 @@ Adapted from random123's threefry.h #include -enum r123_enum_threefry64x4 -{ - /* These are the R_256 constants from the Threefish reference sources - with names changed to R_64x4... */ - R_64x4_0_0 = 14, - R_64x4_0_1 = 16, - R_64x4_1_0 = 52, - R_64x4_1_1 = 57, - R_64x4_2_0 = 23, - R_64x4_2_1 = 40, - R_64x4_3_0 = 5, - R_64x4_3_1 = 37, - R_64x4_4_0 = 25, - R_64x4_4_1 = 33, - R_64x4_5_0 = 46, - R_64x4_5_1 = 12, - R_64x4_6_0 = 58, - R_64x4_6_1 = 22, - R_64x4_7_0 = 32, - R_64x4_7_1 = 32 +enum r123_enum_threefry64x4 { + /* These are the R_256 constants from the Threefish reference sources + with names changed to R_64x4... */ + R_64x4_0_0 = 14, + R_64x4_0_1 = 16, + R_64x4_1_0 = 52, + R_64x4_1_1 = 57, + R_64x4_2_0 = 23, + R_64x4_2_1 = 40, + R_64x4_3_0 = 5, + R_64x4_3_1 = 37, + R_64x4_4_0 = 25, + R_64x4_4_1 = 33, + R_64x4_5_0 = 46, + R_64x4_5_1 = 12, + R_64x4_6_0 = 58, + R_64x4_6_1 = 22, + R_64x4_7_0 = 32, + R_64x4_7_1 = 32 }; -struct r123array4x64 -{ - uint64_t v[4]; +struct r123array4x64 { + uint64_t v[4]; }; /* r123array4x64 */ typedef struct r123array4x64 threefry4x64_key_t; typedef struct r123array4x64 threefry4x64_ctr_t; static inline uint64_t RotL_64(uint64_t x, unsigned int N); -static inline uint64_t RotL_64(uint64_t x, unsigned int N) -{ - return (x << (N & 63)) | (x >> ((64 - N) & 63)); +static inline uint64_t RotL_64(uint64_t x, unsigned int N) { + return (x << (N & 63)) | (x >> ((64 - N) & 63)); } - -static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); -static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) -{ - threefry4x64_ctr_t X; - uint64_t ks[4 + 1]; - int i; - ks[4] = ((0xA9FC1A22) + (((uint64_t)(0x1BD11BDA)) << 32)); - for (i = 0; i < 4; i++) - { - ks[i] = k.v[i]; - X.v[i] = in.v[i]; - ks[4] ^= k.v[i]; - } +static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, + threefry4x64_ctr_t in, + threefry4x64_key_t k); +static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, + threefry4x64_ctr_t in, + threefry4x64_key_t k) { + threefry4x64_ctr_t X; + uint64_t ks[4 + 1]; + int i; + ks[4] = ((0xA9FC1A22) + (((uint64_t)(0x1BD11BDA)) << 32)); + for (i = 0; i < 4; i++) { + ks[i] = k.v[i]; + X.v[i] = in.v[i]; + ks[4] ^= k.v[i]; + } + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + if (Nrounds > 0) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 1) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 2) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 3) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 3) { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 1; + } + if (Nrounds > 4) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 5) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 6) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 7) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 7) { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 2; + } + if (Nrounds > 8) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 9) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 10) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 11) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 11) { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 3; + } + if (Nrounds > 12) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 13) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 14) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 15) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 15) { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 4; + } + if (Nrounds > 16) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 17) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 18) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 19) { + X.v[0] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 19) { X.v[0] += ks[0]; X.v[1] += ks[1]; X.v[2] += ks[2]; X.v[3] += ks[3]; - if (Nrounds > 0) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 1) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 2) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 3) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 3) - { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 1; - } - if (Nrounds > 4) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 5) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 6) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 7) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 7) - { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 2; - } - if (Nrounds > 8) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 9) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 10) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 11) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 11) - { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 3; - } - if (Nrounds > 12) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 13) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 14) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 15) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 15) - { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 4; - } - if (Nrounds > 16) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 17) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 18) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 19) - { - X.v[0] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 19) - { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 5; - } - /* Maximum of 20 rounds */ - if (Nrounds > 20) - { - X.v[0] += X.v[1]; - X.v[1] = RotL_64(X.v[1], R_64x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_64(X.v[3], R_64x4_4_1); - X.v[3] ^= X.v[2]; - } - return X; + X.v[4 - 1] += 5; + } + /* Maximum of 20 rounds */ + if (Nrounds > 20) { + X.v[0] += X.v[1]; + X.v[1] = RotL_64(X.v[1], R_64x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_64(X.v[3], R_64x4_4_1); + X.v[3] ^= X.v[2]; + } + return X; } -enum r123_enum_threefry4x64 -{ - threefry4x64_rounds = 20 -}; +enum r123_enum_threefry4x64 { threefry4x64_rounds = 20 }; typedef struct s_threefry_state { threefry4x64_key_t *ctr; @@ -304,23 +273,33 @@ typedef struct s_threefry_state { uint32_t uinteger; } threefry_state; - static inline uint64_t threefry_next(threefry_state *state) { /* TODO: This 4 should be a constant somewhere */ - if (state->buffer_pos >= 4) { - /* generate 4 new uint64_t */ - int i; - threefry4x64_ctr_t ct; - state->ctr->v[0]++; - ct = threefry4x64_R(threefry4x64_rounds, *state->ctr, *state->key); - for (i=0; i<4; i++){ - state->buffer[i] = ct.v[i]; + if (state->buffer_pos < 4) { + uint64_t out = state->buffer[state->buffer_pos]; + state->buffer_pos++; + return out; + } + /* generate 4 new uint64_t */ + int i; + threefry4x64_ctr_t ct; + 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]++; + } } - state->buffer_pos = 0; } - uint64_t out = state->buffer[state->buffer_pos]; - state->buffer_pos++; - return out; + ct = threefry4x64_R(threefry4x64_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 inline uint64_t threefry_next64(threefry_state *state) { @@ -339,3 +318,7 @@ static inline uint64_t threefry_next32(threefry_state *state) { return (uint32_t)(next >> 32); } + +extern void threefry_jump(threefry_state *state); + +extern void threefry_advance(uint64_t *step, threefry_state *state); diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 3279c23016a9..ede7e7caefbb 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -1,4 +1,3 @@ -from libc.stdint cimport uint32_t, uint64_t from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New @@ -13,8 +12,7 @@ cimport entropy np.import_array() cdef extern from "src/threefry/threefry.h": - - cdef struct s_r123array4x64: + struct s_r123array4x64: uint64_t v[4] ctypedef s_r123array4x64 r123array4x64 @@ -22,7 +20,7 @@ cdef extern from "src/threefry/threefry.h": ctypedef r123array4x64 threefry4x64_key_t ctypedef r123array4x64 threefry4x64_ctr_t - cdef struct s_threefry_state: + struct s_threefry_state: threefry4x64_key_t *ctr; threefry4x64_ctr_t *key; int buffer_pos; @@ -32,8 +30,10 @@ cdef extern from "src/threefry/threefry.h": ctypedef s_threefry_state threefry_state - cdef uint64_t threefry_next64(threefry_state *state) nogil - cdef uint64_t threefry_next32(threefry_state *state) nogil + uint64_t threefry_next64(threefry_state *state) nogil + uint64_t threefry_next32(threefry_state *state) nogil + void threefry_jump(threefry_state *state) + void threefry_advance(uint64_t *step, threefry_state *state) cdef uint64_t threefry_uint64(void* st) nogil: @@ -196,3 +196,19 @@ cdef class ThreeFry: self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] + + def jump(self): + """Jump the state as-if 2**128 draws have been made""" + threefry_jump(self.rng_state) + + def advance(self, step): + """Advance the state as-if a specific number of draws have been made""" + cdef np.ndarray step_a = np.zeros(4,dtype=np.uint64) + if step >= 2**256 or step < 0: + raise ValueError('step must be between 0 and 2**256-1') + loc = 0 + while step > 0: + step_a[loc] = step % 2**64 + step >>= 64 + loc += 1 + threefry_advance(step_a.data, self.rng_state) diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index fc24db07d202..69ce93c31f84 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -14,16 +14,16 @@ np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": - cdef struct s_xoroshiro128_state: + struct s_xoroshiro128_state: uint64_t s[2] int has_uint32 uint32_t uinteger ctypedef s_xoroshiro128_state xoroshiro128_state - cdef uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil - cdef uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil - cdef void xoroshiro128_jump(xoroshiro128_state *state) + uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil + uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil + void xoroshiro128_jump(xoroshiro128_state *state) cdef uint64_t xoroshiro128_uint64(void* st):# nogil: return xoroshiro128_next64(st) From 4b2afc22b7372feaaa9bd49797edc3ca14569496 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 4 Mar 2018 21:36:13 +0000 Subject: [PATCH 020/138] ENH: Add PCG64 Add PCG64 generator --- _randomgen/TODO.md | 27 +- _randomgen/core_prng/__init__.py | 7 +- _randomgen/core_prng/common.pxd | 12 +- _randomgen/core_prng/generator.pyx | 106 +- _randomgen/core_prng/pcg64.pyx | 188 +++ .../src/distributions/distributions.c | 110 +- .../src/distributions/distributions.h | 15 +- .../core_prng/src/distributions/ziggurat.h | 276 ++++ .../src/distributions/ziggurat_constants.h | 1196 +++++++++++++++++ _randomgen/core_prng/src/pcg64/pcg64.c | 92 ++ _randomgen/core_prng/src/pcg64/pcg64.h | 237 ++++ .../core_prng/src/xorshift1024/xorshift1024.c | 31 + .../core_prng/src/xorshift1024/xorshift1024.h | 33 + .../src/xorshift1024/xorshift2014.orig.c | 69 + _randomgen/core_prng/xorshift1024.pyx | 174 +++ _randomgen/demo.py | 7 +- _randomgen/setup.py | 13 + 17 files changed, 2557 insertions(+), 36 deletions(-) create mode 100644 _randomgen/core_prng/pcg64.pyx create mode 100644 _randomgen/core_prng/src/distributions/ziggurat.h create mode 100644 _randomgen/core_prng/src/distributions/ziggurat_constants.h create mode 100644 _randomgen/core_prng/src/pcg64/pcg64.c create mode 100644 _randomgen/core_prng/src/pcg64/pcg64.h create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift1024.c create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift1024.h create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c create mode 100644 _randomgen/core_prng/xorshift1024.pyx diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index 5ba92ab4ef75..fac0a525c94d 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -1,23 +1,28 @@ # TODO -0. Use inheritance to simplify CorePRNG structure. The natural base is - xoroshiro128. -1. Add PCG64 2. Add dSFMT -3. Add xorshift2014 -4. Augment state to include has_gauss and gauss 5. Augment state to have binomial structure 6. Port over 0 parameter distributions - * standard exponential float - * standard exponential ziggurat * standard exponential ziggurat float - * standard normal - * standard normal float * standard normal ziggurat * standard normal ziggurat float - * standard gamma - * standard gamma float 7. Remove SplitMix64 as an external generator 8. Restore ability to use `out` in core distributions +10. Seed/Inc for PCG64 +11. Advance/Jump for PCG64 +12. Key/Counter for ThreeFry ## Done +1. Add PCG64 +3. Add xorshift2014 +4. Augment state to include has_gauss and gauss +6. Port over 0 parameter distributions + * standard exponential ziggurat + * standard exponential float + * standard normal + * standard normal float + * standard gamma - Not implement: This is a 1 param + * standard gamma float - Not implement: This is a 1 param + 9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump +0. NOT IMPLEMENTABLE due to limits on inheritance in Cython: Use inheritance to simplify CorePRNG structure. The natural base is + xoroshiro128. diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 6fa8bf8c40c7..c6123e023d03 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,14 +1,15 @@ from .generator import RandomGenerator from .mt19937 import MT19937 +from .pcg64 import PCG64 from .splitmix64 import SplitMix64 from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 +from .xorshift1024 import XorShift1024 -__all__ = ['RandomGenerator', 'SplitMix64', 'Xoroshiro128', 'ThreeFry', - 'MT19937'] +__all__ = ['RandomGenerator', 'SplitMix64', 'PCG64', 'Xoroshiro128', + 'ThreeFry', 'MT19937', 'XorShift1024'] from ._version import get_versions __version__ = get_versions()['version'] del get_versions - diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 21bab5df3176..b761cc037658 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -6,10 +6,14 @@ cdef extern from "src/distributions/distributions.h": ctypedef float (*random_float_0)(void *st) nogil cdef struct prng: - void *state - uint64_t (*next_uint64)(void *st) - uint32_t (*next_uint32)(void *st) - double (*next_double)(void *st) + void *state + uint64_t (*next_uint64)(void *st) + uint32_t (*next_uint32)(void *st) + double (*next_double)(void *st) + int has_gauss + double gauss + int has_gauss_f + float gauss_f ctypedef prng prng_t diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 115ae9b2e3f5..29b364270ade 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -1,9 +1,14 @@ -from libc.stdint cimport uint64_t, uint32_t import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * -cimport common + +cimport numpy as np +import numpy as np +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer + +from common cimport * + try: from threading import Lock except ImportError: @@ -15,10 +20,13 @@ import core_prng.pickle np.import_array() cdef extern from "src/distributions/distributions.h": - double random_double(void *void_state) nogil - float random_float(void *void_state) nogil - uint32_t random_uint32(void *void_state) nogil - double random_standard_exponential(void *void_state) nogil + double random_double(prng_t *prng_state) nogil + float random_float(prng_t *prng_state) nogil + uint32_t random_uint32(prng_t *prng_state) nogil + double random_standard_exponential(prng_t *prng_state) nogil + float random_standard_exponential_float(prng_t *prng_state) nogil + double random_gauss(prng_t *prng_state) + float random_gauss_float(prng_t *prng_state) cdef class RandomGenerator: """ @@ -48,8 +56,11 @@ cdef class RandomGenerator: cdef const char *anon_name = "CorePRNG" if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") - self._prng = PyCapsule_GetPointer(capsule, anon_name) + self._prng = PyCapsule_GetPointer(capsule, anon_name) self.lock = Lock() + with self.lock: + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 # Pickling support: def __getstate__(self): @@ -66,25 +77,34 @@ cdef class RandomGenerator: @property def state(self): """Get or set the underlying PRNG's state""" - return self.__core_prng.state + state = self.__core_prng.state + state['has_gauss'] = self._prng.has_gauss + state['has_gauss_f'] = self._prng.has_gauss_f + state['gauss'] = self._prng.gauss + state['gauss_f'] = self._prng.gauss_f + return state @state.setter def state(self, value): + self._prng.has_gauss = value['has_gauss'] + self._prng.has_gauss_f = value['has_gauss_f'] + self._prng.gauss = value['gauss'] + self._prng.gauss_f = value['gauss_f'] self.__core_prng.state = value def random_integer(self, bits=64): #print("In random_integer") - if bits==64: + if bits == 64: return self._prng.next_uint64(self._prng.state) - elif bits==32: + elif bits == 32: return random_uint32(self._prng) else: raise ValueError('bits must be 32 or 64') def random_double(self, bits=64): - if bits==64: + if bits == 64: return self._prng.next_double(self._prng.state) - elif bits==32: + elif bits == 32: return random_float(self._prng) else: raise ValueError('bits must be 32 or 64') @@ -143,7 +163,6 @@ cdef class RandomGenerator: else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) - def standard_exponential(self, size=None, dtype=np.float64): """ standard_exponential(size=None, dtype='d', method='inv', out=None) @@ -179,7 +198,66 @@ cdef class RandomGenerator: if key == 'float64': return double_fill(&random_standard_exponential, self._prng, size, self.lock) elif key == 'float32': - return float_fill_from_double(&random_standard_exponential, self._prng, size, self.lock) + return float_fill(&random_standard_exponential_float, self._prng, size, self.lock) else: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) + + # Complicated, continuous distributions: + def standard_normal(self, size=None, dtype=np.float64, method='bm'): + """ + standard_normal(size=None, dtype='d', method='bm', 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'. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations + 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 + -------- + >>> s = np.random.standard_normal(8000) + >>> s + 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) + + """ + key = np.dtype(dtype).name + if key == 'float64': + if method == u'zig': + raise NotImplementedError + #return double_fill(&self.rng_state, &random_gauss_zig_double_fill, size, self.lock, out) + else: + return double_fill(&random_gauss, self._prng, size, self.lock) + elif key == 'float32': + if method == u'zig': + raise NotImplementedError + #return float_fill(&self.rng_state, &random_gauss_zig_float_fill, size, self.lock, out) + else: + return float_fill(&random_gauss_float, self._prng, size, self.lock) + else: + raise TypeError('Unsupported dtype "%s" for standard_normal' % key) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx new file mode 100644 index 000000000000..543202b1293e --- /dev/null +++ b/_randomgen/core_prng/pcg64.pyx @@ -0,0 +1,188 @@ +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + +cdef extern from "src/pcg64/pcg64.h": + + ctypedef struct pcg128_t: + uint64_t high + uint64_t low + + cdef struct pcg_state_setseq_128: + pcg128_t state + pcg128_t inc + + ctypedef pcg_state_setseq_128 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 + uint64_t pcg64_next32(pcg64_state *state) nogil + void pcg64_jump(pcg64_state *state) + + +cdef uint64_t pcg64_uint64(void* st):# nogil: + return pcg64_next64(st) + +cdef uint32_t pcg64_uint32(void *st) nogil: + return pcg64_next32( st) + +cdef double pcg64_double(void* st) nogil: + return uint64_to_double(pcg64_next64(st)) + +cdef class PCG64: + """ + Prototype Core PRNG using pcg64 + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `get_state` and `set_state`. Designed + for use in a `RandomGenerator` object. + """ + cdef pcg64_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(pcg64_state)) + self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) + self._prng = malloc(sizeof(prng_t)) + self.seed(seed) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &pcg64_uint64 + self._prng.next_uint32 = &pcg64_uint32 + self._prng.next_double = &pcg64_double + + self.rng_state.pcg_state.inc.high = 0 + self.rng_state.pcg_state.inc.low = 1 + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng) + + def _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + self.rng_state.pcg_state.state.high = int(state[0]) + self.rng_state.pcg_state.state.low = int(state[1]) + self._reset_state_variables() + + @property + def state(self): + """Get or set the PRNG state""" + state = 2 **64 * self.rng_state.pcg_state.state.high + state += self.rng_state.pcg_state.state.low + inc = 2 **64 * self.rng_state.pcg_state.inc.high + inc += self.rng_state.pcg_state.inc.low + + return {'prng': self.__class__.__name__, + 'state': {'state': state, 'inc':inc}, + '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') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + + self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 + self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 + self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 + self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index d09c49450295..6c19ad020581 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -1,12 +1,18 @@ #include "distributions.h" +#include "ziggurat.h" +#include "ziggurat_constants.h" + +static NPY_INLINE float uint32_to_float(prng_t *prng_state) +{ + return (prng_state->next_uint32(prng_state->state) >> 9) * (1.0f / 8388608.0f); +} uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } float random_float(prng_t *prng_state) { - uint32_t next_32 = prng_state->next_uint32(prng_state->state); - return (next_32 >> 9) * (1.0f / 8388608.0f); + return uint32_to_float(prng_state); } double random_double(prng_t *prng_state) { @@ -16,3 +22,103 @@ double random_double(prng_t *prng_state) { double random_standard_exponential(prng_t *prng_state) { return -log(1.0 - prng_state->next_double(prng_state->state)); } + +float random_standard_exponential_float(prng_t *prng_state) { + return -logf(1.0f - uint32_to_float(prng_state)); +} + +double random_gauss(prng_t *prng_state) +{ + if (prng_state->has_gauss) + { + const double temp = prng_state->gauss; + prng_state->has_gauss = false; + return temp; + } + else + { + double f, x1, x2, r2; + + do + { + x1 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; + x2 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; + r2 = x1 * x1 + x2 * x2; + } while (r2 >= 1.0 || r2 == 0.0); + + /* Box-Muller transform */ + f = sqrt(-2.0 * log(r2) / r2); + /* Keep for next call */ + prng_state->gauss = f * x1; + prng_state->has_gauss = true; + return f * x2; + } +} + +float random_gauss_float(prng_t *prng_state) +{ + if (prng_state->has_gauss_f) + { + const float temp = prng_state->gauss_f; + prng_state->has_gauss_f = false; + return temp; + } + else + { + float f, x1, x2, r2; + + do + { + x1 = 2.0f * uint32_to_float(prng_state) - 1.0f; + x2 = 2.0f * uint32_to_float(prng_state) - 1.0f; + r2 = x1 * x1 + x2 * x2; + } while (r2 >= 1.0 || r2 == 0.0); + + /* Box-Muller transform */ + f = sqrtf(-2.0f * logf(r2) / r2); + /* Keep for next call */ + prng_state->gauss_f = f * x1; + prng_state->has_gauss_f = true; + return f * x2; + } +} + +double standard_exponential_zig_double(prng_t *prng_state); + +static double standard_exponential_zig_double_unlikely(prng_t *prng_state, uint8_t idx, double x) +{ + if (idx == 0) + { + return ziggurat_exp_r - log(random_double(prng_state)); + } + else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(prng_state) + fe_double[idx] < exp(-x)) + { + return x; + } + else + { + return standard_exponential_zig_double(prng_state); + } +} + +double standard_exponential_zig_double(prng_t *prng_state) +{ + uint64_t ri; + uint8_t idx; + double x; + ri = prng_state->next_uint64(prng_state->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_double_unlikely(prng_state, idx, x); +} + +double random_standard_exponential_zig_double(prng_t *prng_state) +{ + return standard_exponential_zig_double(prng_state); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index c5ac4d577f3d..7c029fe60e02 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -15,6 +15,7 @@ typedef int bool; #endif #include +#include "numpy/npy_common.h" typedef double (*random_double_0)(void *st); typedef float (*random_float_0)(void *st); @@ -24,6 +25,10 @@ typedef struct prng { uint64_t (*next_uint64)(void *st); uint32_t (*next_uint32)(void *st); double (*next_double)(void *st); + int has_gauss; + double gauss; + int has_gauss_f; + float gauss_f; } prng_t; float random_float(prng_t *prng_state); @@ -32,4 +37,12 @@ double random_double(prng_t *prng_state); uint32_t random_uint32(prng_t *prng_state); -double random_standard_exponential(prng_t *prng_state); \ No newline at end of file +double random_standard_exponential(prng_t *prng_state); + +float random_standard_exponential_float(prng_t *prng_state); + +double random_gauss(prng_t *prng_state); + +float random_gauss_float(prng_t *prng_state); + +double random_standard_exponential_zig_double(prng_t *prng_state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/distributions/ziggurat.h b/_randomgen/core_prng/src/distributions/ziggurat.h new file mode 100644 index 000000000000..7808c0e68fea --- /dev/null +++ b/_randomgen/core_prng/src/distributions/ziggurat.h @@ -0,0 +1,276 @@ +/* + * Constants from Julia's Ziggurat implementation + */ + +static const uint64_t ki[] = { + 0x0007799ec012f7b2, 0x0000000000000000, 0x0006045f4c7de363, + 0x0006d1aa7d5ec0a5, 0x000728fb3f60f777, 0x0007592af4e9fbc0, + 0x000777a5c0bf655d, 0x00078ca3857d2256, 0x00079bf6b0ffe58b, + 0x0007a7a34ab092ad, 0x0007b0d2f20dd1cb, 0x0007b83d3aa9cb52, + 0x0007be597614224d, 0x0007c3788631abe9, 0x0007c7d32bc192ee, + 0x0007cb9263a6e86d, 0x0007ced483edfa84, 0x0007d1b07ac0fd39, + 0x0007d437ef2da5fc, 0x0007d678b069aa6e, 0x0007d87db38c5c87, + 0x0007da4fc6a9ba62, 0x0007dbf611b37f3b, 0x0007dd7674d0f286, + 0x0007ded5ce8205f6, 0x0007e018307fb62b, 0x0007e141081bd124, + 0x0007e2533d712de8, 0x0007e3514bbd7718, 0x0007e43d54944b52, + 0x0007e5192f25ef42, 0x0007e5e67481118d, 0x0007e6a6897c1ce2, + 0x0007e75aa6c7f64c, 0x0007e803df8ee498, 0x0007e8a326eb6272, + 0x0007e93954717a28, 0x0007e9c727f8648f, 0x0007ea4d4cc85a3c, + 0x0007eacc5c4907a9, 0x0007eb44e0474cf6, 0x0007ebb754e47419, + 0x0007ec242a3d8474, 0x0007ec8bc5d69645, 0x0007ecee83d3d6e9, + 0x0007ed4cb8082f45, 0x0007eda6aee0170f, 0x0007edfcae2dfe68, + 0x0007ee4ef5dccd3e, 0x0007ee9dc08c394e, 0x0007eee9441a17c7, + 0x0007ef31b21b4fb1, 0x0007ef773846a8a7, 0x0007efba00d35a17, + 0x0007effa32ccf69f, 0x0007f037f25e1278, 0x0007f0736112d12c, + 0x0007f0ac9e145c25, 0x0007f0e3c65e1fcc, 0x0007f118f4ed8e54, + 0x0007f14c42ed0dc8, 0x0007f17dc7daa0c3, 0x0007f1ad99aac6a5, + 0x0007f1dbcce80015, 0x0007f20874cf56bf, 0x0007f233a36a3b9a, + 0x0007f25d69a604ad, 0x0007f285d7694a92, 0x0007f2acfba75e3b, + 0x0007f2d2e4720909, 0x0007f2f79f09c344, 0x0007f31b37ec883b, + 0x0007f33dbae36abc, 0x0007f35f330f08d5, 0x0007f37faaf2fa79, + 0x0007f39f2c805380, 0x0007f3bdc11f4f1c, 0x0007f3db71b83850, + 0x0007f3f846bba121, 0x0007f4144829f846, 0x0007f42f7d9a8b9d, + 0x0007f449ee420432, 0x0007f463a0f8675e, 0x0007f47c9c3ea77b, + 0x0007f494e643cd8e, 0x0007f4ac84e9c475, 0x0007f4c37dc9cd50, + 0x0007f4d9d638a432, 0x0007f4ef934a5b6a, 0x0007f504b9d5f33d, + 0x0007f5194e78b352, 0x0007f52d55994a96, 0x0007f540d36aba0c, + 0x0007f553cbef0e77, 0x0007f56642f9ec8f, 0x0007f5783c32f31e, + 0x0007f589bb17f609, 0x0007f59ac2ff1525, 0x0007f5ab5718b15a, + 0x0007f5bb7a71427c, 0x0007f5cb2ff31009, 0x0007f5da7a67cebe, + 0x0007f5e95c7a24e7, 0x0007f5f7d8b7171e, 0x0007f605f18f5ef4, + 0x0007f613a958ad0a, 0x0007f621024ed7e9, 0x0007f62dfe94f8cb, + 0x0007f63aa036777a, 0x0007f646e928065a, 0x0007f652db488f88, + 0x0007f65e786213ff, 0x0007f669c22a7d8a, 0x0007f674ba446459, + 0x0007f67f623fc8db, 0x0007f689bb9ac294, 0x0007f693c7c22481, + 0x0007f69d881217a6, 0x0007f6a6fdd6ac36, 0x0007f6b02a4c61ee, + 0x0007f6b90ea0a7f4, 0x0007f6c1abf254c0, 0x0007f6ca03521664, + 0x0007f6d215c2db82, 0x0007f6d9e43a3559, 0x0007f6e16fa0b329, + 0x0007f6e8b8d23729, 0x0007f6efc09e4569, 0x0007f6f687c84cbf, + 0x0007f6fd0f07ea09, 0x0007f703570925e2, 0x0007f709606cad03, + 0x0007f70f2bc8036f, 0x0007f714b9a5b292, 0x0007f71a0a85725d, + 0x0007f71f1edc4d9e, 0x0007f723f714c179, 0x0007f728938ed843, + 0x0007f72cf4a03fa0, 0x0007f7311a945a16, 0x0007f73505ac4bf8, + 0x0007f738b61f03bd, 0x0007f73c2c193dc0, 0x0007f73f67bd835c, + 0x0007f74269242559, 0x0007f745305b31a1, 0x0007f747bd666428, + 0x0007f74a103f12ed, 0x0007f74c28d414f5, 0x0007f74e0709a42d, + 0x0007f74faab939f9, 0x0007f75113b16657, 0x0007f75241b5a155, + 0x0007f753347e16b8, 0x0007f753ebb76b7c, 0x0007f75467027d05, + 0x0007f754a5f4199d, 0x0007f754a814b207, 0x0007f7546ce003ae, + 0x0007f753f3c4bb29, 0x0007f7533c240e92, 0x0007f75245514f41, + 0x0007f7510e91726c, 0x0007f74f971a9012, 0x0007f74dde135797, + 0x0007f74be2927971, 0x0007f749a39e051c, 0x0007f747202aba8a, + 0x0007f744571b4e3c, 0x0007f741473f9efe, 0x0007f73def53dc43, + 0x0007f73a4dff9bff, 0x0007f73661d4deaf, 0x0007f732294f003f, + 0x0007f72da2d19444, 0x0007f728cca72bda, 0x0007f723a5000367, + 0x0007f71e29f09627, 0x0007f7185970156b, 0x0007f7123156c102, + 0x0007f70baf5c1e2c, 0x0007f704d1150a23, 0x0007f6fd93f1a4e5, + 0x0007f6f5f53b10b6, 0x0007f6edf211023e, 0x0007f6e587671ce9, + 0x0007f6dcb2021679, 0x0007f6d36e749c64, 0x0007f6c9b91bf4c6, + 0x0007f6bf8e1c541b, 0x0007f6b4e95ce015, 0x0007f6a9c68356ff, + 0x0007f69e20ef5211, 0x0007f691f3b517eb, 0x0007f6853997f321, + 0x0007f677ed03ff19, 0x0007f66a08075bdc, 0x0007f65b844ab75a, + 0x0007f64c5b091860, 0x0007f63c8506d4bc, 0x0007f62bfa8798fe, + 0x0007f61ab34364b0, 0x0007f608a65a599a, 0x0007f5f5ca4737e8, + 0x0007f5e214d05b48, 0x0007f5cd7af7066e, 0x0007f5b7f0e4c2a1, + 0x0007f5a169d68fcf, 0x0007f589d80596a5, 0x0007f5712c8d0174, + 0x0007f557574c912b, 0x0007f53c46c77193, 0x0007f51fe7feb9f2, + 0x0007f5022646ecfb, 0x0007f4e2eb17ab1d, 0x0007f4c21dd4a3d1, + 0x0007f49fa38ea394, 0x0007f47b5ebb62eb, 0x0007f4552ee27473, + 0x0007f42cf03d58f5, 0x0007f4027b48549f, 0x0007f3d5a44119df, + 0x0007f3a63a8fb552, 0x0007f37408155100, 0x0007f33ed05b55ec, + 0x0007f3064f9c183e, 0x0007f2ca399c7ba1, 0x0007f28a384bb940, + 0x0007f245ea1b7a2b, 0x0007f1fcdffe8f1b, 0x0007f1ae9af758cd, + 0x0007f15a8917f27e, 0x0007f10001ccaaab, 0x0007f09e413c418a, + 0x0007f034627733d7, 0x0007efc15815b8d5, 0x0007ef43e2bf7f55, + 0x0007eeba84e31dfe, 0x0007ee237294df89, 0x0007ed7c7c170141, + 0x0007ecc2f0d95d3a, 0x0007ebf377a46782, 0x0007eb09d6deb285, + 0x0007ea00a4f17808, 0x0007e8d0d3da63d6, 0x0007e771023b0fcf, + 0x0007e5d46c2f08d8, 0x0007e3e937669691, 0x0007e195978f1176, + 0x0007deb2c0e05c1c, 0x0007db0362002a19, 0x0007d6202c151439, + 0x0007cf4b8f00a2cb, 0x0007c4fd24520efd, 0x0007b362fbf81816, + 0x00078d2d25998e24}; + +static const double wi[] = { + 1.7367254121602630e-15, 9.5586603514556339e-17, 1.2708704834810623e-16, + 1.4909740962495474e-16, 1.6658733631586268e-16, 1.8136120810119029e-16, + 1.9429720153135588e-16, 2.0589500628482093e-16, 2.1646860576895422e-16, + 2.2622940392218116e-16, 2.3532718914045892e-16, 2.4387234557428771e-16, + 2.5194879829274225e-16, 2.5962199772528103e-16, 2.6694407473648285e-16, + 2.7395729685142446e-16, 2.8069646002484804e-16, 2.8719058904113930e-16, + 2.9346417484728883e-16, 2.9953809336782113e-16, 3.0543030007192440e-16, + 3.1115636338921572e-16, 3.1672988018581815e-16, 3.2216280350549905e-16, + 3.2746570407939751e-16, 3.3264798116841710e-16, 3.3771803417353232e-16, + 3.4268340353119356e-16, 3.4755088731729758e-16, 3.5232663846002031e-16, + 3.5701624633953494e-16, 3.6162480571598339e-16, 3.6615697529653540e-16, + 3.7061702777236077e-16, 3.7500889278747798e-16, 3.7933619401549554e-16, + 3.8360228129677279e-16, 3.8781025861250247e-16, 3.9196300853257678e-16, + 3.9606321366256378e-16, 4.0011337552546690e-16, 4.0411583124143332e-16, + 4.0807276830960448e-16, 4.1198623774807442e-16, 4.1585816580828064e-16, + 4.1969036444740733e-16, 4.2348454071520708e-16, 4.2724230518899761e-16, + 4.3096517957162941e-16, 4.3465460355128760e-16, 4.3831194100854571e-16, + 4.4193848564470665e-16, 4.4553546609579137e-16, 4.4910405058828750e-16, + 4.5264535118571397e-16, 4.5616042766900381e-16, 4.5965029108849407e-16, + 4.6311590702081647e-16, 4.6655819856008752e-16, 4.6997804906941950e-16, + 4.7337630471583237e-16, 4.7675377680908526e-16, 4.8011124396270155e-16, + 4.8344945409350080e-16, 4.8676912627422087e-16, 4.9007095245229938e-16, + 4.9335559904654139e-16, 4.9662370843221783e-16, 4.9987590032409088e-16, + 5.0311277306593187e-16, 5.0633490483427195e-16, 5.0954285476338923e-16, + 5.1273716399787966e-16, 5.1591835667857364e-16, 5.1908694086703434e-16, + 5.2224340941340417e-16, 5.2538824077194543e-16, 5.2852189976823820e-16, + 5.3164483832166176e-16, 5.3475749612647295e-16, 5.3786030129452348e-16, + 5.4095367096239933e-16, 5.4403801186554671e-16, 5.4711372088173611e-16, + 5.5018118554603362e-16, 5.5324078453927836e-16, 5.5629288815190902e-16, + 5.5933785872484621e-16, 5.6237605106900435e-16, 5.6540781286489604e-16, + 5.6843348504368141e-16, 5.7145340215092040e-16, 5.7446789269419609e-16, + 5.7747727947569648e-16, 5.8048187991076857e-16, 5.8348200633338921e-16, + 5.8647796628943653e-16, 5.8947006281858718e-16, 5.9245859472561339e-16, + 5.9544385684180598e-16, 5.9842614027720281e-16, 6.0140573266426640e-16, + 6.0438291839361250e-16, 6.0735797884236057e-16, 6.1033119259564394e-16, + 6.1330283566179110e-16, 6.1627318168165963e-16, 6.1924250213258470e-16, + 6.2221106652737879e-16, 6.2517914260879998e-16, 6.2814699653988953e-16, + 6.3111489309056042e-16, 6.3408309582080600e-16, 6.3705186726088149e-16, + 6.4002146908880247e-16, 6.4299216230548961e-16, 6.4596420740788321e-16, + 6.4893786456033965e-16, 6.5191339376461587e-16, 6.5489105502874154e-16, + 6.5787110853507413e-16, 6.6085381480782587e-16, 6.6383943488035057e-16, + 6.6682823046247459e-16, 6.6982046410815579e-16, 6.7281639938375311e-16, + 6.7581630103719006e-16, 6.7882043516829803e-16, 6.8182906940062540e-16, + 6.8484247305500383e-16, 6.8786091732516637e-16, 6.9088467545571690e-16, + 6.9391402292275690e-16, 6.9694923761748294e-16, 6.9999060003307640e-16, + 7.0303839345521508e-16, 7.0609290415654822e-16, 7.0915442159548734e-16, + 7.1222323861967788e-16, 7.1529965167453030e-16, 7.1838396101720629e-16, + 7.2147647093647067e-16, 7.2457748997883870e-16, 7.2768733118146927e-16, + 7.3080631231227429e-16, 7.3393475611774048e-16, 7.3707299057898310e-16, + 7.4022134917657997e-16, 7.4338017116476479e-16, 7.4654980185558890e-16, + 7.4973059291369793e-16, 7.5292290266240584e-16, 7.5612709640179217e-16, + 7.5934354673958895e-16, 7.6257263393567558e-16, 7.6581474626104873e-16, + 7.6907028037219191e-16, 7.7233964170182985e-16, 7.7562324486711744e-16, + 7.7892151409638524e-16, 7.8223488367564108e-16, 7.8556379841610841e-16, + 7.8890871414417552e-16, 7.9227009821522709e-16, 7.9564843005293662e-16, + 7.9904420171571300e-16, 8.0245791849212591e-16, 8.0589009952726568e-16, + 8.0934127848215009e-16, 8.1281200422845008e-16, 8.1630284158098775e-16, + 8.1981437207065329e-16, 8.2334719476060504e-16, 8.2690192710884700e-16, + 8.3047920588053737e-16, 8.3407968811366288e-16, 8.3770405214202216e-16, + 8.4135299867980282e-16, 8.4502725197240968e-16, 8.4872756101861549e-16, + 8.5245470086955962e-16, 8.5620947401062333e-16, 8.5999271183276646e-16, + 8.6380527620052589e-16, 8.6764806112455816e-16, 8.7152199454736980e-16, + 8.7542804025171749e-16, 8.7936719990210427e-16, 8.8334051523084080e-16, + 8.8734907038131345e-16, 8.9139399442240861e-16, 8.9547646404950677e-16, + 8.9959770648910994e-16, 9.0375900262601175e-16, 9.0796169037400680e-16, + 9.1220716831348461e-16, 9.1649689962191353e-16, 9.2083241632623076e-16, + 9.2521532390956933e-16, 9.2964730630864167e-16, 9.3413013134252651e-16, + 9.3866565661866598e-16, 9.4325583596767065e-16, 9.4790272646517382e-16, + 9.5260849610662787e-16, 9.5737543220974496e-16, 9.6220595062948384e-16, + 9.6710260588230542e-16, 9.7206810229016259e-16, 9.7710530627072088e-16, + 9.8221725991905411e-16, 9.8740719604806711e-16, 9.9267855488079765e-16, + 9.9803500261836449e-16, 1.0034804521436181e-15, 1.0090190861637457e-15, + 1.0146553831467086e-15, 1.0203941464683124e-15, 1.0262405372613567e-15, + 1.0322001115486456e-15, 1.0382788623515399e-15, 1.0444832676000471e-15, + 1.0508203448355195e-15, 1.0572977139009890e-15, 1.0639236690676801e-15, + 1.0707072623632994e-15, 1.0776584002668106e-15, 1.0847879564403425e-15, + 1.0921079038149563e-15, 1.0996314701785628e-15, 1.1073733224935752e-15, + 1.1153497865853155e-15, 1.1235791107110833e-15, 1.1320817840164846e-15, + 1.1408809242582780e-15, 1.1500027537839792e-15, 1.1594771891449189e-15, + 1.1693385786910960e-15, 1.1796266352955801e-15, 1.1903876299282890e-15, + 1.2016759392543819e-15, 1.2135560818666897e-15, 1.2261054417450561e-15, + 1.2394179789163251e-15, 1.2536093926602567e-15, 1.2688244814255010e-15, + 1.2852479319096109e-15, 1.3031206634689985e-15, 1.3227655770195326e-15, + 1.3446300925011171e-15, 1.3693606835128518e-15, 1.3979436672775240e-15, + 1.4319989869661328e-15, 1.4744848603597596e-15, 1.5317872741611144e-15, + 1.6227698675312968e-15}; + +static const double fi[] = { + 1.0000000000000000e+00, 9.7710170126767082e-01, 9.5987909180010600e-01, + 9.4519895344229909e-01, 9.3206007595922991e-01, 9.1999150503934646e-01, + 9.0872644005213032e-01, 8.9809592189834297e-01, 8.8798466075583282e-01, + 8.7830965580891684e-01, 8.6900868803685649e-01, 8.6003362119633109e-01, + 8.5134625845867751e-01, 8.4291565311220373e-01, 8.3471629298688299e-01, + 8.2672683394622093e-01, 8.1892919160370192e-01, 8.1130787431265572e-01, + 8.0384948317096383e-01, 7.9654233042295841e-01, 7.8937614356602404e-01, + 7.8234183265480195e-01, 7.7543130498118662e-01, 7.6863731579848571e-01, + 7.6195334683679483e-01, 7.5537350650709567e-01, 7.4889244721915638e-01, + 7.4250529634015061e-01, 7.3620759812686210e-01, 7.2999526456147568e-01, + 7.2386453346862967e-01, 7.1781193263072152e-01, 7.1183424887824798e-01, + 7.0592850133275376e-01, 7.0009191813651117e-01, 6.9432191612611627e-01, + 6.8861608300467136e-01, 6.8297216164499430e-01, 6.7738803621877308e-01, + 6.7186171989708166e-01, 6.6639134390874977e-01, 6.6097514777666277e-01, + 6.5561147057969693e-01, 6.5029874311081637e-01, 6.4503548082082196e-01, + 6.3982027745305614e-01, 6.3465179928762327e-01, 6.2952877992483625e-01, + 6.2445001554702606e-01, 6.1941436060583399e-01, 6.1442072388891344e-01, + 6.0946806492577310e-01, 6.0455539069746733e-01, 5.9968175261912482e-01, + 5.9484624376798689e-01, 5.9004799633282545e-01, 5.8528617926337090e-01, + 5.8055999610079034e-01, 5.7586868297235316e-01, 5.7121150673525267e-01, + 5.6658776325616389e-01, 5.6199677581452390e-01, 5.5743789361876550e-01, + 5.5291049042583185e-01, 5.4841396325526537e-01, 5.4394773119002582e-01, + 5.3951123425695158e-01, 5.3510393238045717e-01, 5.3072530440366150e-01, + 5.2637484717168403e-01, 5.2205207467232140e-01, 5.1775651722975591e-01, + 5.1348772074732651e-01, 5.0924524599574761e-01, 5.0502866794346790e-01, + 5.0083757512614835e-01, 4.9667156905248933e-01, 4.9253026364386815e-01, + 4.8841328470545758e-01, 4.8432026942668288e-01, 4.8025086590904642e-01, + 4.7620473271950547e-01, 4.7218153846772976e-01, 4.6818096140569321e-01, + 4.6420268904817391e-01, 4.6024641781284248e-01, 4.5631185267871610e-01, + 4.5239870686184824e-01, 4.4850670150720273e-01, 4.4463556539573912e-01, + 4.4078503466580377e-01, 4.3695485254798533e-01, 4.3314476911265209e-01, + 4.2935454102944126e-01, 4.2558393133802180e-01, 4.2183270922949573e-01, + 4.1810064983784795e-01, 4.1438753404089090e-01, 4.1069314827018799e-01, + 4.0701728432947315e-01, 4.0335973922111429e-01, 3.9972031498019700e-01, + 3.9609881851583223e-01, 3.9249506145931540e-01, 3.8890886001878855e-01, + 3.8534003484007706e-01, 3.8178841087339344e-01, 3.7825381724561896e-01, + 3.7473608713789086e-01, 3.7123505766823922e-01, 3.6775056977903225e-01, + 3.6428246812900372e-01, 3.6083060098964775e-01, 3.5739482014578022e-01, + 3.5397498080007656e-01, 3.5057094148140588e-01, 3.4718256395679348e-01, + 3.4380971314685055e-01, 3.4045225704452164e-01, 3.3711006663700588e-01, + 3.3378301583071823e-01, 3.3047098137916342e-01, 3.2717384281360129e-01, + 3.2389148237639104e-01, 3.2062378495690530e-01, 3.1737063802991350e-01, + 3.1413193159633707e-01, 3.1090755812628634e-01, 3.0769741250429189e-01, + 3.0450139197664983e-01, 3.0131939610080288e-01, 2.9815132669668531e-01, + 2.9499708779996164e-01, 2.9185658561709499e-01, 2.8872972848218270e-01, + 2.8561642681550159e-01, 2.8251659308370741e-01, 2.7943014176163772e-01, + 2.7635698929566810e-01, 2.7329705406857691e-01, 2.7025025636587519e-01, + 2.6721651834356114e-01, 2.6419576399726080e-01, 2.6118791913272082e-01, + 2.5819291133761890e-01, 2.5521066995466168e-01, 2.5224112605594190e-01, + 2.4928421241852824e-01, 2.4633986350126363e-01, 2.4340801542275012e-01, + 2.4048860594050039e-01, 2.3758157443123795e-01, 2.3468686187232990e-01, + 2.3180441082433859e-01, 2.2893416541468023e-01, 2.2607607132238020e-01, + 2.2323007576391746e-01, 2.2039612748015194e-01, 2.1757417672433113e-01, + 2.1476417525117358e-01, 2.1196607630703015e-01, 2.0917983462112499e-01, + 2.0640540639788071e-01, 2.0364274931033485e-01, 2.0089182249465656e-01, + 1.9815258654577511e-01, 1.9542500351413428e-01, 1.9270903690358912e-01, + 1.9000465167046496e-01, 1.8731181422380025e-01, 1.8463049242679927e-01, + 1.8196065559952254e-01, 1.7930227452284767e-01, 1.7665532144373500e-01, + 1.7401977008183875e-01, 1.7139559563750595e-01, 1.6878277480121151e-01, + 1.6618128576448205e-01, 1.6359110823236570e-01, 1.6101222343751107e-01, + 1.5844461415592431e-01, 1.5588826472447920e-01, 1.5334316106026283e-01, + 1.5080929068184568e-01, 1.4828664273257453e-01, 1.4577520800599403e-01, + 1.4327497897351341e-01, 1.4078594981444470e-01, 1.3830811644855071e-01, + 1.3584147657125373e-01, 1.3338602969166913e-01, 1.3094177717364430e-01, + 1.2850872227999952e-01, 1.2608687022018586e-01, 1.2367622820159654e-01, + 1.2127680548479021e-01, 1.1888861344290998e-01, 1.1651166562561080e-01, + 1.1414597782783835e-01, 1.1179156816383801e-01, 1.0944845714681163e-01, + 1.0711666777468364e-01, 1.0479622562248690e-01, 1.0248715894193508e-01, + 1.0018949876880981e-01, 9.7903279038862284e-02, 9.5628536713008819e-02, + 9.3365311912690860e-02, 9.1113648066373634e-02, 8.8873592068275789e-02, + 8.6645194450557961e-02, 8.4428509570353374e-02, 8.2223595813202863e-02, + 8.0030515814663056e-02, 7.7849336702096039e-02, 7.5680130358927067e-02, + 7.3522973713981268e-02, 7.1377949058890375e-02, 6.9245144397006769e-02, + 6.7124653827788497e-02, 6.5016577971242842e-02, 6.2921024437758113e-02, + 6.0838108349539864e-02, 5.8767952920933758e-02, 5.6710690106202902e-02, + 5.4666461324888914e-02, 5.2635418276792176e-02, 5.0617723860947761e-02, + 4.8613553215868521e-02, 4.6623094901930368e-02, 4.4646552251294443e-02, + 4.2684144916474431e-02, 4.0736110655940933e-02, 3.8802707404526113e-02, + 3.6884215688567284e-02, 3.4980941461716084e-02, 3.3093219458578522e-02, + 3.1221417191920245e-02, 2.9365939758133314e-02, 2.7527235669603082e-02, + 2.5705804008548896e-02, 2.3902203305795882e-02, 2.2117062707308864e-02, + 2.0351096230044517e-02, 1.8605121275724643e-02, 1.6880083152543166e-02, + 1.5177088307935325e-02, 1.3497450601739880e-02, 1.1842757857907888e-02, + 1.0214971439701471e-02, 8.6165827693987316e-03, 7.0508754713732268e-03, + 5.5224032992509968e-03, 4.0379725933630305e-03, 2.6090727461021627e-03, + 1.2602859304985975e-03}; + +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/_randomgen/core_prng/src/distributions/ziggurat_constants.h b/_randomgen/core_prng/src/distributions/ziggurat_constants.h new file mode 100644 index 000000000000..17eccec0fb72 --- /dev/null +++ b/_randomgen/core_prng/src/distributions/ziggurat_constants.h @@ -0,0 +1,1196 @@ +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, +}; diff --git a/_randomgen/core_prng/src/pcg64/pcg64.c b/_randomgen/core_prng/src/pcg64/pcg64.c new file mode 100644 index 000000000000..ba8ce4124cfd --- /dev/null +++ b/_randomgen/core_prng/src/pcg64/pcg64.c @@ -0,0 +1,92 @@ +/* + * PCG64 Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * Copyright 2015 Robert Kern + * + * 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 + */ + +#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); \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h new file mode 100644 index 000000000000..441ebe87d56e --- /dev/null +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -0,0 +1,237 @@ +/* + * PCG64 Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * Copyright 2015 Robert Kern + * + * 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 + */ + +#ifndef PCG64_H_INCLUDED +#define PCG64_H_INCLUDED 1 + +#ifdef _WIN32 +#ifndef _INTTYPES +#include "../common/stdint.h" +#endif +#define inline __forceinline +#else +#include +#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 __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; + + 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_128 \ + PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL) +#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) } + + inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) + { + return (value >> rot) | (value << ((- rot) & 63)); + } + +#ifdef PCG_EMULATED_128BIT_MATH + + 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; + } + + inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t* z1, uint64_t* z0) { + 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); + } + + 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; + } + + 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); + } + + inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) + { + return pcg_rotr_64(state.high ^ state.low, + state.high >> 58u); + } + + 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 & 0x800000000000ULL; + 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); + } + +#else /* PCG_EMULATED_128BIT_MATH */ + + inline void pcg_setseq_128_step_r(pcg_state_setseq_128* rng) + { + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; + } + + 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); + } + + 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 */ + + + 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); + } + + 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); + + 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 + +#endif /* PCG64_H_INCLUDED */ + + +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) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = pcg64_random_r(state->pcg_state); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next & 0xffffffff); + return (uint32_t)(next >> 32); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024.c new file mode 100644 index 000000000000..a7d1fe0fa9aa --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.c @@ -0,0 +1,31 @@ +#include "xorshift1024.h" + +/* This is the jump function for the generator. It is equivalent + to 2^512 calls to next(); it can be used to generate 2^512 + non-overlapping subsequences for parallel computations. */ + +extern inline uint64_t xorshift1024_next(xorshift1024_state *state); +extern inline uint64_t xorshift1024_next64(xorshift1024_state *state); +extern inline uint32_t xorshift1024_next32(xorshift1024_state *state); + +void xorshift1024_jump(xorshift1024_state *state) { + static const uint64_t JUMP[] = { + 0x84242f96eca9c41d, 0xa3c65b8776f96855, 0x5b34a39f070b5837, + 0x4489affce4f31a1e, 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, + 0x3659132bb12fea70, 0xaac17d8efa43cab8, 0xc4cb815590989b13, + 0x5ee975283d71c93b, 0x691548c86c1bd540, 0x7910c41d10a1e6a5, + 0x0b5fc64563b3e2a8, 0x047f7684e9fc949d, 0xb99181f2d8f685ca, + 0x284600e3f30e38c3}; + + uint64_t t[16] = {0}; + for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) + for (int j = 0; j < 16; j++) + t[j] ^= state->s[(j + state->p) & 15]; + xorshift1024_next(state); + } + + for (int j = 0; j < 16; j++) + state->s[(j + state->p) & 15] = t[j]; +} diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h new file mode 100644 index 000000000000..141010d9d5e9 --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h @@ -0,0 +1,33 @@ +#include + +typedef struct s_xorshift1024_state { + uint64_t s[16]; + int p; + int has_uint32; + uint32_t uinteger; +} xorshift1024_state; + +static inline uint64_t xorshift1024_next(xorshift1024_state *state) { + const uint64_t s0 = state->s[state->p]; + uint64_t s1 = state->s[state->p = ((state->p) + 1) & 15]; + s1 ^= s1 << 31; // a + state->s[state->p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c + return state->s[state->p] * 0x9e3779b97f4a7c13; +} + +static inline uint64_t xorshift1024_next64(xorshift1024_state *state) { + return xorshift1024_next(state); +} + +static inline uint32_t xorshift1024_next32(xorshift1024_state *state) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = xorshift1024_next(state); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next & 0xffffffff); + return (uint32_t)(next >> 32); +} + +void xorshift1024_jump(xorshift1024_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c b/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c new file mode 100644 index 000000000000..ed1cf8d6ef77 --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c @@ -0,0 +1,69 @@ +/* Written in 2017 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 . */ + +#include +#include + +/* NOTE: as of 2017-10-08, this generator has a different multiplier (a + fixed-point representation of the golden ratio), which eliminates + linear dependencies from one of the lowest bits. The previous + multiplier was 1181783497276652981 (M_8 in the paper). If you need to + tell apart the two generators, you can refer to this generator as + xorshift1024*φ and to the previous one as xorshift1024*M_8. + + This is a fast, high-quality generator. If 1024 bits of state are too + much, try a xoroshiro128+ generator. + + Note that the two lowest bits of this generator are LFSRs of degree + 1024, and thus will fail binary rank tests. The other bits needs a much + higher degree to be represented as LFSRs. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +uint64_t s[16]; +int p; + +uint64_t next(void) { + const uint64_t s0 = s[p]; + uint64_t s1 = s[p = (p + 1) & 15]; + s1 ^= s1 << 31; // a + s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c + return s[p] * 0x9e3779b97f4a7c13; +} + + +/* This is the jump function for the generator. It is equivalent + to 2^512 calls to next(); it can be used to generate 2^512 + non-overlapping subsequences for parallel computations. */ + +void jump(void) { + static const uint64_t JUMP[] = { 0x84242f96eca9c41d, + 0xa3c65b8776f96855, 0x5b34a39f070b5837, 0x4489affce4f31a1e, + 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, 0x3659132bb12fea70, + 0xaac17d8efa43cab8, 0xc4cb815590989b13, 0x5ee975283d71c93b, + 0x691548c86c1bd540, 0x7910c41d10a1e6a5, 0x0b5fc64563b3e2a8, + 0x047f7684e9fc949d, 0xb99181f2d8f685ca, 0x284600e3f30e38c3 + }; + + uint64_t t[16] = { 0 }; + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for(int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) + for(int j = 0; j < 16; j++) + t[j] ^= s[(j + p) & 15]; + next(); + } + + for(int j = 0; j < 16; j++) + s[(j + p) & 15] = t[j]; +} \ No newline at end of file diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx new file mode 100644 index 000000000000..22892058ede0 --- /dev/null +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -0,0 +1,174 @@ +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + +cdef extern from "src/xorshift1024/xorshift1024.h": + + struct s_xorshift1024_state: + uint64_t s[16] + int p + int has_uint32 + uint32_t uinteger + + ctypedef s_xorshift1024_state xorshift1024_state + + uint64_t xorshift1024_next64(xorshift1024_state *state) nogil + uint64_t xorshift1024_next32(xorshift1024_state *state) nogil + void xorshift1024_jump(xorshift1024_state *state) + +cdef uint64_t xorshift1024_uint64(void* st):# nogil: + return xorshift1024_next64(st) + +cdef uint32_t xorshift1024_uint32(void *st) nogil: + return xorshift1024_next32( st) + +cdef double xorshift1024_double(void* st) nogil: + return uint64_to_double(xorshift1024_next64(st)) + +cdef class XorShift1024: + """ + Prototype Core PRNG using xorshift1024 + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `get_state` and `set_state`. Designed + for use in a `RandomGenerator` object. + """ + cdef xorshift1024_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(xorshift1024_state)) + self._prng = malloc(sizeof(prng_t)) + self.seed(seed) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &xorshift1024_uint64 + self._prng.next_uint32 = &xorshift1024_uint32 + self._prng.next_double = &xorshift1024_double + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng) + + def _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return xorshift1024_next64(self.rng_state) + elif bits == 32: + return xorshift1024_next32(self.rng_state) + else: + raise ValueError('bits must be 32 or 64') + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(32) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 16) + for i in range(16): + self.rng_state.s[i] = int(state[i]) + self.rng_state.p = 0 + self._reset_state_variables() + + def jump(self): + xorshift1024_jump(self.rng_state) + + @property + def state(self): + """Get or set the PRNG state""" + s = np.empty(16, dtype=np.uint64) + for i in range(16): + s[i] = self.rng_state.s[i] + return {'prng': self.__class__.__name__, + 'state': {'s':s,'p':self.rng_state.p}, + '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') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + for i in range(16): + self.rng_state.s[i] = value['state']['s'][i] + self.rng_state.p = value['state']['p'] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 7fe81af01c25..b15f59830114 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,6 +1,6 @@ from core_prng.generator import RandomGenerator -from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937 +from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, XorShift1024 print(RandomGenerator().random_integer()) print(RandomGenerator(Xoroshiro128()).random_integer()) @@ -48,3 +48,8 @@ print(rg.random_integer()) print(rg.random_integer(32)) print(rg.random_sample()) + +rg = RandomGenerator(XorShift1024()) +state = rg.state +print(state) +rg.state = state diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 3e06920e8844..babb7bbbbd85 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -28,6 +28,13 @@ join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'mt19937')]), + Extension("core_prng.pcg64", + ["core_prng/pcg64.pyx", + join(MOD_DIR, 'src', 'pcg64', + 'pcg64.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'pcg64')]), + Extension("core_prng.splitmix64", ["core_prng/splitmix64.pyx", join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], @@ -44,6 +51,12 @@ 'xoroshiro128.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'xoroshiro128')]), + Extension("core_prng.xorshift1024", + ["core_prng/xorshift1024.pyx", + join(MOD_DIR, 'src', 'xorshift1024', + 'xorshift1024.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'xorshift1024')]), Extension("core_prng.generator", ["core_prng/generator.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], From 6b81fa0a1ebdd769dcd3ce82ef98dcbb0fa17767 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 4 Mar 2018 23:29:00 +0000 Subject: [PATCH 021/138] ENH: Add advance and jump to PCG64 Add advance and jump Clean other PRNGs --- _randomgen/TODO.md | 8 +++--- _randomgen/core_prng/common.pxd | 22 ++++++++++++++++ _randomgen/core_prng/generator.pyx | 1 + _randomgen/core_prng/mt19937.pyx | 16 ++++++++++-- _randomgen/core_prng/pcg64.pyx | 26 ++++++++++++++----- _randomgen/core_prng/splitmix64.pyx | 16 ++++++++++-- .../core_prng/src/distributions/binomial.h | 0 .../src/distributions/distributions.h | 22 ++++++++++++++++ _randomgen/core_prng/src/pcg64/pcg64.c | 15 ++++++++++- _randomgen/core_prng/src/pcg64/pcg64.h | 8 +++++- _randomgen/core_prng/threefry.pyx | 7 +++-- _randomgen/core_prng/xoroshiro128.pyx | 3 +++ _randomgen/core_prng/xorshift1024.pyx | 7 +++-- _randomgen/demo.py | 10 +++++-- 14 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 _randomgen/core_prng/src/distributions/binomial.h diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index fac0a525c94d..b374e3a753ff 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -1,20 +1,19 @@ # TODO 2. Add dSFMT -5. Augment state to have binomial structure 6. Port over 0 parameter distributions * standard exponential ziggurat float * standard normal ziggurat * standard normal ziggurat float 7. Remove SplitMix64 as an external generator 8. Restore ability to use `out` in core distributions -10. Seed/Inc for PCG64 -11. Advance/Jump for PCG64 12. Key/Counter for ThreeFry +13. Simplify state ## Done 1. Add PCG64 3. Add xorshift2014 4. Augment state to include has_gauss and gauss +5. Augment state to have binomial structure 6. Port over 0 parameter distributions * standard exponential ziggurat * standard exponential float @@ -22,7 +21,8 @@ * standard normal float * standard gamma - Not implement: This is a 1 param * standard gamma float - Not implement: This is a 1 param - 9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump +10. Seed/Inc for PCG64 +11. Advance/Jump for PCG64 0. NOT IMPLEMENTABLE due to limits on inheritance in Cython: Use inheritance to simplify CorePRNG structure. The natural base is xoroshiro128. diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index b761cc037658..c8b469cc52bc 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -5,6 +5,27 @@ cdef extern from "src/distributions/distributions.h": ctypedef float (*random_float_0)(void *st) nogil + cdef struct s_binomial_t: + int has_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; + + ctypedef s_binomial_t binomial_t + cdef struct prng: void *state uint64_t (*next_uint64)(void *st) @@ -14,6 +35,7 @@ cdef extern from "src/distributions/distributions.h": double gauss int has_gauss_f float gauss_f + binomial_t *binomial ctypedef prng prng_t diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 29b364270ade..671fc9080330 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -2,6 +2,7 @@ import numpy as np cimport numpy as np from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * +from libc.stdlib cimport malloc, free cimport numpy as np import numpy as np diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 6c2f4c5786e2..0cbf3e133733 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -56,6 +56,7 @@ cdef class MT19937: def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -68,6 +69,7 @@ cdef class MT19937: def __dealloc__(self): free(self.rng_state) + free(self._prng.binomial) free(self._prng) # Pickling support: @@ -82,10 +84,15 @@ cdef class MT19937: (self.state['prng'],), self.state) - def __random_integer(self): + def __random_integer(self, bits=64): """ 64-bit Random Integers from the PRNG + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + Returns ------- rv : int @@ -95,7 +102,12 @@ cdef class MT19937: ----- Testing only """ - return mt19937_next64(self.rng_state) + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 543202b1293e..08d52351bd66 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -33,6 +33,7 @@ cdef extern from "src/pcg64/pcg64.h": uint64_t pcg64_next64(pcg64_state *state) nogil uint64_t pcg64_next32(pcg64_state *state) nogil void pcg64_jump(pcg64_state *state) + void pcg64_advance(pcg64_state *state, uint64_t *step) cdef uint64_t pcg64_uint64(void* st):# nogil: @@ -62,20 +63,18 @@ cdef class PCG64: cdef prng_t *_prng cdef public object _prng_capsule - def __init__(self, seed=None): + def __init__(self, seed=None, inc=1): self.rng_state = malloc(sizeof(pcg64_state)) self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) self._prng = malloc(sizeof(prng_t)) - self.seed(seed) + self._prng.binomial = malloc(sizeof(binomial_t)) + self.seed(seed, inc) self._prng.state = self.rng_state self._prng.next_uint64 = &pcg64_uint64 self._prng.next_uint32 = &pcg64_uint32 self._prng.next_double = &pcg64_double - self.rng_state.pcg_state.inc.high = 0 - self.rng_state.pcg_state.inc.low = 1 - cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) @@ -93,6 +92,7 @@ cdef class PCG64: def __dealloc__(self): free(self.rng_state) + free(self._prng.binomial) free(self._prng) def _reset_state_variables(self): @@ -124,7 +124,7 @@ cdef class PCG64: else: raise ValueError('bits must be 32 or 64') - def seed(self, seed=None): + def seed(self, seed=None, inc=1): """ seed(seed=None, stream=None) @@ -138,6 +138,8 @@ cdef class PCG64: ---------- seed : int, optional Seed for ``RandomState``. + inc : int, optional + Increment to use for PCG stream Raises ------ @@ -156,6 +158,8 @@ cdef class PCG64: state = entropy.seed_by_array(seed, 2) self.rng_state.pcg_state.state.high = int(state[0]) self.rng_state.pcg_state.state.low = int(state[1]) + self.rng_state.pcg_state.inc.high = inc // 2**64 + self.rng_state.pcg_state.inc.low = inc % 2**64 self._reset_state_variables() @property @@ -186,3 +190,13 @@ cdef class PCG64: self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] + + def advance(self, step): + cdef np.ndarray delta = np.empty(2,dtype=np.uint64) + delta[0] = step // 2**64 + delta[1] = step % 2**64 + pcg64_advance(self.rng_state, delta.data) + return self + + def jump(self): + return self.advance(2**64) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 515f68884bb8..4ca39c7bbcc3 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -53,6 +53,7 @@ cdef class SplitMix64: def __init__(self, seed=None): self.rng_state = malloc(sizeof(splitmix64_state)) self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -65,6 +66,7 @@ cdef class SplitMix64: def __dealloc__(self): free(self.rng_state) + free(self._prng.binomial) free(self._prng) # Pickling support: @@ -84,10 +86,15 @@ cdef class SplitMix64: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - def __random_integer(self): + def __random_integer(self, bits=64): """ 64-bit Random Integers from the PRNG + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + Returns ------- rv : int @@ -97,7 +104,12 @@ cdef class SplitMix64: ----- Testing only """ - return splitmix64_next64(self.rng_state) + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/src/distributions/binomial.h b/_randomgen/core_prng/src/distributions/binomial.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 7c029fe60e02..757029074285 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -20,6 +20,27 @@ typedef int bool; typedef double (*random_double_0)(void *st); typedef float (*random_float_0)(void *st); +typedef struct s_binomial_t +{ + 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; +} binomial_t; + typedef struct prng { void *state; uint64_t (*next_uint64)(void *st); @@ -29,6 +50,7 @@ typedef struct prng { double gauss; int has_gauss_f; float gauss_f; + binomial_t *binomial; } prng_t; float random_float(prng_t *prng_state); diff --git a/_randomgen/core_prng/src/pcg64/pcg64.c b/_randomgen/core_prng/src/pcg64/pcg64.c index ba8ce4124cfd..8f29947e0047 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.c +++ b/_randomgen/core_prng/src/pcg64/pcg64.c @@ -89,4 +89,17 @@ pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult, #endif extern inline uint64_t pcg64_next64(pcg64_state *state); -extern inline uint32_t pcg64_next32(pcg64_state *state); \ No newline at end of file +extern inline uint32_t pcg64_next32(pcg64_state *state); + +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) +extern void pcg64_advance(pcg64_state *state, pcg128_t step) { + pcg64_advance_r(state->pcg_state, step); +} +#else +extern void pcg64_advance(pcg64_state *state, uint64_t *step) { + pcg128_t delta; + delta.high = step[0]; + delta.low = step[1]; + pcg64_advance_r(state->pcg_state, delta); +} +#endif \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h index 441ebe87d56e..acb6417b86ed 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -234,4 +234,10 @@ static inline uint32_t pcg64_next32(pcg64_state *state) { state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); return (uint32_t)(next >> 32); -} \ No newline at end of file +} + +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) +void pcg64_advance(pcg64_state *state, pcg128_t step); +#else +void pcg64_advance(pcg64_state *state, uint64_t *step); +#endif \ No newline at end of file diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index ede7e7caefbb..010fe39f8007 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -68,6 +68,7 @@ cdef class ThreeFry: self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -94,6 +95,7 @@ cdef class ThreeFry: free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) + free(self._prng.binomial) free(self._prng) def _reset_state_variables(self): @@ -122,9 +124,9 @@ cdef class ThreeFry: Testing only """ if bits == 64: - return threefry_next64(self.rng_state) + return self._prng.next_uint64(self._prng.state) elif bits == 32: - return threefry_next32(self.rng_state) + return self._prng.next_uint32(self._prng.state) else: raise ValueError('bits must be 32 or 64') @@ -200,6 +202,7 @@ cdef class ThreeFry: def jump(self): """Jump the state as-if 2**128 draws have been made""" threefry_jump(self.rng_state) + return self def advance(self, step): """Advance the state as-if a specific number of draws have been made""" diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 69ce93c31f84..38d46b1d7eb8 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -55,6 +55,7 @@ cdef class Xoroshiro128: def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -79,6 +80,7 @@ cdef class Xoroshiro128: def __dealloc__(self): free(self.rng_state) + free(self._prng.binomial) free(self._prng) def _reset_state_variables(self): @@ -146,6 +148,7 @@ cdef class Xoroshiro128: def jump(self): xoroshiro128_jump(self.rng_state) + return self @property def state(self): diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 22892058ede0..0ca23b0a3e98 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -55,6 +55,7 @@ cdef class XorShift1024: def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -79,6 +80,7 @@ cdef class XorShift1024: def __dealloc__(self): free(self.rng_state) + free(self._prng.binomial) free(self._prng) def _reset_state_variables(self): @@ -104,9 +106,9 @@ cdef class XorShift1024: Testing only """ if bits == 64: - return xorshift1024_next64(self.rng_state) + return self._prng.next_uint64(self._prng.state) elif bits == 32: - return xorshift1024_next32(self.rng_state) + return self._prng.next_uint32(self._prng.state) else: raise ValueError('bits must be 32 or 64') @@ -147,6 +149,7 @@ cdef class XorShift1024: def jump(self): xorshift1024_jump(self.rng_state) + return self @property def state(self): diff --git a/_randomgen/demo.py b/_randomgen/demo.py index b15f59830114..47353f9ae6da 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,8 +1,8 @@ from core_prng.generator import RandomGenerator -from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, XorShift1024 +from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, XorShift1024, PCG64 -print(RandomGenerator().random_integer()) +print(RandomGenerator().random_integer(32)) print(RandomGenerator(Xoroshiro128()).random_integer()) print(RandomGenerator(ThreeFry()).random_integer()) print(RandomGenerator(SplitMix64()).random_integer()) @@ -22,6 +22,7 @@ print(rg.state) import numpy as np + a = rg.random_sample((1, 1), dtype=np.float32) print(a) print(a.dtype) @@ -53,3 +54,8 @@ state = rg.state print(state) rg.state = state + +rg = RandomGenerator(PCG64()) +state = rg.state +print(state) +rg.state = state From e150e1a42ea1588ac53ab82d7c7e891d3892d1bd Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 10:21:18 +0000 Subject: [PATCH 022/138] ENH: Add Philox Add philox as a core PRNG --- _randomgen/core_prng/__init__.py | 1 + _randomgen/core_prng/mt19937.pyx | 5 + _randomgen/core_prng/pcg64.pyx | 6 + _randomgen/core_prng/philox.pyx | 232 +++++++++++++++++++++++ _randomgen/core_prng/splitmix64.pyx | 6 + _randomgen/core_prng/src/philox/philox.c | 29 +++ _randomgen/core_prng/src/philox/philox.h | 183 ++++++++++++++++++ _randomgen/core_prng/threefry.pyx | 11 +- _randomgen/core_prng/xoroshiro128.pyx | 5 + _randomgen/core_prng/xorshift1024.pyx | 5 + _randomgen/demo.py | 10 +- _randomgen/setup.py | 5 + 12 files changed, 492 insertions(+), 6 deletions(-) create mode 100644 _randomgen/core_prng/philox.pyx create mode 100644 _randomgen/core_prng/src/philox/philox.c create mode 100644 _randomgen/core_prng/src/philox/philox.h diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index c6123e023d03..1e528323b1d4 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -5,6 +5,7 @@ from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import XorShift1024 +from .philox import Philox __all__ = ['RandomGenerator', 'SplitMix64', 'PCG64', 'Xoroshiro128', 'ThreeFry', 'MT19937', 'XorShift1024'] diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 0cbf3e133733..9e6b936efb5a 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -109,6 +109,11 @@ cdef class MT19937: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + def seed(self, seed=None): """ seed(seed=None, stream=None) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 08d52351bd66..4a3dcfc4b514 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -124,6 +124,12 @@ cdef class PCG64: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + + def seed(self, seed=None, inc=1): """ seed(seed=None, stream=None) diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx new file mode 100644 index 000000000000..111d702be680 --- /dev/null +++ b/_randomgen/core_prng/philox.pyx @@ -0,0 +1,232 @@ +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + +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[4]; + int has_uint32 + uint32_t uinteger + + ctypedef s_philox_state philox_state + + uint64_t philox_next64(philox_state *state) nogil + uint64_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( st) + +cdef uint32_t philox_uint32(void *st) nogil: + return philox_next32( st) + +cdef double philox_double(void*st) nogil: + return uint64_to_double(philox_next64( st)) + +cdef class Philox: + """ + Prototype Core PRNG using philox + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `state`. Designed for use in + a `RandomGenerator` object. + """ + cdef philox_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(philox_state)) + self.rng_state.ctr = malloc( + sizeof(philox4x64_ctr_t)) + self.rng_state.key = malloc( + sizeof(philox4x64_key_t)) + self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) + self.seed(seed) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &philox_uint64 + self._prng.next_uint32 = &philox_uint32 + self._prng.next_double = &philox_double + + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New( self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state.ctr) + free(self.rng_state.key) + free(self.rng_state) + free(self._prng.binomial) + free(self._prng) + + def _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + self.rng_state.buffer_pos = 4 + for i in range(4): + self.rng_state.buffer[i] = 0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') + + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + # TODO: Need to be able to set the key and counter directly + for i in range(4): + self.rng_state.ctr.v[i] = 0 + self.rng_state.key.v[0] = state[0] + self.rng_state.key.v[1] = state[1] + self._reset_state_variables() + + @property + def state(self): + """Get or set the PRNG state""" + ctr = np.empty(4, dtype=np.uint64) + key = np.empty(2, dtype=np.uint64) + buffer = np.empty(4, dtype=np.uint64) + for i in range(4): + ctr[i] = self.rng_state.ctr.v[i] + buffer[i] = self.rng_state.buffer[i] + if i < 2: + key[i] = self.rng_state.key.v[i] + + state = {'ctr': ctr, 'key': key} + return {'prng': 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') + prng = value.get('prng', '') + if prng != 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] = value['state']['ctr'][i] + self.rng_state.buffer[i] = value['buffer'][i] + if i < 2: + self.rng_state.key.v[i] = value['state']['key'][i] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] + self.rng_state.buffer_pos = value['buffer_pos'] + + def jump(self): + """Jump the state as-if 2**128 draws have been made""" + philox_jump(self.rng_state) + return self + + def advance(self, step): + """Advance the state as-if a specific number of draws have been made""" + cdef np.ndarray step_a = np.zeros(4, dtype=np.uint64) + if step >= 2 ** 256 or step < 0: + raise ValueError('step must be between 0 and 2**256-1') + loc = 0 + while step > 0: + step_a[loc] = step % 2 ** 64 + step >>= 64 + loc += 1 + philox_advance( step_a.data, self.rng_state) diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx index 4ca39c7bbcc3..fbc41544cd2f 100644 --- a/_randomgen/core_prng/splitmix64.pyx +++ b/_randomgen/core_prng/splitmix64.pyx @@ -111,6 +111,12 @@ cdef class SplitMix64: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + + def seed(self, seed=None): """ seed(seed=None, stream=None) diff --git a/_randomgen/core_prng/src/philox/philox.c b/_randomgen/core_prng/src/philox/philox.c new file mode 100644 index 000000000000..06eaa3400ebb --- /dev/null +++ b/_randomgen/core_prng/src/philox/philox.c @@ -0,0 +1,29 @@ +#include "philox.h" + +extern inline uint64_t philox_next64(philox_state *state); + +extern inline uint64_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/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h new file mode 100644 index 000000000000..1c6baf3075e5 --- /dev/null +++ b/_randomgen/core_prng/src/philox/philox.h @@ -0,0 +1,183 @@ +#include + +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 __inline struct r123array2x64 +_philox4x64bumpkey(struct r123array2x64 key) { + key.v[0] += (0x9E3779B97F4A7C15ULL); + key.v[1] += (0xBB67AE8584CAA73BULL); + return key; +} + +#ifdef _WIN32 +/* TODO: This isn't correct for many platforms */ +#include +#pragma intrinsic(_umul128) + +static __inline uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { + return _umul128(a, b, hip); +} +#else +static 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; +} +#endif + +// static __inline _forceinline struct r123array4x64 _philox4x64round(struct +// r123array4x64 ctr, struct r123array2x64 key); + +static __inline _forceinline 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 __inline philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { + return uk; +} +// static __inline _forceinline philox4x64_ctr_t philox4x64_R(unsigned int R, +// philox4x64_ctr_t ctr, philox4x64_key_t key); + +static __inline _forceinline 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[4]; + int has_uint32; + uint32_t uinteger; +} philox_state; + +static inline uint64_t philox_next(philox_state *state) { + /* TODO: This 4 should be a constant somewhere */ + if (state->buffer_pos < 4) { + uint64_t out = state->buffer[state->buffer_pos]; + state->buffer_pos++; + return out; + } + /* generate 4 new uint64_t */ + int i; + philox4x64_ctr_t ct; + 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 inline uint64_t philox_next64(philox_state *state) { + return philox_next(state); +} + +static inline uint64_t philox_next32(philox_state *state) { + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + uint64_t next = philox_next(state); + + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next & 0xffffffff); + + return (uint32_t)(next >> 32); +} + +extern void philox_jump(philox_state *state); + +extern void philox_advance(uint64_t *step, philox_state *state); diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 010fe39f8007..3c669a439ca2 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -21,8 +21,8 @@ cdef extern from "src/threefry/threefry.h": ctypedef r123array4x64 threefry4x64_ctr_t struct s_threefry_state: - threefry4x64_key_t *ctr; - threefry4x64_ctr_t *key; + threefry4x64_ctr_t *ctr; + threefry4x64_key_t *key; int buffer_pos; uint64_t buffer[4]; int has_uint32 @@ -130,6 +130,11 @@ cdef class ThreeFry: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + def seed(self, seed=None): """ seed(seed=None, stream=None) @@ -158,7 +163,7 @@ cdef class ThreeFry: state = random_entropy(8, 'fallback') state = state.view(np.uint64) else: - state = entropy.seed_by_array(seed, 2) + state = entropy.seed_by_array(seed, 4) # TODO: Need to be able to set the key and counter directly for i in range(4): self.rng_state.ctr.v[i] = 0 diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 38d46b1d7eb8..0c1f90998d9d 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -112,6 +112,11 @@ cdef class Xoroshiro128: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + def seed(self, seed=None): """ seed(seed=None, stream=None) diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 0ca23b0a3e98..b7b6fc42349f 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -112,6 +112,11 @@ cdef class XorShift1024: else: raise ValueError('bits must be 32 or 64') + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + def seed(self, seed=None): """ seed(seed=None, stream=None) diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 47353f9ae6da..5ab97f01fb63 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,7 +1,7 @@ +from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, \ + XorShift1024, PCG64, Philox from core_prng.generator import RandomGenerator -from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, XorShift1024, PCG64 - print(RandomGenerator().random_integer(32)) print(RandomGenerator(Xoroshiro128()).random_integer()) print(RandomGenerator(ThreeFry()).random_integer()) @@ -22,7 +22,6 @@ print(rg.state) import numpy as np - a = rg.random_sample((1, 1), dtype=np.float32) print(a) print(a.dtype) @@ -59,3 +58,8 @@ state = rg.state print(state) rg.state = state + +rg = RandomGenerator(Philox()) +state = rg.state +print(state) +rg.state = state diff --git a/_randomgen/setup.py b/_randomgen/setup.py index babb7bbbbd85..46cbe56eb7ca 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -28,6 +28,11 @@ join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'mt19937')]), + Extension("core_prng.philox", + ["core_prng/philox.pyx", + join(MOD_DIR, 'src', 'philox', 'philox.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'philox')]), Extension("core_prng.pcg64", ["core_prng/pcg64.pyx", join(MOD_DIR, 'src', 'pcg64', From d6d3ac995f001695de1b81328f77daaf3cf4cf2a Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 10:27:38 +0000 Subject: [PATCH 023/138] CLN: Remove splitmix64 as a visible PRNG Retain splitmix64 for internal use Default is now xoroshiro128 --- _randomgen/TODO.md | 2 +- _randomgen/core_prng/__init__.py | 7 +- _randomgen/core_prng/generator.pyx | 4 +- _randomgen/core_prng/pickle.py | 10 +- _randomgen/core_prng/splitmix64.pyx | 172 -------------------------- _randomgen/core_prng/xorshift1024.pyx | 2 +- _randomgen/demo.py | 10 +- _randomgen/setup.py | 6 - 8 files changed, 17 insertions(+), 196 deletions(-) delete mode 100644 _randomgen/core_prng/splitmix64.pyx diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index b374e3a753ff..2be06b8ec4bf 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -4,7 +4,6 @@ * standard exponential ziggurat float * standard normal ziggurat * standard normal ziggurat float -7. Remove SplitMix64 as an external generator 8. Restore ability to use `out` in core distributions 12. Key/Counter for ThreeFry 13. Simplify state @@ -21,6 +20,7 @@ * standard normal float * standard gamma - Not implement: This is a 1 param * standard gamma float - Not implement: This is a 1 param +7. Remove SplitMix64 as an external generator 9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump 10. Seed/Inc for PCG64 11. Advance/Jump for PCG64 diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 1e528323b1d4..7f554c4d3f97 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,14 +1,13 @@ from .generator import RandomGenerator from .mt19937 import MT19937 from .pcg64 import PCG64 -from .splitmix64 import SplitMix64 from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 -from .xorshift1024 import XorShift1024 +from .xorshift1024 import Xorshift1024 from .philox import Philox -__all__ = ['RandomGenerator', 'SplitMix64', 'PCG64', 'Xoroshiro128', - 'ThreeFry', 'MT19937', 'XorShift1024'] +__all__ = ['RandomGenerator', 'PCG64', 'Xoroshiro128', + 'ThreeFry', 'MT19937', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 671fc9080330..1447e44783d1 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -15,7 +15,7 @@ try: except ImportError: from dummy_threading import Lock -from core_prng.splitmix64 import SplitMix64 +from core_prng.xoroshiro128 import Xoroshiro128 import core_prng.pickle np.import_array() @@ -50,7 +50,7 @@ cdef class RandomGenerator: def __init__(self, prng=None): if prng is None: - prng = SplitMix64() + prng = Xoroshiro128() self.__core_prng = prng capsule = prng._prng_capsule diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/core_prng/pickle.py index e3fede9210b4..d4e5a1f71d63 100644 --- a/_randomgen/core_prng/pickle.py +++ b/_randomgen/core_prng/pickle.py @@ -1,12 +1,16 @@ from .generator import RandomGenerator from .mt19937 import MT19937 -from .splitmix64 import SplitMix64 +from .pcg64 import PCG64 +from .philox import Philox from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 +from .xorshift1024 import Xorshift1024 -PRNGS = {'SplitMix64': SplitMix64, +PRNGS = {'MT19937': MT19937, + 'PCG64': PCG64, + 'Philox': Philox, 'ThreeFry': ThreeFry, - 'MT19937': MT19937, + 'Xorshift1024': Xorshift1024, 'Xoroshiro128': Xoroshiro128} diff --git a/_randomgen/core_prng/splitmix64.pyx b/_randomgen/core_prng/splitmix64.pyx deleted file mode 100644 index fbc41544cd2f..000000000000 --- a/_randomgen/core_prng/splitmix64.pyx +++ /dev/null @@ -1,172 +0,0 @@ -from libc.stdint cimport uint32_t, uint64_t -from libc.stdlib cimport malloc, free -from cpython.pycapsule cimport PyCapsule_New - -import numpy as np -cimport numpy as np - -from common cimport * -from core_prng.entropy import random_entropy -import core_prng.pickle -cimport entropy - -np.import_array() - -cdef extern from "src/splitmix64/splitmix64.h": - struct s_splitmix64_state: - uint64_t state - int has_uint32 - uint32_t uinteger - - ctypedef s_splitmix64_state splitmix64_state - - uint64_t splitmix64_next64(splitmix64_state *state) nogil - uint32_t splitmix64_next32(splitmix64_state *state) nogil - -cdef uint64_t splitmix64_uint64(void *st) nogil: - return splitmix64_next64( st) - -cdef uint32_t splitmix64_uint32(void *st) nogil: - return splitmix64_next32( st) - -cdef double splitmix64_double(void *st) nogil: - return uint64_to_double(splitmix64_uint64( st)) - -cdef class SplitMix64: - """ - Prototype Core PRNG using directly implemented version of SplitMix64. - - Parameters - ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 - - Notes - ----- - Exposes no user-facing API except `get_state` and `set_state`. Designed - for use in a `RandomGenerator` object. - """ - cdef splitmix64_state *rng_state - cdef prng_t *_prng - cdef public object _prng_capsule - - def __init__(self, seed=None): - self.rng_state = malloc(sizeof(splitmix64_state)) - self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) - self.seed(seed) - - self._prng.state = self.rng_state - self._prng.next_uint64 = &splitmix64_uint64 - self._prng.next_uint32 = &splitmix64_uint32 - self._prng.next_double = &splitmix64_double - - cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) - - def __dealloc__(self): - free(self.rng_state) - free(self._prng.binomial) - free(self._prng) - - # Pickling support: - def __getstate__(self): - return self.state - - def __setstate__(self, state): - self.state = state - - def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), - self.state) - - - def _reset_state_variables(self): - self.rng_state.has_uint32 = 0 - self.rng_state.uinteger = 0 - - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return self._prng.next_uint64(self._prng.state) - elif bits == 32: - return self._prng.next_uint32(self._prng.state) - else: - raise ValueError('bits must be 32 or 64') - - def _benchmark(self, Py_ssize_t cnt): - cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) - - - def seed(self, seed=None): - """ - seed(seed=None, stream=None) - - Seed the generator. - - 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, optional - Seed for ``RandomState``. - - Raises - ------ - ValueError - If seed values are out of range for the PRNG. - - """ - ub = 2 ** 64 - if seed is None: - try: - state = random_entropy(2) - except RuntimeError: - state = random_entropy(2, 'fallback') - state = state.view(np.uint64) - else: - state = entropy.seed_by_array(seed, 1) - self.rng_state.state = int(state[0]) - self._reset_state_variables() - - - @property - def state(self): - """Get or set the PRNG state""" - return {'prng': self.__class__.__name__, - 's': self.rng_state.state, - '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') - prng = value.get('prng', '') - if prng != self.__class__.__name__: - raise ValueError('state must be for a {0} ' - 'PRNG'.format(self.__class__.__name__)) - self.rng_state.state = value['s'] - self.rng_state.has_uint32 = value['has_uint32'] - self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index b7b6fc42349f..f693d5a7e208 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -34,7 +34,7 @@ cdef uint32_t xorshift1024_uint32(void *st) nogil: cdef double xorshift1024_double(void* st) nogil: return uint64_to_double(xorshift1024_next64(st)) -cdef class XorShift1024: +cdef class Xorshift1024: """ Prototype Core PRNG using xorshift1024 diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 5ab97f01fb63..0acf66da49b2 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,14 +1,10 @@ -from core_prng import SplitMix64, Xoroshiro128, ThreeFry, MT19937, \ - XorShift1024, PCG64, Philox +from core_prng import Xoroshiro128, ThreeFry, MT19937, \ + Xorshift1024, PCG64, Philox from core_prng.generator import RandomGenerator print(RandomGenerator().random_integer(32)) print(RandomGenerator(Xoroshiro128()).random_integer()) print(RandomGenerator(ThreeFry()).random_integer()) -print(RandomGenerator(SplitMix64()).random_integer()) -print(RandomGenerator(SplitMix64()).random_integer()) -print(RandomGenerator(SplitMix64(1)).random_integer()) -print(RandomGenerator(SplitMix64([1.0, 2.0])).random_integer()) print('\n' * 3) print('Check random_sample') @@ -49,7 +45,7 @@ print(rg.random_integer(32)) print(rg.random_sample()) -rg = RandomGenerator(XorShift1024()) +rg = RandomGenerator(Xorshift1024()) state = rg.state print(state) rg.state = state diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 46cbe56eb7ca..fcda70ad0d0c 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -39,12 +39,6 @@ 'pcg64.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'pcg64')]), - - Extension("core_prng.splitmix64", - ["core_prng/splitmix64.pyx", - join(MOD_DIR, 'src', 'splitmix64', 'splitmix64.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'splitmix64')]), Extension("core_prng.threefry", ["core_prng/threefry.pyx", join(MOD_DIR, 'src', 'threefry', 'threefry.c')], From 323616c8ca2b677371bc42bbf2fa0e8c86a4ebbb Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 12:21:08 +0000 Subject: [PATCH 024/138] BUG: Fix bugs which prevented building on Linux --- _randomgen/core_prng/pcg64.pyx | 53 +++-- _randomgen/core_prng/src/pcg64/pcg64.c | 103 ++++---- _randomgen/core_prng/src/pcg64/pcg64.h | 285 +++++++++++------------ _randomgen/core_prng/src/philox/philox.h | 12 +- _randomgen/demo.py | 17 ++ _randomgen/setup.py | 63 +++-- 6 files changed, 300 insertions(+), 233 deletions(-) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 4a3dcfc4b514..f728e2bbecc0 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -11,11 +11,26 @@ cimport entropy np.import_array() +IF PCG_EMULATED_MATH==1: + cdef extern from "src/pcg64/pcg64.h": + + ctypedef struct pcg128_t: + uint64_t high + uint64_t low +ELSE: + cdef extern from "inttypes.h": + ctypedef unsigned long long __uint128_t + + cdef extern from "src/pcg64/pcg64.h": + ctypedef __uint128_t pcg128_t + cdef extern from "src/pcg64/pcg64.h": ctypedef struct pcg128_t: uint64_t high - uint64_t low + uint64_t low + +cdef extern from "src/pcg64/pcg64.h": cdef struct pcg_state_setseq_128: pcg128_t state @@ -162,19 +177,27 @@ cdef class PCG64: state = state.view(np.uint64) else: state = entropy.seed_by_array(seed, 2) - self.rng_state.pcg_state.state.high = int(state[0]) - self.rng_state.pcg_state.state.low = int(state[1]) - self.rng_state.pcg_state.inc.high = inc // 2**64 - self.rng_state.pcg_state.inc.low = inc % 2**64 + IF PCG_EMULATED_MATH==1: + self.rng_state.pcg_state.state.high = int(state[0]) + self.rng_state.pcg_state.state.low = int(state[1]) + self.rng_state.pcg_state.inc.high = inc // 2**64 + self.rng_state.pcg_state.inc.low = inc % 2**64 + ELSE: + self.rng_state.pcg_state.state = state[0] * 2**64 + state[1] + self.rng_state.pcg_state.inc = inc self._reset_state_variables() @property def state(self): """Get or set the PRNG state""" - state = 2 **64 * self.rng_state.pcg_state.state.high - state += self.rng_state.pcg_state.state.low - inc = 2 **64 * self.rng_state.pcg_state.inc.high - inc += self.rng_state.pcg_state.inc.low + IF PCG_EMULATED_MATH==1: + state = 2 **64 * self.rng_state.pcg_state.state.high + state += self.rng_state.pcg_state.state.low + inc = 2 **64 * self.rng_state.pcg_state.inc.high + inc += self.rng_state.pcg_state.inc.low + ELSE: + state = self.rng_state.pcg_state.state + inc = self.rng_state.pcg_state.inc return {'prng': self.__class__.__name__, 'state': {'state': state, 'inc':inc}, @@ -189,11 +212,15 @@ cdef class PCG64: if prng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) + IF PCG_EMULATED_MATH==1: + self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 + self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 + self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 + self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 + ELSE: + self.rng_state.pcg_state.state = value['state']['state'] + self.rng_state.pcg_state.inc = value['state']['inc'] - self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 - self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 - self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 - self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/src/pcg64/pcg64.c b/_randomgen/core_prng/src/pcg64/pcg64.c index 8f29947e0047..f51099f3f314 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.c +++ b/_randomgen/core_prng/src/pcg64/pcg64.c @@ -24,66 +24,67 @@ #include "pcg64.h" -extern inline void pcg_setseq_128_step_r(pcg_state_setseq_128* rng); +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 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); +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, +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); +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". -*/ + * + * 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; + 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; } - return acc_mult * state + acc_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; + 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); } - return _pcg128_add(_pcg128_mult(acc_mult, state), acc_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 @@ -91,15 +92,13 @@ pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult, 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; #if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) -extern void pcg64_advance(pcg64_state *state, pcg128_t step) { - pcg64_advance_r(state->pcg_state, step); -} + delta = (((pcg128_t)step[0]) << 64) | step[1]; #else -extern void pcg64_advance(pcg64_state *state, uint64_t *step) { - pcg128_t delta; - delta.high = step[0]; - delta.low = step[1]; - pcg64_advance_r(state->pcg_state, delta); + delta.high = step[0]; + delta.low = step[1]; +#endif + pcg64_advance_r(state->pcg_state, delta); } -#endif \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h index acb6417b86ed..244eeb8cff49 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -34,8 +34,7 @@ #include #endif - -#if __GNUC_GNU_INLINE__ && !defined(__cplusplus) +#if __GNUC_GNU_INLINE__ && !defined(__cplusplus) #error Nonstandard GNU inlining semantics. Compile with -std=c99 or better. #endif @@ -44,168 +43,158 @@ extern "C" { #endif #if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) - typedef __uint128_t pcg128_t; -#define PCG_128BIT_CONSTANT(high,low) \ - (((pcg128_t)(high) << 64) + low) +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; - - inline pcg128_t PCG_128BIT_CONSTANT(uint64_t high, uint64_t low) { - pcg128_t result; - result.high = high; - result.low = low; - return result; - } +typedef struct { + uint64_t high; + uint64_t low; +} pcg128_t; + +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; +} pcg_state_128; - typedef struct { - pcg128_t state; - pcg128_t inc; - } pcg_state_setseq_128; +typedef struct { + pcg128_t state; + pcg128_t inc; +} pcg_state_setseq_128; -#define PCG_DEFAULT_MULTIPLIER_128 \ - PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL) -#define PCG_DEFAULT_INCREMENT_128 \ - PCG_128BIT_CONSTANT(6364136223846793005ULL,1442695040888963407ULL) +#define PCG_DEFAULT_MULTIPLIER_128 \ + PCG_128BIT_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) +#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) } + { \ + PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL), \ + PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ + } - inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) - { - return (value >> rot) | (value << ((- rot) & 63)); - } +inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { + return (value >> rot) | (value << ((-rot) & 63)); +} #ifdef PCG_EMULATED_128BIT_MATH - 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; - } - - inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t* z1, uint64_t* z0) { - 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); - } - - 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; - } - - 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); - } - - inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) - { - return pcg_rotr_64(state.high ^ state.low, - state.high >> 58u); - } - - 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 & 0x800000000000ULL; - 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); - } +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; +} + +inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, uint64_t *z0) { + 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); +} + +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; +} + +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); +} + +inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { + return pcg_rotr_64(state.high ^ state.low, state.high >> 58u); +} + +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 & 0x800000000000ULL; + 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); +} #else /* PCG_EMULATED_128BIT_MATH */ - inline void pcg_setseq_128_step_r(pcg_state_setseq_128* rng) - { - rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; - } - - 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); - } - - 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); - } +inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; +} + +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); +} + +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 */ +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); +} + +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); + +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); +} - 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); - } - - 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); - - 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 +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 } @@ -213,14 +202,12 @@ extern "C" { #endif /* PCG64_H_INCLUDED */ - 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); } @@ -236,8 +223,4 @@ static inline uint32_t pcg64_next32(pcg64_state *state) { return (uint32_t)(next >> 32); } -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) -void pcg64_advance(pcg64_state *state, pcg128_t step); -#else void pcg64_advance(pcg64_state *state, uint64_t *step); -#endif \ No newline at end of file diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index 1c6baf3075e5..3121d5cbdc2e 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -1,5 +1,11 @@ #include +#ifdef _WIN32 +#define INLINE __inline _forceinline +#else +#define INLINE inline +#endif + struct r123array2x64 { uint64_t v[2]; }; @@ -38,7 +44,7 @@ static inline uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { // static __inline _forceinline struct r123array4x64 _philox4x64round(struct // r123array4x64 ctr, struct r123array2x64 key); -static __inline _forceinline struct r123array4x64 +static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key) { uint64_t hi0; uint64_t hi1; @@ -49,13 +55,13 @@ _philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key) { return out; } -static __inline philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { +static INLINE philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { return uk; } // static __inline _forceinline philox4x64_ctr_t philox4x64_R(unsigned int R, // philox4x64_ctr_t ctr, philox4x64_key_t key); -static __inline _forceinline philox4x64_ctr_t +static INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, philox4x64_ctr_t ctr, philox4x64_key_t key) { if (R > 0) { ctr = _philox4x64round(ctr, key); diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 0acf66da49b2..b1956831c156 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,3 +1,5 @@ +import timeit + from core_prng import Xoroshiro128, ThreeFry, MT19937, \ Xorshift1024, PCG64, Philox from core_prng.generator import RandomGenerator @@ -59,3 +61,18 @@ state = rg.state print(state) rg.state = state + +PRNGS = [MT19937, PCG64, Philox, ThreeFry, Xoroshiro128, Xorshift1024] + +setup = """ +from core_prng import {module} +m = {module}() +m._benchmark(701) +""" +for p in PRNGS: + module = p.__name__ + print(module) + t = timeit.timeit("m._benchmark(10000000)", setup.format(module=module), + number=10) + print('{:0.2f} ms'.format(1000 * t / 10)) + print('{:,} randoms per second'.format(int(10000000 / (t/10)))) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index fcda70ad0d0c..663c0056c7e0 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,11 +1,10 @@ import os from os.path import join -import versioneer - +import Cython.Compiler.Options import numpy as np +import versioneer from Cython.Build import cythonize -import Cython.Compiler.Options from setuptools import setup, find_packages, Distribution from setuptools.extension import Extension @@ -13,56 +12,91 @@ MOD_DIR = './core_prng' +DEBUG = False +PCG_EMULATED_MATH = False + +EXTRA_COMPILE_ARGS = [] EXTRA_LINK_ARGS = [] if os.name == 'nt': EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] + PCG_EMULATED_MATH = True + if DEBUG: + EXTRA_LINK_ARGS += ['-debug'] + EXTRA_COMPILE_ARGS = ["-Zi", "/Od"] extensions = [Extension('core_prng.entropy', sources=[join(MOD_DIR, 'entropy.pyx'), join(MOD_DIR, 'src', 'entropy', 'entropy.c')], include_dirs=[np.get_include(), join(MOD_DIR, 'src', 'entropy')], - extra_link_args=EXTRA_LINK_ARGS), + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.mt19937", ["core_prng/mt19937.pyx", join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'mt19937')]), + join(MOD_DIR, 'src', 'mt19937')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.philox", ["core_prng/philox.pyx", join(MOD_DIR, 'src', 'philox', 'philox.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'philox')]), + join(MOD_DIR, 'src', 'philox')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.pcg64", ["core_prng/pcg64.pyx", join(MOD_DIR, 'src', 'pcg64', 'pcg64.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'pcg64')]), + join(MOD_DIR, 'src', 'pcg64')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.threefry", ["core_prng/threefry.pyx", join(MOD_DIR, 'src', 'threefry', 'threefry.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'threefry')]), + join(MOD_DIR, 'src', 'threefry')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.xoroshiro128", ["core_prng/xoroshiro128.pyx", join(MOD_DIR, 'src', 'xoroshiro128', 'xoroshiro128.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'xoroshiro128')]), + join(MOD_DIR, 'src', 'xoroshiro128')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.xorshift1024", ["core_prng/xorshift1024.pyx", join(MOD_DIR, 'src', 'xorshift1024', 'xorshift1024.c')], include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'xorshift1024')]), + join(MOD_DIR, 'src', 'xorshift1024')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.generator", ["core_prng/generator.pyx", - join(MOD_DIR, 'src', 'distributions', 'distributions.c')], - include_dirs=[np.get_include()]), + join(MOD_DIR, 'src', 'distributions', + 'distributions.c')], + include_dirs=[np.get_include()], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.common", ["core_prng/common.pyx"], - include_dirs=[np.get_include()]), + include_dirs=[np.get_include()], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), ] @@ -74,7 +108,8 @@ def is_pure(self): setup( version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), - ext_modules=cythonize(extensions), + ext_modules=cythonize(extensions, compile_time_env={ + "PCG_EMULATED_MATH": PCG_EMULATED_MATH}), name='core_prng', packages=find_packages(), package_dir={'core_prng': './core_prng'}, From b41949e5c9e5cc46231adf8de8db22f217bc8989 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 15:34:31 +0000 Subject: [PATCH 025/138] ENH: Add dSFMT --- _randomgen/core_prng/__init__.py | 5 +- _randomgen/core_prng/dsfmt.pyx | 279 +++++++ .../core_prng/src/dsfmt/128-bit-jump.poly.txt | 2 + .../core_prng/src/dsfmt/96-bit-jump.poly.txt | 2 + _randomgen/core_prng/src/dsfmt/LICENSE.txt | 32 + _randomgen/core_prng/src/dsfmt/calc-jump.cpp | 81 +++ .../core_prng/src/dsfmt/dSFMT-calc-jump.hpp | 106 +++ _randomgen/core_prng/src/dsfmt/dSFMT-common.h | 115 +++ _randomgen/core_prng/src/dsfmt/dSFMT-jump.c | 184 +++++ _randomgen/core_prng/src/dsfmt/dSFMT-jump.h | 29 + _randomgen/core_prng/src/dsfmt/dSFMT-params.h | 87 +++ .../core_prng/src/dsfmt/dSFMT-params19937.h | 40 ++ .../core_prng/src/dsfmt/dSFMT-test-gen.c | 53 ++ _randomgen/core_prng/src/dsfmt/dSFMT.c | 639 +++++++++++++++++ _randomgen/core_prng/src/dsfmt/dSFMT.h | 678 ++++++++++++++++++ _randomgen/core_prng/src/mt19937/mt19937.c | 2 - _randomgen/demo.py | 10 +- _randomgen/setup.py | 24 + 18 files changed, 2362 insertions(+), 6 deletions(-) create mode 100644 _randomgen/core_prng/dsfmt.pyx create mode 100644 _randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt create mode 100644 _randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt create mode 100644 _randomgen/core_prng/src/dsfmt/LICENSE.txt create mode 100644 _randomgen/core_prng/src/dsfmt/calc-jump.cpp create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-common.h create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-jump.c create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-jump.h create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-params.h create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-params19937.h create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT.c create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT.h diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 7f554c4d3f97..2d8d0ae6f2e4 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,12 +1,13 @@ +from .dsfmt import DSFMT from .generator import RandomGenerator from .mt19937 import MT19937 from .pcg64 import PCG64 +from .philox import Philox from .threefry import ThreeFry from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 -from .philox import Philox -__all__ = ['RandomGenerator', 'PCG64', 'Xoroshiro128', +__all__ = ['RandomGenerator', 'DSFMT', 'PCG64', 'Xoroshiro128', 'ThreeFry', 'MT19937', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx new file mode 100644 index 000000000000..e43d05a75af9 --- /dev/null +++ b/_randomgen/core_prng/dsfmt.pyx @@ -0,0 +1,279 @@ +import operator +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + +DEF DSFMT_MEXP = 19937 +DEF DSFMT_N = 191 # ((DSFMT_MEXP - 128) / 104 + 1) +DEF DSFMT_N_PLUS_1 = 192 # DSFMT_N + 1 +DEF DSFMT_N64 = DSFMT_N * 2 + +cdef extern from "src/dsfmt/dSFMT.h": + + union W128_T: + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; + + ctypedef W128_T w128_t; + + struct DSFMT_T: + w128_t status[DSFMT_N_PLUS_1]; + int idx; + + ctypedef DSFMT_T dsfmt_t; + + struct s_dsfmt_state: + dsfmt_t *state + int has_uint32 + uint32_t uinteger + + double *buffered_uniforms + int buffer_loc + + ctypedef s_dsfmt_state dsfmt_state + + double dsfmt_next_double(dsfmt_state *state) nogil + uint64_t dsfmt_next64(dsfmt_state *state) nogil + uint64_t dsfmt_next32(dsfmt_state *state) nogil + + void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) + void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) + # void dsfmt_jump(dsfmt_state *state) + +cdef uint64_t dsfmt_uint64(void* st):# nogil: + return dsfmt_next64(st) + +cdef uint32_t dsfmt_uint32(void *st) nogil: + return dsfmt_next32( st) + +cdef double dsfmt_double(void* st) nogil: + return dsfmt_next_double(st) + +cdef class DSFMT: + """ + Prototype Core PRNG using dsfmt + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `state`. Designed for use in a + `RandomGenerator` object. + """ + cdef dsfmt_state *rng_state + cdef prng_t *_prng + cdef public object _prng_capsule + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(dsfmt_state)) + self.rng_state.state = malloc(sizeof(dsfmt_t)) + self.rng_state.buffered_uniforms = malloc(DSFMT_N64 * sizeof(double)) + self.rng_state.buffer_loc = DSFMT_N64 + self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) + self.seed(seed) + self._prng.state = self.rng_state + self._prng.next_uint64 = &dsfmt_uint64 + self._prng.next_uint32 = &dsfmt_uint32 + self._prng.next_double = &dsfmt_double + cdef const char *name = "CorePRNG" + self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state.state) + free(self.rng_state.buffered_uniforms) + free(self.rng_state) + free(self._prng.binomial) + free(self._prng) + + def _reset_state_variables(self): + pass + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return dsfmt_next64(self.rng_state) + elif bits == 32: + return dsfmt_next32(self.rng_state) + else: + raise ValueError('bits must be 32 or 64') + + def _benchmark(self, Py_ssize_t cnt): + cdef Py_ssize_t i + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + cdef np.ndarray obj + try: + if seed is None: + try: + seed = random_entropy(1) + except RuntimeError: + seed = random_entropy(1, 'fallback') + dsfmt_init_gen_rand(self.rng_state.state, seed) + 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") + dsfmt_init_gen_rand(self.rng_state.state, seed) + except TypeError: + obj = np.asarray(seed).astype(np.int64, casting='safe').ravel() + 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') + dsfmt_init_by_array(self.rng_state.state, + obj.data, + np.PyArray_DIM(obj, 0)) + + def seed(self, seed=None): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + cdef np.ndarray init_key + ub = 2 ** 32 + if seed is None: + try: + state = random_entropy(1) + except RuntimeError: + state = random_entropy(1, 'fallback') + seed = state[0] + if np.isscalar(seed): + # TODO: This isn't correct, but works now + seed = int(seed) + if seed < 0 or seed > ub: + raise ValueError('seed must be an unsigned 32-bit integer') + dsfmt_init_gen_rand(self.rng_state.state, seed) + else: + # TODO: This also need to be impeoved to be more careful + init_key = np.asarray(seed, dtype=np.uint32).ravel() + dsfmt_init_by_array(self.rng_state.state, + init_key.data, + init_key.shape[0]) + + self._reset_state_variables() + +# def jump(self): +# dsfmt_jump(self.rng_state) +# return self + + @property + def state(self): + """Get or set the PRNG state""" + cdef Py_ssize_t i, j, loc = 0 + cdef uint64_t[::1] state + cdef double[::1] buffered_uniforms + + state = np.empty(2 *DSFMT_N_PLUS_1, dtype=np.uint64) + for i in range(DSFMT_N_PLUS_1): + for j in range(2): + state[loc] = self.rng_state.state.status[i].u[j] + loc += 1 + buffered_uniforms = np.empty(DSFMT_N64,dtype=np.double) + for i in range(DSFMT_N64): + buffered_uniforms[i] = self.rng_state.buffered_uniforms[i] + return {'prng': self.__class__.__name__, + 'state': {'state':np.asarray(state), + 'idx':self.rng_state.state.idx}, + 'buffer_loc': self.rng_state.buffer_loc, + 'buffered_uniforms':np.asarray(buffered_uniforms)} + + @state.setter + def state(self, value): + cdef Py_ssize_t i, j, loc = 0 + if not isinstance(value, dict): + raise TypeError('state must be a dict') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + state = value['state']['state'] + for i in range(DSFMT_N_PLUS_1): + for j in range(2): + self.rng_state.state.status[i].u[j] = state[loc] + loc += 1 + self.rng_state.state.idx = value['state']['idx'] + buffered_uniforms = value['buffered_uniforms'] + for i in range(DSFMT_N64): + self.rng_state.buffered_uniforms[i] = buffered_uniforms[i] + self.rng_state.buffer_loc = value['buffer_loc'] \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt b/_randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt new file mode 100644 index 000000000000..fea1318fb706 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt @@ -0,0 +1,2 @@ +jump polynomial: +f4dfa6c62049d0776e0bf6f1e953f3aa38abb113df86be024eab3773ad5f2b82ead936022e656dff7e562691c59dd5f7d2566b78d9669002503c4ddb1888a49f32333f515e6c60c4ecd221078ec6f26f0a90f4875067ca1f399a99775037adf905566e2c7e6b42131420f8f04f112c92621c9b1502f2a8aefad6c667904af62f0d55e02d396902d3b89450103c5ce5fe0408d97cbb864861b49e4e42048ff3310b48faac55095a7f422eea4aade752f947f947c6be0a0c665bdea099246ab9eff658ea8ca468bf49d0227748367878de06d7bd86ea6708fcac6e252f5f00f04309b2aac3036b64afb39d990427c6c9f03477cc7e935c43c0e61bc161db8eb15516eee8cb377ecbc1849207990fb6778721b29bfe0d89bfda1b3772fa5b0b1f7ec3daf36052032285898c6f6396f55010c31f8201b7e2e51d94f920bfe57684c5415cc342cb39a0045d9793d13cf8646096daeb8bb9bfc20a90de8f2426da8733267a9b9674f32154e8f84a9932223a2ca3c787d0b66df6675febbdfcba2f9cef09c621c57e11098b3289c77397aaae8b104642ffe0c4b75598efbc53745984d68b4d6656cae299ae2be55217a9a02b009ca7be32f47fbe434bce4914a34d0c9b0085bede9b8a99319c34660d66f0124b5a7714c4bf3cbfec3ee43ed817087168bad80133bebaeeb68cf7929a24d1bb3de831a8340d220906ab04159cf94b21d5ee813bd7c80f10f01b43052af530917513b169254c25d6fcfe6cb420d6ce92f54886ef6eaf9a5ba35e893ff593834d05ddf28899e42d729c7df3d21ef036020789739366f0c11ec52ff92a0bfd8ba69508e27b20fabb8217bd36b90e5aa918159ac87913bc7b46c04e366c23c92807fbe9c6a407e6a4db0b4fc23c3b6c706b5ca058fe8c190f849f18d16d6b48b5ed760eb202fd566291a799420b9654e08b8118bcbfead8e9dd2fdb9b053e9bdfb665285c78718f726d0b3d6c37e116428ec9ac9db2637259e4e8d6402bbada46c6bdb03985e19a82e9b4e57de1b025a3cb1f850beae7e8da9941655825bce0e89d536b6ee9064865b1a85c185e9fc9cb7f435de13d44773c00eed442a286e4ab807e3cab4dc3441d1b7d2af693812ae8b39652bb8c835fc895d13d6da93541afeadeee450475c29f3b2dfa8ef1c1e2547463b2cc2f0ff7a42ac4dd35e25c4fa030d2d2766fbe9f2d04c1304671747bace2f7dd55142bfa60f8cbc968bfc3d7a342152dc684a0fb5a32c0962a62b5220ac0f72add9d8b84d6cc76b97d03245e01fc8da3414a49bb4075d3488f29b56dc42ba69e3b58529448c943ecfd98b3784a39d0b8609a8fb945e757f4569f53bd2cf80f7f638acf5b67fe9c560a3b7b0cf7e0398f31aa8b03cf9c62b24296b6d8596b694469a02686c38daa16a1ef86e012d61a2f7de1693a5c00b3685175caec3c67146477eba54830f1d546cb18a553779aa46adb4f2010e33f3def847c7d89b51a8462b227605f6c920fd558a6daf64bc98682e508ae960c0c571870e603ba1fce0c13d53176f353fd319959e13db93eae1359f06e3dd4767c04f824cf34ec7bf8f60161ba1a615db82852eca9e3869afa711ab9a090660b0dc6cfbea310dda77e02310fbaeacd2636f975838c2dbcdbe9ac2cd85cee28f5e3f0c73abf62f9fa02cd79a7606b7ba855db68a07848b057c3aaf38f1a70086e14616f6f88305a1f9ce6b41378a620d4db3e0e7e1d421590dccaeff86212e232eeb5eb8a8d33a8c9b25ae88f3a7bd5032b4efa68f8af3186a02ffcbf5456f12beccace94c81c360cc4a0dcc642b59f991eec68c59af78139ca60b96d6a18e9535f8995e89bd2cf6a0aef3acffd33d1c0c1b79b66414a91d9f65b2b4ec65844b96f725d2b4b0c309f3eb9d714e9dd939bbdfd85ce8fb43679aeab13f6c29549949503c9466dbd337c4cdde46d6eacd15f21f4d8fdeaa627a47884c88a9c85f0b731d271a8ea7cb9e04a4a149c23c10f56b3a0476dc77a999d6e4f813e4b0f805e2a693e2ae4ae0ecc423c9ba5d17b42e691abf83784a582f2b1fd85d1e0a27ba38a500963568b2450363d2c5e3f7b8ba3e5b56e4e9f745a3a710bf2ae233c303068c532ce78ff031e6ab28b705dd94d7db4500909edb5626b8c9bd5ff4f0b4741388f0b91563ee516934c013e901572cba005ac5c535f4f107903be9af7b2793dfb61b5070facbe71eefe1b5600f975c8c38c3a2350d78beadfecb78e981164ae8bc866e732972d3ceef4aac68e15861f9b881d9b51b4edece150bc124b07645defb4202ef5d0e0962db98cae6ed459561c93c74c20bd64362e4f4fffc389a6cd80514604ff22eecc10c9cbc7981d19a8102b24146354c463107c9dc070e29e70df3578022acf72289ef071ab9f9402a544d0399f1b1e5f206b6d46d445f6d612a490e72918e00c853eda8493bef511149e80c9ab56e8b4b8cba3987249f77d060e61760e5792ac321c987c03c2606e9393a7970212992cdbd16448078d5039d4c2c3199714f53278f4f7b1d2e514cf95bdfc078b8bb0db659cb2c3f5cc02890ea84f05d414c88d2db9e9f8455659b9fa6254405317245fa070d6970cafb4dadb2522b490a5c8e02fe973a8cdbfbfbdbfb01535099ffba3d3896bc4d1189fc570c3e6fdc6469265b8da912772e75dd62ab71be507f700d56cac5e68fd6b57ec166168ab5258a69625c142a5b1b3519f94be1bde5e51d3bd8ea0c12d5af2fe4615b1b7bd4a96628a4fabc65925ff09718f63bbebaad98f89bd9543a27b3ff3b5d8bfa89f941a5eb8cc005ccd4a705190e1c9dc6a9f4264e5ee658520a4438e92de854bffc39f8dc7dfbb5de4f14ba63ea16a37d14a7b4610f95b6cffd55e4679b29cedbdf20e7bd16da822fad910c359ee3a68e48aae6e769b0e291d5d3aa3e2ca9d8d23abe8a1d5349f4991e9300852cc0befb20c2fc0d169306b260763344024f8092cbcc24c6807363e9fc548a30d5faab3a94b2af0782a2942be80c45d8b0587efd587394ef33c33022436e285806ddffdd32fe36345c3c38ed8d680abeb7a028b44ee6f94d060a14c7019bb6af1f1b5f0a562957d19826d8cc216f9b908c989ccd5415e3525dfe9422ffb5b50b7cc3083dc325544751e5683535d7439d3da2b0bb73bea551dd99e04e0e793804f4774eb6b1daf781d9caa5128274e599e847862fe309027813d3e4eda0bbeb7201856a5c5d8370e44dabff0bb229c723ba0a6bcf29c44536147de11b7835991018100105bd4329217f7386903fe8e7363cd7b3e893244e245e0a187467664c05b0be1fd429722b9b9a5e3198147fad72776e8a63aab9054fa9d259af0198d088d71d132e6068676a8e9ebb0f616b51ee34aac39c2c2221c71124017270d75ff4a048363c389e04e9b440ad2032a381ac2cfc54f409caa791e65ee4f5d6cd035008f219b88a803a7382ae447bf65a3df2176b25b3b7b67dabe34decd9a1384dc7a003916ca8fbcb29b3ad6fd8eac5bbbaa3bdfa6c6a3ad9427c4f3ed79fea26e14c8ce5fa3b4f82c5f7b6d2125916753a7b92ce9b46d45 diff --git a/_randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt b/_randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt new file mode 100644 index 000000000000..15c68d155af4 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt @@ -0,0 +1,2 @@ +jump polynomial: +288da521f7244e5f62bf26692bdd1fcdfd38a850addb02d98bd358367cb78c71348f3e163522e0e30e4feb90aa210dd793c94d151fa89aa319911aa42b511ea568a503d595c6d9bcd37317a37ef5679700a5b67f29df72451770fc1eb8c97427cdd9825c23f32dcd5c4fb117a4f5982a3bee8f16595d021165cd9688db342e360e222c9855c8306fd7b5fc82e62e3b1765e7f3319da9da66c325b030bd6175876efc70636306cd2de31a299ca20e9eb1d5063bcbff0ba282aff4737a5b1585cd940ae9cd45fda222308341e0d5588e81b42c4e0574deeb2d80b84c00cb3f8a7ae6278462e1994b83a25b33aa0dc74d5d3d057dabfd6a8a82d7dfb6bb66a223bc46dca2b5fb1885e6ab80fddcd6578b32c21c4a9d761cb9798800c921d56ee356c491454e15956e68ef566c1706fcdfb6a6828ec1fb93db455525828e8741a371c14959658b99bbd358a162230ee451a8432df279e4ba0d3a493954359a5390b16475540578270b168054fefb1e20948d4d20c88005ed09e671b6a94b8ea929f72e7b2f85af4098a92d742b64964ea6b7773b2c20b22a0ff35bd9367c3160b549411230e15a987f361e04daac49d2fe4c7c9371d84bf270d8f33a62680b2ee014bf5be691aa0d82e66e885eaa832a241aff8a09c435ac2b0698bc3865c5125d498a4ffadd31d5f2c6aee6496fdc6c13055b53e7f65a683ef539b6e8ea6e21429a11ff74ccef09ee83eac1b5ddaf1b77fed786fd20e8cbb3e8877b7f80a24fef31a9f8d8108099c50abc886f7ab20c4396bf51af1b806003185eaf2061f55036e26f498b92aabadfb6b5bed2d116b32ae387a692058e6160a9508dc44c971454d9a357ba115278861be0aeaa0926d773c5d4563e37dffcfed8bbf44b79e384650b7eff30aae73154a2ef130cee1eaf32d944e5472ae217789c03276deb8290c73dd5cde0b6dce9b28cbb73776e3e52260768f37a38db3d1c26c3c065b641c7a825edc155d947118d8b6ff8c8818440088724261ca83fa866aa4159fbffac8c28c8a7ca5f1e2fde74b4908c8215cbde20190bdf0de1d5a05a2c116a66eeadcafd643098e74ec3e82b3658c0c4fd7c7797d567b8db3d6b67ca262d713dbf45cc80b89f279be0991f276a4501d2ea6222026caa7e6fbcf4d02fdf65d8f439f88cfb1121d1b0f4dd670d146b93e099a32869448d837e347229745e5c30f1521b0c477b2062c9c8f631dcd29664eec7f28bdcac2a1ca2deabbbc89b21824ba92a61eeb4c5dd62b20c346134d842bcfc189f0e2244bfb8596c38c88d5bd4447fcd30890a4acf71801a6bcf5d806073b9ca730db53e160a79516333748708dd5e5be37d75e90e64d14ddf5ccc9390ae67cbba39916ce9b3b6b1d19378e4bd36ef0c9e62570394051cc273122e0790e381b20e083beca6e88bc2fa8bde22c89689b4b710c775cd9065158b48bf855fc3a3e80693908046ea1da9c558f024ea5ea69d65f40317fc3c8bab7606bf7edf17fcaeb706756c4de38319a51fc24c80a2baccef40f4354f5147fb91c9b1b91011d146da7eeb426d25de17d7e39ee53735ef28b64d5e6e5444676f679a8e4e91314377c7606531b90dc1cd8cf2d929ed9137fdc0d6b6db62e764ef200a439d742b51425b818231ed799a53768119466cc42296ce36f52507411709cd9d622c1f899291db27104589a5e4509d9818cef983d6a13ce1247184c4551c38bd319aa068cd9c0b96f9e08b4a7bd7852c129d4126676cbcb30ae029b0e2cec3c58c110fecae7967fca0752874e2fcc077084dd4d87b4dee632b621f35cb9f22639ab4de86089c56cabb1aa8a4fedbc5d8673cca12b4479dca5dc6f3048bb654fd59c464b033960177a4d6c2ee38b124d193cd5da3cbc5aa5ebdf7197f5d3f3008f01effb599b6d238044f2ee204bf372685256813278ca7a7d145445f5d5eb5490d99ee89d587fe446e1600d7daf9553b7d709bd796c59757e2f7c26cb71990a51ffc49120f358ef4927729b7e8c2cf9ad35a8017667625a39e2d12c8b0dd5de3d3797d9167ac9302a122e0f066a2552a7278a632b043089a1f5a127ce0bc8e688c545f20bca467fd58d9f9b8234f2be7a28152ab4d39ba8d6c4471d574571aa1a4a3aca16f46ac74e664899cf24502334aec637a9c392ba1618340080bfaed493abaa2f684ffb2bc1da86d804305772e30893f67235d5ce8180ef60490e46f131465d249a39df1aaed30621169c0f7db0b6a6adcab975ec00ca68b2fc06f443cfb8933b326f106670e0e528f22ff96d06b2a6d917258d29a87cf637f37c3661b42462c11c73c1cd0a6774e4e10157b02c0cfd9148ad8a23775653db3dec41fd6d1d5eb54a3e5e144a489a18412f21eb96a72b6751482882d636a1cd0057ea48d1a985472b0c301c4a5b24b0152bdc50a47126a01a1d0665270cdbf2ed852e0f61515bad6e58973329d269bf057ffa52331dde4700b926f635cdf49234f4aaabbabca5386526568fc3a80b1d8a9e1566e21bf889546379289263d978e95de390c4bbdb5a813535b7186f661f5c283400adb3bcf9365d45abb6088b729a98789265f1e8e684e2b2c15b4ce53230abc5e5bf6895827c95842e0849fc7fe56b7c65f075baded0f2e172c8e1088219615b8697ff4a3c6f5f708e498e6c7312680f214a877061511d3b85087545fc26708d039e977a0157b95ceba40497cc2dd1b1b1394eb98f651d701dfbc3583c159da8bae76a25db213211d6191d83c5d7a3d4b2320b8a305b5d90e04d6e3de161fff5dae7e3d4f6c9e1cf55cb5ac1677d9cfd560db2209be2b9566a267aad9cf4b9e03c221ba5b0f02cabb50cef19180ba329691d114da670d7b85e36c0b6b7d81613bd31350dfe225050861e90043ac2334478f52584a1a8809f76d40af36da02549c54da164487f0b7f823cff797db1c90f2f1c431eca97fc8bcdfb44c30cd1643c893d5e33aa56cbc0a0c38f5c8f6bb37483d13b85b659ac51ce05311bba19c97772e81c2315a009e80f591c82445d493dc3b5fb12c52e8c50c6260200b0d77092bf19aabce491b2c511fca2a4ebd99b446e55f453314297723894f0b223868ef80f5964468afa3a5e6aa41f2128e6de893bba2cbde9bea91ba97bda18a01905ce8d2e85e6011cc0550f5ae9121361fdec1ec97a6e6892a68732a69147476d54babaa564b883baad7100eb1092a1aa28a29f67e6b53deab511e53eada87cfe1bb6e3c6a215fd8d729840a5b5ac452cfd8acb9be7818d2c806c3e0cedd0847ddf9a5906bf1a0fa4da44ccea829a1a5350d5db0241a221b97e5cd5ba15e58b402529317c854fbcda86a562d4ee44a34193513647af0a3bc9f90ababc1dbbfd9aba8d3dcc39463473ca6bc0e1dc736ba712eef42dee80e31e7d8abe23f98e91ab875d0553bc24be9cb1d9484812c0b038cb177ad52064328e17f8ca7c8737902d964017e3aaae66161270dac21de42a6f60d10d89c1556916a249a130752bb7c7783b93a59d9f5456745ecc512f497b5a31be2678b9587628cb45dae2f5f6bde7ea4500c1ba961e2 diff --git a/_randomgen/core_prng/src/dsfmt/LICENSE.txt b/_randomgen/core_prng/src/dsfmt/LICENSE.txt new file mode 100644 index 000000000000..4570c4603b21 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/LICENSE.txt @@ -0,0 +1,32 @@ +Copyright (c) 2007, 2008, 2009 Mutsuo Saito, Makoto Matsumoto +and Hiroshima University. +Copyright (c) 2011, 2002 Mutsuo Saito, Makoto Matsumoto, Hiroshima +University and The University of Tokyo. +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 Hiroshima University 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/_randomgen/core_prng/src/dsfmt/calc-jump.cpp b/_randomgen/core_prng/src/dsfmt/calc-jump.cpp new file mode 100644 index 000000000000..495b2797c782 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/calc-jump.cpp @@ -0,0 +1,81 @@ +/** + * @file calc-jump.cpp + * + * @brief calc jump function. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + * + * Compile: + * g++ calc-jump.cpp -o calc-jump -lntl + * + * Compute polynomial for 2^128 steps: + * ./calc-jump 340282366920938463463374607431768211456 poly.19937.txt + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dSFMT-calc-jump.hpp" + +using namespace NTL; +using namespace std; +using namespace dsfmt; + +static void read_file(GF2X& lcmpoly, long line_no, const string& file); + +int main(int argc, char * argv[]) { + if (argc <= 2) { + cout << argv[0] << " jump-step poly-file" << endl; + cout << " jump-step: a number between zero and 2^{DSFMT_MEXP}-1.\n" + << " large decimal number is allowed." << endl; + cout << " poly-file: one of poly.{MEXP}.txt " + << "file" << endl; + return -1; + } + string step_string = argv[1]; + string filename = argv[2]; + long no = 0; + GF2X lcmpoly; + read_file(lcmpoly, no, filename); + ZZ step; + stringstream ss(step_string); + ss >> step; + string jump_str; + calc_jump(jump_str, step, lcmpoly); + cout << "jump polynomial:" << endl; + cout << jump_str << endl; + return 0; +} + + +static void read_file(GF2X& lcmpoly, long line_no, const string& file) +{ + ifstream ifs(file.c_str()); + string line; + for (int i = 0; i < line_no; i++) { + ifs >> line; + ifs >> line; + } + if (ifs) { + ifs >> line; + line = ""; + ifs >> line; + } + stringtopoly(lcmpoly, line); +} diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp b/_randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp new file mode 100644 index 000000000000..b960826be43c --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp @@ -0,0 +1,106 @@ +#pragma once +#ifndef DSFMT_CALC_JUMP_HPP +#define DSFMT_CALC_JUMP_HPP +/** + * @file dSFMT-calc-jump.hpp + * + * @brief functions for calculating jump polynomial. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ +#include +#include +#include +#include + +namespace dsfmt { +/** + * converts polynomial to string for convenient use in C language. + * @param x output string + * @param polynomial input polynomial + */ + static inline void polytostring(std::string& x, NTL::GF2X& polynomial) + { + using namespace NTL; + using namespace std; + + long degree = deg(polynomial); + int buff; + stringstream ss; + for (int i = 0; i <= degree; i+=4) { + buff = 0; + for (int j = 0; j < 4; j++) { + if (IsOne(coeff(polynomial, i + j))) { + buff |= 1 << j; + } else { + buff &= (0x0f ^ (1 << j)); + } + } + ss << hex << buff; + } + ss << flush; + x = ss.str(); + } + +/** + * converts string to polynomial + * @param str string + * @param poly output polynomial + */ + static inline void stringtopoly(NTL::GF2X& poly, std::string& str) + { + using namespace NTL; + using namespace std; + + stringstream ss(str); + char c; + long p = 0; + clear(poly); + while(ss) { + ss >> c; + if (!ss) { + break; + } + if (c >= 'a') { + c = c - 'a' + 10; + } else { + c = c - '0'; + } + for (int j = 0; j < 4; j++) { + if (c & (1 << j)) { + SetCoeff(poly, p, 1); + } else { + SetCoeff(poly, p, 0); + } + p++; + } + } + } + +/** + * calculate the jump polynomial. + * SFMT generates 4 32-bit integers from one internal state. + * @param jump_str output string which represents jump polynomial. + * @param step jump step of internal state + * @param characteristic polynomial + */ + static inline void calc_jump(std::string& jump_str, + NTL::ZZ& step, + NTL::GF2X& characteristic) + { + using namespace NTL; + using namespace std; + GF2X jump; + PowerXMod(jump, step, characteristic); + polytostring(jump_str, jump); + } +} +#endif diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-common.h b/_randomgen/core_prng/src/dsfmt/dSFMT-common.h new file mode 100644 index 000000000000..30c26c08bed5 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-common.h @@ -0,0 +1,115 @@ +#pragma once +/** + * @file dSFMT-common.h + * + * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom + * number generator with jump function. This file includes common functions + * used in random number generation and jump. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima + * University. + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima + * University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ +#ifndef DSFMT_COMMON_H +#define DSFMT_COMMON_H + +#include "dSFMT.h" + +#if defined(HAVE_SSE2) +# include +union X128I_T { + uint64_t u[2]; + __m128i i128; +}; +union X128D_T { + double d[2]; + __m128d d128; +}; +/** mask data for sse2 */ +static const union X128I_T sse2_param_mask = {{DSFMT_MSK1, DSFMT_MSK2}}; +#endif + +#if defined(HAVE_ALTIVEC) +inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, + w128_t *lung) { + const vector unsigned char sl1 = ALTI_SL1; + const vector unsigned char sl1_perm = ALTI_SL1_PERM; + const vector unsigned int sl1_msk = ALTI_SL1_MSK; + const vector unsigned char sr1 = ALTI_SR; + const vector unsigned char sr1_perm = ALTI_SR_PERM; + const vector unsigned int sr1_msk = ALTI_SR_MSK; + const vector unsigned char perm = ALTI_PERM; + const vector unsigned int msk1 = ALTI_MSK; + vector unsigned int w, x, y, z; + + z = a->s; + w = lung->s; + x = vec_perm(w, (vector unsigned int)perm, perm); + y = vec_perm(z, (vector unsigned int)sl1_perm, sl1_perm); + y = vec_sll(y, sl1); + y = vec_and(y, sl1_msk); + w = vec_xor(x, b->s); + w = vec_xor(w, y); + x = vec_perm(w, (vector unsigned int)sr1_perm, sr1_perm); + x = vec_srl(x, sr1); + x = vec_and(x, sr1_msk); + y = vec_and(w, msk1); + z = vec_xor(z, y); + r->s = vec_xor(z, x); + lung->s = w; +} +#elif defined(HAVE_SSE2) +/** + * This function represents the recursion formula. + * @param r output 128-bit + * @param a a 128-bit part of the internal state array + * @param b a 128-bit part of the internal state array + * @param d a 128-bit part of the internal state array (I/O) + */ +inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *u) { + __m128i v, w, x, y, z; + + x = a->si; + z = _mm_slli_epi64(x, DSFMT_SL1); + y = _mm_shuffle_epi32(u->si, SSE2_SHUFF); + z = _mm_xor_si128(z, b->si); + y = _mm_xor_si128(y, z); + + v = _mm_srli_epi64(y, DSFMT_SR); + w = _mm_and_si128(y, sse2_param_mask.i128); + v = _mm_xor_si128(v, x); + v = _mm_xor_si128(v, w); + r->si = v; + u->si = y; +} +#else +/** + * This function represents the recursion formula. + * @param r output 128-bit + * @param a a 128-bit part of the internal state array + * @param b a 128-bit part of the internal state array + * @param lung a 128-bit part of the internal state array (I/O) + */ +inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, + w128_t *lung) { + uint64_t t0, t1, L0, L1; + + t0 = a->u[0]; + t1 = a->u[1]; + L0 = lung->u[0]; + L1 = lung->u[1]; + lung->u[0] = (t0 << DSFMT_SL1) ^ (L1 >> 32) ^ (L1 << 32) ^ b->u[0]; + lung->u[1] = (t1 << DSFMT_SL1) ^ (L0 >> 32) ^ (L0 << 32) ^ b->u[1]; + r->u[0] = (lung->u[0] >> DSFMT_SR) ^ (lung->u[0] & DSFMT_MSK1) ^ t0; + r->u[1] = (lung->u[1] >> DSFMT_SR) ^ (lung->u[1] & DSFMT_MSK2) ^ t1; +} +#endif +#endif diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.c b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.c new file mode 100644 index 000000000000..1832bb8853b7 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.c @@ -0,0 +1,184 @@ +/** + * @file dSFMT-jump.c + * + * @brief do jump using jump polynomial. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ + +#include +#include +#include +#include +#include "dSFMT-params.h" +#include "dSFMT.h" +#include "dSFMT-jump.h" +#include "dSFMT-common.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + struct FIX_T { + int mexp; + uint64_t fix[4]; + }; + + struct FIX_T fix_table[] = { + {521, {UINT64_C(0x3fff56977f035125), + UINT64_C(0x3ff553857b015035), + UINT64_C(0x4034434434434434), + UINT64_C(0x0140151151351371)}}, + {1279, {UINT64_C(0x3ff87befce70e89f), + UINT64_C(0x3ff5f6afa3c60868), + UINT64_C(0xa4ca4caccaccacdb), + UINT64_C(0x40444444444c44c4)}}, + {4253, {UINT64_C(0x3ff85a66da51a81a), + UINT64_C(0x3ff4f4aeab9688eb), + UINT64_C(0x20524524534d34d3), + UINT64_C(0xc9cc9cc9cc9ccdcf)}}, + {216091, {UINT64_C(0x3ff096d54a871071), + UINT64_C(0x3ffafa9bfbd5d55d), + UINT64_C(0x0470470470573573), + UINT64_C(0x0250250251259259)}}, + {0} + }; + + inline static void next_state(dsfmt_t * dsfmt); + +#if defined(HAVE_SSE2) +/** + * add internal state of src to dest as F2-vector. + * @param dest destination state + * @param src source state + */ + inline static void add(dsfmt_t *dest, dsfmt_t *src) { + int dp = dest->idx / 2; + int sp = src->idx / 2; + int diff = (sp - dp + DSFMT_N) % DSFMT_N; + int p; + int i; + for (i = 0; i < DSFMT_N - diff; i++) { + p = i + diff; + dest->status[i].si + = _mm_xor_si128(dest->status[i].si, src->status[p].si); + } + for (i = DSFMT_N - diff; i < DSFMT_N; i++) { + p = i + diff - DSFMT_N; + dest->status[i].si + = _mm_xor_si128(dest->status[i].si, src->status[p].si); + } + dest->status[DSFMT_N].si + = _mm_xor_si128(dest->status[DSFMT_N].si, + src->status[DSFMT_N].si); + } +#else + inline static void add(dsfmt_t *dest, dsfmt_t *src) { + int dp = dest->idx / 2; + int sp = src->idx / 2; + int diff = (sp - dp + DSFMT_N) % DSFMT_N; + int p; + int i; + for (i = 0; i < DSFMT_N - diff; i++) { + p = i + diff; + dest->status[i].u[0] ^= src->status[p].u[0]; + dest->status[i].u[1] ^= src->status[p].u[1]; + } + for (; i < DSFMT_N; i++) { + p = i + diff - DSFMT_N; + dest->status[i].u[0] ^= src->status[p].u[0]; + dest->status[i].u[1] ^= src->status[p].u[1]; + } + dest->status[DSFMT_N].u[0] ^= src->status[DSFMT_N].u[0]; + dest->status[DSFMT_N].u[1] ^= src->status[DSFMT_N].u[1]; + } +#endif + +/** + * calculate next state + * @param dsfmt dSFMT internal state + */ + inline static void next_state(dsfmt_t * dsfmt) { + int idx = (dsfmt->idx / 2) % DSFMT_N; + w128_t * lung; + w128_t * pstate = &dsfmt->status[0]; + + lung = &pstate[DSFMT_N]; + do_recursion(&pstate[idx], + &pstate[idx], + &pstate[(idx + DSFMT_POS1) % DSFMT_N], + lung); + dsfmt->idx = (dsfmt->idx + 2) % DSFMT_N64; + } + + inline static void add_fix(dsfmt_t * dsfmt) { + int i; + int index = -1; + for (i = 0; fix_table[i].mexp != 0; i++) { + if (fix_table[i].mexp == DSFMT_MEXP) { + index = i; + } + if (fix_table[i].mexp > DSFMT_MEXP) { + break; + } + } + if (index < 0) { + return; + } + for (i = 0; i < DSFMT_N; i++) { + dsfmt->status[i].u[0] ^= fix_table[index].fix[0]; + dsfmt->status[i].u[1] ^= fix_table[index].fix[1]; + } + dsfmt->status[DSFMT_N].u[0] ^= fix_table[index].fix[2]; + dsfmt->status[DSFMT_N].u[1] ^= fix_table[index].fix[3]; + } + +/** + * jump ahead using jump_string + * @param dsfmt dSFMT internal state input and output. + * @param jump_string string which represents jump polynomial. + */ + void dSFMT_jump(dsfmt_t * dsfmt, const char * jump_string) { + dsfmt_t work; + int index = dsfmt->idx; + int bits; + int i; + int j; + memset(&work, 0, sizeof(dsfmt_t)); + add_fix(dsfmt); + dsfmt->idx = DSFMT_N64; + + for (i = 0; jump_string[i] != '\0'; i++) { + bits = jump_string[i]; + assert(isxdigit(bits)); + bits = tolower(bits); + if (bits >= 'a' && bits <= 'f') { + bits = bits - 'a' + 10; + } else { + bits = bits - '0'; + } + bits = bits & 0x0f; + for (j = 0; j < 4; j++) { + if ((bits & 1) != 0) { + add(&work, dsfmt); + } + next_state(dsfmt); + bits = bits >> 1; + } + } + *dsfmt = work; + add_fix(dsfmt); + dsfmt->idx = index; + } + +#if defined(__cplusplus) +} +#endif diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h new file mode 100644 index 000000000000..2979f3269bc3 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h @@ -0,0 +1,29 @@ +#pragma once +#ifndef DSFMT_JUMP_H +#define DSFMT_JUMP_H +/** + * @file SFMT-jump.h + * + * @brief jump header file. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ +#if defined(__cplusplus) +extern "C" { +#endif + +#include "dSFMT.h" +void dSFMT_jump(dsfmt_t * dsfmt, const char * jump_str); + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-params.h b/_randomgen/core_prng/src/dsfmt/dSFMT-params.h new file mode 100644 index 000000000000..aa0247800488 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-params.h @@ -0,0 +1,87 @@ +#ifndef DSFMT_PARAMS_H +#define DSFMT_PARAMS_H + +#include "dSFMT.h" + +/*---------------------- + the parameters of DSFMT + following definitions are in dSFMT-paramsXXXX.h file. + ----------------------*/ +/** the pick up position of the array. +#define DSFMT_POS1 122 +*/ + +/** the parameter of shift left as four 32-bit registers. +#define DSFMT_SL1 18 + */ + +/** the parameter of shift right as four 32-bit registers. +#define DSFMT_SR1 12 +*/ + +/** A bitmask, used in the recursion. These parameters are introduced + * to break symmetry of SIMD. +#define DSFMT_MSK1 (uint64_t)0xdfffffefULL +#define DSFMT_MSK2 (uint64_t)0xddfecb7fULL +*/ + +/** These definitions are part of a 128-bit period certification vector. +#define DSFMT_PCV1 UINT64_C(0x00000001) +#define DSFMT_PCV2 UINT64_C(0x00000000) +*/ + +#define DSFMT_LOW_MASK UINT64_C(0x000FFFFFFFFFFFFF) +#define DSFMT_HIGH_CONST UINT64_C(0x3FF0000000000000) +#define DSFMT_SR 12 + +/* for sse2 */ +#if defined(HAVE_SSE2) + #define SSE2_SHUFF 0x1b +#elif defined(HAVE_ALTIVEC) + #if defined(__APPLE__) /* For OSX */ + #define ALTI_SR (vector unsigned char)(4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) + #define ALTI_SR_PERM \ + (vector unsigned char)(15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14) + #define ALTI_SR_MSK \ + (vector unsigned int)(0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU) + #define ALTI_PERM \ + (vector unsigned char)(12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3) + #else + #define ALTI_SR {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4} + #define ALTI_SR_PERM {15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14} + #define ALTI_SR_MSK {0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU} + #define ALTI_PERM {12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3} + #endif +#endif + +#if DSFMT_MEXP == 521 + #include "dSFMT-params521.h" +#elif DSFMT_MEXP == 1279 + #include "dSFMT-params1279.h" +#elif DSFMT_MEXP == 2203 + #include "dSFMT-params2203.h" +#elif DSFMT_MEXP == 4253 + #include "dSFMT-params4253.h" +#elif DSFMT_MEXP == 11213 + #include "dSFMT-params11213.h" +#elif DSFMT_MEXP == 19937 + #include "dSFMT-params19937.h" +#elif DSFMT_MEXP == 44497 + #include "dSFMT-params44497.h" +#elif DSFMT_MEXP == 86243 + #include "dSFMT-params86243.h" +#elif DSFMT_MEXP == 132049 + #include "dSFMT-params132049.h" +#elif DSFMT_MEXP == 216091 + #include "dSFMT-params216091.h" +#else +#ifdef __GNUC__ + #error "DSFMT_MEXP is not valid." + #undef DSFMT_MEXP +#else + #undef DSFMT_MEXP +#endif + +#endif + +#endif /* DSFMT_PARAMS_H */ diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-params19937.h b/_randomgen/core_prng/src/dsfmt/dSFMT-params19937.h new file mode 100644 index 000000000000..a600b0dbcc2d --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-params19937.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS19937_H +#define DSFMT_PARAMS19937_H + +/* #define DSFMT_N 191 */ +/* #define DSFMT_MAXDEGREE 19992 */ +#define DSFMT_POS1 117 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000ffafffffffb3f) +#define DSFMT_MSK2 UINT64_C(0x000ffdfffc90fffd) +#define DSFMT_MSK32_1 0x000ffaffU +#define DSFMT_MSK32_2 0xfffffb3fU +#define DSFMT_MSK32_3 0x000ffdffU +#define DSFMT_MSK32_4 0xfc90fffdU +#define DSFMT_FIX1 UINT64_C(0x90014964b32f4329) +#define DSFMT_FIX2 UINT64_C(0x3b8d12ac548a7c7a) +#define DSFMT_PCV1 UINT64_C(0x3d84e1ac0dc82880) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-19937:117-19:ffafffffffb3f-ffdfffc90fffd" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned char)(3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS19937_H */ diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c new file mode 100644 index 000000000000..9103f6d5030d --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c @@ -0,0 +1,53 @@ +/* +* +* gcc dSFMT-test-gen.c dSFMT.c -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o dSFMT +*/ +#include +#include +#include "dSFMT.h" + +int main(void) +{ + int i; + double d; + uint64_t *temp; + uint32_t seed = 1UL; + dsfmt_t state; + dsfmt_init_gen_rand(&state, seed); + double out[1000]; + dsfmt_fill_array_close1_open2(&state, out, 1000); + + FILE *fp; + fp = fopen("dSFMT-testset-1.csv", "w"); + if(fp == NULL){ + printf("Couldn't open file\n"); + return -1; + } + fprintf(fp, "seed, %" PRIu32 "\n", seed); + for (i=0; i < 1000; i++) + { + d = out[i]; + temp = (uint64_t *)&d; + fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); + printf("%d, %" PRIu64 "\n", i, *temp); + } + fclose(fp); + + seed = 123456789UL; + dsfmt_init_gen_rand(&state, seed); + dsfmt_fill_array_close1_open2(&state, out, 1000); + fp = fopen("dSFMT-testset-2.csv", "w"); + if(fp == NULL){ + printf("Couldn't open file\n"); + return -1; + } + fprintf(fp, "seed, %" PRIu32 "\n", seed); + for (i=0; i < 1000; i++) + { + d = out[i]; + temp = (uint64_t *)&d; + fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); + printf("%d, %" PRIu64 "\n", i, *temp); + } + fclose(fp); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.c b/_randomgen/core_prng/src/dsfmt/dSFMT.c new file mode 100644 index 000000000000..3ce156699175 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.c @@ -0,0 +1,639 @@ +/** + * @file dSFMT.c + * @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT) + * based on IEEE 754 format. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (Hiroshima University) + * + * Copyright (C) 2007,2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima + * University. All rights reserved. + * + * The new BSD License is applied to this software, see LICENSE.txt + */ +#include +#include +#include +#include "dSFMT-params.h" +#include "dSFMT-common.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** dsfmt internal state vector */ +dsfmt_t dsfmt_global_data; +/** dsfmt mexp for check */ +static const int dsfmt_mexp = DSFMT_MEXP; + +/*---------------- + STATIC FUNCTIONS + ----------------*/ +inline static uint32_t ini_func1(uint32_t x); +inline static uint32_t ini_func2(uint32_t x); +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static int idxof(int i); +static void initial_mask(dsfmt_t *dsfmt); +static void period_certification(dsfmt_t *dsfmt); + +#if defined(HAVE_SSE2) +/** 1 in 64bit for sse2 */ +static const union X128I_T sse2_int_one = {{1, 1}}; +/** 2.0 double for sse2 */ +static const union X128D_T sse2_double_two = {{2.0, 2.0}}; +/** -1.0 double for sse2 */ +static const union X128D_T sse2_double_m_one = {{-1.0, -1.0}}; +#endif + +/** + * This function simulate a 32-bit array index overlapped to 64-bit + * array of LITTLE ENDIAN in BIG ENDIAN machine. + */ +#if defined(DSFMT_BIG_ENDIAN) +inline static int idxof(int i) { + return i ^ 1; +} +#else +inline static int idxof(int i) { + return i; +} +#endif + +#if defined(HAVE_SSE2) +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range [0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_c0o1(w128_t *w) { + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1]. + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0c1(w128_t *w) { + w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0o1(w128_t *w) { + w->si = _mm_or_si128(w->si, sse2_int_one.i128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); +} +#else /* standard C and altivec */ +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range [0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_c0o1(w128_t *w) { + w->d[0] -= 1.0; + w->d[1] -= 1.0; +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1]. + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0c1(w128_t *w) { + w->d[0] = 2.0 - w->d[0]; + w->d[1] = 2.0 - w->d[1]; +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0o1(w128_t *w) { + w->u[0] |= 1; + w->u[1] |= 1; + w->d[0] -= 1.0; + w->d[1] -= 1.0; +} +#endif + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_c0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_c0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_c0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0c1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0c1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0c1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function represents a function used in the initialization + * by init_by_array + * @param x 32-bit integer + * @return 32-bit integer + */ +static uint32_t ini_func1(uint32_t x) { + return (x ^ (x >> 27)) * (uint32_t)1664525UL; +} + +/** + * This function represents a function used in the initialization + * by init_by_array + * @param x 32-bit integer + * @return 32-bit integer + */ +static uint32_t ini_func2(uint32_t x) { + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; +} + +/** + * This function initializes the internal state array to fit the IEEE + * 754 format. + * @param dsfmt dsfmt state vector. + */ +static void initial_mask(dsfmt_t *dsfmt) { + int i; + uint64_t *psfmt; + + psfmt = &dsfmt->status[0].u[0]; + for (i = 0; i < DSFMT_N * 2; i++) { + psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; + } +} + +/** + * This function certificate the period of 2^{SFMT_MEXP}-1. + * @param dsfmt dsfmt state vector. + */ +static void period_certification(dsfmt_t *dsfmt) { + uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; + uint64_t tmp[2]; + uint64_t inner; + int i; +#if (DSFMT_PCV2 & 1) != 1 + int j; + uint64_t work; +#endif + + tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); + tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); + + inner = tmp[0] & pcv[0]; + inner ^= tmp[1] & pcv[1]; + for (i = 32; i > 0; i >>= 1) { + inner ^= inner >> i; + } + inner &= 1; + /* check OK */ + if (inner == 1) { + return; + } + /* check NG, and modification */ +#if (DSFMT_PCV2 & 1) == 1 + dsfmt->status[DSFMT_N].u[1] ^= 1; +#else + for (i = 1; i >= 0; i--) { + work = 1; + for (j = 0; j < 64; j++) { + if ((work & pcv[i]) != 0) { + dsfmt->status[DSFMT_N].u[i] ^= work; + return; + } + work = work << 1; + } + } +#endif + return; +} + +/*---------------- + PUBLIC FUNCTIONS + ----------------*/ +/** + * This function returns the identification string. The string shows + * the Mersenne exponent, and all parameters of this generator. + * @return id string. + */ +const char *dsfmt_get_idstring(void) { + return DSFMT_IDSTR; +} + +/** + * This function returns the minimum size of array used for \b + * fill_array functions. + * @return minimum size of array used for fill_array functions. + */ +int dsfmt_get_min_array_size(void) { + return DSFMT_N64; +} + +/** + * This function fills the internal state array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + */ +void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { + int i; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&dsfmt->status[0], &dsfmt->status[0], + &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [1, 2) to the + * specified array[] by one call. The number of pseudorandom numbers + * is specified by the argument \b size, which must be at least (SFMT_MEXP + * / 128) * 2 and a multiple of two. The function + * get_min_array_size() returns this minimum size. The generation by + * this function is much faster than the following fill_array_xxx functions. + * + * For initialization, init_gen_rand() or init_by_array() must be called + * before the first call of this function. This function can not be + * used after calling genrand_xxx functions, without initialization. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. The pointer to the array must be "aligned" + * (namely, must be a multiple of 16) in the SIMD version, since it + * refers to the address of a 128-bit integer. In the standard C + * version, the pointer is arbitrary. + * + * @param size the number of 64-bit pseudorandom integers to be + * generated. size must be a multiple of 2, and greater than or equal + * to (SFMT_MEXP / 128) * 2. + * + * @note \b memalign or \b posix_memalign is available to get aligned + * memory. Mac OSX doesn't have these functions, but \b malloc of OSX + * returns the pointer to the aligned memory block. + */ +void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1] to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [0, 1) to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param dsfmt dsfmt state vector. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1) to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); +} + +#if defined(__INTEL_COMPILER) +# pragma warning(disable:981) +#endif +/** + * This function initializes the internal state array with a 32-bit + * integer seed. + * @param dsfmt dsfmt state vector. + * @param seed a 32-bit integer used as the seed. + * @param mexp caller's mersenne expornent + */ +void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { + int i; + uint32_t *psfmt; + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + psfmt = &dsfmt->status[0].u32[0]; + psfmt[idxof(0)] = seed; + for (i = 1; i < (DSFMT_N + 1) * 4; i++) { + psfmt[idxof(i)] = 1812433253UL + * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds + * @param dsfmt dsfmt state vector. + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * @param mexp caller's mersenne expornent + */ +void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length, int mexp) { + int i, j, count; + uint32_t r; + uint32_t *psfmt32; + int lag; + int mid; + int size = (DSFMT_N + 1) * 4; /* pulmonary */ + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + if (size >= 623) { + lag = 11; + } else if (size >= 68) { + lag = 7; + } else if (size >= 39) { + lag = 5; + } else { + lag = 3; + } + mid = (size - lag) / 2; + + psfmt32 = &dsfmt->status[0].u32[0]; + memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); + if (key_length + 1 > size) { + count = key_length + 1; + } else { + count = size; + } + r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] + ^ psfmt32[idxof((size - 1) % size)]); + psfmt32[idxof(mid % size)] += r; + r += key_length; + psfmt32[idxof((mid + lag) % size)] += r; + psfmt32[idxof(0)] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += init_key[j] + i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(psfmt32[idxof(i)] + + psfmt32[idxof((i + mid) % size)] + + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] ^= r; + r -= i; + psfmt32[idxof((i + mid + lag) % size)] ^= r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; +} +#if defined(__INTEL_COMPILER) +# pragma warning(default:981) +#endif + +#if defined(__cplusplus) +} +#endif + +extern inline double dsfmt_next_double(dsfmt_state *state); + +extern inline uint64_t dsfmt_next64(dsfmt_state *state); + +extern inline uint32_t dsfmt_next32(dsfmt_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h new file mode 100644 index 000000000000..52b6b3aedcc2 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -0,0 +1,678 @@ +#pragma once +/** + * @file dSFMT.h + * + * @brief double precision SIMD oriented Fast Mersenne Twister(dSFMT) + * pseudorandom number generator based on IEEE 754 format. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (Hiroshima University) + * + * Copyright (C) 2007, 2008 Mutsuo Saito, Makoto Matsumoto and + * Hiroshima University. All rights reserved. + * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The new BSD License is applied to this software. + * see LICENSE.txt + * + * @note We assume that your system has inttypes.h. If your system + * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t, + * and you have to define PRIu64 and PRIx64 in this file as follows: + * @verbatim + typedef unsigned int uint32_t + typedef unsigned long long uint64_t + #define PRIu64 "llu" + #define PRIx64 "llx" +@endverbatim + * uint32_t must be exactly 32-bit unsigned integer type (no more, no + * less), and uint64_t must be exactly 64-bit unsigned integer type. + * PRIu64 and PRIx64 are used for printf function to print 64-bit + * unsigned int and 64-bit unsigned int in hexadecimal format. + */ + +#ifndef DSFMT_H +#define DSFMT_H +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include + +#if !defined(DSFMT_MEXP) +#ifdef __GNUC__ + #warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." +#endif + #define DSFMT_MEXP 19937 +#endif +/*----------------- + BASIC DEFINITIONS + -----------------*/ +/* Mersenne Exponent. The period of the sequence + * is a multiple of 2^DSFMT_MEXP-1. + * #define DSFMT_MEXP 19937 */ +/** DSFMT generator has an internal state array of 128-bit integers, + * and N is its size. */ +#define DSFMT_N ((DSFMT_MEXP - 128) / 104 + 1) +/** N32 is the size of internal state array when regarded as an array + * of 32-bit integers.*/ +#define DSFMT_N32 (DSFMT_N * 4) +/** N64 is the size of internal state array when regarded as an array + * of 64-bit integers.*/ +#define DSFMT_N64 (DSFMT_N * 2) + +#if !defined(DSFMT_BIG_ENDIAN) +# if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +# if __BYTE_ORDER == __BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) +# if _BYTE_ORDER == _BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) +# if __BYTE_ORDER__ == __BIG_ENDIAN__ +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) +# if BYTE_ORDER == BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) \ + || defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) +# define DSFMT_BIG_ENDIAN 1 +# endif +#endif + +#if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) +# undef DSFMT_BIG_ENDIAN +#endif + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# include +#elif defined(_MSC_VER) || defined(__BORLANDC__) +# if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +# ifndef UINT64_C +# define UINT64_C(v) (v ## ui64) +# endif +# define DSFMT_UINT32_DEFINED +# if !defined(inline) && !defined(__cplusplus) +# define inline __forceinline +# endif +# endif +#else +# include +# if !defined(inline) && !defined(__cplusplus) +# if defined(__GNUC__) +# define inline __forceinline__ +# else +# define inline +# endif +# endif +#endif + +#ifndef PRIu64 +# if defined(_MSC_VER) || defined(__BORLANDC__) +# define PRIu64 "I64u" +# define PRIx64 "I64x" +# else +# define PRIu64 "llu" +# define PRIx64 "llx" +# endif +#endif + +#ifndef UINT64_C +# define UINT64_C(v) (v ## ULL) +#endif + +/*------------------------------------------ + 128-bit SIMD like data type for standard C + ------------------------------------------*/ +#if defined(HAVE_ALTIVEC) +# if !defined(__APPLE__) +# include +# endif +/** 128-bit data structure */ +union W128_T { + vector unsigned int s; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; + +#elif defined(HAVE_SSE2) +# include + +/** 128-bit data structure */ +union W128_T { + __m128i si; + __m128d sd; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; +#else /* standard C */ +/** 128-bit data structure */ +union W128_T { + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; +#endif + +/** 128-bit data type */ +typedef union W128_T w128_t; + +/** the 128-bit internal state array */ +struct DSFMT_T { + w128_t status[DSFMT_N + 1]; + int idx; +}; +typedef struct DSFMT_T dsfmt_t; + +/** dsfmt internal state vector */ +extern dsfmt_t dsfmt_global_data; +/** dsfmt mexp for check */ +extern const int dsfmt_global_mexp; + +void dsfmt_gen_rand_all(dsfmt_t *dsfmt); +void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size); +void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size); +void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size); +void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size); +void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp); +void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length, int mexp); +const char *dsfmt_get_idstring(void); +int dsfmt_get_min_array_size(void); + +#if defined(__GNUC__) +# define DSFMT_PRE_INLINE inline static +# define DSFMT_PST_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) && _MSC_VER >= 1200 +# define DSFMT_PRE_INLINE __forceinline static +# define DSFMT_PST_INLINE +#else +# define DSFMT_PRE_INLINE inline static +# define DSFMT_PST_INLINE +#endif +DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], + int key_length) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length) DSFMT_PST_INLINE; + +/** + * This function generates and returns unsigned 32-bit integer. + * This is slower than SFMT, only for convenience usage. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { + uint32_t r; + uint64_t *psfmt64 = &dsfmt->status[0].u[0]; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++] & 0xffffffffU; + return r; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [1, 2). This is + * the primitive and faster than generating numbers in other ranges. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { + double r; + double *psfmt64 = &dsfmt->status[0].d[0]; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++]; + return r; +} + +/** + * This function generates and returns unsigned 32-bit integer. + * This is slower than SFMT, only for convenience usage. + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +inline static uint32_t dsfmt_gv_genrand_uint32(void) { + return dsfmt_genrand_uint32(&dsfmt_global_data); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [1, 2). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_gv_genrand_close1_open2(void) { + return dsfmt_genrand_close1_open2(&dsfmt_global_data); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [0, 1). + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { + return dsfmt_genrand_close1_open2(dsfmt) - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [0, 1). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_gv_genrand_close_open(void) { + return dsfmt_gv_genrand_close1_open2() - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1]. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { + return 2.0 - dsfmt_genrand_close1_open2(dsfmt); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1]. + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_gv_genrand_open_close(void) { + return 2.0 - dsfmt_gv_genrand_close1_open2(); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1). + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { + double *dsfmt64 = &dsfmt->status[0].d[0]; + union { + double d; + uint64_t u; + } r; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r.d = dsfmt64[dsfmt->idx++]; + r.u |= 1; + return r.d - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +inline static double dsfmt_gv_genrand_open_open(void) { + return dsfmt_genrand_open_open(&dsfmt_global_data); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [1, 2) to the + * specified array[] by one call. This function is the same as + * dsfmt_fill_array_close1_open2() except that this function uses + * \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() + */ +inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { + dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1] to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() and \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { + dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [0, 1) to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { + dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1) to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { + dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); +} + +/** + * This function initializes the internal state array with a 32-bit + * integer seed. + * @param dsfmt dsfmt state vector. + * @param seed a 32-bit integer used as the seed. + */ +inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { + dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); +} + +/** + * This function initializes the internal state array with a 32-bit + * integer seed. This function uses \b global variables. + * @param seed a 32-bit integer used as the seed. + * see also \sa dsfmt_init_gen_rand() + */ +inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { + dsfmt_init_gen_rand(&dsfmt_global_data, seed); +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds. + * @param dsfmt dsfmt state vector + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + */ +inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length) { + dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds. + * This function uses \b global variables. + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * see also \sa dsfmt_init_by_array() + */ +inline static void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { + dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); +} + +#if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) +DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) + DSFMT_PST_INLINE; + +/** + * This function is just the same as dsfmt_get_idstring(). + * @return id string. + * see also \sa dsfmt_get_idstring() + */ +inline static const char *get_idstring(void) { + return dsfmt_get_idstring(); +} + +/** + * This function is just the same as dsfmt_get_min_array_size(). + * @return minimum size of array used for fill_array functions. + * see also \sa dsfmt_get_min_array_size() + */ +inline static int get_min_array_size(void) { + return dsfmt_get_min_array_size(); +} + +/** + * This function is just the same as dsfmt_gv_init_gen_rand(). + * @param seed a 32-bit integer used as the seed. + * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). + */ +inline static void init_gen_rand(uint32_t seed) { + dsfmt_gv_init_gen_rand(seed); +} + +/** + * This function is just the same as dsfmt_gv_init_by_array(). + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). + */ +inline static void init_by_array(uint32_t init_key[], int key_length) { + dsfmt_gv_init_by_array(init_key, key_length); +} + +/** + * This function is just the same as dsfmt_gv_genrand_close1_open2(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_close1_open2() \sa + * dsfmt_gv_genrand_close1_open2() + */ +inline static double genrand_close1_open2(void) { + return dsfmt_gv_genrand_close1_open2(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_close_open(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_close_open() \sa + * dsfmt_gv_genrand_close_open() + */ +inline static double genrand_close_open(void) { + return dsfmt_gv_genrand_close_open(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_open_close(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_open_close() \sa + * dsfmt_gv_genrand_open_close() + */ +inline static double genrand_open_close(void) { + return dsfmt_gv_genrand_open_close(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_open_open(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_open_open() \sa + * dsfmt_gv_genrand_open_open() + */ +inline static double genrand_open_open(void) { + return dsfmt_gv_genrand_open_open(); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_open_close(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_open_close(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void fill_array_open_close(double array[], int size) { + dsfmt_gv_fill_array_open_close(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_close_open(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_close_open(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void fill_array_close_open(double array[], int size) { + dsfmt_gv_fill_array_close_open(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_open_open(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_open_open(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void fill_array_open_open(double array[], int size) { + dsfmt_gv_fill_array_open_open(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_close1_open2(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +inline static void fill_array_close1_open2(double array[], int size) { + dsfmt_gv_fill_array_close1_open2(array, size); +} +#endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ + +#if defined(__cplusplus) +} +#endif + +#endif /* DSFMT_H */ + + +typedef struct s_dsfmt_state { + dsfmt_t *state; + int has_uint32; + uint32_t uinteger; + + double *buffered_uniforms; + int buffer_loc; +} dsfmt_state; + +static inline double dsfmt_next_double(dsfmt_state *state) { + if (state->buffer_loc < DSFMT_N64) { + double out = state->buffered_uniforms[state->buffer_loc]; + state->buffer_loc++; + return out; + } + dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, DSFMT_N64); + state->buffer_loc = 1; + return state->buffered_uniforms[0]; +} + +static inline uint64_t dsfmt_next64(dsfmt_state *state) { + /* Discard bottom 16 bits */ + double d = dsfmt_next_double(state); + uint64_t out; + uint64_t *tmp; + tmp = (uint64_t *)&d; + out = (*tmp >> 16) << 32; + d = dsfmt_next_double(state); + tmp = (uint64_t *)&d; + out |= (*tmp >> 16) & 0xffffffff; + return out; +} + + +static inline uint32_t dsfmt_next32(dsfmt_state *state) { + /* Discard bottom 16 bits */ + double d = dsfmt_next_double(state); + uint64_t *out = (uint64_t *)&d; + return (uint32_t)((*out >> 16) & 0xffffffff); +} diff --git a/_randomgen/core_prng/src/mt19937/mt19937.c b/_randomgen/core_prng/src/mt19937/mt19937.c index 06ce7a16f4e8..699efd21d08a 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937.c +++ b/_randomgen/core_prng/src/mt19937/mt19937.c @@ -1,7 +1,5 @@ #include "mt19937.h" -extern inline uint32_t mt19937_random(mt19937_state *state); - void mt19937_seed(mt19937_state *state, uint32_t seed) { int pos; diff --git a/_randomgen/demo.py b/_randomgen/demo.py index b1956831c156..29f440505330 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -1,7 +1,7 @@ import timeit from core_prng import Xoroshiro128, ThreeFry, MT19937, \ - Xorshift1024, PCG64, Philox + Xorshift1024, PCG64, Philox, DSFMT from core_prng.generator import RandomGenerator print(RandomGenerator().random_integer(32)) @@ -62,7 +62,13 @@ print(state) rg.state = state -PRNGS = [MT19937, PCG64, Philox, ThreeFry, Xoroshiro128, Xorshift1024] +rg = RandomGenerator(DSFMT()) +state = rg.state +print(state) +rg.state = state + + +PRNGS = [MT19937, PCG64, Philox, ThreeFry, Xoroshiro128, Xorshift1024, DSFMT] setup = """ from core_prng import {module} diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 663c0056c7e0..d1dc482b882f 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,3 +1,5 @@ +import struct +import sys import os from os.path import join @@ -10,6 +12,8 @@ Cython.Compiler.Options.annotate = True + +USE_SSE2 = True if not '--no-sse2' in sys.argv else False MOD_DIR = './core_prng' DEBUG = False @@ -24,6 +28,17 @@ EXTRA_LINK_ARGS += ['-debug'] EXTRA_COMPILE_ARGS = ["-Zi", "/Od"] +if USE_SSE2: + if os.name == 'nt': + EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] + if struct.calcsize('P') < 8: + EXTRA_COMPILE_ARGS += ['/arch:SSE2'] + else: + EXTRA_COMPILE_ARGS += ['-msse2'] +DSFMT_DEFS = [('DSFMT_MEXP', '19937')] +if USE_SSE2: + DSFMT_DEFS += [('HAVE_SSE2', '1')] + extensions = [Extension('core_prng.entropy', sources=[join(MOD_DIR, 'entropy.pyx'), join(MOD_DIR, 'src', 'entropy', 'entropy.c')], @@ -32,6 +47,15 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("core_prng.dsfmt", + ["core_prng/dsfmt.pyx", + join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c')], + include_dirs=[np.get_include(), + join(MOD_DIR, 'src', 'dsfmt')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + define_macros=DSFMT_DEFS, + ), Extension("core_prng.mt19937", ["core_prng/mt19937.pyx", join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], From a9cb58d6079566d0e0ccbb914075ac67c2513374 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 18:03:32 +0000 Subject: [PATCH 026/138] ENH: Add out, ziggurat for exponential Add out to fill existing arrays Add ziggurat for exponential --- _randomgen/TODO.md | 10 +-- _randomgen/core_prng/common.pxd | 10 ++- _randomgen/core_prng/common.pyx | 46 +++++++++-- _randomgen/core_prng/generator.pyx | 57 +++++++++----- _randomgen/core_prng/philox.pyx | 76 +++++++++++-------- .../src/distributions/distributions.c | 42 +++++++++- .../src/distributions/distributions.h | 4 +- _randomgen/core_prng/threefry.pyx | 74 +++++++++++------- 8 files changed, 224 insertions(+), 95 deletions(-) diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index 2be06b8ec4bf..93d6ca0536b4 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -1,28 +1,28 @@ # TODO -2. Add dSFMT 6. Port over 0 parameter distributions - * standard exponential ziggurat float * standard normal ziggurat * standard normal ziggurat float -8. Restore ability to use `out` in core distributions -12. Key/Counter for ThreeFry 13. Simplify state ## Done 1. Add PCG64 +2. Add dSFMT 3. Add xorshift2014 4. Augment state to include has_gauss and gauss 5. Augment state to have binomial structure 6. Port over 0 parameter distributions * standard exponential ziggurat + * standard exponential ziggurat float * standard exponential float * standard normal * standard normal float * standard gamma - Not implement: This is a 1 param * standard gamma float - Not implement: This is a 1 param 7. Remove SplitMix64 as an external generator +8. Restore ability to use `out` in core distributions 9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump 10. Seed/Inc for PCG64 11. Advance/Jump for PCG64 -0. NOT IMPLEMENTABLE due to limits on inheritance in Cython: Use inheritance to simplify CorePRNG structure. The natural base is +12. Key/Counter for ThreeFry +0. **NOT IMPLEMENTABLE** due to limits on inheritance in Cython: Use inheritance to simplify CorePRNG structure. The natural base is xoroshiro128. diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index c8b469cc52bc..c8b15b77d409 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,4 +1,6 @@ from libc.stdint cimport uint32_t, uint64_t +import numpy as np +cimport numpy as np cdef extern from "src/distributions/distributions.h": ctypedef double (*random_double_0)(void *st) nogil @@ -42,8 +44,10 @@ cdef extern from "src/distributions/distributions.h": cdef inline double uint64_to_double(uint64_t rnd) nogil: return (rnd >> 11) * (1.0 / 9007199254740992.0) -cdef object double_fill(void *func, void *state, object size, object lock) +cdef object double_fill(void *func, void *state, object size, object lock, object out) -cdef object float_fill(void *func, void *state, object size, object lock) +cdef object float_fill(void *func, void *state, object size, object lock, object out) -cdef object float_fill_from_double(void *func, void *state, object size, object lock) \ No newline at end of file +cdef object float_fill_from_double(void *func, void *state, object size, object lock, object out) + +cdef np.ndarray int_to_array(object value, object name, object bits) \ No newline at end of file diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index b6e832c49219..0d18a8fc8664 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -4,6 +4,27 @@ from common cimport * np.import_array() +cdef np.ndarray int_to_array(object value, object name, object bits): + len = bits // 64 + value = np.asarray(value) + 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=np.uint64) + for i in range(len): + out[i] = value % 2**64 + value >>= 64 + else: + out = value.astype(np.uint64) + 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 @@ -19,7 +40,7 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size and out cannot be simultaneously used') -cdef object double_fill(void *func, void *state, object size, object lock): +cdef object double_fill(void *func, void *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef double *out_array_data cdef np.ndarray out_array @@ -29,7 +50,11 @@ cdef object double_fill(void *func, void *state, object size, object lock): with lock: return random_func(state) - out_array = np.empty(size, np.double) + if out is not None: + check_output(out, np.float64, size) + out_array = out + else: + out_array = np.empty(size, np.double) n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) @@ -38,7 +63,7 @@ cdef object double_fill(void *func, void *state, object size, object lock): out_array_data[i] = random_func(state) return out_array -cdef object float_fill(void *func, void *state, object size, object lock): +cdef object float_fill(void *func, void *state, object size, object lock, object out): cdef random_float_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -48,7 +73,11 @@ cdef object float_fill(void *func, void *state, object size, object lock): with lock: return random_func(state) - out_array = np.empty(size, np.float32) + if out is not None: + check_output(out, np.float32, size) + out_array = out + else: + out_array = np.empty(size, np.float32) n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) @@ -57,7 +86,7 @@ cdef object float_fill(void *func, void *state, object size, object lock): out_array_data[i] = random_func(state) return out_array -cdef object float_fill_from_double(void *func, void *state, object size, object lock): +cdef object float_fill_from_double(void *func, void *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -67,7 +96,11 @@ cdef object float_fill_from_double(void *func, void *state, object size, object with lock: return random_func(state) - out_array = np.empty(size, np.float32) + if out is not None: + check_output(out, np.float32, size) + out_array = out + else: + out_array = np.empty(size, np.float32) n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) @@ -75,3 +108,4 @@ cdef object float_fill_from_double(void *func, void *state, object size, object for i in range(n): out_array_data[i] = random_func(state) return out_array + diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 1447e44783d1..ab9a57b5ad02 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -22,12 +22,14 @@ np.import_array() cdef extern from "src/distributions/distributions.h": double random_double(prng_t *prng_state) nogil - float random_float(prng_t *prng_state) nogil - uint32_t random_uint32(prng_t *prng_state) nogil + double random_standard_exponential_zig_double(prng_t *prng_state) nogil + double random_gauss(prng_t *prng_state) nogil double random_standard_exponential(prng_t *prng_state) nogil + float random_standard_exponential_float(prng_t *prng_state) nogil - double random_gauss(prng_t *prng_state) - float random_gauss_float(prng_t *prng_state) + float random_float(prng_t *prng_state) nogil + float random_gauss_float(prng_t *prng_state) nogil + float random_standard_exponential_zig_float(prng_t *prng_state) nogil cdef class RandomGenerator: """ @@ -98,7 +100,7 @@ cdef class RandomGenerator: if bits == 64: return self._prng.next_uint64(self._prng.state) elif bits == 32: - return random_uint32(self._prng) + return self._prng.next_uint32(self._prng.state) else: raise ValueError('bits must be 32 or 64') @@ -110,7 +112,7 @@ cdef class RandomGenerator: else: raise ValueError('bits must be 32 or 64') - def random_sample(self, size=None, dtype=np.float64): + def random_sample(self, size=None, dtype=np.float64, out=None): """ random_sample(size=None, dtype='d', out=None) @@ -132,6 +134,10 @@ cdef class RandomGenerator: 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 ------- @@ -158,15 +164,15 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double, self._prng, size, self.lock) + return double_fill(&random_double, self._prng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_float, self._prng, size, self.lock) + return float_fill(&random_float, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) - def standard_exponential(self, size=None, dtype=np.float64): + def standard_exponential(self, size=None, dtype=np.float64, method=u'zig', out=None): """ - standard_exponential(size=None, dtype='d', method='inv', out=None) + standard_exponential(size=None, dtype='d', method='zig', out=None) Draw samples from the standard exponential distribution. @@ -183,6 +189,13 @@ cdef class RandomGenerator: 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 ------- @@ -197,17 +210,23 @@ cdef class RandomGenerator: """ key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_standard_exponential, self._prng, size, self.lock) + if method == u'zig': + return double_fill(&random_standard_exponential_zig_double, self._prng, size, self.lock, out) + else: + return double_fill(&random_standard_exponential, self._prng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_standard_exponential_float, self._prng, size, self.lock) + if method == u'zig': + return float_fill(&random_standard_exponential_zig_float, self._prng, size, self.lock, out) + else: + return float_fill(&random_standard_exponential_float, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) # Complicated, continuous distributions: - def standard_normal(self, size=None, dtype=np.float64, method='bm'): + def standard_normal(self, size=None, dtype=np.float64, method=u'zig', out=None): """ - standard_normal(size=None, dtype='d', method='bm', out=None) + standard_normal(size=None, dtype='d', method='zig', out=None) Draw samples from a standard Normal distribution (mean=0, stdev=1). @@ -222,7 +241,7 @@ cdef class RandomGenerator: (or 'float32'). All dtypes are determined by their name. The default value is 'd'. method : str, optional - Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations + Either 'bm' or 'zig'. 'bm' uses the Box-Muller transformations 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, @@ -251,14 +270,14 @@ cdef class RandomGenerator: if key == 'float64': if method == u'zig': raise NotImplementedError - #return double_fill(&self.rng_state, &random_gauss_zig_double_fill, size, self.lock, out) + #return double_fill(&random_gauss_zig_double, self._prng, size, self.lock, out) else: - return double_fill(&random_gauss, self._prng, size, self.lock) + return double_fill(&random_gauss, self._prng, size, self.lock, out) elif key == 'float32': if method == u'zig': raise NotImplementedError - #return float_fill(&self.rng_state, &random_gauss_zig_float_fill, size, self.lock, out) + #return float_fill(&random_gauss_zig_float, self._prng, size, self.lock, out) else: - return float_fill(&random_gauss_float, self._prng, size, self.lock) + return float_fill(&random_gauss_float, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_normal' % key) diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 111d702be680..474bc752ebf0 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -2,7 +2,6 @@ from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New import numpy as np -cimport numpy as np from common cimport * from core_prng.entropy import random_entropy @@ -11,7 +10,7 @@ cimport entropy np.import_array() -cdef extern from "src/philox/philox.h": +cdef extern from 'src/philox/philox.h': struct s_r123array2x64: uint64_t v[2] @@ -67,7 +66,7 @@ cdef class Philox: cdef prng_t *_prng cdef public object _prng_capsule - def __init__(self, seed=None): + def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(philox_state)) self.rng_state.ctr = malloc( sizeof(philox4x64_ctr_t)) @@ -75,14 +74,14 @@ cdef class Philox: sizeof(philox4x64_key_t)) self._prng = malloc(sizeof(prng_t)) self._prng.binomial = malloc(sizeof(binomial_t)) - self.seed(seed) + self.seed(seed, counter, key) self._prng.state = self.rng_state self._prng.next_uint64 = &philox_uint64 self._prng.next_uint32 = &philox_uint32 self._prng.next_double = &philox_double - cdef const char *name = "CorePRNG" + cdef const char *name = 'CorePRNG' self._prng_capsule = PyCapsule_New( self._prng, name, NULL) # Pickling support: @@ -141,9 +140,9 @@ cdef class Philox: for i in range(cnt): self._prng.next_uint64(self._prng.state) - def seed(self, seed=None): + def seed(self, seed=None, counter=None, key=None): """ - seed(seed=None, stream=None) + seed(seed=None, counter=None, key=None) Seed the generator. @@ -155,26 +154,46 @@ cdef class Philox: ---------- seed : int, optional Seed for ``RandomState``. + counter : {int array}, optional + Positive integer less than 2**256 containing the counter position + or a 4 element array of uint64 containing the counter + key : {int, array}, options + Positive integer less than 2**128 containing the key + or a 2 element array of uint64 containing the key Raises ------ ValueError - If seed values are out of range for the PRNG. + If values are out of range for the PRNG. + + Notes + ----- + The two representation of the counter and key are related through + array[i] = (value // 2**(64*i)) % 2**64. """ - ub = 2 ** 64 - if seed is None: - try: - state = random_entropy(4) - except RuntimeError: - state = random_entropy(4, 'fallback') - state = state.view(np.uint64) + if seed is not None and key is not None: + raise ValueError('seed and key cannot be both used') + ub = 2 ** 64 + if key is None: + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 2) + for i in range(2): + self.rng_state.key.v[i] = state[i] else: - state = entropy.seed_by_array(seed, 2) - # TODO: Need to be able to set the key and counter directly + key = int_to_array(key, 'key', 128) + 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) for i in range(4): - self.rng_state.ctr.v[i] = 0 - self.rng_state.key.v[0] = state[0] - self.rng_state.key.v[1] = state[1] + self.rng_state.ctr.v[i] = counter[i] + self._reset_state_variables() @property @@ -189,7 +208,7 @@ cdef class Philox: if i < 2: key[i] = self.rng_state.key.v[i] - state = {'ctr': ctr, 'key': key} + state = {'counter': ctr, 'key': key} return {'prng': self.__class__.__name__, 'state': state, 'buffer': buffer, @@ -206,7 +225,7 @@ cdef class Philox: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): - self.rng_state.ctr.v[i] = value['state']['ctr'][i] + self.rng_state.ctr.v[i] = value['state']['counter'][i] self.rng_state.buffer[i] = value['buffer'][i] if i < 2: self.rng_state.key.v[i] = value['state']['key'][i] @@ -216,17 +235,12 @@ cdef class Philox: def jump(self): """Jump the state as-if 2**128 draws have been made""" - philox_jump(self.rng_state) - return self + return self.advance(2**128) def advance(self, step): """Advance the state as-if a specific number of draws have been made""" - cdef np.ndarray step_a = np.zeros(4, dtype=np.uint64) - if step >= 2 ** 256 or step < 0: - raise ValueError('step must be between 0 and 2**256-1') + cdef np.ndarray step_a + step_a = int_to_array(step, 'step', 256) loc = 0 - while step > 0: - step_a[loc] = step % 2 ** 64 - step >>= 64 - loc += 1 philox_advance( step_a.data, self.rng_state) + return self diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 6c19ad020581..7a348d5325e3 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -121,4 +121,44 @@ double standard_exponential_zig_double(prng_t *prng_state) double random_standard_exponential_zig_double(prng_t *prng_state) { return standard_exponential_zig_double(prng_state); -} \ No newline at end of file +} + +static NPY_INLINE float standard_exponential_zig_float(prng_t *prng_state); + +static float standard_exponential_zig_float_unlikely(prng_t *prng_state, uint8_t idx, float x) +{ + if (idx == 0) + { + return ziggurat_exp_r_f - logf(random_float(prng_state)); + } + else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(prng_state) + fe_float[idx] < expf(-x)) + { + return x; + } + else + { + return standard_exponential_zig_float(prng_state); + } +} + +static NPY_INLINE float standard_exponential_zig_float(prng_t *prng_state) +{ + uint32_t ri; + uint8_t idx; + float x; + ri = prng_state->next_uint32(prng_state->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_float_unlikely(prng_state, idx, x); +} + +float random_standard_exponential_zig_float(prng_t *prng_state) +{ + return standard_exponential_zig_float(prng_state); +} diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 757029074285..028557ae3d62 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -67,4 +67,6 @@ double random_gauss(prng_t *prng_state); float random_gauss_float(prng_t *prng_state); -double random_standard_exponential_zig_double(prng_t *prng_state); \ No newline at end of file +double random_standard_exponential_zig_double(prng_t *prng_state); + +float random_standard_exponential_zig_float(prng_t *prng_state); \ No newline at end of file diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 3c669a439ca2..dfcc6e41da9d 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -2,7 +2,6 @@ from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New import numpy as np -cimport numpy as np from common cimport * from core_prng.entropy import random_entropy @@ -11,7 +10,7 @@ cimport entropy np.import_array() -cdef extern from "src/threefry/threefry.h": +cdef extern from 'src/threefry/threefry.h': struct s_r123array4x64: uint64_t v[4] @@ -63,20 +62,20 @@ cdef class ThreeFry: cdef prng_t *_prng cdef public object _prng_capsule - def __init__(self, seed=None): + def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry_state)) self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) self._prng = malloc(sizeof(prng_t)) self._prng.binomial = malloc(sizeof(binomial_t)) - self.seed(seed) + self.seed(seed, counter, key) self._prng.state = self.rng_state self._prng.next_uint64 = &threefry_uint64 self._prng.next_uint32 = &threefry_uint32 self._prng.next_double = &threefry_double - cdef const char *name = "CorePRNG" + cdef const char *name = 'CorePRNG' self._prng_capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: @@ -135,9 +134,9 @@ cdef class ThreeFry: for i in range(cnt): self._prng.next_uint64(self._prng.state) - def seed(self, seed=None): + def seed(self, seed=None, counter=None, key=None): """ - seed(seed=None, stream=None) + seed(seed=None, counter=None, key=None) Seed the generator. @@ -149,25 +148,47 @@ cdef class ThreeFry: ---------- seed : int, optional Seed for ``RandomState``. + counter : {int array}, optional + Positive integer less than 2**256 containing the counter position + or a 4 element array of uint64 containing the counter + key : {int, array}, options + Positive integer less than 2**256 containing the key + or a 4 element array of uint64 containing the key Raises ------ ValueError - If seed values are out of range for the PRNG. + If values are out of range for the PRNG. + + Notes + ----- + The two representation of the counter and key are related through + array[i] = (value // 2**(64*i)) % 2**64. """ + if seed is not None and key is not None: + raise ValueError('seed and key cannot be both used') ub = 2 ** 64 - if seed is None: - try: - state = random_entropy(8) - except RuntimeError: - state = random_entropy(8, 'fallback') - state = state.view(np.uint64) + if key is None: + if seed is None: + try: + state = random_entropy(8) + except RuntimeError: + state = random_entropy(8, 'fallback') + state = state.view(np.uint64) + else: + state = entropy.seed_by_array(seed, 4) + for i in range(4): + self.rng_state.key.v[i] = state[i] else: - state = entropy.seed_by_array(seed, 4) - # TODO: Need to be able to set the key and counter directly + key = int_to_array(key, 'key', 256) + for i in range(4): + self.rng_state.key.v[i] = key[i] + + counter = 0 if counter is None else counter + counter = int_to_array(counter, 'counter', 256) for i in range(4): - self.rng_state.ctr.v[i] = 0 - self.rng_state.key.v[i] = state[i] + self.rng_state.ctr.v[i] = counter[i] + self._reset_state_variables() @property @@ -180,7 +201,7 @@ cdef class ThreeFry: ctr[i] = self.rng_state.ctr.v[i] key[i] = self.rng_state.key.v[i] buffer[i] = self.rng_state.buffer[i] - state = {'ctr':ctr,'key':key} + state = {'counter':ctr,'key':key} return {'prng': self.__class__.__name__, 'state': state, 'buffer': buffer, @@ -197,7 +218,7 @@ cdef class ThreeFry: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): - self.rng_state.ctr.v[i] = value['state']['ctr'][i] + self.rng_state.ctr.v[i] = value['state']['counter'][i] self.rng_state.key.v[i] = value['state']['key'][i] self.rng_state.buffer[i] = value['buffer'][i] self.rng_state.has_uint32 = value['has_uint32'] @@ -206,17 +227,12 @@ cdef class ThreeFry: def jump(self): """Jump the state as-if 2**128 draws have been made""" - threefry_jump(self.rng_state) - return self + return self.advance(2**128) def advance(self, step): """Advance the state as-if a specific number of draws have been made""" - cdef np.ndarray step_a = np.zeros(4,dtype=np.uint64) - if step >= 2**256 or step < 0: - raise ValueError('step must be between 0 and 2**256-1') + cdef np.ndarray step_a + step_a = int_to_array(step, 'step', 256) loc = 0 - while step > 0: - step_a[loc] = step % 2**64 - step >>= 64 - loc += 1 threefry_advance(step_a.data, self.rng_state) + return self From 626a1a069dae3e6b7fec890a7e236e0422e1f51e Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 20:13:05 +0000 Subject: [PATCH 027/138] REF: Refactor distributions Simplify naming schame Add ziggurate gauss --- _randomgen/TODO.md | 5 +- _randomgen/core_prng/generator.pyx | 36 ++--- .../src/distributions/distributions.c | 131 ++++++++++++++---- .../src/distributions/distributions.h | 19 ++- _randomgen/setup.py | 9 +- 5 files changed, 136 insertions(+), 64 deletions(-) diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md index 93d6ca0536b4..ed2697d9e826 100644 --- a/_randomgen/TODO.md +++ b/_randomgen/TODO.md @@ -1,7 +1,4 @@ # TODO -6. Port over 0 parameter distributions - * standard normal ziggurat - * standard normal ziggurat float 13. Simplify state ## Done @@ -11,6 +8,8 @@ 4. Augment state to include has_gauss and gauss 5. Augment state to have binomial structure 6. Port over 0 parameter distributions + * standard normal ziggurat + * standard normal ziggurat float * standard exponential ziggurat * standard exponential ziggurat float * standard exponential float diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index ab9a57b5ad02..44a717f67fbd 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -21,15 +21,17 @@ import core_prng.pickle np.import_array() cdef extern from "src/distributions/distributions.h": - double random_double(prng_t *prng_state) nogil - double random_standard_exponential_zig_double(prng_t *prng_state) nogil - double random_gauss(prng_t *prng_state) nogil + double random_sample(prng_t *prng_state) nogil double random_standard_exponential(prng_t *prng_state) nogil + double random_standard_exponential_zig(prng_t *prng_state) nogil + double random_gauss(prng_t *prng_state) nogil + double random_gauss_zig(prng_t* prng_state) nogil - float random_standard_exponential_float(prng_t *prng_state) nogil - float random_float(prng_t *prng_state) nogil - float random_gauss_float(prng_t *prng_state) nogil - float random_standard_exponential_zig_float(prng_t *prng_state) nogil + float random_sample_f(prng_t *prng_state) nogil + float random_standard_exponential_f(prng_t *prng_state) nogil + float random_standard_exponential_zig_f(prng_t *prng_state) nogil + float random_gauss_f(prng_t *prng_state) nogil + float random_gauss_zig_f(prng_t* prng_state) nogil cdef class RandomGenerator: """ @@ -108,7 +110,7 @@ cdef class RandomGenerator: if bits == 64: return self._prng.next_double(self._prng.state) elif bits == 32: - return random_float(self._prng) + return random_sample_f(self._prng) else: raise ValueError('bits must be 32 or 64') @@ -164,9 +166,9 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double, self._prng, size, self.lock, out) + return double_fill(&random_sample, self._prng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_float, self._prng, size, self.lock, out) + return float_fill(&random_sample_f, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) @@ -211,14 +213,14 @@ cdef class RandomGenerator: key = np.dtype(dtype).name if key == 'float64': if method == u'zig': - return double_fill(&random_standard_exponential_zig_double, self._prng, size, self.lock, out) + return double_fill(&random_standard_exponential_zig, self._prng, size, self.lock, out) else: return double_fill(&random_standard_exponential, self._prng, size, self.lock, out) elif key == 'float32': if method == u'zig': - return float_fill(&random_standard_exponential_zig_float, self._prng, size, self.lock, out) + return float_fill(&random_standard_exponential_zig_f, self._prng, size, self.lock, out) else: - return float_fill(&random_standard_exponential_float, self._prng, size, self.lock, out) + return float_fill(&random_standard_exponential_f, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) @@ -269,15 +271,13 @@ cdef class RandomGenerator: key = np.dtype(dtype).name if key == 'float64': if method == u'zig': - raise NotImplementedError - #return double_fill(&random_gauss_zig_double, self._prng, size, self.lock, out) + return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) else: return double_fill(&random_gauss, self._prng, size, self.lock, out) elif key == 'float32': if method == u'zig': - raise NotImplementedError - #return float_fill(&random_gauss_zig_float, self._prng, size, self.lock, out) + return float_fill(&random_gauss_zig_f, self._prng, size, self.lock, out) else: - return float_fill(&random_gauss_float, self._prng, size, self.lock, out) + return float_fill(&random_gauss_f, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_normal' % key) diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 7a348d5325e3..aebbbfca1973 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -2,8 +2,7 @@ #include "ziggurat.h" #include "ziggurat_constants.h" -static NPY_INLINE float uint32_to_float(prng_t *prng_state) -{ +static NPY_INLINE float next_float(prng_t *prng_state){ return (prng_state->next_uint32(prng_state->state) >> 9) * (1.0f / 8388608.0f); } @@ -11,11 +10,11 @@ uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } -float random_float(prng_t *prng_state) { - return uint32_to_float(prng_state); +float random_sample_f(prng_t *prng_state) { + return next_float(prng_state); } -double random_double(prng_t *prng_state) { +double random_sample(prng_t *prng_state) { return prng_state->next_double(prng_state->state); } @@ -23,8 +22,8 @@ double random_standard_exponential(prng_t *prng_state) { return -log(1.0 - prng_state->next_double(prng_state->state)); } -float random_standard_exponential_float(prng_t *prng_state) { - return -logf(1.0f - uint32_to_float(prng_state)); +float random_standard_exponential_f(prng_t *prng_state) { + return -logf(1.0f - next_float(prng_state)); } double random_gauss(prng_t *prng_state) @@ -55,7 +54,7 @@ double random_gauss(prng_t *prng_state) } } -float random_gauss_float(prng_t *prng_state) +float random_gauss_f(prng_t *prng_state) { if (prng_state->has_gauss_f) { @@ -69,8 +68,8 @@ float random_gauss_float(prng_t *prng_state) do { - x1 = 2.0f * uint32_to_float(prng_state) - 1.0f; - x2 = 2.0f * uint32_to_float(prng_state) - 1.0f; + x1 = 2.0f * next_float(prng_state) - 1.0f; + x2 = 2.0f * next_float(prng_state) - 1.0f; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); @@ -83,25 +82,25 @@ float random_gauss_float(prng_t *prng_state) } } -double standard_exponential_zig_double(prng_t *prng_state); +double standard_exponential_zig(prng_t *prng_state); -static double standard_exponential_zig_double_unlikely(prng_t *prng_state, uint8_t idx, double x) +static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, double x) { if (idx == 0) { - return ziggurat_exp_r - log(random_double(prng_state)); + return ziggurat_exp_r - log(prng_state->next_double(prng_state->state)); } - else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(prng_state) + fe_double[idx] < exp(-x)) + else if ((fe_double[idx - 1] - fe_double[idx]) * prng_state->next_double(prng_state->state) + fe_double[idx] < exp(-x)) { return x; } else { - return standard_exponential_zig_double(prng_state); + return standard_exponential_zig(prng_state); } } -double standard_exponential_zig_double(prng_t *prng_state) +double standard_exponential_zig(prng_t *prng_state) { uint64_t ri; uint8_t idx; @@ -115,33 +114,33 @@ double standard_exponential_zig_double(prng_t *prng_state) { return x; // 98.9% of the time we return here 1st try } - return standard_exponential_zig_double_unlikely(prng_state, idx, x); + return standard_exponential_zig_unlikely(prng_state, idx, x); } -double random_standard_exponential_zig_double(prng_t *prng_state) +double random_standard_exponential_zig(prng_t *prng_state) { - return standard_exponential_zig_double(prng_state); + return standard_exponential_zig(prng_state); } -static NPY_INLINE float standard_exponential_zig_float(prng_t *prng_state); +static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state); -static float standard_exponential_zig_float_unlikely(prng_t *prng_state, uint8_t idx, float x) +static float standard_exponential_zig_unlikely_f(prng_t *prng_state, uint8_t idx, float x) { if (idx == 0) { - return ziggurat_exp_r_f - logf(random_float(prng_state)); + return ziggurat_exp_r_f - logf(next_float(prng_state)); } - else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(prng_state) + fe_float[idx] < expf(-x)) + else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(prng_state) + fe_float[idx] < expf(-x)) { return x; } else { - return standard_exponential_zig_float(prng_state); + return standard_exponential_zig_f(prng_state); } } -static NPY_INLINE float standard_exponential_zig_float(prng_t *prng_state) +static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) { uint32_t ri; uint8_t idx; @@ -155,10 +154,86 @@ static NPY_INLINE float standard_exponential_zig_float(prng_t *prng_state) { return x; // 98.9% of the time we return here 1st try } - return standard_exponential_zig_float_unlikely(prng_state, idx, x); + return standard_exponential_zig_unlikely_f(prng_state, idx, x); } -float random_standard_exponential_zig_float(prng_t *prng_state) +float random_standard_exponential_zig_f(prng_t *prng_state) { - return standard_exponential_zig_float(prng_state); + return standard_exponential_zig_f(prng_state); } + + +double random_gauss_zig(prng_t* prng_state) +{ + uint64_t r; + int sign; + int64_t rabs; + int idx; + double x, xx, yy; + for (;;) + { + /* r = e3n52sb8 */ + r = prng_state->next_uint64(prng_state->state); + idx = r & 0xff; + r >>= 8; + sign = r & 0x1; + rabs = (int64_t)((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 (;;) + { + xx = -ziggurat_nor_inv_r * log(prng_state->next_double(prng_state->state)); + yy = -log(prng_state->next_double(prng_state->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]) * prng_state->next_double(prng_state->state) + fi_double[idx]) < exp(-0.5 * x * x)) + return x; + } + } +} + +float random_gauss_zig_f(prng_t* prng_state) +{ + uint32_t r; + int sign; + int32_t rabs; + int idx; + float x, xx, yy; + for (;;) + { + /* r = n23sb8 */ + r = prng_state->next_uint32(prng_state->state); + idx = r & 0xff; + sign = (r >> 8) & 0x1; + rabs = (int32_t)((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 (;;) + { + xx = -ziggurat_nor_inv_r_f * logf(next_float(prng_state)); + yy = -logf(next_float(prng_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(prng_state) + fi_float[idx]) < exp(-0.5 * x * x)) + return x; + } + } +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 028557ae3d62..4cd72e9d2320 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -53,20 +53,17 @@ typedef struct prng { binomial_t *binomial; } prng_t; -float random_float(prng_t *prng_state); - -double random_double(prng_t *prng_state); +float random_sample_f(prng_t *prng_state); +double random_sample(prng_t *prng_state); uint32_t random_uint32(prng_t *prng_state); double random_standard_exponential(prng_t *prng_state); - -float random_standard_exponential_float(prng_t *prng_state); +float random_standard_exponential_f(prng_t *prng_state); +double random_standard_exponential_zig(prng_t *prng_state); +float random_standard_exponential_zig_f(prng_t *prng_state); double random_gauss(prng_t *prng_state); - -float random_gauss_float(prng_t *prng_state); - -double random_standard_exponential_zig_double(prng_t *prng_state); - -float random_standard_exponential_zig_float(prng_t *prng_state); \ No newline at end of file +float random_gauss_f(prng_t *prng_state); +double random_gauss_zig(prng_t* prng_state); +float random_gauss_zig_f(prng_t* prng_state); \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index d1dc482b882f..cb633f359ac7 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,17 +1,17 @@ +import os import struct import sys -import os from os.path import join import Cython.Compiler.Options import numpy as np -import versioneer from Cython.Build import cythonize from setuptools import setup, find_packages, Distribution from setuptools.extension import Extension -Cython.Compiler.Options.annotate = True +import versioneer +Cython.Compiler.Options.annotate = True USE_SSE2 = True if not '--no-sse2' in sys.argv else False MOD_DIR = './core_prng' @@ -21,12 +21,13 @@ EXTRA_COMPILE_ARGS = [] EXTRA_LINK_ARGS = [] +EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99'] if os.name == 'nt': EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] PCG_EMULATED_MATH = True if DEBUG: EXTRA_LINK_ARGS += ['-debug'] - EXTRA_COMPILE_ARGS = ["-Zi", "/Od"] + EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] if USE_SSE2: if os.name == 'nt': From 5fe757208f5bca62f100a729ef83bcbab79c19e9 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Mar 2018 23:24:29 +0000 Subject: [PATCH 028/138] ENH: Add std gamma Add standard gamma Add array fillers --- _randomgen/core_prng/common.pxd | 68 +- _randomgen/core_prng/common.pyx | 667 +++++++++++++++++- _randomgen/core_prng/generator.pyx | 110 +++ .../src/distributions/distributions.c | 248 ++++++- .../src/distributions/distributions.h | 66 +- 5 files changed, 1116 insertions(+), 43 deletions(-) diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index c8b15b77d409..38c66814775b 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,11 +1,25 @@ -from libc.stdint cimport uint32_t, uint64_t +from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t +from cpython cimport PyInt_AsLong, PyFloat_AsDouble + import numpy as np cimport numpy as np -cdef extern from "src/distributions/distributions.h": - ctypedef double (*random_double_0)(void *st) nogil +cdef double POISSON_LAM_MAX +cdef uint64_t MAXSIZE - ctypedef float (*random_float_0)(void *st) nogil +cdef enum ConstraintType: + CONS_NONE + CONS_NON_NEGATIVE + CONS_POSITIVE + CONS_BOUNDED_0_1 + CONS_BOUNDED_0_1_NOTNAN + CONS_GT_1 + CONS_GTE_1 + CONS_POISSON + +ctypedef ConstraintType constraint_type + +cdef extern from "src/distributions/distributions.h": cdef struct s_binomial_t: int has_binomial; @@ -41,13 +55,51 @@ cdef extern from "src/distributions/distributions.h": ctypedef prng prng_t +ctypedef double (*random_double_0)(prng_t *state) nogil +ctypedef double (*random_double_1)(prng_t *state, double a) nogil +ctypedef double (*random_double_2)(prng_t *state, double a, double b) nogil +ctypedef double (*random_double_3)(prng_t *state, double a, double b, double c) nogil + +ctypedef float (*random_float_0)(prng_t *state) nogil +ctypedef float (*random_float_1)(prng_t *state, float a) nogil + +ctypedef long (*random_uint_0)(prng_t *state) nogil +ctypedef long (*random_uint_d)(prng_t *state, double a) nogil +ctypedef long (*random_uint_dd)(prng_t *state, double a, double b) nogil +ctypedef long (*random_uint_di)(prng_t *state, double a, uint64_t b) nogil +ctypedef long (*random_uint_i)(prng_t *state, long a) nogil +ctypedef long (*random_uint_iii)(prng_t *state, long a, long b, long c) nogil + +ctypedef uint32_t (*random_uint_0_32)(prng_t *state) nogil +ctypedef uint32_t (*random_uint_1_i_32)(prng_t *state, uint32_t a) nogil + +ctypedef int32_t (*random_int_2_i_32)(prng_t *state, int32_t a, int32_t b) nogil +ctypedef int64_t (*random_int_2_i)(prng_t *state, int64_t a, int64_t b) nogil + + cdef inline double uint64_to_double(uint64_t rnd) nogil: return (rnd >> 11) * (1.0 / 9007199254740992.0) -cdef object double_fill(void *func, void *state, object size, object lock, object out) +cdef object double_fill(void *func, prng_t *state, object size, object lock, object out) + +cdef object float_fill(void *func, prng_t *state, object size, object lock, object out) + +cdef object float_fill_from_double(void *func, prng_t *state, object size, object lock, object out) + +cdef np.ndarray int_to_array(object value, object name, object bits) -cdef object float_fill(void *func, void *state, object size, object lock, object out) +cdef object cont(void *func, prng_t *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 float_fill_from_double(void *func, void *state, object size, object lock, object out) +cdef object disc(void *func, prng_t *state, object size, object lock, + int narg_double, int narg_long, + 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 np.ndarray int_to_array(object value, object name, object bits) \ No newline at end of file +cdef object cont_f(void *func, prng_t *state, object size, object lock, + object a, object a_name, constraint_type a_constraint, + object out) diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 0d18a8fc8664..811824985663 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -1,3 +1,4 @@ +import sys import numpy as np cimport numpy as np from common cimport * @@ -40,7 +41,7 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size and out cannot be simultaneously used') -cdef object double_fill(void *func, void *state, object size, object lock, object out): +cdef object double_fill(void *func, prng_t *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef double *out_array_data cdef np.ndarray out_array @@ -63,7 +64,7 @@ cdef object double_fill(void *func, void *state, object size, object lock, objec out_array_data[i] = random_func(state) return out_array -cdef object float_fill(void *func, void *state, object size, object lock, object out): +cdef object float_fill(void *func, prng_t *state, object size, object lock, object out): cdef random_float_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -86,7 +87,7 @@ cdef object float_fill(void *func, void *state, object size, object lock, object out_array_data[i] = random_func(state) return out_array -cdef object float_fill_from_double(void *func, void *state, object size, object lock, object out): +cdef object float_fill_from_double(void *func, prng_t *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -109,3 +110,663 @@ cdef object float_fill_from_double(void *func, void *state, object size, object out_array_data[i] = random_func(state) return out_array + +cdef double POISSON_LAM_MAX = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10 + +cdef uint64_t MAXSIZE = sys.maxsize + +cdef int check_array_constraint(np.ndarray val, object name, constraint_type cons) except -1: + if cons == CONS_NON_NEGATIVE: + if np.any(np.signbit(val)): + raise ValueError(name + " < 0") + elif cons == CONS_POSITIVE: + if np.any(np.less_equal(val, 0)): + raise ValueError(name + " <= 0") + elif cons == CONS_BOUNDED_0_1 or cons == CONS_BOUNDED_0_1_NOTNAN: + if np.any(np.less(val, 0)) or np.any(np.greater(val, 1)): + raise ValueError(name + " <= 0 or " + name + " >= 1") + if cons == CONS_BOUNDED_0_1_NOTNAN: + if np.any(np.isnan(val)): + raise ValueError(name + ' contains NaNs') + elif cons == CONS_GT_1: + if np.any(np.less_equal(val, 1)): + raise ValueError(name + " <= 1") + elif cons == CONS_GTE_1: + if np.any(np.less(val, 1)): + raise ValueError(name + " < 1") + elif cons == CONS_POISSON: + if np.any(np.greater(val, POISSON_LAM_MAX)): + raise ValueError(name + " value too large") + if np.any(np.less(val, 0.0)): + raise ValueError(name + " < 0") + + return 0 + + + +cdef int check_constraint(double val, object name, constraint_type cons) except -1: + if cons == CONS_NON_NEGATIVE: + if np.signbit(val): + raise ValueError(name + " < 0") + elif cons == CONS_POSITIVE: + if val <= 0: + raise ValueError(name + " <= 0") + elif cons == CONS_BOUNDED_0_1 or cons == CONS_BOUNDED_0_1_NOTNAN: + if val < 0 or val > 1: + raise ValueError(name + " <= 0 or " + name + " >= 1") + if cons == CONS_BOUNDED_0_1_NOTNAN: + if np.isnan(val): + raise ValueError(name + ' contains NaNs') + elif cons == CONS_GT_1: + if val <= 1: + raise ValueError(name + " <= 1") + elif cons == CONS_GTE_1: + if val < 1: + raise ValueError(name + " < 1") + elif cons == CONS_POISSON: + if val < 0: + raise ValueError(name + " < 0") + elif val > POISSON_LAM_MAX: + raise ValueError(name + " value too large") + + return 0 + +cdef object cont_broadcast_1(void *func, prng_t *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 = (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.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 = out + + randoms_data = 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 = (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, prng_t *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 = (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.empty(size, np.double) + else: + it = np.PyArray_MultiIterNew2(a_arr, b_arr) + randoms = np.empty(it.shape, np.double) + # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_DOUBLE) + + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (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, prng_t *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 = (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.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.empty(it.shape, np.double) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] + c_val = (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, prng_t *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.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.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.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 (func)(state) + elif narg == 1: + return (func)(state, _a) + elif narg == 2: + return (func)(state, _a, _b) + elif narg == 3: + return (func)(state, _a, _b, _c) + + cdef np.npy_intp i, n + cdef np.ndarray randoms + if out is None: + randoms = np.empty(size) + else: + randoms = out + n = np.PyArray_SIZE(randoms) + + cdef double *randoms_data = 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 = (func) + for i in range(n): + randoms_data[i] = f0(state) + elif narg == 1: + f1 = (func) + for i in range(n): + randoms_data[i] = f1(state, _a) + elif narg == 2: + f2 = (func) + for i in range(n): + randoms_data[i] = f2(state, _a, _b) + elif narg == 3: + f3 = (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, prng_t *state, object size, object lock, + np.ndarray a_arr, object a_name, constraint_type a_constraint): + + cdef np.ndarray randoms + cdef long *randoms_data + cdef np.broadcast it + cdef random_uint_d f = (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.int) + 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_LONG) + + randoms_data = 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 = (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, prng_t *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 long *randoms_data + cdef np.broadcast it + cdef random_uint_dd f = (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.empty(size, np.int) + else: + it = np.PyArray_MultiIterNew2(a_arr, b_arr) + randoms = np.empty(it.shape, np.int) + # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_LONG) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (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, prng_t *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 long *randoms_data + cdef np.broadcast it + cdef random_uint_di f = (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.empty(size, np.int) + else: + it = np.PyArray_MultiIterNew2(a_arr, b_arr) + randoms = np.empty(it.shape, np.int) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] + (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, prng_t *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 long *randoms_data + cdef np.broadcast it + cdef random_uint_iii f = (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.empty(size, np.int) + else: + it = np.PyArray_MultiIterNew3(a_arr, b_arr, c_arr) + randoms = np.empty(it.shape, np.int) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] + c_val = (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, prng_t *state, object size, object lock, + np.ndarray a_arr, object a_name, constraint_type a_constraint): + cdef np.ndarray randoms + cdef long *randoms_data + cdef np.broadcast it + cdef random_uint_i f = (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.int) + else: + randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_LONG) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + randoms_data[i] = f(state, a_val) + + np.PyArray_MultiIter_NEXT(it) + + return randoms + +# Needs double , double-double , double-long, long , long-long-long +cdef object disc(void *func, prng_t *state, object size, object lock, + int narg_double, int narg_long, + 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 long _ia = 0, _ib = 0 , _ic = 0 + cdef bint is_scalar = True + if narg_double > 0: + a_arr = 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.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0 + elif narg_long == 1: + b_arr = np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0 + else: + if narg_long > 0: + a_arr = np.PyArray_FROM_OTF(a, np.NPY_LONG, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0 + if narg_long > 1: + b_arr = np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0 + if narg_long > 2 : + c_arr = np.PyArray_FROM_OTF(c, np.NPY_LONG, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0 + + if not is_scalar: + if narg_long == 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_long == 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_long == 1: + _ib = PyInt_AsLong(b) + if b_constraint != CONS_NONE and is_scalar: + check_constraint(_ib, b_name, b_constraint) + else: + if narg_long > 0: + _ia = PyInt_AsLong(a) + if a_constraint != CONS_NONE and is_scalar: + check_constraint(_ia, a_name, a_constraint) + if narg_long > 1: + _ib = PyInt_AsLong(b) + if b_constraint != CONS_NONE and is_scalar: + check_constraint(_ib, b_name, b_constraint) + if narg_long > 2 : + _ic = PyInt_AsLong(c) + if c_constraint != CONS_NONE and is_scalar: + check_constraint(_ic, c_name, c_constraint) + + if size is None: + with lock: + if narg_long == 0: + if narg_double == 0: + return (func)(state) + elif narg_double == 1: + return (func)(state, _da) + elif narg_double == 2: + return (func)(state, _da, _db) + elif narg_long == 1: + if narg_double == 0: + return (func)(state, _ia) + if narg_double == 1: + return (func)(state, _da, _ib) + else: + return (func)(state, _ia, _ib, _ic) + + cdef np.npy_intp i, n + cdef np.ndarray randoms = np.empty(size, np.int) + cdef np.int_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.PyArray_DATA(randoms) + + with lock, nogil: + if narg_long == 0: + if narg_double == 0: + f0 = (func) + for i in range(n): + randoms_data[i] = f0(state) + elif narg_double == 1: + fd = (func) + for i in range(n): + randoms_data[i] = fd(state, _da) + elif narg_double == 2: + fdd = (func) + for i in range(n): + randoms_data[i] = fdd(state, _da, _db) + elif narg_long == 1: + if narg_double == 0: + fi = (func) + for i in range(n): + randoms_data[i] = fi(state, _ia) + if narg_double == 1: + fdi = (func) + for i in range(n): + randoms_data[i] = fdi(state, _da, _ib) + else: + fiii = (func) + for i in range(n): + randoms_data[i] = fiii(state, _ia, _ib, _ic) + + return randoms + + +cdef object cont_broadcast_1_f(void *func, prng_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 = (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.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 = out + + randoms_data = 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 = (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, prng_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.PyArray_FROMANY(a, np.NPY_FLOAT32, 0, 0, requirements) + # a_arr = np.PyArray_FROM_OTF(a, np.NPY_FLOAT32, np.NPY_ALIGNED) + 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 = 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 (func)(state, _a) + + cdef np.npy_intp i, n + cdef np.ndarray randoms + if out is None: + randoms = np.empty(size, np.float32) + else: + randoms = out + n = np.PyArray_SIZE(randoms) + + cdef float *randoms_data = np.PyArray_DATA(randoms) + cdef random_float_1 f1 = func; + + with lock, nogil: + for i in range(n): + randoms_data[i] = f1(state, _a) + + if out is None: + return randoms + else: + return out \ No newline at end of file diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 44a717f67fbd..c48afd199aa4 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -26,12 +26,16 @@ cdef extern from "src/distributions/distributions.h": double random_standard_exponential_zig(prng_t *prng_state) nogil double random_gauss(prng_t *prng_state) nogil double random_gauss_zig(prng_t* prng_state) nogil + double random_standard_gamma(prng_t *prng_state, double shape) nogil + double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil float random_sample_f(prng_t *prng_state) nogil float random_standard_exponential_f(prng_t *prng_state) nogil float random_standard_exponential_zig_f(prng_t *prng_state) nogil float random_gauss_f(prng_t *prng_state) nogil float random_gauss_zig_f(prng_t* prng_state) nogil + float random_standard_gamma_f(prng_t *prng_state, float shape) nogil + float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil cdef class RandomGenerator: """ @@ -281,3 +285,109 @@ cdef class RandomGenerator: return float_fill(&random_gauss_f, self._prng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_normal' % key) + + + def standard_gamma(self, shape, size=None, dtype=np.float64, method='zig', + out=None): + """ + standard_gamma(shape, size=None, dtype='d', method='inv', 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, should 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 ``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'. + 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 : 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", + http://en.wikipedia.org/wiki/Gamma_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> shape, scale = 2., 1. # mean and width + >>> s = np.random.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 + >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ + ... (sps.gamma(shape) * scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + """ + cdef void *func + if method != u'zig' and method != u'inv': + raise ValueError("method must be either 'inv' or 'zig'") + key = np.dtype(dtype).name + if key == 'float64': + if method == 'inv': + func = &random_standard_gamma + else: + func = &random_standard_gamma_zig + return cont(func, self._prng, size, self.lock, 1, + shape, 'shape', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE, + out) + if key == 'float32': + if method == 'inv': + func = &random_standard_gamma_f + else: + func = &random_standard_gamma_zig_f + return cont_f(func, self._prng, size, self.lock, + shape, 'shape', CONS_NON_NEGATIVE, + out) + else: + raise TypeError('Unsupported dtype "%s" for standard_gamma' % key) diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index aebbbfca1973..14cc85da0830 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -236,4 +236,250 @@ float random_gauss_zig_f(prng_t* prng_state) return x; } } -} \ No newline at end of file +} + +static NPY_INLINE double standard_gamma(prng_t* prng_state, double shape) +{ + double b, c; + double U, V, X, Y; + + if (shape == 1.0) + { + return random_standard_exponential(prng_state); + } + else if (shape < 1.0) + { + for (;;) + { + U = prng_state->next_double(prng_state->state); + V = random_standard_exponential(prng_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(prng_state); + V = 1.0 + c * X; + } while (V <= 0.0); + + V = V * V * V; + U = random_sample(prng_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(prng_t *prng_state, float shape) +{ + float b, c; + float U, V, X, Y; + + if (shape == 1.0f) + { + return random_standard_exponential_f(prng_state); + } + else if (shape < 1.0f) + { + for (;;) + { + U = random_sample_f(prng_state); + V = random_standard_exponential_f(prng_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(prng_state); + V = 1.0f + c * X; + } while (V <= 0.0f); + + V = V * V * V; + U = random_sample_f(prng_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(prng_t* prng_state, double shape) +{ + return standard_gamma(prng_state, shape); +} + +float random_standard_gamma_f(prng_t* prng_state, float shape) +{ + return standard_gamma_float(prng_state, shape); +} + + +static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) +{ + double b, c; + double U, V, X, Y; + + if (shape == 1.0) + { + return random_standard_exponential_zig(prng_state); + } + else if (shape < 1.0) + { + for (;;) + { + U = random_sample(prng_state); + V = random_standard_exponential_zig(prng_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(prng_state); + V = 1.0 + c * X; + } while (V <= 0.0); + + V = V * V * V; + U = random_sample(prng_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_zig_f(prng_t *prng_state, float shape) +{ + float b, c; + float U, V, X, Y; + + if (shape == 1.0f) + { + return random_standard_exponential_zig_f(prng_state); + } + else if (shape < 1.0f) + { + for (;;) + { + U = random_sample_f(prng_state); + V = random_standard_exponential_zig_f(prng_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(prng_state); + V = 1.0f + c * X; + } while (V <= 0.0f); + + V = V * V * V; + U = random_sample_f(prng_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_zig(prng_t *prng_state, double shape) +{ + return standard_gamma_zig(prng_state, shape); +} + +float random_standard_gamma_zig_f(prng_t *prng_state, float shape) +{ + return standard_gamma_zig_f(prng_state, shape); +} diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 4cd72e9d2320..3672060eab3b 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -14,31 +14,30 @@ typedef int bool; #include #endif -#include #include "numpy/npy_common.h" +#include typedef double (*random_double_0)(void *st); typedef float (*random_float_0)(void *st); -typedef struct s_binomial_t -{ - 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; +typedef struct s_binomial_t { + 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; } binomial_t; typedef struct prng { @@ -53,17 +52,22 @@ typedef struct prng { binomial_t *binomial; } prng_t; -float random_sample_f(prng_t *prng_state); -double random_sample(prng_t *prng_state); +extern float random_sample_f(prng_t *prng_state); +extern double random_sample(prng_t *prng_state); + +extern uint32_t random_uint32(prng_t *prng_state); -uint32_t random_uint32(prng_t *prng_state); +extern double random_standard_exponential(prng_t *prng_state); +extern float random_standard_exponential_f(prng_t *prng_state); +extern double random_standard_exponential_zig(prng_t *prng_state); +extern float random_standard_exponential_zig_f(prng_t *prng_state); -double random_standard_exponential(prng_t *prng_state); -float random_standard_exponential_f(prng_t *prng_state); -double random_standard_exponential_zig(prng_t *prng_state); -float random_standard_exponential_zig_f(prng_t *prng_state); +extern double random_gauss(prng_t *prng_state); +extern float random_gauss_f(prng_t *prng_state); +extern double random_gauss_zig(prng_t *prng_state); +extern float random_gauss_zig_f(prng_t *prng_state); -double random_gauss(prng_t *prng_state); -float random_gauss_f(prng_t *prng_state); -double random_gauss_zig(prng_t* prng_state); -float random_gauss_zig_f(prng_t* prng_state); \ No newline at end of file +extern double random_standard_gamma(prng_t *prng_state, double shape); +extern float random_standard_gamma_f(prng_t *prng_state, float shape); +extern double random_standard_gamma_zig(prng_t *prng_state, double shape); +extern float random_standard_gamma_zig_f(prng_t *prng_state, float shape); From cecd56d7933882721601aefb8624f52a037bf862 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 6 Mar 2018 09:32:13 +0000 Subject: [PATCH 029/138] CLN: Clean random123 generators Simplify these generators a small amount Define constants nhance the demo/benchmark --- _randomgen/core_prng/dsfmt.pyx | 13 +++++-- _randomgen/core_prng/mt19937.pyx | 12 ++++-- _randomgen/core_prng/pcg64.pyx | 12 ++++-- _randomgen/core_prng/philox.pyx | 29 ++++++++++----- _randomgen/core_prng/src/philox/philox.c | 4 +- _randomgen/core_prng/src/philox/philox.h | 39 +++++++++++--------- _randomgen/core_prng/src/threefry/threefry.h | 27 +++++++++----- _randomgen/core_prng/threefry.pyx | 24 ++++++++---- _randomgen/core_prng/xoroshiro128.pyx | 12 ++++-- _randomgen/core_prng/xorshift1024.pyx | 12 ++++-- _randomgen/demo.py | 23 +++++++++++- 11 files changed, 143 insertions(+), 64 deletions(-) diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index e43d05a75af9..68663e4b0d10 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -139,11 +139,16 @@ cdef class DSFMT: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) - + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 9e6b936efb5a..a5b836699697 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -109,10 +109,16 @@ cdef class MT19937: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index f728e2bbecc0..3e447ae3a92a 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -139,10 +139,16 @@ cdef class PCG64: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None, inc=1): diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 474bc752ebf0..f0dcc3a7d1ea 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -10,6 +10,8 @@ cimport entropy np.import_array() +DEF PHILOX_BUFFER_SIZE=4 + cdef extern from 'src/philox/philox.h': struct s_r123array2x64: uint64_t v[2] @@ -27,7 +29,7 @@ cdef extern from 'src/philox/philox.h': philox4x64_ctr_t *ctr; philox4x64_key_t *key; int buffer_pos; - uint64_t buffer[4]; + uint64_t buffer[PHILOX_BUFFER_SIZE]; int has_uint32 uint32_t uinteger @@ -106,8 +108,8 @@ cdef class Philox: def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self.rng_state.buffer_pos = 4 - for i in range(4): + self.rng_state.buffer_pos = PHILOX_BUFFER_SIZE + for i in range(PHILOX_BUFFER_SIZE): self.rng_state.buffer[i] = 0 def __random_integer(self, bits=64): @@ -135,10 +137,16 @@ cdef class Philox: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None, counter=None, key=None): """ @@ -201,12 +209,13 @@ cdef class Philox: """Get or set the PRNG state""" ctr = np.empty(4, dtype=np.uint64) key = np.empty(2, dtype=np.uint64) - buffer = np.empty(4, 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] - buffer[i] = self.rng_state.buffer[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 {'prng': self.__class__.__name__, @@ -226,9 +235,11 @@ cdef class Philox: 'PRNG'.format(self.__class__.__name__)) for i in range(4): self.rng_state.ctr.v[i] = value['state']['counter'][i] - self.rng_state.buffer[i] = value['buffer'][i] if i < 2: self.rng_state.key.v[i] = value['state']['key'][i] + for i in range(PHILOX_BUFFER_SIZE): + self.rng_state.buffer[i] = 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'] diff --git a/_randomgen/core_prng/src/philox/philox.c b/_randomgen/core_prng/src/philox/philox.c index 06eaa3400ebb..ea401e3690d8 100644 --- a/_randomgen/core_prng/src/philox/philox.c +++ b/_randomgen/core_prng/src/philox/philox.c @@ -1,8 +1,8 @@ #include "philox.h" -extern inline uint64_t philox_next64(philox_state *state); +extern INLINE uint64_t philox_next64(philox_state *state); -extern inline uint64_t philox_next32(philox_state *state); +extern INLINE uint64_t philox_next32(philox_state *state); extern void philox_jump(philox_state *state) { /* Advances state as-if 2^128 draws were made */ diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index 3121d5cbdc2e..477ba17accb6 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -1,11 +1,13 @@ #include #ifdef _WIN32 -#define INLINE __inline _forceinline +#define INLINE __inline __forceinline #else #define INLINE inline #endif +#define PHILOX_BUFFER_SIZE 4UL + struct r123array2x64 { uint64_t v[2]; }; @@ -18,7 +20,7 @@ typedef struct r123array4x64 philox4x64_ctr_t; typedef struct r123array2x64 philox4x64_key_t; typedef struct r123array2x64 philox4x64_ukey_t; -static __inline struct r123array2x64 +static INLINE struct r123array2x64 _philox4x64bumpkey(struct r123array2x64 key) { key.v[0] += (0x9E3779B97F4A7C15ULL); key.v[1] += (0xBB67AE8584CAA73BULL); @@ -30,22 +32,22 @@ _philox4x64bumpkey(struct r123array2x64 key) { #include #pragma intrinsic(_umul128) -static __inline uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { +static INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } #else -static inline uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { +static 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; } #endif -// static __inline _forceinline struct r123array4x64 _philox4x64round(struct -// r123array4x64 ctr, struct r123array2x64 key); +static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, + struct r123array2x64 key); -static INLINE struct r123array4x64 -_philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key) { +static 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); @@ -58,11 +60,13 @@ _philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key) { static INLINE philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { return uk; } -// static __inline _forceinline philox4x64_ctr_t philox4x64_R(unsigned int R, -// philox4x64_ctr_t ctr, philox4x64_key_t key); +static INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, + philox4x64_ctr_t ctr, + philox4x64_key_t key); -static INLINE philox4x64_ctr_t -philox4x64_R(unsigned int R, philox4x64_ctr_t ctr, philox4x64_key_t key) { +static INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, + philox4x64_ctr_t ctr, + philox4x64_key_t key) { if (R > 0) { ctr = _philox4x64round(ctr, key); } @@ -133,14 +137,13 @@ typedef struct s_philox_state { philox4x64_ctr_t *ctr; philox4x64_key_t *key; int buffer_pos; - uint64_t buffer[4]; + uint64_t buffer[PHILOX_BUFFER_SIZE]; int has_uint32; uint32_t uinteger; } philox_state; -static inline uint64_t philox_next(philox_state *state) { - /* TODO: This 4 should be a constant somewhere */ - if (state->buffer_pos < 4) { +static INLINE uint64_t philox_next(philox_state *state) { + if (state->buffer_pos < PHILOX_BUFFER_SIZE) { uint64_t out = state->buffer[state->buffer_pos]; state->buffer_pos++; return out; @@ -167,11 +170,11 @@ static inline uint64_t philox_next(philox_state *state) { return state->buffer[0]; } -static inline uint64_t philox_next64(philox_state *state) { +static INLINE uint64_t philox_next64(philox_state *state) { return philox_next(state); } -static inline uint64_t philox_next32(philox_state *state) { +static INLINE uint64_t philox_next32(philox_state *state) { if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index 35a3be53f576..5fa9a716b5a2 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -4,6 +4,14 @@ Adapted from random123's threefry.h #include +#ifdef _WIN32 +#define INLINE __inline __forceinline +#else +#define INLINE inline +#endif + +#define THREEFRY_BUFFER_SIZE 4UL + enum r123_enum_threefry64x4 { /* These are the R_256 constants from the Threefish reference sources with names changed to R_64x4... */ @@ -32,15 +40,15 @@ struct r123array4x64 { typedef struct r123array4x64 threefry4x64_key_t; typedef struct r123array4x64 threefry4x64_ctr_t; -static inline uint64_t RotL_64(uint64_t x, unsigned int N); -static inline uint64_t RotL_64(uint64_t x, unsigned int N) { +static INLINE uint64_t RotL_64(uint64_t x, unsigned int N); +static INLINE uint64_t RotL_64(uint64_t x, unsigned int N) { return (x << (N & 63)) | (x >> ((64 - N) & 63)); } -static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, +static INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); -static inline threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, +static INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) { threefry4x64_ctr_t X; @@ -268,14 +276,13 @@ typedef struct s_threefry_state { threefry4x64_key_t *ctr; threefry4x64_ctr_t *key; int buffer_pos; - uint64_t buffer[4]; + uint64_t buffer[THREEFRY_BUFFER_SIZE]; int has_uint32; uint32_t uinteger; } threefry_state; -static inline uint64_t threefry_next(threefry_state *state) { - /* TODO: This 4 should be a constant somewhere */ - if (state->buffer_pos < 4) { +static INLINE uint64_t threefry_next(threefry_state *state) { + if (state->buffer_pos < THREEFRY_BUFFER_SIZE) { uint64_t out = state->buffer[state->buffer_pos]; state->buffer_pos++; return out; @@ -302,11 +309,11 @@ static inline uint64_t threefry_next(threefry_state *state) { return state->buffer[0]; } -static inline uint64_t threefry_next64(threefry_state *state) { +static INLINE uint64_t threefry_next64(threefry_state *state) { return threefry_next(state); } -static inline uint64_t threefry_next32(threefry_state *state) { +static INLINE uint64_t threefry_next32(threefry_state *state) { if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index dfcc6e41da9d..db83379eb9c5 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -10,6 +10,8 @@ cimport entropy np.import_array() +DEF THREEFRY_BUFFER_SIZE=4 + cdef extern from 'src/threefry/threefry.h': struct s_r123array4x64: uint64_t v[4] @@ -23,7 +25,7 @@ cdef extern from 'src/threefry/threefry.h': threefry4x64_ctr_t *ctr; threefry4x64_key_t *key; int buffer_pos; - uint64_t buffer[4]; + uint64_t buffer[THREEFRY_BUFFER_SIZE]; int has_uint32 uint32_t uinteger @@ -100,8 +102,8 @@ cdef class ThreeFry: def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self.rng_state.buffer_pos = 4 - for i in range(4): + self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE + for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 def __random_integer(self, bits=64): @@ -129,10 +131,16 @@ cdef class ThreeFry: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None, counter=None, key=None): """ @@ -196,10 +204,11 @@ cdef class ThreeFry: """Get or set the PRNG state""" ctr = np.empty(4, dtype=np.uint64) key = np.empty(4, dtype=np.uint64) - buffer = np.empty(4, dtype=np.uint64) + buffer = np.empty(THREEFRY_BUFFER_SIZE, dtype=np.uint64) for i in range(4): ctr[i] = self.rng_state.ctr.v[i] key[i] = self.rng_state.key.v[i] + for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] state = {'counter':ctr,'key':key} return {'prng': self.__class__.__name__, @@ -220,6 +229,7 @@ cdef class ThreeFry: for i in range(4): self.rng_state.ctr.v[i] = value['state']['counter'][i] self.rng_state.key.v[i] = value['state']['key'][i] + for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = value['buffer'][i] self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 0c1f90998d9d..820ae0476e49 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -112,10 +112,16 @@ cdef class Xoroshiro128: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index f693d5a7e208..6c0585369479 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -112,10 +112,16 @@ cdef class Xorshift1024: else: raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt): + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - for i in range(cnt): - self._prng.next_uint64(self._prng.state) + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') def seed(self, seed=None): """ diff --git a/_randomgen/demo.py b/_randomgen/demo.py index 29f440505330..30b0984221d2 100644 --- a/_randomgen/demo.py +++ b/_randomgen/demo.py @@ -75,10 +75,29 @@ m = {module}() m._benchmark(701) """ +import pandas as pd +res = [] for p in PRNGS: module = p.__name__ print(module) t = timeit.timeit("m._benchmark(10000000)", setup.format(module=module), number=10) - print('{:0.2f} ms'.format(1000 * t / 10)) - print('{:,} randoms per second'.format(int(10000000 / (t/10)))) + res.append(pd.Series({'module': module, 'ms': 1000 * + t / 10, 'rps': int(10000000 / (t/10))})) + #print('{:0.2f} ms'.format()) + # print('{:,} randoms per second'.format())) +res = pd.DataFrame(res) +print(res.set_index('module').sort_values('ms')) + +res = [] +for p in PRNGS: + module = p.__name__ + print(module) + t = timeit.timeit("m._benchmark(10000000, 'double')", setup.format(module=module), + number=10) + res.append(pd.Series({'module': module, 'ms': 1000 * + t / 10, 'rps': int(10000000 / (t/10))})) + #print('{:0.2f} ms'.format()) + # print('{:,} randoms per second'.format())) +res = pd.DataFrame(res) +print(res.set_index('module').sort_values('ms')) From 92a09f3d0f08af29b9d58cc4f50bcfedef5497cb Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 6 Mar 2018 12:00:48 +0000 Subject: [PATCH 030/138] TST: Add test and benchmark code --- .../core_prng/src/philox/philox-benchmark.c | 33 ++++++++ .../src/philox/philox-test-data-gen.c | 74 ++++++++++++++++++ .../src/threefry/threefry-benchmark.c | 34 ++++++++ .../src/threefry/threefry-test-data-gen.c | 77 +++++++++++++++++++ 4 files changed, 218 insertions(+) create mode 100644 _randomgen/core_prng/src/philox/philox-benchmark.c create mode 100644 _randomgen/core_prng/src/philox/philox-test-data-gen.c create mode 100644 _randomgen/core_prng/src/threefry/threefry-benchmark.c create mode 100644 _randomgen/core_prng/src/threefry/threefry-test-data-gen.c diff --git a/_randomgen/core_prng/src/philox/philox-benchmark.c b/_randomgen/core_prng/src/philox/philox-benchmark.c new file mode 100644 index 000000000000..03ab8bde0eac --- /dev/null +++ b/_randomgen/core_prng/src/philox/philox-benchmark.c @@ -0,0 +1,33 @@ +/* + * Simple benchamrk command + * + * cl philox-benchmark.c /Ox + * Measure-Command { .\philox-benchmark.exe } + * + * gcc philox-benchmark.c -O3 -o philox-benchmark + * time ./philox-benchmark + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + */ +#include "Random123/philox.h" +#include +#include + +#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 sum = 0; + int i, j; + 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]; + } + } + printf("%" PRIu64 "\n", sum); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/philox/philox-test-data-gen.c b/_randomgen/core_prng/src/philox/philox-test-data-gen.c new file mode 100644 index 000000000000..f50389a4c8aa --- /dev/null +++ b/_randomgen/core_prng/src/philox/philox-test-data-gen.c @@ -0,0 +1,74 @@ +/* + * 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 + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "Random123/philox.h" +#include +#include + +#define N 1000 + +int main() { + philox4x64_ctr_t ctr = {{0, 0, 0, 0}}; + philox4x64_key_t key = {{0, 0xDEADBEAF}}; + philox4x64_ctr_t out; + uint64_t store[N]; + int i, j; + 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, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + for (i = 0; i < N; i++) { + fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + if (i == 999) { + printf("%d, %" PRIu64 "\n", i, store[i]); + } + } + fclose(fp); + + ctr.v[0] = 0; + key.v[0] = 0xDEADBEAF; + key.v[1] = 0xFBADBEEF; + 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, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + for (i = 0; i < N; i++) { + fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + if (i == 999) { + printf("%d, %" PRIu64 "\n", i, store[i]); + } + } + fclose(fp); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/threefry/threefry-benchmark.c b/_randomgen/core_prng/src/threefry/threefry-benchmark.c new file mode 100644 index 000000000000..cc6548bed6e2 --- /dev/null +++ b/_randomgen/core_prng/src/threefry/threefry-benchmark.c @@ -0,0 +1,34 @@ +/* + * Simple benchamrk command + * + * cl threefry-benchmark.c /Ox + * Measure-Command { .\threefry-benchmark.exe } + * + * gcc threefry-benchmark.c -O3 -o threefry-benchmark + * time ./threefry-benchmark + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + */ +#include "Random123/threefry.h" +#include +#include + +#define N 1000000000 + +int main() { + + threefry4x64_key_t ctr = {{0, 0, 0, 0}}; + threefry4x64_ctr_t key = {{0xDEADBEAF, 0, 0, 0}}; + threefry4x64_ctr_t out; + uint64_t sum = 0; + int i, j; + for (i = 0; i < N / 4UL; i++) { + ctr.v[0]++; + out = threefry4x64_R(threefry4x64_rounds, ctr, key); + for (j = 0; j < 4; j++) { + sum += out.v[j]; + } + } + printf("%" PRIu64 "\n", sum); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c new file mode 100644 index 000000000000..4f49914e151c --- /dev/null +++ b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c @@ -0,0 +1,77 @@ +/* + * Generate testing csv files + * + * cl threefry-test-data-gen.c /Ox + * threefry-test-data-gen.exe + * + * gcc threefry-test-data-gen.c -o philox-test-data-gen + * ./threefry-test-data-gen + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "Random123/threefry.h" +#include +#include + +#define N 1000 + +int main() { + threefry4x64_key_t ctr = {{0, 0, 0, 0}}; + threefry4x64_ctr_t key = {{0xDEADBEAF, 0, 0, 0}}; + threefry4x64_ctr_t out; + uint64_t store[N]; + int i, j; + for (i = 0; i < N / 4UL; i++) { + ctr.v[0]++; + out = threefry4x64_R(threefry4x64_rounds, ctr, key); + for (j = 0; j < 4; j++) { + store[i * 4 + j] = out.v[j]; + } + } + + FILE *fp; + fp = fopen("threefry-testset-1.csv", "w"); + if (fp == NULL) { + printf("Couldn't open file\n"); + return -1; + } + fprintf(fp, "key, %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "\n", + key.v[0], key.v[1], key.v[2], key.v[3]); + for (i = 0; i < N; i++) { + fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + if (i == 999) { + printf("%d, %" PRIu64 "\n", i, store[i]); + } + } + fclose(fp); + + ctr.v[0] = 0; + key.v[0] = 0; + key.v[1] = 0; + key.v[2] = 0xFBADBEEF; + key.v[3] = 0xDEADBEAF; + for (i = 0; i < N / 4UL; i++) { + ctr.v[0]++; + out = threefry4x64_R(threefry4x64_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, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + for (i = 0; i < N; i++) { + fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + if (i == 999) { + printf("%d, %" PRIu64 "\n", i, store[i]); + } + } + fclose(fp); +} \ No newline at end of file From f029ebbbfe45adb3480c7827d8a0a3af9901544c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 6 Mar 2018 12:51:47 +0000 Subject: [PATCH 031/138] ENH: Improve benchmark --- _randomgen/.gitignore | 6 + .../core_prng/src/dsfmt/dSFMT-benchmark.c | 41 + .../core_prng/src/mt19937/mt19937-benchmark.c | 31 + .../src/mt19937/mt19937-test-data-gen.c | 66 + _randomgen/core_prng/src/mt19937/randomkit.c | 580 +++++ _randomgen/core_prng/src/mt19937/randomkit.h | 223 ++ .../core_prng/src/pcg64/pcg64-benchmark.c | 42 + .../core_prng/src/pcg64/pcg64-test-data-gen.c | 65 + _randomgen/core_prng/src/pcg64/pcg64.h | 2 +- _randomgen/core_prng/src/pcg64/pcg64.orig.c | 6 + _randomgen/core_prng/src/pcg64/pcg64.orig.h | 2025 +++++++++++++++++ .../core_prng/src/philox/philox-benchmark.c | 13 +- .../src/philox/philox-test-data-gen.c | 12 +- .../src/threefry/threefry-benchmark.c | 14 +- .../src/threefry/threefry-test-data-gen.c | 19 +- .../src/xoroshiro128/xoroshiro128-benchmark.c | 33 + .../xoroshiro128/xoroshiro128-test-data-gen.c | 72 + .../src/xoroshiro128/xoroshiro128plus.orig.h | 5 + .../src/xorshift1024/xorshift1024-benchmark.c | 35 + .../xorshift1024/xorshift1024-test-data-gen.c | 74 + .../src/xorshift1024/xorshift1024.orig.h | 7 + 21 files changed, 3347 insertions(+), 24 deletions(-) create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c create mode 100644 _randomgen/core_prng/src/mt19937/mt19937-benchmark.c create mode 100644 _randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c create mode 100644 _randomgen/core_prng/src/mt19937/randomkit.c create mode 100644 _randomgen/core_prng/src/mt19937/randomkit.h create mode 100644 _randomgen/core_prng/src/pcg64/pcg64-benchmark.c create mode 100644 _randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c create mode 100644 _randomgen/core_prng/src/pcg64/pcg64.orig.c create mode 100644 _randomgen/core_prng/src/pcg64/pcg64.orig.h create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c create mode 100644 _randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c create mode 100644 _randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h diff --git a/_randomgen/.gitignore b/_randomgen/.gitignore index fd7f147c8885..613fc1bf498c 100644 --- a/_randomgen/.gitignore +++ b/_randomgen/.gitignore @@ -2,4 +2,10 @@ build/ *.egg-info/ *.pyd +*.pyc *.html +*.obj +*.exe +**/Random123 +settings.json +*.so diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c b/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c new file mode 100644 index 000000000000..d311179fc2bd --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c @@ -0,0 +1,41 @@ +/* + * + * cl dsfmt-benchmark.c dSFMT.c /Ox -DHAVE_SSE2 + * + * gcc dSFMT-benchmark.c dSFMT.c -O3 -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o + * dSFMT-benchmark + */ +#include "dSFMT.h" +#include +#include + +#define N 1000000000 + +int main() { + int i, j; + uint32_t seed = 0xDEADBEAF; + uint64_t count = 0, sum = 0; + dsfmt_t state; + double buffer[DSFMT_N64]; + + uint64_t out; + uint64_t *tmp; + dsfmt_init_gen_rand(&state, seed); + clock_t begin = clock(); + for (i = 0; i < N / (DSFMT_N64 / 2); i++) { + dsfmt_fill_array_close_open(&state, &buffer[0], DSFMT_N64); + for (j = 0; j < DSFMT_N64; j += 2) { + tmp = (uint64_t *)&buffer[j]; + out = (*tmp >> 16) << 32; + tmp = (uint64_t *)&buffer[j + 1]; + out |= (*tmp >> 16) & 0xffffffff; + sum += out; + 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/_randomgen/core_prng/src/mt19937/mt19937-benchmark.c b/_randomgen/core_prng/src/mt19937/mt19937-benchmark.c new file mode 100644 index 000000000000..039f8030af65 --- /dev/null +++ b/_randomgen/core_prng/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 +#include +#include + +#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/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c b/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c new file mode 100644 index 000000000000..ef98be160b55 --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c @@ -0,0 +1,66 @@ +/* + * 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 +#include + +#define N 1000 + +int main() { + uint64_t sum = 0; + uint64_t temp; + uint32_t seed = 0xDEADBEAF; + int i; + rk_state state; + rk_seed(seed, &state); + uint64_t store[N]; + for (i = 0; i < N; i++) { + temp = 0; + temp = (uint64_t)rk_random(&state) << 32; + temp |= rk_random(&state); + store[i] = temp; + } + + 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++) { + temp = 0; + temp = (uint64_t)rk_random(&state) << 32; + temp |= rk_random(&state); + store[i] = temp; + } + 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/_randomgen/core_prng/src/mt19937/randomkit.c b/_randomgen/core_prng/src/mt19937/randomkit.c new file mode 100644 index 000000000000..17f10a288f39 --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/randomkit.c @@ -0,0 +1,580 @@ +/* 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 +#include + + +/* + * 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 +#include + +#define _FTIME(x) _ftime((x)) +#endif + +#ifndef RK_NO_WINCRYPT +/* Windows crypto */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +#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 +#include +#include + +#endif + +#include +#include +#include +#include +#include +#include +#include + + +#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); + + /* Box-Muller transform */ + f = sqrt(-2.0 * log(r2) / r2); + /* Keep for next call */ + state->gauss = f * x1; + state->has_gauss = 1; + return f * x2; + } +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/mt19937/randomkit.h b/_randomgen/core_prng/src/mt19937/randomkit.h new file mode 100644 index 000000000000..f57f50ae360e --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/randomkit.h @@ -0,0 +1,223 @@ +/* Random kit 1.3 */ + +/* + * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.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. + */ + +/* @(#) $Jeannot: randomkit.h,v 1.24 2005/07/21 22:14:09 js Exp $ */ + +/* + * Typical use: + * + * { + * rk_state state; + * unsigned long seed = 1, random_value; + * + * rk_seed(seed, &state); // Initialize the RNG + * ... + * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] + * } + * + * Instead of rk_seed, you can use rk_randomseed which will get a random seed + * from /dev/urandom (or the clock, if /dev/urandom is unavailable): + * + * { + * rk_state state; + * unsigned long random_value; + * + * rk_randomseed(&state); // Initialize the RNG with a random seed + * ... + * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] + * } + */ + +/* + * Useful macro: + * RK_DEV_RANDOM: the device used for random seeding. + * defaults to "/dev/urandom" + */ + +#ifndef _RANDOMKIT_ +#define _RANDOMKIT_ + +#include +#include + +#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 enum { + RK_NOERR = 0, /* no error */ + RK_ENODEV = 1, /* no RK_DEV_RANDOM device */ + RK_ERR_MAX = 2 +} rk_error; + +/* error strings */ +extern char *rk_strerror[RK_ERR_MAX]; + +/* Maximum generated random value */ +#define RK_MAX 0xFFFFFFFFUL + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Initialize the RNG state using the given seed. + */ +extern void rk_seed(unsigned long seed, rk_state *state); + +/* + * Initialize the RNG state using a random seed. + * Uses /dev/random or, when unavailable, the clock (see randomkit.c). + * Returns RK_NOERR when no errors occurs. + * Returns RK_ENODEV when the use of RK_DEV_RANDOM failed (for example because + * there is no such device). In this case, the RNG was initialized using the + * clock. + */ +extern rk_error rk_randomseed(rk_state *state); + +/* + * Returns a random unsigned long between 0 and RK_MAX inclusive + */ +extern unsigned long rk_random(rk_state *state); + +/* + * Returns a random long between 0 and LONG_MAX inclusive + */ +extern long rk_long(rk_state *state); + +/* + * Returns a random unsigned long between 0 and ULONG_MAX inclusive + */ +extern unsigned long rk_ulong(rk_state *state); + +/* + * Returns a random unsigned long between 0 and max inclusive. + */ +extern unsigned long rk_interval(unsigned long max, rk_state *state); + +/* + * Fills an array with cnt random npy_uint64 between off and off + rng + * inclusive. The numbers wrap if rng is sufficiently large. + */ +extern void rk_random_uint64(npy_uint64 off, npy_uint64 rng, npy_intp cnt, + npy_uint64 *out, rk_state *state); + +/* + * Fills an array with cnt random npy_uint32 between off and off + rng + * inclusive. The numbers wrap if rng is sufficiently large. + */ +extern void rk_random_uint32(npy_uint32 off, npy_uint32 rng, npy_intp cnt, + npy_uint32 *out, rk_state *state); + +/* + * Fills an array with cnt random npy_uint16 between off and off + rng + * inclusive. The numbers wrap if rng is sufficiently large. + */ +extern void rk_random_uint16(npy_uint16 off, npy_uint16 rng, npy_intp cnt, + npy_uint16 *out, rk_state *state); + +/* + * Fills an array with cnt random npy_uint8 between off and off + rng + * inclusive. The numbers wrap if rng is sufficiently large. + */ +extern void rk_random_uint8(npy_uint8 off, npy_uint8 rng, npy_intp cnt, + npy_uint8 *out, rk_state *state); + +/* + * Fills an array with cnt random npy_bool between off and off + rng + * inclusive. It is assumed tha npy_bool as the same size as npy_uint8. + */ +extern void rk_random_bool(npy_bool off, npy_bool rng, npy_intp cnt, + npy_bool *out, rk_state *state); + +/* + * Returns a random double between 0.0 and 1.0, 1.0 excluded. + */ +extern double rk_double(rk_state *state); + +/* + * fill the buffer with size random bytes + */ +extern void rk_fill(void *buffer, size_t size, rk_state *state); + +/* + * fill the buffer with randombytes from the random device + * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is + * On Unix, if strong is defined, RK_DEV_RANDOM is used. If not, RK_DEV_URANDOM + * is used instead. This parameter has no effect on Windows. + * Warning: on most unixes RK_DEV_RANDOM will wait for enough entropy to answer + * which can take a very long time on quiet systems. + */ +extern rk_error rk_devfill(void *buffer, size_t size, int strong); + +/* + * fill the buffer using rk_devfill if the random device is available and using + * rk_fill if it is not + * parameters have the same meaning as rk_fill and rk_devfill + * 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); + +/* + * return a random gaussian deviate with variance unity and zero mean. + */ +extern double rk_gauss(rk_state *state); + +#ifdef __cplusplus +} +#endif + +#endif /* _RANDOMKIT_ */ \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64-benchmark.c b/_randomgen/core_prng/src/pcg64/pcg64-benchmark.c new file mode 100644 index 000000000000..76f3ec78c300 --- /dev/null +++ b/_randomgen/core_prng/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 +#include +#include + +#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/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c new file mode 100644 index 000000000000..d97632d759a0 --- /dev/null +++ b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c @@ -0,0 +1,65 @@ +/* + * 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 "../splitmix64/splitmix64.h" +#include +#include + +#define N 1000 + +int main() { + pcg64_random_t rng; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + __uint128_t temp; + rng.state = (__uint128_t)splitmix64_next(&state) << 64; + rng.state |= splitmix64_next(&state); + rng.inc = (__uint128_t)1; + int i; + uint64_t store[N]; + 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; + rng.state = + (__uint128_t)splitmix64_next(&state) << 64 | splitmix64_next(&state); + rng.inc = (__uint128_t)1; + 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); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h index 244eeb8cff49..54bd37efc7e6 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -29,7 +29,7 @@ #ifndef _INTTYPES #include "../common/stdint.h" #endif -#define inline __forceinline +#define inline __inline __forceinline #else #include #endif diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.c b/_randomgen/core_prng/src/pcg64/pcg64.orig.c new file mode 100644 index 000000000000..4ce4736dbc58 --- /dev/null +++ b/_randomgen/core_prng/src/pcg64/pcg64.orig.c @@ -0,0 +1,6 @@ +#include "pcg64.orig.h" + +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); \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.h b/_randomgen/core_prng/src/pcg64/pcg64.orig.h new file mode 100644 index 000000000000..645025acb01e --- /dev/null +++ b/_randomgen/core_prng/src/pcg64/pcg64.orig.h @@ -0,0 +1,2025 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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 + +#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/_randomgen/core_prng/src/philox/philox-benchmark.c b/_randomgen/core_prng/src/philox/philox-benchmark.c index 03ab8bde0eac..701ee03452cd 100644 --- a/_randomgen/core_prng/src/philox/philox-benchmark.c +++ b/_randomgen/core_prng/src/philox/philox-benchmark.c @@ -2,10 +2,8 @@ * Simple benchamrk command * * cl philox-benchmark.c /Ox - * Measure-Command { .\philox-benchmark.exe } * * gcc philox-benchmark.c -O3 -o philox-benchmark - * time ./philox-benchmark * * Requres the Random123 directory containing header files to be located in the * same directory (not included). @@ -13,6 +11,7 @@ #include "Random123/philox.h" #include #include +#include #define N 1000000000 @@ -20,14 +19,20 @@ int main() { philox4x64_ctr_t ctr = {{0, 0, 0, 0}}; philox4x64_key_t key = {{0, 0xDEADBEAF}}; philox4x64_ctr_t out; - uint64_t sum = 0; + 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++; } } - printf("%" PRIu64 "\n", sum); + 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); } \ No newline at end of file diff --git a/_randomgen/core_prng/src/philox/philox-test-data-gen.c b/_randomgen/core_prng/src/philox/philox-test-data-gen.c index f50389a4c8aa..fd717b959794 100644 --- a/_randomgen/core_prng/src/philox/philox-test-data-gen.c +++ b/_randomgen/core_prng/src/philox/philox-test-data-gen.c @@ -38,11 +38,11 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + fprintf(fp, "key, 0x%" PRIx64 ", 0x%" PRIx64 "\n", key.v[0], key.v[1]); for (i = 0; i < N; i++) { - fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { - printf("%d, %" PRIu64 "\n", i, store[i]); + printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } fclose(fp); @@ -63,11 +63,11 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + fprintf(fp, "key, 0x%" PRIx64 ", 0x%" PRIx64 "\n", key.v[0], key.v[1]); for (i = 0; i < N; i++) { - fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { - printf("%d, %" PRIu64 "\n", i, store[i]); + printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } fclose(fp); diff --git a/_randomgen/core_prng/src/threefry/threefry-benchmark.c b/_randomgen/core_prng/src/threefry/threefry-benchmark.c index cc6548bed6e2..a75e61001970 100644 --- a/_randomgen/core_prng/src/threefry/threefry-benchmark.c +++ b/_randomgen/core_prng/src/threefry/threefry-benchmark.c @@ -2,10 +2,8 @@ * Simple benchamrk command * * cl threefry-benchmark.c /Ox - * Measure-Command { .\threefry-benchmark.exe } * * gcc threefry-benchmark.c -O3 -o threefry-benchmark - * time ./threefry-benchmark * * Requres the Random123 directory containing header files to be located in the * same directory (not included). @@ -13,22 +11,28 @@ #include "Random123/threefry.h" #include #include +#include #define N 1000000000 int main() { - threefry4x64_key_t ctr = {{0, 0, 0, 0}}; threefry4x64_ctr_t key = {{0xDEADBEAF, 0, 0, 0}}; threefry4x64_ctr_t out; - uint64_t sum = 0; + uint64_t count = 0, sum = 0; int i, j; + clock_t begin = clock(); for (i = 0; i < N / 4UL; i++) { ctr.v[0]++; out = threefry4x64_R(threefry4x64_rounds, ctr, key); for (j = 0; j < 4; j++) { sum += out.v[j]; + count++; } } - printf("%" PRIu64 "\n", sum); + 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); } \ No newline at end of file diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c index 4f49914e151c..2fa09eed31f3 100644 --- a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c +++ b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c @@ -4,7 +4,7 @@ * cl threefry-test-data-gen.c /Ox * threefry-test-data-gen.exe * - * gcc threefry-test-data-gen.c -o philox-test-data-gen + * gcc threefry-test-data-gen.c -o threefry-test-data-gen * ./threefry-test-data-gen * * Requres the Random123 directory containing header files to be located in the @@ -38,12 +38,13 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key, %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "\n", + fprintf(fp, + "key, 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 "\n", key.v[0], key.v[1], key.v[2], key.v[3]); for (i = 0; i < N; i++) { - fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { - printf("%d, %" PRIu64 "\n", i, store[i]); + printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } fclose(fp); @@ -61,16 +62,18 @@ int main() { } } - fp = fopen("philox-testset-2.csv", "w"); + fp = fopen("threefry-testset-2.csv", "w"); if (fp == NULL) { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key: %" PRIu64 ", %" PRIu64 "\n", key.v[0], key.v[1]); + fprintf(fp, + "key, 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 "\n", + key.v[0], key.v[1], key.v[2], key.v[3]); for (i = 0; i < N; i++) { - fprintf(fp, "%d, %" PRIu64 "\n", i, store[i]); + fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { - printf("%d, %" PRIu64 "\n", i, store[i]); + printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } fclose(fp); diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c new file mode 100644 index 000000000000..108058eeb103 --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c @@ -0,0 +1,33 @@ +/* + * cl xoroshiro128-benchmark.c xoroshiro128plus.orig.c \ + * ../splitmix64/splitmix64.c /Ox + * + * gcc -O3 xoroshiro128-benchmark.c xoroshiro128plus.orig.c \ + * ../splitmix64/splitmix64.c -o xoroshiro128-benchmark + * + */ +#include "../splitmix64/splitmix64.h" +#include "xoroshiro128plus.orig.h" +#include +#include +#include + +#define N 1000000000 + +int main() { + uint64_t count = 0, sum = 0; + uint64_t seed = 0xDEADBEAF; + s[0] = splitmix64_next(&seed); + s[1] = splitmix64_next(&seed); + int i; + clock_t begin = clock(); + for (i = 0; i < N; i++) { + sum += next(); + 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/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c new file mode 100644 index 000000000000..d49c87ce2109 --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c @@ -0,0 +1,72 @@ +/* + * Generate testing csv files + * + * cl xoroshiro128-test-data-gen.c xoroshiro128plus.orig.c / + * ../splitmix64/splitmix64.c /Ox + * xoroshiro128-test-data-gen.exe * + * + * gcc xoroshiro128-test-data-gen.c xoroshiro128plus.orig.c / + * ../splitmix64/splitmix64.c -o xoroshiro128-test-data-gen + * ./xoroshiro128-test-data-gen + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "../splitmix64/splitmix64.h" +#include "xoroshiro128plus.orig.h" +#include +#include + +#define N 1000 + +int main() { + uint64_t sum = 0; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + int i; + for (i = 0; i < 2; i++) { + s[i] = splitmix64_next(&state); + } + uint64_t store[N]; + for (i = 0; i < N; i++) { + store[i] = next(); + } + + FILE *fp; + fp = fopen("xoroshiro128-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); + + seed = state = 0; + for (i = 0; i < 2; i++) { + s[i] = splitmix64_next(&state); + } + for (i = 0; i < N; i++) { + store[i] = next(); + } + fp = fopen("xoroshiro128-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); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h new file mode 100644 index 000000000000..20c96fe04dec --- /dev/null +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h @@ -0,0 +1,5 @@ +#include + +uint64_t s[2]; +uint64_t next(void); +void jump(void); diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c new file mode 100644 index 000000000000..0eef33537090 --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c @@ -0,0 +1,35 @@ +/* + * cl xorshift1024-benchmark.c xorshift2014.orig.c + * ../splitmix64/splitmix64.c /Ox + * + * gcc -O3 xorshift1024-benchmark.c xorshift2014.orig.c / + * ../splitmix64/splitmix64.c -o xorshift1024-benchmark + * + */ +#include "../splitmix64/splitmix64.h" +#include "xorshift1024.orig.h" +#include +#include +#include + +#define N 1000000000 + +int main() { + uint64_t count = 0, sum = 0; + uint64_t seed = 0xDEADBEAF; + int i; + for (i = 0; i < 16; i++) { + s[i] = splitmix64_next(&seed); + } + p = 0; + clock_t begin = clock(); + for (i = 0; i < N; i++) { + sum += next(); + 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/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c new file mode 100644 index 000000000000..aa0ebca33085 --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c @@ -0,0 +1,74 @@ +/* + * Generate testing csv files + * + * cl xorshift1024-test-data-gen.c xorshift1024.orig.c / + * ../splitmix64/splitmix64.c /Ox + * xorshift1024-test-data-gen.exe * + * + * gcc xorshift1024-test-data-gen.c xorshift1024.orig.c / + * ../splitmix64/splitmix64.c -o xorshift1024-test-data-gen + * ./xorshift1024-test-data-gen + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "../splitmix64/splitmix64.h" +#include "xorshift1024.orig.h" +#include +#include + +#define N 1000 + +int main() { + uint64_t sum = 0; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + int i; + for (i = 0; i < 16; i++) { + s[i] = splitmix64_next(&state); + } + p = 0; + uint64_t store[N]; + for (i = 0; i < N; i++) { + store[i] = next(); + } + + FILE *fp; + fp = fopen("xorshift1024-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); + + seed = state = 0; + for (i = 0; i < 16; i++) { + s[i] = splitmix64_next(&state); + } + p = 0; + for (i = 0; i < N; i++) { + store[i] = next(); + } + fp = fopen("xorshift1024-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); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h b/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h new file mode 100644 index 000000000000..9b7597967677 --- /dev/null +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h @@ -0,0 +1,7 @@ +#include +#include + +uint64_t s[16]; +int p; +uint64_t next(void); +void jump(void); From 8777c61a195384944a9244a6211d6e57acb00a5f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 10:16:16 +0000 Subject: [PATCH 032/138] CLN: Reformat C files Reformat C files using clang-format --- _randomgen/core_prng/src/common/stdint.h | 239 +++--- .../src/distributions/distributions.c | 729 ++++++++---------- .../core_prng/src/dsfmt/dSFMT-test-gen.c | 93 ++- _randomgen/core_prng/src/dsfmt/dSFMT.c | 619 +++++++-------- _randomgen/core_prng/src/dsfmt/dSFMT.h | 325 ++++---- _randomgen/core_prng/src/mt19937/mt19937.c | 166 ++-- _randomgen/core_prng/src/mt19937/mt19937.h | 38 +- _randomgen/core_prng/src/mt19937/randomkit.c | 4 +- _randomgen/core_prng/src/mt19937/randomkit.h | 2 +- .../core_prng/src/pcg64/pcg64-test-data-gen.c | 7 +- _randomgen/core_prng/src/pcg64/pcg64.orig.c | 3 +- _randomgen/core_prng/src/pcg64/pcg64.orig.h | 8 +- .../core_prng/src/philox/philox-benchmark.c | 2 +- .../src/philox/philox-test-data-gen.c | 2 +- .../src/splitmix64/splitmix64.orig.c | 10 +- .../src/threefry/threefry-benchmark.c | 2 +- .../core_prng/src/threefry/threefry-orig.c | 29 +- .../src/threefry/threefry-test-data-gen.c | 2 +- .../xoroshiro128/xoroshiro128-test-data-gen.c | 2 +- .../src/xoroshiro128/xoroshiro128plus.orig.c | 47 +- .../xorshift1024/xorshift1024-test-data-gen.c | 2 +- .../core_prng/src/xorshift1024/xorshift1024.h | 2 +- .../src/xorshift1024/xorshift2014.orig.c | 47 +- 23 files changed, 1125 insertions(+), 1255 deletions(-) diff --git a/_randomgen/core_prng/src/common/stdint.h b/_randomgen/core_prng/src/common/stdint.h index 8941d67c8295..710de1570370 100644 --- a/_randomgen/core_prng/src/common/stdint.h +++ b/_randomgen/core_prng/src/common/stdint.h @@ -54,20 +54,19 @@ #ifdef __cplusplus extern "C" { #endif -# include +#include #ifdef __cplusplus } #endif // Define _W64 macros to mark types changing their size, like intptr_t. #ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif #endif - // 7.18.1 Integer types @@ -77,167 +76,167 @@ extern "C" { // realize that, e.g. char has the same size as __int8 // so we give up on __intX for them. #if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; #else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; #endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers #ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] +typedef signed __int64 intptr_t; +typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ +typedef _W64 signed int intptr_t; +typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; // 7.18.2 Limits of specified-width integer types -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 +#if !defined(__cplusplus) || \ + defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and + // footnote 221 at page 259 // 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX // 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX // 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] +#define PTRDIFF_MIN _I64_MIN +#define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +#define PTRDIFF_MIN _I32_MIN +#define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] +#ifdef _WIN64 // [ +#define SIZE_MAX _UI64_MAX +#else // _WIN64 ][ +#define SIZE_MAX _UI32_MAX +#endif // _WIN64 ] +#endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] +#define WCHAR_MIN 0 +#endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] +#define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX #endif // __STDC_LIMIT_MACROS ] - // 7.18.4 Limits of other integer types -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 +#if !defined(__cplusplus) || \ + defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 // 7.18.4.1 Macros for minimum-width integer constants -#define INT8_C(val) val##i8 +#define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 -#define UINT8_C(val) val##ui8 +#define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 @@ -246,10 +245,10 @@ typedef uint64_t uintmax_t; // These #ifndef's are needed to prevent collisions with . // Check out Issue 9 for the details. #ifndef INTMAX_C // [ -# define INTMAX_C INT64_C -#endif // INTMAX_C ] +#define INTMAX_C INT64_C +#endif // INTMAX_C ] #ifndef UINTMAX_C // [ -# define UINTMAX_C UINT64_C +#define UINTMAX_C UINT64_C #endif // UINTMAX_C ] #endif // __STDC_CONSTANT_MACROS ] diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 14cc85da0830..40b24472747b 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -2,17 +2,16 @@ #include "ziggurat.h" #include "ziggurat_constants.h" -static NPY_INLINE float next_float(prng_t *prng_state){ - return (prng_state->next_uint32(prng_state->state) >> 9) * (1.0f / 8388608.0f); +static NPY_INLINE float next_float(prng_t *prng_state) { + return (prng_state->next_uint32(prng_state->state) >> 9) * + (1.0f / 8388608.0f); } uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } -float random_sample_f(prng_t *prng_state) { - return next_float(prng_state); -} +float random_sample_f(prng_t *prng_state) { return next_float(prng_state); } double random_sample(prng_t *prng_state) { return prng_state->next_double(prng_state->state); @@ -23,463 +22,373 @@ double random_standard_exponential(prng_t *prng_state) { } float random_standard_exponential_f(prng_t *prng_state) { - return -logf(1.0f - next_float(prng_state)); + return -logf(1.0f - next_float(prng_state)); } -double random_gauss(prng_t *prng_state) -{ - if (prng_state->has_gauss) - { - const double temp = prng_state->gauss; - prng_state->has_gauss = false; - return temp; - } - else - { - double f, x1, x2, r2; - - do - { - x1 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; - x2 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; - r2 = x1 * x1 + x2 * x2; - } while (r2 >= 1.0 || r2 == 0.0); - - /* Box-Muller transform */ - f = sqrt(-2.0 * log(r2) / r2); - /* Keep for next call */ - prng_state->gauss = f * x1; - prng_state->has_gauss = true; - return f * x2; - } +double random_gauss(prng_t *prng_state) { + if (prng_state->has_gauss) { + const double temp = prng_state->gauss; + prng_state->has_gauss = false; + return temp; + } else { + double f, x1, x2, r2; + + do { + x1 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; + x2 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; + r2 = x1 * x1 + x2 * x2; + } while (r2 >= 1.0 || r2 == 0.0); + + /* Box-Muller transform */ + f = sqrt(-2.0 * log(r2) / r2); + /* Keep for next call */ + prng_state->gauss = f * x1; + prng_state->has_gauss = true; + return f * x2; + } } -float random_gauss_f(prng_t *prng_state) -{ - if (prng_state->has_gauss_f) - { - const float temp = prng_state->gauss_f; - prng_state->has_gauss_f = false; - return temp; - } - else - { - float f, x1, x2, r2; - - do - { - x1 = 2.0f * next_float(prng_state) - 1.0f; - x2 = 2.0f * next_float(prng_state) - 1.0f; - r2 = x1 * x1 + x2 * x2; - } while (r2 >= 1.0 || r2 == 0.0); - - /* Box-Muller transform */ - f = sqrtf(-2.0f * logf(r2) / r2); - /* Keep for next call */ - prng_state->gauss_f = f * x1; - prng_state->has_gauss_f = true; - return f * x2; - } +float random_gauss_f(prng_t *prng_state) { + if (prng_state->has_gauss_f) { + const float temp = prng_state->gauss_f; + prng_state->has_gauss_f = false; + return temp; + } else { + float f, x1, x2, r2; + + do { + x1 = 2.0f * next_float(prng_state) - 1.0f; + x2 = 2.0f * next_float(prng_state) - 1.0f; + r2 = x1 * x1 + x2 * x2; + } while (r2 >= 1.0 || r2 == 0.0); + + /* Box-Muller transform */ + f = sqrtf(-2.0f * logf(r2) / r2); + /* Keep for next call */ + prng_state->gauss_f = f * x1; + prng_state->has_gauss_f = true; + return f * x2; + } } double standard_exponential_zig(prng_t *prng_state); -static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, double x) -{ - if (idx == 0) - { - return ziggurat_exp_r - log(prng_state->next_double(prng_state->state)); - } - else if ((fe_double[idx - 1] - fe_double[idx]) * prng_state->next_double(prng_state->state) + fe_double[idx] < exp(-x)) - { - return x; - } - else - { - return standard_exponential_zig(prng_state); - } +static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, + double x) { + if (idx == 0) { + return ziggurat_exp_r - log(prng_state->next_double(prng_state->state)); + } else if ((fe_double[idx - 1] - fe_double[idx]) * + prng_state->next_double(prng_state->state) + + fe_double[idx] < + exp(-x)) { + return x; + } else { + return standard_exponential_zig(prng_state); + } } -double standard_exponential_zig(prng_t *prng_state) -{ - uint64_t ri; - uint8_t idx; - double x; - ri = prng_state->next_uint64(prng_state->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(prng_state, idx, x); +double standard_exponential_zig(prng_t *prng_state) { + uint64_t ri; + uint8_t idx; + double x; + ri = prng_state->next_uint64(prng_state->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(prng_state, idx, x); } -double random_standard_exponential_zig(prng_t *prng_state) -{ - return standard_exponential_zig(prng_state); +double random_standard_exponential_zig(prng_t *prng_state) { + return standard_exponential_zig(prng_state); } static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state); -static float standard_exponential_zig_unlikely_f(prng_t *prng_state, uint8_t idx, float x) -{ - if (idx == 0) - { - return ziggurat_exp_r_f - logf(next_float(prng_state)); - } - else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(prng_state) + fe_float[idx] < expf(-x)) - { - return x; - } - else - { - return standard_exponential_zig_f(prng_state); - } +static float standard_exponential_zig_unlikely_f(prng_t *prng_state, + uint8_t idx, float x) { + if (idx == 0) { + return ziggurat_exp_r_f - logf(next_float(prng_state)); + } else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(prng_state) + + fe_float[idx] < + expf(-x)) { + return x; + } else { + return standard_exponential_zig_f(prng_state); + } } -static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) -{ - uint32_t ri; - uint8_t idx; - float x; - ri = prng_state->next_uint32(prng_state->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(prng_state, idx, x); +static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) { + uint32_t ri; + uint8_t idx; + float x; + ri = prng_state->next_uint32(prng_state->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(prng_state, idx, x); } -float random_standard_exponential_zig_f(prng_t *prng_state) -{ - return standard_exponential_zig_f(prng_state); +float random_standard_exponential_zig_f(prng_t *prng_state) { + return standard_exponential_zig_f(prng_state); } - -double random_gauss_zig(prng_t* prng_state) -{ - uint64_t r; - int sign; - int64_t rabs; - int idx; - double x, xx, yy; - for (;;) - { - /* r = e3n52sb8 */ - r = prng_state->next_uint64(prng_state->state); - idx = r & 0xff; - r >>= 8; - sign = r & 0x1; - rabs = (int64_t)((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 (;;) - { - xx = -ziggurat_nor_inv_r * log(prng_state->next_double(prng_state->state)); - yy = -log(prng_state->next_double(prng_state->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]) * prng_state->next_double(prng_state->state) + fi_double[idx]) < exp(-0.5 * x * x)) - return x; - } +double random_gauss_zig(prng_t *prng_state) { + uint64_t r; + int sign; + int64_t rabs; + int idx; + double x, xx, yy; + for (;;) { + /* r = e3n52sb8 */ + r = prng_state->next_uint64(prng_state->state); + idx = r & 0xff; + r >>= 8; + sign = r & 0x1; + rabs = (int64_t)((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 (;;) { + xx = -ziggurat_nor_inv_r * + log(prng_state->next_double(prng_state->state)); + yy = -log(prng_state->next_double(prng_state->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]) * + prng_state->next_double(prng_state->state) + + fi_double[idx]) < exp(-0.5 * x * x)) + return x; } + } } -float random_gauss_zig_f(prng_t* prng_state) -{ - uint32_t r; - int sign; - int32_t rabs; - int idx; - float x, xx, yy; - for (;;) - { - /* r = n23sb8 */ - r = prng_state->next_uint32(prng_state->state); - idx = r & 0xff; - sign = (r >> 8) & 0x1; - rabs = (int32_t)((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 (;;) - { - xx = -ziggurat_nor_inv_r_f * logf(next_float(prng_state)); - yy = -logf(next_float(prng_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(prng_state) + fi_float[idx]) < exp(-0.5 * x * x)) - return x; - } +float random_gauss_zig_f(prng_t *prng_state) { + uint32_t r; + int sign; + int32_t rabs; + int idx; + float x, xx, yy; + for (;;) { + /* r = n23sb8 */ + r = prng_state->next_uint32(prng_state->state); + idx = r & 0xff; + sign = (r >> 8) & 0x1; + rabs = (int32_t)((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 (;;) { + xx = -ziggurat_nor_inv_r_f * logf(next_float(prng_state)); + yy = -logf(next_float(prng_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(prng_state) + + fi_float[idx]) < exp(-0.5 * x * x)) + return x; } + } } -static NPY_INLINE double standard_gamma(prng_t* prng_state, double shape) -{ - double b, c; - double U, V, X, Y; - - if (shape == 1.0) - { - return random_standard_exponential(prng_state); - } - else if (shape < 1.0) - { - for (;;) - { - U = prng_state->next_double(prng_state->state); - V = random_standard_exponential(prng_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; - } - } +static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { + double b, c; + double U, V, X, Y; + + if (shape == 1.0) { + return random_standard_exponential(prng_state); + } else if (shape < 1.0) { + for (;;) { + U = prng_state->next_double(prng_state->state); + V = random_standard_exponential(prng_state); + if (U <= 1.0 - shape) { + X = pow(U, 1. / shape); + if (X <= V) { + return X; } - } - else - { - b = shape - 1. / 3.; - c = 1. / sqrt(9 * b); - for (;;) - { - do - { - X = random_gauss(prng_state); - V = 1.0 + c * X; - } while (V <= 0.0); - - V = V * V * V; - U = random_sample(prng_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); + } 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(prng_state); + V = 1.0 + c * X; + } while (V <= 0.0); + + V = V * V * V; + U = random_sample(prng_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(prng_t *prng_state, float shape) -{ - float b, c; - float U, V, X, Y; - - if (shape == 1.0f) - { - return random_standard_exponential_f(prng_state); - } - else if (shape < 1.0f) - { - for (;;) - { - U = random_sample_f(prng_state); - V = random_standard_exponential_f(prng_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; - } - } +static NPY_INLINE float standard_gamma_float(prng_t *prng_state, float shape) { + float b, c; + float U, V, X, Y; + + if (shape == 1.0f) { + return random_standard_exponential_f(prng_state); + } else if (shape < 1.0f) { + for (;;) { + U = random_sample_f(prng_state); + V = random_standard_exponential_f(prng_state); + if (U <= 1.0f - shape) { + X = powf(U, 1.0f / shape); + if (X <= V) { + return X; } - } - else - { - b = shape - 1.0f / 3.0f; - c = 1.0f / sqrtf(9.0f * b); - for (;;) - { - do - { - X = random_gauss_f(prng_state); - V = 1.0f + c * X; - } while (V <= 0.0f); - - V = V * V * V; - U = random_sample_f(prng_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); + } 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(prng_state); + V = 1.0f + c * X; + } while (V <= 0.0f); + + V = V * V * V; + U = random_sample_f(prng_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(prng_t* prng_state, double shape) -{ - return standard_gamma(prng_state, shape); +double random_standard_gamma(prng_t *prng_state, double shape) { + return standard_gamma(prng_state, shape); } -float random_standard_gamma_f(prng_t* prng_state, float shape) -{ - return standard_gamma_float(prng_state, shape); +float random_standard_gamma_f(prng_t *prng_state, float shape) { + return standard_gamma_float(prng_state, shape); } - -static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) -{ - double b, c; - double U, V, X, Y; - - if (shape == 1.0) - { - return random_standard_exponential_zig(prng_state); - } - else if (shape < 1.0) - { - for (;;) - { - U = random_sample(prng_state); - V = random_standard_exponential_zig(prng_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; - } - } +static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) { + double b, c; + double U, V, X, Y; + + if (shape == 1.0) { + return random_standard_exponential_zig(prng_state); + } else if (shape < 1.0) { + for (;;) { + U = random_sample(prng_state); + V = random_standard_exponential_zig(prng_state); + if (U <= 1.0 - shape) { + X = pow(U, 1. / shape); + if (X <= V) { + return X; } - } - else - { - b = shape - 1. / 3.; - c = 1. / sqrt(9 * b); - for (;;) - { - do - { - X = random_gauss_zig(prng_state); - V = 1.0 + c * X; - } while (V <= 0.0); - - V = V * V * V; - U = random_sample(prng_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); + } 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(prng_state); + V = 1.0 + c * X; + } while (V <= 0.0); + + V = V * V * V; + U = random_sample(prng_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_zig_f(prng_t *prng_state, float shape) -{ - float b, c; - float U, V, X, Y; - - if (shape == 1.0f) - { - return random_standard_exponential_zig_f(prng_state); - } - else if (shape < 1.0f) - { - for (;;) - { - U = random_sample_f(prng_state); - V = random_standard_exponential_zig_f(prng_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; - } - } +static NPY_INLINE float standard_gamma_zig_f(prng_t *prng_state, float shape) { + float b, c; + float U, V, X, Y; + + if (shape == 1.0f) { + return random_standard_exponential_zig_f(prng_state); + } else if (shape < 1.0f) { + for (;;) { + U = random_sample_f(prng_state); + V = random_standard_exponential_zig_f(prng_state); + if (U <= 1.0f - shape) { + X = powf(U, 1.0f / shape); + if (X <= V) { + return X; } - } - else - { - b = shape - 1.0f / 3.0f; - c = 1.0f / sqrtf(9.0f * b); - for (;;) - { - do - { - X = random_gauss_zig_f(prng_state); - V = 1.0f + c * X; - } while (V <= 0.0f); - - V = V * V * V; - U = random_sample_f(prng_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); + } 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(prng_state); + V = 1.0f + c * X; + } while (V <= 0.0f); + + V = V * V * V; + U = random_sample_f(prng_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_zig(prng_t *prng_state, double shape) -{ - return standard_gamma_zig(prng_state, shape); +double random_standard_gamma_zig(prng_t *prng_state, double shape) { + return standard_gamma_zig(prng_state, shape); } -float random_standard_gamma_zig_f(prng_t *prng_state, float shape) -{ - return standard_gamma_zig_f(prng_state, shape); +float random_standard_gamma_zig_f(prng_t *prng_state, float shape) { + return standard_gamma_zig_f(prng_state, shape); } diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c index 9103f6d5030d..c34451236ec7 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c @@ -1,53 +1,50 @@ /* -* -* gcc dSFMT-test-gen.c dSFMT.c -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o dSFMT -*/ -#include -#include + * + * gcc dSFMT-test-gen.c dSFMT.c -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o dSFMT + */ #include "dSFMT.h" +#include +#include -int main(void) -{ - int i; - double d; - uint64_t *temp; - uint32_t seed = 1UL; - dsfmt_t state; - dsfmt_init_gen_rand(&state, seed); - double out[1000]; - dsfmt_fill_array_close1_open2(&state, out, 1000); +int main(void) { + int i; + double d; + uint64_t *temp; + uint32_t seed = 1UL; + dsfmt_t state; + dsfmt_init_gen_rand(&state, seed); + double out[1000]; + dsfmt_fill_array_close1_open2(&state, out, 1000); - FILE *fp; - fp = fopen("dSFMT-testset-1.csv", "w"); - if(fp == NULL){ - printf("Couldn't open file\n"); - return -1; - } - fprintf(fp, "seed, %" PRIu32 "\n", seed); - for (i=0; i < 1000; i++) - { - d = out[i]; - temp = (uint64_t *)&d; - fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); - printf("%d, %" PRIu64 "\n", i, *temp); - } - fclose(fp); + FILE *fp; + fp = fopen("dSFMT-testset-1.csv", "w"); + if (fp == NULL) { + printf("Couldn't open file\n"); + return -1; + } + fprintf(fp, "seed, %" PRIu32 "\n", seed); + for (i = 0; i < 1000; i++) { + d = out[i]; + temp = (uint64_t *)&d; + fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); + printf("%d, %" PRIu64 "\n", i, *temp); + } + fclose(fp); - seed = 123456789UL; - dsfmt_init_gen_rand(&state, seed); - dsfmt_fill_array_close1_open2(&state, out, 1000); - fp = fopen("dSFMT-testset-2.csv", "w"); - if(fp == NULL){ - printf("Couldn't open file\n"); - return -1; - } - fprintf(fp, "seed, %" PRIu32 "\n", seed); - for (i=0; i < 1000; i++) - { - d = out[i]; - temp = (uint64_t *)&d; - fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); - printf("%d, %" PRIu64 "\n", i, *temp); - } - fclose(fp); -} \ No newline at end of file + seed = 123456789UL; + dsfmt_init_gen_rand(&state, seed); + dsfmt_fill_array_close1_open2(&state, out, 1000); + fp = fopen("dSFMT-testset-2.csv", "w"); + if (fp == NULL) { + printf("Couldn't open file\n"); + return -1; + } + fprintf(fp, "seed, %" PRIu32 "\n", seed); + for (i = 0; i < 1000; i++) { + d = out[i]; + temp = (uint64_t *)&d; + fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); + printf("%d, %" PRIu64 "\n", i, *temp); + } + fclose(fp); +} diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.c b/_randomgen/core_prng/src/dsfmt/dSFMT.c index 3ce156699175..0955e087fbaa 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.c @@ -11,11 +11,11 @@ * * The new BSD License is applied to this software, see LICENSE.txt */ +#include "dSFMT-common.h" +#include "dSFMT-params.h" #include -#include #include -#include "dSFMT-params.h" -#include "dSFMT-common.h" +#include #if defined(__cplusplus) extern "C" { @@ -31,14 +31,10 @@ static const int dsfmt_mexp = DSFMT_MEXP; ----------------*/ inline static uint32_t ini_func1(uint32_t x); inline static uint32_t ini_func2(uint32_t x); -inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, - int size); +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, int size); inline static int idxof(int i); static void initial_mask(dsfmt_t *dsfmt); static void period_certification(dsfmt_t *dsfmt); @@ -57,13 +53,9 @@ static const union X128D_T sse2_double_m_one = {{-1.0, -1.0}}; * array of LITTLE ENDIAN in BIG ENDIAN machine. */ #if defined(DSFMT_BIG_ENDIAN) -inline static int idxof(int i) { - return i ^ 1; -} +inline static int idxof(int i) { return i ^ 1; } #else -inline static int idxof(int i) { - return i; -} +inline static int idxof(int i) { return i; } #endif #if defined(HAVE_SSE2) @@ -74,7 +66,7 @@ inline static int idxof(int i) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } /** @@ -84,7 +76,7 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); + w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); } /** @@ -94,8 +86,8 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->si = _mm_or_si128(w->si, sse2_int_one.i128); - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->si = _mm_or_si128(w->si, sse2_int_one.i128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } #else /* standard C and altivec */ /** @@ -105,8 +97,8 @@ inline static void convert_o0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } /** @@ -116,8 +108,8 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->d[0] = 2.0 - w->d[0]; - w->d[1] = 2.0 - w->d[1]; + w->d[0] = 2.0 - w->d[0]; + w->d[1] = 2.0 - w->d[1]; } /** @@ -127,10 +119,10 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->u[0] |= 1; - w->u[1] |= 1; - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->u[0] |= 1; + w->u[1] |= 1; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } #endif @@ -142,34 +134,33 @@ inline static void convert_o0o1(w128_t *w) { * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -180,39 +171,38 @@ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_c0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_c0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_c0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_c0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_c0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_c0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -223,39 +213,38 @@ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -266,39 +255,38 @@ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0c1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0c1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0c1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0c1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0c1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0c1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -308,7 +296,7 @@ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, * @return 32-bit integer */ static uint32_t ini_func1(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1664525UL; + return (x ^ (x >> 27)) * (uint32_t)1664525UL; } /** @@ -318,7 +306,7 @@ static uint32_t ini_func1(uint32_t x) { * @return 32-bit integer */ static uint32_t ini_func2(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1566083941UL; + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; } /** @@ -327,13 +315,13 @@ static uint32_t ini_func2(uint32_t x) { * @param dsfmt dsfmt state vector. */ static void initial_mask(dsfmt_t *dsfmt) { - int i; - uint64_t *psfmt; + int i; + uint64_t *psfmt; - psfmt = &dsfmt->status[0].u[0]; - for (i = 0; i < DSFMT_N * 2; i++) { - psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; - } + psfmt = &dsfmt->status[0].u[0]; + for (i = 0; i < DSFMT_N * 2; i++) { + psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; + } } /** @@ -341,44 +329,44 @@ static void initial_mask(dsfmt_t *dsfmt) { * @param dsfmt dsfmt state vector. */ static void period_certification(dsfmt_t *dsfmt) { - uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; - uint64_t tmp[2]; - uint64_t inner; - int i; + uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; + uint64_t tmp[2]; + uint64_t inner; + int i; #if (DSFMT_PCV2 & 1) != 1 - int j; - uint64_t work; + int j; + uint64_t work; #endif - tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); - tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); - - inner = tmp[0] & pcv[0]; - inner ^= tmp[1] & pcv[1]; - for (i = 32; i > 0; i >>= 1) { - inner ^= inner >> i; - } - inner &= 1; - /* check OK */ - if (inner == 1) { - return; - } + tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); + tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); + + inner = tmp[0] & pcv[0]; + inner ^= tmp[1] & pcv[1]; + for (i = 32; i > 0; i >>= 1) { + inner ^= inner >> i; + } + inner &= 1; + /* check OK */ + if (inner == 1) { + return; + } /* check NG, and modification */ #if (DSFMT_PCV2 & 1) == 1 - dsfmt->status[DSFMT_N].u[1] ^= 1; + dsfmt->status[DSFMT_N].u[1] ^= 1; #else - for (i = 1; i >= 0; i--) { - work = 1; - for (j = 0; j < 64; j++) { - if ((work & pcv[i]) != 0) { - dsfmt->status[DSFMT_N].u[i] ^= work; - return; - } - work = work << 1; - } - } + for (i = 1; i >= 0; i--) { + work = 1; + for (j = 0; j < 64; j++) { + if ((work & pcv[i]) != 0) { + dsfmt->status[DSFMT_N].u[i] ^= work; + return; + } + work = work << 1; + } + } #endif - return; + return; } /*---------------- @@ -389,18 +377,14 @@ static void period_certification(dsfmt_t *dsfmt) { * the Mersenne exponent, and all parameters of this generator. * @return id string. */ -const char *dsfmt_get_idstring(void) { - return DSFMT_IDSTR; -} +const char *dsfmt_get_idstring(void) { return DSFMT_IDSTR; } /** * This function returns the minimum size of array used for \b * fill_array functions. * @return minimum size of array used for fill_array functions. */ -int dsfmt_get_min_array_size(void) { - return DSFMT_N64; -} +int dsfmt_get_min_array_size(void) { return DSFMT_N64; } /** * This function fills the internal state array with double precision @@ -408,21 +392,21 @@ int dsfmt_get_min_array_size(void) { * @param dsfmt dsfmt state vector. */ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { - int i; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&dsfmt->status[0], &dsfmt->status[0], - &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); - } - dsfmt->status[DSFMT_N] = lung; + int i; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&dsfmt->status[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -454,9 +438,9 @@ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { * returns the pointer to the aligned memory block. */ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); } /** @@ -472,9 +456,9 @@ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); } /** @@ -490,9 +474,9 @@ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); } /** @@ -508,13 +492,13 @@ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); } #if defined(__INTEL_COMPILER) -# pragma warning(disable:981) +#pragma warning(disable : 981) #endif /** * This function initializes the internal state array with a 32-bit @@ -524,23 +508,23 @@ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { - int i; - uint32_t *psfmt; - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - psfmt = &dsfmt->status[0].u32[0]; - psfmt[idxof(0)] = seed; - for (i = 1; i < (DSFMT_N + 1) * 4; i++) { - psfmt[idxof(i)] = 1812433253UL - * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int i; + uint32_t *psfmt; + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + psfmt = &dsfmt->status[0].u32[0]; + psfmt[idxof(0)] = seed; + for (i = 1; i < (DSFMT_N + 1) * 4; i++) { + psfmt[idxof(i)] = + 1812433253UL * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } /** @@ -552,80 +536,77 @@ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], - int key_length, int mexp) { - int i, j, count; - uint32_t r; - uint32_t *psfmt32; - int lag; - int mid; - int size = (DSFMT_N + 1) * 4; /* pulmonary */ - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - if (size >= 623) { - lag = 11; - } else if (size >= 68) { - lag = 7; - } else if (size >= 39) { - lag = 5; - } else { - lag = 3; - } - mid = (size - lag) / 2; - - psfmt32 = &dsfmt->status[0].u32[0]; - memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); - if (key_length + 1 > size) { - count = key_length + 1; - } else { - count = size; - } - r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] - ^ psfmt32[idxof((size - 1) % size)]); - psfmt32[idxof(mid % size)] += r; - r += key_length; - psfmt32[idxof((mid + lag) % size)] += r; - psfmt32[idxof(0)] = r; - count--; - for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = ini_func1(psfmt32[idxof(i)] - ^ psfmt32[idxof((i + mid) % size)] - ^ psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += init_key[j] + i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (; j < count; j++) { - r = ini_func1(psfmt32[idxof(i)] - ^ psfmt32[idxof((i + mid) % size)] - ^ psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (j = 0; j < size; j++) { - r = ini_func2(psfmt32[idxof(i)] - + psfmt32[idxof((i + mid) % size)] - + psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] ^= r; - r -= i; - psfmt32[idxof((i + mid + lag) % size)] ^= r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int key_length, int mexp) { + int i, j, count; + uint32_t r; + uint32_t *psfmt32; + int lag; + int mid; + int size = (DSFMT_N + 1) * 4; /* pulmonary */ + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + if (size >= 623) { + lag = 11; + } else if (size >= 68) { + lag = 7; + } else if (size >= 39) { + lag = 5; + } else { + lag = 3; + } + mid = (size - lag) / 2; + + psfmt32 = &dsfmt->status[0].u32[0]; + memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); + if (key_length + 1 > size) { + count = key_length + 1; + } else { + count = size; + } + r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] ^ + psfmt32[idxof((size - 1) % size)]); + psfmt32[idxof(mid % size)] += r; + r += key_length; + psfmt32[idxof((mid + lag) % size)] += r; + psfmt32[idxof(0)] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += init_key[j] + i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % size)] + + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] ^= r; + r -= i; + psfmt32[idxof((i + mid + lag) % size)] ^= r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } #if defined(__INTEL_COMPILER) -# pragma warning(default:981) +#pragma warning(default : 981) #endif #if defined(__cplusplus) @@ -636,4 +617,4 @@ extern inline double dsfmt_next_double(dsfmt_state *state); extern inline uint64_t dsfmt_next64(dsfmt_state *state); -extern inline uint32_t dsfmt_next32(dsfmt_state *state); \ No newline at end of file +extern inline uint32_t dsfmt_next32(dsfmt_state *state); diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index 52b6b3aedcc2..c9a34ae86691 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -38,14 +38,14 @@ extern "C" { #endif -#include #include +#include #if !defined(DSFMT_MEXP) #ifdef __GNUC__ - #warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." +#warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." #endif - #define DSFMT_MEXP 19937 +#define DSFMT_MEXP 19937 #endif /*----------------- BASIC DEFINITIONS @@ -64,103 +64,103 @@ extern "C" { #define DSFMT_N64 (DSFMT_N * 2) #if !defined(DSFMT_BIG_ENDIAN) -# if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) -# if __BYTE_ORDER == __BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) -# if _BYTE_ORDER == _BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) -# if __BYTE_ORDER__ == __BIG_ENDIAN__ -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) -# if BYTE_ORDER == BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) \ - || defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) -# define DSFMT_BIG_ENDIAN 1 -# endif +#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +#if __BYTE_ORDER == __BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) +#if _BYTE_ORDER == _BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) +#if __BYTE_ORDER__ == __BIG_ENDIAN__ +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) +#if BYTE_ORDER == BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || \ + defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) +#define DSFMT_BIG_ENDIAN 1 +#endif #endif #if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) -# undef DSFMT_BIG_ENDIAN +#undef DSFMT_BIG_ENDIAN #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# include +#include #elif defined(_MSC_VER) || defined(__BORLANDC__) -# if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) +#if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; -# ifndef UINT64_C -# define UINT64_C(v) (v ## ui64) -# endif -# define DSFMT_UINT32_DEFINED -# if !defined(inline) && !defined(__cplusplus) -# define inline __forceinline -# endif -# endif +#ifndef UINT64_C +#define UINT64_C(v) (v##ui64) +#endif +#define DSFMT_UINT32_DEFINED +#if !defined(inline) && !defined(__cplusplus) +#define inline __forceinline +#endif +#endif +#else +#include +#if !defined(inline) && !defined(__cplusplus) +#if defined(__GNUC__) +#define inline __forceinline__ #else -# include -# if !defined(inline) && !defined(__cplusplus) -# if defined(__GNUC__) -# define inline __forceinline__ -# else -# define inline -# endif -# endif +#define inline +#endif +#endif #endif #ifndef PRIu64 -# if defined(_MSC_VER) || defined(__BORLANDC__) -# define PRIu64 "I64u" -# define PRIx64 "I64x" -# else -# define PRIu64 "llu" -# define PRIx64 "llx" -# endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#else +#define PRIu64 "llu" +#define PRIx64 "llx" +#endif #endif #ifndef UINT64_C -# define UINT64_C(v) (v ## ULL) +#define UINT64_C(v) (v##ULL) #endif /*------------------------------------------ 128-bit SIMD like data type for standard C ------------------------------------------*/ #if defined(HAVE_ALTIVEC) -# if !defined(__APPLE__) -# include -# endif +#if !defined(__APPLE__) +#include +#endif /** 128-bit data structure */ union W128_T { - vector unsigned int s; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + vector unsigned int s; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #elif defined(HAVE_SSE2) -# include +#include /** 128-bit data structure */ union W128_T { - __m128i si; - __m128d sd; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + __m128i si; + __m128d sd; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; -#else /* standard C */ +#else /* standard C */ /** 128-bit data structure */ union W128_T { - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #endif @@ -169,8 +169,8 @@ typedef union W128_T w128_t; /** the 128-bit internal state array */ struct DSFMT_T { - w128_t status[DSFMT_N + 1]; - int idx; + w128_t status[DSFMT_N + 1]; + int idx; }; typedef struct DSFMT_T dsfmt_t; @@ -191,42 +191,42 @@ const char *dsfmt_get_idstring(void); int dsfmt_get_min_array_size(void); #if defined(__GNUC__) -# define DSFMT_PRE_INLINE inline static -# define DSFMT_PST_INLINE __attribute__((always_inline)) +#define DSFMT_PRE_INLINE inline static +#define DSFMT_PST_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) && _MSC_VER >= 1200 -# define DSFMT_PRE_INLINE __forceinline static -# define DSFMT_PST_INLINE +#define DSFMT_PRE_INLINE __forceinline static +#define DSFMT_PST_INLINE #else -# define DSFMT_PRE_INLINE inline static -# define DSFMT_PST_INLINE +#define DSFMT_PRE_INLINE inline static +#define DSFMT_PST_INLINE #endif DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_close_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_open_close(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_open_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void +dsfmt_gv_fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, + uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) DSFMT_PST_INLINE; @@ -239,15 +239,15 @@ DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { - uint32_t r; - uint64_t *psfmt64 = &dsfmt->status[0].u[0]; + uint32_t r; + uint64_t *psfmt64 = &dsfmt->status[0].u[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++] & 0xffffffffU; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++] & 0xffffffffU; + return r; } /** @@ -260,15 +260,15 @@ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { - double r; - double *psfmt64 = &dsfmt->status[0].d[0]; + double r; + double *psfmt64 = &dsfmt->status[0].d[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++]; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++]; + return r; } /** @@ -279,7 +279,7 @@ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_gv_genrand_uint32(void) { - return dsfmt_genrand_uint32(&dsfmt_global_data); + return dsfmt_genrand_uint32(&dsfmt_global_data); } /** @@ -290,7 +290,7 @@ inline static uint32_t dsfmt_gv_genrand_uint32(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close1_open2(void) { - return dsfmt_genrand_close1_open2(&dsfmt_global_data); + return dsfmt_genrand_close1_open2(&dsfmt_global_data); } /** @@ -302,7 +302,7 @@ inline static double dsfmt_gv_genrand_close1_open2(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { - return dsfmt_genrand_close1_open2(dsfmt) - 1.0; + return dsfmt_genrand_close1_open2(dsfmt) - 1.0; } /** @@ -313,7 +313,7 @@ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close_open(void) { - return dsfmt_gv_genrand_close1_open2() - 1.0; + return dsfmt_gv_genrand_close1_open2() - 1.0; } /** @@ -325,7 +325,7 @@ inline static double dsfmt_gv_genrand_close_open(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { - return 2.0 - dsfmt_genrand_close1_open2(dsfmt); + return 2.0 - dsfmt_genrand_close1_open2(dsfmt); } /** @@ -336,7 +336,7 @@ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_close(void) { - return 2.0 - dsfmt_gv_genrand_close1_open2(); + return 2.0 - dsfmt_gv_genrand_close1_open2(); } /** @@ -348,19 +348,19 @@ inline static double dsfmt_gv_genrand_open_close(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { - double *dsfmt64 = &dsfmt->status[0].d[0]; - union { - double d; - uint64_t u; - } r; - - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r.d = dsfmt64[dsfmt->idx++]; - r.u |= 1; - return r.d - 1.0; + double *dsfmt64 = &dsfmt->status[0].d[0]; + union { + double d; + uint64_t u; + } r; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r.d = dsfmt64[dsfmt->idx++]; + r.u |= 1; + return r.d - 1.0; } /** @@ -371,7 +371,7 @@ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_open(void) { - return dsfmt_genrand_open_open(&dsfmt_global_data); + return dsfmt_genrand_open_open(&dsfmt_global_data); } /** @@ -386,7 +386,7 @@ inline static double dsfmt_gv_genrand_open_open(void) { * see also \sa dsfmt_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { - dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); + dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); } /** @@ -402,7 +402,7 @@ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { - dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); } /** @@ -418,7 +418,7 @@ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { - dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); } /** @@ -434,7 +434,7 @@ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { - dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); } /** @@ -444,7 +444,7 @@ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { * @param seed a 32-bit integer used as the seed. */ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { - dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); + dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); } /** @@ -454,7 +454,7 @@ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { * see also \sa dsfmt_init_gen_rand() */ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { - dsfmt_init_gen_rand(&dsfmt_global_data, seed); + dsfmt_init_gen_rand(&dsfmt_global_data, seed); } /** @@ -466,7 +466,7 @@ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { */ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) { - dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); + dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); } /** @@ -478,36 +478,34 @@ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * see also \sa dsfmt_init_by_array() */ inline static void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { - dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); + dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); } #if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], + int key_length) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_close(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], + int size) DSFMT_PST_INLINE; /** * This function is just the same as dsfmt_get_idstring(). * @return id string. * see also \sa dsfmt_get_idstring() */ -inline static const char *get_idstring(void) { - return dsfmt_get_idstring(); -} +inline static const char *get_idstring(void) { return dsfmt_get_idstring(); } /** * This function is just the same as dsfmt_get_min_array_size(). @@ -515,7 +513,7 @@ inline static const char *get_idstring(void) { * see also \sa dsfmt_get_min_array_size() */ inline static int get_min_array_size(void) { - return dsfmt_get_min_array_size(); + return dsfmt_get_min_array_size(); } /** @@ -524,7 +522,7 @@ inline static int get_min_array_size(void) { * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). */ inline static void init_gen_rand(uint32_t seed) { - dsfmt_gv_init_gen_rand(seed); + dsfmt_gv_init_gen_rand(seed); } /** @@ -534,7 +532,7 @@ inline static void init_gen_rand(uint32_t seed) { * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). */ inline static void init_by_array(uint32_t init_key[], int key_length) { - dsfmt_gv_init_by_array(init_key, key_length); + dsfmt_gv_init_by_array(init_key, key_length); } /** @@ -544,7 +542,7 @@ inline static void init_by_array(uint32_t init_key[], int key_length) { * dsfmt_gv_genrand_close1_open2() */ inline static double genrand_close1_open2(void) { - return dsfmt_gv_genrand_close1_open2(); + return dsfmt_gv_genrand_close1_open2(); } /** @@ -554,7 +552,7 @@ inline static double genrand_close1_open2(void) { * dsfmt_gv_genrand_close_open() */ inline static double genrand_close_open(void) { - return dsfmt_gv_genrand_close_open(); + return dsfmt_gv_genrand_close_open(); } /** @@ -564,7 +562,7 @@ inline static double genrand_close_open(void) { * dsfmt_gv_genrand_open_close() */ inline static double genrand_open_close(void) { - return dsfmt_gv_genrand_open_close(); + return dsfmt_gv_genrand_open_close(); } /** @@ -574,7 +572,7 @@ inline static double genrand_open_close(void) { * dsfmt_gv_genrand_open_open() */ inline static double genrand_open_open(void) { - return dsfmt_gv_genrand_open_open(); + return dsfmt_gv_genrand_open_open(); } /** @@ -587,7 +585,7 @@ inline static double genrand_open_open(void) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_close(double array[], int size) { - dsfmt_gv_fill_array_open_close(array, size); + dsfmt_gv_fill_array_open_close(array, size); } /** @@ -600,7 +598,7 @@ inline static void fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close_open(double array[], int size) { - dsfmt_gv_fill_array_close_open(array, size); + dsfmt_gv_fill_array_close_open(array, size); } /** @@ -613,7 +611,7 @@ inline static void fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_open(double array[], int size) { - dsfmt_gv_fill_array_open_open(array, size); + dsfmt_gv_fill_array_open_open(array, size); } /** @@ -625,7 +623,7 @@ inline static void fill_array_open_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close1_open2(double array[], int size) { - dsfmt_gv_fill_array_close1_open2(array, size); + dsfmt_gv_fill_array_close1_open2(array, size); } #endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ @@ -635,7 +633,6 @@ inline static void fill_array_close1_open2(double array[], int size) { #endif /* DSFMT_H */ - typedef struct s_dsfmt_state { dsfmt_t *state; int has_uint32; @@ -651,7 +648,8 @@ static inline double dsfmt_next_double(dsfmt_state *state) { state->buffer_loc++; return out; } - dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, DSFMT_N64); + dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, + DSFMT_N64); state->buffer_loc = 1; return state->buffered_uniforms[0]; } @@ -669,7 +667,6 @@ static inline uint64_t dsfmt_next64(dsfmt_state *state) { return out; } - static inline uint32_t dsfmt_next32(dsfmt_state *state) { /* Discard bottom 16 bits */ double d = dsfmt_next_double(state); diff --git a/_randomgen/core_prng/src/mt19937/mt19937.c b/_randomgen/core_prng/src/mt19937/mt19937.c index 699efd21d08a..bb080c1a2ee1 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937.c +++ b/_randomgen/core_prng/src/mt19937/mt19937.c @@ -1,109 +1,103 @@ #include "mt19937.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; +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; +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; - } +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; } - 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; - } + if (j >= key_length) { + j = 0; } - - 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); + } + 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; } - 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; + 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); \ No newline at end of file +extern inline double mt19937_next_double(mt19937_state *state); diff --git a/_randomgen/core_prng/src/mt19937/mt19937.h b/_randomgen/core_prng/src/mt19937/mt19937.h index b9617769a622..18da9622decf 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937.h +++ b/_randomgen/core_prng/src/mt19937/mt19937.h @@ -14,7 +14,6 @@ #define inline __forceinline #endif - #define RK_STATE_LEN 624 #define N 624 @@ -23,10 +22,9 @@ #define UPPER_MASK 0x80000000UL #define LOWER_MASK 0x7fffffffUL -typedef struct s_mt19937_state -{ - uint32_t key[RK_STATE_LEN]; - int pos; +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); @@ -34,26 +32,26 @@ 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; +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++]; + 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); + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); - return y; + return y; } -extern void mt19937_init_by_array(mt19937_state *state, uint32_t *init_key, int key_length); +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); diff --git a/_randomgen/core_prng/src/mt19937/randomkit.c b/_randomgen/core_prng/src/mt19937/randomkit.c index 17f10a288f39..947d2adb1067 100644 --- a/_randomgen/core_prng/src/mt19937/randomkit.c +++ b/_randomgen/core_prng/src/mt19937/randomkit.c @@ -81,7 +81,6 @@ #include #include - /* * 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 @@ -128,7 +127,6 @@ #include #include - #ifndef RK_DEV_URANDOM #define RK_DEV_URANDOM "/dev/urandom" #endif @@ -577,4 +575,4 @@ double rk_gauss(rk_state *state) { state->has_gauss = 1; return f * x2; } -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/mt19937/randomkit.h b/_randomgen/core_prng/src/mt19937/randomkit.h index f57f50ae360e..abb082cb2ed8 100644 --- a/_randomgen/core_prng/src/mt19937/randomkit.h +++ b/_randomgen/core_prng/src/mt19937/randomkit.h @@ -220,4 +220,4 @@ extern double rk_gauss(rk_state *state); } #endif -#endif /* _RANDOMKIT_ */ \ No newline at end of file +#endif /* _RANDOMKIT_ */ diff --git a/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c index d97632d759a0..cb675346c4c0 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c +++ b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c @@ -3,11 +3,12 @@ * * GCC only * - * gcc pcg64-test-data-gen.c pcg64.orig.c ../splitmix64/splitmix64.c -o pgc64-test-data-gen + * gcc pcg64-test-data-gen.c pcg64.orig.c ../splitmix64/splitmix64.c -o + * pgc64-test-data-gen */ -#include "pcg64.orig.h" #include "../splitmix64/splitmix64.h" +#include "pcg64.orig.h" #include #include @@ -62,4 +63,4 @@ int main() { } } fclose(fp); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.c b/_randomgen/core_prng/src/pcg64/pcg64.orig.c index 4ce4736dbc58..24488123edfe 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.orig.c +++ b/_randomgen/core_prng/src/pcg64/pcg64.orig.c @@ -3,4 +3,5 @@ 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); \ No newline at end of file +extern uint64_t +pcg_setseq_128_xsl_rr_64_random_r(struct pcg_state_setseq_128 *rng); diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.h b/_randomgen/core_prng/src/pcg64/pcg64.orig.h index 645025acb01e..74be91f31a50 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.orig.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.orig.h @@ -241,10 +241,10 @@ inline pcg128_t pcg_output_xsl_rr_rr_128_128(pcg128_t state) { PCG_128BIT_CONSTANT(6364136223846793005ULL, 1442695040888963407ULL) #endif -/* - * Static initialization constants (if you can't call srandom for some - * bizarre reason). - */ + /* + * Static initialization constants (if you can't call srandom for some + * bizarre reason). + */ #define PCG_STATE_ONESEQ_8_INITIALIZER \ { 0xd7U } diff --git a/_randomgen/core_prng/src/philox/philox-benchmark.c b/_randomgen/core_prng/src/philox/philox-benchmark.c index 701ee03452cd..0cab04cf55ca 100644 --- a/_randomgen/core_prng/src/philox/philox-benchmark.c +++ b/_randomgen/core_prng/src/philox/philox-benchmark.c @@ -35,4 +35,4 @@ int main() { printf("0x%" PRIx64 "\ncount: %" PRIu64 "\n", sum, count); printf("%" PRIu64 " randoms per second\n", (uint64_t)(N / time_spent) / 1000000 * 1000000); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/philox/philox-test-data-gen.c b/_randomgen/core_prng/src/philox/philox-test-data-gen.c index fd717b959794..b17dd153b3d0 100644 --- a/_randomgen/core_prng/src/philox/philox-test-data-gen.c +++ b/_randomgen/core_prng/src/philox/philox-test-data-gen.c @@ -71,4 +71,4 @@ int main() { } } fclose(fp); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c b/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c index d0c1e158fe0c..df6133aabf4d 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c @@ -9,7 +9,7 @@ See . */ #include /* This is a fixed-increment version of Java 8's SplittableRandom generator - See http://dx.doi.org/10.1145/2714064.2660195 and + 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 @@ -21,8 +21,8 @@ See . */ 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); + uint64_t z = (x += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); } diff --git a/_randomgen/core_prng/src/threefry/threefry-benchmark.c b/_randomgen/core_prng/src/threefry/threefry-benchmark.c index a75e61001970..6d6239cd3d24 100644 --- a/_randomgen/core_prng/src/threefry/threefry-benchmark.c +++ b/_randomgen/core_prng/src/threefry/threefry-benchmark.c @@ -35,4 +35,4 @@ int main() { printf("0x%" PRIx64 "\ncount: %" PRIu64 "\n", sum, count); printf("%" PRIu64 " randoms per second\n", (uint64_t)(N / time_spent) / 1000000 * 1000000); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/threefry/threefry-orig.c b/_randomgen/core_prng/src/threefry/threefry-orig.c index 1a5094fa6b6d..d27cfd7974ff 100644 --- a/_randomgen/core_prng/src/threefry/threefry-orig.c +++ b/_randomgen/core_prng/src/threefry/threefry-orig.c @@ -29,9 +29,8 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include #include "threefry.h" +#include #define N_WORDS 2 #define KEY_LENGTH 3 @@ -42,9 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static const int ROTATION[] = {16, 42, 12, 31, 16, 32, 24, 21}; -uint64_t rotl_64(uint64_t x, int d) { - return ((x << d) | (x >> (64-d))); -} +uint64_t rotl_64(uint64_t x, int d) { return ((x << d) | (x >> (64 - d))); } threefry_t mix(threefry_t x, int R) { x.c0 += x.c1; @@ -53,21 +50,21 @@ threefry_t mix(threefry_t x, int R) { } threefry_t threefry(threefry_t p, threefry_t k) { - uint64_t K[] = {k.c0, k.c1, C240^k.c0^k.c1}; + uint64_t K[] = {k.c0, k.c1, C240 ^ k.c0 ^ k.c1}; int rmod4, rdiv4; threefry_t x; x = p; - for (int r=0; rc0++; return x.c0 * DOUBLE_MULT; -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c index 2fa09eed31f3..4494802489e6 100644 --- a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c +++ b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c @@ -77,4 +77,4 @@ int main() { } } fclose(fp); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c index d49c87ce2109..d95260eca176 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c @@ -69,4 +69,4 @@ int main() { } } fclose(fp); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c index d55a3b3776ca..c0293cc2b586 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c @@ -35,40 +35,39 @@ See . */ uint64_t s[2]; static inline uint64_t rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); + return (x << k) | (x >> (64 - k)); } uint64_t next(void) { - const uint64_t s0 = s[0]; - uint64_t s1 = s[1]; - const uint64_t result = s0 + s1; + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; + const uint64_t result = s0 + s1; - s1 ^= s0; - s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b - s[1] = rotl(s1, 36); // c + s1 ^= s0; + s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b + s[1] = rotl(s1, 36); // c - return result; + return result; } - /* This is the jump function for the generator. It is equivalent to 2^64 calls to next(); it can be used to generate 2^64 non-overlapping subsequences for parallel computations. */ void jump(void) { - static const uint64_t JUMP[] = { 0xbeac0467eba5facb, 0xd86b048b86aa9922 }; - - uint64_t s0 = 0; - uint64_t s1 = 0; - for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for(int b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= s[0]; - s1 ^= s[1]; - } - next(); - } - - s[0] = s0; - s[1] = s1; + static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; + + uint64_t s0 = 0; + uint64_t s1 = 0; + for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + } + next(); + } + + s[0] = s0; + s[1] = s1; } diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c index aa0ebca33085..a2ae08df4f6b 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c @@ -71,4 +71,4 @@ int main() { } } fclose(fp); -} \ No newline at end of file +} diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h index 141010d9d5e9..ae8d24f7dcff 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h @@ -30,4 +30,4 @@ static inline uint32_t xorshift1024_next32(xorshift1024_state *state) { return (uint32_t)(next >> 32); } -void xorshift1024_jump(xorshift1024_state *state); \ No newline at end of file +void xorshift1024_jump(xorshift1024_state *state); diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c b/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c index ed1cf8d6ef77..e4f899fb7b09 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c +++ b/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c @@ -34,36 +34,35 @@ uint64_t s[16]; int p; uint64_t next(void) { - const uint64_t s0 = s[p]; - uint64_t s1 = s[p = (p + 1) & 15]; - s1 ^= s1 << 31; // a - s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c - return s[p] * 0x9e3779b97f4a7c13; + const uint64_t s0 = s[p]; + uint64_t s1 = s[p = (p + 1) & 15]; + s1 ^= s1 << 31; // a + s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c + return s[p] * 0x9e3779b97f4a7c13; } - /* This is the jump function for the generator. It is equivalent to 2^512 calls to next(); it can be used to generate 2^512 non-overlapping subsequences for parallel computations. */ void jump(void) { - static const uint64_t JUMP[] = { 0x84242f96eca9c41d, - 0xa3c65b8776f96855, 0x5b34a39f070b5837, 0x4489affce4f31a1e, - 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, 0x3659132bb12fea70, - 0xaac17d8efa43cab8, 0xc4cb815590989b13, 0x5ee975283d71c93b, - 0x691548c86c1bd540, 0x7910c41d10a1e6a5, 0x0b5fc64563b3e2a8, - 0x047f7684e9fc949d, 0xb99181f2d8f685ca, 0x284600e3f30e38c3 - }; + static const uint64_t JUMP[] = { + 0x84242f96eca9c41d, 0xa3c65b8776f96855, 0x5b34a39f070b5837, + 0x4489affce4f31a1e, 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, + 0x3659132bb12fea70, 0xaac17d8efa43cab8, 0xc4cb815590989b13, + 0x5ee975283d71c93b, 0x691548c86c1bd540, 0x7910c41d10a1e6a5, + 0x0b5fc64563b3e2a8, 0x047f7684e9fc949d, 0xb99181f2d8f685ca, + 0x284600e3f30e38c3}; - uint64_t t[16] = { 0 }; - for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for(int b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) - for(int j = 0; j < 16; j++) - t[j] ^= s[(j + p) & 15]; - next(); - } + uint64_t t[16] = {0}; + for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) + for (int j = 0; j < 16; j++) + t[j] ^= s[(j + p) & 15]; + next(); + } - for(int j = 0; j < 16; j++) - s[(j + p) & 15] = t[j]; -} \ No newline at end of file + for (int j = 0; j < 16; j++) + s[(j + p) & 15] = t[j]; +} From a07137888d6d4345c9ffb46f5b526a4aeea16fdc Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 10:29:53 +0000 Subject: [PATCH 033/138] CLN: Fix dsfmt import issues Revers DSFMT import changes --- .../core_prng/src/dsfmt/dSFMT-benchmark.c | 4 +- .../core_prng/src/dsfmt/dSFMT-test-gen.c | 14 +- _randomgen/core_prng/src/dsfmt/dSFMT.c | 619 +++++++++--------- _randomgen/core_prng/src/dsfmt/dSFMT.h | 325 ++++----- 4 files changed, 497 insertions(+), 465 deletions(-) diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c b/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c index d311179fc2bd..af29d0e1f771 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c @@ -5,10 +5,12 @@ * gcc dSFMT-benchmark.c dSFMT.c -O3 -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o * dSFMT-benchmark */ -#include "dSFMT.h" #include #include +#include "dSFMT.h" + + #define N 1000000000 int main() { diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c index c34451236ec7..697a3010afcb 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c @@ -1,11 +1,15 @@ /* + * cl dSFMT-test-gen.c dSFMT.c -DHAVE_SSE2 -DDSFMT_MEXP=19937 /Ox * * gcc dSFMT-test-gen.c dSFMT.c -DHAVE_SSE2 -DDSFMT_MEXP=19937 -o dSFMT */ -#include "dSFMT.h" + #include #include +#include "dSFMT.h" + + int main(void) { int i; double d; @@ -27,7 +31,9 @@ int main(void) { d = out[i]; temp = (uint64_t *)&d; fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); - printf("%d, %" PRIu64 "\n", i, *temp); + if (i==999) { + printf("%d, %" PRIu64 "\n", i, *temp); + } } fclose(fp); @@ -44,7 +50,9 @@ int main(void) { d = out[i]; temp = (uint64_t *)&d; fprintf(fp, "%d, %" PRIu64 "\n", i, *temp); - printf("%d, %" PRIu64 "\n", i, *temp); + if (i==999) { + printf("%d, %" PRIu64 "\n", i, *temp); + } } fclose(fp); } diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.c b/_randomgen/core_prng/src/dsfmt/dSFMT.c index 0955e087fbaa..3ce156699175 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.c @@ -11,11 +11,11 @@ * * The new BSD License is applied to this software, see LICENSE.txt */ -#include "dSFMT-common.h" -#include "dSFMT-params.h" #include -#include #include +#include +#include "dSFMT-params.h" +#include "dSFMT-common.h" #if defined(__cplusplus) extern "C" { @@ -31,10 +31,14 @@ static const int dsfmt_mexp = DSFMT_MEXP; ----------------*/ inline static uint32_t ini_func1(uint32_t x); inline static uint32_t ini_func2(uint32_t x); -inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, int size); -inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, int size); -inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, int size); -inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, + int size); inline static int idxof(int i); static void initial_mask(dsfmt_t *dsfmt); static void period_certification(dsfmt_t *dsfmt); @@ -53,9 +57,13 @@ static const union X128D_T sse2_double_m_one = {{-1.0, -1.0}}; * array of LITTLE ENDIAN in BIG ENDIAN machine. */ #if defined(DSFMT_BIG_ENDIAN) -inline static int idxof(int i) { return i ^ 1; } +inline static int idxof(int i) { + return i ^ 1; +} #else -inline static int idxof(int i) { return i; } +inline static int idxof(int i) { + return i; +} #endif #if defined(HAVE_SSE2) @@ -66,7 +74,7 @@ inline static int idxof(int i) { return i; } * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } /** @@ -76,7 +84,7 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); + w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); } /** @@ -86,8 +94,8 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->si = _mm_or_si128(w->si, sse2_int_one.i128); - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->si = _mm_or_si128(w->si, sse2_int_one.i128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } #else /* standard C and altivec */ /** @@ -97,8 +105,8 @@ inline static void convert_o0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } /** @@ -108,8 +116,8 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->d[0] = 2.0 - w->d[0]; - w->d[1] = 2.0 - w->d[1]; + w->d[0] = 2.0 - w->d[0]; + w->d[1] = 2.0 - w->d[1]; } /** @@ -119,10 +127,10 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->u[0] |= 1; - w->u[1] |= 1; - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->u[0] |= 1; + w->u[1] |= 1; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } #endif @@ -134,33 +142,34 @@ inline static void convert_o0o1(w128_t *w) { * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], - &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], - &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -171,38 +180,39 @@ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], - &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], - &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_c0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_c0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_c0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_c0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_c0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_c0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -213,38 +223,39 @@ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], - &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], - &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -255,38 +266,39 @@ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], - &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], - &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0c1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0c1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0c1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0c1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0c1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0c1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -296,7 +308,7 @@ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, * @return 32-bit integer */ static uint32_t ini_func1(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1664525UL; + return (x ^ (x >> 27)) * (uint32_t)1664525UL; } /** @@ -306,7 +318,7 @@ static uint32_t ini_func1(uint32_t x) { * @return 32-bit integer */ static uint32_t ini_func2(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1566083941UL; + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; } /** @@ -315,13 +327,13 @@ static uint32_t ini_func2(uint32_t x) { * @param dsfmt dsfmt state vector. */ static void initial_mask(dsfmt_t *dsfmt) { - int i; - uint64_t *psfmt; + int i; + uint64_t *psfmt; - psfmt = &dsfmt->status[0].u[0]; - for (i = 0; i < DSFMT_N * 2; i++) { - psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; - } + psfmt = &dsfmt->status[0].u[0]; + for (i = 0; i < DSFMT_N * 2; i++) { + psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; + } } /** @@ -329,44 +341,44 @@ static void initial_mask(dsfmt_t *dsfmt) { * @param dsfmt dsfmt state vector. */ static void period_certification(dsfmt_t *dsfmt) { - uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; - uint64_t tmp[2]; - uint64_t inner; - int i; + uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; + uint64_t tmp[2]; + uint64_t inner; + int i; #if (DSFMT_PCV2 & 1) != 1 - int j; - uint64_t work; + int j; + uint64_t work; #endif - tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); - tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); - - inner = tmp[0] & pcv[0]; - inner ^= tmp[1] & pcv[1]; - for (i = 32; i > 0; i >>= 1) { - inner ^= inner >> i; - } - inner &= 1; - /* check OK */ - if (inner == 1) { - return; - } + tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); + tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); + + inner = tmp[0] & pcv[0]; + inner ^= tmp[1] & pcv[1]; + for (i = 32; i > 0; i >>= 1) { + inner ^= inner >> i; + } + inner &= 1; + /* check OK */ + if (inner == 1) { + return; + } /* check NG, and modification */ #if (DSFMT_PCV2 & 1) == 1 - dsfmt->status[DSFMT_N].u[1] ^= 1; + dsfmt->status[DSFMT_N].u[1] ^= 1; #else - for (i = 1; i >= 0; i--) { - work = 1; - for (j = 0; j < 64; j++) { - if ((work & pcv[i]) != 0) { - dsfmt->status[DSFMT_N].u[i] ^= work; - return; - } - work = work << 1; - } - } + for (i = 1; i >= 0; i--) { + work = 1; + for (j = 0; j < 64; j++) { + if ((work & pcv[i]) != 0) { + dsfmt->status[DSFMT_N].u[i] ^= work; + return; + } + work = work << 1; + } + } #endif - return; + return; } /*---------------- @@ -377,14 +389,18 @@ static void period_certification(dsfmt_t *dsfmt) { * the Mersenne exponent, and all parameters of this generator. * @return id string. */ -const char *dsfmt_get_idstring(void) { return DSFMT_IDSTR; } +const char *dsfmt_get_idstring(void) { + return DSFMT_IDSTR; +} /** * This function returns the minimum size of array used for \b * fill_array functions. * @return minimum size of array used for fill_array functions. */ -int dsfmt_get_min_array_size(void) { return DSFMT_N64; } +int dsfmt_get_min_array_size(void) { + return DSFMT_N64; +} /** * This function fills the internal state array with double precision @@ -392,21 +408,21 @@ int dsfmt_get_min_array_size(void) { return DSFMT_N64; } * @param dsfmt dsfmt state vector. */ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { - int i; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&dsfmt->status[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); - } - dsfmt->status[DSFMT_N] = lung; + int i; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&dsfmt->status[0], &dsfmt->status[0], + &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -438,9 +454,9 @@ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { * returns the pointer to the aligned memory block. */ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); } /** @@ -456,9 +472,9 @@ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); } /** @@ -474,9 +490,9 @@ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); } /** @@ -492,13 +508,13 @@ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); } #if defined(__INTEL_COMPILER) -#pragma warning(disable : 981) +# pragma warning(disable:981) #endif /** * This function initializes the internal state array with a 32-bit @@ -508,23 +524,23 @@ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { - int i; - uint32_t *psfmt; - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - psfmt = &dsfmt->status[0].u32[0]; - psfmt[idxof(0)] = seed; - for (i = 1; i < (DSFMT_N + 1) * 4; i++) { - psfmt[idxof(i)] = - 1812433253UL * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int i; + uint32_t *psfmt; + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + psfmt = &dsfmt->status[0].u32[0]; + psfmt[idxof(0)] = seed; + for (i = 1; i < (DSFMT_N + 1) * 4; i++) { + psfmt[idxof(i)] = 1812433253UL + * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } /** @@ -536,77 +552,80 @@ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], - int key_length, int mexp) { - int i, j, count; - uint32_t r; - uint32_t *psfmt32; - int lag; - int mid; - int size = (DSFMT_N + 1) * 4; /* pulmonary */ - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - if (size >= 623) { - lag = 11; - } else if (size >= 68) { - lag = 7; - } else if (size >= 39) { - lag = 5; - } else { - lag = 3; - } - mid = (size - lag) / 2; - - psfmt32 = &dsfmt->status[0].u32[0]; - memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); - if (key_length + 1 > size) { - count = key_length + 1; - } else { - count = size; - } - r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] ^ - psfmt32[idxof((size - 1) % size)]); - psfmt32[idxof(mid % size)] += r; - r += key_length; - psfmt32[idxof((mid + lag) % size)] += r; - psfmt32[idxof(0)] = r; - count--; - for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ - psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += init_key[j] + i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (; j < count; j++) { - r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ - psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (j = 0; j < size; j++) { - r = ini_func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % size)] + - psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] ^= r; - r -= i; - psfmt32[idxof((i + mid + lag) % size)] ^= r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int key_length, int mexp) { + int i, j, count; + uint32_t r; + uint32_t *psfmt32; + int lag; + int mid; + int size = (DSFMT_N + 1) * 4; /* pulmonary */ + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + if (size >= 623) { + lag = 11; + } else if (size >= 68) { + lag = 7; + } else if (size >= 39) { + lag = 5; + } else { + lag = 3; + } + mid = (size - lag) / 2; + + psfmt32 = &dsfmt->status[0].u32[0]; + memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); + if (key_length + 1 > size) { + count = key_length + 1; + } else { + count = size; + } + r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] + ^ psfmt32[idxof((size - 1) % size)]); + psfmt32[idxof(mid % size)] += r; + r += key_length; + psfmt32[idxof((mid + lag) % size)] += r; + psfmt32[idxof(0)] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += init_key[j] + i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(psfmt32[idxof(i)] + + psfmt32[idxof((i + mid) % size)] + + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] ^= r; + r -= i; + psfmt32[idxof((i + mid + lag) % size)] ^= r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } #if defined(__INTEL_COMPILER) -#pragma warning(default : 981) +# pragma warning(default:981) #endif #if defined(__cplusplus) @@ -617,4 +636,4 @@ extern inline double dsfmt_next_double(dsfmt_state *state); extern inline uint64_t dsfmt_next64(dsfmt_state *state); -extern inline uint32_t dsfmt_next32(dsfmt_state *state); +extern inline uint32_t dsfmt_next32(dsfmt_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index c9a34ae86691..52b6b3aedcc2 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -38,14 +38,14 @@ extern "C" { #endif -#include #include +#include #if !defined(DSFMT_MEXP) #ifdef __GNUC__ -#warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." + #warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." #endif -#define DSFMT_MEXP 19937 + #define DSFMT_MEXP 19937 #endif /*----------------- BASIC DEFINITIONS @@ -64,103 +64,103 @@ extern "C" { #define DSFMT_N64 (DSFMT_N * 2) #if !defined(DSFMT_BIG_ENDIAN) -#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) -#if __BYTE_ORDER == __BIG_ENDIAN -#define DSFMT_BIG_ENDIAN 1 -#endif -#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) -#if _BYTE_ORDER == _BIG_ENDIAN -#define DSFMT_BIG_ENDIAN 1 -#endif -#elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) -#if __BYTE_ORDER__ == __BIG_ENDIAN__ -#define DSFMT_BIG_ENDIAN 1 -#endif -#elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) -#if BYTE_ORDER == BIG_ENDIAN -#define DSFMT_BIG_ENDIAN 1 -#endif -#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || \ - defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) -#define DSFMT_BIG_ENDIAN 1 -#endif +# if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +# if __BYTE_ORDER == __BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) +# if _BYTE_ORDER == _BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) +# if __BYTE_ORDER__ == __BIG_ENDIAN__ +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) +# if BYTE_ORDER == BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) \ + || defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) +# define DSFMT_BIG_ENDIAN 1 +# endif #endif #if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) -#undef DSFMT_BIG_ENDIAN +# undef DSFMT_BIG_ENDIAN #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -#include +# include #elif defined(_MSC_VER) || defined(__BORLANDC__) -#if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) +# if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; -#ifndef UINT64_C -#define UINT64_C(v) (v##ui64) -#endif -#define DSFMT_UINT32_DEFINED -#if !defined(inline) && !defined(__cplusplus) -#define inline __forceinline -#endif -#endif -#else -#include -#if !defined(inline) && !defined(__cplusplus) -#if defined(__GNUC__) -#define inline __forceinline__ +# ifndef UINT64_C +# define UINT64_C(v) (v ## ui64) +# endif +# define DSFMT_UINT32_DEFINED +# if !defined(inline) && !defined(__cplusplus) +# define inline __forceinline +# endif +# endif #else -#define inline -#endif -#endif +# include +# if !defined(inline) && !defined(__cplusplus) +# if defined(__GNUC__) +# define inline __forceinline__ +# else +# define inline +# endif +# endif #endif #ifndef PRIu64 -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#else -#define PRIu64 "llu" -#define PRIx64 "llx" -#endif +# if defined(_MSC_VER) || defined(__BORLANDC__) +# define PRIu64 "I64u" +# define PRIx64 "I64x" +# else +# define PRIu64 "llu" +# define PRIx64 "llx" +# endif #endif #ifndef UINT64_C -#define UINT64_C(v) (v##ULL) +# define UINT64_C(v) (v ## ULL) #endif /*------------------------------------------ 128-bit SIMD like data type for standard C ------------------------------------------*/ #if defined(HAVE_ALTIVEC) -#if !defined(__APPLE__) -#include -#endif +# if !defined(__APPLE__) +# include +# endif /** 128-bit data structure */ union W128_T { - vector unsigned int s; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + vector unsigned int s; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #elif defined(HAVE_SSE2) -#include +# include /** 128-bit data structure */ union W128_T { - __m128i si; - __m128d sd; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + __m128i si; + __m128d sd; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; -#else /* standard C */ +#else /* standard C */ /** 128-bit data structure */ union W128_T { - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #endif @@ -169,8 +169,8 @@ typedef union W128_T w128_t; /** the 128-bit internal state array */ struct DSFMT_T { - w128_t status[DSFMT_N + 1]; - int idx; + w128_t status[DSFMT_N + 1]; + int idx; }; typedef struct DSFMT_T dsfmt_t; @@ -191,42 +191,42 @@ const char *dsfmt_get_idstring(void); int dsfmt_get_min_array_size(void); #if defined(__GNUC__) -#define DSFMT_PRE_INLINE inline static -#define DSFMT_PST_INLINE __attribute__((always_inline)) +# define DSFMT_PRE_INLINE inline static +# define DSFMT_PST_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) && _MSC_VER >= 1200 -#define DSFMT_PRE_INLINE __forceinline static -#define DSFMT_PST_INLINE +# define DSFMT_PRE_INLINE __forceinline static +# define DSFMT_PST_INLINE #else -#define DSFMT_PRE_INLINE inline static -#define DSFMT_PST_INLINE +# define DSFMT_PRE_INLINE inline static +# define DSFMT_PST_INLINE #endif DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double -dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double -dsfmt_genrand_close_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double -dsfmt_genrand_open_close(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double -dsfmt_genrand_open_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) + DSFMT_PST_INLINE; DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void -dsfmt_gv_fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) + DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, - uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) + DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) DSFMT_PST_INLINE; @@ -239,15 +239,15 @@ DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { - uint32_t r; - uint64_t *psfmt64 = &dsfmt->status[0].u[0]; + uint32_t r; + uint64_t *psfmt64 = &dsfmt->status[0].u[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++] & 0xffffffffU; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++] & 0xffffffffU; + return r; } /** @@ -260,15 +260,15 @@ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { - double r; - double *psfmt64 = &dsfmt->status[0].d[0]; + double r; + double *psfmt64 = &dsfmt->status[0].d[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++]; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++]; + return r; } /** @@ -279,7 +279,7 @@ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_gv_genrand_uint32(void) { - return dsfmt_genrand_uint32(&dsfmt_global_data); + return dsfmt_genrand_uint32(&dsfmt_global_data); } /** @@ -290,7 +290,7 @@ inline static uint32_t dsfmt_gv_genrand_uint32(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close1_open2(void) { - return dsfmt_genrand_close1_open2(&dsfmt_global_data); + return dsfmt_genrand_close1_open2(&dsfmt_global_data); } /** @@ -302,7 +302,7 @@ inline static double dsfmt_gv_genrand_close1_open2(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { - return dsfmt_genrand_close1_open2(dsfmt) - 1.0; + return dsfmt_genrand_close1_open2(dsfmt) - 1.0; } /** @@ -313,7 +313,7 @@ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close_open(void) { - return dsfmt_gv_genrand_close1_open2() - 1.0; + return dsfmt_gv_genrand_close1_open2() - 1.0; } /** @@ -325,7 +325,7 @@ inline static double dsfmt_gv_genrand_close_open(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { - return 2.0 - dsfmt_genrand_close1_open2(dsfmt); + return 2.0 - dsfmt_genrand_close1_open2(dsfmt); } /** @@ -336,7 +336,7 @@ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_close(void) { - return 2.0 - dsfmt_gv_genrand_close1_open2(); + return 2.0 - dsfmt_gv_genrand_close1_open2(); } /** @@ -348,19 +348,19 @@ inline static double dsfmt_gv_genrand_open_close(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { - double *dsfmt64 = &dsfmt->status[0].d[0]; - union { - double d; - uint64_t u; - } r; - - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r.d = dsfmt64[dsfmt->idx++]; - r.u |= 1; - return r.d - 1.0; + double *dsfmt64 = &dsfmt->status[0].d[0]; + union { + double d; + uint64_t u; + } r; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r.d = dsfmt64[dsfmt->idx++]; + r.u |= 1; + return r.d - 1.0; } /** @@ -371,7 +371,7 @@ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_open(void) { - return dsfmt_genrand_open_open(&dsfmt_global_data); + return dsfmt_genrand_open_open(&dsfmt_global_data); } /** @@ -386,7 +386,7 @@ inline static double dsfmt_gv_genrand_open_open(void) { * see also \sa dsfmt_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { - dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); + dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); } /** @@ -402,7 +402,7 @@ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { - dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); } /** @@ -418,7 +418,7 @@ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { - dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); } /** @@ -434,7 +434,7 @@ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { - dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); } /** @@ -444,7 +444,7 @@ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { * @param seed a 32-bit integer used as the seed. */ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { - dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); + dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); } /** @@ -454,7 +454,7 @@ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { * see also \sa dsfmt_init_gen_rand() */ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { - dsfmt_init_gen_rand(&dsfmt_global_data, seed); + dsfmt_init_gen_rand(&dsfmt_global_data, seed); } /** @@ -466,7 +466,7 @@ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { */ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) { - dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); + dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); } /** @@ -478,34 +478,36 @@ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * see also \sa dsfmt_init_by_array() */ inline static void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { - dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); + dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); } #if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], - int key_length) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) + DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_close(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close_open(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_open(double array[], - int size) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], - int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) + DSFMT_PST_INLINE; /** * This function is just the same as dsfmt_get_idstring(). * @return id string. * see also \sa dsfmt_get_idstring() */ -inline static const char *get_idstring(void) { return dsfmt_get_idstring(); } +inline static const char *get_idstring(void) { + return dsfmt_get_idstring(); +} /** * This function is just the same as dsfmt_get_min_array_size(). @@ -513,7 +515,7 @@ inline static const char *get_idstring(void) { return dsfmt_get_idstring(); } * see also \sa dsfmt_get_min_array_size() */ inline static int get_min_array_size(void) { - return dsfmt_get_min_array_size(); + return dsfmt_get_min_array_size(); } /** @@ -522,7 +524,7 @@ inline static int get_min_array_size(void) { * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). */ inline static void init_gen_rand(uint32_t seed) { - dsfmt_gv_init_gen_rand(seed); + dsfmt_gv_init_gen_rand(seed); } /** @@ -532,7 +534,7 @@ inline static void init_gen_rand(uint32_t seed) { * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). */ inline static void init_by_array(uint32_t init_key[], int key_length) { - dsfmt_gv_init_by_array(init_key, key_length); + dsfmt_gv_init_by_array(init_key, key_length); } /** @@ -542,7 +544,7 @@ inline static void init_by_array(uint32_t init_key[], int key_length) { * dsfmt_gv_genrand_close1_open2() */ inline static double genrand_close1_open2(void) { - return dsfmt_gv_genrand_close1_open2(); + return dsfmt_gv_genrand_close1_open2(); } /** @@ -552,7 +554,7 @@ inline static double genrand_close1_open2(void) { * dsfmt_gv_genrand_close_open() */ inline static double genrand_close_open(void) { - return dsfmt_gv_genrand_close_open(); + return dsfmt_gv_genrand_close_open(); } /** @@ -562,7 +564,7 @@ inline static double genrand_close_open(void) { * dsfmt_gv_genrand_open_close() */ inline static double genrand_open_close(void) { - return dsfmt_gv_genrand_open_close(); + return dsfmt_gv_genrand_open_close(); } /** @@ -572,7 +574,7 @@ inline static double genrand_open_close(void) { * dsfmt_gv_genrand_open_open() */ inline static double genrand_open_open(void) { - return dsfmt_gv_genrand_open_open(); + return dsfmt_gv_genrand_open_open(); } /** @@ -585,7 +587,7 @@ inline static double genrand_open_open(void) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_close(double array[], int size) { - dsfmt_gv_fill_array_open_close(array, size); + dsfmt_gv_fill_array_open_close(array, size); } /** @@ -598,7 +600,7 @@ inline static void fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close_open(double array[], int size) { - dsfmt_gv_fill_array_close_open(array, size); + dsfmt_gv_fill_array_close_open(array, size); } /** @@ -611,7 +613,7 @@ inline static void fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_open(double array[], int size) { - dsfmt_gv_fill_array_open_open(array, size); + dsfmt_gv_fill_array_open_open(array, size); } /** @@ -623,7 +625,7 @@ inline static void fill_array_open_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close1_open2(double array[], int size) { - dsfmt_gv_fill_array_close1_open2(array, size); + dsfmt_gv_fill_array_close1_open2(array, size); } #endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ @@ -633,6 +635,7 @@ inline static void fill_array_close1_open2(double array[], int size) { #endif /* DSFMT_H */ + typedef struct s_dsfmt_state { dsfmt_t *state; int has_uint32; @@ -648,8 +651,7 @@ static inline double dsfmt_next_double(dsfmt_state *state) { state->buffer_loc++; return out; } - dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, - DSFMT_N64); + dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, DSFMT_N64); state->buffer_loc = 1; return state->buffered_uniforms[0]; } @@ -667,6 +669,7 @@ static inline uint64_t dsfmt_next64(dsfmt_state *state) { return out; } + static inline uint32_t dsfmt_next32(dsfmt_state *state) { /* Discard bottom 16 bits */ double d = dsfmt_next_double(state); From eab33902389503d8dac7b901a175e4fc03b6596a Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 11:36:37 +0000 Subject: [PATCH 034/138] ENH: Enable Python 2.7 compatability Enable Python 2.7 --- _randomgen/core_prng/src/common/inttypes.h | 306 ++++++++++++++++++ _randomgen/core_prng/src/pcg64/pcg64.h | 3 +- _randomgen/core_prng/src/philox/philox.h | 14 +- .../core_prng/src/splitmix64/splitmix64.h | 14 +- _randomgen/core_prng/src/threefry/threefry.c | 4 +- _randomgen/core_prng/src/threefry/threefry.h | 21 +- .../core_prng/src/xoroshiro128/xoroshiro128.c | 15 +- .../core_prng/src/xoroshiro128/xoroshiro128.h | 24 +- .../core_prng/src/xorshift1024/xorshift1024.c | 15 +- .../core_prng/src/xorshift1024/xorshift1024.h | 22 +- _randomgen/setup.py | 48 +-- 11 files changed, 427 insertions(+), 59 deletions(-) create mode 100644 _randomgen/core_prng/src/common/inttypes.h diff --git a/_randomgen/core_prng/src/common/inttypes.h b/_randomgen/core_prng/src/common/inttypes.h new file mode 100644 index 000000000000..8f8b61108a21 --- /dev/null +++ b/_randomgen/core_prng/src/common/inttypes.h @@ -0,0 +1,306 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// 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 product 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 AUTHOR ``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 AUTHOR 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h index 54bd37efc7e6..8b1746d9d0dc 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -213,11 +213,12 @@ static inline uint64_t pcg64_next64(pcg64_state *state) { } static inline uint32_t pcg64_next32(pcg64_state *state) { + uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = pcg64_random_r(state->pcg_state); + next = pcg64_random_r(state->pcg_state); state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); return (uint32_t)(next >> 32); diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index 477ba17accb6..bc87b3d3a125 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -6,7 +6,7 @@ #define INLINE inline #endif -#define PHILOX_BUFFER_SIZE 4UL +#define PHILOX_BUFFER_SIZE 4L struct r123array2x64 { uint64_t v[2]; @@ -143,14 +143,16 @@ typedef struct s_philox_state { } philox_state; static INLINE uint64_t philox_next(philox_state *state) { + uint64_t out; + int i; + philox4x64_ctr_t ct; + if (state->buffer_pos < PHILOX_BUFFER_SIZE) { - uint64_t out = state->buffer[state->buffer_pos]; + out = state->buffer[state->buffer_pos]; state->buffer_pos++; return out; } /* generate 4 new uint64_t */ - int i; - philox4x64_ctr_t ct; state->ctr->v[0]++; /* Handle carry */ if (state->ctr->v[0] == 0) { @@ -175,11 +177,13 @@ static INLINE uint64_t philox_next64(philox_state *state) { } static INLINE uint64_t philox_next32(philox_state *state) { + uint64_t next; + if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = philox_next(state); + next = philox_next(state); state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/core_prng/src/splitmix64/splitmix64.h index 6fbaa1657abf..0691064428b7 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.h +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.h @@ -1,4 +1,13 @@ -#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define inline __forceinline +#else +#include +#endif +#else +#include +#endif typedef struct s_splitmix64_state { uint64_t state; @@ -18,11 +27,12 @@ static inline uint64_t splitmix64_next64(splitmix64_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; } - uint64_t next = splitmix64_next64(state); + next = splitmix64_next64(state); state->uinteger = next & 0xffffffff; state->has_uint32 = 1; return (uint32_t)(next >> 32); diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/core_prng/src/threefry/threefry.c index 069ac5356d9a..56b499bd9dda 100644 --- a/_randomgen/core_prng/src/threefry/threefry.c +++ b/_randomgen/core_prng/src/threefry/threefry.c @@ -33,9 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "threefry.h" -extern inline uint64_t threefry_next64(threefry_state *state); +extern INLINE uint64_t threefry_next64(threefry_state *state); -extern inline uint64_t threefry_next32(threefry_state *state); +extern INLINE uint64_t threefry_next32(threefry_state *state); extern void threefry_jump(threefry_state *state) { /* Advances state as-if 2^128 draws were made */ diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index 5fa9a716b5a2..d620f6a1aaca 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -2,15 +2,20 @@ Adapted from random123's threefry.h */ -#include - #ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include #define INLINE __inline __forceinline +#endif #else +#include #define INLINE inline #endif -#define THREEFRY_BUFFER_SIZE 4UL +#define THREEFRY_BUFFER_SIZE 4L enum r123_enum_threefry64x4 { /* These are the R_256 constants from the Threefish reference sources @@ -282,14 +287,15 @@ typedef struct s_threefry_state { } threefry_state; static INLINE uint64_t threefry_next(threefry_state *state) { + int i; + threefry4x64_ctr_t ct; + uint64_t out; if (state->buffer_pos < THREEFRY_BUFFER_SIZE) { - uint64_t out = state->buffer[state->buffer_pos]; + out = state->buffer[state->buffer_pos]; state->buffer_pos++; return out; } /* generate 4 new uint64_t */ - int i; - threefry4x64_ctr_t ct; state->ctr->v[0]++; /* Handle carry */ if (state->ctr->v[0] == 0) { @@ -314,11 +320,12 @@ static INLINE uint64_t threefry_next64(threefry_state *state) { } static INLINE uint64_t threefry_next32(threefry_state *state) { + uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = threefry_next(state); + next = threefry_next(state); state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c index 928e5c523566..981aeab8478c 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c @@ -32,17 +32,20 @@ See . */ #include "xoroshiro128.h" -extern inline uint64_t xoroshiro128_next64(xoroshiro128_state *state); +extern INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); -extern inline uint32_t xoroshiro128_next32(xoroshiro128_state *state); +extern INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); void xoroshiro128_jump(xoroshiro128_state *state) { + int i, b; + uint64_t s0; + uint64_t s1; static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; - uint64_t s0 = 0; - uint64_t s1 = 0; - for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (int b = 0; b < 64; b++) { + s0 = 0; + s1 = 0; + for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) { s0 ^= state->s[0]; s1 ^= state->s[1]; diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h index bc6256aa6267..ad1ddb194901 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -1,4 +1,15 @@ -#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include +#define INLINE __inline __forceinline +#endif +#else +#include +#define INLINE inline +#endif typedef struct s_xoroshiro128_state { uint64_t s[2]; @@ -6,11 +17,11 @@ typedef struct s_xoroshiro128_state { uint32_t uinteger; } xoroshiro128_state; -static inline uint64_t rotl(const uint64_t x, int k) { +static INLINE uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -static inline uint64_t xoroshiro128_next(uint64_t *s) { +static INLINE uint64_t xoroshiro128_next(uint64_t *s) { const uint64_t s0 = s[0]; uint64_t s1 = s[1]; const uint64_t result = s0 + s1; @@ -22,16 +33,17 @@ static inline uint64_t xoroshiro128_next(uint64_t *s) { return result; } -static inline uint64_t xoroshiro128_next64(xoroshiro128_state *state) { +static INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) { return xoroshiro128_next(&state->s[0]); } -static inline uint32_t xoroshiro128_next32(xoroshiro128_state *state) { +static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) { + uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = xoroshiro128_next(&state->s[0]); + next = xoroshiro128_next(&state->s[0]); state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); return (uint32_t)(next >> 32); diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024.c index a7d1fe0fa9aa..8737b5a82ae4 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift1024.c +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.c @@ -4,11 +4,12 @@ to 2^512 calls to next(); it can be used to generate 2^512 non-overlapping subsequences for parallel computations. */ -extern inline uint64_t xorshift1024_next(xorshift1024_state *state); -extern inline uint64_t xorshift1024_next64(xorshift1024_state *state); -extern inline uint32_t xorshift1024_next32(xorshift1024_state *state); +extern INLINE uint64_t xorshift1024_next(xorshift1024_state *state); +extern INLINE uint64_t xorshift1024_next64(xorshift1024_state *state); +extern INLINE uint32_t xorshift1024_next32(xorshift1024_state *state); void xorshift1024_jump(xorshift1024_state *state) { + int i, j, b; static const uint64_t JUMP[] = { 0x84242f96eca9c41d, 0xa3c65b8776f96855, 0x5b34a39f070b5837, 0x4489affce4f31a1e, 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, @@ -18,14 +19,14 @@ void xorshift1024_jump(xorshift1024_state *state) { 0x284600e3f30e38c3}; uint64_t t[16] = {0}; - for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (int b = 0; b < 64; b++) { + for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (b = 0; b < 64; b++) { if (JUMP[i] & UINT64_C(1) << b) - for (int j = 0; j < 16; j++) + for (j = 0; j < 16; j++) t[j] ^= state->s[(j + state->p) & 15]; xorshift1024_next(state); } - for (int j = 0; j < 16; j++) + for (j = 0; j < 16; j++) state->s[(j + state->p) & 15] = t[j]; } diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h index ae8d24f7dcff..2cceee7284f2 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h @@ -1,4 +1,15 @@ -#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include +#define INLINE __inline __forceinline +#endif +#else +#include +#define INLINE inline +#endif typedef struct s_xorshift1024_state { uint64_t s[16]; @@ -7,7 +18,7 @@ typedef struct s_xorshift1024_state { uint32_t uinteger; } xorshift1024_state; -static inline uint64_t xorshift1024_next(xorshift1024_state *state) { +static INLINE uint64_t xorshift1024_next(xorshift1024_state *state) { const uint64_t s0 = state->s[state->p]; uint64_t s1 = state->s[state->p = ((state->p) + 1) & 15]; s1 ^= s1 << 31; // a @@ -15,16 +26,17 @@ static inline uint64_t xorshift1024_next(xorshift1024_state *state) { return state->s[state->p] * 0x9e3779b97f4a7c13; } -static inline uint64_t xorshift1024_next64(xorshift1024_state *state) { +static INLINE uint64_t xorshift1024_next64(xorshift1024_state *state) { return xorshift1024_next(state); } -static inline uint32_t xorshift1024_next32(xorshift1024_state *state) { +static INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { + uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; return state->uinteger; } - uint64_t next = xorshift1024_next(state); + next = xorshift1024_next(state); state->has_uint32 = 1; state->uinteger = (uint32_t)(next & 0xffffffff); return (uint32_t)(next >> 32); diff --git a/_randomgen/setup.py b/_randomgen/setup.py index cb633f359ac7..2d726909bef8 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -19,6 +19,7 @@ DEBUG = False PCG_EMULATED_MATH = False +EXTRA_INCLUDE_DIRS = [] EXTRA_COMPILE_ARGS = [] EXTRA_LINK_ARGS = [] EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99'] @@ -28,6 +29,8 @@ if DEBUG: EXTRA_LINK_ARGS += ['-debug'] EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] +if os.name == 'nt' and sys.version_info < (3, 0): + EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] if USE_SSE2: if os.name == 'nt': @@ -43,16 +46,18 @@ extensions = [Extension('core_prng.entropy', sources=[join(MOD_DIR, 'entropy.pyx'), join(MOD_DIR, 'src', 'entropy', 'entropy.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'entropy')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'entropy')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), Extension("core_prng.dsfmt", ["core_prng/dsfmt.pyx", join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'dsfmt')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'dsfmt')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, define_macros=DSFMT_DEFS, @@ -60,16 +65,18 @@ Extension("core_prng.mt19937", ["core_prng/mt19937.pyx", join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'mt19937')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'mt19937')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), Extension("core_prng.philox", ["core_prng/philox.pyx", join(MOD_DIR, 'src', 'philox', 'philox.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'philox')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'philox')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -77,16 +84,18 @@ ["core_prng/pcg64.pyx", join(MOD_DIR, 'src', 'pcg64', 'pcg64.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'pcg64')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'pcg64')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), Extension("core_prng.threefry", ["core_prng/threefry.pyx", join(MOD_DIR, 'src', 'threefry', 'threefry.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'threefry')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'threefry')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -94,8 +103,10 @@ ["core_prng/xoroshiro128.pyx", join(MOD_DIR, 'src', 'xoroshiro128', 'xoroshiro128.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'xoroshiro128')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join( + MOD_DIR, 'src', + 'xoroshiro128')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -103,8 +114,9 @@ ["core_prng/xorshift1024.pyx", join(MOD_DIR, 'src', 'xorshift1024', 'xorshift1024.c')], - include_dirs=[np.get_include(), - join(MOD_DIR, 'src', 'xorshift1024')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'xorshift1024')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -112,13 +124,13 @@ ["core_prng/generator.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], - include_dirs=[np.get_include()], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), Extension("core_prng.common", ["core_prng/common.pyx"], - include_dirs=[np.get_include()], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), From c3155db741021bcf785ede6084b18248a4911d70 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 12:45:17 +0000 Subject: [PATCH 035/138] ENH: Add jump to mt19937 and dsfmt Add jump to dsfmt and mt19937 --- _randomgen/core_prng/dsfmt.pyx | 50 +- _randomgen/core_prng/mt19937.pyx | 5 + _randomgen/core_prng/src/dsfmt/dSFMT-jump.h | 2 +- _randomgen/core_prng/src/dsfmt/dSFMT-poly.h | 53 ++ _randomgen/core_prng/src/dsfmt/dSFMT.c | 621 +++++++++--------- _randomgen/core_prng/src/dsfmt/dSFMT.h | 327 +++++---- .../core_prng/src/mt19937/mt19937-jump.c | 224 +++++++ .../core_prng/src/mt19937/mt19937-jump.h | 15 + .../core_prng/src/mt19937/mt19937-poly.h | 207 ++++++ _randomgen/core_prng/src/mt19937/mt19937.c | 4 + _randomgen/core_prng/src/mt19937/mt19937.h | 2 + _randomgen/setup.py | 6 +- 12 files changed, 1008 insertions(+), 508 deletions(-) create mode 100644 _randomgen/core_prng/src/dsfmt/dSFMT-poly.h create mode 100644 _randomgen/core_prng/src/mt19937/mt19937-jump.c create mode 100644 _randomgen/core_prng/src/mt19937/mt19937-jump.h create mode 100644 _randomgen/core_prng/src/mt19937/mt19937-poly.h diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 68663e4b0d10..b82007abe437 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -48,7 +48,7 @@ cdef extern from "src/dsfmt/dSFMT.h": void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) - # void dsfmt_jump(dsfmt_state *state) + void dsfmt_jump(dsfmt_state *state); cdef uint64_t dsfmt_uint64(void* st):# nogil: return dsfmt_next64(st) @@ -215,32 +215,34 @@ cdef class DSFMT: If seed values are out of range for the PRNG. """ - cdef np.ndarray init_key - ub = 2 ** 32 - if seed is None: - try: - state = random_entropy(1) - except RuntimeError: - state = random_entropy(1, 'fallback') - seed = state[0] - if np.isscalar(seed): - # TODO: This isn't correct, but works now - seed = int(seed) - if seed < 0 or seed > ub: - raise ValueError('seed must be an unsigned 32-bit integer') - dsfmt_init_gen_rand(self.rng_state.state, seed) - else: - # TODO: This also need to be impeoved to be more careful - init_key = np.asarray(seed, dtype=np.uint32).ravel() - dsfmt_init_by_array(self.rng_state.state, - init_key.data, - init_key.shape[0]) + cdef np.ndarray obj + try: + if seed is None: + try: + seed = random_entropy(1) + except RuntimeError: + seed = random_entropy(1, 'fallback') + dsfmt_init_gen_rand(self.rng_state.state, seed[0]) + 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") + dsfmt_init_gen_rand(self.rng_state.state, seed) + except TypeError: + obj = np.asarray(seed).astype(np.int64, casting='safe').ravel() + 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') + dsfmt_init_by_array(self.rng_state.state, obj.data, + np.PyArray_DIM(obj, 0)) self._reset_state_variables() -# def jump(self): -# dsfmt_jump(self.rng_state) -# return self + def jump(self): + dsfmt_jump(self.rng_state) + return self @property def state(self): diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index a5b836699697..b1d9125c308a 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -25,6 +25,7 @@ cdef extern from "src/mt19937/mt19937.h": 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) cdef uint64_t mt19937_uint64(void *st) nogil: return mt19937_next64( st) @@ -162,6 +163,10 @@ cdef class MT19937: obj = obj.astype(np.uint32, casting='unsafe', order='C') mt19937_init_by_array(self.rng_state, obj.data, np.PyArray_DIM(obj, 0)) + def jump(self): + mt19937_jump(self.rng_state) + return self + @property def state(self): """Get or set the PRNG state""" diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h index 2979f3269bc3..689f9499a833 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h @@ -21,7 +21,7 @@ extern "C" { #endif #include "dSFMT.h" -void dSFMT_jump(dsfmt_t * dsfmt, const char * jump_str); +void dSFMT_jump(dsfmt_t *dsfmt, const char *jump_str); #if defined(__cplusplus) } diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-poly.h b/_randomgen/core_prng/src/dsfmt/dSFMT-poly.h new file mode 100644 index 000000000000..f8e15c3eb419 --- /dev/null +++ b/_randomgen/core_prng/src/dsfmt/dSFMT-poly.h @@ -0,0 +1,53 @@ +static const char * poly_128 = +"f4dfa6c62049d0776e0bf6f1e953f3aa38abb113df86be024eab3773ad5f2b82ead936022e656dff7e562691c59dd5f7d2" +"566b78d9669002503c4ddb1888a49f32333f515e6c60c4ecd221078ec6f26f0a90f4875067ca1f399a99775037adf90556" +"6e2c7e6b42131420f8f04f112c92621c9b1502f2a8aefad6c667904af62f0d55e02d396902d3b89450103c5ce5fe0408d9" +"7cbb864861b49e4e42048ff3310b48faac55095a7f422eea4aade752f947f947c6be0a0c665bdea099246ab9eff658ea8c" +"a468bf49d0227748367878de06d7bd86ea6708fcac6e252f5f00f04309b2aac3036b64afb39d990427c6c9f03477cc7e93" +"5c43c0e61bc161db8eb15516eee8cb377ecbc1849207990fb6778721b29bfe0d89bfda1b3772fa5b0b1f7ec3daf3605203" +"2285898c6f6396f55010c31f8201b7e2e51d94f920bfe57684c5415cc342cb39a0045d9793d13cf8646096daeb8bb9bfc2" +"0a90de8f2426da8733267a9b9674f32154e8f84a9932223a2ca3c787d0b66df6675febbdfcba2f9cef09c621c57e11098b" +"3289c77397aaae8b104642ffe0c4b75598efbc53745984d68b4d6656cae299ae2be55217a9a02b009ca7be32f47fbe434b" +"ce4914a34d0c9b0085bede9b8a99319c34660d66f0124b5a7714c4bf3cbfec3ee43ed817087168bad80133bebaeeb68cf7" +"929a24d1bb3de831a8340d220906ab04159cf94b21d5ee813bd7c80f10f01b43052af530917513b169254c25d6fcfe6cb4" +"20d6ce92f54886ef6eaf9a5ba35e893ff593834d05ddf28899e42d729c7df3d21ef036020789739366f0c11ec52ff92a0b" +"fd8ba69508e27b20fabb8217bd36b90e5aa918159ac87913bc7b46c04e366c23c92807fbe9c6a407e6a4db0b4fc23c3b6c" +"706b5ca058fe8c190f849f18d16d6b48b5ed760eb202fd566291a799420b9654e08b8118bcbfead8e9dd2fdb9b053e9bdf" +"b665285c78718f726d0b3d6c37e116428ec9ac9db2637259e4e8d6402bbada46c6bdb03985e19a82e9b4e57de1b025a3cb" +"1f850beae7e8da9941655825bce0e89d536b6ee9064865b1a85c185e9fc9cb7f435de13d44773c00eed442a286e4ab807e" +"3cab4dc3441d1b7d2af693812ae8b39652bb8c835fc895d13d6da93541afeadeee450475c29f3b2dfa8ef1c1e2547463b2" +"cc2f0ff7a42ac4dd35e25c4fa030d2d2766fbe9f2d04c1304671747bace2f7dd55142bfa60f8cbc968bfc3d7a342152dc6" +"84a0fb5a32c0962a62b5220ac0f72add9d8b84d6cc76b97d03245e01fc8da3414a49bb4075d3488f29b56dc42ba69e3b58" +"529448c943ecfd98b3784a39d0b8609a8fb945e757f4569f53bd2cf80f7f638acf5b67fe9c560a3b7b0cf7e0398f31aa8b" +"03cf9c62b24296b6d8596b694469a02686c38daa16a1ef86e012d61a2f7de1693a5c00b3685175caec3c67146477eba548" +"30f1d546cb18a553779aa46adb4f2010e33f3def847c7d89b51a8462b227605f6c920fd558a6daf64bc98682e508ae960c" +"0c571870e603ba1fce0c13d53176f353fd319959e13db93eae1359f06e3dd4767c04f824cf34ec7bf8f60161ba1a615db8" +"2852eca9e3869afa711ab9a090660b0dc6cfbea310dda77e02310fbaeacd2636f975838c2dbcdbe9ac2cd85cee28f5e3f0" +"c73abf62f9fa02cd79a7606b7ba855db68a07848b057c3aaf38f1a70086e14616f6f88305a1f9ce6b41378a620d4db3e0e" +"7e1d421590dccaeff86212e232eeb5eb8a8d33a8c9b25ae88f3a7bd5032b4efa68f8af3186a02ffcbf5456f12beccace94" +"c81c360cc4a0dcc642b59f991eec68c59af78139ca60b96d6a18e9535f8995e89bd2cf6a0aef3acffd33d1c0c1b79b6641" +"4a91d9f65b2b4ec65844b96f725d2b4b0c309f3eb9d714e9dd939bbdfd85ce8fb43679aeab13f6c29549949503c9466dbd" +"337c4cdde46d6eacd15f21f4d8fdeaa627a47884c88a9c85f0b731d271a8ea7cb9e04a4a149c23c10f56b3a0476dc77a99" +"9d6e4f813e4b0f805e2a693e2ae4ae0ecc423c9ba5d17b42e691abf83784a582f2b1fd85d1e0a27ba38a500963568b2450" +"363d2c5e3f7b8ba3e5b56e4e9f745a3a710bf2ae233c303068c532ce78ff031e6ab28b705dd94d7db4500909edb5626b8c" +"9bd5ff4f0b4741388f0b91563ee516934c013e901572cba005ac5c535f4f107903be9af7b2793dfb61b5070facbe71eefe" +"1b5600f975c8c38c3a2350d78beadfecb78e981164ae8bc866e732972d3ceef4aac68e15861f9b881d9b51b4edece150bc" +"124b07645defb4202ef5d0e0962db98cae6ed459561c93c74c20bd64362e4f4fffc389a6cd80514604ff22eecc10c9cbc7" +"981d19a8102b24146354c463107c9dc070e29e70df3578022acf72289ef071ab9f9402a544d0399f1b1e5f206b6d46d445" +"f6d612a490e72918e00c853eda8493bef511149e80c9ab56e8b4b8cba3987249f77d060e61760e5792ac321c987c03c260" +"6e9393a7970212992cdbd16448078d5039d4c2c3199714f53278f4f7b1d2e514cf95bdfc078b8bb0db659cb2c3f5cc0289" +"0ea84f05d414c88d2db9e9f8455659b9fa6254405317245fa070d6970cafb4dadb2522b490a5c8e02fe973a8cdbfbfbdbf" +"b01535099ffba3d3896bc4d1189fc570c3e6fdc6469265b8da912772e75dd62ab71be507f700d56cac5e68fd6b57ec1661" +"68ab5258a69625c142a5b1b3519f94be1bde5e51d3bd8ea0c12d5af2fe4615b1b7bd4a96628a4fabc65925ff09718f63bb" +"ebaad98f89bd9543a27b3ff3b5d8bfa89f941a5eb8cc005ccd4a705190e1c9dc6a9f4264e5ee658520a4438e92de854bff" +"c39f8dc7dfbb5de4f14ba63ea16a37d14a7b4610f95b6cffd55e4679b29cedbdf20e7bd16da822fad910c359ee3a68e48a" +"ae6e769b0e291d5d3aa3e2ca9d8d23abe8a1d5349f4991e9300852cc0befb20c2fc0d169306b260763344024f8092cbcc2" +"4c6807363e9fc548a30d5faab3a94b2af0782a2942be80c45d8b0587efd587394ef33c33022436e285806ddffdd32fe363" +"45c3c38ed8d680abeb7a028b44ee6f94d060a14c7019bb6af1f1b5f0a562957d19826d8cc216f9b908c989ccd5415e3525" +"dfe9422ffb5b50b7cc3083dc325544751e5683535d7439d3da2b0bb73bea551dd99e04e0e793804f4774eb6b1daf781d9c" +"aa5128274e599e847862fe309027813d3e4eda0bbeb7201856a5c5d8370e44dabff0bb229c723ba0a6bcf29c44536147de" +"11b7835991018100105bd4329217f7386903fe8e7363cd7b3e893244e245e0a187467664c05b0be1fd429722b9b9a5e319" +"8147fad72776e8a63aab9054fa9d259af0198d088d71d132e6068676a8e9ebb0f616b51ee34aac39c2c2221c7112401727" +"0d75ff4a048363c389e04e9b440ad2032a381ac2cfc54f409caa791e65ee4f5d6cd035008f219b88a803a7382ae447bf65" +"a3df2176b25b3b7b67dabe34decd9a1384dc7a003916ca8fbcb29b3ad6fd8eac5bbbaa3bdfa6c6a3ad9427c4f3ed79fea2" +"6e14c8ce5fa3b4f82c5f7b6d2125916753a7b92ce9b46d45"; \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.c b/_randomgen/core_prng/src/dsfmt/dSFMT.c index 3ce156699175..0f122c26c81e 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.c +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.c @@ -12,10 +12,14 @@ * The new BSD License is applied to this software, see LICENSE.txt */ #include -#include #include +#include + #include "dSFMT-params.h" + #include "dSFMT-common.h" +#include "dSFMT-jump.h" +#include "dSFMT-poly.h" #if defined(__cplusplus) extern "C" { @@ -31,14 +35,10 @@ static const int dsfmt_mexp = DSFMT_MEXP; ----------------*/ inline static uint32_t ini_func1(uint32_t x); inline static uint32_t ini_func2(uint32_t x); -inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, - int size); -inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, - int size); +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, int size); +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, int size); inline static int idxof(int i); static void initial_mask(dsfmt_t *dsfmt); static void period_certification(dsfmt_t *dsfmt); @@ -57,13 +57,9 @@ static const union X128D_T sse2_double_m_one = {{-1.0, -1.0}}; * array of LITTLE ENDIAN in BIG ENDIAN machine. */ #if defined(DSFMT_BIG_ENDIAN) -inline static int idxof(int i) { - return i ^ 1; -} +inline static int idxof(int i) { return i ^ 1; } #else -inline static int idxof(int i) { - return i; -} +inline static int idxof(int i) { return i; } #endif #if defined(HAVE_SSE2) @@ -74,7 +70,7 @@ inline static int idxof(int i) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } /** @@ -84,7 +80,7 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); + w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); } /** @@ -94,8 +90,8 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->si = _mm_or_si128(w->si, sse2_int_one.i128); - w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); + w->si = _mm_or_si128(w->si, sse2_int_one.i128); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } #else /* standard C and altivec */ /** @@ -105,8 +101,8 @@ inline static void convert_o0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } /** @@ -116,8 +112,8 @@ inline static void convert_c0o1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { - w->d[0] = 2.0 - w->d[0]; - w->d[1] = 2.0 - w->d[1]; + w->d[0] = 2.0 - w->d[0]; + w->d[1] = 2.0 - w->d[1]; } /** @@ -127,10 +123,10 @@ inline static void convert_o0c1(w128_t *w) { * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { - w->u[0] |= 1; - w->u[1] |= 1; - w->d[0] -= 1.0; - w->d[1] -= 1.0; + w->u[0] |= 1; + w->u[1] |= 1; + w->d[0] -= 1.0; + w->d[1] -= 1.0; } #endif @@ -142,34 +138,33 @@ inline static void convert_o0o1(w128_t *w) { * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -180,39 +175,38 @@ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_c0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_c0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_c0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_c0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_c0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_c0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -223,39 +217,38 @@ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0o1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0o1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0o1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -266,39 +259,38 @@ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, - int size) { - int i, j; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], - &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&array[i], &dsfmt->status[i], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - } - for (; i < size - DSFMT_N; i++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - convert_o0c1(&array[i - DSFMT_N]); - } - for (j = 0; j < 2 * DSFMT_N - size; j++) { - dsfmt->status[j] = array[j + size - DSFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - DSFMT_N], - &array[i + DSFMT_POS1 - DSFMT_N], &lung); - dsfmt->status[j] = array[i]; - convert_o0c1(&array[i - DSFMT_N]); - } - for (i = size - DSFMT_N; i < size; i++) { - convert_o0c1(&array[i]); - } - dsfmt->status[DSFMT_N] = lung; + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], + &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], + &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0c1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0c1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0c1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -308,7 +300,7 @@ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, * @return 32-bit integer */ static uint32_t ini_func1(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1664525UL; + return (x ^ (x >> 27)) * (uint32_t)1664525UL; } /** @@ -318,7 +310,7 @@ static uint32_t ini_func1(uint32_t x) { * @return 32-bit integer */ static uint32_t ini_func2(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1566083941UL; + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; } /** @@ -327,13 +319,13 @@ static uint32_t ini_func2(uint32_t x) { * @param dsfmt dsfmt state vector. */ static void initial_mask(dsfmt_t *dsfmt) { - int i; - uint64_t *psfmt; + int i; + uint64_t *psfmt; - psfmt = &dsfmt->status[0].u[0]; - for (i = 0; i < DSFMT_N * 2; i++) { - psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; - } + psfmt = &dsfmt->status[0].u[0]; + for (i = 0; i < DSFMT_N * 2; i++) { + psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; + } } /** @@ -341,44 +333,44 @@ static void initial_mask(dsfmt_t *dsfmt) { * @param dsfmt dsfmt state vector. */ static void period_certification(dsfmt_t *dsfmt) { - uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; - uint64_t tmp[2]; - uint64_t inner; - int i; + uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; + uint64_t tmp[2]; + uint64_t inner; + int i; #if (DSFMT_PCV2 & 1) != 1 - int j; - uint64_t work; + int j; + uint64_t work; #endif - tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); - tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); - - inner = tmp[0] & pcv[0]; - inner ^= tmp[1] & pcv[1]; - for (i = 32; i > 0; i >>= 1) { - inner ^= inner >> i; - } - inner &= 1; - /* check OK */ - if (inner == 1) { - return; - } + tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); + tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); + + inner = tmp[0] & pcv[0]; + inner ^= tmp[1] & pcv[1]; + for (i = 32; i > 0; i >>= 1) { + inner ^= inner >> i; + } + inner &= 1; + /* check OK */ + if (inner == 1) { + return; + } /* check NG, and modification */ #if (DSFMT_PCV2 & 1) == 1 - dsfmt->status[DSFMT_N].u[1] ^= 1; + dsfmt->status[DSFMT_N].u[1] ^= 1; #else - for (i = 1; i >= 0; i--) { - work = 1; - for (j = 0; j < 64; j++) { - if ((work & pcv[i]) != 0) { - dsfmt->status[DSFMT_N].u[i] ^= work; - return; - } - work = work << 1; - } - } + for (i = 1; i >= 0; i--) { + work = 1; + for (j = 0; j < 64; j++) { + if ((work & pcv[i]) != 0) { + dsfmt->status[DSFMT_N].u[i] ^= work; + return; + } + work = work << 1; + } + } #endif - return; + return; } /*---------------- @@ -389,18 +381,14 @@ static void period_certification(dsfmt_t *dsfmt) { * the Mersenne exponent, and all parameters of this generator. * @return id string. */ -const char *dsfmt_get_idstring(void) { - return DSFMT_IDSTR; -} +const char *dsfmt_get_idstring(void) { return DSFMT_IDSTR; } /** * This function returns the minimum size of array used for \b * fill_array functions. * @return minimum size of array used for fill_array functions. */ -int dsfmt_get_min_array_size(void) { - return DSFMT_N64; -} +int dsfmt_get_min_array_size(void) { return DSFMT_N64; } /** * This function fills the internal state array with double precision @@ -408,21 +396,21 @@ int dsfmt_get_min_array_size(void) { * @param dsfmt dsfmt state vector. */ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { - int i; - w128_t lung; - - lung = dsfmt->status[DSFMT_N]; - do_recursion(&dsfmt->status[0], &dsfmt->status[0], - &dsfmt->status[DSFMT_POS1], &lung); - for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1], &lung); - } - for (; i < DSFMT_N; i++) { - do_recursion(&dsfmt->status[i], &dsfmt->status[i], - &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); - } - dsfmt->status[DSFMT_N] = lung; + int i; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&dsfmt->status[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); + } + dsfmt->status[DSFMT_N] = lung; } /** @@ -454,9 +442,9 @@ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { * returns the pointer to the aligned memory block. */ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); } /** @@ -472,9 +460,9 @@ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); } /** @@ -490,9 +478,9 @@ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); } /** @@ -508,13 +496,13 @@ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { - assert(size % 2 == 0); - assert(size >= DSFMT_N64); - gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); } #if defined(__INTEL_COMPILER) -# pragma warning(disable:981) +#pragma warning(disable : 981) #endif /** * This function initializes the internal state array with a 32-bit @@ -524,23 +512,23 @@ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { - int i; - uint32_t *psfmt; - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - psfmt = &dsfmt->status[0].u32[0]; - psfmt[idxof(0)] = seed; - for (i = 1; i < (DSFMT_N + 1) * 4; i++) { - psfmt[idxof(i)] = 1812433253UL - * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int i; + uint32_t *psfmt; + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + psfmt = &dsfmt->status[0].u32[0]; + psfmt[idxof(0)] = seed; + for (i = 1; i < (DSFMT_N + 1) * 4; i++) { + psfmt[idxof(i)] = + 1812433253UL * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } /** @@ -552,80 +540,77 @@ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], - int key_length, int mexp) { - int i, j, count; - uint32_t r; - uint32_t *psfmt32; - int lag; - int mid; - int size = (DSFMT_N + 1) * 4; /* pulmonary */ - - /* make sure caller program is compiled with the same MEXP */ - if (mexp != dsfmt_mexp) { - fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); - exit(1); - } - if (size >= 623) { - lag = 11; - } else if (size >= 68) { - lag = 7; - } else if (size >= 39) { - lag = 5; - } else { - lag = 3; - } - mid = (size - lag) / 2; - - psfmt32 = &dsfmt->status[0].u32[0]; - memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); - if (key_length + 1 > size) { - count = key_length + 1; - } else { - count = size; - } - r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] - ^ psfmt32[idxof((size - 1) % size)]); - psfmt32[idxof(mid % size)] += r; - r += key_length; - psfmt32[idxof((mid + lag) % size)] += r; - psfmt32[idxof(0)] = r; - count--; - for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = ini_func1(psfmt32[idxof(i)] - ^ psfmt32[idxof((i + mid) % size)] - ^ psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += init_key[j] + i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (; j < count; j++) { - r = ini_func1(psfmt32[idxof(i)] - ^ psfmt32[idxof((i + mid) % size)] - ^ psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] += r; - r += i; - psfmt32[idxof((i + mid + lag) % size)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - for (j = 0; j < size; j++) { - r = ini_func2(psfmt32[idxof(i)] - + psfmt32[idxof((i + mid) % size)] - + psfmt32[idxof((i + size - 1) % size)]); - psfmt32[idxof((i + mid) % size)] ^= r; - r -= i; - psfmt32[idxof((i + mid + lag) % size)] ^= r; - psfmt32[idxof(i)] = r; - i = (i + 1) % size; - } - initial_mask(dsfmt); - period_certification(dsfmt); - dsfmt->idx = DSFMT_N64; + int key_length, int mexp) { + int i, j, count; + uint32_t r; + uint32_t *psfmt32; + int lag; + int mid; + int size = (DSFMT_N + 1) * 4; /* pulmonary */ + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + if (size >= 623) { + lag = 11; + } else if (size >= 68) { + lag = 7; + } else if (size >= 39) { + lag = 5; + } else { + lag = 3; + } + mid = (size - lag) / 2; + + psfmt32 = &dsfmt->status[0].u32[0]; + memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); + if (key_length + 1 > size) { + count = key_length + 1; + } else { + count = size; + } + r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] ^ + psfmt32[idxof((size - 1) % size)]); + psfmt32[idxof(mid % size)] += r; + r += key_length; + psfmt32[idxof((mid + lag) % size)] += r; + psfmt32[idxof(0)] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += init_key[j] + i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % size)] + + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] ^= r; + r -= i; + psfmt32[idxof((i + mid + lag) % size)] ^= r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; } #if defined(__INTEL_COMPILER) -# pragma warning(default:981) +#pragma warning(default : 981) #endif #if defined(__cplusplus) @@ -636,4 +621,6 @@ extern inline double dsfmt_next_double(dsfmt_state *state); extern inline uint64_t dsfmt_next64(dsfmt_state *state); -extern inline uint32_t dsfmt_next32(dsfmt_state *state); \ No newline at end of file +extern inline uint32_t dsfmt_next32(dsfmt_state *state); + +void dsfmt_jump(dsfmt_state *state) { dSFMT_jump(state->state, poly_128); }; \ No newline at end of file diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index 52b6b3aedcc2..2d616acd8276 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -38,14 +38,14 @@ extern "C" { #endif -#include #include +#include #if !defined(DSFMT_MEXP) #ifdef __GNUC__ - #warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." +#warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." #endif - #define DSFMT_MEXP 19937 +#define DSFMT_MEXP 19937 #endif /*----------------- BASIC DEFINITIONS @@ -64,103 +64,103 @@ extern "C" { #define DSFMT_N64 (DSFMT_N * 2) #if !defined(DSFMT_BIG_ENDIAN) -# if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) -# if __BYTE_ORDER == __BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) -# if _BYTE_ORDER == _BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) -# if __BYTE_ORDER__ == __BIG_ENDIAN__ -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) -# if BYTE_ORDER == BIG_ENDIAN -# define DSFMT_BIG_ENDIAN 1 -# endif -# elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) \ - || defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) -# define DSFMT_BIG_ENDIAN 1 -# endif +#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +#if __BYTE_ORDER == __BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) +#if _BYTE_ORDER == _BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) +#if __BYTE_ORDER__ == __BIG_ENDIAN__ +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) +#if BYTE_ORDER == BIG_ENDIAN +#define DSFMT_BIG_ENDIAN 1 +#endif +#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || \ + defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) +#define DSFMT_BIG_ENDIAN 1 +#endif #endif #if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) -# undef DSFMT_BIG_ENDIAN +#undef DSFMT_BIG_ENDIAN #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# include +#include #elif defined(_MSC_VER) || defined(__BORLANDC__) -# if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) +#if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; -# ifndef UINT64_C -# define UINT64_C(v) (v ## ui64) -# endif -# define DSFMT_UINT32_DEFINED -# if !defined(inline) && !defined(__cplusplus) -# define inline __forceinline -# endif -# endif +#ifndef UINT64_C +#define UINT64_C(v) (v##ui64) +#endif +#define DSFMT_UINT32_DEFINED +#if !defined(inline) && !defined(__cplusplus) +#define inline __forceinline +#endif +#endif +#else +#include +#if !defined(inline) && !defined(__cplusplus) +#if defined(__GNUC__) +#define inline __forceinline__ #else -# include -# if !defined(inline) && !defined(__cplusplus) -# if defined(__GNUC__) -# define inline __forceinline__ -# else -# define inline -# endif -# endif +#define inline +#endif +#endif #endif #ifndef PRIu64 -# if defined(_MSC_VER) || defined(__BORLANDC__) -# define PRIu64 "I64u" -# define PRIx64 "I64x" -# else -# define PRIu64 "llu" -# define PRIx64 "llx" -# endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#else +#define PRIu64 "llu" +#define PRIx64 "llx" +#endif #endif #ifndef UINT64_C -# define UINT64_C(v) (v ## ULL) +#define UINT64_C(v) (v##ULL) #endif /*------------------------------------------ 128-bit SIMD like data type for standard C ------------------------------------------*/ #if defined(HAVE_ALTIVEC) -# if !defined(__APPLE__) -# include -# endif +#if !defined(__APPLE__) +#include +#endif /** 128-bit data structure */ union W128_T { - vector unsigned int s; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + vector unsigned int s; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #elif defined(HAVE_SSE2) -# include +#include /** 128-bit data structure */ union W128_T { - __m128i si; - __m128d sd; - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + __m128i si; + __m128d sd; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; -#else /* standard C */ +#else /* standard C */ /** 128-bit data structure */ union W128_T { - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; }; #endif @@ -169,8 +169,8 @@ typedef union W128_T w128_t; /** the 128-bit internal state array */ struct DSFMT_T { - w128_t status[DSFMT_N + 1]; - int idx; + w128_t status[DSFMT_N + 1]; + int idx; }; typedef struct DSFMT_T dsfmt_t; @@ -191,42 +191,42 @@ const char *dsfmt_get_idstring(void); int dsfmt_get_min_array_size(void); #if defined(__GNUC__) -# define DSFMT_PRE_INLINE inline static -# define DSFMT_PST_INLINE __attribute__((always_inline)) +#define DSFMT_PRE_INLINE inline static +#define DSFMT_PST_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) && _MSC_VER >= 1200 -# define DSFMT_PRE_INLINE __forceinline static -# define DSFMT_PST_INLINE +#define DSFMT_PRE_INLINE __forceinline static +#define DSFMT_PST_INLINE #else -# define DSFMT_PRE_INLINE inline static -# define DSFMT_PST_INLINE +#define DSFMT_PRE_INLINE inline static +#define DSFMT_PST_INLINE #endif DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_close_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_open_close(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double +dsfmt_genrand_open_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void +dsfmt_gv_fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, + uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) DSFMT_PST_INLINE; @@ -239,15 +239,15 @@ DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { - uint32_t r; - uint64_t *psfmt64 = &dsfmt->status[0].u[0]; + uint32_t r; + uint64_t *psfmt64 = &dsfmt->status[0].u[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++] & 0xffffffffU; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++] & 0xffffffffU; + return r; } /** @@ -260,15 +260,15 @@ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { - double r; - double *psfmt64 = &dsfmt->status[0].d[0]; + double r; + double *psfmt64 = &dsfmt->status[0].d[0]; - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r = psfmt64[dsfmt->idx++]; - return r; + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++]; + return r; } /** @@ -279,7 +279,7 @@ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_gv_genrand_uint32(void) { - return dsfmt_genrand_uint32(&dsfmt_global_data); + return dsfmt_genrand_uint32(&dsfmt_global_data); } /** @@ -290,7 +290,7 @@ inline static uint32_t dsfmt_gv_genrand_uint32(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close1_open2(void) { - return dsfmt_genrand_close1_open2(&dsfmt_global_data); + return dsfmt_genrand_close1_open2(&dsfmt_global_data); } /** @@ -302,7 +302,7 @@ inline static double dsfmt_gv_genrand_close1_open2(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { - return dsfmt_genrand_close1_open2(dsfmt) - 1.0; + return dsfmt_genrand_close1_open2(dsfmt) - 1.0; } /** @@ -313,7 +313,7 @@ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close_open(void) { - return dsfmt_gv_genrand_close1_open2() - 1.0; + return dsfmt_gv_genrand_close1_open2() - 1.0; } /** @@ -325,7 +325,7 @@ inline static double dsfmt_gv_genrand_close_open(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { - return 2.0 - dsfmt_genrand_close1_open2(dsfmt); + return 2.0 - dsfmt_genrand_close1_open2(dsfmt); } /** @@ -336,7 +336,7 @@ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_close(void) { - return 2.0 - dsfmt_gv_genrand_close1_open2(); + return 2.0 - dsfmt_gv_genrand_close1_open2(); } /** @@ -348,19 +348,19 @@ inline static double dsfmt_gv_genrand_open_close(void) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { - double *dsfmt64 = &dsfmt->status[0].d[0]; - union { - double d; - uint64_t u; - } r; - - if (dsfmt->idx >= DSFMT_N64) { - dsfmt_gen_rand_all(dsfmt); - dsfmt->idx = 0; - } - r.d = dsfmt64[dsfmt->idx++]; - r.u |= 1; - return r.d - 1.0; + double *dsfmt64 = &dsfmt->status[0].d[0]; + union { + double d; + uint64_t u; + } r; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r.d = dsfmt64[dsfmt->idx++]; + r.u |= 1; + return r.d - 1.0; } /** @@ -371,7 +371,7 @@ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_open(void) { - return dsfmt_genrand_open_open(&dsfmt_global_data); + return dsfmt_genrand_open_open(&dsfmt_global_data); } /** @@ -386,7 +386,7 @@ inline static double dsfmt_gv_genrand_open_open(void) { * see also \sa dsfmt_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { - dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); + dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); } /** @@ -402,7 +402,7 @@ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { - dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); } /** @@ -418,7 +418,7 @@ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { - dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); } /** @@ -434,7 +434,7 @@ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { - dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); + dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); } /** @@ -444,7 +444,7 @@ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { * @param seed a 32-bit integer used as the seed. */ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { - dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); + dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); } /** @@ -454,7 +454,7 @@ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { * see also \sa dsfmt_init_gen_rand() */ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { - dsfmt_init_gen_rand(&dsfmt_global_data, seed); + dsfmt_init_gen_rand(&dsfmt_global_data, seed); } /** @@ -466,7 +466,7 @@ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { */ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) { - dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); + dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); } /** @@ -478,36 +478,34 @@ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], * see also \sa dsfmt_init_by_array() */ inline static void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { - dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); + dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); } #if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], + int key_length) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) - DSFMT_PST_INLINE; -DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) - DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_close(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_open(double array[], + int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], + int size) DSFMT_PST_INLINE; /** * This function is just the same as dsfmt_get_idstring(). * @return id string. * see also \sa dsfmt_get_idstring() */ -inline static const char *get_idstring(void) { - return dsfmt_get_idstring(); -} +inline static const char *get_idstring(void) { return dsfmt_get_idstring(); } /** * This function is just the same as dsfmt_get_min_array_size(). @@ -515,7 +513,7 @@ inline static const char *get_idstring(void) { * see also \sa dsfmt_get_min_array_size() */ inline static int get_min_array_size(void) { - return dsfmt_get_min_array_size(); + return dsfmt_get_min_array_size(); } /** @@ -524,7 +522,7 @@ inline static int get_min_array_size(void) { * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). */ inline static void init_gen_rand(uint32_t seed) { - dsfmt_gv_init_gen_rand(seed); + dsfmt_gv_init_gen_rand(seed); } /** @@ -534,7 +532,7 @@ inline static void init_gen_rand(uint32_t seed) { * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). */ inline static void init_by_array(uint32_t init_key[], int key_length) { - dsfmt_gv_init_by_array(init_key, key_length); + dsfmt_gv_init_by_array(init_key, key_length); } /** @@ -544,7 +542,7 @@ inline static void init_by_array(uint32_t init_key[], int key_length) { * dsfmt_gv_genrand_close1_open2() */ inline static double genrand_close1_open2(void) { - return dsfmt_gv_genrand_close1_open2(); + return dsfmt_gv_genrand_close1_open2(); } /** @@ -554,7 +552,7 @@ inline static double genrand_close1_open2(void) { * dsfmt_gv_genrand_close_open() */ inline static double genrand_close_open(void) { - return dsfmt_gv_genrand_close_open(); + return dsfmt_gv_genrand_close_open(); } /** @@ -564,7 +562,7 @@ inline static double genrand_close_open(void) { * dsfmt_gv_genrand_open_close() */ inline static double genrand_open_close(void) { - return dsfmt_gv_genrand_open_close(); + return dsfmt_gv_genrand_open_close(); } /** @@ -574,7 +572,7 @@ inline static double genrand_open_close(void) { * dsfmt_gv_genrand_open_open() */ inline static double genrand_open_open(void) { - return dsfmt_gv_genrand_open_open(); + return dsfmt_gv_genrand_open_open(); } /** @@ -587,7 +585,7 @@ inline static double genrand_open_open(void) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_close(double array[], int size) { - dsfmt_gv_fill_array_open_close(array, size); + dsfmt_gv_fill_array_open_close(array, size); } /** @@ -600,7 +598,7 @@ inline static void fill_array_open_close(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close_open(double array[], int size) { - dsfmt_gv_fill_array_close_open(array, size); + dsfmt_gv_fill_array_close_open(array, size); } /** @@ -613,7 +611,7 @@ inline static void fill_array_close_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_open(double array[], int size) { - dsfmt_gv_fill_array_open_open(array, size); + dsfmt_gv_fill_array_open_open(array, size); } /** @@ -625,7 +623,7 @@ inline static void fill_array_open_open(double array[], int size) { * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close1_open2(double array[], int size) { - dsfmt_gv_fill_array_close1_open2(array, size); + dsfmt_gv_fill_array_close1_open2(array, size); } #endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ @@ -635,7 +633,6 @@ inline static void fill_array_close1_open2(double array[], int size) { #endif /* DSFMT_H */ - typedef struct s_dsfmt_state { dsfmt_t *state; int has_uint32; @@ -651,7 +648,8 @@ static inline double dsfmt_next_double(dsfmt_state *state) { state->buffer_loc++; return out; } - dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, DSFMT_N64); + dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, + DSFMT_N64); state->buffer_loc = 1; return state->buffered_uniforms[0]; } @@ -669,10 +667,11 @@ static inline uint64_t dsfmt_next64(dsfmt_state *state) { return out; } - static inline uint32_t dsfmt_next32(dsfmt_state *state) { /* Discard bottom 16 bits */ double d = dsfmt_next_double(state); uint64_t *out = (uint64_t *)&d; return (uint32_t)((*out >> 16) & 0xffffffff); } + +void dsfmt_jump(dsfmt_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/mt19937/mt19937-jump.c b/_randomgen/core_prng/src/mt19937/mt19937-jump.c new file mode 100644 index 000000000000..46b28cf96bcb --- /dev/null +++ b/_randomgen/core_prng/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/_randomgen/core_prng/src/mt19937/mt19937-jump.h b/_randomgen/core_prng/src/mt19937/mt19937-jump.h new file mode 100644 index 000000000000..394c150a0336 --- /dev/null +++ b/_randomgen/core_prng/src/mt19937/mt19937-jump.h @@ -0,0 +1,15 @@ +#pragma once +#include "mt19937.h" +#include + +/* 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/_randomgen/core_prng/src/mt19937/mt19937-poly.h b/_randomgen/core_prng/src/mt19937/mt19937-poly.h new file mode 100644 index 000000000000..b03747881348 --- /dev/null +++ b/_randomgen/core_prng/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/_randomgen/core_prng/src/mt19937/mt19937.c b/_randomgen/core_prng/src/mt19937/mt19937.c index bb080c1a2ee1..e5ca9e0cff67 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937.c +++ b/_randomgen/core_prng/src/mt19937/mt19937.c @@ -1,4 +1,6 @@ #include "mt19937.h" +#include "mt19937-jump.h" +#include "mt19937-poly.h" void mt19937_seed(mt19937_state *state, uint32_t seed) { int pos; @@ -101,3 +103,5 @@ 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/_randomgen/core_prng/src/mt19937/mt19937.h b/_randomgen/core_prng/src/mt19937/mt19937.h index 18da9622decf..8105329ece6b 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937.h +++ b/_randomgen/core_prng/src/mt19937/mt19937.h @@ -65,3 +65,5 @@ 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/_randomgen/setup.py b/_randomgen/setup.py index 2d726909bef8..3c40089a4e7f 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -54,7 +54,8 @@ ), Extension("core_prng.dsfmt", ["core_prng/dsfmt.pyx", - join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c')], + join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c'), + join(MOD_DIR, 'src', 'dsfmt', 'dSFMT-jump.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'dsfmt')], @@ -64,7 +65,8 @@ ), Extension("core_prng.mt19937", ["core_prng/mt19937.pyx", - join(MOD_DIR, 'src', 'mt19937', 'mt19937.c')], + join(MOD_DIR, 'src', 'mt19937', 'mt19937.c'), + join(MOD_DIR, 'src', 'mt19937', 'mt19937-jump.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'mt19937')], From e9e0a8c32e72d739e4bb637bc85bb2b5a42545c7 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 17:45:56 +0000 Subject: [PATCH 036/138] ENH: Add ctypes interface and examples Add prototype ctypes interface to Xoroshiro128 Add example showing use in Cython Add eample showing use in Numba --- _randomgen/core_prng/xoroshiro128.pyx | 11 ++++++++ _randomgen/examples/cython/extending.pyx | 25 ++++++++++++++++ _randomgen/examples/cython/setup.py | 11 ++++++++ _randomgen/examples/numba/extending.py | 36 ++++++++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 _randomgen/examples/cython/extending.pyx create mode 100644 _randomgen/examples/cython/setup.py create mode 100644 _randomgen/examples/numba/extending.py diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 820ae0476e49..4e5240ced998 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -2,6 +2,9 @@ from libc.stdint cimport uint32_t, uint64_t from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +from collections import namedtuple +ctypes_interface = namedtuple('ctypes_interface', ['state','next_uint64','next_uint32','next_double']) + import numpy as np cimport numpy as np @@ -10,6 +13,8 @@ from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy +import ctypes + np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": @@ -51,6 +56,7 @@ cdef class Xoroshiro128: cdef xoroshiro128_state *rng_state cdef prng_t *_prng cdef public object _prng_capsule + cdef public object ctypes def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) @@ -62,6 +68,11 @@ cdef class Xoroshiro128: self._prng.next_uint64 = &xoroshiro128_uint64 self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double + + self.ctypes = ctypes_interface(ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoroshiro128_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p))) cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/examples/cython/extending.pyx b/_randomgen/examples/cython/extending.pyx new file mode 100644 index 000000000000..1af47b48d267 --- /dev/null +++ b/_randomgen/examples/cython/extending.pyx @@ -0,0 +1,25 @@ +import numpy as np +cimport numpy as np +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from core_prng.common cimport prng_t +from core_prng.xoroshiro128 import Xoroshiro128 + +np.import_array() + +def uniform_mean(Py_ssize_t N): + cdef Py_ssize_t i + cdef prng_t *rng + cdef const char *anon_name = "CorePRNG" + cdef double[::1] random_values + cdef np.ndarray randoms + + x = Xoroshiro128() + capsule = x._prng_capsule + if not PyCapsule_IsValid(capsule, anon_name): + raise ValueError("Invalid pointer to anon_func_state") + rng = PyCapsule_GetPointer(capsule, anon_name) + random_values = np.empty(N) + for i in range(N): + random_values[i] = rng.next_double(rng.state) + randoms = np.asarray(random_values) + return randoms.mean() diff --git a/_randomgen/examples/cython/setup.py b/_randomgen/examples/cython/setup.py new file mode 100644 index 000000000000..408ea3254ea8 --- /dev/null +++ b/_randomgen/examples/cython/setup.py @@ -0,0 +1,11 @@ +# 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 + +setup( + ext_modules=cythonize([Extension("extending", + sources=['extending.pyx'], + include_dirs=[np.get_include()])]) +) diff --git a/_randomgen/examples/numba/extending.py b/_randomgen/examples/numba/extending.py new file mode 100644 index 000000000000..46b125dc2e88 --- /dev/null +++ b/_randomgen/examples/numba/extending.py @@ -0,0 +1,36 @@ +from core_prng import Xoroshiro128 +import numpy as np +import numba as nb + +x = Xoroshiro128() +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 + + +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): + bounded_uint(lb, ub, state) + + +bounded_uints(323, 2394691, 10000000, s.value) From 0e5ffae5152713352246e66e1129d13c0ad9e7da Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 20:10:39 +0000 Subject: [PATCH 037/138] CLN: Mix skipped nogils Re-enable all nogils --- _randomgen/core_prng/dsfmt.pyx | 2 +- _randomgen/core_prng/pcg64.pyx | 2 +- _randomgen/core_prng/xoroshiro128.pyx | 2 +- _randomgen/core_prng/xorshift1024.pyx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index b82007abe437..90b2a6bffec3 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -50,7 +50,7 @@ cdef extern from "src/dsfmt/dSFMT.h": void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) void dsfmt_jump(dsfmt_state *state); -cdef uint64_t dsfmt_uint64(void* st):# nogil: +cdef uint64_t dsfmt_uint64(void* st) nogil: return dsfmt_next64(st) cdef uint32_t dsfmt_uint32(void *st) nogil: diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 3e447ae3a92a..dcacb797179a 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -51,7 +51,7 @@ cdef extern from "src/pcg64/pcg64.h": void pcg64_advance(pcg64_state *state, uint64_t *step) -cdef uint64_t pcg64_uint64(void* st):# nogil: +cdef uint64_t pcg64_uint64(void* st) nogil: return pcg64_next64(st) cdef uint32_t pcg64_uint32(void *st) nogil: diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 4e5240ced998..17807c4efb50 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -30,7 +30,7 @@ cdef extern from "src/xoroshiro128/xoroshiro128.h": uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil void xoroshiro128_jump(xoroshiro128_state *state) -cdef uint64_t xoroshiro128_uint64(void* st):# nogil: +cdef uint64_t xoroshiro128_uint64(void* st) nogil: return xoroshiro128_next64(st) cdef uint32_t xoroshiro128_uint32(void *st) nogil: diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 6c0585369479..27499e30c2a0 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -25,7 +25,7 @@ cdef extern from "src/xorshift1024/xorshift1024.h": uint64_t xorshift1024_next32(xorshift1024_state *state) nogil void xorshift1024_jump(xorshift1024_state *state) -cdef uint64_t xorshift1024_uint64(void* st):# nogil: +cdef uint64_t xorshift1024_uint64(void* st) nogil: return xorshift1024_next64(st) cdef uint32_t xorshift1024_uint32(void *st) nogil: From 5d274afe3145fccd83bc05ea2fe1e20a26d41dea Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 7 Mar 2018 22:48:10 +0000 Subject: [PATCH 038/138] ENH: Add cffi interface Add xffi interface for xoroshir128 --- _randomgen/core_prng/xoroshiro128.pyx | 28 ++++++++++++++---- _randomgen/examples/numba/extending.py | 39 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 17807c4efb50..76d78652dadd 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -3,7 +3,7 @@ from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New from collections import namedtuple -ctypes_interface = namedtuple('ctypes_interface', ['state','next_uint64','next_uint32','next_double']) +interface = namedtuple('interface', ['state_address','state','next_uint64','next_uint32','next_double']) import numpy as np cimport numpy as np @@ -14,6 +14,7 @@ import core_prng.pickle cimport entropy import ctypes +import cffi np.import_array() @@ -57,6 +58,8 @@ cdef class Xoroshiro128: cdef prng_t *_prng cdef public object _prng_capsule cdef public object ctypes + cdef public object cffi + cdef public object state_address def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) @@ -68,11 +71,26 @@ cdef class Xoroshiro128: self._prng.next_uint64 = &xoroshiro128_uint64 self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double + + ffi = cffi.FFI() + self.cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',&xoroshiro128_uint64), + ffi.cast('uint32_t (*)(void *)',&xoroshiro128_uint32), + ffi.cast('double (*)(void *)',&xoroshiro128_double)) - self.ctypes = ctypes_interface(ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoroshiro128_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p))) + self.state_address = self.rng_state + self.ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoroshiro128_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p))) cdef const char *name = "CorePRNG" self._prng_capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/examples/numba/extending.py b/_randomgen/examples/numba/extending.py index 46b125dc2e88..aa7122c9543a 100644 --- a/_randomgen/examples/numba/extending.py +++ b/_randomgen/examples/numba/extending.py @@ -34,3 +34,42 @@ def bounded_uints(lb, ub, n, 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//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 + out[2*i+1] = f*x2 + + if n % 2 == 1: + 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[n] = f*x1 + return out + + +print(normals(10, cffi_state).var()) + +normalsj = nb.jit(normals, nopython=True) + +print(normalsj(10000000, state_addr).var()) From 2f9b9c0a30dc7f660f498c12e34c9340ce12152b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 8 Mar 2018 09:39:58 +0000 Subject: [PATCH 039/138] ENH: Add example using distributions Add example Rename _prng_capsule to capsule Use common.pxd to gather all information about distirbutionsh --- _randomgen/core_prng/common.pxd | 21 ++++++- _randomgen/core_prng/dsfmt.pyx | 4 +- _randomgen/core_prng/generator.pyx | 19 +------ _randomgen/core_prng/mt19937.pyx | 4 +- _randomgen/core_prng/pcg64.pyx | 4 +- _randomgen/core_prng/philox.pyx | 4 +- _randomgen/core_prng/threefry.pyx | 4 +- _randomgen/core_prng/xoroshiro128.pyx | 57 ++++++++++--------- _randomgen/core_prng/xorshift1024.pyx | 4 +- _randomgen/examples/cython/extending.pyx | 45 +++++++++++++-- .../cython/extending_distributions.pyx | 44 ++++++++++++++ _randomgen/examples/cython/setup.py | 15 ++++- 12 files changed, 158 insertions(+), 67 deletions(-) create mode 100644 _randomgen/examples/cython/extending_distributions.pyx diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 38c66814775b..3387894e81e8 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -21,7 +21,7 @@ ctypedef ConstraintType constraint_type cdef extern from "src/distributions/distributions.h": - cdef struct s_binomial_t: + struct s_binomial_t: int has_binomial; double psave; long nsave; @@ -42,7 +42,7 @@ cdef extern from "src/distributions/distributions.h": ctypedef s_binomial_t binomial_t - cdef struct prng: + struct prng: void *state uint64_t (*next_uint64)(void *st) uint32_t (*next_uint32)(void *st) @@ -55,6 +55,23 @@ cdef extern from "src/distributions/distributions.h": ctypedef prng prng_t + double random_sample(prng_t *prng_state) nogil + double random_standard_exponential(prng_t *prng_state) nogil + double random_standard_exponential_zig(prng_t *prng_state) nogil + double random_gauss(prng_t *prng_state) nogil + double random_gauss_zig(prng_t* prng_state) nogil + double random_standard_gamma(prng_t *prng_state, double shape) nogil + double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil + + float random_sample_f(prng_t *prng_state) nogil + float random_standard_exponential_f(prng_t *prng_state) nogil + float random_standard_exponential_zig_f(prng_t *prng_state) nogil + float random_gauss_f(prng_t *prng_state) nogil + float random_gauss_zig_f(prng_t* prng_state) nogil + float random_standard_gamma_f(prng_t *prng_state, float shape) nogil + float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil + + ctypedef double (*random_double_0)(prng_t *state) nogil ctypedef double (*random_double_1)(prng_t *state, double a) nogil ctypedef double (*random_double_2)(prng_t *state, double a, double b) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 90b2a6bffec3..0341d9a43c8d 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -75,7 +75,7 @@ cdef class DSFMT: """ cdef dsfmt_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(dsfmt_state)) @@ -90,7 +90,7 @@ cdef class DSFMT: self._prng.next_uint32 = &dsfmt_uint32 self._prng.next_double = &dsfmt_double cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: def __getstate__(self): diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index c48afd199aa4..69205245be6f 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -20,23 +20,6 @@ import core_prng.pickle np.import_array() -cdef extern from "src/distributions/distributions.h": - double random_sample(prng_t *prng_state) nogil - double random_standard_exponential(prng_t *prng_state) nogil - double random_standard_exponential_zig(prng_t *prng_state) nogil - double random_gauss(prng_t *prng_state) nogil - double random_gauss_zig(prng_t* prng_state) nogil - double random_standard_gamma(prng_t *prng_state, double shape) nogil - double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil - - float random_sample_f(prng_t *prng_state) nogil - float random_standard_exponential_f(prng_t *prng_state) nogil - float random_standard_exponential_zig_f(prng_t *prng_state) nogil - float random_gauss_f(prng_t *prng_state) nogil - float random_gauss_zig_f(prng_t* prng_state) nogil - float random_standard_gamma_f(prng_t *prng_state, float shape) nogil - float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil - cdef class RandomGenerator: """ Prototype Random Generator that consumes randoms from a CorePRNG class @@ -61,7 +44,7 @@ cdef class RandomGenerator: prng = Xoroshiro128() self.__core_prng = prng - capsule = prng._prng_capsule + capsule = prng.capsule cdef const char *anon_name = "CorePRNG" if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid pointer to anon_func_state") diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index b1d9125c308a..5c09709921e2 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -52,7 +52,7 @@ cdef class MT19937: """ cdef mt19937_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) @@ -66,7 +66,7 @@ cdef class MT19937: self._prng.next_double = &mt19937_double cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) def __dealloc__(self): free(self.rng_state) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index dcacb797179a..a2e0842eb1c5 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -76,7 +76,7 @@ cdef class PCG64: """ cdef pcg64_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None, inc=1): self.rng_state = malloc(sizeof(pcg64_state)) @@ -91,7 +91,7 @@ cdef class PCG64: self._prng.next_double = &pcg64_double cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: def __getstate__(self): diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index f0dcc3a7d1ea..ce9e47be9e73 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -66,7 +66,7 @@ cdef class Philox: """ cdef philox_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(philox_state)) @@ -84,7 +84,7 @@ cdef class Philox: self._prng.next_double = &philox_double cdef const char *name = 'CorePRNG' - self._prng_capsule = PyCapsule_New( self._prng, name, NULL) + self.capsule = PyCapsule_New( self._prng, name, NULL) # Pickling support: def __getstate__(self): diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index db83379eb9c5..aedfc70c7cea 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -62,7 +62,7 @@ cdef class ThreeFry: """ cdef threefry_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry_state)) @@ -78,7 +78,7 @@ cdef class ThreeFry: self._prng.next_double = &threefry_double cdef const char *name = 'CorePRNG' - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: def __getstate__(self): diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 76d78652dadd..367d140c0169 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -13,9 +13,6 @@ from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy -import ctypes -import cffi - np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": @@ -56,10 +53,7 @@ cdef class Xoroshiro128: """ cdef xoroshiro128_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule - cdef public object ctypes - cdef public object cffi - cdef public object state_address + cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) @@ -72,28 +66,8 @@ cdef class Xoroshiro128: self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double - ffi = cffi.FFI() - self.cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',&xoroshiro128_uint64), - ffi.cast('uint32_t (*)(void *)',&xoroshiro128_uint32), - ffi.cast('double (*)(void *)',&xoroshiro128_double)) - - self.state_address = self.rng_state - self.ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoroshiro128_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p))) - cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: def __getstate__(self): @@ -213,3 +187,30 @@ cdef class Xoroshiro128: self.rng_state.s[1] = value['s'][1] self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] + + @property + def ctypes(self): + import ctypes + + return interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoroshiro128_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&xoroshiro128_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p))) + + @property + def cffi(self): + import cffi + + ffi = cffi.FFI() + return interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), + ffi.cast('double (*)(void *)',self._prng.next_double)) diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 27499e30c2a0..635bb24961f9 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -50,7 +50,7 @@ cdef class Xorshift1024: """ cdef xorshift1024_state *rng_state cdef prng_t *_prng - cdef public object _prng_capsule + cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) @@ -64,7 +64,7 @@ cdef class Xorshift1024: self._prng.next_double = &xorshift1024_double cdef const char *name = "CorePRNG" - self._prng_capsule = PyCapsule_New(self._prng, name, NULL) + self.capsule = PyCapsule_New(self._prng, name, NULL) # Pickling support: def __getstate__(self): diff --git a/_randomgen/examples/cython/extending.pyx b/_randomgen/examples/cython/extending.pyx index 1af47b48d267..f09563aff5ee 100644 --- a/_randomgen/examples/cython/extending.pyx +++ b/_randomgen/examples/cython/extending.pyx @@ -1,5 +1,7 @@ import numpy as np cimport numpy as np +cimport cython +from libc.stdint cimport uint32_t from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from core_prng.common cimport prng_t from core_prng.xoroshiro128 import Xoroshiro128 @@ -9,17 +11,52 @@ np.import_array() def uniform_mean(Py_ssize_t N): cdef Py_ssize_t i cdef prng_t *rng - cdef const char *anon_name = "CorePRNG" + cdef const char *capsule_name = "CorePRNG" cdef double[::1] random_values cdef np.ndarray randoms x = Xoroshiro128() - capsule = x._prng_capsule - if not PyCapsule_IsValid(capsule, anon_name): + capsule = x.capsule + if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, anon_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(N) for i in range(N): random_values[i] = rng.next_double(rng.state) randoms = np.asarray(random_values) return randoms.mean() + +cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, prng_t *rng): + 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 prng_t *rng + cdef uint32_t[::1] out + cdef const char *capsule_name = "CorePRNG" + + x = Xoroshiro128() + 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 = PyCapsule_GetPointer(capsule, capsule_name) + + for i in range(n): + out[i] = bounded_uint(lb, ub, rng) + return np.asarray(out) diff --git a/_randomgen/examples/cython/extending_distributions.pyx b/_randomgen/examples/cython/extending_distributions.pyx new file mode 100644 index 000000000000..9d16743a6384 --- /dev/null +++ b/_randomgen/examples/cython/extending_distributions.pyx @@ -0,0 +1,44 @@ +import numpy as np +cimport numpy as np +cimport cython +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from core_prng.common cimport * +from core_prng.xoroshiro128 import Xoroshiro128 + +@cython.boundscheck(False) +@cython.wraparound(False) +def normals_bm(Py_ssize_t n): + cdef Py_ssize_t i + cdef prng_t *rng + cdef const char *capsule_name = "CorePRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + for i in range(n): + random_values[i] = random_gauss(rng) + randoms = np.asarray(random_values) + return randoms + +@cython.boundscheck(False) +@cython.wraparound(False) +def normals_zig(Py_ssize_t n): + cdef Py_ssize_t i + cdef prng_t *rng + cdef const char *capsule_name = "CorePRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + for i in range(n): + random_values[i] = random_gauss_zig(rng) + randoms = np.asarray(random_values) + return randoms diff --git a/_randomgen/examples/cython/setup.py b/_randomgen/examples/cython/setup.py index 408ea3254ea8..61bdc5f606f3 100644 --- a/_randomgen/examples/cython/setup.py +++ b/_randomgen/examples/cython/setup.py @@ -3,9 +3,18 @@ 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('..', '..', 'core_prng', 'src', 'distributions', 'distributions.c')], + include_dirs=[np.get_include()]) + +extensions = [extending, distributions] setup( - ext_modules=cythonize([Extension("extending", - sources=['extending.pyx'], - include_dirs=[np.get_include()])]) + ext_modules=cythonize(extensions) ) From fcef7aee3dad85d5d18dceba9b9661cfdbf486bb Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 8 Mar 2018 10:30:20 +0000 Subject: [PATCH 040/138] ENH: Enable building distributions as a DLL Enable using distributions as a DLL --- .../src/distributions/distributions.h | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 3672060eab3b..9048784467a4 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -17,6 +17,12 @@ typedef int bool; #include "numpy/npy_common.h" #include +#ifdef DLL_EXPORT +#define DECLDIR __declspec(dllexport) +#else +#define DECLDIR extern +#endif + typedef double (*random_double_0)(void *st); typedef float (*random_float_0)(void *st); @@ -52,22 +58,22 @@ typedef struct prng { binomial_t *binomial; } prng_t; -extern float random_sample_f(prng_t *prng_state); -extern double random_sample(prng_t *prng_state); +DECLDIR float random_sample_f(prng_t *prng_state); +DECLDIR double random_sample(prng_t *prng_state); -extern uint32_t random_uint32(prng_t *prng_state); +DECLDIR uint32_t random_uint32(prng_t *prng_state); -extern double random_standard_exponential(prng_t *prng_state); -extern float random_standard_exponential_f(prng_t *prng_state); -extern double random_standard_exponential_zig(prng_t *prng_state); -extern float random_standard_exponential_zig_f(prng_t *prng_state); +DECLDIR double random_standard_exponential(prng_t *prng_state); +DECLDIR float random_standard_exponential_f(prng_t *prng_state); +DECLDIR double random_standard_exponential_zig(prng_t *prng_state); +DECLDIR float random_standard_exponential_zig_f(prng_t *prng_state); -extern double random_gauss(prng_t *prng_state); -extern float random_gauss_f(prng_t *prng_state); -extern double random_gauss_zig(prng_t *prng_state); -extern float random_gauss_zig_f(prng_t *prng_state); +DECLDIR double random_gauss(prng_t *prng_state); +DECLDIR float random_gauss_f(prng_t *prng_state); +DECLDIR double random_gauss_zig(prng_t *prng_state); +DECLDIR float random_gauss_zig_f(prng_t *prng_state); -extern double random_standard_gamma(prng_t *prng_state, double shape); -extern float random_standard_gamma_f(prng_t *prng_state, float shape); -extern double random_standard_gamma_zig(prng_t *prng_state, double shape); -extern float random_standard_gamma_zig_f(prng_t *prng_state, float shape); +DECLDIR double random_standard_gamma(prng_t *prng_state, double shape); +DECLDIR float random_standard_gamma_f(prng_t *prng_state, float shape); +DECLDIR double random_standard_gamma_zig(prng_t *prng_state, double shape); +DECLDIR float random_standard_gamma_zig_f(prng_t *prng_state, float shape); From 784315e997c08ddeadf028232d77e6d743d201e9 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 8 Mar 2018 10:30:55 +0000 Subject: [PATCH 041/138] ENH: Example numba example using external distributions --- _randomgen/core_prng/xoroshiro128.pyx | 11 +++- .../examples/numba/extending_distributions.py | 64 +++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 _randomgen/examples/numba/extending_distributions.py diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 367d140c0169..b56f643f73e5 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -3,7 +3,7 @@ from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New from collections import namedtuple -interface = namedtuple('interface', ['state_address','state','next_uint64','next_uint32','next_double']) +interface = namedtuple('interface', ['state_address','state','next_uint64','next_uint32','next_double','prng']) import numpy as np cimport numpy as np @@ -89,6 +89,9 @@ cdef class Xoroshiro128: def _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + # TODO: These should be done everywhere for safety + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 def __random_integer(self, bits=64): """ @@ -202,7 +205,8 @@ cdef class Xoroshiro128: ctypes.c_void_p)), ctypes.cast(&xoroshiro128_double, ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p))) + ctypes.c_void_p)), + ctypes.c_void_p(self._prng)) @property def cffi(self): @@ -213,4 +217,5 @@ cdef class Xoroshiro128: ffi.cast('void *',self.rng_state), ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), - ffi.cast('double (*)(void *)',self._prng.next_double)) + ffi.cast('double (*)(void *)',self._prng.next_double), + ffi.cast('void *',self._prng)) diff --git a/_randomgen/examples/numba/extending_distributions.py b/_randomgen/examples/numba/extending_distributions.py new file mode 100644 index 000000000000..5c365f338a6c --- /dev/null +++ b/_randomgen/examples/numba/extending_distributions.py @@ -0,0 +1,64 @@ +r""" +On *nix, execute in core_prng/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 numpy as np +from cffi import FFI +from core_prng import Xoroshiro128 +import numba as nb + +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(void *prng_state); +double random_gauss_zig(void *prng_state); +""") +x = Xoroshiro128() +xffi = x.cffi +prng = xffi.prng + +random_gauss = lib.random_gauss +random_gauss_zig = lib.random_gauss_zig + + +def normals(n, prng): + out = np.empty(n) + for i in range(n): + out[i] = random_gauss(prng) + return out + + +def normals_zig(n, prng): + out = np.empty(n) + for i in range(n): + out[i] = random_gauss_zig(prng) + return out + + +normalsj = nb.jit(normals, nopython=True) +normals_zigj = nb.jit(normals_zig, nopython=True) + +# Numba requires a memory address for void * +# Can also get address from x.ctypes.prng.value +prng_address = int(ffi.cast('uintptr_t', prng)) + +norm = normalsj(1000, prng_address) +norm_zig = normals_zigj(1000, prng_address) From 5b262efd51d863e815be892d34e380e67f7a7bad Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 8 Mar 2018 11:54:34 +0000 Subject: [PATCH 042/138] BUG: Precent GC of CorePRNG when using CFFI/CTypes Keep a copy of cffi/ctypes interface handing over to end users to prevent main class from being garbage collected --- _randomgen/core_prng/xoroshiro128.pyx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index b56f643f73e5..0b59f6dccd12 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -54,6 +54,8 @@ cdef class Xoroshiro128: cdef xoroshiro128_state *rng_state cdef prng_t *_prng cdef public object capsule + cdef object ctypes + cdef object cffi def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) @@ -66,6 +68,9 @@ cdef class Xoroshiro128: self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double + self.ctypes = None + self.cffi = None + cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) @@ -193,9 +198,12 @@ cdef class Xoroshiro128: @property def ctypes(self): + if self.ctypes is not None: + return self.ctypes + import ctypes - return interface(self.rng_state, + self.ctypes = interface(self.rng_state, ctypes.c_void_p(self.rng_state), ctypes.cast(&xoroshiro128_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, @@ -207,15 +215,19 @@ cdef class Xoroshiro128: ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), ctypes.c_void_p(self._prng)) + return self.ctypes @property def cffi(self): + if self.cffi is not None: + return self.cffi import cffi ffi = cffi.FFI() - return interface(self.rng_state, + self.cffi = interface(self.rng_state, ffi.cast('void *',self.rng_state), ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), ffi.cast('double (*)(void *)',self._prng.next_double), ffi.cast('void *',self._prng)) + return self.cffi From 12355458601a3de5b54cb12985da33e9f2601984 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 8 Mar 2018 20:04:20 +0000 Subject: [PATCH 043/138] ENH: Port over external functions Power over external functionss from randomstate --- _randomgen/core_prng/common.pxd | 148 +- _randomgen/core_prng/common.pyx | 12 + _randomgen/core_prng/dsfmt.pyx | 15 +- _randomgen/core_prng/generator.pyx | 4058 ++++++++++++++++- _randomgen/core_prng/mt19937.pyx | 1 + _randomgen/core_prng/philox.pyx | 1 + .../src/aligned_malloc/aligned_malloc.c | 9 + .../src/aligned_malloc/aligned_malloc.h | 49 + .../src/distributions/distributions.c | 993 ++++ .../src/distributions/distributions.h | 88 +- _randomgen/core_prng/src/dsfmt/dSFMT.h | 22 +- _randomgen/core_prng/threefry.pyx | 1 + _randomgen/core_prng/xoroshiro128.pyx | 1 + _randomgen/core_prng/xorshift1024.pyx | 1 + _randomgen/setup.py | 3 +- 15 files changed, 5255 insertions(+), 147 deletions(-) create mode 100644 _randomgen/core_prng/src/aligned_malloc/aligned_malloc.c create mode 100644 _randomgen/core_prng/src/aligned_malloc/aligned_malloc.h diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 3387894e81e8..ec4029e59db9 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,4 +1,6 @@ -from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t +from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, + int8_t, int16_t, int32_t, int64_t, intptr_t) +from libc.math cimport sqrt from cpython cimport PyInt_AsLong, PyFloat_AsDouble import numpy as np @@ -19,34 +21,41 @@ cdef enum ConstraintType: ctypedef ConstraintType constraint_type +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); + cdef extern from "src/distributions/distributions.h": struct s_binomial_t: - int has_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; + int has_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 ctypedef s_binomial_t binomial_t struct prng: void *state - uint64_t (*next_uint64)(void *st) - uint32_t (*next_uint32)(void *st) - double (*next_double)(void *st) + 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 int has_gauss double gauss int has_gauss_f @@ -71,6 +80,81 @@ cdef extern from "src/distributions/distributions.h": float random_standard_gamma_f(prng_t *prng_state, float shape) nogil float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil + uint32_t random_uint32(prng_t *prng_state) nogil + int64_t random_positive_int64(prng_t *prng_state) nogil + int32_t random_positive_int32(prng_t *prng_state) nogil + long random_positive_int(prng_t *prng_state) nogil + unsigned long random_uint(prng_t *prng_state) nogil + + double random_normal(prng_t *prng_state, double loc, double scale) nogil + double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil + + double random_gamma(prng_t *prng_state, double shape, double scale) nogil + float random_gamma_float(prng_t *prng_state, float shape, float scale) nogil + + double random_exponential(prng_t *prng_state, double scale) nogil + double random_uniform(prng_t *prng_state, double lower, double range) nogil + double random_beta(prng_t *prng_state, double a, double b) nogil + double random_chisquare(prng_t *prng_state, double df) nogil + double random_f(prng_t *prng_state, double dfnum, double dfden) nogil + double random_standard_cauchy(prng_t *prng_state) nogil + double random_pareto(prng_t *prng_state, double a) nogil + double random_weibull(prng_t *prng_state, double a) nogil + double random_power(prng_t *prng_state, double a) nogil + double random_laplace(prng_t *prng_state, double loc, double scale) nogil + double random_gumbel(prng_t *prng_state, double loc, double scale) nogil + double random_logistic(prng_t *prng_state, double loc, double scale) nogil + double random_lognormal(prng_t *prng_state, double mean, double sigma) nogil + double random_rayleigh(prng_t *prng_state, double mode) nogil + double random_standard_t(prng_t *prng_state, double df) nogil + double random_noncentral_chisquare(prng_t *prng_state, double df, + double nonc) nogil + double random_noncentral_f(prng_t *prng_state, double dfnum, + double dfden, double nonc) nogil + double random_wald(prng_t *prng_state, double mean, double scale) nogil + double random_vonmises(prng_t *prng_state, double mu, double kappa) nogil + double random_triangular(prng_t *prng_state, double left, double mode, + double right) nogil + + long random_poisson(prng_t *prng_state, double lam) nogil + long random_negative_binomial(prng_t *prng_state, double n, double p) nogil + long random_binomial(prng_t *prng_state, double p, long n) nogil + long random_logseries(prng_t *prng_state, double p) nogil + long random_geometric_search(prng_t *prng_state, double p) nogil + long random_geometric_inversion(prng_t *prng_state, double p) nogil + long random_geometric(prng_t *prng_state, double p) nogil + long random_zipf(prng_t *prng_state, double a) nogil + long random_hypergeometric(prng_t *prng_state, long good, long bad, + long sample) nogil + unsigned long random_interval(prng_t *prng_state, unsigned long max) nogil + uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, + uint64_t rng, uint64_t mask) nogil + uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, + uint32_t rng, uint32_t mask, + int *bcnt, uint32_t *buf) nogil + + uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, + uint16_t rng, uint16_t mask, + int *bcnt, uint32_t *buf) nogil + uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, + uint8_t rng, uint8_t mask, + int *bcnt, uint32_t *buf) nogil + np.npy_bool random_buffered_bounded_bool(prng_t *prng_state, np.npy_bool off, + np.npy_bool rng, np.npy_bool mask, + int *bcnt, uint32_t *buf) nogil + void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, + uint64_t rng, np.npy_intp cnt, + uint64_t *out) nogil + void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, + uint32_t rng, np.npy_intp cnt, + uint32_t *out) nogil + void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, + uint16_t rng, np.npy_intp cnt, + uint16_t *out) nogil + void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, + uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil + void random_bounded_bool_fill(prng_t *prng_state, np.npy_bool off, + np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil ctypedef double (*random_double_0)(prng_t *state) nogil ctypedef double (*random_double_1)(prng_t *state, double a) nogil @@ -93,6 +177,7 @@ ctypedef uint32_t (*random_uint_1_i_32)(prng_t *state, uint32_t a) nogil ctypedef int32_t (*random_int_2_i_32)(prng_t *state, int32_t a, int32_t b) nogil ctypedef int64_t (*random_int_2_i)(prng_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) @@ -120,3 +205,24 @@ cdef object disc(void *func, prng_t *state, object size, object lock, cdef object cont_f(void *func, prng_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out) + +cdef object cont_broadcast_3(void *func, prng_t *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, prng_t *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 inline void compute_complex(double *rv_r, double *rv_i, double loc_r, + double loc_i, double var_r, double var_i, double rho) nogil: + cdef double scale_c, scale_i, scale_r + + scale_c = sqrt(1 - rho * rho) + scale_r = sqrt(var_r) + scale_i = sqrt(var_i) + + rv_i[0] = loc_i + scale_i * (rho * rv_r[0] + scale_c * rv_i[0]) + rv_r[0] = loc_r + scale_r * rv_r[0] diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 811824985663..b7a6f5327cfd 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -5,6 +5,18 @@ from common cimport * np.import_array() +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 np.ndarray int_to_array(object value, object name, object bits): len = bits // 64 value = np.asarray(value) diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 0341d9a43c8d..5acc2960f86c 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -44,7 +44,8 @@ cdef extern from "src/dsfmt/dSFMT.h": double dsfmt_next_double(dsfmt_state *state) nogil uint64_t dsfmt_next64(dsfmt_state *state) nogil - uint64_t dsfmt_next32(dsfmt_state *state) nogil + uint32_t dsfmt_next32(dsfmt_state *state) nogil + uint64_t dsfmt_next_raw(dsfmt_state *state) nogil void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) @@ -59,6 +60,9 @@ cdef uint32_t dsfmt_uint32(void *st) nogil: cdef double dsfmt_double(void* st) nogil: return dsfmt_next_double(st) +cdef uint64_t dsfmt_raw(void *st) nogil: + return dsfmt_next_raw(st) + cdef class DSFMT: """ Prototype Core PRNG using dsfmt @@ -79,8 +83,8 @@ cdef class DSFMT: def __init__(self, seed=None): self.rng_state = malloc(sizeof(dsfmt_state)) - self.rng_state.state = malloc(sizeof(dsfmt_t)) - self.rng_state.buffered_uniforms = malloc(DSFMT_N64 * sizeof(double)) + self.rng_state.state = PyArray_malloc_aligned(sizeof(dsfmt_t)) + self.rng_state.buffered_uniforms = PyArray_malloc_aligned(DSFMT_N64 * sizeof(double)) self.rng_state.buffer_loc = DSFMT_N64 self._prng = malloc(sizeof(prng_t)) self._prng.binomial = malloc(sizeof(binomial_t)) @@ -89,6 +93,7 @@ cdef class DSFMT: self._prng.next_uint64 = &dsfmt_uint64 self._prng.next_uint32 = &dsfmt_uint32 self._prng.next_double = &dsfmt_double + self._prng.next_raw = &dsfmt_raw cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) @@ -105,8 +110,8 @@ cdef class DSFMT: self.state) def __dealloc__(self): - free(self.rng_state.state) - free(self.rng_state.buffered_uniforms) + PyArray_free_aligned(self.rng_state.state) + PyArray_free_aligned(self.rng_state.buffered_uniforms) free(self.rng_state) free(self._prng.binomial) free(self._prng) diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 69205245be6f..80a4d0a60018 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -1,7 +1,15 @@ +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +import operator +import warnings + import numpy as np cimport numpy as np +cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from cpython cimport Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles from common cimport * +from libc cimport string from libc.stdlib cimport malloc, free cimport numpy as np @@ -84,6 +92,122 @@ cdef class RandomGenerator: self._prng.gauss_f = value['gauss_f'] self.__core_prng.state = value + def random_uintegers(self, size=None, int bits=64): + """ + random_uintegers(size=None, bits=64) + + Return random unsigned integers + + 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. + bits : int {32, 64} + Size of the unsigned integer to return, either 32 bit or 64 bit. + + Returns + ------- + out : uint or ndarray + Drawn samples. + + Notes + ----- + This method effectively exposes access to the raw underlying + pseudo-random number generator since these all produce unsigned + integers. In practice these are most useful for generating other + random numbers. + + These should not be used to produce bounded random numbers by + simple truncation. + """ + cdef np.npy_intp i, n + cdef np.ndarray array + cdef uint32_t* data32 + cdef uint64_t* data64 + if bits == 64: + if size is None: + with self.lock: + return self._prng.next_uint64(self._prng.state) + array = np.empty(size, np.uint64) + n = np.PyArray_SIZE(array) + data64 = np.PyArray_DATA(array) + with self.lock, nogil: + for i in range(n): + data64[i] = self._prng.next_uint64(self._prng.state) + elif bits == 32: + if size is None: + with self.lock: + return self._prng.next_uint32(self._prng.state) + array = np.empty(size, np.uint32) + n = np.PyArray_SIZE(array) + data32 = np.PyArray_DATA(array) + with self.lock, nogil: + for i in range(n): + data32[i] = self._prng.next_uint32(self._prng.state) + else: + raise ValueError('Unknown value of bits. Must be either 32 or 64.') + + return array + + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying PRNG + + 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. + """ + cdef np.ndarray randoms + cdef uint64_t *randoms_data + cdef Py_ssize_t i, n + + if not output: + if size is None: + with self.lock: + self._prng.next_raw(self._prng.state) + return None + n = np.asarray(size).sum() + with self.lock, nogil: + for i in range(n): + self._prng.next_raw(self._prng.state) + return None + + if size is None: + with self.lock: + return self._prng.next_raw(self._prng.state) + + randoms = np.empty(size, np.uint64) + randoms_data = np.PyArray_DATA(randoms) + n = np.PyArray_SIZE(randoms) + + with self.lock, nogil: + for i in range(n): + randoms_data[i] = self._prng.next_raw(self._prng.state) + return randoms + def random_integer(self, bits=64): #print("In random_integer") if bits == 64: @@ -159,6 +283,101 @@ cdef class RandomGenerator: else: raise TypeError('Unsupported dtype "%s" for random_sample' % 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 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, non-negative. + b : float or array_like of floats + Beta, 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`` 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._prng, 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`. + 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", + http://en.wikipedia.org/wiki/Poisson_process + .. [3] Wikipedia, "Exponential distribution", + http://en.wikipedia.org/wiki/Exponential_distribution + + """ + return cont(&random_exponential, self._prng, 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) @@ -212,12 +431,14 @@ cdef class RandomGenerator: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) - # Complicated, continuous distributions: - def standard_normal(self, size=None, dtype=np.float64, method=u'zig', out=None): + def tomaxint(self, size=None): """ - standard_normal(size=None, dtype='d', method='zig', out=None) + tomaxint(size=None) - Draw samples from a standard Normal distribution (mean=0, stdev=1). + Random integers between 0 and ``sys.maxint``, inclusive. + + Return a sample of uniformly distributed random integers in the interval + [0, ``sys.maxint``]. Parameters ---------- @@ -225,152 +446,3765 @@ cdef class RandomGenerator: 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'. - method : str, optional - Either 'bm' or 'zig'. 'bm' uses the Box-Muller transformations - 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. + out : ndarray + Drawn samples, with shape `size`. + + See Also + -------- + randint : Uniform sampling over a given half-open interval of integers. + random_integers : Uniform sampling over a given closed interval of + integers. Examples -------- - >>> s = np.random.standard_normal(8000) - >>> s - 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) + >>> RS = np.random.mtrand.RandomState() # need a RandomState object + >>> RS.tomaxint((2,2,2)) + array([[[1170048599, 1600360186], + [ 739731006, 1947757578]], + [[1871712945, 752307660], + [1601631370, 1479324245]]]) + >>> import sys + >>> sys.maxint + 2147483647 + >>> RS.tomaxint((2,2,2)) < sys.maxint + array([[[ True, True], + [ True, True]], + [[ True, True], + [ True, True]]], dtype=bool) """ - key = np.dtype(dtype).name - if key == 'float64': - if method == u'zig': - return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) - else: - return double_fill(&random_gauss, self._prng, size, self.lock, out) - elif key == 'float32': - if method == u'zig': - return float_fill(&random_gauss_zig_f, self._prng, size, self.lock, out) - else: - return float_fill(&random_gauss_f, self._prng, size, self.lock, out) - else: - raise TypeError('Unsupported dtype "%s" for standard_normal' % key) + cdef np.npy_intp n + cdef np.ndarray randoms + cdef long *randoms_data + if size is None: + with self.lock: + return random_positive_int(self._prng) - def standard_gamma(self, shape, size=None, dtype=np.float64, method='zig', - out=None): + randoms = np.empty(size, dtype=np.int) + randoms_data = 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._prng) + return randoms + + def randint(self, low, high=None, size=None, dtype=int): """ - standard_gamma(shape, size=None, dtype='d', method='inv', out=None) + randint(low, high=None, size=None, dtype='l') - Draw samples from a standard Gamma distribution. + Return random integers from `low` (inclusive) to `high` (exclusive). - Samples are drawn from a Gamma distribution with specified parameters, - shape (sometimes designated "k") and scale=1. + Return random integers from the "discrete uniform" distribution of + the specified dtype in the "half-open" interval [`low`, `high`). If + `high` is None (the default), then results are from [0, `low`). Parameters ---------- - shape : float or array_like of floats - Parameter, should be > 0. + 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 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. If size is ``None`` (default), - a single value is returned if ``shape`` is a scalar. Otherwise, - ``np.array(shape).size`` samples are drawn. + ``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'. - 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. + 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'. + + .. versionadded:: 1.11.0 Returns ------- - out : ndarray or scalar - Drawn samples from the parameterized standard gamma distribution. + 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. See Also -------- - scipy.stats.gamma : probability density function, distribution or - cumulative density function, etc. + 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. - Notes - ----- - The probability density for the Gamma distribution is + Examples + -------- + >>> np.random.randint(2, size=10) + array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) + >>> np.random.randint(1, size=10) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)}, + Generate a 2 x 4 array of ints between 0 and 4, inclusive: - where :math:`k` is the shape and :math:`\\theta` the scale, - and :math:`\\Gamma` is the Gamma function. + >>> np.random.randint(5, size=(2, 4)) + array([[4, 0, 2, 1], + [3, 2, 2, 0]]) - 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. + Generate a 1 x 3 array with 3 different upper bounds - References + >>> np.random.randint(1, [3, 5, 10]) + array([2, 2, 9]) + + Generate a 1 by 3 array with 3 different lower bounds + + >>> np.random.randint([1, 5, 7], 10) + array([9, 8, 7]) + + 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], + [ 1, 16, 9, 12]], dtype=uint8) + """ + raise NotImplementedError('To be completed') + + def bytes(self, np.npy_intp length): + """ + bytes(length) + + Return random bytes. + + Parameters ---------- - .. [1] Weisstein, Eric W. "Gamma Distribution." From MathWorld--A - Wolfram Web Resource. - http://mathworld.wolfram.com/GammaDistribution.html - .. [2] Wikipedia, "Gamma distribution", - http://en.wikipedia.org/wiki/Gamma_distribution + length : int + Number of random bytes. + + Returns + ------- + out : str + String of length `length`. Examples -------- - Draw samples from the distribution: + >>> np.random.bytes(10) + ' eh\\x85\\x022SZ\\xbf\\xa4' #random - >>> shape, scale = 2., 1. # mean and width - >>> s = np.random.standard_gamma(shape, 1000000) + """ + cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) + return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] - Display the histogram of the samples, along with - the probability density function: - >>> import matplotlib.pyplot as plt - >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, normed=True) - >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ - ... (sps.gamma(shape) * scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') - >>> plt.show() + @cython.wraparound(True) + def choice(self, a, size=None, replace=True, p=None): """ - cdef void *func - if method != u'zig' and method != u'inv': - raise ValueError("method must be either 'inv' or 'zig'") - key = np.dtype(dtype).name - if key == 'float64': - if method == 'inv': - func = &random_standard_gamma + choice(a, size=None, replace=True, p=None) + + Generates a random sample from a given 1-D array + + .. 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) + 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. + 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. + + 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 + probabilities, if a and p have different lengths, or if + replace=False and the sample size is greater than the population + 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]) + >>> #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]) + + 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]) + >>> #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]) + + 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') + + """ + + # 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: + raise ValueError("a must be greater than 0") + elif a.ndim != 1: + raise ValueError("a must be 1-dimensional") + else: + pop_size = a.shape[0] + if pop_size is 0: + raise ValueError("a must be non-empty") + + 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.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED) + pix = 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") + if np.logical_or.reduce(p < 0): + raise ValueError("probabilities are not non-negative") + if abs(kahan_sum(pix, d) - 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_sample(shape) + idx = cdf.searchsorted(uniform_samples, side='right') + idx = np.array(idx, copy=False) # searchsorted returns a scalar else: - func = &random_standard_gamma_zig - return cont(func, self._prng, size, self.lock, 1, - shape, 'shape', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE, - 0.0, '', CONS_NONE, - out) - if key == 'float32': - if method == 'inv': - func = &random_standard_gamma_f + 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 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.int) + flat_found = found.ravel() + while n_uniq < size: + x = self.rand(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: - func = &random_standard_gamma_zig_f - return cont_f(func, self._prng, size, self.lock, - shape, 'shape', CONS_NON_NEGATIVE, - out) + idx = self.permutation(pop_size)[:size] + 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 + + return a[idx] + + + 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 + -------- + randint : Discrete uniform distribution, yielding integers. + random_integers : Discrete uniform distribution over the closed + interval ``[low, high]``. + random_sample : Floats uniformly distributed over ``[0, 1)``. + random : Alias for `random_sample`. + rand : Convenience function that accepts dimensions as input, e.g., + ``rand(2,2)`` would generate a 2-by-2 array of floats, + uniformly distributed over ``[0, 1)``. + + 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.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, normed=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.PyArray_FROM_OTF(low, np.NPY_DOUBLE, np.NPY_ALIGNED) + ahigh = 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._prng, 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.PyArray_EnsureArray(temp) + if not np.all(np.isfinite(arange)): + raise OverflowError('Range exceeds valid bounds') + return cont(&random_uniform, self._prng, size, self.lock, 2, + alow, '', CONS_NONE, + arange, '', CONS_NONE, + 0.0, '', CONS_NONE, + None) + + def rand(self, *args, dtype=np.float64): + """ + rand(d0, d1, ..., dn, dtype='d') + + Random values in a given shape. + + Create an array of the given shape and populate it with + random samples from a uniform distribution + over ``[0, 1)``. + + Parameters + ---------- + d0, d1, ..., dn : int, optional + The dimensions of the returned array, should all be positive. + If no argument is given a single Python float 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'. + + Returns + ------- + out : ndarray, shape ``(d0, d1, ..., dn)`` + Random values. + + See Also + -------- + 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. + + ``dtype`` can only be changed using a keyword argument. + + Examples + -------- + >>> np.random.rand(3,2) + array([[ 0.14022471, 0.96360618], #random + [ 0.37601032, 0.25528411], #random + [ 0.49313049, 0.94909878]]) #random + """ + if len(args) == 0: + return self.random_sample(dtype=dtype) else: - raise TypeError('Unsupported dtype "%s" for standard_gamma' % key) + return self.random_sample(size=args, dtype=dtype) + + def randn(self, *args, method=u'zig', dtype=np.float64): + """ + randn(d0, d1, ..., dn, method='zig', dtype='d') + + 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. + + This is a convenience function. If you want an interface that takes a + tuple as the first argument, use `numpy.random.standard_normal` instead. + + Parameters + ---------- + d0, d1, ..., dn : int, optional + The dimensions of the returned array, should be all positive. + If no argument is given a single Python float is returned. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the default Box-Muller + transformations method. 'zig' uses the much faster Ziggurat + method of Marsaglia and Tsang. + 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'. + + Returns + ------- + Z : ndarray or float + A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from + the standard normal distribution, or a single such float if + no parameters were supplied. + + See Also + -------- + random.standard_normal : Similar, but takes a tuple as its argument. + + Notes + ----- + For random samples from :math:`N(\\mu, \\sigma^2)`, use: + + ``sigma * np.random.randn(...) + mu`` + + Examples + -------- + >>> np.random.randn() + 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 + + """ + if len(args) == 0: + return self.standard_normal(method=method, dtype=dtype) + else: + return self.standard_normal(size=args, method=method, dtype=dtype) + + def random_integers(self, low, high=None, size=None): + """ + random_integers(low, high=None, size=None) + + Random integers of type np.int between `low` and `high`, inclusive. + + 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. + + This function has been deprecated. Use randint instead. + + .. deprecated:: 1.11.0 + + Parameters + ---------- + low : int + Lowest (signed) integer to be drawn from the distribution (unless + ``high=None``, in which case this parameter is the *highest* such + integer). + high : int, optional + If provided, the largest (signed) integer to be drawn from the + distribution (see above for behavior if ``high=None``). + size : int or tuple of ints, optional + Output shape. 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 : 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. + + See Also + -------- + random.randint : Similar to `random_integers`, only for the half-open + interval [`low`, `high`), and 0 is the lowest value if `high` is + omitted. + + Notes + ----- + To sample from N evenly spaced floating-point numbers between a and b, + use:: + + a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) + + Examples + -------- + >>> np.random.random_integers(5) + 4 + >>> type(np.random.random_integers(5)) + + >>> np.random.random_integers(5, size=(3.,2.)) + array([[5, 4], + [3, 3], + [4, 5]]) + + Choose five random numbers from the set of five evenly-spaced + numbers between 0 and 2.5, inclusive (*i.e.*, from the set + :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 ]) + + Roll two six sided dice 1000 times and sum the results: + + >>> d1 = np.random.random_integers(1, 6, 1000) + >>> d2 = np.random.random_integers(1, 6, 1000) + >>> dsums = d1 + d2 + + Display results as a histogram: + + >>> import matplotlib.pyplot as plt + >>> count, bins, ignored = plt.hist(dsums, 11, normed=True) + >>> plt.show() + + """ + if high is None: + warnings.warn(("This function is deprecated. Please call " + "randint(1, {low} + 1) instead".format(low=low)), + DeprecationWarning) + high = low + low = 1 + + 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') + + + + # Complicated, continuous distributions: + def standard_normal(self, size=None, dtype=np.float64, method=u'zig', out=None): + """ + standard_normal(size=None, dtype='d', method='zig', 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'. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the Box-Muller transformations + 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 + -------- + >>> s = np.random.standard_normal(8000) + >>> s + 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) + + """ + key = np.dtype(dtype).name + if key == 'float64': + if method == u'zig': + return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) + else: + return double_fill(&random_gauss, self._prng, size, self.lock, out) + elif key == 'float32': + if method == u'zig': + return float_fill(&random_gauss_zig_f, self._prng, size, self.lock, out) + else: + return float_fill(&random_gauss_f, self._prng, 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, method=u'zig'): + """ + normal(loc=0.0, scale=1.0, size=None, method='zig') + + 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. + 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. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations + method. 'zig' uses the much faster Ziggurat method of Marsaglia and Tsang. + + + 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 + `numpy.random.normal` is more likely to return samples lying close to + the mean, rather than those far away. + + References + ---------- + .. [1] Wikipedia, "Normal distribution", + http://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.normal(mu, sigma, 1000) + + Verify the mean and the variance: + + >>> abs(mu - np.mean(s)) < 0.01 + True + + >>> abs(sigma - np.std(s, ddof=1)) < 0.01 + True + + Display the histogram of the samples, along with + the probability density function: + + >>> import matplotlib.pyplot as plt + >>> count, bins, ignored = plt.hist(s, 30, normed=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() + + """ + if method == 'bm': + return cont(&random_normal, self._prng, size, self.lock, 2, + loc, '', CONS_NONE, + scale, 'scale', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + None) + else: + return cont(&random_normal_zig, self._prng, size, self.lock, 2, + loc, '', CONS_NONE, + scale, 'scale', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + None) + + def complex_normal(self, loc=0.0, gamma=1.0, relation=0.0, size=None, + method=u'zig'): + """ + complex_normal(loc=0.0, gamma=1.0, relation=0.0, size=None, method='zig') + + Draw random samples from a complex normal (Gaussian) distribution. + + Parameters + ---------- + loc : complex or array_like of complex + Mean of the distribution. + gamma : float, complex or array_like of float or complex + Variance of the distribution + relation : float, complex or array_like of float or complex + Relation between the two component normals + 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``, ``gamma`` and ``relation`` + are all scalars. Otherwise, + ``np.broadcast(loc, gamma, relation).size`` samples are drawn. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the default Box-Muller + transformations method. 'zig' uses the much faster Ziggurat + method of Marsaglia and Tsang. + + Returns + ------- + out : ndarray or scalar + Drawn samples from the parameterized complex normal distribution. + + See Also + -------- + numpy.random.normal : random values from a real-valued normal + distribution + + Notes + ----- + **EXPERIMENTAL** Not part of official NumPy RandomState, may change until + formal release on PyPi. + + Complex normals are generated from a bivariate normal where the + variance of the real component is 0.5 Re(gamma + relation), the + variance of the imaginary component is 0.5 Re(gamma - relation), and + the covariance between the two is 0.5 Im(relation). The implied + covariance matrix must be positive semi-definite and so both variances + must be zero and the covariance must be weakly smaller than the + product of the two standard deviations. + + References + ---------- + .. [1] Wikipedia, "Complex normal distribution", + https://en.wikipedia.org/wiki/Complex_normal_distribution + .. [2] Leigh J. Halliwell, "Complex Random Variables" in "Casualty + Actuarial Society E-Forum", Fall 2015. + + Examples + -------- + Draw samples from the distribution: + + >>> s = np.random.complex_normal(size=1000) + """ + if method != u'zig' and method != u'bm': + raise ValueError("method must be either 'bm' or 'zig'") + cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho + cdef double *randoms_data + cdef double fgamma_r, fgamma_i, frelation_r, frelation_i, frho, fvar_r , fvar_i, \ + floc_r, floc_i, f_real, f_imag, i_r_scale, r_scale, i_scale, f_rho + cdef np.npy_intp i, j, n + cdef np.broadcast it + + oloc = np.PyArray_FROM_OTF(loc, np.NPY_COMPLEX128, np.NPY_ALIGNED) + ogamma = np.PyArray_FROM_OTF(gamma, np.NPY_COMPLEX128, np.NPY_ALIGNED) + orelation = np.PyArray_FROM_OTF(relation, np.NPY_COMPLEX128, np.NPY_ALIGNED) + + if np.PyArray_NDIM(ogamma) == np.PyArray_NDIM(orelation) == np.PyArray_NDIM(oloc) == 0: + floc_r = PyComplex_RealAsDouble(loc) + floc_i = PyComplex_ImagAsDouble(loc) + fgamma_r = PyComplex_RealAsDouble(gamma) + fgamma_i = PyComplex_ImagAsDouble(gamma) + frelation_r = PyComplex_RealAsDouble(relation) + frelation_i = 0.5 * PyComplex_ImagAsDouble(relation) + + fvar_r = 0.5 * (fgamma_r + frelation_r) + fvar_i = 0.5 * (fgamma_r - frelation_r) + if fgamma_i != 0: + raise ValueError('Im(gamma) != 0') + if fvar_i < 0: + raise ValueError('Re(gamma - relation) < 0') + if fvar_r < 0: + raise ValueError('Re(gamma + relation) < 0') + f_rho = 0.0 + if fvar_i > 0 and fvar_r > 0: + f_rho = frelation_i / sqrt(fvar_i * fvar_r) + if f_rho > 1.0 or f_rho < -1.0: + raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation** 2)') + + if size is None: + if method == u'zig': + f_real = random_gauss_zig(self._prng) + f_imag = random_gauss_zig(self._prng) + else: + f_real = random_gauss(self._prng) + f_imag = random_gauss(self._prng) + + compute_complex(&f_real, &f_imag, floc_r, floc_i, fvar_r, fvar_i, f_rho) + return PyComplex_FromDoubles(f_real, f_imag) + + randoms = np.empty(size, np.complex128) + randoms_data = np.PyArray_DATA(randoms) + n = np.PyArray_SIZE(randoms) + + i_r_scale = sqrt(1 - f_rho * f_rho) + r_scale = sqrt(fvar_r) + i_scale = sqrt(fvar_i) + j = 0 + with self.lock, nogil: + if method == u'zig': + for i in range(n): + f_real = random_gauss_zig(self._prng) + f_imag = random_gauss_zig(self._prng) + randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) + randoms_data[j] = floc_r + r_scale * f_real + j += 2 + else: + for i in range(n): + f_real = random_gauss(self._prng) + f_imag = random_gauss(self._prng) + randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) + randoms_data[j] = floc_r + r_scale * f_real + j += 2 + + return randoms + + gpc = ogamma + orelation + gmc = ogamma - orelation + v_real = (0.5 * np.real(gpc)) + if np.any(np.less(v_real, 0)): + raise ValueError('Re(gamma + relation) < 0') + v_imag = (0.5 * np.real(gmc)) + if np.any(np.less(v_imag, 0)): + raise ValueError('Re(gamma - relation) < 0') + if np.any(np.not_equal(np.imag(ogamma), 0)): + raise ValueError('Im(gamma) != 0') + + cov = 0.5 * np.imag(orelation) + rho = np.zeros_like(cov) + idx = (v_real.flat > 0) & (v_imag.flat > 0) + rho.flat[idx] = cov.flat[idx] / np.sqrt(v_real.flat[idx] * v_imag.flat[idx]) + if np.any(cov.flat[~idx] != 0) or np.any(np.abs(rho) > 1): + raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation ** 2)') + + if size is not None: + randoms = np.empty(size, np.complex128) + else: + it = np.PyArray_MultiIterNew4(oloc, v_real, v_imag, rho) + randoms = np.empty(it.shape, np.complex128) + + randoms_data = np.PyArray_DATA(randoms) + n = np.PyArray_SIZE(randoms) + + it = np.PyArray_MultiIterNew5(randoms, oloc, v_real, v_imag, rho) + with self.lock, nogil: + if method == u'zig': + for i in range( 2 * n): + randoms_data[i] = random_gauss_zig(self._prng) + else: + for i in range( 2 * n): + randoms_data[i] = random_gauss(self._prng) + with nogil: + j = 0 + for i in range(n): + floc_r= (np.PyArray_MultiIter_DATA(it, 1))[0] + floc_i= (np.PyArray_MultiIter_DATA(it, 1))[1] + fvar_r = (np.PyArray_MultiIter_DATA(it, 2))[0] + fvar_i = (np.PyArray_MultiIter_DATA(it, 3))[0] + f_rho = (np.PyArray_MultiIter_DATA(it, 4))[0] + compute_complex(&randoms_data[j], &randoms_data[j+1], floc_r, floc_i, fvar_r, fvar_i, f_rho) + j += 2 + np.PyArray_MultiIter_NEXT(it) + + return randoms + + def standard_gamma(self, shape, size=None, dtype=np.float64, method=u'zig', + out=None): + """ + standard_gamma(shape, size=None, dtype='d', method='inv', 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, should 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 ``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'. + 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 : 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", + http://en.wikipedia.org/wiki/Gamma_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> shape, scale = 2., 1. # mean and width + >>> s = np.random.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 + >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ + ... (sps.gamma(shape) * scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + """ + cdef void *func + if method != u'zig' and method != u'inv': + raise ValueError("method must be either 'inv' or 'zig'") + key = np.dtype(dtype).name + if key == 'float64': + if method == 'inv': + func = &random_standard_gamma + else: + func = &random_standard_gamma_zig + return cont(func, self._prng, size, self.lock, 1, + shape, 'shape', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE, + out) + if key == 'float32': + if method == 'inv': + func = &random_standard_gamma_f + else: + func = &random_standard_gamma_zig_f + return cont_f(func, self._prng, 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. Should be greater than zero. + scale : float or array_like of floats, optional + The scale of the gamma distribution. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Gamma_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> shape, scale = 2., 2. # mean and dispersion + >>> s = np.random.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 + >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> y = bins**(shape-1)*(np.exp(-bins/scale) / + ... (sps.gamma(shape)*scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + + """ + return cont(&random_gamma, self._prng, 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 should 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 : int or array_like of ints + Degrees of freedom in numerator. Should be greater than zero. + dfden : int or array_like of ints + Degrees of freedom in denominator. Should be greater than zero. + 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", + http://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.f(dfnum, dfden, 1000) + + The lower bound for the top 1% of the samples is : + + >>> sort(s)[-10] + 7.61988120985 + + 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._prng, 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 : int or array_like of ints + Parameter, should be > 1. + dfden : int or array_like of ints + Parameter, should be > 1. + nonc : float or array_like of floats + Parameter, should 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", + http://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. + + >>> dfnum = 3 # between group deg of freedom + >>> dfden = 20 # within groups degrees of freedom + >>> nonc = 3.0 + >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> NF = np.histogram(nc_vals, bins=50, normed=True) + >>> c_vals = np.random.f(dfnum, dfden, 1000000) + >>> F = np.histogram(c_vals, bins=50, normed=True) + >>> plt.plot(F[1][1:], F[0]) + >>> plt.plot(NF[1][1:], NF[0]) + >>> plt.show() + + """ + return cont(&random_noncentral_f, self._prng, 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 : int or array_like of ints + Number of degrees of freedom. + 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" + http://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm + + Examples + -------- + >>> np.random.chisquare(2,4) + array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) + + """ + return cont(&random_chisquare, self._prng, 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 generalisation of + the :math:`\\chi^2` distribution. + + Parameters + ---------- + df : int or array_like of ints + Degrees of freedom, should be > 0 as of NumPy 1.10.0, + should be > 1 for earlier versions. + nonc : float or array_like of floats + Non-centrality, should 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. + + 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-square distribution" + http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution + + Examples + -------- + Draw values from the distribution and plot the histogram + + >>> import matplotlib.pyplot as plt + >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), + ... bins=200, normed=True) + >>> plt.show() + + Draw values from a noncentral chisquare with very small noncentrality, + and compare to a chisquare. + + >>> plt.figure() + >>> values = plt.hist(np.random.noncentral_chisquare(3, .0000001, 100000), + ... bins=np.arange(0., 25, .1), normed=True) + >>> values2 = plt.hist(np.random.chisquare(3, 100000), + ... bins=np.arange(0., 25, .1), normed=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(np.random.noncentral_chisquare(3, 20, 100000), + ... bins=200, normed=True) + >>> plt.show() + + """ + return cont(&random_noncentral_chisquare, self._prng, 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", + http://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" + http://en.wikipedia.org/wiki/Cauchy_distribution + + Examples + -------- + Draw samples and plot the distribution: + + >>> s = np.random.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._prng, 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 : int or array_like of ints + Degrees of freedom, should 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" + http://en.wikipedia.org/wiki/Student's_t-distribution + + Examples + -------- + From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 + women in 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.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, normed=True) + + For a one-sided t-test, how far out in the distribution does the t + statistic appear? + + >>> np.sum(s=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.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 + >>> plt.hist(s, 50, normed=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') + >>> plt.show() + + """ + return cont(&random_vonmises, self._prng, 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. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Pareto_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> a, m = 3., 2. # shape and mode + >>> s = (np.random.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, normed=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._prng, 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 of the distribution. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Weibull_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> a = 5. # shape + >>> s = np.random.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(np.random.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._prng, 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. Should be greater than zero. + 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. + http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf + + Examples + -------- + Draw samples from the distribution: + + >>> a = 5. # shape + >>> samples = 1000 + >>> s = np.random.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 + >>> rvs = np.random.power(5, 1000000) + >>> rvsp = np.random.pareto(5, 1000000) + >>> xx = np.linspace(0,1,100) + >>> powpdf = stats.powerlaw.pdf(xx,5) + + >>> plt.figure() + >>> plt.hist(rvs, bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('np.random.power(5)') + + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of 1 + np.random.pareto(5)') + + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of stats.pareto(5)') + + """ + return cont(&random_power, self._prng, 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. + 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", + http://en.wikipedia.org/wiki/Laplace_distribution + + Examples + -------- + Draw samples from the distribution + + >>> loc, scale = 0., 1. + >>> s = np.random.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, normed=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._prng, 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. + 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: + + >>> mu, beta = 0, 0.1 # location and scale + >>> s = np.random.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, normed=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 = np.random.normal(mu, beta, 1000) + ... means.append(a.mean()) + ... maxima.append(a.max()) + >>> count, bins, ignored = plt.hist(maxima, 30, normed=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._prng, 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. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Logistic_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> loc, scale = 10, 1 + >>> s = np.random.logistic(loc, scale, 10000) + >>> count, bins, ignored = plt.hist(s, bins=50) + + # 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()) + >>> plt.show() + + """ + return cont(&random_logistic, self._prng, size, self.lock, 2, + loc, 'loc', CONS_NONE, + scale, 'scale', CONS_POSITIVE, + 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. Should + be greater than zero. 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. + http://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: + + >>> mu, sigma = 3., 1. # mean and standard deviation + >>> s = np.random.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, normed=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. + >>> b = [] + >>> for i in range(1000): + ... a = 10. + np.random.random(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, normed=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._prng, 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. Should be >= 0. 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," + http://www.brighton-webs.co.uk/distributions/rayleigh.asp + .. [2] Wikipedia, "Rayleigh distribution" + http://en.wikipedia.org/wiki/Rayleigh_distribution + + Examples + -------- + Draw values from the distribution and plot the histogram + + >>> values = hist(np.random.rayleigh(3, 100000), bins=200, normed=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 = np.random.rayleigh(modevalue, 1000000) + + The percentage of waves larger than 3 meters is: + + >>> 100.*sum(s>3)/1000000. + 0.087300000000000003 + + """ + return cont(&random_rayleigh, self._prng, 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, should be > 0. + scale : float or array_like of floats + Scale parameter, should 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, + http://www.brighton-webs.co.uk/distributions/wald.asp + .. [2] Chhikara, Raj S., and Folks, J. Leroy, "The Inverse Gaussian + Distribution: Theory : Methodology, and Applications", CRC Press, + 1988. + .. [3] Wikipedia, "Wald distribution" + http://en.wikipedia.org/wiki/Wald_distribution + + Examples + -------- + Draw values from the distribution and plot the histogram: + + >>> import matplotlib.pyplot as plt + >>> h = plt.hist(np.random.wald(3, 2, 100000), bins=200, normed=True) + >>> plt.show() + + """ + return cont(&random_wald, self._prng, 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 should fulfill the condition ``left <= mode <= right``. + right : float or array_like of floats + Upper limit, should 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" + http://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.triangular(-3, 0, 8, 100000), bins=200, + ... normed=True) + >>> plt.show() + + """ + cdef bint is_scalar = True + cdef double fleft, fmode, fright + cdef np.ndarray oleft, omode, oright + + oleft = np.PyArray_FROM_OTF(left, np.NPY_DOUBLE, np.NPY_ALIGNED) + omode = np.PyArray_FROM_OTF(mode, np.NPY_DOUBLE, np.NPY_ALIGNED) + oright = 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._prng, 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._prng, 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", + http://en.wikipedia.org/wiki/Binomial_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> n, p = 10, .5 # number of trials, probability of each trial + >>> s = np.random.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(np.random.binomial(9, 0.1, 20000) == 0)/20000. + # answer = 0.38885, or 38%. + + """ + return disc(&random_binomial, self._prng, size, self.lock, 1, 1, + p, 'p', CONS_BOUNDED_0_1_NOTNAN, + n, 'n', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE) + + 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` trials and `p` probability of success where `n` is an + integer > 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. + 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 trials it took to + achieve n - 1 successes, N - (n - 1) failures, and a success on the, + (N + n)th trial. + + Notes + ----- + The probability density for the negative binomial distribution is + + .. math:: P(N;n,p) = \\binom{N+n-1}{n-1}p^{n}(1-p)^{N}, + + where :math:`n-1` is the number of successes, :math:`p` is the + probability of success, and :math:`N+n-1` is the number of trials. + The negative binomial distribution gives the probability of n-1 + successes and N failures in N+n-1 trials, and success on the (N+n)th + 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", + http://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.negative_binomial(1, 0.1, 100000) + >>> for i in range(1, 11): + ... probability = sum(s= 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 long 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", + http://en.wikipedia.org/wiki/Poisson_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> import numpy as np + >>> s = np.random.poisson(5, 10000) + + Display histogram of the sample: + + >>> import matplotlib.pyplot as plt + >>> count, bins, ignored = plt.hist(s, 14, normed=True) + >>> plt.show() + + Draw each 100 values for lambda 100 and 500: + + >>> s = np.random.poisson(lam=(100., 500.), size=(100, 2)) + + """ + return disc(&random_poisson, self._prng, 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. Should 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.zipf(a, 1000) + + Display the histogram of the samples, along with + the probability density function: + + >>> import matplotlib.pyplot as plt + >>> from scipy import special + + Truncate s values at 50 so plot is interesting: + + >>> count, bins, ignored = plt.hist(s[s<50], 50, normed=True) + >>> x = np.arange(1., 50.) + >>> y = x**(-a) / special.zetac(a) + >>> plt.plot(x, y/max(y), linewidth=2, color='r') + >>> plt.show() + + """ + return disc(&random_zipf, self._prng, 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.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._prng, size, self.lock, 1, 0, + p, 'p', CONS_BOUNDED_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. + nbad : int or array_like of ints + Number of ways to make a bad selection. Must be nonnegative. + nsample : int or array_like of ints + Number of items sampled. Must be at least 1 and at most + ``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. + + 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{m}{n}\\binom{N-m}{n-x}}{\\binom{N}{n}}, + + where :math:`0 \\le x \\le m` and :math:`n+m-N \\le x \\le n` + + for P(x) the probability of x successes, n = ngood, m = nbad, and + N = number of samples. + + Consider an urn with black and white marbles in it, ngood of them + 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. + + 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", + http://en.wikipedia.org/wiki/Hypergeometric_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> ngood, nbad, nsamp = 100, 2, 10 + # number of good, number of bad, and number of samples + >>> s = np.random.hypergeometric(ngood, nbad, nsamp, 1000) + >>> 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 = np.random.hypergeometric(15, 15, 15, 100000) + >>> sum(s>=12)/100000. + sum(s<=3)/100000. + # answer = 0.003 ... pretty unlikely! + + """ + cdef bint is_scalar = True + cdef np.ndarray ongood, onbad, onsample + cdef long lngood, lnbad, lnsample + + ongood = np.PyArray_FROM_OTF(ngood, np.NPY_LONG, np.NPY_ALIGNED) + onbad = np.PyArray_FROM_OTF(nbad, np.NPY_LONG, np.NPY_ALIGNED) + onsample = 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 = 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") + if lngood + lnbad < lnsample: + raise ValueError("ngood + nbad < nsample") + return disc(&random_hypergeometric, self._prng, size, self.lock, 0, 3, + lngood, 'ngood', CONS_NON_NEGATIVE, + lnbad, 'nbad', CONS_NON_NEGATIVE, + lnsample, 'nsample', CONS_GTE_1) + + if np.any(np.less(np.add(ongood, onbad),onsample)): + raise ValueError("ngood + nbad < nsample") + return discrete_broadcast_iii(&random_hypergeometric, self._prng, size, self.lock, + ongood, 'ngood', CONS_NON_NEGATIVE, + onbad, nbad, CONS_NON_NEGATIVE, + onsample, 'nsample', CONS_GTE_1) + + 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 density 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", + http://en.wikipedia.org/wiki/Logarithmic_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> a = .6 + >>> s = np.random.logseries(a, 10000) + >>> count, bins, ignored = plt.hist(s) + + # plot against distribution + + >>> def logseries(k, p): + ... return -p**k/(k*log(1-p)) + >>> plt.plot(bins, logseries(bins, a)*count.max()/ + logseries(bins, a).max(), 'r') + >>> plt.show() + + """ + return disc(&random_logseries, self._prng, 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, method=u'zig'): + """ + multivariate_normal(self, mean, cov, size=None, check_valid='warn', + tol=1e-8, method='zig') + + 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. + method : str, optional + Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations + method. 'zig' uses the much faster Ziggurat method of Marsaglia and Tsang. + + 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.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.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] + + """ + 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, method=method).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 + # symmetrical and the singular value of the corresponding row is + # not zero. We continue to use the SVD rather than Cholesky in + # order to preserve current outputs. Note that symmetry has not + # been checked. + + (u, s, v) = svd(cov) + + 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, 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 + 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 + 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 + 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: + + >>> np.random.multinomial(20, [1/6.]*6, size=1) + array([[4, 1, 7, 5, 2, 1]]) + + 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], + [2, 4, 3, 4, 0, 7]]) + + 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. + + 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]) + + 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: + + >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + array([38, 62]) + + not like: + + >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG + array([100, 0]) + + """ + cdef np.npy_intp d + cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" + cdef double *pix + cdef long *mnix + cdef np.npy_intp i, j, dn, sz + cdef double Sum + + d = len(pvals) + parr = np.PyArray_FROM_OTF(pvals, np.NPY_DOUBLE, np.NPY_ALIGNED) + pix = np.PyArray_DATA(parr) + + if kahan_sum(pix, d-1) > (1.0 + 1e-12): + raise ValueError("sum(pvals[:-1]) > 1.0") + + if size is None: + shape = (d,) + else: + try: + shape = (operator.index(size), d) + except: + shape = tuple(size) + (d,) + + multin = np.zeros(shape, dtype=np.int) + mnarr = multin + mnix = np.PyArray_DATA(mnarr) + sz = np.PyArray_SIZE(mnarr) + + with self.lock, nogil: + i = 0 + while i < sz: + Sum = 1.0 + dn = n + for j in range(d-1): + mnix[i+j] = random_binomial(self._prng, pix[j]/Sum, dn) + dn = dn - mnix[i+j] + if dn <= 0: + break + Sum = Sum - pix[j] + if dn > 0: + mnix[i+d-1] = dn + + i = i + d + + return multin + + 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. Dirichlet pdf is the conjugate + prior of a multinomial 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). + + Notes + ----- + .. math:: X \\approx \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i} + + 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. + + References + ---------- + .. [1] David McKay, "Information Theory, Inference and Learning + Algorithms," chapter 23, + http://www.inference.phy.cam.ac.uk/mackay/ + .. [2] Wikipedia, "Dirichlet distribution", + http://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.dirichlet((10, 5, 3), 20).transpose() + + >>> 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 + cdef np.npy_intp totsize + cdef np.ndarray alpha_arr, val_arr + cdef double *alpha_data + cdef double *val_data + cdef np.npy_intp i, j + cdef double acc, invacc + + k = len(alpha) + alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) + if np.any(np.less_equal(alpha_arr, 0)): + raise ValueError('alpha <= 0') + alpha_data = 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 = diric + val_data= 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(self._prng, 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 + -------- + >>> arr = np.arange(10) + >>> np.random.shuffle(arr) + >>> arr + [1 7 5 2 9 4 3 6 0 8] + + 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], + [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 = 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 = 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, 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 > 1 and x.size: + # Multidimensional ndarrays require a bounce buffer. + buf = np.empty_like(x[0]) + with self.lock: + for i in reversed(range(1, n)): + j = random_interval(self._prng, i) + if i == j : continue # i == j is not needed and memcpy is undefined. + 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._prng, i) + x[i], x[j] = x[j], x[i] + + 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 = random_interval(self._prng, i) + string.memcpy(buf, data + j * stride, itemsize) + string.memcpy(data + j * stride, data + i * stride, itemsize) + string.memcpy(data + i * stride, buf, itemsize) + + 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 + -------- + >>> np.random.permutation(10) + array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) + + >>> np.random.permutation([1, 4, 9, 12, 15]) + array([15, 1, 9, 4, 12]) + + >>> arr = np.arange(9).reshape((3, 3)) + >>> np.random.permutation(arr) + array([[6, 7, 8], + [0, 1, 2], + [3, 4, 5]]) + + """ + if isinstance(x, (int, long, np.integer)): + arr = np.arange(x) + else: + arr = np.array(x) + self.shuffle(arr) + return arr diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 5c09709921e2..230a29a74b5a 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -64,6 +64,7 @@ cdef class MT19937: self._prng.next_uint64 = &mt19937_uint64 self._prng.next_uint32 = &mt19937_uint32 self._prng.next_double = &mt19937_double + self._prng.next_raw = &mt19937_uint64 cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index ce9e47be9e73..2765334cf050 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -82,6 +82,7 @@ cdef class Philox: self._prng.next_uint64 = &philox_uint64 self._prng.next_uint32 = &philox_uint32 self._prng.next_double = &philox_double + self._prng.next_raw = &philox_uint64 cdef const char *name = 'CorePRNG' self.capsule = PyCapsule_New( self._prng, name, NULL) diff --git a/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.c b/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.c new file mode 100644 index 000000000000..6e8192cfbeed --- /dev/null +++ b/_randomgen/core_prng/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/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.h b/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.h new file mode 100644 index 000000000000..55716525338b --- /dev/null +++ b/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.h @@ -0,0 +1,49 @@ +#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); +} \ No newline at end of file diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 40b24472747b..3edc59261041 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -11,6 +11,10 @@ uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } +static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { + return prng_state->next_uint64(prng_state->state); +} + float random_sample_f(prng_t *prng_state) { return next_float(prng_state); } double random_sample(prng_t *prng_state) { @@ -392,3 +396,992 @@ double random_standard_gamma_zig(prng_t *prng_state, double shape) { float random_standard_gamma_zig_f(prng_t *prng_state, float shape) { return standard_gamma_zig_f(prng_state, shape); } + +int64_t random_positive_int64(prng_t *prng_state) { + return prng_state->next_uint64(prng_state->state) >> 1; +} + +int32_t random_positive_int32(prng_t *prng_state) { + return prng_state->next_uint32(prng_state->state) >> 1; +} + +long random_positive_int(prng_t *prng_state) { +#if ULONG_MAX <= 0xffffffffUL + return (long)(prng_state->next_uint32(prng_state->state) >> 1); +#else + return (long)(prng_state->next_uint64(prng_state->state) >> 1); +#endif +} + +unsigned long random_uint(prng_t *prng_state) { +#if ULONG_MAX <= 0xffffffffUL + return prng_state->next_uint32(prng_state->state); +#else + return prng_state->next_uint64(prng_state->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. + */ +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 random_normal(prng_t *prng_state, double loc, double scale) { + return loc + scale * random_gauss(prng_state); +} + +double random_normal_zig(prng_t *prng_state, double loc, double scale) { + return loc + scale * random_gauss_zig(prng_state); +} + +double random_exponential(prng_t *prng_state, double scale) { + return scale * random_standard_exponential(prng_state); +} + +double random_uniform(prng_t *prng_state, double lower, double range) { + return lower + range * random_sample(prng_state); +} + +double random_gamma(prng_t *prng_state, double shape, double scale) { + return scale * random_standard_gamma(prng_state, shape); +} + +float random_gamma_float(prng_t *prng_state, float shape, float scale) { + return scale * random_standard_gamma_f(prng_state, shape); +} + +double random_beta(prng_t *prng_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 = random_sample(prng_state); + V = random_sample(prng_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 = random_standard_gamma(prng_state, a); + Gb = random_standard_gamma(prng_state, b); + return Ga / (Ga + Gb); + } +} + +double random_chisquare(prng_t *prng_state, double df) { + return 2.0 * random_standard_gamma(prng_state, df / 2.0); +} + +double random_f(prng_t *prng_state, double dfnum, double dfden) { + return ((random_chisquare(prng_state, dfnum) * dfden) / + (random_chisquare(prng_state, dfden) * dfnum)); +} + +double random_standard_cauchy(prng_t *prng_state) { + return random_gauss(prng_state) / random_gauss(prng_state); +} + +double random_pareto(prng_t *prng_state, double a) { + return exp(random_standard_exponential(prng_state) / a) - 1; +} + +double random_weibull(prng_t *prng_state, double a) { + return pow(random_standard_exponential(prng_state), 1. / a); +} + +double random_power(prng_t *prng_state, double a) { + return pow(1 - exp(-random_standard_exponential(prng_state)), 1. / a); +} + +double random_laplace(prng_t *prng_state, double loc, double scale) { + double U; + + U = random_sample(prng_state); + if (U < 0.5) { + U = loc + scale * log(U + U); + } else { + U = loc - scale * log(2.0 - U - U); + } + return U; +} + +double random_gumbel(prng_t *prng_state, double loc, double scale) { + double U; + + U = 1.0 - random_sample(prng_state); + return loc - scale * log(-log(U)); +} + +double random_logistic(prng_t *prng_state, double loc, double scale) { + double U; + + U = random_sample(prng_state); + return loc + scale * log(U / (1.0 - U)); +} + +double random_lognormal(prng_t *prng_state, double mean, double sigma) { + return exp(random_normal(prng_state, mean, sigma)); +} + +double random_rayleigh(prng_t *prng_state, double mode) { + return mode * sqrt(-2.0 * log(1.0 - random_sample(prng_state))); +} + +double random_standard_t(prng_t *prng_state, double df) { + double num, denom; + + num = random_gauss(prng_state); + denom = random_standard_gamma(prng_state, df / 2); + return sqrt(df / 2) * num / sqrt(denom); +} + +static long random_poisson_mult(prng_t *prng_state, double lam) { + long X; + double prod, U, enlam; + + enlam = exp(-lam); + X = 0; + prod = 1.0; + while (1) { + U = random_sample(prng_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 long random_poisson_ptrs(prng_t *prng_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 = random_sample(prng_state) - 0.5; + V = random_sample(prng_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 random_poisson(prng_t *prng_state, double lam) { + if (lam >= 10) { + return random_poisson_ptrs(prng_state, lam); + } else if (lam == 0) { + return 0; + } else { + return random_poisson_mult(prng_state, lam); + } +} + +long random_negative_binomial(prng_t *prng_state, double n, double p) { + double Y = random_gamma(prng_state, n, (1 - p) / p); + return random_poisson(prng_state, Y); +} + +long random_binomial_btpe(prng_t *prng_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 (!(prng_state->binomial->has_binomial) || + (prng_state->binomial->nsave != n) || + (prng_state->binomial->psave != p)) { + /* initialize */ + prng_state->binomial->nsave = n; + prng_state->binomial->psave = p; + prng_state->binomial->has_binomial = 1; + prng_state->binomial->r = r = min(p, 1.0 - p); + prng_state->binomial->q = q = 1.0 - r; + prng_state->binomial->fm = fm = n * r + r; + prng_state->binomial->m = m = (long)floor(prng_state->binomial->fm); + prng_state->binomial->p1 = p1 = + floor(2.195 * sqrt(n * r * q) - 4.6 * q) + 0.5; + prng_state->binomial->xm = xm = m + 0.5; + prng_state->binomial->xl = xl = xm - p1; + prng_state->binomial->xr = xr = xm + p1; + prng_state->binomial->c = c = 0.134 + 20.5 / (15.3 + m); + a = (fm - xl) / (fm - xl * r); + prng_state->binomial->laml = laml = a * (1.0 + a / 2.0); + a = (xr - fm) / (xr * q); + prng_state->binomial->lamr = lamr = a * (1.0 + a / 2.0); + prng_state->binomial->p2 = p2 = p1 * (1.0 + 2.0 * c); + prng_state->binomial->p3 = p3 = p2 + c / laml; + prng_state->binomial->p4 = p4 = p3 + c / lamr; + } else { + r = prng_state->binomial->r; + q = prng_state->binomial->q; + fm = prng_state->binomial->fm; + m = prng_state->binomial->m; + p1 = prng_state->binomial->p1; + xm = prng_state->binomial->xm; + xl = prng_state->binomial->xl; + xr = prng_state->binomial->xr; + c = prng_state->binomial->c; + laml = prng_state->binomial->laml; + lamr = prng_state->binomial->lamr; + p2 = prng_state->binomial->p2; + p3 = prng_state->binomial->p3; + p4 = prng_state->binomial->p4; + } + +/* sigh ... */ +Step10: + nrq = n * r * q; + u = random_sample(prng_state) * p4; + v = random_sample(prng_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); + if (y < 0) + goto Step10; + v = v * (u - p2) * laml; + goto Step50; + +Step40: + y = (long)floor(xr - log(v) / lamr); + if (y > n) + 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 random_binomial_inversion(prng_t *prng_state, long n, double p) { + double q, qn, np, px, U; + long X, bound; + + if (!(prng_state->binomial->has_binomial) || + (prng_state->binomial->nsave != n) || + (prng_state->binomial->psave != p)) { + prng_state->binomial->nsave = n; + prng_state->binomial->psave = p; + prng_state->binomial->has_binomial = 1; + prng_state->binomial->q = q = 1.0 - p; + prng_state->binomial->r = qn = exp(n * log(q)); + prng_state->binomial->c = np = n * p; + prng_state->binomial->m = bound = + (long)min(n, np + 10.0 * sqrt(np * q + 1)); + } else { + q = prng_state->binomial->q; + qn = prng_state->binomial->r; + np = prng_state->binomial->c; + bound = prng_state->binomial->m; + } + X = 0; + px = qn; + U = random_sample(prng_state); + while (U > px) { + X++; + if (X > bound) { + X = 0; + px = qn; + U = random_sample(prng_state); + } else { + U -= px; + px = ((n - X + 1) * p * px) / (X * q); + } + } + return X; +} + +long random_binomial(prng_t *prng_state, double p, long n) { + double q; + + if (p <= 0.5) { + if (p * n <= 30.0) { + return random_binomial_inversion(prng_state, n, p); + } else { + return random_binomial_btpe(prng_state, n, p); + } + } else { + q = 1.0 - p; + if (q * n <= 30.0) { + return n - random_binomial_inversion(prng_state, n, q); + } else { + return n - random_binomial_btpe(prng_state, n, q); + } + } +} + +double random_noncentral_chisquare(prng_t *prng_state, double df, double nonc) { + if (nonc == 0) { + return random_chisquare(prng_state, df); + } + if (1 < df) { + const double Chi2 = random_chisquare(prng_state, df - 1); + const double n = random_gauss(prng_state) + sqrt(nonc); + return Chi2 + n * n; + } else { + const long i = random_poisson(prng_state, nonc / 2.0); + return random_chisquare(prng_state, df + 2 * i); + } +} + +double random_noncentral_f(prng_t *prng_state, double dfnum, double dfden, + double nonc) { + double t = random_noncentral_chisquare(prng_state, dfnum, nonc) * dfden; + return t / (random_chisquare(prng_state, dfden) * dfnum); +} + +double random_wald(prng_t *prng_state, double mean, double scale) { + double U, X, Y; + double mu_2l; + + mu_2l = mean / (2 * scale); + Y = random_gauss(prng_state); + Y = mean * Y * Y; + X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y)); + U = random_sample(prng_state); + if (U <= mean / (mean + X)) { + return X; + } else { + return mean * mean / X; + } +} + +double random_vonmises(prng_t *prng_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 * random_sample(prng_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 = random_sample(prng_state); + Z = cos(M_PI * U); + W = (1 + s * Z) / (s + Z); + Y = kappa * (s - W); + V = random_sample(prng_state); + if ((Y * (2 - Y) - V >= 0) || (log(Y / V) + 1 - Y >= 0)) { + break; + } + } + + U = random_sample(prng_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; + } +} + +long random_logseries(prng_t *prng_state, double p) { + double q, r, U, V; + long result; + + r = log(1.0 - p); + + while (1) { + V = random_sample(prng_state); + if (V >= p) { + return 1; + } + U = random_sample(prng_state); + q = 1.0 - exp(r * U); + if (V <= q * q) { + result = (long)floor(1 + log(V) / log(q)); + if (result < 1) { + continue; + } else { + return result; + } + } + if (V >= q) { + return 1; + } + return 2; + } +} + +long random_geometric_search(prng_t *prng_state, double p) { + double U; + long X; + double sum, prod, q; + + X = 1; + sum = prod = p; + q = 1.0 - p; + U = random_sample(prng_state); + while (U > sum) { + prod *= q; + sum += prod; + X++; + } + return X; +} + +long random_geometric_inversion(prng_t *prng_state, double p) { + return (long)ceil(log(1.0 - random_sample(prng_state)) / log(1.0 - p)); +} + +long random_geometric(prng_t *prng_state, double p) { + if (p >= 0.333333333333333333333333) { + return random_geometric_search(prng_state, p); + } else { + return random_geometric_inversion(prng_state, p); + } +} + +long random_zipf(prng_t *prng_state, double a) { + double T, U, V; + long X; + double am1, b; + + am1 = a - 1.0; + b = pow(2.0, am1); + do { + U = 1.0 - random_sample(prng_state); + V = random_sample(prng_state); + X = (long)floor(pow(U, -1.0 / am1)); + /* The real result may be above what can be represented in a signed + * long. It will get casted to -sys.maxint-1. Since this is + * a straightforward rejection algorithm, we can just reject this value + * in the rejection condition below. This function then models a Zipf + * distribution truncated to sys.maxint. + */ + T = pow(1.0 + 1.0 / X, am1); + } while (((V * X * (T - 1.0) / (b - 1.0)) > (T / b)) || X < 1); + return X; +} + +double random_triangular(prng_t *prng_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 = random_sample(prng_state); + if (U <= ratio) { + return left + sqrt(U * leftprod); + } else { + return right - sqrt((1.0 - U) * rightprod); + } +} + +long random_hypergeometric_hyp(prng_t *prng_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 = random_sample(prng_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 random_hypergeometric_hrua(prng_t *prng_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 = random_sample(prng_state); + Y = random_sample(prng_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 random_hypergeometric(prng_t *prng_state, long good, long bad, + long sample) { + if (sample > 10) { + return random_hypergeometric_hrua(prng_state, good, bad, sample); + } else { + return random_hypergeometric_hyp(prng_state, good, bad, sample); + } +} + +unsigned long random_interval(prng_t *prng_state, unsigned long max) { + unsigned long 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; +#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 = (random_uint32(prng_state) & mask)) > max) + ; + } else { + while ((value = (random_uint64(prng_state) & mask)) > max) + ; + } +#else + while ((value = (random_uint32(prng_state) & mask)) > max) + ; +#endif + return value; +} + +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; +} + +/* + * Fills an array with cnt random npy_uint64 between off and off + rng + * inclusive. The numbers wrap if rng is sufficiently large. + */ + +static NPY_INLINE uint64_t bounded_uint64(prng_t *prng_state, uint64_t off, + uint64_t rng, uint64_t mask) { + uint64_t val; + if (rng == 0) + return off; + + if (rng <= 0xffffffffUL) { + while ((val = (random_uint32(prng_state) & mask)) > rng) + ; + } else { + while ((val = (random_uint64(prng_state) & mask)) > rng) + ; + } + return off + val; +} + +uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, uint64_t rng, + uint64_t mask) { + return bounded_uint64(prng_state, off, rng, mask); +} + +static NPY_INLINE uint32_t bounded_uint32(prng_t *prng_state, uint32_t off, + uint32_t rng, uint32_t mask) { + /* + * 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; + if (rng == 0) + return off; + + while ((val = (random_uint32(prng_state) & mask)) > rng) + ; + return off + val; +} + +uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, + uint32_t rng, uint32_t mask, int *bcnt, + uint32_t *buf) { + /* + * Unused bcnt and buf are here only to allow templating with other uint + * generators + */ + return bounded_uint32(prng_state, off, rng, mask); +} + +static NPY_INLINE uint16_t buffered_bounded_uint16(prng_t *prng_state, + uint16_t off, uint16_t rng, + uint16_t mask, int *bcnt, + uint32_t *buf) { + uint16_t val; + if (rng == 0) + return off; + + do { + if (!(bcnt[0])) { + buf[0] = random_uint32(prng_state); + bcnt[0] = 1; + } else { + buf[0] >>= 16; + bcnt[0] -= 1; + } + val = (uint16_t)buf[0] & mask; + } while (val > rng); + return off + val; +} + +uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, + uint16_t rng, uint16_t mask, int *bcnt, + uint32_t *buf) { + return buffered_bounded_uint16(prng_state, off, rng, mask, bcnt, buf); +} + +static NPY_INLINE uint8_t buffered_bounded_uint8(prng_t *prng_state, + uint8_t off, uint8_t rng, + uint8_t mask, int *bcnt, + uint32_t *buf) { + uint8_t val; + if (rng == 0) + return off; + do { + if (!(bcnt[0])) { + buf[0] = random_uint32(prng_state); + bcnt[0] = 3; + } else { + buf[0] >>= 8; + bcnt[0] -= 1; + } + val = (uint8_t)buf[0] & mask; + } while (val > rng); + return off + val; +} + +uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, + uint8_t rng, uint8_t mask, int *bcnt, + uint32_t *buf) { + return buffered_bounded_uint8(prng_state, off, rng, mask, bcnt, buf); +} + +static NPY_INLINE npy_bool buffered_bounded_bool(prng_t *prng_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] = random_uint32(prng_state); + bcnt[0] = 31; + } else { + buf[0] >>= 1; + bcnt[0] -= 1; + } + return (buf[0] & 0x00000001UL) != 0; +} + +npy_bool random_buffered_bounded_bool(prng_t *prng_state, npy_bool off, + npy_bool rng, npy_bool mask, int *bcnt, + uint32_t *buf) { + return buffered_bounded_bool(prng_state, off, rng, mask, bcnt, buf); +} + +void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, uint64_t rng, + npy_intp cnt, uint64_t *out) { + uint64_t mask; + npy_intp i; + + /* Smallest bit mask >= max */ + mask = gen_mask(rng); + for (i = 0; i < cnt; i++) { + out[i] = bounded_uint64(prng_state, off, rng, mask); + } +} + +/* + * 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(prng_t *prng_state, uint32_t off, uint32_t rng, + npy_intp cnt, uint32_t *out) { + uint32_t mask; + npy_intp i; + + /* Smallest bit mask >= max */ + mask = (uint32_t)gen_mask(rng); + for (i = 0; i < cnt; i++) { + out[i] = bounded_uint32(prng_state, off, rng, mask); + } +} + +/* + * 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(prng_t *prng_state, uint16_t off, uint16_t rng, + npy_intp cnt, uint16_t *out) { + uint16_t mask; + npy_intp i; + uint32_t buf = 0; + int bcnt = 0; + + /* Smallest bit mask >= max */ + mask = (uint16_t)gen_mask(rng); + for (i = 0; i < cnt; i++) { + out[i] = buffered_bounded_uint16(prng_state, off, rng, mask, &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(prng_t *prng_state, uint8_t off, uint8_t rng, + npy_intp cnt, uint8_t *out) { + uint8_t mask; + npy_intp i; + uint32_t buf = 0; + int bcnt = 0; + + /* Smallest bit mask >= max */ + mask = (uint8_t)gen_mask(rng); + for (i = 0; i < cnt; i++) { + out[i] = buffered_bounded_uint8(prng_state, off, rng, mask, &bcnt, &buf); + } +} + +/* + * Fills an array with cnt random npy_bool between off and off + rng + * inclusive. + */ +void random_bounded_bool_fill(prng_t *prng_state, npy_bool off, npy_bool rng, + npy_intp cnt, 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(prng_state, off, rng, mask, &bcnt, &buf); + } +} diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 9048784467a4..aedd0c6505e8 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -23,8 +23,14 @@ typedef int bool; #define DECLDIR extern #endif -typedef double (*random_double_0)(void *st); -typedef float (*random_float_0)(void *st); +#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 */ @@ -51,6 +57,7 @@ typedef struct prng { uint64_t (*next_uint64)(void *st); uint32_t (*next_uint32)(void *st); double (*next_double)(void *st); + uint64_t (*next_raw)(void *st); int has_gauss; double gauss; int has_gauss_f; @@ -62,6 +69,10 @@ DECLDIR float random_sample_f(prng_t *prng_state); DECLDIR double random_sample(prng_t *prng_state); DECLDIR uint32_t random_uint32(prng_t *prng_state); +DECLDIR int64_t random_positive_int64(prng_t *prng_state); +DECLDIR int32_t random_positive_int32(prng_t *prng_state); +DECLDIR long random_positive_int(prng_t *prng_state); +DECLDIR unsigned long random_uint(prng_t *prng_state); DECLDIR double random_standard_exponential(prng_t *prng_state); DECLDIR float random_standard_exponential_f(prng_t *prng_state); @@ -77,3 +88,76 @@ DECLDIR double random_standard_gamma(prng_t *prng_state, double shape); DECLDIR float random_standard_gamma_f(prng_t *prng_state, float shape); DECLDIR double random_standard_gamma_zig(prng_t *prng_state, double shape); DECLDIR float random_standard_gamma_zig_f(prng_t *prng_state, float shape); + +DECLDIR double random_normal(prng_t *prng_state, double loc, double scale); +DECLDIR double random_normal_zig(prng_t *prng_state, double loc, double scale); + +DECLDIR double random_gamma(prng_t *prng_state, double shape, double scale); +DECLDIR float random_gamma_float(prng_t *prng_state, float shape, float scale); + +DECLDIR double random_exponential(prng_t *prng_state, double scale); +DECLDIR double random_uniform(prng_t *prng_state, double lower, double range); +DECLDIR double random_beta(prng_t *prng_state, double a, double b); +DECLDIR double random_chisquare(prng_t *prng_state, double df); +DECLDIR double random_f(prng_t *prng_state, double dfnum, double dfden); +DECLDIR double random_standard_cauchy(prng_t *prng_state); +DECLDIR double random_pareto(prng_t *prng_state, double a); +DECLDIR double random_weibull(prng_t *prng_state, double a); +DECLDIR double random_power(prng_t *prng_state, double a); +DECLDIR double random_laplace(prng_t *prng_state, double loc, double scale); +DECLDIR double random_gumbel(prng_t *prng_state, double loc, double scale); +DECLDIR double random_logistic(prng_t *prng_state, double loc, double scale); +DECLDIR double random_lognormal(prng_t *prng_state, double mean, double sigma); +DECLDIR double random_rayleigh(prng_t *prng_state, double mode); +DECLDIR double random_standard_t(prng_t *prng_state, double df); +DECLDIR double random_noncentral_chisquare(prng_t *prng_state, double df, + double nonc); +DECLDIR double random_noncentral_f(prng_t *prng_state, double dfnum, + double dfden, double nonc); +DECLDIR double random_wald(prng_t *prng_state, double mean, double scale); +DECLDIR double random_vonmises(prng_t *prng_state, double mu, double kappa); +DECLDIR double random_triangular(prng_t *prng_state, double left, double mode, + double right); + +DECLDIR long random_poisson(prng_t *prng_state, double lam); +DECLDIR long random_negative_binomial(prng_t *prng_state, double n, double p); +DECLDIR long random_binomial(prng_t *prng_state, double p, long n); +DECLDIR long random_logseries(prng_t *prng_state, double p); +DECLDIR long random_geometric_search(prng_t *prng_state, double p); +DECLDIR long random_geometric_inversion(prng_t *prng_state, double p); +DECLDIR long random_geometric(prng_t *prng_state, double p); +DECLDIR long random_zipf(prng_t *prng_state, double a); +DECLDIR long random_hypergeometric(prng_t *prng_state, long good, long bad, + long sample); +DECLDIR unsigned long random_interval(prng_t *prng_state, unsigned long max); +DECLDIR uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, + uint64_t rng, uint64_t mask); +DECLDIR uint32_t random_buffered_bounded_uint32(prng_t *prng_state, + uint32_t off, uint32_t rng, + uint32_t mask, int *bcnt, + uint32_t *buf); + +DECLDIR uint16_t random_buffered_bounded_uint16(prng_t *prng_state, + uint16_t off, uint16_t rng, + uint16_t mask, int *bcnt, + uint32_t *buf); +DECLDIR uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, + uint8_t rng, uint8_t mask, + int *bcnt, uint32_t *buf); +DECLDIR npy_bool random_buffered_bounded_bool(prng_t *prng_state, npy_bool off, + npy_bool rng, npy_bool mask, + int *bcnt, uint32_t *buf); +DECLDIR void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, + uint64_t rng, npy_intp cnt, + uint64_t *out); +DECLDIR void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, + uint32_t rng, npy_intp cnt, + uint32_t *out); +DECLDIR void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, + uint16_t rng, npy_intp cnt, + uint16_t *out); +DECLDIR void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, + uint8_t rng, npy_intp cnt, uint8_t *out); +DECLDIR void random_bounded_bool_fill(prng_t *prng_state, npy_bool off, + npy_bool rng, npy_intp cnt, + npy_bool *out); diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index 2d616acd8276..fa608cd758f1 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -642,26 +642,30 @@ typedef struct s_dsfmt_state { int buffer_loc; } dsfmt_state; -static inline double dsfmt_next_double(dsfmt_state *state) { +static inline double dsfmt_next_buffer(dsfmt_state *state) { if (state->buffer_loc < DSFMT_N64) { double out = state->buffered_uniforms[state->buffer_loc]; state->buffer_loc++; return out; } - dsfmt_fill_array_close_open(state->state, state->buffered_uniforms, - DSFMT_N64); + dsfmt_fill_array_close1_open2(state->state, state->buffered_uniforms, + DSFMT_N64); state->buffer_loc = 1; return state->buffered_uniforms[0]; } +static inline double dsfmt_next_double(dsfmt_state *state) { + return dsfmt_next_buffer(state) - 1.0; +} + static inline uint64_t dsfmt_next64(dsfmt_state *state) { /* Discard bottom 16 bits */ - double d = dsfmt_next_double(state); + double d = dsfmt_next_buffer(state); uint64_t out; uint64_t *tmp; tmp = (uint64_t *)&d; out = (*tmp >> 16) << 32; - d = dsfmt_next_double(state); + d = dsfmt_next_buffer(state); tmp = (uint64_t *)&d; out |= (*tmp >> 16) & 0xffffffff; return out; @@ -669,9 +673,15 @@ static inline uint64_t dsfmt_next64(dsfmt_state *state) { static inline uint32_t dsfmt_next32(dsfmt_state *state) { /* Discard bottom 16 bits */ - double d = dsfmt_next_double(state); + double d = dsfmt_next_buffer(state); uint64_t *out = (uint64_t *)&d; return (uint32_t)((*out >> 16) & 0xffffffff); } +static inline uint64_t dsfmt_next_raw(dsfmt_state *state) { + double d; + d = dsfmt_next_buffer(state); + return *((uint64_t *)&d); +} + void dsfmt_jump(dsfmt_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index aedfc70c7cea..eb580671bb8c 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -76,6 +76,7 @@ cdef class ThreeFry: self._prng.next_uint64 = &threefry_uint64 self._prng.next_uint32 = &threefry_uint32 self._prng.next_double = &threefry_double + self._prng.next_raw = &threefry_uint64 cdef const char *name = 'CorePRNG' self.capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 0b59f6dccd12..07abc9b233a1 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -67,6 +67,7 @@ cdef class Xoroshiro128: self._prng.next_uint64 = &xoroshiro128_uint64 self._prng.next_uint32 = &xoroshiro128_uint32 self._prng.next_double = &xoroshiro128_double + self._prng.next_raw = &xoroshiro128_uint64 self.ctypes = None self.cffi = None diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 635bb24961f9..0eb6a9f3f8d5 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -62,6 +62,7 @@ cdef class Xorshift1024: self._prng.next_uint64 = &xorshift1024_uint64 self._prng.next_uint32 = &xorshift1024_uint32 self._prng.next_double = &xorshift1024_double + self._prng.next_raw = &xorshift1024_uint64 cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 3c40089a4e7f..8307ade74ee1 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -55,7 +55,8 @@ Extension("core_prng.dsfmt", ["core_prng/dsfmt.pyx", join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c'), - join(MOD_DIR, 'src', 'dsfmt', 'dSFMT-jump.c')], + join(MOD_DIR, 'src', 'dsfmt', 'dSFMT-jump.c'), + join(MOD_DIR, 'src', 'aligned_malloc', 'aligned_malloc.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'dsfmt')], From 7ca6e62eafb43b2cb24b96b2c8b8ec0a7b69d1af Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 9 Mar 2018 08:58:09 +0000 Subject: [PATCH 044/138] ENH: Add bounded intergers Add bounded integers Refactors distributions headers Add benchmark --- _randomgen/benchmark.py | 128 ++++++++++ _randomgen/core_prng/bounded_integers.pxd.in | 39 +++ _randomgen/core_prng/bounded_integers.pyx.in | 236 +++++++++++++++++++ _randomgen/core_prng/common.pxd | 131 +--------- _randomgen/core_prng/distributions.pxd | 133 +++++++++++ _randomgen/core_prng/dsfmt.pyx | 1 + _randomgen/core_prng/generator.pyx | 1 + _randomgen/core_prng/mt19937.pyx | 6 +- _randomgen/core_prng/pcg64.pyx | 2 + _randomgen/core_prng/philox.pyx | 1 + _randomgen/core_prng/threefry.pyx | 1 + _randomgen/core_prng/xoroshiro128.pyx | 1 + _randomgen/core_prng/xorshift1024.pyx | 1 + _randomgen/setup.py | 31 +++ 14 files changed, 581 insertions(+), 131 deletions(-) create mode 100644 _randomgen/benchmark.py create mode 100644 _randomgen/core_prng/bounded_integers.pxd.in create mode 100644 _randomgen/core_prng/bounded_integers.pyx.in create mode 100644 _randomgen/core_prng/distributions.pxd diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py new file mode 100644 index 000000000000..e670e72657c5 --- /dev/null +++ b/_randomgen/benchmark.py @@ -0,0 +1,128 @@ +import os +import struct +import timeit + +import numpy as np +import pandas as pd +from numpy.random import RandomState + +rs = RandomState() + +SETUP = ''' +import numpy as np +if '{prng}' == 'numpy': + import numpy.random + rg = numpy.random.RandomState() +else: + from core_prng import RandomGenerator, {prng} + rg = RandomGenerator({prng}()) +rg.random_sample() +''' + +scale_32 = scale_64 = 1 +if struct.calcsize('P') == 8 and os.name != 'nt': + # 64 bit + scale_32 = 0.5 +else: + scale_64 = 2 + +PRNGS = ['PCG64', 'MT19937', 'Xoroshiro128', 'Xorshift1024', + 'Philox', 'ThreeFry', 'numpy'] # , 'Xorshift1024', +#'Xoroshiro128', 'DSFMT', 'random'] + + +def timer(code, setup): + return 1000 * min(timeit.Timer(code, setup=setup).repeat(10, 10)) / 10.0 + + +def print_legend(legend): + print('\n' + legend + '\n' + '*' * max(60, len(legend))) + + +def run_timer(dist, command, numpy_command=None, setup='', random_type=''): + print('-' * 80) + if numpy_command is None: + numpy_command = command + + res = {} + for prng in PRNGS: + cmd = numpy_command if prng == 'numpy' else command + res[prng] = timer(cmd, setup=setup.format(prng=prng)) + + s = pd.Series(res) + t = s.apply(lambda x: '{0:0.2f} ms'.format(x)) + print_legend('Time to produce 1,000,000 ' + random_type) + print(t.sort_index()) + + p = 1000.0 / s + p = p.apply(lambda x: '{0:0.2f} million'.format(x)) + print_legend(random_type + ' per second') + print(p.sort_index()) + + baseline = [k for k in p.index if 'numpy' in k][0] + p = 1000.0 / s + p = p / p[baseline] * 100 - 100 + p = p.drop(baseline, 0) + p = p.apply(lambda x: '{0:0.1f}%'.format(x)) + print_legend('Speed-up relative to NumPy') + print(p.sort_index()) + print('-' * 80) + + +def timer_raw(): + dist = 'random_raw' + command = 'rg.random_raw(size=1000000, output=False)' + info = np.iinfo(np.int32) + command_numpy = 'rg.random_integers({max},size=1000000)' + command_numpy = command_numpy.format(max=info.max) + run_timer(dist, command, command_numpy, SETUP, 'Raw Values') + + +def timer_uniform(): + dist = 'random_sample' + command = 'rg.random_sample(1000000)' + run_timer(dist, command, None, SETUP, 'Uniforms') + + +def timer_32bit(): + info = np.iinfo(np.uint32) + min, max = info.min, info.max + dist = 'random_uintegers' + command = 'rg.random_uintegers(1000000, 32)' + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' + command_numpy = command_numpy.format(min=min, max=max) + run_timer(dist, command, command_numpy, SETUP, '32-bit unsigned integers') + + +def timer_64bit(): + info = np.iinfo(np.uint64) + min, max = info.min, info.max + dist = 'random_uintegers' + command = 'rg.random_uintegers(1000000)' + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64)' + command_numpy = command_numpy.format(min=min, max=max) + run_timer(dist, command, command_numpy, SETUP, '64-bit unsigned integers') + + +def timer_normal(): + dist = 'standard_normal' + command = 'rg.standard_normal(1000000, method="bm")' + command_numpy = 'rg.standard_normal(1000000)' + run_timer(dist, command, command_numpy, SETUP, 'Box-Muller normals') + + +def timer_normal_zig(): + dist = 'standard_normal' + command = 'rg.standard_normal(1000000, method="zig")' + command_numpy = 'rg.standard_normal(1000000)' + run_timer(dist, command, command_numpy, SETUP, + 'Standard normals (Ziggurat)') + + +if __name__ == '__main__': + timer_raw() + timer_uniform() + timer_32bit() + timer_64bit() + timer_normal() + timer_normal_zig() diff --git a/_randomgen/core_prng/bounded_integers.pxd.in b/_randomgen/core_prng/bounded_integers.pxd.in new file mode 100644 index 000000000000..c04aba7cedc2 --- /dev/null +++ b/_randomgen/core_prng/bounded_integers.pxd.in @@ -0,0 +1,39 @@ +from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, + int8_t, int16_t, int32_t, int64_t, intptr_t) +from common cimport prng_t +import numpy as np +cimport numpy as np +ctypedef np.npy_bool bool_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: +type_info = ('uint32','uint16','uint8','bool','int32','int16','int8') +}} +{{for nptype in type_info}} +cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock) +{{endfor}} +{{ +py: +big_type_info = ('uint64', 'int64') +}} +{{for nptype in big_type_info}} +cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, prng_t *state, object lock) +{{endfor}} +{{ +py: +type_info = ('uint64','uint32','uint16','uint8','bool','int64','int32','int16','int8') +}} +{{for nptype in type_info}} +cdef object _rand_{{nptype}}(object low, object high, object size, prng_t *state, object lock) +{{endfor}} diff --git a/_randomgen/core_prng/bounded_integers.pyx.in b/_randomgen/core_prng/bounded_integers.pyx.in new file mode 100644 index 000000000000..00dc08571125 --- /dev/null +++ b/_randomgen/core_prng/bounded_integers.pyx.in @@ -0,0 +1,236 @@ +from distributions cimport * + +_randint_type = {'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, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef {{utype}}_t rng, last_rng, off, val, mask, out_val + 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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, {{lb}})): + raise ValueError('low is out of bounds for {{nptype}}') + if np.any(np.greater(high_arr, {{ub}})): + raise ValueError('high is out of bounds for {{nptype}}') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.{{otype}}) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = 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] + rng = <{{utype}}_t>((high_v - 1) - 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, &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, prng_t *state, object lock): + """Array path for 64-bit integer types""" + cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr + cdef np.npy_intp i, cnt + 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 = low + high_arr = high + + if np.any(np.less(low_arr, {{lb}})): + raise ValueError('low is out of bounds for {{nptype}}') + + highm1_arr = 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): + closed_upper = int(flat[i]) - 1 + if closed_upper > {{ub}}: + raise ValueError('high is out of bounds for {{nptype}}') + if closed_upper < {{lb}}: + raise ValueError('low >= high') + highm1_data[i] = <{{nptype}}_t>closed_upper + + if np.any(np.greater(low_arr, highm1_arr)): + raise ValueError('low >= high') + + high_arr = highm1_arr + low_arr = np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.{{nptype}}) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.{{nptype}}) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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] + rng = <{{utype}}_t>(high_v - low_v) # No -1 here since implemented above + 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) + + 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, prng_t *state, object lock): + """ + _rand_{{nptype}}(low, high, size, *state, lock) + + Return random np.{{nptype}} integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState 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. + """ + 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, cnt + + if size is not None: + if (np.prod(size) == 0): + return np.empty(size, dtype=np.{{nptype}}) + + low_arr = np.array(low, copy=False) + high_arr = 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) + 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 + raise ValueError("low >= high") + + 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, &out_val) + return np.{{otype}}(<{{nptype}}_t>out_val) + else: + out_arr = 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, out_data) + return out_arr + return _rand_{{nptype}}_broadcast(low_arr, high_arr, size, state, lock) +{{endfor}} diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index ec4029e59db9..a6419cfa4958 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -2,7 +2,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) from libc.math cimport sqrt from cpython cimport PyInt_AsLong, PyFloat_AsDouble - +from distributions cimport prng_t import numpy as np cimport numpy as np @@ -27,135 +27,6 @@ cdef extern from "src/aligned_malloc/aligned_malloc.h": cdef void *PyArray_calloc_aligned(size_t n, size_t s); cdef void PyArray_free_aligned(void *p); -cdef extern from "src/distributions/distributions.h": - - struct s_binomial_t: - int has_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 - - ctypedef s_binomial_t binomial_t - - struct prng: - 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 - int has_gauss - double gauss - int has_gauss_f - float gauss_f - binomial_t *binomial - - ctypedef prng prng_t - - double random_sample(prng_t *prng_state) nogil - double random_standard_exponential(prng_t *prng_state) nogil - double random_standard_exponential_zig(prng_t *prng_state) nogil - double random_gauss(prng_t *prng_state) nogil - double random_gauss_zig(prng_t* prng_state) nogil - double random_standard_gamma(prng_t *prng_state, double shape) nogil - double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil - - float random_sample_f(prng_t *prng_state) nogil - float random_standard_exponential_f(prng_t *prng_state) nogil - float random_standard_exponential_zig_f(prng_t *prng_state) nogil - float random_gauss_f(prng_t *prng_state) nogil - float random_gauss_zig_f(prng_t* prng_state) nogil - float random_standard_gamma_f(prng_t *prng_state, float shape) nogil - float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil - - uint32_t random_uint32(prng_t *prng_state) nogil - int64_t random_positive_int64(prng_t *prng_state) nogil - int32_t random_positive_int32(prng_t *prng_state) nogil - long random_positive_int(prng_t *prng_state) nogil - unsigned long random_uint(prng_t *prng_state) nogil - - double random_normal(prng_t *prng_state, double loc, double scale) nogil - double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil - - double random_gamma(prng_t *prng_state, double shape, double scale) nogil - float random_gamma_float(prng_t *prng_state, float shape, float scale) nogil - - double random_exponential(prng_t *prng_state, double scale) nogil - double random_uniform(prng_t *prng_state, double lower, double range) nogil - double random_beta(prng_t *prng_state, double a, double b) nogil - double random_chisquare(prng_t *prng_state, double df) nogil - double random_f(prng_t *prng_state, double dfnum, double dfden) nogil - double random_standard_cauchy(prng_t *prng_state) nogil - double random_pareto(prng_t *prng_state, double a) nogil - double random_weibull(prng_t *prng_state, double a) nogil - double random_power(prng_t *prng_state, double a) nogil - double random_laplace(prng_t *prng_state, double loc, double scale) nogil - double random_gumbel(prng_t *prng_state, double loc, double scale) nogil - double random_logistic(prng_t *prng_state, double loc, double scale) nogil - double random_lognormal(prng_t *prng_state, double mean, double sigma) nogil - double random_rayleigh(prng_t *prng_state, double mode) nogil - double random_standard_t(prng_t *prng_state, double df) nogil - double random_noncentral_chisquare(prng_t *prng_state, double df, - double nonc) nogil - double random_noncentral_f(prng_t *prng_state, double dfnum, - double dfden, double nonc) nogil - double random_wald(prng_t *prng_state, double mean, double scale) nogil - double random_vonmises(prng_t *prng_state, double mu, double kappa) nogil - double random_triangular(prng_t *prng_state, double left, double mode, - double right) nogil - - long random_poisson(prng_t *prng_state, double lam) nogil - long random_negative_binomial(prng_t *prng_state, double n, double p) nogil - long random_binomial(prng_t *prng_state, double p, long n) nogil - long random_logseries(prng_t *prng_state, double p) nogil - long random_geometric_search(prng_t *prng_state, double p) nogil - long random_geometric_inversion(prng_t *prng_state, double p) nogil - long random_geometric(prng_t *prng_state, double p) nogil - long random_zipf(prng_t *prng_state, double a) nogil - long random_hypergeometric(prng_t *prng_state, long good, long bad, - long sample) nogil - unsigned long random_interval(prng_t *prng_state, unsigned long max) nogil - uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, - uint64_t rng, uint64_t mask) nogil - uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, - uint32_t rng, uint32_t mask, - int *bcnt, uint32_t *buf) nogil - - uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, - uint16_t rng, uint16_t mask, - int *bcnt, uint32_t *buf) nogil - uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, - uint8_t rng, uint8_t mask, - int *bcnt, uint32_t *buf) nogil - np.npy_bool random_buffered_bounded_bool(prng_t *prng_state, np.npy_bool off, - np.npy_bool rng, np.npy_bool mask, - int *bcnt, uint32_t *buf) nogil - void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, - uint64_t rng, np.npy_intp cnt, - uint64_t *out) nogil - void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, - uint32_t rng, np.npy_intp cnt, - uint32_t *out) nogil - void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, - uint16_t rng, np.npy_intp cnt, - uint16_t *out) nogil - void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, - uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil - void random_bounded_bool_fill(prng_t *prng_state, np.npy_bool off, - np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil - ctypedef double (*random_double_0)(prng_t *state) nogil ctypedef double (*random_double_1)(prng_t *state, double a) nogil ctypedef double (*random_double_2)(prng_t *state, double a, double b) nogil diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd new file mode 100644 index 000000000000..22761826af74 --- /dev/null +++ b/_randomgen/core_prng/distributions.pxd @@ -0,0 +1,133 @@ +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 + +cdef extern from "src/distributions/distributions.h": + + struct s_binomial_t: + int has_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 + + ctypedef s_binomial_t binomial_t + + struct prng: + 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 + int has_gauss + double gauss + int has_gauss_f + float gauss_f + binomial_t *binomial + + ctypedef prng prng_t + + double random_sample(prng_t *prng_state) nogil + double random_standard_exponential(prng_t *prng_state) nogil + double random_standard_exponential_zig(prng_t *prng_state) nogil + double random_gauss(prng_t *prng_state) nogil + double random_gauss_zig(prng_t* prng_state) nogil + double random_standard_gamma(prng_t *prng_state, double shape) nogil + double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil + + float random_sample_f(prng_t *prng_state) nogil + float random_standard_exponential_f(prng_t *prng_state) nogil + float random_standard_exponential_zig_f(prng_t *prng_state) nogil + float random_gauss_f(prng_t *prng_state) nogil + float random_gauss_zig_f(prng_t* prng_state) nogil + float random_standard_gamma_f(prng_t *prng_state, float shape) nogil + float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil + + uint32_t random_uint32(prng_t *prng_state) nogil + int64_t random_positive_int64(prng_t *prng_state) nogil + int32_t random_positive_int32(prng_t *prng_state) nogil + long random_positive_int(prng_t *prng_state) nogil + unsigned long random_uint(prng_t *prng_state) nogil + + double random_normal(prng_t *prng_state, double loc, double scale) nogil + double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil + + double random_gamma(prng_t *prng_state, double shape, double scale) nogil + float random_gamma_float(prng_t *prng_state, float shape, float scale) nogil + + double random_exponential(prng_t *prng_state, double scale) nogil + double random_uniform(prng_t *prng_state, double lower, double range) nogil + double random_beta(prng_t *prng_state, double a, double b) nogil + double random_chisquare(prng_t *prng_state, double df) nogil + double random_f(prng_t *prng_state, double dfnum, double dfden) nogil + double random_standard_cauchy(prng_t *prng_state) nogil + double random_pareto(prng_t *prng_state, double a) nogil + double random_weibull(prng_t *prng_state, double a) nogil + double random_power(prng_t *prng_state, double a) nogil + double random_laplace(prng_t *prng_state, double loc, double scale) nogil + double random_gumbel(prng_t *prng_state, double loc, double scale) nogil + double random_logistic(prng_t *prng_state, double loc, double scale) nogil + double random_lognormal(prng_t *prng_state, double mean, double sigma) nogil + double random_rayleigh(prng_t *prng_state, double mode) nogil + double random_standard_t(prng_t *prng_state, double df) nogil + double random_noncentral_chisquare(prng_t *prng_state, double df, + double nonc) nogil + double random_noncentral_f(prng_t *prng_state, double dfnum, + double dfden, double nonc) nogil + double random_wald(prng_t *prng_state, double mean, double scale) nogil + double random_vonmises(prng_t *prng_state, double mu, double kappa) nogil + double random_triangular(prng_t *prng_state, double left, double mode, + double right) nogil + + long random_poisson(prng_t *prng_state, double lam) nogil + long random_negative_binomial(prng_t *prng_state, double n, double p) nogil + long random_binomial(prng_t *prng_state, double p, long n) nogil + long random_logseries(prng_t *prng_state, double p) nogil + long random_geometric_search(prng_t *prng_state, double p) nogil + long random_geometric_inversion(prng_t *prng_state, double p) nogil + long random_geometric(prng_t *prng_state, double p) nogil + long random_zipf(prng_t *prng_state, double a) nogil + long random_hypergeometric(prng_t *prng_state, long good, long bad, + long sample) nogil + unsigned long random_interval(prng_t *prng_state, unsigned long max) nogil + uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, + uint64_t rng, uint64_t mask) nogil + uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, + uint32_t rng, uint32_t mask, + int *bcnt, uint32_t *buf) nogil + + uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, + uint16_t rng, uint16_t mask, + int *bcnt, uint32_t *buf) nogil + uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, + uint8_t rng, uint8_t mask, + int *bcnt, uint32_t *buf) nogil + np.npy_bool random_buffered_bounded_bool(prng_t *prng_state, np.npy_bool off, + np.npy_bool rng, np.npy_bool mask, + int *bcnt, uint32_t *buf) nogil + void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, + uint64_t rng, np.npy_intp cnt, + uint64_t *out) nogil + void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, + uint32_t rng, np.npy_intp cnt, + uint32_t *out) nogil + void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, + uint16_t rng, np.npy_intp cnt, + uint16_t *out) nogil + void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, + uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil + void random_bounded_bool_fill(prng_t *prng_state, np.npy_bool off, + np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 5acc2960f86c..09857aa621fb 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -6,6 +6,7 @@ import numpy as np cimport numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 80a4d0a60018..811b8d978224 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -9,6 +9,7 @@ cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles from common cimport * +from distributions cimport * from libc cimport string from libc.stdlib cimport malloc, free diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 230a29a74b5a..8f2f77f83922 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -7,6 +7,7 @@ import numpy as np cimport numpy as np from common cimport * +from distributions cimport prng_t, binomial_t import core_prng.pickle from core_prng.entropy import random_entropy @@ -36,6 +37,9 @@ cdef uint32_t mt19937_uint32(void *st) nogil: cdef double mt19937_double(void *st) nogil: return mt19937_next_double( st) +cdef uint64_t mt19937_raw(void *st) nogil: + return mt19937_next32( st) + cdef class MT19937: """ Prototype Core PRNG using MT19937 @@ -64,7 +68,7 @@ cdef class MT19937: self._prng.next_uint64 = &mt19937_uint64 self._prng.next_uint32 = &mt19937_uint32 self._prng.next_double = &mt19937_double - self._prng.next_raw = &mt19937_uint64 + self._prng.next_raw = &mt19937_raw cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index a2e0842eb1c5..bba905c19c98 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -5,6 +5,7 @@ import numpy as np cimport numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -89,6 +90,7 @@ cdef class PCG64: self._prng.next_uint64 = &pcg64_uint64 self._prng.next_uint32 = &pcg64_uint32 self._prng.next_double = &pcg64_double + self._prng.next_raw = &pcg64_uint64 cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 2765334cf050..41c520a1aba3 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -4,6 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index eb580671bb8c..4322baf3575a 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -4,6 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 07abc9b233a1..3cbb73752512 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -9,6 +9,7 @@ import numpy as np cimport numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 0eb6a9f3f8d5..ef686e003291 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -5,6 +5,7 @@ import numpy as np cimport numpy as np from common cimport * +from distributions cimport prng_t, binomial_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 8307ade74ee1..330d0cfeea16 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,4 +1,5 @@ import os +import glob import struct import sys from os.path import join @@ -9,6 +10,15 @@ from setuptools import setup, find_packages, Distribution from setuptools.extension import Extension +try: + import Cython.Tempita as tempita +except ImportError: + try: + import tempita + except ImportError: + raise ImportError('tempita required to install, ' + 'use pip install tempita') + import versioneer Cython.Compiler.Options.annotate = True @@ -43,6 +53,19 @@ if USE_SSE2: DSFMT_DEFS += [('HAVE_SSE2', '1')] +files = glob.glob('./core_prng/*.in') +for templated_file in files: + print(templated_file) + output_file_name = os.path.splitext(templated_file)[0] + if (os.path.exists(output_file_name) and + (os.path.getmtime(templated_file) < os.path.getmtime(output_file_name))): + continue + with open(templated_file, 'r') as source_file: + template = tempita.Template(source_file.read()) + with open(output_file_name, 'w') as output_file: + output_file.write(template.substitute()) + + extensions = [Extension('core_prng.entropy', sources=[join(MOD_DIR, 'entropy.pyx'), join(MOD_DIR, 'src', 'entropy', 'entropy.c')], @@ -137,6 +160,14 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("core_prng.bounded_integers", + ["core_prng/bounded_integers.pyx", + join(MOD_DIR, 'src', 'distributions', + 'distributions.c')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), ] From 65ceada8cf55aba86ceb0b0e324fa661cc578b4c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 9 Mar 2018 23:55:20 +0000 Subject: [PATCH 045/138] TST: Add tests --- _randomgen/.travis.yml | 59 + _randomgen/appveyor.yml | 33 + _randomgen/core_prng/__init__.py | 4 +- _randomgen/core_prng/_testing.py | 311 +++ _randomgen/core_prng/bounded_integers.pxd | 39 + _randomgen/core_prng/bounded_integers.pxd.in | 31 +- _randomgen/core_prng/bounded_integers.pyx | 1181 +++++++++++ _randomgen/core_prng/bounded_integers.pyx.in | 21 +- _randomgen/core_prng/common.pyx | 9 +- _randomgen/core_prng/distributions.pxd | 1 - _randomgen/core_prng/dsfmt.pyx | 10 +- _randomgen/core_prng/entropy.pyx | 35 +- _randomgen/core_prng/generator.pyx | 59 +- _randomgen/core_prng/mt19937.pyx | 18 + _randomgen/core_prng/pcg64.pyx | 44 +- _randomgen/core_prng/philox.pyx | 6 +- _randomgen/core_prng/pickle.py | 2 + .../src/distributions/distributions.c | 4 +- .../src/distributions/distributions.h | 2 +- .../src/mt19937/mt19937-test-data-gen.c | 11 +- _randomgen/core_prng/src/pcg64/pcg64.c | 14 + _randomgen/core_prng/src/pcg64/pcg64.h | 14 +- .../src/philox/philox-test-data-gen.c | 18 +- _randomgen/core_prng/src/philox/philox.h | 5 +- .../core_prng/src/splitmix64/splitmix64.h | 4 +- .../src/threefry/threefry-test-data-gen.c | 29 +- _randomgen/core_prng/src/threefry/threefry.h | 5 +- .../core_prng/src/xoroshiro128/xoroshiro128.h | 4 +- .../core_prng/src/xorshift1024/xorshift1024.h | 4 +- ...orshift2014.orig.c => xorshift1024.orig.c} | 0 .../core_prng/tests/data/dSFMT-testset-1.csv | 1001 ++++++++++ .../core_prng/tests/data/dSFMT-testset-2.csv | 1001 ++++++++++ .../tests/data/mt19937-testset-1.csv | 1001 ++++++++++ .../tests/data/mt19937-testset-2.csv | 1001 ++++++++++ .../core_prng/tests/data/philox-testset-1.csv | 1001 ++++++++++ .../core_prng/tests/data/philox-testset-2.csv | 1001 ++++++++++ .../tests/data/threefry-testset-1.csv | 1001 ++++++++++ .../tests/data/threefry-testset-2.csv | 1001 ++++++++++ .../tests/data/xoroshiro128-testset-1.csv | 1001 ++++++++++ .../tests/data/xoroshiro128-testset-2.csv | 1001 ++++++++++ .../tests/data/xorshift1024-testset-1.csv | 1001 ++++++++++ .../tests/data/xorshift1024-testset-2.csv | 1001 ++++++++++ .../core_prng/tests/test_against_numpy.py | 535 +++++ _randomgen/core_prng/tests/test_direct.py | 373 ++++ .../core_prng/tests/test_numpy_mt19937.py | 1752 +++++++++++++++++ .../tests/test_numpy_mt19937_regressions.py | 140 ++ _randomgen/core_prng/tests/test_smoke.py | 976 +++++++++ _randomgen/core_prng/threefry.pyx | 6 +- _randomgen/core_prng/xoroshiro128.pyx | 10 +- _randomgen/core_prng/xorshift1024.pyx | 6 +- _randomgen/setup.py | 1 - 51 files changed, 17659 insertions(+), 129 deletions(-) create mode 100644 _randomgen/.travis.yml create mode 100644 _randomgen/appveyor.yml create mode 100644 _randomgen/core_prng/_testing.py create mode 100644 _randomgen/core_prng/bounded_integers.pxd create mode 100644 _randomgen/core_prng/bounded_integers.pyx rename _randomgen/core_prng/src/xorshift1024/{xorshift2014.orig.c => xorshift1024.orig.c} (100%) create mode 100644 _randomgen/core_prng/tests/data/dSFMT-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/dSFMT-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/mt19937-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/mt19937-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/philox-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/philox-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/threefry-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/threefry-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/xorshift1024-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/xorshift1024-testset-2.csv create mode 100644 _randomgen/core_prng/tests/test_against_numpy.py create mode 100644 _randomgen/core_prng/tests/test_direct.py create mode 100644 _randomgen/core_prng/tests/test_numpy_mt19937.py create mode 100644 _randomgen/core_prng/tests/test_numpy_mt19937_regressions.py create mode 100644 _randomgen/core_prng/tests/test_smoke.py diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml new file mode 100644 index 000000000000..e30030a4bb39 --- /dev/null +++ b/_randomgen/.travis.yml @@ -0,0 +1,59 @@ +# Travis script that uses miniconda in place of the system installed python +# versions. Allows substantial flexability for choosing versions of +# required packages and is simpler to use to test up-to-date scientific Python +# stack +group: edge +dist: trusty +sudo: required +language: python + +matrix: + fast_finish: true + include: + - env: + - PYTHON=2.7 + - NUMPY=1.10 + - CYTHON=0.24 + - env: + - PYTHON=3.5 + - NUMPY=1.11 + - env: + - PYTHON=3.6 + - NUMPY=1.13 + - CYTHON=0.25 + - env: + - PYTHON=3.6 + - NUMPY=1.13 + - CYTHON=0.26 + - env: + - PYTHON=3.6 + +before_install: + - if [ ${TRAVIS_OS_NAME} = "osx" ]; then wget https://repo.continuum.io/miniconda/Miniconda-latest-MacOSX-x86_64.sh -O miniconda.sh; fi + - if [ ${TRAVIS_OS_NAME} = "linux" ]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi + - chmod +x miniconda3.sh + - ./miniconda3.sh -b + - export PATH=/home/travis/miniconda3/bin:$PATH + - conda config --set always_yes true + # Disable until fixed + # - conda update --all --quiet + - PKGS="python=${PYTHON}" + - PKGS="${PKGS} numpy"; if [ ${NUMPY} ]; then PKGS="${PKGS}=${NUMPY}"; fi + - PKGS="${PKGS} Cython"; if [ ${CYTHON} ]; then PKGS="${PKGS}=${CYTHON}"; fi + - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi + - export BUILD_DIR=$PWD + - conda create -n core-prng-test ${PKGS} pytest setuptools nose --quiet + - source activate core-prng-test + - pip install tempita -q + +install: + - python setup.py develop + +script: + - set -e + - pytest core_prng + - | + if [ -z ${NUMPY} ]; then + cd ${BUILD_DIR} + python benchmark.py; + fi diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml new file mode 100644 index 000000000000..1106f48c154e --- /dev/null +++ b/_randomgen/appveyor.yml @@ -0,0 +1,33 @@ +skip_tags: true +clone_depth: 50 + +os: Visual Studio 2015 + +environment: + matrix: + - PY_MAJOR_VER: 2 + PYTHON_ARCH: "x86" + - PY_MAJOR_VER: 3 + PYTHON_ARCH: "x86_64" + - PY_MAJOR_VER: 3 + PYTHON_ARCH: "x86" + +platform: + - x64 + +build_script: + - ps: Start-FileDownload "https://repo.continuum.io/miniconda/Miniconda$env:PY_MAJOR_VER-latest-Windows-$env:PYTHON_ARCH.exe" C:\Miniconda.exe; echo "Finished downloading miniconda" + - cmd: C:\Miniconda.exe /S /D=C:\Py + - SET PATH=C:\Py;C:\Py\Scripts;C:\Py\Library\bin;%PATH% + - conda config --set always_yes yes + - conda update conda --quiet + - conda install numpy cython nose pandas pytest --quiet + - python setup.py develop + - set "GIT_DIR=%cd%" + +test_script: + - pytest core_prng + +on_success: + - cd %GIT_DIR%\ + - IF %PYTHON_ARCH%==x86_64 python benchmark.py \ No newline at end of file diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 2d8d0ae6f2e4..d5577f3bf3cb 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -7,8 +7,8 @@ from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 -__all__ = ['RandomGenerator', 'DSFMT', 'PCG64', 'Xoroshiro128', - 'ThreeFry', 'MT19937', 'Xorshift1024'] +__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'Philox', + 'ThreeFry', 'Xoroshiro128', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/core_prng/_testing.py b/_randomgen/core_prng/_testing.py new file mode 100644 index 000000000000..2f74d06e7b05 --- /dev/null +++ b/_randomgen/core_prng/_testing.py @@ -0,0 +1,311 @@ +""" +Shim for NumPy's suppress_warnings +""" + + +try: + from numpy.testing import suppress_warnings +except ImportError: + + # The following two classes are copied from python 2.6 warnings module (context + # manager) + class WarningMessage(object): + + """ + Holds the result of a single showwarning() call. + Deprecated in 1.8.0 + Notes + ----- + `WarningMessage` is copied from the Python 2.6 warnings module, + so it can be used in NumPy with older Python versions. + """ + + _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", + "line") + + def __init__(self, message, category, filename, lineno, file=None, + line=None): + local_values = locals() + for attr in self._WARNING_DETAILS: + setattr(self, attr, local_values[attr]) + if category: + self._category_name = category.__name__ + else: + self._category_name = None + + def __str__(self): + return ("{message : %r, category : %r, filename : %r, lineno : %s, " + "line : %r}" % (self.message, self._category_name, + self.filename, self.lineno, self.line)) + + import re + import warnings + from functools import wraps + + class suppress_warnings(object): + """ + Context manager and decorator doing much the same as + ``warnings.catch_warnings``. + However, it also provides a filter mechanism to work around + http://bugs.python.org/issue4180. + This bug causes Python before 3.4 to not reliably show warnings again + after they have been ignored once (even within catch_warnings). It + means that no "ignore" filter can be used easily, since following + tests might need to see the warning. Additionally it allows easier + specificity for testing warnings and can be nested. + Parameters + ---------- + forwarding_rule : str, optional + One of "always", "once", "module", or "location". Analogous to + the usual warnings module filter mode, it is useful to reduce + noise mostly on the outmost level. Unsuppressed and unrecorded + warnings will be forwarded based on this rule. Defaults to "always". + "location" is equivalent to the warnings "default", match by exact + location the warning warning originated from. + Notes + ----- + Filters added inside the context manager will be discarded again + when leaving it. Upon entering all filters defined outside a + context will be applied automatically. + When a recording filter is added, matching warnings are stored in the + ``log`` attribute as well as in the list returned by ``record``. + If filters are added and the ``module`` keyword is given, the + warning registry of this module will additionally be cleared when + applying it, entering the context, or exiting it. This could cause + warnings to appear a second time after leaving the context if they + were configured to be printed once (default) and were already + printed before the context was entered. + Nesting this context manager will work as expected when the + forwarding rule is "always" (default). Unfiltered and unrecorded + warnings will be passed out and be matched by the outer level. + On the outmost level they will be printed (or caught by another + warnings context). The forwarding rule argument can modify this + behaviour. + Like ``catch_warnings`` this context manager is not threadsafe. + Examples + -------- + >>> with suppress_warnings() as sup: + ... sup.filter(DeprecationWarning, "Some text") + ... sup.filter(module=np.ma.core) + ... log = sup.record(FutureWarning, "Does this occur?") + ... command_giving_warnings() + ... # The FutureWarning was given once, the filtered warnings were + ... # ignored. All other warnings abide outside settings (may be + ... # printed/error) + ... assert_(len(log) == 1) + ... assert_(len(sup.log) == 1) # also stored in log attribute + Or as a decorator: + >>> sup = suppress_warnings() + >>> sup.filter(module=np.ma.core) # module must match exact + >>> @sup + >>> def some_function(): + ... # do something which causes a warning in np.ma.core + ... pass + """ + def __init__(self, forwarding_rule="always"): + self._entered = False + + # Suppressions are either instance or defined inside one with block: + self._suppressions = [] + + if forwarding_rule not in {"always", "module", "once", "location"}: + raise ValueError("unsupported forwarding rule.") + self._forwarding_rule = forwarding_rule + + def _clear_registries(self): + if hasattr(warnings, "_filters_mutated"): + # clearing the registry should not be necessary on new pythons, + # instead the filters should be mutated. + warnings._filters_mutated() + return + # Simply clear the registry, this should normally be harmless, + # note that on new pythons it would be invalidated anyway. + for module in self._tmp_modules: + if hasattr(module, "__warningregistry__"): + module.__warningregistry__.clear() + + def _filter(self, category=Warning, message="", module=None, record=False): + if record: + record = [] # The log where to store warnings + else: + record = None + if self._entered: + if module is None: + warnings.filterwarnings( + "always", category=category, message=message) + else: + module_regex = module.__name__.replace('.', '\.') + '$' + warnings.filterwarnings( + "always", category=category, message=message, + module=module_regex) + self._tmp_modules.add(module) + self._clear_registries() + + self._tmp_suppressions.append( + (category, message, re.compile(message, re.I), module, record)) + else: + self._suppressions.append( + (category, message, re.compile(message, re.I), module, record)) + + return record + + def filter(self, category=Warning, message="", module=None): + """ + Add a new suppressing filter or apply it if the state is entered. + Parameters + ---------- + category : class, optional + Warning class to filter + message : string, optional + Regular expression matching the warning message. + module : module, optional + Module to filter for. Note that the module (and its file) + must match exactly and cannot be a submodule. This may make + it unreliable for external modules. + Notes + ----- + When added within a context, filters are only added inside + the context and will be forgotten when the context is exited. + """ + self._filter(category=category, message=message, module=module, + record=False) + + def record(self, category=Warning, message="", module=None): + """ + Append a new recording filter or apply it if the state is entered. + All warnings matching will be appended to the ``log`` attribute. + Parameters + ---------- + category : class, optional + Warning class to filter + message : string, optional + Regular expression matching the warning message. + module : module, optional + Module to filter for. Note that the module (and its file) + must match exactly and cannot be a submodule. This may make + it unreliable for external modules. + Returns + ------- + log : list + A list which will be filled with all matched warnings. + Notes + ----- + When added within a context, filters are only added inside + the context and will be forgotten when the context is exited. + """ + return self._filter(category=category, message=message, module=module, + record=True) + + def __enter__(self): + if self._entered: + raise RuntimeError("cannot enter suppress_warnings twice.") + + self._orig_show = warnings.showwarning + if hasattr(warnings, "_showwarnmsg"): + self._orig_showmsg = warnings._showwarnmsg + self._filters = warnings.filters + warnings.filters = self._filters[:] + + self._entered = True + self._tmp_suppressions = [] + self._tmp_modules = set() + self._forwarded = set() + + self.log = [] # reset global log (no need to keep same list) + + for cat, mess, _, mod, log in self._suppressions: + if log is not None: + del log[:] # clear the log + if mod is None: + warnings.filterwarnings( + "always", category=cat, message=mess) + else: + module_regex = mod.__name__.replace('.', '\.') + '$' + warnings.filterwarnings( + "always", category=cat, message=mess, + module=module_regex) + self._tmp_modules.add(mod) + warnings.showwarning = self._showwarning + if hasattr(warnings, "_showwarnmsg"): + warnings._showwarnmsg = self._showwarnmsg + self._clear_registries() + + return self + + def __exit__(self, *exc_info): + warnings.showwarning = self._orig_show + if hasattr(warnings, "_showwarnmsg"): + warnings._showwarnmsg = self._orig_showmsg + warnings.filters = self._filters + self._clear_registries() + self._entered = False + del self._orig_show + del self._filters + + def _showwarnmsg(self, msg): + self._showwarning(msg.message, msg.category, msg.filename, msg.lineno, + msg.file, msg.line, use_warnmsg=msg) + + def _showwarning(self, message, category, filename, lineno, + *args, **kwargs): + use_warnmsg = kwargs.pop("use_warnmsg", None) + for cat, _, pattern, mod, rec in ( + self._suppressions + self._tmp_suppressions)[::-1]: + if (issubclass(category, cat) and + pattern.match(message.args[0]) is not None): + if mod is None: + # Message and category match, either recorded or ignored + if rec is not None: + msg = WarningMessage(message, category, filename, + lineno, **kwargs) + self.log.append(msg) + rec.append(msg) + return + # Use startswith, because warnings strips the c or o from + # .pyc/.pyo files. + elif mod.__file__.startswith(filename): + # The message and module (filename) match + if rec is not None: + msg = WarningMessage(message, category, filename, + lineno, **kwargs) + self.log.append(msg) + rec.append(msg) + return + + # There is no filter in place, so pass to the outside handler + # unless we should only pass it once + if self._forwarding_rule == "always": + if use_warnmsg is None: + self._orig_show(message, category, filename, lineno, + *args, **kwargs) + else: + self._orig_showmsg(use_warnmsg) + return + + if self._forwarding_rule == "once": + signature = (message.args, category) + elif self._forwarding_rule == "module": + signature = (message.args, category, filename) + elif self._forwarding_rule == "location": + signature = (message.args, category, filename, lineno) + + if signature in self._forwarded: + return + self._forwarded.add(signature) + if use_warnmsg is None: + self._orig_show(message, category, filename, lineno, *args, + **kwargs) + else: + self._orig_showmsg(use_warnmsg) + + def __call__(self, func): + """ + Function decorator to apply certain suppressions to a whole + function. + """ + @wraps(func) + def new_func(*args, **kwargs): + with self: + return func(*args, **kwargs) + + return new_func \ No newline at end of file diff --git a/_randomgen/core_prng/bounded_integers.pxd b/_randomgen/core_prng/bounded_integers.pxd new file mode 100644 index 000000000000..0da686427dec --- /dev/null +++ b/_randomgen/core_prng/bounded_integers.pxd @@ -0,0 +1,39 @@ +from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, + int8_t, int16_t, int32_t, int64_t, intptr_t) +from common cimport prng_t +import numpy as np +cimport numpy as np +ctypedef np.npy_bool bool_t + +_randint_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) + } + +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 + +cdef object _rand_uint64(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_uint32(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_uint16(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_uint8(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_bool(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_int64(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_int32(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_int16(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_int8(object low, object high, object size, prng_t *state, object lock) diff --git a/_randomgen/core_prng/bounded_integers.pxd.in b/_randomgen/core_prng/bounded_integers.pxd.in index c04aba7cedc2..1b87e8d7ed69 100644 --- a/_randomgen/core_prng/bounded_integers.pxd.in +++ b/_randomgen/core_prng/bounded_integers.pxd.in @@ -5,6 +5,17 @@ import numpy as np cimport numpy as np ctypedef np.npy_bool bool_t +_randint_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) + } + cdef inline uint64_t _gen_mask(uint64_t max_val) nogil: """Mask generator for use in bounded random numbers""" # Smallest bit mask >= max @@ -18,22 +29,8 @@ cdef inline uint64_t _gen_mask(uint64_t max_val) nogil: return mask {{ py: -type_info = ('uint32','uint16','uint8','bool','int32','int16','int8') -}} -{{for nptype in type_info}} -cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock) -{{endfor}} -{{ -py: -big_type_info = ('uint64', 'int64') -}} -{{for nptype in big_type_info}} -cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, prng_t *state, object lock) -{{endfor}} -{{ -py: -type_info = ('uint64','uint32','uint16','uint8','bool','int64','int32','int16','int8') +inttypes = ('uint64','uint32','uint16','uint8','bool','int64','int32','int16','int8') }} -{{for nptype in type_info}} -cdef object _rand_{{nptype}}(object low, object high, object size, prng_t *state, object lock) +{{for inttype in inttypes}} +cdef object _rand_{{inttype}}(object low, object high, object size, prng_t *state, object lock) {{endfor}} diff --git a/_randomgen/core_prng/bounded_integers.pyx b/_randomgen/core_prng/bounded_integers.pyx new file mode 100644 index 000000000000..e8840d341f6c --- /dev/null +++ b/_randomgen/core_prng/bounded_integers.pyx @@ -0,0 +1,1181 @@ +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True + +import numpy as np +cimport numpy as np +from distributions cimport * +np.import_array() + + + + +cdef object _rand_uint32_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint32_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint32_t *out_data + cdef uint64_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, 0)): + raise ValueError('low is out of bounds for uint32') + if np.any(np.greater(high_arr, 0X100000000ULL)): + raise ValueError('high is out of bounds for uint32') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.uint32) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.uint32) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint32(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_uint16_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint16_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint16_t *out_data + cdef uint32_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, 0)): + raise ValueError('low is out of bounds for uint16') + if np.any(np.greater(high_arr, 0X10000UL)): + raise ValueError('high is out of bounds for uint16') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT32, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT32, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.uint16) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.uint16) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint16(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_uint8_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint8_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint8_t *out_data + cdef uint16_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, 0)): + raise ValueError('low is out of bounds for uint8') + if np.any(np.greater(high_arr, 0X100UL)): + raise ValueError('high is out of bounds for uint8') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT16, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT16, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.uint8) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.uint8) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint8(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_bool_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef bool_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef bool_t *out_data + cdef uint8_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, 0)): + raise ValueError('low is out of bounds for bool') + if np.any(np.greater(high_arr, 0x2UL)): + raise ValueError('high is out of bounds for bool') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT8, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT8, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.bool_) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.bool_) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_bool(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_int32_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint32_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint32_t *out_data + cdef uint64_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, -0x80000000LL)): + raise ValueError('low is out of bounds for int32') + if np.any(np.greater(high_arr, 0x80000000LL)): + raise ValueError('high is out of bounds for int32') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.int32) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.int32) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint32(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_int16_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint16_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint16_t *out_data + cdef uint32_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, -0x8000LL)): + raise ValueError('low is out of bounds for int16') + if np.any(np.greater(high_arr, 0x8000LL)): + raise ValueError('high is out of bounds for int16') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT32, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT32, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.int16) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.int16) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint16(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + +cdef object _rand_int8_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): + """Array path for smaller integer types""" + cdef uint8_t rng, last_rng, off, val, mask, out_val + cdef uint32_t buf + cdef uint8_t *out_data + cdef uint16_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 + low_arr = low + high_arr = high + if np.any(np.less(low_arr, -0x80LL)): + raise ValueError('low is out of bounds for int8') + if np.any(np.greater(high_arr, 0x80LL)): + raise ValueError('high is out of bounds for int8') + if np.any(np.greater_equal(low_arr, high_arr)): + raise ValueError('low >= high') + + low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT16, np.NPY_ALIGNED | np.NPY_FORCECAST) + high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT16, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.int8) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.int8) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = ((high_v - 1) - low_v) + off = (low_v) + + if rng != last_rng: + # Smallest bit mask >= max + mask = _gen_mask(rng) + + out_data[i] = random_buffered_bounded_uint8(state, off, rng, mask, &buf_rem, &buf) + + np.PyArray_MultiIter_NEXT(it) + return out_arr + + + +cdef object _rand_uint64_broadcast(object low, object high, object size, prng_t *state, object lock): + """Array path for 64-bit integer types""" + 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 uint64_t *highm1_data + cdef uint64_t low_v, high_v + cdef uint64_t rng, last_rng, val, mask, off, out_val + + low_arr = low + high_arr = high + + if np.any(np.less(low_arr, 0x0ULL)): + raise ValueError('low is out of bounds for uint64') + + highm1_arr = np.empty_like(high_arr, dtype=np.uint64) + highm1_data = np.PyArray_DATA(highm1_arr) + cnt = np.PyArray_SIZE(high_arr) + flat = high_arr.flat + for i in range(cnt): + closed_upper = int(flat[i]) - 1 + if closed_upper > 0xFFFFFFFFFFFFFFFFULL: + raise ValueError('high is out of bounds for uint64') + if closed_upper < 0x0ULL: + raise ValueError('low >= high') + highm1_data[i] = closed_upper + + if np.any(np.greater(low_arr, highm1_arr)): + raise ValueError('low >= high') + + high_arr = highm1_arr + low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.uint64) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.uint64) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = (high_v - low_v) # No -1 here since implemented above + off = (low_v) + + if rng != last_rng: + mask = _gen_mask(rng) + out_data[i] = random_bounded_uint64(state, off, rng, mask) + + np.PyArray_MultiIter_NEXT(it) + + return out_arr + +cdef object _rand_int64_broadcast(object low, object high, object size, prng_t *state, object lock): + """Array path for 64-bit integer types""" + 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 int64_t *highm1_data + cdef int64_t low_v, high_v + cdef uint64_t rng, last_rng, val, mask, off, out_val + + low_arr = low + high_arr = high + + if np.any(np.less(low_arr, -0x8000000000000000LL)): + raise ValueError('low is out of bounds for int64') + + highm1_arr = np.empty_like(high_arr, dtype=np.int64) + highm1_data = np.PyArray_DATA(highm1_arr) + cnt = np.PyArray_SIZE(high_arr) + flat = high_arr.flat + for i in range(cnt): + closed_upper = int(flat[i]) - 1 + if closed_upper > 0x7FFFFFFFFFFFFFFFLL: + raise ValueError('high is out of bounds for int64') + if closed_upper < -0x8000000000000000LL: + raise ValueError('low >= high') + highm1_data[i] = closed_upper + + if np.any(np.greater(low_arr, highm1_arr)): + raise ValueError('low >= high') + + high_arr = highm1_arr + low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) + + if size is not None: + out_arr = np.empty(size, np.int64) + else: + it = np.PyArray_MultiIterNew2(low_arr, high_arr) + out_arr = np.empty(it.shape, np.int64) + + it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) + out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] + high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] + rng = (high_v - low_v) # No -1 here since implemented above + off = (low_v) + + if rng != last_rng: + mask = _gen_mask(rng) + out_data[i] = random_bounded_uint64(state, off, rng, mask) + + np.PyArray_MultiIter_NEXT(it) + + return out_arr + + + +cdef object _rand_uint64(object low, object high, object size, prng_t *state, object lock): + """ + _rand_uint64(low, high, size, *state, lock) + + Return random np.uint64 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.uint64 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.uint64 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint64_t rng, off, out_val + cdef uint64_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.uint64) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < 0x0ULL: + raise ValueError("low is out of bounds for uint64") + if high > 0xFFFFFFFFFFFFFFFFULL: + raise ValueError("high is out of bounds for uint64") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint64_fill(state, off, rng, 1, &out_val) + return np.uint64(out_val) + else: + out_arr = np.empty(size, np.uint64) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint64_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_uint64_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_uint32(object low, object high, object size, prng_t *state, object lock): + """ + _rand_uint32(low, high, size, *state, lock) + + Return random np.uint32 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.uint32 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.uint32 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint32_t rng, off, out_val + cdef uint32_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.uint32) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < 0x0UL: + raise ValueError("low is out of bounds for uint32") + if high > 0XFFFFFFFFUL: + raise ValueError("high is out of bounds for uint32") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint32_fill(state, off, rng, 1, &out_val) + return np.uint32(out_val) + else: + out_arr = np.empty(size, np.uint32) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint32_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_uint32_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_uint16(object low, object high, object size, prng_t *state, object lock): + """ + _rand_uint16(low, high, size, *state, lock) + + Return random np.uint16 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.uint16 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.uint16 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint16_t rng, off, out_val + cdef uint16_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.uint16) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < 0x0UL: + raise ValueError("low is out of bounds for uint16") + if high > 0XFFFFUL: + raise ValueError("high is out of bounds for uint16") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint16_fill(state, off, rng, 1, &out_val) + return np.uint16(out_val) + else: + out_arr = np.empty(size, np.uint16) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint16_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_uint16_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_uint8(object low, object high, object size, prng_t *state, object lock): + """ + _rand_uint8(low, high, size, *state, lock) + + Return random np.uint8 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.uint8 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.uint8 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint8_t rng, off, out_val + cdef uint8_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.uint8) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < 0x0UL: + raise ValueError("low is out of bounds for uint8") + if high > 0XFFUL: + raise ValueError("high is out of bounds for uint8") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint8_fill(state, off, rng, 1, &out_val) + return np.uint8(out_val) + else: + out_arr = np.empty(size, np.uint8) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint8_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_uint8_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_bool(object low, object high, object size, prng_t *state, object lock): + """ + _rand_bool(low, high, size, *state, lock) + + Return random np.bool integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.bool 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.bool + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef bool_t rng, off, out_val + cdef bool_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.bool) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < 0x0UL: + raise ValueError("low is out of bounds for bool") + if high > 0x1UL: + raise ValueError("high is out of bounds for bool") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_bool_fill(state, off, rng, 1, &out_val) + return np.bool_(out_val) + else: + out_arr = np.empty(size, np.bool) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_bool_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_bool_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_int64(object low, object high, object size, prng_t *state, object lock): + """ + _rand_int64(low, high, size, *state, lock) + + Return random np.int64 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.int64 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.int64 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint64_t rng, off, out_val + cdef uint64_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.int64) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < -0x8000000000000000LL: + raise ValueError("low is out of bounds for int64") + if high > 0x7FFFFFFFFFFFFFFFL: + raise ValueError("high is out of bounds for int64") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint64_fill(state, off, rng, 1, &out_val) + return np.int64(out_val) + else: + out_arr = np.empty(size, np.int64) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint64_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_int64_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_int32(object low, object high, object size, prng_t *state, object lock): + """ + _rand_int32(low, high, size, *state, lock) + + Return random np.int32 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.int32 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.int32 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint32_t rng, off, out_val + cdef uint32_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.int32) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < -0x80000000L: + raise ValueError("low is out of bounds for int32") + if high > 0x7FFFFFFFL: + raise ValueError("high is out of bounds for int32") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint32_fill(state, off, rng, 1, &out_val) + return np.int32(out_val) + else: + out_arr = np.empty(size, np.int32) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint32_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_int32_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_int16(object low, object high, object size, prng_t *state, object lock): + """ + _rand_int16(low, high, size, *state, lock) + + Return random np.int16 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.int16 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.int16 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint16_t rng, off, out_val + cdef uint16_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.int16) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < -0x8000L: + raise ValueError("low is out of bounds for int16") + if high > 0x7FFFL: + raise ValueError("high is out of bounds for int16") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint16_fill(state, off, rng, 1, &out_val) + return np.int16(out_val) + else: + out_arr = np.empty(size, np.int16) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint16_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_int16_broadcast(low_arr, high_arr, size, state, lock) + +cdef object _rand_int8(object low, object high, object size, prng_t *state, object lock): + """ + _rand_int8(low, high, size, *state, lock) + + Return random np.int8 integers between `low` and `high`, inclusive. + + Return random integers from the "discrete uniform" distribution in the + closed 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.int8 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, 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. + state : augmented random state + State to use in the core random number generators + lock : threading.Lock + Lock to prevent multiple using a single RandomState simultaneously + + Returns + ------- + out : python scalar or ndarray of np.int8 + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + """ + cdef np.ndarray out_arr, low_arr, high_arr + cdef uint8_t rng, off, out_val + cdef uint8_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.int8) + + low_arr = np.array(low, copy=False) + high_arr = 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) + high -= 1 + + if low < -0x80L: + raise ValueError("low is out of bounds for int8") + if high > 0x7FL: + raise ValueError("high is out of bounds for int8") + if low > high: # -1 already subtracted, closed interval + raise ValueError("low >= high") + + rng = (high - low) + off = (low) + if size is None: + with lock: + random_bounded_uint8_fill(state, off, rng, 1, &out_val) + return np.int8(out_val) + else: + out_arr = np.empty(size, np.int8) + cnt = np.PyArray_SIZE(out_arr) + out_data = np.PyArray_DATA(out_arr) + with lock, nogil: + random_bounded_uint8_fill(state, off, rng, cnt, out_data) + return out_arr + return _rand_int8_broadcast(low_arr, high_arr, size, state, lock) diff --git a/_randomgen/core_prng/bounded_integers.pyx.in b/_randomgen/core_prng/bounded_integers.pyx.in index 00dc08571125..ea0bba028d0b 100644 --- a/_randomgen/core_prng/bounded_integers.pyx.in +++ b/_randomgen/core_prng/bounded_integers.pyx.in @@ -1,15 +1,10 @@ -from distributions cimport * +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True -_randint_type = {'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) - } +import numpy as np +cimport numpy as np +from distributions cimport * +np.import_array() {{ py: @@ -86,7 +81,7 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, prng_t *state, object lock): """Array path for 64-bit integer types""" cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr - cdef np.npy_intp i, cnt + cdef np.npy_intp i, cnt, n cdef np.broadcast it cdef object closed_upper cdef uint64_t *out_data @@ -196,7 +191,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size, prng_t *state 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, cnt + cdef np.npy_intp i, n, cnt if size is not None: if (np.prod(size) == 0): diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index b7a6f5327cfd..5dedbdbde1e8 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -1,3 +1,6 @@ +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True + import sys import numpy as np cimport numpy as np @@ -59,7 +62,7 @@ cdef object double_fill(void *func, prng_t *state, object size, object lock, obj cdef np.ndarray out_array cdef np.npy_intp i, n - if size is None: + if size is None and out is None: with lock: return random_func(state) @@ -82,7 +85,7 @@ cdef object float_fill(void *func, prng_t *state, object size, object lock, obje cdef np.ndarray out_array cdef np.npy_intp i, n - if size is None: + if size is None and out is None: with lock: return random_func(state) @@ -105,7 +108,7 @@ cdef object float_fill_from_double(void *func, prng_t *state, object size, objec cdef np.ndarray out_array cdef np.npy_intp i, n - if size is None: + if size is None and out is None: with lock: return random_func(state) diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd index 22761826af74..5359a1be0eaa 100644 --- a/_randomgen/core_prng/distributions.pxd +++ b/_randomgen/core_prng/distributions.pxd @@ -56,7 +56,6 @@ cdef extern from "src/distributions/distributions.h": float random_standard_gamma_f(prng_t *prng_state, float shape) nogil float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil - uint32_t random_uint32(prng_t *prng_state) nogil int64_t random_positive_int64(prng_t *prng_state) nogil int32_t random_positive_int32(prng_t *prng_state) nogil long random_positive_int(prng_t *prng_state) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 09857aa621fb..c95f4f2d3918 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -85,7 +85,7 @@ cdef class DSFMT: def __init__(self, seed=None): self.rng_state = malloc(sizeof(dsfmt_state)) self.rng_state.state = PyArray_malloc_aligned(sizeof(dsfmt_t)) - self.rng_state.buffered_uniforms = PyArray_malloc_aligned(DSFMT_N64 * sizeof(double)) + self.rng_state.buffered_uniforms = PyArray_calloc_aligned(DSFMT_N64, sizeof(double)) self.rng_state.buffer_loc = DSFMT_N64 self._prng = malloc(sizeof(prng_t)) self._prng.binomial = malloc(sizeof(binomial_t)) @@ -117,8 +117,11 @@ cdef class DSFMT: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): - pass + cdef _reset_state_variables(self): + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ @@ -199,6 +202,7 @@ cdef class DSFMT: dsfmt_init_by_array(self.rng_state.state, obj.data, np.PyArray_DIM(obj, 0)) + self._reset_state_variables() def seed(self, seed=None): """ diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/core_prng/entropy.pyx index a4747f36b0fd..19dbb0fd20b2 100644 --- a/_randomgen/core_prng/entropy.pyx +++ b/_randomgen/core_prng/entropy.pyx @@ -44,27 +44,34 @@ cdef np.ndarray seed_by_array(object seed, Py_ssize_t n): cdef Py_ssize_t seed_size, iter_bound cdef int i, loc = 0 - try: - if hasattr(seed, 'squeeze'): - seed = seed.squeeze() - idx = operator.index(seed) - if idx > int(2**64 - 1) or idx < 0: - raise ValueError("Seed must be between 0 and 2**64 - 1") - seed = [seed] - seed_array = np.array(seed, dtype=np.uint64) - except TypeError: - exc_msg = "Seed values must be integers between 0 and 2**64 - 1" - obj = np.asarray(seed).astype(np.object).ravel() + 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) + 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(exc_msg) + raise ValueError(err_msg) try: obj_int = obj.astype(np.uint64, casting='unsafe') except ValueError: - raise ValueError(exc_msg) + raise ValueError(err_msg) if not (obj == obj_int).all(): - raise ValueError(exc_msg) + raise TypeError(err_msg) seed_array = obj_int seed_size = seed_array.shape[0] diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 811b8d978224..0e3bbf0cc799 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -10,6 +10,7 @@ from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles from common cimport * from distributions cimport * +from bounded_integers cimport * from libc cimport string from libc.stdlib cimport malloc, free @@ -29,6 +30,17 @@ import core_prng.pickle np.import_array() +_randint_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) + } + cdef class RandomGenerator: """ Prototype Random Generator that consumes randoms from a CorePRNG class @@ -75,6 +87,13 @@ cdef class RandomGenerator: (self.state['prng'],), self.state) + def seed(self, *args, **kwargs): + """ + TODO: Should this remain + """ + self.__core_prng.seed(*args, **kwargs) + return self + @property def state(self): """Get or set the underlying PRNG's state""" @@ -87,11 +106,14 @@ cdef class RandomGenerator: @state.setter def state(self, value): + self.__core_prng.state = value + if isinstance(value, tuple): + # Legacy MT19937 state + return self._prng.has_gauss = value['has_gauss'] self._prng.has_gauss_f = value['has_gauss_f'] self._prng.gauss = value['gauss'] self._prng.gauss_f = value['gauss_f'] - self.__core_prng.state = value def random_uintegers(self, size=None, int bits=64): """ @@ -210,7 +232,6 @@ cdef class RandomGenerator: return randoms def random_integer(self, bits=64): - #print("In random_integer") if bits == 64: return self._prng.next_uint64(self._prng.state) elif bits == 32: @@ -568,7 +589,37 @@ cdef class RandomGenerator: array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) """ - raise NotImplementedError('To be completed') + if high is None: + high = low + low = 0 + + key = np.dtype(dtype).name + if not key in _randint_types: + raise TypeError('Unsupported dtype "%s" for randint' % key) + + if key == 'int32': + ret = _rand_int32(low, high, size, self._prng, self.lock) + elif key == 'int64': + ret = _rand_int64(low, high, size, self._prng, self.lock) + elif key == 'int16': + ret = _rand_int16(low, high, size, self._prng, self.lock) + elif key == 'int8': + ret = _rand_int8(low, high, size, self._prng, self.lock) + elif key == 'uint64': + ret = _rand_uint64(low, high, size, self._prng, self.lock) + elif key == 'uint32': + ret = _rand_uint32(low, high, size, self._prng, self.lock) + elif key == 'uint16': + ret = _rand_uint16(low, high, size, self._prng, self.lock) + elif key == 'uint8': + ret = _rand_uint8(low, high, size, self._prng, self.lock) + elif key == 'bool': + ret = _rand_bool(low, high, size, self._prng, 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): """ @@ -1095,8 +1146,6 @@ cdef class RandomGenerator: return self.randint(low, high + 1, size=size, dtype='l') - - # Complicated, continuous distributions: def standard_normal(self, size=None, dtype=np.float64, method=u'zig', out=None): """ diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 8f2f77f83922..53a909100727 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -78,6 +78,12 @@ cdef class MT19937: free(self._prng.binomial) free(self._prng) + cdef _reset_state_variables(self): + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 + # Pickling support: def __getstate__(self): return self.state @@ -167,6 +173,7 @@ cdef class MT19937: 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, obj.data, np.PyArray_DIM(obj, 0)) + self._reset_state_variables() def jump(self): mt19937_jump(self.rng_state) @@ -184,6 +191,17 @@ cdef class MT19937: @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') + self._reset_state_variables() + if len(value) == 5: + self._prng.has_gauss = value[3] + self._prng.gauss = value[4] + value ={'prng': 'MT19937', + 'state':{'key': value[1], 'pos': value[2]} + } + if not isinstance(value, dict): raise TypeError('state must be a dict') prng = value.get('prng', '') diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index bba905c19c98..7353a77beaf2 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -50,7 +50,7 @@ cdef extern from "src/pcg64/pcg64.h": uint64_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) cdef uint64_t pcg64_uint64(void* st) nogil: return pcg64_next64(st) @@ -112,9 +112,13 @@ cdef class PCG64: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): + cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ @@ -176,23 +180,33 @@ cdef class PCG64: If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + cdef np.ndarray _seed, _inc + ub = 2 ** 128 if seed is None: try: - state = random_entropy(4) + _seed = random_entropy(4) except RuntimeError: - state = random_entropy(4, 'fallback') - state = state.view(np.uint64) + _seed = random_entropy(4, 'fallback') + + _seed = _seed.view(np.uint64) else: - state = entropy.seed_by_array(seed, 2) - IF PCG_EMULATED_MATH==1: - self.rng_state.pcg_state.state.high = int(state[0]) - self.rng_state.pcg_state.state.low = int(state[1]) - self.rng_state.pcg_state.inc.high = inc // 2**64 - self.rng_state.pcg_state.inc.low = inc % 2**64 - ELSE: - self.rng_state.pcg_state.state = state[0] * 2**64 + state[1] - self.rng_state.pcg_state.inc = inc + if not np.isscalar(seed): + raise TypeError('seed must be a scalar integer between 0 and {ub}'.format(ub=ub)) + if seed < 0 or seed > ub or int(seed) != seed: + raise ValueError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + _seed = np.empty(2, np.uint64) + _seed[0] = int(seed) // 2**64 + _seed[1] = int(seed) % 2**64 + + if not np.isscalar(inc): + raise TypeError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + if inc < 0 or inc > ub or int(inc) != inc: + raise ValueError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + _inc = np.empty(2, np.uint64) + _inc[0] = int(inc) // 2**64 + _inc[1] = int(inc) % 2**64 + + pcg64_set_seed(self.rng_state, _seed.data, _inc.data) self._reset_state_variables() @property diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 41c520a1aba3..12d69fe6813a 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -107,9 +107,13 @@ cdef class Philox: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): + cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 self.rng_state.buffer_pos = PHILOX_BUFFER_SIZE for i in range(PHILOX_BUFFER_SIZE): self.rng_state.buffer[i] = 0 diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/core_prng/pickle.py index d4e5a1f71d63..44b7e6b24210 100644 --- a/_randomgen/core_prng/pickle.py +++ b/_randomgen/core_prng/pickle.py @@ -1,4 +1,5 @@ from .generator import RandomGenerator +from .dsfmt import DSFMT from .mt19937 import MT19937 from .pcg64 import PCG64 from .philox import Philox @@ -7,6 +8,7 @@ from .xorshift1024 import Xorshift1024 PRNGS = {'MT19937': MT19937, + 'DSFMT': DSFMT, 'PCG64': PCG64, 'Philox': Philox, 'ThreeFry': ThreeFry, diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 3edc59261041..4c2896e888ab 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -7,7 +7,7 @@ static NPY_INLINE float next_float(prng_t *prng_state) { (1.0f / 8388608.0f); } -uint32_t random_uint32(prng_t *prng_state) { +static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } @@ -33,6 +33,7 @@ double random_gauss(prng_t *prng_state) { if (prng_state->has_gauss) { const double temp = prng_state->gauss; prng_state->has_gauss = false; + prng_state->gauss = 0.0; return temp; } else { double f, x1, x2, r2; @@ -56,6 +57,7 @@ float random_gauss_f(prng_t *prng_state) { if (prng_state->has_gauss_f) { const float temp = prng_state->gauss_f; prng_state->has_gauss_f = false; + prng_state->gauss_f = 0.0f; return temp; } else { float f, x1, x2, r2; diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index aedd0c6505e8..9f368837eaeb 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -14,6 +14,7 @@ typedef int bool; #include #endif +#include "Python.h" #include "numpy/npy_common.h" #include @@ -68,7 +69,6 @@ typedef struct prng { DECLDIR float random_sample_f(prng_t *prng_state); DECLDIR double random_sample(prng_t *prng_state); -DECLDIR uint32_t random_uint32(prng_t *prng_state); DECLDIR int64_t random_positive_int64(prng_t *prng_state); DECLDIR int32_t random_positive_int32(prng_t *prng_state); DECLDIR long random_positive_int(prng_t *prng_state); diff --git a/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c b/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c index ef98be160b55..4f4ec1d6458d 100644 --- a/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c +++ b/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c @@ -14,17 +14,13 @@ int main() { uint64_t sum = 0; - uint64_t temp; uint32_t seed = 0xDEADBEAF; int i; rk_state state; rk_seed(seed, &state); uint64_t store[N]; for (i = 0; i < N; i++) { - temp = 0; - temp = (uint64_t)rk_random(&state) << 32; - temp |= rk_random(&state); - store[i] = temp; + store[i] = (uint64_t)rk_random(&state); } FILE *fp; @@ -45,10 +41,7 @@ int main() { seed = 0; rk_seed(seed, &state); for (i = 0; i < N; i++) { - temp = 0; - temp = (uint64_t)rk_random(&state) << 32; - temp |= rk_random(&state); - store[i] = temp; + store[i] = (uint64_t)rk_random(&state); } fp = fopen("mt19937-testset-2.csv", "w"); if (fp == NULL) { diff --git a/_randomgen/core_prng/src/pcg64/pcg64.c b/_randomgen/core_prng/src/pcg64/pcg64.c index f51099f3f314..c7c1eb045a41 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.c +++ b/_randomgen/core_prng/src/pcg64/pcg64.c @@ -102,3 +102,17 @@ extern void pcg64_advance(pcg64_state *state, uint64_t *step) { #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; +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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); +} diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/core_prng/src/pcg64/pcg64.h index 8b1746d9d0dc..df265cb1a3a4 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.h +++ b/_randomgen/core_prng/src/pcg64/pcg64.h @@ -61,9 +61,7 @@ inline pcg128_t PCG_128BIT_CONSTANT(uint64_t high, uint64_t low) { #define PCG_EMULATED_128BIT_MATH 1 #endif -typedef struct { - pcg128_t state; -} pcg_state_128; +typedef struct { pcg128_t state; } pcg_state_128; typedef struct { pcg128_t state; @@ -76,8 +74,8 @@ typedef struct { PCG_128BIT_CONSTANT(6364136223846793005ULL, 1442695040888963407ULL) #define PCG_STATE_SETSEQ_128_INITIALIZER \ { \ - PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL), \ - PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ + PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL) \ + , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ } inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { @@ -220,8 +218,10 @@ static inline uint32_t pcg64_next32(pcg64_state *state) { } next = pcg64_random_r(state->pcg_state); state->has_uint32 = 1; - state->uinteger = (uint32_t)(next & 0xffffffff); - return (uint32_t)(next >> 32); + 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); diff --git a/_randomgen/core_prng/src/philox/philox-test-data-gen.c b/_randomgen/core_prng/src/philox/philox-test-data-gen.c index b17dd153b3d0..442e18b559c3 100644 --- a/_randomgen/core_prng/src/philox/philox-test-data-gen.c +++ b/_randomgen/core_prng/src/philox/philox-test-data-gen.c @@ -12,6 +12,7 @@ * */ +#include "../splitmix64/splitmix64.h" #include "Random123/philox.h" #include #include @@ -20,10 +21,15 @@ int main() { philox4x64_ctr_t ctr = {{0, 0, 0, 0}}; - philox4x64_key_t key = {{0, 0xDEADBEAF}}; + 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); @@ -38,7 +44,7 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key, 0x%" PRIx64 ", 0x%" PRIx64 "\n", key.v[0], key.v[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) { @@ -48,8 +54,10 @@ int main() { fclose(fp); ctr.v[0] = 0; - key.v[0] = 0xDEADBEAF; - key.v[1] = 0xFBADBEEF; + 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); @@ -63,7 +71,7 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, "key, 0x%" PRIx64 ", 0x%" PRIx64 "\n", key.v[0], key.v[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) { diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index bc87b3d3a125..d469eabb2adc 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -186,9 +186,8 @@ static INLINE uint64_t philox_next32(philox_state *state) { next = philox_next(state); state->has_uint32 = 1; - state->uinteger = (uint32_t)(next & 0xffffffff); - - return (uint32_t)(next >> 32); + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); } extern void philox_jump(philox_state *state); diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/core_prng/src/splitmix64/splitmix64.h index 0691064428b7..880132970744 100644 --- a/_randomgen/core_prng/src/splitmix64/splitmix64.h +++ b/_randomgen/core_prng/src/splitmix64/splitmix64.h @@ -33,7 +33,7 @@ static inline uint32_t splitmix64_next32(splitmix64_state *state) { return state->uinteger; } next = splitmix64_next64(state); - state->uinteger = next & 0xffffffff; state->has_uint32 = 1; - return (uint32_t)(next >> 32); + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); } diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c index 4494802489e6..444824c1231a 100644 --- a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c +++ b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c @@ -1,10 +1,11 @@ /* * Generate testing csv files * - * cl threefry-test-data-gen.c /Ox + * cl threefry-test-data-gen.c /Ox ../splitmix64/splitmix64.c /Ox * threefry-test-data-gen.exe * - * gcc threefry-test-data-gen.c -o threefry-test-data-gen + * gcc threefry-test-data-gen.c ../splitmix64/splitmix64.c /Ox -o + * threefry-test-data-gen * ./threefry-test-data-gen * * Requres the Random123 directory containing header files to be located in the @@ -12,6 +13,7 @@ * */ +#include "../splitmix64/splitmix64.h" #include "Random123/threefry.h" #include #include @@ -20,10 +22,15 @@ int main() { threefry4x64_key_t ctr = {{0, 0, 0, 0}}; - threefry4x64_ctr_t key = {{0xDEADBEAF, 0, 0, 0}}; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + threefry4x64_ctr_t key = {{0}}; threefry4x64_ctr_t out; uint64_t store[N]; int i, j; + for (i = 0; i < 4; i++) { + key.v[i] = splitmix64_next(&state); + } for (i = 0; i < N / 4UL; i++) { ctr.v[0]++; out = threefry4x64_R(threefry4x64_rounds, ctr, key); @@ -38,9 +45,6 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, - "key, 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 "\n", - key.v[0], key.v[1], key.v[2], key.v[3]); for (i = 0; i < N; i++) { fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { @@ -50,11 +54,11 @@ int main() { fclose(fp); ctr.v[0] = 0; - key.v[0] = 0; - key.v[1] = 0; - key.v[2] = 0xFBADBEEF; - key.v[3] = 0xDEADBEAF; - for (i = 0; i < N / 4UL; i++) { + state = seed = 0; + for (i = 0; i < 4; i++) { + key.v[i] = splitmix64_next(&state); + } + for (i = 0; i < N / 4; i++) { ctr.v[0]++; out = threefry4x64_R(threefry4x64_rounds, ctr, key); for (j = 0; j < 4; j++) { @@ -67,9 +71,6 @@ int main() { printf("Couldn't open file\n"); return -1; } - fprintf(fp, - "key, 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 "\n", - key.v[0], key.v[1], key.v[2], key.v[3]); for (i = 0; i < N; i++) { fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); if (i == 999) { diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index d620f6a1aaca..0b557a00d119 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -328,9 +328,8 @@ static INLINE uint64_t threefry_next32(threefry_state *state) { next = threefry_next(state); state->has_uint32 = 1; - state->uinteger = (uint32_t)(next & 0xffffffff); - - return (uint32_t)(next >> 32); + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); } extern void threefry_jump(threefry_state *state); diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h index ad1ddb194901..3fa5b32e9a46 100644 --- a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h @@ -45,8 +45,8 @@ static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) { } next = xoroshiro128_next(&state->s[0]); state->has_uint32 = 1; - state->uinteger = (uint32_t)(next & 0xffffffff); - return (uint32_t)(next >> 32); + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); } void xoroshiro128_jump(xoroshiro128_state *state); diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h index 2cceee7284f2..998dde06c6b3 100644 --- a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h +++ b/_randomgen/core_prng/src/xorshift1024/xorshift1024.h @@ -38,8 +38,8 @@ static INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { } next = xorshift1024_next(state); state->has_uint32 = 1; - state->uinteger = (uint32_t)(next & 0xffffffff); - return (uint32_t)(next >> 32); + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); } void xorshift1024_jump(xorshift1024_state *state); diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c b/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.c similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift2014.orig.c rename to _randomgen/core_prng/src/xorshift1024/xorshift1024.orig.c diff --git a/_randomgen/core_prng/tests/data/dSFMT-testset-1.csv b/_randomgen/core_prng/tests/data/dSFMT-testset-1.csv new file mode 100644 index 000000000000..9f3f68aeefd2 --- /dev/null +++ b/_randomgen/core_prng/tests/data/dSFMT-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 1 +0, 4607719943344484518 +1, 4611291582431749820 +2, 4609448534071823958 +3, 4611106200950903790 +4, 4609580282971267356 +5, 4609720762470045007 +6, 4607636870422133563 +7, 4611678836133173816 +8, 4610735809705346030 +9, 4608789817543785341 +10, 4610393651369520670 +11, 4611623758339670553 +12, 4608444108616433164 +13, 4607465458608330898 +14, 4610235165931416513 +15, 4608103709635697272 +16, 4608100588970381609 +17, 4608641074646810943 +18, 4608616221842668388 +19, 4607549343270027634 +20, 4610344140656206312 +21, 4610535464314418457 +22, 4611312430982209353 +23, 4607401331162512449 +24, 4609116099984352425 +25, 4611257698187747276 +26, 4607645174989853474 +27, 4608837854111428888 +28, 4608691299413198001 +29, 4608930266190921041 +30, 4608332808182207925 +31, 4608421484748440698 +32, 4608383650014337452 +33, 4611545817730524178 +34, 4611496890204636496 +35, 4610861924086585884 +36, 4608194351754852419 +37, 4610283774852204513 +38, 4609474926233319727 +39, 4608727547276598994 +40, 4609717674488922238 +41, 4609423015229480073 +42, 4609349380679114027 +43, 4610751388265382808 +44, 4607733281112877867 +45, 4610591846531581004 +46, 4610735578621585065 +47, 4611251806424951188 +48, 4609460646876881407 +49, 4611551161354804803 +50, 4611249469634822485 +51, 4608821959551777081 +52, 4610052971574464565 +53, 4607777094091618436 +54, 4610851094220499210 +55, 4607702337070583856 +56, 4611414385520522876 +57, 4611576460026085858 +58, 4611473034943841786 +59, 4608897639026169673 +60, 4607883926313481761 +61, 4608797023994348324 +62, 4610894444453627505 +63, 4608376332448068935 +64, 4609893849888152414 +65, 4610202941918038529 +66, 4611056233415559924 +67, 4610877544761426248 +68, 4610994780372079388 +69, 4609067797141254153 +70, 4610982998126297925 +71, 4610789518257002641 +72, 4610598903890296442 +73, 4608025197953180744 +74, 4610185556158198401 +75, 4608809010429661575 +76, 4608768447244428523 +77, 4609124503281513660 +78, 4611101360372917414 +79, 4611042322702996474 +80, 4610858523716073186 +81, 4610375945852385997 +82, 4608483154301089968 +83, 4607798251963762687 +84, 4609119835265156007 +85, 4609188963843200093 +86, 4607266275697659547 +87, 4610923287424505039 +88, 4609618008081028402 +89, 4608201696292514469 +90, 4611530915051149734 +91, 4607364802882841466 +92, 4611236492431573193 +93, 4610807042893722656 +94, 4610080772943107179 +95, 4608570487813674878 +96, 4610901704116296546 +97, 4610535849683417477 +98, 4609487776344637464 +99, 4607684048114742415 +100, 4609756145565247020 +101, 4609839920313018364 +102, 4607300199263955605 +103, 4608349701001143604 +104, 4608563526536655950 +105, 4608211471894692660 +106, 4611561832400682724 +107, 4607607690303987255 +108, 4609884829632656291 +109, 4610554863807344395 +110, 4609913857729390656 +111, 4608533735726217242 +112, 4611205573734963697 +113, 4608825835576863771 +114, 4611237004326669392 +115, 4609254174450399374 +116, 4607622879864982635 +117, 4610819003887309229 +118, 4607698308712315302 +119, 4607833259972583494 +120, 4607681632288287295 +121, 4607910755187354207 +122, 4611122191561013257 +123, 4611656235846796861 +124, 4610565432604340253 +125, 4610908827351842030 +126, 4611268340320100590 +127, 4609313851656821466 +128, 4608528427564169020 +129, 4608200570336395038 +130, 4610538403125154877 +131, 4608888436053455398 +132, 4611543165544411944 +133, 4610250257231662522 +134, 4609297917742740245 +135, 4610400815978769483 +136, 4610528657337572565 +137, 4610705415667566712 +138, 4611077904559980731 +139, 4609927849369442287 +140, 4609397759777226314 +141, 4609010898016502992 +142, 4609120772081864228 +143, 4607237141609153161 +144, 4610571899308981431 +145, 4609008993363640801 +146, 4610287560785901157 +147, 4608623756174376020 +148, 4608653243870415213 +149, 4609547819331301107 +150, 4609673847833623842 +151, 4608235666485521661 +152, 4610114805542994107 +153, 4610479707694856806 +154, 4609103555741806169 +155, 4608500007602890176 +156, 4610672856146553685 +157, 4611610717675563449 +158, 4610730068759051595 +159, 4608685224971234052 +160, 4609413185190097208 +161, 4608897450787802174 +162, 4607186845514749512 +163, 4607348569795042779 +164, 4611009214373065786 +165, 4609635836233645619 +166, 4610977547720639382 +167, 4610180471225090534 +168, 4608711346241655575 +169, 4608627118356010890 +170, 4611222988628267196 +171, 4610585467803239650 +172, 4608953295299223634 +173, 4610267719343621921 +174, 4608384815012305523 +175, 4610760760005158447 +176, 4609888294496573856 +177, 4608487712307397941 +178, 4610046813921597302 +179, 4607901372889700267 +180, 4611648045743259157 +181, 4611287922111507955 +182, 4609242748471226007 +183, 4607755201380013067 +184, 4611417807283839436 +185, 4609947268752725748 +186, 4610889795243117380 +187, 4610682734427309711 +188, 4609430103755831273 +189, 4610392513282878252 +190, 4608028130931026108 +191, 4609354927353821574 +192, 4607999262827197226 +193, 4608772265877184447 +194, 4611465843018312306 +195, 4607857062574325894 +196, 4610666426888867633 +197, 4610600830920094283 +198, 4609205915408410545 +199, 4607853688411879209 +200, 4607747795491854335 +201, 4608262126937716822 +202, 4611534185487112177 +203, 4610074422869556166 +204, 4609237471248388861 +205, 4609177882315404739 +206, 4607287155741697257 +207, 4611476554139586317 +208, 4609517208333105115 +209, 4607319309983389553 +210, 4608526076922090888 +211, 4610748479257207053 +212, 4609931527304084444 +213, 4608009987636217635 +214, 4610407130291313714 +215, 4608891664598965696 +216, 4610296160139884006 +217, 4611484560328101663 +218, 4611019501503618978 +219, 4610246433435823295 +220, 4608562757718917889 +221, 4607471913719777131 +222, 4611613370049530904 +223, 4608319297993304206 +224, 4607745017639172981 +225, 4609731861577957712 +226, 4609663467149266458 +227, 4609543591294589508 +228, 4608524115958204496 +229, 4611293271186698245 +230, 4610645493162693253 +231, 4607841282620685061 +232, 4608714555579084575 +233, 4608149900642705668 +234, 4609881346718346991 +235, 4609652423006025080 +236, 4610576204477932347 +237, 4608419142720251589 +238, 4609292870725527035 +239, 4607915743890091921 +240, 4610631007573258876 +241, 4611091737638956363 +242, 4610866832498942602 +243, 4608679206316379049 +244, 4611254040795706209 +245, 4608564985000526959 +246, 4609448881222436994 +247, 4611606861023266002 +248, 4608930513670169902 +249, 4607323764955464423 +250, 4607288181905687970 +251, 4610373160370490855 +252, 4608411794278861897 +253, 4610212894218458057 +254, 4610694380708700429 +255, 4609922533346642803 +256, 4609392056590729641 +257, 4609803732845487397 +258, 4608878803170308012 +259, 4611524443328391151 +260, 4608174079771415727 +261, 4607408890033763317 +262, 4607845699541088935 +263, 4611555920103058967 +264, 4607479194613061911 +265, 4607653663534995980 +266, 4610070893479029228 +267, 4611538868870820080 +268, 4608567899678704260 +269, 4608770231079288078 +270, 4610411454914405807 +271, 4607820664883172463 +272, 4610714780751262327 +273, 4607194611952450391 +274, 4609087763682578279 +275, 4608165254026394594 +276, 4609234355157830083 +277, 4609341303623897409 +278, 4607843258265880283 +279, 4609385462693327627 +280, 4610305709185463397 +281, 4607607148427164960 +282, 4608714881122218799 +283, 4609651616092383148 +284, 4609231203213271499 +285, 4611257982347817477 +286, 4610152698091154688 +287, 4608144133423192484 +288, 4610573628352437761 +289, 4608544728261953288 +290, 4610198309467009097 +291, 4610449593868273119 +292, 4610593290392091594 +293, 4609046058809591309 +294, 4611622292530238189 +295, 4610657414068263882 +296, 4611165834719653845 +297, 4610350928332385108 +298, 4611352448760095628 +299, 4609948012409647959 +300, 4610309189747788666 +301, 4607755081207867022 +302, 4610231879852064105 +303, 4607888125265337265 +304, 4609172092280206898 +305, 4608588257784565842 +306, 4607741678424158070 +307, 4609025150930086850 +308, 4609393539064468217 +309, 4610911632660167908 +310, 4610958667007850644 +311, 4611286666277101605 +312, 4609804183682242390 +313, 4611608707704948262 +314, 4609669610113267167 +315, 4607666787328441261 +316, 4607581099645179700 +317, 4610190388918185110 +318, 4610216151360211572 +319, 4608284982213104796 +320, 4609043908200033150 +321, 4610094358636174240 +322, 4607727851642292863 +323, 4607748339680477190 +324, 4610333796608461237 +325, 4611630659133526098 +326, 4611011836822995398 +327, 4611271586336335851 +328, 4608676990846072419 +329, 4610486194528414452 +330, 4607576606876065603 +331, 4607719568700291080 +332, 4608551235063435831 +333, 4611011581816455613 +334, 4608841433006333809 +335, 4609590566174099924 +336, 4610751108417575356 +337, 4609783802139185311 +338, 4610078674097919534 +339, 4608133838483219458 +340, 4609277956691541130 +341, 4608489591310323203 +342, 4608190218485836055 +343, 4611079531841410411 +344, 4608880618309483643 +345, 4608911948674088293 +346, 4611291894381153496 +347, 4608451717289459361 +348, 4608796294882212937 +349, 4608414460486049632 +350, 4607422609721232463 +351, 4608080483385313266 +352, 4607622634488318995 +353, 4609289604313013439 +354, 4609239936097680379 +355, 4608372018123900887 +356, 4610702814261825804 +357, 4611274091783983647 +358, 4611215484124931059 +359, 4608990421919168365 +360, 4609097190054835106 +361, 4610994750415795356 +362, 4611072443902954170 +363, 4608952917718970557 +364, 4608900180943861654 +365, 4608934424322310689 +366, 4609731940535270405 +367, 4610297241526025992 +368, 4608524744985785409 +369, 4610233647335282974 +370, 4609397840502965617 +371, 4609931050226720744 +372, 4607823742164438535 +373, 4607386223202154150 +374, 4611077706407577954 +375, 4608540055157729754 +376, 4610737951147572257 +377, 4610902929285966658 +378, 4611385693211960164 +379, 4607224622379354821 +380, 4609166781986849209 +381, 4608748083335025668 +382, 4610443657454469430 +383, 4610468401119056286 +384, 4610937884247828753 +385, 4609084940396193513 +386, 4611415358123142084 +387, 4610501805353766962 +388, 4607767036448986638 +389, 4607461223165192234 +390, 4608226484980255663 +391, 4611607256659641032 +392, 4609945211367732974 +393, 4609006453263783302 +394, 4610265844375613630 +395, 4607694615392738521 +396, 4608606212547814938 +397, 4610034239111814504 +398, 4610103751968466900 +399, 4611088505838050253 +400, 4608851769231884474 +401, 4610288514235425111 +402, 4608505539036108714 +403, 4611453738759382658 +404, 4611101647329150173 +405, 4607983202842737743 +406, 4607628593913051809 +407, 4610817169808213622 +408, 4610274104936495796 +409, 4607686898188473999 +410, 4611494545938384459 +411, 4609445238317096124 +412, 4609809658023272942 +413, 4610395993443671939 +414, 4609532016275791584 +415, 4610018501692092651 +416, 4608683763430851439 +417, 4608548880896401248 +418, 4610478349829709585 +419, 4607855690965045385 +420, 4609679774972563395 +421, 4609301972366993458 +422, 4609957828433462989 +423, 4611601276026033182 +424, 4610886414042292178 +425, 4610540517589250995 +426, 4609329807459066933 +427, 4611012060649555364 +428, 4611004988464520281 +429, 4610092518739796845 +430, 4608982525313436661 +431, 4610220581774992574 +432, 4608389110412341488 +433, 4610577194017978099 +434, 4607777219986546519 +435, 4608552325706694521 +436, 4609384775042120780 +437, 4610819470183619029 +438, 4608862514454376763 +439, 4608050912492519261 +440, 4609954958938789219 +441, 4611451357502982166 +442, 4607476785936630269 +443, 4611329691194458319 +444, 4610683876885297263 +445, 4608922438780754530 +446, 4607347319284557650 +447, 4610212564213298006 +448, 4607187736152210274 +449, 4607821132969264993 +450, 4610701944842365016 +451, 4609138892484188991 +452, 4607579978932469946 +453, 4608297026731285373 +454, 4609117946354613867 +455, 4609873371753866995 +456, 4609883036162181473 +457, 4610617143057865264 +458, 4609705966715129773 +459, 4609266086686667759 +460, 4611092203109148192 +461, 4607277668644988197 +462, 4610243051742855164 +463, 4611488200475462773 +464, 4610159190694085398 +465, 4607187122077884953 +466, 4609178002227614028 +467, 4607200609172450908 +468, 4607203109970409745 +469, 4610157519627986095 +470, 4608168608616624151 +471, 4607556712879928934 +472, 4610602971628266891 +473, 4607272386871519909 +474, 4609226601189759664 +475, 4608821958178910465 +476, 4610337925540682923 +477, 4607756826141445338 +478, 4610670714123277518 +479, 4609997633318663199 +480, 4610992528318514467 +481, 4610508873379935121 +482, 4610548944839799582 +483, 4608576872646763539 +484, 4611475238517289488 +485, 4609969545809504006 +486, 4611604653736723262 +487, 4610513754499061149 +488, 4610047791400434915 +489, 4610466779122303079 +490, 4609199569907073109 +491, 4611355331378329938 +492, 4609211256613089457 +493, 4611345984656025190 +494, 4609276744577281463 +495, 4610677520254288398 +496, 4611565920468553537 +497, 4608887769347254935 +498, 4607891688277052029 +499, 4611210417809931519 +500, 4609181196197018924 +501, 4608620849445253589 +502, 4610338756450099522 +503, 4610235666137930968 +504, 4610190689620274242 +505, 4608156139098624503 +506, 4610233351376219666 +507, 4611116196066412550 +508, 4611244546095227734 +509, 4608354486449139402 +510, 4608722837522685541 +511, 4607298792335449598 +512, 4610940117180049531 +513, 4609905783847698405 +514, 4611068115688450709 +515, 4609567280627055335 +516, 4609668102454567333 +517, 4608575291283631952 +518, 4608606739858036458 +519, 4609920659405064132 +520, 4609633855399730395 +521, 4607420399082287137 +522, 4607497830797814837 +523, 4608734929795542569 +524, 4611677103224173563 +525, 4609895185651955231 +526, 4608551100268458835 +527, 4608794936863357442 +528, 4608839444940253689 +529, 4609723875823547919 +530, 4609134168731540965 +531, 4610864297289180458 +532, 4609561568240290174 +533, 4609455706988469654 +534, 4610110730269692806 +535, 4607590724900811004 +536, 4609841446856073581 +537, 4607519144944801539 +538, 4610958924924618965 +539, 4608058978781928209 +540, 4608930736822030783 +541, 4610339624224904683 +542, 4611268940884582276 +543, 4611614440252938509 +544, 4610283933065539718 +545, 4610827563929259801 +546, 4610238281320018148 +547, 4609068702417082470 +548, 4609965625349945622 +549, 4610567655464689798 +550, 4609517999871284092 +551, 4608853313183377285 +552, 4608597386123068580 +553, 4608596804275711127 +554, 4608806942254133750 +555, 4611595740982862812 +556, 4610653226348519116 +557, 4610010878229382699 +558, 4611430012536690008 +559, 4608194334909286956 +560, 4609770785529395235 +561, 4609636612234158840 +562, 4610467762650198285 +563, 4611250113292757754 +564, 4611123483515753501 +565, 4610256050464540468 +566, 4611554812085476534 +567, 4609545597507432057 +568, 4610251629953739706 +569, 4608097940038860692 +570, 4608939256004427493 +571, 4609549477949346267 +572, 4607856563525396488 +573, 4608407566119329436 +574, 4610977065049540740 +575, 4608677612836947043 +576, 4611670385382852661 +577, 4609169914628845192 +578, 4608385528780825832 +579, 4608431699759708725 +580, 4610213210579325967 +581, 4607790519129120154 +582, 4611460475578903177 +583, 4611645204412117197 +584, 4611045465835867018 +585, 4610795725227740679 +586, 4607610666986980838 +587, 4607713533366355938 +588, 4608008411737790225 +589, 4607218032541409981 +590, 4610712747455657843 +591, 4607322986186115065 +592, 4608609778168478040 +593, 4609117986895835630 +594, 4608387138944308707 +595, 4609405159006321483 +596, 4609201389487900126 +597, 4610814010656557822 +598, 4610461402205528089 +599, 4608856848982780180 +600, 4610009661369407408 +601, 4609531046728456306 +602, 4608781638378145485 +603, 4611071218907304246 +604, 4607718364365206169 +605, 4610766522014845193 +606, 4610418511682022913 +607, 4611489866910598987 +608, 4611024768525348505 +609, 4608411227740737072 +610, 4608347021514952714 +611, 4607229154687220486 +612, 4609527688395331186 +613, 4608610487126715045 +614, 4610163014754346271 +615, 4610119594096556803 +616, 4609099103543638986 +617, 4607960911715387937 +618, 4610543345562112354 +619, 4611673200269784439 +620, 4607890122556287450 +621, 4610510919142595773 +622, 4611000945873569885 +623, 4609861297670464893 +624, 4607365464269028252 +625, 4610263820456779466 +626, 4608382757430988076 +627, 4608592826360850405 +628, 4607897223655826864 +629, 4608783406301942627 +630, 4610831809342653056 +631, 4610592838071858481 +632, 4607625427481844846 +633, 4610803200293531160 +634, 4607315949328468373 +635, 4609568473332490124 +636, 4608018723588381940 +637, 4610473680670701003 +638, 4608867424437758236 +639, 4607226771732395005 +640, 4607648878101783522 +641, 4608407495823699878 +642, 4609303470297933457 +643, 4607995287639912115 +644, 4610604756706603303 +645, 4608065328364362400 +646, 4607659009213858799 +647, 4609407180393559403 +648, 4610161232799622667 +649, 4608312339248283632 +650, 4611365830215244879 +651, 4609241343071166241 +652, 4607187426157508336 +653, 4611008486844877795 +654, 4609348293209960853 +655, 4611430342690450936 +656, 4610022123422557819 +657, 4610662613803950933 +658, 4610421175429479085 +659, 4609631547889552562 +660, 4609940555785407216 +661, 4609822163096232669 +662, 4608970136612861659 +663, 4609427082274890719 +664, 4608697401879465484 +665, 4611207783165609518 +666, 4611373087590380940 +667, 4610545384528497527 +668, 4607694071454287047 +669, 4607913509258771897 +670, 4607226952976335318 +671, 4611367164497924691 +672, 4610773799850733403 +673, 4608923576905855388 +674, 4610829132227252858 +675, 4611539466506594954 +676, 4607450455252831956 +677, 4607924760556738513 +678, 4609257351177318999 +679, 4607886491020993167 +680, 4607262386448907585 +681, 4608805527475164058 +682, 4608519384875417362 +683, 4609768003609528793 +684, 4607990620996706344 +685, 4608000541499168509 +686, 4607514221391064237 +687, 4610596308708149427 +688, 4608457358343713720 +689, 4611109413177548323 +690, 4609292098957449828 +691, 4608275497070553256 +692, 4609949308659603960 +693, 4610508332440425814 +694, 4610523421224858005 +695, 4611628503654168653 +696, 4608988043865917565 +697, 4609452807254068291 +698, 4611008104380823402 +699, 4609415493514583781 +700, 4608204811849219551 +701, 4608154991732011594 +702, 4609565684575358357 +703, 4607201300980991047 +704, 4611578953897989322 +705, 4608949284388541303 +706, 4608953402339590043 +707, 4611094520261253641 +708, 4611564299263181877 +709, 4611244613212746921 +710, 4607665698546290637 +711, 4609929742865966113 +712, 4608756528459788870 +713, 4608559801324682100 +714, 4611161313083363936 +715, 4610640544822605367 +716, 4610461950314271130 +717, 4608429389531989501 +718, 4610594975443340868 +719, 4610653541215203471 +720, 4610354404384656514 +721, 4611322467270517926 +722, 4609004358268238303 +723, 4610113217342068535 +724, 4607247286313434436 +725, 4607936058322365025 +726, 4607498677954044120 +727, 4607367643972642434 +728, 4610903724213995603 +729, 4608398398619525170 +730, 4609011100867415968 +731, 4609286350498400836 +732, 4610564846286379047 +733, 4610610842418549113 +734, 4609379950548700715 +735, 4608749477629127198 +736, 4609389534628643041 +737, 4609709510894589547 +738, 4609720477301256427 +739, 4610433170873472685 +740, 4607581786915955136 +741, 4610426993537088574 +742, 4609893496842706786 +743, 4608182222083733544 +744, 4607415409292672163 +745, 4608909799371727180 +746, 4609682438519448644 +747, 4609837420608110159 +748, 4607722492204198941 +749, 4608063142644927447 +750, 4611212896211946065 +751, 4610459279330601000 +752, 4610766525803719281 +753, 4610541719260518609 +754, 4608446538192511629 +755, 4608529268885531628 +756, 4607702152237957857 +757, 4608797703031075472 +758, 4607439116134819826 +759, 4608311115301487628 +760, 4611675179452768396 +761, 4608076597967526423 +762, 4611585923502702782 +763, 4611007505903425519 +764, 4610334401882712716 +765, 4611292864862708587 +766, 4610520603991775838 +767, 4610790439348561649 +768, 4608020323209861832 +769, 4609132354146195150 +770, 4611648991029158429 +771, 4608415373761338387 +772, 4611222889759456059 +773, 4610394879407915891 +774, 4611223274533537520 +775, 4611048920373264726 +776, 4611203040226595031 +777, 4608581225592953052 +778, 4607944132899105268 +779, 4610553416357950208 +780, 4609183189134981159 +781, 4610931403284842449 +782, 4609626797792255137 +783, 4608437008274383407 +784, 4608841271194024119 +785, 4609511843950082189 +786, 4608432804080683600 +787, 4607886713946305196 +788, 4610350555892554303 +789, 4611041162152526452 +790, 4608810036185927099 +791, 4609731609025465382 +792, 4608387458587420116 +793, 4608846429123315125 +794, 4610376323596472588 +795, 4609423912646885032 +796, 4609218872949994167 +797, 4611375967003041069 +798, 4609485140993387628 +799, 4607604870717557062 +800, 4609495797464442279 +801, 4611456949409319675 +802, 4610344977769413626 +803, 4610598065942935600 +804, 4608013012863891262 +805, 4610252455143552284 +806, 4607700593028756519 +807, 4610045641566183312 +808, 4609480926180737252 +809, 4610275596338864080 +810, 4607659695464558950 +811, 4607219197645073589 +812, 4608177295501330522 +813, 4611273956331899579 +814, 4610913813005660249 +815, 4608470207120093898 +816, 4608174217124512103 +817, 4610065364926597101 +818, 4607349317207213784 +819, 4607602167222023985 +820, 4607657145979677117 +821, 4611508729708873431 +822, 4607908717595303714 +823, 4609727931398518344 +824, 4609540956592359987 +825, 4610440481396242417 +826, 4611346585992438567 +827, 4611152612229187917 +828, 4610384157247730087 +829, 4610830126611132722 +830, 4610272123470087431 +831, 4607234503905390991 +832, 4610613653079230069 +833, 4609179215008588124 +834, 4608441295871321425 +835, 4608116436734160239 +836, 4607605033373857689 +837, 4610599359267200688 +838, 4611379096030431268 +839, 4609842285031861233 +840, 4611250379332137731 +841, 4608487405142537379 +842, 4607380789043538335 +843, 4609546285413174259 +844, 4608919052624376420 +845, 4611474363794717141 +846, 4611079221421189606 +847, 4607871497110868045 +848, 4608251852430693481 +849, 4611271625089563201 +850, 4608142282722604751 +851, 4610614961087854140 +852, 4611030874745849847 +853, 4609674534508351596 +854, 4610748124279118172 +855, 4610214076525417764 +856, 4608915989016466776 +857, 4611186209375381383 +858, 4609729165373960964 +859, 4608171107224247283 +860, 4608322267844345836 +861, 4611385726702876896 +862, 4607526082606428148 +863, 4609300797912528830 +864, 4607995042613073018 +865, 4609544162095522243 +866, 4607273392907536721 +867, 4610915254133616443 +868, 4608528592480458486 +869, 4611065489354804147 +870, 4610750286707033259 +871, 4609777244768435300 +872, 4610807148417457906 +873, 4607877316209555589 +874, 4610316726265842451 +875, 4608771732565061950 +876, 4611471267762612145 +877, 4607984815868159369 +878, 4608744077489931245 +879, 4611032300367986435 +880, 4609572801223705776 +881, 4607388928679638867 +882, 4610440380910085523 +883, 4611677400759288526 +884, 4608231223120382380 +885, 4609826308636672129 +886, 4610729764513821105 +887, 4608945691565841376 +888, 4608283276108322908 +889, 4611090204591740692 +890, 4610600988861462466 +891, 4608814357404053556 +892, 4611331328900205001 +893, 4610440474296736006 +894, 4607431388306045801 +895, 4610821334292221218 +896, 4608554210663333875 +897, 4609824397495829498 +898, 4607541211343519985 +899, 4608435017263349928 +900, 4607219271691108353 +901, 4608430070452421044 +902, 4609082847439943417 +903, 4610866784520449850 +904, 4608287501071307688 +905, 4609218510235145503 +906, 4608114112360957267 +907, 4609922412275378983 +908, 4608601574612929512 +909, 4608063236537296892 +910, 4610507352144992045 +911, 4610831100303954067 +912, 4610989778846895898 +913, 4611131006465079227 +914, 4607610719457154999 +915, 4610658650342157966 +916, 4607418499615550301 +917, 4610402445180375078 +918, 4610463803051786556 +919, 4610040245423397003 +920, 4610291132556872432 +921, 4610915180727115233 +922, 4607198239226330244 +923, 4610719993407015954 +924, 4608790436210431943 +925, 4611518788065155885 +926, 4609410806758155597 +927, 4610354727542013410 +928, 4609032496183417847 +929, 4607612835462448389 +930, 4609119308314247716 +931, 4610676295665807893 +932, 4610030018059715751 +933, 4610396681520935881 +934, 4610115299841718605 +935, 4610531703556384068 +936, 4607313656834232832 +937, 4607826054856970203 +938, 4609717410497090129 +939, 4609043343821435147 +940, 4607629724646231370 +941, 4611347190635269674 +942, 4607431356324177025 +943, 4609743147159956874 +944, 4608919951624732686 +945, 4608549836830011507 +946, 4609835749585271216 +947, 4610001878208091800 +948, 4607727638454636808 +949, 4608140523490695322 +950, 4610951723878037203 +951, 4609561113218416843 +952, 4607375879120504969 +953, 4610968421496640577 +954, 4608729663137359994 +955, 4611521561048982293 +956, 4607647181466306462 +957, 4608815536941397702 +958, 4611410078681334217 +959, 4610883601143579986 +960, 4609217767853028115 +961, 4610569694955441160 +962, 4608142872889589658 +963, 4609078496262967192 +964, 4610075946790752678 +965, 4607952350453678296 +966, 4610919620741525096 +967, 4611050224420434596 +968, 4608163018441029734 +969, 4611368242936987963 +970, 4607644493316907613 +971, 4611292201819050900 +972, 4610919228494056420 +973, 4607225037781465524 +974, 4609803354294636294 +975, 4610012640039408504 +976, 4610054964621136538 +977, 4609178240405976665 +978, 4607687932449852507 +979, 4609284420963602445 +980, 4609123874172501167 +981, 4608282636137081729 +982, 4609729376153713229 +983, 4611206065074370636 +984, 4609819396180228727 +985, 4610891933717707670 +986, 4608390654319867654 +987, 4610530001352182832 +988, 4608968440000980355 +989, 4611276663454436837 +990, 4609638657758409036 +991, 4610986200094730228 +992, 4610734380577234553 +993, 4609408663096464249 +994, 4609878290485950846 +995, 4607522064640469547 +996, 4610791378999926894 +997, 4607540164715119602 +998, 4609346418539511860 +999, 4611057822391293948 diff --git a/_randomgen/core_prng/tests/data/dSFMT-testset-2.csv b/_randomgen/core_prng/tests/data/dSFMT-testset-2.csv new file mode 100644 index 000000000000..2ec2d7a51cb1 --- /dev/null +++ b/_randomgen/core_prng/tests/data/dSFMT-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 123456789 +0, 4611184391270596398 +1, 4607748002806405513 +2, 4610950593283603895 +3, 4608090221984835117 +4, 4608620401509188549 +5, 4608933259318787038 +6, 4609013189947794152 +7, 4610981701838014712 +8, 4607749361849391199 +9, 4607937126452632796 +10, 4607787877636103702 +11, 4610534911848167216 +12, 4610758085486021829 +13, 4608376900672555174 +14, 4611475749905869564 +15, 4610499914926478618 +16, 4610900925684457179 +17, 4609184136046668572 +18, 4610480821748015478 +19, 4609898134786890046 +20, 4610017288264709787 +21, 4610945461469807520 +22, 4611377383751342990 +23, 4610945102533068783 +24, 4611669662318553242 +25, 4609191925356202514 +26, 4607369493394647937 +27, 4610171428966243908 +28, 4608117572388953111 +29, 4608266910229155519 +30, 4608559463354581151 +31, 4608291596231703883 +32, 4609993154230249063 +33, 4608158820656759750 +34, 4607825861011031752 +35, 4611091529260321033 +36, 4609803558980700204 +37, 4610892045184692457 +38, 4607844754686911799 +39, 4609239584278564809 +40, 4608975935937490223 +41, 4611186452462884146 +42, 4610644474758878544 +43, 4608188546959932195 +44, 4610317408616093972 +45, 4607827178108179262 +46, 4611275432938764949 +47, 4608511443742655969 +48, 4607200952336491646 +49, 4609727773590041393 +50, 4609137674464229063 +51, 4611529391150713249 +52, 4607446200291229812 +53, 4608618724431091553 +54, 4608231197118968153 +55, 4609848377535763472 +56, 4609769454787363651 +57, 4609093431634418146 +58, 4610941233823434235 +59, 4609301175512188901 +60, 4610884340334734656 +61, 4610063958683836346 +62, 4607897080185028324 +63, 4610305504370096344 +64, 4609499707572786607 +65, 4609874865902334026 +66, 4610351583670684094 +67, 4607292638794148255 +68, 4609412782688385863 +69, 4610390851314330496 +70, 4610340712140767101 +71, 4611109929809487388 +72, 4608431958302562464 +73, 4611491800847619506 +74, 4611664179902108071 +75, 4609243488780021515 +76, 4611114015923144350 +77, 4608524512724098287 +78, 4610450327089558934 +79, 4608720370826377375 +80, 4609572763010883699 +81, 4610381056495781763 +82, 4610005210825690556 +83, 4610341565220388232 +84, 4609034688757121677 +85, 4608823563858030255 +86, 4607971981785212736 +87, 4608714648124969040 +88, 4608968779454607977 +89, 4607272316660152324 +90, 4610748035362895446 +91, 4611319709331049410 +92, 4611390662594804501 +93, 4610054939662414847 +94, 4610394601776085983 +95, 4611424622746948620 +96, 4609395571329163407 +97, 4608527159228147662 +98, 4608379506646233343 +99, 4608996098073467200 +100, 4609633861067625056 +101, 4609387288473331641 +102, 4609369354653726335 +103, 4609305386464755625 +104, 4609085462578529471 +105, 4607213117834450226 +106, 4608676147693465985 +107, 4609894016428056597 +108, 4610808023909042858 +109, 4608152398284126687 +110, 4608864655829389907 +111, 4608853043279974421 +112, 4609998495057236534 +113, 4610971344400740897 +114, 4610947677840469570 +115, 4608888205458648733 +116, 4607306226266885750 +117, 4609476897174960733 +118, 4609298769587075756 +119, 4608046849854182276 +120, 4607709982476583693 +121, 4608905629015127110 +122, 4610027478304152622 +123, 4610378827605636632 +124, 4609168469605184889 +125, 4608424320664524511 +126, 4611224145925927248 +127, 4610598390440508158 +128, 4607548101463088366 +129, 4610445109429344448 +130, 4608982837349247842 +131, 4611526772283530460 +132, 4609215133306156120 +133, 4610747257006687691 +134, 4611305960482481336 +135, 4610602687315818756 +136, 4607839670910202130 +137, 4610527601541091852 +138, 4611462737727028786 +139, 4609212169757271808 +140, 4608447721028771557 +141, 4608224903291976145 +142, 4607298632533980318 +143, 4607975637289743494 +144, 4608776340673956742 +145, 4608578170133208214 +146, 4611177429384019220 +147, 4607665628038835535 +148, 4609531011383000577 +149, 4609360969802432085 +150, 4609908488618542164 +151, 4607366945146869514 +152, 4610136614778041377 +153, 4611168569218164361 +154, 4610462572118833671 +155, 4608070981696376487 +156, 4611058778037833630 +157, 4608159294705821382 +158, 4607530053661949689 +159, 4609136441084496096 +160, 4609331241894336822 +161, 4611313107630037707 +162, 4607957053472625207 +163, 4609675126838719650 +164, 4609482958203648215 +165, 4609691585561697624 +166, 4611475423312731438 +167, 4611412076067906505 +168, 4610429355560523848 +169, 4610625875093760541 +170, 4607241368914269823 +171, 4608589893979475221 +172, 4610073186156188115 +173, 4607291233411155158 +174, 4607675047628278616 +175, 4610869395774400226 +176, 4610232438803745722 +177, 4611554162813131112 +178, 4611642473714833781 +179, 4610563419014907913 +180, 4608459192490850885 +181, 4610780149188594220 +182, 4608960376226045768 +183, 4609069361322693819 +184, 4607256923555182400 +185, 4608474664242579394 +186, 4610207389506744572 +187, 4609112003475072746 +188, 4609240603140788354 +189, 4607525348408117354 +190, 4611149396864007205 +191, 4609114686465130118 +192, 4608849128028589904 +193, 4607248401924217556 +194, 4611387244175010347 +195, 4610567855974092668 +196, 4608169346845917282 +197, 4608490452199719856 +198, 4611203596728963611 +199, 4609287639795895008 +200, 4611614031789088265 +201, 4607236671819565824 +202, 4607466608820858068 +203, 4609639323480231358 +204, 4611254610116912557 +205, 4608807229543638034 +206, 4608381564380368174 +207, 4607428682272410485 +208, 4611229637925604134 +209, 4609236526826003496 +210, 4608889880949328886 +211, 4611135901473627148 +212, 4609923185324027506 +213, 4608879482743843897 +214, 4607662449177713187 +215, 4609980811569949840 +216, 4608275147595190524 +217, 4610799005466054235 +218, 4607667917597769158 +219, 4610185589593486163 +220, 4607529819757965470 +221, 4608839547249506178 +222, 4607706145147011973 +223, 4610988495472186250 +224, 4611534361958731542 +225, 4611641549824093970 +226, 4607316484858856298 +227, 4608641757303921184 +228, 4609375357848069574 +229, 4610565635665894453 +230, 4611147322350665952 +231, 4610071054475069545 +232, 4608886005124134993 +233, 4611384240695070553 +234, 4609556577749744408 +235, 4607688273402525356 +236, 4609395656487625483 +237, 4607920617948366178 +238, 4608233544953726639 +239, 4607736865102992897 +240, 4611554956498550667 +241, 4608735997467283056 +242, 4608499613076219431 +243, 4607926707839352263 +244, 4607349468190181214 +245, 4607855564980078814 +246, 4608566548361033733 +247, 4608689878198670581 +248, 4607485839302113425 +249, 4611493753178685166 +250, 4608566613320387204 +251, 4609743179886038389 +252, 4610508594994820223 +253, 4608995913792958562 +254, 4610248353463386070 +255, 4609788192124211795 +256, 4610619330306161425 +257, 4610873599325465005 +258, 4607324385499645328 +259, 4610611165167596515 +260, 4608006298637673371 +261, 4608540339048264499 +262, 4609631136716349669 +263, 4608685013736282276 +264, 4607363759784022848 +265, 4609492611310929004 +266, 4607780070180818716 +267, 4611531753698196550 +268, 4609227266216837458 +269, 4609211002065400677 +270, 4610668395253295080 +271, 4609134381345731597 +272, 4609382192034225627 +273, 4607208308209034488 +274, 4610579328733327647 +275, 4608921603525338555 +276, 4608290209927931669 +277, 4610866583781415461 +278, 4608182329361248100 +279, 4611648549813945436 +280, 4608601920453704621 +281, 4607406218324299637 +282, 4610748358143595351 +283, 4607437422367397844 +284, 4610299319830347312 +285, 4607992330520188137 +286, 4607658701765777668 +287, 4610721959305012250 +288, 4608971493894533044 +289, 4610010722223631500 +290, 4611050493332836673 +291, 4611164520867402836 +292, 4610619993846650787 +293, 4610600062391983254 +294, 4610986071470687711 +295, 4607815296700712791 +296, 4608678841251990428 +297, 4609887779099788759 +298, 4609503319862290027 +299, 4608809762931362117 +300, 4608037449870401927 +301, 4607755403017924034 +302, 4609087730452781738 +303, 4608773046045154889 +304, 4609803415624001168 +305, 4610998875554212160 +306, 4610380022165388956 +307, 4607984105708776524 +308, 4607847620250154418 +309, 4609666480042052524 +310, 4609307223459772378 +311, 4610669103098622941 +312, 4611513493576426284 +313, 4610110724985187558 +314, 4607584875859460118 +315, 4607466337518526743 +316, 4610953875036984820 +317, 4608473324196281668 +318, 4610528420574205379 +319, 4611218523029715214 +320, 4609404517070225101 +321, 4610679296055932161 +322, 4611602007192673713 +323, 4608768227857799294 +324, 4611351262607349204 +325, 4608656666931918232 +326, 4607814222059811944 +327, 4610377735718844205 +328, 4609693488663627404 +329, 4607234605916181353 +330, 4610438458653690136 +331, 4607691881688829838 +332, 4610084067104393530 +333, 4610193058189981242 +334, 4610500065590109969 +335, 4608182288567589802 +336, 4610884979206264676 +337, 4607934930963198287 +338, 4608198333740812601 +339, 4611615912551444803 +340, 4611091273781746311 +341, 4609878217869378267 +342, 4610329799427547900 +343, 4608946066069950044 +344, 4610517372931467061 +345, 4610173879547218394 +346, 4610768143539619524 +347, 4608251912463490886 +348, 4609138858501301814 +349, 4609537774087558923 +350, 4607501599203475779 +351, 4608820206286486654 +352, 4607594549608867563 +353, 4608928529430502872 +354, 4610326793501581341 +355, 4609216901643916714 +356, 4609921023396761286 +357, 4610188250845345370 +358, 4609056567531193554 +359, 4608042356944953893 +360, 4611153374110275273 +361, 4607652688871602388 +362, 4607736758450185452 +363, 4607772815382776660 +364, 4610793989334300613 +365, 4610810029813744832 +366, 4608713713202824549 +367, 4610555523666319407 +368, 4608933966316349782 +369, 4610847233909664040 +370, 4610569003709254271 +371, 4610141934611190870 +372, 4609800637427386711 +373, 4609531911954538534 +374, 4610018946619778104 +375, 4607563033735657544 +376, 4609466294634090519 +377, 4609110904485970900 +378, 4608802716203741548 +379, 4611231193234792818 +380, 4609853965624850005 +381, 4607407678664700238 +382, 4611560957363283790 +383, 4607258843130776963 +384, 4607438437753792222 +385, 4610880518315386981 +386, 4608724997072138032 +387, 4607896367882266335 +388, 4609466683623316620 +389, 4609649679136642775 +390, 4607572059242669390 +391, 4610690224087953221 +392, 4607212888873300995 +393, 4610115548532567091 +394, 4611204182849533970 +395, 4611480154563209673 +396, 4607313745181304733 +397, 4609677304468142434 +398, 4608230866091821000 +399, 4607916785319391722 +400, 4607735989143160304 +401, 4608364795273033367 +402, 4608202139927885958 +403, 4608897400704372931 +404, 4611267249785141575 +405, 4609988674862878902 +406, 4607825900064550736 +407, 4611018040541037989 +408, 4608438772151688632 +409, 4610422591938237999 +410, 4607217184553988938 +411, 4607633087503746743 +412, 4609394147749351901 +413, 4608101641384193571 +414, 4609733515509206078 +415, 4611489547250433971 +416, 4607834589624331833 +417, 4611349716992792673 +418, 4609707846875238752 +419, 4607311797705362203 +420, 4608945328148355588 +421, 4611273525690510581 +422, 4611458884537996759 +423, 4607997755969685936 +424, 4609048489714323017 +425, 4610334128017869552 +426, 4607485869716832613 +427, 4607547499540098372 +428, 4611447798198333473 +429, 4607207442813565439 +430, 4611108178646490883 +431, 4609758124675924332 +432, 4610269457948568827 +433, 4607360068671694963 +434, 4607781179483110631 +435, 4610840076859630697 +436, 4609605188868326206 +437, 4610833404575495679 +438, 4609202151986229830 +439, 4607653465598307819 +440, 4610341806509732173 +441, 4608937637268370608 +442, 4608846981481205936 +443, 4609890399657918800 +444, 4607475810914216914 +445, 4610779510882657410 +446, 4607200291019787105 +447, 4608763897810030884 +448, 4611030953084521579 +449, 4610608205209840707 +450, 4609901665329352338 +451, 4608229933322773774 +452, 4608306405922059711 +453, 4609402784224466904 +454, 4607797912916831810 +455, 4609320676286567523 +456, 4611203509963612873 +457, 4609443449463211381 +458, 4611201121136708490 +459, 4607891679344035909 +460, 4609295647591940857 +461, 4608699650823090334 +462, 4610113773137160513 +463, 4609644998840868353 +464, 4607236971413190205 +465, 4610986387001985169 +466, 4607686165213831157 +467, 4608006708913412573 +468, 4611617607231087789 +469, 4607950605030537282 +470, 4611312308422726037 +471, 4609920921889730694 +472, 4611272051294701454 +473, 4610732866915233164 +474, 4611475736494024667 +475, 4609129855793761412 +476, 4610896503566695638 +477, 4608983293576256239 +478, 4611337113271775442 +479, 4607264202049306366 +480, 4609273459645222412 +481, 4607686257312802596 +482, 4610552669683473434 +483, 4609573159080816112 +484, 4610109994193793014 +485, 4609104807624348930 +486, 4609056640876615682 +487, 4611233171931551808 +488, 4610700243077601839 +489, 4609689839939656894 +490, 4608154258714850667 +491, 4611519937102265713 +492, 4608524210713510379 +493, 4609408429794931452 +494, 4608727835041307081 +495, 4608363974471195432 +496, 4611053981101408157 +497, 4611244348235020563 +498, 4611215359362792075 +499, 4611323939601701219 +500, 4607339198007393537 +501, 4611192785515763411 +502, 4609520870364372480 +503, 4610305448099707859 +504, 4607627137213702268 +505, 4609512376112901200 +506, 4607188668249670063 +507, 4611507107596430103 +508, 4611290552034620332 +509, 4610948015281142465 +510, 4610082188797301672 +511, 4611154579920165202 +512, 4607910614898084038 +513, 4609111687709912685 +514, 4607756890586988655 +515, 4611478346930052063 +516, 4610271854072480776 +517, 4607666773584055448 +518, 4611269065667018778 +519, 4607229932372594880 +520, 4609361761863029782 +521, 4610810902409829664 +522, 4608310590726885309 +523, 4611549741777094242 +524, 4608905382237807476 +525, 4607539324166606283 +526, 4611302527859497090 +527, 4607673514510851852 +528, 4610239139758062881 +529, 4608296614307074920 +530, 4611131538327332418 +531, 4610491790884660304 +532, 4608012090568842826 +533, 4611145939579689859 +534, 4611569174305843109 +535, 4607548241749347055 +536, 4611302507266314629 +537, 4607334076415859573 +538, 4610759794541675536 +539, 4611562195466283509 +540, 4608064277646826273 +541, 4611362206697199696 +542, 4611267027417975453 +543, 4609817290222129321 +544, 4610075404291128380 +545, 4609555606129743990 +546, 4607220569899493231 +547, 4611584841957177930 +548, 4609037839026191075 +549, 4611594336803497113 +550, 4607225960438616513 +551, 4609362154617705500 +552, 4609887291423254556 +553, 4608541390551696577 +554, 4608696812349818364 +555, 4608371224718817057 +556, 4610715234165102256 +557, 4607906422122850842 +558, 4610831254800690212 +559, 4607810400373332275 +560, 4608705747590604299 +561, 4608938946760670556 +562, 4610310158116436046 +563, 4610355131502528018 +564, 4609768625905121586 +565, 4610143261296345738 +566, 4611431373682787281 +567, 4608146686998001641 +568, 4609198539721817636 +569, 4608916158230506393 +570, 4607654288747635129 +571, 4611682519183492769 +572, 4607197631212679817 +573, 4607299807028695407 +574, 4609116180622479613 +575, 4611019095836572557 +576, 4608581189094026112 +577, 4607488328508280547 +578, 4608587490233232612 +579, 4607245708447615950 +580, 4607189799494915135 +581, 4609348574263949313 +582, 4608021918670812153 +583, 4608172706554967110 +584, 4608811025395016288 +585, 4609364751750743520 +586, 4607844470980185823 +587, 4609405096277516268 +588, 4607748139765213490 +589, 4608512257043070004 +590, 4609962195184017357 +591, 4608461665680660962 +592, 4611127630212845842 +593, 4609686172238940069 +594, 4608777755231651430 +595, 4608284543534209439 +596, 4610868067515254496 +597, 4611535716997037852 +598, 4611319738221220860 +599, 4608658969391651641 +600, 4609452813595548756 +601, 4610236109831493974 +602, 4609938178451088584 +603, 4610331640367617101 +604, 4610901433958649983 +605, 4609766058585980491 +606, 4609222434831315585 +607, 4609778306904942608 +608, 4609448207660443683 +609, 4611299794046339746 +610, 4607801595505703392 +611, 4609594326292439532 +612, 4607668862605395543 +613, 4608245023900457864 +614, 4610578512588843180 +615, 4608185699959219467 +616, 4610904181340375013 +617, 4610647304739305074 +618, 4609795287579987586 +619, 4607960349041110093 +620, 4607703003215776639 +621, 4609403905570407605 +622, 4611233143041131400 +623, 4610530479829073842 +624, 4610679919769197229 +625, 4611448708224350289 +626, 4611445633822299312 +627, 4610496480556319861 +628, 4609555553457224207 +629, 4607626163577357218 +630, 4608595404165123581 +631, 4610510352711119715 +632, 4610203134139830798 +633, 4607550008954478579 +634, 4611603434572420257 +635, 4609780364056746558 +636, 4607295948877799964 +637, 4609867047995237092 +638, 4607936708021896797 +639, 4608897965423418533 +640, 4611287469240086203 +641, 4608515945123070881 +642, 4609851530250371283 +643, 4607577382199018499 +644, 4607744147814966969 +645, 4607260472041943130 +646, 4610683962948666275 +647, 4609625943316701593 +648, 4607251851603159602 +649, 4608016163551470839 +650, 4607202891515091580 +651, 4609099272171658208 +652, 4608510662830783836 +653, 4607744672536335386 +654, 4608142194450948613 +655, 4609476103099505412 +656, 4611399217441119768 +657, 4611495773005281088 +658, 4608815211248586470 +659, 4607337589064315457 +660, 4611394644152964336 +661, 4610812001439064700 +662, 4610702350009793284 +663, 4611075442411386625 +664, 4611077060876180663 +665, 4608164209437610624 +666, 4611368259599962784 +667, 4608333197470863467 +668, 4607183015995911227 +669, 4607199710185468635 +670, 4609413972037912933 +671, 4609234714230829818 +672, 4607739028685645905 +673, 4608232319438231981 +674, 4609333542787352994 +675, 4607657722219109388 +676, 4609193924059916664 +677, 4611141187805060655 +678, 4611068281150742947 +679, 4610549552759132313 +680, 4610085533805630329 +681, 4607232810679281805 +682, 4608493447592041083 +683, 4607355443052807819 +684, 4608410340438808883 +685, 4610315775824782427 +686, 4610312241247357403 +687, 4611287815156776852 +688, 4608076401857758978 +689, 4607457081882300105 +690, 4610908420357480199 +691, 4609797527119137644 +692, 4607351051017728429 +693, 4607618982820305008 +694, 4609846699151054310 +695, 4609389871379854176 +696, 4611243148153910479 +697, 4609270449294231868 +698, 4610832482336321517 +699, 4608101914557495685 +700, 4609128450704503077 +701, 4607351438344234793 +702, 4610010340063776057 +703, 4608461610523881117 +704, 4607869099658377415 +705, 4611211613048598168 +706, 4611196065771110369 +707, 4610515053922650643 +708, 4610096469861694516 +709, 4610477093507778048 +710, 4611547661480689243 +711, 4608438911039690892 +712, 4611311311815318674 +713, 4609279386396407118 +714, 4608222142760880731 +715, 4611613394716251191 +716, 4607603661150022989 +717, 4610135239835120022 +718, 4610929039427992532 +719, 4610757208246529003 +720, 4610920496514785256 +721, 4607326205191641070 +722, 4607938491595237155 +723, 4608585902537439220 +724, 4609326104534891368 +725, 4609325776820376036 +726, 4609693740995539995 +727, 4611329366056096595 +728, 4609303022615335557 +729, 4611512548552170265 +730, 4610404528899365728 +731, 4608023620660481005 +732, 4609431135637339890 +733, 4610767321626117704 +734, 4611106580332635792 +735, 4607433026987401919 +736, 4609580917376189588 +737, 4608816125719706388 +738, 4608380327649573838 +739, 4608700977565012592 +740, 4609148128564608995 +741, 4609631585490496912 +742, 4610745913090661333 +743, 4607498234984630394 +744, 4608367220496728902 +745, 4608365876885021447 +746, 4611537321062599251 +747, 4611238252705917535 +748, 4607525503355262497 +749, 4610601812175940986 +750, 4610145907668011789 +751, 4610384184669464682 +752, 4610699305276533889 +753, 4611440399153628650 +754, 4607963045023571960 +755, 4611498554915678298 +756, 4609015832347581911 +757, 4610795942139040060 +758, 4608894432143218464 +759, 4609704019108678046 +760, 4608168143636007672 +761, 4609566697927636482 +762, 4608690694207868944 +763, 4607746195488024521 +764, 4608350743731006452 +765, 4608442252024570087 +766, 4608428784099249674 +767, 4608941009071857822 +768, 4609298165329524240 +769, 4610447927377989769 +770, 4608304643580688447 +771, 4611265394576506233 +772, 4611210499769545678 +773, 4610114198739241967 +774, 4610653279632780678 +775, 4609515286518383576 +776, 4607984314013723903 +777, 4611541983726033367 +778, 4611393756437132236 +779, 4608968117844197920 +780, 4609367443784351367 +781, 4609488775108334110 +782, 4607529648757616057 +783, 4610676930934349350 +784, 4607750265025461672 +785, 4610373465791644318 +786, 4609305678766837551 +787, 4608947449753189724 +788, 4610366767677719066 +789, 4610439177886004542 +790, 4611242968978180676 +791, 4609370292455902521 +792, 4607754584885122450 +793, 4611224375496789735 +794, 4608921239858925416 +795, 4609513753577022933 +796, 4608075523570985167 +797, 4608608957047081948 +798, 4611273688846153770 +799, 4608394757574873003 +800, 4610377036529664140 +801, 4608600356910393592 +802, 4609667431524003711 +803, 4608601585637259149 +804, 4611533564639785432 +805, 4607510309835958191 +806, 4609651505654903275 +807, 4608166496451053374 +808, 4609515171183335141 +809, 4609776525693204395 +810, 4607696284598399608 +811, 4608607508956363891 +812, 4609695267960623947 +813, 4607576367302408137 +814, 4608741052307396862 +815, 4611095472713646530 +816, 4610161900255157770 +817, 4609145054582502965 +818, 4607410140376051944 +819, 4608126518935915215 +820, 4608269617716261203 +821, 4609477491264110038 +822, 4607463147955504958 +823, 4608999294660391637 +824, 4608694924732427850 +825, 4611156031005634796 +826, 4608453663346634965 +827, 4611380857524502488 +828, 4611362793875369801 +829, 4611632478058955853 +830, 4609434664425350531 +831, 4607606564530411276 +832, 4607391976443208678 +833, 4607762558563019180 +834, 4608554249145639939 +835, 4607806692993216225 +836, 4609510831152869655 +837, 4608164624489904634 +838, 4608455009317767175 +839, 4607280108540066925 +840, 4610080527249430824 +841, 4608840198094196329 +842, 4608916984669714190 +843, 4609771655387294402 +844, 4611351501375292078 +845, 4610356649846014183 +846, 4609861702465798084 +847, 4609335612683847594 +848, 4608963836668425606 +849, 4611448716653608808 +850, 4611618237088472583 +851, 4607650248665393412 +852, 4609477068480641193 +853, 4611408250260317487 +854, 4607799702152927524 +855, 4608984567553844241 +856, 4608966215304179278 +857, 4607599007502108199 +858, 4611197470586031919 +859, 4607738821906038713 +860, 4610174343711771016 +861, 4609411396159113704 +862, 4610528341790372072 +863, 4610621185894682737 +864, 4611164850264296206 +865, 4607500722733965482 +866, 4608747074062289526 +867, 4609587390330409056 +868, 4608013778287410191 +869, 4609438917309909895 +870, 4611359511257377419 +871, 4611161903145694224 +872, 4609908825458581349 +873, 4609974364203149964 +874, 4608056454984693014 +875, 4607485841556578933 +876, 4607689636557505920 +877, 4607225026099434704 +878, 4608918180817633858 +879, 4607389899324828547 +880, 4609528891100730648 +881, 4609347474444270651 +882, 4610604256334495724 +883, 4607717534965049292 +884, 4607416814400338843 +885, 4609568365470566179 +886, 4609490489177847460 +887, 4609959177607409888 +888, 4608249931585238164 +889, 4608374394377617948 +890, 4609359264913370700 +891, 4610789661266619275 +892, 4607881230950036624 +893, 4608163786355022310 +894, 4608830462616805753 +895, 4609531962596587483 +896, 4610555549279318514 +897, 4610008765530009024 +898, 4609509527271380682 +899, 4608445793235798406 +900, 4608895922045956617 +901, 4611496044586314375 +902, 4609855938206283389 +903, 4610584515201059904 +904, 4608185787632733541 +905, 4609925998848840417 +906, 4609746471060930910 +907, 4608322802169846228 +908, 4611668609080045996 +909, 4610918346613262546 +910, 4607487495258046096 +911, 4610091716845110326 +912, 4611060358092721143 +913, 4610617258787020006 +914, 4607968616643301279 +915, 4607216453440634248 +916, 4607683961727519867 +917, 4610192441377241514 +918, 4611340079503032986 +919, 4607737818907905432 +920, 4608040273267030617 +921, 4609075420363483026 +922, 4610025209467938351 +923, 4608669897432477872 +924, 4608611467736828996 +925, 4610963769428151250 +926, 4611230933830803123 +927, 4609892039139108424 +928, 4608322827835753071 +929, 4608048405227745232 +930, 4611336950552458383 +931, 4609990562309176924 +932, 4608539034786829718 +933, 4609715165139430182 +934, 4608805499266985258 +935, 4607728070995330274 +936, 4608780877909747196 +937, 4607569412899178661 +938, 4607268788340312926 +939, 4608510300788384404 +940, 4609202712081615466 +941, 4609583146251705462 +942, 4610981698790205568 +943, 4607925526524476327 +944, 4607793604049723576 +945, 4610915422726587727 +946, 4607690153123448022 +947, 4610957908781080072 +948, 4609688199240625930 +949, 4609195637372175715 +950, 4607455193109906152 +951, 4607614996131060051 +952, 4607821739007708428 +953, 4611432473374206640 +954, 4609331676904204846 +955, 4607810059335115947 +956, 4611077768988065423 +957, 4611510065592294343 +958, 4608753144000455824 +959, 4610618261702230984 +960, 4609478955747078670 +961, 4608250680894683660 +962, 4611056070648131063 +963, 4607756102257795122 +964, 4610370838903190290 +965, 4611412764774525666 +966, 4609100881666906368 +967, 4610119679924928715 +968, 4609686905253473358 +969, 4608711239949443984 +970, 4607839187561408271 +971, 4609413459785445169 +972, 4609209994304368132 +973, 4609118705149046785 +974, 4607291458128247233 +975, 4611161411572838996 +976, 4610256654040673624 +977, 4608882855825268963 +978, 4609049328169514708 +979, 4609651814435298462 +980, 4609304465056789103 +981, 4607682759379096849 +982, 4609946393233090661 +983, 4609946524554590950 +984, 4610880973039636436 +985, 4607217356662986962 +986, 4608230276563898969 +987, 4610664933477117472 +988, 4607562227262100270 +989, 4610133121835039282 +990, 4609071027656845298 +991, 4610444138469204749 +992, 4607185460608050805 +993, 4609895459462574326 +994, 4610016322490782234 +995, 4609380549113996677 +996, 4609371524623560982 +997, 4610108153607631096 +998, 4607489006177078361 +999, 4607632190656691768 diff --git a/_randomgen/core_prng/tests/data/mt19937-testset-1.csv b/_randomgen/core_prng/tests/data/mt19937-testset-1.csv new file mode 100644 index 000000000000..3d4995840fcf --- /dev/null +++ b/_randomgen/core_prng/tests/data/mt19937-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xca6b2fb1 +1, 0x3fa2a974 +2, 0xc12788fe +3, 0x27c9b64d +4, 0xabea28ce +5, 0x540ac30f +6, 0xb239d7be +7, 0x440e5156 +8, 0xc65c133c +9, 0x7333c5fa +10, 0x8292807d +11, 0x459bdab6 +12, 0x4f9f1306 +13, 0xe261f5f7 +14, 0xdb8b69 +15, 0xdf65ed00 +16, 0x5fc8bb71 +17, 0x35a46ece +18, 0x6344e7ce +19, 0xd4c1c08b +20, 0xb88c9bf1 +21, 0x72292bb3 +22, 0xbfb6a51f +23, 0xbb2ab6f +24, 0x9378d4f3 +25, 0x85bc696 +26, 0x1fa92b2a +27, 0x5816122 +28, 0x54e84469 +29, 0x8cdbea8c +30, 0xefa62749 +31, 0x7b13a32e +32, 0xe0c88cc3 +33, 0x238fba9f +34, 0xbee28cb4 +35, 0xc4a2bbe1 +36, 0x8ebb893f +37, 0x53333007 +38, 0x42c59297 +39, 0x507542da +40, 0x4c89a1d9 +41, 0x28cd06c0 +42, 0x63b1b8ff +43, 0x890947ca +44, 0x73996302 +45, 0x7b9afff +46, 0x3d6cf3a2 +47, 0x2d8cf12c +48, 0x1915a047 +49, 0x2e9f42a2 +50, 0xe1d7ea8 +51, 0x8ce9eb49 +52, 0x452706b0 +53, 0x1495dda9 +54, 0x62339095 +55, 0x1fb22d23 +56, 0x6f68cf26 +57, 0x905f8cc4 +58, 0xde25d38f +59, 0xf4f3efa2 +60, 0x8b60b406 +61, 0xecf051fb +62, 0x287a9210 +63, 0x96e96fb +64, 0xb60dd795 +65, 0x305f4bb5 +66, 0xfe838ef2 +67, 0x40671f78 +68, 0xa1cfdcb3 +69, 0xa06c0c2d +70, 0xbcbce0a0 +71, 0x6485453c +72, 0xd6d9e7b5 +73, 0xeac233ef +74, 0xb2a276b4 +75, 0xb5b97ad1 +76, 0x87bc49da +77, 0x1036f82b +78, 0x1e6fc3df +79, 0x87afcd40 +80, 0xe827dc29 +81, 0x16d11b25 +82, 0xe0c549ba +83, 0x427b8a +84, 0x346fa564 +85, 0x5449ea5c +86, 0x511199c6 +87, 0x5ccf41ab +88, 0x9a8a0bbc +89, 0x77f12026 +90, 0x4c9b8ad3 +91, 0xead800a7 +92, 0x80c8a86b +93, 0x3c84c630 +94, 0x19a6c752 +95, 0xc9187482 +96, 0x7eb43f2f +97, 0x89f4fdeb +98, 0x14db06ce +99, 0xcbdc6e25 +100, 0x43ac775 +101, 0xbd730a54 +102, 0xf722dcaa +103, 0x41768d48 +104, 0x20992130 +105, 0xe9973805 +106, 0x61d15976 +107, 0x94c478c8 +108, 0x2b743992 +109, 0xf6fff8fa +110, 0xaac859b1 +111, 0xf03d49ec +112, 0x620dc61 +113, 0x4ce7143c +114, 0x6b85f7cc +115, 0x5fa31164 +116, 0xa284fa6a +117, 0x8714fcfe +118, 0x5d7713ff +119, 0x423c4261 +120, 0x78897296 +121, 0x84281814 +122, 0xec3f65c5 +123, 0xa3922399 +124, 0x7465ebf7 +125, 0x5e794eae +126, 0xaca415d0 +127, 0x277cf6ea +128, 0x248357fa +129, 0xefabaa92 +130, 0x57982e83 +131, 0xb1d764c +132, 0x7c945b58 +133, 0xfd684cf6 +134, 0xeac7a06d +135, 0x367835e0 +136, 0x1a5d6883 +137, 0xf900c7da +138, 0xe3571db7 +139, 0x9d6834db +140, 0xbba4a672 +141, 0x4cd219a3 +142, 0x58c4197e +143, 0x4b037cf4 +144, 0x357acf28 +145, 0x284d7c27 +146, 0x8d0c4569 +147, 0x6ed031f +148, 0xd43e8a5f +149, 0x9cef208b +150, 0x189ea68b +151, 0xf7dad179 +152, 0x5e562f3d +153, 0x322b1e73 +154, 0x3a328762 +155, 0xc4078884 +156, 0x20798ff2 +157, 0xbcfbf409 +158, 0xeb6d471 +159, 0x8a0cba0d +160, 0x53726e18 +161, 0x22b38033 +162, 0xa321a604 +163, 0xf40c90a3 +164, 0x755bb1d3 +165, 0x2832a2a8 +166, 0xfffce275 +167, 0x3afdb520 +168, 0x98d8f18d +169, 0x7a4183b4 +170, 0x69a43d75 +171, 0xd631a4ef +172, 0x2aec3183 +173, 0x60767685 +174, 0x214e1dfd +175, 0x9f14f54d +176, 0xfde4f2bc +177, 0x60a7d47b +178, 0xeaece219 +179, 0xd634f4a0 +180, 0x80ad6fab +181, 0xbe1a53d2 +182, 0xf9a527a4 +183, 0xfdf0ac75 +184, 0x924f54f +185, 0xf99626ee +186, 0xcf7140d3 +187, 0xc8169d5d +188, 0xeb43d58d +189, 0x4b44ace +190, 0xb44ecabe +191, 0x613d8bdf +192, 0x65e3c025 +193, 0x2e324718 +194, 0x9dba63bc +195, 0x8e01c6d2 +196, 0x34800136 +197, 0xc2b01a3 +198, 0x59a182fa +199, 0xf834c79f +200, 0x20e41a8d +201, 0x94079cae +202, 0xcafb9877 +203, 0x87a4b067 +204, 0xa89f22a7 +205, 0xa2932911 +206, 0x580f0787 +207, 0xe4ca48c5 +208, 0x65c9677a +209, 0x37a7ae16 +210, 0xb978422c +211, 0x565bef70 +212, 0xbd7e6dc4 +213, 0xe4ebe924 +214, 0x4a789e96 +215, 0x99520b24 +216, 0xebad792e +217, 0x5d28630a +218, 0x4b33a5bb +219, 0x5a5dedda +220, 0x7ce8d5e +221, 0xa6cdd3a9 +222, 0xb2bcef6a +223, 0x13a8db8c +224, 0x61791eb4 +225, 0xb71e2381 +226, 0xb80dbbcf +227, 0x4d82b92f +228, 0x4f655a9b +229, 0x7748a0a9 +230, 0x508f7c48 +231, 0xd0713d9b +232, 0x3f48b380 +233, 0xd71d7c16 +234, 0x1f8ccd28 +235, 0xebcb920 +236, 0x2f5f4540 +237, 0xb9f69275 +238, 0x6dd968b4 +239, 0x417759f7 +240, 0x7a73257d +241, 0x154ecc84 +242, 0x12f280ce +243, 0x8391eb4b +244, 0xd76d638d +245, 0xf6c44241 +246, 0x8b137d48 +247, 0x71fb30ef +248, 0xe738bba6 +249, 0x28f9bbac +250, 0x46b0dcfe +251, 0x933856e8 +252, 0xad21fdbb +253, 0x5706c9d +254, 0x254b3ce +255, 0xc95fa489 +256, 0x4cc8fd61 +257, 0x9f6d990f +258, 0x3ed84328 +259, 0xfb1251c7 +260, 0x1da78081 +261, 0x2592d895 +262, 0x5c8396cf +263, 0x47fa1df +264, 0x94526768 +265, 0xa41e6fb4 +266, 0x97d47f9a +267, 0x35a56c1f +268, 0xc7af497e +269, 0x906dbbfc +270, 0x861e3287 +271, 0xe91e3387 +272, 0x5b08570d +273, 0x69574f7c +274, 0x32ccf53 +275, 0xf6a6bee3 +276, 0x373d970f +277, 0xaa780838 +278, 0x309d4cc9 +279, 0x58ec672f +280, 0x47cb0305 +281, 0xd4809ac9 +282, 0x138a774d +283, 0x82fa852b +284, 0x53bbd107 +285, 0x1512b55d +286, 0x6d53592c +287, 0x92b7ab58 +288, 0x6654f430 +289, 0xe11837f3 +290, 0x4538410d +291, 0xa2101ede +292, 0x93c2435e +293, 0x5e91b4e4 +294, 0x8f16260 +295, 0x3e64fed1 +296, 0x267fc0f9 +297, 0x3d3ecd37 +298, 0xc4352f2d +299, 0x2170164d +300, 0x3fc50df +301, 0x2c9313dc +302, 0xe69e1950 +303, 0xf834dec1 +304, 0x598d6cb1 +305, 0x79b36360 +306, 0x5d49f11a +307, 0x2ab7af4b +308, 0xf80cc125 +309, 0x824e4b68 +310, 0x36800a00 +311, 0x39186f93 +312, 0x84e177fd +313, 0xe6a40078 +314, 0x86f11e7a +315, 0xa1e79fe1 +316, 0x19fc66f9 +317, 0xb3a2dfb4 +318, 0x88e8091f +319, 0x37dce87d +320, 0xd54b5bc1 +321, 0x323e0c83 +322, 0x1c3d9868 +323, 0x14096d96 +324, 0xe5fbfe55 +325, 0x330004c2 +326, 0x8991d8f +327, 0x934ba7db +328, 0x828aea71 +329, 0xaa955f4d +330, 0xb9097b03 +331, 0xdb924c7c +332, 0xc0fd3c77 +333, 0x6571bc9e +334, 0x3f89462f +335, 0x30ec5ce9 +336, 0xd5083782 +337, 0x68f7c4cc +338, 0x4fd9cbe6 +339, 0xbcf08518 +340, 0xeebb9016 +341, 0xadaf6dbe +342, 0x5aadbf38 +343, 0x5b52ba6c +344, 0x6f31bd06 +345, 0x76b03446 +346, 0xec383171 +347, 0xe5547138 +348, 0x8c87998a +349, 0x1c166e4 +350, 0xd73c5950 +351, 0xa257e0fd +352, 0x9f042772 +353, 0x7b26801e +354, 0x16bce15d +355, 0xb1b3b033 +356, 0x12fc256e +357, 0x8426ed90 +358, 0x16dc30d0 +359, 0x3e003f97 +360, 0x22bf7feb +361, 0x12941766 +362, 0x4da7a3e3 +363, 0x4e4e9900 +364, 0xc2a6efe8 +365, 0x16522570 +366, 0xc49fd435 +367, 0xfc8137a5 +368, 0xe595897e +369, 0xf9dcef1b +370, 0xabdef12a +371, 0x4ebe25f0 +372, 0x86f58fdd +373, 0x46cac45a +374, 0xe430ec3a +375, 0xfd6e6a04 +376, 0xeacffe64 +377, 0xe026aa7f +378, 0xdaf0b65b +379, 0xc0b72e68 +380, 0x63c1dd42 +381, 0x18ec01ec +382, 0x18678c16 +383, 0x2cbbbcc5 +384, 0x457872b4 +385, 0x937347d4 +386, 0x6bdf0813 +387, 0xc6e572de +388, 0x9e0c6f94 +389, 0x45225c3b +390, 0x6fe099ce +391, 0x73b82a0f +392, 0x27203a8e +393, 0xc402180c +394, 0x3b26ea4d +395, 0x852b4444 +396, 0xa6b9a99e +397, 0xecb23332 +398, 0x27fff68a +399, 0x234a59a3 +400, 0xd8a13a6c +401, 0x9e4e99a +402, 0xd4500a99 +403, 0x97822d54 +404, 0x1747949e +405, 0x79b82e14 +406, 0xe907796e +407, 0x2b4bd2ce +408, 0x242b9adf +409, 0xc6979922 +410, 0xa122e4c9 +411, 0x45289a38 +412, 0xa123f35d +413, 0x4464993d +414, 0x89a70091 +415, 0x29f6e129 +416, 0xa2bc559b +417, 0x7b9d89c9 +418, 0x74969534 +419, 0x97fdef8c +420, 0xff09ac83 +421, 0x8a8e913f +422, 0xcfb04bba +423, 0x4ae8ce80 +424, 0x5113f1b6 +425, 0x5e8cfda0 +426, 0x1c3b5e35 +427, 0xeab9562c +428, 0x18a11b6e +429, 0x2f8a0ac1 +430, 0xd564482f +431, 0x772b6c44 +432, 0x27937ce5 +433, 0x202aa930 +434, 0x1a6fb83a +435, 0x3514c661 +436, 0x8c6d26b2 +437, 0x62ce4154 +438, 0x86a82cf2 +439, 0x8a73e17f +440, 0xd7798e07 +441, 0xbd83717d +442, 0x886b880b +443, 0xf7ff35c6 +444, 0x3357dc52 +445, 0x3266f4f8 +446, 0x384ad1fb +447, 0xb34e4e06 +448, 0xfbe250d8 +449, 0xd3d37e83 +450, 0x862b1b12 +451, 0x839a3f7 +452, 0xb22afe3a +453, 0x851d430d +454, 0x514d7503 +455, 0xf8bb3e8 +456, 0x4acdb849 +457, 0xcdd0ace0 +458, 0x6f6b6638 +459, 0x37a6e0ef +460, 0x3e55d305 +461, 0x9ac94ea4 +462, 0x34d82789 +463, 0x1e50a54b +464, 0x12eca710 +465, 0x7813b899 +466, 0x7d56587 +467, 0xa0daf18d +468, 0x461f0a88 +469, 0xc38a68a8 +470, 0xb61e025f +471, 0x9c27611e +472, 0x21a055c9 +473, 0x5f2545d9 +474, 0x981e0107 +475, 0x3f651b42 +476, 0x72b8aece +477, 0x84b09757 +478, 0x3ce97c5 +479, 0x4ebc1ac2 +480, 0x395c23d +481, 0x7c87b77d +482, 0xa5a5b68 +483, 0x5b8a13a8 +484, 0xe5e6f965 +485, 0xf47c69d0 +486, 0x8a7bd38a +487, 0x59a94533 +488, 0xb506fe84 +489, 0x8d96d007 +490, 0x4052151e +491, 0xcaf48e44 +492, 0x2889548b +493, 0x4262fe1e +494, 0x93e43134 +495, 0xb585fdf2 +496, 0x3339e66a +497, 0xe530ee9e +498, 0xa2987fae +499, 0x977205c +500, 0xbfece4e0 +501, 0xf9c925bb +502, 0x999b687b +503, 0x35a166ed +504, 0xe9eba709 +505, 0x40827685 +506, 0xa301a157 +507, 0x18f6e790 +508, 0x8148659f +509, 0x1896e693 +510, 0x90cc1b28 +511, 0x4189c62e +512, 0xda765fdc +513, 0xd219eb8f +514, 0xfac2dd2e +515, 0xef5a48f5 +516, 0xe16f0fe +517, 0x341cba94 +518, 0x69d6e865 +519, 0xaa36eeb8 +520, 0xcfb99f18 +521, 0x8bb61595 +522, 0xa8c2123b +523, 0x3c9310e8 +524, 0x1ee33b4 +525, 0x70c4ca87 +526, 0x1fe3babc +527, 0x7e1a697d +528, 0xf950c974 +529, 0x62c4350f +530, 0xdf4b4b4c +531, 0xb3c8c87f +532, 0xf406b1b9 +533, 0x5b53d2a3 +534, 0x283606bf +535, 0xdf1dc8a8 +536, 0xdaf05fe +537, 0x6bd95a2c +538, 0xa40ffa04 +539, 0xc59ffac5 +540, 0x333bbaa2 +541, 0xa2e970e9 +542, 0x8686876e +543, 0xe7eff30f +544, 0xce8349c5 +545, 0xfb32eef3 +546, 0x692e678 +547, 0xb22eef64 +548, 0x32309c10 +549, 0xd28593bc +550, 0x1055cd1a +551, 0xeec5e7a4 +552, 0x9b15bd7f +553, 0x62068ffb +554, 0x35d431e6 +555, 0x6f795d99 +556, 0x5a583e83 +557, 0x940f9322 +558, 0xbb6392db +559, 0x9133e1be +560, 0x4ba22917 +561, 0x3d98a18d +562, 0xd7aa3d1a +563, 0xdd912a6 +564, 0x99265a2b +565, 0x7d2e4e3f +566, 0x9cfc42f3 +567, 0xad2be67e +568, 0xed7ef841 +569, 0xb1d3b8b4 +570, 0xa56b36f8 +571, 0xe2ef74e0 +572, 0xdf0ef0d9 +573, 0xfd944a1a +574, 0x8dbaa48 +575, 0x7842914 +576, 0x316243c2 +577, 0x2e4c5f54 +578, 0xb86e001a +579, 0x46546448 +580, 0x9643c3d6 +581, 0xbdf7d2da +582, 0xc4e703cb +583, 0x4a45fbad +584, 0xa6375deb +585, 0xa9fc789a +586, 0xc0d075d4 +587, 0xe1824e00 +588, 0xdb54581 +589, 0x645bd158 +590, 0x2044aaa9 +591, 0x706ab8db +592, 0x35151344 +593, 0x2ef15d18 +594, 0xf48d0690 +595, 0x5c23ba6c +596, 0x565c730e +597, 0xc8ed50ad +598, 0xbc6d554e +599, 0x37a911d2 +600, 0x865dc33b +601, 0xfb9ab637 +602, 0x453dcafe +603, 0x7889820c +604, 0xb9f6ef68 +605, 0x7815d4a0 +606, 0xe97080ad +607, 0xbbef816a +608, 0x52d9c2b8 +609, 0x15ea5696 +610, 0x3a83f72f +611, 0xa1378189 +612, 0x892d5668 +613, 0x919e54b4 +614, 0xdb28c6f5 +615, 0xdf6cdf84 +616, 0x8f8f8a52 +617, 0xb3ee2710 +618, 0x9ece78ae +619, 0xe60ffbb4 +620, 0x1e7646ac +621, 0x1682946d +622, 0xd4a252d0 +623, 0xcbc981de +624, 0x5261bf81 +625, 0xa33cd368 +626, 0x98e9e554 +627, 0xa14efd44 +628, 0xcd777d9 +629, 0x8ee578e5 +630, 0x169fcd30 +631, 0x46964c36 +632, 0x49415678 +633, 0xfbc239f3 +634, 0xe00071f4 +635, 0x5a4c1d76 +636, 0xa753cb6d +637, 0x6327b16e +638, 0xb38c5ebd +639, 0x8185adf5 +640, 0xb1cfdc44 +641, 0xaffdc601 +642, 0x46559995 +643, 0xf739bbda +644, 0x950a90f9 +645, 0x779bec0e +646, 0x55791e65 +647, 0xfd94fd72 +648, 0x982b57d6 +649, 0x935efae1 +650, 0x18707a87 +651, 0x5123add3 +652, 0x54b8a239 +653, 0xff5a40bd +654, 0x63ead20d +655, 0x125e8aa0 +656, 0xbae0eba5 +657, 0xc9238af1 +658, 0x3767fc3a +659, 0xc3df41b7 +660, 0xdc53148b +661, 0xd2fb97c5 +662, 0xf8c89afc +663, 0xbb6deecf +664, 0xbcc6ec6f +665, 0xc7931d3c +666, 0x9f40e3be +667, 0x4d966e4e +668, 0xf369918f +669, 0x43c3d8dd +670, 0x305248ca +671, 0xb6b52eab +672, 0x97aa1849 +673, 0x840729bf +674, 0x4cb6e57 +675, 0xa7d59069 +676, 0x1a9a8197 +677, 0xf584e7b5 +678, 0x699c6a70 +679, 0x189b83e8 +680, 0x49f4b09e +681, 0xe726ab1a +682, 0x243775c8 +683, 0x8220f49d +684, 0x6edba081 +685, 0x2fbd3b8a +686, 0x34818276 +687, 0x81bbd13c +688, 0xf30e9f84 +689, 0x2b75ac4b +690, 0xfe66b7ff +691, 0x178b6c29 +692, 0x89ff4e30 +693, 0xc047a72d +694, 0x87977310 +695, 0xa91bf888 +696, 0xf2abc0c6 +697, 0x8547f3ce +698, 0xe78699e9 +699, 0x7c715be7 +700, 0x715aec9c +701, 0x260708ea +702, 0x4bf72dba +703, 0x19134f34 +704, 0xcefe0ecc +705, 0xb74397aa +706, 0x8e48750 +707, 0xb4c2d35e +708, 0x76d81bcd +709, 0x9788da5d +710, 0x234182d6 +711, 0x7efb59e4 +712, 0x15656eb2 +713, 0x2b2ebf2c +714, 0x4d44ac09 +715, 0x57cb6312 +716, 0xe5facad4 +717, 0x6f2dda2 +718, 0x1ace7d61 +719, 0x703ca72e +720, 0x88481396 +721, 0x7235f4bc +722, 0x30921317 +723, 0xd0575405 +724, 0x7c96cf3a +725, 0xabf955c7 +726, 0x27ecd579 +727, 0xfc70f045 +728, 0x68a835b +729, 0x73bc67ba +730, 0x84fd3806 +731, 0x8e08d696 +732, 0x5454e052 +733, 0x1e2dd75d +734, 0xc7903278 +735, 0x50ddb207 +736, 0xcf7431a9 +737, 0x5e2db746 +738, 0x817e811c +739, 0x56c11bf +740, 0xe6f5e4e9 +741, 0x97816caf +742, 0x7abaa833 +743, 0x7d7d777e +744, 0x62d02361 +745, 0x162b687f +746, 0x1360b813 +747, 0xe1c25671 +748, 0x19cd787 +749, 0x9321cab6 +750, 0x799dc638 +751, 0x1b49aef0 +752, 0x6ebd59a5 +753, 0x173cdc79 +754, 0x77e4d187 +755, 0x21803577 +756, 0xa75154bc +757, 0xd92067f1 +758, 0xfcbbda1c +759, 0x713722ff +760, 0xb95dedf +761, 0x10c217fa +762, 0xb166163 +763, 0x39a49d38 +764, 0x4a5f52c6 +765, 0xba172c1 +766, 0x471eb536 +767, 0x9dec38e5 +768, 0x14d3b53 +769, 0x5c588a4c +770, 0xe1a85acc +771, 0x78a5baad +772, 0xd6f90a59 +773, 0xe8d371f7 +774, 0x931890ae +775, 0xea3e4b0e +776, 0xd63407ac +777, 0xf797c99d +778, 0x48da86e8 +779, 0xe23019c0 +780, 0xa70bebaa +781, 0xa49dde13 +782, 0x3f242449 +783, 0x1eddf689 +784, 0xad0e89a4 +785, 0x32e046dd +786, 0x572feee9 +787, 0xfe8cd35e +788, 0x361ade3f +789, 0x2781da1c +790, 0x7fe09627 +791, 0x9a81a896 +792, 0xb52dfbad +793, 0x862b12c8 +794, 0xd0dc9c3b +795, 0x410e82c1 +796, 0x20d95af3 +797, 0x17357938 +798, 0xd1f2e42a +799, 0x99efd6c3 +800, 0x2dae59f4 +801, 0x51702dba +802, 0xa020dc62 +803, 0xd71ebd9d +804, 0x9c498db6 +805, 0xc50017ae +806, 0x4f944ffc +807, 0xe9a8e62f +808, 0xac490f79 +809, 0xc816d8b0 +810, 0xf3770304 +811, 0x4ba63128 +812, 0x7f4be54f +813, 0xdcf19d03 +814, 0x589718c4 +815, 0xed7c3114 +816, 0x70e5d73d +817, 0xdce25620 +818, 0x411e12af +819, 0xd68dfd60 +820, 0xbd44f0e1 +821, 0xb2962c96 +822, 0x4c7fa632 +823, 0x85136387 +824, 0x41b232a4 +825, 0xdb9a8997 +826, 0xfcb5df1b +827, 0xa046c4 +828, 0x5a7e53d4 +829, 0xe214dfbf +830, 0xc0861c7d +831, 0x3087ed3 +832, 0xd70b7358 +833, 0x369a9dee +834, 0xb99e904c +835, 0x22052e4b +836, 0x9afd4d95 +837, 0xd9dbcec +838, 0x9c18c47a +839, 0x97caa173 +840, 0x6f124137 +841, 0x26db8abb +842, 0x2dfeba8f +843, 0xc9ebd4dd +844, 0x2bf6f89b +845, 0xec81549f +846, 0xee3f1ac2 +847, 0xa3bad22a +848, 0xb9597c71 +849, 0xe220adf +850, 0xa9fbfdb5 +851, 0x9d817858 +852, 0x5679190d +853, 0x216c47c0 +854, 0x6c1d0b13 +855, 0x401d2e42 +856, 0xf3ca424f +857, 0x2894625e +858, 0xa614fdd8 +859, 0xa11e427 +860, 0xbc937623 +861, 0xe684b934 +862, 0x33821e19 +863, 0xbfc008f9 +864, 0x11579cd9 +865, 0x9886df8f +866, 0x5889e2e8 +867, 0xefbba03b +868, 0x182e7d44 +869, 0x217f4e99 +870, 0x82623484 +871, 0x6bb6f662 +872, 0x49bb5fcf +873, 0xf7c8d1a9 +874, 0xea51c810 +875, 0x40ef965e +876, 0x24d4b1a3 +877, 0xe9266bbf +878, 0xfb5179a0 +879, 0x92d23fc +880, 0x8c646351 +881, 0x527608ec +882, 0xd215edf3 +883, 0x3434a6ad +884, 0x757e915e +885, 0x62ef706f +886, 0x467080bc +887, 0x2578c3b6 +888, 0xc308bc20 +889, 0x44fe744f +890, 0x50ea3915 +891, 0xeb3995d3 +892, 0xe5ee8390 +893, 0xb9c7a39f +894, 0x83ab2921 +895, 0xb194f017 +896, 0x17e00f01 +897, 0x54ca5220 +898, 0xa10e3a60 +899, 0x1426c5ca +900, 0xdd42073d +901, 0x6a7b3945 +902, 0xda2127d7 +903, 0x4b0dd400 +904, 0xd35134fd +905, 0xcfa033e8 +906, 0xcbf475f0 +907, 0xcdb92b39 +908, 0xde8c0c75 +909, 0x219d1cd7 +910, 0xd6398be +911, 0xa3eaac5f +912, 0x92898b14 +913, 0xf4c27fce +914, 0xd5f7cb82 +915, 0xc10ec953 +916, 0xa01d0f31 +917, 0xc794c9e4 +918, 0x54168123 +919, 0x723bcdf2 +920, 0x6cea1b +921, 0xdf18376a +922, 0x922a0845 +923, 0x8eda2a83 +924, 0x9b0608f +925, 0x472cbc78 +926, 0x7afdce6b +927, 0x1bfa7fdd +928, 0x5ada3d12 +929, 0x5cf41e17 +930, 0xc506060b +931, 0x7214c2ac +932, 0xc19ae321 +933, 0x9b031d30 +934, 0x4c7b88da +935, 0xd00e5d13 +936, 0xee6b59c4 +937, 0x79ddaf5b +938, 0x29cf931 +939, 0xc6fa4b96 +940, 0x874ab89b +941, 0x4abc046c +942, 0x366d693e +943, 0xd6a1758b +944, 0xd964eb41 +945, 0x7eabd20b +946, 0xf71f17ac +947, 0xdb5d8c06 +948, 0x54602ce1 +949, 0x786313f6 +950, 0xae4aea46 +951, 0xca92465b +952, 0x60047085 +953, 0x39f7dd56 +954, 0x9d1ff152 +955, 0xfdf62ba0 +956, 0xa15cf163 +957, 0xb953b33 +958, 0xc912dbb9 +959, 0x9e7f36f1 +960, 0x34c02ede +961, 0x6742f244 +962, 0xd586cf43 +963, 0xc2bf8b07 +964, 0x814f36b4 +965, 0xaef9cfbd +966, 0x1ec4b840 +967, 0x7aaaf552 +968, 0x5eab3290 +969, 0xc6f9bfdc +970, 0x7e43bf8e +971, 0x3c63bf8 +972, 0x4ce6e886 +973, 0x4b1e48ca +974, 0xff5bade3 +975, 0xdf72eca5 +976, 0x48e273a4 +977, 0x8b186129 +978, 0xcf6f6016 +979, 0x7c70ccf7 +980, 0xe82e54f8 +981, 0xcfdb9cfb +982, 0x884af787 +983, 0x839fb72d +984, 0x6f021358 +985, 0xbe27e737 +986, 0x12de7b8c +987, 0x946ce6c1 +988, 0xd95a0cee +989, 0x54adc084 +990, 0x6850d90e +991, 0x8e7e4a4a +992, 0x27e99d2c +993, 0xa966b606 +994, 0x6f9e586 +995, 0x141df137 +996, 0x80bdaf81 +997, 0xa1cd6dce +998, 0xecd7c0de +999, 0x44dc0c32 diff --git a/_randomgen/core_prng/tests/data/mt19937-testset-2.csv b/_randomgen/core_prng/tests/data/mt19937-testset-2.csv new file mode 100644 index 000000000000..d2f6c156c97d --- /dev/null +++ b/_randomgen/core_prng/tests/data/mt19937-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x8c7f0aac +1, 0x97c4aa2f +2, 0xb716a675 +3, 0xd821ccc0 +4, 0x9a4eb343 +5, 0xdba252fb +6, 0x8b7d76c3 +7, 0xd8e57d67 +8, 0x6c74a409 +9, 0x9fa1ded3 +10, 0xa5595115 +11, 0x6266d6f2 +12, 0x7005b724 +13, 0x4c2b3a57 +14, 0xe44b3c46 +15, 0xe84bdd8 +16, 0xf6b29a58 +17, 0x45cccd8c +18, 0x6229393a +19, 0x7a4842c1 +20, 0xcaae7de6 +21, 0xcfea4a27 +22, 0x8765a857 +23, 0x7adfc8ae +24, 0x916b5e58 +25, 0x648d8b51 +26, 0xecf3e6a5 +27, 0xd6094219 +28, 0x122f6b4d +29, 0x565f9848 +30, 0x164e1b09 +31, 0xa5ee9794 +32, 0x52d0873 +33, 0x5e4513d0 +34, 0xd52692f3 +35, 0xf5081ec5 +36, 0xc73547fe +37, 0x23ee074f +38, 0xdeb91daf +39, 0xdebe09c0 +40, 0xfa86bb52 +41, 0x793e6063 +42, 0xcc95a7d8 +43, 0xcd087cb1 +44, 0x762382f3 +45, 0x853e031d +46, 0xc7d0c293 +47, 0xadcb0c93 +48, 0x1e473b8e +49, 0xb87b61a7 +50, 0xa3d1dd20 +51, 0x94ff3fc1 +52, 0x24b2cd09 +53, 0x89914ab9 +54, 0xf1d5d27f +55, 0xc234a220 +56, 0x8597da1f +57, 0x1b1cc2ca +58, 0x6a2748f4 +59, 0x793de097 +60, 0x43b9eaa3 +61, 0x2fb379fe +62, 0xc6342dcb +63, 0xbca6ab72 +64, 0x74c644b7 +65, 0x376fd81c +66, 0x9184e322 +67, 0x229da880 +68, 0x4cf6880 +69, 0x52fae7a4 +70, 0x9e1d5c35 +71, 0x26511785 +72, 0x9cb24e26 +73, 0x38ea0de8 +74, 0x9def62f4 +75, 0x62f0f111 +76, 0xf199794f +77, 0xe710b184 +78, 0xae8bc669 +79, 0x732fec2a +80, 0x5c08b5ba +81, 0x9cf1ba1f +82, 0x6fe15378 +83, 0xe7005101 +84, 0xb297f541 +85, 0x196a6fe7 +86, 0xf6aefa9 +87, 0xf8456839 +88, 0xaab13923 +89, 0xa7342f66 +90, 0xabaeec77 +91, 0x2bc0bb0b +92, 0x35dba1ae +93, 0x5bafdc52 +94, 0x2101505b +95, 0xc02cf780 +96, 0x50bfe98e +97, 0x9b9aca63 +98, 0x5d1c2635 +99, 0x53364b8c +100, 0x91f86a79 +101, 0x9d63faa +102, 0x70483054 +103, 0xa25fc8cb +104, 0xfd061144 +105, 0xf57db306 +106, 0x1a1f9bc4 +107, 0xa71d442f +108, 0x3578f27f +109, 0xa29337f4 +110, 0x294b9483 +111, 0xfecbf3cc +112, 0xa7321b64 +113, 0x94f424b4 +114, 0x40d7b7e8 +115, 0x6a140f4e +116, 0x7760248f +117, 0x7985c694 +118, 0x3e92ace3 +119, 0x9f9e5bba +120, 0x28b23b17 +121, 0x5687aacf +122, 0x1c418b8d +123, 0xacbc9175 +124, 0xa8053755 +125, 0x51342230 +126, 0x235ff531 +127, 0xc741a645 +128, 0x325338a9 +129, 0xf31716a3 +130, 0x5e64c5c0 +131, 0xa99b5c5f +132, 0xd22c9cc5 +133, 0x3796e5e +134, 0x18dba100 +135, 0x9f72d771 +136, 0xd6838eb2 +137, 0xac74f524 +138, 0x1899e7a2 +139, 0xf8d16330 +140, 0xf9f93f5d +141, 0xe0d14983 +142, 0x77f98662 +143, 0x8276be2a +144, 0xfa0d03cd +145, 0xe435170 +146, 0x9ad727e7 +147, 0x737f2b95 +148, 0xbd4060c9 +149, 0x51de97f +150, 0xa083600 +151, 0x7113f78a +152, 0x48660972 +153, 0xfac6322b +154, 0x1ec533ba +155, 0x5c048d7f +156, 0x4bcfd817 +157, 0x7b1bd6bb +158, 0x1e64f082 +159, 0xb04c1979 +160, 0x51675862 +161, 0xe166de3e +162, 0x6a0d23a3 +163, 0xeb117ade +164, 0x106bf87b +165, 0x3781a7c3 +166, 0xb145da52 +167, 0x90b037ae +168, 0x910ccae3 +169, 0xdd775c94 +170, 0x43f090d1 +171, 0x824bca32 +172, 0x85f3959b +173, 0xeaae5b0e +174, 0x180c7c29 +175, 0xebd0fc3a +176, 0x93713ac1 +177, 0x1546dc24 +178, 0xede65b0a +179, 0x47189056 +180, 0x518dbc2b +181, 0x2653368 +182, 0xaadb680b +183, 0xd7a3bb02 +184, 0x21bd8133 +185, 0xa5ad3450 +186, 0xb7613820 +187, 0xd76514b6 +188, 0x4a168480 +189, 0x43c55b26 +190, 0x2ee5a113 +191, 0x65d794ae +192, 0x9625b62a +193, 0x8d85b573 +194, 0x525c4b8 +195, 0x2a3989bc +196, 0xd43569e8 +197, 0x5eabbe4d +198, 0x133b91e +199, 0x257d3518 +200, 0xad85627d +201, 0x91d28302 +202, 0x451f3e03 +203, 0xb428205e +204, 0xbc35ace2 +205, 0x49d9976b +206, 0xf651fd0d +207, 0x6eebf770 +208, 0x3fae4928 +209, 0xc1903548 +210, 0x937f0c13 +211, 0x6566b25f +212, 0x97900f48 +213, 0xe562c59a +214, 0x927f19c2 +215, 0xa39054f8 +216, 0x391be0b4 +217, 0xe43ce943 +218, 0xf3e75bec +219, 0xae181f3d +220, 0x7276cf0e +221, 0x72fe9f60 +222, 0xd8ae3d04 +223, 0xfa839fc3 +224, 0xb31112ed +225, 0x1dbf688b +226, 0x4c24d3fc +227, 0xc45baa56 +228, 0xd0550dcd +229, 0x696d0b79 +230, 0x6581666d +231, 0xace9934b +232, 0xe18ffab8 +233, 0x3ff2a610 +234, 0x94ce4c98 +235, 0x502f139d +236, 0xe1b96895 +237, 0xf725846e +238, 0xb149c019 +239, 0x96a5a5d0 +240, 0xb9aa43bc +241, 0xa8e00779 +242, 0x8056cb76 +243, 0x88803475 +244, 0xf4c1e5bd +245, 0x3b043653 +246, 0xa4dc8aa1 +247, 0x65162768 +248, 0x6c81c3a0 +249, 0x9e6a3ce4 +250, 0x9b3c95fb +251, 0x7990eafb +252, 0x4e9d879 +253, 0x785a9546 +254, 0x4d3401d5 +255, 0xb750a91f +256, 0xa901220d +257, 0x49b9c747 +258, 0x4a4286b8 +259, 0x622a9498 +260, 0x9e36424f +261, 0xbfc99829 +262, 0x6dc3c912 +263, 0xe0e23e28 +264, 0x22ae6db6 +265, 0x1a5540cf +266, 0x4c5c3b0b +267, 0x17a5d0a6 +268, 0x91e9386f +269, 0x5aa2cd5d +270, 0x97436ff9 +271, 0x8d43d481 +272, 0x9306fadf +273, 0x89ba776 +274, 0xa7382b2c +275, 0xf80de0d8 +276, 0xa6f03d7d +277, 0x522ce018 +278, 0x6e717043 +279, 0x38a4abd2 +280, 0xe58413ef +281, 0x2429df03 +282, 0x5e1888ea +283, 0x18e606cc +284, 0x6f94d7e6 +285, 0xfbea3123 +286, 0xe45516d6 +287, 0x42a5b3fe +288, 0xce62babd +289, 0x897a4ec5 +290, 0xb4320ad7 +291, 0x72ab4a2b +292, 0x19a87820 +293, 0x197d5c0b +294, 0xeb633668 +295, 0x5a3118d4 +296, 0xb6d8848a +297, 0x7820b6b6 +298, 0xffb46feb +299, 0xd754f5a5 +300, 0x26423e7d +301, 0xe796fe9c +302, 0xde3d826f +303, 0x99d7de8 +304, 0x29992302 +305, 0x8220f61b +306, 0x9d954fd3 +307, 0x2ab684d9 +308, 0x1fb2aa97 +309, 0xc76fe335 +310, 0xd9171133 +311, 0xdd6c44ae +312, 0xceac7494 +313, 0x69514bb5 +314, 0x91b0961d +315, 0x23d53e43 +316, 0x683d2a23 +317, 0x8814327 +318, 0x11b4ed89 +319, 0xfb8a0849 +320, 0xb28ab129 +321, 0x5f8ffb97 +322, 0x741b5f83 +323, 0x6b8a0f2e +324, 0xb8d8a2da +325, 0xcf357b2 +326, 0xddcb3b6c +327, 0x5d912703 +328, 0xf9bbc71f +329, 0x441bb09 +330, 0xdb15ed8a +331, 0x3b11ee1b +332, 0x2ffb1ad +333, 0xc3d140c7 +334, 0x5c2785a7 +335, 0xf1b2143d +336, 0xbae0a955 +337, 0xbffff361 +338, 0x2befec2c +339, 0x56e32b22 +340, 0x8562a7a2 +341, 0x7d531458 +342, 0xde91821 +343, 0x56c7ba85 +344, 0x3332f8e8 +345, 0x2df312ff +346, 0x4bdd824 +347, 0x2bc5c700 +348, 0xcb2fc5cb +349, 0x76a4b922 +350, 0x395320c5 +351, 0xdfe4037e +352, 0x5868f7b5 +353, 0xf1b1d4fe +354, 0xed96bc50 +355, 0x9bb675be +356, 0xb4548088 +357, 0x98be68bd +358, 0x8269881 +359, 0xc89ce8d1 +360, 0x2a296570 +361, 0x8001b923 +362, 0x9f193578 +363, 0xce50d5b +364, 0x93c540a8 +365, 0xb2f81774 +366, 0x3ce68b24 +367, 0xfe0db0b0 +368, 0xef28a619 +369, 0x446b5143 +370, 0x9d2cdf67 +371, 0xadd8e1fc +372, 0x891f3b23 +373, 0xdd418c72 +374, 0x9704571e +375, 0xc037541d +376, 0xbae946f1 +377, 0xf6e8cd21 +378, 0x4fdba092 +379, 0x8de2d511 +380, 0x65f1d0dd +381, 0x365f3954 +382, 0x35b851fd +383, 0x38f20a02 +384, 0x2faa5845 +385, 0x37fff565 +386, 0xf1c2638c +387, 0x91cf922c +388, 0xbd533375 +389, 0x73bd6afd +390, 0x7d8eb542 +391, 0xf8616e6f +392, 0x3a37d85b +393, 0xae382d55 +394, 0x411d81a7 +395, 0x15d5ee27 +396, 0xedaffcb +397, 0xe716e96 +398, 0x6f35ed9e +399, 0x7ce2ee91 +400, 0x4fd1dac6 +401, 0xe18983c7 +402, 0xb2439112 +403, 0xf9f5a35c +404, 0x60b4582b +405, 0x9e1ed453 +406, 0x2dfa81b1 +407, 0x8ae13329 +408, 0x651585d +409, 0xdac7f4ae +410, 0x11374595 +411, 0xbe6bf0c9 +412, 0xadecaf59 +413, 0x7a8549f2 +414, 0x742579e0 +415, 0xad5537db +416, 0x895d4149 +417, 0x9b674e1c +418, 0xe58c3feb +419, 0xb6f660d1 +420, 0xfd86da69 +421, 0x7830f7ba +422, 0x37868f80 +423, 0x74bd5fd6 +424, 0xa9bf7e3f +425, 0xe80b0410 +426, 0x4369186a +427, 0x2320e0a4 +428, 0x549625e +429, 0x3aae1e18 +430, 0xc2251a74 +431, 0xe1af94bf +432, 0x51eca4c3 +433, 0xe7886533 +434, 0x622ab088 +435, 0xa55223b8 +436, 0x969bf35b +437, 0x531e6c5d +438, 0xd4bf977b +439, 0x850bcaee +440, 0xa104f457 +441, 0x3a0a0 +442, 0xdf660893 +443, 0x4fd61248 +444, 0x4606d9c7 +445, 0x6cea6457 +446, 0xcc4ccc0d +447, 0xe2a57d3a +448, 0x2f85d651 +449, 0xae0c9478 +450, 0xf3ea2774 +451, 0x74c4ebb7 +452, 0xafff3b40 +453, 0x7bc0aacb +454, 0x372b82dc +455, 0xc9ead3a4 +456, 0xf286e119 +457, 0x3abcb320 +458, 0xbb195daa +459, 0xe15b2f0e +460, 0x410251d6 +461, 0x504e251c +462, 0x369b9d14 +463, 0xf51b7fd2 +464, 0x84a8cd44 +465, 0x78c4b616 +466, 0x691d4e3 +467, 0xb62a5b7a +468, 0x351cc253 +469, 0x27588287 +470, 0x6cb82fc8 +471, 0xbafe423d +472, 0x5fc99a8d +473, 0xa5719605 +474, 0x76ace100 +475, 0x37026c88 +476, 0x4712accf +477, 0x2fbbb9cf +478, 0x96377fb5 +479, 0xcebd948b +480, 0xdd25a404 +481, 0xbf4099a7 +482, 0x1e16915c +483, 0xacc2cbad +484, 0x8472f51a +485, 0x46e2824a +486, 0x21cf3734 +487, 0x2cc6d3ee +488, 0xb7841db1 +489, 0xb4586cdb +490, 0x65642b33 +491, 0x769102e3 +492, 0x90bf7369 +493, 0xd7265312 +494, 0x2eeb6d75 +495, 0x34721522 +496, 0x2514be33 +497, 0x2a3abe9e +498, 0x7cf141b5 +499, 0x1ff50f3a +500, 0x5b096fab +501, 0xb8da4737 +502, 0xf0c025fc +503, 0x7cbc3fc +504, 0xc3ec5b12 +505, 0xbf3b03ad +506, 0xbfa86b57 +507, 0x17b461c1 +508, 0xe75a2d46 +509, 0x37aad5ea +510, 0x155b2c35 +511, 0xbfcf2330 +512, 0x8d5c7c5e +513, 0xbb50483b +514, 0x95a03950 +515, 0xbad669a +516, 0xf641767c +517, 0x358b50a3 +518, 0x4aca2e3a +519, 0x497343b1 +520, 0x3da6f46a +521, 0xad6120c9 +522, 0x19acdd2c +523, 0x1023470d +524, 0x434bb79 +525, 0x8e3f0746 +526, 0xedf5a226 +527, 0x25d8ea7 +528, 0xab7fa688 +529, 0xd541fc0d +530, 0xc8ffc7f8 +531, 0xfbfd0387 +532, 0x481f76d0 +533, 0xb4183bf8 +534, 0x961efa16 +535, 0x2e7f61f8 +536, 0x105f5f4f +537, 0x832c37d9 +538, 0x7c521708 +539, 0x94982ee3 +540, 0xfa3d1f06 +541, 0xc99c5cd1 +542, 0xe062a5c7 +543, 0x9b41f9d4 +544, 0x569195d9 +545, 0x37e93fc2 +546, 0xf629763c +547, 0x7485f190 +548, 0x3b50cc38 +549, 0xe0fd9b72 +550, 0xf3068eed +551, 0x7e054a97 +552, 0xf0fe2118 +553, 0xb72f0404 +554, 0xcc988a64 +555, 0x7c74f3ec +556, 0xa1650931 +557, 0xb5636957 +558, 0xdfd1561e +559, 0x7f861e36 +560, 0x4b036099 +561, 0xd8346f14 +562, 0xd9545d61 +563, 0x31c06965 +564, 0x9e2d2ab9 +565, 0xc5f8b197 +566, 0x3637d9b +567, 0xf969041d +568, 0x58e44ba1 +569, 0xdcc05573 +570, 0x25ec8f35 +571, 0xc7ca0a77 +572, 0xfb592bb3 +573, 0xfc2b1356 +574, 0x7a7679f6 +575, 0xc0e9f007 +576, 0x7f550a69 +577, 0x1094bf1 +578, 0xa3b47889 +579, 0x44fc9ab6 +580, 0x5e5b8f80 +581, 0x69160353 +582, 0x230be578 +583, 0x6da013a4 +584, 0xd2764ed1 +585, 0x4c3f5c94 +586, 0x3099df75 +587, 0x66b09bf0 +588, 0x82e5cd03 +589, 0x1ee3607e +590, 0x396cd72a +591, 0xfb0f2241 +592, 0x190c5614 +593, 0x67f78324 +594, 0xdcb89544 +595, 0x91b7cbd0 +596, 0xf9114070 +597, 0x57f687af +598, 0xf5f9428a +599, 0xc9f390ed +600, 0xe8140568 +601, 0x694fb3de +602, 0xc627f75b +603, 0x5bf9362b +604, 0x5549003f +605, 0x66458f9f +606, 0x14c30f94 +607, 0x4d44c9c6 +608, 0x6840f509 +609, 0xc674cdbc +610, 0x3b73b25b +611, 0xed1c4a6f +612, 0x21eab5a3 +613, 0x53478953 +614, 0xdad674c +615, 0xf3ef5512 +616, 0xb9c08d71 +617, 0x3921f4a +618, 0x2ece8e2 +619, 0x889134e1 +620, 0xc544c7ab +621, 0x4df91683 +622, 0x259e4b8c +623, 0xe2031ce4 +624, 0x145b8f3a +625, 0x4028cf81 +626, 0x16f03971 +627, 0xad6adc80 +628, 0xac0b5327 +629, 0xcf77f418 +630, 0x3ed062ba +631, 0x6ea14124 +632, 0x6ba87963 +633, 0xc08be345 +634, 0x8eafb886 +635, 0xd460d003 +636, 0xdc4d14e2 +637, 0x61085b79 +638, 0xba1f92a8 +639, 0x18b779bc +640, 0x453435a1 +641, 0x41925d1c +642, 0x21a8db44 +643, 0x9789101a +644, 0xe2d02e0 +645, 0x79fa68f8 +646, 0x4d35916d +647, 0x7ce947b3 +648, 0x431a2cc9 +649, 0x756135b5 +650, 0x74c5a0c5 +651, 0x864bb3a1 +652, 0xaeeb8687 +653, 0x7127ea7d +654, 0xb214825e +655, 0xda464848 +656, 0x4894b0f6 +657, 0x6ef5db54 +658, 0x6142e487 +659, 0xd3adc6c3 +660, 0x2e5fe8d5 +661, 0x82643ddb +662, 0xc9de1e6c +663, 0x161ccd43 +664, 0xe8d9866 +665, 0xa8f85f54 +666, 0xb26e6947 +667, 0x34e36253 +668, 0xc75894df +669, 0xd8e70900 +670, 0xc7042e85 +671, 0xae6d8d5b +672, 0x4269846b +673, 0x2da97b9e +674, 0x5fb237c9 +675, 0x11e247d3 +676, 0x966cee07 +677, 0x27aec95 +678, 0x45d7a7e5 +679, 0xe45d5ddc +680, 0x5ef03588 +681, 0x222ac6ab +682, 0x3272262e +683, 0xc7792000 +684, 0x75b91d68 +685, 0xecd782b3 +686, 0xb6bb626 +687, 0xb715f459 +688, 0xccbf6c4a +689, 0x7da649f3 +690, 0x13b36ae2 +691, 0x78310a7b +692, 0x84d26157 +693, 0xe1f93c60 +694, 0x4e8b1b53 +695, 0x7d08711a +696, 0x93d9dace +697, 0x6a211820 +698, 0xf59d6c73 +699, 0x2c9299c6 +700, 0xa5441761 +701, 0x79ac91ac +702, 0x90d833b +703, 0xc89d2739 +704, 0x6e2edab2 +705, 0x8e7228ad +706, 0x829076e9 +707, 0x28ed0c84 +708, 0x8942edb9 +709, 0x24d2005d +710, 0xae6fbd5b +711, 0xa6433591 +712, 0x471089a3 +713, 0x8a0a8ec2 +714, 0x20fd0194 +715, 0x536013ad +716, 0x648664b9 +717, 0x25a2b3cf +718, 0xf4d70177 +719, 0x28ed3ea4 +720, 0x2fe7cf69 +721, 0x21212abe +722, 0xe76b7e04 +723, 0x943441f1 +724, 0x8b36ddf2 +725, 0x179e5ccd +726, 0x74f8259e +727, 0xe919756d +728, 0xe1cd7757 +729, 0x153da2e2 +730, 0x756711a3 +731, 0xcce59a49 +732, 0xb9630cda +733, 0xe08ba7b7 +734, 0x6626861a +735, 0x17ecf576 +736, 0xe76f7416 +737, 0x6d2261cc +738, 0xb0a57acf +739, 0x7924fd62 +740, 0xb31a6e5a +741, 0x9487cc33 +742, 0x53e57be6 +743, 0xb75bc72e +744, 0xc1bc3ed0 +745, 0x6edfe3d +746, 0xa2d4e5bc +747, 0xbb3cdb2f +748, 0x3d71f7fa +749, 0xc457b868 +750, 0x29191280 +751, 0x2800d8a +752, 0xcbe04fcb +753, 0x4eebd78d +754, 0xf58bf147 +755, 0x3b9d125e +756, 0x75489606 +757, 0x80e09ead +758, 0x974abcf5 +759, 0xf427159e +760, 0xdb93b60f +761, 0x8eccb8a9 +762, 0x750c98a6 +763, 0x18f3b535 +764, 0xf3ae0bab +765, 0x9f265252 +766, 0x93646d87 +767, 0xdcef0cdc +768, 0xd21dcb41 +769, 0x285a96a9 +770, 0xe8a9fb42 +771, 0xfe0fdc72 +772, 0xd0c62b5c +773, 0x15c2a14e +774, 0x28cf62e5 +775, 0x182e64db +776, 0xa0ff7cf6 +777, 0xa2342064 +778, 0x65ffc99f +779, 0xf30528dd +780, 0x100df4b2 +781, 0xefce9dfc +782, 0x6c8d60ae +783, 0x7287625d +784, 0x42391e72 +785, 0xba4a4ea1 +786, 0xd95a930c +787, 0xbe034ee0 +788, 0x886a6e9 +789, 0x4e96a350 +790, 0xf57fe442 +791, 0x1ea955c8 +792, 0x5af973f3 +793, 0x71a2087d +794, 0x5b51248a +795, 0x644b5270 +796, 0x42e1ada +797, 0x8827449b +798, 0x2f6b62b8 +799, 0xd8695c78 +800, 0x66b8f141 +801, 0x894949c0 +802, 0xede60ac5 +803, 0xae262f58 +804, 0x19805d22 +805, 0x9bf30fcf +806, 0xf1ff4803 +807, 0x1935dabc +808, 0xde96ccee +809, 0x178f1ea5 +810, 0x7443fcab +811, 0xe53c6d3 +812, 0x53a2ab58 +813, 0x1626fe46 +814, 0x3b951e94 +815, 0x3cb76386 +816, 0x9d4d8f1c +817, 0xd6ea5273 +818, 0x8779386 +819, 0x85ba1342 +820, 0x3fec25c +821, 0x8358dfdc +822, 0x6dc58e66 +823, 0xa65b6365 +824, 0x116d4d7b +825, 0x8b6a4ec5 +826, 0x407f346d +827, 0x84fa549 +828, 0x389e0064 +829, 0x9484d2b6 +830, 0x40d1234d +831, 0xc5661795 +832, 0x218cd5fb +833, 0x6050629f +834, 0x314ce51 +835, 0x7db3cc23 +836, 0x1d9060ed +837, 0xfb4cbcf3 +838, 0x9e54b8fa +839, 0x3ea17988 +840, 0xf968dafe +841, 0x5fd3a519 +842, 0xfd874015 +843, 0xbb059ad +844, 0x68b7c4e5 +845, 0x4f6097d6 +846, 0x29b76190 +847, 0xd4de7499 +848, 0xa385e3ee +849, 0xce990c77 +850, 0x7d84a6a5 +851, 0xa3d89f7f +852, 0xfd49f581 +853, 0x5e3bf585 +854, 0x10b7c6c6 +855, 0x5010998c +856, 0xc8820d5a +857, 0xcd45224a +858, 0x49d47bfb +859, 0x1208d3b6 +860, 0x3dcd9c4e +861, 0xaefea33e +862, 0xa999e648 +863, 0x617778c7 +864, 0x3efdff2d +865, 0xa2494c85 +866, 0xaa75be2f +867, 0xed47f2bb +868, 0x846e54aa +869, 0xda9bd1c3 +870, 0x6c91188a +871, 0x7f67d2f2 +872, 0x8e000539 +873, 0x6d868ddb +874, 0x497c3559 +875, 0xd2934183 +876, 0xb4e2147d +877, 0xbcfc6ace +878, 0x6a340f52 +879, 0x727804c5 +880, 0x5c4cb6ba +881, 0xf80a0784 +882, 0xd422dc11 +883, 0x5cf822c5 +884, 0xeccaa1bf +885, 0x65c4c15e +886, 0xbc72298 +887, 0xbd1a4e83 +888, 0x3b8d7145 +889, 0x72f721a8 +890, 0x593890a4 +891, 0xeff1de3a +892, 0xd0a1a4b1 +893, 0x41da0db7 +894, 0xfc492a98 +895, 0x61bb02a1 +896, 0xf80e8792 +897, 0xb277df61 +898, 0xe7aab1ce +899, 0xe5a662f1 +900, 0x4beb1c87 +901, 0x1efdc7b5 +902, 0xfdf472eb +903, 0x3dd5f02e +904, 0x3fd9fdf0 +905, 0x3a6f7bf4 +906, 0x1b1caa7f +907, 0x7d507ba1 +908, 0xf371a151 +909, 0xe43ad49d +910, 0x3bc16e0c +911, 0x5bacee76 +912, 0xb094a72e +913, 0x629eeb76 +914, 0xef07120 +915, 0xeaae9f22 +916, 0xbb0fc073 +917, 0x1d231657 +918, 0xe1b86a7c +919, 0xa1917199 +920, 0x45be6cae +921, 0x220029f2 +922, 0x6109df6b +923, 0x5fce7e34 +924, 0x5fd1dfe9 +925, 0x530c326e +926, 0xbfb09640 +927, 0xae1c0d4c +928, 0x3ce0ef76 +929, 0xcba82a49 +930, 0x2bfe9092 +931, 0x8101cb04 +932, 0x7304c707 +933, 0x4bd68a83 +934, 0x4df1a430 +935, 0xe2ce6c4c +936, 0xd6d51925 +937, 0x5a143074 +938, 0x3cdca5ed +939, 0xbd072630 +940, 0x809c986d +941, 0x8e2c27d2 +942, 0xf14d28b3 +943, 0x3396aa31 +944, 0xa24dac47 +945, 0x8c6bbf5a +946, 0xde06adb1 +947, 0x85074fee +948, 0xf0b1951d +949, 0x5949d203 +950, 0xc032204a +951, 0x64d7e54 +952, 0xb31759ea +953, 0x2619ad41 +954, 0xf7cc9777 +955, 0x21c10e14 +956, 0xfe910cd0 +957, 0xb53a142a +958, 0x73aa95f2 +959, 0xb585c01c +960, 0x1224859a +961, 0x9c9b8b57 +962, 0x4af48cb4 +963, 0xac021930 +964, 0x2700b7c2 +965, 0x72906666 +966, 0x6ae06309 +967, 0xb2321d02 +968, 0x219c2d74 +969, 0x60d9fb6c +970, 0x9aa776e9 +971, 0x199bb359 +972, 0x61ffb57c +973, 0xf5d36375 +974, 0xe5380264 +975, 0x128b105a +976, 0xf7c16444 +977, 0x4f0e269 +978, 0x8c00a60a +979, 0xfac5500c +980, 0x465ad668 +981, 0x2602a8e1 +982, 0x979c69a5 +983, 0x423a50a7 +984, 0xe59223a0 +985, 0x372ce57a +986, 0x681fad21 +987, 0x9475239a +988, 0x8d550063 +989, 0xf9cadcd9 +990, 0x458b0932 +991, 0x45e3e958 +992, 0x7497fcd2 +993, 0xf856d714 +994, 0x66d6b2de +995, 0x686fe9c +996, 0x3f980648 +997, 0xe356d512 +998, 0x81807599 +999, 0xb5676398 diff --git a/_randomgen/core_prng/tests/data/philox-testset-1.csv b/_randomgen/core_prng/tests/data/philox-testset-1.csv new file mode 100644 index 000000000000..64c1516cbdc0 --- /dev/null +++ b/_randomgen/core_prng/tests/data/philox-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xa4016d3bd1adb1dc +1, 0xa554a8f84b75ce6e +2, 0x64aaf86f2a8b501a +3, 0xd1de65006998520b +4, 0x392794fdb78e642e +5, 0x13aba45f3ded2bc7 +6, 0x72953d6a6ed0ce9b +7, 0x81dc11fff0ade5e9 +8, 0x28c22fa622755161 +9, 0x2d0bf144d156bca8 +10, 0x88c67c8c249075ea +11, 0xaf979d9c3fa6a9f4 +12, 0x8351dedf59eda5c3 +13, 0xa597c60a8db6df19 +14, 0xbd22a90d6d81b032 +15, 0x3034c0d2086b8564 +16, 0x2879c4883a14c06 +17, 0x5a66f8a2208a94f5 +18, 0xcda7bf16739a6681 +19, 0x369b3461c902a66f +20, 0x14a3541487ef7613 +21, 0x60dc1cc40c854dba +22, 0xb8d6129bcbdf1894 +23, 0xddc1e842a5ce4b82 +24, 0xf5a5c000d4804841 +25, 0x29c1123be4c5a3 +26, 0x928197be48d100b +27, 0x9164d36b36459765 +28, 0xa5b361d3b9fe5094 +29, 0x966e6293e46a92e9 +30, 0x380b501fcd0e9e1b +31, 0x538c1834694cb627 +32, 0x68397c2b7e36891a +33, 0x569416ce7905efdc +34, 0xf58f21254316c4ce +35, 0x1e19d04d36f0446b +36, 0x4eab321b90c3059e +37, 0xf4eef8577ce3621e +38, 0x86aa30aad7e74bd7 +39, 0x46ad14d76a4e9edc +40, 0x9158798abc57ef60 +41, 0x54206b8453720f00 +42, 0x44e68b9350e349a4 +43, 0xfee4ef034f34ec46 +44, 0xd47125c4a5cd9a5d +45, 0x174e9bb06dab2e1b +46, 0xc6a3beafe03adf09 +47, 0x8a155bf8f077f2ff +48, 0xc037f7a702e0e091 +49, 0x7121788b47bb1f67 +50, 0xcc1e3035fd6cee3f +51, 0xf59ef1e37c98f033 +52, 0x54e5c5049de62701 +53, 0x46353528f1594539 +54, 0xb93695a2d9cf5a1c +55, 0x29e0dfdf2ce8cfa7 +56, 0x598f527bbe1f0abd +57, 0x7b1c84c93d833619 +58, 0xe05228837711bc0c +59, 0x1cb8fc3e70fd977a +60, 0x109d878184b67919 +61, 0x9f971fe0d44411b7 +62, 0x886c0994aaf201e1 +63, 0xc0dd321f1390b2e7 +64, 0x3fdef712372f8321 +65, 0xfa7c6d8918cd8a29 +66, 0x11c1eb4cb16252c4 +67, 0xbc57160901fbbc4e +68, 0x9035cb331c1c6032 +69, 0xa75b7195d844181d +70, 0xaee9b050676d9595 +71, 0x34d540b1d61818ca +72, 0x851885a79cfef55f +73, 0x2f5602c107a51176 +74, 0xf02cce653d94ae18 +75, 0x69703c81d7642c2e +76, 0xc37f35a3762bf75d +77, 0x584d48c1678ba110 +78, 0x214f883b77e43d91 +79, 0x32c9f2e834bc151e +80, 0xa25ec540319a0279 +81, 0xd0ef31b3a764dd1e +82, 0x413fc1760f4696b0 +83, 0x2ec088887c392c6e +84, 0x643e07972c0d7edf +85, 0x181da5ad37378493 +86, 0x7807a71aee267e7a +87, 0xc8251e8b6f84c9cc +88, 0xaecd92db4caa82db +89, 0xe6b737b621d0f5e4 +90, 0x74a594617dfd217a +91, 0xa167df989d02c069 +92, 0xea01be29eee2049f +93, 0xeee29b33c17d78a9 +94, 0x3491d38fb23f3fc8 +95, 0xeb4487ea874377e6 +96, 0x7997f3b9ba996313 +97, 0x8eb5bda3e878f439 +98, 0x1a17f0c4997b9dac +99, 0x449f4caa3e49d3bd +100, 0x1d6864b879e608b1 +101, 0x32c53c6d5e4e51ae +102, 0x508f8f76cf4660ec +103, 0x6c06057521c22c33 +104, 0x868a66b6414f4e2 +105, 0x5715002f33452e98 +106, 0x115fbd06a3ac4e8a +107, 0xfcac2badb17c901a +108, 0x4c44e1e868322197 +109, 0xeb8fa2d7d096a4fa +110, 0x5418a67b92163d7 +111, 0xd9c592de8e80a341 +112, 0x732a44e5218c1cf0 +113, 0xa9368ebfa3fe327 +114, 0xc5fea8642de21f5b +115, 0x8aa7606b2c790548 +116, 0xdc345a26c0b0d0be +117, 0xf3926ddb06d16b69 +118, 0x8221732a3335efcc +119, 0xf9617131e08d7747 +120, 0x99327d82da6c2710 +121, 0x489965f6c29fc095 +122, 0x489883ac61fbf8a5 +123, 0xf93180c072491e2d +124, 0xbc652ef0fb7fa413 +125, 0x26b645337e0f0151 +126, 0x221c4fd98d9d04a0 +127, 0xbf37f891d23b1a5a +128, 0xf895c9daa40736d4 +129, 0xce74ab4966a7df8b +130, 0xd2ede8866e13602a +131, 0x6f1c653376aed88c +132, 0x795f01d45d648320 +133, 0xe871c1ca660fb460 +134, 0x40ab3bbc97818d76 +135, 0x35d7ffca14a7ade7 +136, 0xc4e33deed96936a +137, 0x23e3678027f084a +138, 0xaca324e1826bc2bc +139, 0x912083410f2c9602 +140, 0xe60447c78d94dab8 +141, 0xccfa70966b894010 +142, 0xda52cf984a6fcecc +143, 0x4bd41ad2099c8555 +144, 0xd48a643116cbfdfb +145, 0xbf7fc5b1bc00ce08 +146, 0xada212b7bd53caf1 +147, 0xd6852e20e7ec8990 +148, 0x37334ee1ef839cb6 +149, 0x4cfcfdfb1210ba72 +150, 0x86621c6062cecdce +151, 0xaa81f5bd7dc7f04b +152, 0x6803d22953c928 +153, 0x25af4104ef0196bc +154, 0x3f43caa463f637f1 +155, 0x752c82a0d44e4276 +156, 0x564b16249685d0d6 +157, 0xba4752d6711744b +158, 0x78ff9b2d759bd294 +159, 0xb93c8b5b9ca0ab4f +160, 0x7a3b59e3c26e8aeb +161, 0x483b45671cc7a011 +162, 0x600055f7d0ab48b5 +163, 0xe83dfca027b30174 +164, 0x5283c2d730c533de +165, 0xf5ff0af35cc16bef +166, 0xe65e629ad63ace2 +167, 0x4599b59b43471c90 +168, 0x3b883221ddd0edbe +169, 0xd1bd681d7571586a +170, 0x2f76707a866652f4 +171, 0xfa431b2763618557 +172, 0xbb30fd01840f73fe +173, 0x4e05560dda8ff28 +174, 0x7d463765716205db +175, 0x6802d6a4c64bc942 +176, 0x23f97ab176fc38c7 +177, 0x6fa71a806a74e049 +178, 0x4f8c47e05d613085 +179, 0x1c62a84ea1a987c2 +180, 0xb985dd9fcfcbaf12 +181, 0xbfd1d96717312296 +182, 0xf7623c95eba45fef +183, 0x9aacb0d9d2bc45ed +184, 0xe479947525498f64 +185, 0x6fcef0ca0aca8a90 +186, 0x278894094d25783a +187, 0xdc02388636ed13d5 +188, 0xc62e48f5953cbcd7 +189, 0xe19a9fa5bed7628e +190, 0xdeb078ae8fe5dfb0 +191, 0x4e6860e046964ce5 +192, 0xd8cdb2898e2a30b4 +193, 0x635e6d7bf2d5ad3c +194, 0x382287d0bbc15096 +195, 0x4dce30919aaed075 +196, 0x91f2eeeb2e9d3bc0 +197, 0x8815aed14f2ce31a +198, 0xd1587cbd77a69435 +199, 0xf27ba7a7f17e068e +200, 0xc91ea6657949ca8a +201, 0x8fb304e0fd14e8aa +202, 0x20435550a23087b3 +203, 0x711f1c68e57b2b9a +204, 0xea6994cf0be86f7f +205, 0xd18c615acc777905 +206, 0xb90960bb87ffd1a0 +207, 0xac90e55e19311295 +208, 0x31659affc36aae91 +209, 0xd7d7e48ef29c958a +210, 0xaee7da2da84dc993 +211, 0xdc7dffa68e28f198 +212, 0x2a640b7dddf397ff +213, 0x96c8eb4f3eee1b5c +214, 0x783f85e380c37624 +215, 0xe03c5ffaab657342 +216, 0x699873d780917aa6 +217, 0xb19fdd3fdfe2195a +218, 0xe5ac242b8935d3d3 +219, 0x40fefd049828e9a2 +220, 0xc5376b89b3da4996 +221, 0x4a41f1092c5468bb +222, 0x2155cf97cbf75962 +223, 0xaa3ec3edde80ba66 +224, 0x1caec347492ffadd +225, 0xd80dc91a46a52d31 +226, 0x12f749bee8cd142b +227, 0x82212e1e4913e774 +228, 0x5746ee2f1e40f3c5 +229, 0x8e62e2276ac29cb6 +230, 0x267b7a85f83e8b95 +231, 0x3c6436ef222f439c +232, 0xb52ff729bf93362b +233, 0x169d41a9b76ad990 +234, 0xcffd92d5315e9a76 +235, 0x2b6596632a14e62b +236, 0x4b86680bf8d00375 +237, 0xe57684dbc26d0e4f +238, 0xd437041fa45a59f5 +239, 0x7e1f0aac84d7e4e2 +240, 0x1187ce212e5e7834 +241, 0x76f1c2154a2e3d50 +242, 0x712d0e28711856a9 +243, 0xd5f54dc83e5c12ad +244, 0xc24a17f46e4c418a +245, 0xc51e029ea6d4f2e2 +246, 0xc31a655846a16146 +247, 0xef88f4da62201b06 +248, 0xf33e2f9d0a8d91e0 +249, 0xdc679372436366b3 +250, 0x25c9763e8013baee +251, 0xd8aa69cdaac03261 +252, 0x57e8bde3bc84e10c +253, 0x21c8c1336d7f36e1 +254, 0xe8accbc264dab29 +255, 0xc98322f62b53cf6a +256, 0x8b83421277b969f +257, 0xb57131b80e2e277b +258, 0x444d7e89c60d71dd +259, 0xb0d9e46bb1c33e76 +260, 0x3d5a684c6113db38 +261, 0x2711e1981a992b2d +262, 0xf2d4db5c46a2ec57 +263, 0xed7b35c56ef6a104 +264, 0x83f3cdb9bc4ada6a +265, 0xe022709b7ea47148 +266, 0xb570382def08f207 +267, 0x1ff1a063da5e52e6 +268, 0x1431c8c76bfd271f +269, 0x36a3ae42d26ae46b +270, 0xe49797ad98a160ee +271, 0xd1facb5e688b3c6f +272, 0xa9080cfeb38b849c +273, 0x35e77aa7d3827d44 +274, 0x96d94f159c2bc6f5 +275, 0x9a1005b1aae0602c +276, 0xc12ba0bda081de45 +277, 0x12781e7aa9155495 +278, 0xbc8bf25c33eb784a +279, 0x2c59317df88aeaef +280, 0x712c3f6f0647fe7f +281, 0x6de6cc238b4334b4 +282, 0x5084214e6a6e8e44 +283, 0xfccf29c93e989fd2 +284, 0x908bd387fff422a4 +285, 0x1bea6614135216b5 +286, 0xfc77a0b775e22d6f +287, 0xe060b6e9fea8bc24 +288, 0x28efa8a899554d2 +289, 0x2472913e201c807d +290, 0x7105e53d38203b17 +291, 0xfd930d5b12f274af +292, 0xde103731a6b10d73 +293, 0x1abed9ae891a6fd5 +294, 0x2ac90b2b44327c6c +295, 0x8b2590bb2b05e83f +296, 0xfa1d4711c71d541f +297, 0xd4ca45335ac19253 +298, 0x8e1d05c7517e4e72 +299, 0x9c0902deb45e3f6e +300, 0xbaba37c175ce76b0 +301, 0x601af65183731007 +302, 0x7eb8587a2d4c135b +303, 0x20bb71c6e9199a23 +304, 0xc0ca4dc39757b5a6 +305, 0xcc6be1e1ed4d8273 +306, 0xcc74c8e5d18f5f7b +307, 0x86ce3a5781885ae9 +308, 0x7b62ce783ec46209 +309, 0xfb266311a6c0550c +310, 0x554773cccbec1559 +311, 0xa977c8205a4aae08 +312, 0x9ee5fc0c8fbf6dce +313, 0x4f5705626b4f2d17 +314, 0x22d88963961cbf4f +315, 0xfd6dc42eb7fcc0e +316, 0xf88e30d786e0ecbe +317, 0x78fe0f1b15436367 +318, 0x7499f2d214cb7268 +319, 0x913d1695a973ce15 +320, 0xb83d91cdf10b568f +321, 0x93dbc1f9fb7d1e0c +322, 0x7d7bc7061aad68ac +323, 0xaa0601e59a625056 +324, 0xa72cbfff7c7ff448 +325, 0x7318a8d3915ace11 +326, 0x36842549fb894417 +327, 0xb68ea7ad73e99b6a +328, 0xcbdf94cb59042237 +329, 0xa2a7fd9eddd13720 +330, 0x732dd9f06eb3c5fc +331, 0x4fb08823a37032ed +332, 0xe6c856ed41016c49 +333, 0x996c3d0e4f3b417 +334, 0x7b34a700117568fb +335, 0x199eefcf92de5f86 +336, 0xa3f4961be1c5b0d5 +337, 0x5f41b28cf7b244b5 +338, 0x312410aa5e2fb5f9 +339, 0x1586dba27b082c7e +340, 0x84ed5134c1917f33 +341, 0x59f4afdb3c49271a +342, 0x925d17fb348c7028 +343, 0xfc7d3c57ea5636b9 +344, 0x6d1171ae97fb0915 +345, 0x398f4cbc4e9c54fc +346, 0x1c2ebb92b1b504ef +347, 0x3b2328cb18c05023 +348, 0x8d9db4e20415c26f +349, 0x6a0a8a1b1845e93 +350, 0x8dc25082c60f2f7 +351, 0x717be0ac6519b0fc +352, 0x96b0e9458c83e3aa +353, 0x95672c97c1e1d811 +354, 0x38eeff8eaee7b86d +355, 0xfcaf43097da98c20 +356, 0x3c3e92583d27de30 +357, 0x9c497d64afc8474d +358, 0xd9490e6e4d69e245 +359, 0x659965798924d480 +360, 0x3fe6c83496d2e8a3 +361, 0x35f0e70b604c298b +362, 0x6b2b04775eabc4be +363, 0x91db116a3482d1f +364, 0x4530affe8ed6651b +365, 0xaeb91d6b34fac1ea +366, 0x84c7b10dbcb7c855 +367, 0xa484c7232eb07597 +368, 0xbc408d28ff7b549b +369, 0x59806824675e1397 +370, 0xd090322df3ed7160 +371, 0x98584fcfd0731210 +372, 0x72f1dfc286dac4c6 +373, 0xf19a3de3ac829f2d +374, 0xfded8b979c32a9c3 +375, 0x11183cf8e5fd735b +376, 0x1fd22c3a64e887aa +377, 0xf1ad39eaea361b09 +378, 0xca21672cc4c0afcf +379, 0xcf9ca801297c015d +380, 0xb58af039ca2132a9 +381, 0xb2c1cfebc559a4d3 +382, 0xe6aeeddc924fe174 +383, 0xa4ee5d69059f2a35 +384, 0xb4891d7ce04994fc +385, 0x2d86e4a3aebe4406 +386, 0xe0e37a9afe1410dd +387, 0x3fad3ef7713a378e +388, 0xe6546dc8f25626ce +389, 0x610065e43da6b067 +390, 0x246433cc66b2ae3 +391, 0x987f33b8819a1248 +392, 0xdef42b9ae3070ada +393, 0x372e29ed9ca79858 +394, 0xa77c59d5f963ad7a +395, 0xab30aad91674d0f8 +396, 0xdef9084c78c88b91 +397, 0xf43176d0a08831dd +398, 0x3c9199a67d636dae +399, 0x1c1740467f01f9d3 +400, 0x526f48081c053f81 +401, 0xfb3e2a79343e5e29 +402, 0x18c4950887faec3a +403, 0x8bc979d8a8985fa6 +404, 0xcf40e8843fd3059b +405, 0xb19676125f3f52f2 +406, 0x4a0a6b19170a7ad7 +407, 0xd34de55b18b57416 +408, 0xbdc1e59e8ec23c6e +409, 0x8ec4b1a49fecac44 +410, 0xfdc61f4b5c67d0b6 +411, 0xe2fe45308ec48888 +412, 0x14cdeaf1d4e6d7cd +413, 0xc3ba3ec042a56233 +414, 0x332da8b89898979c +415, 0xfba5de9a6658a159 +416, 0x6a8e39f8f9251c9 +417, 0x99de3f00ca6ac555 +418, 0x6b83762f9cde7610 +419, 0x2c9724e61be893d0 +420, 0x482951b5de7a8676 +421, 0x94c864bf7b7b3ce1 +422, 0xe7fb63eaa8034f7b +423, 0x3606766d32778e49 +424, 0x832fb6d1c1702fad +425, 0x231a34aa65f35f3 +426, 0x2dbbb19d5057dc11 +427, 0xadc96a7b0ec4d7c6 +428, 0xcedb950834baeeaf +429, 0x10454de5dd5b2b4c +430, 0xacb5218055b223a8 +431, 0xfc7935a53eef226a +432, 0x7ecfef66f3a0a28d +433, 0xa3c506354fdf354d +434, 0xbf718d5dc3f872f +435, 0x58a8cd40351434ff +436, 0xf4a5f71e6b8feb50 +437, 0x7c362e216ad9c96a +438, 0x2a6431ffce1c07ad +439, 0xae65a7b73a58f481 +440, 0x67653634cd12e61a +441, 0x6d1fcfb52e19bf3c +442, 0x91ad77d4053b6726 +443, 0xd945d1507c4924f2 +444, 0xf45ae9093c093257 +445, 0x64b2b6a4bac0adff +446, 0x5ff6f2b342d71de5 +447, 0x59925318c904944d +448, 0x95dbf54419fb4864 +449, 0xd55ba61f567a0a97 +450, 0xee563293f29b5750 +451, 0x5837051585cad45c +452, 0xfcf40f619994def9 +453, 0x5260f8ee6f748019 +454, 0x71764f26e092ad15 +455, 0x3ccbde223b20fea3 +456, 0xad863d51bde55140 +457, 0xc580fad0c3e9843 +458, 0xa5337a7858a6a49c +459, 0xc43e9199c2d296a7 +460, 0xa3172bc5d23744fb +461, 0x6fb2b18f90271d5a +462, 0x1061bd95c79f5218 +463, 0x38002aa34425849f +464, 0x4cefbbbc74ff719e +465, 0xcadbed5627af6154 +466, 0x7bebd30f09338836 +467, 0xba48fd224dbcf41f +468, 0x6fb65073938adfdd +469, 0x1c74e5ea63a196f +470, 0x6aa6af9b2f2c56b7 +471, 0xb34d1259dbc5283e +472, 0x4e31ff60e92e2d44 +473, 0xefe7fa9b9e3f35b5 +474, 0x980e16e5be4f7b63 +475, 0x750f9235268a94cc +476, 0x6007d403696373c2 +477, 0x13bcd1966ef5491c +478, 0xa10fd6a45986ae0f +479, 0x14bfd2c4cef77b84 +480, 0x9e337eaad201c664 +481, 0x87b8f2c4b3f086e +482, 0x5f70b6cdb796ed2 +483, 0x1982229ded0932a1 +484, 0x466663c9cff20aa3 +485, 0x3272c93bbfd9638b +486, 0xe403c4d56c483b55 +487, 0x93280ac4c48d7eec +488, 0x614d81b45505675 +489, 0xac26c793b1c92d2f +490, 0x98c856891490319b +491, 0xc860935122dddb3c +492, 0x4c8a4de8767c40bd +493, 0x2ff98c8c4470f390 +494, 0x2f1c72a213351fe3 +495, 0xda85b3af5a866362 +496, 0x791b0597c01db174 +497, 0xb57b6f82b8cb8538 +498, 0x66b967b6d6b78e1f +499, 0x10e25dff7fa9eb1 +500, 0xd7221749de25e2c4 +501, 0xe7de3dd12683afbc +502, 0x4fab8db8efc41caf +503, 0x55c69af11e357f2d +504, 0x819ae1c6dc834542 +505, 0x181feb56b1b09fea +506, 0x8c02b115f96e8a13 +507, 0xfcd520bd3bde3795 +508, 0xb8f13e1a17520781 +509, 0xc5077e62eb3455f6 +510, 0xb35be37dfe324f62 +511, 0x215c3528cfabaea2 +512, 0x4e8f73eb0ecfacba +513, 0xb53be656d283bc61 +514, 0xc84605b63da1659d +515, 0xdd14e6951ae728a9 +516, 0x23bf5133fcdb04bb +517, 0x635b0a6bf6d16290 +518, 0x69d3fce4b4da412b +519, 0xa7642708d4edf170 +520, 0xdfd18fcd236b3ada +521, 0xdee7ba05f5412891 +522, 0x4ef5da00ff54f4e0 +523, 0x7996c43afbd32752 +524, 0x9ab61401c8ed09d7 +525, 0x9f0cbb35ba418b5c +526, 0xcd335f0227cbb2e +527, 0xeeb415a10dc69acc +528, 0x8f306fd5fb98c8ce +529, 0x87d290a1e5a13313 +530, 0x73bb14ad65f03b8f +531, 0x1c38b0604e39eae2 +532, 0x6255e18db9d3f32f +533, 0x821de64507a248c4 +534, 0x43aa3f96160e265d +535, 0xb3933c53a37e8d6a +536, 0x40537d6206fce5a4 +537, 0x3d6562e600316952 +538, 0x853babe67dc6d5fc +539, 0xc9ec1b74c77a1be6 +540, 0xb17e8cba32fcb3b0 +541, 0x49acd5802328ad54 +542, 0x4f709402e925e357 +543, 0x17419c407e3c214 +544, 0x5e758c00e4ad3ff +545, 0x7fde5d319d81baeb +546, 0x979a20b570910f27 +547, 0x8f97c3b7bc9e2298 +548, 0x12e2ad36da1cc7f7 +549, 0xa236e7dca97e968f +550, 0x1f04cbca5bc0154 +551, 0x3d6f127682d12600 +552, 0xc804b6f9d73c745f +553, 0x46aa2378c21345cc +554, 0x5c22330d6f5a499b +555, 0xc4afed1b7326be94 +556, 0x1641ecf0c9a05ed2 +557, 0x1f78fcb51185438d +558, 0x4e9d044248ccc312 +559, 0xa2bb59525d96e061 +560, 0xd3b0cbbe755638eb +561, 0x8c8aa4004d6c679 +562, 0x7f8f8bedc781d3c0 +563, 0x80f49ed821a1a95f +564, 0x773058f8744da45 +565, 0x7ad50eacc2795e2 +566, 0xb9e5489a8c83b4f2 +567, 0xc69f139896eebc1f +568, 0x1e43056dd8930ca7 +569, 0x6f301a2edb56134a +570, 0x6c2317117ee73dec +571, 0xb2c8685976f265d9 +572, 0x16b2bde0a97af5a0 +573, 0x742f17525776cf92 +574, 0x1c61c4de2d9a2698 +575, 0x8c9af9dc2211b55d +576, 0xa3cedd5c5841f80a +577, 0xb59a544f559dc6a4 +578, 0xdf8fff92e4ee4db +579, 0x56b7366da8b55759 +580, 0xd8e36fe0d19f75ab +581, 0x23e355b5133d1b2d +582, 0x372dbbfd1a91bfa0 +583, 0xec3a5bfc17d9f90c +584, 0xda6fe7ef39ac4212 +585, 0xba4be9c5525834c1 +586, 0xd7fce5922edc81e2 +587, 0x601ea3b1ef2b295c +588, 0x7019d5f3f8590283 +589, 0xd335a01edc3f7cc5 +590, 0x561e4eec723f9a8f +591, 0x25d5c1063d9ce2f3 +592, 0xd92c0a861004228 +593, 0x4ced9cfa54381973 +594, 0x64575d21559fff7a +595, 0x9b9941185367da2b +596, 0x81bb1186ab30672f +597, 0x3e22dee929fae7cd +598, 0x9316d034a8d5f460 +599, 0x5544fa1e4ccfd6b6 +600, 0xb548fce22e15c29c +601, 0x4a0c0d2156cec5c4 +602, 0xaf626e963a3d720c +603, 0xa18ccb5d828344cd +604, 0xacb3dad256bd3927 +605, 0xd9415709dd1b9838 +606, 0x5c5b91e09865d9f +607, 0x916e81ea4277c555 +608, 0x47fd254a985abcb9 +609, 0xb4bf05873d1de57b +610, 0x78be8dbe976e57be +611, 0xe4497bee300305ad +612, 0xa35bc9c0b8790666 +613, 0x50e32823b12df325 +614, 0x2d2235134b876e43 +615, 0x4d11093673d2f723 +616, 0xba9a6386593bb306 +617, 0xff94de871ecb0f5b +618, 0xfa30dee676c84ad3 +619, 0x3deaa3f79a9c0e3e +620, 0xee5884952aa60b5 +621, 0xc785a19fdff41a34 +622, 0x8b0845fe5f10501 +623, 0xa152b0aa81b88df6 +624, 0xa19f3d7b2118d7e7 +625, 0xd85b2d1b42a29eb9 +626, 0xc9e3567083b1b07 +627, 0x173666e13a07198e +628, 0x5d523316500ff20e +629, 0x911ba2359d617b98 +630, 0x5e2e9d9033cb6c6e +631, 0x28d18aca1d7a2bc7 +632, 0xfd8b5c9ac51081bc +633, 0xae9791fd100e0e0a +634, 0x62bbcfdfac3357cd +635, 0xad0eb70d33a1528c +636, 0x3f6bf8f30c99a45f +637, 0xcef98adf350e59a7 +638, 0x42a3ce1618e864ea +639, 0xe593360a79499134 +640, 0xd2bd28c812adbd7b +641, 0x4ea00dde869a07c8 +642, 0xf0fa202e5de5c677 +643, 0x80e31fa27e0bf3 +644, 0xf6e3947034e63c80 +645, 0xd792c5bd89a9ed4d +646, 0xfab57bccb903c09e +647, 0xff018b3b5e307f5c +648, 0x9bfca67e7f2358d6 +649, 0xdec771cacfb0257e +650, 0xeeefd9fea081fda7 +651, 0x1076a0fbd79b2c07 +652, 0xf44113350dd482e8 +653, 0xf191e0fc45973564 +654, 0xc3e3444776e39e6a +655, 0xfdd317f3d4debba6 +656, 0x54ccec6719532a9b +657, 0x9a6e8ca48d8c1e7d +658, 0xc609af730bb6d832 +659, 0xa8b4c8470d968391 +660, 0x5cf64a7f47b204e6 +661, 0x5e965176dfa25003 +662, 0x66813628e15874bd +663, 0xd35f6b140e1878e0 +664, 0xaac7f75e4539ee5d +665, 0x39be402d139f7abe +666, 0x1cbe6759828a8ccd +667, 0xc670bbac7cb8211 +668, 0xb2c2d0f58e907080 +669, 0x93ef7a9684abfe0 +670, 0xceb30e0e22ed95a0 +671, 0x2c440668139c0076 +672, 0x32e60072a459bcea +673, 0xb0bc43bf10e8f79a +674, 0xa8531d49c980b58d +675, 0x45f37d8f1c93663 +676, 0xc9fd75750fdfe198 +677, 0xc36b9ce50aeeeae0 +678, 0xe8fc776625253cb3 +679, 0x70c77614d74d06bf +680, 0x51c1cad2d2f2badd +681, 0x66a4db21d7db02db +682, 0xfaf1271dee5b290f +683, 0xae86058acd20130f +684, 0x745443d08c22783a +685, 0x223143faa7c25250 +686, 0x5b1cde70be845cb4 +687, 0x4f0df398464d9edd +688, 0x6b20e39a68f7c30e +689, 0xd37f02c77f07e8f0 +690, 0xe1bf957b24c8b2a9 +691, 0x562dc0bf6f77d28c +692, 0x76c9f88dc50f60ae +693, 0x9702059e9c5919c9 +694, 0x281383e10e722801 +695, 0x171f956c8b0712b2 +696, 0x5eaf54175f8edeb +697, 0x7cc99560d2398c4f +698, 0xc4d69f843120e45 +699, 0xc941f10439e94167 +700, 0xb34086ca06e338c6 +701, 0xa01d149b929f36bd +702, 0xbd19942652a4afcf +703, 0x4722d03a7e6970ab +704, 0xc0e805aa2dc36bdd +705, 0x6e68e26fecfeee1c +706, 0x4aba8fbd1caf2a03 +707, 0xdebe09b8084c052d +708, 0xb332c6c54337d33f +709, 0x903cfa39f4899243 +710, 0xe688cd984e93f499 +711, 0x2c6ae72dc00fc910 +712, 0xde0d582c9957f91b +713, 0xebe5afa3d0c3d91b +714, 0x4fc2b36f2a137cc +715, 0xed2107ce829ed259 +716, 0x8ffeb322143a2190 +717, 0x8e53ef386fb835a0 +718, 0xc73496bdb11c7047 +719, 0x6ca8c4835c9c4f8c +720, 0x8ea4f4901f2e0265 +721, 0x644a3a28ff8560df +722, 0x8953e7fdf979ed19 +723, 0x43dc435a24a800a3 +724, 0x2f15b97ed169e6f8 +725, 0x3ce69e60d6bcd79d +726, 0x5a733285b92355f8 +727, 0x31606b5b067028be +728, 0x1b4f051f3664639e +729, 0x859f66e980f2a3a +730, 0x46572b5b026e4d99 +731, 0x3a8c3dbab89136e3 +732, 0x30fcbfb69d4e2045 +733, 0xc2001ffc2ee041da +734, 0xe2e789a7d6b5c353 +735, 0x20a6a29c6bc894a +736, 0xb9c75c4ffd10962 +737, 0x58de12481df29458 +738, 0xc3a269b0fcf75ec2 +739, 0xfaba5acbbc077e5e +740, 0x8c281f561efe477f +741, 0x61d8922c3b1e9f79 +742, 0xc92d49730840a9ba +743, 0x5ad9b3bd172d9804 +744, 0x4da50ea6a7a283b2 +745, 0x5e781612f5f1ca9f +746, 0xb6a3887cbb2c4080 +747, 0x2b2a7dc43c678866 +748, 0x5a556144413f6593 +749, 0x286ee3aa8819f92c +750, 0x45c169e82a919218 +751, 0x913f34ea9bf5d6e7 +752, 0x48d84f1aef099220 +753, 0x843e00085d83b19b +754, 0xe639c98005983b17 +755, 0x223f1d8680cfe4ed +756, 0x6b589d901b8e5ddb +757, 0xce43033319d740cd +758, 0xb400d5b22521cbd3 +759, 0x6b89f6ac56a9f684 +760, 0x21dc6e3bd591ee5 +761, 0xe062d33650fe9bac +762, 0x7d843bb328d65a27 +763, 0xc4ba63ee38e9d608 +764, 0xdefe72f65f0185dd +765, 0xfbcd7e2ef2ea79f9 +766, 0x514e2e715ce8f7d2 +767, 0x21af168dda65563 +768, 0xf0952635f1b9b8b6 +769, 0xcd098331c00eb2dc +770, 0x88d48ac80843c49a +771, 0x3fcef1cdf0cc92a +772, 0xea558fc018ffc6d4 +773, 0x53fe63708554d32b +774, 0x82a976d57ad79413 +775, 0x5671621e1cfcc958 +776, 0x9057b32b84fd54eb +777, 0xecf93fd1f073494 +778, 0x95e3be825c83bbea +779, 0x31f711958b37fcb3 +780, 0x7764e9c1b68905d5 +781, 0x19ff29bbe3450d1 +782, 0xbe9d66d0b7a63370 +783, 0xb90d94f54339e1c7 +784, 0xb86e7e4f983f5058 +785, 0xbb37df7a822c631d +786, 0x34d71226eddefe66 +787, 0x647b6f2dd0167b3d +788, 0x2964bea0cb5814b8 +789, 0x5111f6bf0575d9b0 +790, 0x598e941686def9ad +791, 0x541a6d6e840b4142 +792, 0x6a9ec878a98f32cf +793, 0x28e7a3598a6cbe38 +794, 0x22b0e914e1d9aad0 +795, 0x6e4f306af93619a8 +796, 0x62ad701e6072aafc +797, 0x20f304620a3e4459 +798, 0xd7217bc244bb9cc1 +799, 0xeb66fa201326ce9d +800, 0x60a8de18a022c5e2 +801, 0x31a14a91815a918b +802, 0xd90de92cb757c772 +803, 0x738a110b95e161f8 +804, 0x2ef5cf2da3e98788 +805, 0x76b0bb8ff3123517 +806, 0x4bef942413b602e9 +807, 0x1c90bd1e24c93bd9 +808, 0x20eba165958bac22 +809, 0xcd5639b3751988cf +810, 0x6fc8cc48b1dd184a +811, 0xfdf2eab5e428ac3 +812, 0x621d191371614b86 +813, 0x3977622fee6de38e +814, 0x501165fbcfb2a7bf +815, 0x3d117c309c6a11a2 +816, 0xf1f6a98f2d352d28 +817, 0xf7b0984596865aca +818, 0xb9eb071ad42bb21d +819, 0x19c555aeeaf0cf28 +820, 0x425c90febfcc526c +821, 0x8133e767f229ca4c +822, 0x50534af80dc7d238 +823, 0x4267194590c15804 +824, 0x5afc2d9d7a0692ea +825, 0x66feaa4a0443081 +826, 0x10f74efe039c5534 +827, 0xd79bc6e3e26cb0e +828, 0xfd511b94e4229f4d +829, 0x4b3735fb47ceecb5 +830, 0x7f3da62bb14a61d5 +831, 0xd92a4f2f534a654e +832, 0xb906bf6a9989e53b +833, 0x13018c2b34f999fa +834, 0x6590385a18c6a603 +835, 0x8fc8db59a2567498 +836, 0x3cc13cfa2306cc4f +837, 0xdd79e765006a327e +838, 0xcb3dbb849468b870 +839, 0x9932fe5f00ea0e19 +840, 0xdb36176dc85cc926 +841, 0xff36a852d77a76a2 +842, 0x7228cc6dc7a583dc +843, 0x3239f99e8c1e75bb +844, 0xcaebcc7ada26fb97 +845, 0x58695e996613ec7a +846, 0x2167b9da13f07e09 +847, 0xbe7bab67bb8bf660 +848, 0x22d605faa70bd9b +849, 0x4126e31a67fa20e4 +850, 0x9f5e1b0c6ce38bdc +851, 0xafdff88a50a87b2 +852, 0xcf22aadf30733a23 +853, 0x1fd9969ff955272d +854, 0x8f7488ef919369da +855, 0x9fc58576f9366b +856, 0xcd113f7c06d404ee +857, 0xf0c3dfbb77faa02 +858, 0xfa6b4df32e5b13cf +859, 0xfcdfd2ef4ed2901b +860, 0x2dc695fbefb81029 +861, 0x66cfcef096b1aa07 +862, 0xce6c9411a0a43c1e +863, 0x7ce97001b7b94086 +864, 0xa9e80966efa21989 +865, 0x9db01384e57130f2 +866, 0xb4c4481e7ea597ca +867, 0x1fc20274d0a21c7a +868, 0x4e23bbbeb9f83211 +869, 0xd8cad36baeec8333 +870, 0x8742502cb17ca60f +871, 0xd79d2dc157d5afd4 +872, 0xea1b2c00ffcf7ca0 +873, 0x1aa557af2fd43a1d +874, 0xe73708cc03d175ca +875, 0x6229a5af98522983 +876, 0xfa42c93d6b4f22f +877, 0x1e65a381061656e2 +878, 0x8933f33ef286b6b5 +879, 0x17c422cf0aff3638 +880, 0x66c1c8e8488bdded +881, 0x2d3c290f57f89df1 +882, 0x7be0a80f249572f1 +883, 0xe04b4abafd35f742 +884, 0xe7ae3420d1ae8262 +885, 0x7ac0a00e9418b10a +886, 0x2c459481c2268d1d +887, 0x4d83267be8955a75 +888, 0xdeac45087ce7e783 +889, 0x6ba80c634128a42c +890, 0xaccf8778cb440125 +891, 0xee610bb6dbe2316d +892, 0x4354e249ac02fd00 +893, 0x9d2fa76bc69ed31a +894, 0x3e6119655e632f1 +895, 0x94b9895001a11b04 +896, 0x2e24e88414b70981 +897, 0x68ada416de03c378 +898, 0xaa35f41451efd2cf +899, 0x28eb447c4d24bfe8 +900, 0xa5137e57245e7f9e +901, 0xc9b19572f5c16c79 +902, 0xc940ce6692436e95 +903, 0x67411f98ce32ad1 +904, 0x1d40e58013165af0 +905, 0x3cec810dd5b24273 +906, 0xa7c6bc87d530d864 +907, 0xfc43ba7ae1a3fe7a +908, 0x9d8794810bf47814 +909, 0xec8cddf1e0f9e93d +910, 0xa564bd558f2d6414 +911, 0xc5106bef612f55a2 +912, 0x7be0dce9a92ba80 +913, 0x2eb62f6a3f2074de +914, 0xc36ee0b068558f0d +915, 0xf5684163785c9867 +916, 0x338887da708650da +917, 0xbb716f53f9844869 +918, 0xdcfc496eecdda21 +919, 0xdf53415424439f94 +920, 0x3a05abd08e2d9ee4 +921, 0x18a6480a9399523f +922, 0x9cc0dab9dc1983b0 +923, 0xb375dcd416372e71 +924, 0xbd8d75af2b5984a3 +925, 0xe86d2b59f0e26c0e +926, 0xcb6b2f761c2c8fb6 +927, 0x2549bff97b63663c +928, 0xfd29bc4f73ab6a9a +929, 0xf690ba893bafe3c7 +930, 0x94c30c32da8d8ca2 +931, 0x44899149ffb1c95e +932, 0xc23549c093cdf753 +933, 0xe2029fe9cc90d5 +934, 0xb2c70637a91ce191 +935, 0xbcc0420e35bf6942 +936, 0xe108b087861a186e +937, 0x54a69c4b23f5f6b9 +938, 0x4ac1a35efeb13e67 +939, 0x39982383bf0173a1 +940, 0x9eb169c7613a5e48 +941, 0x848940fd0d654ff2 +942, 0xdb663c2c2718be99 +943, 0xe4b7a6ef4ca1cdf6 +944, 0xa560cffd62c75504 +945, 0x26ddb1df4420b2d0 +946, 0x980b3101000e3e29 +947, 0x2dd1445c80dbb8bf +948, 0x135c42daf949295b +949, 0xd19f5c74b895dae2 +950, 0xb690a628b77a9293 +951, 0xfe04f5a5928ab34d +952, 0x2df10dc128a516f0 +953, 0x89f79ab12e337c3b +954, 0xb98c589f33c1748b +955, 0x30df1793cd9f6b01 +956, 0x6538ad32fa56a9da +957, 0x93453d17e6ea27b +958, 0xe2a92ebb82c104ca +959, 0x2ce2b05ef3bc1404 +960, 0x1a327d3cdc07ed1f +961, 0xa7c4bed4e2c10779 +962, 0xfe9c13e0e6912c65 +963, 0x15ea29dc894638 +964, 0x887160de1f9f0149 +965, 0x13a80eb973cf8899 +966, 0xef27446cc86e47a6 +967, 0x8890e569d70fc03e +968, 0x1d0136f928ea9c40 +969, 0x99cb2f3b50431cbd +970, 0xbba687f34ac3061e +971, 0x23a9b639b2bb1a83 +972, 0xa93c79780f08e4da +973, 0x1b9f12f0c9997121 +974, 0x512ab00fd2ed5bb8 +975, 0x928815bf7a2288ad +976, 0xfb76b86de4b7f17a +977, 0x38513665d5c85718 +978, 0xa7af48360b80b6e1 +979, 0xc08b51b293e84a8 +980, 0x7f044ecd175afdf4 +981, 0x73e18a7f5c3efa06 +982, 0xf6ef1911e91f0c87 +983, 0xe09e6a85a182b1d1 +984, 0xeca0e6fcfa3d7c66 +985, 0x2466210516727cc0 +986, 0xb8cc106a4bffefda +987, 0x41ad3e2899041e58 +988, 0x4b5ba3abf6a9fec3 +989, 0x436fd42b29a1e822 +990, 0x9d9f29ada8a6b310 +991, 0xf9f066631426bda4 +992, 0x36660b826a0a1b8d +993, 0x26aee243162a41ea +994, 0x8c38cbfbf0d4b792 +995, 0xcda46557b68f0ae6 +996, 0x5900339a5e9132c1 +997, 0x6de1710051cdc7e8 +998, 0xb76aaba70884f776 +999, 0x297c27d0daac3c3c diff --git a/_randomgen/core_prng/tests/data/philox-testset-2.csv b/_randomgen/core_prng/tests/data/philox-testset-2.csv new file mode 100644 index 000000000000..1c2d4eba06ba --- /dev/null +++ b/_randomgen/core_prng/tests/data/philox-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x79969cc23abb91b4 +1, 0x5d45aaf4ec59c2d0 +2, 0x694e6df1b3048ed4 +3, 0x29caa3dbe7b3fad3 +4, 0x40de4437fb7c6391 +5, 0xced65c8c17cbd934 +6, 0x3a34149842e4c076 +7, 0x4bd68ff0459067c7 +8, 0x22a1cd386c044cb +9, 0x707d516e7b2321bb +10, 0xd31e9fbe226156b3 +11, 0x1e7c92b4a1111385 +12, 0x40b26d1e3ad54f68 +13, 0x2b512df2e2c7b340 +14, 0xbc566a77564902eb +15, 0x38019add5d6c49f2 +16, 0xabc12bede6d19b9f +17, 0x8ffda997c28b3314 +18, 0x7758a16e37aa29dd +19, 0xc75be56d772bbd45 +20, 0x7dd842b9b7ef652f +21, 0x874bb05dffe32330 +22, 0x6215b5d304389ab0 +23, 0x67b7659e0f6f074d +24, 0x3dee6f7f663aa80e +25, 0x35f1ebc3a43422e2 +26, 0x91ca84accba13894 +27, 0x19a82e52cf0a5aa5 +28, 0x99193ec846ff4752 +29, 0xaa85d8c7b98454eb +30, 0xdc9fd9a6cf639903 +31, 0x6a7f3a04051963e4 +32, 0xe6315de20fb99cc5 +33, 0xc6e64d30591ea5e4 +34, 0x2c3a032c8af3ea95 +35, 0x4a6ac2609731f163 +36, 0xd0075b64c816b32f +37, 0x6ba834fc94d46b11 +38, 0xce81c72980d4c0d5 +39, 0xe4527c390cd95d99 +40, 0x281a4f40fbef803a +41, 0x8b96b67ef65af945 +42, 0xd8228d14e17d995c +43, 0x822e355afd5a0708 +44, 0x76875e970f78780 +45, 0x1dd4625c16f578fa +46, 0xed94ce7d1cf6affd +47, 0xfd92c8d7728d9656 +48, 0x31da5185dee2c21f +49, 0x8cb0591af5c81267 +50, 0xfca589420074336f +51, 0x8521d19430fae019 +52, 0x20273ae3419daf9 +53, 0x27ee172bbae69340 +54, 0x98fce350defda2d6 +55, 0xbf8b350e4cc6c7ff +56, 0x30718006f3e0170b +57, 0xe06ba2542d7acd63 +58, 0xdd2af87a79df1722 +59, 0xd7fdadbfc51ac4fe +60, 0xbf5cac7b6b07e5cd +61, 0xead793949b8ed548 +62, 0x1840f7d95c0fcaa9 +63, 0x9abd3340d80c15af +64, 0xa287da079eb9a1d8 +65, 0x1f0f530858927e87 +66, 0x56abe10813899150 +67, 0xbe0182c8f2ab4575 +68, 0xf9e318a24d72471a +69, 0xca9fa810134e0866 +70, 0xd6f89ce5a65a0791 +71, 0x120528d7fc273c9f +72, 0xef0c8cfe4b167be9 +73, 0xef5d36463f4d8c7f +74, 0xa017cd944ee9c3d7 +75, 0x6c38f735847f9c65 +76, 0xafb6a0a5ced5e991 +77, 0x6d474406bcbfab26 +78, 0xa90b7997de0d58f3 +79, 0x1fed779ebc5d221a +80, 0x77a5fb8e08e9ae6d +81, 0x70150de0fda752f7 +82, 0x55a942db08ffdd56 +83, 0x6a79d3640b2e7d68 +84, 0xf74772c9926374c1 +85, 0x8f37888d12b4d52f +86, 0xe331da4eb3ede8d6 +87, 0x9a248bc67dbf1b35 +88, 0x35fb9ec1b8f35151 +89, 0xd55260d8fa30259c +90, 0xf2dc194b962d0dc3 +91, 0x7421accacb7612e4 +92, 0x84188c4b9af469a1 +93, 0x7dbf34d5fcc07b5b +94, 0x6814325ad6bd0142 +95, 0xe81c0fb52c978dc0 +96, 0x7383aeadf20cdad7 +97, 0xdf578a6544720b72 +98, 0x2bf78fa3ee23ee5d +99, 0x86de4a9a5d5b30ec +100, 0x5399499273ab2312 +101, 0xb7e56b49c81098ad +102, 0x545c46236115c503 +103, 0xbb1ebf762b9f6d50 +104, 0xfdf2aa180180f729 +105, 0x53cc5b07cfcbfe8c +106, 0xb83e28400cedb4e +107, 0x9c31e53a2e1d5692 +108, 0x3f0826e1d4354c85 +109, 0xf4fcfe401a637569 +110, 0x1efcd12f58dcbf87 +111, 0xa444a0c48c35221d +112, 0x72d1c01d6b6bd176 +113, 0xed0d5d536d32ac13 +114, 0xe954ce02b26a6059 +115, 0xde62023001249b9c +116, 0x841f789718400085 +117, 0xeec06a70d8c0621f +118, 0xd291a59fc833590b +119, 0xc6376fd2243fb8b +120, 0x28a87d88893881ce +121, 0x98d049b96c67da8a +122, 0x1aa980a3f10e9bbf +123, 0xe659d1a052cfa2f7 +124, 0xda413dc6222914da +125, 0x661e049b99b2056e +126, 0xe288cd7c76014e5e +127, 0x865d98946f3ca341 +128, 0xfd4a9504dc3c9481 +129, 0x68821b878bea1073 +130, 0x98a9ae702cca6f4d +131, 0xb02c218bd6ecf7be +132, 0xad9f2cc45e9f71b8 +133, 0x1a73edfde94ac922 +134, 0xad6e36771e49599b +135, 0x33132de3eae3b26b +136, 0xe38bf29f74c219c8 +137, 0x9a7d1bd6d6954dc +138, 0xfa0504aa41d2da3 +139, 0x18c2c0a825aa8c77 +140, 0x4575d335c5a52fee +141, 0xf8e12f4237ad2574 +142, 0x4da2b3d1a4b207a5 +143, 0xd483ee8735b0cd0e +144, 0x9b92d7e5650dce24 +145, 0x2e85af91423bab47 +146, 0xec285fc870875add +147, 0xc049f35180d0b26 +148, 0xbf9d3486b1510d3e +149, 0x6136b10aa8cd75a +150, 0xf4a468c92c6b01c7 +151, 0xe6d7ac00bee004aa +152, 0x5a060bd23d3d6a16 +153, 0xaf68b049fb08130 +154, 0x188cde6b2e6d18fb +155, 0x913aa1123363a9d +156, 0xb35a584b6899fbb +157, 0x1a0b2cfcc7002419 +158, 0x51a6f914a1436297 +159, 0xae5af7e12493c9fa +160, 0xd5a4a33453104298 +161, 0xd46c795e6ced12dd +162, 0x24578f112e9896e5 +163, 0x3879bc9d1d1c79df +164, 0x38d21818a9044427 +165, 0x1489a65967bbd74c +166, 0xf004d910e27d5453 +167, 0xacae738e2b4a1b7c +168, 0xee8dfe42955be33 +169, 0xd9d5d1ecb7524335 +170, 0xaceab4d48e8eb2a0 +171, 0x7747bb87ea6f47e5 +172, 0xfd1b1bab29e1a5b1 +173, 0x2f4b6b0f9300b44 +174, 0xdab086094510e334 +175, 0xa571c54824e95668 +176, 0xfc5108b22f0c15e +177, 0x9989597611a00527 +178, 0x6ef24f0f951b29c8 +179, 0x5824eef87de85c1a +180, 0x78a35def7f709c63 +181, 0xfdfac9f100645cef +182, 0x1f0027accbd50b57 +183, 0xf4379eb0e470a43 +184, 0xe108523693012b4d +185, 0x1dbcaa15e104e367 +186, 0x91a01715bfa8f4a2 +187, 0x90b12f2dc6612875 +188, 0x3a0c81439df90067 +189, 0x92bcce47af32a0cb +190, 0xf1f8ec01579f0749 +191, 0x656fe00e45f73d01 +192, 0x66b3ce57b8a63a03 +193, 0x7f711c6efceb22f6 +194, 0xcf6c2d639062aea0 +195, 0xddc95dcbe9455707 +196, 0xe24dbe6495077239 +197, 0x7d02e17fba62ea00 +198, 0x84d60e07638b79c5 +199, 0x767bd78a1e45e41f +200, 0xfe3fe1d74008b0c6 +201, 0x4b98deab82ab23a9 +202, 0xdb104f1846592508 +203, 0x23086e881366ad53 +204, 0x64c16b00fbf72cd6 +205, 0xb19eb55587ad61e3 +206, 0xfdb8caa9ab6dfe07 +207, 0x125b0675253c081b +208, 0xbd8ca76e7797a1d5 +209, 0x6fa2177be1444f15 +210, 0x23c4388e40529ab0 +211, 0xf3ad977faf5aee04 +212, 0xb1ca87d8c64c3bf2 +213, 0xa68ee8636f7a4f7 +214, 0xa40199a2bec23e46 +215, 0x5fcae2801e7e0b4e +216, 0x2e1260c7c7afef8a +217, 0xaeb347f6912b9cf3 +218, 0x2702e2510b9b4e4e +219, 0xd281ab9c087c1401 +220, 0x7d73d1c89ec1ecc3 +221, 0xfaf594c2b9bd6355 +222, 0x78641e1415fadd6f +223, 0x6bcbc45443f34f98 +224, 0xc5ea1bbd7ad47fc1 +225, 0x21a6bde64e7934f0 +226, 0xe48d5c1eac30eae +227, 0x7645dd59feeee713 +228, 0x236dc6e399a0f8b +229, 0x7d47bb3105e270d0 +230, 0x5c30af0f8e670624 +231, 0xd77864a3d3eedbaf +232, 0xa8ce734357f09a67 +233, 0xa5848bf5de97769a +234, 0x197e3bd0511be793 +235, 0xf1797421fced9f11 +236, 0xab395568cdb296d5 +237, 0x2c163053937c4e5c +238, 0x88aab0204548c66c +239, 0x59e43e9ee50ccf47 +240, 0x5646ec79dc2b8717 +241, 0xdd21d5fe2594e739 +242, 0xe3b36b715e030f2c +243, 0x72b9c7dc781ee215 +244, 0x3928edaa51d23161 +245, 0x18072b29ad229306 +246, 0x5a6e1a7146df0219 +247, 0x44fa2420a3a521e5 +248, 0x26c8c4d7e48e49c7 +249, 0x19829824d9ab3d0f +250, 0x208e2308990de3ca +251, 0x644d4c7725308bb +252, 0xbcd356813965c89e +253, 0x7cc4a5d0629a09c6 +254, 0x78ecec3f9f660e71 +255, 0x4c5017c2cc05d260 +256, 0x1a630b52a53d5d4c +257, 0xaad6058d6091bddb +258, 0x42310f01d0dec7ba +259, 0x352501f1bf98692c +260, 0x5b32220790b2eef9 +261, 0x9cec92f85a3ad24a +262, 0x392bed113812b6a7 +263, 0x2c4a91bc9a27b61d +264, 0xa3ddb8a73a00331 +265, 0x71564f4cc1ff38b6 +266, 0x3bf1cdb52f7d6121 +267, 0x317f2427d4ece2ff +268, 0x61b510f62d30c1d1 +269, 0xf3118eb3bc72b4db +270, 0x6cf9e03844d59394 +271, 0x9a48891e9593372c +272, 0xe6f07884178198e2 +273, 0xdb8d7ffb3f7b48e7 +274, 0xd843287403436ab2 +275, 0x281067329d659944 +276, 0xa9be89389e933e98 +277, 0xa559f1b2c64d698b +278, 0x177c147eecc213a0 +279, 0xb60d1b8907f932b6 +280, 0xbf3dfd3933f22dde +281, 0xc97688e8fc9e974a +282, 0xf10b069f84d5a0bb +283, 0x30aef0a063e9948e +284, 0x149d4526e4606eef +285, 0x3d47374e3f68d21d +286, 0xa8ec81fb5259d900 +287, 0xa8a2f4cdf3ea7a0 +288, 0x15bcdb63f1092d6b +289, 0xec827b483fa8d1f0 +290, 0x31fa9b0586f00970 +291, 0xdbe7d320cf2931a3 +292, 0x1b11cccdc34368d1 +293, 0x1fe27662861788f4 +294, 0xf709d76eb49bd879 +295, 0x2450c5dc16476c8 +296, 0x7a0a7d863198b16d +297, 0x5d1f6c9563f68aa5 +298, 0x36c7d7757e74eb02 +299, 0xc0656a90d456269c +300, 0xeff66ab0f6d035d0 +301, 0x27afcd4b473c8f6e +302, 0xadfc46fa3ee6ce03 +303, 0xd8096465daf41c99 +304, 0x602ddafb5eaa9460 +305, 0xd731e659599d021d +306, 0x33c3a32355ab4e63 +307, 0x974e3554d7bcc0c3 +308, 0x249dceb9428a7bd4 +309, 0x378eb9b47abb256f +310, 0xedbce8679ab00480 +311, 0xd1746d7de7777fdb +312, 0x14a30aa451c0f7b7 +313, 0x1d28baed82fd8b04 +314, 0x714174c401e78e26 +315, 0xf1788905ecb84469 +316, 0x22eff71d89f9be8c +317, 0x6b2819eb724b4e74 +318, 0x1636191b8000b39e +319, 0x73ea3d60587f3cfe +320, 0xe7ed97702c468226 +321, 0xe10824982050c4f2 +322, 0xfc2749ffbc81d160 +323, 0x5cdf3c2d78f56706 +324, 0xc01c94db79631370 +325, 0xc5f5776c2840747a +326, 0xada78ed21449a7f9 +327, 0xe987713c3d87e4f2 +328, 0x7b8e12fcf69b7ab +329, 0xd596a488c255523e +330, 0x9e9b813baca7c51e +331, 0xa624b911e58175a2 +332, 0x3c832b46e35fa5c7 +333, 0x515825156be5fb3b +334, 0xe91c83a0fc6c7f4d +335, 0x907e8ed6e7d67004 +336, 0x7de3df361f634d83 +337, 0x1ccf96f2394200c2 +338, 0x845175395e3598e1 +339, 0x4905098c8b06775a +340, 0x4424d6e6a10c0c02 +341, 0x820010ef3887713f +342, 0x2d918fc9225aaa82 +343, 0x32eba0dd41ce9092 +344, 0x1b66fe6dbc525c20 +345, 0x394b67ad8a323e4a +346, 0x5e696185a5c86bd9 +347, 0x69b12c2752514602 +348, 0x1ff9214a510255cb +349, 0x2bc5a0ca899aad12 +350, 0xb57d6e14b16a7718 +351, 0x79beb7612a6fd6e7 +352, 0xbc79c45b1f8e7f8d +353, 0x44d32a278b964fcd +354, 0x2e483a22ca7de50b +355, 0xf5ceabc566b350f1 +356, 0x7b582ffc4b9d5e43 +357, 0x42ab9492574ac3ab +358, 0x3a8a1fec1ab3e71d +359, 0x75478c52e0efb094 +360, 0xaf1377c197c720e7 +361, 0xd1be85afc6bd298e +362, 0x9a4e6e8660a4d81 +363, 0x1a4bb91a268e65be +364, 0x3a10b0755792f8dd +365, 0xe95153d3eec0c19d +366, 0xf3036b6f8e02be83 +367, 0xdffc9d3fdc293619 +368, 0xfad8ee79745a8a9a +369, 0xa9a8062d64f3dc61 +370, 0x7ddb3f6012d81dd8 +371, 0x623856260cae9962 +372, 0x35d0e6eb91622fa5 +373, 0xe3fcfa2208a3b5a8 +374, 0xcc8ec36185748ebf +375, 0x762cd35896ae6777 +376, 0x5e529053ce500de2 +377, 0x6545fcfc0da9a2c +378, 0x8cb156892a6669be +379, 0x96f80d4770f396a7 +380, 0xbd99a1ca2c8d3e41 +381, 0xd6297cf0b8e5eb63 +382, 0xb522d18d7b34c41e +383, 0x4c76d7b243817c1 +384, 0x733337cba2e74d55 +385, 0x769ee9acdce2279a +386, 0x158fe92000a829d6 +387, 0x2de70d67481a26ee +388, 0x481a32f89f48bbf +389, 0x7910c1fd5b66cbcb +390, 0x40e915445d6794ba +391, 0x694dd31fc3616af4 +392, 0xf66a0f17f6ca78a +393, 0xd09055d52155dd27 +394, 0xd0e4a5654cb1f0d3 +395, 0x27a33f6e7976580 +396, 0x2bc002e93ea14a88 +397, 0x8163bbc9277dfc50 +398, 0xd74612f9829a45e4 +399, 0x492779facb39266a +400, 0x2b4a269c9d211e86 +401, 0xdc88f4805b8abb5c +402, 0xdb8cb18b5beef640 +403, 0x14effaf6271aeae5 +404, 0x133fdf95232daaf4 +405, 0x9811dd5ee80ef423 +406, 0xe80815ce0f365122 +407, 0xe5a983ff40008d1 +408, 0xc22f3249a950a7a3 +409, 0x2d6a29c7daeebc71 +410, 0x7271a3a40d1734d5 +411, 0xb5efee15c4c99160 +412, 0x7d7c2efe86ddaf7c +413, 0x928ad499a4d85e9e +414, 0xddcef9fd941e988a +415, 0xb57daba38cc70276 +416, 0x164b60673494c318 +417, 0x2af60e897eae1cb3 +418, 0x74181074bff82452 +419, 0xe7afe1452aca2b1e +420, 0xbcee4075ee5e82f9 +421, 0xdeb277d596122a61 +422, 0xad4ec522ed5fcbca +423, 0x7ae8d97528caa837 +424, 0x96f5bcd5902002ba +425, 0x77127d87f69da6f3 +426, 0x5ebf71761fcb9e16 +427, 0x79c817f24b4acca9 +428, 0x21ad1662937a31a5 +429, 0x69e3ea5a65934f93 +430, 0x1b96b0d05b7f12f9 +431, 0xf1a68375ae6e350 +432, 0xbce495ba788c1f93 +433, 0x35281fc46a1ed6e4 +434, 0x38db141e96c2fb20 +435, 0x55d11f14ea71953f +436, 0x2c00398cffff67e8 +437, 0xb16dabaa263e92a2 +438, 0x9f21e025912c81a7 +439, 0x67865a4fd348f4e3 +440, 0x8b37f5aa1d953557 +441, 0xf972409a9231da99 +442, 0xdceb2001f7ae4f3 +443, 0x8f840ed0e94b642 +444, 0x7fb486ac9cf23354 +445, 0xbf0731eb9fb2f26f +446, 0x64f6a87eb3ad3997 +447, 0x2efaf458ab38b3af +448, 0xb0a84922ae63a985 +449, 0xa6e4ad47f5a8bed +450, 0x78ea04257180c6ea +451, 0xdab32fcc7935f61f +452, 0x81c51b7fc2702c1c +453, 0x63fb80362df72986 +454, 0xb672007383cbe435 +455, 0x3c2795c9fd489191 +456, 0x382fba5fdbbd0d1d +457, 0x5b7c398dd14c7819 +458, 0x62f0b67bf107ac7d +459, 0xe064c5f9f54201e9 +460, 0x176eba949b66b75c +461, 0x82678f7ce2748a4f +462, 0x43ea9b0b4852476e +463, 0xa7f9cf3569313631 +464, 0xc0833878700008d7 +465, 0x140e34c3d600d7f8 +466, 0xe0bfa1eba68fec03 +467, 0x4e3ae5e387d3f283 +468, 0xb799c08bac503857 +469, 0x217b43c04870ab8e +470, 0xe5e845d2fd3bcfc5 +471, 0xb335c469515e740e +472, 0xc2e3c4de7a47050c +473, 0x817b2e6751cfc87b +474, 0x59eb6cd8266ed00f +475, 0x61719b760716f1af +476, 0xc632bab8a5379b7d +477, 0x3fd80526456a4087 +478, 0xce5ef34e009a09a4 +479, 0x4da72557a2c81e6d +480, 0x45035c138cf0a07f +481, 0x2e0e2c65cf2fd15a +482, 0x5526e0f129feb1bc +483, 0xf970fd5e145bb284 +484, 0x4ca7ada616378b04 +485, 0xa8f8ccaf6fe721f3 +486, 0x1b69aca028dec51a +487, 0xc646b9db8f01cde6 +488, 0x77d8bc4b328434e9 +489, 0x5b8c1bd76c5d361 +490, 0x998199eb58998641 +491, 0xacae79454a30f83a +492, 0xd1456bd45a42152c +493, 0x1a7aee80e3e170f +494, 0x5d611e45c9446edf +495, 0x8c681b0c3daa09bf +496, 0x91affbbcf9c1e020 +497, 0x7fa4f3756b231b2a +498, 0xd2c13c5a29826810 +499, 0x993830f7fa0d51ae +500, 0x80636484c971d447 +501, 0xbe32c99bfecf878c +502, 0xf1880b2dc3e4f7e1 +503, 0x4b8fa1cc8fe57b65 +504, 0xdebafe0f90ad1b5a +505, 0x1d11dd9200f8b4b8 +506, 0x75042aaa397d9a99 +507, 0xc9ee367b527e2a09 +508, 0xdecdd82920560b63 +509, 0x64dfc74fd7f2bfe +510, 0x6ab0b966bc6fcb9b +511, 0xeb0199bf8f8a3816 +512, 0x7d603f5a0fdf7616 +513, 0xbf0177f27b06e799 +514, 0x83a5a1dd75b536c0 +515, 0xf898601d81b9d989 +516, 0x264944efd59443dd +517, 0x8e93bfdffb880aba +518, 0x697561a56735dd59 +519, 0x4377f57af134b8cd +520, 0xb84884431d02a53d +521, 0xfcf3b5efbdf216c8 +522, 0xbca95d7a8ad81290 +523, 0x3320c204d5e92a49 +524, 0x5e19b0ec2072b07e +525, 0x3ac2c56483ec19fd +526, 0xbccad8ee0f613b5d +527, 0xd351c964ab750837 +528, 0x4b46de746194625a +529, 0xbcc0a7cbaca03293 +530, 0xe35955fded6f2276 +531, 0x21aef4fb23229559 +532, 0x38c67966f1aa2296 +533, 0x2313034e68aad3a6 +534, 0xe79c154be56b5576 +535, 0xe8313f229a85e811 +536, 0x32ce60d1f50fd321 +537, 0x47713272c46d00b +538, 0x16c9165c6f10d24a +539, 0x30e39109e3275951 +540, 0x885b243b1a057c75 +541, 0xea6743a2c6a384af +542, 0x4a7270162f8329c8 +543, 0x6ecbc6ad90ade794 +544, 0x8f5e8dd3a37e94e0 +545, 0x91d2ad50e044c382 +546, 0x8b6bb0b7f6ac61db +547, 0x324b36acdaab4457 +548, 0x59ed97721860509d +549, 0xc45924166bfb2ea2 +550, 0x7cbb46bd01b1ca53 +551, 0xa41d17a5456d70f7 +552, 0x22d26eb275d0440f +553, 0x74bc05ce1bb10c2e +554, 0xd4ed1084eb81c707 +555, 0x75e936d690b1c4e9 +556, 0x94dca2299e381e0f +557, 0x7f7ae722fe2f3642 +558, 0xa72d301ef5d62837 +559, 0x1bc5cde83663d558 +560, 0x36d21d07bf182d05 +561, 0x37bf7daa7282720b +562, 0xa8f37c56dac3d1fe +563, 0x8a973e5fdca1418a +564, 0x3e4fa296626fc6eb +565, 0xb00b0d0baa75d0a8 +566, 0x2bbf9c70cdf0f0b2 +567, 0x41a8ca894eb8dae5 +568, 0xfaf4d210bddc32d9 +569, 0x1e317a055a699e1f +570, 0xc01d715dc83689b7 +571, 0x32008479d35b9d3f +572, 0x16bfea67573f8517 +573, 0xdd1418e1ca46d5a5 +574, 0xb3f330c663a20f9a +575, 0x5bd1c898e9611e78 +576, 0xf6df66445155ec97 +577, 0xc905ee3a15b83c9d +578, 0x50797ef789745157 +579, 0x1330d937a4856523 +580, 0x1001c0e08524c59d +581, 0x95b258cac211f178 +582, 0x2e61f6778ba53029 +583, 0x7e35c5afb3b67215 +584, 0x4a966942b4ce407e +585, 0x63c0fa981400623d +586, 0x2788e6c96c1826bb +587, 0x1d58691c7e579526 +588, 0x554a15ef02ac25be +589, 0x310310aa113cd278 +590, 0x932347c64ef37cfd +591, 0x3480e6062a9de198 +592, 0x3df126e84fed6094 +593, 0xeb1b2d9f2f7faab4 +594, 0x79305ff41717170e +595, 0xd16dd9d121ed79a6 +596, 0x380bf103a818f05c +597, 0x6d4ead6c20945455 +598, 0x358c06a132638a3c +599, 0x8a31c49306807c4f +600, 0x8348dcc031129070 +601, 0xadf66bfd4278f38a +602, 0xcd95d2350db96365 +603, 0x81d71916ebbefa43 +604, 0x1a0623944ba56e2c +605, 0xd1bcefa9d4e7bfd3 +606, 0xdbdefc03acdec398 +607, 0xfde9fa4617ef7ddd +608, 0xfb1e9e696648bb26 +609, 0xbf88b7580d5927e9 +610, 0x4da178dcc3a89aea +611, 0x94db8b1d876087e4 +612, 0xecfcf60f47c79854 +613, 0x9ef7d0d251da35a7 +614, 0x453f774fa09a8d10 +615, 0x8c31c57925b239fd +616, 0x8e580a43a3bff5ff +617, 0x9af792c383b7395d +618, 0x9df36c3bbcd3bf55 +619, 0x93579179eb304881 +620, 0x2502bfcd7d85a7fc +621, 0x7145b93f7f91133c +622, 0x24d943ff68afb6a2 +623, 0x7ed7322e9d26161e +624, 0x98d58e67dc211d3f +625, 0x606e6eda3d49e928 +626, 0x91ff5582f2e126bc +627, 0x32c18cbe9f068fa1 +628, 0x158fb0b7b1cbb0f +629, 0xb8efba4e9e18aa84 +630, 0x73042bf5836dae0e +631, 0xb08db72716e1547a +632, 0xa77c6291e0bc43cf +633, 0xc32a216129c65832 +634, 0x9ba8c3a6e28320c3 +635, 0x68a860b0460f4d7a +636, 0xb2d6acaad96ad2b8 +637, 0x7e99ec06a1b12969 +638, 0x4e73072434778be5 +639, 0x45c738380472436f +640, 0xacc1dc0cb1671a1d +641, 0xe2b3a601c8028dd2 +642, 0x4f9011640c0cb086 +643, 0xc6424d085d77f7d8 +644, 0x4be1e01ddc4931ab +645, 0x7cc90d0d28c27c95 +646, 0x74769cbb87388666 +647, 0xd09b8c57ab2ab780 +648, 0x9e37e07f5b413afb +649, 0xe2a4dfc86e985dd4 +650, 0xbcebd68950a62876 +651, 0xe61186758e286164 +652, 0x5be83633e0653215 +653, 0x60f5f3346f1e7a63 +654, 0x90be5b5bd3e71f3c +655, 0xd873686587fbaf23 +656, 0x56a78bdda770ffb9 +657, 0x10ac45a16daa49f3 +658, 0xb8df2a1dd5781cc2 +659, 0x7b2ed0fc9abf7e9b +660, 0xbea9373bd4d879ec +661, 0x130c660f2edbf5b +662, 0x5d3f614bbf3204f +663, 0xf328a315e9d0b932 +664, 0x7cbe580281817508 +665, 0x3b7ae752ef5de9ea +666, 0xd88a2f398c8e195d +667, 0x2db535bba7ba7358 +668, 0x762e4bf7fe733a9e +669, 0x126f629c46663b0 +670, 0x91bb6e238a5a9669 +671, 0xeea8827b9c3f2e5 +672, 0xe86738844c67fe4 +673, 0xed15fd801bb9d73f +674, 0x157517cf2091af44 +675, 0xa73e89c3d7bbf546 +676, 0xb56f610a41176770 +677, 0xeb33707d25578bf6 +678, 0x1b89e1301a46663f +679, 0x75ddc343b67f1ea7 +680, 0xe2da07af36f0448d +681, 0xb5567854075a0f6 +682, 0x6247afc791977380 +683, 0x824b342ef7df201e +684, 0xd72654ce78b69f06 +685, 0xa81b601c56d7cb9c +686, 0x721c4b5d80932ead +687, 0xc99bba379d154c88 +688, 0xb12e74cabfb084de +689, 0x182d98bf2d14d5b6 +690, 0xabd6445ca6180320 +691, 0x61bd348533393374 +692, 0x8b24cce3636ee185 +693, 0x9d9092316dbb7960 +694, 0x46b005f6176cea5d +695, 0xf07c167b80eeb610 +696, 0x589f0fa902170da5 +697, 0x96cb5756946a309c +698, 0x8a8eaeb00cc65201 +699, 0xb283c55de49423be +700, 0x67f5595dcba6dbb1 +701, 0xd9776bfbf6065931 +702, 0x6e10ca882deba83a +703, 0x6102d62102809372 +704, 0xdfeeeb5a115e8703 +705, 0x9b2320c4d818be3e +706, 0x9168936a8d01a485 +707, 0x22d3744fea4f78dc +708, 0xd40b836aa128a062 +709, 0x6c61a41c6d65f12d +710, 0x55730397d9510398 +711, 0x7dee61ad38acc6d9 +712, 0xda1912bf3de3e557 +713, 0xbfe6c019850006f3 +714, 0xe845fb0710682483 +715, 0xcdf60b34c368e5d7 +716, 0xd6e7dc0e6c3df1b1 +717, 0xfeb190e94f30088d +718, 0x4476cfcd6c9bca02 +719, 0x2977673195da3490 +720, 0x96c568ec008e2df4 +721, 0x817d59faea6f872c +722, 0x2bc4e7547b5e1381 +723, 0x25c7680da190b93f +724, 0x2dd815c2e3716198 +725, 0x85bbefcc5b6d1f6d +726, 0x5ec31ffbefc3056 +727, 0xc29d2756e13c1449 +728, 0x25b61ddfdeaa3182 +729, 0x2365b4967dc141de +730, 0xe275f2a9be026689 +731, 0xf30d1c218692aff5 +732, 0xb48fe560af269c01 +733, 0x9852c4e3dfa37603 +734, 0xe5a1de23fcc3f727 +735, 0x22fdaf11989cd063 +736, 0xe397e17c8392a847 +737, 0x7529eaad7a530992 +738, 0x5f3f32fd3dfb3320 +739, 0xfc9f4b0bfb548db9 +740, 0x1471cf6df6e134ab +741, 0x873db4bb386fc282 +742, 0xbc94c6a3780f79ba +743, 0x4bd508d98988c251 +744, 0xd1a817a879c8923 +745, 0x12a350db356edaab +746, 0xd3257e02fe6faddf +747, 0xdc09eecdbc32c2b5 +748, 0xde18b15a13a8dc6 +749, 0x753c4c30f7c35e2e +750, 0x596d3436a834d6a0 +751, 0xf3319db462c1b9c7 +752, 0xb73715d61ffdb26d +753, 0x5330c9d08115e44 +754, 0xc008a119c220cfa9 +755, 0x1f624f431b83ed39 +756, 0x6d1130e066efd112 +757, 0xfd3eff082f54c839 +758, 0x1b31da85da96c5a0 +759, 0x849e94a219c2b71b +760, 0xe1b772ea1fb31ec4 +761, 0x67db72a68f2ced9e +762, 0x99426581623fba83 +763, 0x7a6b306ed67cb4dc +764, 0xc18f42740fa62dd9 +765, 0xce90428779eeed7d +766, 0x9d1c7db3d6c3491 +767, 0xb26a8c31ab6f277b +768, 0xd31845885962e222 +769, 0x83aaeff5e24f551c +770, 0x5a73fbc17f10d179 +771, 0x5cc19c3807d48a2f +772, 0xc8e6f01324d0bf9e +773, 0x404f95c06aacef62 +774, 0xfbd0e7a11580e337 +775, 0xe35a206927cad6e4 +776, 0x79a7b1b6c80142e5 +777, 0x81a28a97d7110959 +778, 0xa22d612df01a16b +779, 0xbed9dbcaf3d82bd9 +780, 0xd3e5b22df6fcca95 +781, 0xcf4626d3739b65d2 +782, 0x3bea29bf8bcb3439 +783, 0x3e8f7021bb137dcc +784, 0x2fdd4faa44a68574 +785, 0xbd830ac3f0be7750 +786, 0x7a3e6f39eb05d5c4 +787, 0xaf229fb1db175bc5 +788, 0x7295e47bfccfb76e +789, 0x62695e99d0a25e7b +790, 0x30cd8850c858838d +791, 0xaff09ffcea838e89 +792, 0x4e9d0b99386dbf42 +793, 0x9eac0e6b0025bfb8 +794, 0x383465e3b1a6fffe +795, 0x5b6c0c45aaf4ce5d +796, 0xe5cfe9da80e4348e +797, 0xb1157c89a7d97df +798, 0x1c27501515138d47 +799, 0xd4f4a083e3d14728 +800, 0xdf69ff0a7982ab61 +801, 0xc376eafe88dc182e +802, 0xf93ab7882723b2dd +803, 0x89b8a08615a7aaf6 +804, 0x2b6cdf2f80adbdef +805, 0x2d57a9420550aa14 +806, 0xe9c1ad378ee6612d +807, 0xb48e3b9ca52568c9 +808, 0x9e67310a9b7ad7c2 +809, 0x24f74c637b7fd180 +810, 0x8956247efecfb1db +811, 0xc0a17f81a8a93104 +812, 0xaa2226f0ff5ef2b9 +813, 0x6aac7d569a285253 +814, 0x642982be37a0a179 +815, 0x1da6f2b46c5eb14b +816, 0x146eb12f17563cb7 +817, 0x490e0fe4d69695db +818, 0x50f6bb32abf00166 +819, 0xc78be77c8e1a7b3f +820, 0x130b147b093c659a +821, 0x8a28c321e9df8c19 +822, 0xbd81ea9f26c58a93 +823, 0x786c73446361dc31 +824, 0xfeb7d2a60d500f73 +825, 0x84b0e0368a98bd73 +826, 0xc944c636fb4f2ad1 +827, 0x64dff6c2acc378b +828, 0xe26a5b23e5f2bf96 +829, 0x86dee0cf9f52dedc +830, 0x13f40d996945e7cb +831, 0x9965d35d76866320 +832, 0x55169e779bc4403f +833, 0x5453e9e5d6399943 +834, 0x7ae5cce348460939 +835, 0x206be2007941abff +836, 0x59a1fc9441a2c060 +837, 0xd65e845fdc736883 +838, 0x2d9411da47dc596f +839, 0x3f8bcba4fd0f03d +840, 0x533895c1b19c6262 +841, 0x9cc38eac5006493 +842, 0x2244a1f903232422 +843, 0x8c7eba4b9893e04f +844, 0x8b669e0537581368 +845, 0x48aa4ce1b62dea35 +846, 0x98a789136697266f +847, 0xf087571d08796c39 +848, 0xeff986fba7345e0f +849, 0xd0d667be7bb85237 +850, 0xe83dbf0bc699feb1 +851, 0x8501ff412116d9ae +852, 0x4d2c06d690a13e80 +853, 0xf64b077cba13b5d0 +854, 0xb166fee2ada390fa +855, 0x3bc475043c332873 +856, 0xe21b6d7da7e9ee13 +857, 0xac6c3264958b1f6b +858, 0x701c1df185e6fddd +859, 0xaf7e8501f7445559 +860, 0xe34e79719b3c2367 +861, 0xa75d03f5b049c044 +862, 0x7b1fed41fbb62155 +863, 0xdc98215140275e6a +864, 0xb593660fe8bf00df +865, 0x499f416dfea8a062 +866, 0x2463b217bffaf042 +867, 0xde955f615e68a961 +868, 0x9db7cab1b500249 +869, 0xc4e0c255193f8d3c +870, 0x3a220f4068fe8189 +871, 0x310f311d1151affd +872, 0x9d2723448ff8a1bc +873, 0x219c5f555182f8ad +874, 0xcc6a54b756154997 +875, 0xa9894b81e72d03b4 +876, 0x1c489f42758b4008 +877, 0xc57737e1fff628da +878, 0x752e08a04dbb3654 +879, 0x397ef980659aeefe +880, 0x6da11abffcbf51df +881, 0xb28f6931d8425ccc +882, 0xb2589acc6764a5a4 +883, 0x6e7caeb3edf4c9ae +884, 0x3333bef1c33d3648 +885, 0x50b975012e7f0d58 +886, 0x4c24195a5576d9e5 +887, 0x5fb697e515523d4c +888, 0x4c25e6146105725c +889, 0xcade882dd4674db0 +890, 0xe0f1cba246c94df6 +891, 0xc7ccf728811bf9a2 +892, 0xce2b631b55492ed6 +893, 0x9ca2e1c4fd5080d1 +894, 0x5c99b44ca03cba57 +895, 0xc12a90a937b45e7b +896, 0xd97f8d5d4c44db88 +897, 0x54077ccf8ba0193b +898, 0xe1ce544f328b8d8d +899, 0x8a322880b5237d01 +900, 0x286a178d86ff3d49 +901, 0x211a8e5021074880 +902, 0x3be20d7210e4a91 +903, 0xb7c35a62c4f646dc +904, 0x2b409ad4e03b7290 +905, 0xac3087c5382e7e58 +906, 0xa3748972b982ce4a +907, 0xb340ca0dcdd4fc46 +908, 0x92a567cc37525316 +909, 0x32ab0e108dd31e1a +910, 0x9cc564c8306fe4d4 +911, 0x2f30238d788e4aa4 +912, 0x5d7b2d5a1cfb3ca6 +913, 0x3d7c7cfb5c3dac2a +914, 0x68a2fcc7c90bc67c +915, 0x93c931b07c7bcaaa +916, 0xb07e858c5f6804fa +917, 0xf34487568770d540 +918, 0x92d0c14ac66fc693 +919, 0x1df3edf3172dbe1f +920, 0x99dd6452e5beb2a3 +921, 0xe38aa3644a74fde1 +922, 0xc049af84d1206652 +923, 0x45ac2398eaf40225 +924, 0xd12607b558ef0006 +925, 0x1e7381c46a70f619 +926, 0xdb7c30532160e472 +927, 0x73ef892949f375f6 +928, 0x19ffd06c4ab2173f +929, 0x5d36078951fde0ab +930, 0xa1dd5b24e3e82ebe +931, 0xa007a426d0f94cb +932, 0x927ab34a8d844365 +933, 0x8a3e93aae579f9c9 +934, 0xfab14d979a048f4f +935, 0x91a360f46855dcf2 +936, 0x76466996b49f4705 +937, 0x12d4f323c1a88644 +938, 0x5505395519967856 +939, 0xfa64fc82da5d6486 +940, 0x1bd1dc97bd219e89 +941, 0xaf41e0011c68d69c +942, 0xf1851e78d15d95a0 +943, 0xc00178a6f4449839 +944, 0xf74517746fee73d0 +945, 0x14e21fb6693e2dd5 +946, 0x30fe5c4d988342c4 +947, 0x9981d1554e52001c +948, 0x164e36540569db94 +949, 0x711c12fa1f32de8d +950, 0xe43201111f3e1990 +951, 0xd3f5395b84e4d93d +952, 0x40319e5870e18ea +953, 0x7a45fee8655d707f +954, 0x3610639f0564fd3a +955, 0xac97da399634ec25 +956, 0x5cc8615a764d8cee +957, 0x82463c24e8b3e5a1 +958, 0x3af60e152b97a91d +959, 0xefcaa0964723b3ff +960, 0xd5979b8da2b0875b +961, 0xd718909a9cfd5aef +962, 0x985995c251b18b56 +963, 0x2c7c126f9a0eabe2 +964, 0xb4ebcd9ab305d7e1 +965, 0x28fd69e0a7bb4846 +966, 0x2af7b43ea9164e56 +967, 0x9f72bdc5fe1ec72b +968, 0xf1a884206bb1559c +969, 0x5caea3abafc00777 +970, 0x2e5901b394a13b22 +971, 0xdd4281ace415ef7b +972, 0x1e421afa2c23a9ee +973, 0x64942a448f2a61f7 +974, 0x32475573b78af5e0 +975, 0x348602ab7221 +976, 0xda1cf48b3c778ac9 +977, 0x202730803de016c +978, 0x7f07500a97253303 +979, 0x912df89c5702453b +980, 0x7a483f96506f7e2e +981, 0xb0331694db0d3557 +982, 0x244b924fd11c49ac +983, 0x5d1097770b6f4740 +984, 0xb227f8cb5f5ae045 +985, 0xc66e1b71c02fb86a +986, 0xe08b547dbee66315 +987, 0x4e7e2986cce8bbff +988, 0x96f7bfe16d59aa73 +989, 0x82f97f418750013e +990, 0x1329bc356103905b +991, 0x82183603b406408d +992, 0x3818107e93ac9397 +993, 0x3b477193a3f61669 +994, 0xf4e443832f9e886f +995, 0x466becfe7debd82c +996, 0xe32937bc5daaf7c7 +997, 0x90bd4530b0e0574a +998, 0xb78055db48f56255 +999, 0x78829570b3775e14 diff --git a/_randomgen/core_prng/tests/data/threefry-testset-1.csv b/_randomgen/core_prng/tests/data/threefry-testset-1.csv new file mode 100644 index 000000000000..ddfa736dc398 --- /dev/null +++ b/_randomgen/core_prng/tests/data/threefry-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x8dfd999efc587d2e +1, 0x3bf6c47ed872597f +2, 0xd82537743662be19 +3, 0x46103c1408067361 +4, 0x7346b65b404eb9fe +5, 0x4b83687af205cda8 +6, 0xc9cccc1fc1c330 +7, 0xf1998771158a2109 +8, 0xda5dc10ad259dbda +9, 0x4646e487520d8e1 +10, 0x159fc0e3e691e0af +11, 0xe2776a537d1a14db +12, 0xc1c7a9c84e1ebeae +13, 0x884ac2384b510f2 +14, 0x4884b09c9a60131 +15, 0xb13a1cda0d508af4 +16, 0xc3d21a2f212bfce4 +17, 0xa3b801d11d523597 +18, 0x1032f052626e5c62 +19, 0xd3b97f4372f6b7d8 +20, 0xd2982ca1c2af2372 +21, 0x13be3d71202f619 +22, 0xdace9f84ef1ddfa6 +23, 0x111bf9b9cd36c31a +24, 0x1ccc5e5be7281a26 +25, 0xa4cd1aa57030bafd +26, 0x99e30fc07a8990a3 +27, 0x9bfa5257d8e64ba2 +28, 0xfab6cdc7f1ed5221 +29, 0x85a4cf41ee744f97 +30, 0x1bfa09917b2906ae +31, 0xda161ec1288b8909 +32, 0x6b1b3ca2bd91573 +33, 0xcef3a71775de82e9 +34, 0xe8ca72781abf1c22 +35, 0x5b8b673b060631ad +36, 0x6658737a84dfe2a7 +37, 0x65a2254b602bb09f +38, 0x5ee6bfeadda0b432 +39, 0x8f3e8af494aeb36f +40, 0xd1c29d016aa72890 +41, 0xfd96891840f0e51d +42, 0x6103cebcf8398a46 +43, 0x7d899055702823a0 +44, 0xf9597bb3dce6d7e0 +45, 0x85b3bf105f26219 +46, 0xedfe4b32a28e4386 +47, 0x74f2415ce2908181 +48, 0x7de6c2f16372ca16 +49, 0xe2b29d517e17feb5 +50, 0x30d7ffc292038441 +51, 0xad4522ce80cf4c1b +52, 0xa9c79bfa1f31b5d +53, 0xc2f17eaf6c6fb057 +54, 0x27938c6a95a6663b +55, 0x239db1ec714acc17 +56, 0x8df60daf4949f4bd +57, 0xb2f6b97d127209d4 +58, 0xad58961f74c8596b +59, 0x6e920c60d6460627 +60, 0xc3839f29e9ce8be0 +61, 0x339161e608237aa3 +62, 0xf148b8d4fef7386d +63, 0x2cf8bd6438b2a52 +64, 0xa1e432e4a618e741 +65, 0x56e1e56517151ed5 +66, 0x61e528b5a3f6d4ce +67, 0xcddea3f49d6ded23 +68, 0xf966618d29452959 +69, 0x5d4fb65eb30e8f28 +70, 0x4a913ea38620fee5 +71, 0xa00f4c5528a3b760 +72, 0x1ac5a2ce0486d8ab +73, 0x521ca18c998b8d5 +74, 0xb0779142f4d0bd69 +75, 0x22f054d9131f1fe8 +76, 0x8c45b6c48016430d +77, 0xbefe70d6c6f8727e +78, 0xc581436cc4c2c0ea +79, 0x5864d0268e18ee15 +80, 0xca47fe47d22aa5e6 +81, 0xdffdbbc0db7ad425 +82, 0x2ae423bd73de5d15 +83, 0xb83b4651838308bc +84, 0x16fa5f72b53c5d6 +85, 0xa0b6cb353724ac01 +86, 0x64d4dc2db97a7d36 +87, 0x79ccd3dd98b33cdb +88, 0xadda2d6132e73ebe +89, 0x7d1a82eff9dba6ce +90, 0xc27defdc4f9c42a7 +91, 0xe12bcf2300cc0585 +92, 0xdbc65c0ee8511e31 +93, 0xaa9a1edff55c22cc +94, 0xc007f355f38dc50c +95, 0x4fbed1aca4bf4222 +96, 0xf137a501255f8852 +97, 0x416ce22d2c6b8e4d +98, 0x5f9fc6ca7a7e9000 +99, 0x9133f67a9222cbf +100, 0xb5fad01321365bfe +101, 0xe3e971e5481249d1 +102, 0xb2950204c847bc0a +103, 0x7ea97815ffa7d45a +104, 0x482c5be26c8bdf3b +105, 0xe42e7e3114197d0a +106, 0x3b74ae3e10f20ae7 +107, 0x92a5e6eca6ce4c38 +108, 0x951ef146ac76378 +109, 0x282f71a81cf08455 +110, 0x3f267412ad1483a5 +111, 0xa5b91846efa301ef +112, 0xaa31cdcfd08603b5 +113, 0x2e16b10730082c4f +114, 0xbdf14631f750e96 +115, 0xd008abe07ede91b6 +116, 0x994ee56c08ff60bd +117, 0x53f0ce17c7c350b9 +118, 0x4c6f01008b3f93 +119, 0x575ee5e7fa184714 +120, 0x83ef0302e14bdc0d +121, 0x5bf2a34323954dab +122, 0xb489e8c4c51a8683 +123, 0x4c9e9801a6acaa07 +124, 0xe9d2e19c20612fe0 +125, 0x2ee2ca0a4d83aa46 +126, 0x19d3a90895d7773c +127, 0x4130367c3abf9b1a +128, 0x1163968e394a67a1 +129, 0x67ffcbbfe478276c +130, 0xd57b578ec019ce0c +131, 0xb455156a987ea010 +132, 0xa9b429ce5f337432 +133, 0xff84cf0f673cc4c4 +134, 0xf034b32b302d0953 +135, 0x9bb6bc59375bbf53 +136, 0x44a2d4bc278da710 +137, 0x78023c9fc08e6247 +138, 0x6b27a1397bd5d278 +139, 0x193758c805b28105 +140, 0x28b88044af4b5313 +141, 0xdf32108c3da9cbc9 +142, 0x6cdb5ffbc5b589e1 +143, 0x702d9691e509de76 +144, 0x405cba179f3db3b5 +145, 0x73d44e0be3ac8048 +146, 0xf9d578eed861f37d +147, 0x9d04541aaacab238 +148, 0xce4507880b30adca +149, 0xaec02613164bec9a +150, 0x346180904e9beade +151, 0x624adb9e18bf4dca +152, 0x3ad2ab92b1f11b23 +153, 0x7d5ae064eee4f228 +154, 0x4e2bb6e3851953c2 +155, 0x55bedadf90ddfa04 +156, 0x4f9422b9142c837b +157, 0xeb5592fb0a763ead +158, 0x3ecb85424422c74a +159, 0x119bbfa61eb2222d +160, 0x6505a8c9e46616bf +161, 0x57bb55ae533b24c5 +162, 0xd6cee34b85233f67 +163, 0x7ea146f8a6edccf3 +164, 0x76615fab897424c1 +165, 0x6d79fe83053e2769 +166, 0xa2759466a39a899d +167, 0xc71216f7edc5fa52 +168, 0xbad1fec86d6684f6 +169, 0xd461ed7882597a5b +170, 0xa437d1518e84a43d +171, 0x5f7d08235e202553 +172, 0xdd87bf84dd2ee070 +173, 0xf2be8b7cda72f89d +174, 0xb221c206f95bb237 +175, 0xbf0643fe5b908171 +176, 0x6bf7c1606a106580 +177, 0xdb356bbb10ea4eda +178, 0xe237835dd0d4690 +179, 0xe6c2fff624891ed0 +180, 0xe08936b04987ce88 +181, 0x2837dbe9582a2658 +182, 0x51d176aba32aba6b +183, 0x5e84cf73553b7d65 +184, 0x65ae1e2bfd16072a +185, 0xf1e5ba1a331380bc +186, 0xd635cc846b72af5 +187, 0x5b0ebda48c952d27 +188, 0x5e05122799559b71 +189, 0x58636876eda68987 +190, 0xbd7af40a48bec96e +191, 0x85c640b51a9f45f1 +192, 0x204a037b8e6e312c +193, 0x961e7967c267be6f +194, 0xa638d40cdc30c59c +195, 0x5a39715f059bdc4d +196, 0x672b41e8c97af455 +197, 0xd30fed911bba090f +198, 0x491a830b50c133b5 +199, 0xa17c651d10ef18d4 +200, 0x18c5ed30299ca860 +201, 0x422b896bb244bf22 +202, 0xc5f46ffd55ef2588 +203, 0x709cc6441b029ef2 +204, 0xf253dfa120c336c1 +205, 0xecaa82e7fbe74f55 +206, 0x2fd810efb17f6736 +207, 0xe7a25ab84fb25ed2 +208, 0xaf7193b55b4f2c68 +209, 0x2a759a4ee4a1ce66 +210, 0x16996f2d902284bb +211, 0x87d8c6d1879f76fd +212, 0xdc966392468278dc +213, 0xe41e4051d267adfe +214, 0x381a17ee5c0be0bf +215, 0x92f27f7e4d3316a8 +216, 0xcfc791e85c47d026 +217, 0xd3fdbf29fc4b3b9a +218, 0x42e5919e80dbe10 +219, 0xab84a06c93add70a +220, 0x4f09d5438a9cf6ed +221, 0x60e5a77f3e81cc62 +222, 0x86e0c8b80336e771 +223, 0x899c3c4372b18cd8 +224, 0x8e4b3213708a89e1 +225, 0x265ed6061b84ce2 +226, 0x80770e2169b55299 +227, 0x39fccaaf318d18b2 +228, 0xf1b996ca0a6b8dcb +229, 0x2d5a2497533e1bbf +230, 0x82e8bdbea5fd4825 +231, 0x96beae4bc404d6a3 +232, 0x6bd730a492452ec8 +233, 0xb64ebc3e1342d159 +234, 0xb1632475806f1236 +235, 0x2e753cfda372774b +236, 0xa071f3cfac5af1c2 +237, 0x2cf0268115fca199 +238, 0x79255186612c0e7b +239, 0x2ddda40d56bcea5d +240, 0xcae06b8e382dc2f3 +241, 0x4c4eeb5a29713cb9 +242, 0x9094b57b8a7d48e0 +243, 0xc770e33c1203b229 +244, 0x86d82971c2c93900 +245, 0x890e721300b7c4d3 +246, 0x3060aab5f8cac918 +247, 0xbe1eb72ed892942e +248, 0x7c9dd3cb08d8b96c +249, 0x5fd00ae5885d5de9 +250, 0x4417cce0c28a8c3f +251, 0x43cd3a2dc30b89de +252, 0xc2cb18532d9530fe +253, 0x28abfd68d23173ec +254, 0xc4d76303811fce07 +255, 0x59bd12a60ec03a +256, 0x34d7ccec03c71605 +257, 0x8b75d9264501f015 +258, 0x7cd57fab83c4a0a0 +259, 0x8da871dc3cbc9eab +260, 0xb584498a027618eb +261, 0xc6e40e951710b610 +262, 0x41178da78714af7e +263, 0xd23bf6c5d4f72956 +264, 0x96a7e56e7cd445aa +265, 0x9a0c33f1026bc110 +266, 0xa9e827283fabfb28 +267, 0xc5db920653ca6532 +268, 0x7d7c2798440bf4fa +269, 0x29c67ba6461f747a +270, 0xb8714cd0b123302c +271, 0xd3dbfaad42155417 +272, 0xbf7a42afb38e35b2 +273, 0xc68987e460f75e2b +274, 0xc1870d0d8b3749d1 +275, 0xedd865f6c4742810 +276, 0x97257a657fb3cabe +277, 0x7481e43145a8d41 +278, 0xd5bf38b5e9dafc7f +279, 0xd79afc7b1005e7a +280, 0x6ad40d65e9b5a5ad +281, 0x65075c2e32fff49d +282, 0xd1be9510a7f3b969 +283, 0xd07acc1e3f6eb257 +284, 0x41dfff9ffb08776b +285, 0x2521ba1b48ef458c +286, 0x178fdba8b65a61c5 +287, 0xf72679d974b82e5b +288, 0x723c29de610d0b12 +289, 0x84726f3e749c0c1 +290, 0x7316136529dbbb9d +291, 0x62d5c6fcfdd7b104 +292, 0x5ed0a981f49819f +293, 0xedc777d4f5085908 +294, 0xd1758061e06720f3 +295, 0xccdf37b1a089e664 +296, 0x4c7eccdfcc38b22e +297, 0x3af579b044760f54 +298, 0x4ebb096a5a14053d +299, 0xf84f1e6aea913534 +300, 0xab8187a201171f +301, 0x2fdd889a5b23ab70 +302, 0xae0894fe8c9356ce +303, 0x3c98be30e5ac171f +304, 0x566953af2a7a305d +305, 0xb15bb69ebd40f8bf +306, 0xeefca1ec57e47780 +307, 0x88e3d9a3377cd873 +308, 0x39ed63117f8e1ba5 +309, 0xeee20fabef374e5f +310, 0x836c24fbfe91a231 +311, 0x9de79447cb2301de +312, 0x8e3028226501f563 +313, 0xede195f88a8976fe +314, 0xfa67e7f210a9ea65 +315, 0x33a9286c9cc0519c +316, 0xf293cfc77d255e0 +317, 0xcfd8e6a385302439 +318, 0xf801e78f6bad9935 +319, 0x831bb783f70bac85 +320, 0xb85b9b1e1dcdf06 +321, 0xa41009e83579efac +322, 0x9095c71cf018e4d +323, 0x2ec789714277148c +324, 0x46067636a9ed2f33 +325, 0xd9385c2b49db3d95 +326, 0x69102374c36463aa +327, 0x94dec24132bb3042 +328, 0x81c5ff32132d8a4b +329, 0xa9cf7ef654a14c5c +330, 0xcea3e704414db905 +331, 0x9b8ad73d3cecbe73 +332, 0x59c3613f1f59c91f +333, 0x96becdd5d3d6eb7e +334, 0xe532174a0e32c691 +335, 0x52f9ef72eb3a0e0 +336, 0xc47812f381b1034d +337, 0x112ff07cbc1d95d7 +338, 0x8af49fc2e11d14e9 +339, 0x5f0bb0c8e6d38f37 +340, 0x5c92bc8be957afbd +341, 0xe8f175d0f89fd52c +342, 0x76223aa3b45638b3 +343, 0x3e68dc64b3402203 +344, 0x7a1da1d307e31444 +345, 0xd0eb8f54e2fab68c +346, 0x44182e518700331f +347, 0xf149093ac30a395c +348, 0xfd23f8f75c25fcfb +349, 0xfcf727ca90f9e4b7 +350, 0x85dc5c47fd81b61d +351, 0x72b726cf22d2f20e +352, 0x3f57ccd8f6a33bce +353, 0xe363ae312c97ec06 +354, 0xfde8b0a33423ee87 +355, 0xe8c89d34bb501e9d +356, 0xbd4d8774ebaf9046 +357, 0x40333dcde4e889d0 +358, 0x5c31d5695aaf7a18 +359, 0xc168172eafb6021b +360, 0x1bed01cec3613e8d +361, 0xdeb623f4effcfd6 +362, 0xd02f73c698f24935 +363, 0xbae9cb97df30d4b +364, 0x2c8dfe769edc25ee +365, 0x768041adc56396be +366, 0xf11f31e14bcc8f86 +367, 0x1cc1ac84b5a5eef8 +368, 0x7cd911d41054b0f8 +369, 0x60228e0c35106ce9 +370, 0xa92ac07cfd218b7a +371, 0x6e0ce56984fd6817 +372, 0x780b1c87423fef3f +373, 0x677be089b5bd8fd9 +374, 0x2454954f7e5c8c0d +375, 0xea1d3e8e67934975 +376, 0xd0199f2ad1c5b0bc +377, 0xa7961b7893a67372 +378, 0x28517fd857003446 +379, 0x69cfc7298d4f2aab +380, 0x14e673667c3a9c31 +381, 0x3d2326c751b57454 +382, 0x323f62bc000f68f6 +383, 0x58c1b8561f61d24 +384, 0xf4cb934358649f62 +385, 0xa4268dd0327460a4 +386, 0x922dcda4b4062a54 +387, 0xe1c77cc9775004a5 +388, 0x4d6648be23d1aae3 +389, 0x36e66b76d509f22f +390, 0x98a79de81ada9683 +391, 0x911308910ad0d0e6 +392, 0xa78a75232eb9c534 +393, 0xd1620acff1293f3b +394, 0xc2564f1312d27a65 +395, 0x70d5a4d369a56e95 +396, 0xa27a741994153da7 +397, 0x3fd84f4095c66967 +398, 0x8370c9ea207fa4dc +399, 0xffef37922d7c15d3 +400, 0x10bc39f6a7575b21 +401, 0x6ae92a96b97e1f1f +402, 0x8adfba7ab6ca7a72 +403, 0xdf1b40629ce3a3b +404, 0x55d0451d15de716f +405, 0x2bd54462ff147e0 +406, 0x676723dc7af24d1c +407, 0xc3a7f70b34988a83 +408, 0xe716a0967a8c69d6 +409, 0xaf124e06fc7cac59 +410, 0x7951c1b7294d532a +411, 0x543e87364c521abc +412, 0xff5c44c50d4ee584 +413, 0x4a20724584833ef2 +414, 0xf605912a8c86b52e +415, 0x58e76b9dfd4da8db +416, 0x2279cf8b4a4f8894 +417, 0x99e4535e58af23e3 +418, 0x98b357e92d197aec +419, 0xb665faf7ec3c5892 +420, 0x74ff68056822f96c +421, 0x2443b541f675a9fd +422, 0x2ddb1042d52c00ae +423, 0x53bce4d472853bbd +424, 0xddd12064af825de +425, 0xd9e451ebb7871b0b +426, 0x284e8b62b5140d39 +427, 0x392f6f741ec18b5c +428, 0x53c1471d27c62d28 +429, 0x957c668aaa12dcab +430, 0x905899dcc9c8d748 +431, 0x85b9cdbb0195492 +432, 0x3285475338298b0 +433, 0x362aec5454354816 +434, 0xaffcafd1179a163c +435, 0xe7303efbbc4f41fc +436, 0xe5bef7dc443e92f4 +437, 0xc30a00527a65fcad +438, 0x10f35ee768a411c5 +439, 0x46ab523cfd6f019f +440, 0xf96997ee80420b3c +441, 0xd6bd882bc6334bce +442, 0xce8082585fcccb74 +443, 0x10a585df3e216780 +444, 0x8bef43483e7359bb +445, 0xb88fc9f0de92ebab +446, 0x8f9f9ec7e1bcdc7f +447, 0xec0da8b08dbf8ab7 +448, 0x8967d7116f0ca59b +449, 0x3ec612e1c87c23ff +450, 0x5f4c5e66476f3c37 +451, 0x536d0ddad6830a22 +452, 0xce05b606110b2ff2 +453, 0xbc06b0392b8db2f4 +454, 0x109feccc811d2237 +455, 0x1c6d58cbd3717d5e +456, 0x4bf990f210d7046 +457, 0x98c0e58f2e655da2 +458, 0xe71155da62d7207f +459, 0xe619955157476acd +460, 0x5484ce353c85962d +461, 0x4f30e140971d815e +462, 0x1aee57fec03675c1 +463, 0x9d6ac96b29e5236d +464, 0xa8bc59565b8d58f9 +465, 0x888f185056d1ef52 +466, 0x32bf6f97834d5f3e +467, 0x4fda3ca53a0aad5e +468, 0xb06670f7d65dc538 +469, 0x3394e29fd0a067d1 +470, 0x29f7c702dcaa4d6b +471, 0xafc0eb498bafddbe +472, 0x5002c13e14be570 +473, 0x11b62a54a56e7468 +474, 0x15ae967503c5b445 +475, 0xa1282117755e25e4 +476, 0x247ae0993e30d491 +477, 0x328f519e2974c09d +478, 0x963e0c8c57e3a4e1 +479, 0xfd2d1a916eb9def2 +480, 0xa4625165c4cd23b6 +481, 0x935663b351deb205 +482, 0x4ec13ee6fd28c2ce +483, 0x57365950d55bcfeb +484, 0x36d56e4c073cb9a2 +485, 0xa3deb42d6419e3c7 +486, 0xc0a6b68eadab9a81 +487, 0xf99a94679e32a1e5 +488, 0xc42d64e664eb0375 +489, 0x323de13c4da53f9e +490, 0x548e4376950c3229 +491, 0x5d53452624beda53 +492, 0xdb8dbdc4d06fcbde +493, 0xcfae0fedb5744805 +494, 0x8d093170690f3ac5 +495, 0x31ad2ff1c80c20ac +496, 0x40c7570d7660805e +497, 0xdfc383cd341cc5fe +498, 0xa571fa523e56de7e +499, 0x5fe751124076e6aa +500, 0x6696c91142c1a338 +501, 0x5c2295e731cc37e4 +502, 0xea4759143aeafa7f +503, 0xf51103c2360f23d8 +504, 0x58a0e754c23434a0 +505, 0xc81291121fdac698 +506, 0x8679b3dc92d444dd +507, 0x9ec6662d4aecb616 +508, 0xb508daa350249f07 +509, 0xdaf489538ed15145 +510, 0xcb6bd65b1c81a90c +511, 0x7f5492214c7c11e8 +512, 0x875effe96d081ca9 +513, 0x1e35d4b75f19369 +514, 0x49029232ba45725b +515, 0xa73202231bebe958 +516, 0x8011e084a420d3fa +517, 0xe7ff845074367c35 +518, 0x3a9e9ddb2ff812c +519, 0x6f5e47f4aa71a356 +520, 0x91e5a3a77e5b008c +521, 0xad173c173829519f +522, 0xadf0a51b9dfe9e97 +523, 0xa8fb30c571be5e92 +524, 0xb78e79d25ff80064 +525, 0x120eeaa9accedc7c +526, 0x81020045a1ff2669 +527, 0x66a50f790048fefc +528, 0x933c1efb74bbabfd +529, 0xc5fc20f210302719 +530, 0x8151dec3094fabde +531, 0xd2213b923bf407aa +532, 0x78da0fc0b44771eb +533, 0xd3a628d7eaf1f5d0 +534, 0xf7e444d35eaaaea4 +535, 0x2e5a8469332422c0 +536, 0xc4e9e4166203bdc0 +537, 0x68b11509577357cc +538, 0x1c22ba556358f1a5 +539, 0x1130c889b5c71f31 +540, 0x68fd0def61e6a4d3 +541, 0xd91797bb9243ba7e +542, 0xa2230c8c22e607b4 +543, 0x777331fadde75233 +544, 0x5a10baebd665287c +545, 0xc6e37c206f8ef53f +546, 0x2153e16620a7a26f +547, 0x7c044870163ebd66 +548, 0x2a78dbc7b40026b5 +549, 0xe1b372326f13f738 +550, 0x1bd9ed17eb120bf8 +551, 0xd69aa5ce828d6f6a +552, 0xedb21795bc2fe078 +553, 0x9424cee925d04cb0 +554, 0x1487a67127236306 +555, 0xbb04e7bc49c9e892 +556, 0x7d2cb1fef10eb638 +557, 0xb2165be14331dfee +558, 0x608b006694436407 +559, 0xde51a803f31ecf58 +560, 0x2baad9e91021165 +561, 0xc5fdebb7bfe058d6 +562, 0x7d70f942899e39d0 +563, 0x6125c0830f211474 +564, 0x2b63c71b5e2257b0 +565, 0x38162d3452ce5a43 +566, 0x47d92f8500ecfe89 +567, 0xb4b0e8e986835907 +568, 0x64024e226440fdd3 +569, 0xef14e5e470056074 +570, 0xbd98e6483f249d13 +571, 0xb772dcbc1a4c59f3 +572, 0x39f88aee50df9b +573, 0xe1284ee3b725f8bc +574, 0x30b997b194c75fe4 +575, 0xcb8830869e416d6d +576, 0x96dda63deae7dd5f +577, 0x250cbc3004548474 +578, 0xd386e14eb6612f48 +579, 0x516613a018bc41ec +580, 0x3d38173562501913 +581, 0x8f95bbd2fe704484 +582, 0xeea5bc9616a584ec +583, 0x35a6ab8de8843dac +584, 0x9df0a94962efbd1 +585, 0xfdb0bd56c87735c2 +586, 0x8cfc1e372a8368f5 +587, 0x8b23d5fd3b5591d5 +588, 0xa67e55c12bf454d5 +589, 0xc1de05db8c87c9a7 +590, 0xc922075e71b9a176 +591, 0xb8411ab83c539350 +592, 0x6e3e5390e04bf51f +593, 0x265f5f4efd50c24b +594, 0xda4a0b190ed7e4bb +595, 0xe3b9badfb5f149f1 +596, 0x96b3c82ae413d007 +597, 0x6f0ad7739a6c754a +598, 0x8356ae17125221d +599, 0x7f54dbfd1bed2149 +600, 0x1db3446564c48acf +601, 0xeab66293c35e8bb3 +602, 0xec71de5e82111496 +603, 0x307d1ffb851f3ea3 +604, 0xe7763576290aa70a +605, 0xb54df18f36ec2901 +606, 0x1274c4c6b71070dc +607, 0xd5427bfaa1046f0 +608, 0x779d99339f644b2f +609, 0x408c3b4b6a634b96 +610, 0x1735ee7f87bb6851 +611, 0xa5780777c5f4d916 +612, 0x5bf9f4d091ee8ac +613, 0x72a16b375faacbed +614, 0x1cbcdedec43afe95 +615, 0x969f6bb71211f0d6 +616, 0x16205de04f90e353 +617, 0x3d8383b3ebca6fb0 +618, 0x10fdeba49ed28dc7 +619, 0x7db0d19d648a705b +620, 0x58e3c21bdcabf3d +621, 0x62a3082250cb2532 +622, 0xb253b1030f0b10ee +623, 0x83050c560043946 +624, 0xde988add6676546 +625, 0x40ff1d99d7afa3e5 +626, 0x2949dcd8f797c0d0 +627, 0x85b3588ea7d06109 +628, 0xe6158241a7818a08 +629, 0x874c0e4d8f133e8a +630, 0x802ef6fade0787ff +631, 0xc8f4c96631fd13bd +632, 0x1cc53ceabaae0621 +633, 0xa3a8215bac5844d0 +634, 0x3e9a46365495fca9 +635, 0x5b1a8b67d0cfff39 +636, 0xa4c00a256a7528d8 +637, 0xdb0dcabfeec2f50c +638, 0xb4b11e407e0ce53d +639, 0xf0290a216960acb5 +640, 0x647c256bc27149c1 +641, 0xa4c65fa3a1b3a384 +642, 0xcfc3a91aabff01f5 +643, 0x56af49b0be94e98d +644, 0x78192db16ba970bf +645, 0x8be6ab828ca60453 +646, 0xaec8783f7b08389f +647, 0xbf60b1a0a05822e9 +648, 0x773dcad583ad616a +649, 0x66c7c2accfe05b5e +650, 0xeaf428e3f8a86013 +651, 0xbafafbbea503ca83 +652, 0x12fbfe395a53b22 +653, 0x5b0803a9835dc747 +654, 0x6c104a7da8b0bb27 +655, 0xa8b88e467c4c4264 +656, 0xaf921baa5bf05a3b +657, 0x65ba0568bee94c6f +658, 0x20e4f7d26ae8126b +659, 0x1a21cdcb32a11571 +660, 0xb54cc85ddabf7169 +661, 0x7a96f253742c7ad +662, 0x6232ed42c7776d82 +663, 0x28617c73281c3332 +664, 0xdeb63b98b7f96fc0 +665, 0xa99b062863e06102 +666, 0xebf044bcefed86f0 +667, 0x6e3c394a7dcf0654 +668, 0xa8010615532d4185 +669, 0x7a848c300193a6c0 +670, 0x24cd4460125dc3ac +671, 0xcb7855b33cca6b82 +672, 0xcec13cf78f398d29 +673, 0x8ad170d6a9b257dd +674, 0x974e175bcd30d07d +675, 0xd354ce50f8f40865 +676, 0x4b28bba40a25dde4 +677, 0x6e7e9d53b8842846 +678, 0xa1a7effae10190df +679, 0xd04d564e0c0df5d5 +680, 0xffde7841dc21b687 +681, 0x9b1860198d2e41aa +682, 0x24a7d92cbcd7782d +683, 0xe87352efade1fe66 +684, 0x5f302e85b504b68f +685, 0xee93d343f09d8749 +686, 0xbfd683a06d5944ca +687, 0x325743a5a7dc38c7 +688, 0x7e96fe56f6884304 +689, 0x9bee81fb0adafed4 +690, 0x35e5b7dabf13f87f +691, 0xecb4fe689d3f2d62 +692, 0xc98df0a573051cca +693, 0x31344816b051aba +694, 0x6b74db489de2aeac +695, 0xbae6b717869cd684 +696, 0x9dbd5b6a5263c332 +697, 0xd2a84a6af9dd66dd +698, 0x6ec0ed649d6c0423 +699, 0x4fb425d69c495aa6 +700, 0x5f3c4bb82c849352 +701, 0xf936695a6db83ecf +702, 0x1850bca22a80a0e5 +703, 0xd682f6ac9f78d35f +704, 0x739ed6e0627599b8 +705, 0x2d1c3113339984bc +706, 0x1677a16b08764c69 +707, 0x1a46fe6b943eb342 +708, 0x45bc46da8e1ae218 +709, 0x6b899e934ca545d3 +710, 0xa49c7d04a14f01a +711, 0xf6cc946f76aee8f9 +712, 0xd57765ce52bc2626 +713, 0x9d5a611be45e54f8 +714, 0xc4e943fd1d93c8e8 +715, 0xf8bf900e053ae678 +716, 0x35fd93a2d3ca3ad0 +717, 0x28da11b273ad9626 +718, 0x4046bf1292aa4736 +719, 0xad2edd82a440e376 +720, 0x2d2e469cc5815e02 +721, 0x2bbdb981bd3477e1 +722, 0xf7e1ab492ae78b50 +723, 0xd8e8a2f1deb35bd3 +724, 0x38648d4e5ef1f775 +725, 0x66db82d34d00b6f +726, 0x29d9f8ee57bc77b0 +727, 0xdbd37997c9496231 +728, 0x99da76ed64137b55 +729, 0x41e94018a92a92af +730, 0xe9444b859466bc63 +731, 0x139ea8ec0363ec81 +732, 0xe5573db463b521eb +733, 0x91ee2c97612ff6ab +734, 0x17038e62d8d5547e +735, 0xdae84fda26485133 +736, 0xf32ca23f5fb0a2d9 +737, 0x874a456ee5fb95c2 +738, 0xdd0e839b975e3475 +739, 0x1d45382adaf65c68 +740, 0xe98fb57275e4f06b +741, 0x5680ec280f703935 +742, 0xeddec081cf938ff4 +743, 0xf6e156698ddc7f3f +744, 0x5653fb5f9493628d +745, 0x31128e4f1bb7abbc +746, 0x966392eb3ab3d294 +747, 0xc18f506c9bd5727f +748, 0x33f3861681488c3 +749, 0x88eea94d91f3ec4f +750, 0xc07df01a897cfcbe +751, 0x1273a8b06bb1a271 +752, 0x92eceeb94ee16b54 +753, 0x2372a2660388f673 +754, 0x12f0f9c80ae16123 +755, 0x192880a152ad8fd3 +756, 0x67ddde771ec9e527 +757, 0x29ef5b708626c4fa +758, 0xdf65824bc7e2f5d1 +759, 0xed186a843266c66d +760, 0x82bcae004f3c0011 +761, 0x3a00ac4e2aa8f1b8 +762, 0x14542fa617647e91 +763, 0xab833973b418a788 +764, 0xfff24c07ee1e1a8e +765, 0xc9483de3fa539f39 +766, 0x3ac2fe43b2865dd0 +767, 0x3fa95781cd250f59 +768, 0x306e75a4e686b37d +769, 0x6590018fe7123137 +770, 0x29fa6de7fe953978 +771, 0x235a7778eb3defcb +772, 0x4866fd1cbb1de581 +773, 0x66294fb38c3a4d1b +774, 0x2eba0e0b6a16a3a +775, 0xc416b8fce537f10e +776, 0x11b40b753610cf +777, 0xa800cb9afe30a55d +778, 0xc7843d545c02d7ae +779, 0x19d74191419fd649 +780, 0xed8d718b6f8c05bf +781, 0x321b3469a3b9f8dc +782, 0x558799f6b55c0ae0 +783, 0xb289b9140c769381 +784, 0xc96bb650d7a5d3e0 +785, 0xc2e92e33b8559b77 +786, 0xf4f5f6ae13188205 +787, 0x2ee80f197ec22d18 +788, 0x6d87c2241c3e6d63 +789, 0xd145a7a0a2e7b011 +790, 0xc62cd586690015a0 +791, 0x9f58724c6bb22eb5 +792, 0x1f4d76cccba65f65 +793, 0x2c8ef48d0ed3f00a +794, 0x4100357f24318944 +795, 0x99f50ea3b1e806b7 +796, 0x80b0b55abef2e2ba +797, 0x728eaa6f3dea3ff2 +798, 0xb9fe60138d05628a +799, 0x4670c98cb3b1c59a +800, 0xed88e42657806925 +801, 0xa5f002df4a0fccb8 +802, 0xec8c1a342c98136f +803, 0xa356077ed340cc9c +804, 0xe87cc8ce72c844df +805, 0x663b6b98d1b215f5 +806, 0xe8ad0986f0a51b9f +807, 0xf77e0dd6396d98ca +808, 0x16d0284cc96530d2 +809, 0x21dca6308157182d +810, 0x4e80e0e6a0023ddd +811, 0xec147ee76408744f +812, 0x7772e8a51336d259 +813, 0x5e951007cd864259 +814, 0x9921dd15ebef245d +815, 0xa094b493f836ae35 +816, 0xd7fab52dd503383 +817, 0x2b7f2d67820bfedf +818, 0x15a2ab3bb9a269eb +819, 0x92f10dfb889b32af +820, 0x38fd566d1787da48 +821, 0x2b1f206adf06f0f2 +822, 0x998729e56a03596b +823, 0x9caa4041b8b8284e +824, 0xfe10ef8016e923f2 +825, 0x5181ba35c1a28b42 +826, 0xeb61ed1495837bcc +827, 0x3a320559880e1a29 +828, 0xac1edb5359dd9260 +829, 0xd2ce3b57da95c407 +830, 0x4375b7b9f6fbba1d +831, 0x446ec944796ff6bb +832, 0xaec4b78b5e828092 +833, 0x58004da5a0c153e8 +834, 0x5a2a2fad35215a5b +835, 0xeaf28165ff768948 +836, 0xc082d63ddad8c91f +837, 0x283d10a4300609d2 +838, 0xd2b4552391560573 +839, 0x4fdbefb9e342f858 +840, 0xa43906a7198f7ef4 +841, 0xcef94695a5d3cd88 +842, 0x8296bafa49c5cea3 +843, 0x351e0421b7ce8812 +844, 0x81d394848a445647 +845, 0xbfda8ffeba72599d +846, 0x823c00f90918421d +847, 0x2bad7eceb840b4b3 +848, 0xed9ca1321e8475f2 +849, 0x33ca86b7634608f7 +850, 0x3351c775ea252a18 +851, 0x6ad518a58bbb6469 +852, 0x2114c295e612cd6 +853, 0x18ba78ee3c710e1b +854, 0xfef3c2f9abae434a +855, 0x2f2033652e9eeeb5 +856, 0xfa5baabf35fa10fc +857, 0x38f160d51e3019b +858, 0x455cbd400f87e960 +859, 0x942f1352c9b1445c +860, 0xc61f0edd263951da +861, 0xa447110dcc7921fd +862, 0x4c811f5af4e0cbb0 +863, 0xe997fff7a5939781 +864, 0x1224dbad82b23c97 +865, 0x65cdec93d671a0cd +866, 0x22990c95303470c8 +867, 0x40e6e0c576b97f56 +868, 0x53bf25c3c12b43fd +869, 0x1992bafa30093644 +870, 0xc80b6626b1b3084d +871, 0x46e018183031721c +872, 0x10b23bc65323effb +873, 0x176c121f9bd81f23 +874, 0x19047376d9ddd242 +875, 0x47c0b554263ae3d4 +876, 0x7d6c14c2e40bf7ce +877, 0xeb3c30a640d082fe +878, 0x5155bd10f1818c38 +879, 0x24ca5ce343390351 +880, 0xb9d7a5dfc4f89d34 +881, 0x1b8f0b8c3a3bd8b7 +882, 0x708ab95c219a2ffa +883, 0x1cf3befb2776fec4 +884, 0xece471e68eb13a0a +885, 0xcd9e646295c6ad1f +886, 0x63a5a97e805b58c3 +887, 0x6bdd3bc818330ba5 +888, 0x642a2e1992d481d9 +889, 0x60362b11bbb1cc44 +890, 0x5c10e85acb9ad8f5 +891, 0xb8ceba6af37425d6 +892, 0x855bdea1d7415466 +893, 0x108bec5b41275d30 +894, 0xb0fce44c3caed15e +895, 0x6e1d44a82e34b3f4 +896, 0x698ed735e1db5220 +897, 0xe4d427dcfba23857 +898, 0x85ad0edc6ebbccc7 +899, 0x7c9cd7bc58fa5ff6 +900, 0xc2f19c0d76f53615 +901, 0x773385c16db8f379 +902, 0x2bb9120cfa435e1f +903, 0x295961649184169e +904, 0x20de31c807978633 +905, 0xd36701dbda31b982 +906, 0x5551feb741996e9a +907, 0xf8aaad4d0c52434b +908, 0xce6f4b0dcaef6cfd +909, 0xdacbbb33921fd85c +910, 0x587a5cb0cf051eda +911, 0x42124bd99d594fa9 +912, 0x9ad4a203e1ba3c84 +913, 0x775b758d4944c2e5 +914, 0xa7276e35b33e62a2 +915, 0xf5657d537c6271fc +916, 0x69b45cfd145b352d +917, 0x8672a0e552f7dfaa +918, 0xd5c0b8f929f63c84 +919, 0x1062b14c01bf1560 +920, 0x3ae6927a61dc70e6 +921, 0x2ed5f06dc3ceef22 +922, 0xf79f417a63f1dbf2 +923, 0xf6a74c03f7ab1744 +924, 0xf2a8523818bb492a +925, 0x8db8ec62b7262a19 +926, 0x4ac507b9aa8ac0d6 +927, 0xe1db6db360091041 +928, 0x97205197883ee213 +929, 0xc83c6265be4a8612 +930, 0x99e84f3f743ec327 +931, 0x931ab84b78b922f +932, 0x900ebb02329a6201 +933, 0xdb720a24d6d93400 +934, 0xdd0de802d3780399 +935, 0x177fac072d4ff0d3 +936, 0x95f5688bd75ec33d +937, 0xce19d334b40b7c45 +938, 0x780c71636ca880c7 +939, 0xf8188c0626e3ddbb +940, 0x32ef96e74be5a76e +941, 0x8f9adc11e6ee08c7 +942, 0x860a6c1d95bd01f3 +943, 0xb19d517b4a3054d7 +944, 0x196cb745dc3a674b +945, 0xf611c20fecc9b445 +946, 0xdb0f8f14fbb237c4 +947, 0xfafc6fc52d7b483e +948, 0xcffd5779f52badef +949, 0x8a626e983ccfd9e8 +950, 0x8f2ccac91dfaaad0 +951, 0xbda4bdb3cc57689d +952, 0x2a8af26a1d17c1c3 +953, 0x9feab9b49105010f +954, 0xe2a9046372fe5c04 +955, 0xd55195108d63dd4d +956, 0x4702e92922745d80 +957, 0x423c590b3ef222da +958, 0x2b56e611f1272bbe +959, 0x90d65326f9c21b6d +960, 0x56777609cd5360db +961, 0xa35a55eabfc4d9c0 +962, 0xf6134f2e8cf2a92f +963, 0xfe7864a5510c499f +964, 0xb205f42b43d89001 +965, 0x2618c3eb687e9050 +966, 0x1c85ebb7eafb6c1b +967, 0xfe47cb43ba8f5e02 +968, 0xceed09f98fe493b4 +969, 0xe7e51b4e51c5e0bf +970, 0x53343be07ce85327 +971, 0x816a17136951159c +972, 0x92adfb8807d45418 +973, 0xd6eaf3cef3390e14 +974, 0x6d7c2adefcdd411f +975, 0xdcde0a6376ecb43f +976, 0x47d162d5a140ea78 +977, 0xf55fdc7283476df5 +978, 0x2f66d5d029982dfe +979, 0x56a94f1fdf81fb24 +980, 0x46eeed06237aa921 +981, 0xb5f585d18b026038 +982, 0x29e12cba3b5a03a1 +983, 0xb8433a70685341e3 +984, 0x4e86f031c2bf4939 +985, 0x7167c51db1d096e1 +986, 0xa300693a1ce05ff7 +987, 0xddf7f5ef8994b6f6 +988, 0x5c99ebf9a1eff32 +989, 0x441bbc76e92979b5 +990, 0x7724f07eaaf30a94 +991, 0xd9946d64346a0d59 +992, 0x3d49489a6a952877 +993, 0x2b4846d1c8f4bc56 +994, 0x1d5f7891a6caaf50 +995, 0x7f9f458f479c6677 +996, 0x9177526a634cac18 +997, 0x82b316c3ba3cea55 +998, 0x84d769b6ffd7a5d6 +999, 0xa1230c54cf6f4b5e diff --git a/_randomgen/core_prng/tests/data/threefry-testset-2.csv b/_randomgen/core_prng/tests/data/threefry-testset-2.csv new file mode 100644 index 000000000000..275604557279 --- /dev/null +++ b/_randomgen/core_prng/tests/data/threefry-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x6dc04d22e096eea4 +1, 0xb8c023f98cd7ada0 +2, 0xa7efe930de644973 +3, 0xe05ea045a0add077 +4, 0x404ab9dfd366d169 +5, 0x4d42fb74611bbd30 +6, 0x9343a758211b6d70 +7, 0x4dab40877197665c +8, 0xaa7b143cf838b109 +9, 0xcad1f00ed5cea835 +10, 0xf7c7d7d6c9a824a8 +11, 0xf20b64a5b42100f3 +12, 0xe155fec329e4ff46 +13, 0xe9db5c878d78e4c5 +14, 0xe96ecf5f3d8434fb +15, 0xa4a5369e8b676159 +16, 0x26f540900462fdc3 +17, 0x805e684c0bf0600d +18, 0x950c55250dcb9322 +19, 0x1df00ab0d9a5f9fb +20, 0x2e75b8e9fb48b88f +21, 0x8982e680b983b07e +22, 0x7c730288ec003204 +23, 0x8d4a42efba070902 +24, 0xcae4317a285d026e +25, 0x587af8ba811a8883 +26, 0x236cb94da85e9409 +27, 0xf4d25c2e0d7b2bd4 +28, 0xd51e53d74420f649 +29, 0x29f9ad48909f580d +30, 0x39e2a46d5962fc7e +31, 0xd40bb4045f9288fc +32, 0x86d6d29c0a126484 +33, 0x198289c6d8589ec8 +34, 0x5c4ffb186e8f69c2 +35, 0xeaa9fe626ca6f961 +36, 0x58816ea059f6b7ef +37, 0x9a636de4086ed493 +38, 0xe5a2b327a52f6500 +39, 0xa6d200345a8c4135 +40, 0x8ad50053fae7c70c +41, 0x1afd6de09771e167 +42, 0x7372d8a4cfe85c9d +43, 0xe2a99f3770165e93 +44, 0x193e99ffd7b45a30 +45, 0x4af13faae1f4ee8f +46, 0xe799ae38aea2a54a +47, 0x19bc5efb105b9b55 +48, 0x428799856ed8d2b5 +49, 0xc7e1c76dfb93b581 +50, 0x1c8000fb2afbe108 +51, 0x5d217734dc6fdcb2 +52, 0x4f9b436f2fa7b5d +53, 0x6c6a8e841f5f7f2b +54, 0xf7af258a895489e7 +55, 0xd4afe725c6deee +56, 0x11959dd7c1a0e56e +57, 0xa82b5a575ba9234d +58, 0x356bb807c17fe67f +59, 0x4113ba7ea9234d28 +60, 0x87c7fef17934c764 +61, 0xed5d2e29701db2ce +62, 0x4b4bf08b62160f5f +63, 0x32057a60eda862a5 +64, 0x446b5409b56a9311 +65, 0x31e84acfaf48c9f7 +66, 0x8951479289443c2c +67, 0xff84ec0fff1b3d23 +68, 0x3db2e8a284e2cee5 +69, 0x2c8aca76f7caab8e +70, 0xfe8ff095676417ee +71, 0xbb7d6ed0c641e84a +72, 0xd862d2552159e272 +73, 0xd320d329cd2b0419 +74, 0x41bd59f68a0fc99a +75, 0x1adb5cf5cc0462d9 +76, 0xaa152c0b16d38826 +77, 0x1358fc52142b5523 +78, 0xdc29465d24a25fc2 +79, 0xda86700b570eaa33 +80, 0x461c6b79f1aea5da +81, 0x4dcbf7406497da6b +82, 0x5f9d552eef82e555 +83, 0x27261b525e6c02df +84, 0x75076fe041440603 +85, 0x7cb47c620018a06 +86, 0xd7b7d17c3d1ee39a +87, 0xbc7eada7c2ebc70 +88, 0xcac816c1d36ebb7e +89, 0xbe1fd6bcb3d795a9 +90, 0xbd822d8f1edd205b +91, 0x5c0ebf018ade95fb +92, 0x9c6ee7cca010ad02 +93, 0xa210e3829a0b1b62 +94, 0xf5b25b53e25dba71 +95, 0xa4a69d9d6e73b9a2 +96, 0x2718cf614f82e185 +97, 0xf5aaf0eefd4f29cc +98, 0x343f41179d6056be +99, 0xc897506f84b7a9bc +100, 0x547ce04e8810e66f +101, 0xf61f6f95782be285 +102, 0x522e0fa1964a631f +103, 0x500fe922b3a102ca +104, 0xd39b38e1ae6f8218 +105, 0xce6079eafb932dc9 +106, 0x2896e00f1fdb8c46 +107, 0xe5719f1535cd23b4 +108, 0xc4d4dc27f6393389 +109, 0x95b3c17025e7ea85 +110, 0xcea3f280dae8ebbe +111, 0x6d91c862fbf2fda2 +112, 0x99c5197b21f1f444 +113, 0x9ddb59c15db5411d +114, 0xd6ed4ec1b494f92e +115, 0x3270a479f7e1fcd7 +116, 0x79e8d185e02ad6e +117, 0xe548786a4c6309fc +118, 0x1dd3bf9d9f3fc9ed +119, 0xe52ba084f8713b48 +120, 0xbd6c473054430deb +121, 0xaedf39aa96279c3e +122, 0xaa3a7bbe2fd381cb +123, 0xa087544796e01cef +124, 0x6596602a719be04c +125, 0x282a96eaaa790ee1 +126, 0x313b3f42aa9ce4 +127, 0x9998a73e798ea881 +128, 0xf51dc8e618571e13 +129, 0x1df638afa23f4d8d +130, 0x26385330319db8d5 +131, 0x1e1912386c519544 +132, 0x46c42a55ab556cdd +133, 0xc049b83a6f04efa2 +134, 0xecd2d18baafa8af3 +135, 0xc1108f82d1765b42 +136, 0x7dcd72d9f729db44 +137, 0xfa73627c9a20cf11 +138, 0x9ac69ccfda0ee7a8 +139, 0xd02f2c2c1776c62c +140, 0x75b4da786706ddeb +141, 0xeebe6ece4a516bdf +142, 0xf274b3ee4fb7ff3d +143, 0xd4b1093bd35d25c8 +144, 0xc341c37b9cfe28c9 +145, 0x32c4fb8e8e6aea6 +146, 0x4adefc5712ca8606 +147, 0x750302d8f108d3f +148, 0x76e6e3259264f240 +149, 0x31c6db85c206dc2d +150, 0xda47cf5e8d07c49 +151, 0xc5939dd565786002 +152, 0xa02e5128b7f04e77 +153, 0xea2e5fa9ffdad0fe +154, 0x7b1f9bcb5578cc5e +155, 0x3fe776dc8398e6a3 +156, 0x31b97c4a0973fc4d +157, 0x29a985a2bb602d89 +158, 0xe6a76cfb1a5c0faf +159, 0x4f9f62edb1e6d19a +160, 0xa589097a26f2b615 +161, 0x6bca21ae81e149ad +162, 0xa6570f8fdbf98af4 +163, 0xa740f226d53bc40f +164, 0xf0a4fe08ab331d24 +165, 0xdc1eaaff2c67c65d +166, 0xf227a9a3e89a7271 +167, 0x1f539a105ac9a7dc +168, 0xdf2fc18d2f4004ba +169, 0xc36711f5ef877b67 +170, 0x29e30f4b30ad39a9 +171, 0x3af92a16534fad9e +172, 0xf66e30d65df7faf1 +173, 0x2594f6d925228c49 +174, 0x8b8b3d9f20fa8a67 +175, 0x88e8d38366cb411b +176, 0xe881af89393b5a8d +177, 0x2f190890e152d243 +178, 0xbca3c2b43bd2e2ce +179, 0xaecb17f2dceb2ed1 +180, 0xa07f556a40d4dab4 +181, 0x59c729c94cb2b4c1 +182, 0x5364cee304495a05 +183, 0xa628681d16e0c604 +184, 0x40e2f3e0d9124851 +185, 0xb3da737ef7918179 +186, 0xb946e59c4905271d +187, 0xc079b7dd74752ccd +188, 0xfce4f9ef02e73130 +189, 0x86baa280d2d9aff6 +190, 0x778ae7465aca2696 +191, 0xcb1f60b74f32078b +192, 0x71bf826587c2c1f3 +193, 0x7ad5d51794ccc972 +194, 0x4b6ae15708464071 +195, 0x86c6829137a4110 +196, 0xc002aa2f64a5283b +197, 0xcef3ae65b916b6bb +198, 0x1e691414155bd2ad +199, 0x9fc613bcc3a961a0 +200, 0xf55caa38c2b7866f +201, 0x3aa6008a705ea431 +202, 0xc1587b4c3d3e6146 +203, 0x56e5eb96d0556293 +204, 0x796730a5bde01777 +205, 0xf4b5de3097e501a3 +206, 0xb5a2d840b9e7737 +207, 0x9059674f6dc9db07 +208, 0xddaa8f7b09773c74 +209, 0xce2e4850507c2b27 +210, 0x2d1dc2977de11249 +211, 0x335e7ef86408ea2d +212, 0xde7bc6f22af7ad0e +213, 0x4a36bd6edb976e6d +214, 0x8eaef966a64aeb94 +215, 0x7689476d2572797a +216, 0x4635219f62159d76 +217, 0xfe9958903e4d4ae6 +218, 0x288d7f77642371c4 +219, 0x2f17b9477da7c2e4 +220, 0x4a987e3814cbcb5 +221, 0xcc2ddf12905e9c9f +222, 0xf5cba7330c86853 +223, 0xc646ecb698e336ce +224, 0xc05d862c10b83e50 +225, 0xa673040049fdc79d +226, 0x52871df3f523fb29 +227, 0xeae829e337d8a5cc +228, 0xb17d70979ea53cd4 +229, 0x253a9e29eef246dc +230, 0xdc09f4831946ef53 +231, 0x15a4034a8917e29 +232, 0x57246ff6c9594b8 +233, 0xd80620e906fd1cf4 +234, 0x861bec5cd30c08ad +235, 0xc58f38b68714ccf0 +236, 0xd21c19157efdd920 +237, 0x51e1b8f40b8045a5 +238, 0xfd56fa4ceebbd2e3 +239, 0xcee1959a7f9d12be +240, 0x75f22e1dfb5ade8c +241, 0x3b87a61bcd763482 +242, 0x4018fbdbadcc95e7 +243, 0x3ff57380e846b8ab +244, 0x7e44c8a4005515ed +245, 0x824c847c6767640e +246, 0x2b34ef279cdcf5d1 +247, 0xfd0bfc2786afed92 +248, 0x7faeff889a39834a +249, 0x37a6cbda4f00e6c7 +250, 0x4214fd32c40b0894 +251, 0x4320e334bfd18ed6 +252, 0x74b1f0c2812db646 +253, 0xf48232c0988ea643 +254, 0x5841c46c56967a29 +255, 0xb08204c4c9e83fca +256, 0x2a0bbd0b42a4a708 +257, 0xfe76573ec821c87f +258, 0xbd2e46ac0feeb0d9 +259, 0x3552a2cfc1bdca32 +260, 0xfbdc96046c1020a5 +261, 0xd5d79356b52560d4 +262, 0xaffee5796b293a6b +263, 0x5ef4dd67d2cc9042 +264, 0x7204094f6053ba36 +265, 0x1a89384fd317d01a +266, 0x68129e5eaa1d4a28 +267, 0xcd2a9c8b6938cb65 +268, 0x434bb1bd9872647a +269, 0xeaa17b0b5fa27832 +270, 0x442e1c5fa8113c44 +271, 0x38bcc81ea8386d97 +272, 0xa653c2f1f13a54f8 +273, 0x82d74e165850f5a6 +274, 0xf4b9d5dce18bd047 +275, 0x2666dba219ea409e +276, 0x8ada69aa37a215b1 +277, 0x2cdaa0dc42ba5b64 +278, 0xfa7b44675ef531ad +279, 0xd87d4bc750795b22 +280, 0x562fa1b77f3c52b0 +281, 0xaec092b6afa4b7f2 +282, 0xc2dcf8735598f14f +283, 0xc65a4e439f790832 +284, 0x73fca9d888e184f0 +285, 0xaf38a6918896df93 +286, 0xeddbfe61d62902db +287, 0x2e8e831abd28891b +288, 0xdfea332c8ba5e7c7 +289, 0xb980b3ea4806e11 +290, 0x37f771e71cd26079 +291, 0x65b880af5cf288c3 +292, 0x69bef58494777df0 +293, 0x207706d3b013c1c6 +294, 0xe9b4014efb64e6e7 +295, 0xece0298dfad7da0b +296, 0xcfed2f0d392af845 +297, 0xfbb1407059436788 +298, 0x74e9d65370ea5662 +299, 0x6e8bce550b2c36a2 +300, 0xf38d767f77abe8de +301, 0xc6befbfbf4c57ddb +302, 0x9fffced31abe51b8 +303, 0x761beb850b4659e7 +304, 0x5af78afae250836b +305, 0xbe64a1bb37c08d0 +306, 0x5dd328d85327ba3d +307, 0xa43238b39aae76ec +308, 0x1f58743f079a14a +309, 0x8f2b1a8cbe77f565 +310, 0x47526c74521adf72 +311, 0x542062d916e30f3d +312, 0x2f3f86a12c7561eb +313, 0x725a6f82106fd202 +314, 0x5939d692a6203676 +315, 0xcd607e13aeae5717 +316, 0x12a76dd01d4e46d +317, 0xddc96ae023be007e +318, 0x71341b774bace597 +319, 0xf69db6a379f38d34 +320, 0x87cd1ea3a6629c70 +321, 0xadc8798060e39c27 +322, 0x532982fe9d77655b +323, 0x1c49d24a1bb2fb83 +324, 0xdcba3b57f87cf725 +325, 0x62b96a90dcaa0a3 +326, 0x89d704a4512cefe0 +327, 0x41685667b144aec0 +328, 0x49395424e7982bce +329, 0xb493878ae98f87f +330, 0x2b2a23e3696a5588 +331, 0x2bbb82d12da62157 +332, 0x98092e701b17da7 +333, 0xb55d717ca8a4d039 +334, 0xf4547583b84a03a6 +335, 0x9609c10b7e68759a +336, 0x2a60eea68cdb7812 +337, 0x15146ffa8acbe5ed +338, 0x521e3b2ca6e16844 +339, 0x27528ffae94c01c2 +340, 0xc5df652e08db6be8 +341, 0xba1275ce0594c2f4 +342, 0x9c66fc6882ac8cf1 +343, 0xfcc5c3e413a7dad6 +344, 0x8309532dc68a36c1 +345, 0x7f9351a45e66c50b +346, 0xa70e6b123bdbad47 +347, 0xad49d29da3a694b0 +348, 0xf198452973eefdaf +349, 0x53b7951ab7b24800 +350, 0xb226c827c5cf8233 +351, 0xea184af7dc0cece3 +352, 0x77d5dc22579d919a +353, 0x583ec0e8d8295fa3 +354, 0xac35b75b4dd17e0d +355, 0x7d273f1ef4ec8df2 +356, 0x85665ea56b49b5e3 +357, 0x7cc0ee21b59ec57a +358, 0xae595b1cf72dc292 +359, 0x4eaf57e8e6880fb5 +360, 0xe51931811683e382 +361, 0xdb29479871fc8dc9 +362, 0x9b2f9c40c6506d91 +363, 0x35ee0dbbf239bb06 +364, 0x40aa630242bc7e2d +365, 0xf3a3d9b2f5839a26 +366, 0x17e920c38a2e329 +367, 0xae28a796412706f9 +368, 0x3327dbcbf0cee5e +369, 0xdbca13ee810f8546 +370, 0x390f9a7560cd1a23 +371, 0x444085fe4b30b123 +372, 0x4a1dea59c8ffa505 +373, 0xc12708a6534b7424 +374, 0xc331d65b7dd17bdc +375, 0x4d1a64113fb84526 +376, 0x7af40a24916e7ba9 +377, 0xefc466d746e83001 +378, 0x631fb61962533374 +379, 0x355629ff71ec6c69 +380, 0x89e5c7e5a2b6b82b +381, 0x307fc816d73c725e +382, 0x3c7c2fad16ee2808 +383, 0x3db362fd0d93dc47 +384, 0x7c7d9b1ecc6bbc7e +385, 0xcdab8413e0b594bd +386, 0x3e45d66baf972abd +387, 0xbd8bdc23f1926e70 +388, 0xfbc61c9f0b6c1a71 +389, 0x68b9e52b65d64f9c +390, 0x5b371b49f49af63 +391, 0xdab60623156c1ebc +392, 0x14ed99c617db324b +393, 0x5c7f7b5f6db77c0e +394, 0xeae562127e55128 +395, 0xf5ff71155fca2c5c +396, 0x8271b2d1ad93bd4c +397, 0x1ca96341dd5b034 +398, 0x49265a39bf18e8d6 +399, 0x5bbe70cdacf51f1 +400, 0xbf198a70b59ff062 +401, 0x41058370f356a21 +402, 0x47e8c7127044ea +403, 0x3a031703f1e98d83 +404, 0x63db42df128a9d7b +405, 0x67360bba6d058db6 +406, 0x2cb06097a2bdcc21 +407, 0x9e69d402ec5ce471 +408, 0xef55f0fa21cde5b0 +409, 0x2ce15bd742eb7acc +410, 0x2f29a82fc4076787 +411, 0x312992a6d3fb93ec +412, 0xd9abccb15b2535bb +413, 0xdfcc55a43bad4c90 +414, 0x51ca5637dd4ea18e +415, 0x9be4b1911b1ae9f7 +416, 0xb835b284b26d4057 +417, 0xca26765b4414729f +418, 0x211fd5e340cd6f9a +419, 0x64984a44077081d2 +420, 0x859ea6fc92cbf37d +421, 0x99f190ca3756084b +422, 0x38549b8f8b5a7201 +423, 0xc3940c2807d34ed8 +424, 0xbcbcf498fa77d02e +425, 0x2c24b6360e1033d2 +426, 0x9602edbde8d9a850 +427, 0xbf4ce69ab0e00203 +428, 0xd479d334b0c716f3 +429, 0xeebd6ba9a827a3e1 +430, 0xea0b5cec6b42e089 +431, 0xded6e289584813bc +432, 0x9894568e6a3f4ab8 +433, 0x73ee7a9acd6f667 +434, 0x4c849a0da094f2f5 +435, 0x4fe6f5fe0f90f786 +436, 0x9887c17ea5f92327 +437, 0x318df65aa9a53d5 +438, 0x70a7bc8178292fd1 +439, 0x612a38a535b8e3d2 +440, 0x15a79aa16d0228e1 +441, 0xd3288c336eb0b33a +442, 0xf84e2fd1e4db070c +443, 0xa2efb0e34d0114d5 +444, 0xc528e890e7fa6409 +445, 0x4b837fde84319af1 +446, 0x632edec918b02d23 +447, 0xce980f566494c149 +448, 0xe54e204d31452188 +449, 0x9ca51e2e7fe3a3b0 +450, 0xb0a7183126df963c +451, 0x2de5fd96c125669a +452, 0x17ab43849b96549e +453, 0x49850d9bb767cfd8 +454, 0x632d44d7add93bf0 +455, 0x3fba66506af7b132 +456, 0xc06c6bdeaec6d733 +457, 0x3e7795ace33e8cd1 +458, 0x8f522c2f76ae3bd7 +459, 0xec883650a2d2b2d1 +460, 0xccb11ad5bff431bf +461, 0x936d66262607c537 +462, 0x3102298a92f643fc +463, 0x76078e8357fd5e15 +464, 0xf22a64a885d7e7ac +465, 0xe111261b30caa160 +466, 0xed2c2d728a8ced12 +467, 0x64e659163f8d1d71 +468, 0x8c7c5f696f55dbe7 +469, 0xf0bdb7e3168a82d4 +470, 0x1eea602c6df9464f +471, 0xa10d1d8502d43304 +472, 0x824245afbf95950c +473, 0x7b4a64e619e29d10 +474, 0x73d4d21a8f412218 +475, 0x3ee5be3d8af0bc17 +476, 0x78979eebb7bb7b9c +477, 0xe2acf9a6f17cb00d +478, 0x77d8f02baea98694 +479, 0xba80648f6872987a +480, 0x1cc1fa8be28d090c +481, 0x9df7f91ded8fb4d9 +482, 0xd5bc13c3dad13991 +483, 0xa57c268e5153f06d +484, 0x662f2e1fdc97ca36 +485, 0x1242a97a1148c369 +486, 0xa85178a88b821450 +487, 0x32fa270cddccdc1 +488, 0xd52af3c8d3d9ccbf +489, 0x105d4ee4420a2035 +490, 0x8ccec92b29bb6f3a +491, 0x7330a89b0ec713b8 +492, 0x712f7f946a661b8c +493, 0xdd11f248be047eab +494, 0x15aab9e558d04865 +495, 0x791b42bd188d3042 +496, 0x571a03a98b08d2c2 +497, 0xe8362e466304c2e0 +498, 0x690bcf82d6f7e815 +499, 0xf387d12b216e039e +500, 0xa1a0e6721cadf720 +501, 0xc238cd658c3c48b6 +502, 0x303d33d956cd19b7 +503, 0xb91002fb2c06523c +504, 0x3fd6c979ecc9e53a +505, 0xe709a011bbd9684c +506, 0x9f9730e4466b178a +507, 0x5d6a951a17dea6de +508, 0x8ad48c770be7ff5c +509, 0x840349738f1840ef +510, 0x62b71fa4d4713278 +511, 0xb54bc131be88e301 +512, 0xcd360f29092f1b48 +513, 0x51e2d80a7974e018 +514, 0x4716923492cb7c11 +515, 0xc5a3426512ccf92e +516, 0xa29da51d76692ec2 +517, 0x7760e22a2a966fa6 +518, 0x17027bb9ebea4f10 +519, 0x1cbfeb90083c7472 +520, 0x21df956d73e46 +521, 0x3d3f98cec3a0f9c5 +522, 0xcbb44f6843e8f84b +523, 0x5387cf5c8dc08f09 +524, 0x9874b020a7cd16eb +525, 0xb26656f3d0e54b45 +526, 0xf7535314e62cc2b1 +527, 0x9d98c18c8b832a78 +528, 0x4782e4a90afa6bb0 +529, 0x98a5b50793977e75 +530, 0x699bfd767f3c1fb6 +531, 0x2b0c137df6bff06d +532, 0x1dcf680df83ac493 +533, 0x41433da3b84a308e +534, 0xaa5b2dab82fd7a7c +535, 0xd35f4a2331f962c +536, 0xfed4b74303c0ee4d +537, 0xf9a9dcb35118765a +538, 0x4d09906765751e55 +539, 0x96f997988dbaa2ba +540, 0x761968dfdcee7a25 +541, 0x942f82665a09c18e +542, 0xa630ee4197ab0e0b +543, 0x68bfe324bbe3b7b1 +544, 0x8613dd09e8566784 +545, 0x3738178b0a67bae9 +546, 0x78678e656aa91115 +547, 0x6d182cdb34ba7a53 +548, 0x46749ef4e5670d88 +549, 0x2cddc1808c4018e +550, 0x22b2aae091c52f90 +551, 0xa4709bcfefd0d6fd +552, 0xade8916af4dd85f +553, 0x763c7e7df0416c26 +554, 0x78b365ba6d6416e5 +555, 0xadba0adf9c5b5e3a +556, 0x5a146cb126d32c3d +557, 0xa5f2f65ef03145c4 +558, 0x2708930e062a88a5 +559, 0xfc94da4d17e4d4fa +560, 0x78b500b283574f39 +561, 0xdb657f35be884f22 +562, 0x1de17d2450338525 +563, 0xc602ad9d8fe83980 +564, 0xc731d0497705a493 +565, 0xc3e443ea6c794843 +566, 0xb946fc377698953d +567, 0x98ad8f7f193cee5c +568, 0xa8da8ecd4301cb4f +569, 0x99ff5cc72e206b24 +570, 0x2422ef61bb3c9be4 +571, 0xea62c83986a29b61 +572, 0xcbcfb5a9953d1a6a +573, 0x229f258aac962310 +574, 0x8730e2f36b1fbf6b +575, 0xc3d6ddbe26ead961 +576, 0x814fc47c7edcbae0 +577, 0x23af1859cb36c99d +578, 0xeadfaf827ee1de0c +579, 0x15ac2339684c36d2 +580, 0x54c617fd9b17d56f +581, 0x8b88689c24920b0d +582, 0x5294092543a1f59b +583, 0xbcf7fadb518fad77 +584, 0x8e784c0359e6349d +585, 0xa45831bb0c97d3d7 +586, 0x1d0b8d79ab84847e +587, 0xd7f23d7e384fb139 +588, 0x8fc7ee55f1d37f0d +589, 0xc44dc853b1913765 +590, 0x20d40baab760366a +591, 0x6067cee1fc99a47b +592, 0x7927a7b24ecb93bc +593, 0x26819db47e3cd94 +594, 0x236853cd14a54aec +595, 0x36e7a2f60284be9b +596, 0xb11accb3a708d6e0 +597, 0x98c7651be6436342 +598, 0xaf27f94af527010 +599, 0x4ad2ef538542349c +600, 0x63becd7dc3d6fc6a +601, 0x8dfd8f874d18f093 +602, 0x2401cad63eaeaff3 +603, 0x7be4a82015531b1e +604, 0xfca36bc859cff476 +605, 0xbd3f9383a20e1fac +606, 0xee9e7e4bf1c444f6 +607, 0x4ad8b91ea66cd1fe +608, 0x85ffa6d1cafcc553 +609, 0x665f66043e6bf320 +610, 0x4d409c2d9cb23e6a +611, 0x1815b94fcb2e85bd +612, 0xbbb8439e003579a2 +613, 0x16dbe31fced48255 +614, 0xf4f7079142a17040 +615, 0x96df1c5c35e5c231 +616, 0x41fc7faaa1bd8cd4 +617, 0x6a51ef3658d4bd38 +618, 0x31e64c6ff2d1598e +619, 0x20f2f339395fec58 +620, 0xf329aaa477f87f9f +621, 0xfe461c3073c63ad4 +622, 0xa60ce6531c0ab64a +623, 0x527eff919a0305ac +624, 0x7708978a5d010a53 +625, 0x2ab687dab81f0ca +626, 0xa7af71e850497d34 +627, 0x8edba42a07e35155 +628, 0x45b4f3ae5e07472e +629, 0x29e3636e047b7c5e +630, 0x6ddd57807c1830a3 +631, 0x800e6743648c9cb5 +632, 0x921389557585d720 +633, 0xf2fa96f5bbdcafbd +634, 0x4f1634ad80d0bdcf +635, 0x7125668667218b0d +636, 0x23373d9919906087 +637, 0xa27ea3fbff83bd41 +638, 0x871cbab37176d63c +639, 0xe6939db32970f816 +640, 0xf3484c2ce0dd0481 +641, 0x76e8298b27b9d68e +642, 0xf966f9fb426c1950 +643, 0x4066c4f62c307e4d +644, 0x187ddce6f94afb2 +645, 0x656f00e6a70fbfef +646, 0x2ef17886ec419448 +647, 0xbd748ea59342e5d2 +648, 0x1f204c5d3c9428a1 +649, 0xc08854fa8992794c +650, 0x17d0f325121fc218 +651, 0x34c63c258a663b88 +652, 0x60f94e4cf248344c +653, 0xf9ffcbcdce936a7a +654, 0x93ac50ca4456c69d +655, 0xb9039b4d7dd82c9a +656, 0x117e3c6d6891e836 +657, 0xff6289aedb2ab5f0 +658, 0xd5f695f19d6786f6 +659, 0x8bab970181c86e97 +660, 0xee6be4ee832333fa +661, 0x648ea0623082ae36 +662, 0x972b001b4b4d4431 +663, 0x92fb47b9ff9b1ee4 +664, 0x792ed2bd14f8896a +665, 0xc98e2723d55b08d7 +666, 0x2a4f0b7da6210c89 +667, 0x19a1fb785fec7a64 +668, 0x937a44924b337455 +669, 0x26802ce94caeaefa +670, 0x604539849b56a532 +671, 0xccf6eeb0a664d39a +672, 0x545584db524a2307 +673, 0x8ce4edbc37515d8e +674, 0x1d548ba9281312b5 +675, 0xd0c51f891244ed57 +676, 0x3b464ba79600dd6c +677, 0xc28ae0f8c4db373 +678, 0x938e49fcbbe8941 +679, 0xf084e4c8d9799dcd +680, 0x61ca52d24bdd1083 +681, 0x536d617222724841 +682, 0x506cd8085d16a6bb +683, 0x422158a96747781d +684, 0xbd13ded440c16bb6 +685, 0x97913b1b8c2077ca +686, 0x5ab588aab438e8b4 +687, 0xf4c6831523402b4f +688, 0x91e962c39ccbbac6 +689, 0x861c95ffeeb7b7ad +690, 0x6b318a9abb0eb7a2 +691, 0xac4164b45978ce20 +692, 0x71d64942f1d72b40 +693, 0x1675fe85018ea357 +694, 0xe19ef9073183417f +695, 0x3e057316b3a37a7c +696, 0xaccd00b688c8fb36 +697, 0x8c2d1b84d24b89d5 +698, 0x4cc97086400b2631 +699, 0x38c2cb4daafa93b5 +700, 0xd44e889f968a38af +701, 0x53cf738410523792 +702, 0x487b1b84bd6f0ee3 +703, 0x1824ae549bfadd6b +704, 0x7b6654bfe0f085d2 +705, 0xa289e4fa5b2f971b +706, 0x24c971b485491f26 +707, 0x8827b700bb7136a +708, 0xe2871794cd6f7a2b +709, 0xa21bfa8e0e237703 +710, 0x8447f083c77d1be +711, 0x1b1d926efb334728 +712, 0x8dd2d4fed543c38d +713, 0xe69ba3c162cd489f +714, 0x3f9659c66b35acc3 +715, 0x45ac347675850ebe +716, 0x8e572a9ea7ec6b12 +717, 0xd3a11284b37761b9 +718, 0x8e276c1c9616b7ee +719, 0x7a03569e90501954 +720, 0x4ddd0afb9d3f2605 +721, 0x9342896d66482c8c +722, 0x9edca50722c69db6 +723, 0x3dff88b2257e3ae0 +724, 0xad92c2d56ccd8d11 +725, 0x81e6dc441c0b6df4 +726, 0x1a8a0d10f7326b8d +727, 0x8382991eb90958b +728, 0x9570d9b1a0527ba7 +729, 0xa1820138d6f96490 +730, 0x1c8c678ebb2aeb4c +731, 0xd782fddd578fc4ec +732, 0xc78d60cf41e509fa +733, 0x82dfbe4d435f747e +734, 0xd9a410610e4b3dca +735, 0x2d687c7a90220751 +736, 0x6838c5d233cff81c +737, 0xe2e64ef24f7b004b +738, 0x65c11d97293f0da1 +739, 0x53e2016d79145a35 +740, 0x3ebd6882b1de3c7c +741, 0xb1b47458c2b31ac5 +742, 0x4321907da2d2df2e +743, 0x57f211e1521e0eb9 +744, 0x25798e7fa3227f0 +745, 0x9e696273f7255ec6 +746, 0x784755cb23c3190 +747, 0xd4e82b43d8eb119a +748, 0x894047215bf58241 +749, 0x71545bb714d43bba +750, 0x3eb48187007c99a2 +751, 0xd3a03fe5a57dde89 +752, 0xe336d1bfc90141f +753, 0x13e5b11c8ab27b7f +754, 0x476e5d1c3f5ddb41 +755, 0x7e0987fb7ea434ca +756, 0xa7af6d90f6868d59 +757, 0x16be8514db2ba69b +758, 0x9358b7eb6b64161d +759, 0xc6e6e49346403b75 +760, 0xb8738eaf21cb369c +761, 0x65a2a7d3ad804624 +762, 0xf49f135e789969d4 +763, 0xf20a963cbeeaae3a +764, 0xd17e058559753d56 +765, 0x8e8bf41d9c4916ec +766, 0xe48ef68e5aa23dd3 +767, 0xe2f0001eda60c8bc +768, 0x5b99e00b24f1aa8f +769, 0x4ad710b2a99b14c8 +770, 0xd3aa3920af73ddd7 +771, 0x3d76e216667d1382 +772, 0xa8c330ec75317940 +773, 0x12534fc207bb29a9 +774, 0xd15c55c83b4a35e6 +775, 0x535e26026622714d +776, 0xb56782cf34123bc1 +777, 0xbd925db7098d6155 +778, 0x682df0f1e54e2d9d +779, 0xb330167f33195b63 +780, 0xe9658f089aea3987 +781, 0x2b095fe8bc8fb610 +782, 0x204269c3aa0af463 +783, 0xd1c858c4a6b68013 +784, 0xe2f281cf9ef91e34 +785, 0xc29a55f11e4479c6 +786, 0x12a8e1df7d6166 +787, 0xfa0b4dd7d67c578 +788, 0x6db2b74e2e42db1 +789, 0x478694b16b033d71 +790, 0x47a79614736e8c3f +791, 0x247e0e4d132cf874 +792, 0x22845b7634d0e71f +793, 0x9942faa26a68bb81 +794, 0x381aeeee89549313 +795, 0x2052200f6ff0d6ba +796, 0x5c9f92b675b2f641 +797, 0xe6b34f7a1e196039 +798, 0xe1b77d497bef7516 +799, 0xc59d1b80b7b3b30b +800, 0x819f5098375913b2 +801, 0xca0f73cffdaa9370 +802, 0x2f5bf935c691c5f4 +803, 0xecbd8bb256d09c58 +804, 0x43406aa69a99ecf4 +805, 0xf05f8b2ee179651d +806, 0xb7c70142a0228f54 +807, 0xfc2db144bec4b245 +808, 0x2abce886e1a45ebc +809, 0xaf58b72a59bca78e +810, 0xa52b038f4d4541bf +811, 0xc0d14bf583b241aa +812, 0xc8a1abd7115cf8a7 +813, 0xe02e5a30a769d474 +814, 0x56acfdbd29796da9 +815, 0xe7387234b8b03889 +816, 0xf1227dd110b8f9c1 +817, 0x8b124ad0cb62d460 +818, 0x97b7c747f3b13887 +819, 0x216f43a8fc2314bf +820, 0xaec316edaf92f3 +821, 0x10186bef157d36fe +822, 0xf37a7ddce615aca1 +823, 0x9b5b913d16158f6c +824, 0x59be9a31bf90f02a +825, 0x24170e196a66a0a0 +826, 0x589a9527086fc354 +827, 0xc5990d0f438d434a +828, 0x90eee29b52e7a094 +829, 0xb703a0dc266849dd +830, 0x6d0bff0ad3ad2faa +831, 0x91f7fc0cd9e78804 +832, 0xe86041baf693528d +833, 0x1efabed627bb50a6 +834, 0xb59397e5f2895f58 +835, 0xd07f3b88397416dd +836, 0x340f1719b497c11e +837, 0x284e6cb714f9b6 +838, 0x185fc6ffc0b68229 +839, 0xfa2deec9e6c26b24 +840, 0x62c6578b4b262188 +841, 0xad4109b1cc118f48 +842, 0xa395d493b26d6f0e +843, 0x325b4fe3d0dd4338 +844, 0xf91410de49c18d30 +845, 0xf07bf8b60923ce02 +846, 0x1423fe617d564876 +847, 0xc077f782126eb9cf +848, 0x2fcb2f20910e89ae +849, 0xc2bd451afd2e6816 +850, 0x77fb4184cb7d54b7 +851, 0x3f179aed62349343 +852, 0xd9186ae032d49425 +853, 0xb5eb57360137bdf8 +854, 0x3e4be92a340c6331 +855, 0x8429236eb3127098 +856, 0xdef72542e2b2b80 +857, 0x63a489df51948c4 +858, 0x8a7e00c797fde2b4 +859, 0xaf0ecdb100a40c24 +860, 0x5861013d27e2e75b +861, 0x755b9daf64e225f3 +862, 0x3d2df8752fc1f0a5 +863, 0x603430c7044c9cc1 +864, 0x861421e1eacce08f +865, 0x617e02ea4d46a34c +866, 0xb5a65006a14421c6 +867, 0xb0f80b679b414c72 +868, 0x9906164388248865 +869, 0xc9c844ffa4051128 +870, 0xca9d7bf3530f5c33 +871, 0xab16e556b494c5ee +872, 0x7221a1b8ef1aa54d +873, 0xc271845c7d1a4e37 +874, 0x6a76797104475a2 +875, 0x908e423fb8735430 +876, 0xb5bb58134b1677c +877, 0x9ffdd2ae9c3118c6 +878, 0x7e180fcd6840b8cc +879, 0xf94537df07d2fdc4 +880, 0x5cc348554d45bb14 +881, 0x3d4daf3c2b6664b9 +882, 0xfd04db3f786791ad +883, 0xc493d37c83bb96d2 +884, 0xbc9faef5435f86f1 +885, 0xbc65cb3d3f6e9d9e +886, 0x9cbf2ffa56e6ecd1 +887, 0x9250836b7c20ad40 +888, 0x4f5c0071a0db9a4f +889, 0xdc3f0522b1445aef +890, 0x7506e5599b850a1f +891, 0x81ed2abe0e2de08d +892, 0x240490146352067a +893, 0x3c77af13f5eea2cb +894, 0xa7f4cdb8ff827eb4 +895, 0x1417242e31ad2476 +896, 0x76016b03999f9478 +897, 0xf94521fac0306668 +898, 0x8269175893be1d41 +899, 0xfc753632a234f285 +900, 0xf612755268cace8d +901, 0xa14828c9024be019 +902, 0xfa70c71b9d1eaf55 +903, 0xdf1b71a62e31de5d +904, 0x5501951e0e1edc8a +905, 0x2f8f803b8df69cde +906, 0x574f363439f7da1 +907, 0xfb10c35585727813 +908, 0x749b3c2837397d13 +909, 0xf3cdd1febe8cfdc7 +910, 0xe394963ee5056211 +911, 0x577d7d7b18de73af +912, 0x47ab5d83b0c59c10 +913, 0x9dc8a3fadd1e6f9 +914, 0x83fe8257e75854d6 +915, 0x2e43cb3aa0046160 +916, 0x1dc475fcab4ac1dc +917, 0xf0bc49e0566ce0ec +918, 0xb603cdcf1f30fa6d +919, 0x526760cc6bb6babe +920, 0x7c1da274cfc404cc +921, 0x1e7f5020e4872eb0 +922, 0x5810d9ce7b4eb5d8 +923, 0x5ddd35b6fdc8ccf1 +924, 0x3384120a60586e91 +925, 0xbea2bd919e0f3ce9 +926, 0x5a5e242545609467 +927, 0x4bde47bcf26eb4f6 +928, 0xb0a735deefec6c20 +929, 0x68a22c177454e398 +930, 0x8c9bdb2d15db7858 +931, 0xcf3748c5ce8663d9 +932, 0x4815c2a33d2e0b89 +933, 0x8ccabff1a06d51a8 +934, 0x9a5ac9d5cd9bde72 +935, 0x1dc5a9d71a51705e +936, 0xbcdb2971a66f27a8 +937, 0x31b0cd0bd56e4640 +938, 0xf7efe6b1f1f5dabf +939, 0xc5c99d9b4fb22013 +940, 0x1ba119bae4d4fba4 +941, 0xf65a6d9da77cc4bd +942, 0x25cd9545d90e715b +943, 0xb7477672a3531ea3 +944, 0xcf247ec31abeebc4 +945, 0x7e057e2450496fbd +946, 0x38ef5e25d359c979 +947, 0x4c19225c27c2eace +948, 0x2f0a528453e09547 +949, 0x59c8f78eba33f6bb +950, 0xfc8e46c35ef2fd53 +951, 0xad32d2fb43958df0 +952, 0xa4925809889d9dec +953, 0x91511a8ded719be9 +954, 0x8bafdd3b61b109d +955, 0xedc9854399b02ea8 +956, 0xa50a9ba9d3f10ac3 +957, 0xbd94acf2d2a1833b +958, 0xcdefa8e500cb91d6 +959, 0x95d64c722dd9ce9c +960, 0x2593274b7561d701 +961, 0x9d5854a252f7d4ee +962, 0xd799bae55a43bac4 +963, 0xd56a4f738e03f65 +964, 0x9c100f2599fe70cf +965, 0x1fb9b7564fd6984a +966, 0x16ca3ffcfbc77ab5 +967, 0x3a98bb3993bfe243 +968, 0x7fc4a69a94fc389e +969, 0xf4adfc0494731b85 +970, 0xd691ed499cd189f2 +971, 0x7207391cf3664115 +972, 0xae2186bf1bb2773 +973, 0x5f10cea41eee2bd0 +974, 0x35f3303dba442fce +975, 0x41f7580460af8f7d +976, 0x6f92dcae967f8045 +977, 0xf8a23d127dfb64da +978, 0xca2955a095bfa56d +979, 0xf5f9a75318e0b668 +980, 0x94eabcf4d9fffbc1 +981, 0xfb5f2b3c85a44eb +982, 0x1edb77bc0d4ceef1 +983, 0x98bbacdb3bbbfc39 +984, 0xeeb6d6bc48b6156e +985, 0xc9c56b8f2fa29b0e +986, 0x22f31ccb223886d0 +987, 0xbb7f3e16bc706aaa +988, 0xe38c1e50cd965c52 +989, 0xb15aa0b68271c538 +990, 0x1c0dba1cfa587e61 +991, 0x70f267cd2d88e846 +992, 0xa439b7443ffebc10 +993, 0xd586c99b86177873 +994, 0xb05ff9807bdcb212 +995, 0xd7c08bd208fc8e05 +996, 0xd11063113d01ac5 +997, 0xd4c9beffc525f0b8 +998, 0x3d7303181643bc80 +999, 0xd75ef9b19286142 diff --git a/_randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv b/_randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv new file mode 100644 index 000000000000..8289ff27eb96 --- /dev/null +++ b/_randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x86f9f4feeebed928 +1, 0xcd2c9d2d1dc1c071 +2, 0x94741e0555641979 +3, 0x81eed88d38a9138e +4, 0x54b9f49cd0035507 +5, 0x8c112b85821a173a +6, 0x51f4c2eabf05c192 +7, 0xefa6a9ad4ca56d94 +8, 0xd3bd969b3aeb5457 +9, 0xcd4f28af5618e25a +10, 0xa20fd197fb60aad +11, 0x796b5146f61afc52 +12, 0xf6fe619effce6d62 +13, 0x763ed6613d00e8bd +14, 0x333d357571b249c +15, 0xc2a39f35ba8f4ce6 +16, 0xae35d916c6cf8a2b +17, 0xfdfaa6b7eb9591d3 +18, 0x52668584489de943 +19, 0xca982b4b760effb8 +20, 0x32c7256797c26f09 +21, 0x3115b9539d722cc +22, 0x5183f1d23dd2f56e +23, 0xa0a2a2c524e6650c +24, 0x3191f4b5260e5a2d +25, 0x1eebe2655fb4f190 +26, 0x5781c6b75a253a88 +27, 0xae45a39543b4140d +28, 0xfc62724b20d2df78 +29, 0x3770290ba157dc9c +30, 0xc4731569807dbff4 +31, 0xd42ec771a7a0a08f +32, 0x743276e0eb868d75 +33, 0x37f95d1ba1faebc6 +34, 0x3b4800b089a323cf +35, 0x437fa9c71af61839 +36, 0x1cab936dd28c6f1c +37, 0xe9d60347286dd9f0 +38, 0x716625cbd57bbd63 +39, 0xbd6c0f5e6aea7288 +40, 0x7c782d5b111a89f3 +41, 0xaeb1b9478b99970 +42, 0xbdffccb6a96cb533 +43, 0x9423e6ea789f29f1 +44, 0x53df9a7a0ea73fe6 +45, 0x7d9bec5c15c7e349 +46, 0xd1fc83fcf223aea5 +47, 0xd1dce35338ad3bab +48, 0x297bd5f1cf79e758 +49, 0x19ec39a6191419da +50, 0x45e57323ad58071b +51, 0x395bcbebe1ddf611 +52, 0x22d9065efb013222 +53, 0x4ea2d534fd9fecb3 +54, 0x9b9779e1edeb2e27 +55, 0x1ba777ba576a236e +56, 0x23cf95e34d62dd3f +57, 0x6d1689730795e6bd +58, 0x24e510f9d2f65379 +59, 0x1e12d607e78701e8 +60, 0x3347fe3ddc50a23e +61, 0x331754f825305d97 +62, 0xf21a675c0344709c +63, 0xcc9bd2062ae5fb39 +64, 0xd2dcd3a1ee6afe9e +65, 0xbdb0388382c408d1 +66, 0x19476497aaef64ad +67, 0x906dfff3b1181dd7 +68, 0x47edd3c528f4c753 +69, 0xba2a0f289279aec2 +70, 0x710bc73fd1c732a9 +71, 0xe0238b1ab604610d +72, 0x10f68d7eb0d19e19 +73, 0xc13654f8b8f3d9b7 +74, 0x112c76bf71ad04a9 +75, 0x4b9d965062e9a0fd +76, 0xe0b13496fec19aa8 +77, 0x999493dababe73c8 +78, 0x87104db5240f12fb +79, 0x8fc8dff016c96a13 +80, 0x3eff4853e8b167a8 +81, 0x438b6f5c3d10b85d +82, 0xc2f94a0707d949f5 +83, 0x87981b13beefb01f +84, 0x1718db5072923bb2 +85, 0xbe7ae4310234b5f1 +86, 0x3ad4306f2b2b3b47 +87, 0x9de166baaf152f81 +88, 0xebca2cf057a00802 +89, 0x99bfd19b5e0a87b2 +90, 0x5ae7b3ab9d2623c0 +91, 0x8de5811587a53d2e +92, 0x629a57a87d068ee4 +93, 0xfd80a82607740601 +94, 0x5758bfc8610d0b8b +95, 0x8f0c00fab932c1f5 +96, 0x3d49bd296a34582d +97, 0xc99c1bb8319ce526 +98, 0x1dd5ba47ac1443ba +99, 0xb5a40a33c9ca1cf9 +100, 0xa1025156b711394c +101, 0xdb3ef94ee8bc71a4 +102, 0x6d3292123ffa9bc9 +103, 0x4b9683ebf2f98d1f +104, 0x4d1a4709b547bfe7 +105, 0x3623a9c4054355b1 +106, 0xed15f8852d329b4d +107, 0x60ef76852f40e346 +108, 0xe64c2bfc6d0ef2dc +109, 0xf286f874cfb68ee2 +110, 0xb1b07a7ca9268329 +111, 0xf618a9bfe00b7cdd +112, 0x54a40c4f52cab527 +113, 0x5007a4d41eaf0af1 +114, 0x6fa7f2210a7b7f3a +115, 0x7b448faa473ad765 +116, 0x901b6276232cb3c2 +117, 0xd69d06b85d118dfd +118, 0xf8fb03c5dfef937a +119, 0x5a53e96d5ebc4689 +120, 0xe24e81bbd9772b3c +121, 0xa996ed94405e1811 +122, 0x7d8712833a4cbd96 +123, 0xd8b81a509f392481 +124, 0x76b52a270551424b +125, 0x4c854325eaa4ef23 +126, 0xc8823e5a74757b2f +127, 0x9ac8deb0aa215a3f +128, 0x89641160b3eeafdd +129, 0x17781aba3d908856 +130, 0xd12e5f215de0a3b4 +131, 0xd94cd412b8bef057 +132, 0x40e85ebd5844b9e8 +133, 0xa581cf7ef62e70a2 +134, 0x74953df639f8a9a2 +135, 0xaa92c9804434caa6 +136, 0xf186398542a15448 +137, 0xa0888e1233d64da3 +138, 0x277d14f22bc64c91 +139, 0x2851b3b5fc49ad5 +140, 0x68182666788909 +141, 0x5ea068625e49839 +142, 0x63bac5a5d225e8db +143, 0x2dd9db0ad24aff05 +144, 0x3f637e71528ad6ad +145, 0xe3b7ba911c4fe47 +146, 0xe4bcf50c8ada7ab6 +147, 0x4470ffb01cd6980c +148, 0x377cfdbe8e810731 +149, 0xdb33ff37954849c7 +150, 0xb622ead14010ad64 +151, 0x6c44d65c7a81a5cb +152, 0xd99a3fca5a5d9fce +153, 0x24e7360e1ee2efd4 +154, 0xbd927a3fb576d81 +155, 0x1ea3f2b7c909ffb7 +156, 0x48aedb2bec244a7e +157, 0xc17d9539cf53a5f7 +158, 0xe4ea45fcf4de590b +159, 0xe1d863ebb77cb7de +160, 0x8ecf0bc8d88fefe4 +161, 0xa881cef3b3209e05 +162, 0x8f34a14a6978afb6 +163, 0xed4e2e5e1f4966fe +164, 0xede897e11cbe230d +165, 0xd344af5e50042d6 +166, 0xb2739594ba906c81 +167, 0x83c0bbde6d95b632 +168, 0x6b7ae9d1c4af98b2 +169, 0xc4b8f6816eae17f +170, 0xf8e3a6bf7855bd3b +171, 0x9f64ff72d6357488 +172, 0x50b6a304f9543f58 +173, 0x330e8281e591cc6e +174, 0x15dfdd5af7b421e3 +175, 0x8d3224e62524222c +176, 0x90d89d139a75b44f +177, 0xf6efb68e15639dce +178, 0x98cf64777861f844 +179, 0xa031e78e4b3a7b3a +180, 0xa3647dbd85c538eb +181, 0x73656c8c77d9c56 +182, 0x88840b683d4fdb72 +183, 0x3b84749774eac55 +184, 0xb9b753a86ec15b39 +185, 0x31ab026ace06b686 +186, 0x4fd37ef5b5b1d284 +187, 0x7cc6c46fb114a76 +188, 0x463ff22f392dbd4c +189, 0x188c3718f2068889 +190, 0x769892f97d895302 +191, 0x9838246e76757b6f +192, 0x546a68f394c391ee +193, 0xc9e32a7d2a7fb559 +194, 0xd84ac91984217239 +195, 0x82ef273042519aaf +196, 0x79650a2c9bf2a812 +197, 0xb7aa6dc1c23eaecb +198, 0x60326b9e25b055d +199, 0x6b17c296feac0e6a +200, 0x7813f405baa0d85 +201, 0xb9d52400dcb399d2 +202, 0xfb588178727e0012 +203, 0x448763bafa3d9095 +204, 0xd63fd1757e94e19f +205, 0x2bc98e05f296e73 +206, 0x9e05ff0a641889cb +207, 0x1e1716c76c9a8990 +208, 0x9e2f67e555f5389 +209, 0x430a8a612033934b +210, 0xd49a74a4d8743bf +211, 0x7b08085a0b4aee34 +212, 0x2c0482984960e7c1 +213, 0xae26bcde5d8fe8fa +214, 0x8f40022b951f98c9 +215, 0xcc59b599dd0383a6 +216, 0xb6833d7a5e00c373 +217, 0x3e025759aba46bdb +218, 0x2558a3dd775dee09 +219, 0xdcd8370368d091a8 +220, 0x9e55348e5734fa9f +221, 0x1061a08056830eea +222, 0xdca96b36adc5ed23 +223, 0x8563d7d016fe5d7b +224, 0xa3fb6b79b0095ee3 +225, 0xb887cd180ae6f882 +226, 0x670e10186fda74a9 +227, 0xa25f08a01b69032e +228, 0x5d90bfde7e21c0c8 +229, 0xb1b154f328250786 +230, 0xe0050135775487f3 +231, 0xbd7001fa00656593 +232, 0xcb6136e259180b69 +233, 0xf7480387c0872215 +234, 0x2e478a3efc5a7ec4 +235, 0xeb1cad9cb7d82f45 +236, 0x5d4c127c6c060ca3 +237, 0x1f9efe7a0bc11db5 +238, 0x59b9712ac8f24207 +239, 0xb94edcfe7b8e7ded +240, 0x474b672b27aef61b +241, 0xc2150760d3da0859 +242, 0x1146d26c90b6becb +243, 0x52926b0e9e820413 +244, 0x24f2b065f78bdaa5 +245, 0xf94b5372ca68e5e +246, 0xfdf3e645313db1fa +247, 0x181af7ab689d2ec7 +248, 0x1e275b8f25520a3 +249, 0x1f287f3ff3d55dc8 +250, 0xa035801d4747cae9 +251, 0xba6ed878f55ebd +252, 0x74d6598302a5c786 +253, 0xe92ce6198f39ded4 +254, 0x7b811ab7cda273c9 +255, 0x9d17fb60483addd4 +256, 0xf2b457f77ba326f +257, 0x32e5956d2a580c90 +258, 0xcba559493cdd2b6 +259, 0x59276c178ca0e7a6 +260, 0x509681deb2f0160b +261, 0x1bc2df48eb8f2a3a +262, 0xbe7f17f92c808cd8 +263, 0xebbcd3a312ab80b7 +264, 0xef85e7595c591a83 +265, 0x914028c61432c620 +266, 0x7d8f67244eb3ea9e +267, 0xa0512684d8ca4355 +268, 0x5a12209ada976a9c +269, 0xfa0cf430c33df55c +270, 0xd514dc8064688736 +271, 0xc5020a78e10201f7 +272, 0x9df7e30707f4591b +273, 0xbc41eeb3c45f4ba2 +274, 0x2b5605d64a470e5d +275, 0x77753b9a125af99a +276, 0x7ba925c3af8e2a4 +277, 0x46c1dadcd05c1165 +278, 0xcb64cd52411f993 +279, 0xa6c3c1f065f7c758 +280, 0xad68088813a0068a +281, 0x6dd039e4b9d4631a +282, 0x528f220f2f54270e +283, 0xfe565ea36805959e +284, 0x3f2edbdc64385933 +285, 0xf0ea2fe07768bf3a +286, 0xd120fe046bfafc74 +287, 0x85c1b029a6d56aa1 +288, 0xb03c986da026593d +289, 0xd126fed2a4ca68a7 +290, 0x7e63d8216bc42201 +291, 0xadbfd88dcf50e179 +292, 0x6c1c1308ee42ca66 +293, 0xf5415a024cbf5458 +294, 0x4e50d4d388352815 +295, 0x38949c203a1a34ab +296, 0x3a35d5ff38274f23 +297, 0xc96c009af2982c00 +298, 0x581691437bf0b1e7 +299, 0x793d1a61f0b0dcf8 +300, 0xa36a3b1c3e39c61e +301, 0xff2938c1b78db0fc +302, 0x1e82a7fc6b7c4725 +303, 0xd91883febcf4672e +304, 0x22c55d5c95f1d985 +305, 0x3fc97236c50bfce1 +306, 0x28a3e0c7a4380bcb +307, 0x2c072113ce5f2570 +308, 0x9c816b6af1d912a3 +309, 0x83698f6af8e41daa +310, 0xa7b1b189d398eae5 +311, 0xb5b44ce05dd0867e +312, 0x5ceaebf68b501f84 +313, 0xdf384c2545db9168 +314, 0xa75eae42ad85396f +315, 0x88273ff551afa924 +316, 0xda2c47046eabd9f0 +317, 0x18d83b83988fa9bb +318, 0xeed5ad076674a6ac +319, 0x28d969bd36a0d5e8 +320, 0x9259eebb564cfd98 +321, 0xdc2e175377ffcd6a +322, 0xcdb19c84396bc51d +323, 0xeaa3a7674b5e5da8 +324, 0x9bd54f94110b36a +325, 0x88d96179c0a35528 +326, 0xea1536654ceee668 +327, 0xdd1cc9d40ad3ea60 +328, 0xe9106bddc3221293 +329, 0xe096d5b5acd9ff46 +330, 0x4cb27170156f9265 +331, 0xd0d3e5b9edadb2bb +332, 0xf75347484f2af9b4 +333, 0x6170333a4e6885d5 +334, 0x99a50b6b702b80ba +335, 0x10629a67c9781899 +336, 0x374a33743030da9d +337, 0x289fdbd0bc89f257 +338, 0xa67c56d1bc5dc5dc +339, 0x38e90cd1dd6d64f2 +340, 0xcc5ed5dc4955655e +341, 0x723d33bae999723d +342, 0x46af17f0c981605a +343, 0xd1d3a915f899b0ff +344, 0x9a60c9bee03dcb43 +345, 0x11753a29a1d9201 +346, 0x491c99adde4e0a73 +347, 0x634437d6dc4388ea +348, 0x5f4cf58d810069e0 +349, 0x8d950ed29ac1703d +350, 0xa6330099182b17e3 +351, 0xfc9bf9a5cd4ea35d +352, 0x4560dc5769ff741b +353, 0x374a9ff29ee966ba +354, 0x16a9bd5c9214e40d +355, 0x46fdfb2899af3e80 +356, 0xe2eff8b6ad57da07 +357, 0xa67c709690485024 +358, 0x87551c8907b62ead +359, 0xde03a75e08382365 +360, 0x6744ad2be09ed2c1 +361, 0xb34ec9f71efb1f48 +362, 0x4fb71847ea9a525a +363, 0x10ffcd51ebb2f5b9 +364, 0x489431753bfacc7b +365, 0x7a9cc00b29aa7802 +366, 0x8017011d2285ce9d +367, 0xd54d90e061d61b87 +368, 0xa41a40e4a81526a +369, 0x47b5ba075adc3b4c +370, 0xb8cbbc5498cc428b +371, 0x6165fcf1ef4795b +372, 0x57926a7aebb26866 +373, 0x226ec9794dd0714f +374, 0x2759cca87ce9a2ed +375, 0xb41a74ac376c84d3 +376, 0x3e8101b52e2518a6 +377, 0xc8f18bb165e3db1d +378, 0x187f3ef2ff1093d2 +379, 0xb5c1069cdbe57e46 +380, 0xd3f342f3104a5902 +381, 0xf32e59c6c7b8458 +382, 0xfdb39f79b5b1f574 +383, 0x526dce2fc3115682 +384, 0x1a2e8128c0180ae +385, 0x5eead6a0e587e4c6 +386, 0x450e7d15d282c580 +387, 0x931a6cd04be42fe5 +388, 0xb4d321f03fb71277 +389, 0x32479d856fd9bdfa +390, 0xa28dc713e419022a +391, 0x6c8dcea6b5adbb14 +392, 0x4ae7b8d58ef7aa3d +393, 0x49903e3fbd56493e +394, 0x5238b0c9ee856f3b +395, 0x77deab4c733cb2 +396, 0xea5d74aec663c8dc +397, 0x899afbc707b0899 +398, 0x56a9418f18219182 +399, 0xb42801a6445d852a +400, 0xd8462e581c7cd53b +401, 0x802701332acff0c8 +402, 0x309618a5c049ddaf +403, 0x66f6d281cd986fa +404, 0x53f089859dd3e861 +405, 0x497078aabbed67cd +406, 0x9cdc9d89a2e1cc9 +407, 0x871b1721c6f463c4 +408, 0xe9f8872d8f113d84 +409, 0x48e03acc1ff301b +410, 0x79d5f73993eb02ef +411, 0x5ac76f9f2329e39b +412, 0x878c2c8d84a9643a +413, 0xd1d0786d40a7391d +414, 0xf024ad81eea63787 +415, 0x9f96b1146e5354b3 +416, 0xa85fd9a5bc0fc195 +417, 0xafd0522c28edfd2f +418, 0x6c1aa508159a1fcd +419, 0x873f632373719c87 +420, 0x5db129eaa27ff3d1 +421, 0xd81037e5b49f399d +422, 0xa40a347abfc43a81 +423, 0x314452aabf5a95b1 +424, 0x6f8642230a3edee8 +425, 0x2aaa01f7cc73fb09 +426, 0xa0ebf15ee345343 +427, 0x19fddca117f16f35 +428, 0x111be87b23ca2143 +429, 0x46de5fd13663c896 +430, 0x2dacbe0fca5e4efe +431, 0xd534f9dce19043c7 +432, 0x7a548f9a35a6759b +433, 0x3c6f046dd15b6fe3 +434, 0x1f7a17cbfc090519 +435, 0xd8a282357a83d2ce +436, 0x96a8a5cfb5be2843 +437, 0xce416b54c95c6006 +438, 0xcda9d6127cb716cb +439, 0xb062a607b35aef78 +440, 0x141e913718707191 +441, 0xef829605cf4aa346 +442, 0xb9555c4c76d6a7c4 +443, 0xd41bd4a1593170ca +444, 0x2e00143ad3d88b4d +445, 0x1afa722d16ac1d47 +446, 0xa22530a5d53159c8 +447, 0x17f76921e5633a50 +448, 0x8e3ed4b11072799f +449, 0xedb6ace0cb513a05 +450, 0x8dbf3d235449385e +451, 0xd01fb688b01b798f +452, 0x8e3aa7aa93ab0436 +453, 0x8b18ef4c8cc20636 +454, 0xf40181de15f5029a +455, 0xfcf54366f31c924b +456, 0x7b16e64f5c3a1d71 +457, 0x6b5f96df49784c48 +458, 0xcb5914727615bb07 +459, 0xf228f7b32ec2d237 +460, 0x37c51a8a1b854a84 +461, 0x63484491b02c7fac +462, 0x526a9f0a571e170a +463, 0xeb8d59e7fbbe583a +464, 0x4fd1fa3bd32b8c84 +465, 0x825ba1ed08b31e1f +466, 0x644d2cadd8ddeeb2 +467, 0x3874924732d3c6d7 +468, 0xd2679fee287a403a +469, 0x17ddb27712b6cdb9 +470, 0xcce6bed3fa81f460 +471, 0x8a2df0f2ccb3f028 +472, 0x85d166e4456aae72 +473, 0x5dc4ce3fab56777 +474, 0x555b2c69b6eabb7 +475, 0x873bc152fdb3717d +476, 0x5670068eb7d52805 +477, 0x7f776ca61f79e219 +478, 0xa8b51d2bd8c8c939 +479, 0x50345828de969faa +480, 0xbefa083bfbd71b60 +481, 0x883809b883dffdca +482, 0x49ccf930ea76fce8 +483, 0x97cc45c4c2dcf12b +484, 0x4d3aef2e2a4a450b +485, 0xc7ed768e40efd44d +486, 0x5530c69ecdc47b2c +487, 0x2fbb8ad65b3e777a +488, 0x45234e14d9fd969d +489, 0xb6a758912ec87c9d +490, 0xb35f335efeac2d3b +491, 0x21efc82b1e65a1cf +492, 0x897db9fe20a2702f +493, 0x444042b714793c27 +494, 0x37356cc844e57cb7 +495, 0x602ecce617309266 +496, 0x4ea323a5d93363b7 +497, 0x2c2f0344303d7067 +498, 0x983de14baf7a9234 +499, 0xc4edde0900601361 +500, 0x12574e754cf862a8 +501, 0x82eb774465a3a83b +502, 0x115fd6ada32ab10 +503, 0xce23f43213ea118a +504, 0x912e289389130f18 +505, 0x977464bbb2fc0cd9 +506, 0xeb944201e2747c79 +507, 0xa41dae77205e05ee +508, 0x66c91981aba16d08 +509, 0xbd4aefbeb385af57 +510, 0xd7c7d36c0ec75862 +511, 0x492e43720ebee40c +512, 0xf44861d4636833df +513, 0xb9fb92c7203e2a1a +514, 0xd75f7f48e860938b +515, 0x8235d433d3e773f8 +516, 0x36cc65bb70a32774 +517, 0x3898d9516512bffa +518, 0x4f5c36707161dc35 +519, 0xa35e3d81512f0a8e +520, 0x4ae50933ef7bd3b9 +521, 0x641dc03f71dc81f3 +522, 0xc6002d833e1d768e +523, 0x6c7d94f79b7a1956 +524, 0x4027405ac3c6e666 +525, 0xab69f022928e86d8 +526, 0x90272e57839563ab +527, 0x56e78769f743d98 +528, 0xb5c7931145b93a39 +529, 0x253fbe3201939650 +530, 0x5325825cbe56c3a9 +531, 0x159aa2be6163c7bf +532, 0x56b8d5a5ed375c9 +533, 0xbd4b45a7cce10f56 +534, 0x2f799de5fd80339e +535, 0x40232bd30ebb82d2 +536, 0xc10e2198616b20a6 +537, 0x6a13ecc0b52813f +538, 0xfafd5d5b466ee59e +539, 0x810cbf398208d400 +540, 0x7137dc6f08e5b6d3 +541, 0xfe59d9caf7564d0c +542, 0x3117cae7c6ee6927 +543, 0x89e83cf15785a430 +544, 0x386b6daed57236e1 +545, 0xc2e6fb38df98a4dc +546, 0x496513da22e1e53e +547, 0x57efdf29edd94aab +548, 0x3433ac46ce163ef3 +549, 0x296565c39cba14f3 +550, 0x1ce89ad8ff370a6f +551, 0xcb12c5a7db52fd27 +552, 0x8125373ad475530a +553, 0x75ed8dda02fd5bbc +554, 0xaf2c279596340f93 +555, 0x18c7f80478479a56 +556, 0x14edf2ed871d9c41 +557, 0xf35731f0b8d26e4a +558, 0x2cace2d1996272bd +559, 0x84c3b017f5b12bb8 +560, 0x441c286a303c81c8 +561, 0x92a7c594c92b2353 +562, 0xb175a7a7e0cab31f +563, 0x501d7003cb9e530d +564, 0x1e9d3dea32bb5d6 +565, 0x60756fd6e4b239d2 +566, 0xf979b4c7ddf4bb22 +567, 0x1e5c0ba3d2797a7a +568, 0x94590d4209c70c70 +569, 0xc5dbc6ef6fd8c203 +570, 0x46a0eb4fc61727f2 +571, 0xe3ddaa7f4033fcb0 +572, 0x4fc177555a6b2f9b +573, 0xce0f6ab675596a18 +574, 0xe11a08478844ecec +575, 0x47054780433de44 +576, 0x89a3be9609dc2a34 +577, 0x9ea612c49a4c170f +578, 0x8212e9db2df9ca7d +579, 0xdf1cedac92affa7c +580, 0xc21b0ff068580e5a +581, 0x49168be340b1ade +582, 0xce3a5fd54225a6a9 +583, 0x80ecff24ec6cdb9f +584, 0xd14429e950a1a21e +585, 0xc66a1ad3cad8f9a6 +586, 0xcc76bdca3ded453c +587, 0x748165a5cb8b6bd +588, 0xcc77eb3966db7c5d +589, 0xbaceadcc1db342d6 +590, 0x33b42e3dc005fc38 +591, 0x43b5661eead65675 +592, 0x356821fd43c46e5 +593, 0x4efdd2444e0c5ffa +594, 0xf84ce60e2c0de959 +595, 0x14a4b1dd26583f04 +596, 0x6ffb885f5fe18b87 +597, 0x8233b6a95b1af132 +598, 0x7e2e9c449dd06b71 +599, 0x736bc96174cd4d97 +600, 0x86591ab3ab385777 +601, 0xb7696e3909a91039 +602, 0xda363e1a90c99d9c +603, 0x793cd7e1855b9a43 +604, 0xa9dbce0ccacd24c2 +605, 0x5d9a1d9b06fcf2f2 +606, 0xa7db7fd7c2b50d55 +607, 0x13c85aaefd37bf77 +608, 0xcba5689a383aa436 +609, 0x7dcbc3e297d2bd31 +610, 0x9860da13006164e8 +611, 0xda3be955750ba8a6 +612, 0x57f6a78ac6d2cb3 +613, 0x861ed21955702cef +614, 0x3cfdfb6fa0763186 +615, 0xd075f803b072f140 +616, 0x6b1622638e94a714 +617, 0x6f4b177c0213a295 +618, 0x26c113226bbfa72 +619, 0xbcb962e03d008ba7 +620, 0x1e50555d6e75d9b9 +621, 0xd67082f15ff0086 +622, 0x20766d0fc6bd729b +623, 0xeea24b2ecc4db639 +624, 0x3136637be559ec83 +625, 0xd3f2c641faccfcf8 +626, 0xe43f5bfe95bfb2c2 +627, 0xbc801108984335e3 +628, 0x19ff6b0c435e06a1 +629, 0x7b8f28c44eb5195d +630, 0x375460c52c467757 +631, 0x534f4697a2a2f0d3 +632, 0xbd1aed6c1a94e586 +633, 0x9dec33a59dd000e1 +634, 0x4611fc38e6902126 +635, 0x1296da2fca821b09 +636, 0xce4684ac8861a6b7 +637, 0x16bdaa7a0563d3c8 +638, 0x22a6a8b6de1fcd10 +639, 0xeed5c457b2d2a399 +640, 0xb66c697c0e328f69 +641, 0xe678d6d573b2dc21 +642, 0xd0a78328399774d2 +643, 0x7fee339fadd44eaa +644, 0x32c2da48753c8818 +645, 0x691f87af10bc6f5c +646, 0xe382722ac6ebdbb3 +647, 0x28bb87557931a39f +648, 0xc3aba948d7d22fa6 +649, 0x3ce7016f24e2f50b +650, 0x863b408ab8161d28 +651, 0x1e3d2d6746c16b31 +652, 0xe5a21dc5843a37d6 +653, 0x8ecb559ea375c81d +654, 0xff2681b83a599f98 +655, 0xcd9893140d02b725 +656, 0x80294d390a4e1a08 +657, 0x254166d362613f84 +658, 0xd2c336ba5b4ae618 +659, 0xef79a05286b75aaf +660, 0x704140e00e02ea9f +661, 0xa2623b124bb92365 +662, 0x2225846e393c249b +663, 0x95676d7c7aae81a3 +664, 0xe0cbe12ba194b3d9 +665, 0xda8ca3d800ea6152 +666, 0x8b2c2f63db05c887 +667, 0xf14012751ef435e9 +668, 0x33820fbd9a06d78 +669, 0xf37375a008192ae8 +670, 0xaa2c34f4b405589e +671, 0xd26bbda155ac158b +672, 0x418b108b101ea70d +673, 0xb9648a82ca0617d7 +674, 0xae6e2213c8c0d3e3 +675, 0xda7335c158d64615 +676, 0x78f175a4a89cdf5b +677, 0xac7a07b66a84f751 +678, 0x266019228d3bdb87 +679, 0x3a7798913c66d5a +680, 0x2aa9c173879dc048 +681, 0x67453dc96c3642da +682, 0xbe9ea095f8333cda +683, 0x10998be0d5702361 +684, 0x77a4e1af57a6b02e +685, 0x66356334d32ab0fe +686, 0x2df9585cb5ea1b34 +687, 0x51159b44acaa000f +688, 0xbc433d2fbb8a4953 +689, 0x5a533a3838335feb +690, 0xd57ffb6f839fc89d +691, 0xe7cd85b8d026e706 +692, 0xdd4acea5a81530e7 +693, 0xd7af04b51606fa0f +694, 0xe31e683c116deb37 +695, 0x4e2adf78e2a88fd1 +696, 0xc58b907a61dee8f +697, 0x673e1a4b00b0a2de +698, 0x36b639fa8091f63 +699, 0x7782c303339e2f0a +700, 0xfd84e0fb7774b0be +701, 0x2a6ac41e094d6e25 +702, 0xcf221a0187c8ca32 +703, 0x4e457ef8a6a528dd +704, 0x9a7714c8913ac3a2 +705, 0x5a6513aaec56ddf0 +706, 0x254fc4d74dc56a5 +707, 0x93e1bd37d16ee5f2 +708, 0xd1a16a2aa652c2ce +709, 0xa66ab34e5262848 +710, 0x5e6f429f482e4a2d +711, 0x198eeff9e36608ec +712, 0x3bea433a42228c7b +713, 0x1a85a30f51e1ad8 +714, 0xe80b6a4fdb0d0482 +715, 0xc3e8d0c13f8879e +716, 0xbaa3c52bb9413a89 +717, 0xc2d4614798d79e2e +718, 0xbbd3f6abc551b6a3 +719, 0x282e112e6bdf2de8 +720, 0x615cc8613f4d4518 +721, 0x53b2627138d76555 +722, 0x1b19126726fd77a1 +723, 0x915c0a108cd2d357 +724, 0x1061822da93d9907 +725, 0xe79aee77f55dc17a +726, 0x7b367a3165fbeba7 +727, 0x1894d6a0059bc074 +728, 0x876235ba0475437c +729, 0x2b8f64a5357907dd +730, 0xadabbbf775f4c3a2 +731, 0xf70d7e73e0914757 +732, 0x50c1494071662c91 +733, 0xae3cc90ade2512c8 +734, 0xd73f9d2b66333aa8 +735, 0x46342e130d23dc94 +736, 0x6c8307abda3d568a +737, 0x235d9a334f4eae0c +738, 0x33d0ccce19e66c93 +739, 0xd83559cfbc7acb8 +740, 0x430f65543bfcfad6 +741, 0x5dbe2eb34c5b25cd +742, 0xdcad606d1b515392 +743, 0x6376bc62812519c9 +744, 0xf292cdcbab076b52 +745, 0x5b6669c53c3e9b1 +746, 0xbd5a95d4d51f18ec +747, 0xf71d40c0b07b0a16 +748, 0xa51966e8052a050d +749, 0x7fd18ced5be2d350 +750, 0x82727df4050382b7 +751, 0x7c10a4e48f664caa +752, 0x3712f2d7d2e6bdba +753, 0x2535b833ad6b4ef6 +754, 0x420577375164ff95 +755, 0x68c40b08f579888f +756, 0x8922d2a586203dcd +757, 0xf317b95e3aff246a +758, 0xbbd1c166e380207d +759, 0x9303601189dfdda1 +760, 0xef342abd93377a47 +761, 0x499773d085e7de1a +762, 0xd204bb687ac202ea +763, 0x19ffb5b90619622a +764, 0xc59bff0531dfbe98 +765, 0x8c6d480a717445db +766, 0x8c3c030ca187e2f4 +767, 0x53f0740df18d7b6a +768, 0x1a5eed54662e3c6e +769, 0xbb29a94e32f03c3c +770, 0xdb0df407c4bbc009 +771, 0x6c0a9f4598ac0ba8 +772, 0x2e0ac7251648f892 +773, 0xb4555f7c1e3fe8ac +774, 0x2cd8ce106d8e441d +775, 0x608e38e439a239d5 +776, 0x1bb66d4c2a2ca5a8 +777, 0xc32ec47253591fa6 +778, 0xd3974f6f2b8b038a +779, 0xdcbfd9eb4a9b1626 +780, 0x8589b3e6fc1ba06b +781, 0x81f34f1da9f27f9a +782, 0xd3bdd7496dcc21bd +783, 0x7c963559e1c47305 +784, 0x5817e571d2fcc113 +785, 0x4f35fea60a0582c8 +786, 0xb851f167a0bda1c2 +787, 0xf57e13249380eddb +788, 0x570e69bf38151a56 +789, 0x117feac919f19d69 +790, 0x49ce46af93025c96 +791, 0x4220f6c18e8e1f9a +792, 0xf082699d8fd5070b +793, 0xccd31756abff1928 +794, 0xbf9d4ab46de14d1 +795, 0xf2e0be2c2bbbc823 +796, 0x6e9b495ef22563ed +797, 0x9a609cdcff6e3152 +798, 0xbbd2e5dafc83fcd4 +799, 0xac153055d6c5770c +800, 0x312bbcdd6b681016 +801, 0x3ed60c24fd5a2f3a +802, 0xc7f3b2948dcdf5c9 +803, 0x8cc631df1fac1c1d +804, 0x77f4aab62a657d61 +805, 0x2f43e30323829573 +806, 0x5b7d20ab0ef901b6 +807, 0x7fa99ec817785705 +808, 0x5c95cf94241f1e3c +809, 0xafa2d371f8f579e1 +810, 0xe4c314c4017e2e77 +811, 0xf672b575a585c0b3 +812, 0x6600a50a45d6ecdb +813, 0xe06c0d7edb63485b +814, 0xf1b45b82f4d0e8f1 +815, 0x41581d87cc1b759b +816, 0x8807b689eddf602e +817, 0x9e11d2949076d4c0 +818, 0x9f3b430319e48bb1 +819, 0xb27fa37d89396b64 +820, 0xd930a0cc6723c8b0 +821, 0x935fe6e9c7a57eaf +822, 0x184f5dba2f19591a +823, 0x513f86165d0adb73 +824, 0x4f2cd09cb85aef51 +825, 0xda66728c1901a11c +826, 0x2445b8938b33db42 +827, 0x98fd86e4b89be5e8 +828, 0x2f752d8769747705 +829, 0x2cb9b42b98ce0c0a +830, 0xf3314e0e0c57d31b +831, 0xf9c382d55868b2df +832, 0x83264a41539ec2c6 +833, 0xa2b3674f0adc1d0f +834, 0x2dd7ad1d92001e7e +835, 0xee210f6047a94713 +836, 0x71a18140729bbcfa +837, 0x415058c01e01384b +838, 0x6cc2e2079c9de72a +839, 0x8561a9093d2b5d72 +840, 0xd6c276d566895b2 +841, 0x57cb2804836f4867 +842, 0x78becdfda7fd91d6 +843, 0x4046a94c8377a3 +844, 0xadaaaa0d558d261a +845, 0x56ef182050db8865 +846, 0xbc28289519f6ebe5 +847, 0xbe7b95e4334540fe +848, 0x384b9838c105f8c8 +849, 0xecfb823fc8815c7e +850, 0xafdbbb2bfa8bdff8 +851, 0xed33653dbeb638b8 +852, 0xf4164289a7a6dc1 +853, 0x6e5cc51c2a3a8b20 +854, 0xdd59a99d16116f34 +855, 0xd48f95ba89787b5 +856, 0xacf9753586b8be7d +857, 0xc0430da7c73bf373 +858, 0x25320aec467ee989 +859, 0x5108e8f4be4f8d8 +860, 0x69b1c7d23ff502c1 +861, 0x7c08bd62caea3313 +862, 0x4285d5b8ce1d19fc +863, 0xbe03dc19cc3be0ad +864, 0x182cdb615e4d4147 +865, 0xf75270e6096d5d1a +866, 0x467b7ac524d17060 +867, 0xb0960b398a111ec3 +868, 0x126c099178f50090 +869, 0x19980d353ddb289d +870, 0xd4b394e2c0305403 +871, 0x5972d7c748938602 +872, 0x276461c9da39bec4 +873, 0x6b3a2046d6ebdce3 +874, 0x4c55d74597c27388 +875, 0x363bf469f4f673be +876, 0x9b26d4e69d36f584 +877, 0x21d441f573e56b6f +878, 0xc29509f2a1e9c4c8 +879, 0x5178088ff6e62d5e +880, 0x902f8ecd57128a7 +881, 0x479fddd275330bae +882, 0xf56ac8b6f6364526 +883, 0x4904060a896d759f +884, 0x1c0f1f4e800bbfe6 +885, 0x9b03bcb77880240d +886, 0x2f35904d9867379d +887, 0xf88a05a4dd6928e7 +888, 0xb5341282b6781021 +889, 0x225910a217522b71 +890, 0xa76bac3bf3675285 +891, 0xf19973940d9a57d +892, 0x9f6ef608ed4291d6 +893, 0xec63cdbf5911fb10 +894, 0x8a359dd4ec3b41ec +895, 0x8373d0d4e6af7261 +896, 0xfc6a14169335e7d5 +897, 0xf06ff499b6856cda +898, 0x71f5ce76943ec9e8 +899, 0x9417034d7879b92b +900, 0xfa0e3c78f47c0276 +901, 0xea9ebf817a3e3b93 +902, 0x7c08ff3d42e19a10 +903, 0x8697e5798f9bab52 +904, 0x10eb4dab88e4ce59 +905, 0xbd11bc073298b46c +906, 0xf46483b5fea2427b +907, 0xafed38960dd33a59 +908, 0xf7a00b0413eb47f6 +909, 0x4233464f10e7666c +910, 0x7ce6db32b60aba3a +911, 0xf9ae9414469308da +912, 0xf5c4e8e04c008924 +913, 0xb89c735c89bdafde +914, 0x8b815ec319546463 +915, 0xdd57dedbf1fa66e +916, 0xdc0bba0705548598 +917, 0x1ed685fb6c966b2f +918, 0xd9afc3ac4319d72a +919, 0xed7c7e9407e71351 +920, 0x585b44a509258719 +921, 0xdf9eac3020de19aa +922, 0x102102d94b983d57 +923, 0x85dbeaa806a02e79 +924, 0x4bacf4194786b961 +925, 0x32bf2fed8ab9b611 +926, 0xce94384eb215dd1f +927, 0xfd1da2a7795c4801 +928, 0x149b31c0a14f7d02 +929, 0x4e01962d69248840 +930, 0x41d509a1c742473c +931, 0x46105403c2b4e56d +932, 0xe6fca820341c56e4 +933, 0xf1982bf03572ac79 +934, 0x9f99e2fb3cc2715e +935, 0x6e3bd2ca3d50faf2 +936, 0xd0aea8d0fee1014 +937, 0xda0ededd067cc72b +938, 0x56c42899c5af28b7 +939, 0x8c4883568ff28ba2 +940, 0xad9019516b75c1d3 +941, 0x3aa1b33682aaf348 +942, 0x31187b962cf65f58 +943, 0x7f2cc27ce4c8459a +944, 0xb75ee9bbf97014c3 +945, 0x8eb8f42b9a9c3024 +946, 0x5b7dcf683a3c14c5 +947, 0xa258b18ccb7cb3c4 +948, 0x7587bc7015c145f5 +949, 0x7536427aff38edd3 +950, 0x437b33489ef425b7 +951, 0x22febd7e96538bfd +952, 0x9fefcc49d567b35e +953, 0xfd756268183d7d6d +954, 0x480df3a7112b2eea +955, 0xfd02a24b1eed9e6a +956, 0xcb3b6c96d65ab879 +957, 0x19f8b328f365f6c8 +958, 0x7d5d20e6328ef6cd +959, 0x8d74057415768152 +960, 0xcba11867467079a2 +961, 0xf86138cf35f091fb +962, 0xdb3204b36a02eb61 +963, 0x8974a7786d5f6894 +964, 0xc8445cca1175a023 +965, 0x1523bfeb2f088c15 +966, 0x4e39bb650d7c4de0 +967, 0x91c9e9ff5b823702 +968, 0x7c3a6850a7c143e7 +969, 0x131999c480253f47 +970, 0x3ac336af37f6a4e7 +971, 0xb057ae911b406d5a +972, 0xde0b70c5f9d5be60 +973, 0x93fd54e75618a86a +974, 0x3955e207acb1f65c +975, 0xa33450c2890b0b61 +976, 0xc6294720e971cd52 +977, 0x89cb13a5b1364169 +978, 0xa6fbc61118b44104 +979, 0xba0651279f93958b +980, 0x6995c30cf06ed3dd +981, 0xd75cd3472c5f86a9 +982, 0xb18d90ce11dfe2ad +983, 0xd69200ae86d53222 +984, 0xe73fc25107e53e90 +985, 0xc1edc96f67bcb096 +986, 0x587cc0fc53992abe +987, 0x2139d74bc6f3edff +988, 0x1b4609bbfa08b543 +989, 0x564e5d7acb190539 +990, 0x1099ce214921efbf +991, 0x7764cd537ccb1b55 +992, 0x4232db7dbdad3998 +993, 0x54c970b3ca338f24 +994, 0xf28c8f460244de6a +995, 0xbd37dcd3829c5a4b +996, 0xefbfe21ef1ab13ae +997, 0x6df8dfc0a865d4a3 +998, 0x5e65a5bfa3f4d555 +999, 0xf6affb932cc9f3f2 diff --git a/_randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv b/_randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv new file mode 100644 index 000000000000..6c513476bbef --- /dev/null +++ b/_randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x509946a41cd733a3 +1, 0x885667b1934bfa +2, 0x1061f9ad258fd5d5 +3, 0x3f8be44897a4317c +4, 0x60da683bea50e6ab +5, 0xd6b52f5379de1de0 +6, 0x2608bc9fedc5b750 +7, 0xb9fac9c7ec9de02a +8, 0xc1942c64262d8742 +9, 0xc2c334fa4c2214b4 +10, 0xe53cfba26ba5ce93 +11, 0xf01f0c9d5398a979 +12, 0x1bfa2ef194eeb86d +13, 0xc9df57572868239 +14, 0x728e35871474105a +15, 0xdc7b1e93de9e112a +16, 0xc4d930cafb32002b +17, 0xf18b0bd68577e055 +18, 0x4929ceed7e690239 +19, 0x3b7a547b356b29d8 +20, 0x660f1cebb7affd72 +21, 0xf850e6052cc5f5c3 +22, 0x931512b017c71f1 +23, 0x8d88b7af3b8731e7 +24, 0x3050de537e8e84e0 +25, 0xc917230b8bd3d552 +26, 0xf58da0814356b478 +27, 0xcfc06b804972be32 +28, 0xe3892682eff28645 +29, 0x55bc734a03ca4fa6 +30, 0xe2f7700a020152b9 +31, 0xcba5a308a8d40969 +32, 0x928b63592b6b2f55 +33, 0xa372b4e0293d90c1 +34, 0xd73e00b1c0fdbb6 +35, 0x43c712d398019cad +36, 0x295d994760c6501b +37, 0xe94236abdd256f1d +38, 0xed4566687d847ec0 +39, 0xd3a838dfcbcb5df1 +40, 0xf4ac54b3d79aae61 +41, 0xcabd8f089de74dc8 +42, 0xd58e132a2cd64b6d +43, 0x4eb8bc55f8993dd2 +44, 0x8e4ee152013579ca +45, 0x1aa7c7e058e02a75 +46, 0x5038184ea8f1dfbe +47, 0xa9af7da9879e99ed +48, 0x267567fe1128a585 +49, 0x3a3d637084865189 +50, 0x35179207577f3a88 +51, 0xc323e40ec505a4a7 +52, 0xd2ff171e3203c51f +53, 0xf524706a4db15f35 +54, 0xbff297a90126dd1c +55, 0xec7517f97c47dbf7 +56, 0xf56604fd9a8a7f3e +57, 0x2a63c3bb1635de13 +58, 0x9c22f64a9b9acfc +59, 0x6fc94c63f4e1b311 +60, 0x955820d474d00924 +61, 0x5a4d25256934ab74 +62, 0x95ea0cf2b73da09e +63, 0x8e21647894c89a8d +64, 0xa6ffd9037f6627ae +65, 0xca5d03082b0007fd +66, 0x2ee116ac7bdd65ce +67, 0xa9e6e172042fa80e +68, 0x4763c82d6e7c3d8d +69, 0x325169a3ff49a8fe +70, 0xe0be054ea126080c +71, 0x4ccc1794542607ba +72, 0x58c480dddafc29d4 +73, 0xedab421340a8d4d +74, 0xd28d8f3c2ab241cc +75, 0xb2a89fabba9566c3 +76, 0x1b12fc8b30a80b49 +77, 0x65e178e0065959ef +78, 0x4adc931b03e25f55 +79, 0xefb7b250b854feff +80, 0xe024be0a14bf3da2 +81, 0x60c2285324a5a642 +82, 0x280dfcde16655ff +83, 0x18c2cbf4c0ba9bb0 +84, 0xcbeea642049c68c +85, 0xa1b19b0b60833fa9 +86, 0x10f72a22ef81e27f +87, 0x5cc3db165dde75b2 +88, 0x947a3c40223e6bd0 +89, 0x5d469f487abb870f +90, 0x1b1f4fea711c039d +91, 0x63b22d9e9616b06c +92, 0x689aa9d9808ffa7c +93, 0x2164f59dcc5f3e03 +94, 0xbdfc99e1f2c1193b +95, 0xdc9e85a6a6b8f61e +96, 0x11ad0ede8657e961 +97, 0x73a69427c838bafa +98, 0xfa4b98f49849cc62 +99, 0x5ccb852e4e18aad9 +100, 0xae102d1e06ad3569 +101, 0x4be41a104f8d8463 +102, 0x723f50acab4314fc +103, 0xd3b7b694a6bb6c38 +104, 0x8bfd1fbedfb8f092 +105, 0x3d5d9aea4d80f37f +106, 0x28cd19af64bfc553 +107, 0xceba7e81e5ec8edc +108, 0xd8c0513fca3ca719 +109, 0xfefef4fd2a0896f0 +110, 0x1aa7320084a97662 +111, 0xf63c0bb8fdae24ea +112, 0x497a5e9d0a13c0d5 +113, 0x37fabc943a07639 +114, 0xb5be9f1d19096cc1 +115, 0x4385acd2ed447c52 +116, 0x8e146c6874b731fd +117, 0x553c3c72c9e05a64 +118, 0xb9cca017a8d4be34 +119, 0x8f8e09bbd56564ef +120, 0xcf6da1a96df67f67 +121, 0x5882a27646d3189e +122, 0x1554cc47896d846f +123, 0x105600be06e72171 +124, 0x95a04162a7ec3791 +125, 0xadeb00515f0d6be0 +126, 0x22ed3d1ca5ebc008 +127, 0x312629837e981334 +128, 0xca916e4cef410dd2 +129, 0x18556a16bdff0e5 +130, 0xfab80417581d6927 +131, 0x40f7ecce118881b5 +132, 0x6a12fe0d0c5f3ca2 +133, 0xd3e2ba4104a669f5 +134, 0xdeb3d714e1fd921b +135, 0x32cc61dc107d240a +136, 0x1a79efae30dbd860 +137, 0xebd6029e65fcefa9 +138, 0x94289c890d17c9b4 +139, 0xd91bbe374cb9f243 +140, 0x3352bdd3eccaa300 +141, 0x5cc9a4bf3127b238 +142, 0xebd9f454d96adb59 +143, 0xd5f61261bb7089ff +144, 0xa743f21be20ce5f2 +145, 0x3d2a78d45bfb1da9 +146, 0x9ebbad453112c987 +147, 0xff48b7b97e3f597b +148, 0x2b57be29ae160a9f +149, 0x90df488fada68e76 +150, 0x785b4250ae46cc0 +151, 0x1c4fdcb6c66db255 +152, 0x3567f33a12172e96 +153, 0xc173a5f010dbe48c +154, 0x859eac8b59dd2bc0 +155, 0x532809d8c8b5378b +156, 0x656f93a00428ed0e +157, 0xd4ee7e2199473a09 +158, 0x9bc701f16ecf35a4 +159, 0xcea39cb296d32304 +160, 0x43fbb2333d392310 +161, 0xc9d66a1062247d +162, 0x271a83a113c42b2f +163, 0xee17f7585ab05734 +164, 0x5e98cde55d0b8ae9 +165, 0x488cc07f036165b3 +166, 0xd78481d7416f6724 +167, 0x681436c7434b6260 +168, 0xc53bd2c997a04ce5 +169, 0x61b5951080b80e26 +170, 0x48f285546280fec1 +171, 0x87ff976327bf74ce +172, 0xc10c08c9bc8b05ee +173, 0xa62f879a73bf12a2 +174, 0x31d7cbb6f9c1acf +175, 0x3e522645e518ee29 +176, 0xb85967a95e811cf8 +177, 0x99f8643751545edd +178, 0x3f962076f920dd9 +179, 0xc92abe52da7ed89c +180, 0xc1fe02e7dba484c9 +181, 0x7904149975239b19 +182, 0x5bfaad7ac409b74b +183, 0xb915e6eba7685946 +184, 0x8b2291b29fd71d66 +185, 0xe57e5709ad0bd967 +186, 0x3fe55bb3338f0f1d +187, 0xf41f8f7a981c05d6 +188, 0x80d3d9160712aa45 +189, 0x2da872bdd8bbffe7 +190, 0x6698441241fe0a4e +191, 0x4870fc969dc6676c +192, 0xd420fc68814fe867 +193, 0x6aa0500b9d8bacb5 +194, 0x55078d31633dcd47 +195, 0x6d758a56c80bd405 +196, 0x122149ae571cb397 +197, 0x22d1134c99ac507b +198, 0xe7d9e27ae05a47d1 +199, 0xd18a73dc45e5a290 +200, 0xb5bc1909e08803e2 +201, 0xe9a1e3ee93f2e109 +202, 0xf040a8f79841c101 +203, 0x9a705a608899152d +204, 0x4f7783a0dab4290f +205, 0x11c5bad24bb23af3 +206, 0x58545a19a22fb881 +207, 0xeeaf5ab573077828 +208, 0x9e036466fd858142 +209, 0xef70bf26fdd6bc94 +210, 0xcc3a2971056cb9f7 +211, 0xef120c86e84d643f +212, 0xa499226ab42f6d7a +213, 0xa85cae4acfa0a29d +214, 0xc8280371e2c25d89 +215, 0x246336f7e63ac4e6 +216, 0x76561f7777c7b915 +217, 0x704f83c71583f0b8 +218, 0x489db8592a76cd3b +219, 0x268d584af17550c3 +220, 0x350e989762428fe +221, 0x6857adc12d13f1bb +222, 0xde62c7d9517260e2 +223, 0xc1f37ee8baac988e +224, 0x714732f71cdd5374 +225, 0x56f01487bfa58c5 +226, 0x5163b23d41d95f14 +227, 0x745150434b747a38 +228, 0xdcf7cd6c6b14b1b +229, 0xd853cc6bc2580f81 +230, 0x693562e66b579775 +231, 0x8f15d6369dbe6678 +232, 0x464c1791098ad19d +233, 0xeeba6610f16ac2b9 +234, 0x3b307cc3c5bf5859 +235, 0x7e82177c4dcb75e0 +236, 0xae5978c33dd3e817 +237, 0xec3c0128360b0b2 +238, 0x2c325b630e904749 +239, 0x237ff1d19b4e7ead +240, 0x3c82e47b67a33956 +241, 0xf38b46203355a168 +242, 0x4df09cfda8d5774c +243, 0x4b06980b33ad6226 +244, 0x7afc1e940df03034 +245, 0xaa093355c596ecb7 +246, 0xbbb5100165d1445f +247, 0x599c0f30608a36d +248, 0xd35999534e29986d +249, 0xd0cae757abc97c36 +250, 0x9ec9f2c24bbe3b70 +251, 0x76b96e93352c2960 +252, 0x4dd3acf1c01ae06c +253, 0x71ebb829cb09312a +254, 0x3234f4c24cdbb897 +255, 0x9b0930936363bc6 +256, 0x2ede98b9aacc3672 +257, 0x7388672bfb4c92c8 +258, 0x53011e6a80763bca +259, 0x69eb6ca56f23129a +260, 0x59d98a723f847ad5 +261, 0x234af2de04ba218 +262, 0x589b028bf0830748 +263, 0x525da4a281c641e5 +264, 0x47ceb48568778c5f +265, 0xa2d73af3a884d972 +266, 0xdc6fab52b39bfe68 +267, 0x7f1a5e5ea6139484 +268, 0x70571bee802a1fa1 +269, 0x489f1d18d9c61c4a +270, 0xd781c38aa8aafbc +271, 0x5aa610ad2539aa57 +272, 0xd71a2a69974ae4a0 +273, 0xe4479465870487bb +274, 0xf714dacd7fc4475b +275, 0x5cb9c32e10d39249 +276, 0x746650ada73de1a3 +277, 0xbdd059359907cd53 +278, 0x38352adeaf41c72a +279, 0x330a370593019b35 +280, 0xc75ff9305bdaf3c3 +281, 0xc64723389b0bd56e +282, 0xbafccbf3fae88f31 +283, 0x3fc2c4b1d35da1fc +284, 0xd9414b4382f59e69 +285, 0xec31e6d32a58f7e1 +286, 0x4763fb9ad6cadb98 +287, 0x5e9817762a380e57 +288, 0x9a670c79b387ff5b +289, 0x467beb71ab258339 +290, 0x23cafda15a336768 +291, 0xe42ebf79e2d170e0 +292, 0xced716e4bbfe75ea +293, 0x1057597f33a23633 +294, 0x563d3fb59a847744 +295, 0x1a3f85cf84ea5e0a +296, 0x7630855876b41b32 +297, 0xb59e3eecb52851b2 +298, 0x26aed463d3769fd2 +299, 0x530d3898b8d043c6 +300, 0x28fa6b7cdc76ae94 +301, 0x99591569d7464343 +302, 0xa46da7d9e275579a +303, 0x30f6e5979a92bcfe +304, 0xaf345d66f7e756d6 +305, 0xdfad061213a92b33 +306, 0x2843134719ff646 +307, 0xbc8699b6d3f04313 +308, 0xacb08fbaeaedce6 +309, 0xe8fd50dc65724bc7 +310, 0x956d0436e93242fd +311, 0xa9c3e3eee8a80b9 +312, 0x9bf71b03710af171 +313, 0xbd61bd65edf3d9ad +314, 0x531b6865fc4f810d +315, 0x58ca69e7da1ea2f2 +316, 0x4946f99ec03e8adf +317, 0x3b9d4f48b1eb484b +318, 0x605be28093b8144a +319, 0xa7a4c6c8f2ade7af +320, 0x729f97c8057a21f6 +321, 0xc97d9d778a4e2932 +322, 0xc173b6c3d0c5168f +323, 0xd400c6f451c927fa +324, 0x611d96eb9e70ecdf +325, 0x3ad1a1709255cd86 +326, 0xf85d02d9fd5678eb +327, 0x495bd5eb58af79ab +328, 0x977bc4282d97381e +329, 0x9a5b1811cde9f133 +330, 0x49b2b9d26ba0977b +331, 0xf6c4e846b99bb87a +332, 0xc399d5f8661b0c8 +333, 0xaf9a91415ddeb79f +334, 0xb93df0259e6f3c5e +335, 0x80ad075b109611b5 +336, 0xf3004a806f25186b +337, 0x89a86842ef14b472 +338, 0xba53e5942ca79cdd +339, 0xc4cd49237032e3a0 +340, 0xb39700c89fc1109d +341, 0xc35fd5106aa40bf7 +342, 0xa0ff3091df2010c7 +343, 0xd4970cd890097774 +344, 0x39e7db9319a17976 +345, 0x56306e9316a184b7 +346, 0xe4d218267f28a145 +347, 0xbaa24a30caf53ebe +348, 0xf4811ee0d51ce11d +349, 0xccb9ece4a25b129d +350, 0x132b2d1c4f092d60 +351, 0x7d5e7a59f14dd113 +352, 0x8ed30762f02d3098 +353, 0x8a92bb806bf9a4c0 +354, 0xd1957618db32f95 +355, 0x3ae37701b1db294a +356, 0xc29e705f675713ad +357, 0x3d12dc6fc3dcc569 +358, 0x7bc096e1e2ca2e43 +359, 0xf58f4f816e71b16d +360, 0x23e6f93c7d0f1050 +361, 0xacaf403b80890da3 +362, 0x7a5e19bf92de04ec +363, 0x72b3638076a857e8 +364, 0xb87601882acb1f3d +365, 0xb51d157f2576ac70 +366, 0x7ef0c2f1ae02af0f +367, 0xd519f6224fb2866 +368, 0xe00a80d729843eab +369, 0x3c95b55c523d0871 +370, 0x81dcfef1772a151f +371, 0xa5b20337760a602d +372, 0xf36049e3e0f98eac +373, 0x21bc3e0f1083016a +374, 0xd8f295098597530f +375, 0x78a2582906003e78 +376, 0x1c5cf0f434493262 +377, 0x2228d56b7da9cc80 +378, 0xc3d7eaedd0f36349 +379, 0xc9ca575c3b6dfe54 +380, 0xb5f03d2d974c91b3 +381, 0xb2f7ce70c56a865c +382, 0x98f33d64e66602ec +383, 0x559904911cb8b69c +384, 0x19c426ae3d196913 +385, 0x818fcd24869feeec +386, 0xf4c52f4b00f4295e +387, 0xbdb808d5fe34cb3f +388, 0x5014922c0ca80ee9 +389, 0x9f7e4c8068fb96d2 +390, 0xec99128e620a2df8 +391, 0xfcbb4fc594857a59 +392, 0x6aebf62bc7c79e4f +393, 0xde8cba80e35ed831 +394, 0x55bb9ced0fcb6fd7 +395, 0xbe7534a18c050ef7 +396, 0xed2e6d1767c7ed5c +397, 0xc88e18ac1064dd88 +398, 0xf71fbae1105d8324 +399, 0xb4431f0a4b807ea4 +400, 0x78de56556e1272d7 +401, 0x34d3e7e84ceed376 +402, 0x72f0ca866b3b182b +403, 0x4747a9b5faaa6dfe +404, 0x5a0f85d879e90288 +405, 0xbecbea458ec061f1 +406, 0x5e0bcff71b1911e3 +407, 0xc2e32dc60548a6ca +408, 0xfa76a9a3d449b8c2 +409, 0x81303b7e225dea8b +410, 0x4aa42b413ca5c63c +411, 0x4d7372d31df5b70d +412, 0x2a408f03bb0499d1 +413, 0xd75529b610d56d9c +414, 0xa6e9d1356654ffbd +415, 0xe10bdb510c440754 +416, 0x8fce6a25abf05e69 +417, 0x21aaf272093d6081 +418, 0xcc18cf69f0f0b2bd +419, 0xbb4e0a1cda31a035 +420, 0x70128e6522fe238d +421, 0xaaeae87b79d223da +422, 0x6882e6705d12bc8f +423, 0x8e110abf1ccb274e +424, 0xb7ebac3cfca55a39 +425, 0x909705e2a6e584ce +426, 0x3b54f18e8f7708cf +427, 0xcac28674d5caa98e +428, 0xdde0e042ad4107a5 +429, 0xfc2ca3a740f903ac +430, 0x9aae84ca64051770 +431, 0x858a0d2d879442e +432, 0x75b3e7d29e357b39 +433, 0x9f6f5487d5ec5ac1 +434, 0xfd95986f2765eed4 +435, 0x2899b60770693140 +436, 0xb8ab9650b7300ee8 +437, 0xaa772209ef643b16 +438, 0x9c98fb4b5946fc61 +439, 0x6f614d64e4a38b84 +440, 0xbe0099b53347a13f +441, 0xe8d05eabf7db8a0e +442, 0x4c849670c59692d5 +443, 0x421d2e32838ebba6 +444, 0x1fb1f7427466dd6b +445, 0xd79d9987fd12fa15 +446, 0xc195d5fedaa613c1 +447, 0xfecdf6c6fb6c4924 +448, 0xd8536233459d6d65 +449, 0xaed30f22454f593c +450, 0x14d427078bb818c1 +451, 0xf7235f42e291617a +452, 0xb1fc436bdb2efb83 +453, 0x21cc3fd0fb82e07b +454, 0x2df968f572e077bb +455, 0xe1b76c513528f8c3 +456, 0x955681442083db83 +457, 0x2e009197f295008c +458, 0x2c258d6b1935587a +459, 0xd10fda2d14ce8e70 +460, 0xd21cdc7f5db09825 +461, 0xe39168a7b3a080cc +462, 0xc82c2a353a812026 +463, 0x6adc63d4bb7f26b0 +464, 0x5d2acdd2deaed807 +465, 0x47c39719b79aee01 +466, 0x5b6351daac993e69 +467, 0x1e2d2cf25d029df +468, 0x671c43218ccc62b +469, 0x783093122682b9c8 +470, 0x8055e091219d2263 +471, 0xa6e7f6bc43717757 +472, 0x91855fe232480a87 +473, 0x554030e74824042 +474, 0xd0c14f8ff34b1a30 +475, 0x13aa852fdea8bca8 +476, 0x27ed292b1a4fa598 +477, 0x3e56548b7095af08 +478, 0x47432aa82a4bfcfc +479, 0xadddde35537dc4c8 +480, 0xadb0d103d29faa1f +481, 0x14818cb71d4cdaf9 +482, 0x31507bcc3d46a5d +483, 0x7407577173399611 +484, 0xac03706bbe4da972 +485, 0x4efb0cae8499469c +486, 0xc6d4bcbc4396a20b +487, 0xd7581757d38762c3 +488, 0x6308e217f7e69120 +489, 0x6931392a2fcf3756 +490, 0xb5a5b36744f09886 +491, 0x8da8292d0bf2ed08 +492, 0x13e0aa8d5a24bd3d +493, 0x1131dbe7a2b97139 +494, 0x2098efd4a1e7108c +495, 0x9c470e15e690e574 +496, 0xe60e3aeb65560eb8 +497, 0x4ae5444669ffc65f +498, 0x911fc7e6820923b8 +499, 0x25b3fbb125c1ae19 +500, 0xa8b6c812471f37f0 +501, 0xe6d9aec89655113e +502, 0x59d24e18c48dd532 +503, 0xc9b320756e0d6c35 +504, 0xb70a2316319c8e2a +505, 0x328a0b16ff39152c +506, 0xc2088e4c8a3298 +507, 0x10bce05ac0971264 +508, 0xe26b5b7655fd4ad5 +509, 0xfb1d818177211481 +510, 0x98d83c41a7196f86 +511, 0x45801b77072aace8 +512, 0x563268328ebfb870 +513, 0x4d26e320a51123fa +514, 0xf531c63a3438f527 +515, 0xd94525fda256c193 +516, 0x883de65d7957b025 +517, 0x7be095e05de1599b +518, 0xd27792977b3a11dd +519, 0xfd179d3c4a5f06fe +520, 0xfbe066b302e09da2 +521, 0xb841424fbd2c7249 +522, 0x566dc3e3f2345fc1 +523, 0x14e8cfa0ee0ab392 +524, 0xf1e11e1841884ad7 +525, 0xc895b028b3b7df26 +526, 0x70f727baee1dc909 +527, 0xc2f4bcd3f8c7905a +528, 0x6d294a99118f9f47 +529, 0x18a723a0ddcf902e +530, 0xac36efa0258143c4 +531, 0xc558a61c40490895 +532, 0x430341fd196a18e7 +533, 0x27fea5b52f4178c7 +534, 0xd0d628d45d51e088 +535, 0xc016cdc47158510a +536, 0x925a6cdd446f0555 +537, 0x5e5a30a2f1d9bd08 +538, 0x918ad9cea082da5b +539, 0x23bb26bfaa0e79d8 +540, 0xf667bd79197706ca +541, 0x9ae3d6e8290fa1d5 +542, 0x20a15e60e0007e64 +543, 0x7d88beb1713a320b +544, 0x2d8b1728e392a6c3 +545, 0xb4cc0ae2c22afad3 +546, 0x749fe3524435e61f +547, 0x137bc8f57e7060a3 +548, 0x8070ee0def7571b +549, 0x2d5cacc36c121329 +550, 0x8408aeea38281006 +551, 0xc05e54af2206ce49 +552, 0xd547b24a26ebd3c2 +553, 0xc66d83645d95b57d +554, 0x8f4187e81ac31f25 +555, 0xe2878187a7ffa7e2 +556, 0xf7802760e1a8b9e9 +557, 0xd7f135ce1d83b5d +558, 0x4e2d5eee2bbad34c +559, 0x9b73503bcada0bcc +560, 0xc3fb41b2fdd2b56e +561, 0xc5958ed587dca76f +562, 0x1029b90ef3fa1e44 +563, 0xeb52236cba057b2f +564, 0xd411396dfa523c6d +565, 0xccb05527609c690f +566, 0xe73e27fd2c6295e0 +567, 0x363628b4f2a7bd3a +568, 0x443bcaaab9b67c72 +569, 0x1142926c0ff02a91 +570, 0x6d7fe0d6fbcb7265 +571, 0xea31775a5191e8a2 +572, 0xc44a633ed2339375 +573, 0x261bfdb83fc7a23b +574, 0x4cb967260869e0e7 +575, 0xf3b7134ffac658c0 +576, 0x97b266a6b95e219a +577, 0x18a5be54082669aa +578, 0x9adbdbfe1ad667c +579, 0x6fd02995faae35b0 +580, 0x9e62832c534ef39f +581, 0xb89e8229d7a85aec +582, 0xa46c8670446a0539 +583, 0x6960eeea3b3a4c70 +584, 0x27901b708cbb4f97 +585, 0xde1abdbbffa9cf6c +586, 0xcadb304d56e1ad33 +587, 0x579b5110955d30c9 +588, 0x77b57f59d61ebdbb +589, 0x900adb153a8037c0 +590, 0x1f5200f1f8be5a4a +591, 0xc491a76e1cefe1f1 +592, 0x6724370243b5d0c9 +593, 0x6cc8e3b9fbb98c87 +594, 0xca1722c5183b2b57 +595, 0xe9a61a3f20c59fec +596, 0x91723ba5418ed1b5 +597, 0x4299a43bd28daf49 +598, 0x8dc266e15f1f32b1 +599, 0x91a22c16ad09703b +600, 0xfe36e6cd32ebd06c +601, 0x30c0d9f9a60a11ae +602, 0xfad538e8bf1a0f03 +603, 0x47c2a0261dc808f6 +604, 0x9148743d0cdc81a +605, 0x17c3f4257197c037 +606, 0xdc8b06b5220c01a7 +607, 0xf9ad586eb09e30f4 +608, 0x702600c123b400c6 +609, 0x9218eef469b0db7e +610, 0xce16c9bac0969bb4 +611, 0xa758408742a37457 +612, 0x2eb094509e812e4a +613, 0x28440b87ce1e0e21 +614, 0xab48eb01ee07e56a +615, 0x85e69345a3649100 +616, 0x517927d4a415e569 +617, 0xd02de9b703206f93 +618, 0x5cae9cf67b9d62a9 +619, 0x8b0e1e0c2623250d +620, 0xce893eb84c72510b +621, 0xd97bdcd1e00f8c3d +622, 0x106c1721a5e8546 +623, 0xb4fc0554e61e059a +624, 0x5fad1bc4c54c3136 +625, 0xd09dc05514ba4ad3 +626, 0xc934e2153df00372 +627, 0x3cff94fa0fa2967a +628, 0x4e7ca152c113e934 +629, 0xc5ccf2350fb82ffc +630, 0x10aa453d349b70df +631, 0xf8270070253de14 +632, 0x412b14bc12ef4538 +633, 0xaf83140fc27938c2 +634, 0xf342d1c8c97c7e74 +635, 0x693b4b07b79cfdc2 +636, 0xe859c76fde1be4aa +637, 0x90ac4aa1c012a971 +638, 0xeca381124c9bf23b +639, 0x1f544598d356ab2f +640, 0xbcd78485f20f8339 +641, 0x6b8eb4bf854dcdf5 +642, 0xdb231419a9323609 +643, 0xb2f0167ca051a61a +644, 0x9806e89e8d3ebd15 +645, 0x69ce87797a14c206 +646, 0x143ecc33c23e61f5 +647, 0x3be37d8fbcfc396f +648, 0x2a4336f50c851387 +649, 0xe665ed14a40c6400 +650, 0xc229fc93c03a6a24 +651, 0xb7f27088c74af74 +652, 0x8a8da4fbf5fb90a6 +653, 0x8c54684d5db6a600 +654, 0x11ef0e952c8ad4ec +655, 0x928a518e677b87a6 +656, 0x6b6c8ebe9db7253e +657, 0x9feecd8eaf8a8101 +658, 0x4f270f30f3ad2d0b +659, 0x23798146bff58d75 +660, 0x7d9134e4005b9246 +661, 0x18b5eb6833bb921e +662, 0xff0ef41f6c734814 +663, 0x388b18f678774f4e +664, 0xa51646467be5785e +665, 0x9f96bbe291c9361 +666, 0xce39cac00148c7b1 +667, 0x69d41ab8914f944f +668, 0x579ca60b75dbf4e5 +669, 0x352f2b89c968d81 +670, 0x181d45a561c05553 +671, 0x5a6aeaa048d6a494 +672, 0xd7938433b99408ca +673, 0x13bd6696806f0800 +674, 0x2ca8e35e87037dbb +675, 0x70d9d33ef79088a1 +676, 0xcdcb45940c9ba3e7 +677, 0x2546f21a69a29dc +678, 0xc674c5afa1f9abdf +679, 0x856dfa52fdff93b5 +680, 0x614b66daa02187bb +681, 0x55ce165aee2e205e +682, 0xf34d6cf856f941e3 +683, 0xa4a0ec51b4f25b25 +684, 0x83e6bf89bfe39762 +685, 0xb559b9a68edf3381 +686, 0x9259778b54c31479 +687, 0x4e4e21e81138cacd +688, 0xbbb990cd25c2fb2d +689, 0x38a85ad84d9e31e +690, 0x5b4f4081ffba398d +691, 0xfb12eb300dada910 +692, 0x6975328f3eebcb34 +693, 0x3db017218a6478f0 +694, 0x9397aca7eaa5de14 +695, 0x6f7318d0d9ffed6 +696, 0x40cf276103c34010 +697, 0xeacef8ae2095ec8a +698, 0x80f7593e9ddaa152 +699, 0x8d4bc01f7e5c6520 +700, 0xbbc9606e7518e199 +701, 0xfe71ef90abbaca29 +702, 0x528edfe3e467ed43 +703, 0x52b322c36f60627d +704, 0x9946be5ea3beac73 +705, 0x890745d71a02c404 +706, 0x5570d1bde8bb7993 +707, 0x563fceeff8466dcc +708, 0x62a9ca23db6e4d62 +709, 0x89d6038410c92e8 +710, 0x16bc3b1ea7b90a89 +711, 0x12ff3e9c30d8dde6 +712, 0xe78cb53e8dd40a77 +713, 0x643722181b85d5a +714, 0x73e26524635d78e3 +715, 0x941ccfc41d47c53b +716, 0xadbedec82c31e57c +717, 0x2addd39e7a36aad6 +718, 0xe64d81fa432bb65d +719, 0x1e2e63d01399ca82 +720, 0x760a3c0edbbef3a6 +721, 0x801131e88419a79c +722, 0xa2a75136213dbb6 +723, 0x83e576905753c3ff +724, 0xdbbdab8007c4ea0 +725, 0xbb73b13358898c2d +726, 0x5818372d8fe036f7 +727, 0x3aa052cd647e29d1 +728, 0x235219635ff4abb6 +729, 0xe24e07311fa76b65 +730, 0x4967574b62c3efb8 +731, 0xb04b4c210022e795 +732, 0x3d48e77713ef3fda +733, 0xf4ec1050775fd3b1 +734, 0x38953c604d35190d +735, 0xf731a6450c1e23fe +736, 0xac66ae73ecc6b9dd +737, 0x442e2bcbca5bbaa8 +738, 0xa74a741bd02570bf +739, 0xa85473cbf3b4c45e +740, 0x24d43199c69cdda +741, 0x59f78fa87f895d36 +742, 0x78f5513621dc1813 +743, 0x226c2606635698c9 +744, 0xea39babbad3df384 +745, 0x2f178b076f08f80d +746, 0xaee482470bd9acb5 +747, 0x48571d8c4235c1f6 +748, 0x6569395eec2df1d7 +749, 0xa9b7408c1d67a372 +750, 0x3b9c5ba01aecae9d +751, 0xb047b26325765767 +752, 0x9bb1968c8b6149d4 +753, 0xbba4038fdd341986 +754, 0xc1d23b5b89beaa88 +755, 0xaa9a341db334c8ac +756, 0xaa9337dd1fddf923 +757, 0x9fdf160ed939d68b +758, 0xbf48cdd432d0f148 +759, 0x2a01743f1f7b581b +760, 0xb68d5c631e9fb70a +761, 0xe9ab844ec026cc7b +762, 0x1fabd46f0d5266f0 +763, 0x29e53ae817eec5b +764, 0xeffbebc07500ad4d +765, 0x432ae3b596c1589b +766, 0x48d44f3895d6dc23 +767, 0xcc3a5576e24ec2bf +768, 0xc8f4a042462e95d9 +769, 0x24c12cd6ef57b6 +770, 0xa7896ae26675f69 +771, 0xb98a1790d429c90b +772, 0x71f7ac96dea8ffb6 +773, 0x7878c64cad319f72 +774, 0x65586d63156e1a05 +775, 0xa70ef198e61e2a11 +776, 0xf5a84f622d490449 +777, 0x7789e1c1927e82c6 +778, 0xfe053fdbb586b8fd +779, 0x59a94b735df951c3 +780, 0xdf5e72909ff2bfbd +781, 0x34dc2bd8876a92e5 +782, 0x7e408900bfa3b282 +783, 0x844176cb62d5008b +784, 0x7406e9e156cddc9c +785, 0x6a6d87de33056193 +786, 0x20c388365359e4c +787, 0xdbda2eee6499be64 +788, 0x3574cf8bc4840b47 +789, 0xc2d904ac50e44ee3 +790, 0xb9edf042b0d96102 +791, 0x2ac087f3922dd11e +792, 0xeaf244df29c2a8ae +793, 0xb4243528d8d0649c +794, 0xed67e39d9217e6cd +795, 0xcbdcd1620727437 +796, 0xcc00dec8485d0dfb +797, 0x2e5411679d89f548 +798, 0xdd355c299c05131e +799, 0x6fc81e1e9beb2c8 +800, 0x205ac04eedc0085c +801, 0x8bf73a08c5240640 +802, 0xec6f8daf06673cae +803, 0x6e29f78f0a59638e +804, 0x8c530fd613aeccda +805, 0x58b99ce19626ee04 +806, 0xb16f71c11f209bb9 +807, 0xea1d7ee0e82f9146 +808, 0x5641482551d357fa +809, 0x13fb8eff6efa4b89 +810, 0xca4bdfac87e46ce0 +811, 0x9e2babf08f33b6ad +812, 0x482633792e270729 +813, 0xd5c17bce83e146e9 +814, 0xf8df8169c7ff4df6 +815, 0xad974ea8b3bb7e7d +816, 0x8ad356322d6c0a26 +817, 0x5ba5a24cff70d235 +818, 0xb604ea125e469d44 +819, 0xecb90d0ca42445d9 +820, 0x9c499d3f441e6eb3 +821, 0x2aed9e67fc701d26 +822, 0xb3476334028bed9 +823, 0xba079723415a89fd +824, 0x8684b0e124ebd181 +825, 0x6effee2741402b37 +826, 0x15e734115d68f8a4 +827, 0xafc15b8a9fa93205 +828, 0x9749e35360fcd91 +829, 0x8ffbf6ba4b02bacd +830, 0x2f107b6a820f44ba +831, 0x230cdb06c5f7422b +832, 0x2149918883f7c858 +833, 0x3e8eb9dbfb832b71 +834, 0x871f0b4369d3dbc3 +835, 0x3553e06132e55fa4 +836, 0x1ec19fd1ce7a5823 +837, 0xf3908fc23446b3a2 +838, 0xe300b55305c8d7f3 +839, 0x61e4ab3372dce7dc +840, 0xb50f68be3632604f +841, 0xd6d2993fa6d155b9 +842, 0xf9c8d0fed0c90246 +843, 0xdd1b49530387141f +844, 0xd1db9818546e095c +845, 0xb91885ccff43ee8c +846, 0x8d704dca3b7fdb63 +847, 0x8309c9077939df4 +848, 0x6536739d7ae608f7 +849, 0xdab8a503cb9b94a6 +850, 0xc504248b8f69f733 +851, 0xb0ccfb81eb67e3e4 +852, 0x45ac4f949c418493 +853, 0x7763a70137c01376 +854, 0x7f08d6362b17c470 +855, 0xb190bb422946ad46 +856, 0xdafe7dfcb0d71320 +857, 0xec415ea4c54398f5 +858, 0x5955b81204c5657c +859, 0xff1f983c56d6d7cb +860, 0xb25b4a0de0bf393d +861, 0x3a90222bef45f3fc +862, 0xf0eb0903e3695f44 +863, 0x405ecabf26817b33 +864, 0xccf01a062f2351eb +865, 0xa62a5f63e31545b1 +866, 0x673d1baf237668d3 +867, 0xd15db3cddfb0a161 +868, 0xa8adebfc9b5351f6 +869, 0xc297fae49f0b2d08 +870, 0xe5ed1156ab569225 +871, 0xf4aa4bab70aa8c11 +872, 0x8e32dd1eb44c6363 +873, 0xc7aa250f1492e86d +874, 0xc645795d705914cf +875, 0xfdd8a48c0fb81c53 +876, 0x6ad1401f539799fe +877, 0xa157e71b6bdd4254 +878, 0x4cc09814465a6c9e +879, 0xed1f66bd824e39ec +880, 0x6b74f7f6f2d4c16b +881, 0xa3391c0100010ae4 +882, 0xe0f384530c0e7eb +883, 0xf6aeb9f0d64c7159 +884, 0x3d7f6bd980e07a17 +885, 0x8b4e1bd3e782ea4e +886, 0x7b005009d95b7d38 +887, 0xf43f001d5e7326c0 +888, 0x16600ff7361a1721 +889, 0x13778aceafd72087 +890, 0x85d3359c37907c58 +891, 0x7374f768c968d0f +892, 0x2373d89b9b8f9e9a +893, 0x21a3fe7e4dc5cc35 +894, 0xb02abcad4f4ae60 +895, 0xb9eb579582666e3b +896, 0x9c12186973b91695 +897, 0x1bd25ac6911295e7 +898, 0x9f5a90e0fc16ffa2 +899, 0xe3e8f10ce7fbb9e1 +900, 0x5867e566887d2d16 +901, 0xd569aaf2ffead057 +902, 0x678359b93dfd07f1 +903, 0x9fb73a4f1b777d94 +904, 0x5c6b0bcc70df3a54 +905, 0x66fd71a67ed5e59d +906, 0x62f21a6fe936b212 +907, 0x86922151e4b251c4 +908, 0xbfdee56cdeabe8bd +909, 0xbe3bc7c4c2380ffc +910, 0xd09ebebb0e786d49 +911, 0x4951a83005aa22de +912, 0xc1b7da6cf08630c4 +913, 0x8b294b5fef04b0af +914, 0xaca7a47f7fda4d5f +915, 0x70bbddc64b4b1a91 +916, 0xad306a764087085c +917, 0x19b9f11c14adb74a +918, 0xbf1a7d2c83fbbbe +919, 0xb78da8a53fa857 +920, 0x5b614c5060a543b7 +921, 0xb6f32557404d475f +922, 0x9fc53dfe5281f084 +923, 0x43ad9d302c10a475 +924, 0xa4575be2c10fbc13 +925, 0xe58c4c02d5b2bc8a +926, 0xaa838a3e5a16bb55 +927, 0x95c39373858011e1 +928, 0x17a6be18c1801fa +929, 0x835e6c3d99898c27 +930, 0x9af26334bd726505 +931, 0x7addf56712a22afb +932, 0xf619281f6d4d37d0 +933, 0x310c6b1e29ca7eaa +934, 0xe8106bbe1ea0f3c9 +935, 0xc89add421cfe7bb9 +936, 0xe01b7a6885180236 +937, 0xda8cd608ee0eee61 +938, 0x3bb2f5f40a8f4880 +939, 0xd434cddc85946350 +940, 0x6390806f8d1465f +941, 0x2a5f0150c8362cf3 +942, 0xcc6980e968b75f37 +943, 0xd86756899b2c95d2 +944, 0x95ab76b54f439605 +945, 0x1e0d6f6a99569ffc +946, 0xd47b20b72c0f02e3 +947, 0xcd9fff1462fe8a25 +948, 0x71867c57f009bc8b +949, 0x85238c818139a22b +950, 0x58247991b6447ce7 +951, 0x3b41a627153bcc9f +952, 0xa3ddf05f18153e13 +953, 0x21a3d47762fbdbe4 +954, 0x8ee55f20e5c5b14 +955, 0xc3ed8e23589b365f +956, 0xbd12efde1b5e8afc +957, 0x35b81175f738edc8 +958, 0x16b2627c28c952c0 +959, 0xb16a5009047b002b +960, 0x5e4c769bd80bed26 +961, 0x96174863aa73bf6b +962, 0xb3bfe6a2d7d05881 +963, 0x5c0a1757302c3fb6 +964, 0xfcc52e2da058ae67 +965, 0x12b26055c0ea26e8 +966, 0x87d8126b14b8417b +967, 0xc87745c58eaa597f +968, 0xb38b4b4b579ab55 +969, 0x559ece2bb0ca0b32 +970, 0xecbf6af7914a6435 +971, 0xd994b534e3f46c42 +972, 0x67301d5555cbaf1 +973, 0x4b2222c098aecb6a +974, 0x2f1b7acadaa10ffc +975, 0x4c48c65a542d56f4 +976, 0xf3fbde71409cd64c +977, 0xb32e3ef1dc24a7cb +978, 0x229321ce5bcd85 +979, 0xcad7e7dfee447d7a +980, 0x7fddd28936d166a5 +981, 0x928bfb0027da2715 +982, 0x97b17752c6aaa82b +983, 0x3eaca529c941d7c1 +984, 0x91937555520265e +985, 0x8e7e5c3786ee3588 +986, 0x27162348b08a9aca +987, 0x302165a3d76eab04 +988, 0x94111b7672c6bd95 +989, 0x7a471169035fc35a +990, 0xe850ed94b0be86e1 +991, 0xf7a3721d6c85c1cc +992, 0x6727a68e16268dfc +993, 0x65433e82f0e19d29 +994, 0x6109fd616c977544 +995, 0x7068ef83a29cdc70 +996, 0xcef2deae0fccb574 +997, 0xee2a2ee021a6ad5a +998, 0x5195005fba78706c +999, 0x31364d630d333f34 diff --git a/_randomgen/core_prng/tests/data/xorshift1024-testset-1.csv b/_randomgen/core_prng/tests/data/xorshift1024-testset-1.csv new file mode 100644 index 000000000000..661b157b155a --- /dev/null +++ b/_randomgen/core_prng/tests/data/xorshift1024-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x2968fec4616d9509 +1, 0xe82b10da7bd80ac4 +2, 0xa876e84316e70643 +3, 0x888c2d982b27d7ea +4, 0xd47d3d65778ed02f +5, 0x25af25e8c1c544c9 +6, 0x8e6f9814c92f661b +7, 0x3e71ea4e4046b05d +8, 0x9e1b58fa0207d9c0 +9, 0xc0393d91a0decbd +10, 0xd47df476d2f67dd6 +11, 0xf8a1b120acb29876 +12, 0x54d2351fff4b408d +13, 0x9321d56bc4bef94a +14, 0x12cb604007aac05f +15, 0xdabe30bab4e9a876 +16, 0x31962560988e567 +17, 0x53c8c00896fb249a +18, 0x9168b213fa8b49d2 +19, 0xe826ed57af7757c6 +20, 0x44084ca88c61d0e1 +21, 0x8a447ca13984034f +22, 0xea56bca7496a1192 +23, 0x38e40233ed1cbbdf +24, 0x826a5efdb65df22 +25, 0xe08ec869c2a206ad +26, 0x20bf847ba6e1475c +27, 0x268e99dc93ac3518 +28, 0x214e2263efcc56f8 +29, 0x4e62968a99e00539 +30, 0x2a12a52c634607b4 +31, 0xb0341a4f4a44ee46 +32, 0xaef66935a23e89bd +33, 0xe73d009165d10070 +34, 0x9d29bca8937c1712 +35, 0xac3450f789a44382 +36, 0x443eaafc99628e70 +37, 0x48609ba2fdc6814a +38, 0x6e01d53af8a01099 +39, 0x1b725df253d832a0 +40, 0x68ead3c52c36b98e +41, 0x36ba072b471d0dc8 +42, 0xac1fb808b1d93c3c +43, 0x2c36d9080979be7d +44, 0xcb9b374317b668c9 +45, 0x3c960912b44d56e +46, 0x657454550f8d9c1d +47, 0xbf072badce6c2737 +48, 0x6ee018e5c5cdd2ae +49, 0x609301623d936f60 +50, 0x35b40c58a518a941 +51, 0xf7d24a9c7d57564c +52, 0x7e4845b8f0374310 +53, 0x2a8223e03ac4cc2e +54, 0x1dc81758070ebd3d +55, 0x1320cd7c3abce6ca +56, 0xe95f5f03abd4731e +57, 0x90b6a7ee72f350f3 +58, 0x55e452037c949ad5 +59, 0x78d987c7609b326f +60, 0x9bff2e52746449e8 +61, 0x72cbc26a9b57c406 +62, 0xb8959ab6826ac35a +63, 0x59fe539c62ff9483 +64, 0x8c4cde1d65563241 +65, 0xe95ac9f2113f1be8 +66, 0x2846aa0dff366b9a +67, 0x39c3e61f5dc795cf +68, 0xf2b9b55af6b6b5b0 +69, 0x733951a107450c51 +70, 0x936dd0f66530a3a5 +71, 0xd55b63e0b5b6ae46 +72, 0xaa1035d6d371b80c +73, 0xf4f3719e466df564 +74, 0xece7d9e23f0a45bf +75, 0x95934ea577a81777 +76, 0x976a1776f73c1dac +77, 0x18029546eafd78b5 +78, 0xbb3ab35668fd6e65 +79, 0xb6915972b96a5b95 +80, 0x850ad09ba84b49c0 +81, 0xdb4a551245fcd15f +82, 0xbc2d21640007eacf +83, 0xba298f635a1645c2 +84, 0xa4aa6afabb88bb5d +85, 0xebcfc388cf8b1367 +86, 0xef6be3c48d331077 +87, 0x19132af4445e429d +88, 0x2f76a37bc0e45ced +89, 0x13f96ad00878df48 +90, 0xb8fdad62c4f0c365 +91, 0xf95de6a5528ec985 +92, 0x481aa24b342ffcfa +93, 0x132ccc5c3747112c +94, 0xb196b0efd2d09259 +95, 0xcf62746a3bcdec2c +96, 0x996325bf949590b5 +97, 0x305700d04fa07df1 +98, 0xaeab52bb4902e669 +99, 0x80068435ef98181f +100, 0xf3246828280d675d +101, 0xf59f61b26f5caffe +102, 0x15b7df7abf1d8759 +103, 0x3ff43423d8680a02 +104, 0xafbaaadfeb8ec37e +105, 0xf8be84cb4cbfedbd +106, 0x9e797d3b952a645e +107, 0xb9ff208124efc7a +108, 0x2e2ea03051b1d3f4 +109, 0xf059946cd8062ef5 +110, 0x5dfaa02e1c1c33a7 +111, 0xb938008377468bc2 +112, 0x29bd7ba26ddb5cfd +113, 0x8599e95956955b5b +114, 0x9674aa92fdbbaf2b +115, 0x6927290eba39179b +116, 0x48a4b594b063fc01 +117, 0x12cb99682cc95ca8 +118, 0xd0198db4fe06e935 +119, 0xe2efc92564cd6d78 +120, 0xf29e3401fe800978 +121, 0x3a45b04622a1918d +122, 0xc7d986f6cee748a +123, 0x18fe46fe75a1d8b7 +124, 0x94b0e9c83192d269 +125, 0x381890e6c4a10efd +126, 0x42305bef9a1eb0e7 +127, 0xd2e8f910b5a96bd3 +128, 0xa7343b2938ef16a9 +129, 0xe432fca6a883a22c +130, 0xd923cd3bb0c77a46 +131, 0x771440156f17d440 +132, 0x3a103372ad5c822b +133, 0xd65317c76a70e0b6 +134, 0x6bf5a7df9ddcbbea +135, 0x8a62bfb4bd7ee1cc +136, 0x14c564aeddaa9842 +137, 0x111d23185c329a25 +138, 0x80066727b94859b0 +139, 0xe76f847614409d35 +140, 0x61330b492b389f64 +141, 0xde2a98a5a181fb20 +142, 0x50ffc4f594291ec0 +143, 0xe766de7529bff4a +144, 0x440629959a350415 +145, 0x6e6f7cc6e501d547 +146, 0xb31b8eb4db5cd9e5 +147, 0x32e8e659bbfa3651 +148, 0xa3bcfee564006c60 +149, 0x71563f2f89f0da28 +150, 0x83dee9a700a53a62 +151, 0x4f3cf79d558883cf +152, 0x6a3f3d752b3ef555 +153, 0x92582ef4c19a74da +154, 0x6dd33c13eb4103a2 +155, 0x63e7310213e9f7fa +156, 0x9ce3c17c6b9a076c +157, 0x5e3f2d4d07b42014 +158, 0x109589489e174134 +159, 0xaf51d807c1140a71 +160, 0xd5223c84c2425bec +161, 0x6ba4d7869f4259b3 +162, 0x597067c2bfcf3489 +163, 0xf9c59e81f49883a9 +164, 0x5e4a60775ded4b74 +165, 0xba6535ab12b07bf4 +166, 0x9922d0b7a853d36d +167, 0x9059571a67c9bd7a +168, 0x55c0b45bc5687a44 +169, 0x22b726e1a977463f +170, 0xd3467ec3e6888b9e +171, 0x420d1f2b5a3db74f +172, 0x87ac3bbf7ead0f24 +173, 0x6eefc0436f3199b2 +174, 0xe862c445add78a8f +175, 0xe2408382341cc1ef +176, 0x759152fe96db65ae +177, 0x58a46b8ee63f95f5 +178, 0xc2b639beacfb790c +179, 0x50f35b69ec430636 +180, 0xb565cc1acac8a8dd +181, 0xe2a379d5edc2ff2f +182, 0xd0abfb8ff3c76c0f +183, 0xaacb26508bf52c62 +184, 0xece254ff3e0fdb97 +185, 0xc41bf846cdd6b3a1 +186, 0xef03f2c371e3a12b +187, 0x1ce74e57ba14f001 +188, 0x9b5dc37c48907b32 +189, 0x6312b7a3c0e0d71 +190, 0xde51fea867eac892 +191, 0xa09af6cd2a5e2703 +192, 0x173416b34c78e921 +193, 0x892a28ab1909ba26 +194, 0xc77a69b6885a8f89 +195, 0x3d508e62c2feee2f +196, 0x5119ad966235eea2 +197, 0x67f0222ecb886bea +198, 0xa9c1bdae30c4e60a +199, 0x2d518b070541cb10 +200, 0xadc88b8fb3d0345b +201, 0xaa8e0549c3d8081a +202, 0xf6922301b0234292 +203, 0x57c61f02f871f052 +204, 0xb68b57425ec40f26 +205, 0x64e6bc6cdeb78a38 +206, 0x1dc5e9141a3e0118 +207, 0xdb5c616c4b112874 +208, 0xccaa45b96144a599 +209, 0x3c2570670361fba5 +210, 0xab63b1345fee697a +211, 0x2cbcf6518ca555f5 +212, 0x4b84780b234494f3 +213, 0x934519ac136d696a +214, 0xdf19065ede5d9033 +215, 0xc4f240f01a18c940 +216, 0x51799f4eb478267e +217, 0x22bdaa06e7ced71f +218, 0xc42a003cdaa32e09 +219, 0xa3746906fac5abc8 +220, 0x6ff7b8a74c61d8cc +221, 0x48fa29ab00d2e849 +222, 0x1409a2bdc81c923 +223, 0x50d00ad328c1fe85 +224, 0xab79bc5db01d9a6e +225, 0x3fbcfd2cebabc23e +226, 0x1814a2065f9efbcc +227, 0xbeaa8ece82351ba7 +228, 0x391ad79ff0512dfa +229, 0xad5babcb6318a0a5 +230, 0x2cf1ae641d54b7c5 +231, 0xca32becbaabf2e9c +232, 0x8ba3d47914242362 +233, 0xf1a764b81ffcf79c +234, 0x91f20f4ba933dbbf +235, 0x88ac060061f0363f +236, 0xda21e847fc8e1aab +237, 0xdc7f4d3e6cf0baa6 +238, 0xd85c1d81dc96ee90 +239, 0xba23e43a6b5051ea +240, 0x90a0939eea412d8b +241, 0x12ce33d77b029fec +242, 0x5fbfb6a87d6357d2 +243, 0xa7597dd027f65afb +244, 0x8ebb6b8b8b185239 +245, 0x45e89426a0d04436 +246, 0x4a5383818bb40ec8 +247, 0x919b5b80a43bda4e +248, 0xf9b8d22461280026 +249, 0xe13ad8f7ab5ee8f3 +250, 0x39c8d72628967129 +251, 0x6de22f7a2fbf9e40 +252, 0xc6c5744d174deb7b +253, 0x626e5f3a50df3c90 +254, 0x62f8e30ba24dd13 +255, 0xd72dc4febe774cf4 +256, 0xd200b1afb0a73c25 +257, 0x65c7563901c2fc64 +258, 0x30e9818e85515f7c +259, 0x8643ffb0bb71293a +260, 0x3abe1c4ea7de258c +261, 0x45084bb1f370c75e +262, 0xed89ee41dc8c95a0 +263, 0x99bb56fb1279d194 +264, 0x217d6c46d7d50ea4 +265, 0x42dae06f1ca3c2be +266, 0x3103af8d85ea50a8 +267, 0x7cbd22f30fc047c +268, 0x9b981290c7de08b4 +269, 0xb0d2dbe062abbbfa +270, 0x2de6fdb8df120a87 +271, 0xffd5f46e69d4f755 +272, 0xee735a0f05dc71fd +273, 0xe079ecc2224d9a64 +274, 0xbf400cdc00cd920d +275, 0xa2757efb078c65dc +276, 0x3a0d632515afc842 +277, 0x164dfab63dafc317 +278, 0xcb7a3131d97eaa24 +279, 0x3ce938f6a615ad07 +280, 0x8e23c8155a33858 +281, 0x26ffdf8d6b4312a5 +282, 0xa73c99c8f5a2efff +283, 0xb622fba6a1cca389 +284, 0x933a270fee14587c +285, 0x97684114e2320ae4 +286, 0x585ba967f0b16324 +287, 0xb0b3306cd44abac0 +288, 0x6ca0f5ef7c106cde +289, 0x995d51989aa1c417 +290, 0xc9f2c923fe4455a5 +291, 0x643815429f7eb3b2 +292, 0x62ea9ec7264da11c +293, 0x447d0b45dd80f0c6 +294, 0x28f4cfd3070a7954 +295, 0xe489352888499c52 +296, 0x8052cbc99a85e051 +297, 0xb8f3cb6026cc90ad +298, 0x912584210563a88d +299, 0x6d4d13a07f86a423 +300, 0xfa4d51b338c3b5ae +301, 0xa03ef23eb024427e +302, 0x6f7f11baaa5687bd +303, 0x408d5fb68881b088 +304, 0x29e51d59129fc75c +305, 0xcdec3ff5975e02f7 +306, 0x6008150d8694fb00 +307, 0x1716a8dc698523b0 +308, 0x5630cb8b8291ffa +309, 0x5fd5da716e1a78da +310, 0xb1a6db0fce436d0 +311, 0x57e1d30fd93a3c37 +312, 0x72757a0a3321ea6d +313, 0xcc76c5afc421e56d +314, 0x16190b05f0b40caf +315, 0xf78a3f994c913ad +316, 0x7e1a1b1c5d24c00b +317, 0xa1e2fb1ff0b9d6db +318, 0xfc498b8039b54f0f +319, 0xe53a07e1d2eaea28 +320, 0x78fb2fe5aead5931 +321, 0xc88e3c02e3dc1785 +322, 0x1316793c718709cc +323, 0x87ee50ee2442393d +324, 0xfaed744d0586ef7f +325, 0xb421ca20f3f36511 +326, 0x167a97dae8220873 +327, 0xd1923f827aaa2686 +328, 0xdabb838e2156893c +329, 0xef5035dbb60a0e43 +330, 0x4eb59086d683c897 +331, 0xf53508888be59fda +332, 0x6c901a026863b64f +333, 0x533e9b2905812820 +334, 0x5995efd0f86f0247 +335, 0x85407d7c71a8519c +336, 0x4ec365075d3107de +337, 0x2ef189e758ccac93 +338, 0x94965c831e00c74a +339, 0xc703660168ee5f1e +340, 0xb299ff5db8adc89 +341, 0xf016bd3198c82f20 +342, 0xb547315812240a6a +343, 0x2615627e3eba8870 +344, 0xb78e0f43405b7898 +345, 0xa9d14916e9b7efb8 +346, 0x112d9ae68e8904d9 +347, 0x3dd1e5d8d87a2a00 +348, 0xe72d6f0971f538dc +349, 0xa39e9d3bb475c18b +350, 0xe8e4c1e4d8c6a8d8 +351, 0xbd79ba7f0ad62765 +352, 0xc385792825aa00a8 +353, 0xb6d7f610d9c4d243 +354, 0x4335b0eb532176f1 +355, 0xc0a2e5238b8e0677 +356, 0x16c65023c679608b +357, 0x4d994626744b8f46 +358, 0xcb0b2741af2df9ca +359, 0xe4a7e3fe75a1aaab +360, 0xe32a45741e898d8d +361, 0xe67a3f4fd4b2b6d2 +362, 0xa0ea8adc980fb9df +363, 0x22677c7e716dff46 +364, 0x61a419a44db57308 +365, 0x2450dd931ff2ec3f +366, 0xce84c6e8acfad7fc +367, 0x760e778b2e193a05 +368, 0x8eae9f11a89be32 +369, 0xa4e9d719935d50f6 +370, 0xd5b566b0369a52a2 +371, 0x42fc4fca6052ff0e +372, 0x54bdc983732078bd +373, 0x2a34b26ece1a4a1f +374, 0x4a6c02709bf62226 +375, 0xe764d4869ca86a88 +376, 0x3b55160e0eccab3d +377, 0x6298740e7a75206b +378, 0xf5dfabfaf966966a +379, 0xb69af13f6a58df15 +380, 0x40d98d1218870fd0 +381, 0xd31db917ad090d36 +382, 0xa0f51d92105470eb +383, 0xd49a359996308801 +384, 0x9c0a51cf0afe4987 +385, 0x3c5139c9bde54e2f +386, 0x3d8764a94f3910f0 +387, 0x72c022834f060c6e +388, 0xfc1bdf8001e68e68 +389, 0x99fe3ed21088ad60 +390, 0x53d270e055960efa +391, 0xace8c828bb806861 +392, 0x281e3aeb0a9c4834 +393, 0x449b247a025d9c17 +394, 0x9d348001ba4afbbf +395, 0x287d8e15971d6c94 +396, 0x95f6b9856848aa36 +397, 0x7ad4738f43ec445c +398, 0xf5dc701c62cb0707 +399, 0xf85fba15e2f3af47 +400, 0x339c4e96a86d310a +401, 0x8ce140d016eff7fa +402, 0x65edfc5c5c98dbd9 +403, 0x1d0a87d9af90f167 +404, 0x203dc34e1e9ee146 +405, 0x1660fbddaca7a089 +406, 0xa4595cfc69627ae6 +407, 0xf5c6c28fdf65db44 +408, 0x73cc91643c51bf0e +409, 0x56d5ec5f4df77ef1 +410, 0x238903979a24cf65 +411, 0x96268de7413313b8 +412, 0x28a3c908362a9bad +413, 0x728d68bc8b6496d0 +414, 0xbfb6a39f37f22189 +415, 0x9c1e845d3b060423 +416, 0x11962b88cf841c42 +417, 0x5d91b9809053bfcb +418, 0x854693772fd6c780 +419, 0xba2a80b61299b067 +420, 0xc167859290090b3a +421, 0xd8ebc6acc7fdc96 +422, 0x5840dddbfb862b08 +423, 0x5202ea8acba4faa8 +424, 0x49d3bbda86413c0e +425, 0x32be126f76f93277 +426, 0x89663ff83ea2de5b +427, 0x80f40ad26cb40dd2 +428, 0xf766a092380d8ebd +429, 0xa4487b65fe0744ca +430, 0x322eb186046a4a94 +431, 0xc02a504c09a45a1c +432, 0xdb7ee621ffff440e +433, 0xfc0dfc9f26c858eb +434, 0x69c4fe6af18bcd7c +435, 0xefe02edb24d56ea4 +436, 0xa50a14ad0e9eef00 +437, 0xe423d1c202ef28a6 +438, 0x7afd0f5d320da389 +439, 0xdc08b10bf5eb2150 +440, 0x2725a6e6b0d16c3c +441, 0x4ebc9a86ad70a406 +442, 0xe5b234e726949788 +443, 0x61895444577fa683 +444, 0x579bb863c9c0f4d4 +445, 0xf57472f1c2186e40 +446, 0xe20f9e4dd18b7a86 +447, 0xdd874db6f18ad18d +448, 0xd33a6863b26e7e0f +449, 0xfbb06768ee299508 +450, 0xa698449c04c6dac7 +451, 0xef8956f00b0b93b6 +452, 0x50187c36dcbb27b5 +453, 0xe183c93b50fc5db2 +454, 0xeff4e91a9f691af5 +455, 0xfeb0c53b5f79d85f +456, 0xcdf64cb7aa9e77b8 +457, 0x92c7e1c5d0cf8545 +458, 0x2364334169a8777c +459, 0xbb59d00220215aa6 +460, 0xf0e84db1ba5e485c +461, 0x32eadec20b527e69 +462, 0x40a8c172ae43ffe9 +463, 0xef1bede2c2ded35a +464, 0x92db9273d1c956a3 +465, 0x6c9cb922edb2d4b +466, 0x5a679c0c94b3f39f +467, 0xe6a5221838453419 +468, 0x66de19b420c14ee1 +469, 0x8c2bd98ad9467af1 +470, 0xa147d5f399568982 +471, 0x9e8aae9d332472be +472, 0xdefb07cadadfbd88 +473, 0x444a202d1b2edd27 +474, 0x319c8773f6a754fc +475, 0x36606ba635cfced5 +476, 0x31504a5b044d1808 +477, 0x806e09994bdacb17 +478, 0x9427e77e577af871 +479, 0xb59d548f5aff715b +480, 0xf52251410861803d +481, 0x38e43e9d0e116362 +482, 0x4193f31faf42df63 +483, 0x220bc4765445a54c +484, 0xa70017472927b966 +485, 0x7df2a19540ba70f7 +486, 0x312517443864a8a6 +487, 0x5b3050b6e7369529 +488, 0x7d78902a459de6bc +489, 0xb55cc03b010496e2 +490, 0x4b5e70c18d90afe8 +491, 0xa25c9282539ffa39 +492, 0xb3634844d85ca854 +493, 0xd70f1ba5cb23f155 +494, 0xa7164bd3ba66fd13 +495, 0xe8fa24efc28e0b35 +496, 0x53cffa8448fa39a3 +497, 0xda1963ccf029a46d +498, 0xab159eb294b3b2ed +499, 0xa3a837503c32174a +500, 0x83b5e56c63ca910d +501, 0x77174c7925c01bc4 +502, 0xd9723ab7a9b06742 +503, 0x407fc7b87e1b3301 +504, 0x3067a710c13076ae +505, 0xf490b50ae1c760c0 +506, 0x3984834f76388042 +507, 0x8f61a75763eebcc6 +508, 0x5526d22e2c18bfca +509, 0xbd1f2ed9006893e5 +510, 0x751810cfad06bf24 +511, 0xf21af6042e4b3618 +512, 0xc159c3b878206376 +513, 0x1f40d0561588b836 +514, 0x84e387cbeefc8370 +515, 0xef8378b1b551cf8b +516, 0x501934cdd42db314 +517, 0x2671bd3b0b8edb35 +518, 0xe08db954f218bf8b +519, 0x6e2daf982de67f0d +520, 0xa07c0f0c4958d787 +521, 0xd7fe2217582a0977 +522, 0x8c4b91a83a7dd84e +523, 0xb0f97b4621d12984 +524, 0xccb5ea2b6fc4d012 +525, 0x65fd9271c2cdf119 +526, 0xedad88bbdb81bc5d +527, 0x3d744a2bba50afd +528, 0xf30a4cc4a9a02eae +529, 0x1ec08d6b2a3aae18 +530, 0x93fc3ba3fda6076d +531, 0x1a51f49322a2a528 +532, 0xa9f55a607051835e +533, 0xce3bccb15f94a155 +534, 0xc7e0428cc4a6cd37 +535, 0x24707a92b8e71cd8 +536, 0x443fe1ef6689de4d +537, 0xe5610bdfa3bc3809 +538, 0x1c684dfabc1a719f +539, 0x3e41dff1948ab65a +540, 0xa58cb5d77eed149f +541, 0xc589c050bea7760 +542, 0xe4b8316d7455d38d +543, 0x3ad6140f84f0c0dd +544, 0xdf7deca619fedeb9 +545, 0x5fcb5d0ea1b1e47a +546, 0xc602267112df1d8f +547, 0x91f44054fac54920 +548, 0xd740c0213fdac4a0 +549, 0x677a64717564c678 +550, 0x733009a5e9360091 +551, 0xa50ee09f5b7f8854 +552, 0x2b7a9cb61c3de26d +553, 0x23349b2382903734 +554, 0xb498a233184e1c0e +555, 0xb44201ef4443deae +556, 0x6daca8c5a6647612 +557, 0x36f4b7e94bfd7b50 +558, 0x8ca5d0a0098bea0e +559, 0x5bfa417533e65be3 +560, 0xb2b7ca005d530c22 +561, 0x780136e2cf6fc471 +562, 0x874a13ef938027a5 +563, 0x1e855317eaf4937d +564, 0xe9e122ade32fc335 +565, 0xf24661d4287b8f5f +566, 0x6113a640f6a23e6a +567, 0xa5d681ea6fd4538d +568, 0x2f5afe3fa42ac6f8 +569, 0x924ace74f2200a67 +570, 0x2860af7bdc0a1328 +571, 0xc18d7e42dbe8defa +572, 0xd565ccbc02300ca1 +573, 0xe2c425203673bc87 +574, 0xe7cc4d62fcb1b7a5 +575, 0x4736a2fc73e0408 +576, 0x8b63d58d06bf6f4f +577, 0x2fe82ed95c103404 +578, 0x9d6458914f301d00 +579, 0xe6dbde6799cb0c2d +580, 0x437153bd57359448 +581, 0x91cca254d0b51be1 +582, 0x4b5618013971476 +583, 0xf7a30620ebd70ebd +584, 0x3170e9eba79c8fea +585, 0x8983fb74dc098ba3 +586, 0xe597a911134d02ee +587, 0xc1bf7730780802cd +588, 0x1ac341a0343abe36 +589, 0x877addb61c4f6d53 +590, 0xaa6326c5c9f7dfc3 +591, 0x2176da3fa9450570 +592, 0xb9086e2124d7db1a +593, 0x75b150a1ad48736 +594, 0x72361f3255bb1c6c +595, 0xe77633cc35d21649 +596, 0x7fe0c14523deda1e +597, 0xbed948a006ab7ae +598, 0x5deecc48e391cc9e +599, 0x1c60216cb5b769be +600, 0xeb3158cd91cefbfe +601, 0x8ff0059d384b3482 +602, 0xc270fdcdf1b27054 +603, 0xcbda49df540f7bee +604, 0x9569dad154192b1 +605, 0x626b1d9dc5af9355 +606, 0x1f2e390fb9f72c34 +607, 0xb5da34db64cb3c12 +608, 0x91bc689a0a76f72a +609, 0x722e70eb16c2883f +610, 0x4e3e4ffd2dbc23eb +611, 0x530b6cc8da38189d +612, 0xcc1e8a97bc9f7f3 +613, 0x8606896c6384df29 +614, 0xf12057ea9246c3a6 +615, 0xa36176adf40ed649 +616, 0xbd41dd899b1e7e1e +617, 0xee6b4a30cfc1705a +618, 0xecaf8b48645b1a1d +619, 0x45b9d22e4b67d526 +620, 0xf4633b7932f7b231 +621, 0x3d110c58b9d3af76 +622, 0x5476134f5a62c65c +623, 0x8b8c459aebedbcfd +624, 0x85438a06efcf7244 +625, 0x4093cff6b13d0235 +626, 0x3441e41c4240a04a +627, 0x7d2ddfcef9e1502a +628, 0xb103bf1629052a4e +629, 0xc7b6242cd4b0ac6 +630, 0xca90bbd3896e5cef +631, 0x475a4f194b2efc95 +632, 0x40b7befb56e87d9c +633, 0x6cad487ce5b9fab7 +634, 0xfea988ecd11b1e48 +635, 0xeae1a787969dd6a +636, 0xca61203919f24b59 +637, 0x4fbb1b7da2ed1eae +638, 0x2293875acfb13bce +639, 0x83bdb0d855f80904 +640, 0xc6cb9af3dc51663c +641, 0x3670a82bf259af61 +642, 0xad19636327ae2f9 +643, 0x1e3c9eda8aa86f0e +644, 0x9bf0294f709db9c8 +645, 0x82634a2a6f68d88b +646, 0xd28459865ee6ba06 +647, 0xdca0589a37b686bc +648, 0x6d599e666b676946 +649, 0x532da8f80b2ab6fe +650, 0xd04c13960c6ada57 +651, 0x6b6be861eaa20840 +652, 0x7bee96f844d8af14 +653, 0x5262b1b291404b11 +654, 0x7c2e76df26ec97a5 +655, 0x200a74e9d28af98f +656, 0x4c524db7ac5bdae0 +657, 0x7220e9ce3b2bd645 +658, 0x253c92bd314da1e1 +659, 0x61c99004de5ee6ad +660, 0x1a8b45e7a2b8a09b +661, 0x8210afa2eb0147e6 +662, 0x275f3a56f6ec8ba8 +663, 0x882e054db980aee2 +664, 0xa2a4f61060588c1d +665, 0x7c4cfbadd5d38529 +666, 0xee8a9c0ae89de452 +667, 0x3a1e9d46843f2574 +668, 0xd076b0d7f2e7dd81 +669, 0x16c1e3acf3b45fbe +670, 0x182de2922f0e2a0c +671, 0x9ae8e92260ea419a +672, 0xe07af4e2b7b48d7d +673, 0x600e3ec66ee20ec2 +674, 0xf7036d1caeacf4b8 +675, 0xc147ed61fcd4f647 +676, 0x7f9e195665802bba +677, 0xfed9db42c4ab22eb +678, 0xaef24cde91dbcab4 +679, 0xf84b896fabe3218a +680, 0xc99a2b2725700ca1 +681, 0x8e9e3242ed539a42 +682, 0xd68f96459b7d4eda +683, 0x3519bfc85e559ae1 +684, 0x6837e68bef1bac4a +685, 0xa09f0e34eb061e55 +686, 0xbf9ad807ad35e4e9 +687, 0x5a5d949c5bc4a894 +688, 0xc5c44dae5464903a +689, 0xca5b2b8c8ea7b8a8 +690, 0xa55ff2894f125040 +691, 0x9f6ff13eae26b16f +692, 0x584babe068e32d0b +693, 0x675701bb344f15d8 +694, 0xc7cf1a1ae4965137 +695, 0xcbd397007200464 +696, 0x441dbbbc178e9f1f +697, 0x68de3be524e615d0 +698, 0xeeefd0ae2953fde1 +699, 0xf3f25710aac6e8dc +700, 0xa6e739afd86491f8 +701, 0x788b33d85140da94 +702, 0x93e31f17b30996bf +703, 0xe339877de36dc99b +704, 0xab8d1922e63a81a7 +705, 0x2fdec0bc47274e3b +706, 0x46fac763279a6456 +707, 0xcf43d49178b7e2c8 +708, 0x6c97160d52f7541 +709, 0x338082733f40fe0f +710, 0xaaa7adedc68075fc +711, 0xf6be5a0983c7e38e +712, 0x23704a0305bb6e4f +713, 0x863b4177c8b4b645 +714, 0x49d46155cd596ed4 +715, 0x9c3aff0f8f51e7aa +716, 0x818d564029593dd6 +717, 0xf86d183be4f9bc67 +718, 0x2913f9929b732227 +719, 0x70170b1cd3a3ac54 +720, 0xb8a80aa5e5a049ab +721, 0xc11837b6e5d05914 +722, 0xac4e428e8179ffd0 +723, 0x365ae1ad260341a2 +724, 0xdeb434fa400c659a +725, 0x301e5022964913a7 +726, 0x9b5353184587e65c +727, 0xe87952dcff2bb94b +728, 0x38018ea9168498f +729, 0x5329faa0a9b31518 +730, 0x4e9826e7a5309cc6 +731, 0x8c8b3902b3fb31cb +732, 0x51fa6eb8243361a7 +733, 0xf83033cee6066488 +734, 0xb5bfa21e11d0084a +735, 0x5dea1df773d5472c +736, 0x8df2cd3cf75596ea +737, 0x927d1c793c8cea03 +738, 0xf1c36260836e102d +739, 0x1359f6c8df89970d +740, 0xa6d259498334bc +741, 0xa6e07155f17c845f +742, 0x10deac98d78f615e +743, 0x82dd4e3ebd26fe73 +744, 0xa38711f23c38a1af +745, 0x2fdcd69782301538 +746, 0x216d402e19d85877 +747, 0xac673ce673285122 +748, 0x7875f10741c5d847 +749, 0x68c40a47711addc5 +750, 0x2993772e15b714ab +751, 0x7e98b5fb52c5fa95 +752, 0x4bbf5c436cc0ae +753, 0x18b9dd31c535817f +754, 0xb461f16678918bed +755, 0x3c036fc204d6af40 +756, 0x97a7f1ee6acbac2d +757, 0xe14fd6e30c86a58d +758, 0x88573c172e1f841b +759, 0xc34525268445a76a +760, 0xd87d260c104a3640 +761, 0xe4e89f8d92a8d78a +762, 0xa8ddfdacfdb10b31 +763, 0xa4afe400345727fe +764, 0xc86d9a624d1c58ec +765, 0xf343ee93309d8a86 +766, 0x3e2e1a0436b09535 +767, 0x6d43bc645ed9ac6c +768, 0x851c37fabf29f39b +769, 0xc3426e0cb4dd3941 +770, 0x497fc67d26f9c0eb +771, 0x763f57a1e7b7c7f2 +772, 0x6d17c1946432276a +773, 0x8eb40863a03a9f6 +774, 0xb4d2efaf434f99e +775, 0x3b7362a21b09a974 +776, 0x8346f15db661117d +777, 0x935d7f4718c0b76b +778, 0xebecf09e8cd66494 +779, 0x6488514887be6d6e +780, 0x8967e6482106a9b1 +781, 0x1027a9c65d640f4b +782, 0x616ac0c09e0c0424 +783, 0x370fd6f501ee434e +784, 0x64656b86647db284 +785, 0x1e75f13e5710fe36 +786, 0x6f707be9595741f3 +787, 0x36005270b95cedb2 +788, 0xef4d96d7855c072e +789, 0xe00dd4df241aa017 +790, 0xb7636a7a39dbec9d +791, 0x55f0089bed163558 +792, 0xbc2629bb08892645 +793, 0x7972323d3b65070a +794, 0x6d034ae888e1dde3 +795, 0xe3746defc543a1fc +796, 0xe21f07f7946046e5 +797, 0xb4a1beab89060010 +798, 0x7599da8e80780a1f +799, 0x2c9a6831a67fac80 +800, 0xd96d4d3e81ba74d5 +801, 0xb9945639961e680a +802, 0xd8a540ebd9244a95 +803, 0xa083f2ced29445e6 +804, 0x8be65673106fa2dc +805, 0x9896bf42455914ee +806, 0x12143e7988bb5799 +807, 0x53c754030fa4a756 +808, 0x1737b69502b0aa59 +809, 0x2ddf23fe48a62247 +810, 0x3841e493ee590199 +811, 0x912f09f5d33d43b8 +812, 0x19229c58ff93efb4 +813, 0xf1779404e2983aaa +814, 0xe83633e2c248d359 +815, 0xc717450be4d4874 +816, 0x96c7e09c87a882d3 +817, 0xf7de965536666dea +818, 0x8500552659716f4e +819, 0xa325745ddbd5991d +820, 0x646a7720bf41f124 +821, 0xfcb2de34a2319f8c +822, 0xa5cb25a06e56c96e +823, 0xc2098ced3a1d7f16 +824, 0x4e0c42ddc545e1ec +825, 0x1a81a4072bc8c70d +826, 0x33c8c26ee5f2a8a8 +827, 0xfa73293671dcdea2 +828, 0xdfcef95a123b6e75 +829, 0x1be31c104c2f8884 +830, 0xa3a38df49047b410 +831, 0x927d2d9fcfd5e906 +832, 0xacd1b5febc723579 +833, 0xdb3ae10ff6179edc +834, 0x83034561e2390270 +835, 0xbd9316c92698ccde +836, 0xaa17f5dc651ba328 +837, 0x21fda6d3c574a13 +838, 0x5510e62023ec3b60 +839, 0x8d939254ae548157 +840, 0x10f3d1f467526a1 +841, 0xb86c845b5fc5248a +842, 0x8545fc74955c82d1 +843, 0x394de00459610bf5 +844, 0xb98e7648d039f546 +845, 0xec2c9942f392b082 +846, 0x63fb45dc65abb87c +847, 0xa293317b6f87fbe7 +848, 0xeec10eee4880bdab +849, 0x7e0a96d7a639db96 +850, 0xeafa162cdb08dcb3 +851, 0x816e68da04ed4bf6 +852, 0xa4700cf2444147a6 +853, 0x5538ff41c87380bf +854, 0xe7e18e47273372ad +855, 0x6b9344f90332664a +856, 0x38f37af3a5ecf737 +857, 0x51e7197547bae5f2 +858, 0x417b49ddbd5c8ac1 +859, 0x7aefd1477efa2b53 +860, 0x3760d5701bf49440 +861, 0x710be29a267e823e +862, 0xf4c6d8607df3e45e +863, 0x452230b3ed570aa8 +864, 0x6f99237e35b6950b +865, 0x6abf4caea61cecdf +866, 0xd43740daec5c5a5f +867, 0xa7f576b3fd5d5d05 +868, 0xb076d89b96a33c88 +869, 0xa39c1bcd83b190b2 +870, 0x7618d27a72b13ce1 +871, 0xaf93ae79c6dac995 +872, 0xc837ce1ec14feacd +873, 0x1606184f9270d69b +874, 0x98a0d302ec1868fb +875, 0x8e4010b8c6ba8b85 +876, 0x91fabe97c826be7c +877, 0x69bd7d8486501178 +878, 0x15008364e9a58f51 +879, 0xa51ab44e26267b7 +880, 0x85ee973bc9e19ee9 +881, 0xfb39b02ce57899 +882, 0xc0f80d8e1f5c890e +883, 0x3f229a821ba4bff2 +884, 0xe9d4c6ff69970580 +885, 0x83e9ccaa3d5ff548 +886, 0xc6554c73cb94447c +887, 0x56d094f66000a7ba +888, 0x2180ce39c7ba63a2 +889, 0x70b47bf5afc29d65 +890, 0x976a3290e523061a +891, 0x3950058fb90fe132 +892, 0x76da108a69799048 +893, 0x42699b4c4f7d1866 +894, 0xf281a11c6bb173ef +895, 0x700b4d769e2f5ef +896, 0xf0e0ce96a60102f9 +897, 0x77b92c4fee413da6 +898, 0xe5dbad4fd50d56fd +899, 0xa240bb500fda3852 +900, 0xa2ace5d55a2f4da0 +901, 0xca519e0c48a53c8c +902, 0x5451834c28b0ed25 +903, 0xf8b83e1f7de31f36 +904, 0x9c8c416b9a1091b0 +905, 0x25884ab7529ae96 +906, 0x6097e452343a4525 +907, 0xff30584230d3f39e +908, 0x56d383168357ba28 +909, 0xca95d287a8895aa6 +910, 0x1820536c986a151f +911, 0x8bb62b7c25dfdf4b +912, 0x46ea14775124a4d9 +913, 0x2424a64e4d04bb9c +914, 0x17738043edc89d31 +915, 0xdba93bd6dc35fba9 +916, 0xf4d84f1396123324 +917, 0xd3afb0d529380864 +918, 0xfa9b0888c037d6f1 +919, 0x5978537bec8f972a +920, 0x8fa9926a080affd4 +921, 0xd5d0b7419c2c0a6b +922, 0x5218c0d0da166bf8 +923, 0x113766ed52074b0a +924, 0xcb3cb49751a8ed51 +925, 0x76f4964c1369cfb8 +926, 0x248ef6f6a0b7987c +927, 0x124962f6cd30d2a4 +928, 0x3ac9098b45d56fcd +929, 0x9db9dc39098adf0b +930, 0x281d775a9aabe3e1 +931, 0xade94768d752f284 +932, 0x2916418b2780283c +933, 0xf6842d520f056828 +934, 0x644f905ae21dee4c +935, 0xb33624d20348f897 +936, 0xe10430135a63b21d +937, 0xe4f73ae0a126d8f6 +938, 0xbe6ba34486dbfea9 +939, 0xd4ee40812332dd9 +940, 0x4ee8a69b86449ad5 +941, 0xb1a298727256af05 +942, 0xa3e558c4f12d9f59 +943, 0x645703828b4d5fbe +944, 0xdf4223058118c420 +945, 0x251dcdba6d3ded09 +946, 0xb2d84c99dcbf9318 +947, 0x8dc95fe1c9863322 +948, 0xfdc6ad87458a50e4 +949, 0x4cf57028f4f133cd +950, 0x5a13d134a30830f9 +951, 0xa550bddcdb0804a +952, 0x8f50b20e973d1ad9 +953, 0x5d8fd8547fbb25a2 +954, 0x57fb0001fd795ae7 +955, 0x80a847e957440201 +956, 0x12e25c663b26ed6e +957, 0x8a3793d5204fdc1a +958, 0xa7e782709f666612 +959, 0xf08d5b5e3e6fe48c +960, 0x226c01d4c843035b +961, 0xde70ce6a314b4a5b +962, 0x2b3f4c7488c346ca +963, 0xda121178e4f987ea +964, 0x9c39f51596ab15d4 +965, 0x56b363742c0401e9 +966, 0x791873978c61e53d +967, 0x703acd4c93373bc1 +968, 0xfa9d1ce6b783d3f5 +969, 0x1dc0a81be853fe40 +970, 0x95a2eff6de671578 +971, 0x49bffaacb5073f9a +972, 0x4f5875882fc088a1 +973, 0xb2cb0e0a7684f052 +974, 0xc8a96b8e988aee2f +975, 0x906c865a40447872 +976, 0x9713e82964a3e5eb +977, 0xa0d4766ce887c073 +978, 0x7375bbdc687fd720 +979, 0x4edbab65f44b6dd7 +980, 0x77d3db5253bac0ca +981, 0x8fd1b3db8997a7df +982, 0x7977905089848b28 +983, 0x60d769441eaa0ceb +984, 0x17eef7b60f4f9f5 +985, 0xdffd2e0b4deff6e0 +986, 0x6c07d6c0eab9583d +987, 0xb6d0c41c540524e8 +988, 0xa5f74648efa213b0 +989, 0xccf793ee870c7483 +990, 0xcb057091573dd7d5 +991, 0x572507949b0a9d22 +992, 0x51bfc469fa3bbb0c +993, 0xc0e35708c36e3969 +994, 0xee22a97b146d408 +995, 0x5b4049f83503ef66 +996, 0xf0bcba04dba7bc72 +997, 0xd27a0dff278d071f +998, 0x9b7eaff14d464db6 +999, 0xfe5f490518b254cf diff --git a/_randomgen/core_prng/tests/data/xorshift1024-testset-2.csv b/_randomgen/core_prng/tests/data/xorshift1024-testset-2.csv new file mode 100644 index 000000000000..ef10e6872219 --- /dev/null +++ b/_randomgen/core_prng/tests/data/xorshift1024-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x3f76833568b96fd6 +1, 0x49701b0dcd023e7e +2, 0x5f266f1686d3bb85 +3, 0x4df1723af9a5a67d +4, 0x2fb393fa5be2f6bd +5, 0xf7212425ebb2ea96 +6, 0x3f02cec25804b60e +7, 0x7f3a0fa3228a48a1 +8, 0x79d9baad4538be8b +9, 0x4ae9b98e9c834b48 +10, 0x39b5728e47ba6016 +11, 0x9f1d986c6dced8f +12, 0x90e883bb0ca1a839 +13, 0x98995f729732f4ec +14, 0x26b741189221c8e3 +15, 0x293ae8b010a6b556 +16, 0x30180d5248809a52 +17, 0x3edc6105a838a0a1 +18, 0x315e9f489399aa35 +19, 0xd2c7f9142fc59292 +20, 0xe9f6c92674f1e75b +21, 0x785fdf1bf2633d4e +22, 0xbffdf9ac080cf1f7 +23, 0x29c63dce8aca1786 +24, 0x1e16e12f382e3f58 +25, 0x1509b2db378308f8 +26, 0x2f82c24732d9ab17 +27, 0x94feeee6b53644bb +28, 0xea274cb2e3a714ee +29, 0xbe0a718ad2dcb289 +30, 0x3c8ab9a7bb57e51e +31, 0x7eca590bacfdcca4 +32, 0xfcf259b0ee0f33a1 +33, 0x6323e00217e9bb03 +34, 0xbeba78e81e3e1e11 +35, 0xdc83427163d46eae +36, 0xc93193975a686b2e +37, 0x8984b33e2993452d +38, 0x98f329f05f37585d +39, 0x76ce85b5532f566 +40, 0x87bda8155b05a2f1 +41, 0xd949bf037a42d942 +42, 0x9f4021daa72f983c +43, 0x184bff5390deca78 +44, 0x4588bd90c642a4ab +45, 0x907886ff47abc57c +46, 0x7d5edf3810ac69a1 +47, 0xa22a609f3af5f287 +48, 0x6b40ffc40ebcc7b7 +49, 0xebdc35de8c34aef6 +50, 0x27f55c4ed36bd7b3 +51, 0xcb5680ca28b93c4 +52, 0xde59d0be040aeafe +53, 0xcb98df139b6ffb67 +54, 0xe5f29ae79bc3fbd2 +55, 0xf594a05f7d5c2cf4 +56, 0xbf9c12fce3be883b +57, 0xab1ae13d69b39529 +58, 0x421d72f4cc8f996b +59, 0x1e11487c7c5c80e5 +60, 0x3735d17439eec8c8 +61, 0x4b45af31c2a90a7f +62, 0x30a2cb0b8f4effc5 +63, 0x1d9c11ce9ed98912 +64, 0x459938610b8c056e +65, 0xcf8dc26a419b01cb +66, 0x6811a148c58a4b2e +67, 0xb524fbb0a1f9364e +68, 0xba973b1bafcafc8e +69, 0xa5ddb20be4f0ffdb +70, 0xc454734347f3ebc +71, 0x4712b34f7bc603ca +72, 0xcfd5fc37f5f96d64 +73, 0xd9376e1384a016dc +74, 0xd3e2e66d7522c11 +75, 0x143e2e7ceb65246b +76, 0xec0c92eb1c04628 +77, 0x45748e2648e1cf23 +78, 0xe0a78e265aed478d +79, 0x1ade12b47bff7af9 +80, 0x7df63a29c36980b1 +81, 0x1244bbc2c3b55d5b +82, 0x71dafa1fcd09e981 +83, 0x6da5bfe009eb025b +84, 0x446e999577098c05 +85, 0x4e740791bd030e0c +86, 0xeb81a0c4b7411481 +87, 0x78fb5228d162578a +88, 0x22e0adc5d0865c85 +89, 0x161f0870dc2730c8 +90, 0x55cd2b4204fc7021 +91, 0xa3f7032a1b14b9ca +92, 0x854f738869897eec +93, 0x6034a7deeec8a32e +94, 0xa65fdd6da09fcb69 +95, 0xad33713fcb48206e +96, 0xd3dbaad174c43ae9 +97, 0x96dd91e508c447f +98, 0x1a3340c5f67ac6c7 +99, 0xea0c47871d675b88 +100, 0x54bacdff7e665368 +101, 0x9bcc294b0224dc44 +102, 0x61ab987c7f6f44e0 +103, 0xa889ce8426a089e9 +104, 0xb3fbf7d9d2693b82 +105, 0xa034bba7212e9bcd +106, 0xf5b9ceb0347e27ec +107, 0x21a294cdc75fe066 +108, 0xdefd61a8423cc66b +109, 0x8bb34afc4238ac28 +110, 0x123125a26fec35fb +111, 0x12264435308f2e02 +112, 0x3040dc41d9d44a7f +113, 0xc0afa8f0419dd5c9 +114, 0xb104cc03806dbcc1 +115, 0xfee1222b5504c5e4 +116, 0xbd030f4ee7c7bb42 +117, 0xd9ae404361851df3 +118, 0xa152dc8b4829587f +119, 0xbe098e4fc3244521 +120, 0x962610a22b49f5f8 +121, 0x332846cf38524603 +122, 0x50df3207fc830c79 +123, 0xf3f3f1e7e4dc35e6 +124, 0x84a45b323586ee98 +125, 0xd081c30746cd1271 +126, 0x2f8a32f0bab99b4 +127, 0x10b35b4eaaa85d37 +128, 0x544e543d7301f095 +129, 0x7d4eb1f6620b0e8b +130, 0x8fc9da866e9f7d9d +131, 0xad4fc278afffcefe +132, 0x6ec8f6e385d52ba3 +133, 0xe373d4e2c67e1eac +134, 0xb66c7a0aafeb8bdf +135, 0x9c2861000abb6a04 +136, 0xd7ac7033ba369609 +137, 0xa89efcd43ddff9e1 +138, 0x8691faea965fab39 +139, 0x4706b127c3c60cb0 +140, 0x1f2bb20c07eee57 +141, 0x75de540960f2d73c +142, 0xa7d357a7588a06e2 +143, 0xc2fb0569e2deefcf +144, 0x2daa6fdc86ed6b5e +145, 0x8d22e7f3ddb473d2 +146, 0x4bfb1c145aa187ff +147, 0x4072049cc0ac3535 +148, 0x33aff50fd4fbd9a6 +149, 0x3b6b44b730ccbf99 +150, 0x6c642c48d77b70d9 +151, 0x5d906e071f55e4cd +152, 0xd2339209bf1902f6 +153, 0xe83a2462b66f9630 +154, 0x99b0e7998ef43ae3 +155, 0x10f9fed156fa7a40 +156, 0x916d7fe56fac3286 +157, 0x3300c38652e68e29 +158, 0x567d9b4b64e1b06c +159, 0x84760e41f897468d +160, 0xe20a22b206efe5ae +161, 0xcf62d03b167564a8 +162, 0x84154af6fd23be10 +163, 0xe598e0d0794d9418 +164, 0xf8aae24ab57b3e2c +165, 0xd32964005491aef8 +166, 0x227d2b64377a4129 +167, 0xa72ddc508c67727a +168, 0x2e2d60c022c700ec +169, 0x69fa3d4d34fbe852 +170, 0x756111547c3d3310 +171, 0xd462579cae5de843 +172, 0xe6cffa31860e71d8 +173, 0x3b63062bbcf07c93 +174, 0x25a83fddb4d2a4c0 +175, 0xe6b93ed6ee5b01a8 +176, 0x4ce86cf8224d215c +177, 0xe700f73f958137d5 +178, 0xeedce56e96870b8b +179, 0x3a03a241098f72b1 +180, 0xe066b4e17c9e7591 +181, 0x73b18bbd4b75ee0d +182, 0xe2b966c36c34d2c5 +183, 0x11f5a749521edf76 +184, 0x8f865c02ebed5bc7 +185, 0xcb93fe0bce57f9f7 +186, 0xe380b5ddf23dda17 +187, 0x98b03716d02f2dd9 +188, 0x9594e9b56cd3a8de +189, 0x6aa30fb660591e99 +190, 0x1e35c2dd1fcf24be +191, 0x1af2e84dbaae951a +192, 0x7fa337d7cd70b8d7 +193, 0xd0a270c39990acae +194, 0xcabf237235574a17 +195, 0xdf8219166c76b423 +196, 0x7ee41851de09d1c3 +197, 0xd444c75128a3aead +198, 0x595291e15ace95b1 +199, 0x3f96f0a33493d662 +200, 0x524c9f003c2d74aa +201, 0x30e4b6855164d763 +202, 0xd2cc4597098a4500 +203, 0x9a11cf7e7d856ddd +204, 0x6f71b7f4da0728ab +205, 0xa4f4b90919184391 +206, 0xc420d20c06ddc291 +207, 0x40bd7102c1406163 +208, 0x3e0ffda5947e78b2 +209, 0x2b283f6394d08786 +210, 0xea1381e7f22269e2 +211, 0xd9af6fb63feb67ab +212, 0xe65d7ada4c0ed57d +213, 0x29390a105449ba95 +214, 0xb714f9a216f85022 +215, 0x99761fbf534d3253 +216, 0x8bee9140cc17f8ad +217, 0x119bf94d69993284 +218, 0xca34608a9dad7608 +219, 0x6f85cf613b771566 +220, 0xa5d41c9378efd4e2 +221, 0x1189d8ac0d41087d +222, 0x9cc77851a3d6256a +223, 0x363a1ed11a7bceab +224, 0x3e20c00dde9ac9b4 +225, 0xbf1033cb123038ac +226, 0x748824fc5d57ae8d +227, 0x29c6f3b0f34acaca +228, 0x89336ff6ffb38204 +229, 0x367634fdf6f5e062 +230, 0x17dada74ad118131 +231, 0x77fa722a7b7758c4 +232, 0x8ab624aa783988dd +233, 0xbb1a2d574226dd4b +234, 0x1367c3ee11cc302c +235, 0xe303b78053ea7d45 +236, 0x57692f8f470748db +237, 0x88117a25910baa9c +238, 0x67945be555ef710b +239, 0xf78d697319517706 +240, 0xc624069abacab039 +241, 0x406c99876ee0014b +242, 0xc268f98bb4187961 +243, 0x34c1fe6d9a249a66 +244, 0x7b229f23ed186b48 +245, 0x813447c8c6b3a02f +246, 0x7dd08df945ce95fa +247, 0xe8439c737db475cf +248, 0xa060ed8d264bb4e9 +249, 0xfec7390334233d46 +250, 0xc786d08ab50aa0b5 +251, 0x8f8f5f96fc6d877e +252, 0x2ef7ccf97c1c4568 +253, 0x27a14053814966b +254, 0x2ea6f6167c4ce2e5 +255, 0xe45bdc101c584e71 +256, 0x7927f5ac670f2125 +257, 0x51d140214f8fb611 +258, 0x96eba70b12dc9642 +259, 0x30c35af279a715c2 +260, 0x5e6f1fef8babd762 +261, 0x3d84a3c7012aa1ed +262, 0xfaa23aae7c57a141 +263, 0x4f91d0308ab5ccd +264, 0x9ba4c6fb766b1d71 +265, 0xc3bb36fe1a75b832 +266, 0x9c41667dc9637d7c +267, 0x18e7228d28293b69 +268, 0x1d6b71e7e87d5950 +269, 0xbfc7e99d1eea3c7c +270, 0xda9afc08f8b7bbea +271, 0x3ff5761b30c8bb43 +272, 0x81df41076e62f613 +273, 0x7e0a93b2112863a +274, 0x2aded22e3c3505d3 +275, 0xac8708ce5ef15377 +276, 0x273889f29f88382a +277, 0x5f74810e09927568 +278, 0x6e10e51a892a9da8 +279, 0xe6eefe4463d9038d +280, 0xfe194822bf0b3419 +281, 0xcf98d3b3f7701024 +282, 0x3b68bfc20c696612 +283, 0xef06d708e6327398 +284, 0x115d9132577f4566 +285, 0xb0247d0045c6524 +286, 0x1ffb63669817b448 +287, 0x10954c02bb530f75 +288, 0x3e7c1076a5e89acc +289, 0x239b3401cd7e8056 +290, 0x9f8df322b64c4962 +291, 0xbe9539d72df565d7 +292, 0x7ebdf0839712cee9 +293, 0x72f59054c80879ab +294, 0x78cf26fdca1e23bf +295, 0x7f53ea01601034e2 +296, 0xac0e9524b4043f55 +297, 0x1bb323be19e1b898 +298, 0x381e9a0b43ba368b +299, 0xbcbc8ff4b598c9ab +300, 0xa453f6680a2eb4d7 +301, 0x91ffe27309f97963 +302, 0x91c516cace3203be +303, 0x3224f64f8714d361 +304, 0x4f6d6f775c7a2b32 +305, 0x7b84b4d40a2177ce +306, 0x81bbcc7123cbc6e1 +307, 0x97a72d7f8b0d2dd4 +308, 0x21bd4232adf86e98 +309, 0xec4ab4065e523a75 +310, 0x420dfc4bc490cc07 +311, 0xb8bfb45dce69f9c5 +312, 0x6d0459f3cfc48a26 +313, 0xad9c1dea5e333a1a +314, 0x256625ac14326b06 +315, 0x396ea8de20ed603e +316, 0x7419c2884aa94922 +317, 0xd9eeb9a53cb471ae +318, 0xa0aac8233b2d27f3 +319, 0xdecb4cc4c1fd518d +320, 0x5ddd5eb974b7183b +321, 0xdcaf4600c6f236b2 +322, 0x6a7fa0a9ab5dfe2c +323, 0x91608b5fb33fd9e4 +324, 0x934bc1e6635f93f1 +325, 0xcda9674329048f55 +326, 0x7db603137ab31c62 +327, 0x788842593a8a36ed +328, 0xc1144ce4e0cfc1b6 +329, 0xca0da06301356dee +330, 0x2e609e408dc6d488 +331, 0x2c910b390a076ccb +332, 0xcdad30b1f4c3aa7 +333, 0xe5f2803b739851ac +334, 0x9f8ea3daa1c36e56 +335, 0x47ed39920178a5a +336, 0x4cef4092c54e9c51 +337, 0x12ebdfeb4847b6bf +338, 0xebc3f046a004670 +339, 0xce66c4aab5ea2aa2 +340, 0x27088642c863fd4 +341, 0xd7729cf6e92fd77f +342, 0x5a736a0216708ed6 +343, 0xfb49b5fd93f2c041 +344, 0x3e72423a05badd91 +345, 0x7c71eb29547e7bc8 +346, 0xcb40d0049872cf15 +347, 0xa284b7e30ca1145 +348, 0x592d91e0d87f9123 +349, 0xfa4db97733a8d46a +350, 0x33e0188f9b5d5a15 +351, 0xcef2c9a938c4b632 +352, 0x7b0e7bb55e2de88a +353, 0x154509b3c6ccf5e7 +354, 0xd9f168c6562843cb +355, 0x5774a6c2f1870f6c +356, 0xcf61f03f990d2fa8 +357, 0xeebff250f37ba8a2 +358, 0x6e5cda9f932e1052 +359, 0x4d305d91b590a85f +360, 0x26d083f26c6f0962 +361, 0x193d7cf4666a62d6 +362, 0x16d5f99e8a5b06a8 +363, 0x7b0b84b314572d8f +364, 0xc2b5d8f73da78be2 +365, 0x997e699bbdc0e646 +366, 0x720e559e24126bcd +367, 0x46b281355d2f486e +368, 0x6fe30651b885494c +369, 0x5736ed3979ae2d1e +370, 0x3298bf38f1185e64 +371, 0x33c4cf1fd1c9f0e1 +372, 0x84c8acaa32f4972 +373, 0x203d97007f3eff1d +374, 0x6b0b1b27d8fd7c84 +375, 0xc791ed0eed40ddbe +376, 0x13863752048fe702 +377, 0xc5ad8abd0b55c285 +378, 0x1ff361677761ec1d +379, 0x50630e4db5d26a0f +380, 0x1d874f4f175bfaaf +381, 0xf9a772934d22937a +382, 0x33e35f9ec8f608e3 +383, 0xc0953e273301c556 +384, 0x722fa1dbd45e5ae7 +385, 0x937eff91f242e7a5 +386, 0xa1a9e58a6c492813 +387, 0x5a72e88472ea3927 +388, 0xb5267cbdb4e014fc +389, 0xcdaa66f2de7c5ec4 +390, 0x64435583f46235cd +391, 0x95d31d5b002ce32e +392, 0xbfb014b274a6c503 +393, 0x74e839390843cd16 +394, 0xac6949cbf5d364ef +395, 0x1479db78d333bb8e +396, 0x2c7c11dda1f4905a +397, 0xb96f093c2e1b7e20 +398, 0x975acd07a18de87e +399, 0x812358a90bc79d95 +400, 0x76cdee04f004fb29 +401, 0x5e3b3481faf2bb49 +402, 0x890a8a9d41bae44 +403, 0xb7be0ca619af0890 +404, 0x4acb36efb0d6b770 +405, 0x71f80306003ade01 +406, 0x6fecdbb899af55d0 +407, 0x8314c0048baaddca +408, 0x534b12b2f7f0cc76 +409, 0xd9355306b6cb3f52 +410, 0xb0f97ca0e0ab1d93 +411, 0x89d153e37f98ea2b +412, 0x12e68f2795d4f051 +413, 0x906e397219a1ace +414, 0xd4727951a949b01c +415, 0xd33e3ff226ae285e +416, 0xfca4fa59e21a1dd1 +417, 0xec3fe6b91647b696 +418, 0x63d7aa385795076c +419, 0x55ebe0e2765d55af +420, 0xed70c55156b6944b +421, 0x2e65098d479e0006 +422, 0x5311ac9e79d145c8 +423, 0xaca7a78c96a8901a +424, 0xcb38f5f6a6992d08 +425, 0x9c144477c018fb03 +426, 0x216b3b13e04a6495 +427, 0x8e4d521ab71f367 +428, 0xa17063caaccda60 +429, 0x23900aaa25cf3bc8 +430, 0x1889209510603108 +431, 0xc8f99af9d0de76a7 +432, 0xc6fad82edb65f52c +433, 0x9f382a97ae383143 +434, 0xbb4596f5e389ede6 +435, 0xdfbb3da5441e6923 +436, 0x35bf9ee561580153 +437, 0x3c401b162f4a4479 +438, 0xbba8e9feab108d71 +439, 0x78c15ec1926e3d40 +440, 0x24c54d5604a9fb4d +441, 0x3d65e97ac30dd152 +442, 0x3ff106c26e925fa1 +443, 0x994d0fc4273e547f +444, 0x9348554463808d14 +445, 0x16a8f20bbdd24edb +446, 0xcb20c09774c4ce20 +447, 0x83f1b14f2bab7fe1 +448, 0x5b03859915c40093 +449, 0xc578aeb49ce9ecf9 +450, 0xb51d25e52cfa85f1 +451, 0x58781d91ce35247 +452, 0xcd4222374d4e7eb8 +453, 0xbe7bc2cd6690b2e9 +454, 0x2f56338457305032 +455, 0xa5e696a2c3010178 +456, 0x249bb58b22f4bfb0 +457, 0xf439f41bd99cf89a +458, 0xff4987ee68c91e95 +459, 0x496a634e8032a27d +460, 0x8571dd7ba26413d5 +461, 0xec112e9e23f14e63 +462, 0xcff790437f3c20ed +463, 0xa67b9fa0db0aa231 +464, 0x765cc90556d15624 +465, 0x8683c3dd207422ab +466, 0xff2d139be6499b33 +467, 0x72d02be5b40ad6aa +468, 0x8f6d1c4265a58b12 +469, 0x9f0cb4e8a53cb479 +470, 0x85d4cd253510301b +471, 0x3ef6422a20e34ec9 +472, 0x2b510e1f5ec6f97e +473, 0x46a2e5b35fb78706 +474, 0x506a027d4e2205f5 +475, 0x36de7c336f2c9a05 +476, 0x86fbe1c3ea00a2de +477, 0xeec25bddc61238c9 +478, 0xf02b9c043c956a05 +479, 0x6b13b95622a9807b +480, 0x2a9e68f100ee409 +481, 0x41d3ad00d81683f1 +482, 0x8a4b386910e89455 +483, 0x7ab9f9fa2285614b +484, 0x359c0b462d735de9 +485, 0x3b4cc9b3c45ff686 +486, 0x36efe94862f105a1 +487, 0x8b425f27f3996c8c +488, 0x396750b5141990c0 +489, 0x95e8016fd8be3b03 +490, 0x76fc07ca93fa58d9 +491, 0x846bb14c645b0c75 +492, 0xa605cfb398297aac +493, 0x19e42af61faaefcd +494, 0x8fbc9c5be2370b9 +495, 0xfabb6a708b774c92 +496, 0x24e23045a7ccb7e6 +497, 0x84caca37453c53a7 +498, 0x9fbe0deda0ab217a +499, 0xf41cce8970ac144b +500, 0x8e8a33acaab17e59 +501, 0x846608d05c9b73fe +502, 0xb32c80a1c82fcc1b +503, 0x89c4d0ea85766f75 +504, 0x99405647ddcb348c +505, 0x1e831b51204b7a63 +506, 0xfd8bf1b743791185 +507, 0xde489c75cda83196 +508, 0xd579f8a2c70628f1 +509, 0x60e4bb07af5ace5d +510, 0x262843c44883481d +511, 0x992a22735ab308c9 +512, 0x74de79ece0a914b0 +513, 0xd4a3ff83127baf97 +514, 0x23dc69bcc5fe770d +515, 0x58f3497d5a9ad653 +516, 0x58ed53ecb7a64cb0 +517, 0x6ee92d9763d37f9e +518, 0x7f6f9fbf877b0164 +519, 0x7139eeb4b3c482bd +520, 0x197316b659bf8834 +521, 0xc28a627d979022f6 +522, 0x85ae4049d8ad47fb +523, 0x11c9516d4ae13e22 +524, 0xaccdffbd16f33d28 +525, 0x68882afaea90ca13 +526, 0x7e6c6fe98874f58 +527, 0xa2aac5489c8ab7cc +528, 0x3978eabb2543d737 +529, 0xa17c62e45a3fe296 +530, 0x6eb109d81c9224d8 +531, 0x49e550d7a5f68291 +532, 0x550c48610a266785 +533, 0x717df8f6f8c4c714 +534, 0x6c9171ae4c97ebc5 +535, 0x9248555f2e938277 +536, 0xeee197be9a685e21 +537, 0x23b10d152729c79e +538, 0xd99a0e35e22c02c5 +539, 0xb2a229086a71360a +540, 0xb53ad493eca7e4d8 +541, 0xdce4c80cc7b59a25 +542, 0x1d0f7a0a78f628bd +543, 0xebf4133a6b4da324 +544, 0x1c6a43aaa8a28e82 +545, 0x417512b9c8c332fe +546, 0xb82c515788d7474e +547, 0x58d8b6d62366b9a9 +548, 0x417383f667b82e5d +549, 0x5065df19d5156876 +550, 0x45f7a177dce0ae19 +551, 0x51bb2b6e4b99b7d0 +552, 0x607a99fb8d715e92 +553, 0x5f8ae53d33601b03 +554, 0x555a8aa2cf4dbe8c +555, 0x5fe3af983f2dd205 +556, 0x340b495f8d7f771d +557, 0x5b1efc807762ee26 +558, 0xbe0f72f3f2b2529c +559, 0xec1b0691d58149a7 +560, 0x97e7874c9af94cf1 +561, 0x7da8f0dca84401eb +562, 0xc4c0f0da6a25bdfa +563, 0x1d1b16f1a51b9535 +564, 0x805482e682b26d71 +565, 0x2b6f9a35fee36ca1 +566, 0x57ef4cb20da96729 +567, 0x261932d0691874e6 +568, 0x314883c0836ac0e3 +569, 0x1f831417a3c49289 +570, 0xaded4280fb377fa3 +571, 0x43bc2d0eb4fe43c7 +572, 0xc1d71eefdfe9cea4 +573, 0xa876eba383515868 +574, 0x994d9fcf3142f08 +575, 0x8f10d482bda9d35c +576, 0xd4a386334c346cc3 +577, 0x410ea73faef00896 +578, 0x2b19d1288b764b7c +579, 0x73d80efec82579b6 +580, 0x79fe50849dd6db16 +581, 0x99d073390884e5b5 +582, 0xb656c4f5b7d8c251 +583, 0x265f1a55f456463 +584, 0x3ca410702fe4f733 +585, 0x838c4431205583ff +586, 0x1223f9eca84c7513 +587, 0x68ab8b0bde2f7e5c +588, 0x6ea394530b224537 +589, 0x9ef5afd2667e6cf0 +590, 0x3f6ea8a19a50ba0c +591, 0x5f279dd237a1e3a9 +592, 0x7c4cee031b6361c6 +593, 0x9646a6547ac7b2b9 +594, 0x3ff18f84973f81aa +595, 0x9ddf4b58616f4374 +596, 0xd484e12a4d9c6c08 +597, 0xf6df9d6cbbfacdfb +598, 0xa55f08713250cbbe +599, 0xdcbc45f59afd73e3 +600, 0xa6c1b651ac0b5b8 +601, 0xdb57ae1da9226710 +602, 0x2a825af2f9016875 +603, 0x5634e077906a70f5 +604, 0xcfe76fb8a918b9af +605, 0x96a65ede52b0f259 +606, 0x3b1ea564eaf66326 +607, 0x42ecb562ebd36e80 +608, 0xeefe615d1df23980 +609, 0xd6c79be5c011e807 +610, 0x22e39b0698f93131 +611, 0xa5d5cafff6e1dc41 +612, 0x8f2b02fe6f4a3c06 +613, 0x207edba6a1336b20 +614, 0x363262b62a0d36c7 +615, 0x295ec0d93e112449 +616, 0x83c1f7c6b1b985e5 +617, 0xc02a5c40cdb4d615 +618, 0x23a73f3c52eb8f32 +619, 0x62cc20f4d6e11dd8 +620, 0x766166e1da546d7c +621, 0x9d16d9030c9cfb84 +622, 0xaefc85375fa75d91 +623, 0xba77a56d0ea4ba13 +624, 0x39a31a730e0687d7 +625, 0xe3a57f64109f562d +626, 0x1d74491bd9d29388 +627, 0xa6c5f561a185dfb +628, 0x633992b1c0d3fe44 +629, 0xee814a1280651a2c +630, 0xe2f2b54ae6a45ded +631, 0xf391217301365d25 +632, 0xbb76dda0270a6006 +633, 0x3b48ecebee5b9bce +634, 0x6d06438edf209241 +635, 0x357ba920e8b1997d +636, 0x6041cf82c985d9e1 +637, 0x26e199481a8f8370 +638, 0x402bef99c898c7ad +639, 0xaf537688258ece78 +640, 0x8bd65a5e42349fc1 +641, 0x966d6db227125e56 +642, 0x1c2bf537dbdf6a18 +643, 0xf882d51b88effda7 +644, 0x7934750e1ff84314 +645, 0x5d3a2ef7b201a299 +646, 0x43a1c0074fc7f3b2 +647, 0xe4ac4fa8e80ea889 +648, 0x7edcb91435ab94e4 +649, 0xbfc1dd08ddf7a0f +650, 0x14952561bbe706d6 +651, 0x76ff2246de9054bb +652, 0x164e716d44262e2 +653, 0xa2f0f0863f249aaa +654, 0x306df43087c5eab3 +655, 0x9e082542ffd2eac6 +656, 0x15371e1c1c88ef39 +657, 0x88380af1bbcb80bb +658, 0x6970f2d4e27e8997 +659, 0x7852aa8ba9e1d9bd +660, 0x353e12a671e73337 +661, 0xad43311c6ad719de +662, 0xb650a6d41913f4b0 +663, 0x1970174855d8058d +664, 0x8bb04033e9ae7065 +665, 0xac845cd23eeaf4ae +666, 0x75a264443291a7d4 +667, 0xab2b59c9ff6a40ca +668, 0x55733ca31b6413f6 +669, 0x6646ece8a89f9a74 +670, 0x318b0f83763269b1 +671, 0x285718955e9e5eda +672, 0xbe635b7f41321ba5 +673, 0x5208b1776231474b +674, 0x77f3df408394f208 +675, 0xd65a9dd028a3be77 +676, 0xb870f9a5a396b5de +677, 0x171038f25bc6ac14 +678, 0x99080d183e6246a5 +679, 0xe6260240b3509008 +680, 0xa0d3d2b8e1e5c4ff +681, 0x361a2692ef38fc0d +682, 0x907f5f272f8cc40a +683, 0x69fe3e0760201193 +684, 0x376118679943bc68 +685, 0xb137d0ab55d55d9d +686, 0x93f13b625502297 +687, 0xa49ed908d712453f +688, 0xbc215abe4adbf771 +689, 0x6a8e285265915d23 +690, 0xb838f15249c88f2d +691, 0xfd0fe93ee175e160 +692, 0xa86c8a70a0f1efb +693, 0xe2385851319e2d35 +694, 0xa0109f10353a584d +695, 0x63d54fde29ca316f +696, 0x6101dbcb043a06f9 +697, 0xceaa0b0a69440ce5 +698, 0x33e883a6b04e5103 +699, 0xee1b5ff43e231092 +700, 0xb427baf113599501 +701, 0x12b2317e71c6f9e8 +702, 0x1e3b122a92d24b36 +703, 0xc48ac99bd429a525 +704, 0xb07d638ce8aa1535 +705, 0x84c65dcac2b974ca +706, 0xdb4c47b0ec83241c +707, 0xed92b08dcb8c8bdb +708, 0xc9ea8ecb281d5a28 +709, 0xfa0b3e63ea37fd67 +710, 0x228ff7b873098379 +711, 0x77d6f7cf9c6e7bda +712, 0x8fe3f2b9ace02ffd +713, 0x2384ac4a406dcbe2 +714, 0x1fdce3138708f093 +715, 0xd34e85210c534b21 +716, 0xf8916e32dbfabbda +717, 0xb86418c0e2a753f2 +718, 0x98aaf36286e26ede +719, 0x66167e59c5d5a36b +720, 0x4c4d4c520ab6ae3a +721, 0xe83dcbe740d700cf +722, 0xafdbf579b9bfd667 +723, 0x2ae659b5e10ed7c4 +724, 0x7aa4d22f99423301 +725, 0x62c315f474195042 +726, 0x7c9212e3389c5959 +727, 0xa1f58e637d2c5a05 +728, 0xa0bb57dfd563a2ea +729, 0xb1ba41472dc9907a +730, 0x4355e0abae1b4e2b +731, 0x7831551c86ba472c +732, 0x6377246eb9c563c1 +733, 0xc33cca358031cd73 +734, 0x1a3df433adc587b9 +735, 0x959e58590ac04430 +736, 0x551713647091eb40 +737, 0xf15b81000b87a230 +738, 0x3c73394683730b04 +739, 0xc5ecf4d9c0d365a6 +740, 0x3cf3bb6f48141888 +741, 0xebd1e9e53e18117a +742, 0xa61d9146dcf3de9 +743, 0x9f64cf0611d26ff5 +744, 0xbea8440eee55a206 +745, 0x77426a4854f7dc77 +746, 0x415be11a6b4b34f8 +747, 0xbea05b3645aaf507 +748, 0x57d73bee3328d944 +749, 0x96c76260dae635b7 +750, 0xbbac81463c836e7a +751, 0x687822e5d4be6aed +752, 0xe3a0256c9e82d869 +753, 0x87efe94616042e3b +754, 0x127ecd55502079e0 +755, 0xdeed29e6ad9d3e5e +756, 0xd0f2b4d2fff9819f +757, 0x2c8ae834d48257d0 +758, 0x1f3aa79b5cd2cf52 +759, 0x693344b041cd0a74 +760, 0xe274c86488294f4 +761, 0x6a72fe61886a1d90 +762, 0xf7ec995387d51db +763, 0xc8f89ee89a223b6f +764, 0xc18a8258219c435b +765, 0xd2b83efbe2cb4fb3 +766, 0xf641b18d7ac141bc +767, 0x749d69c6371218c3 +768, 0x9435604b36073ca2 +769, 0x108bef88ea3a207 +770, 0x755776561f260626 +771, 0x4427e10b7c01c9da +772, 0xe503a94f8c3736bb +773, 0x4af8b8388166989e +774, 0xded90567abb2ee96 +775, 0x2337907e762a4f7 +776, 0x281fbe8330c24237 +777, 0x9d05969f770ba3b6 +778, 0x5b14db87a3978c1f +779, 0x1aca424488742d16 +780, 0xea3d971ce98124af +781, 0x5a45029209753fc5 +782, 0x551db2424e7892d +783, 0x55c5e85b29fa995b +784, 0x6f9b5885dae0bb3b +785, 0x40c269f378668751 +786, 0x31db833ffc89d7b4 +787, 0x54360752ef548928 +788, 0xde47ece2daf0f4c4 +789, 0x705c2f3be27845a9 +790, 0xdddd3a82ef299df0 +791, 0x24f914ca137e58c1 +792, 0xf737cd929f8a0b74 +793, 0x61642bf1f0f67553 +794, 0xf8876f5d9aaef9e2 +795, 0x766d2cb707ad74f2 +796, 0xf44c1e3d1083a1 +797, 0x996635c0d00e9fe0 +798, 0xefebf35270fa64c5 +799, 0x7db96619def7e9c0 +800, 0xf331b2e18b743845 +801, 0x62a2f25ec518575e +802, 0x31c3681a727de50f +803, 0xf98c015a5a1c54fb +804, 0x743bd3b5fbec0062 +805, 0xf3dc863a7f8b7ab6 +806, 0x839b8142fa0abd9f +807, 0xa641d1b43d37b18a +808, 0xb71faae321765fd +809, 0x2ec5a90aa7b571f0 +810, 0x89764721520044c0 +811, 0xf231a2e03edf49ba +812, 0xa1579465ebb9cdd +813, 0xfcb73c83c8438163 +814, 0x1aecf871e3e78339 +815, 0xe4466ba1de623b9a +816, 0xfab6458b9a8b7425 +817, 0xd08a56b73b9c289e +818, 0x821d2fcc13b84a8f +819, 0xbfb8842df2e876f1 +820, 0x94682890433e1e78 +821, 0x6a06072528ac8590 +822, 0xc408544d50b3b450 +823, 0x808753793fb29a6e +824, 0xabf989d4fa6b4087 +825, 0x796eacee17b0dc9b +826, 0xf6a77ae26e88dbac +827, 0x2fa97a02950c054f +828, 0xc711f4f82d4a6bb5 +829, 0x9caf50bbb28c3998 +830, 0x3bb92e640c99b657 +831, 0xbd888a8215f757f7 +832, 0xb75989e611a773b2 +833, 0x566399962d08ee5 +834, 0xf71d630e51443477 +835, 0xa0e3179e50dca26a +836, 0xebaf61a44eacc2c +837, 0xd5a358ff51aba185 +838, 0x3ea9c5e748d7ef7d +839, 0x897d6f8d03cd8cfe +840, 0xbedff90968cc3d94 +841, 0x87c5d60ba0e32b94 +842, 0x77898f21c70aa1a5 +843, 0xf02536e75c4381a4 +844, 0x4846df09787df4b0 +845, 0x4228b5bbc1e7137b +846, 0x87591acaee0d2b2a +847, 0x1094db803d6a2294 +848, 0x351bd6517744343d +849, 0xc6b66f7b4ab87e27 +850, 0xa138357faf31fffa +851, 0x3412ebb334d67bf9 +852, 0x831e1dbb632ff45d +853, 0xb008f6fa331ac5c4 +854, 0x9e22b7aef7223f2c +855, 0xc460a6aa5002f154 +856, 0xf353a66ff09b0a26 +857, 0xd5254e93c6a14abe +858, 0x4f72ff6246201214 +859, 0x10c1343f8a78f3e9 +860, 0x33b25deced647ff3 +861, 0x1a1f8abfd8907972 +862, 0x5a6278a9f7ed8433 +863, 0x7a40269035528530 +864, 0x7ef16d32772d58ce +865, 0x8252729ff8c33aed +866, 0x436c4d77c6bf0e2e +867, 0x5fd97535df293b19 +868, 0x8fde6dc6be9469b2 +869, 0xfaba1ba4fdb254d2 +870, 0x1d517806e45f2257 +871, 0xa040c894d9b0d308 +872, 0x48f32da1e1f879fb +873, 0xba444bb3081a8225 +874, 0x51e174f14631ce31 +875, 0x4b0eade95134975c +876, 0x5189f935656f29ab +877, 0x30c58e655faafb4f +878, 0x371996d1e3ac1806 +879, 0x953ae118b4e7385a +880, 0x7169becb6a7701a7 +881, 0x65c138388881dd6a +882, 0x9facc10f2cde5ac8 +883, 0xd80e3d6e2a953134 +884, 0xd410f904163c2a4a +885, 0x73a836e050f95de8 +886, 0x1a03a8183edcd8cd +887, 0x46ae001eec388186 +888, 0xeea3aa51afca2103 +889, 0x7af3b7ac380c934e +890, 0x7ca100978bbea8a8 +891, 0x8231c46ea318f711 +892, 0xe848e769f59373d4 +893, 0xae4823022d3452a7 +894, 0xc8bd326d8092a1a6 +895, 0x9e0ae695cae65d4b +896, 0x95e760a060655036 +897, 0x6fb7c9035c3ad544 +898, 0xcade3a08dea3432f +899, 0xad47f39e3fdb2ece +900, 0x41cdb1fb154826f6 +901, 0xb55de258f6727990 +902, 0x1c547ad05236f8da +903, 0xb6d373042359f1d +904, 0xdb9aad9d0f6549e2 +905, 0x6f09843e435c9d18 +906, 0x4b15fdd5f152bbc0 +907, 0xe9423d09f9d91535 +908, 0x8eb6dd3e2e87aebc +909, 0x7a8583a8124b1741 +910, 0xe6d5ce1819791a58 +911, 0x5d362b7f66fccbec +912, 0xc737676690fa26ea +913, 0x832aa877e040d398 +914, 0xe1aab8a68d879f2b +915, 0x8939c5616a219730 +916, 0x7e2ebccbd4019680 +917, 0xd86f3e4cb2a2f76 +918, 0xd82d4bb2eb375edc +919, 0x737d7bdf10e00e90 +920, 0x3764d163ed0a417f +921, 0xe06f90beaefb963a +922, 0xa74d750318857241 +923, 0xf804ecbcb5c25c8 +924, 0xbf9b027357f99374 +925, 0x2e5b2d58d1144a08 +926, 0xfa7ce04633c5cac2 +927, 0x4eb7775c4e9ee4e5 +928, 0x65457f52533039f0 +929, 0x5182d68bf085853c +930, 0xdcf362534f2b4616 +931, 0xee7ccedf18c95a68 +932, 0x691f8ff9750b925 +933, 0x3d82b8e8d8fc31fb +934, 0x85c0bb0f4b4a112f +935, 0xe95df77752e5e173 +936, 0x3605e7d61fb76af5 +937, 0x60335d8c6cbf6988 +938, 0x2b5a314000327ed5 +939, 0xca0cffe76d1778e6 +940, 0xd6033f0b2e789355 +941, 0x8f90a41a4fdfcc53 +942, 0xcb2b7cfc32976d3f +943, 0xce14afa2b8fb65b2 +944, 0x94a561aba9fe7cf +945, 0xf1c0bc3b71900acf +946, 0x47d384605f859409 +947, 0xb2becb4cb5ebb62f +948, 0x6080faf5ce884092 +949, 0x870ba05eb5ae8340 +950, 0x32116515ddc7e7cd +951, 0xc40857c60e3dba4a +952, 0x4e1e70e385c9c86e +953, 0xa8a36df8f9ec77b8 +954, 0x7ae475e0af4c4883 +955, 0xf60a62a9b8e92e66 +956, 0x9b4fb6700726b37f +957, 0xf30871c82b621163 +958, 0x87fa839419a1b038 +959, 0x7c70f09e12e5c9c6 +960, 0x2a55a6b0700f191e +961, 0xc5319239b1cb6247 +962, 0x5b3d7daa4da4d79d +963, 0xc845b957a849bf3e +964, 0x8ab82092c3b8ea4e +965, 0xe4d3330f64e85823 +966, 0x8b4359b012bf4ec7 +967, 0x94f2ae8fc8a645c2 +968, 0xe1c16a64d7ccb7d5 +969, 0xf7ab947c49dd9053 +970, 0x3ffe0e57136f4933 +971, 0x8378e36e4fdda387 +972, 0xbb3e9622b0527aa2 +973, 0x754dfcf2de3400df +974, 0x73b47f3626ed9d1b +975, 0xe056dc83a126f693 +976, 0xf9c646b99afe77f +977, 0x20d89f4d3b7ea72a +978, 0x82d8b24230c46c2a +979, 0x9ba818f53341aad3 +980, 0x4a0e781a1646ea64 +981, 0xc7d87a350ff43d7a +982, 0xc396afe3eab47776 +983, 0x6a61f73b628e8892 +984, 0x60e383f172e15eeb +985, 0x9722fdbd2a03b13e +986, 0xfd634049374a2628 +987, 0xf9863806fbc39457 +988, 0xc83f2fc42eca9f +989, 0x16d1bfdf49fc98f0 +990, 0xa28f80d5c410cd30 +991, 0xe94f58e03cbdf4ee +992, 0xe5ad5ccde4a99bb3 +993, 0x482c3dfa3bc71d3b +994, 0x75fee65a654d5c0a +995, 0x6aa16a97c454a20d +996, 0xfbe5549c65d74c76 +997, 0xa2292c465994cb9b +998, 0x5d1d10d51694d4d1 +999, 0x40e57b3aa1059716 diff --git a/_randomgen/core_prng/tests/test_against_numpy.py b/_randomgen/core_prng/tests/test_against_numpy.py new file mode 100644 index 000000000000..6bd4bc0912ac --- /dev/null +++ b/_randomgen/core_prng/tests/test_against_numpy.py @@ -0,0 +1,535 @@ +import numpy as np +import numpy.random +import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_equal + +from core_prng import RandomGenerator, MT19937 + + +def compare_0_input(f1, f2): + inputs = [(tuple([]), {}), (tuple([]), {'size': 10}), + (tuple([]), {'size': (20, 31)}), + (tuple([]), {'size': (20, 31, 5)})] + + +def compare_1_input(f1, f2, is_small=False, core_prng_kwargs=None): + if core_prng_kwargs is None: + core_prng_kwargs = {} + a = 0.3 if is_small else 10 + inputs = [((a,), {}), + ((a,), {'size': 10}), + ((np.array([a] * 10),), {}), + ((np.array([a] * 10),), {'size': 10}), + ((np.array([a] * 10),), {'size': (100, 10)})] + for i in inputs: + v1 = f1(*i[0], **i[1]) + i[1].update(core_prng_kwargs) + v2 = f2(*i[0], **i[1]) + assert_allclose(v1, v2) + + +def compare_2_input(f1, f2, is_np=False, is_scalar=False, core_prng_kwargs=None): + if core_prng_kwargs is None: + core_prng_kwargs = {} + if is_np: + a, b = 10, 0.3 + dtype = np.int + else: + a, b = 2, 3 + dtype = np.double + inputs = [((a, b), {}), + ((a, b), {'size': 10}), + ((a, b), {'size': (23, 7)}), + ((np.array([a] * 10), b), {}), + ((a, np.array([b] * 10)), {}), + ((a, np.array([b] * 10)), {'size': 10}), + ((np.reshape(np.array([[a] * 100]), (100, 1)), np.array([b] * 10)), {'size': (100, 10)}), + ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (7, 31)}), + ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (10, 7, 31)})] + + if is_scalar: + inputs = inputs[:3] + + for i in inputs: + v1 = f1(*i[0], **i[1]) + i[1].update(core_prng_kwargs) + v2 = f2(*i[0], **i[1]) + assert_allclose(v1, v2) + + +def compare_3_input(f1, f2, is_np=False): + a, b, c = 10, 20, 25 + inputs = [((a, b, c), {}), + ((a, b, c), {'size': 10}), + ((a, b, c), {'size': (23, 7)}), + ((np.array([a] * 10), b, c), {}), + ((a, np.array([b] * 10), c), {}), + ((a, b, np.array([c] * 10)), {}), + ((a, np.array([b] * 10), np.array([c] * 10)), {}), + ((a, np.array([b] * 10), c), {'size': 10}), + ((np.ones((1, 37), dtype=np.int) * a, + np.ones((23, 1), dtype=np.int) * [b], + c * np.ones((7, 1, 1), dtype=np.int)), + {}), + ((np.ones((1, 37), dtype=np.int) * a, + np.ones((23, 1), dtype=np.int) * [b], + c * np.ones((7, 1, 1), dtype=np.int)), + {'size': (7, 23, 37)}) + ] + + for i in inputs: + v1 = f1(*i[0], **i[1]) + v2 = f2(*i[0], **i[1]) + assert_allclose(v1, v2) + + +class TestAgainstNumPy(object): + @classmethod + def setup_class(cls): + cls.np = numpy.random + cls.prng = MT19937 + cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.nprs = cls.np.RandomState(*cls.seed) + cls.initial_state = cls.rg.state + cls._set_common_state() + + @classmethod + def _set_common_state(cls): + state = cls.rg.state + st = [[]] * 5 + st[0] = 'MT19937' + st[1] = state['state']['key'] + st[2] = state['state']['pos'] + st[3] = state['has_gauss'] + st[4] = state['gauss'] + cls.nprs.set_state(st) + + def _is_state_common(self): + state = self.nprs.get_state() + state2 = self.rg.state + assert (state[1] == state2['state']['key']).all() + assert (state[2] == state2['state']['pos']) + assert (state[3] == state2['has_gauss']) + assert_allclose(state[4], state2['gauss']) + + def test_common_seed(self): + self.rg.seed(1234) + self.nprs.seed(1234) + self._is_state_common() + self.rg.seed(23456) + self.nprs.seed(23456) + self._is_state_common() + + def test_numpy_state(self): + nprs = np.random.RandomState() + nprs.standard_normal(99) + state = nprs.get_state() + self.rg.state = state + state2 = self.rg.state + assert (state[1] == state2['state']['key']).all() + assert (state[2] == state2['state']['pos']) + assert (state[3] == state2['has_gauss']) + assert (state[4] == state2['gauss']) + + def test_random_sample(self): + self._set_common_state() + self._is_state_common() + v1 = self.nprs.random_sample(10) + v2 = self.rg.random_sample(10) + + assert_array_equal(v1, v2) + + def test_standard_normal(self): + self._set_common_state() + self._is_state_common() + compare_0_input(self.nprs.standard_normal, + self.rg.standard_normal) + self._is_state_common() + + def test_standard_cauchy(self): + self._set_common_state() + self._is_state_common() + compare_0_input(self.nprs.standard_cauchy, + self.rg.standard_cauchy) + self._is_state_common() + + def test_standard_exponential(self): + self._set_common_state() + self._is_state_common() + compare_0_input(self.nprs.standard_exponential, + self.rg.standard_exponential) + self._is_state_common() + + def test_tomaxint(self): + self._set_common_state() + self._is_state_common() + compare_0_input(self.nprs.tomaxint, + self.rg.tomaxint) + self._is_state_common() + + def test_chisquare(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.chisquare, + self.rg.chisquare) + self._is_state_common() + + def test_standard_gamma(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.standard_gamma, + self.rg.standard_gamma, + core_prng_kwargs={'method':'inv'}) + self._is_state_common() + + def test_standard_t(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.standard_t, + self.rg.standard_t) + self._is_state_common() + + def test_pareto(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.pareto, + self.rg.pareto) + self._is_state_common() + + def test_poisson(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.poisson, + self.rg.poisson) + self._is_state_common() + + def test_power(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.power, + self.rg.power) + self._is_state_common() + + def test_rayleigh(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.rayleigh, + self.rg.rayleigh) + self._is_state_common() + + def test_weibull(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.weibull, + self.rg.weibull) + self._is_state_common() + + def test_zipf(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.zipf, + self.rg.zipf) + self._is_state_common() + + def test_logseries(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.logseries, + self.rg.logseries, + is_small=True) + self._is_state_common() + + def test_zipf(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.geometric, + self.rg.geometric, + is_small=True) + self._is_state_common() + + def test_beta(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.beta, + self.rg.beta) + self._is_state_common() + + def test_exponential(self): + self._set_common_state() + self._is_state_common() + compare_1_input(self.nprs.exponential, + self.rg.exponential) + self._is_state_common() + + def test_f(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.f, + self.rg.f) + self._is_state_common() + + def test_gamma(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.gamma, + self.rg.gamma) + self._is_state_common() + + def test_logistic(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.logistic, + self.rg.logistic) + self._is_state_common() + + def test_gumbel(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.gumbel, + self.rg.gumbel) + self._is_state_common() + + def test_laplace(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.laplace, + self.rg.laplace) + self._is_state_common() + + def test_lognormal(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.lognormal, + self.rg.lognormal) + self._is_state_common() + + def test_noncentral_chisquare(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.noncentral_chisquare, + self.rg.noncentral_chisquare) + self._is_state_common() + + def test_normal(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.normal, + self.rg.normal, + core_prng_kwargs={'method':'bm'}) + self._is_state_common() + + def test_uniform(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.uniform, + self.rg.uniform) + self._is_state_common() + + def test_vonmises(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.vonmises, + self.rg.vonmises) + self._is_state_common() + + def test_wald(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.wald, + self.rg.wald) + self._is_state_common() + + def test_random_integers(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.random_integers, + self.rg.random_integers, + is_scalar=True) + self._is_state_common() + + def test_binomial(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.binomial, + self.rg.binomial, + is_np=True) + self._is_state_common() + + def test_negative_binomial(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.nprs.negative_binomial, + self.rg.negative_binomial, + is_np=True) + self._is_state_common() + + def test_randn(self): + f = self.rg.randn + g = self.nprs.randn + assert_allclose(f(10, method='bm'), g(10)) + assert_allclose(f(3, 4, 5, method='bm'), g(3, 4, 5)) + + def test_rand(self): + f = self.rg.rand + g = self.nprs.rand + assert_allclose(f(10), g(10)) + assert_allclose(f(3, 4, 5), g(3, 4, 5)) + + @pytest.mark.xfail + def test_poisson_lam_max(self): + assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) + + def test_dirichlet(self): + f = self.rg.dirichlet + g = self.nprs.dirichlet + a = [3, 4, 5, 6, 7, 10] + assert_allclose(f(a), g(a)) + assert_allclose(f(np.array(a), 10), g(np.array(a), 10)) + assert_allclose(f(np.array(a), (3, 37)), g(np.array(a), (3, 37))) + + def test_noncentral_f(self): + self._set_common_state() + self._is_state_common() + compare_3_input(self.nprs.noncentral_f, + self.rg.noncentral_f) + self._is_state_common() + + def test_triangular(self): + self._set_common_state() + self._is_state_common() + compare_3_input(self.nprs.triangular, + self.rg.triangular) + self._is_state_common() + + def test_hypergeometric(self): + self._set_common_state() + self._is_state_common() + compare_3_input(self.nprs.hypergeometric, + self.rg.hypergeometric) + self._is_state_common() + + def test_bytes(self): + self._set_common_state() + self._is_state_common() + assert_equal(self.rg.bytes(8), self.nprs.bytes(8)) + self._is_state_common() + assert_equal(self.rg.bytes(103), self.nprs.bytes(103)) + self._is_state_common() + assert_equal(self.rg.bytes(8), self.nprs.bytes(8)) + self._is_state_common() + + def test_multinomial(self): + self._set_common_state() + self._is_state_common() + f = self.rg.multinomial + g = self.nprs.multinomial + p = [.1, .3, .4, .2] + assert_equal(f(100, p), g(100, p)) + assert_equal(f(100, np.array(p)), g(100, np.array(p))) + assert_equal(f(100, np.array(p), size=(7, 23)), g(100, np.array(p), size=(7, 23))) + self._is_state_common() + + def test_choice(self): + self._set_common_state() + self._is_state_common() + f = self.rg.choice + g = self.nprs.choice + a = np.arange(100) + size = 25 + for replace in (True, False): + assert_equal(f(a, size, replace), g(a, size, replace)) + assert_equal(f(100, size, replace), g(100, size, replace)) + self._is_state_common() + + def test_permutation(self): + self._set_common_state() + self._is_state_common() + f = self.rg.permutation + g = self.nprs.permutation + a = np.arange(100) + assert_equal(f(a), g(a)) + assert_equal(f(23), g(23)) + self._is_state_common() + + def test_shuffle(self): + self._set_common_state() + self._is_state_common() + f = self.rg.shuffle + g = self.nprs.shuffle + a = np.arange(100) + fa = a.copy() + ga = a.copy() + g(ga) + f(fa) + assert_equal(fa, ga) + self._is_state_common() + + def test_multivariate_normal(self): + self._set_common_state() + self._is_state_common() + mu = [1, 2, 3] + cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] + f = self.rg.multivariate_normal + g = self.nprs.multivariate_normal + assert_allclose(f(mu, cov, method='bm'), g(mu, cov)) + assert_allclose(f(np.array(mu), cov, method='bm'), g(np.array(mu), cov)) + assert_allclose(f(np.array(mu), np.array(cov), method='bm'), + g(np.array(mu), np.array(cov))) + assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31), method='bm'), + g(np.array(mu), np.array(cov), size=(7, 31))) + self._is_state_common() + + def test_randint(self): + self._set_common_state() + self._is_state_common() + compare_2_input(self.rg.randint, + self.nprs.randint, + is_scalar=True) + self._is_state_common() + + def test_scalar(self): + s = RandomGenerator(MT19937(0)) + assert_equal(s.randint(1000), 684) + s1 = np.random.RandomState(0) + assert_equal(s1.randint(1000), 684) + assert_equal(s1.randint(1000), s.randint(1000)) + + s = RandomGenerator(MT19937(4294967295)) + assert_equal(s.randint(1000), 419) + s1 = np.random.RandomState(4294967295) + assert_equal(s1.randint(1000), 419) + assert_equal(s1.randint(1000), s.randint(1000)) + + self.rg.seed(4294967295) + self.nprs.seed(4294967295) + self._is_state_common() + + def test_array(self): + s = RandomGenerator(MT19937(range(10))) + assert_equal(s.randint(1000), 468) + s = np.random.RandomState(range(10)) + assert_equal(s.randint(1000), 468) + + s = RandomGenerator(MT19937(np.arange(10))) + assert_equal(s.randint(1000), 468) + s = RandomGenerator(MT19937([0])) + assert_equal(s.randint(1000), 973) + s = RandomGenerator(MT19937([4294967295])) + assert_equal(s.randint(1000), 265) + + def test_dir(self): + nprs_d = set(dir(self.nprs)) + rs_d = dir(self.rg) + excluded = {'get_state', 'poisson_lam_max','set_state'} + nprs_d.difference_update(excluded) + assert (len(nprs_d.difference(rs_d)) == 0) + + # npmod = dir(numpy.random) + # mod = dir(randomstate) + # known_exlcuded = ['__all__', 'Tester', 'info', 'bench', + # '__RandomState_ctor', 'mtrand', 'test', + # '__warningregistry__', '_numpy_tester'] + # mod += known_exlcuded + # diff = set(npmod).difference(mod) + # assert_equal(len(diff), 0) diff --git a/_randomgen/core_prng/tests/test_direct.py b/_randomgen/core_prng/tests/test_direct.py new file mode 100644 index 000000000000..9496cc1916f9 --- /dev/null +++ b/_randomgen/core_prng/tests/test_direct.py @@ -0,0 +1,373 @@ +import os +import sys +from os.path import join + +import numpy as np +from numpy.testing import assert_equal, assert_allclose, assert_array_equal, \ + assert_raises + +from core_prng import * + +if (sys.version_info > (3, 0)): + long = int + +pwd = os.path.dirname(os.path.abspath(__file__)) + + +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_uint63(x): + x = np.uint64(x) + x = np.uint32(x >> np.uint64(32)) + out = (x >> 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 == 63: + return uniform32_from_uint63(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 uint64_from_uint63(x): + out = np.empty(len(x) // 2, dtype=np.uint64) + for i in range(0, len(x), 2): + a = x[i] & np.uint64(0xffffffff00000000) + b = x[i + 1] >> np.uint64(32) + out[i // 2] = a | b + 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) + elif 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] + + +class Base(object): + dtype = np.uint64 + data2 = data1 = {} + + @classmethod + def setup_class(cls): + cls.prng = Xoroshiro128 + cls.bits = 64 + cls.dtype = np.uint64 + cls.seed_error_type = TypeError + + @classmethod + def _read_csv(cls, filename): + with open(filename) as csv: + seed = csv.readline() + seed = seed.split(',') + seed = [long(s.strip(), 0) for s in seed[1:]] + data = [] + for line in csv: + data.append(long(line.split(',')[-1].strip(), 0)) + return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)} + + def test_raw(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + uints = rs.random_raw(1000) + assert_equal(uints, self.data1['data']) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + uints = rs.random_raw(1000) + assert_equal(uints, self.data2['data']) + + def test_gauss_inv(self): + n = 25 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + gauss = rs.standard_normal(n, method='bm') + assert_allclose(gauss, + gauss_from_uint(self.data1['data'], n, self.bits)) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + gauss = rs.standard_normal(25, method='bm') + assert_allclose(gauss, + gauss_from_uint(self.data2['data'], n, self.bits)) + + def test_uniform_double(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + vals = uniform_from_uint(self.data1['data'], self.bits) + uniforms = rs.random_sample(len(vals)) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float64) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + vals = uniform_from_uint(self.data2['data'], self.bits) + uniforms = rs.random_sample(len(vals)) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float64) + + def test_uniform_float(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + vals = uniform32_from_uint(self.data1['data'], self.bits) + uniforms = rs.random_sample(len(vals), dtype=np.float32) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float32) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + vals = uniform32_from_uint(self.data2['data'], self.bits) + uniforms = rs.random_sample(len(vals), dtype=np.float32) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float32) + + def test_seed_float(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.seed, np.pi) + assert_raises(self.seed_error_type, rs.seed, -np.pi) + + def test_seed_float_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) + assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) + assert_raises(ValueError, rs.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.seed, [np.pi]) + assert_raises(TypeError, rs.seed, [0, np.pi]) + + def test_seed_out_of_range(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.seed, -1) + + def test_seed_out_of_range_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(ValueError, rs.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.seed, [-1]) + + +class TestXoroshiro128(Base): + @classmethod + def setup_class(cls): + cls.prng = Xoroshiro128 + cls.bits = 64 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv( + join(pwd, './data/xoroshiro128-testset-1.csv')) + cls.data2 = cls._read_csv( + join(pwd, './data/xoroshiro128-testset-2.csv')) + cls.seed_error_type = TypeError + + +class TestXorshift1024(Base): + @classmethod + def setup_class(cls): + cls.prng = Xorshift1024 + cls.bits = 64 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv( + join(pwd, './data/xorshift1024-testset-1.csv')) + cls.data2 = cls._read_csv( + join(pwd, './data/xorshift1024-testset-2.csv')) + cls.seed_error_type = TypeError + + +class TestThreeFry(Base): + @classmethod + def setup_class(cls): + cls.prng = ThreeFry + cls.bits = 64 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv( + join(pwd, './data/threefry-testset-1.csv')) + cls.data2 = cls._read_csv( + join(pwd, './data/threefry-testset-2.csv')) + cls.seed_error_type = TypeError + + +class TestPhilox(Base): + @classmethod + def setup_class(cls): + cls.prng = 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 + + +class TestMT19937(Base): + @classmethod + def setup_class(cls): + cls.prng = 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 + + def test_seed_out_of_range(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(ValueError, rs.seed, 2 ** (self.bits + 1)) + assert_raises(ValueError, rs.seed, -1) + assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) + + def test_seed_out_of_range_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.seed, [-1]) + assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) + + def test_seed_float(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(TypeError, rs.seed, np.pi) + assert_raises(TypeError, rs.seed, -np.pi) + + def test_seed_float_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(TypeError, rs.seed, np.array([np.pi])) + assert_raises(TypeError, rs.seed, np.array([-np.pi])) + assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.seed, [np.pi]) + assert_raises(TypeError, rs.seed, [0, np.pi]) + + +class TestDSFMT(Base): + @classmethod + def setup_class(cls): + cls.prng = DSFMT + cls.bits = 53 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv(join(pwd, './data/dSFMT-testset-1.csv')) + cls.data2 = cls._read_csv(join(pwd, './data/dSFMT-testset-2.csv')) + cls.seed_error_type = TypeError + + def test_uniform_double(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + aa = uniform_from_dsfmt(self.data1['data']) + assert_array_equal(uniform_from_dsfmt(self.data1['data']), + rs.random_sample(1000)) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + assert_equal(uniform_from_dsfmt(self.data2['data']), + rs.random_sample(1000)) + + def test_gauss_inv(self): + n = 25 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + gauss = rs.standard_normal(n, method='bm') + assert_allclose(gauss, + gauss_from_uint(self.data1['data'], n, 'dsfmt')) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + gauss = rs.standard_normal(25, method='bm') + assert_allclose(gauss, + gauss_from_uint(self.data2['data'], n, 'dsfmt')) + + def test_seed_out_of_range_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.seed, [-1]) + assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) + + def test_seed_float(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(TypeError, rs.seed, np.pi) + assert_raises(TypeError, rs.seed, -np.pi) + + def test_seed_float_array(self): + # GH #82 + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(TypeError, rs.seed, np.array([np.pi])) + assert_raises(TypeError, rs.seed, np.array([-np.pi])) + assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.seed, [np.pi]) + assert_raises(TypeError, rs.seed, [0, np.pi]) + + def test_uniform_float(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + vals = uniform32_from_uint(self.data1['data'], self.bits) + uniforms = rs.random_sample(len(vals), dtype=np.float32) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float32) + + rs = RandomGenerator(self.prng(*self.data2['seed'])) + vals = uniform32_from_uint(self.data2['data'], self.bits) + uniforms = rs.random_sample(len(vals), dtype=np.float32) + assert_allclose(uniforms, vals) + assert_equal(uniforms.dtype, np.float32) diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937.py b/_randomgen/core_prng/tests/test_numpy_mt19937.py new file mode 100644 index 000000000000..3fa936f2f3c1 --- /dev/null +++ b/_randomgen/core_prng/tests/test_numpy_mt19937.py @@ -0,0 +1,1752 @@ +from __future__ import division, absolute_import, print_function + +import sys +import warnings + +import numpy as np +from numpy.testing import ( + run_module_suite, assert_, assert_raises, assert_equal, + assert_warns, assert_no_warnings, assert_array_equal, + assert_array_almost_equal) +import pytest + +from core_prng._testing import suppress_warnings +from core_prng import RandomGenerator, MT19937 + +random = mt19937 = RandomGenerator(MT19937()) + +class TestSeed(object): + def test_scalar(self): + s = RandomGenerator(MT19937(0)) + assert_equal(s.randint(1000), 684) + s = RandomGenerator(MT19937(4294967295)) + assert_equal(s.randint(1000), 419) + + def test_array(self): + s = RandomGenerator(MT19937(range(10))) + assert_equal(s.randint(1000), 468) + s = RandomGenerator(MT19937(np.arange(10))) + assert_equal(s.randint(1000), 468) + s = RandomGenerator(MT19937([0])) + assert_equal(s.randint(1000), 973) + s = RandomGenerator(MT19937([4294967295])) + assert_equal(s.randint(1000), 265) + + 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 32 bit integer + assert_raises(TypeError, MT19937, [-0.5]) + assert_raises(ValueError, MT19937, [-1]) + assert_raises(ValueError, MT19937, [4294967296]) + assert_raises(ValueError, MT19937, [1, 2, 4294967296]) + assert_raises(ValueError, MT19937, [1, -2, 4294967296]) + + +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(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.multinomial(1, p, [2, 2]).shape, (2, 2, 2)) + assert_equal(mt19937.multinomial(1, p, (2, 2)).shape, (2, 2, 2)) + assert_equal(mt19937.multinomial(1, p, np.array((2, 2))).shape, + (2, 2, 2)) + + assert_raises(TypeError, mt19937.multinomial, 1, p, + float(1)) + + +class TestSetState(object): + def setup(self): + self.seed = 1234567890 + self.prng = RandomGenerator(MT19937(self.seed)) + self.state = self.prng.state + self.legacy_state = (self.state['prng'], + self.state['state']['key'], + self.state['state']['pos'], + self.state['has_gauss'], + self.state['gauss']) + + def test_basic(self): + old = self.prng.tomaxint(16) + self.prng.state = self.state + new = self.prng.tomaxint(16) + assert_(np.all(old == new)) + + def test_gaussian_reset(self): + # Make sure the cached every-other-Gaussian is reset. + old = self.prng.standard_normal(size=3) + self.prng.state = self.state + new = self.prng.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.prng.standard_normal() + state = self.prng.state + old = self.prng.standard_normal(size=3) + self.prng.state = state + new = self.prng.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.legacy_state[:-2] + x1 = self.prng.standard_normal(size=16) + self.prng.state = old_state + x2 = self.prng.standard_normal(size=16) + self.prng.state = self.state + x3 = self.prng.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.prng.negative_binomial(0.5, 0.5) + + +class TestRandint(object): + rfunc = mt19937.randint + + # 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): + assert_raises(TypeError, self.rfunc, 1, dtype=float) + + def test_bounds_checking(self): + 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 + 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) + + 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_bounds_checking_array(self): + 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 + assert_raises(ValueError, self.rfunc, [lbnd - 1] * 2, [ubnd] * 2, dtype=dt) + assert_raises(ValueError, self.rfunc, [lbnd] * 2, [ubnd + 1] * 2, dtype=dt) + assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2, dtype=dt) + assert_raises(ValueError, self.rfunc, [1] * 2, 0, dtype=dt) + + def test_rng_zero_and_extremes(self): + 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 + + tgt = ubnd - 1 + assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt) + 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) + 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) + assert_equal(self.rfunc([tgt], [tgt + 1], size=1000, dtype=dt), tgt) + + def test_rng_zero_and_extremes_array(self): + 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 + + 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): + # 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 + + 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_full_range_array(self): + # 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 + + try: + self.rfunc([lbnd] * 2, [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 + mt19937.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=bool) + + assert_(vals.max() < 2) + assert_(vals.min() >= 0) + + def test_scalar_array_equiv(self): + 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 + + size = 1000 + mt19937.seed(1234) + scalar = self.rfunc(lbnd, ubnd, size=size, dtype=dt) + + mt19937.seed(1234) + scalar_array = self.rfunc([lbnd], [ubnd], size=size, dtype=dt) + + mt19937.seed(1234) + array = self.rfunc([lbnd] * size, [ubnd] * size, size=size, dtype=dt) + assert_array_equal(scalar, scalar_array) + assert_array_equal(scalar, array) + + def test_repeatability(self): + 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': '7dd3170d7aa461d201a65f8bcf3944b0', + 'int16': '1b7741b80964bb190c50d541dca1cac1', + 'int32': '4dc9fcc2b395577ebb51793e58ed1a05', + 'int64': '17db902806f448331b5a758d7d2ee672', + 'int8': '27dd30c4e08a797063dffac2490b0be6', + 'uint16': '1b7741b80964bb190c50d541dca1cac1', + 'uint32': '4dc9fcc2b395577ebb51793e58ed1a05', + 'uint64': '17db902806f448331b5a758d7d2ee672', + 'uint8': '27dd30c4e08a797063dffac2490b0be6'} + + for dt in self.itype[1:]: + mt19937.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() + print(tgt[np.dtype(dt).name] == res) + # TODO + # assert_(tgt[np.dtype(dt).name] == res) + + # bools do not depend on endianess + mt19937.seed(1234) + val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8) + res = hashlib.md5(val).hexdigest() + print(tgt[np.dtype(bool).name] == res) + # TODO + # assert_(tgt[np.dtype(bool).name] == res) + + def test_repeatability_broadcasting(self): + + 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 + + # view as little endian for hash + mt19937.seed(1234) + val = self.rfunc(lbnd, ubnd, size=1000, dtype=dt) + + mt19937.seed(1234) + val_bc = self.rfunc([lbnd] * 1000, ubnd, dtype=dt) + + assert_array_equal(val, val_bc) + + mt19937.seed(1234) + val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, dtype=dt) + + assert_array_equal(val, val_bc) + + 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 = mt19937.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 bool else np.iinfo(dt).min + ubnd = 2 if dt is bool else np.iinfo(dt).max + 1 + dt = np.bool_ if dt is bool else dt + + sample = self.rfunc(lbnd, ubnd, 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 + + # 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) + + def test_respect_dtype_array(self): + # 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 + dt = np.bool_ if dt is bool else dt + + sample = self.rfunc([lbnd], [ubnd], dtype=dt) + assert_equal(sample.dtype, dt) + sample = self.rfunc([lbnd] * 2, [ubnd] * 2, dtype=dt) + assert_equal(sample.dtype, dt) + + def test_zero_size(self): + # See gh-7203 + for dt in self.itype: + sample = self.rfunc(0, 0, (3, 0, 4), dtype=dt) + assert sample.shape == (3, 0, 4) + assert sample.dtype == dt + assert self.rfunc(0, -10, 0, dtype=dt).shape == (0,) + + +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): + mt19937.seed(self.seed) + actual = mt19937.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_randn(self): + mt19937.seed(self.seed) + actual = mt19937.randn(3, 2, method='bm') + 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_randint(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + with suppress_warnings() as sup: + w = sup.record(DeprecationWarning) + actual = mt19937.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) + + 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 = mt19937.random_integers(np.iinfo('l').max, + np.iinfo('l').max) + assert_(len(w) == 1) + + desired = np.iinfo('l').max + 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, + mt19937.random_integers, + np.iinfo('l').max) + + # DeprecationWarning raised with high != None + assert_raises(DeprecationWarning, + mt19937.random_integers, + np.iinfo('l').max, np.iinfo('l').max) + + def test_random_sample(self): + mt19937.seed(self.seed) + actual = mt19937.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) + + def test_choice_uniform_replace(self): + mt19937.seed(self.seed) + actual = mt19937.choice(4, 4) + desired = np.array([2, 3, 2, 3]) + assert_array_equal(actual, desired) + + def test_choice_nonuniform_replace(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.choice(4, 3, replace=False) + desired = np.array([0, 1, 3]) + assert_array_equal(actual, desired) + + def test_choice_nonuniform_noreplace(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.choice(['a', 'b', 'c', 'd'], 4) + desired = np.array(['c', 'd', 'c', 'd']) + assert_array_equal(actual, desired) + + def test_choice_exceptions(self): + sample = mt19937.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) + 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(mt19937.choice(2, replace=True))) + assert_(np.isscalar(mt19937.choice(2, replace=False))) + assert_(np.isscalar(mt19937.choice(2, replace=True, p=p))) + assert_(np.isscalar(mt19937.choice(2, replace=False, p=p))) + assert_(np.isscalar(mt19937.choice([1, 2], replace=True))) + assert_(mt19937.choice([None], replace=True) is None) + a = np.array([1, 2]) + arr = np.empty(1, dtype=object) + arr[0] = a + assert_(mt19937.choice(arr, replace=True) is a) + + # Check 0-d array + s = tuple() + assert_(not np.isscalar(mt19937.choice(2, s, replace=True))) + assert_(not np.isscalar(mt19937.choice(2, s, replace=False))) + assert_(not np.isscalar(mt19937.choice(2, s, replace=True, p=p))) + assert_(not np.isscalar(mt19937.choice(2, s, replace=False, p=p))) + assert_(not np.isscalar(mt19937.choice([1, 2], s, replace=True))) + assert_(mt19937.choice([None], s, replace=True).ndim == 0) + a = np.array([1, 2]) + arr = np.empty(1, dtype=object) + arr[0] = a + assert_(mt19937.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_(mt19937.choice(6, s, replace=True).shape, s) + assert_(mt19937.choice(6, s, replace=False).shape, s) + assert_(mt19937.choice(6, s, replace=True, p=p).shape, s) + assert_(mt19937.choice(6, s, replace=False, p=p).shape, s) + assert_(mt19937.choice(np.arange(6), s, replace=True).shape, s) + + def test_bytes(self): + mt19937.seed(self.seed) + actual = mt19937.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-4270 + lambda x: np.asarray([(i, i) for i in x], + [("a", object, 1), + ("b", np.int32, 1)])]: + mt19937.seed(self.seed) + alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) + mt19937.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): + mt19937.shuffle(a) + assert_equal( + sorted(a.data[~a.mask]), sorted(a_orig.data[~a_orig.mask])) + mt19937.shuffle(b) + assert_equal( + sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) + + def test_beta(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.binomial(100.123, .456, size=(3, 2)) + desired = np.array([[37, 43], + [42, 48], + [46, 45]]) + assert_array_equal(actual, desired) + + def test_chisquare(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + alpha = np.array([51.72840233779265162, 39.74494232180943953]) + actual = mt19937.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, mt19937.dirichlet, bad_alpha) + + def test_dirichlet_size(self): + # gh-3173 + p = np.array([51.72840233779265162, 39.74494232180943953]) + assert_equal(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) + assert_equal(mt19937.dirichlet(p, [2, 2]).shape, (2, 2, 2)) + assert_equal(mt19937.dirichlet(p, (2, 2)).shape, (2, 2, 2)) + assert_equal(mt19937.dirichlet(p, np.array((2, 2))).shape, (2, 2, 2)) + + assert_raises(TypeError, mt19937.dirichlet, p, float(1)) + + def test_dirichlet_bad_alpha(self): + # gh-2089 + alpha = np.array([5.4e-01, -1.0e-16]) + assert_raises(ValueError, mt19937.dirichlet, alpha) + + def test_exponential(self): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.exponential(scale=0), 0) + assert_raises(ValueError, mt19937.exponential, scale=-0.) + + def test_f(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.gamma(shape=0, scale=0), 0) + assert_raises(ValueError, mt19937.gamma, shape=-0., scale=-0.) + + def test_geometric(self): + mt19937.seed(self.seed) + actual = mt19937.geometric(.123456789, size=(3, 2)) + desired = np.array([[8, 7], + [17, 17], + [5, 12]]) + assert_array_equal(actual, desired) + + def test_gumbel(self): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.gumbel(scale=0), 0) + assert_raises(ValueError, mt19937.gumbel, scale=-0.) + + def test_hypergeometric(self): + mt19937.seed(self.seed) + actual = mt19937.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 = mt19937.hypergeometric(5, 0, 3, size=4) + desired = np.array([3, 3, 3, 3]) + assert_array_equal(actual, desired) + + actual = mt19937.hypergeometric(15, 0, 12, size=4) + desired = np.array([12, 12, 12, 12]) + assert_array_equal(actual, desired) + + # Test ngood = 0 + actual = mt19937.hypergeometric(0, 5, 3, size=4) + desired = np.array([0, 0, 0, 0]) + assert_array_equal(actual, desired) + + actual = mt19937.hypergeometric(0, 15, 12, size=4) + desired = np.array([0, 0, 0, 0]) + assert_array_equal(actual, desired) + + def test_laplace(self): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.laplace(scale=0), 0) + assert_raises(ValueError, mt19937.laplace, scale=-0.) + + def test_logistic(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.lognormal(sigma=0), 1) + assert_raises(ValueError, mt19937.lognormal, sigma=-0.) + + def test_logseries(self): + mt19937.seed(self.seed) + actual = mt19937.logseries(p=.923456789, size=(3, 2)) + desired = np.array([[2, 2], + [6, 17], + [3, 6]]) + assert_array_equal(actual, desired) + + def test_multinomial(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + mean = (.123456789, 10) + cov = [[1, 0], [0, 1]] + size = (3, 2) + actual = mt19937.multivariate_normal(mean, cov, size, method='bm') + 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 = mt19937.multivariate_normal(mean, cov, method='bm') + 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, mt19937.multivariate_normal, mean, cov, method='bm') + + # and that it doesn't warn with RuntimeWarning check_valid='ignore' + assert_no_warnings(mt19937.multivariate_normal, mean, cov, + check_valid='ignore', method='bm') + + # and that it raises with RuntimeWarning check_valid='raises' + assert_raises(ValueError, mt19937.multivariate_normal, mean, cov, + check_valid='raise', method='bm') + + def test_negative_binomial(self): + mt19937.seed(self.seed) + actual = mt19937.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_noncentral_chisquare(self): + mt19937.seed(self.seed) + actual = mt19937.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 = mt19937.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) + + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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_normal(self): + mt19937.seed(self.seed) + actual = mt19937.normal(loc=.123456789, scale=2.0, size=(3, 2), method='bm') + 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(mt19937.normal(scale=0), 0) + assert_raises(ValueError, mt19937.normal, scale=-0.) + + def test_pareto(self): + mt19937.seed(self.seed) + actual = mt19937.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: + # http://mail.scipy.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): + mt19937.seed(self.seed) + actual = mt19937.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, mt19937.poisson, lamneg) + assert_raises(ValueError, mt19937.poisson, [lamneg] * 10) + assert_raises(ValueError, mt19937.poisson, lambig) + assert_raises(ValueError, mt19937.poisson, [lambig] * 10) + + def test_power(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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(mt19937.rayleigh(scale=0), 0) + assert_raises(ValueError, mt19937.rayleigh, scale=-0.) + + def test_standard_cauchy(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.standard_exponential(size=(3, 2), method='inv') + 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): + mt19937.seed(self.seed) + actual = mt19937.standard_gamma(shape=3, size=(3, 2), method='inv') + 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(mt19937.standard_gamma(shape=0), 0) + assert_raises(ValueError, mt19937.standard_gamma, shape=-0.) + + def test_standard_normal(self): + mt19937.seed(self.seed) + actual = mt19937.standard_normal(size=(3, 2), method='bm') + 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_standard_t(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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 = mt19937.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 + mt19937.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, mt19937.uniform, throwing_float, throwing_float) + + class ThrowingInteger(np.ndarray): + def __int__(self): + raise TypeError + + throwing_int = np.array(1).view(ThrowingInteger) + assert_raises(TypeError, mt19937.hypergeometric, throwing_int, 1, 1) + + def test_vonmises(self): + mt19937.seed(self.seed) + actual = mt19937.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 + mt19937.seed(self.seed) + r = mt19937.vonmises(mu=0., kappa=1.1e-8, size=10 ** 6) + assert_(np.isfinite(r).all()) + + def test_wald(self): + mt19937.seed(self.seed) + actual = mt19937.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): + mt19937.seed(self.seed) + actual = mt19937.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): + assert_equal(mt19937.weibull(a=0), 0) + assert_raises(ValueError, mt19937.weibull, a=-0.) + + def test_zipf(self): + mt19937.seed(self.seed) + actual = mt19937.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) + + # TODO: Include test for randint once it can broadcast + # Can steal the test written in PR #6938 + + 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, method='bm') + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, normal, loc * 3, bad_scale) + + self.set_seed() + actual = normal(loc, scale * 3, method='bm') + 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, method='inv') + 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_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_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) + + 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) + + 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) + + 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) + + 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) + + 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) + + self.set_seed() + actual = lognormal(mean, sigma * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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) + + 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) + + 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) + + 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) + + @pytest.mark.xfail + 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) + + 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) + + 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=(RandomGenerator(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(RandomGenerator(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 = (mt19937.exponential, mt19937.standard_gamma, + mt19937.chisquare, mt19937.standard_t, + mt19937.pareto, mt19937.weibull, + mt19937.power, mt19937.rayleigh, + mt19937.poisson, mt19937.zipf, + mt19937.geometric, mt19937.logseries) + + probfuncs = (mt19937.geometric, mt19937.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 = (mt19937.uniform, mt19937.normal, + mt19937.beta, mt19937.gamma, + mt19937.f, mt19937.noncentral_chisquare, + mt19937.vonmises, mt19937.laplace, + mt19937.gumbel, mt19937.logistic, + mt19937.lognormal, mt19937.wald, + mt19937.binomial, mt19937.negative_binomial) + + probfuncs = (mt19937.binomial, mt19937.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_randint(self): + itype = [np.bool, np.int8, np.uint8, np.int16, np.uint16, + np.int32, np.uint32, np.int64, np.uint64] + func = mt19937.randint + high = np.array([1]) + low = np.array([0]) + + for dt in itype: + out = func(low, high, dtype=dt) + assert_equal(out.shape, self.tgtShape) + + out = func(low[0], high, dtype=dt) + assert_equal(out.shape, self.tgtShape) + + out = func(low, high[0], dtype=dt) + assert_equal(out.shape, self.tgtShape) + + def test_three_arg_funcs(self): + funcs = [mt19937.noncentral_f, mt19937.triangular, + mt19937.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) + + +if __name__ == "__main__": + run_module_suite() diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937_regressions.py b/_randomgen/core_prng/tests/test_numpy_mt19937_regressions.py new file mode 100644 index 000000000000..37ca9aa77f00 --- /dev/null +++ b/_randomgen/core_prng/tests/test_numpy_mt19937_regressions.py @@ -0,0 +1,140 @@ +from __future__ import division, absolute_import, print_function + +import sys +from numpy.testing import (run_module_suite, assert_, + assert_array_equal, assert_raises) +from numpy.compat import long +import numpy as np +import pytest +from core_prng import RandomGenerator, MT19937 + +mt19937 = RandomGenerator(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 + ] + 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 + for arg in args: + assert_(mt19937.hypergeometric(*arg) > 0) + + def test_logseries_convergence(self): + # Test for ticket #923 + N = 1000 + mt19937.seed(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.seed(1234) + a = mt19937.permutation(12) + mt19937.seed(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.seed(12345) + shuffled = list(t) + mt19937.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 = RandomGenerator(MT19937()) # mt19937.RandomState() + res = np.array([0, 8, 7, 2, 1, 9, 4, 7, 0, 3]) + for i in range(3): + mt19937.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. + 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.seed(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.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 = 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.seed(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.seed(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() + +if __name__ == "__main__": + run_module_suite() diff --git a/_randomgen/core_prng/tests/test_smoke.py b/_randomgen/core_prng/tests/test_smoke.py new file mode 100644 index 000000000000..a5678dbaa406 --- /dev/null +++ b/_randomgen/core_prng/tests/test_smoke.py @@ -0,0 +1,976 @@ +import pickle +import time +import sys +import os +import numpy as np +import pytest + +from core_prng import * +from core_prng import entropy + +from numpy.testing import assert_almost_equal, assert_equal, assert_raises, assert_, assert_array_equal + + +@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, method='bm') + rg.standard_normal(n, method='zig') + rg.standard_normal(n, method='bm', dtype=np.float32) + rg.standard_normal(n, method='zig', dtype=np.float32) + rg.randint(0, 2 ** 24, n, dtype=np.uint64) + rg.randint(0, 2 ** 48, n, dtype=np.uint64) + rg.standard_gamma(11.0, n) + rg.standard_gamma(11.0, n, dtype=np.float32) + rg.random_sample(n, dtype=np.float64) + rg.random_sample(n, dtype=np.float32) + + +class RNG(object): + @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.state = self.initial_state + + def test_init(self): + rg = RandomGenerator(self.prng()) + state = rg.state + rg.standard_normal(1, method='bm') + rg.standard_normal(1, method='zig') + rg.state = state + new_state = rg.state + assert_(comp_state(state, new_state)) + + def test_advance(self): + state = self.rg.state + if hasattr(self.rg, 'advance'): + self.rg.advance(self.advance) + assert_(not comp_state(state, self.rg.state)) + else: + pytest.skip() + + def test_jump(self): + state = self.rg.state + if hasattr(self.rg, 'jump'): + self.rg.jump() + jumped_state = self.rg.state + assert_(not comp_state(state, jumped_state)) + self.rg.random_sample(2*3*5*7*11*13*17) + self.rg.state = state + self.rg.jump() + rejumped_state = self.rg.state + assert_(comp_state(jumped_state, rejumped_state)) + else: + pytest.skip() + + def test_random_uintegers(self): + assert_(len(self.rg.random_uintegers(10)) == 10) + + def test_random_raw(self): + assert_(len(self.rg.random_raw(10)) == 10) + assert_(self.rg.random_raw((10, 10)).shape == (10, 10)) + + 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_sample(self): + assert_(len(self.rg.random_sample(10)) == 10) + params_0(self.rg.random_sample) + + def test_standard_normal_zig(self): + assert_(len(self.rg.standard_normal(10, method='zig')) == 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_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.state + int_1 = self.rg.random_raw(1) + self.rg.state = state + int_2 = self.rg.random_raw(1) + assert_(int_1 == int_2) + + def test_entropy_init(self): + rg = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.prng()) + s1 = rg.state + s2 = rg2.state + assert_(not comp_state(rg.state, rg2.state)) + + def test_seed(self): + rg = RandomGenerator(self.prng(*self.seed)) + rg2 = RandomGenerator(self.prng(*self.seed)) + rg.random_sample() + rg2.random_sample() + if not comp_state(rg.state, rg2.state): + for key in rg.state: + print(key) + print(rg.state[key]) + print(rg2.state[key]) + assert_(comp_state(rg.state, rg2.state)) + + def test_reset_state_gauss(self): + rg = RandomGenerator(self.prng(*self.seed)) + rg.standard_normal() + state = rg.state + n1 = rg.standard_normal(size=10) + rg2 = RandomGenerator(self.prng()) + rg2.state = state + n2 = rg2.standard_normal(size=10) + assert_array_equal(n1, n2) + + def test_reset_state_uint32(self): + rg = RandomGenerator(self.prng(*self.seed)) + rg.randint(0, 2 ** 24, 120, dtype=np.uint32) + state = rg.state + n1 = rg.randint(0, 2 ** 24, 10, dtype=np.uint32) + rg2 = RandomGenerator(self.prng()) + rg2.state = state + n2 = rg2.randint(0, 2 ** 24, 10, dtype=np.uint32) + assert_array_equal(n1, n2) + + def test_reset_state_uintegers(self): + rg = RandomGenerator(self.prng(*self.seed)) + rg.random_uintegers(bits=32) + state = rg.state + n1 = rg.random_uintegers(bits=32, size=10) + rg2 = RandomGenerator(self.prng()) + rg2.state = state + n2 = rg2.random_uintegers(bits=32, size=10) + 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_tomaxint(self): + vals = self.rg.tomaxint(size=100000) + maxsize = 0 + if os.name == 'nt': + maxsize = 2 ** 31 - 1 + else: + try: + maxsize = sys.maxint + except: + maxsize = sys.maxsize + if maxsize < 2 ** 32: + assert_((vals < sys.maxsize).all()) + else: + assert_((vals >= 2 ** 32).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_complex_normal(self): + st = self.rg.state + vals = self.rg.complex_normal( + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='zig') + assert_(len(vals) == 10) + + self.rg.state = st + vals2 = [self.rg.complex_normal( + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='zig') for _ in range(10)] + np.testing.assert_allclose(vals, vals2) + + self.rg.state = st + vals3 = self.rg.complex_normal( + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='zig') + np.testing.assert_allclose(vals, vals3) + + self.rg.state = st + norms = self.rg.standard_normal(size=20, method='zig') + norms = np.reshape(norms, (10, 2)) + cov = 0.5 * (-5.0) + v_real = 7.5 + v_imag = 2.5 + rho = cov / np.sqrt(v_real * v_imag) + imag = 7 + np.sqrt(v_imag) * (rho * + norms[:, 0] + np.sqrt(1 - rho ** 2) * norms[:, 1]) + real = 2 + np.sqrt(v_real) * norms[:, 0] + vals4 = [re + im * (0 + 1.0j) for re, im in zip(real, imag)] + + np.testing.assert_allclose(vals4, vals) + + def test_complex_normal_bm(self): + st = self.rg.state + vals = self.rg.complex_normal( + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='bm') + assert_(len(vals) == 10) + + self.rg.state = st + vals2 = [self.rg.complex_normal( + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='bm') for _ in range(10)] + np.testing.assert_allclose(vals, vals2) + + self.rg.state = st + vals3 = self.rg.complex_normal( + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='bm') + np.testing.assert_allclose(vals, vals3) + + def test_complex_normal_zero_variance(self): + st = self.rg.state + c = self.rg.complex_normal(0, 1.0, 1.0) + assert_almost_equal(c.imag, 0.0) + self.rg.state = st + n = self.rg.standard_normal() + np.testing.assert_allclose(c, n, atol=1e-8) + + st = self.rg.state + c = self.rg.complex_normal(0, 1.0, -1.0) + assert_almost_equal(c.real, 0.0) + self.rg.state = st + self.rg.standard_normal() + n = self.rg.standard_normal() + assert_almost_equal(c.real, 0.0) + np.testing.assert_allclose(c.imag, n, atol=1e-8) + + 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_rand(self): + state = self.rg.state + vals = self.rg.rand(10, 10, 10) + self.rg.state = state + assert_((vals == self.rg.random_sample((10, 10, 10))).all()) + assert_(vals.shape == (10, 10, 10)) + vals = self.rg.rand(10, 10, 10, dtype=np.float32) + assert_(vals.shape == (10, 10, 10)) + + def test_randn(self): + state = self.rg.state + vals = self.rg.randn(10, 10, 10) + self.rg.state = state + assert_equal(vals, self.rg.standard_normal((10, 10, 10))) + assert_equal(vals.shape, (10, 10, 10)) + + state = self.rg.state + vals = self.rg.randn(10, 10, 10, method='bm') + self.rg.state = state + assert_equal(vals, self.rg.standard_normal((10, 10, 10), method='bm')) + + state = self.rg.state + vals_inv = self.rg.randn(10, 10, 10, method='bm') + self.rg.state = state + vals_zig = self.rg.randn(10, 10, 10, method='zig') + assert_((vals_zig != vals_inv).any()) + + vals = self.rg.randn(10, 10, 10, dtype=np.float32) + assert_(vals.shape == (10, 10, 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_randint(self): + vals = self.rg.randint(10, 20, 10) + assert_(len(vals) == 10) + + def test_random_integers(self): + vals = self.rg.random_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, method='zig') + assert_(x.shape == (5000, 2)) + x_inv = self.rg.multivariate_normal(mean, cov, 5000, method='bm') + 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.state, unpick.state)) + + pick = pickle.dumps(self.rg) + unpick = pickle.loads(pick) + assert_((type(self.rg) == type(unpick))) + assert_(comp_state(self.rg.state, unpick.state)) + + @pytest.mark.xfail + def test_version(self): + state = self.rg.state + assert_('version' in state) + assert_(state['version'] == 0) + + def test_seed_array(self): + if self.seed_vector_bits is None: + pytest.skip() + + if self.seed_vector_bits == 32: + dtype = np.uint32 + else: + dtype = np.uint64 + seed = np.array([1], dtype=dtype) + self.rg.seed(seed) + state1 = self.rg.state + self.rg.seed(1) + state2 = self.rg.state + assert_(comp_state(state1, state2)) + + seed = np.arange(4, dtype=dtype) + self.rg.seed(seed) + state1 = self.rg.state + self.rg.seed(seed[0]) + state2 = self.rg.state + assert_(not comp_state(state1, state2)) + + seed = np.arange(1500, dtype=dtype) + self.rg.seed(seed) + state1 = self.rg.state + self.rg.seed(seed[0]) + state2 = self.rg.state + assert_(not comp_state(state1, state2)) + + seed = 2 ** np.mod(np.arange(1500, dtype=dtype), + self.seed_vector_bits - 1) + 1 + self.rg.seed(seed) + state1 = self.rg.state + self.rg.seed(seed[0]) + state2 = self.rg.state + assert_(not comp_state(state1, state2)) + + def test_seed_array_error(self): + if self.seed_vector_bits == 32: + out_of_bounds = 2 ** 32 + else: + out_of_bounds = 2 ** 64 + + seed = -1 + with pytest.raises(ValueError): + self.rg.seed(seed) + + seed = np.array([-1], dtype=np.int32) + with pytest.raises(ValueError): + self.rg.seed(seed) + + seed = np.array([1, 2, 3, -5], dtype=np.int32) + with pytest.raises(ValueError): + self.rg.seed(seed) + + seed = np.array([1, 2, 3, out_of_bounds]) + with pytest.raises(ValueError): + self.rg.seed(seed) + + def test_uniform_float(self): + rg = RandomGenerator(self.prng(12345)) + warmup(rg) + state = rg.state + r1 = rg.random_sample(11, dtype=np.float32) + rg2 = RandomGenerator(self.prng()) + warmup(rg2) + rg2.state = state + r2 = rg2.random_sample(11, dtype=np.float32) + assert_array_equal(r1, r2) + assert_equal(r1.dtype, np.float32) + assert_(comp_state(rg.state, rg2.state)) + + def test_gamma_floats(self): + rg = RandomGenerator(self.prng()) + warmup(rg) + state = rg.state + r1 = rg.standard_gamma(4.0, 11, dtype=np.float32) + rg2 = RandomGenerator(self.prng()) + warmup(rg2) + rg2.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.state, rg2.state)) + + def test_normal_floats(self): + rg = RandomGenerator(self.prng()) + warmup(rg) + state = rg.state + r1 = rg.standard_normal(11, method='bm', dtype=np.float32) + rg2 = RandomGenerator(self.prng()) + warmup(rg2) + rg2.state = state + r2 = rg2.standard_normal(11, method='bm', dtype=np.float32) + assert_array_equal(r1, r2) + assert_equal(r1.dtype, np.float32) + assert_(comp_state(rg.state, rg2.state)) + + def test_normal_zig_floats(self): + rg = RandomGenerator(self.prng()) + warmup(rg) + state = rg.state + r1 = rg.standard_normal(11, method='zig', dtype=np.float32) + rg2 = RandomGenerator(self.prng()) + warmup(rg2) + rg2.state = state + r2 = rg2.standard_normal(11, method='zig', dtype=np.float32) + assert_array_equal(r1, r2) + assert_equal(r1.dtype, np.float32) + assert_(comp_state(rg.state, rg2.state)) + + def test_output_fill(self): + rg = self.rg + state = rg.state + size = (31, 7, 97) + existing = np.empty(size) + rg.state = state + rg.standard_normal(out=existing) + rg.state = state + direct = rg.standard_normal(size=size) + assert_equal(direct, existing) + + existing = np.empty(size, dtype=np.float32) + rg.state = state + rg.standard_normal(out=existing, dtype=np.float32) + rg.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.state + size = (31, 7, 97) + existing = np.empty(size) + rg.state = state + rg.random_sample(out=existing) + rg.state = state + direct = rg.random_sample(size=size) + assert_equal(direct, existing) + + existing = np.empty(size, dtype=np.float32) + rg.state = state + rg.random_sample(out=existing, dtype=np.float32) + rg.state = state + direct = rg.random_sample(size=size, dtype=np.float32) + assert_equal(direct, existing) + + def test_output_filling_exponential(self): + rg = self.rg + state = rg.state + size = (31, 7, 97) + existing = np.empty(size) + rg.state = state + rg.standard_exponential(out=existing) + rg.state = state + direct = rg.standard_exponential(size=size) + assert_equal(direct, existing) + + existing = np.empty(size, dtype=np.float32) + rg.state = state + rg.standard_exponential(out=existing, dtype=np.float32) + rg.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.state + size = (31, 7, 97) + existing = np.zeros(size) + rg.state = state + rg.standard_gamma(1.0, out=existing) + rg.state = state + direct = rg.standard_gamma(1.0, size=size) + assert_equal(direct, existing) + + existing = np.zeros(size, dtype=np.float32) + rg.state = state + rg.standard_gamma(1.0, out=existing, dtype=np.float32) + rg.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.state + size = (31, 7, 97) + mu = np.arange(97.0) + 1.0 + existing = np.zeros(size) + rg.state = state + rg.standard_gamma(mu, out=existing) + rg.state = state + direct = rg.standard_gamma(mu, size=size) + assert_equal(direct, existing) + + existing = np.zeros(size, dtype=np.float32) + rg.state = state + rg.standard_gamma(mu, out=existing, dtype=np.float32) + rg.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_randint_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.randint(lower, [upper] * 10, dtype=dtype) + self._reset_state() + b = self.rg.randint([lower] * 10, upper, dtype=dtype) + assert_equal(a, b) + self._reset_state() + c = self.rg.randint(lower, upper, size=10, dtype=dtype) + assert_equal(a, c) + self._reset_state() + d = self.rg.randint(np.array( + [lower] * 10), np.array([upper], dtype=np.object), size=10, dtype=dtype) + assert_equal(a, d) + self._reset_state() + e = self.rg.randint( + np.array([lower] * 10), np.array([upper] * 10), size=10, dtype=dtype) + assert_equal(a, e) + + self._reset_state() + a = self.rg.randint(0, upper, size=10, dtype=dtype) + self._reset_state() + b = self.rg.randint([upper] * 10, dtype=dtype) + assert_equal(a, b) + + def test_randint_numpy(self, dtype): + high = np.array([1]) + low = np.array([0]) + + out = self.rg.randint(low, high, dtype=dtype) + assert out.shape == (1,) + + out = self.rg.randint(low[0], high, dtype=dtype) + assert out.shape == (1,) + + out = self.rg.randint(low, high[0], dtype=dtype) + assert out.shape == (1,) + + def test_randint_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.randint(lower, [upper + 1] * 10, dtype=dtype) + with pytest.raises(ValueError): + self.rg.randint(lower - 1, [upper] * 10, dtype=dtype) + with pytest.raises(ValueError): + self.rg.randint([lower - 1], [upper] * 10, dtype=dtype) + with pytest.raises(ValueError): + self.rg.randint([0], [0], dtype=dtype) + + +class TestMT19937(RNG): + @classmethod + def setup_class(cls): + cls.prng = MT19937 + cls.advance = None + cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 32 + cls._extra_setup() + cls.seed_error = ValueError + + @pytest.mark.xfail + def test_numpy_state(self): + # TODO: Do we want lagacy state support + nprg = np.random.RandomState() + nprg.standard_normal(99) + state = nprg.state + self.rg.state = state + state2 = self.rg.state + assert_((state[1] == state2['state'][0]).all()) + assert_((state[2] == state2['state'][1])) + assert_((state[3] == state2['gauss']['has_gauss'])) + assert_((state[4] == state2['gauss']['gauss'])) + + +class TestPCG64(RNG): + @classmethod + def setup_class(cls): + cls.prng = PCG64 + cls.advance = 2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 + cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = None + cls._extra_setup() + + def test_seed_array_error(self): + # GH #82 for error type changes + if self.seed_vector_bits == 32: + out_of_bounds = 2 ** 32 + else: + out_of_bounds = 2 ** 64 + + seed = -1 + with pytest.raises(ValueError): + self.rg.seed(seed) + + error_type = ValueError if self.seed_vector_bits else TypeError + seed = np.array([-1], dtype=np.int32) + with pytest.raises(error_type): + self.rg.seed(seed) + + seed = np.array([1, 2, 3, -5], dtype=np.int32) + with pytest.raises(error_type): + self.rg.seed(seed) + + seed = np.array([1, 2, 3, out_of_bounds]) + with pytest.raises(error_type): + self.rg.seed(seed) + + +class TestPhilox(RNG): + @classmethod + def setup_class(cls): + cls.prng = Philox + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + +class TestThreeFry(RNG): + @classmethod + def setup_class(cls): + cls.prng = ThreeFry + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + +class TestXoroshiro128(RNG): + @classmethod + def setup_class(cls): + cls.prng = Xoroshiro128 + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + +class TestXorshift1024(RNG): + @classmethod + def setup_class(cls): + cls.prng = Xorshift1024 + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + +class TestDSFMT(RNG): + @classmethod + def setup_class(cls): + cls.prng = DSFMT + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls._extra_setup() + cls.seed_vector_bits = 32 + + +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/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 4322baf3575a..99c7027734a3 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -101,9 +101,13 @@ cdef class ThreeFry: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): + cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 3cbb73752512..34f88859d1c1 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -93,12 +93,13 @@ cdef class Xoroshiro128: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): + cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - # TODO: These should be done everywhere for safety self._prng.has_gauss = 0 self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ @@ -223,7 +224,10 @@ cdef class Xoroshiro128: def cffi(self): if self.cffi is not None: return self.cffi - import cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() self.cffi = interface(self.rng_state, diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index ef686e003291..effc2b3d0538 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -85,9 +85,13 @@ cdef class Xorshift1024: free(self._prng.binomial) free(self._prng) - def _reset_state_variables(self): + cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 330d0cfeea16..0f48e3f7aa10 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -55,7 +55,6 @@ files = glob.glob('./core_prng/*.in') for templated_file in files: - print(templated_file) output_file_name = os.path.splitext(templated_file)[0] if (os.path.exists(output_file_name) and (os.path.getmtime(templated_file) < os.path.getmtime(output_file_name))): From 3b7b1e4199f41f93b2460689a74301db7ed5930c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 11 Mar 2018 22:07:49 +0000 Subject: [PATCH 046/138] DOC: Update readme Update readme --- _randomgen/README.md | 240 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 226 insertions(+), 14 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index 0e0bdda72e63..095f897ed306 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -1,30 +1,242 @@ # Core PRNG +[![Travis Build Status](https://travis-ci.org/bashtage/ng-numpy-randomstate.svg?branch=master)](https://travis-ci.org/bashtage/core-prng) +[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/core-prng/branch/master) + Experimental Core Pseudo Random Number Generator interface for future NumPy RandomState evolution. -## Demo +This is a library and generic interface for alternative random +generators in Python and NumPy. + +## Features + +* Replacement for NumPy's RandomState + +```python +# import numpy.random as rnd +from core_prng import RandomGenerator, MT19937 +rnd = RandomGenerator(MT19937()) +x = rnd.standard_normal(100) +y = rnd.random_sample(100) +z = rnd.randn(10,10) +``` + +* Default random generator is a fast generator called Xoroshiro128plus +* Support for random number generators that support independent streams + and jumping ahead so that sub-streams can be generated +* Faster random number generation, especially for normal, standard + exponential and standard gamma using the Ziggurat method + +```python +from core_prng import RandomGenerator +# Use Xoroshiro128 +rnd = RandomGenerator() +w = rnd.standard_normal(10000, method='zig') +x = rnd.standard_exponential(10000, method='zig') +y = rnd.standard_gamma(5.5, 10000, method='zig') +``` + +* Support for 32-bit floating randoms for core generators. + Currently supported: + + * Uniforms (`random_sample`) + * Exponentials (`standard_exponential`, both Inverse CDF and Ziggurat) + * Normals (`standard_normal`, both Box-Muller and Ziggurat) + * Standard Gammas (via `standard_gamma`, both Inverse CDF and Ziggurat) + + **WARNING**: The 32-bit generators are **experimental** and subject + to change. + + **Note**: There are _no_ plans to extend the alternative precision + generation to all random number types. + +* Support for filling existing arrays using `out` keyword argument. Currently + supported in (both 32- and 64-bit outputs) + + * Uniforms (`random_sample`) + * Exponentials (`standard_exponential`) + * Normals (`standard_normal`) + * Standard Gammas (via `standard_gamma`) + +## Included Pseudo Random Number Generators + +This modules includes a number of alternative random +number generators in addition to the MT19937 that is included in NumPy. +The RNGs include: + +* [MT19937](https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/), + the NumPy rng +* [dSFMT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/) a + SSE2-aware version of the MT19937 generator that is especially fast at + generating doubles +* [xoroshiro128+](http://xoroshiro.di.unimi.it/) and + [xorshift1024*](http://xorshift.di.unimi.it/) +* [PCG64](http:w//www.pcg-random.org/) +* ThreeFry and Philox implementationf from [Random123](https://www.deshawrsearch.com/resources_random123.html) +## Differences from `numpy.random.RandomState` + +### New Features +* `standard_normal`, `normal`, `randn` and `multivariate_normal` all + support an additional `method` keyword argument which can be `bm` or + `zig` where `bm` corresponds to the current method using the Box-Muller + transformation and `zig` uses the much faster (100%+) Ziggurat method. +* `standard_exponential` and `standard_gamma` both support an additional + `method` keyword argument which can be `inv` or + `zig` where `inv` corresponds to the current method using the inverse + CDF and `zig` uses the much faster (100%+) Ziggurat method. +* Core random number generators can produce either single precision + (`np.float32`) or double precision (`np.float64`, the default) using + an the optional keyword argument `dtype` +* Core random number generators can fill existing arrays using the + `out` keyword argument + + +### New Functions + +* `random_entropy` - Read from the system entropy provider, which is +commonly used in cryptographic applications +* `random_raw` - Direct access to the values produced by the underlying +PRNG. The range of the values returned depends on the specifics of the +PRNG implementation. +* `random_uintegers` - unsigned integers, either 32- (`[0, 2**32-1]`) +or 64-bit (`[0, 2**64-1]`) +* `jump` - Jumps RNGs that support it. `jump` moves the state a great +distance. _Only available if supported by the RNG._ +* `advance` - Advanced the core RNG 'as-if' a number of draws were made, +without actually drawing the numbers. _Only available if supported by +the RNG._ + +## Status + +* Replacement for `numpy.random.RandomState`. The + `MT19937` generator is identical to `numpy.random.RandomState`, and + will produce an identical sequence of random numbers for a given seed. +* Builds and passes all tests on: + * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 (probably works on 2.6 and 3.3) + * PC-BSD (FreeBSD) 64-bit, Python 2.7 + * OSX 64-bit, Python 2.7 + * Windows 32/64 bit (only tested on Python 2.7, 3.5 and 3.6, but + should work on 3.3/3.4) -Basic POC demonstration +## Version +The version matched the latest version of NumPy where +`RandoMGenerator(MT19937())` passes all NumPy test. + +## Documentation + +An occasionally updated build of the documentation is available on +[my github pages](http://bashtage.github.io/core-prng/). + +## Plans +This module is essentially complete. There are a few rough edges that +need to be smoothed. + +* Creation of additional streams from a RandomState where supported + (i.e. a `next_stream()` method) + +## Requirements +Building requires: + + * Python (2.7, 3.4, 3.5, 3.6) + * NumPy (1.9, 1.10, 1.11, 1.12) + * Cython (0.22, **not** 0.23, 0.24, 0.25) + * tempita (0.5+), if not provided by Cython + +Testing requires pytest (3.0+). + +**Note:** it might work with other versions but only tested with these +versions. + +## Development and Testing + +All development has been on 64-bit Linux, and it is regularly tested on +Travis-CI (Linux) and Appveyor (Windows). The library is occasionally +tested on Linux 32-bit, OSX 10.13, Free BSD 11.1. + +Basic tests are in place for all RNGs. The MT19937 is tested against +NumPy's implementation for identical results. It also passes NumPy's +test suite. + +## Installing + +```bash +python setup.py install +``` + +### SSE2 +`dSFTM` makes use of SSE2 by default. If you have a very old computer +or are building on non-x86, you can install using: ```bash -python setup.py develop +python setup.py install --no-sse2 ``` -```ipython -In [1]: import core_prng.generator +### Windows +Either use a binary installer, or if building from scratch, use +Python 3.6 with Visual Studio 2015 Community Edition. It can also be +build using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7, +although some modifications may be needed to `distutils` to find the +compiler. + +## Using + +The separate generators are importable from `core_prng` -# Default generator is Splitmix64 -In [2]: rg = core_prng.generator.RandomGenerator() +```python +from core_prng import RandomGenerator, ThreeFry, PCG64, MT19937 +rg = RandomGenerator(ThreeFry()) +rg.random_sample(100) -In [3]: rg.random_integer() -Out[3]: 872337561037043212 +rg = RandomGenerator(PCG64()) +rg.random_sample(100) -In [4]: from core_prng.xoroshiro128 import Xoroshiro128 +# Identical to NumPy +rg = RandomGenerator(MT19937()) +rg.random_sample(100) +``` + +## License +Standard NCSA, plus sub licenses for components. -# Swap the generator -In [5]: rg = core_prng.generator.RandomGenerator(Xoroshiro128()) +## Performance +Performance is promising, and even the mt19937 seems to be faster than +NumPy's mt19937. -In [6]: rg.random_integer() -Out[6]: 13370384800127340062 ``` +Speed-up relative to NumPy (Uniform Doubles) +************************************************************ +MT19937 22.9% +PCG64 109.6% +Philox -6.2% +ThreeFry -16.6% +Xoroshiro128 161.0% +Xorshift1024 119.9% + +Speed-up relative to NumPy (64-bit unsigned integers) +************************************************************ +MT19937 6.2% +PCG64 88.2% +Philox -23.0% +ThreeFry -26.5% +Xoroshiro128 142.4% +Xorshift1024 107.5% + +Speed-up relative to NumPy (Standard normals (Box-Muller)) +************************************************************ +MT19937 17.7% +PCG64 35.6% +Philox -26.2% +ThreeFry -16.9% +Xoroshiro128 57.9% +Xorshift1024 40.9% + +Speed-up relative to NumPy (Standard normals (Ziggurat)) +************************************************************ +MT19937 107.9% +PCG64 149.6% +Philox 11.1% +ThreeFry 78.8% +Xoroshiro128 224.7% +Xorshift1024 158.6% +``` \ No newline at end of file From cfe9e95741383636aa9e87817150f1d9a6d32d2f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 11 Mar 2018 23:28:43 +0000 Subject: [PATCH 047/138] ENH: Add support for Philon on 32 bit Windows Performance is terrible --- _randomgen/core_prng/src/philox/philox.h | 26 +++++++++++++++++++++++- _randomgen/setup.py | 8 +++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index d469eabb2adc..f0ca24e6a677 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -28,10 +28,34 @@ _philox4x64bumpkey(struct r123array2x64 key) { } #ifdef _WIN32 -/* TODO: This isn't correct for many platforms */ #include +/* TODO: This isn't correct for many platforms */ +#ifdef _WIN64 #pragma intrinsic(_umul128) +#else +#pragma intrinsic(__emulu) +static 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 INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 0f48e3f7aa10..9ccb2b8f4c4e 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -30,7 +30,6 @@ PCG_EMULATED_MATH = False EXTRA_INCLUDE_DIRS = [] -EXTRA_COMPILE_ARGS = [] EXTRA_LINK_ARGS = [] EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99'] if os.name == 'nt': @@ -39,9 +38,10 @@ if DEBUG: EXTRA_LINK_ARGS += ['-debug'] EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] -if os.name == 'nt' and sys.version_info < (3, 0): - EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] + if sys.version_info < (3, 0): + EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] +DSFMT_DEFS = [('DSFMT_MEXP', '19937')] if USE_SSE2: if os.name == 'nt': EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] @@ -49,8 +49,6 @@ EXTRA_COMPILE_ARGS += ['/arch:SSE2'] else: EXTRA_COMPILE_ARGS += ['-msse2'] -DSFMT_DEFS = [('DSFMT_MEXP', '19937')] -if USE_SSE2: DSFMT_DEFS += [('HAVE_SSE2', '1')] files = glob.glob('./core_prng/*.in') From 390860a905a9ad89063f70017841f67510ad27fd Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 10:03:17 +0000 Subject: [PATCH 048/138] ENH: Add support for ThreeFry32x4 Add support for ThreeFry32x4 to benchmark --- _randomgen/appveyor.yml | 2 +- _randomgen/benchmark.py | 3 +- _randomgen/core_prng/__init__.py | 3 +- _randomgen/core_prng/_testing.py | 40 +- _randomgen/core_prng/common.pxd | 2 +- _randomgen/core_prng/common.pyx | 19 +- _randomgen/core_prng/generator.pyx | 1 + _randomgen/core_prng/pcg64.pyx | 17 +- _randomgen/core_prng/philox.pyx | 8 +- _randomgen/core_prng/pickle.py | 2 + .../src/distributions/distributions.c | 33 +- .../core_prng/src/pcg64/pcg64-test-data-gen.c | 23 +- _randomgen/core_prng/src/pcg64/pcg64.orig.c | 4 + .../src/threefry/threefry-test-data-gen.c | 2 + _randomgen/core_prng/src/threefry/threefry.c | 33 - .../src/threefry32/threefry32-test-data-gen.c | 88 ++ .../core_prng/src/threefry32/threefry32.c | 29 + .../core_prng/src/threefry32/threefry32.h | 827 ++++++++++++++ .../core_prng/tests/data/pcg64-testset-1.csv | 1001 +++++++++++++++++ .../core_prng/tests/data/pcg64-testset-2.csv | 1001 +++++++++++++++++ .../tests/data/threefry32-testset-1.csv | 1001 +++++++++++++++++ .../tests/data/threefry32-testset-2.csv | 1001 +++++++++++++++++ .../core_prng/tests/test_against_numpy.py | 3 +- _randomgen/core_prng/tests/test_direct.py | 40 +- .../core_prng/tests/test_numpy_mt19937.py | 3 +- _randomgen/core_prng/tests/test_smoke.py | 72 +- _randomgen/core_prng/threefry.pyx | 9 +- _randomgen/core_prng/threefry32.pyx | 250 ++++ _randomgen/core_prng/xoroshiro128.pyx | 2 +- _randomgen/core_prng/xorshift1024.pyx | 2 +- _randomgen/setup.py | 9 + 31 files changed, 5389 insertions(+), 141 deletions(-) create mode 100644 _randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c create mode 100644 _randomgen/core_prng/src/threefry32/threefry32.c create mode 100644 _randomgen/core_prng/src/threefry32/threefry32.h create mode 100644 _randomgen/core_prng/tests/data/pcg64-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/pcg64-testset-2.csv create mode 100644 _randomgen/core_prng/tests/data/threefry32-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/threefry32-testset-2.csv create mode 100644 _randomgen/core_prng/threefry32.pyx diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml index 1106f48c154e..86d98b2b67aa 100644 --- a/_randomgen/appveyor.yml +++ b/_randomgen/appveyor.yml @@ -30,4 +30,4 @@ test_script: on_success: - cd %GIT_DIR%\ - - IF %PYTHON_ARCH%==x86_64 python benchmark.py \ No newline at end of file + - IF %PY_MAJOR_VER%==3 python benchmark.py \ No newline at end of file diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index e670e72657c5..f828f657d24f 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -27,8 +27,7 @@ scale_64 = 2 PRNGS = ['PCG64', 'MT19937', 'Xoroshiro128', 'Xorshift1024', - 'Philox', 'ThreeFry', 'numpy'] # , 'Xorshift1024', -#'Xoroshiro128', 'DSFMT', 'random'] + 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] def timer(code, setup): diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index d5577f3bf3cb..9b7d10631927 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -4,11 +4,12 @@ from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry +from .threefry32 import ThreeFry32 from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 __all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'Philox', - 'ThreeFry', 'Xoroshiro128', 'Xorshift1024'] + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/core_prng/_testing.py b/_randomgen/core_prng/_testing.py index 2f74d06e7b05..86c5ea2b157a 100644 --- a/_randomgen/core_prng/_testing.py +++ b/_randomgen/core_prng/_testing.py @@ -7,8 +7,8 @@ from numpy.testing import suppress_warnings except ImportError: - # The following two classes are copied from python 2.6 warnings module (context - # manager) + # The following two classes are copied from python 2.6 warnings module + # (context manager) class WarningMessage(object): """ @@ -20,8 +20,8 @@ class WarningMessage(object): so it can be used in NumPy with older Python versions. """ - _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", - "line") + _WARNING_DETAILS = ("message", "category", "filename", "lineno", + "file", "line") def __init__(self, message, category, filename, lineno, file=None, line=None): @@ -34,7 +34,8 @@ def __init__(self, message, category, filename, lineno, file=None, self._category_name = None def __str__(self): - return ("{message : %r, category : %r, filename : %r, lineno : %s, " + return ("{message : %r, category : %r, " + "filename : %r, lineno : %s, " "line : %r}" % (self.message, self._category_name, self.filename, self.lineno, self.line)) @@ -59,9 +60,9 @@ class suppress_warnings(object): One of "always", "once", "module", or "location". Analogous to the usual warnings module filter mode, it is useful to reduce noise mostly on the outmost level. Unsuppressed and unrecorded - warnings will be forwarded based on this rule. Defaults to "always". - "location" is equivalent to the warnings "default", match by exact - location the warning warning originated from. + warnings will be forwarded based on this rule. Defaults to + "always". "location" is equivalent to the warnings "default", match + by exact location the warning warning originated from. Notes ----- Filters added inside the context manager will be discarded again @@ -105,7 +106,7 @@ class suppress_warnings(object): def __init__(self, forwarding_rule="always"): self._entered = False - # Suppressions are either instance or defined inside one with block: + # Suppressions are instance or defined inside one with block: self._suppressions = [] if forwarding_rule not in {"always", "module", "once", "location"}: @@ -124,7 +125,8 @@ def _clear_registries(self): if hasattr(module, "__warningregistry__"): module.__warningregistry__.clear() - def _filter(self, category=Warning, message="", module=None, record=False): + def _filter(self, category=Warning, message="", module=None, + record=False): if record: record = [] # The log where to store warnings else: @@ -142,10 +144,12 @@ def _filter(self, category=Warning, message="", module=None, record=False): self._clear_registries() self._tmp_suppressions.append( - (category, message, re.compile(message, re.I), module, record)) + (category, message, re.compile(message, re.I), module, + record)) else: self._suppressions.append( - (category, message, re.compile(message, re.I), module, record)) + (category, message, re.compile(message, re.I), module, + record)) return record @@ -193,8 +197,8 @@ def record(self, category=Warning, message="", module=None): When added within a context, filters are only added inside the context and will be forgotten when the context is exited. """ - return self._filter(category=category, message=message, module=module, - record=True) + return self._filter(category=category, message=message, + module=module, record=True) def __enter__(self): if self._entered: @@ -243,8 +247,8 @@ def __exit__(self, *exc_info): del self._filters def _showwarnmsg(self, msg): - self._showwarning(msg.message, msg.category, msg.filename, msg.lineno, - msg.file, msg.line, use_warnmsg=msg) + self._showwarning(msg.message, msg.category, msg.filename, + msg.lineno, msg.file, msg.line, use_warnmsg=msg) def _showwarning(self, message, category, filename, lineno, *args, **kwargs): @@ -254,7 +258,7 @@ def _showwarning(self, message, category, filename, lineno, if (issubclass(category, cat) and pattern.match(message.args[0]) is not None): if mod is None: - # Message and category match, either recorded or ignored + # Message and category match, recorded or ignored if rec is not None: msg = WarningMessage(message, category, filename, lineno, **kwargs) @@ -308,4 +312,4 @@ def new_func(*args, **kwargs): with self: return func(*args, **kwargs) - return new_func \ No newline at end of file + return new_func diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index a6419cfa4958..43981f476f15 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -59,7 +59,7 @@ cdef object float_fill(void *func, prng_t *state, object size, object lock, obje cdef object float_fill_from_double(void *func, prng_t *state, object size, object lock, object out) -cdef np.ndarray int_to_array(object value, object name, object bits) +cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size) cdef object cont(void *func, prng_t *state, object size, object lock, int narg, object a, object a_name, constraint_type a_constraint, diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index 5dedbdbde1e8..fb3e96697bae 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -20,21 +20,28 @@ cdef double kahan_sum(double *darr, np.npy_intp n): sum = t return sum -cdef np.ndarray int_to_array(object value, object name, object bits): - len = bits // 64 +cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size): + 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=np.uint64) + + out = np.empty(len, dtype=dtype) for i in range(len): - out[i] = value % 2**64 - value >>= 64 + out[i] = value % 2**int(uint_size) + value >>= int(uint_size) else: - out = value.astype(np.uint64) + out = value.astype(dtype) if out.shape != (len,): raise ValueError('{name} must have {len} elements when using ' 'array form'.format(name=name, len=len)) diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 0e3bbf0cc799..e5fd47ec4f6f 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -59,6 +59,7 @@ cdef class RandomGenerator: cdef public object __core_prng cdef prng_t *_prng cdef object lock + poisson_lam_max = POISSON_LAM_MAX def __init__(self, prng=None): if prng is None: diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 7353a77beaf2..70aa57b76610 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -47,7 +47,7 @@ cdef extern from "src/pcg64/pcg64.h": ctypedef s_pcg64_state pcg64_state uint64_t pcg64_next64(pcg64_state *state) nogil - uint64_t pcg64_next32(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) @@ -79,7 +79,7 @@ cdef class PCG64: cdef prng_t *_prng cdef public object capsule - def __init__(self, seed=None, inc=1): + def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg64_state)) self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) self._prng = malloc(sizeof(prng_t)) @@ -157,7 +157,7 @@ cdef class PCG64: raise ValueError('Unknown method') - def seed(self, seed=None, inc=1): + def seed(self, seed=None, inc=0): """ seed(seed=None, stream=None) @@ -187,13 +187,16 @@ cdef class PCG64: _seed = random_entropy(4) except RuntimeError: _seed = random_entropy(4, 'fallback') - _seed = _seed.view(np.uint64) else: + err_msg = 'inc must be a scalar integer between 0 and ' \ + '{ub}'.format(ub=ub) if not np.isscalar(seed): - raise TypeError('seed must be a scalar integer between 0 and {ub}'.format(ub=ub)) - if seed < 0 or seed > ub or int(seed) != seed: - raise ValueError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + raise TypeError(err_msg) + if int(seed) != seed: + raise TypeError(err_msg) + if seed < 0 or seed > ub: + raise ValueError(err_msg) _seed = np.empty(2, np.uint64) _seed[0] = int(seed) // 2**64 _seed[1] = int(seed) % 2**64 diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 12d69fe6813a..c724e5ee8be0 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -37,7 +37,7 @@ cdef extern from 'src/philox/philox.h': ctypedef s_philox_state philox_state uint64_t philox_next64(philox_state *state) nogil - uint64_t philox_next32(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) @@ -200,11 +200,11 @@ cdef class Philox: for i in range(2): self.rng_state.key.v[i] = state[i] else: - key = int_to_array(key, 'key', 128) + key = int_to_array(key, 'key', 128, 64) 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) + counter = int_to_array(counter, 'counter', 256, 64) for i in range(4): self.rng_state.ctr.v[i] = counter[i] @@ -257,7 +257,7 @@ cdef class Philox: def advance(self, step): """Advance the state as-if a specific number of draws have been made""" cdef np.ndarray step_a - step_a = int_to_array(step, 'step', 256) + step_a = int_to_array(step, 'step', 256, 64) loc = 0 philox_advance( step_a.data, self.rng_state) return self diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/core_prng/pickle.py index 44b7e6b24210..56f4de56240e 100644 --- a/_randomgen/core_prng/pickle.py +++ b/_randomgen/core_prng/pickle.py @@ -4,6 +4,7 @@ from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry +from .threefry32 import ThreeFry32 from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 @@ -12,6 +13,7 @@ 'PCG64': PCG64, 'Philox': Philox, 'ThreeFry': ThreeFry, + 'ThreeFry32': ThreeFry32, 'Xorshift1024': Xorshift1024, 'Xoroshiro128': Xoroshiro128} diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 4c2896e888ab..fbdad8f2f669 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -2,15 +2,14 @@ #include "ziggurat.h" #include "ziggurat_constants.h" -static NPY_INLINE float next_float(prng_t *prng_state) { - return (prng_state->next_uint32(prng_state->state) >> 9) * - (1.0f / 8388608.0f); -} - static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } +static NPY_INLINE float next_float(prng_t *prng_state) { + return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); +} + static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { return prng_state->next_uint64(prng_state->state); } @@ -77,7 +76,7 @@ float random_gauss_f(prng_t *prng_state) { } } -double standard_exponential_zig(prng_t *prng_state); +static NPY_INLINE double standard_exponential_zig(prng_t *prng_state); static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, double x) { @@ -93,11 +92,11 @@ static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, } } -double standard_exponential_zig(prng_t *prng_state) { +static NPY_INLINE double standard_exponential_zig(prng_t *prng_state) { uint64_t ri; uint8_t idx; double x; - ri = prng_state->next_uint64(prng_state->state); + ri = random_uint64(prng_state); ri >>= 3; idx = ri & 0xFF; ri >>= 8; @@ -131,7 +130,7 @@ static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) { uint32_t ri; uint8_t idx; float x; - ri = prng_state->next_uint32(prng_state->state); + ri = random_uint32(prng_state); ri >>= 1; idx = ri & 0xFF; ri >>= 8; @@ -154,7 +153,7 @@ double random_gauss_zig(prng_t *prng_state) { double x, xx, yy; for (;;) { /* r = e3n52sb8 */ - r = prng_state->next_uint64(prng_state->state); + r = random_uint64(prng_state); idx = r & 0xff; r >>= 8; sign = r & 0x1; @@ -190,7 +189,7 @@ float random_gauss_zig_f(prng_t *prng_state) { float x, xx, yy; for (;;) { /* r = n23sb8 */ - r = prng_state->next_uint32(prng_state->state); + r = random_uint32(prng_state); idx = r & 0xff; sign = (r >> 8) & 0x1; rabs = (int32_t)((r >> 9) & 0x0007fffff); @@ -400,26 +399,26 @@ float random_standard_gamma_zig_f(prng_t *prng_state, float shape) { } int64_t random_positive_int64(prng_t *prng_state) { - return prng_state->next_uint64(prng_state->state) >> 1; + return random_uint64(prng_state) >> 1; } int32_t random_positive_int32(prng_t *prng_state) { - return prng_state->next_uint32(prng_state->state) >> 1; + return random_uint32(prng_state) >> 1; } long random_positive_int(prng_t *prng_state) { #if ULONG_MAX <= 0xffffffffUL - return (long)(prng_state->next_uint32(prng_state->state) >> 1); + return (long)(random_uint32(prng_state) >> 1); #else - return (long)(prng_state->next_uint64(prng_state->state) >> 1); + return (long)(random_uint64(prng_state) >> 1); #endif } unsigned long random_uint(prng_t *prng_state) { #if ULONG_MAX <= 0xffffffffUL - return prng_state->next_uint32(prng_state->state); + return random_uint32(prng_state); #else - return prng_state->next_uint64(prng_state->state); + return random_uint64(prng_state); #endif } diff --git a/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c index cb675346c4c0..0c2b079a3e15 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c +++ b/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c @@ -7,7 +7,6 @@ * pgc64-test-data-gen */ -#include "../splitmix64/splitmix64.h" #include "pcg64.orig.h" #include #include @@ -18,12 +17,16 @@ int main() { pcg64_random_t rng; uint64_t state, seed = 0xDEADBEAF; state = seed; - __uint128_t temp; - rng.state = (__uint128_t)splitmix64_next(&state) << 64; - rng.state |= splitmix64_next(&state); - rng.inc = (__uint128_t)1; + __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); } @@ -44,9 +47,13 @@ int main() { fclose(fp); state = seed = 0; - rng.state = - (__uint128_t)splitmix64_next(&state) << 64 | splitmix64_next(&state); - rng.inc = (__uint128_t)1; + 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); } diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.c b/_randomgen/core_prng/src/pcg64/pcg64.orig.c index 24488123edfe..07e97e4b6d97 100644 --- a/_randomgen/core_prng/src/pcg64/pcg64.orig.c +++ b/_randomgen/core_prng/src/pcg64/pcg64.orig.c @@ -1,5 +1,9 @@ #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); diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c index 444824c1231a..328eb257589e 100644 --- a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c +++ b/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c @@ -45,6 +45,7 @@ int main() { 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) { @@ -71,6 +72,7 @@ int main() { 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) { diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/core_prng/src/threefry/threefry.c index 56b499bd9dda..6aac7b5256c8 100644 --- a/_randomgen/core_prng/src/threefry/threefry.c +++ b/_randomgen/core_prng/src/threefry/threefry.c @@ -1,36 +1,3 @@ -/* -Adapted from https://github.com/pdebuyl/threefry - -Copyright (c) 2017, Pierre de Buyl - -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. -*/ - #include "threefry.h" extern INLINE uint64_t threefry_next64(threefry_state *state); diff --git a/_randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c b/_randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c new file mode 100644 index 000000000000..0e62299957b1 --- /dev/null +++ b/_randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c @@ -0,0 +1,88 @@ +/* + * Generate testing csv files + * + * cl threefry32-test-data-gen.c /Ox ../splitmix64/splitmix64.c /Ox + * threefry32-test-data-gen.exe + * + * gcc threefry32-test-data-gen.c ../splitmix64/splitmix64.c /Ox -o + * threefry32-test-data-gen + * ./threefry32-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/threefry.h" +#include +#include + +#define N 1000 + +int main() { + threefry4x32_key_t ctr = {{0, 0, 0, 0}}; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + threefry4x32_ctr_t key = {{0}}; + threefry4x32_ctr_t out; + uint64_t store[N]; + uint64_t seed_val; + int i, j; + for (i = 0; i < 4; i++) { + seed_val = splitmix64_next(&state); + key.v[2*i] = (uint32_t)seed_val; + key.v[2*i+1] = (uint32_t)(seed_val >> 32); + } + for (i = 0; i < N / 4UL; i++) { + ctr.v[0]++; + out = threefry4x32_R(threefry4x32_rounds, ctr, key); + for (j = 0; j < 4; j++) { + store[i * 4 + j] = out.v[j]; + } + } + + FILE *fp; + fp = fopen("threefry32-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 < 4; i++) { + seed_val = splitmix64_next(&state); + key.v[2*i] = (uint32_t)seed_val; + key.v[2*i+1] = (uint32_t)(seed_val >> 32); + } + for (i = 0; i < N / 4; i++) { + ctr.v[0]++; + out = threefry4x32_R(threefry4x32_rounds, ctr, key); + for (j = 0; j < 4; j++) { + store[i * 4 + j] = out.v[j]; + } + } + + fp = fopen("threefry32-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/_randomgen/core_prng/src/threefry32/threefry32.c b/_randomgen/core_prng/src/threefry32/threefry32.c new file mode 100644 index 000000000000..e30d9c5690e8 --- /dev/null +++ b/_randomgen/core_prng/src/threefry32/threefry32.c @@ -0,0 +1,29 @@ +#include "threefry32.h" + +extern INLINE uint64_t threefry32_next64(threefry32_state *state); + +extern INLINE uint64_t threefry32_next32(threefry32_state *state); + +extern void threefry32_jump(threefry32_state *state) { + /* Advances state as-if 2^64 draws were made */ + state->ctr->v[2]++; + if (state->ctr->v[2] == 0) { + state->ctr->v[3]++; + } +} + +extern void threefry32_advance(uint32_t *step, threefry32_state *state) { + int i, carry = 0; + uint32_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/_randomgen/core_prng/src/threefry32/threefry32.h b/_randomgen/core_prng/src/threefry32/threefry32.h new file mode 100644 index 000000000000..8e9a1161e4ed --- /dev/null +++ b/_randomgen/core_prng/src/threefry32/threefry32.h @@ -0,0 +1,827 @@ +/* +Adapted from random123's threefry.h +*/ + +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include +#define INLINE __inline __forceinline +#endif +#else +#include +#define INLINE inline +#endif + +#define THREEFRY_BUFFER_SIZE 4L + + +static INLINE uint32_t RotL_32(uint32_t x, unsigned int N); +static INLINE uint32_t RotL_32(uint32_t x, unsigned int N) +{ + return (x << (N & 31)) | (x >> ((32-N) & 31)); +} + +struct r123array4x32{ uint32_t v[4]; }; + +enum r123_enum_threefry32x4 { + + R_32x4_0_0=10, R_32x4_0_1=26, + R_32x4_1_0=11, R_32x4_1_1=21, + R_32x4_2_0=13, R_32x4_2_1=27, + R_32x4_3_0=23, R_32x4_3_1= 5, + R_32x4_4_0= 6, R_32x4_4_1=20, + R_32x4_5_0=17, R_32x4_5_1=11, + R_32x4_6_0=25, R_32x4_6_1=10, + R_32x4_7_0=18, R_32x4_7_1=20 + +}; + +typedef struct r123array4x32 threefry4x32_ctr_t; +typedef struct r123array4x32 threefry4x32_key_t; +typedef struct r123array4x32 threefry4x32_ukey_t; +static INLINE threefry4x32_key_t threefry4x32keyinit(threefry4x32_ukey_t uk) { + return uk; +}; +static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in , threefry4x32_key_t k); +static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in , threefry4x32_key_t k) { + threefry4x32_ctr_t X; + uint32_t ks[4 + 1]; + int i; + ks[4] = 0x1BD11BDA; + for (i = 0; i < 4; i++) { + ks[i] = k.v[i]; + X.v[i] = in .v[i]; + ks[4] ^= k.v[i]; + } + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + if (Nrounds > 0) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 1) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 2) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 3) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 3) { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 1; + } + if (Nrounds > 4) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 5) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 6) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 7) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 7) { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 2; + } + if (Nrounds > 8) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 9) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 10) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 11) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 11) { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 3; + } + if (Nrounds > 12) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 13) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 14) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 15) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 15) { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 4; + } + if (Nrounds > 16) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 17) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 18) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 19) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 19) { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 5; + } + if (Nrounds > 20) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 21) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 22) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 23) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 23) { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 6; + } + if (Nrounds > 24) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 25) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 26) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 27) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 27) { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 7; + } + if (Nrounds > 28) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 29) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 30) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 31) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 31) { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 8; + } + if (Nrounds > 32) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 33) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 34) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 35) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 35) { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 9; + } + if (Nrounds > 36) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 37) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 38) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 39) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 39) { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 10; + } + if (Nrounds > 40) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 41) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 42) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 43) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 43) { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 11; + } + if (Nrounds > 44) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 45) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 46) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 47) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 47) { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 12; + } + if (Nrounds > 48) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 49) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 50) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 51) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 51) { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 13; + } + if (Nrounds > 52) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 53) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 54) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 55) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 55) { + X.v[0] += ks[4]; + X.v[1] += ks[0]; + X.v[2] += ks[1]; + X.v[3] += ks[2]; + X.v[4 - 1] += 14; + } + if (Nrounds > 56) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 57) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 58) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 59) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 59) { + X.v[0] += ks[0]; + X.v[1] += ks[1]; + X.v[2] += ks[2]; + X.v[3] += ks[3]; + X.v[4 - 1] += 15; + } + if (Nrounds > 60) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 61) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 62) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 63) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 63) { + X.v[0] += ks[1]; + X.v[1] += ks[2]; + X.v[2] += ks[3]; + X.v[3] += ks[4]; + X.v[4 - 1] += 16; + } + if (Nrounds > 64) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_0_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_0_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 65) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_1_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_1_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 66) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_2_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_2_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 67) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_3_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_3_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 67) { + X.v[0] += ks[2]; + X.v[1] += ks[3]; + X.v[2] += ks[4]; + X.v[3] += ks[0]; + X.v[4 - 1] += 17; + } + if (Nrounds > 68) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_4_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_4_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 69) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_5_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_5_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 70) { + X.v[0] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_6_0); + X.v[1] ^= X.v[0]; + X.v[2] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_6_1); + X.v[3] ^= X.v[2]; + } + if (Nrounds > 71) { + X.v[0] += X.v[3]; + X.v[3] = RotL_32(X.v[3], R_32x4_7_0); + X.v[3] ^= X.v[0]; + X.v[2] += X.v[1]; + X.v[1] = RotL_32(X.v[1], R_32x4_7_1); + X.v[1] ^= X.v[2]; + } + if (Nrounds > 71) { + X.v[0] += ks[3]; + X.v[1] += ks[4]; + X.v[2] += ks[0]; + X.v[3] += ks[1]; + X.v[4 - 1] += 18; + } + return X; +} +enum r123_enum_threefry4x32 { + threefry4x32_rounds = 20 +}; +static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in , threefry4x32_key_t k); +static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in , threefry4x32_key_t k) { + return threefry4x32_R(threefry4x32_rounds, in , k); +} + + +typedef struct s_threefry32_state { + threefry4x32_key_t *ctr; + threefry4x32_ctr_t *key; + int buffer_pos; + uint32_t buffer[THREEFRY_BUFFER_SIZE]; +} threefry32_state; + +static INLINE uint32_t threefry32_next(threefry32_state *state) { + int i; + threefry4x32_ctr_t ct; + uint32_t out; + if (state->buffer_pos < THREEFRY_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 = threefry4x32_R(threefry4x32_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 INLINE uint64_t threefry32_next64(threefry32_state *state) { + return ((uint64_t)threefry32_next(state) << 32) | threefry32_next(state); +} + +static INLINE uint64_t threefry32_next32(threefry32_state *state) { + return threefry32_next(state); +} + +static INLINE double threefry32_next_double(threefry32_state *state) { + int32_t a = threefry32_next(state) >> 5, b = threefry32_next(state) >> 6; + return (a * 67108864.0 + b) / 9007199254740992.0; +} + +extern void threefry32_jump(threefry32_state *state); + +extern void threefry32_advance(uint32_t *step, threefry32_state *state); diff --git a/_randomgen/core_prng/tests/data/pcg64-testset-1.csv b/_randomgen/core_prng/tests/data/pcg64-testset-1.csv new file mode 100644 index 000000000000..da6d77d40f19 --- /dev/null +++ b/_randomgen/core_prng/tests/data/pcg64-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xb174ddf3fe597da6 +1, 0xfc217240c1e61e6f +2, 0x20279da26fec9cbf +3, 0xa5f4ee34651f4e1e +4, 0xb254d7901c68b9db +5, 0x6bf2a64e4052c36f +6, 0xbec4c7418c0f61b6 +7, 0xb03e595a4ef2b2bd +8, 0xc8e051957ccb74c6 +9, 0xf5082df7473c6f62 +10, 0xb72aa3dc22752a38 +11, 0x7a941561514bd680 +12, 0x90a95f42834f347b +13, 0x88e17b9d59def797 +14, 0x18f19c86bfe60368 +15, 0x667f89277be8d1d8 +16, 0x63305475e7aeff27 +17, 0xd7e4d5c09fb0fb4c +18, 0x7dd6deab03a8c26a +19, 0x42bbcb746e2d4b26 +20, 0xe91f2ac4fa90689c +21, 0x2f83458da0af3125 +22, 0x49a43537a00fae89 +23, 0xef02111d1ebc16eb +24, 0x32b3b3019875f3e7 +25, 0x89eb15c48cd02774 +26, 0xa9f1b37865752731 +27, 0xe0eff9dadc47fb3 +28, 0xae859b1c54cc90c2 +29, 0x7b7c5e04d5015dec +30, 0x38faeff5ce3266ff +31, 0xd2ddd0d19fbc24ee +32, 0xe0d4f692829a31a9 +33, 0x30a6aa3f408e71c2 +34, 0x298362be21de6d44 +35, 0xb7efab759e691149 +36, 0x2ae1f84bba093d4c +37, 0xf6ab55f78f8b9258 +38, 0x2275d0af583cec95 +39, 0x18cfe066b183ac3c +40, 0xcc0a546d54064cf5 +41, 0x5de027ea3c25c225 +42, 0xdaf31ef489fe71e1 +43, 0xa7a2b1a72a4360e7 +44, 0x678a55d7a0506791 +45, 0x36facd8799ad2b78 +46, 0x32fec94506dca70e +47, 0x34e890d8539871f8 +48, 0xec48b5362b0d7818 +49, 0xe2e58921cf8228d3 +50, 0xd163588ec22730a4 +51, 0x17e2322b6be47d25 +52, 0xe1544989a0c6d24f +53, 0xa3a10fb279cdc347 +54, 0xad4ee318a5853900 +55, 0xc96a185feef4a85d +56, 0x82ec5b3aed6636fb +57, 0x2aac2ef8f25426d7 +58, 0xa81e3114165e0d08 +59, 0xc1d8128f83969da5 +60, 0x157505508eaf50f1 +61, 0x77c175067c9c199c +62, 0x973052089bd7af0 +63, 0x3cd70041e32c1921 +64, 0x7783719f13a254a0 +65, 0x2216485ff502d9ff +66, 0x7dae695d2c7f3b79 +67, 0x809ce710156fea36 +68, 0xb90ac31262460e4e +69, 0xc1afe8019306e7d7 +70, 0x6c57638edba4ca0a +71, 0xbe6133f6ab1e9aeb +72, 0x8f5699ff0bcf341d +73, 0x69d0218df036bcbc +74, 0xf0976fd79735d47d +75, 0x82b36a795e5cc74b +76, 0x263c30766b985686 +77, 0xf7426f94511d5ba0 +78, 0x8b04f9573050ed9e +79, 0x7280d4ec202e8359 +80, 0xa8235fbd1324f172 +81, 0x6dbd5d500a809a8c +82, 0x26c53c69292bca1d +83, 0xe348f657b20305ec +84, 0x562f0e2fbb375421 +85, 0xdf2be07bebfbe447 +86, 0x4275044640683760 +87, 0xad5d68bfe4ab4858 +88, 0x3c0e57df5b3306f0 +89, 0xc9d87622ac847565 +90, 0x83d04fd9e102c311 +91, 0x71996b9c65aaf5c0 +92, 0xe3df32742d6fc446 +93, 0x58d3a6573a39d0cb +94, 0x74dfa090e96d289d +95, 0x7856f45e5416c1ea +96, 0x80a18e88b3e4dff8 +97, 0x60565bbcb04f56ac +98, 0x9f4cf5ec45fae3a6 +99, 0x885d2909fe34e3f0 +100, 0x7a1db9118f60dee0 +101, 0xc4c17dc810746c7e +102, 0x8b954b14effe83b1 +103, 0x4f89fb0940999c86 +104, 0xc62e634bceca1c97 +105, 0x7e06e87dffd1619f +106, 0xd1ccbce841371671 +107, 0xe7f99698c66df1b3 +108, 0x5302c2f0e4e1f4e0 +109, 0xa57d11d3d7ee652e +110, 0x8abe0ed0e5508407 +111, 0x6780588af9f6c2ff +112, 0x8603a9fc73b6a4cd +113, 0x169c13a0b7a166b9 +114, 0x868969fb53578598 +115, 0x6089e0eacbe69039 +116, 0xf82482d424397dc2 +117, 0x11475d20896fc890 +118, 0x7983933df29e2aa0 +119, 0x4889c4780cd8e9cc +120, 0x53ebb258f3ea266b +121, 0x121896059b256fd1 +122, 0x2f9934516b2f8090 +123, 0xbabb9fa1d1efa60c +124, 0xfb0b1370ea044797 +125, 0x782ab293b597bc8e +126, 0x297fc0b3977271f5 +127, 0xa573e4d0674d02fc +128, 0xc7e8ddb6efe8a2db +129, 0xaae8a024e62f6e32 +130, 0x3217a47698c9e439 +131, 0xd7015db847a3de0b +132, 0xbc0b4368776e10a7 +133, 0x69d9ef0178679bfb +134, 0x28fd8f0936b66fab +135, 0x45b1c4d4aa9b5aca +136, 0x28feade39cd3ac00 +137, 0xa7e6515c534520f1 +138, 0x735703b5f4bfd54e +139, 0x798271ae0c91b8d8 +140, 0xf858458f9efa8d2 +141, 0x6a41f5845422a9e +142, 0x7fb0bba5f097aab0 +143, 0xbfaea58fe090e745 +144, 0x84770504bfb15b35 +145, 0x67ae11aa368049b8 +146, 0x846c5e493ee15e4a +147, 0xbbcf3baf029f056c +148, 0xd30c23bde142a356 +149, 0x32cd403edb746a8d +150, 0x40161ab00c636730 +151, 0x3a882c3c60d3e19a +152, 0xca8faab24d826529 +153, 0x241a687288551d04 +154, 0xbbc607fb9b48ac00 +155, 0xa844329d0c2d475a +156, 0x8fa4aa1d7296b9e4 +157, 0x82c7dc1f588ce2fc +158, 0xcbdaa663041e078c +159, 0xec108d219b2b147a +160, 0xcab01864270b334 +161, 0x6d3d08545041621b +162, 0x2aae054b8e5648f +163, 0x1bf5a72fa70e7eab +164, 0x2dddb2050af45a3a +165, 0x2b910b7078021a75 +166, 0xf7160201ede45f4e +167, 0xfaf75ae996f079bb +168, 0x407984a9451e659c +169, 0xbdf9c0a9ea078ac0 +170, 0x1e7717b8345acbb6 +171, 0x25cc2df4c0c8dc4a +172, 0xfda1715b573850db +173, 0x50e5cedad99e2651 +174, 0x9a67673ed73cfc0 +175, 0x802ec4fc9e946805 +176, 0x677cd320e641999f +177, 0xbfeb1b6053fe4f78 +178, 0x220cfc90bd31541 +179, 0xe4fdfae10ae6c86f +180, 0x76c568fd869af80d +181, 0xd17dc57109200bb1 +182, 0xeb96ba01c95382be +183, 0x6a9c7ebea5b5f7ac +184, 0xc1680450532fb8cd +185, 0x26b0829f68888094 +186, 0x98335aa1612d7c70 +187, 0xad8662125bf32ae3 +188, 0x15f18a9025ae26e8 +189, 0x5d065dba0d17c9fc +190, 0xf68e1d59f10ff109 +191, 0xcfbd97901a79f8b0 +192, 0x3e72a9fd1d95f143 +193, 0xe7ee82c1bb740dfd +194, 0x3a0f4ae5db22527b +195, 0xf4d025080ed4ea92 +196, 0x6924a99549b4657 +197, 0xcb83b51552208e2f +198, 0x9f306634214b44e9 +199, 0x4fb3307b0e1a7535 +200, 0x73d202d4225c5394 +201, 0xd5a2fa42f8cc8c5c +202, 0x7b3b3e3f7b948d3c +203, 0xa2dbc4d30d8c148e +204, 0xd1bfc1f05a8f2c5d +205, 0x2b00a4efa2f19262 +206, 0x9d4a05bb18647f48 +207, 0xff21fbaf0b46d13f +208, 0x126f9c5f2132af20 +209, 0xd4b7629b0d9a6b89 +210, 0x2d61949fb3126ecc +211, 0x30d61648763db1ce +212, 0x9c5234d15120bf17 +213, 0x2eb0eccb6cc14c8a +214, 0xcf18eff5ca2af8a4 +215, 0xab5fe599ea68c377 +216, 0xe47a0bb8436af89 +217, 0xd3728a566187c400 +218, 0xb8b54592b62f633e +219, 0xe02b958f9c13a180 +220, 0x9e5f5cc85283f24a +221, 0xbd1ab869878744a +222, 0xb93fd6297a29c8dc +223, 0xf22f06ee61dc2413 +224, 0xc93fe440766cbd8e +225, 0x7459d9b19375a51c +226, 0xd4ec87c57baa4127 +227, 0x1514d0226dc0409e +228, 0xc6b0d7e1bd56b190 +229, 0xc0c61c73c9dbffee +230, 0x2f1154afb48a93e2 +231, 0xd2ca05901bae0117 +232, 0x6263f647273694a0 +233, 0x94a98bf80488205b +234, 0xcb0d63747735bead +235, 0x9cbd4e1659932c5b +236, 0x1807e01931b5ade0 +237, 0x1d9f7721d3067854 +238, 0xb25dbde4ec77e547 +239, 0x4b186592a39adcd6 +240, 0xe8ad5514de72a98f +241, 0x2deac1cb096a09b4 +242, 0x6952f4b82a2c87 +243, 0xaa1590223ed83ffe +244, 0x9baf13d08f572e12 +245, 0x83ec1bca1e724d88 +246, 0x5c61bf2222b4907 +247, 0xd950ff64ad7b956e +248, 0x36bf5e992bf1f211 +249, 0x75ad67249d7a6c35 +250, 0xeb12dcef5c2bfe7d +251, 0xc508da925157e39d +252, 0x91cbd7491ea7f70e +253, 0xf10c018ec0b0e55 +254, 0xeeffb21fef1e87f1 +255, 0xe31692b834d067dd +256, 0xd69bbafdeb5c0d15 +257, 0x41358dadb9260eb1 +258, 0x5fa3c67d353cd6b2 +259, 0xdbb743cac20b2eda +260, 0xe7877ba98b2bfe4 +261, 0xf14d679436fd2dcf +262, 0xa313e39059d62afe +263, 0x7eaa134c761a6183 +264, 0x7719af9ad1fecaec +265, 0x533f921a4702d433 +266, 0xe072f9665ec3a3c8 +267, 0xba89560ab4ba08fa +268, 0xe94f0aa266e56d53 +269, 0x774b84bcb152afc +270, 0x787c9517e589748d +271, 0x3831a5303adfd362 +272, 0x19cb20184a4264f8 +273, 0x9bc5e99e1773700e +274, 0xed323bf38642f651 +275, 0x860868c0eba789f2 +276, 0x8c1602ffd9a5621a +277, 0xe298d8fc74e146ce +278, 0x3181a2083c76037f +279, 0x27942fd6842079c0 +280, 0x38fe8c0406516df +281, 0xd211a4a42857bec3 +282, 0x56002508b351879d +283, 0x2472ed93614c7e99 +284, 0xbcafdaadc0f77b7c +285, 0x86becbd3e5303107 +286, 0x930251d84de72320 +287, 0xea79aa2964954052 +288, 0x6dbc5e63b50b1724 +289, 0xb098535ed4bc7372 +290, 0x6490d6d8541fb656 +291, 0xc738f6ccb4b7076b +292, 0xd69ee4fd6ce63026 +293, 0xfa98e9d78a628338 +294, 0x9c30b63a70d607b6 +295, 0x8d544b5d224a25d9 +296, 0xa051f7fe38445228 +297, 0xf6931861338a00f5 +298, 0xecd71cd64b0b5dcd +299, 0xdbc818e7126193b +300, 0x3aaaa032aad8199a +301, 0x6fd68a3818e0c439 +302, 0xc82a651ba9ede8c9 +303, 0xe6d958e267017187 +304, 0x73a9eab64de651ae +305, 0x5a6757f7f222bb3c +306, 0xe62e7cca6bd17a32 +307, 0xc4f6c31f528dd387 +308, 0xdecd8b663c995773 +309, 0x69a21dedcbfef9c7 +310, 0xb33f8ac00f17b6b2 +311, 0xe32b3c962d613ba3 +312, 0xa9c317d026600d41 +313, 0x901d971c49671213 +314, 0x46c3f3d35db8808b +315, 0x1336297232af9791 +316, 0xed88d9242e11edb3 +317, 0xc70c48843f54af0 +318, 0x611062a0461deedf +319, 0x7e3183514f127f20 +320, 0x7b549d10bace1c47 +321, 0x6db523d19d0a7af3 +322, 0xf6e677e5222a21a4 +323, 0x28e5188ba7055c32 +324, 0xbe7b41d2ce539c4f +325, 0x5c085a18c3b7bbe0 +326, 0x209cf345b3c3b06c +327, 0x79ca5407dd486857 +328, 0x8e07ac4c65338ccd +329, 0x56dd5372249cadad +330, 0x27e0b07863fa27ff +331, 0x78dec95d299a8699 +332, 0xbd5d71253b73d456 +333, 0xbf83b6cedd205e9 +334, 0xee2352ee69aa68e +335, 0x4b14f253d684cfbc +336, 0x12ffa5d5f8a34bec +337, 0x2e38346fbc793f67 +338, 0x2ab5862872b4850b +339, 0xcbc8aec1e2bb6760 +340, 0xd79ef783845cc329 +341, 0xdbdcde91e1685704 +342, 0x29880643aa1095e4 +343, 0xcd5ccc1fe9a616af +344, 0xc7b6cdc4a43c132c +345, 0x7b08597fdec7fc9c +346, 0xa01ab3827e120a16 +347, 0x89ce37de99ca7748 +348, 0xb4644823ea6b90d5 +349, 0xdbe189861c409209 +350, 0xbfeb614759981b60 +351, 0x48c2c3a6d2419755 +352, 0x1aa1df0e99b3417e +353, 0xb9f061bf98c0da28 +354, 0x8bce2755a0b5b8ae +355, 0xc9bb2ff33d60b3e7 +356, 0x6abcbb1ea0d3a575 +357, 0x983a3c16a0e5d6f8 +358, 0xa122e616797ccdbe +359, 0x751dfe60252a01d0 +360, 0x8d1bcbbde84f6a11 +361, 0xb6bc4f2942ba0e57 +362, 0xb298977a4bb20e12 +363, 0xcf658188dd931722 +364, 0x39735757b19c90a3 +365, 0xc2fcf1df99f1b7c4 +366, 0xd42c50f6a912aaea +367, 0x95d0cb8a953965c4 +368, 0x75c7d03289269f25 +369, 0xd8d96184031fb36b +370, 0xb3b34b5ba8bac75 +371, 0xcfbf16d241e46f8c +372, 0xec465e59019b6f6f +373, 0x4051ce0bc2562a63 +374, 0x859f05ce7b75da05 +375, 0xf2661ef2e3c733ef +376, 0x8067f432dd5af0c4 +377, 0x6e8542a346911713 +378, 0xfcda2ac6aa45ca20 +379, 0x571f23fdacb25fe2 +380, 0x2546f5badf7adb8b +381, 0x929ebe6fbd330e2b +382, 0x9d41d6ded9facbeb +383, 0x4cf9d9da6c125106 +384, 0x495d5708443faa36 +385, 0xb0023a41a6057e59 +386, 0x37fa1cd9ce66b20a +387, 0x96a376fca4aff5a8 +388, 0xc22469c4a3e1ea85 +389, 0x5ab79b721966249b +390, 0x2124be452f7d4ca4 +391, 0xe71bb882b954ca11 +392, 0x322bdcaf9c7b0efa +393, 0x4c99c8753878439f +394, 0x3ffd6caec9f9ac49 +395, 0xfba842dd40a3c72e +396, 0xfd93517d31681d77 +397, 0x44c139a74249a128 +398, 0x828a145610684c8 +399, 0xb53696f802522b6 +400, 0xa2da2199474d079a +401, 0x739e508fbbdeb714 +402, 0xe75c4734a7c95f94 +403, 0x5c22c226f2bd8487 +404, 0x7108fa6b99b0d72e +405, 0x3c60b40f6e4bebde +406, 0x395150555d56dd18 +407, 0x13246a6e4d795fe3 +408, 0x27dca990fb678027 +409, 0xc5a92c32724a7373 +410, 0x30fed89f4171a817 +411, 0xf7f7810edea2e7eb +412, 0x46e930eef5351212 +413, 0xe1331cd8a678dc66 +414, 0xd4cc0a5f96a72457 +415, 0x2559f8d286b1da16 +416, 0x73831b2f6e4a4ba +417, 0xd929ccf267504761 +418, 0x8a7a1b357f8bbc38 +419, 0xd5e0d3e200d0d633 +420, 0xc2cc05cc3ac5abb +421, 0x75b8f78a06ca465b +422, 0xeaf1d6aa9c0baef3 +423, 0xa6c9bc3dbe45e62e +424, 0xb1496074b4c338d7 +425, 0xc18ebb892108cec +426, 0xf6cbbf4cd0f8f9ba +427, 0xd73759407ecbdcf6 +428, 0x54dc0805c85a3b0c +429, 0x4ba3936d6be048f3 +430, 0xa3fbea19803cf35 +431, 0x78b1d3a837d4bed +432, 0x6ed09ac2c177453b +433, 0x16134c4e8b30f6ba +434, 0x94718ce4868f01a3 +435, 0x612fa336da82e66d +436, 0x5d8833c9483b235d +437, 0xf5c72d4883bed9a2 +438, 0x2a6e27d1ed337134 +439, 0xfba250d6b9cc0d2b +440, 0x432f8734b61e4366 +441, 0x45e8becd5ccb4f32 +442, 0xffc7d68cb343170a +443, 0x247cb9a6b29b1a35 +444, 0x89876df3681dc65 +445, 0xd1e646c49aac769b +446, 0x4c3cd721635602d0 +447, 0x5139344709c749fc +448, 0xc5130d981e1a6b14 +449, 0xff269bea082608cb +450, 0xf45a5d57a6d4c6a6 +451, 0xc4c9f3e5398db827 +452, 0x2b3a0eacd42665b4 +453, 0x94d847d848a8e65d +454, 0x1a8aff186e1d75d2 +455, 0x6ad986366c54a242 +456, 0xbd832c0607523e7e +457, 0x973064c20c31842d +458, 0x34d0513e6d602f80 +459, 0x91b3c812f83392ed +460, 0x4c49ba38b6a4cf90 +461, 0x82e3370e1c5ad5d4 +462, 0xa29a01fa53250a13 +463, 0xbe8ed1e615a1ee6a +464, 0x17fb15941a9fe6b4 +465, 0x84aea1c0138fb970 +466, 0xab065efb4558003d +467, 0x3345b340257a2551 +468, 0xfd2ebda1048c0dcd +469, 0x2aa72fce0cb23982 +470, 0x9952f9363830ff6d +471, 0xdb240e279cb7f901 +472, 0xb4a1e7b54206aca4 +473, 0xe13bdbb980623f25 +474, 0xd989f009368f8a9a +475, 0x7084b7695149660d +476, 0x55b92a3f139c7f1 +477, 0xdb43c75c633debd0 +478, 0x94e362574c70b9a8 +479, 0x218a1a06d9223f9b +480, 0x82f3c3808f86bb95 +481, 0x63e9de6cee4b77b2 +482, 0x3bc5effa36bb166 +483, 0x8369cbe5fa0ecab +484, 0x2a5808b4d7bc8572 +485, 0x6856e29700de99f5 +486, 0x107e86fcfd4a48d9 +487, 0x15c9ee6528c1c223 +488, 0xbf7318d4206c5e75 +489, 0x15d7a6aa9343c9e8 +490, 0x93419fe0ee3bd5df +491, 0x916c7f75ededdd53 +492, 0xe89d6230690f74f1 +493, 0xf92f96834e0eb27 +494, 0xed5adc06c305adc9 +495, 0xf656fe40e7ecb4d7 +496, 0x32a2d3eda46114b6 +497, 0xb3f17867d23c75e2 +498, 0x2a2cc838c4d89c33 +499, 0x413df7052f8866e7 +500, 0x373bd93e91bbed18 +501, 0x78c8e5aa1e1e2dda +502, 0x6bd362f6be6d572b +503, 0xba1926efd387aeb5 +504, 0x3b826b77ae3e53fd +505, 0x383cf5a66fb6723c +506, 0xf5a4e1dded64d931 +507, 0x76d9843a304729d3 +508, 0x205b8753b6d309f0 +509, 0xd2a68ef67d8e7758 +510, 0x60d517f325411c0c +511, 0x37a3bb4950cf08d5 +512, 0xea3d4f95542ffe2d +513, 0xa88708db07fb1d34 +514, 0xd96555e1194f7ee0 +515, 0xdd046e642b59fa51 +516, 0x18ff34e73582d46b +517, 0x7ed73af03535c5fe +518, 0x8ffd64801d2c5187 +519, 0x7134902903c9cfe2 +520, 0x74fa0b238ad1e1ec +521, 0xa220ff0032395fd5 +522, 0x4ed0a7a2d9c3a064 +523, 0xb02cb878b4c9a04d +524, 0x8437cebea5ae2bec +525, 0xabcc162a0027aefa +526, 0xc8e86ab8f5c09011 +527, 0xc28dfaf764ec07d4 +528, 0xb19127d64ae5db18 +529, 0x857cb1b00ac7fbc7 +530, 0x173a441c4b494aad +531, 0x255af1a4d50952c3 +532, 0x87ff01c7d0139add +533, 0x489b15e4c97cfcde +534, 0xd4abbccecfb67239 +535, 0xa1a2912ad34ac4fb +536, 0x94b7f12e10bf720 +537, 0xdb8840c295333634 +538, 0x5a29aab5b359f2c0 +539, 0x630352d282b695bd +540, 0x399f00854d3fbdf3 +541, 0x19e917e0eb8bf070 +542, 0xa464b4dc93d1fe7d +543, 0xf152d3cdecbd7647 +544, 0x517907b570a6b082 +545, 0xfeb06f4bd978e7bc +546, 0xa22859ad14c0f183 +547, 0x33c11e90be9721e3 +548, 0x8394f642b5a40d7d +549, 0x9525633e7e60ab73 +550, 0xf97401c9b4b96001 +551, 0x3d78ce1ecf900029 +552, 0xa85791d9754a2765 +553, 0x16e77aadd9a30946 +554, 0xc91d4defe72f39f2 +555, 0x2fb67bd91edc4b51 +556, 0x95d635e95b468fa7 +557, 0x28b81869d1739e29 +558, 0x5b098fa22cb1747f +559, 0x6544b8704bd2400a +560, 0x91a64f9ec6e93245 +561, 0x2b46ba92268db263 +562, 0xbb52d7758efd5416 +563, 0x7032adc08e6d39da +564, 0xe9d3bbefdb61feb6 +565, 0x2d603389c757996b +566, 0x5871ed32ce17d042 +567, 0x31d622a6b8438f70 +568, 0xc71af17db6bf7aed +569, 0xe419e3c6fbe86530 +570, 0x648471d670f18dcd +571, 0xd13f9e25078599ed +572, 0xdaf86e56826d07a3 +573, 0x3c9374e4420a8580 +574, 0xcd75b12ad6d8d9fe +575, 0x2d4530f6e2b93ca3 +576, 0x303bb663ad4ca963 +577, 0xf8caecede4436b61 +578, 0x315a8124669a907f +579, 0x1c18d130a4b93836 +580, 0x9e0b83663631562a +581, 0x400059c1ce071c7f +582, 0xb27f7f67e7cbd970 +583, 0x6b446e8c4866f3d0 +584, 0x4ab1755d2734121c +585, 0xb9fc8e017d89edf2 +586, 0x3a9aa7f50355c0c9 +587, 0x899fece06a169b2e +588, 0x19d7d7088db0b27d +589, 0xe4f8862ca8f6b87e +590, 0xceaf0d6ab4ba624d +591, 0x318965c56f79886d +592, 0xb1840d9bb60b720e +593, 0x387427e7549150ca +594, 0x9be3edb621a5d2ef +595, 0x9758993cca6a481 +596, 0x3733c5cd48a1590c +597, 0x9bbe26951c666fb1 +598, 0x74c7e89fefb4ba59 +599, 0x6aa490a23907053f +600, 0xa62febef1e8d7300 +601, 0xdbfb07bbba2fd4cd +602, 0x11ee9e4bbd4f358 +603, 0x6b40912657c7f02f +604, 0x8d56c1a9216714bb +605, 0x7fcd86985949c2f9 +606, 0x706bb172d5677f2c +607, 0xfb657efea1331957 +608, 0x6e3032f72a3fe367 +609, 0x509fb8c5b618a18e +610, 0x3599e957259222e7 +611, 0xaafc78bea53c9102 +612, 0x404addaf7ac55279 +613, 0x97db28b3b0a2dddc +614, 0xd3f5b151a9f5aefb +615, 0x1a6534a9be80a19a +616, 0x78f989eb80e055b7 +617, 0xe0200fe015112dce +618, 0xfbe67decef6204dd +619, 0x662fef92c8e00970 +620, 0x9a7838962250f5d7 +621, 0xac0eabb1621567b3 +622, 0x1874cf715cdc5daa +623, 0xd3281a25a82ceecc +624, 0xd8ac0e497b11156c +625, 0x3c8bf98f8210af89 +626, 0x971973ff9d428a3f +627, 0x1af47276bc157e63 +628, 0x671cd5e661ed0a05 +629, 0x71b8ffba9b976a0 +630, 0x8763f1fa85c5f5d5 +631, 0x61f3c56f3441aad4 +632, 0x86482f5e90362e3c +633, 0x8e9d9aceba401c48 +634, 0x51d916579d19d42b +635, 0x67bdfa28310ad3c7 +636, 0xb9ab819d6a00add8 +637, 0xaa12cb0ed2d507bf +638, 0xc636190dfc7f6d43 +639, 0xf3f1e6c104c5e782 +640, 0xaed0be2f07ad4313 +641, 0x1d782d74661278bf +642, 0x58e6501bc7e61fa2 +643, 0x8ca4ad0e02d7fb42 +644, 0x8afc9e9fe83d4b78 +645, 0x72cb69cf4abf0b1d +646, 0x7601a7b3500d474d +647, 0x97fee7da53b533b0 +648, 0xd6ab646f53c0e19a +649, 0x6480f60992f2fcc0 +650, 0x64ec7590c60a4c00 +651, 0x3ccab37f11acbe91 +652, 0x9ddd546f201299fd +653, 0x9a0dc59d0b545d96 +654, 0x8c5f366bd21664f5 +655, 0xc0af97b445bfc5ee +656, 0x29762536dc00c3fc +657, 0xfc30927fd8f1c257 +658, 0xac9aadfced7d59fb +659, 0x8d039f87658a29cd +660, 0x13a3d73580eacf6f +661, 0x80b80e0adcc11ac5 +662, 0x1e53c21e639f9d08 +663, 0x8a73352dc442bca7 +664, 0xec7cb2fe0e6b0100 +665, 0xfa5e63f403ac3f33 +666, 0x493d9a0018185f8c +667, 0x1b1d1f41c6cf5cb4 +668, 0x95b4caca3e2500a7 +669, 0x4e759e6f89f62f91 +670, 0xd0a76a3198d7c05f +671, 0x86eee6259cab63b5 +672, 0x1daab21067011b59 +673, 0xd02d9236ebc91b38 +674, 0x693e17ac2b70e1b7 +675, 0xceb5899aa14d0f86 +676, 0x59ffc317faf17ab2 +677, 0xce94f02892a0fa30 +678, 0xf7c9d6f9e753737c +679, 0x87258cf7ff6a29b5 +680, 0xb39fc8ea8aa52a0e +681, 0xadd4b4e73af1103f +682, 0x511f423730b25a4e +683, 0x7f673288e53502b2 +684, 0x9aa499e3b6295919 +685, 0x83841ad95e6a7a6 +686, 0x6e549a2457a850c +687, 0x4763220b923113c3 +688, 0x99737bb550aa5049 +689, 0x89eb31b3f707c4 +690, 0xdad5331dda8a58d3 +691, 0x5f1681518d5a21b8 +692, 0x258a0b9b24110918 +693, 0x8854bb025009fa21 +694, 0x7ac331fd885642af +695, 0xe520f0e9bedf0bf6 +696, 0xc9419e8801aa2afb +697, 0x356fdc0fc3702b37 +698, 0x6d6a25f39fbc9524 +699, 0x930f65c4dbf8ae94 +700, 0xa73d7bbf8c19c4b3 +701, 0xe473f700513139fa +702, 0xfef8f0e84c521bae +703, 0x88525351995576a7 +704, 0xa156b646ab95f272 +705, 0x1a46ff3b9ae7e723 +706, 0xf6d82b8bd9f2a80 +707, 0x837b8127d8f39ebf +708, 0x1f8e120ea11fc9bb +709, 0xbd0918421430f8c9 +710, 0x4ef121a688d130c7 +711, 0x3fef66f1cf180b77 +712, 0xa92070bdc6a0100 +713, 0x2444dcbb4853c174 +714, 0xe46b7d6234504df8 +715, 0xe5ac8fd968a5d1fd +716, 0x988828d885f04f30 +717, 0x9730c37b69f3d963 +718, 0xdb9a0d16bf0a2aab +719, 0xe75d00b3681941b9 +720, 0x518421d62db82da0 +721, 0x4da04c94268c1dae +722, 0xdcf2635a55b7da9e +723, 0xb679d8206c55a04c +724, 0x1fbf58865fec1e83 +725, 0x53ca7cc07c0e5785 +726, 0xd18eee3f5b57c813 +727, 0x9fc8d328e41d1299 +728, 0xb2231521e026e15 +729, 0x1a7e2a8df269acde +730, 0xe5f547b160b0a6de +731, 0xab01e7130bd70c14 +732, 0x82a051680f661a75 +733, 0x479da77dd9686ca2 +734, 0x1417cc197738b272 +735, 0xb65b5ced585a8186 +736, 0x40b5a74813e7a05b +737, 0x55481e0f404fc2c5 +738, 0xef1ca09a2640c44a +739, 0xa0f1d37ee2db47cf +740, 0xcabb0c8e551f0587 +741, 0x84227dd83ad941ef +742, 0x7b47691b6e8327d +743, 0x4fe615394f53d6d2 +744, 0x60bca7e568f65c80 +745, 0x8676b74f2d5600f4 +746, 0x70f256171f1eb9b1 +747, 0x6b1d25099f80e1fd +748, 0xd8e77e8a67ff3338 +749, 0x3ec375feb7727aca +750, 0x26b9ad4afd4be26b +751, 0x849e6f9bc5ec636 +752, 0xa34e3fad187c089f +753, 0xe369ba87f04ecc37 +754, 0x83c6e1c3985cab4e +755, 0x6ffc032379a15336 +756, 0x654645504b159afc +757, 0xabc97562087edfad +758, 0x4633765a9f068fe5 +759, 0xa226c586394d348b +760, 0x7034d9fd40133a22 +761, 0x89e1d142a1a20097 +762, 0x7a3e1387a5ecdf70 +763, 0xf0ae75084f0a1bc4 +764, 0xdcf97778ae782977 +765, 0x87996a44dbac128d +766, 0x94b102ac15479072 +767, 0x9d670a01e10c48a0 +768, 0x8f977a03176d0cb1 +769, 0x8522bdbed25653c +770, 0x8f2b64a9cd6b5483 +771, 0x86b2beaa71c92fbc +772, 0x40f896707639f820 +773, 0x40e7df1535fc03ad +774, 0x1d34c491e13debde +775, 0x862d5ad393292476 +776, 0xd33ee4efdd4b14d9 +777, 0x63ce5c7643b85ecd +778, 0xd28a7fe0700fd15 +779, 0x8c3536390f9b7b55 +780, 0xfaf87a9036dd0265 +781, 0x187e261c23b454a5 +782, 0x95362150f08e5f86 +783, 0x6588c21939d9521d +784, 0xc7cee242280b7526 +785, 0xc1b8f83462038485 +786, 0x68c2f342724de8d6 +787, 0x35c283dbca3c62fd +788, 0x556c441e9fdc5cee +789, 0x898ba42c4ad3f5ba +790, 0xc654a072fe9ce540 +791, 0xcc2da7cabdc658d4 +792, 0x518b6badf9c1ba7 +793, 0xd43b259427de48cd +794, 0xfe7e74d4415bea8a +795, 0xdee4cacb454d92c +796, 0xdfb09dde6d6c3000 +797, 0x5c0d4ce2c7a8d426 +798, 0x29ccf2d288f4de4a +799, 0x4106e7f40d2597ad +800, 0x3bc376950bccf69 +801, 0x65b74e149d1066e3 +802, 0x751d008e4f823e5e +803, 0x4a3b9a34d8ece205 +804, 0x372e79ed6d9461fc +805, 0x78e08cab6244f8d2 +806, 0x7d273315b6d9250b +807, 0x26c401cb05f556b2 +808, 0x3324d95fbc93408d +809, 0x14fb55fb83ab0a8a +810, 0x7ea7efcddd0a747f +811, 0x150a110bd5cb1b57 +812, 0x1122b31f5d20ad23 +813, 0xbd996a43507da1 +814, 0x6d11fad057e5a75a +815, 0x22a4d3223d77684b +816, 0x349973b5dda3d3e8 +817, 0xe4dab5aec267e32d +818, 0x371cbd61bbb7858c +819, 0x7e49182abfc0fc68 +820, 0x937722b126a7d173 +821, 0x29604490ccbe6611 +822, 0x6c8b230bdcc8dfaa +823, 0xb1c267c94d4550ee +824, 0x80d1fa6e33cde91f +825, 0xe205a132f35af0a7 +826, 0xe4e8e50899fea5c8 +827, 0x3a6517d09206dfef +828, 0xeff4e4f8efd0a4ba +829, 0xd8df88c992b3df74 +830, 0x5b0df3c40071c0ac +831, 0xd44a062781f833f0 +832, 0xef35653edcb68251 +833, 0x21f879df2bd3cfe0 +834, 0xdb5e837565891932 +835, 0x6da15316efae41e7 +836, 0xd33cdc0d05f8dd6d +837, 0x3c6588502a24be1c +838, 0x3d25da26bee94818 +839, 0x79979979960d383d +840, 0x8a20663424f816ec +841, 0x74c587d5824ee15 +842, 0x145f90c6b342c489 +843, 0xe2c2d15b8de95387 +844, 0xd9deaecc24e84ede +845, 0xce52add2f5c3ea3 +846, 0xd1da2db8cca0014d +847, 0xcbeed544f8791232 +848, 0xb55b421de003edf0 +849, 0xde102a5a87a9a5da +850, 0xd74fc9d34c964bd3 +851, 0xda7e1e271d197070 +852, 0x1167b33a6bad0d13 +853, 0xd35c886fd0e28798 +854, 0xfb3334085bbcef67 +855, 0x88f4957ddc912f99 +856, 0x7c1b0e356835cffa +857, 0x8c737bc009bf5a1c +858, 0x44edc242bfd88b0f +859, 0x391f8b5db15f8b01 +860, 0xd44794c8a4245701 +861, 0xefa90e38ba4a2f6e +862, 0x597f65c886e697b4 +863, 0x28972f6be3ca8677 +864, 0x18a487b5e89a9dbb +865, 0xffb15ebcb8a15fb1 +866, 0xa1f64108b7feeab0 +867, 0x36fc88b440612004 +868, 0x72a723294ba9af87 +869, 0x1a38da0ff8f187d7 +870, 0x529d7f6cd18f664a +871, 0x6a5941953b4732c7 +872, 0xe91243bd8fb27a03 +873, 0xb80c55de03262828 +874, 0xacb9183e5b28a8d0 +875, 0x4c4ca12eb3d5d2e5 +876, 0x758635a20eb18211 +877, 0x211e03e90d6bd001 +878, 0xe36e20fbf0f271b5 +879, 0x4daecb676fc64ebd +880, 0x8f1e82c4dd582eb7 +881, 0x6e3c35a21bca1b8f +882, 0xf3c2a69420f159e8 +883, 0x2cda4d630caba89f +884, 0x4c93f3f96360d308 +885, 0x4192046fb5e9d801 +886, 0x349f2b172f49599c +887, 0x7bbff8dd8b480e6c +888, 0x83b33fafc4388bf +889, 0x9a5440f806d9d1b +890, 0x8d6b62101dcfe51f +891, 0xbc7dd6987af227ca +892, 0x4338e67e0d6ba6a0 +893, 0x4a23deabbb5fc3ce +894, 0x9f8edc91e6356eb8 +895, 0xf6b723dd2dd5f80b +896, 0x35c558dd3443021d +897, 0xa559dd33c2cf594d +898, 0xa50ceeced7a82783 +899, 0x21107b581db4ee9f +900, 0x13e8dd9302e8c97d +901, 0xbd8491f437e57ad6 +902, 0x72f4c2a57c06f35f +903, 0x518fbb95071d8d7d +904, 0xcdbbe8d47f9b13e9 +905, 0xe8152b0f387251cd +906, 0x411070a4f345676 +907, 0xc589c285b962389 +908, 0x8b0eb9e285844319 +909, 0xe2b007f446a21b38 +910, 0x868ffafb958a6c40 +911, 0x19ccccd559408de0 +912, 0xa7666f366db0ae71 +913, 0xd78c5f137da6dbc2 +914, 0xeeecc913fdb9af03 +915, 0x7a5afb2f3d54a396 +916, 0x64fadf73d7ba200b +917, 0xaa1b82c6b4b346aa +918, 0x9a312d9482244a60 +919, 0xadb3c0a30f68d0f4 +920, 0x21eee75a717008c1 +921, 0xcda2779023f54837 +922, 0xea3c577c6d7783e2 +923, 0xdaae89efcd431a13 +924, 0x9a6102d2dafaded8 +925, 0xd29443448e01734e +926, 0x6b968e58c3d5bcd0 +927, 0x13949d0c5c0f9d19 +928, 0x7053eef909932489 +929, 0x49fb97e33c279171 +930, 0xc955e4854e254d03 +931, 0x3300cb752a7834fd +932, 0x8319585b09da0928 +933, 0xd35c64e4ce23a294 +934, 0x9a41d980ba1774dd +935, 0xff570729be1f3f02 +936, 0x3f68ae1c3e690a41 +937, 0x6f58a3e861159e42 +938, 0x111d9975e94f0004 +939, 0x276d3ea0ff1ca6c +940, 0x4209cb1f5ca1c594 +941, 0x71699dc4c58f1bcf +942, 0xe0288bffc5a27a2e +943, 0x6c0962c36163c4f5 +944, 0x3a8ad088b4fd204f +945, 0xb945dc7721092d36 +946, 0x315f4c1738bdf365 +947, 0xe07ddd7121cafb70 +948, 0x626fadaee66f331e +949, 0x6fe3f71dd5e7ebe1 +950, 0xe3cfb6b53bd8713c +951, 0x30f5b732f7070968 +952, 0xce2f941f93b957f2 +953, 0x116897bad7f55bca +954, 0xb9d2c4a98826c3ff +955, 0x9672c28485d1c95c +956, 0xd0656535c3df1e44 +957, 0x15294f18a999528d +958, 0x82a98977ad1e933a +959, 0xddd17b6eeced5f84 +960, 0x9901a04270fa2d5c +961, 0xcd2a8d3ab69a0c62 +962, 0x706bf86127a4597b +963, 0xe614aa96ed708afb +964, 0x7f6361ae8f59987 +965, 0x6a355657b59c4874 +966, 0x5211dca87f30cdd +967, 0xa21cbbc602f58ee4 +968, 0x68dff176c9b02a7b +969, 0x68f89bb7bca83c5a +970, 0x229cb884febc7e56 +971, 0xce4f300cf6b70884 +972, 0x6ad3f343c76c5e0c +973, 0xb059a099f121222e +974, 0x9e990641d81a63b8 +975, 0x5564e79afe160ecb +976, 0x2a9fa9c590511dcb +977, 0xca36751ba40931da +978, 0x23a332a9fe1104aa +979, 0xdfe116c321547662 +980, 0xf484bfbe18f2c1cf +981, 0xf8f2b4adf2d1ad4 +982, 0x4308800511929ba +983, 0xe2773c41e0082a51 +984, 0x6b74adc21bac6b3a +985, 0x1faa6a3704bd1b66 +986, 0x89e3e641298e87cd +987, 0xcb2f118548abcdc3 +988, 0x690e34dfb4153ab9 +989, 0x103d668edb5f7e88 +990, 0xb29d9f22b3b1d4a4 +991, 0xc4ce3be9022b314d +992, 0x1cb3d5af1306da15 +993, 0x8236da372d964cce +994, 0x79188ac299f06c2b +995, 0x953dfd978aad2545 +996, 0x6058e1066e7285cd +997, 0xf47307b50589e391 +998, 0x2923873ecd9c4d32 +999, 0x4c44d61328ac5e4a diff --git a/_randomgen/core_prng/tests/data/pcg64-testset-2.csv b/_randomgen/core_prng/tests/data/pcg64-testset-2.csv new file mode 100644 index 000000000000..779761d0f8a7 --- /dev/null +++ b/_randomgen/core_prng/tests/data/pcg64-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0xd4feb4e5a4bcfe09 +1, 0xe85a7fe071b026e6 +2, 0x3a5b9037fe928c11 +3, 0x7b044380d100f216 +4, 0x1c7850a6b6d83e6a +5, 0x240b82fcc04f0926 +6, 0x7e43df85bf9fba26 +7, 0x43adf3380b1fe129 +8, 0x3f0fb307287219c +9, 0x781f4b84f42a2df +10, 0x36dac886f4232c6f +11, 0xa32006a96a8d46b +12, 0xa56e609a788ce098 +13, 0x75711678fa371144 +14, 0xbcdd4619fa063896 +15, 0x5cb5c9a1594f1a04 +16, 0x799e6cc7d09bf3fd +17, 0xda1a4b52f72a8c6f +18, 0x374b6f698c864e48 +19, 0x96a3e4d45b8d252d +20, 0x5fc89e7cbf7735e4 +21, 0xe0cfe37beef7efe6 +22, 0xc3467c95f4649808 +23, 0x95cbda6a3275f18a +24, 0x3a4dc1e59bdb4172 +25, 0x47f8755023ac78b5 +26, 0xef8e166bf07dfa95 +27, 0x40065cf0fa99882d +28, 0xbaa083ad70102eb6 +29, 0x7c88e9d1a72a8dc +30, 0x1484e44aa83e901e +31, 0xf0f8df78086fdeba +32, 0x5114e38e0cff505d +33, 0x7e04bb9a2828c944 +34, 0xb88c0de9e2af5658 +35, 0xecba992ca7e9178d +36, 0x8b40b65347cfeffb +37, 0xfce9281a9381a55f +38, 0xfde34f9f228fc03f +39, 0x8c46656aa79eba9d +40, 0x1ed0d3f416073189 +41, 0xd7adcc20a26d48d1 +42, 0x2429dcfa355eddba +43, 0xec100f2285aaad68 +44, 0x91a83984506e1ef4 +45, 0x4c10c0f973e3cba5 +46, 0x45d0d0ad9ab6890e +47, 0xa52b22d88ddb6090 +48, 0x63f7e7549bf80c43 +49, 0xfb03f87e5ea7137d +50, 0x822f96594246a4aa +51, 0x42242b1335cd3424 +52, 0xf78652fc51ec76ac +53, 0x24db7314bda69cc5 +54, 0xcce4cf66737c8427 +55, 0xffd70eeca33ed90f +56, 0xc154aff2caddd546 +57, 0x59d47a8ccd59e1bb +58, 0xabf793045ca561f8 +59, 0x3f1486708729b21d +60, 0x76ed98409f3f9abe +61, 0x3f0bb2cd7cedd012 +62, 0x448f78da1713ac85 +63, 0xddbae7151c1578b2 +64, 0xcf94237ec0973cd7 +65, 0x76a0657cedebac81 +66, 0x2b13b564bed7a3b3 +67, 0x47a6fc0f4604c781 +68, 0x22acf016523ae80f +69, 0xf728771b939c13a2 +70, 0xab4aee3986c80ec8 +71, 0x61d8c8c918b3fe52 +72, 0x7a40380c747f9044 +73, 0xfaf974af2e96a882 +74, 0xb8bd56d90c69d42c +75, 0x7cea307dda515497 +76, 0x56d0858a27ded2a3 +77, 0x8717ea17698706b7 +78, 0x6b34d0c0587e8867 +79, 0x387a8142ee80d29a +80, 0xbba414cee59e3194 +81, 0x6d2fe8bec0e51a8 +82, 0x11d5dc961ba15ec5 +83, 0x7af1ae07932b2fb8 +84, 0xb13ea6b28d63b57e +85, 0x7e89a6f060cf59c5 +86, 0xad1f662c4daa4764 +87, 0x929a054dec3e229f +88, 0xf7f41c2a34920f09 +89, 0xf0eac1b75822b72b +90, 0x24f311773d90d399 +91, 0x9c2147da3d098c17 +92, 0xa62963f5bb0f8b9e +93, 0x97f650195285e480 +94, 0x602433fd24fe4125 +95, 0x6f17d6e3b5fd704c +96, 0x3ad6f2cf0ffd6a04 +97, 0x73a6d93edf693e03 +98, 0x467d4e6fecdfdb20 +99, 0x6aadbba2b2f8a2f8 +100, 0xc865bae9d8713526 +101, 0xa94d7c6b462e5acc +102, 0xdcbb47fdacd4d865 +103, 0x80aa6a71fd60cb40 +104, 0xf27ad62910288223 +105, 0x88f93784d309825c +106, 0xf7f9a500b821c886 +107, 0x6cd6e37a5dca4830 +108, 0x57694853b9c75561 +109, 0x9c7ef1aa6b8f2c1 +110, 0x12046439309d6e40 +111, 0xee3d652c43bd35b9 +112, 0x3838110676b26d7a +113, 0x9efd697137fa24c9 +114, 0x1eeaa149a7edd5be +115, 0x17eb32cd212e374a +116, 0x73dd5b7d7fd3b280 +117, 0x788e514de9649f29 +118, 0x6e2fb96fbf87fe8b +119, 0xc736a34c7ea74137 +120, 0xa4d48bb7df0e3c51 +121, 0x25b66ee78063d37f +122, 0x9058e087b9696e7 +123, 0xa2e6397ebdd3d935 +124, 0x394a16ba856e6899 +125, 0xe4aad4f1bc61d046 +126, 0x5e4904686af5c43 +127, 0x4e58956c61a1880a +128, 0x7328c827d6236eff +129, 0x29463809b511cf73 +130, 0xceb2c403cef62247 +131, 0x9ccc00f358aa8346 +132, 0x6fdc1c42421ba33 +133, 0x1111d660460f5300 +134, 0x97a4f922e55a9226 +135, 0xbc2a217152bfbc63 +136, 0x3617700c68d104d9 +137, 0x8eecc63c4a929622 +138, 0xc69cf9d8f8b45df3 +139, 0xa2a8ca8262f8921b +140, 0x4339edf9e292f9e0 +141, 0xfe385e2e7f6e1a1a +142, 0x5f30d1b803abc1d9 +143, 0xf123207050238c3c +144, 0x79e3401200b54b1a +145, 0x858d7ce163d4de92 +146, 0x5803a44cd013b965 +147, 0x17c65b0b01800940 +148, 0xc50b38bb58dcb3c7 +149, 0xe476e9925898603 +150, 0x3972fb0fa748a3a5 +151, 0x93da971efb1036f7 +152, 0x658bab8ef6082bf2 +153, 0xf664abd0de92444f +154, 0xa2145e8039e61d87 +155, 0x28af5560cb0ee0ac +156, 0xc1e43e6a30cefef6 +157, 0x74f61d623cc6965e +158, 0x3ee0139a07b6c130 +159, 0x214992e8a6134c54 +160, 0xaa83b771c9421231 +161, 0x15487762c93cf5c6 +162, 0xa3d37b883fffdfe8 +163, 0xe398d2bd15c1c511 +164, 0x3154f894aedd5938 +165, 0xc7ed5190721ec2b5 +166, 0xca02cf8dcfef83b4 +167, 0xa22c6a2e5460e0f3 +168, 0x2d72e4d264875109 +169, 0xf282e30c8b945616 +170, 0xa1a286624feece2e +171, 0x6f773be8548d3fe +172, 0x8c6dc6f48c83c30f +173, 0x13dc5926122501a1 +174, 0x5537f3d25d126e0d +175, 0xdb654b8409365aa5 +176, 0x55d8f727e066e818 +177, 0x534841122140f9a3 +178, 0x4e4ecc7b2ce8efa0 +179, 0x3655d535028e4044 +180, 0x6c2ad71379f15365 +181, 0xd1f1238395ce193c +182, 0x4ecd9ccc56595a72 +183, 0x3304220c15b60f7a +184, 0x3726fecf394006bf +185, 0x4523e03e39a92ac1 +186, 0x191c97036c0e20a8 +187, 0xbfbcf849ecc37cd5 +188, 0x3c6090d256b1c780 +189, 0xf7e94dd0d3e02fd8 +190, 0x83034fb1c17bb99f +191, 0xa7be8e0eb37c9260 +192, 0x177d2c560b0b55af +193, 0x55da4c839514e82e +194, 0xc9b393b79b0e7617 +195, 0xe9658403d3a140 +196, 0xc86401b988be38e7 +197, 0xe82baf54ee5df9e1 +198, 0x3a562e6572a853a4 +199, 0xcb83facbed1cb364 +200, 0x4db406f08ea62242 +201, 0x9cc816f5376ab97a +202, 0xe65a32f96a78b09 +203, 0x59e7b42c496e2c2f +204, 0x7e3e59a4546b6b33 +205, 0xc51a371516d5adc4 +206, 0x19ba384285a523ca +207, 0x5b998f71002a0912 +208, 0x81ee2f95f53dbce1 +209, 0x966a0c0bbf15492e +210, 0x80f88202ff2d29c2 +211, 0xf827f45274e32733 +212, 0x66a2611b73547490 +213, 0x1b2c3c3ae80997d0 +214, 0x264a86e09c63e4c9 +215, 0x35d4bf9c9d0d89a2 +216, 0x6051e319babb305f +217, 0xdf0d08608262be49 +218, 0xbe7aa9a7697278c2 +219, 0xac531985f79fca17 +220, 0x7ce7de0d95ba34d +221, 0x9a03956d30de1ee0 +222, 0x8106a5873e7950b0 +223, 0x804c06b1fab989fc +224, 0x20d5fe19357e95dd +225, 0xf3e89c08d1841c79 +226, 0xfc93b079bdb323cb +227, 0x8f6eb1dea40eda88 +228, 0x6e7f6b657f6d971e +229, 0xf2b15bb03a49e9bf +230, 0xcf7fed1aff1786b +231, 0xe53366adc5bafe42 +232, 0x89b853ed67fc2387 +233, 0xd13dadf3828f1df7 +234, 0x2f884ffbb83075b9 +235, 0x8efd2baea4771d71 +236, 0x7872e80c946c6bce +237, 0xcc487bc4ea869070 +238, 0x820609347e4fdd75 +239, 0xe939e3c63701a997 +240, 0xf70ed361e42164e9 +241, 0xa9f29046fce9ba8d +242, 0x61edfa750175e868 +243, 0xb7d2424653bde389 +244, 0xdadd225205e74ef4 +245, 0xecfb9a633ee3c774 +246, 0xcbc69459f0634f30 +247, 0xdbcd82538e0785e2 +248, 0x2b272f59ad36e01c +249, 0x601a38897a57cc68 +250, 0xfa012b9e5722d8be +251, 0x5bce8d48277d7338 +252, 0xd1b6ca2b93483dc2 +253, 0x8b94eceb88f55be9 +254, 0x93403aea5df5da18 +255, 0x57b6fcaf351c16b8 +256, 0x70f5e54095404bd8 +257, 0x9124d47160362770 +258, 0x987ed72af8aa305d +259, 0x71e3a8d5156f82c7 +260, 0xf788e966e86f7004 +261, 0xcf0cd5911c4bb0e1 +262, 0x3340b119d3e2f28f +263, 0x9952106be6e3bf95 +264, 0x99a6213e19fe9d1a +265, 0x4f0d3811a8a5d481 +266, 0x62d732ee5f975dd2 +267, 0x3abc8340ab323ebd +268, 0x15da761a2518c843 +269, 0xb453de7d4d15b261 +270, 0x4adc2d7cc2cc0049 +271, 0xcc9b7fa135c7dba4 +272, 0xa14857a738db2b52 +273, 0xce036b49e28c19c7 +274, 0xaee7e9fde421bd4c +275, 0x15dd298915099a9e +276, 0xa3fa6550b639b66b +277, 0x5f27c59b035a6532 +278, 0x2eef2e6292288715 +279, 0xabd211c514e3699e +280, 0x6d7bf9b33f8b09e5 +281, 0x91ff83561361c170 +282, 0x8f8e309797a91e4f +283, 0x2b11ef1cedf1036b +284, 0x6fc36ed305d27972 +285, 0x7e294e03a91eb01f +286, 0xbe16009d8b2f38a4 +287, 0x2bf69c7b54e60cea +288, 0x860079a07fade829 +289, 0x8f0ce6ae4c90d38a +290, 0xab10e5f8ab4835fc +291, 0x49ed43ddd4ca0a76 +292, 0x201eaa53b6df058c +293, 0x2d9a4fdb16f6c1c +294, 0xd3406193e1dd0760 +295, 0xad38857b542ddb6a +296, 0x52ec1e450363aad8 +297, 0x6e65469594331886 +298, 0x4b027ce344dd6660 +299, 0xbc801654b4a1ccad +300, 0x155be4bc51328b2c +301, 0xa9a1965f9b2b5bdb +302, 0x386b8dc34de0889 +303, 0xd60ee4b1b9cbb057 +304, 0x6c1e60b6914c4876 +305, 0xd07bf84dc30bf653 +306, 0x362d5b19b3f4f7e9 +307, 0xd145b8fef9a6a3d2 +308, 0x5c401126b505dd09 +309, 0x8f5d1d4446f9cb4c +310, 0x725618359f1a3e38 +311, 0xaedad9cf455de2e5 +312, 0x7f7e4e549b4bde1b +313, 0x35002b8e995f815 +314, 0x9aecaf8f393cade0 +315, 0xf346a49595886d86 +316, 0x459d5a9e92e9c149 +317, 0x60885682c3d6ff0d +318, 0x90f5e985e08bfc3d +319, 0xbf413a432e1a1b81 +320, 0x789503524aa48aa9 +321, 0x7880e5bb484bd49e +322, 0x7426535c324b7176 +323, 0x190ad37f84acba3 +324, 0xbd52510631d4f5d7 +325, 0x98f794ad565c986d +326, 0xa0ea374e66c0bf56 +327, 0xd683fe7102145335 +328, 0x9b3dac61db2f2930 +329, 0x470d31e3096c2450 +330, 0x1f445f8292f6f3dd +331, 0x1687ff432def56a7 +332, 0x887d4e6617525278 +333, 0xcd81ce8cc70b13ff +334, 0xaadbc4c3525c18e1 +335, 0x96d81490c362b621 +336, 0x128b95092e36796c +337, 0xffeffbed0980cdb7 +338, 0x3bcef6c52b36d07a +339, 0x400879c888eeabe2 +340, 0x373c9978059787d +341, 0x35979fef9e20050a +342, 0xf4581367f3fc43b +343, 0xcec7b91352ed0186 +344, 0xa7b06e92b765203 +345, 0x6713f0b11fb9f296 +346, 0x95c53b86deafbd95 +347, 0x3694844a5eca42df +348, 0xd0f334ea2c650574 +349, 0x5ae6771044110ddf +350, 0x9f61d9087e7d36e5 +351, 0x28f04e48625e3e5e +352, 0x6164d6b5445cf130 +353, 0xa36b5c2de27084be +354, 0xa099a43d5c5f21bb +355, 0x706edfb05fbe8b9e +356, 0x7aacffffc81ebc3b +357, 0x6f49121baebd0e6a +358, 0x41fda7ba6df8f4cb +359, 0x1bea4b596dbac5ac +360, 0x71dd0261d65b02c6 +361, 0xad7f50624c15e9c9 +362, 0xf7c4eeb84d4866b6 +363, 0xa5e23dd382f48bdb +364, 0xe6ffdf875d534bfa +365, 0x40104d8444f75a7c +366, 0x8218a42f24a88364 +367, 0x9d3f9382759cae86 +368, 0x101d7adffbd9ebde +369, 0xf9fe3578d6b739dd +370, 0xd23c47039e882eb2 +371, 0x37fc4fff590191b3 +372, 0x2a672fc8cd3e0cf7 +373, 0x995b8faabb4332c7 +374, 0xabc6117aa665a743 +375, 0x3fc49d11869352ea +376, 0x4ccc3cfa9540797f +377, 0x111c57f059fa3ef4 +378, 0x44a737bac79496bd +379, 0x37924823edfe0774 +380, 0xa4d8ee07ab241d02 +381, 0xbb0bf46c50f349ac +382, 0x4db0a8506e22199c +383, 0x93239f377c85ba51 +384, 0x56f51e3970e409f5 +385, 0xe82d51ebc177609e +386, 0xec866d8b473eaeb +387, 0x42f8018bb955abed +388, 0xf58ba8a916b04fa1 +389, 0xf12d2f0cb0a41cff +390, 0x8102b5f91923cc2a +391, 0x91d95fcb9cb1346d +392, 0x819ccf0d122537ac +393, 0x34646b1c3f9a8527 +394, 0x4a3a7df812ff79cb +395, 0xc3d0b50ed434ad24 +396, 0x3e6cd372b453b5f0 +397, 0x39101f6226c43c8c +398, 0xff41e5b6b7ff540c +399, 0x1e8d77bc3f12e0f4 +400, 0x748d0860be568eee +401, 0x5baac1f743bfeff3 +402, 0x8bdbd895b2eed2d8 +403, 0x5d3a01fa82bd88d4 +404, 0x577271d2de3e06f4 +405, 0xd4fccaeb0db61acb +406, 0xa088377ed2b1d841 +407, 0x6f2e9e1566f37b5b +408, 0xb8d85eef688c049a +409, 0x6b7c06c55078761 +410, 0x223cd94cad1e0c32 +411, 0xbf27c193ae5881e3 +412, 0x5b784893a36d57dc +413, 0xdc9fa53968c262dd +414, 0xd7e820c76855fb61 +415, 0x72260eb94f096e2a +416, 0x49144b5732ca1b94 +417, 0xba8d85a47582d428 +418, 0x558abe242dc84de2 +419, 0xc27b1d54557b9de5 +420, 0x80c1f06559385330 +421, 0x4a5c1d4252675c73 +422, 0x225e3a9f7b2da067 +423, 0x9ac95bac9d2234a1 +424, 0x696e500589e0e490 +425, 0xd0fe548d81c82185 +426, 0x68d8b783037b4743 +427, 0xbe1664f1a8d814f +428, 0x2304308b691ca712 +429, 0x68e680af6b7189c5 +430, 0x13abe6c989949072 +431, 0x4c209f5029a59d0b +432, 0x63361139df6fea7a +433, 0xf07c52d8272cbdb +434, 0x665023146f27fa7 +435, 0x7cb535c55ad7ad0e +436, 0x76e366c7317eb1b0 +437, 0xa7d9b80b51585e9b +438, 0x85f0bd60122198b9 +439, 0x34bc89d7e7827fd5 +440, 0xdfa1167988c85807 +441, 0xe78f45588bfdba02 +442, 0x172a023eba7357b2 +443, 0x7bc4c79e06ea755b +444, 0x8aace6120b766b95 +445, 0x17b43a5a81b0db26 +446, 0xbc2b95819d959ff6 +447, 0x1b8841f2fe9c4622 +448, 0xc094a747ec30d67a +449, 0xf5b93ec01484b937 +450, 0x659bbe8bdfd43f01 +451, 0x9d96c22bcf9c64c9 +452, 0xcf7df324fba052ec +453, 0x5e4acd4f9e048e0b +454, 0xe3a0e7e9869c5dd2 +455, 0x4eb444727e1c346e +456, 0x7f6cda1ca7b3eb67 +457, 0x72fccac63ca649e9 +458, 0x711bfbf79a093651 +459, 0x5d48599fae7fd6a3 +460, 0xcc640119a296b34e +461, 0x39acfb198b2b439 +462, 0xde759b50e2db66f9 +463, 0xe83bf8363827e06 +464, 0x484d50365017de87 +465, 0x4c3b5dbacd68394b +466, 0xbbe47788c079218c +467, 0xd44099290c25fe62 +468, 0x3b7d1bd6f91f3857 +469, 0xe7366a677d2b7eb3 +470, 0xfaa770590b197910 +471, 0x610b7a2fe8c4e80e +472, 0x13451e1bf520a796 +473, 0x7e3d18c47e821077 +474, 0x8fd3a77c86eb9804 +475, 0xf24be740c87eadab +476, 0xd5a52e6d0b58345 +477, 0xae386b5ca037a8d +478, 0xb59fd16baf160f26 +479, 0xd4a05b473f6e0a8a +480, 0x47ede6678c2c6420 +481, 0x8851ed397da6f850 +482, 0x1de775cdb392d89b +483, 0x74e6c8ec9513ea38 +484, 0x30ae39e04187a984 +485, 0x614cfd09d043d601 +486, 0x3e0173138f562ee1 +487, 0x822d415a26bdba96 +488, 0x432f6dec77edd9a8 +489, 0x47a3a179627546b8 +490, 0x845dd7ffb1fe6d78 +491, 0x9778d5782de13a48 +492, 0x760198319b3cacce +493, 0x420ee262d07dd7c +494, 0x847c7424c365df20 +495, 0x56b3b590fb83ba16 +496, 0x7cd2410390a3e797 +497, 0xbb0c21b47aab8857 +498, 0x2743883e70a36a18 +499, 0xff8b29cdc75ebb7 +500, 0xe1e04a0f0379686f +501, 0xcfdf3083b792f281 +502, 0x27392ca026b55e88 +503, 0xeeb195994fd56abb +504, 0x7cf210041345882c +505, 0x3ddca2b8951fea4e +506, 0x21c89d88a3833996 +507, 0xe7128bccc4b25c9b +508, 0xe39b0fb96a4c05ae +509, 0xedf5326550594554 +510, 0x4aa45fe66b575558 +511, 0x2799fc8d3b06f777 +512, 0x2824863087187501 +513, 0xa15fa00818118906 +514, 0x559fc9e9344a310 +515, 0x1682745f8d571671 +516, 0x80b54f29f47a28d0 +517, 0x38e28103ffd9f771 +518, 0xedb5f440dab80945 +519, 0xdb0b8d04cece6091 +520, 0x1f60a7cae5ae8412 +521, 0x6719c0405e92b31d +522, 0x56752def7d642302 +523, 0xa5b0900f93c352dd +524, 0x5b82baf53be8983d +525, 0x7726202ccee5cbb6 +526, 0x1641c84c7f87a765 +527, 0x835ae1a82be4265e +528, 0x5f9ccee69c1d9da +529, 0x3e2a2228e21039b7 +530, 0xa45873582866d005 +531, 0x7fbeffc99401e59e +532, 0xcf66a6a974057890 +533, 0xd53704a96af96fd +534, 0x1a8b5e3460704b64 +535, 0x6939b27bb32ba451 +536, 0x3c39293e637a0115 +537, 0x335a6e6b779b8c4e +538, 0x75235d767dfd3d00 +539, 0xbdf0b36936b17c90 +540, 0x982dc5e4915a3a3a +541, 0x74657ac256407f55 +542, 0x603a724457b796b6 +543, 0xf178694f7a3f98bd +544, 0xe712de12db2aba47 +545, 0x1ca272d99a3355d8 +546, 0x93e7054d3e8dafc7 +547, 0xa29597810eff04c1 +548, 0xade242c0ae4bcea3 +549, 0xbcd226e2bd9d0e64 +550, 0x2e02e5736f889a +551, 0x3622dc09f5fdd576 +552, 0x6e66bd2a10d78705 +553, 0x71d8f19110d5b4d0 +554, 0xacae934ab3d759f0 +555, 0x68d670d5f9272132 +556, 0x571fb09d082e7da7 +557, 0x154540c51b7d8b33 +558, 0x1e2f3710c0b6890 +559, 0xaf26a826ef444b30 +560, 0x9fc9fdbd9342be72 +561, 0x9b33b306d22a35e0 +562, 0xb6d5895f56d4197b +563, 0x92fef06c1353b2e3 +564, 0x804e3eb42e65b938 +565, 0x73d5cd4bb7270902 +566, 0x274b8ac4925da8fd +567, 0xa9a57999f5df2e2f +568, 0xa6000be059e088b +569, 0x57de4fc48c9e9e84 +570, 0x16727392e94ee9bf +571, 0x53c9032f62848c4d +572, 0x8a8ddd8fcf0676dd +573, 0x1436de7c1735087 +574, 0xfa93b7d1425e8667 +575, 0xec34ca5f3f84bb2f +576, 0x489ed44d0880c4c8 +577, 0xb3b6051de7a6f740 +578, 0x2f303cb0f4040f11 +579, 0x302c42a6adbcbcb2 +580, 0x28ed7b87695cd600 +581, 0xee78d3b782a2fcd0 +582, 0xc47a2441a1082032 +583, 0xec9965704a044f33 +584, 0xcb1563e968460dc +585, 0xfecbb4fa2b544f93 +586, 0x3f3d7437a6d29a3d +587, 0xe4bfaccd729414ca +588, 0xb741ed954572d172 +589, 0xf34b49bf10ae47b6 +590, 0x1fbd1f068f1b796d +591, 0xc1d556e64345b226 +592, 0x85bbfa50a899c7be +593, 0x5310045dcf0fea8 +594, 0xbc6f6fb7f00e5960 +595, 0xf8bdf4074f2b5f5e +596, 0x2a5817aa122dc97f +597, 0x6d5ef86d6b8ad0ce +598, 0x96e7ccc235abb79e +599, 0x8d531c4cea492f66 +600, 0xfc124a123b4ce02a +601, 0xc6087ffd9130c2ca +602, 0x3a724c46f0f06175 +603, 0x59980713cfe4fe92 +604, 0xecde418e64a11bd +605, 0x5c9b333a0f0337cc +606, 0xcf014d508fc8e83a +607, 0x83998bb2aa4e16ba +608, 0xde8f5167ac0a40d9 +609, 0xe93b1846914c0dc7 +610, 0x668831ca8fd50c25 +611, 0xec764b87e402c28e +612, 0xd0e1303e56f6b268 +613, 0xa6b9f3c4872dbcd5 +614, 0x12a89c116ad924f0 +615, 0x23857c375ae928c8 +616, 0x29b117f63f2e8c1b +617, 0x64ff6cce272aa46d +618, 0xd40fb15b38d59f70 +619, 0x6e5a6257c4cc0c66 +620, 0x7b54845e6e119a4e +621, 0x9d88bf3dd9fa0f0e +622, 0xb6687fd4980a5d43 +623, 0x4f2e3fef88b640b8 +624, 0xf07ac2f7e2df40fa +625, 0x24059bd0ecb6c6a9 +626, 0x6204a47cbd57453d +627, 0x8477fd1a13ea9678 +628, 0x4555083f5eada49f +629, 0x352443e5d984691c +630, 0x3e904f796a9c5ffa +631, 0x11e182bc43754609 +632, 0x608cdbe03699a5d4 +633, 0x2619146efbf59f0 +634, 0x9b852370063940ee +635, 0xa1d8e7e91e42a52b +636, 0x19179affce38fa3c +637, 0xf68ff1ccce70380c +638, 0x12103cb41741ab38 +639, 0xdca7902fa6d960b2 +640, 0xad46a2fc70025445 +641, 0xac92f0b2d150d716 +642, 0x5de115babb43326e +643, 0xf335366fd69e4bcd +644, 0xe9aecd1f88889cd +645, 0xbce60087987b51d1 +646, 0xcfd395a167103939 +647, 0x2fdcb12826ac806c +648, 0xbd5129970869ccd6 +649, 0x5e922b68030c2698 +650, 0x7ada02a56d17779a +651, 0x7a1254c652b99ccc +652, 0x8be78733623db772 +653, 0xc22439789b68f0a8 +654, 0xee51ad4ab1a9a6ed +655, 0x44b15fa27694d9be +656, 0xc5b93e6c57805153 +657, 0xcf03df495c283a89 +658, 0x5c2a41954bb44bb +659, 0x9e651cb8c650dd +660, 0x73a20ee82570d4a8 +661, 0x5f805cab085e971f +662, 0x5354410872a8f587 +663, 0x1b50ef4e9519338d +664, 0xdeb873412301a1ce +665, 0x3a286bb2f5f8db39 +666, 0xad117a0d4dc7f82e +667, 0xdd880d581169d989 +668, 0x8356be106382a704 +669, 0x7c684ad93e996ff3 +670, 0x6b2d09e61ac02c11 +671, 0x99ad8c074fe046dc +672, 0x4a9b4f0e7c4ffa24 +673, 0x38afdcb5893b466 +674, 0x7ad58ef97c3d35c +675, 0xdd7c17c0d67ab69 +676, 0x61c77caf27938c86 +677, 0x978fc491080c0cee +678, 0x4c1750f8684c1ca4 +679, 0x86b4c683d5fe657e +680, 0x720e2bd8ec76cffc +681, 0x73ca52b4a7dd3b85 +682, 0xeb10a691e12ea3ca +683, 0x90355e369297b259 +684, 0x6c6bc16f639678ca +685, 0xd989f4c724f8fba7 +686, 0xbb1ba7e2ca1c4391 +687, 0x81e4194500a0d267 +688, 0xbb25489c1dcbf93f +689, 0x74d26b75e9f57fd +690, 0x59c085fa99b6493d +691, 0x3359805b0fc3fef9 +692, 0x60ef0f3a85e60650 +693, 0xf1a3692c8591e8d6 +694, 0xd7c8d2e7f3d3546e +695, 0xe8fc8518c11ca881 +696, 0x3380ef12114d1818 +697, 0x87203c98ff21fcaf +698, 0xbc37f8e034002ef8 +699, 0x891b7c3f55d02300 +700, 0x814eec8ff8956f0a +701, 0xa370639852acceae +702, 0x6c566310b6b00f15 +703, 0xd69fe78b9c8a05a6 +704, 0xb7b0df518738419e +705, 0x2a0c1185b29ed965 +706, 0x636c841214c0a8cf +707, 0xbf56297859e9bb72 +708, 0x2b5b9d432d6d008f +709, 0x1ea586cf0f86f542 +710, 0x23a2a1af76cbc988 +711, 0x6c72c799b6ed93f3 +712, 0x2266785315f3bb13 +713, 0xb68cd6e87b94065a +714, 0x5d395704514bb808 +715, 0x334bde59d526ee4 +716, 0xc5a6d87f96f055fa +717, 0xd47001378b4dcf08 +718, 0x7305818a39057557 +719, 0x8f72c128eac6d32 +720, 0x4957ed799339bbdc +721, 0xeb47d505f61dd5fa +722, 0x8ce8817cd6acc93a +723, 0x84ef66e511a52f35 +724, 0xbf5aa34bbaef7e1f +725, 0xadaa5ba2a5ee660e +726, 0x6eec8ac924058eea +727, 0x8af63be4d1a1b202 +728, 0x88eccf85fd9fce32 +729, 0xf19a1122f394af05 +730, 0x8dcd15d1c14f5077 +731, 0x6c0f2e6135e36545 +732, 0xe58f89bec4d929c8 +733, 0x4eea88221d983ef9 +734, 0x51ae3956d53e1a80 +735, 0x40d8a172bf713bb6 +736, 0x3e33536e43ad4fa2 +737, 0xeff9938a179138fa +738, 0x3e372bff1f51df8b +739, 0x59b86a407817c86c +740, 0x947164c2c57f9bd8 +741, 0xd8e67bb799d84475 +742, 0x4d9ed254d8189595 +743, 0xa021d8d181328996 +744, 0xc703e402f8e4688b +745, 0xd1eb104c970dd5fe +746, 0xd5bf4683b9337f8e +747, 0x98f405a2d998f06 +748, 0x59c734ddd208e85c +749, 0xbd167be2d43fde24 +750, 0x70602daab163fbe2 +751, 0xeb2f2b37cbfe13e7 +752, 0x28baa8f3fc4c4666 +753, 0xe212ffe352ea5ce6 +754, 0x538b93d2285eda3a +755, 0x3a9482ac69a39e1b +756, 0x3a98983ed4367767 +757, 0x1dc851c69e35d601 +758, 0xac7f83e4b02e9bb8 +759, 0xa939f99c5615ef7b +760, 0x439437f129076339 +761, 0x79a251bb1d50ce25 +762, 0xaa7b6ff8f13a7424 +763, 0x1b244bd86404327b +764, 0xc84d99185ab2a7d6 +765, 0xf6dcde975493c40b +766, 0xdee46f4346cf6af +767, 0x739b75df1fe18712 +768, 0x3d05cb298311f3e9 +769, 0x1fba9d9c10dc7780 +770, 0x31637fc416267053 +771, 0x46694e36246b8be2 +772, 0x8c67095ae6eaf1e4 +773, 0xebe2a68c27963dca +774, 0x532d344b14306cf2 +775, 0x6a847c8f3ae2ac92 +776, 0x8034bcb5a50cbd6a +777, 0x7544766784261059 +778, 0xe641799652df63ca +779, 0xd8cacad7099c07de +780, 0x429e62da116e4876 +781, 0x4442c8b57a5b7ef5 +782, 0xa7ea9c348cbeebaa +783, 0xce1a34f57bb2a7fa +784, 0xbb29ef457c9509cc +785, 0x1ba1030b19a32c1c +786, 0x412d1eb07cee79b8 +787, 0x3627dd37c6b36848 +788, 0x45432b319f26a2a9 +789, 0xb9a12e188cee2a29 +790, 0xeee69e0f1b1efd66 +791, 0xd4ccd61bc3fb8837 +792, 0x1b600476917cbf62 +793, 0x522950ddce26c142 +794, 0x956d8a5dbe9aa431 +795, 0x31cfba73bb524b7d +796, 0xc3b709a56885a6ac +797, 0x7341d4e32fffcdf8 +798, 0x5ed87c5315e4775 +799, 0x60fa512183e3dad5 +800, 0x4df6df14e9c2935f +801, 0xdec2dc983ab42a9 +802, 0x28265e213fd6de41 +803, 0x2f85d825454add06 +804, 0xf18119191ac41aa +805, 0xf870e36e83f4face +806, 0x2a4b213d973d83c8 +807, 0x2c7094cde18ba8ec +808, 0xb5998e0a1914446b +809, 0xefcb960ff010503a +810, 0xa8d928b99104aef5 +811, 0xe7a6893116e383a8 +812, 0x552dbe180a51b6c9 +813, 0x16b73f3832c9990c +814, 0xfefee9504783e187 +815, 0xc12d3aa0c1f8608b +816, 0xd5232106c7adea7e +817, 0xb207e82667fb71ed +818, 0xe93c50ef54a791cf +819, 0x3099900fdf7b1750 +820, 0xaa2a46c352132ad0 +821, 0xf2414daa174335e4 +822, 0x33080f98c42bbad2 +823, 0x9df24fe0b5b13394 +824, 0x840eedf2eec5fdb6 +825, 0x3715e262efbc907d +826, 0xa70a8cccfbe8a11f +827, 0x4a57a6f16ea4c9f3 +828, 0xe03dbe2f1493e9e1 +829, 0xbd92759a7becd4e4 +830, 0x21a3d87c3766887e +831, 0x6414f570caa74ef1 +832, 0x4e27490fc3fc0234 +833, 0xd4c40310c6ab2eba +834, 0xfbe8acd168ffd62d +835, 0x30b19992f1975ac8 +836, 0xaf93d22a8561f631 +837, 0x4574ebab81bed3b1 +838, 0x5390c6026e3940c7 +839, 0x7a5154d076a8b504 +840, 0x9676f2495f742943 +841, 0x8cfdb9e11bdb4502 +842, 0x36af5c8754d9ca17 +843, 0x61477e76367296ee +844, 0xd6f5f40f66acc700 +845, 0xe62c2462e96af1b8 +846, 0x18029746ac09ef3e +847, 0x871bbe15da7e0176 +848, 0x2443e806f54d179 +849, 0x9103af1634f9d0ac +850, 0xe6e5358eaa0efa2b +851, 0xdff4859198244a67 +852, 0x6e48c357be6042b +853, 0x6bb9e8aeb24d656a +854, 0x1b89fbb05f8438cb +855, 0xe0cea835b4db045d +856, 0x4eafe5c195e29d47 +857, 0xd2f0a452be9163f0 +858, 0xa7ae1d0eee928fe6 +859, 0x42c7a26c82a062c4 +860, 0xa8e93bcd89c5704e +861, 0x73784be379f09c34 +862, 0x91f8e599342d013f +863, 0x79c20bc462215ccc +864, 0x6ee77bc91b3753a6 +865, 0xd2c116d1eb2650d0 +866, 0x388f9767cfe30ebe +867, 0xdde5d5966815e7ae +868, 0x459b838c87ca1dec +869, 0xdf96cdb2bc916a60 +870, 0x215c4195b935d5ca +871, 0x56c9f516528598e5 +872, 0x1d8492a9923640f3 +873, 0x97830ac45234686f +874, 0x67f75117a7c952bb +875, 0xf1939dc69391e65d +876, 0xfc44bb1162cb2868 +877, 0x92b33d9df8fc6925 +878, 0x6c4496920de0d558 +879, 0xa4616bb101e924aa +880, 0xa0afc9701ad83cdb +881, 0x62d555323b0494d2 +882, 0xf18b31447a2dfdc3 +883, 0xb2ece318c128d4f3 +884, 0x29efea45a76b9b8f +885, 0xae05362b365d9cd2 +886, 0x5c4d374ce6aefb44 +887, 0xb9cdc65eec94136e +888, 0xf0212f42e3d4f5dc +889, 0xcde7c5085f95d8d8 +890, 0x9cc3799673a644e8 +891, 0xf878d89199bead01 +892, 0xab684fb9666abf61 +893, 0x3070d399b7a07d3d +894, 0x6d8c51673eeeef73 +895, 0x9bf4062ff5471832 +896, 0x92774cd03c511d00 +897, 0xc1aad7c6980df547 +898, 0x3291e3a234d50cc0 +899, 0x75645079bbe9d34a +900, 0x7f28bab9eba28fae +901, 0xa84415684ed6d765 +902, 0x56d9d67653cd172 +903, 0xa7bfed939db93e91 +904, 0x92940e5162d50470 +905, 0xcd6bf601e08f07a9 +906, 0x2ea9104d785e35cb +907, 0xd771ddd541649214 +908, 0x352554afbf9258d +909, 0x9d855486b77c5bc3 +910, 0xdb03cd71e906e1df +911, 0x7c2621690aabc265 +912, 0x1dd4ac7369a04640 +913, 0x57796cbc93d4d854 +914, 0x42a373d152eca785 +915, 0xbe7389edb8b144d3 +916, 0x8b6245bf01d2e4df +917, 0xacd1f9fcca317652 +918, 0x84545ac79a3eb960 +919, 0x2d2f28e6a8459db3 +920, 0x42b3a2e26ddeccdd +921, 0xe858272777abcef6 +922, 0xd9b5be7340dec08d +923, 0xe991af3579ac4fb6 +924, 0x7c30699b349fa6c1 +925, 0xbb842be14f7b5b9a +926, 0x1d31e1ca791a1cf0 +927, 0xf2bd448ebb878bc0 +928, 0x26a6adf6709863cb +929, 0xb11aa978539e3a34 +930, 0xce554a11bbbedd1d +931, 0x553d3c012682a47b +932, 0xb3c90ed36715903 +933, 0xda3c5c706e39e395 +934, 0x4e7f66006d583c2a +935, 0x6424190e9d28ca3a +936, 0x9916685e7384f3bf +937, 0x1285e17347eb806d +938, 0x877f10baf13e6659 +939, 0x222700ed5086438d +940, 0xd2473d08396634b8 +941, 0xb6b68f3bc883a77d +942, 0x168a489b0b7f5f63 +943, 0xee34dcf1f93ad3fa +944, 0xd25ef824f614f65a +945, 0xe30981905354f477 +946, 0x9463ef623c5eb3f8 +947, 0x46657408ea66980d +948, 0xa2e58d51d6e8e7f9 +949, 0xd80d7df3007e9845 +950, 0xd90fa96f4fc0f7aa +951, 0xd2a6059d171bbb33 +952, 0xb8bacb8f11c65c2d +953, 0x401de84b6a8b1ac +954, 0xf8b6eed644c802d9 +955, 0x30c927749fdd8e6 +956, 0x17c2f4f9c4524e16 +957, 0xa9c677daae4acc7e +958, 0x82c78d9c6b10446f +959, 0x5e544188277da629 +960, 0x7c6e1bd3b861dcd7 +961, 0xd4b00871a7f67d0d +962, 0x6b66ee142821e6d5 +963, 0x176d5e39f3b22474 +964, 0x58ea746f62acf933 +965, 0xc61fabd9961c3a51 +966, 0xb27ce0f87b416e3d +967, 0xd3c82b525b000e70 +968, 0x99578704fb3ff4e4 +969, 0x747da52468875493 +970, 0x5c5bfab7a474465b +971, 0xd82276bdb30e3dbd +972, 0x1d758772eebffe2 +973, 0xfed9d1e3ca887a6e +974, 0x23dd5f7b3ff9472b +975, 0xae2e842b51c9c598 +976, 0xe851bc45531123d7 +977, 0x1a18d2777151c29 +978, 0x9e82f3be14b12a48 +979, 0xdf9fdb3abc3e72cf +980, 0xdbea56e918ccb176 +981, 0x47abbd896eb0ca1a +982, 0xe850ee3cef9334dd +983, 0x3d69fe95275e7f2e +984, 0x4fcb936c048d8812 +985, 0xc98f0f6bb9865a99 +986, 0xc951cdb73514709 +987, 0x3ca839c27ca26de9 +988, 0x1478848a311f9cc5 +989, 0x35d2244064967478 +990, 0xe71df2d9732ffdc0 +991, 0xa12417d7b7b9e0ce +992, 0xa1bb6da3f284f77c +993, 0xf551e1c3171575eb +994, 0x16083ac8a062747d +995, 0x866d6c3a630fd4da +996, 0x8a972ff46b3c5c4c +997, 0x70af3b475e4a3d5d +998, 0x2c143fd5c01d9cf5 +999, 0x68089ffadc8ea2b9 diff --git a/_randomgen/core_prng/tests/data/threefry32-testset-1.csv b/_randomgen/core_prng/tests/data/threefry32-testset-1.csv new file mode 100644 index 000000000000..3aec7304df34 --- /dev/null +++ b/_randomgen/core_prng/tests/data/threefry32-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x6cffcc99 +1, 0x2b7c051c +2, 0x4ab0b74a +3, 0xee73ea3c +4, 0x5b43def8 +5, 0x7e166501 +6, 0xead67c35 +7, 0xa8bd9381 +8, 0x67d79512 +9, 0x18a341e4 +10, 0xd6672c17 +11, 0x40a13b1e +12, 0xcd31ce04 +13, 0x12fdb46d +14, 0xf2fd0ffa +15, 0x4e4fc443 +16, 0x61a53917 +17, 0xff60cc00 +18, 0x51671412 +19, 0xf3a08627 +20, 0x5ba59f45 +21, 0x1a9f5793 +22, 0x3e2a31fe +23, 0xa2242742 +24, 0xcafae297 +25, 0x5eb5a116 +26, 0x23ef9e16 +27, 0x54f01377 +28, 0x47114dcb +29, 0x4ce52425 +30, 0xc898c3a8 +31, 0xf34d52b +32, 0xf05e3aea +33, 0x8e122dd +34, 0x57ed51e5 +35, 0xa949f8c1 +36, 0x6b0c6ca2 +37, 0xeaff706a +38, 0x7ff23d83 +39, 0xb29857d5 +40, 0xbc79b2d3 +41, 0x350e2f98 +42, 0x3deae452 +43, 0x75c70896 +44, 0x8743a85c +45, 0x8c05ccda +46, 0xbb547a23 +47, 0x53f341ee +48, 0xfdf5fe22 +49, 0x6bea4979 +50, 0x1dc06326 +51, 0x58f1fc83 +52, 0x1130e7e5 +53, 0xc434fc00 +54, 0x13acc9b6 +55, 0x198a6356 +56, 0xe59278f7 +57, 0x720ce91c +58, 0xa4587617 +59, 0xa68be124 +60, 0xd54392ab +61, 0x19eeb16a +62, 0x5abac829 +63, 0x2303dcdd +64, 0xaffc0c4c +65, 0xd3757435 +66, 0x8fd204f +67, 0x7f48f1d +68, 0x94512051 +69, 0x4d5d385b +70, 0xd4877f13 +71, 0x834af295 +72, 0xf97fca51 +73, 0x31b766b5 +74, 0xa25a5371 +75, 0x21ae0ebb +76, 0xe5e1066a +77, 0x1633cf01 +78, 0xab411bb9 +79, 0xb2982b5c +80, 0x67cc822b +81, 0x2eabd825 +82, 0x21e0dc17 +83, 0xb9170084 +84, 0x53c52c00 +85, 0x3acc5cec +86, 0x985ce088 +87, 0xf6e2d9b1 +88, 0x37cc5a23 +89, 0x34222cf3 +90, 0xc8f6823a +91, 0x581173b2 +92, 0x300416ea +93, 0x2357d4ad +94, 0x1bfceca9 +95, 0x48e6cdc5 +96, 0xcbf8d214 +97, 0x25c47e6a +98, 0x8a99c824 +99, 0x367c07b6 +100, 0x38643cfb +101, 0x7899c225 +102, 0xefd1c7f9 +103, 0xdfd3d507 +104, 0x7a868d74 +105, 0xac8cfcfa +106, 0x901aac22 +107, 0x52d4f1e5 +108, 0xb8d0b9a3 +109, 0x4d1ac438 +110, 0x1b6995e3 +111, 0xf2b49c8c +112, 0xa4ee5aa9 +113, 0x63f48457 +114, 0x1f092683 +115, 0xe1ffa0c1 +116, 0x64c14ec9 +117, 0x7c86caae +118, 0x96810301 +119, 0xfdeb5934 +120, 0x70636d11 +121, 0x857cc412 +122, 0x83244693 +123, 0xa46e5de7 +124, 0x47406f19 +125, 0x34a31ade +126, 0xb5168ae6 +127, 0xca6e0cc1 +128, 0xb7f612e6 +129, 0x296f0512 +130, 0xe7230082 +131, 0xde6f547f +132, 0xf12bd1cc +133, 0xf51dd599 +134, 0x8a5ab59e +135, 0xd8b1cd87 +136, 0xe81304df +137, 0x3c0ddff1 +138, 0xc6d3a649 +139, 0x2d950bdb +140, 0xafecc338 +141, 0x5b20a006 +142, 0x6d813023 +143, 0xcb698f0f +144, 0xdb7ba980 +145, 0x78942bed +146, 0xb12a3df5 +147, 0xde84510e +148, 0xe99351ee +149, 0xbe5ff58e +150, 0xe0fd9ef +151, 0x1e4b9d22 +152, 0x8bca03a1 +153, 0x7c6377a0 +154, 0x37fbd0a3 +155, 0xe8bef1ba +156, 0xb14651cb +157, 0x3e69d08a +158, 0x56cc688a +159, 0xf86ddf5a +160, 0xd5818aff +161, 0xfe1b8f29 +162, 0x2b505d54 +163, 0xd85caf4 +164, 0x7d360464 +165, 0x276c469 +166, 0xb949fc4a +167, 0xc2bef2ac +168, 0xd07c9118 +169, 0xb0ac2494 +170, 0xbda3bc0f +171, 0xc3fe015d +172, 0x741b443 +173, 0xafd4a887 +174, 0xc3ee9b82 +175, 0x12a16e1b +176, 0x7c3a37f9 +177, 0xee996915 +178, 0x52e7f5a0 +179, 0x1f3880de +180, 0x8735c769 +181, 0x7e51e99b +182, 0xf3c35d4c +183, 0x49f56f0 +184, 0x18c5a61f +185, 0x76a3685f +186, 0xabe0061f +187, 0x9393af8b +188, 0x97fc918b +189, 0xf512e881 +190, 0x2ddd9768 +191, 0x1b7c2e28 +192, 0x5f6a6f1f +193, 0x7960eb61 +194, 0x7805d6c2 +195, 0x20165f7a +196, 0x77490b1c +197, 0xb2cdd255 +198, 0xe6d1bcb5 +199, 0x9687e506 +200, 0x55a213f7 +201, 0xedf9c17d +202, 0xdeec02a8 +203, 0x9d182919 +204, 0x61a1d691 +205, 0xedfa20aa +206, 0x843a4793 +207, 0x56d799cd +208, 0x8535f679 +209, 0x37dbf765 +210, 0x92353041 +211, 0x82532156 +212, 0xa118dd43 +213, 0x198bda1e +214, 0x5d8d60f4 +215, 0xcef238f2 +216, 0x8474c6e0 +217, 0x169a9ab1 +218, 0x50cc819 +219, 0x9b3bda9a +220, 0xd813c3ec +221, 0x8dafb7c4 +222, 0xf3d9ace2 +223, 0x8b9cf3da +224, 0xe9d8fd48 +225, 0xaa7f1866 +226, 0xe8186b07 +227, 0xd6ff13a4 +228, 0xc4a41308 +229, 0xefa359f6 +230, 0x4b257335 +231, 0xffda6c5e +232, 0xc3f7362 +233, 0xe3b123cf +234, 0xe774fc0c +235, 0x4d470897 +236, 0x8930aaf5 +237, 0xa801bc +238, 0x638348ec +239, 0x1002026f +240, 0x196fbcaf +241, 0x422838fa +242, 0xf101e6a1 +243, 0x823e3a7e +244, 0x89efe85c +245, 0x710d363d +246, 0xa96fe815 +247, 0x4b6921c6 +248, 0xe744e488 +249, 0xa0b744a2 +250, 0xac95b93e +251, 0xf820586d +252, 0x9b54d2bc +253, 0x78f663a4 +254, 0xdab3fe37 +255, 0x9212053c +256, 0xa23d60ea +257, 0x82c99bd3 +258, 0x90a9a2d3 +259, 0x80fee31c +260, 0xf14ecf6e +261, 0xde7ce14 +262, 0x9d3cd17c +263, 0x4f07180e +264, 0xa1f53dd2 +265, 0xf7b8f170 +266, 0x4947ceb5 +267, 0x9cc97da3 +268, 0x11e679a7 +269, 0x707ac9f2 +270, 0xa02c05c8 +271, 0xefcd3b07 +272, 0xba998379 +273, 0xf4d1d5b +274, 0xec4d44c0 +275, 0xf9775389 +276, 0xbee26a88 +277, 0x604a69da +278, 0x69dd0436 +279, 0x64ace3c4 +280, 0x74a7effd +281, 0x93a88a8 +282, 0x9d86abd9 +283, 0x2d7c8fd7 +284, 0x2e34bfd1 +285, 0xda5d15ec +286, 0x666c44ea +287, 0x1e97fd34 +288, 0x64fffc5e +289, 0x7d909a49 +290, 0xe5b8a071 +291, 0xc71ecf14 +292, 0x32bc254e +293, 0xe6ffc12e +294, 0x76488aaa +295, 0xfaa24b5d +296, 0x2546a15f +297, 0xd61ec5e +298, 0x5b28529f +299, 0xe9d32272 +300, 0x9937f54e +301, 0x83fcf3cb +302, 0xf57e30df +303, 0x6ed40238 +304, 0x455afea +305, 0x39c1421b +306, 0x97056915 +307, 0xa7fb7b80 +308, 0xe12d4aeb +309, 0xd701e899 +310, 0x191d6f8e +311, 0xb276c998 +312, 0xd5640ed +313, 0xc8607d38 +314, 0xd1f75765 +315, 0x4046f224 +316, 0xf9fa0881 +317, 0x9f835301 +318, 0x70282b9a +319, 0x261420a1 +320, 0x1bace8af +321, 0x6506d84e +322, 0x990ad5b7 +323, 0x63ef0eb7 +324, 0x2dafd32d +325, 0xe119e891 +326, 0x1e163f6f +327, 0x2eb990b2 +328, 0xd9768cf8 +329, 0x93424291 +330, 0xd531428e +331, 0x6d130cb +332, 0xdce0f084 +333, 0x8e7932dd +334, 0xe83a0030 +335, 0xbe046ef8 +336, 0x47d195c2 +337, 0xe2987a93 +338, 0x9c17514e +339, 0xa771c561 +340, 0xcd6ebf92 +341, 0x500e7961 +342, 0x14c5473e +343, 0x45a306b7 +344, 0x21255baa +345, 0xb691678f +346, 0x4131c107 +347, 0x3432699c +348, 0xf5ac1ff3 +349, 0x1e1f80b7 +350, 0xab6004e3 +351, 0xbd693e1f +352, 0x2758f73e +353, 0x7b263738 +354, 0xfed2a560 +355, 0xf7f167d6 +356, 0x34103c7b +357, 0xcf976532 +358, 0xb8b12c25 +359, 0x9d5d119f +360, 0xc9e759fe +361, 0x86d83a5e +362, 0x1552d7c0 +363, 0x797787fe +364, 0xcd07ca28 +365, 0xca65456f +366, 0x534771 +367, 0x47690072 +368, 0x5b9dac8b +369, 0x4cca6876 +370, 0x1568b652 +371, 0x6e5013fd +372, 0xfd62e488 +373, 0xd548844a +374, 0xfa88dff +375, 0xa95def7e +376, 0x34c6113e +377, 0x77d17485 +378, 0xe3177854 +379, 0xef3cf974 +380, 0x4f503249 +381, 0x6cac12b8 +382, 0x93b1b00d +383, 0xe12d8b14 +384, 0x8b7761f6 +385, 0xae579607 +386, 0x12698508 +387, 0xb7cc10cb +388, 0xe3dea112 +389, 0xa0c8aaa3 +390, 0xdff5d91a +391, 0x2b9d97fa +392, 0x666986e4 +393, 0x78362d27 +394, 0x19d29dde +395, 0x204c0a1 +396, 0xf47d5694 +397, 0xab6869c5 +398, 0x48b31962 +399, 0x44d25176 +400, 0xaf7fcc00 +401, 0xa36ce44b +402, 0x2407cd84 +403, 0xd026a2a6 +404, 0x90b84a3d +405, 0x9d603df5 +406, 0x4d967930 +407, 0x5502e782 +408, 0x882554ed +409, 0xcfe11605 +410, 0xbeb03084 +411, 0x603ee8b8 +412, 0xbcac4498 +413, 0x2363e45b +414, 0x7c21d019 +415, 0x4e61e47b +416, 0x67bd2c08 +417, 0xba375f5d +418, 0xa696833e +419, 0xcb34c947 +420, 0xf15f7f3d +421, 0x1a4c69f3 +422, 0x7e4a1b40 +423, 0x9dee5fdd +424, 0x5c147767 +425, 0xe7e03c3f +426, 0x794164c3 +427, 0x5f898b58 +428, 0x88040da8 +429, 0x5e1a8b3 +430, 0x5cb9efed +431, 0xfb1101dd +432, 0xaf9efd69 +433, 0x8290ea8a +434, 0x64f8f010 +435, 0x49807233 +436, 0xeb88e614 +437, 0xba226f1d +438, 0x61210a53 +439, 0x531c4f30 +440, 0x74e22c1a +441, 0x9cae65a6 +442, 0x6e8e3937 +443, 0x96a2bd8c +444, 0xafae3c8f +445, 0xbaf80a8e +446, 0x449afe78 +447, 0x40383d30 +448, 0x3e66c60a +449, 0x2a31d63b +450, 0x48b3969a +451, 0x5775f739 +452, 0xe026f067 +453, 0xbc709fbd +454, 0xde443d0 +455, 0xe6894de7 +456, 0xf52c6863 +457, 0x62467a12 +458, 0xe3e04ed5 +459, 0x20465164 +460, 0xaa776694 +461, 0x6eb049cc +462, 0x9e12645d +463, 0xf2d9811c +464, 0x250cfb6d +465, 0xf0c558a5 +466, 0x1ba68ddc +467, 0xeb613fca +468, 0xf7b3ea83 +469, 0x285856db +470, 0xee7eec5 +471, 0xb29a8957 +472, 0xd53ae176 +473, 0xf6bc1b72 +474, 0x84fcd042 +475, 0xd69b4de +476, 0x64f75919 +477, 0x975dbac4 +478, 0x468516c6 +479, 0x5fc2b6a8 +480, 0x843a7733 +481, 0x8617a7d3 +482, 0x1ae51e88 +483, 0x504cfd60 +484, 0x66370c96 +485, 0xabf2b071 +486, 0x8352d0db +487, 0xa08736a7 +488, 0x1e7aeeed +489, 0xe8c0c560 +490, 0x980f18d8 +491, 0x197e42e3 +492, 0x6e54de4c +493, 0x61ff23b0 +494, 0x73a7e155 +495, 0x6ebf82ca +496, 0xea6877b4 +497, 0xbef6f25d +498, 0x6f184109 +499, 0x60ea6b22 +500, 0xd19f311f +501, 0x936a60d0 +502, 0x6dc64c +503, 0xaa004e58 +504, 0x347ffbb3 +505, 0xb778b487 +506, 0x3c59f9e9 +507, 0xbfef5c8f +508, 0x140797f0 +509, 0x83751722 +510, 0x99ea8dac +511, 0x265e85e7 +512, 0x9888771e +513, 0x55df56b1 +514, 0xb7a38fc0 +515, 0x87b0367d +516, 0xb178bf83 +517, 0xc9cecbae +518, 0xd51a44f8 +519, 0x14ed0be5 +520, 0xcc59258d +521, 0x81d6fb8a +522, 0xb8cf3c7b +523, 0x5181ed39 +524, 0xc600f024 +525, 0xd0cc403a +526, 0x8d30f27e +527, 0x2c2a2d50 +528, 0x253ed4f3 +529, 0x9c60942e +530, 0xe6981fc2 +531, 0xa56bc4c7 +532, 0x982b8be0 +533, 0x7f6bd77c +534, 0x7125b484 +535, 0x583b1e69 +536, 0xd37ffc24 +537, 0x576d6403 +538, 0xd74af7ae +539, 0xe16d3263 +540, 0x317e011c +541, 0x3ce41efe +542, 0x83d23f63 +543, 0x9d2cf991 +544, 0xa4e2a0fa +545, 0xbf4eee6e +546, 0x2569d1ed +547, 0xcc5ad808 +548, 0xb220c85f +549, 0x89f80cc6 +550, 0xe548df1c +551, 0x41ac99ea +552, 0x4e87664a +553, 0xb68e1066 +554, 0xcbeeecf +555, 0xfb1e10a0 +556, 0xebedff9d +557, 0x50228e53 +558, 0xee98ed95 +559, 0xc0f85f66 +560, 0x93cd2127 +561, 0xdbde4239 +562, 0x39ecb5ac +563, 0x8eb7231e +564, 0x887c5d5f +565, 0x2c60e46c +566, 0xbc1ee8e9 +567, 0x58879130 +568, 0x5a96d152 +569, 0x5606b37d +570, 0x34c032dc +571, 0x9c14c594 +572, 0x9906cc61 +573, 0x96af599b +574, 0x1157986c +575, 0xae56ee8d +576, 0x5cfb4b8a +577, 0x1f4cc06 +578, 0x736b8866 +579, 0x9746edbf +580, 0xfec1033e +581, 0xc7c4674a +582, 0xac4d187d +583, 0xfe1a82c +584, 0x5a128715 +585, 0x5ad9dd00 +586, 0xab377c1d +587, 0xf03eccd7 +588, 0xab5f33d0 +589, 0xf45a33ad +590, 0x1d9bbedd +591, 0x9eb804f6 +592, 0x35bd73ca +593, 0xe5d1fbd8 +594, 0x49831b90 +595, 0x15db3cba +596, 0x8f0ead01 +597, 0x6411208 +598, 0x23519624 +599, 0x2b8a7684 +600, 0x150a66df +601, 0x1e795760 +602, 0xabf9d64e +603, 0xcccae49c +604, 0x5f3f8b4f +605, 0x603e684c +606, 0x3845d5d8 +607, 0x7391be20 +608, 0xbeaccb8c +609, 0x2d13a52e +610, 0x84f2af52 +611, 0xa2bbde3d +612, 0x4ce5614f +613, 0x7ae9b8da +614, 0xf6106be4 +615, 0xe7e1285 +616, 0xba30e483 +617, 0x83d280ed +618, 0x21f2c5d2 +619, 0x55e9ba2f +620, 0x207e76e2 +621, 0x5ebc56cf +622, 0xd729163f +623, 0xcc23cc38 +624, 0x670da835 +625, 0xbc773681 +626, 0x898775db +627, 0x82a10cd0 +628, 0x427f744 +629, 0xe6cea8b4 +630, 0x204e288e +631, 0x1cbe370e +632, 0x3b5dedc1 +633, 0x6bb98282 +634, 0x1a91857b +635, 0xaa19bacd +636, 0xfc6f1648 +637, 0x635f80 +638, 0x4fd9e77f +639, 0x44fec088 +640, 0x99c56a90 +641, 0xb2ea52cc +642, 0xc470432b +643, 0x530429ac +644, 0xdca36aad +645, 0x49a809ef +646, 0xb482c9 +647, 0x23d6b0ae +648, 0xa04bb8db +649, 0xe152bead +650, 0x712cd313 +651, 0xdd8884 +652, 0x878d5dd8 +653, 0xc07b6349 +654, 0x1756faf7 +655, 0xad018b +656, 0xdc43b58b +657, 0xf85bdb52 +658, 0xc122a040 +659, 0x82fe93e0 +660, 0x1d96963 +661, 0x10c3c58e +662, 0xfb2cbb70 +663, 0x4b791df8 +664, 0x809955ab +665, 0x9c953fbc +666, 0xa5cccc3c +667, 0x64da4f2f +668, 0xac3e0846 +669, 0x80a4e88b +670, 0xc8294a38 +671, 0x9edbd52d +672, 0xf1c197f1 +673, 0xd94a32d8 +674, 0x221a2152 +675, 0x7fd4186 +676, 0x1f571e9b +677, 0x3af1d0c +678, 0x2c43e1b +679, 0x45e08358 +680, 0xe5b95a08 +681, 0x65c7ff38 +682, 0xb7e9408d +683, 0x35be615c +684, 0xd3a51e78 +685, 0xa043073e +686, 0x1dac1ad8 +687, 0xcd20bbf4 +688, 0x3ab08692 +689, 0x3d31363b +690, 0x5617339c +691, 0x2f329775 +692, 0x63ba0912 +693, 0xd09e248c +694, 0x3bc83bb7 +695, 0xc9348e84 +696, 0x488f5f0d +697, 0xb3458148 +698, 0x98e67262 +699, 0xb36e3560 +700, 0x929127c7 +701, 0x91e3d3f1 +702, 0xc6116448 +703, 0xd6422c05 +704, 0xbd483f8b +705, 0x10063cee +706, 0x2807588f +707, 0xa69116b4 +708, 0xd7ca402c +709, 0x246046be +710, 0xeb6d6a28 +711, 0x8f6a3400 +712, 0xd6bf311d +713, 0x6c351a62 +714, 0xedcdcdcf +715, 0x59c4a3bf +716, 0xcd30992 +717, 0x7fc3aa6f +718, 0xe0d1366 +719, 0xa7c21e2c +720, 0xbf08babf +721, 0xfe06a4d5 +722, 0xd6928489 +723, 0xb05a6b77 +724, 0xe24da592 +725, 0x670f8cab +726, 0xf9f7bc1b +727, 0xd947c6a1 +728, 0x5ecb738a +729, 0x7205a778 +730, 0xd3ec7582 +731, 0x3a4193b4 +732, 0xe886eae +733, 0xdfe36b6b +734, 0x3c60bd41 +735, 0x2df8d216 +736, 0xd6cd52dc +737, 0x62349c08 +738, 0xedc081d7 +739, 0x64b8b994 +740, 0x1dce9981 +741, 0x3a79907 +742, 0xb32a0cf0 +743, 0xc03eef19 +744, 0x8bb7c178 +745, 0xcd1b5db +746, 0x7321faf0 +747, 0x19e68294 +748, 0x839c6c14 +749, 0xdd5a50b +750, 0xe2d86a23 +751, 0xa569857a +752, 0xd65ae947 +753, 0x46b31b8d +754, 0x48972e1c +755, 0x78fadb27 +756, 0x628cd86e +757, 0x6deaa2fb +758, 0x27f03380 +759, 0xbe85ea45 +760, 0x3c756834 +761, 0x4c23f1b1 +762, 0x2fe19c7d +763, 0x440f4bce +764, 0x476f20a +765, 0x36ddd49 +766, 0x8045684e +767, 0x86f4929c +768, 0xb59d7fb5 +769, 0xa27493e6 +770, 0x6f138746 +771, 0x65f4c3e7 +772, 0xea8b35ca +773, 0xfedf7607 +774, 0x370a4ea6 +775, 0xa169c840 +776, 0xa5027aee +777, 0x4eb8e8bb +778, 0xeaf37f83 +779, 0xea132a33 +780, 0x69cb7c2f +781, 0xde8bf9d5 +782, 0x5130d59a +783, 0x35b0ea82 +784, 0xaa6caf17 +785, 0x6b32b3ac +786, 0x2e93d09f +787, 0x8caa797e +788, 0x2ac7a457 +789, 0xd14ef094 +790, 0xecd60b04 +791, 0x7ff2f29f +792, 0x2573aeec +793, 0x7dabab04 +794, 0x198ec9c5 +795, 0x4a06b4d1 +796, 0xdbffff88 +797, 0xa2590396 +798, 0x31f42c16 +799, 0xe17aa6a +800, 0x354d8dcf +801, 0xc85f2d16 +802, 0x73784c21 +803, 0x56f1fbd7 +804, 0x1e3bf2a8 +805, 0x6f05ca05 +806, 0xa3710020 +807, 0xc0b0f694 +808, 0x30e9a497 +809, 0x3ff37729 +810, 0xe3f1b68f +811, 0xce718921 +812, 0xa9074ee2 +813, 0xdeb2b4a2 +814, 0x26eb212b +815, 0x5e87a111 +816, 0xc41c4197 +817, 0xbc48ed4e +818, 0x1de24c29 +819, 0x59dc549a +820, 0x6b4399d5 +821, 0xb9860ac5 +822, 0xdf2fc014 +823, 0x260aaa8d +824, 0xdabad253 +825, 0x12e71787 +826, 0x5664c1db +827, 0x6d495c83 +828, 0x79e0b310 +829, 0x368f29e +830, 0x3acdb5bb +831, 0xcbf13e70 +832, 0x6278dc5c +833, 0xd1e6cb57 +834, 0x706e951c +835, 0xa7cfc951 +836, 0x8704efc3 +837, 0xf7800daf +838, 0x5fb19c1b +839, 0x78112b3b +840, 0xdac745fd +841, 0x47df196b +842, 0x4f88a4a2 +843, 0x7e6baeff +844, 0xac2ea7f2 +845, 0x25c3b636 +846, 0xc4d965ee +847, 0x7b69c478 +848, 0xedd5c411 +849, 0x3657cccd +850, 0xbc9445 +851, 0x543d022e +852, 0xd730178b +853, 0x77ab0476 +854, 0xaad88906 +855, 0x30e20b4f +856, 0x6b22eac5 +857, 0x546b82d0 +858, 0xf929bc3a +859, 0xd0b0b99f +860, 0x514df63a +861, 0xfbc7e698 +862, 0xee55f095 +863, 0xda24f02a +864, 0x5ff2707c +865, 0x89827981 +866, 0xb9cc9888 +867, 0x650869c8 +868, 0x4fd63ace +869, 0xd39d2f37 +870, 0xa679e9d8 +871, 0x41704f94 +872, 0xd805ec68 +873, 0xa8c5b428 +874, 0x8da67e50 +875, 0xfd9a0b2d +876, 0x4dad37db +877, 0x5e96adc2 +878, 0xb6def746 +879, 0xc0f62686 +880, 0x48b3cfbc +881, 0xb37fc4b9 +882, 0xa7cf842 +883, 0x6507dc6d +884, 0x6196b146 +885, 0x43c5d8aa +886, 0x60f33402 +887, 0x4414f4ba +888, 0x10e28315 +889, 0xe186ea71 +890, 0xf8b720f6 +891, 0xc91596da +892, 0xcb08553a +893, 0x70089537 +894, 0x8b04e96b +895, 0x3916b464 +896, 0xc6dc1c6 +897, 0x14a76f2f +898, 0xdb04c528 +899, 0xbea612a5 +900, 0xe3676fe5 +901, 0x8a375532 +902, 0x79b1094a +903, 0x82d1bb88 +904, 0xaff5eefd +905, 0x1cb16caf +906, 0x86e420d7 +907, 0x6a84d295 +908, 0xbb861954 +909, 0x8a07d8c4 +910, 0x123ee917 +911, 0x754c2657 +912, 0x740340d9 +913, 0xd59bad68 +914, 0xd64f4821 +915, 0x6f462234 +916, 0x6897df5 +917, 0xc96399fa +918, 0x2d4b464a +919, 0x54b49a +920, 0x3b1ba328 +921, 0x37a28fb3 +922, 0xb870be13 +923, 0xb6f2eca +924, 0x75b05373 +925, 0x7c6ebdde +926, 0x7b6fc55a +927, 0xe386aee +928, 0xbcd168a7 +929, 0x51f8affa +930, 0x284a497b +931, 0xa0b5e79c +932, 0x1f6ae589 +933, 0xb16f5bba +934, 0x98d750d6 +935, 0xe2ecc0fd +936, 0xa73276c4 +937, 0x6a25d164 +938, 0x4f074d9a +939, 0x8daed6a0 +940, 0x505cbbde +941, 0x2abf25b7 +942, 0x6aea0f39 +943, 0x142efd1f +944, 0x8f668dd4 +945, 0xda98e857 +946, 0xb74b0c57 +947, 0x843da941 +948, 0x80c9c03e +949, 0x9dcc37a7 +950, 0xc09b0037 +951, 0x32d52326 +952, 0xe4c9f6bf +953, 0xde872120 +954, 0x2e7b2957 +955, 0xe17b7baa +956, 0x6d32aad0 +957, 0xdfe6c604 +958, 0xc4e497c9 +959, 0xb6208fef +960, 0x88d8f15d +961, 0x9b8b48d5 +962, 0x591c1666 +963, 0xb974dfd4 +964, 0xb880e0dd +965, 0x4a2774ef +966, 0x3a735723 +967, 0x5b580f75 +968, 0x9a988e56 +969, 0x2ea12bfc +970, 0x11995890 +971, 0x48525745 +972, 0xe9d12a00 +973, 0x7dc73054 +974, 0xa2701b3e +975, 0xcc9b116b +976, 0xc438f3ec +977, 0xfe61e77d +978, 0xed2afc8c +979, 0x9468ca59 +980, 0x8d9c84fb +981, 0x4fe77716 +982, 0x39bb1634 +983, 0x4b1e04bb +984, 0xf0dcc50b +985, 0x109f398d +986, 0xd9f23761 +987, 0x348cb388 +988, 0x2c9b1a0f +989, 0x911041ad +990, 0x282e5df9 +991, 0x575a1995 +992, 0x7204304e +993, 0x797d6d3 +994, 0xae7d37c +995, 0x5521a6cf +996, 0x712c3e19 +997, 0x8fb8dbd5 +998, 0x7ded12a7 +999, 0x50a92df2 diff --git a/_randomgen/core_prng/tests/data/threefry32-testset-2.csv b/_randomgen/core_prng/tests/data/threefry32-testset-2.csv new file mode 100644 index 000000000000..b7753638fd04 --- /dev/null +++ b/_randomgen/core_prng/tests/data/threefry32-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x96bf21c6 +1, 0xa0fe05c7 +2, 0xe1fe280e +3, 0xf35055dc +4, 0x4ec871e3 +5, 0x3bc86276 +6, 0x17a5b958 +7, 0xf49e5388 +8, 0xf7374019 +9, 0x917691a0 +10, 0x448e864 +11, 0x6d3821bc +12, 0x4db62dea +13, 0x4ea93fd4 +14, 0x8a2981e0 +15, 0x6db52782 +16, 0x1391de47 +17, 0x8cbe2e34 +18, 0x6001fa10 +19, 0xa38115ee +20, 0x14199363 +21, 0x934fcba +22, 0xb240df72 +23, 0x6ab87661 +24, 0x60b9d9f5 +25, 0xdbd34621 +26, 0x526af21d +27, 0x1a6b4bf5 +28, 0xd7173663 +29, 0xdce2b053 +30, 0x62080540 +31, 0xe1c3dd3e +32, 0x33ae037a +33, 0xe602063e +34, 0x5ea0ec41 +35, 0xf0313701 +36, 0xa41e72c +37, 0x291889ad +38, 0x6eb6b020 +39, 0x4d623617 +40, 0x5a1574d7 +41, 0x78d45c73 +42, 0xeb9e4d3c +43, 0xe4775f83 +44, 0x89f67a5 +45, 0xcaa0ac99 +46, 0x6caee87b +47, 0x5cafd04e +48, 0x9717a3a0 +49, 0xd6be9166 +50, 0x1288e672 +51, 0x6dfe4ec3 +52, 0x3bb56a74 +53, 0x58582a09 +54, 0x44c7519a +55, 0x17500801 +56, 0xdddc251 +57, 0xc32bf7a8 +58, 0x6f79b324 +59, 0x8a6f971d +60, 0x246d519e +61, 0xda4d3a03 +62, 0x9bed7502 +63, 0xe3dc760a +64, 0x35eb67da +65, 0x717b6e2c +66, 0xe540553b +67, 0xa8ffd00e +68, 0xc7f801c2 +69, 0x2b762e33 +70, 0x420e2c94 +71, 0x8c339dfa +72, 0x99f694f8 +73, 0x217f423a +74, 0x1fd8e09f +75, 0xb3f76cd2 +76, 0x1cee1308 +77, 0xc83f9c45 +78, 0xd48e24a1 +79, 0xb779cf03 +80, 0x1e042002 +81, 0x8f18d559 +82, 0x9d5e185d +83, 0xe2ca5f65 +84, 0x13f56ff3 +85, 0x20fd0f05 +86, 0x201f99ab +87, 0x331c3df5 +88, 0xbaba8549 +89, 0xc6f7306 +90, 0x2b360412 +91, 0x31043048 +92, 0x959c617f +93, 0xadf28e64 +94, 0xfc5b23e6 +95, 0x70e6b601 +96, 0x6bb34693 +97, 0x1fddbf26 +98, 0x7cd372db +99, 0x695ed6f3 +100, 0xc5a37f9a +101, 0x575aba37 +102, 0x74ae0700 +103, 0x8443b8e9 +104, 0x4157dfc0 +105, 0x150dc093 +106, 0x3f7d86 +107, 0x5a11d745 +108, 0x26e3530b +109, 0x2700974b +110, 0x3f395b3c +111, 0x32dc070 +112, 0x7816fd58 +113, 0xf11f39b0 +114, 0xb1bdb3ae +115, 0x933c37a +116, 0x9621e2b +117, 0x6aa61ac8 +118, 0xea05ee84 +119, 0x9e481f10 +120, 0xbc5f31b4 +121, 0x4c29115c +122, 0xcc492bf4 +123, 0xe8f67fb +124, 0xcf9ef4d6 +125, 0xde0d0e81 +126, 0x7b673c75 +127, 0xad3fe9ed +128, 0xbee239e9 +129, 0x1e087877 +130, 0x912eee8a +131, 0x2f55f5ee +132, 0xd0fa0da0 +133, 0xa14fb442 +134, 0xd86b0234 +135, 0x7b1d72db +136, 0x919aa862 +137, 0xfa0196ec +138, 0x30e35f2d +139, 0xa907b642 +140, 0x537204fa +141, 0x8ef7f10d +142, 0x3625e260 +143, 0x5b4d7d73 +144, 0x436729fd +145, 0x8c52723 +146, 0xcde668bd +147, 0xe1d74aa2 +148, 0x73e380e2 +149, 0x19d2f3b4 +150, 0x693d2c4d +151, 0xf1ee106 +152, 0x110b4a39 +153, 0x367df2b2 +154, 0x603b9495 +155, 0xf1fe7afb +156, 0xe77de62d +157, 0xfb68fae5 +158, 0x235b3ef5 +159, 0xc4bdad24 +160, 0xb57f08f3 +161, 0x195a8e95 +162, 0x29f1a9de +163, 0x8d4c905f +164, 0x1419c72e +165, 0x8944437d +166, 0x13587ab7 +167, 0x8c2c89f0 +168, 0xc5446300 +169, 0x7d4dbbd1 +170, 0xb4ce733 +171, 0x2e106d +172, 0x1aecbeb2 +173, 0xd6e885e3 +174, 0x8a0969e0 +175, 0x402a5a80 +176, 0x963d7b5f +177, 0x366051e9 +178, 0x9221f52e +179, 0x3922be06 +180, 0x3f3ea09c +181, 0xb4c67478 +182, 0xa582bfad +183, 0xd8190211 +184, 0x1a5bdcca +185, 0x438d1ac +186, 0x91e68cc7 +187, 0xb584a426 +188, 0x248e2953 +189, 0xff061284 +190, 0x14204e87 +191, 0x41be6ee6 +192, 0xd28c68e9 +193, 0x7c1a6cb2 +194, 0x3dfb5acc +195, 0x9350bf13 +196, 0x633a5ea +197, 0x4e2d241b +198, 0x5a4878f1 +199, 0x775a7a87 +200, 0x7d1538fa +201, 0x43f49533 +202, 0xafc96ab9 +203, 0xe08e3b31 +204, 0xe5f234ff +205, 0x91953358 +206, 0x45cf4358 +207, 0x8070f40f +208, 0x61140fa4 +209, 0xb56542bc +210, 0x3def3833 +211, 0x3afcb202 +212, 0x9ddad97e +213, 0x364f535a +214, 0x722d4445 +215, 0x292e4364 +216, 0x708a1fda +217, 0x9ddb0c16 +218, 0xf3a27c5e +219, 0x18acae39 +220, 0x93e92f61 +221, 0x3e2fa33 +222, 0x878d11f3 +223, 0x61a220a9 +224, 0x4a649d1f +225, 0x394c9f4b +226, 0x9e7c84ad +227, 0xf7fd62c4 +228, 0xcbb4ba39 +229, 0x5eadd8c1 +230, 0x720fa83c +231, 0x64c36bf9 +232, 0x574d17c3 +233, 0x8cdf6eec +234, 0x7638f112 +235, 0xa9c131ce +236, 0x4466a7e0 +237, 0x5e932445 +238, 0xe504370f +239, 0xed84b1c +240, 0x216bd3f5 +241, 0xe8068a58 +242, 0xa15bcde9 +243, 0xee5dbcce +244, 0x413e0b5e +245, 0xfe3255f6 +246, 0x5d9816d0 +247, 0xbcd5a8a0 +248, 0x49ef0ff6 +249, 0x872570c1 +250, 0x3ca3bb8b +251, 0xc4b4d57d +252, 0x25d109b5 +253, 0x5c750b00 +254, 0xc46b7428 +255, 0x2484eda +256, 0xd4c33354 +257, 0x38bb7d44 +258, 0x113da842 +259, 0xb86e73d7 +260, 0x134b9007 +261, 0x672857a +262, 0x7e1f4f33 +263, 0x6c562447 +264, 0x8e592c4b +265, 0x32d2c0b9 +266, 0x5c734488 +267, 0x52acf2d5 +268, 0xfcb64a7f +269, 0xe2ab9d6a +270, 0x18dde6a7 +271, 0xa518ca9c +272, 0x12c92fce +273, 0x9bed83a6 +274, 0x8a78b026 +275, 0x946d9163 +276, 0xddddd15e +277, 0x4d80628c +278, 0x4c6feb7f +279, 0x8f775fbc +280, 0xb1a8e3b +281, 0x3809bc2d +282, 0xd2c72be8 +283, 0x4b481760 +284, 0xc2e72e75 +285, 0x8f37c5ea +286, 0x7307ed25 +287, 0xdc14b350 +288, 0xb2c286f2 +289, 0xa050d102 +290, 0x2f114a3a +291, 0xc27c7a7b +292, 0xdea01eb +293, 0x932cf59d +294, 0xcf4d5b30 +295, 0x86b6bbbf +296, 0x2b290705 +297, 0xabebd181 +298, 0x702ddf78 +299, 0xf4ca859d +300, 0x2020e833 +301, 0x217f3e4 +302, 0x7f0e8cbd +303, 0x7904900 +304, 0x77cb8b6 +305, 0x5daffd7 +306, 0xb6f1a28c +307, 0xfc3a016f +308, 0x61c54f36 +309, 0x27061341 +310, 0xcff54873 +311, 0x4e9690f9 +312, 0x4836fd91 +313, 0x17166086 +314, 0x5bee87b9 +315, 0x1824513f +316, 0x2e121297 +317, 0xeb6700d +318, 0x131ba5ed +319, 0xadef4e19 +320, 0x6b4f51ad +321, 0x35361ab8 +322, 0x5663d841 +323, 0xb2f164a2 +324, 0x402d76f +325, 0xafbd20c0 +326, 0xf8876253 +327, 0x2bf3b986 +328, 0x9f91ddf8 +329, 0xf2b9da4c +330, 0xaa14c7e4 +331, 0xe15cf29b +332, 0x357f2012 +333, 0x4561ab12 +334, 0x1bc5dff3 +335, 0xf07dad88 +336, 0xdd3cc715 +337, 0xe560ac91 +338, 0x8b9475e3 +339, 0xd181c80f +340, 0x55d1cd2c +341, 0x11d425f6 +342, 0x2ca6b58f +343, 0x21b3ad57 +344, 0x1754cd75 +345, 0x90a8050e +346, 0x72e84c22 +347, 0x96dd5f3d +348, 0x6044db23 +349, 0x63434074 +350, 0x6bd5b611 +351, 0xd72ae77c +352, 0xc82da625 +353, 0x7e98cda9 +354, 0x276e09ff +355, 0x24a72915 +356, 0xac1f8749 +357, 0x8c5d96fc +358, 0x322933ef +359, 0x6e8fd47 +360, 0x931acda0 +361, 0x6a714821 +362, 0xfa5ee5c +363, 0x48e64ef0 +364, 0xd8e3e670 +365, 0x4b30496f +366, 0x56959138 +367, 0x121fa62a +368, 0x927f7b6e +369, 0xdee500 +370, 0x38fb7e0c +371, 0x17708fb1 +372, 0xd55c07be +373, 0x2e18a475 +374, 0x431d85a7 +375, 0xa405d3f8 +376, 0x5de38b47 +377, 0x96f6b788 +378, 0xd0f84145 +379, 0xd2392752 +380, 0x44a6566c +381, 0xb3d46be3 +382, 0xc8c9dc5f +383, 0xa952122d +384, 0x197d11c9 +385, 0xa135e6e2 +386, 0xd9d91bbb +387, 0xf4b56186 +388, 0x3cb621ba +389, 0xb572252f +390, 0x8668224e +391, 0x44cb5619 +392, 0xa68bb5c8 +393, 0x224639d9 +394, 0xde35e870 +395, 0x3df1148 +396, 0x21fe35fa +397, 0xccfaffb5 +398, 0x18add490 +399, 0x8126b15e +400, 0xbfd69b4e +401, 0x216fd33a +402, 0x932589c0 +403, 0xabbdd53 +404, 0x1ded816b +405, 0xad0c1ff0 +406, 0x6a5f7a8d +407, 0xcb3e1d5e +408, 0xa8559680 +409, 0xfad440ef +410, 0xdc3e4a27 +411, 0xd1606be4 +412, 0x9e8b03ea +413, 0xf3a38fb8 +414, 0x9cab22b +415, 0x4d25b615 +416, 0xc46114c6 +417, 0xa2726196 +418, 0x65ecb782 +419, 0x79439d3c +420, 0x69ab8d82 +421, 0x216184d2 +422, 0xab262a47 +423, 0xecee9422 +424, 0xa3c1674e +425, 0x357992aa +426, 0x44278f94 +427, 0x4c12fab +428, 0x7740f7fc +429, 0x944222fd +430, 0xc251348 +431, 0x83b629f8 +432, 0x4b594fa0 +433, 0x51d6a9ab +434, 0x830bef86 +435, 0xe250fac1 +436, 0xfde9e381 +437, 0x9e22470a +438, 0x8653c37 +439, 0xd7ec4710 +440, 0xa698bf59 +441, 0x4bf8a5fe +442, 0xbb9fd26 +443, 0xd3cc40d +444, 0xcc1d24da +445, 0x8100b99c +446, 0x199a71bd +447, 0x77464e71 +448, 0x65556a05 +449, 0x1c713ff +450, 0x99c9edc3 +451, 0xa1a0a60d +452, 0x4cf77f1e +453, 0x407ffa53 +454, 0xcebf9b42 +455, 0x2228074e +456, 0x29332ee0 +457, 0x66b2c926 +458, 0x8c7b4df3 +459, 0xd1968179 +460, 0xde7124c9 +461, 0x6d8abf4e +462, 0x25d0af4c +463, 0x65e6fbf4 +464, 0xf8c9d76a +465, 0x5b39bce9 +466, 0x1e9dda4f +467, 0x99dfa42 +468, 0x11531373 +469, 0x5e387ef +470, 0xb474e29a +471, 0xff1d322d +472, 0x3de7e402 +473, 0xb3e2a619 +474, 0xac6f3b84 +475, 0x32650d1d +476, 0x854d9bd7 +477, 0x177d6cf2 +478, 0x64cbb5f7 +479, 0x9a86778 +480, 0x6e1277ef +481, 0xfb4c2f35 +482, 0x1e1931a8 +483, 0x8c66d53 +484, 0xb60870e0 +485, 0xb27759f3 +486, 0x525bfba8 +487, 0xea4b4ac0 +488, 0xb8d944a3 +489, 0xee27be58 +490, 0x506d723f +491, 0x5ceb9607 +492, 0x91efc140 +493, 0x799cb2c5 +494, 0x30c9a8a0 +495, 0x5f03f36 +496, 0xed6ade24 +497, 0xfaaa5117 +498, 0x9174a363 +499, 0x4eef8150 +500, 0x1eec4b8e +501, 0x39901de7 +502, 0xf92f40a3 +503, 0xaa1d14 +504, 0xb9313106 +505, 0xb68676ea +506, 0x6f11d728 +507, 0x66c59d63 +508, 0xb09e79f9 +509, 0x68d29514 +510, 0x9deedf1d +511, 0xfd972780 +512, 0x9bf1cbbd +513, 0x18c1f79 +514, 0x5fed1afe +515, 0xd7a51fc6 +516, 0x2eae8dbb +517, 0xf293e112 +518, 0x1e437bbb +519, 0x5e3d390e +520, 0xbcced217 +521, 0x55d23765 +522, 0xa02aa678 +523, 0xec96a24a +524, 0x29e500a8 +525, 0x98b8a4d2 +526, 0x8c2d9136 +527, 0xe65dec90 +528, 0x3eba15de +529, 0x3c25ef33 +530, 0xdbca90a6 +531, 0x4f09311d +532, 0x990e05c6 +533, 0x54679cf9 +534, 0x8d0ae2b3 +535, 0xa33b8506 +536, 0xf5437070 +537, 0x887fe2ad +538, 0x906a30e0 +539, 0xb2b464f4 +540, 0x415c3577 +541, 0x6057c5c0 +542, 0x70cc0f44 +543, 0x9b2fb077 +544, 0x7336a7f3 +545, 0x9068d9ec +546, 0xc5057d25 +547, 0x705d52e7 +548, 0x6a4aca4c +549, 0x2dadbe60 +550, 0x9c59fba4 +551, 0x791bd0ac +552, 0x11299194 +553, 0xb21a9f2d +554, 0x30aa87c3 +555, 0xede7a398 +556, 0xeece9bb0 +557, 0x38f46a57 +558, 0xb69cd5a8 +559, 0xa04d6d8e +560, 0x42db338f +561, 0x933948d9 +562, 0xb8c1b512 +563, 0x9915f7a2 +564, 0xf0467ab7 +565, 0xc43a5426 +566, 0x53e1470c +567, 0x60c764c7 +568, 0x676c6da5 +569, 0xace51d51 +570, 0x240628e7 +571, 0x3f0c776 +572, 0x7185d397 +573, 0x4209e930 +574, 0xcd75c0db +575, 0x3917fb29 +576, 0x3c95c879 +577, 0x10e9bb04 +578, 0x63a072ce +579, 0x39401a04 +580, 0x6ea9edc1 +581, 0xe4008fe0 +582, 0xebf2bf0d +583, 0x760c3233 +584, 0x7b8edd5f +585, 0xfd632b63 +586, 0x863a8155 +587, 0x9e5dcf41 +588, 0x374dc183 +589, 0xe6279dcf +590, 0x3a802f +591, 0xa17e7cb5 +592, 0x773a8161 +593, 0xda344f6a +594, 0x86a50b9 +595, 0x2defa7cb +596, 0x87b49d8 +597, 0x2169b33c +598, 0x2e1f1748 +599, 0x7d10a959 +600, 0x86fe64a6 +601, 0x9fd5b948 +602, 0xaad08122 +603, 0x1a2a52a3 +604, 0xeede4a8f +605, 0x17117e8 +606, 0xa4650709 +607, 0x2ce293d1 +608, 0x5d1cf4ee +609, 0x94b23094 +610, 0x150f50ff +611, 0x7beeeefa +612, 0xa0baf1db +613, 0x363a69f2 +614, 0x5a67965 +615, 0x9e014734 +616, 0xb7313d3e +617, 0x6e070b62 +618, 0x4fc9b70f +619, 0x455a5d8b +620, 0x21c94a8a +621, 0x203853dc +622, 0x79e0dde1 +623, 0x68b11257 +624, 0x888bb806 +625, 0xa7e9178e +626, 0x8022be3 +627, 0xc550db7b +628, 0xa8f3f180 +629, 0xd28c1484 +630, 0x955445a5 +631, 0xc84c1609 +632, 0x71463ea6 +633, 0x20962712 +634, 0xf9a074 +635, 0xae59fb67 +636, 0x5bf0a427 +637, 0x165146c2 +638, 0xb08ec935 +639, 0x20cfa297 +640, 0x8492faa8 +641, 0xa1f3cf65 +642, 0x646479a9 +643, 0xb035174e +644, 0xb3b039f8 +645, 0x7780d61b +646, 0x63754f94 +647, 0x286565d0 +648, 0x10e13878 +649, 0x145f546f +650, 0xd857539 +651, 0xd8db00e8 +652, 0xc092dc9e +653, 0xb835b8bf +654, 0xe207b116 +655, 0x7961075d +656, 0x5e50116b +657, 0x355bf5c1 +658, 0x897dde54 +659, 0xc505a279 +660, 0x729aaf7c +661, 0xdfb9f60c +662, 0xdb75db2e +663, 0x520f947d +664, 0x6847c154 +665, 0x69a24a1a +666, 0xecf825c7 +667, 0x8b4da35b +668, 0x71e73004 +669, 0xaa594a1c +670, 0x70f6260e +671, 0x73b565a +672, 0xf050bb33 +673, 0xd9409845 +674, 0x32354d60 +675, 0xabed3745 +676, 0x1995883 +677, 0x6418b501 +678, 0x6a96c78c +679, 0xece6bffc +680, 0xc3892389 +681, 0xf1fa0e62 +682, 0x59a93622 +683, 0xac1d1798 +684, 0x8b1984b4 +685, 0x2603f602 +686, 0x4fdd2d48 +687, 0xaa57c8af +688, 0x49735a97 +689, 0x73075464 +690, 0x75647208 +691, 0xe88930a0 +692, 0x4c51d399 +693, 0x86904118 +694, 0x62af2995 +695, 0x4c62090e +696, 0x7319e53 +697, 0xb11c255c +698, 0xa9fb903f +699, 0xc602439b +700, 0x447eb0a4 +701, 0x9b602006 +702, 0xa6583b9a +703, 0xc33d5e64 +704, 0xf945c9be +705, 0x1199ecfc +706, 0x58ca9756 +707, 0xc0f98006 +708, 0x7694cb6e +709, 0x537b5f33 +710, 0x5ad022df +711, 0xc23ae783 +712, 0xf27d584c +713, 0x3410e1d4 +714, 0xc69867f2 +715, 0x239cb4fc +716, 0xedeffd68 +717, 0x9cc9e0be +718, 0xb44585c7 +719, 0xf811df78 +720, 0x32e3779c +721, 0x495830a7 +722, 0xb5c7ecb2 +723, 0x8583521a +724, 0x26cd0f3f +725, 0x7f79bf6e +726, 0xf63c2afa +727, 0xabbf2df3 +728, 0x90cead53 +729, 0xdac401a +730, 0x76d10bb8 +731, 0xa7a6a87e +732, 0x3f7783c1 +733, 0x2cdf71e0 +734, 0xb7e5ebfb +735, 0xa5eb1c64 +736, 0xfa462a94 +737, 0x92e33c33 +738, 0xb1f5f201 +739, 0xb58b1587 +740, 0x212b9bbf +741, 0x63938326 +742, 0xd7562019 +743, 0x9e1974ea +744, 0x670c615b +745, 0x62460641 +746, 0x9be46c7e +747, 0x34421fab +748, 0xe722475c +749, 0x8e6170aa +750, 0xfa68a479 +751, 0xb77324b0 +752, 0xa64c0f97 +753, 0x5183720b +754, 0xf3160e77 +755, 0x23a3b269 +756, 0x9d7b11d1 +757, 0x3cfbefd4 +758, 0x1fe0e235 +759, 0x910ebbce +760, 0x84eae93d +761, 0xe390b082 +762, 0xce29298f +763, 0xe7e718c7 +764, 0x7adc4e73 +765, 0xc3c5dae4 +766, 0x685c0b9b +767, 0xa5ed9a8 +768, 0x5a2ccb4a +769, 0x3c94fa33 +770, 0xdc8726ef +771, 0x92121728 +772, 0xe2c57ec6 +773, 0x522712e1 +774, 0xec5e6145 +775, 0xe486d06c +776, 0x1ef7fa3a +777, 0xd3e8ac09 +778, 0xca770944 +779, 0xd490c429 +780, 0x5b626100 +781, 0x973f8555 +782, 0x5b690d01 +783, 0x3ba958c1 +784, 0xa4b3f08c +785, 0x6760f219 +786, 0x59bac764 +787, 0xb1c54d52 +788, 0xcb4aa641 +789, 0x2d6c9a4e +790, 0xebd48ef +791, 0xee3109d4 +792, 0xd286c88e +793, 0xfd26fd0f +794, 0x450825c5 +795, 0xaa1a4313 +796, 0xb07511ed +797, 0xb2836487 +798, 0x900cd63b +799, 0x2345cfa0 +800, 0xc6de4d20 +801, 0xf57de173 +802, 0x24890b60 +803, 0x522ce8c2 +804, 0xb70a8eb2 +805, 0x358ee7a +806, 0x6a29365c +807, 0x402f9666 +808, 0x6889332c +809, 0x21e55b7e +810, 0x8c886218 +811, 0x943ce0c2 +812, 0x637f3dcc +813, 0x336ceaef +814, 0x65d94c0d +815, 0x2e07516c +816, 0x7b03d97a +817, 0x5d0dd1ce +818, 0x98e27a9f +819, 0x329e3e00 +820, 0xa758619e +821, 0xf2401413 +822, 0xc73c21d2 +823, 0xa7f97da5 +824, 0x397c2e9c +825, 0x9511ed82 +826, 0x824760e6 +827, 0x2391d3c2 +828, 0x7ca7092c +829, 0xbb63f94 +830, 0xa7370c1d +831, 0x61a44ce8 +832, 0xfdf08bf1 +833, 0x5dba1ae3 +834, 0x72a21633 +835, 0x2239c7fe +836, 0xfbcc7e2 +837, 0xe2f724d7 +838, 0x69223ca3 +839, 0xd7759240 +840, 0xbdeda501 +841, 0x413c2cf0 +842, 0xbc7e5c63 +843, 0x339f3ef9 +844, 0x95749faf +845, 0xb1ac835 +846, 0x866fb03a +847, 0x90873b55 +848, 0x59c09bd6 +849, 0x180f8d78 +850, 0x729bf2a0 +851, 0x13a32fe6 +852, 0x62dd49a5 +853, 0x9eecb212 +854, 0x258d30e8 +855, 0x2153d968 +856, 0xaba5083a +857, 0x726aaf8e +858, 0x512c3192 +859, 0x62414d +860, 0x48fa16b8 +861, 0xf761e7e4 +862, 0xf6012be7 +863, 0x77dff028 +864, 0xd21abf72 +865, 0xed2f995f +866, 0x69cee22 +867, 0x54200535 +868, 0xd883594c +869, 0x28b475e6 +870, 0xe0a2038c +871, 0x1b56c6e1 +872, 0x7220704 +873, 0xf842418 +874, 0x90aa400 +875, 0x941b5975 +876, 0x576d964d +877, 0x93ef2176 +878, 0xd9562201 +879, 0xf7433ac +880, 0x23ede5c7 +881, 0xfadf3362 +882, 0x769830d1 +883, 0x21ee4b1e +884, 0x6c60a5f8 +885, 0xf42ec278 +886, 0x5ac46157 +887, 0xc527c639 +888, 0xdbbbb7bc +889, 0xcbf79715 +890, 0x26384600 +891, 0x9cdfad11 +892, 0x60815d7a +893, 0x20bcf98a +894, 0x4652d4ba +895, 0x7ea46112 +896, 0x7c560e8d +897, 0xbeb3e89d +898, 0xb861dd4 +899, 0xe1d4189c +900, 0xe83ea3e5 +901, 0x92393c2b +902, 0xdd6bbf3d +903, 0x620a691a +904, 0xdb64b940 +905, 0x5fbadf2d +906, 0x1ce81d5f +907, 0x4b20d0d7 +908, 0x53ea3105 +909, 0xf350f9fc +910, 0xd04736d8 +911, 0x358e8630 +912, 0x18fb3a7d +913, 0x8633154e +914, 0xf48a9fec +915, 0x98c40cb2 +916, 0x98596dac +917, 0xb5e16a27 +918, 0x1834670b +919, 0x3e8cf415 +920, 0x6e6ba2b8 +921, 0xfa5cddae +922, 0x77032bac +923, 0x97b9e6c +924, 0x3ffc2aa1 +925, 0x879b53a +926, 0xbbf693b5 +927, 0x971efbd3 +928, 0x9ab6ad89 +929, 0x160d498a +930, 0x66cebdce +931, 0x4fb855c0 +932, 0x68558584 +933, 0xa695f564 +934, 0xebea0104 +935, 0xb349d0b1 +936, 0xb27c5871 +937, 0xd4965433 +938, 0x3b48325d +939, 0x816851ad +940, 0xa7328098 +941, 0x307cdf7c +942, 0xfacb2352 +943, 0xac2ded57 +944, 0xd01efb86 +945, 0x9e039163 +946, 0xb9e02f +947, 0xd18c1916 +948, 0xef4380f0 +949, 0x1c578bcf +950, 0x737f6c89 +951, 0x47dd10af +952, 0x459bbd41 +953, 0xf0c0a4ff +954, 0xc2166f81 +955, 0x4ffabd22 +956, 0x89731a04 +957, 0x989a031a +958, 0x941ed188 +959, 0xa77ec4d9 +960, 0x3e6ca8e5 +961, 0x238e5fe7 +962, 0x2ac9b71b +963, 0x95a0d1be +964, 0xfc56dbaf +965, 0xbb5a4378 +966, 0x4cc6e834 +967, 0x36175364 +968, 0xb097fbe3 +969, 0xea1466d4 +970, 0x317733fc +971, 0xeb88ef75 +972, 0xb82570c6 +973, 0x2b8adfa2 +974, 0xd7a86699 +975, 0x6d13d28f +976, 0x6dd2c41b +977, 0x92d733e6 +978, 0x928f31a5 +979, 0xfe7c01bd +980, 0x62a1bc47 +981, 0x47d9b6e1 +982, 0xae6f97a4 +983, 0xbdaed100 +984, 0xbb24138 +985, 0xa6f1819 +986, 0xdc5f99a +987, 0xc5b5b978 +988, 0xdfb7fc81 +989, 0xc82744ca +990, 0xbdd30239 +991, 0x6c11d175 +992, 0x3910ed7a +993, 0x6b9efa62 +994, 0x29a9dd01 +995, 0x492afa85 +996, 0x151b62e8 +997, 0x2546c48d +998, 0x3cb52c7c +999, 0x8fc96435 diff --git a/_randomgen/core_prng/tests/test_against_numpy.py b/_randomgen/core_prng/tests/test_against_numpy.py index 6bd4bc0912ac..9f0cfe054fa0 100644 --- a/_randomgen/core_prng/tests/test_against_numpy.py +++ b/_randomgen/core_prng/tests/test_against_numpy.py @@ -240,7 +240,7 @@ def test_logseries(self): is_small=True) self._is_state_common() - def test_zipf(self): + def test_geometric(self): self._set_common_state() self._is_state_common() compare_1_input(self.nprs.geometric, @@ -376,7 +376,6 @@ def test_rand(self): assert_allclose(f(10), g(10)) assert_allclose(f(3, 4, 5), g(3, 4, 5)) - @pytest.mark.xfail def test_poisson_lam_max(self): assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) diff --git a/_randomgen/core_prng/tests/test_direct.py b/_randomgen/core_prng/tests/test_direct.py index 9496cc1916f9..61dafdcaa924 100644 --- a/_randomgen/core_prng/tests/test_direct.py +++ b/_randomgen/core_prng/tests/test_direct.py @@ -6,7 +6,8 @@ from numpy.testing import assert_equal, assert_allclose, assert_array_equal, \ assert_raises -from core_prng import * +from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ + PCG64, Philox, Xoroshiro128, Xorshift1024 if (sys.version_info > (3, 0)): long = int @@ -250,6 +251,31 @@ def setup_class(cls): cls.seed_error_type = TypeError +class TestPCG64(Base): + @classmethod + def setup_class(cls): + cls.prng = 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 = TypeError + + def test_seed_float_array(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) + assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) + assert_raises(self.seed_error_type, rs.seed, np.array([np.pi, -np.pi])) + assert_raises(self.seed_error_type, rs.seed, np.array([0, np.pi])) + assert_raises(self.seed_error_type, rs.seed, [np.pi]) + assert_raises(self.seed_error_type, rs.seed, [0, np.pi]) + + def test_seed_out_of_range_array(self): + rs = RandomGenerator(self.prng(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(self.seed_error_type, rs.seed, [-1]) + + class TestPhilox(Base): @classmethod def setup_class(cls): @@ -316,7 +342,6 @@ def setup_class(cls): def test_uniform_double(self): rs = RandomGenerator(self.prng(*self.data1['seed'])) - aa = uniform_from_dsfmt(self.data1['data']) assert_array_equal(uniform_from_dsfmt(self.data1['data']), rs.random_sample(1000)) @@ -371,3 +396,14 @@ def test_uniform_float(self): uniforms = rs.random_sample(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) + + +class TestThreeFry32(Base): + @classmethod + def setup_class(cls): + cls.prng = ThreeFry32 + cls.bits = 32 + cls.dtype = np.uint32 + cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) + cls.data2 = cls._read_csv(join(pwd, './data/threefry32-testset-2.csv')) + cls.seed_error_type = TypeError diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937.py b/_randomgen/core_prng/tests/test_numpy_mt19937.py index 3fa936f2f3c1..5097f82bd355 100644 --- a/_randomgen/core_prng/tests/test_numpy_mt19937.py +++ b/_randomgen/core_prng/tests/test_numpy_mt19937.py @@ -1526,9 +1526,8 @@ def test_negative_binomial(self): assert_raises(ValueError, neg_binom, n, bad_p_one * 3) assert_raises(ValueError, neg_binom, n, bad_p_two * 3) - @pytest.mark.xfail def test_poisson(self): - max_lam = random.RandomState().poisson_lam_max + max_lam = random.poisson_lam_max lam = [1] bad_lam_one = [-1] diff --git a/_randomgen/core_prng/tests/test_smoke.py b/_randomgen/core_prng/tests/test_smoke.py index a5678dbaa406..929fd1e9f0ca 100644 --- a/_randomgen/core_prng/tests/test_smoke.py +++ b/_randomgen/core_prng/tests/test_smoke.py @@ -1,18 +1,21 @@ +import os import pickle -import time import sys -import os +import time + import numpy as np import pytest +from numpy.testing import assert_almost_equal, assert_equal, assert_, \ + assert_array_equal -from core_prng import * +from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ + PCG64, Philox, Xoroshiro128, Xorshift1024 from core_prng import entropy -from numpy.testing import assert_almost_equal, assert_equal, assert_raises, assert_, assert_array_equal - -@pytest.fixture(scope='module', params=(np.bool, np.int8, np.int16, np.int32, np.int64, - np.uint8, np.uint16, np.uint32, np.uint64)) +@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 @@ -71,7 +74,8 @@ def comp_state(state1, state2): 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))): + 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: @@ -128,7 +132,7 @@ def test_jump(self): self.rg.jump() jumped_state = self.rg.state assert_(not comp_state(state, jumped_state)) - self.rg.random_sample(2*3*5*7*11*13*17) + self.rg.random_sample(2 * 3 * 5 * 7 * 11 * 13 * 17) self.rg.state = state self.rg.jump() rejumped_state = self.rg.state @@ -206,8 +210,6 @@ def test_reset_state(self): def test_entropy_init(self): rg = RandomGenerator(self.prng()) rg2 = RandomGenerator(self.prng()) - s1 = rg.state - s2 = rg2.state assert_(not comp_state(rg.state, rg2.state)) def test_seed(self): @@ -270,7 +272,7 @@ def test_tomaxint(self): else: try: maxsize = sys.maxint - except: + except AttributeError: maxsize = sys.maxsize if maxsize < 2 ** 32: assert_((vals < sys.maxsize).all()) @@ -311,7 +313,8 @@ def test_complex_normal(self): self.rg.state = st vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='zig') + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, + method='zig') np.testing.assert_allclose(vals, vals3) self.rg.state = st @@ -322,7 +325,8 @@ def test_complex_normal(self): v_imag = 2.5 rho = cov / np.sqrt(v_real * v_imag) imag = 7 + np.sqrt(v_imag) * (rho * - norms[:, 0] + np.sqrt(1 - rho ** 2) * norms[:, 1]) + norms[:, 0] + np.sqrt(1 - rho ** 2) * + norms[:, 1]) real = 2 + np.sqrt(v_real) * norms[:, 0] vals4 = [re + im * (0 + 1.0j) for re, im in zip(real, imag)] @@ -341,7 +345,8 @@ def test_complex_normal_bm(self): self.rg.state = st vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='bm') + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, + method='bm') np.testing.assert_allclose(vals, vals3) def test_complex_normal_zero_variance(self): @@ -541,12 +546,6 @@ def test_pickle(self): assert_((type(self.rg) == type(unpick))) assert_(comp_state(self.rg.state, unpick.state)) - @pytest.mark.xfail - def test_version(self): - state = self.rg.state - assert_('version' in state) - assert_(state['version'] == 0) - def test_seed_array(self): if self.seed_vector_bits is None: pytest.skip() @@ -790,11 +789,13 @@ def test_randint_broadcast(self, dtype): assert_equal(a, c) self._reset_state() d = self.rg.randint(np.array( - [lower] * 10), np.array([upper], dtype=np.object), size=10, dtype=dtype) + [lower] * 10), np.array([upper], dtype=np.object), size=10, + dtype=dtype) assert_equal(a, d) self._reset_state() e = self.rg.randint( - np.array([lower] * 10), np.array([upper] * 10), size=10, dtype=dtype) + np.array([lower] * 10), np.array([upper] * 10), size=10, + dtype=dtype) assert_equal(a, e) self._reset_state() @@ -846,18 +847,16 @@ def setup_class(cls): cls._extra_setup() cls.seed_error = ValueError - @pytest.mark.xfail def test_numpy_state(self): - # TODO: Do we want lagacy state support nprg = np.random.RandomState() nprg.standard_normal(99) - state = nprg.state + state = nprg.get_state() self.rg.state = state state2 = self.rg.state - assert_((state[1] == state2['state'][0]).all()) - assert_((state[2] == state2['state'][1])) - assert_((state[3] == state2['gauss']['has_gauss'])) - assert_((state[4] == state2['gauss']['gauss'])) + assert_((state[1] == state2['state']['key']).all()) + assert_((state[2] == state2['state']['pos'])) + assert_((state[3] == state2['has_gauss'])) + assert_((state[4] == state2['gauss'])) class TestPCG64(RNG): @@ -957,6 +956,19 @@ def setup_class(cls): cls.seed_vector_bits = 32 +class TestThreeFry32(RNG): + @classmethod + def setup_class(cls): + cls.prng = ThreeFry32 + cls.advance = [2 ** 96 + 2 ** 16 + 2 ** 5 + 1] + cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + cls.seed_error = ValueError + + class TestEntropy(object): def test_entropy(self): e1 = entropy.random_entropy() diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 99c7027734a3..4cf50e3e7669 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -33,7 +33,7 @@ cdef extern from 'src/threefry/threefry.h': ctypedef s_threefry_state threefry_state uint64_t threefry_next64(threefry_state *state) nogil - uint64_t threefry_next32(threefry_state *state) nogil + uint32_t threefry_next32(threefry_state *state) nogil void threefry_jump(threefry_state *state) void threefry_advance(uint64_t *step, threefry_state *state) @@ -181,7 +181,6 @@ cdef class ThreeFry: """ if seed is not None and key is not None: raise ValueError('seed and key cannot be both used') - ub = 2 ** 64 if key is None: if seed is None: try: @@ -194,12 +193,12 @@ cdef class ThreeFry: for i in range(4): self.rng_state.key.v[i] = state[i] else: - key = int_to_array(key, 'key', 256) + key = int_to_array(key, 'key', 256, 64) for i in range(4): self.rng_state.key.v[i] = key[i] counter = 0 if counter is None else counter - counter = int_to_array(counter, 'counter', 256) + counter = int_to_array(counter, 'counter', 256, 64) for i in range(4): self.rng_state.ctr.v[i] = counter[i] @@ -248,7 +247,7 @@ cdef class ThreeFry: def advance(self, step): """Advance the state as-if a specific number of draws have been made""" cdef np.ndarray step_a - step_a = int_to_array(step, 'step', 256) + step_a = int_to_array(step, 'step', 256, 64) loc = 0 threefry_advance(step_a.data, self.rng_state) return self diff --git a/_randomgen/core_prng/threefry32.pyx b/_randomgen/core_prng/threefry32.pyx new file mode 100644 index 000000000000..3a5bc92d62ac --- /dev/null +++ b/_randomgen/core_prng/threefry32.pyx @@ -0,0 +1,250 @@ +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np + +from common cimport * +from distributions cimport prng_t, binomial_t +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + +DEF THREEFRY_BUFFER_SIZE=4 + +cdef extern from 'src/threefry32/threefry32.h': + struct s_r123array4x32: + uint32_t v[4] + + ctypedef s_r123array4x32 r123array4x32 + + ctypedef r123array4x32 threefry4x32_key_t + ctypedef r123array4x32 threefry4x32_ctr_t + + struct s_threefry32_state: + threefry4x32_ctr_t *ctr; + threefry4x32_key_t *key; + int buffer_pos; + uint32_t buffer[THREEFRY_BUFFER_SIZE]; + + ctypedef s_threefry32_state threefry32_state + + uint64_t threefry32_next64(threefry32_state *state) nogil + uint32_t threefry32_next32(threefry32_state *state) nogil + double threefry32_next_double(threefry32_state *state) nogil + void threefry32_jump(threefry32_state *state) + void threefry32_advance(uint32_t *step, threefry32_state *state) + + +cdef uint64_t threefry32_uint64(void* st) nogil: + return threefry32_next64(st) + +cdef uint32_t threefry32_uint32(void *st) nogil: + return threefry32_next32( st) + +cdef double threefry32_double(void* st) nogil: + return threefry32_next_double(st) + +cdef uint64_t threefry32_raw(void *st) nogil: + return threefry32_next32( st) + + +cdef class ThreeFry32: + """ + Prototype Core PRNG using threefry + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `state`. Designed for use in + a `RandomGenerator` object. + """ + cdef threefry32_state *rng_state + cdef prng_t *_prng + cdef public object capsule + + def __init__(self, seed=None, counter=None, key=None): + self.rng_state = malloc(sizeof(threefry32_state)) + self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) + self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) + self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) + self.seed(seed, counter, key) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &threefry32_uint64 + self._prng.next_uint32 = &threefry32_uint32 + self._prng.next_double = &threefry32_double + self._prng.next_raw = &threefry32_raw + + cdef const char *name = 'CorePRNG' + self.capsule = PyCapsule_New(self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state.ctr) + free(self.rng_state.key) + free(self.rng_state) + free(self._prng.binomial) + free(self._prng) + + cdef _reset_state_variables(self): + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 + self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE + for i in range(THREEFRY_BUFFER_SIZE): + self.rng_state.buffer[i] = 0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') + + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): + cdef Py_ssize_t i + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') + + def seed(self, seed=None, counter=None, key=None): + """ + seed(seed=None, counter=None, key=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + counter : {int array}, optional + Positive integer less than 2**128 containing the counter position + or a 4 element array of uint32 containing the counter + key : {int, array}, options + Positive integer less than 2**128 containing the key + or a 4 element array of uint32 containing the key + + Raises + ------ + ValueError + If values are out of range for the PRNG. + + Notes + ----- + The two representation of the counter and key are related through + array[i] = (value // 2**(32*i)) % 2**32. + """ + if seed is not None and key is not None: + raise ValueError('seed and key cannot be both used') + if key is None: + if seed is None: + try: + state = random_entropy(4) + except RuntimeError: + state = random_entropy(4, 'fallback') + else: + state = entropy.seed_by_array(seed, 2) + state = state.view(np.uint32) + for i in range(4): + self.rng_state.key.v[i] = state[i] + else: + key = int_to_array(key, 'key', 128, 32) + for i in range(4): + self.rng_state.key.v[i] = key[i] + + counter = 0 if counter is None else counter + counter = int_to_array(counter, 'counter', 128, 32) + for i in range(4): + self.rng_state.ctr.v[i] = counter[i] + + self._reset_state_variables() + + @property + def state(self): + """Get or set the PRNG state""" + ctr = np.empty(4, dtype=np.uint32) + key = np.empty(4, dtype=np.uint32) + buffer = np.empty(THREEFRY_BUFFER_SIZE, dtype=np.uint32) + for i in range(4): + ctr[i] = self.rng_state.ctr.v[i] + key[i] = self.rng_state.key.v[i] + for i in range(THREEFRY_BUFFER_SIZE): + buffer[i] = self.rng_state.buffer[i] + state = {'counter':ctr,'key':key} + return {'prng': self.__class__.__name__, + 'state': state, + 'buffer': buffer, + 'buffer_pos': self.rng_state.buffer_pos} + + @state.setter + def state(self, value): + if not isinstance(value, dict): + raise TypeError('state must be a dict') + prng = value.get('prng', '') + if prng != 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] = value['state']['counter'][i] + self.rng_state.key.v[i] = value['state']['key'][i] + for i in range(THREEFRY_BUFFER_SIZE): + self.rng_state.buffer[i] = value['buffer'][i] + self.rng_state.buffer_pos = value['buffer_pos'] + + def jump(self): + """Jump the state as-if 2**64draws have been made""" + return self.advance(2**64) + + def advance(self, step): + """Advance the state as-if a specific number of draws have been made""" + cdef np.ndarray step_a + step_a = int_to_array(step, 'step', 128, 32) + loc = 0 + threefry32_advance(step_a.data, self.rng_state) + return self diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 34f88859d1c1..fa623382f832 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -26,7 +26,7 @@ cdef extern from "src/xoroshiro128/xoroshiro128.h": ctypedef s_xoroshiro128_state xoroshiro128_state uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil - uint64_t xoroshiro128_next32(xoroshiro128_state *state) nogil + uint32_t xoroshiro128_next32(xoroshiro128_state *state) nogil void xoroshiro128_jump(xoroshiro128_state *state) cdef uint64_t xoroshiro128_uint64(void* st) nogil: diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index effc2b3d0538..939dc702b557 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -23,7 +23,7 @@ cdef extern from "src/xorshift1024/xorshift1024.h": ctypedef s_xorshift1024_state xorshift1024_state uint64_t xorshift1024_next64(xorshift1024_state *state) nogil - uint64_t xorshift1024_next32(xorshift1024_state *state) nogil + uint32_t xorshift1024_next32(xorshift1024_state *state) nogil void xorshift1024_jump(xorshift1024_state *state) cdef uint64_t xorshift1024_uint64(void* st) nogil: diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 9ccb2b8f4c4e..1e922550dc7e 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -122,6 +122,15 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("core_prng.threefry32", + ["core_prng/threefry32.pyx", + join(MOD_DIR, 'src', 'threefry32', 'threefry32.c')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'threefry32')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.xoroshiro128", ["core_prng/xoroshiro128.pyx", join(MOD_DIR, 'src', 'xoroshiro128', From 8fa8c2b19abca353c85a8b57f1ca654672a03f48 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 13:44:03 +0000 Subject: [PATCH 049/138] BUG: Enable build to run on 32-bit Linux Enable 32-bit Linux support --- _randomgen/appveyor.yml | 2 +- _randomgen/benchmark.py | 4 ++-- _randomgen/core_prng/src/philox/philox.h | 27 ++++++++++++++++++++++++ _randomgen/setup.py | 2 ++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml index 86d98b2b67aa..25b2f0c54337 100644 --- a/_randomgen/appveyor.yml +++ b/_randomgen/appveyor.yml @@ -30,4 +30,4 @@ test_script: on_success: - cd %GIT_DIR%\ - - IF %PY_MAJOR_VER%==3 python benchmark.py \ No newline at end of file + - python benchmark.py \ No newline at end of file diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index f828f657d24f..c0082cfc8ac0 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -26,8 +26,8 @@ else: scale_64 = 2 -PRNGS = ['PCG64', 'MT19937', 'Xoroshiro128', 'Xorshift1024', - 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] +PRNGS = ['DSFMT', 'MT19937', 'PCG64', 'Philox', 'ThreeFry', 'ThreeFry32', + 'Xoroshiro128', 'Xorshift1024', 'numpy'] def timer(code, setup): diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index f0ca24e6a677..e0545bce3540 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -60,11 +60,38 @@ static INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } #else +#if __SIZEOF_INT128__ static 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 +static 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 INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { + return _umul128(a, b, hip); +} +#endif #endif static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 1e922550dc7e..0eb997c05d36 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -50,6 +50,8 @@ else: EXTRA_COMPILE_ARGS += ['-msse2'] DSFMT_DEFS += [('HAVE_SSE2', '1')] +if struct.calcsize('P') < 8: + PCG_EMULATED_MATH = True files = glob.glob('./core_prng/*.in') for templated_file in files: From 644d8838a8982ad5aafd39af127b717ef9f5c744 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 17:43:20 +0000 Subject: [PATCH 050/138] ENH: Add PCG32 Add PCG32 for benchmarking --- _randomgen/benchmark.py | 4 +- _randomgen/core_prng/__init__.py | 3 +- _randomgen/core_prng/pcg32.pyx | 216 ++ _randomgen/core_prng/pcg64.pyx | 2 +- _randomgen/core_prng/pickle.py | 2 + _randomgen/core_prng/src/dsfmt/dSFMT.h | 30 +- .../core_prng/src/pcg32/pcg-advance-64.c | 62 + .../core_prng/src/pcg32/pcg32-test-data-gen.c | 59 + _randomgen/core_prng/src/pcg32/pcg32.c | 30 + _randomgen/core_prng/src/pcg32/pcg32.h | 86 + _randomgen/core_prng/src/pcg32/pcg_variants.h | 2210 +++++++++++++++++ .../core_prng/tests/data/pcg32-testset-1.csv | 1001 ++++++++ .../core_prng/tests/data/pcg32-testset-2.csv | 1001 ++++++++ _randomgen/core_prng/tests/test_direct.py | 15 +- _randomgen/core_prng/tests/test_smoke.py | 15 +- _randomgen/setup.py | 12 +- 16 files changed, 4726 insertions(+), 22 deletions(-) create mode 100644 _randomgen/core_prng/pcg32.pyx create mode 100644 _randomgen/core_prng/src/pcg32/pcg-advance-64.c create mode 100644 _randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c create mode 100644 _randomgen/core_prng/src/pcg32/pcg32.c create mode 100644 _randomgen/core_prng/src/pcg32/pcg32.h create mode 100644 _randomgen/core_prng/src/pcg32/pcg_variants.h create mode 100644 _randomgen/core_prng/tests/data/pcg32-testset-1.csv create mode 100644 _randomgen/core_prng/tests/data/pcg32-testset-2.csv diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index c0082cfc8ac0..852773f2bd22 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -26,8 +26,8 @@ else: scale_64 = 2 -PRNGS = ['DSFMT', 'MT19937', 'PCG64', 'Philox', 'ThreeFry', 'ThreeFry32', - 'Xoroshiro128', 'Xorshift1024', 'numpy'] +PRNGS = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', 'Xorshift1024', + 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] def timer(code, setup): diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 9b7d10631927..9a4b0a1b19a6 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,6 +1,7 @@ from .dsfmt import DSFMT from .generator import RandomGenerator from .mt19937 import MT19937 +from .pcg32 import PCG32 from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry @@ -8,7 +9,7 @@ from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 -__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'Philox', +__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/core_prng/pcg32.pyx b/_randomgen/core_prng/pcg32.pyx new file mode 100644 index 000000000000..316dc81d9087 --- /dev/null +++ b/_randomgen/core_prng/pcg32.pyx @@ -0,0 +1,216 @@ +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from common cimport * +from distributions cimport prng_t, binomial_t +from core_prng.entropy import random_entropy +import core_prng.pickle +cimport entropy + +np.import_array() + + +cdef extern from "src/pcg32/pcg32.h": + + cdef struct pcg_state_setseq_64: + uint64_t state + uint64_t inc + + ctypedef pcg_state_setseq_64 pcg32_random_t + + struct s_pcg32_state: + pcg32_random_t *pcg_state + + ctypedef s_pcg32_state pcg32_state + + uint64_t pcg32_next64(pcg32_state *state) nogil + uint32_t pcg32_next32(pcg32_state *state) nogil + double pcg32_next_double(pcg32_state *state) nogil + void pcg32_jump(pcg32_state *state) + void pcg32_advance_state(pcg32_state *state, uint64_t step) + void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) + +cdef uint64_t pcg32_uint64(void* st) nogil: + return pcg32_next64(st) + +cdef uint32_t pcg32_uint32(void *st) nogil: + return pcg32_next32( st) + +cdef double pcg32_double(void* st) nogil: + return pcg32_next_double(st) + +cdef uint64_t pcg32_raw(void* st) nogil: + return pcg32_next32( st) + + +cdef class PCG32: + """ + Prototype Core PRNG using pcg64 + + Parameters + ---------- + seed : int, array of int + Integer or array of integers between 0 and 2**64 - 1 + + Notes + ----- + Exposes no user-facing API except `get_state` and `set_state`. Designed + for use in a `RandomGenerator` object. + """ + cdef pcg32_state *rng_state + cdef prng_t *_prng + cdef public object capsule + + def __init__(self, seed=None, inc=0): + self.rng_state = malloc(sizeof(pcg32_state)) + self.rng_state.pcg_state = malloc(sizeof(pcg32_random_t)) + self._prng = malloc(sizeof(prng_t)) + self._prng.binomial = malloc(sizeof(binomial_t)) + self.seed(seed, inc) + + self._prng.state = self.rng_state + self._prng.next_uint64 = &pcg32_uint64 + self._prng.next_uint32 = &pcg32_uint32 + self._prng.next_double = &pcg32_double + self._prng.next_raw = &pcg32_raw + + cdef const char *name = "CorePRNG" + self.capsule = PyCapsule_New(self._prng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (core_prng.pickle.__prng_ctor, + (self.state['prng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state) + free(self._prng.binomial) + free(self._prng) + + cdef _reset_state_variables(self): + self._prng.has_gauss = 0 + self._prng.has_gauss_f = 0 + self._prng.gauss = 0.0 + self._prng.gauss_f = 0.0 + + def __random_integer(self, bits=64): + """ + 64-bit Random Integers from the PRNG + + Parameters + ---------- + bits : {32, 64} + Number of random bits to return + + Returns + ------- + rv : int + Next random value + + Notes + ----- + Testing only + """ + if bits == 64: + return self._prng.next_uint64(self._prng.state) + elif bits == 32: + return self._prng.next_uint32(self._prng.state) + else: + raise ValueError('bits must be 32 or 64') + + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): + cdef Py_ssize_t i + if method==u'uint64': + for i in range(cnt): + self._prng.next_uint64(self._prng.state) + elif method==u'double': + for i in range(cnt): + self._prng.next_double(self._prng.state) + else: + raise ValueError('Unknown method') + + + def seed(self, seed=None, inc=0): + """ + seed(seed=None, stream=None) + + Seed the generator. + + 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, optional + Seed for ``RandomState``. + inc : int, optional + Increment to use for PCG stream + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + + """ + ub = 2 ** 64 + if seed is None: + try: + seed = random_entropy(2) + except RuntimeError: + seed = random_entropy(2, 'fallback') + seed = seed.view(np.uint64).squeeze() + else: + err_msg = 'seed must be a scalar integer between 0 and ' \ + '{ub}'.format(ub=ub) + if not np.isscalar(seed): + raise TypeError(err_msg) + if int(seed) != seed: + raise TypeError(err_msg) + if seed < 0 or seed > ub: + raise ValueError(err_msg) + + if not np.isscalar(inc): + raise TypeError('inc must be a scalar integer between 0 ' + 'and {ub}'.format(ub=ub)) + if inc < 0 or inc > ub or int(inc) != inc: + raise ValueError('inc must be a scalar integer between 0 ' + 'and {ub}'.format(ub=ub)) + + pcg32_set_seed(self.rng_state, seed, inc) + self._reset_state_variables() + + @property + def state(self): + """Get or set the PRNG state""" + return {'prng': self.__class__.__name__, + 'state': {'state': self.rng_state.pcg_state.state, + 'inc':self.rng_state.pcg_state.inc}} + + @state.setter + def state(self, value): + if not isinstance(value, dict): + raise TypeError('state must be a dict') + prng = value.get('prng', '') + if prng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + self.rng_state.pcg_state.state = value['state']['state'] + self.rng_state.pcg_state.inc = value['state']['inc'] + + def advance(self, step): + pcg32_advance_state(self.rng_state, step) + return self + + def jump(self): + return self.advance(2**32) diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 70aa57b76610..c01156d72f37 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -189,7 +189,7 @@ cdef class PCG64: _seed = random_entropy(4, 'fallback') _seed = _seed.view(np.uint64) else: - err_msg = 'inc must be a scalar integer between 0 and ' \ + err_msg = 'seed must be a scalar integer between 0 and ' \ '{ub}'.format(ub=ub) if not np.isscalar(seed): raise TypeError(err_msg) diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/core_prng/pickle.py index 56f4de56240e..40557d63edbd 100644 --- a/_randomgen/core_prng/pickle.py +++ b/_randomgen/core_prng/pickle.py @@ -1,6 +1,7 @@ from .generator import RandomGenerator from .dsfmt import DSFMT from .mt19937 import MT19937 +from .pcg32 import PCG32 from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry @@ -10,6 +11,7 @@ PRNGS = {'MT19937': MT19937, 'DSFMT': DSFMT, + 'PCG32': PCG32, 'PCG64': PCG64, 'Philox': Philox, 'ThreeFry': ThreeFry, diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index fa608cd758f1..0ae8a016d871 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -633,6 +633,11 @@ inline static void fill_array_close1_open2(double array[], int size) { #endif /* DSFMT_H */ +union random_val_t { + double d; + uint64_t u64; +}; + typedef struct s_dsfmt_state { dsfmt_t *state; int has_uint32; @@ -660,28 +665,27 @@ static inline double dsfmt_next_double(dsfmt_state *state) { static inline uint64_t dsfmt_next64(dsfmt_state *state) { /* Discard bottom 16 bits */ - double d = dsfmt_next_buffer(state); + union random_val_t rv; + rv.d = dsfmt_next_buffer(state); uint64_t out; - uint64_t *tmp; - tmp = (uint64_t *)&d; - out = (*tmp >> 16) << 32; - d = dsfmt_next_buffer(state); - tmp = (uint64_t *)&d; - out |= (*tmp >> 16) & 0xffffffff; + out = (rv.u64 >> 16) << 32; + rv.d = dsfmt_next_buffer(state); + out |= (rv.u64 >> 16) & 0xffffffff; return out; } static inline uint32_t dsfmt_next32(dsfmt_state *state) { /* Discard bottom 16 bits */ - double d = dsfmt_next_buffer(state); - uint64_t *out = (uint64_t *)&d; - return (uint32_t)((*out >> 16) & 0xffffffff); + union random_val_t rv; + rv.d = dsfmt_next_buffer(state); + // uint64_t *out = (uint64_t *)&d; + return (uint32_t)((rv.u64 >> 16) & 0xffffffff); } static inline uint64_t dsfmt_next_raw(dsfmt_state *state) { - double d; - d = dsfmt_next_buffer(state); - return *((uint64_t *)&d); + union random_val_t rv; + rv.d = dsfmt_next_buffer(state); + return rv.u64; } void dsfmt_jump(dsfmt_state *state); \ No newline at end of file diff --git a/_randomgen/core_prng/src/pcg32/pcg-advance-64.c b/_randomgen/core_prng/src/pcg32/pcg-advance-64.c new file mode 100644 index 000000000000..8210e75650eb --- /dev/null +++ b/_randomgen/core_prng/src/pcg32/pcg-advance-64.c @@ -0,0 +1,62 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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. + * + * Repetative C code is derived using C preprocessor metaprogramming + * techniques. + */ + +#include "pcg_variants.h" + +/* 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". + */ + +uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, + uint64_t cur_plus) +{ + uint64_t acc_mult = 1u; + uint64_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; +} + diff --git a/_randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c b/_randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c new file mode 100644 index 000000000000..cccaf84b9948 --- /dev/null +++ b/_randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c @@ -0,0 +1,59 @@ +/* + * Generate testing csv files + * + * + * gcc pcg32-test-data-gen.c pcg32.orig.c ../splitmix64/splitmix64.c -o + * pgc64-test-data-gen + */ + +#include "pcg_variants.h" +#include +#include + +#define N 1000 + +int main() { + pcg32_random_t rng; + uint64_t inc, seed = 0xDEADBEAF; + inc = 0; + int i; + uint64_t store[N]; + pcg32_srandom_r(&rng, seed, inc); + for (i = 0; i < N; i++) { + store[i] = pcg32_random_r(&rng); + } + + FILE *fp; + fp = fopen("pcg32-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); + + seed = 0; + pcg32_srandom_r(&rng, seed, inc); + for (i = 0; i < N; i++) { + store[i] = pcg32_random_r(&rng); + } + fp = fopen("pcg32-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/_randomgen/core_prng/src/pcg32/pcg32.c b/_randomgen/core_prng/src/pcg32/pcg32.c new file mode 100644 index 000000000000..5fbf6759f1a3 --- /dev/null +++ b/_randomgen/core_prng/src/pcg32/pcg32.c @@ -0,0 +1,30 @@ +#include "pcg32.h" + +extern inline uint64_t pcg32_next64(pcg32_state *state); +extern inline uint32_t pcg32_next32(pcg32_state *state); +extern inline double pcg32_next_double(pcg32_state *state); + +uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, + uint64_t cur_plus) { + uint64_t acc_mult, acc_plus; + acc_mult = 1u; + 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; +} + +extern void pcg32_advance_state(pcg32_state *state, uint64_t step) { + pcg32_advance_r(state->pcg_state, step); +} + +extern void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) { + pcg32_srandom_r(state->pcg_state, seed, inc); +} diff --git a/_randomgen/core_prng/src/pcg32/pcg32.h b/_randomgen/core_prng/src/pcg32/pcg32.h new file mode 100644 index 000000000000..5ab59cc85105 --- /dev/null +++ b/_randomgen/core_prng/src/pcg32/pcg32.h @@ -0,0 +1,86 @@ + +#ifdef _WIN32 +#ifndef _INTTYPES +#include "../common/stdint.h" +#endif +#define inline __inline __forceinline +#else +#include +#endif + +#define PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL + +struct pcg_state_setseq_64 { + uint64_t state; + uint64_t inc; +}; + +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 void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) { + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc; +} + +inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { + return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u); +} + +inline uint32_t +pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) { + uint64_t oldstate; + oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +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); +} + +extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, + uint64_t cur_mult, uint64_t cur_plus); + +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); +} + +typedef struct pcg_state_setseq_64 pcg32_random_t; +#define pcg32_random_r pcg_setseq_64_xsh_rr_32_random_r +#define pcg32_srandom_r pcg_setseq_64_srandom_r +#define pcg32_advance_r pcg_setseq_64_advance_r + +typedef struct s_pcg32_state { + pcg32_random_t *pcg_state; +} pcg32_state; + +static inline uint64_t pcg32_next64(pcg32_state *state) { + return (uint64_t)(pcg32_random_r(state->pcg_state)) << 32 | + pcg32_random_r(state->pcg_state); +} + +static inline uint32_t pcg32_next32(pcg32_state *state) { + return pcg32_random_r(state->pcg_state); +} + +static inline double pcg32_next_double(pcg32_state *state) { + int32_t a = pcg32_random_r(state->pcg_state) >> 5, + b = pcg32_random_r(state->pcg_state) >> 6; + return (a * 67108864.0 + b) / 9007199254740992.0; +} + +void pcg32_advance_state(pcg32_state *state, uint64_t step); +void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc); diff --git a/_randomgen/core_prng/src/pcg32/pcg_variants.h b/_randomgen/core_prng/src/pcg32/pcg_variants.h new file mode 100644 index 000000000000..32daac1ce4f5 --- /dev/null +++ b/_randomgen/core_prng/src/pcg32/pcg_variants.h @@ -0,0 +1,2210 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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 + +#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/_randomgen/core_prng/tests/data/pcg32-testset-1.csv b/_randomgen/core_prng/tests/data/pcg32-testset-1.csv new file mode 100644 index 000000000000..6bddc8d5ccc2 --- /dev/null +++ b/_randomgen/core_prng/tests/data/pcg32-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xbeb77374 +1, 0x75cad014 +2, 0xabc6773e +3, 0xe99a034e +4, 0x1e3f5c6d +5, 0x513d3c5b +6, 0x4a378bad +7, 0xba5b3488 +8, 0x21e96448 +9, 0x5197a3d3 +10, 0x84bbcc90 +11, 0x674fce76 +12, 0xd1dd9879 +13, 0x1625afd4 +14, 0x4bb5e330 +15, 0x3f4b8f74 +16, 0xf0a7c00b +17, 0xecdb92d0 +18, 0xf069232c +19, 0x56dbeaa2 +20, 0x70c62231 +21, 0x6c68e57e +22, 0x3829213c +23, 0x9b8bc5e6 +24, 0x45abd553 +25, 0xf5991ce7 +26, 0xb4aff20a +27, 0x677a5785 +28, 0x108f180d +29, 0x2b3f1001 +30, 0x838fdfcb +31, 0x8ad3c2a0 +32, 0x596268fa +33, 0xee6bcc56 +34, 0x46810af0 +35, 0x1648a587 +36, 0x7265a926 +37, 0xed0f3acc +38, 0x72a1ac0 +39, 0xb3f7109f +40, 0x6ddd75f2 +41, 0xa968127f +42, 0x40df20fd +43, 0xde835b80 +44, 0xe453cd68 +45, 0x26ad68eb +46, 0x23a052d2 +47, 0x17881c5c +48, 0x785d41b9 +49, 0x61b4530a +50, 0x5ee92c84 +51, 0x4cad7358 +52, 0x843db584 +53, 0x3576368b +54, 0x14db6b2b +55, 0xb6e8b042 +56, 0x6323e866 +57, 0x9a709e25 +58, 0xae594bdc +59, 0x4be9ec1b +60, 0x77b4fd05 +61, 0x4421667 +62, 0x24bf98f7 +63, 0xfb202aed +64, 0x2f01b05f +65, 0xac766e69 +66, 0xc1572ce2 +67, 0xb26354d6 +68, 0x4db5f193 +69, 0x41a4609b +70, 0x26bbb4cc +71, 0x676b7438 +72, 0x13b2be7d +73, 0x7df521c4 +74, 0x57f770f3 +75, 0x78a8a8 +76, 0x164d46c6 +77, 0xbb29da20 +78, 0x5c262bf9 +79, 0xfd305d0 +80, 0xb500d90b +81, 0xbb7b4e37 +82, 0x5ba2bbfd +83, 0xa9561043 +84, 0xe175c662 +85, 0x3a5c8eec +86, 0xac5e2184 +87, 0x1e1c7de7 +88, 0x46be092a +89, 0x8b82f5be +90, 0xb1c1b591 +91, 0x6f06d957 +92, 0x1d26dc5c +93, 0x158c57e3 +94, 0x6da1ebf8 +95, 0x74501e60 +96, 0x70587043 +97, 0xa19b90fe +98, 0x7d327dff +99, 0x22dc6b90 +100, 0xf48a9ae6 +101, 0x75eeb769 +102, 0x9cdc12cb +103, 0x7fe2cdc6 +104, 0x4fba8066 +105, 0x1a7a0667 +106, 0xd9289d22 +107, 0x3a045bce +108, 0x60e5f71f +109, 0xd81b35dc +110, 0xceae6194 +111, 0xa032a688 +112, 0x7157b327 +113, 0x61c74c80 +114, 0x2d519c39 +115, 0x5b1a352e +116, 0x5ad266da +117, 0x9118352b +118, 0xdd20b6e1 +119, 0xc0d154fa +120, 0x93bbb9c9 +121, 0x91170de2 +122, 0xa3af5e05 +123, 0x1b19ff2f +124, 0xf814c3bf +125, 0x8914a953 +126, 0x5278efb7 +127, 0x3c96d7bd +128, 0xb5422a7 +129, 0x2aee2619 +130, 0x60c6a90c +131, 0xfbec0e9c +132, 0xef794075 +133, 0xda93d22e +134, 0xb956d02a +135, 0xd97cc49b +136, 0x80737244 +137, 0x7c56a95 +138, 0xa5311355 +139, 0x7dcdd592 +140, 0x92add23e +141, 0xb1ba1317 +142, 0x507e5330 +143, 0x2644b95a +144, 0xa1afa519 +145, 0x596c65c0 +146, 0x6f47dd11 +147, 0xfd2fbada +148, 0x98675d7c +149, 0xb9e21413 +150, 0x8bae5eca +151, 0xe1f50018 +152, 0x7dd08715 +153, 0x36a888e1 +154, 0x7fcd6364 +155, 0xb84c093 +156, 0x18e2d58f +157, 0x19fd21ed +158, 0x3c25e3a3 +159, 0x7a0d833b +160, 0x47525b28 +161, 0xba88474 +162, 0xd108e7da +163, 0x32b06660 +164, 0xbce027b3 +165, 0x96b31787 +166, 0x916ab263 +167, 0xa5fa088 +168, 0x3cb9cd59 +169, 0x7a97051f +170, 0x104b6883 +171, 0x6e08c314 +172, 0x33a4c62c +173, 0x14eb854 +174, 0x873f730a +175, 0x8c3f7224 +176, 0x9a41beeb +177, 0xe4e2ab0a +178, 0xfa89ad0e +179, 0x4aa62ac3 +180, 0xb75dc1bf +181, 0x3f4c5131 +182, 0x3fef0f91 +183, 0xffa06655 +184, 0x417d7d38 +185, 0x1e7734df +186, 0x25685235 +187, 0x33fe5b68 +188, 0x68923f72 +189, 0x5da45ff +190, 0xb871df26 +191, 0xd3ffd8c6 +192, 0x1718d862 +193, 0xe127d844 +194, 0xadcdc48a +195, 0x79ee30cb +196, 0x931a6cba +197, 0x9463c42d +198, 0x9f8d2806 +199, 0xa3695a97 +200, 0xfc9587bc +201, 0xb3943573 +202, 0x50ed8901 +203, 0x6891f33 +204, 0xb7a12dfb +205, 0x1245cf5d +206, 0xbc0f73a7 +207, 0x26cbfeb2 +208, 0x774d8e83 +209, 0xa19e9c1 +210, 0xc147a437 +211, 0xe034f2a3 +212, 0xd288b664 +213, 0xdcd0356d +214, 0x2b695901 +215, 0x3bc31736 +216, 0x4a5b1998 +217, 0x18537410 +218, 0x11b40f35 +219, 0xf16f6f89 +220, 0xe844cffe +221, 0xce026166 +222, 0x3770aaba +223, 0xc62566ee +224, 0x6db2d1f8 +225, 0xe4720b6d +226, 0x68321a69 +227, 0x488539ac +228, 0x5e18ab61 +229, 0xb58e598e +230, 0x6f501a91 +231, 0xc4fd3e8d +232, 0x9faa3631 +233, 0x184366b0 +234, 0xecf74d6a +235, 0x3773d622 +236, 0x382ca536 +237, 0x93451381 +238, 0x9f148ed5 +239, 0x2b66f241 +240, 0xa6807c39 +241, 0xbb087446 +242, 0xa18ba432 +243, 0x8e7a6013 +244, 0xab30278e +245, 0xbf457c78 +246, 0xb24814b1 +247, 0x710f99d5 +248, 0xbcb84762 +249, 0x4913a7e7 +250, 0x90a31a0c +251, 0x6d4b1673 +252, 0x18873994 +253, 0x1efd517a +254, 0x99b499d1 +255, 0x2d488776 +256, 0x1cded201 +257, 0xa53b02e4 +258, 0xcb20d0fd +259, 0x72bfaae3 +260, 0x858c865b +261, 0x2e2d3e96 +262, 0x8bc5b0b9 +263, 0x8980346a +264, 0xa8e47fba +265, 0x2a39fe16 +266, 0x9f34eeeb +267, 0x7baebcc9 +268, 0xbc0b8d74 +269, 0x37373c8 +270, 0xe128cfc4 +271, 0x49cdb150 +272, 0x5965c726 +273, 0xfc326226 +274, 0x53a3e8e +275, 0xa99d89f7 +276, 0x33ac111c +277, 0x143fe678 +278, 0x96212281 +279, 0x6a83bffd +280, 0x529852f7 +281, 0x97fef4 +282, 0x303ce151 +283, 0x4f8c7b83 +284, 0xd5ef9c82 +285, 0xede9d572 +286, 0xc03e2c38 +287, 0x89d7f886 +288, 0x21e998b0 +289, 0x58d505cf +290, 0x5c42089 +291, 0x9a01dcab +292, 0x83d8cc17 +293, 0x7d6aacf +294, 0xa1cbdced +295, 0x47365e25 +296, 0xbb61e976 +297, 0xfeafd0a6 +298, 0x760d82b4 +299, 0x9ffb351d +300, 0x28e19ac0 +301, 0x891131c6 +302, 0xc1656522 +303, 0x4536d90 +304, 0x956b1b84 +305, 0xf9ff54f6 +306, 0xb0050d88 +307, 0x7d7fafa2 +308, 0x430e670b +309, 0x18ad450d +310, 0xd5a1d6b6 +311, 0x390a6da4 +312, 0xc70d557d +313, 0xd8fadb5e +314, 0xfb4b4cb6 +315, 0xce707f8b +316, 0x4c18d350 +317, 0x8dc0d200 +318, 0x228d9e85 +319, 0xd6485ba3 +320, 0x37c4a70a +321, 0x9d7cc5f5 +322, 0x889a9b9 +323, 0x41d2f942 +324, 0x4c13b3bd +325, 0x70e58147 +326, 0x4a0e1270 +327, 0x3cdc1b73 +328, 0x7a4e56f3 +329, 0xd8350406 +330, 0x46068108 +331, 0xfc4da48 +332, 0xf6111245 +333, 0x40a15167 +334, 0x38a591ac +335, 0x3e97e682 +336, 0x5c515d2d +337, 0x45023a37 +338, 0xacb0ed6a +339, 0x899f0ebb +340, 0x2054df01 +341, 0x6d629607 +342, 0x79ced597 +343, 0xba0a3a12 +344, 0xde63b611 +345, 0x228cb776 +346, 0x61f10dba +347, 0x9a1095d3 +348, 0xf08dcb3 +349, 0x88e58009 +350, 0x131880aa +351, 0xc55002ee +352, 0xcf556f47 +353, 0x17b6dd76 +354, 0x6110ba20 +355, 0x74a91935 +356, 0xe83cf9ed +357, 0x3138e936 +358, 0x103bfb72 +359, 0x2084abe4 +360, 0xf3a05dd9 +361, 0x9213f3a4 +362, 0xe7674dd7 +363, 0xcd09d629 +364, 0x260461f2 +365, 0x411c2428 +366, 0xbb5f6f2e +367, 0x6feb8c93 +368, 0x3cde3ece +369, 0x7a424d2c +370, 0x808a0948 +371, 0x653c3fdf +372, 0x26f88849 +373, 0xf540b6ae +374, 0x1f82e8ac +375, 0x300f7e39 +376, 0xb6e62e7b +377, 0x970441a1 +378, 0x91f2946c +379, 0xaad281f +380, 0x43be1dcf +381, 0x95a1b4c8 +382, 0x2d956dea +383, 0xc532ca29 +384, 0xc93f1fcf +385, 0x70762aab +386, 0x231a72ef +387, 0xe5bd1b75 +388, 0xfa31468 +389, 0x77e1b7b5 +390, 0x19d80215 +391, 0xd45704b7 +392, 0x33472a0d +393, 0x833a435e +394, 0x2354a326 +395, 0x8af39828 +396, 0x603a7960 +397, 0x288c2d54 +398, 0x75bd7c23 +399, 0xe2dd42e1 +400, 0x9a87b486 +401, 0x32e9bcd1 +402, 0x8630f74f +403, 0x160408ea +404, 0xd2127c63 +405, 0xaf327f8e +406, 0x8d879a61 +407, 0xc5c88f60 +408, 0x53a19fa1 +409, 0x706dacb4 +410, 0xd04ea0f +411, 0x94806c1a +412, 0x941cfe69 +413, 0x956a5562 +414, 0xee1f71c +415, 0xe6ba12d +416, 0x333e31f6 +417, 0x17aee12e +418, 0x20ccfedb +419, 0xd7bb7f92 +420, 0xba7d14f3 +421, 0xb935d4fb +422, 0xbdb8f5e1 +423, 0xb24e7adc +424, 0xc9abef71 +425, 0x3e3d8125 +426, 0x5fc0878b +427, 0x5ba172d9 +428, 0xe28f648c +429, 0x5137f3a7 +430, 0xb57273df +431, 0xe68df236 +432, 0xbc29802b +433, 0xb1419e66 +434, 0x69ecb739 +435, 0x490e8eb6 +436, 0x61e25a6c +437, 0xc1fa0de6 +438, 0x2bf2fbf1 +439, 0x9487e8da +440, 0xce5c5532 +441, 0x75859040 +442, 0x2606bdeb +443, 0x1b77c072 +444, 0xe5fbeed1 +445, 0xea9e1ab3 +446, 0x55cf96ae +447, 0x283ed27d +448, 0xc94067a1 +449, 0x8687b3e5 +450, 0x4031b307 +451, 0xc5790e82 +452, 0x4031ee7f +453, 0x952c4503 +454, 0x379ec606 +455, 0x7c35e19d +456, 0x2d333769 +457, 0xbca36d54 +458, 0xcdc70741 +459, 0xa3ab56fb +460, 0x187a2fd6 +461, 0xdd1f32f1 +462, 0xc007ac56 +463, 0x14c441c1 +464, 0xf290ed47 +465, 0xc833edac +466, 0x13f0a8fe +467, 0x63c10b6e +468, 0x6af1be34 +469, 0x5bd4930e +470, 0xfe56bfbb +471, 0x1b412c8e +472, 0xf0c7712a +473, 0xf3a96226 +474, 0xbd0aaad8 +475, 0xbd00355e +476, 0x8ba9eca1 +477, 0x81f136a0 +478, 0x7de3a327 +479, 0x7be298ea +480, 0xe60e320a +481, 0xaf4373b +482, 0x6eacbf3 +483, 0x1291760f +484, 0xd48ed89b +485, 0x596603d4 +486, 0x53abc8 +487, 0x82123b2f +488, 0x1276dc8 +489, 0xfeb474bb +490, 0x4013da51 +491, 0x111cb9d6 +492, 0x5726df82 +493, 0x45806861 +494, 0x2580801a +495, 0x1326049e +496, 0xb9474bf9 +497, 0x6c5d85ed +498, 0x9c4a9352 +499, 0x9eb915ed +500, 0x914505 +501, 0xd14c5b9a +502, 0x57ef8ffd +503, 0x480d8719 +504, 0xb18d7fce +505, 0xfd29e178 +506, 0x2679f6c9 +507, 0xd94a086e +508, 0x6e46f559 +509, 0xb7c3a2e3 +510, 0x793a4c3b +511, 0x4e5252f9 +512, 0x1bdb53a4 +513, 0xbed5794 +514, 0x31a3ebc7 +515, 0xa6eb54e1 +516, 0xc6ae5d92 +517, 0x392acfc8 +518, 0xb283fb8f +519, 0x80b15ffe +520, 0x763b49a8 +521, 0x3febc1d3 +522, 0x60f2b20 +523, 0xd93aeba9 +524, 0xeddf06bb +525, 0x13992ab3 +526, 0x4521bcf6 +527, 0x5ad82a14 +528, 0xf2bfc79c +529, 0xf664b9b +530, 0xeb9540a2 +531, 0x5641dc50 +532, 0x9282d9c4 +533, 0x5d2443a4 +534, 0x407b5011 +535, 0x84a415d7 +536, 0x5db90eae +537, 0xd2947d4c +538, 0x8bd8856d +539, 0xbc05a99b +540, 0x1c2e0f5 +541, 0xb94d03a2 +542, 0xb8ed5ac1 +543, 0x199943d9 +544, 0x12482e5c +545, 0x20aa7c9f +546, 0x8733e45c +547, 0x277b4f44 +548, 0x673d5a73 +549, 0xabc0aad9 +550, 0xbed6cd98 +551, 0x2943c24b +552, 0x5237d6f9 +553, 0x1cb1a392 +554, 0xc7b69454 +555, 0x4f792707 +556, 0xa32ef400 +557, 0x7a5b6b72 +558, 0xa8683acc +559, 0x418d0491 +560, 0x56e2470e +561, 0xbe385495 +562, 0xe7944341 +563, 0x438abaab +564, 0x82ad2c2 +565, 0x7afc306b +566, 0xfcb88957 +567, 0x530414bd +568, 0x2e3c7d41 +569, 0x633f7573 +570, 0xeffeefb2 +571, 0xf6de11f9 +572, 0x337710f2 +573, 0x88bf46dc +574, 0x6fdaf5dc +575, 0x34229d26 +576, 0x46b0aba0 +577, 0x78e40a29 +578, 0x7f9623cd +579, 0x6cfe8779 +580, 0x1d4af99 +581, 0x78f97244 +582, 0xa198d714 +583, 0x9124883e +584, 0x1cf88a12 +585, 0x69fe0966 +586, 0x78484a68 +587, 0xf9d8718b +588, 0xcbf3ba5b +589, 0xf67fb149 +590, 0xc95977c1 +591, 0x474f57f5 +592, 0x11bb9ec1 +593, 0xe28f21be +594, 0x8ca6e21b +595, 0x2609defc +596, 0x989b6f6b +597, 0x1c87383e +598, 0xacd78f57 +599, 0x8c46cfcb +600, 0xc37cce08 +601, 0x327d196a +602, 0xf63c3572 +603, 0xc56780b5 +604, 0x9ac37d16 +605, 0xe692a39c +606, 0x563938a3 +607, 0x1e80e32f +608, 0x745652af +609, 0xe425c9a8 +610, 0x11c71e82 +611, 0x9c721f6d +612, 0xef89b973 +613, 0x494c7e80 +614, 0xadc29895 +615, 0xc7ee35ad +616, 0x19beeb0c +617, 0x9c25ae3f +618, 0x27bf930f +619, 0x223970a0 +620, 0x7cdb17ca +621, 0xa49054f +622, 0xf8321dcb +623, 0x3f96a9eb +624, 0x4468072a +625, 0xfd7d727 +626, 0xee0af4f1 +627, 0xe6585512 +628, 0x56a6d8a1 +629, 0x40586642 +630, 0xb46bdaa0 +631, 0xe053a140 +632, 0x4de1953d +633, 0xb6cbc718 +634, 0x2ed92c19 +635, 0x9da2840 +636, 0x6ab418b1 +637, 0x179f64cf +638, 0x7c281c0 +639, 0x7015b62a +640, 0x8d31e38e +641, 0xa6de57ca +642, 0xe509c4e1 +643, 0xa010162c +644, 0xf71abd42 +645, 0x3d24ac8b +646, 0xc2deb72f +647, 0xd81570ba +648, 0x17fc7d15 +649, 0xf17997b6 +650, 0xfa2ec5b5 +651, 0xbf7e189b +652, 0xb3d9e761 +653, 0xe1194bd1 +654, 0x8d5280dd +655, 0xdea2d148 +656, 0x6d85e66c +657, 0x37f5fb07 +658, 0x65c1dd1 +659, 0xf52c04f8 +660, 0x4460d846 +661, 0x1729f55f +662, 0xe03a699d +663, 0x9f05ff9f +664, 0x31abe986 +665, 0x64899f61 +666, 0x52fba7 +667, 0x2833ce74 +668, 0xa34d0e57 +669, 0x7203d492 +670, 0x1a63d91e +671, 0x463781b7 +672, 0xf9842e7b +673, 0x809276ad +674, 0x88237b9d +675, 0xaa648b06 +676, 0x9cf916bd +677, 0x3b3068e4 +678, 0x20d6ae7d +679, 0x7855dafd +680, 0x9ebd14ed +681, 0xc5934a1c +682, 0xb3c421a1 +683, 0xa2b709a2 +684, 0x91fa8b34 +685, 0x9009a54 +686, 0xb2c4215f +687, 0x7b294eb1 +688, 0x1802911e +689, 0xa2067de5 +690, 0x5ebd85e9 +691, 0xc4f8e698 +692, 0xd143d368 +693, 0x2ca2b6fb +694, 0xb5d27ebc +695, 0x410146ca +696, 0x9d6948fe +697, 0xfafd0af5 +698, 0x290e9c5f +699, 0x2ff06292 +700, 0x417903d5 +701, 0xc51af07c +702, 0xd2bbaf6b +703, 0xfa3720f1 +704, 0x4a6eb52d +705, 0xed86ad3c +706, 0x72a8676e +707, 0xc3c2bbed +708, 0x62b6a951 +709, 0xe08f9534 +710, 0xe2686ea5 +711, 0x3dbbf99b +712, 0xfec5319f +713, 0xef9c67eb +714, 0x9d69d19b +715, 0xc732ed2 +716, 0xc6e829bd +717, 0xe712e882 +718, 0xd24594ca +719, 0x102b8426 +720, 0xa5145730 +721, 0x62fecd71 +722, 0xe6439ca2 +723, 0x58819419 +724, 0xef722791 +725, 0x5ef6ab17 +726, 0x85ce3714 +727, 0xd4e18303 +728, 0xf91eb9c2 +729, 0x86bae692 +730, 0x6d81c21c +731, 0xd9985982 +732, 0xfdd55f22 +733, 0x72ecd91a +734, 0x4b1cee6 +735, 0xefa672ec +736, 0x3f18114f +737, 0xacae5e62 +738, 0x68369afd +739, 0xff5e6612 +740, 0x3760af8c +741, 0xd8c878bf +742, 0x3945fe59 +743, 0x2cf7f99a +744, 0x2cc59bb4 +745, 0xbba95cd6 +746, 0x6511688d +747, 0xcf326178 +748, 0xf850cc68 +749, 0x4bd2540e +750, 0xa02cf5e5 +751, 0x5546fcb5 +752, 0xe2b289fd +753, 0x960c6ba +754, 0x3a2c9d74 +755, 0x2def7a8f +756, 0x54e57d43 +757, 0xf953c277 +758, 0xd9b414b1 +759, 0x19a25920 +760, 0xaf2691a1 +761, 0x81e88159 +762, 0x49a3eab +763, 0x276a797d +764, 0x98337885 +765, 0x37055fd0 +766, 0x6927effc +767, 0xb6de7fc0 +768, 0x9e920f9a +769, 0xd2dc9145 +770, 0xe2861109 +771, 0xe42e2c1e +772, 0x836fe968 +773, 0x23452a15 +774, 0xd49f0e2b +775, 0x2998f647 +776, 0x94f8c803 +777, 0xf8be479e +778, 0xfd44079f +779, 0x685ab9c1 +780, 0xea8eeab3 +781, 0x580ff5d8 +782, 0x88ad0666 +783, 0x19df5d86 +784, 0xe4862012 +785, 0x3ad25460 +786, 0x677449ce +787, 0x1c7e0b9a +788, 0x287a98d0 +789, 0xed39d094 +790, 0x40501707 +791, 0xb99073a4 +792, 0x31847bd4 +793, 0x91e5b7 +794, 0x46815e56 +795, 0xc823384c +796, 0xdb6fb24 +797, 0xabe50dd8 +798, 0x2a33797b +799, 0x4fb617ec +800, 0x811a36df +801, 0xb6b7a25f +802, 0x8962cd0a +803, 0xc40818fe +804, 0x5dbe4e57 +805, 0x591f6c61 +806, 0x22aa4809 +807, 0xc0e4a72 +808, 0xa8a0e2e7 +809, 0xf91d553a +810, 0x77674da7 +811, 0x196657d6 +812, 0x5ae38c0f +813, 0x8bcf1ed2 +814, 0x9e0a2c8f +815, 0xf94e5215 +816, 0x11299b2b +817, 0xc499eca3 +818, 0x25e58d1b +819, 0xdd722954 +820, 0x816f4c21 +821, 0x2504fd9b +822, 0x722a597a +823, 0x92f80aab +824, 0xe2d7e54d +825, 0xefb26dba +826, 0x9ebf8863 +827, 0xd297ec21 +828, 0xa0ebfbb5 +829, 0xec609873 +830, 0xd079b3d1 +831, 0x920f722d +832, 0xfd58146 +833, 0x5fbb5784 +834, 0x30187f5d +835, 0x887f4ec6 +836, 0x6839a2ed +837, 0x72bccd98 +838, 0x7565903e +839, 0x8d3afaef +840, 0xfb713a03 +841, 0x34216b35 +842, 0xbe0da7e9 +843, 0x4b11764e +844, 0x6666922a +845, 0x3f2dc90d +846, 0xeca8fb8d +847, 0x91579404 +848, 0x8d413df7 +849, 0x2a0f8307 +850, 0x39d5a495 +851, 0x79ba5e62 +852, 0xbb06fd0f +853, 0x47ba4208 +854, 0x4a2efb9c +855, 0xee3a07f0 +856, 0x291a73e0 +857, 0xe42a46c5 +858, 0x203455b2 +859, 0x40545253 +860, 0xa618bb0a +861, 0xd4792a15 +862, 0xd6e62559 +863, 0x8149e2f0 +864, 0x5f6499a9 +865, 0xa63fc585 +866, 0xe33e1c1f +867, 0x36ecb45b +868, 0x267883ca +869, 0x905d98fb +870, 0xfac3512c +871, 0x374d0a0e +872, 0x9920f3e0 +873, 0xfb961c9f +874, 0x70f2d752 +875, 0x69c44d12 +876, 0xcb6075d2 +877, 0xaf802ac8 +878, 0x2c4b792b +879, 0xa2203217 +880, 0xc2c15619 +881, 0xb13af213 +882, 0x759b165c +883, 0x411ecdf2 +884, 0x158e5fba +885, 0x70874450 +886, 0x226a484f +887, 0x87b95ecf +888, 0x45cef22f +889, 0xfaf186bd +890, 0x3544972a +891, 0xb4a2f73 +892, 0x5f5d10de +893, 0xf3d05e29 +894, 0x7616ba85 +895, 0x4d2e198 +896, 0x1f240293 +897, 0x317c2286 +898, 0x3bd97e7b +899, 0xd7e39d6f +900, 0x142ee43c +901, 0x688ada72 +902, 0xad8deac8 +903, 0xf7cc8d5e +904, 0xa84600f5 +905, 0xda6b1b3 +906, 0x5bad09de +907, 0x6f4276c7 +908, 0xa789933f +909, 0xede4329a +910, 0xa31f2df5 +911, 0x869c0c3c +912, 0x6658f5b +913, 0xdb451b7c +914, 0x16ec0b18 +915, 0x2e35872c +916, 0xf7bf3c44 +917, 0xda59c872 +918, 0x1ab63c0c +919, 0x9a361a82 +920, 0xd2e1afcc +921, 0x5c41ac55 +922, 0xd1d761db +923, 0x3639bb85 +924, 0x7a418cfb +925, 0xf0b06b8f +926, 0xa2ef4d47 +927, 0x4fac4d1b +928, 0x47e42283 +929, 0x6ee6a7df +930, 0xfe786975 +931, 0x4475b665 +932, 0xd881e311 +933, 0x6b02224 +934, 0xcba19b84 +935, 0x4efa35f6 +936, 0x3873a72d +937, 0x984d7964 +938, 0xe23cda62 +939, 0xea9949d2 +940, 0x243b83b1 +941, 0x48d1bcc4 +942, 0xe35b6a23 +943, 0x125288f1 +944, 0x72fdd401 +945, 0xa2af6873 +946, 0x7c211096 +947, 0xa00a13dd +948, 0x7b4ce5d6 +949, 0x1e4be120 +950, 0xc771cc00 +951, 0x343ae31 +952, 0xe8e0be50 +953, 0xd9095a3f +954, 0x616b7c17 +955, 0xa96e1580 +956, 0x60501426 +957, 0xeaac50b +958, 0x130c33b5 +959, 0xba30925b +960, 0xf942c440 +961, 0xc52e8e20 +962, 0x5f460318 +963, 0x94e1dadd +964, 0xdfa4f20e +965, 0xc9bbd26a +966, 0x75322ecb +967, 0x3dc3ff18 +968, 0xfa896826 +969, 0xe4ad213c +970, 0x7a0f97c3 +971, 0xd7b7b08f +972, 0x6ebcab4e +973, 0x1a37d816 +974, 0x16299fee +975, 0x89d94a3a +976, 0x11c2f073 +977, 0x4ef27a32 +978, 0xaaf42781 +979, 0x9862c844 +980, 0xaa672e94 +981, 0xba4f2690 +982, 0x1f767d21 +983, 0x157e1a5e +984, 0x5b6de343 +985, 0xc494501e +986, 0xe97b507b +987, 0x98cae4c8 +988, 0xc4a6b036 +989, 0x746f8686 +990, 0xe761c86 +991, 0xefdaaa15 +992, 0xb907b816 +993, 0xe9d05992 +994, 0xed2e1b0e +995, 0xe129d3ee +996, 0xb41bb95f +997, 0xaec36181 +998, 0xdcdcf5f0 +999, 0xf175572a diff --git a/_randomgen/core_prng/tests/data/pcg32-testset-2.csv b/_randomgen/core_prng/tests/data/pcg32-testset-2.csv new file mode 100644 index 000000000000..2d4c8aed1312 --- /dev/null +++ b/_randomgen/core_prng/tests/data/pcg32-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0xe4c14788 +1, 0x379c6516 +2, 0x5c4ab3bb +3, 0x601d23e0 +4, 0x1c382b8c +5, 0xd1faab16 +6, 0x67680a2d +7, 0x92014a6e +8, 0x628ae389 +9, 0xa794034d +10, 0x5cc38cd9 +11, 0xfc913a3b +12, 0x81c851dc +13, 0x90c820e4 +14, 0x60dfa703 +15, 0xd613ae14 +16, 0x38ea1699 +17, 0x51f04d1b +18, 0xc4ef01a1 +19, 0x321eec02 +20, 0x4c37a737 +21, 0x6bfd1aa8 +22, 0x71a28325 +23, 0x4656d6e9 +24, 0x17509653 +25, 0x830bd521 +26, 0x6d35e3aa +27, 0x4ab85020 +28, 0x21c1da2c +29, 0x6a6057a2 +30, 0xf3a90dc1 +31, 0xa1cbdcd9 +32, 0xf70b61bf +33, 0x3b2b09a8 +34, 0xbc2ef54d +35, 0xce07f38f +36, 0xb51bc60b +37, 0x729efb83 +38, 0x7e4a5f66 +39, 0xdd824ead +40, 0x9be85945 +41, 0x57f8779c +42, 0xdb449e87 +43, 0xc0be253f +44, 0x18b4267e +45, 0xff78821 +46, 0xb53e3425 +47, 0x4550b21b +48, 0xefe89a4c +49, 0x74c130b9 +50, 0x1656a3a0 +51, 0x194da2a6 +52, 0x1a6cdb1d +53, 0x7c1fd58e +54, 0x3162d1e9 +55, 0x3e2f2c7d +56, 0xb0ab9b5c +57, 0x79156d4d +58, 0x97b85150 +59, 0x967a02ce +60, 0x1e64548d +61, 0x4196d24a +62, 0xd047eef5 +63, 0x8451cc3c +64, 0x7227eb94 +65, 0xb1191064 +66, 0x82e162d0 +67, 0xb473f07d +68, 0x92ea0426 +69, 0xbf2a25fa +70, 0x9935be52 +71, 0x28baec93 +72, 0xa29368b5 +73, 0xe3d6d97d +74, 0x85ecf1d4 +75, 0x482e4bc8 +76, 0xe4f22219 +77, 0x7531047 +78, 0x3c41ef1f +79, 0x19db5112 +80, 0xc1534caf +81, 0x6c45710a +82, 0xb323c369 +83, 0x2dac53c6 +84, 0xd5dc48b4 +85, 0x1dc6d7a1 +86, 0x3ae2bc10 +87, 0x6a7635e8 +88, 0xdeee7b7f +89, 0xcb705cd3 +90, 0xba11e537 +91, 0xb64a4936 +92, 0xff4b245e +93, 0x39cb1219 +94, 0x64833e10 +95, 0x76b0f975 +96, 0x333d7c7d +97, 0x88ccfb17 +98, 0xad78dace +99, 0xd82fb71 +100, 0x1595d411 +101, 0x47f9d57a +102, 0xd4dad6cb +103, 0x78bf16bd +104, 0x71b053d2 +105, 0xa4bb076e +106, 0xd7c57664 +107, 0x3fbcbf8f +108, 0xc816befc +109, 0x6df46890 +110, 0xd16f271f +111, 0xeeeb1571 +112, 0x58222e89 +113, 0xa55e81d3 +114, 0xafbe7622 +115, 0x938475a8 +116, 0xd8740af2 +117, 0xf937dbd7 +118, 0x7d3940fa +119, 0x694c55f2 +120, 0x2261fb68 +121, 0x6ce39e94 +122, 0xab43634 +123, 0xd92ff7c4 +124, 0xe8db22d +125, 0x52e250b1 +126, 0xaf0f7029 +127, 0xc23dd3a +128, 0xd66dc2b9 +129, 0xea7f01f3 +130, 0x4df54b3f +131, 0xf1eff09c +132, 0x2813663e +133, 0x21ae8115 +134, 0xb00d790d +135, 0x11e6adbb +136, 0x61005f4c +137, 0x3de17bf0 +138, 0x7b2050b9 +139, 0xe20dd275 +140, 0xafa0bdcc +141, 0x9c6d4c6c +142, 0xe938606 +143, 0x8eecdd8f +144, 0xea9a90a9 +145, 0x99cbb123 +146, 0x16fccad1 +147, 0x7e81fdd9 +148, 0x116e6abd +149, 0xdeb9ff4e +150, 0xc589f525 +151, 0x57d701a9 +152, 0xcf05e950 +153, 0x533a2839 +154, 0x12d592e7 +155, 0xae61f43f +156, 0x419ae221 +157, 0x81126e0a +158, 0xc3988c97 +159, 0xb3262eaa +160, 0x3baddf9e +161, 0xf19d8a16 +162, 0x2a8b130f +163, 0xe4c9ccea +164, 0xf5ae2ea +165, 0x75aaa98d +166, 0xdd45ce49 +167, 0x98e0d4f6 +168, 0xb1ec10a1 +169, 0xc9592952 +170, 0x23bb1f45 +171, 0xd0827b45 +172, 0x7a79b800 +173, 0x9d1b8348 +174, 0xe2958863 +175, 0x5143e17e +176, 0x44110af9 +177, 0x49d76858 +178, 0xdba4688e +179, 0x4e4d61dd +180, 0x729b81cc +181, 0xf3576e03 +182, 0x9b028e9d +183, 0x68d8d869 +184, 0xda15e018 +185, 0x5384abb2 +186, 0x1027ed5e +187, 0xaf5401f1 +188, 0x31411375 +189, 0xc75d87be +190, 0xad73f5fd +191, 0xadb3add7 +192, 0x4d5452ee +193, 0xdef42029 +194, 0x89d58a78 +195, 0x464d6b4a +196, 0xd01f533a +197, 0xb9533dd4 +198, 0x55c5d023 +199, 0x3dcf8fef +200, 0x198395ca +201, 0x7cdca51c +202, 0x6f4074f +203, 0xb9f79995 +204, 0xbbe3d9a5 +205, 0x520d417e +206, 0x9a8df0bd +207, 0xe390f486 +208, 0x5b578b3f +209, 0xb4cdf767 +210, 0x12d45034 +211, 0xe661e293 +212, 0x70cd3e91 +213, 0xdbc7f190 +214, 0x49829849 +215, 0x12017fbe +216, 0x1e35bf48 +217, 0x1effc3c7 +218, 0xe1f574cb +219, 0xf613ab7d +220, 0xd09d16fa +221, 0xa58bcf5a +222, 0xac39afdc +223, 0xd611d1ab +224, 0x36edd3b2 +225, 0xd9ea5d98 +226, 0xf6f2fce4 +227, 0x42cb31ce +228, 0xdd1f6530 +229, 0x3e43a7d0 +230, 0x175ec7fc +231, 0x8077af4b +232, 0x37cbcc22 +233, 0x26a89f +234, 0x998c930e +235, 0xb84e5f21 +236, 0x83817130 +237, 0x2ad05d66 +238, 0x48f3b861 +239, 0xd69f626 +240, 0x1d09f12 +241, 0xf207e7f0 +242, 0xcc709acc +243, 0x1b2881d7 +244, 0x7e18cc6c +245, 0xbfd9589c +246, 0xce0d301e +247, 0xc8668b4b +248, 0x584482bd +249, 0x722e14ae +250, 0xd79dfcff +251, 0xcc7e9c21 +252, 0xd081f540 +253, 0x3b49f7fa +254, 0xf23efb2a +255, 0xfd7fe8f8 +256, 0x9abcbf25 +257, 0x5b713674 +258, 0x1300e351 +259, 0xe884f0ad +260, 0x3c290461 +261, 0x4f64c1a1 +262, 0x17c55223 +263, 0xd5953a5f +264, 0xd85e042e +265, 0x75dfc597 +266, 0x379edfb +267, 0x75ebddc9 +268, 0xc19b98e1 +269, 0x1dd1b751 +270, 0xc5760a60 +271, 0x5f6e2f17 +272, 0x29e8610e +273, 0xb2edd7db +274, 0x9233eeca +275, 0xbc02b187 +276, 0xc997bb5b +277, 0x88ad3a98 +278, 0x3d1167ad +279, 0xcea54c9c +280, 0x7ea493eb +281, 0x586e3aa8 +282, 0xe2e027c7 +283, 0xae50ef9e +284, 0xd32e0c38 +285, 0xeba0edf6 +286, 0x980ad22a +287, 0x3b14e644 +288, 0xd7bfbff8 +289, 0xe0af1647 +290, 0x292d72dd +291, 0xb8c421bb +292, 0x114d690e +293, 0x85a86bd +294, 0x39f2b5e2 +295, 0x7c9c6b43 +296, 0xca387767 +297, 0x84f24ecf +298, 0x2aec5804 +299, 0x27d0f2 +300, 0xcd7bb6a9 +301, 0xe925969f +302, 0xc6454099 +303, 0xf7435a9d +304, 0xf7bc998f +305, 0xfa81f361 +306, 0xcba07d00 +307, 0x3e8a8a14 +308, 0xf0e7f785 +309, 0x25aecff +310, 0xe1a90226 +311, 0x4af1339d +312, 0x983f4fb9 +313, 0xbaec847f +314, 0x4e504dbb +315, 0xe7d0be86 +316, 0x73cb80ef +317, 0x336db698 +318, 0x8bf7de05 +319, 0x36e4e6ba +320, 0x47a8239b +321, 0x2a98e1d0 +322, 0x64a6c087 +323, 0x4a8591cb +324, 0x642d5d67 +325, 0x9f4b84b2 +326, 0x6bdf1176 +327, 0x7e2b1639 +328, 0xc90453f5 +329, 0xe72d0b96 +330, 0x5f0e1d0c +331, 0x156af798 +332, 0x6124d8e8 +333, 0xaa2f2ad7 +334, 0x145b30b7 +335, 0xd6582106 +336, 0x203abbad +337, 0x929d8d43 +338, 0x14d5b6dc +339, 0xef0f4eb2 +340, 0x8ff54463 +341, 0x588113a +342, 0x1bc43ba6 +343, 0x44f44097 +344, 0xb84cfdc6 +345, 0x3ee638af +346, 0xdd169321 +347, 0xaaac5f56 +348, 0xbb022bc2 +349, 0xf9ef8bde +350, 0x2829b2fb +351, 0x563368fa +352, 0x82ce66ae +353, 0x6d820e38 +354, 0xb87a080e +355, 0x756469af +356, 0x78086990 +357, 0xa220e762 +358, 0x14ba6bdb +359, 0xfa775c1b +360, 0x65fa7396 +361, 0xbae24370 +362, 0x8e42ddb8 +363, 0x1f46b8ac +364, 0x3c9236c5 +365, 0xd3a2184c +366, 0x308ba74 +367, 0x5638eb84 +368, 0x64076fe6 +369, 0x37fe334f +370, 0x8de24732 +371, 0xf0d0b02b +372, 0x18492b71 +373, 0x848f38ac +374, 0x9b46dc75 +375, 0xf5d3c06a +376, 0x203afe47 +377, 0x19857724 +378, 0x38033528 +379, 0xf7fa640c +380, 0xf1cb86e8 +381, 0x1fcd5b99 +382, 0xb07f1023 +383, 0x3bb9ab75 +384, 0x57f54e78 +385, 0xf5b51d4b +386, 0xe94eba44 +387, 0xa5a39292 +388, 0x50803af +389, 0x34ea9cc5 +390, 0xabf621ca +391, 0xb275f802 +392, 0xf46dffd6 +393, 0xd33e27d1 +394, 0xca9a56e +395, 0x6eda85a4 +396, 0x639b78ba +397, 0x799d1980 +398, 0xf3c09bf1 +399, 0x6d4cdbe +400, 0x112dae8d +401, 0xd97414b1 +402, 0x9499df3d +403, 0xa58ece6c +404, 0xe56bf91b +405, 0x3bdbfd9 +406, 0x91aae1fd +407, 0xec1fce54 +408, 0x60e0eced +409, 0x278d5b22 +410, 0xdee29da2 +411, 0xf1f55d27 +412, 0xd532ab83 +413, 0xb0fe9589 +414, 0x88fcc255 +415, 0xf524359b +416, 0x7270a00b +417, 0x42489eaf +418, 0xc020d6bb +419, 0xf9ed0f78 +420, 0x4bc5cdec +421, 0x55061393 +422, 0x6b84a5a4 +423, 0x826c0471 +424, 0x9e69e30d +425, 0x9dfd9b15 +426, 0xf4014c40 +427, 0xcd04ef4d +428, 0x7376c02c +429, 0xb15a9e3c +430, 0xf76c1fa9 +431, 0xcd51bdd8 +432, 0x99f2859e +433, 0xb62c6a4d +434, 0x52239d8b +435, 0x27fa2869 +436, 0x6dba918c +437, 0x9891e444 +438, 0x71e29f5 +439, 0xa9cd3ac9 +440, 0xf6ec3b80 +441, 0x8c8d3226 +442, 0x7c528725 +443, 0xd543932b +444, 0xf76b3e02 +445, 0xeccaf183 +446, 0x8f757854 +447, 0x785edb62 +448, 0x54397da0 +449, 0xe1fe0557 +450, 0x7a79d418 +451, 0xd2740507 +452, 0xc3561bc7 +453, 0xef7c3f18 +454, 0xecf8effe +455, 0xc7a073ad +456, 0xeb5ea9fd +457, 0x33dade18 +458, 0x89d0e41c +459, 0x7720d298 +460, 0xe912f029 +461, 0x7794462 +462, 0xa436dcf6 +463, 0x55cbb318 +464, 0x7b4a78e0 +465, 0xa8ce0afb +466, 0x7e18bb28 +467, 0x92c4f8f6 +468, 0x6828052c +469, 0xbf619f8 +470, 0x272d1d15 +471, 0xb34e2e52 +472, 0x52158f7f +473, 0x682fb062 +474, 0x52e80435 +475, 0x787e0fb3 +476, 0xe331da39 +477, 0xfad42e58 +478, 0x1bdb3f90 +479, 0xe313ab2 +480, 0xe61af9bb +481, 0x46f03903 +482, 0x926b3d33 +483, 0x2b23ce3b +484, 0xed04d4af +485, 0x34c49faf +486, 0x142f503c +487, 0x47cf6a21 +488, 0x5352250c +489, 0xf5942210 +490, 0xca5950ae +491, 0xc5302422 +492, 0x41a5e9b1 +493, 0x30076390 +494, 0x8951d0e4 +495, 0xebe74e22 +496, 0xfcb7dbf8 +497, 0xd55076e7 +498, 0x88a1165b +499, 0x1a89b5a3 +500, 0xda2c3e2e +501, 0xdc1d606d +502, 0xfda0315c +503, 0x5f5610dd +504, 0x3eba316c +505, 0x72cae07b +506, 0x5336095 +507, 0x6a110322 +508, 0x46cb153b +509, 0xa2b11116 +510, 0xe2543988 +511, 0x51f53bae +512, 0x3b10466d +513, 0x189ddd56 +514, 0x1fd355b6 +515, 0x1230e8d3 +516, 0x2050d313 +517, 0x2fbb5c16 +518, 0x64b03f4f +519, 0xbd6cdc1a +520, 0x9d423316 +521, 0xc71a702f +522, 0xf2254f39 +523, 0xd953728b +524, 0xef3c8bb5 +525, 0x685a2fab +526, 0xcea73dff +527, 0x4a7fa029 +528, 0xa27e8058 +529, 0x561a1413 +530, 0x570fc5bc +531, 0x917e93ee +532, 0x15fdbb15 +533, 0xabee295e +534, 0xc40f5307 +535, 0xba18b087 +536, 0x6ea6e339 +537, 0x7e282248 +538, 0x875062c2 +539, 0xd1520c30 +540, 0xb4cef1a5 +541, 0x55812dd1 +542, 0x9c67743c +543, 0x22fd5992 +544, 0x1dacbfa +545, 0x5b35eab1 +546, 0xfa8c9316 +547, 0x490bc71c +548, 0xe5129bfb +549, 0xe7acb79f +550, 0x87667765 +551, 0x945be067 +552, 0x8acf5c32 +553, 0x466e0ee +554, 0x8fa89be0 +555, 0x4eb4afcc +556, 0x3302055b +557, 0x8f2e3ab9 +558, 0xc5bc175e +559, 0x903a3e85 +560, 0x4055dd04 +561, 0x37873bac +562, 0x2965a951 +563, 0x2206c56a +564, 0xf34dc2db +565, 0x34e43ba2 +566, 0xb61caa44 +567, 0xfd3eb260 +568, 0x9dcdc817 +569, 0x7019df83 +570, 0x6fcd9bea +571, 0x270cba0a +572, 0xd6cc3241 +573, 0x6345c906 +574, 0xd213fb94 +575, 0x6195e5b5 +576, 0x804abab7 +577, 0xb4cace45 +578, 0xded19bbc +579, 0x617db00c +580, 0xafb933d6 +581, 0x8192cae8 +582, 0x45ffd8af +583, 0x13ae0868 +584, 0x840f4541 +585, 0x12cd1a05 +586, 0xbb5b7d6d +587, 0x3907ab3 +588, 0xd77a1582 +589, 0x4e741292 +590, 0x28c60865 +591, 0xbaad11e2 +592, 0xa9d3e364 +593, 0x88a197cb +594, 0xe90f021f +595, 0x2056017a +596, 0xeb0a2fd9 +597, 0x1d3435aa +598, 0xdaa0b802 +599, 0x8121bf09 +600, 0x95a88f55 +601, 0xa8b9c257 +602, 0xb0ab4914 +603, 0xf360b741 +604, 0x5563d4ab +605, 0xad33cf0e +606, 0x397d315a +607, 0x6893767f +608, 0x79dd5b31 +609, 0xa9ea6777 +610, 0xcf48c06 +611, 0xb4cceafc +612, 0xf53cab50 +613, 0x72426c8 +614, 0xd128aa5a +615, 0x511eec88 +616, 0x668ab20a +617, 0xb9b53dbe +618, 0x3b03a0fb +619, 0x8f416a98 +620, 0xaa15b7f6 +621, 0xc7767aba +622, 0xa64d3342 +623, 0x42cf1388 +624, 0xfc3ee7c0 +625, 0x892a2902 +626, 0xdb054bf6 +627, 0x4973223f +628, 0xb9f74682 +629, 0x72f2ece +630, 0xddf94382 +631, 0x67581d86 +632, 0x9cb9cd6f +633, 0xed74731a +634, 0xcca05451 +635, 0x3b21fdc0 +636, 0x9e18e52b +637, 0xa40bb287 +638, 0x8bb05e07 +639, 0xa33555fe +640, 0x4c819ed +641, 0x5373903e +642, 0x611403c2 +643, 0x133e25fb +644, 0x9c7a44e4 +645, 0x67197b8d +646, 0xfa910436 +647, 0xa86a825d +648, 0xfc9b24c1 +649, 0x464a718e +650, 0x7421bc26 +651, 0x3c3186b7 +652, 0xf7304619 +653, 0x7ac7be81 +654, 0xae6adcc4 +655, 0xca96bf8c +656, 0x49711d50 +657, 0x74c51f0 +658, 0x275804c0 +659, 0x228098c5 +660, 0x73a31b94 +661, 0x7f01db79 +662, 0xb36209c8 +663, 0x6ccf8677 +664, 0x70dbcce0 +665, 0xa533d8cd +666, 0xd0b0f097 +667, 0xd9a3b784 +668, 0x80a929fc +669, 0x9708f29a +670, 0x95e1e56f +671, 0xd07a0b45 +672, 0x566acdb6 +673, 0x92663054 +674, 0x3667dc9a +675, 0x80f850ff +676, 0x549dd640 +677, 0xc3ff18ca +678, 0x8c70d392 +679, 0xf5547e3b +680, 0x8dbee1d7 +681, 0x51fe33b8 +682, 0xb1ea480b +683, 0x6646f6d0 +684, 0x4a8e7de9 +685, 0xcb053e32 +686, 0x6311aee8 +687, 0xcc2a411b +688, 0x5330e60b +689, 0x4680e825 +690, 0x96bdd8a2 +691, 0x8cf4268a +692, 0x8445c833 +693, 0xc237eef1 +694, 0x459670e8 +695, 0xedf26624 +696, 0x5713340f +697, 0x5a3e87a3 +698, 0xa24a7c2d +699, 0xfa9fdceb +700, 0x746fd14e +701, 0xc6aef3e5 +702, 0x3d957e9b +703, 0xc1926f7a +704, 0xee717768 +705, 0x101fe323 +706, 0xec0d63ab +707, 0x8b8e6f42 +708, 0x8c3d2286 +709, 0xb573dd68 +710, 0x53b68ec0 +711, 0x696525cf +712, 0xdab65d8e +713, 0xd2c6ed42 +714, 0xa1fc10f6 +715, 0x1554666 +716, 0x6ed42947 +717, 0x87f7e62 +718, 0xaf34733b +719, 0xc55baa8b +720, 0xcbff66f +721, 0x2516c228 +722, 0xec6980fb +723, 0x4f53d66c +724, 0x1be17a32 +725, 0xdcfb31df +726, 0x4b17d04f +727, 0x81e1f54b +728, 0x749eae52 +729, 0x3811c4d5 +730, 0x5d11e6a1 +731, 0x535d5d6c +732, 0xbb74cd20 +733, 0xd1b18b71 +734, 0xfbf7221a +735, 0x817c4279 +736, 0xcef30b85 +737, 0x41dee06c +738, 0x9d340a3a +739, 0x691f0449 +740, 0x363a515d +741, 0x73a1af6c +742, 0x25718271 +743, 0xb4a52d50 +744, 0x1e392f40 +745, 0x3c811345 +746, 0xc9aa8565 +747, 0x357c24e0 +748, 0x19ad7230 +749, 0xed250e20 +750, 0x4acc4824 +751, 0x825d53a +752, 0xcf2f515f +753, 0xb7973ff4 +754, 0xb03ce53f +755, 0x1afad500 +756, 0x39f64ee8 +757, 0x60bea483 +758, 0xedf16817 +759, 0x88beff73 +760, 0x4909868 +761, 0x879a96da +762, 0x52d4ac6b +763, 0x46fabe65 +764, 0x88fa5751 +765, 0x71df4521 +766, 0xfc6eb286 +767, 0xf83e78ad +768, 0x885e5aca +769, 0x77e63e4a +770, 0x2bdf5c02 +771, 0x2528323c +772, 0x5b5d1ce9 +773, 0xf795be8c +774, 0x5e113b2b +775, 0xa993c7aa +776, 0xe5f8560a +777, 0x77e1e8d +778, 0x5e9db88a +779, 0xdac4e96b +780, 0x9126b945 +781, 0x15bf293a +782, 0x1dc9a8f4 +783, 0x909b48b1 +784, 0xb50ce29e +785, 0x21671c87 +786, 0xcda80dec +787, 0xf5aff1a9 +788, 0xd70cdb2e +789, 0xd293139a +790, 0xcbf4f51d +791, 0xb23c6d7a +792, 0x1a06aa33 +793, 0x21880210 +794, 0x92679678 +795, 0x8d5bb26b +796, 0x23304100 +797, 0x8f5d1df4 +798, 0x143b39ff +799, 0x29e97d16 +800, 0xbfad952f +801, 0x257ca1d8 +802, 0x32ad2f8f +803, 0x84d320c3 +804, 0xcc4c59a +805, 0xbb5ae046 +806, 0x3d5fcf1d +807, 0xa0130b0 +808, 0xad86e9de +809, 0x1e422521 +810, 0x6b56a617 +811, 0xbe64d9fc +812, 0xfff31ed0 +813, 0xd1ad616e +814, 0x13486a20 +815, 0x1754613b +816, 0x52c7b9da +817, 0xc05d75aa +818, 0xd719cd98 +819, 0x61890574 +820, 0xc4711a8b +821, 0x9afd5635 +822, 0x4dabed21 +823, 0x94f173 +824, 0xb8b6e708 +825, 0x1d590111 +826, 0x60315dfd +827, 0x7fb8ae79 +828, 0xc69f4f2b +829, 0xcaf1c898 +830, 0x861a0c8b +831, 0x6ed14eaa +832, 0xc77da58 +833, 0x8fd4f29a +834, 0xa38187fb +835, 0x6ed1ee88 +836, 0xf1a9f55a +837, 0x74368cc8 +838, 0xf327e944 +839, 0x97a578af +840, 0x8a5345e5 +841, 0x63ee0a30 +842, 0xa7e4919b +843, 0x51e26930 +844, 0x38dbe017 +845, 0xedace3a9 +846, 0x9cda2ad4 +847, 0x96b1119 +848, 0xff56282a +849, 0x71773edf +850, 0xe41fb69c +851, 0xe7bce539 +852, 0x221ffeed +853, 0x35d3f67f +854, 0x7e089168 +855, 0x6fd47823 +856, 0x43bfb28d +857, 0x9ce49e62 +858, 0xde32120 +859, 0x6eacfe4e +860, 0x116c6128 +861, 0x5f975284 +862, 0xc547361c +863, 0xf48e8251 +864, 0x2ac8a3bd +865, 0x9a0fce5b +866, 0x1764e3d9 +867, 0xa31e6954 +868, 0xb9dca055 +869, 0x1cd35c79 +870, 0x1b502882 +871, 0xf973ab10 +872, 0x8b585146 +873, 0x841fd3f8 +874, 0x4999200f +875, 0x7ad10c4b +876, 0xcf1695bd +877, 0x26c58bc3 +878, 0xdc1f8310 +879, 0x546e1e86 +880, 0x2e39fec8 +881, 0x8c65e2ed +882, 0x6469bac +883, 0xbc4af1ff +884, 0xa1669010 +885, 0x41dabd80 +886, 0x5797e218 +887, 0x9bed24c1 +888, 0xa7552347 +889, 0x4e214099 +890, 0x34d4f986 +891, 0x316cc527 +892, 0xde30c21c +893, 0x4f273c1e +894, 0xc3dd9324 +895, 0xe61fda1c +896, 0x1d0f8076 +897, 0x5570867e +898, 0x289d6062 +899, 0x465b8b26 +900, 0xb72307de +901, 0xe78c8647 +902, 0xfee9723e +903, 0xa1534c9b +904, 0x4d652645 +905, 0xe623b6c2 +906, 0x454cfc8 +907, 0xc5a7fcaf +908, 0x1de804d9 +909, 0xa2501de7 +910, 0xe036c091 +911, 0xa4a55d1d +912, 0x50409892 +913, 0x58fd2731 +914, 0xb6fd3618 +915, 0xa0180bd2 +916, 0xd9bb2fe8 +917, 0x7c8e7a2c +918, 0xd90906fc +919, 0xf8721260 +920, 0x451b372d +921, 0xeeb1c70 +922, 0xc1a18778 +923, 0xd466244a +924, 0x88e4b84a +925, 0x4fc3af63 +926, 0xcf4387e4 +927, 0xb8872734 +928, 0x276eadef +929, 0xd2c164a1 +930, 0xd3c812d9 +931, 0x5a94f176 +932, 0xfba6f632 +933, 0xf7aeba97 +934, 0x9207585f +935, 0x70a41d67 +936, 0xa0b70910 +937, 0xd579fc6b +938, 0xf06a8fca +939, 0x471fd406 +940, 0xb15a0491 +941, 0x2f340f7a +942, 0x3df02de3 +943, 0x6022f8d6 +944, 0xa15b11c2 +945, 0x45715dd6 +946, 0xf293d85e +947, 0x7a2100d +948, 0x7dff786e +949, 0x52c6a183 +950, 0x5fbce2db +951, 0xbc29ec65 +952, 0x3dd14b27 +953, 0x1bedecd1 +954, 0xbfcba31c +955, 0xb911a26d +956, 0x6b6de680 +957, 0x36e8769 +958, 0x908de4a0 +959, 0xe1abee1f +960, 0x83acd7f8 +961, 0x5008c1eb +962, 0xd8bc7a2b +963, 0x6f639c56 +964, 0xe1f2634b +965, 0x267222ec +966, 0x48fa416c +967, 0xfa01e3cb +968, 0x2d28a700 +969, 0x58dcdc97 +970, 0x685ac2e7 +971, 0x9318840b +972, 0x99247a55 +973, 0x8d749b83 +974, 0x403f8415 +975, 0x373eb9c6 +976, 0xb840b6a2 +977, 0x9bb7bfc4 +978, 0xd5800634 +979, 0x3ef4a02d +980, 0x2ffa791f +981, 0x8a671150 +982, 0x40fdfc5e +983, 0xfa4bd35e +984, 0xf4ca1642 +985, 0x17fb231a +986, 0x42a3e57c +987, 0x58cf119d +988, 0x32f19c67 +989, 0xf3e2e153 +990, 0x66fce6fb +991, 0x9d61059b +992, 0x1628eafb +993, 0x9a6cf683 +994, 0x5ff5df3a +995, 0x206fb3c9 +996, 0x1914913c +997, 0x58c002ad +998, 0xd099145f +999, 0x155aab4b diff --git a/_randomgen/core_prng/tests/test_direct.py b/_randomgen/core_prng/tests/test_direct.py index 61dafdcaa924..cada2d58d394 100644 --- a/_randomgen/core_prng/tests/test_direct.py +++ b/_randomgen/core_prng/tests/test_direct.py @@ -7,7 +7,7 @@ assert_raises from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG64, Philox, Xoroshiro128, Xorshift1024 + PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 if (sys.version_info > (3, 0)): long = int @@ -24,7 +24,7 @@ def uniform32_from_uint64(x): out = (joined >> np.uint32(9)) * (1.0 / 2 ** 23) return out.astype(np.float32) - + def uniform32_from_uint63(x): x = np.uint64(x) x = np.uint32(x >> np.uint64(32)) @@ -407,3 +407,14 @@ def setup_class(cls): cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) cls.data2 = cls._read_csv(join(pwd, './data/threefry32-testset-2.csv')) cls.seed_error_type = TypeError + + +class TestPCG32(TestPCG64): + @classmethod + def setup_class(cls): + cls.prng = PCG32 + cls.bits = 32 + cls.dtype = np.uint32 + cls.data1 = cls._read_csv(join(pwd, './data/pcg32-testset-1.csv')) + cls.data2 = cls._read_csv(join(pwd, './data/pcg32-testset-2.csv')) + cls.seed_error_type = TypeError diff --git a/_randomgen/core_prng/tests/test_smoke.py b/_randomgen/core_prng/tests/test_smoke.py index 929fd1e9f0ca..8e184bce1ac8 100644 --- a/_randomgen/core_prng/tests/test_smoke.py +++ b/_randomgen/core_prng/tests/test_smoke.py @@ -9,7 +9,7 @@ assert_array_equal from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG64, Philox, Xoroshiro128, Xorshift1024 + PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 from core_prng import entropy @@ -986,3 +986,16 @@ def test_fallback(self): time.sleep(0.1) e2 = entropy.random_entropy(source='fallback') assert_((e1 != e2)) + + +class TestPCG32(TestPCG64): + @classmethod + def setup_class(cls): + cls.prng = PCG32 + cls.advance = 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 + cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] + cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = None + cls._extra_setup() diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 0eb997c05d36..6508bde6473c 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -107,14 +107,22 @@ ), Extension("core_prng.pcg64", ["core_prng/pcg64.pyx", - join(MOD_DIR, 'src', 'pcg64', - 'pcg64.c')], + join(MOD_DIR, 'src', 'pcg64', 'pcg64.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'pcg64')], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("core_prng.pcg32", + ["core_prng/pcg32.pyx", + join(MOD_DIR, 'src', 'pcg32', 'pcg32.c')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join(MOD_DIR, 'src', + 'pcg32')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("core_prng.threefry", ["core_prng/threefry.pyx", join(MOD_DIR, 'src', 'threefry', 'threefry.c')], From e81e93fc279419e42ede2a0fae20c394d1cfde9b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 19:54:50 +0000 Subject: [PATCH 051/138] BUG: Fix variable declarations in dsfmt Fix order for VS2008 Improve repr --- _randomgen/core_prng/generator.pyx | 8 +++++++- _randomgen/core_prng/src/dsfmt/dSFMT.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index e5fd47ec4f6f..59a42b603f16 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -69,13 +69,19 @@ cdef class RandomGenerator: capsule = prng.capsule cdef const char *anon_name = "CorePRNG" if not PyCapsule_IsValid(capsule, anon_name): - raise ValueError("Invalid pointer to anon_func_state") + raise ValueError("Invalid prng. The prng must be instantized.") self._prng = PyCapsule_GetPointer(capsule, anon_name) self.lock = Lock() with self.lock: self._prng.has_gauss = 0 self._prng.has_gauss_f = 0 + def __repr__(self): + return self.__str__() + ' at 0x{:X}'.format(id(self)) + + def __str__(self): + return 'RandomGenerator(' + self.__core_prng.__class__.__name__ + ')' + # Pickling support: def __getstate__(self): return self.state diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/core_prng/src/dsfmt/dSFMT.h index 0ae8a016d871..224d0108fbf3 100644 --- a/_randomgen/core_prng/src/dsfmt/dSFMT.h +++ b/_randomgen/core_prng/src/dsfmt/dSFMT.h @@ -665,9 +665,9 @@ static inline double dsfmt_next_double(dsfmt_state *state) { static inline uint64_t dsfmt_next64(dsfmt_state *state) { /* Discard bottom 16 bits */ + uint64_t out; union random_val_t rv; rv.d = dsfmt_next_buffer(state); - uint64_t out; out = (rv.u64 >> 16) << 32; rv.d = dsfmt_next_buffer(state); out |= (rv.u64 >> 16) & 0xffffffff; From 76a31a93bdad583291035bedf72afcb41ba231f6 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 20:08:21 +0000 Subject: [PATCH 052/138] ENH: Enable testing on OSX --- _randomgen/.travis.yml | 44 ++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index e30030a4bb39..7da8cb80b1ab 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -10,38 +10,33 @@ language: python matrix: fast_finish: true include: - - env: - - PYTHON=2.7 - - NUMPY=1.10 - - CYTHON=0.24 - - env: - - PYTHON=3.5 - - NUMPY=1.11 - - env: - - PYTHON=3.6 - - NUMPY=1.13 - - CYTHON=0.25 - - env: - - PYTHON=3.6 - - NUMPY=1.13 - - CYTHON=0.26 - - env: - - PYTHON=3.6 + - os: linux + env: [PYTHON=2.7, NUMPY=1.10, CYTHON=0.24] + - os: linux + env: [PYTHON=3.5, NUMPY=1.11] + - os: linux + env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.25] + - os: linux + env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.26] + - os: linux + env: [PYTHON=3.6] + - os: osx + language: generic + env: [PYTHON=3.6] + before_install: - - if [ ${TRAVIS_OS_NAME} = "osx" ]; then wget https://repo.continuum.io/miniconda/Miniconda-latest-MacOSX-x86_64.sh -O miniconda.sh; fi - - if [ ${TRAVIS_OS_NAME} = "linux" ]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi + - if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda3.sh; fi + - if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi - chmod +x miniconda3.sh - ./miniconda3.sh -b - - export PATH=/home/travis/miniconda3/bin:$PATH + - export PATH=${HOME}/miniconda3/bin:$PATH - conda config --set always_yes true - # Disable until fixed - # - conda update --all --quiet + - conda update --all --quiet - PKGS="python=${PYTHON}" - PKGS="${PKGS} numpy"; if [ ${NUMPY} ]; then PKGS="${PKGS}=${NUMPY}"; fi - PKGS="${PKGS} Cython"; if [ ${CYTHON} ]; then PKGS="${PKGS}=${CYTHON}"; fi - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi - - export BUILD_DIR=$PWD - conda create -n core-prng-test ${PKGS} pytest setuptools nose --quiet - source activate core-prng-test - pip install tempita -q @@ -53,7 +48,6 @@ script: - set -e - pytest core_prng - | - if [ -z ${NUMPY} ]; then - cd ${BUILD_DIR} + if [[ -z ${NUMPY} ]]; then python benchmark.py; fi From a8882b22cf6652019dabf56ee12be5256be317bf Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 12 Mar 2018 22:45:12 +0000 Subject: [PATCH 053/138] CLN: Remove small bugs and alter variable size --- _randomgen/benchmark.py | 16 +++-- _randomgen/core_prng/generator.pyx | 10 +-- .../src/distributions/distributions.c | 65 ++++++++++--------- .../src/distributions/distributions.h | 3 +- _randomgen/core_prng/src/philox/philox.c | 2 +- _randomgen/core_prng/src/philox/philox.h | 8 ++- _randomgen/core_prng/src/threefry/threefry.c | 2 +- _randomgen/core_prng/src/threefry/threefry.h | 2 +- .../core_prng/src/threefry32/threefry32.c | 2 +- .../core_prng/src/threefry32/threefry32.h | 59 ++++++++++------- 10 files changed, 95 insertions(+), 74 deletions(-) diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 852773f2bd22..3b489781a3b8 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -119,9 +119,15 @@ def timer_normal_zig(): if __name__ == '__main__': - timer_raw() + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--full', dest='full', action='store_true') + args = parser.parse_args() + timer_uniform() - timer_32bit() - timer_64bit() - timer_normal() - timer_normal_zig() + if args.full: + timer_raw() + timer_32bit() + timer_64bit() + timer_normal() + timer_normal_zig() diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 59a42b603f16..72d357067047 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -1385,7 +1385,7 @@ cdef class RandomGenerator: cdef double *randoms_data cdef double fgamma_r, fgamma_i, frelation_r, frelation_i, frho, fvar_r , fvar_i, \ floc_r, floc_i, f_real, f_imag, i_r_scale, r_scale, i_scale, f_rho - cdef np.npy_intp i, j, n + cdef np.npy_intp i, j, n, n2 cdef np.broadcast it oloc = np.PyArray_FROM_OTF(loc, np.NPY_COMPLEX128, np.NPY_ALIGNED) @@ -1480,11 +1480,12 @@ cdef class RandomGenerator: it = np.PyArray_MultiIterNew5(randoms, oloc, v_real, v_imag, rho) with self.lock, nogil: + n2 = 2 * n # Avoid compiler noise for cast to long if method == u'zig': - for i in range( 2 * n): + for i in range(n2): randoms_data[i] = random_gauss_zig(self._prng) else: - for i in range( 2 * n): + for i in range(n2): randoms_data[i] = random_gauss(self._prng) with nogil: j = 0 @@ -3967,11 +3968,10 @@ cdef class RandomGenerator: array([100, 0]) """ - cdef np.npy_intp d + cdef np.npy_intp d, i, j, dn, sz cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" cdef double *pix cdef long *mnix - cdef np.npy_intp i, j, dn, sz cdef double Sum d = len(pvals) diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index fbdad8f2f669..070a2edfbb5b 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -2,30 +2,38 @@ #include "ziggurat.h" #include "ziggurat_constants.h" +/* Inline generators for internal use */ static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { return prng_state->next_uint32(prng_state->state); } -static NPY_INLINE float next_float(prng_t *prng_state) { +static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { + return prng_state->next_uint64(prng_state->state); +} + +static NPY_INLINE float random_float(prng_t *prng_state) { return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); } -static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { - return prng_state->next_uint64(prng_state->state); +static NPY_INLINE float random_double(prng_t *prng_state) { + return prng_state->next_double(prng_state->state); } -float random_sample_f(prng_t *prng_state) { return next_float(prng_state); } +/* Random generators for external use */ +float random_sample_f(prng_t *prng_state) { + return random_float(prng_state); +} double random_sample(prng_t *prng_state) { - return prng_state->next_double(prng_state->state); + return random_double(prng_state); } double random_standard_exponential(prng_t *prng_state) { - return -log(1.0 - prng_state->next_double(prng_state->state)); + return -log(1.0 - random_double(prng_state)); } float random_standard_exponential_f(prng_t *prng_state) { - return -logf(1.0f - next_float(prng_state)); + return -logf(1.0f - random_float(prng_state)); } double random_gauss(prng_t *prng_state) { @@ -38,8 +46,8 @@ double random_gauss(prng_t *prng_state) { double f, x1, x2, r2; do { - x1 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; - x2 = 2.0 * prng_state->next_double(prng_state->state) - 1.0; + x1 = 2.0 * random_double(prng_state) - 1.0; + x2 = 2.0 * random_double(prng_state) - 1.0; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); @@ -62,8 +70,8 @@ float random_gauss_f(prng_t *prng_state) { float f, x1, x2, r2; do { - x1 = 2.0f * next_float(prng_state) - 1.0f; - x2 = 2.0f * next_float(prng_state) - 1.0f; + x1 = 2.0f * random_float(prng_state) - 1.0f; + x2 = 2.0f * random_float(prng_state) - 1.0f; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); @@ -81,9 +89,9 @@ static NPY_INLINE double standard_exponential_zig(prng_t *prng_state); static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, double x) { if (idx == 0) { - return ziggurat_exp_r - log(prng_state->next_double(prng_state->state)); + return ziggurat_exp_r - log(random_double(prng_state)); } else if ((fe_double[idx - 1] - fe_double[idx]) * - prng_state->next_double(prng_state->state) + + random_double(prng_state) + fe_double[idx] < exp(-x)) { return x; @@ -116,8 +124,8 @@ static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state); static float standard_exponential_zig_unlikely_f(prng_t *prng_state, uint8_t idx, float x) { if (idx == 0) { - return ziggurat_exp_r_f - logf(next_float(prng_state)); - } else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(prng_state) + + return ziggurat_exp_r_f - logf(random_float(prng_state)); + } else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(prng_state) + fe_float[idx] < expf(-x)) { return x; @@ -166,15 +174,15 @@ double random_gauss_zig(prng_t *prng_state) { if (idx == 0) { for (;;) { xx = -ziggurat_nor_inv_r * - log(prng_state->next_double(prng_state->state)); - yy = -log(prng_state->next_double(prng_state->state)); + log(random_double(prng_state)); + yy = -log(random_double(prng_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]) * - prng_state->next_double(prng_state->state) + + random_double(prng_state) + fi_double[idx]) < exp(-0.5 * x * x)) return x; } @@ -200,14 +208,14 @@ float random_gauss_zig_f(prng_t *prng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r_f * logf(next_float(prng_state)); - yy = -logf(next_float(prng_state)); + xx = -ziggurat_nor_inv_r_f * logf(random_float(prng_state)); + yy = -logf(random_float(prng_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(prng_state) + + if (((fi_float[idx - 1] - fi_float[idx]) * random_float(prng_state) + fi_float[idx]) < exp(-0.5 * x * x)) return x; } @@ -222,7 +230,7 @@ static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { return random_standard_exponential(prng_state); } else if (shape < 1.0) { for (;;) { - U = prng_state->next_double(prng_state->state); + U = random_double(prng_state); V = random_standard_exponential(prng_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); @@ -1134,8 +1142,8 @@ long random_hypergeometric(prng_t *prng_state, long good, long bad, } } -unsigned long random_interval(prng_t *prng_state, unsigned long max) { - unsigned long mask, value; +uint64_t random_interval(prng_t *prng_state, uint64_t max) { + uint64_t mask, value; if (max == 0) { return 0; } @@ -1148,12 +1156,9 @@ unsigned long random_interval(prng_t *prng_state, unsigned long max) { 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 + /* Search a random value in [0..mask] <= max */ if (max <= 0xffffffffUL) { while ((value = (random_uint32(prng_state) & mask)) > max) ; @@ -1161,10 +1166,6 @@ unsigned long random_interval(prng_t *prng_state, unsigned long max) { while ((value = (random_uint64(prng_state) & mask)) > max) ; } -#else - while ((value = (random_uint32(prng_state) & mask)) > max) - ; -#endif return value; } diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 9f368837eaeb..0ca1c1397919 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -129,7 +129,8 @@ DECLDIR long random_geometric(prng_t *prng_state, double p); DECLDIR long random_zipf(prng_t *prng_state, double a); DECLDIR long random_hypergeometric(prng_t *prng_state, long good, long bad, long sample); -DECLDIR unsigned long random_interval(prng_t *prng_state, unsigned long max); + +DECLDIR uint64_t random_interval(prng_t *prng_state, uint64_t max); DECLDIR uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, uint64_t rng, uint64_t mask); DECLDIR uint32_t random_buffered_bounded_uint32(prng_t *prng_state, diff --git a/_randomgen/core_prng/src/philox/philox.c b/_randomgen/core_prng/src/philox/philox.c index ea401e3690d8..3382c60d6acf 100644 --- a/_randomgen/core_prng/src/philox/philox.c +++ b/_randomgen/core_prng/src/philox/philox.c @@ -2,7 +2,7 @@ extern INLINE uint64_t philox_next64(philox_state *state); -extern INLINE uint64_t philox_next32(philox_state *state); +extern INLINE uint32_t philox_next32(philox_state *state); extern void philox_jump(philox_state *state) { /* Advances state as-if 2^128 draws were made */ diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/core_prng/src/philox/philox.h index e0545bce3540..a130010e626b 100644 --- a/_randomgen/core_prng/src/philox/philox.h +++ b/_randomgen/core_prng/src/philox/philox.h @@ -49,7 +49,8 @@ static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { 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; + (a_x_b_lo >> 32)) >> + 32; *high = a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit; @@ -82,7 +83,8 @@ static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { 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; + (a_x_b_lo >> 32)) >> + 32; *high = a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit; @@ -227,7 +229,7 @@ static INLINE uint64_t philox_next64(philox_state *state) { return philox_next(state); } -static INLINE uint64_t philox_next32(philox_state *state) { +static INLINE uint32_t philox_next32(philox_state *state) { uint64_t next; if (state->has_uint32) { diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/core_prng/src/threefry/threefry.c index 6aac7b5256c8..19c37df1bf93 100644 --- a/_randomgen/core_prng/src/threefry/threefry.c +++ b/_randomgen/core_prng/src/threefry/threefry.c @@ -2,7 +2,7 @@ extern INLINE uint64_t threefry_next64(threefry_state *state); -extern INLINE uint64_t threefry_next32(threefry_state *state); +extern INLINE uint32_t threefry_next32(threefry_state *state); extern void threefry_jump(threefry_state *state) { /* Advances state as-if 2^128 draws were made */ diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/core_prng/src/threefry/threefry.h index 0b557a00d119..e0e4c21a57b7 100644 --- a/_randomgen/core_prng/src/threefry/threefry.h +++ b/_randomgen/core_prng/src/threefry/threefry.h @@ -319,7 +319,7 @@ static INLINE uint64_t threefry_next64(threefry_state *state) { return threefry_next(state); } -static INLINE uint64_t threefry_next32(threefry_state *state) { +static INLINE uint32_t threefry_next32(threefry_state *state) { uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; diff --git a/_randomgen/core_prng/src/threefry32/threefry32.c b/_randomgen/core_prng/src/threefry32/threefry32.c index e30d9c5690e8..500e9482d906 100644 --- a/_randomgen/core_prng/src/threefry32/threefry32.c +++ b/_randomgen/core_prng/src/threefry32/threefry32.c @@ -2,7 +2,7 @@ extern INLINE uint64_t threefry32_next64(threefry32_state *state); -extern INLINE uint64_t threefry32_next32(threefry32_state *state); +extern INLINE uint32_t threefry32_next32(threefry32_state *state); extern void threefry32_jump(threefry32_state *state) { /* Advances state as-if 2^64 draws were made */ diff --git a/_randomgen/core_prng/src/threefry32/threefry32.h b/_randomgen/core_prng/src/threefry32/threefry32.h index 8e9a1161e4ed..9e4cdf2fc3ac 100644 --- a/_randomgen/core_prng/src/threefry32/threefry32.h +++ b/_randomgen/core_prng/src/threefry32/threefry32.h @@ -17,25 +17,33 @@ Adapted from random123's threefry.h #define THREEFRY_BUFFER_SIZE 4L - static INLINE uint32_t RotL_32(uint32_t x, unsigned int N); -static INLINE uint32_t RotL_32(uint32_t x, unsigned int N) -{ - return (x << (N & 31)) | (x >> ((32-N) & 31)); +static INLINE uint32_t RotL_32(uint32_t x, unsigned int N) { + return (x << (N & 31)) | (x >> ((32 - N) & 31)); } -struct r123array4x32{ uint32_t v[4]; }; +struct r123array4x32 { + uint32_t v[4]; +}; enum r123_enum_threefry32x4 { - R_32x4_0_0=10, R_32x4_0_1=26, - R_32x4_1_0=11, R_32x4_1_1=21, - R_32x4_2_0=13, R_32x4_2_1=27, - R_32x4_3_0=23, R_32x4_3_1= 5, - R_32x4_4_0= 6, R_32x4_4_1=20, - R_32x4_5_0=17, R_32x4_5_1=11, - R_32x4_6_0=25, R_32x4_6_1=10, - R_32x4_7_0=18, R_32x4_7_1=20 + R_32x4_0_0 = 10, + R_32x4_0_1 = 26, + R_32x4_1_0 = 11, + R_32x4_1_1 = 21, + R_32x4_2_0 = 13, + R_32x4_2_1 = 27, + R_32x4_3_0 = 23, + R_32x4_3_1 = 5, + R_32x4_4_0 = 6, + R_32x4_4_1 = 20, + R_32x4_5_0 = 17, + R_32x4_5_1 = 11, + R_32x4_6_0 = 25, + R_32x4_6_1 = 10, + R_32x4_7_0 = 18, + R_32x4_7_1 = 20 }; @@ -45,15 +53,19 @@ typedef struct r123array4x32 threefry4x32_ukey_t; static INLINE threefry4x32_key_t threefry4x32keyinit(threefry4x32_ukey_t uk) { return uk; }; -static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in , threefry4x32_key_t k); -static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in , threefry4x32_key_t k) { +static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, + threefry4x32_ctr_t in, + threefry4x32_key_t k); +static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, + threefry4x32_ctr_t in, + threefry4x32_key_t k) { threefry4x32_ctr_t X; uint32_t ks[4 + 1]; int i; ks[4] = 0x1BD11BDA; for (i = 0; i < 4; i++) { ks[i] = k.v[i]; - X.v[i] = in .v[i]; + X.v[i] = in.v[i]; ks[4] ^= k.v[i]; } X.v[0] += ks[0]; @@ -764,15 +776,14 @@ static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x } return X; } -enum r123_enum_threefry4x32 { - threefry4x32_rounds = 20 -}; -static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in , threefry4x32_key_t k); -static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in , threefry4x32_key_t k) { - return threefry4x32_R(threefry4x32_rounds, in , k); +enum r123_enum_threefry4x32 { threefry4x32_rounds = 20 }; +static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, + threefry4x32_key_t k); +static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, + threefry4x32_key_t k) { + return threefry4x32_R(threefry4x32_rounds, in, k); } - typedef struct s_threefry32_state { threefry4x32_key_t *ctr; threefry4x32_ctr_t *key; @@ -813,7 +824,7 @@ static INLINE uint64_t threefry32_next64(threefry32_state *state) { return ((uint64_t)threefry32_next(state) << 32) | threefry32_next(state); } -static INLINE uint64_t threefry32_next32(threefry32_state *state) { +static INLINE uint32_t threefry32_next32(threefry32_state *state) { return threefry32_next(state); } From dc0c84baca3efbcbd03aee607cd180231c0d0620 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 13 Mar 2018 09:15:55 +0000 Subject: [PATCH 054/138] BUG: Fix returned type Return double --- _randomgen/core_prng/src/distributions/distributions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 070a2edfbb5b..6b39763714e3 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -15,7 +15,7 @@ static NPY_INLINE float random_float(prng_t *prng_state) { return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); } -static NPY_INLINE float random_double(prng_t *prng_state) { +static NPY_INLINE double random_double(prng_t *prng_state) { return prng_state->next_double(prng_state->state); } From c1f4fa0f8ace5d7ccc0da7e42ab1b7dff5e9498a Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 13 Mar 2018 09:11:11 +0000 Subject: [PATCH 055/138] REF: Drop Box-Muller Drop Box-Muller and supported infrastructure --- _randomgen/core_prng/distributions.pxd | 8 - _randomgen/core_prng/dsfmt.pyx | 5 +- _randomgen/core_prng/generator.pyx | 162 ++++-------------- _randomgen/core_prng/mt19937.pyx | 15 +- _randomgen/core_prng/pcg32.pyx | 7 - _randomgen/core_prng/pcg64.pyx | 4 - _randomgen/core_prng/philox.pyx | 4 - .../src/distributions/distributions.c | 54 +++--- .../src/distributions/distributions.h | 27 ++- .../core_prng/tests/test_against_numpy.py | 55 +++--- _randomgen/core_prng/tests/test_direct.py | 11 +- .../core_prng/tests/test_numpy_mt19937.py | 52 ++++-- _randomgen/core_prng/tests/test_smoke.py | 53 +++--- _randomgen/core_prng/threefry.pyx | 4 - _randomgen/core_prng/threefry32.pyx | 4 - _randomgen/core_prng/xoroshiro128.pyx | 4 - _randomgen/core_prng/xorshift1024.pyx | 4 - .../cython/extending_distributions.pyx | 19 -- .../examples/numba/extending_distributions.py | 12 +- 19 files changed, 187 insertions(+), 317 deletions(-) diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd index 5359a1be0eaa..e26effa1adaa 100644 --- a/_randomgen/core_prng/distributions.pxd +++ b/_randomgen/core_prng/distributions.pxd @@ -32,10 +32,6 @@ cdef extern from "src/distributions/distributions.h": uint32_t (*next_uint32)(void *st) nogil double (*next_double)(void *st) nogil uint64_t (*next_raw)(void *st) nogil - int has_gauss - double gauss - int has_gauss_f - float gauss_f binomial_t *binomial ctypedef prng prng_t @@ -43,15 +39,12 @@ cdef extern from "src/distributions/distributions.h": double random_sample(prng_t *prng_state) nogil double random_standard_exponential(prng_t *prng_state) nogil double random_standard_exponential_zig(prng_t *prng_state) nogil - double random_gauss(prng_t *prng_state) nogil double random_gauss_zig(prng_t* prng_state) nogil - double random_standard_gamma(prng_t *prng_state, double shape) nogil double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil float random_sample_f(prng_t *prng_state) nogil float random_standard_exponential_f(prng_t *prng_state) nogil float random_standard_exponential_zig_f(prng_t *prng_state) nogil - float random_gauss_f(prng_t *prng_state) nogil float random_gauss_zig_f(prng_t* prng_state) nogil float random_standard_gamma_f(prng_t *prng_state, float shape) nogil float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil @@ -61,7 +54,6 @@ cdef extern from "src/distributions/distributions.h": long random_positive_int(prng_t *prng_state) nogil unsigned long random_uint(prng_t *prng_state) nogil - double random_normal(prng_t *prng_state, double loc, double scale) nogil double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil double random_gamma(prng_t *prng_state, double shape, double scale) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index c95f4f2d3918..4280c22f9b3f 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -118,10 +118,7 @@ cdef class DSFMT: free(self._prng) cdef _reset_state_variables(self): - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 + pass def __random_integer(self, bits=64): """ diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 72d357067047..d6bda579ba18 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -72,9 +72,6 @@ cdef class RandomGenerator: raise ValueError("Invalid prng. The prng must be instantized.") self._prng = PyCapsule_GetPointer(capsule, anon_name) self.lock = Lock() - with self.lock: - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 def __repr__(self): return self.__str__() + ' at 0x{:X}'.format(id(self)) @@ -104,23 +101,11 @@ cdef class RandomGenerator: @property def state(self): """Get or set the underlying PRNG's state""" - state = self.__core_prng.state - state['has_gauss'] = self._prng.has_gauss - state['has_gauss_f'] = self._prng.has_gauss_f - state['gauss'] = self._prng.gauss - state['gauss_f'] = self._prng.gauss_f - return state + return self.__core_prng.state @state.setter def state(self, value): self.__core_prng.state = value - if isinstance(value, tuple): - # Legacy MT19937 state - return - self._prng.has_gauss = value['has_gauss'] - self._prng.has_gauss_f = value['has_gauss_f'] - self._prng.gauss = value['gauss'] - self._prng.gauss_f = value['gauss_f'] def random_uintegers(self, size=None, int bits=64): """ @@ -246,14 +231,6 @@ cdef class RandomGenerator: else: raise ValueError('bits must be 32 or 64') - def random_double(self, bits=64): - if bits == 64: - return self._prng.next_double(self._prng.state) - elif bits == 32: - return random_sample_f(self._prng) - else: - raise ValueError('bits must be 32 or 64') - def random_sample(self, size=None, dtype=np.float64, out=None): """ random_sample(size=None, dtype='d', out=None) @@ -994,9 +971,9 @@ cdef class RandomGenerator: else: return self.random_sample(size=args, dtype=dtype) - def randn(self, *args, method=u'zig', dtype=np.float64): + def randn(self, *args, dtype=np.float64): """ - randn(d0, d1, ..., dn, method='zig', dtype='d') + randn(d0, d1, ..., dn, dtype='d') Return a sample (or samples) from the "standard normal" distribution. @@ -1016,10 +993,6 @@ cdef class RandomGenerator: d0, d1, ..., dn : int, optional The dimensions of the returned array, should be all positive. If no argument is given a single Python float is returned. - method : str, optional - Either 'bm' or 'zig'. 'bm' uses the default Box-Muller - transformations method. 'zig' uses the much faster Ziggurat - method of Marsaglia and Tsang. 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 @@ -1055,9 +1028,9 @@ cdef class RandomGenerator: """ if len(args) == 0: - return self.standard_normal(method=method, dtype=dtype) + return self.standard_normal(dtype=dtype) else: - return self.standard_normal(size=args, method=method, dtype=dtype) + return self.standard_normal(size=args, dtype=dtype) def random_integers(self, low, high=None, size=None): """ @@ -1154,9 +1127,9 @@ cdef class RandomGenerator: return self.randint(low, high + 1, size=size, dtype='l') # Complicated, continuous distributions: - def standard_normal(self, size=None, dtype=np.float64, method=u'zig', out=None): + def standard_normal(self, size=None, dtype=np.float64, out=None): """ - standard_normal(size=None, dtype='d', method='zig', out=None) + standard_normal(size=None, dtype='d', out=None) Draw samples from a standard Normal distribution (mean=0, stdev=1). @@ -1170,9 +1143,6 @@ cdef class RandomGenerator: 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 'bm' or 'zig'. 'bm' uses the Box-Muller transformations - 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 @@ -1198,22 +1168,17 @@ cdef class RandomGenerator: """ key = np.dtype(dtype).name if key == 'float64': - if method == u'zig': - return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) - else: - return double_fill(&random_gauss, self._prng, size, self.lock, out) + return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) elif key == 'float32': - if method == u'zig': - return float_fill(&random_gauss_zig_f, self._prng, size, self.lock, out) - else: - return float_fill(&random_gauss_f, self._prng, size, self.lock, out) + return float_fill(&random_gauss_zig_f, self._prng, 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, method=u'zig'): + def normal(self, loc=0.0, scale=1.0, size=None): """ - normal(loc=0.0, scale=1.0, size=None, method='zig') + normal(loc=0.0, scale=1.0, size=None) Draw random samples from a normal (Gaussian) distribution. @@ -1238,10 +1203,6 @@ cdef class RandomGenerator: ``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. - method : str, optional - Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations - method. 'zig' uses the much faster Ziggurat method of Marsaglia and Tsang. - Returns ------- @@ -1304,23 +1265,15 @@ cdef class RandomGenerator: >>> plt.show() """ - if method == 'bm': - return cont(&random_normal, self._prng, size, self.lock, 2, - loc, '', CONS_NONE, - scale, 'scale', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE, - None) - else: - return cont(&random_normal_zig, self._prng, size, self.lock, 2, - loc, '', CONS_NONE, - scale, 'scale', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE, - None) + return cont(&random_normal_zig, self._prng, size, self.lock, 2, + loc, '', CONS_NONE, + scale, 'scale', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + None) - def complex_normal(self, loc=0.0, gamma=1.0, relation=0.0, size=None, - method=u'zig'): + def complex_normal(self, loc=0.0, gamma=1.0, relation=0.0, size=None): """ - complex_normal(loc=0.0, gamma=1.0, relation=0.0, size=None, method='zig') + complex_normal(loc=0.0, gamma=1.0, relation=0.0, size=None) Draw random samples from a complex normal (Gaussian) distribution. @@ -1338,10 +1291,6 @@ cdef class RandomGenerator: a single value is returned if ``loc``, ``gamma`` and ``relation`` are all scalars. Otherwise, ``np.broadcast(loc, gamma, relation).size`` samples are drawn. - method : str, optional - Either 'bm' or 'zig'. 'bm' uses the default Box-Muller - transformations method. 'zig' uses the much faster Ziggurat - method of Marsaglia and Tsang. Returns ------- @@ -1379,8 +1328,6 @@ cdef class RandomGenerator: >>> s = np.random.complex_normal(size=1000) """ - if method != u'zig' and method != u'bm': - raise ValueError("method must be either 'bm' or 'zig'") cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho cdef double *randoms_data cdef double fgamma_r, fgamma_i, frelation_r, frelation_i, frho, fvar_r , fvar_i, \ @@ -1415,12 +1362,8 @@ cdef class RandomGenerator: raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation** 2)') if size is None: - if method == u'zig': - f_real = random_gauss_zig(self._prng) - f_imag = random_gauss_zig(self._prng) - else: - f_real = random_gauss(self._prng) - f_imag = random_gauss(self._prng) + f_real = random_gauss_zig(self._prng) + f_imag = random_gauss_zig(self._prng) compute_complex(&f_real, &f_imag, floc_r, floc_i, fvar_r, fvar_i, f_rho) return PyComplex_FromDoubles(f_real, f_imag) @@ -1434,20 +1377,12 @@ cdef class RandomGenerator: i_scale = sqrt(fvar_i) j = 0 with self.lock, nogil: - if method == u'zig': - for i in range(n): - f_real = random_gauss_zig(self._prng) - f_imag = random_gauss_zig(self._prng) - randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) - randoms_data[j] = floc_r + r_scale * f_real - j += 2 - else: - for i in range(n): - f_real = random_gauss(self._prng) - f_imag = random_gauss(self._prng) - randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) - randoms_data[j] = floc_r + r_scale * f_real - j += 2 + for i in range(n): + f_real = random_gauss_zig(self._prng) + f_imag = random_gauss_zig(self._prng) + randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) + randoms_data[j] = floc_r + r_scale * f_real + j += 2 return randoms @@ -1481,12 +1416,8 @@ cdef class RandomGenerator: it = np.PyArray_MultiIterNew5(randoms, oloc, v_real, v_imag, rho) with self.lock, nogil: n2 = 2 * n # Avoid compiler noise for cast to long - if method == u'zig': - for i in range(n2): - randoms_data[i] = random_gauss_zig(self._prng) - else: - for i in range(n2): - randoms_data[i] = random_gauss(self._prng) + for i in range(n2): + randoms_data[i] = random_gauss_zig(self._prng) with nogil: j = 0 for i in range(n): @@ -1501,10 +1432,9 @@ cdef class RandomGenerator: return randoms - def standard_gamma(self, shape, size=None, dtype=np.float64, method=u'zig', - out=None): + def standard_gamma(self, shape, size=None, dtype=np.float64, out=None): """ - standard_gamma(shape, size=None, dtype='d', method='inv', out=None) + standard_gamma(shape, size=None, dtype='d', out=None) Draw samples from a standard Gamma distribution. @@ -1524,9 +1454,6 @@ cdef class RandomGenerator: 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 @@ -1582,25 +1509,15 @@ cdef class RandomGenerator: >>> plt.show() """ cdef void *func - if method != u'zig' and method != u'inv': - raise ValueError("method must be either 'inv' or 'zig'") key = np.dtype(dtype).name if key == 'float64': - if method == 'inv': - func = &random_standard_gamma - else: - func = &random_standard_gamma_zig - return cont(func, self._prng, size, self.lock, 1, + return cont(&random_standard_gamma_zig, self._prng, size, self.lock, 1, shape, 'shape', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, out) if key == 'float32': - if method == 'inv': - func = &random_standard_gamma_f - else: - func = &random_standard_gamma_zig_f - return cont_f(func, self._prng, size, self.lock, + return cont_f(&random_standard_gamma_zig_f, self._prng, size, self.lock, shape, 'shape', CONS_NON_NEGATIVE, out) else: @@ -3242,7 +3159,6 @@ cdef class RandomGenerator: >>> sum(np.random.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. - """ return disc(&random_binomial, self._prng, size, self.lock, 1, 1, p, 'p', CONS_BOUNDED_0_1_NOTNAN, @@ -3729,10 +3645,10 @@ cdef class RandomGenerator: # Multivariate distributions: def multivariate_normal(self, mean, cov, size=None, check_valid='warn', - tol=1e-8, method=u'zig'): + tol=1e-8): """ multivariate_normal(self, mean, cov, size=None, check_valid='warn', - tol=1e-8, method='zig') + tol=1e-8) Draw random samples from a multivariate normal distribution. @@ -3759,9 +3675,6 @@ cdef class RandomGenerator: Behavior when the covariance matrix is not positive semidefinite. tol : float, optional Tolerance when checking the singular values in covariance matrix. - method : str, optional - Either 'bm' or 'zig'. 'bm' uses the default Box-Muller transformations - method. 'zig' uses the much faster Ziggurat method of Marsaglia and Tsang. Returns ------- @@ -3858,7 +3771,7 @@ cdef class RandomGenerator: # form a matrix of shape final_shape. final_shape = list(shape[:]) final_shape.append(mean.shape[0]) - x = self.standard_normal(final_shape, method=method).reshape(-1, mean.shape[0]) + x = self.standard_normal(final_shape).reshape(-1, mean.shape[0]) # Transform matrix of standard normals into matrix where each row # contains multivariate normals with the desired covariance. @@ -4125,7 +4038,8 @@ cdef class RandomGenerator: while i < totsize: acc = 0.0 for j in range(k): - val_data[i+j] = random_standard_gamma(self._prng, alpha_data[j]) + val_data[i+j] = random_standard_gamma_zig(self._prng, + alpha_data[j]) acc = acc + val_data[i + j] invacc = 1/acc for j in range(k): diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index 53a909100727..e755d958d351 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -78,12 +78,6 @@ cdef class MT19937: free(self._prng.binomial) free(self._prng) - cdef _reset_state_variables(self): - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 - # Pickling support: def __getstate__(self): return self.state @@ -173,7 +167,6 @@ cdef class MT19937: 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, obj.data, np.PyArray_DIM(obj, 0)) - self._reset_state_variables() def jump(self): mt19937_jump(self.rng_state) @@ -194,13 +187,9 @@ cdef class MT19937: if isinstance(value, tuple): if value[0] != 'MT19937' or len(value) not in (3,5): raise ValueError('state is not a legacy MT19937 state') - self._reset_state_variables() - if len(value) == 5: - self._prng.has_gauss = value[3] - self._prng.gauss = value[4] value ={'prng': 'MT19937', - 'state':{'key': value[1], 'pos': value[2]} - } + 'state':{'key': value[1], 'pos': value[2]}} + if not isinstance(value, dict): raise TypeError('state must be a dict') diff --git a/_randomgen/core_prng/pcg32.pyx b/_randomgen/core_prng/pcg32.pyx index 316dc81d9087..9e46461c6b1b 100644 --- a/_randomgen/core_prng/pcg32.pyx +++ b/_randomgen/core_prng/pcg32.pyx @@ -97,12 +97,6 @@ cdef class PCG32: free(self._prng.binomial) free(self._prng) - cdef _reset_state_variables(self): - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 - def __random_integer(self, bits=64): """ 64-bit Random Integers from the PRNG @@ -188,7 +182,6 @@ cdef class PCG32: 'and {ub}'.format(ub=ub)) pcg32_set_seed(self.rng_state, seed, inc) - self._reset_state_variables() @property def state(self): diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index c01156d72f37..d0c3e5f7638d 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -115,10 +115,6 @@ cdef class PCG64: cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index c724e5ee8be0..59d6359adb56 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -110,10 +110,6 @@ cdef class Philox: cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 self.rng_state.buffer_pos = PHILOX_BUFFER_SIZE for i in range(PHILOX_BUFFER_SIZE): self.rng_state.buffer[i] = 0 diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 6b39763714e3..aa1284ed0afd 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -2,23 +2,6 @@ #include "ziggurat.h" #include "ziggurat_constants.h" -/* Inline generators for internal use */ -static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { - return prng_state->next_uint32(prng_state->state); -} - -static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { - return prng_state->next_uint64(prng_state->state); -} - -static NPY_INLINE float random_float(prng_t *prng_state) { - return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); -} - -static NPY_INLINE double random_double(prng_t *prng_state) { - return prng_state->next_double(prng_state->state); -} - /* Random generators for external use */ float random_sample_f(prng_t *prng_state) { return random_float(prng_state); @@ -36,6 +19,7 @@ float random_standard_exponential_f(prng_t *prng_state) { return -logf(1.0f - random_float(prng_state)); } +/* double random_gauss(prng_t *prng_state) { if (prng_state->has_gauss) { const double temp = prng_state->gauss; @@ -51,9 +35,9 @@ double random_gauss(prng_t *prng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + // Box-Muller transform f = sqrt(-2.0 * log(r2) / r2); - /* Keep for next call */ + // Keep for next call prng_state->gauss = f * x1; prng_state->has_gauss = true; return f * x2; @@ -75,14 +59,15 @@ float random_gauss_f(prng_t *prng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + // Box-Muller transform f = sqrtf(-2.0f * logf(r2) / r2); - /* Keep for next call */ + // Keep for next call prng_state->gauss_f = f * x1; prng_state->has_gauss_f = true; return f * x2; } } +*/ static NPY_INLINE double standard_exponential_zig(prng_t *prng_state); @@ -222,6 +207,7 @@ float random_gauss_zig_f(prng_t *prng_state) { } } +/* static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { double b, c; double U, V, X, Y; @@ -306,6 +292,7 @@ static NPY_INLINE float standard_gamma_float(prng_t *prng_state, float shape) { } } + double random_standard_gamma(prng_t *prng_state, double shape) { return standard_gamma(prng_state, shape); } @@ -313,6 +300,7 @@ double random_standard_gamma(prng_t *prng_state, double shape) { float random_standard_gamma_f(prng_t *prng_state, float shape) { return standard_gamma_float(prng_state, shape); } +*/ static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) { double b, c; @@ -469,9 +457,11 @@ static double loggam(double x) { return gl; } +/* double random_normal(prng_t *prng_state, double loc, double scale) { return loc + scale * random_gauss(prng_state); } +*/ double random_normal_zig(prng_t *prng_state, double loc, double scale) { return loc + scale * random_gauss_zig(prng_state); @@ -486,11 +476,11 @@ double random_uniform(prng_t *prng_state, double lower, double range) { } double random_gamma(prng_t *prng_state, double shape, double scale) { - return scale * random_standard_gamma(prng_state, shape); + return scale * random_standard_gamma_zig(prng_state, shape); } float random_gamma_float(prng_t *prng_state, float shape, float scale) { - return scale * random_standard_gamma_f(prng_state, shape); + return scale * random_standard_gamma_zig_f(prng_state, shape); } double random_beta(prng_t *prng_state, double a, double b) { @@ -521,14 +511,14 @@ double random_beta(prng_t *prng_state, double a, double b) { } } } else { - Ga = random_standard_gamma(prng_state, a); - Gb = random_standard_gamma(prng_state, b); + Ga = random_standard_gamma_zig(prng_state, a); + Gb = random_standard_gamma_zig(prng_state, b); return Ga / (Ga + Gb); } } double random_chisquare(prng_t *prng_state, double df) { - return 2.0 * random_standard_gamma(prng_state, df / 2.0); + return 2.0 * random_standard_gamma_zig(prng_state, df / 2.0); } double random_f(prng_t *prng_state, double dfnum, double dfden) { @@ -537,7 +527,7 @@ double random_f(prng_t *prng_state, double dfnum, double dfden) { } double random_standard_cauchy(prng_t *prng_state) { - return random_gauss(prng_state) / random_gauss(prng_state); + return random_gauss_zig(prng_state) / random_gauss_zig(prng_state); } double random_pareto(prng_t *prng_state, double a) { @@ -579,7 +569,7 @@ double random_logistic(prng_t *prng_state, double loc, double scale) { } double random_lognormal(prng_t *prng_state, double mean, double sigma) { - return exp(random_normal(prng_state, mean, sigma)); + return exp(random_normal_zig(prng_state, mean, sigma)); } double random_rayleigh(prng_t *prng_state, double mode) { @@ -589,8 +579,8 @@ double random_rayleigh(prng_t *prng_state, double mode) { double random_standard_t(prng_t *prng_state, double df) { double num, denom; - num = random_gauss(prng_state); - denom = random_standard_gamma(prng_state, df / 2); + num = random_gauss_zig(prng_state); + denom = random_standard_gamma_zig(prng_state, df / 2); return sqrt(df / 2) * num / sqrt(denom); } @@ -867,7 +857,7 @@ double random_noncentral_chisquare(prng_t *prng_state, double df, double nonc) { } if (1 < df) { const double Chi2 = random_chisquare(prng_state, df - 1); - const double n = random_gauss(prng_state) + sqrt(nonc); + const double n = random_gauss_zig(prng_state) + sqrt(nonc); return Chi2 + n * n; } else { const long i = random_poisson(prng_state, nonc / 2.0); @@ -886,7 +876,7 @@ double random_wald(prng_t *prng_state, double mean, double scale) { double mu_2l; mu_2l = mean / (2 * scale); - Y = random_gauss(prng_state); + Y = random_gauss_zig(prng_state); Y = mean * Y * Y; X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y)); U = random_sample(prng_state); diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 0ca1c1397919..95e839cb0967 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -59,13 +59,26 @@ typedef struct prng { uint32_t (*next_uint32)(void *st); double (*next_double)(void *st); uint64_t (*next_raw)(void *st); - int has_gauss; - double gauss; - int has_gauss_f; - float gauss_f; binomial_t *binomial; } prng_t; +/* Inline generators for internal use */ +static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { + return prng_state->next_uint32(prng_state->state); +} + +static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { + return prng_state->next_uint64(prng_state->state); +} + +static NPY_INLINE float random_float(prng_t *prng_state) { + return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); +} + +static NPY_INLINE double random_double(prng_t *prng_state) { + return prng_state->next_double(prng_state->state); +} + DECLDIR float random_sample_f(prng_t *prng_state); DECLDIR double random_sample(prng_t *prng_state); @@ -79,17 +92,23 @@ DECLDIR float random_standard_exponential_f(prng_t *prng_state); DECLDIR double random_standard_exponential_zig(prng_t *prng_state); DECLDIR float random_standard_exponential_zig_f(prng_t *prng_state); +/* DECLDIR double random_gauss(prng_t *prng_state); DECLDIR float random_gauss_f(prng_t *prng_state); +*/ DECLDIR double random_gauss_zig(prng_t *prng_state); DECLDIR float random_gauss_zig_f(prng_t *prng_state); +/* DECLDIR double random_standard_gamma(prng_t *prng_state, double shape); DECLDIR float random_standard_gamma_f(prng_t *prng_state, float shape); +*/ DECLDIR double random_standard_gamma_zig(prng_t *prng_state, double shape); DECLDIR float random_standard_gamma_zig_f(prng_t *prng_state, float shape); +/* DECLDIR double random_normal(prng_t *prng_state, double loc, double scale); +*/ DECLDIR double random_normal_zig(prng_t *prng_state, double loc, double scale); DECLDIR double random_gamma(prng_t *prng_state, double shape, double scale); diff --git a/_randomgen/core_prng/tests/test_against_numpy.py b/_randomgen/core_prng/tests/test_against_numpy.py index 9f0cfe054fa0..61a7a10206df 100644 --- a/_randomgen/core_prng/tests/test_against_numpy.py +++ b/_randomgen/core_prng/tests/test_against_numpy.py @@ -1,7 +1,7 @@ import numpy as np import numpy.random -import pytest from numpy.testing import assert_allclose, assert_array_equal, assert_equal +import pytest from core_prng import RandomGenerator, MT19937 @@ -12,9 +12,7 @@ def compare_0_input(f1, f2): (tuple([]), {'size': (20, 31, 5)})] -def compare_1_input(f1, f2, is_small=False, core_prng_kwargs=None): - if core_prng_kwargs is None: - core_prng_kwargs = {} +def compare_1_input(f1, f2, is_small=False): a = 0.3 if is_small else 10 inputs = [((a,), {}), ((a,), {'size': 10}), @@ -23,14 +21,11 @@ def compare_1_input(f1, f2, is_small=False, core_prng_kwargs=None): ((np.array([a] * 10),), {'size': (100, 10)})] for i in inputs: v1 = f1(*i[0], **i[1]) - i[1].update(core_prng_kwargs) v2 = f2(*i[0], **i[1]) assert_allclose(v1, v2) -def compare_2_input(f1, f2, is_np=False, is_scalar=False, core_prng_kwargs=None): - if core_prng_kwargs is None: - core_prng_kwargs = {} +def compare_2_input(f1, f2, is_np=False, is_scalar=False): if is_np: a, b = 10, 0.3 dtype = np.int @@ -52,7 +47,6 @@ def compare_2_input(f1, f2, is_np=False, is_scalar=False, core_prng_kwargs=None) for i in inputs: v1 = f1(*i[0], **i[1]) - i[1].update(core_prng_kwargs) v2 = f2(*i[0], **i[1]) assert_allclose(v1, v2) @@ -101,8 +95,8 @@ def _set_common_state(cls): st[0] = 'MT19937' st[1] = state['state']['key'] st[2] = state['state']['pos'] - st[3] = state['has_gauss'] - st[4] = state['gauss'] + st[3] = 0 + st[4] = 0.0 cls.nprs.set_state(st) def _is_state_common(self): @@ -110,8 +104,6 @@ def _is_state_common(self): state2 = self.rg.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) - assert (state[3] == state2['has_gauss']) - assert_allclose(state[4], state2['gauss']) def test_common_seed(self): self.rg.seed(1234) @@ -129,8 +121,6 @@ def test_numpy_state(self): state2 = self.rg.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) - assert (state[3] == state2['has_gauss']) - assert (state[4] == state2['gauss']) def test_random_sample(self): self._set_common_state() @@ -168,6 +158,7 @@ def test_tomaxint(self): self.rg.tomaxint) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_chisquare(self): self._set_common_state() self._is_state_common() @@ -175,14 +166,15 @@ def test_chisquare(self): self.rg.chisquare) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_gamma(self): self._set_common_state() self._is_state_common() compare_1_input(self.nprs.standard_gamma, - self.rg.standard_gamma, - core_prng_kwargs={'method':'inv'}) + self.rg.standard_gamma) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_t(self): self._set_common_state() self._is_state_common() @@ -248,6 +240,7 @@ def test_geometric(self): is_small=True) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_beta(self): self._set_common_state() self._is_state_common() @@ -262,6 +255,7 @@ def test_exponential(self): self.rg.exponential) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_f(self): self._set_common_state() self._is_state_common() @@ -269,6 +263,7 @@ def test_f(self): self.rg.f) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gamma(self): self._set_common_state() self._is_state_common() @@ -297,6 +292,7 @@ def test_laplace(self): self.rg.laplace) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_lognormal(self): self._set_common_state() self._is_state_common() @@ -304,6 +300,7 @@ def test_lognormal(self): self.rg.lognormal) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_chisquare(self): self._set_common_state() self._is_state_common() @@ -311,12 +308,12 @@ def test_noncentral_chisquare(self): self.rg.noncentral_chisquare) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_normal(self): self._set_common_state() self._is_state_common() compare_2_input(self.nprs.normal, - self.rg.normal, - core_prng_kwargs={'method':'bm'}) + self.rg.normal) self._is_state_common() def test_uniform(self): @@ -333,6 +330,7 @@ def test_vonmises(self): self.rg.vonmises) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_wald(self): self._set_common_state() self._is_state_common() @@ -356,6 +354,7 @@ def test_binomial(self): is_np=True) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_negative_binomial(self): self._set_common_state() self._is_state_common() @@ -364,13 +363,16 @@ def test_negative_binomial(self): is_np=True) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_randn(self): f = self.rg.randn g = self.nprs.randn - assert_allclose(f(10, method='bm'), g(10)) - assert_allclose(f(3, 4, 5, method='bm'), g(3, 4, 5)) + assert_allclose(f(10), g(10)) + assert_allclose(f(3, 4, 5), g(3, 4, 5)) def test_rand(self): + self._set_common_state() + self._is_state_common() f = self.rg.rand g = self.nprs.rand assert_allclose(f(10), g(10)) @@ -379,6 +381,7 @@ def test_rand(self): def test_poisson_lam_max(self): assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_dirichlet(self): f = self.rg.dirichlet g = self.nprs.dirichlet @@ -387,6 +390,7 @@ def test_dirichlet(self): assert_allclose(f(np.array(a), 10), g(np.array(a), 10)) assert_allclose(f(np.array(a), (3, 37)), g(np.array(a), (3, 37))) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_f(self): self._set_common_state() self._is_state_common() @@ -464,6 +468,7 @@ def test_shuffle(self): assert_equal(fa, ga) self._is_state_common() + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_multivariate_normal(self): self._set_common_state() self._is_state_common() @@ -471,11 +476,11 @@ def test_multivariate_normal(self): cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] f = self.rg.multivariate_normal g = self.nprs.multivariate_normal - assert_allclose(f(mu, cov, method='bm'), g(mu, cov)) - assert_allclose(f(np.array(mu), cov, method='bm'), g(np.array(mu), cov)) - assert_allclose(f(np.array(mu), np.array(cov), method='bm'), + assert_allclose(f(mu, cov), g(mu, cov)) + assert_allclose(f(np.array(mu), cov), g(np.array(mu), cov)) + assert_allclose(f(np.array(mu), np.array(cov)), g(np.array(mu), np.array(cov))) - assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31), method='bm'), + assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31)), g(np.array(mu), np.array(cov), size=(7, 31))) self._is_state_common() diff --git a/_randomgen/core_prng/tests/test_direct.py b/_randomgen/core_prng/tests/test_direct.py index cada2d58d394..1bd5deafebdc 100644 --- a/_randomgen/core_prng/tests/test_direct.py +++ b/_randomgen/core_prng/tests/test_direct.py @@ -5,6 +5,7 @@ import numpy as np from numpy.testing import assert_equal, assert_allclose, assert_array_equal, \ assert_raises +import pytest from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 @@ -145,15 +146,16 @@ def test_raw(self): uints = rs.random_raw(1000) assert_equal(uints, self.data2['data']) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.prng(*self.data1['seed'])) - gauss = rs.standard_normal(n, method='bm') + gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, self.bits)) rs = RandomGenerator(self.prng(*self.data2['seed'])) - gauss = rs.standard_normal(25, method='bm') + gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, self.bits)) @@ -349,15 +351,16 @@ def test_uniform_double(self): assert_equal(uniform_from_dsfmt(self.data2['data']), rs.random_sample(1000)) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.prng(*self.data1['seed'])) - gauss = rs.standard_normal(n, method='bm') + gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, 'dsfmt')) rs = RandomGenerator(self.prng(*self.data2['seed'])) - gauss = rs.standard_normal(25, method='bm') + gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, 'dsfmt')) diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937.py b/_randomgen/core_prng/tests/test_numpy_mt19937.py index 5097f82bd355..9ff45504fdb2 100644 --- a/_randomgen/core_prng/tests/test_numpy_mt19937.py +++ b/_randomgen/core_prng/tests/test_numpy_mt19937.py @@ -96,9 +96,7 @@ def setup(self): self.state = self.prng.state self.legacy_state = (self.state['prng'], self.state['state']['key'], - self.state['state']['pos'], - self.state['has_gauss'], - self.state['gauss']) + self.state['state']['pos']) def test_basic(self): old = self.prng.tomaxint(16) @@ -124,6 +122,7 @@ def test_gaussian_reset_in_media_res(self): new = self.prng.standard_normal(size=3) assert_(np.all(old == new)) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_backwards_compatibility(self): # Make sure we can accept old state tuples that do not have the # cached Gaussian value. @@ -408,9 +407,10 @@ def test_rand(self): [0.4575674820298663, 0.7781880808593471]]) assert_array_almost_equal(actual, desired, decimal=15) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_randn(self): mt19937.seed(self.seed) - actual = mt19937.randn(3, 2, method='bm') + actual = mt19937.randn(3, 2) desired = np.array([[1.34016345771863121, 1.73759122771936081], [1.498988344300628, -0.2286433324536169], [2.031033998682787, 2.17032494605655257]]) @@ -614,6 +614,7 @@ def test_binomial(self): [46, 45]]) assert_array_equal(actual, desired) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_chisquare(self): mt19937.seed(self.seed) actual = mt19937.chisquare(50, size=(3, 2)) @@ -622,6 +623,7 @@ def test_chisquare(self): [72.3828403199695174, 74.18408615260374006]]) assert_array_almost_equal(actual, desired, decimal=13) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_dirichlet(self): mt19937.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) @@ -665,6 +667,7 @@ def test_exponential_0(self): assert_equal(mt19937.exponential(scale=0), 0) assert_raises(ValueError, mt19937.exponential, scale=-0.) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_f(self): mt19937.seed(self.seed) actual = mt19937.f(12, 77, size=(3, 2)) @@ -673,6 +676,7 @@ def test_f(self): [1.02176975757740629, 1.34431827623300415]]) assert_array_almost_equal(actual, desired, decimal=15) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gamma(self): mt19937.seed(self.seed) actual = mt19937.gamma(5, 3, size=(3, 2)) @@ -751,6 +755,7 @@ def test_logistic(self): [-0.21682183359214885, 2.63373365386060332]]) assert_array_almost_equal(actual, desired, decimal=15) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_lognormal(self): mt19937.seed(self.seed) actual = mt19937.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) @@ -782,12 +787,13 @@ def test_multinomial(self): [4, 3, 4, 2, 3, 4]]]) assert_array_equal(actual, desired) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_multivariate_normal(self): mt19937.seed(self.seed) mean = (.123456789, 10) cov = [[1, 0], [0, 1]] size = (3, 2) - actual = mt19937.multivariate_normal(mean, cov, size, method='bm') + actual = mt19937.multivariate_normal(mean, cov, size) desired = np.array([[[1.463620246718631, 11.73759122771936], [1.622445133300628, 9.771356667546383]], [[2.154490787682787, 12.170324946056553], @@ -798,7 +804,7 @@ def test_multivariate_normal(self): assert_array_almost_equal(actual, desired, decimal=15) # Check for default size, was raising deprecation warning - actual = mt19937.multivariate_normal(mean, cov, method='bm') + actual = mt19937.multivariate_normal(mean, cov) desired = np.array([0.895289569463708, 9.17180864067987]) assert_array_almost_equal(actual, desired, decimal=15) @@ -806,16 +812,17 @@ def test_multivariate_normal(self): # RuntimeWarning mean = [0, 0] cov = [[1, 2], [2, 1]] - assert_warns(RuntimeWarning, mt19937.multivariate_normal, mean, cov, method='bm') + assert_warns(RuntimeWarning, mt19937.multivariate_normal, mean, cov) # and that it doesn't warn with RuntimeWarning check_valid='ignore' assert_no_warnings(mt19937.multivariate_normal, mean, cov, - check_valid='ignore', method='bm') + check_valid='ignore') # and that it raises with RuntimeWarning check_valid='raises' assert_raises(ValueError, mt19937.multivariate_normal, mean, cov, - check_valid='raise', method='bm') + check_valid='raise') + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_negative_binomial(self): mt19937.seed(self.seed) actual = mt19937.negative_binomial(n=100, p=.12345, size=(3, 2)) @@ -824,6 +831,7 @@ def test_negative_binomial(self): [779, 647]]) assert_array_equal(actual, desired) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_chisquare(self): mt19937.seed(self.seed) actual = mt19937.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) @@ -845,6 +853,7 @@ def test_noncentral_chisquare(self): [13.484222138963087, 14.377255424602957]]) assert_array_almost_equal(actual, desired, decimal=14) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_f(self): mt19937.seed(self.seed) actual = mt19937.noncentral_f(dfnum=5, dfden=2, nonc=1, @@ -854,9 +863,10 @@ def test_noncentral_f(self): [0.43741599463544162, 1.1774208752428319]]) assert_array_almost_equal(actual, desired, decimal=14) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_normal(self): mt19937.seed(self.seed) - actual = mt19937.normal(loc=.123456789, scale=2.0, size=(3, 2), method='bm') + actual = mt19937.normal(loc=.123456789, scale=2.0, size=(3, 2)) desired = np.array([[2.80378370443726244, 3.59863924443872163], [3.121433477601256, -0.33382987590723379], [4.18552478636557357, 4.46410668111310471]]) @@ -917,6 +927,7 @@ def test_rayleigh_0(self): assert_equal(mt19937.rayleigh(scale=0), 0) assert_raises(ValueError, mt19937.rayleigh, scale=-0.) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_cauchy(self): mt19937.seed(self.seed) actual = mt19937.standard_cauchy(size=(3, 2)) @@ -933,6 +944,7 @@ def test_standard_exponential(self): [0.6116915921431676, 1.50592546727413201]]) assert_array_almost_equal(actual, desired, decimal=15) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_gamma(self): mt19937.seed(self.seed) actual = mt19937.standard_gamma(shape=3, size=(3, 2), method='inv') @@ -945,14 +957,16 @@ def test_standard_gamma_0(self): assert_equal(mt19937.standard_gamma(shape=0), 0) assert_raises(ValueError, mt19937.standard_gamma, shape=-0.) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_normal(self): mt19937.seed(self.seed) - actual = mt19937.standard_normal(size=(3, 2), method='bm') + actual = mt19937.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) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_t(self): mt19937.seed(self.seed) actual = mt19937.standard_t(df=10, size=(3, 2)) @@ -1029,6 +1043,7 @@ def test_vonmises_small(self): r = mt19937.vonmises(mu=0., kappa=1.1e-8, size=10 ** 6) assert_(np.isfinite(r).all()) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_wald(self): mt19937.seed(self.seed) actual = mt19937.wald(mean=1.23, scale=1.54, size=(3, 2)) @@ -1086,6 +1101,7 @@ def test_uniform(self): actual = uniform(low, high * 3) assert_array_almost_equal(actual, desired, decimal=14) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_normal(self): loc = [0] scale = [1] @@ -1096,15 +1112,16 @@ def test_normal(self): 1.8417114045748335]) self.set_seed() - actual = normal(loc * 3, scale, method='bm') + 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, method='bm') + actual = normal(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, normal, loc, bad_scale * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_beta(self): a = [1] b = [2] @@ -1140,6 +1157,7 @@ def test_exponential(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, exponential, bad_scale * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_gamma(self): shape = [1] bad_shape = [-1] @@ -1153,6 +1171,7 @@ def test_standard_gamma(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, std_gamma, bad_shape * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gamma(self): shape = [1] scale = [2] @@ -1175,6 +1194,7 @@ def test_gamma(self): assert_raises(ValueError, gamma, bad_shape, scale * 3) assert_raises(ValueError, gamma, shape, bad_scale * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_f(self): dfnum = [1] dfden = [2] @@ -1197,6 +1217,7 @@ def test_f(self): assert_raises(ValueError, f, bad_dfnum, dfden * 3) assert_raises(ValueError, f, dfnum, bad_dfden * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_f(self): dfnum = [2] dfden = [3] @@ -1243,6 +1264,7 @@ def test_chisquare(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, chisquare, bad_df * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_chisquare(self): df = [1] nonc = [2] @@ -1265,6 +1287,7 @@ def test_noncentral_chisquare(self): assert_raises(ValueError, nonc_chi, bad_df, nonc * 3) assert_raises(ValueError, nonc_chi, df, bad_nonc * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_t(self): df = [1] bad_df = [-1] @@ -1393,6 +1416,7 @@ def test_logistic(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, logistic, loc, bad_scale * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_lognormal(self): mean = [0] sigma = [1] @@ -1425,6 +1449,7 @@ def test_rayleigh(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, rayleigh, bad_scale * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_wald(self): mean = [0.5] scale = [1] @@ -1503,6 +1528,7 @@ def test_binomial(self): assert_raises(ValueError, binom, n, bad_p_one * 3) assert_raises(ValueError, binom, n, bad_p_two * 3) + @pytest.mark.skip(reason='Box-Muller no longer supported') def test_negative_binomial(self): n = [1] p = [0.5] diff --git a/_randomgen/core_prng/tests/test_smoke.py b/_randomgen/core_prng/tests/test_smoke.py index 8e184bce1ac8..a5f35390da45 100644 --- a/_randomgen/core_prng/tests/test_smoke.py +++ b/_randomgen/core_prng/tests/test_smoke.py @@ -86,10 +86,10 @@ def comp_state(state1, state2): def warmup(rg, n=None): if n is None: n = 11 + np.random.randint(0, 20) - rg.standard_normal(n, method='bm') - rg.standard_normal(n, method='zig') - rg.standard_normal(n, method='bm', dtype=np.float32) - rg.standard_normal(n, method='zig', dtype=np.float32) + rg.standard_normal(n) + rg.standard_normal(n) + rg.standard_normal(n, dtype=np.float32) + rg.standard_normal(n, dtype=np.float32) rg.randint(0, 2 ** 24, n, dtype=np.uint64) rg.randint(0, 2 ** 48, n, dtype=np.uint64) rg.standard_gamma(11.0, n) @@ -112,8 +112,8 @@ def _reset_state(self): def test_init(self): rg = RandomGenerator(self.prng()) state = rg.state - rg.standard_normal(1, method='bm') - rg.standard_normal(1, method='zig') + rg.standard_normal(1) + rg.standard_normal(1) rg.state = state new_state = rg.state assert_(comp_state(state, new_state)) @@ -173,7 +173,7 @@ def test_random_sample(self): params_0(self.rg.random_sample) def test_standard_normal_zig(self): - assert_(len(self.rg.standard_normal(10, method='zig')) == 10) + assert_(len(self.rg.standard_normal(10)) == 10) def test_standard_normal(self): assert_(len(self.rg.standard_normal(10)) == 10) @@ -303,22 +303,21 @@ def test_chisquare(self): def test_complex_normal(self): st = self.rg.state vals = self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='zig') + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10) assert_(len(vals) == 10) self.rg.state = st vals2 = [self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='zig') for _ in range(10)] + 2.0 + 7.0j, 10.0, 5.0 - 5.0j) for _ in range(10)] np.testing.assert_allclose(vals, vals2) self.rg.state = st vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, - method='zig') + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j) np.testing.assert_allclose(vals, vals3) self.rg.state = st - norms = self.rg.standard_normal(size=20, method='zig') + norms = self.rg.standard_normal(size=20) norms = np.reshape(norms, (10, 2)) cov = 0.5 * (-5.0) v_real = 7.5 @@ -335,18 +334,17 @@ def test_complex_normal(self): def test_complex_normal_bm(self): st = self.rg.state vals = self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='bm') + 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10) assert_(len(vals) == 10) self.rg.state = st vals2 = [self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='bm') for _ in range(10)] + 2.0 + 7.0j, 10.0, 5.0 - 5.0j) for _ in range(10)] np.testing.assert_allclose(vals, vals2) self.rg.state = st vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, - method='bm') + 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j) np.testing.assert_allclose(vals, vals3) def test_complex_normal_zero_variance(self): @@ -421,15 +419,14 @@ def test_randn(self): assert_equal(vals.shape, (10, 10, 10)) state = self.rg.state - vals = self.rg.randn(10, 10, 10, method='bm') + vals = self.rg.randn(10, 10, 10) self.rg.state = state - assert_equal(vals, self.rg.standard_normal((10, 10, 10), method='bm')) + assert_equal(vals, self.rg.standard_normal((10, 10, 10))) state = self.rg.state - vals_inv = self.rg.randn(10, 10, 10, method='bm') + vals_inv = self.rg.randn(10, 10, 10) self.rg.state = state - vals_zig = self.rg.randn(10, 10, 10, method='zig') - assert_((vals_zig != vals_inv).any()) + vals_zig = self.rg.randn(10, 10, 10) vals = self.rg.randn(10, 10, 10, dtype=np.float32) assert_(vals.shape == (10, 10, 10)) @@ -519,9 +516,9 @@ def test_multivariate_normal(self): 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, method='zig') + x_zig = self.rg.multivariate_normal(mean, cov, 5000) assert_(x.shape == (5000, 2)) - x_inv = self.rg.multivariate_normal(mean, cov, 5000, method='bm') + x_inv = self.rg.multivariate_normal(mean, cov, 5000) assert_(x.shape == (5000, 2)) assert_((x_zig != x_inv).any()) @@ -635,11 +632,11 @@ def test_normal_floats(self): rg = RandomGenerator(self.prng()) warmup(rg) state = rg.state - r1 = rg.standard_normal(11, method='bm', dtype=np.float32) + r1 = rg.standard_normal(11, dtype=np.float32) rg2 = RandomGenerator(self.prng()) warmup(rg2) rg2.state = state - r2 = rg2.standard_normal(11, method='bm', dtype=np.float32) + r2 = rg2.standard_normal(11, dtype=np.float32) assert_array_equal(r1, r2) assert_equal(r1.dtype, np.float32) assert_(comp_state(rg.state, rg2.state)) @@ -648,11 +645,11 @@ def test_normal_zig_floats(self): rg = RandomGenerator(self.prng()) warmup(rg) state = rg.state - r1 = rg.standard_normal(11, method='zig', dtype=np.float32) + r1 = rg.standard_normal(11, dtype=np.float32) rg2 = RandomGenerator(self.prng()) warmup(rg2) rg2.state = state - r2 = rg2.standard_normal(11, method='zig', dtype=np.float32) + r2 = rg2.standard_normal(11, dtype=np.float32) assert_array_equal(r1, r2) assert_equal(r1.dtype, np.float32) assert_(comp_state(rg.state, rg2.state)) @@ -855,8 +852,6 @@ def test_numpy_state(self): state2 = self.rg.state assert_((state[1] == state2['state']['key']).all()) assert_((state[2] == state2['state']['pos'])) - assert_((state[3] == state2['has_gauss'])) - assert_((state[4] == state2['gauss'])) class TestPCG64(RNG): diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 4cf50e3e7669..961d2f3be995 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -104,10 +104,6 @@ cdef class ThreeFry: cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 diff --git a/_randomgen/core_prng/threefry32.pyx b/_randomgen/core_prng/threefry32.pyx index 3a5bc92d62ac..a001d30c705a 100644 --- a/_randomgen/core_prng/threefry32.pyx +++ b/_randomgen/core_prng/threefry32.pyx @@ -105,10 +105,6 @@ cdef class ThreeFry32: free(self._prng) cdef _reset_state_variables(self): - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index fa623382f832..ba727924d6c8 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -96,10 +96,6 @@ cdef class Xoroshiro128: cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 939dc702b557..7fd4d73bafe5 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -88,10 +88,6 @@ cdef class Xorshift1024: cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - self._prng.has_gauss = 0 - self._prng.has_gauss_f = 0 - self._prng.gauss = 0.0 - self._prng.gauss_f = 0.0 def __random_integer(self, bits=64): """ diff --git a/_randomgen/examples/cython/extending_distributions.pyx b/_randomgen/examples/cython/extending_distributions.pyx index 9d16743a6384..65ff44f9320f 100644 --- a/_randomgen/examples/cython/extending_distributions.pyx +++ b/_randomgen/examples/cython/extending_distributions.pyx @@ -5,25 +5,6 @@ from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from core_prng.common cimport * from core_prng.xoroshiro128 import Xoroshiro128 -@cython.boundscheck(False) -@cython.wraparound(False) -def normals_bm(Py_ssize_t n): - cdef Py_ssize_t i - cdef prng_t *rng - cdef const char *capsule_name = "CorePRNG" - cdef double[::1] random_values - - x = Xoroshiro128() - capsule = x.capsule - if not PyCapsule_IsValid(capsule, capsule_name): - raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(n) - for i in range(n): - random_values[i] = random_gauss(rng) - randoms = np.asarray(random_values) - return randoms - @cython.boundscheck(False) @cython.wraparound(False) def normals_zig(Py_ssize_t n): diff --git a/_randomgen/examples/numba/extending_distributions.py b/_randomgen/examples/numba/extending_distributions.py index 5c365f338a6c..230362747882 100644 --- a/_randomgen/examples/numba/extending_distributions.py +++ b/_randomgen/examples/numba/extending_distributions.py @@ -28,25 +28,16 @@ raise RuntimeError('Required DLL/so file was not found.') ffi.cdef(""" -double random_gauss(void *prng_state); double random_gauss_zig(void *prng_state); """) x = Xoroshiro128() xffi = x.cffi prng = xffi.prng -random_gauss = lib.random_gauss random_gauss_zig = lib.random_gauss_zig def normals(n, prng): - out = np.empty(n) - for i in range(n): - out[i] = random_gauss(prng) - return out - - -def normals_zig(n, prng): out = np.empty(n) for i in range(n): out[i] = random_gauss_zig(prng) @@ -54,11 +45,10 @@ def normals_zig(n, prng): normalsj = nb.jit(normals, nopython=True) -normals_zigj = nb.jit(normals_zig, nopython=True) + # Numba requires a memory address for void * # Can also get address from x.ctypes.prng.value prng_address = int(ffi.cast('uintptr_t', prng)) norm = normalsj(1000, prng_address) -norm_zig = normals_zigj(1000, prng_address) From ee51dcf3c29d59e34e1c05e4d48b37580dc46371 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 13 Mar 2018 10:40:48 +0000 Subject: [PATCH 056/138] REF: Remove binomial_t from prng Remvoe binomial_t from each prng_state and use a single implementation at the level of a RandomGenerator --- _randomgen/README.md | 102 ++++++++-------- _randomgen/benchmark.py | 10 +- _randomgen/core_prng/common.pxd | 3 + _randomgen/core_prng/distributions.pxd | 3 +- _randomgen/core_prng/dsfmt.pyx | 4 +- _randomgen/core_prng/generator.pyx | 76 ++++++++++-- _randomgen/core_prng/mt19937.pyx | 4 +- _randomgen/core_prng/pcg32.pyx | 4 +- _randomgen/core_prng/pcg64.pyx | 4 +- _randomgen/core_prng/philox.pyx | 4 +- .../src/distributions/distributions.c | 110 +++++++++--------- .../src/distributions/distributions.h | 3 +- _randomgen/core_prng/threefry.pyx | 4 +- _randomgen/core_prng/threefry32.pyx | 4 +- _randomgen/core_prng/xoroshiro128.pyx | 24 ++-- _randomgen/core_prng/xorshift1024.pyx | 4 +- 16 files changed, 201 insertions(+), 162 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index 095f897ed306..213a6cf4b1f6 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -7,7 +7,14 @@ Experimental Core Pseudo Random Number Generator interface for future NumPy RandomState evolution. This is a library and generic interface for alternative random -generators in Python and NumPy. +generators in Python and NumPy. + + +### Compatibility Warning +Core PRNG no longer supports Box-Muller normal variates and so it not +100% compatible with NumPy (or randomstate). Box-Muller normals are slow +to generate and all functions which previously relied on Box-Muller +normals now use the faster Ziggurat implementation. ## Features @@ -42,14 +49,14 @@ y = rnd.standard_gamma(5.5, 10000, method='zig') * Uniforms (`random_sample`) * Exponentials (`standard_exponential`, both Inverse CDF and Ziggurat) - * Normals (`standard_normal`, both Box-Muller and Ziggurat) - * Standard Gammas (via `standard_gamma`, both Inverse CDF and Ziggurat) + * Normals (`standard_normal`) + * Standard Gammas (via `standard_gamma`) **WARNING**: The 32-bit generators are **experimental** and subject to change. **Note**: There are _no_ plans to extend the alternative precision - generation to all random number types. + generation to all distributions. * Support for filling existing arrays using `out` keyword argument. Currently supported in (both 32- and 64-bit outputs) @@ -61,7 +68,7 @@ y = rnd.standard_gamma(5.5, 10000, method='zig') ## Included Pseudo Random Number Generators -This modules includes a number of alternative random +This module includes a number of alternative random number generators in addition to the MT19937 that is included in NumPy. The RNGs include: @@ -71,23 +78,22 @@ The RNGs include: SSE2-aware version of the MT19937 generator that is especially fast at generating doubles * [xoroshiro128+](http://xoroshiro.di.unimi.it/) and - [xorshift1024*](http://xorshift.di.unimi.it/) + [xorshift1024*φ](http://xorshift.di.unimi.it/) * [PCG64](http:w//www.pcg-random.org/) -* ThreeFry and Philox implementationf from [Random123](https://www.deshawrsearch.com/resources_random123.html) +* ThreeFry and Philox from [Random123](https://www.deshawrsearch.com/resources_random123.html) ## Differences from `numpy.random.RandomState` ### New Features * `standard_normal`, `normal`, `randn` and `multivariate_normal` all - support an additional `method` keyword argument which can be `bm` or - `zig` where `bm` corresponds to the current method using the Box-Muller - transformation and `zig` uses the much faster (100%+) Ziggurat method. -* `standard_exponential` and `standard_gamma` both support an additional + use the much faster (100%+) Ziggurat method. +* `standard_gamma` and `gamma` both use the much faster Ziggurat method. +* `standard_exponential` `exponential` both support an additional `method` keyword argument which can be `inv` or `zig` where `inv` corresponds to the current method using the inverse CDF and `zig` uses the much faster (100%+) Ziggurat method. * Core random number generators can produce either single precision (`np.float32`) or double precision (`np.float64`, the default) using - an the optional keyword argument `dtype` + the optional keyword argument `dtype` * Core random number generators can fill existing arrays using the `out` keyword argument @@ -126,7 +132,7 @@ The version matched the latest version of NumPy where ## Documentation An occasionally updated build of the documentation is available on -[my github pages](http://bashtage.github.io/core-prng/). +[my GitHub pages](http://bashtage.github.io/core-prng/). ## Plans This module is essentially complete. There are a few rough edges that @@ -139,8 +145,8 @@ need to be smoothed. Building requires: * Python (2.7, 3.4, 3.5, 3.6) - * NumPy (1.9, 1.10, 1.11, 1.12) - * Cython (0.22, **not** 0.23, 0.24, 0.25) + * NumPy (1.10, 1.11, 1.12, 1.13, 1.14) + * Cython (0.25+) * tempita (0.5+), if not provided by Cython Testing requires pytest (3.0+). @@ -151,12 +157,12 @@ versions. ## Development and Testing All development has been on 64-bit Linux, and it is regularly tested on -Travis-CI (Linux) and Appveyor (Windows). The library is occasionally -tested on Linux 32-bit, OSX 10.13, Free BSD 11.1. +Travis-CI (Linux/OSX) and Appveyor (Windows). The library is occasionally +tested on Linux 32-bit and Free BSD 11.1. Basic tests are in place for all RNGs. The MT19937 is tested against NumPy's implementation for identical results. It also passes NumPy's -test suite. +test suite where still relevant. ## Installing @@ -206,37 +212,37 @@ NumPy's mt19937. ``` Speed-up relative to NumPy (Uniform Doubles) ************************************************************ -MT19937 22.9% -PCG64 109.6% -Philox -6.2% -ThreeFry -16.6% -Xoroshiro128 161.0% -Xorshift1024 119.9% +DSFMT 137.1% +MT19937 21.0% +PCG32 101.2% +PCG64 110.7% +Philox -2.7% +ThreeFry -11.4% +ThreeFry32 -62.3% +Xoroshiro128 181.4% +Xorshift1024 141.8% Speed-up relative to NumPy (64-bit unsigned integers) ************************************************************ -MT19937 6.2% -PCG64 88.2% -Philox -23.0% -ThreeFry -26.5% -Xoroshiro128 142.4% -Xorshift1024 107.5% - -Speed-up relative to NumPy (Standard normals (Box-Muller)) -************************************************************ -MT19937 17.7% -PCG64 35.6% -Philox -26.2% -ThreeFry -16.9% -Xoroshiro128 57.9% -Xorshift1024 40.9% - -Speed-up relative to NumPy (Standard normals (Ziggurat)) +DSFMT 24.8% +MT19937 15.0% +PCG32 92.6% +PCG64 99.0% +Philox -20.4% +ThreeFry -21.7% +ThreeFry32 -64.4% +Xoroshiro128 164.2% +Xorshift1024 120.8% + +Speed-up relative to NumPy (Standard normals) ************************************************************ -MT19937 107.9% -PCG64 149.6% -Philox 11.1% -ThreeFry 78.8% -Xoroshiro128 224.7% -Xorshift1024 158.6% -``` \ No newline at end of file +DSFMT 299.4% +MT19937 271.2% +PCG32 364.5% +PCG64 364.2% +Philox 256.9% +ThreeFry 236.0% +ThreeFry32 97.0% +Xoroshiro128 477.4% +Xorshift1024 360.7% +``` diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 3b489781a3b8..462f405fe5cc 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -103,16 +103,9 @@ def timer_64bit(): run_timer(dist, command, command_numpy, SETUP, '64-bit unsigned integers') -def timer_normal(): - dist = 'standard_normal' - command = 'rg.standard_normal(1000000, method="bm")' - command_numpy = 'rg.standard_normal(1000000)' - run_timer(dist, command, command_numpy, SETUP, 'Box-Muller normals') - - def timer_normal_zig(): dist = 'standard_normal' - command = 'rg.standard_normal(1000000, method="zig")' + command = 'rg.standard_normal(1000000)' command_numpy = 'rg.standard_normal(1000000)' run_timer(dist, command, command_numpy, SETUP, 'Standard normals (Ziggurat)') @@ -129,5 +122,4 @@ def timer_normal_zig(): timer_raw() timer_32bit() timer_64bit() - timer_normal() timer_normal_zig() diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 43981f476f15..c571c57a2950 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -21,6 +21,9 @@ cdef enum ConstraintType: ctypedef ConstraintType constraint_type +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); diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd index e26effa1adaa..29dc5f114fa3 100644 --- a/_randomgen/core_prng/distributions.pxd +++ b/_randomgen/core_prng/distributions.pxd @@ -32,7 +32,6 @@ cdef extern from "src/distributions/distributions.h": uint32_t (*next_uint32)(void *st) nogil double (*next_double)(void *st) nogil uint64_t (*next_raw)(void *st) nogil - binomial_t *binomial ctypedef prng prng_t @@ -85,7 +84,7 @@ cdef extern from "src/distributions/distributions.h": long random_poisson(prng_t *prng_state, double lam) nogil long random_negative_binomial(prng_t *prng_state, double n, double p) nogil - long random_binomial(prng_t *prng_state, double p, long n) nogil + long random_binomial(prng_t *prng_state, double p, long n, binomial_t *binomial) nogil long random_logseries(prng_t *prng_state, double p) nogil long random_geometric_search(prng_t *prng_state, double p) nogil long random_geometric_inversion(prng_t *prng_state, double p) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 4280c22f9b3f..552941b189d1 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -6,7 +6,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -88,7 +88,6 @@ cdef class DSFMT: self.rng_state.buffered_uniforms = PyArray_calloc_aligned(DSFMT_N64, sizeof(double)) self.rng_state.buffer_loc = DSFMT_N64 self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state self._prng.next_uint64 = &dsfmt_uint64 @@ -114,7 +113,6 @@ cdef class DSFMT: PyArray_free_aligned(self.rng_state.state) PyArray_free_aligned(self.rng_state.buffered_uniforms) free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index d6bda579ba18..51cdebc19550 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -3,9 +3,6 @@ import operator import warnings -import numpy as np -cimport numpy as np -cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles from common cimport * @@ -13,9 +10,10 @@ from distributions cimport * from bounded_integers cimport * from libc cimport string from libc.stdlib cimport malloc, free - cimport numpy as np import numpy as np +cimport cython + from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from common cimport * @@ -58,6 +56,7 @@ cdef class RandomGenerator: """ cdef public object __core_prng cdef prng_t *_prng + cdef binomial_t *_binomial cdef object lock poisson_lam_max = POISSON_LAM_MAX @@ -71,8 +70,12 @@ cdef class RandomGenerator: if not PyCapsule_IsValid(capsule, anon_name): raise ValueError("Invalid prng. The prng must be instantized.") self._prng = PyCapsule_GetPointer(capsule, anon_name) + self._binomial = malloc(sizeof(binomial_t)) self.lock = Lock() + def __dealloc__(self): + free(self._binomial) + def __repr__(self): return self.__str__() + ' at 0x{:X}'.format(id(self)) @@ -3160,10 +3163,64 @@ cdef class RandomGenerator: >>> sum(np.random.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ - return disc(&random_binomial, self._prng, size, self.lock, 1, 1, - p, 'p', CONS_BOUNDED_0_1_NOTNAN, - n, 'n', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE) + + # 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 np.int_t *randoms_data + cdef np.broadcast it + + p_arr = 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.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_NOTNAN) + check_array_constraint(n_arr, 'n', CONS_NON_NEGATIVE) + if size is not None: + randoms = np.empty(size, np.int) + else: + it = np.PyArray_MultiIterNew2(p_arr, n_arr) + randoms = np.empty(it.shape, np.int) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._prng, _dp, _in, self._binomial) + + np.PyArray_MultiIter_NEXT(it) + + return randoms + + _dp = PyFloat_AsDouble(p) + _in = PyInt_AsLong(n) + check_constraint(_dp, 'p', CONS_BOUNDED_0_1_NOTNAN) + check_constraint(_in, 'n', CONS_NON_NEGATIVE) + + if size is None: + with self.lock: + return random_binomial(self._prng, _dp, _in, self._binomial) + + randoms = np.empty(size, np.int) + cnt = np.PyArray_SIZE(randoms) + randoms_data = np.PyArray_DATA(randoms) + + with self.lock, nogil: + for i in range(cnt): + randoms_data[i] = random_binomial(self._prng, _dp, _in, + self._binomial) + + return randoms + def negative_binomial(self, n, p, size=None): """ @@ -3913,7 +3970,8 @@ cdef class RandomGenerator: Sum = 1.0 dn = n for j in range(d-1): - mnix[i+j] = random_binomial(self._prng, pix[j]/Sum, dn) + mnix[i+j] = random_binomial(self._prng, pix[j]/Sum, dn, + self._binomial) dn = dn - mnix[i+j] if dn <= 0: break diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/core_prng/mt19937.pyx index e755d958d351..9622b725a236 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/core_prng/mt19937.pyx @@ -7,7 +7,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t import core_prng.pickle from core_prng.entropy import random_entropy @@ -61,7 +61,6 @@ cdef class MT19937: def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -75,7 +74,6 @@ cdef class MT19937: def __dealloc__(self): free(self.rng_state) - free(self._prng.binomial) free(self._prng) # Pickling support: diff --git a/_randomgen/core_prng/pcg32.pyx b/_randomgen/core_prng/pcg32.pyx index 9e46461c6b1b..df97e1a815df 100644 --- a/_randomgen/core_prng/pcg32.pyx +++ b/_randomgen/core_prng/pcg32.pyx @@ -5,7 +5,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -68,7 +68,6 @@ cdef class PCG32: self.rng_state = malloc(sizeof(pcg32_state)) self.rng_state.pcg_state = malloc(sizeof(pcg32_random_t)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed, inc) self._prng.state = self.rng_state @@ -94,7 +93,6 @@ cdef class PCG32: def __dealloc__(self): free(self.rng_state) - free(self._prng.binomial) free(self._prng) def __random_integer(self, bits=64): diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index d0c3e5f7638d..1d6b504f8038 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -5,7 +5,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -83,7 +83,6 @@ cdef class PCG64: self.rng_state = malloc(sizeof(pcg64_state)) self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed, inc) self._prng.state = self.rng_state @@ -109,7 +108,6 @@ cdef class PCG64: def __dealloc__(self): free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 59d6359adb56..399c95bfad58 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -4,7 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -76,7 +76,6 @@ cdef class Philox: self.rng_state.key = malloc( sizeof(philox4x64_key_t)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed, counter, key) self._prng.state = self.rng_state @@ -104,7 +103,6 @@ cdef class Philox: free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index aa1284ed0afd..3dd83e66d38a 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -653,50 +653,50 @@ long random_negative_binomial(prng_t *prng_state, double n, double p) { return random_poisson(prng_state, Y); } -long random_binomial_btpe(prng_t *prng_state, long n, double p) { +long random_binomial_btpe(prng_t *prng_state, long 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; long m, y, k, i; - if (!(prng_state->binomial->has_binomial) || - (prng_state->binomial->nsave != n) || - (prng_state->binomial->psave != p)) { + if (!(binomial->has_binomial) || + (binomial->nsave != n) || + (binomial->psave != p)) { /* initialize */ - prng_state->binomial->nsave = n; - prng_state->binomial->psave = p; - prng_state->binomial->has_binomial = 1; - prng_state->binomial->r = r = min(p, 1.0 - p); - prng_state->binomial->q = q = 1.0 - r; - prng_state->binomial->fm = fm = n * r + r; - prng_state->binomial->m = m = (long)floor(prng_state->binomial->fm); - prng_state->binomial->p1 = p1 = + 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 = (long)floor(binomial->fm); + binomial->p1 = p1 = floor(2.195 * sqrt(n * r * q) - 4.6 * q) + 0.5; - prng_state->binomial->xm = xm = m + 0.5; - prng_state->binomial->xl = xl = xm - p1; - prng_state->binomial->xr = xr = xm + p1; - prng_state->binomial->c = c = 0.134 + 20.5 / (15.3 + m); + 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); - prng_state->binomial->laml = laml = a * (1.0 + a / 2.0); + binomial->laml = laml = a * (1.0 + a / 2.0); a = (xr - fm) / (xr * q); - prng_state->binomial->lamr = lamr = a * (1.0 + a / 2.0); - prng_state->binomial->p2 = p2 = p1 * (1.0 + 2.0 * c); - prng_state->binomial->p3 = p3 = p2 + c / laml; - prng_state->binomial->p4 = p4 = p3 + c / lamr; + 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 = prng_state->binomial->r; - q = prng_state->binomial->q; - fm = prng_state->binomial->fm; - m = prng_state->binomial->m; - p1 = prng_state->binomial->p1; - xm = prng_state->binomial->xm; - xl = prng_state->binomial->xl; - xr = prng_state->binomial->xr; - c = prng_state->binomial->c; - laml = prng_state->binomial->laml; - lamr = prng_state->binomial->lamr; - p2 = prng_state->binomial->p2; - p3 = prng_state->binomial->p3; - p4 = prng_state->binomial->p4; + 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 ... */ @@ -794,26 +794,26 @@ long random_binomial_btpe(prng_t *prng_state, long n, double p) { return y; } -long random_binomial_inversion(prng_t *prng_state, long n, double p) { +long random_binomial_inversion(prng_t *prng_state, long n, double p, binomial_t* binomial) { double q, qn, np, px, U; long X, bound; - if (!(prng_state->binomial->has_binomial) || - (prng_state->binomial->nsave != n) || - (prng_state->binomial->psave != p)) { - prng_state->binomial->nsave = n; - prng_state->binomial->psave = p; - prng_state->binomial->has_binomial = 1; - prng_state->binomial->q = q = 1.0 - p; - prng_state->binomial->r = qn = exp(n * log(q)); - prng_state->binomial->c = np = n * p; - prng_state->binomial->m = 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 = (long)min(n, np + 10.0 * sqrt(np * q + 1)); } else { - q = prng_state->binomial->q; - qn = prng_state->binomial->r; - np = prng_state->binomial->c; - bound = prng_state->binomial->m; + q = binomial->q; + qn = binomial->r; + np = binomial->c; + bound = binomial->m; } X = 0; px = qn; @@ -832,21 +832,21 @@ long random_binomial_inversion(prng_t *prng_state, long n, double p) { return X; } -long random_binomial(prng_t *prng_state, double p, long n) { +long random_binomial(prng_t *prng_state, double p, long n, binomial_t * binomial) { double q; if (p <= 0.5) { if (p * n <= 30.0) { - return random_binomial_inversion(prng_state, n, p); + return random_binomial_inversion(prng_state, n, p, binomial); } else { - return random_binomial_btpe(prng_state, n, p); + return random_binomial_btpe(prng_state, n, p, binomial); } } else { q = 1.0 - p; if (q * n <= 30.0) { - return n - random_binomial_inversion(prng_state, n, q); + return n - random_binomial_inversion(prng_state, n, q, binomial); } else { - return n - random_binomial_btpe(prng_state, n, q); + return n - random_binomial_btpe(prng_state, n, q, binomial); } } } diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 95e839cb0967..9b1a70e9e1fc 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -59,7 +59,6 @@ typedef struct prng { uint32_t (*next_uint32)(void *st); double (*next_double)(void *st); uint64_t (*next_raw)(void *st); - binomial_t *binomial; } prng_t; /* Inline generators for internal use */ @@ -140,7 +139,7 @@ DECLDIR double random_triangular(prng_t *prng_state, double left, double mode, DECLDIR long random_poisson(prng_t *prng_state, double lam); DECLDIR long random_negative_binomial(prng_t *prng_state, double n, double p); -DECLDIR long random_binomial(prng_t *prng_state, double p, long n); +DECLDIR long random_binomial(prng_t *prng_state, double p, long n, binomial_t* binomial); DECLDIR long random_logseries(prng_t *prng_state, double p); DECLDIR long random_geometric_search(prng_t *prng_state, double p); DECLDIR long random_geometric_inversion(prng_t *prng_state, double p); diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 961d2f3be995..197fe4aaa703 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -4,7 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -70,7 +70,6 @@ cdef class ThreeFry: self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed, counter, key) self._prng.state = self.rng_state @@ -98,7 +97,6 @@ cdef class ThreeFry: free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): diff --git a/_randomgen/core_prng/threefry32.pyx b/_randomgen/core_prng/threefry32.pyx index a001d30c705a..ef31bfb1b328 100644 --- a/_randomgen/core_prng/threefry32.pyx +++ b/_randomgen/core_prng/threefry32.pyx @@ -4,7 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -73,7 +73,6 @@ cdef class ThreeFry32: self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed, counter, key) self._prng.state = self.rng_state @@ -101,7 +100,6 @@ cdef class ThreeFry32: free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index ba727924d6c8..0301c0ea20f3 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -9,7 +9,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -55,13 +55,12 @@ cdef class Xoroshiro128: cdef xoroshiro128_state *rng_state cdef prng_t *_prng cdef public object capsule - cdef object ctypes - cdef object cffi + cdef object _ctypes + cdef object _cffi def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -70,8 +69,8 @@ cdef class Xoroshiro128: self._prng.next_double = &xoroshiro128_double self._prng.next_raw = &xoroshiro128_uint64 - self.ctypes = None - self.cffi = None + self._ctypes = None + self._cffi = None cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) @@ -90,7 +89,6 @@ cdef class Xoroshiro128: def __dealloc__(self): free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): @@ -197,12 +195,12 @@ cdef class Xoroshiro128: @property def ctypes(self): - if self.ctypes is not None: - return self.ctypes + if self._ctypes is not None: + return self._ctypes import ctypes - self.ctypes = interface(self.rng_state, + self._ctypes = interface(self.rng_state, ctypes.c_void_p(self.rng_state), ctypes.cast(&xoroshiro128_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, @@ -218,15 +216,15 @@ cdef class Xoroshiro128: @property def cffi(self): - if self.cffi is not None: - return self.cffi + if self._cffi is not None: + return self._cffi try: import cffi except ImportError: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self.cffi = interface(self.rng_state, + self._cffi = interface(self.rng_state, ffi.cast('void *',self.rng_state), ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 7fd4d73bafe5..73fa052850bb 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -5,7 +5,7 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t, binomial_t +from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle cimport entropy @@ -56,7 +56,6 @@ cdef class Xorshift1024: def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) self._prng = malloc(sizeof(prng_t)) - self._prng.binomial = malloc(sizeof(binomial_t)) self.seed(seed) self._prng.state = self.rng_state @@ -82,7 +81,6 @@ cdef class Xorshift1024: def __dealloc__(self): free(self.rng_state) - free(self._prng.binomial) free(self._prng) cdef _reset_state_variables(self): From fde774259218521b5eae2995b5049e0ff5e0ad64 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 13 Mar 2018 12:25:07 +0000 Subject: [PATCH 057/138] ENH: Switch to int64 Switch to int64 to avoid platform-dependencies for integer values randoms --- _randomgen/README.md | 1 + _randomgen/TODO.md | 27 ---- _randomgen/core_prng/common.pxd | 14 +- _randomgen/core_prng/common.pyx | 102 ++++++------- _randomgen/core_prng/distributions.pxd | 30 ++-- _randomgen/core_prng/generator.pyx | 54 ++++--- .../src/distributions/distributions.c | 134 ++++++++---------- .../src/distributions/distributions.h | 45 ++++-- .../core_prng/tests/test_numpy_mt19937.py | 9 +- _randomgen/demo.py | 103 -------------- 10 files changed, 196 insertions(+), 323 deletions(-) delete mode 100644 _randomgen/TODO.md delete mode 100644 _randomgen/demo.py diff --git a/_randomgen/README.md b/_randomgen/README.md index 213a6cf4b1f6..19f216b3eaf4 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -96,6 +96,7 @@ The RNGs include: the optional keyword argument `dtype` * Core random number generators can fill existing arrays using the `out` keyword argument +* Standardizes integer-values random values as int64 for all platforms. ### New Functions diff --git a/_randomgen/TODO.md b/_randomgen/TODO.md deleted file mode 100644 index ed2697d9e826..000000000000 --- a/_randomgen/TODO.md +++ /dev/null @@ -1,27 +0,0 @@ -# TODO -13. Simplify state - -## Done -1. Add PCG64 -2. Add dSFMT -3. Add xorshift2014 -4. Augment state to include has_gauss and gauss -5. Augment state to have binomial structure -6. Port over 0 parameter distributions - * standard normal ziggurat - * standard normal ziggurat float - * standard exponential ziggurat - * standard exponential ziggurat float - * standard exponential float - * standard normal - * standard normal float - * standard gamma - Not implement: This is a 1 param - * standard gamma float - Not implement: This is a 1 param -7. Remove SplitMix64 as an external generator -8. Restore ability to use `out` in core distributions -9. Add correct carry for ThreeFry to allow full set of counters. Important when implemeting jump -10. Seed/Inc for PCG64 -11. Advance/Jump for PCG64 -12. Key/Counter for ThreeFry -0. **NOT IMPLEMENTABLE** due to limits on inheritance in Cython: Use inheritance to simplify CorePRNG structure. The natural base is - xoroshiro128. diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index c571c57a2950..66d961edc4ef 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -38,12 +38,12 @@ ctypedef double (*random_double_3)(prng_t *state, double a, double b, double c) ctypedef float (*random_float_0)(prng_t *state) nogil ctypedef float (*random_float_1)(prng_t *state, float a) nogil -ctypedef long (*random_uint_0)(prng_t *state) nogil -ctypedef long (*random_uint_d)(prng_t *state, double a) nogil -ctypedef long (*random_uint_dd)(prng_t *state, double a, double b) nogil -ctypedef long (*random_uint_di)(prng_t *state, double a, uint64_t b) nogil -ctypedef long (*random_uint_i)(prng_t *state, long a) nogil -ctypedef long (*random_uint_iii)(prng_t *state, long a, long b, long c) nogil +ctypedef int64_t (*random_uint_0)(prng_t *state) nogil +ctypedef int64_t (*random_uint_d)(prng_t *state, double a) nogil +ctypedef int64_t (*random_uint_dd)(prng_t *state, double a, double b) nogil +ctypedef int64_t (*random_uint_di)(prng_t *state, double a, uint64_t b) nogil +ctypedef int64_t (*random_uint_i)(prng_t *state, int64_t a) nogil +ctypedef int64_t (*random_uint_iii)(prng_t *state, int64_t a, int64_t b, int64_t c) nogil ctypedef uint32_t (*random_uint_0_32)(prng_t *state) nogil ctypedef uint32_t (*random_uint_1_i_32)(prng_t *state, uint32_t a) nogil @@ -71,7 +71,7 @@ cdef object cont(void *func, prng_t *state, object size, object lock, int narg, object out) cdef object disc(void *func, prng_t *state, object size, object lock, - int narg_double, int narg_long, + 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) diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index fb3e96697bae..b25510e1a955 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -407,7 +407,7 @@ cdef object discrete_broadcast_d(void *func, prng_t *state, object size, object np.ndarray a_arr, object a_name, constraint_type a_constraint): cdef np.ndarray randoms - cdef long *randoms_data + cdef int64_t *randoms_data cdef np.broadcast it cdef random_uint_d f = (func) cdef np.npy_intp i, n @@ -416,12 +416,12 @@ cdef object discrete_broadcast_d(void *func, prng_t *state, object size, object check_array_constraint(a_arr, a_name, a_constraint) if size is not None: - randoms = np.empty(size, np.int) + 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_LONG) + randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_INT64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) n = np.PyArray_SIZE(randoms) it = np.PyArray_MultiIterNew2(randoms, a_arr) @@ -438,7 +438,7 @@ cdef object discrete_broadcast_dd(void *func, prng_t *state, object size, object 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 long *randoms_data + cdef int64_t *randoms_data cdef np.broadcast it cdef random_uint_dd f = (func) cdef np.npy_intp i, n @@ -449,13 +449,13 @@ cdef object discrete_broadcast_dd(void *func, prng_t *state, object size, object check_array_constraint(b_arr, b_name, b_constraint) if size is not None: - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) else: it = np.PyArray_MultiIterNew2(a_arr, b_arr) - randoms = np.empty(it.shape, np.int) - # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_LONG) + randoms = np.empty(it.shape, np.int64) + # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_INT64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) n = np.PyArray_SIZE(randoms) it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr) @@ -473,7 +473,7 @@ cdef object discrete_broadcast_di(void *func, prng_t *state, object size, object 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 long *randoms_data + cdef int64_t *randoms_data cdef np.broadcast it cdef random_uint_di f = (func) cdef np.npy_intp i, n @@ -486,20 +486,20 @@ cdef object discrete_broadcast_di(void *func, prng_t *state, object size, object check_array_constraint(b_arr, b_name, b_constraint) if size is not None: - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) else: it = np.PyArray_MultiIterNew2(a_arr, b_arr) - randoms = np.empty(it.shape, np.int) + randoms = np.empty(it.shape, np.int64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] - b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = f(state, a_val, b_val) + b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] + (np.PyArray_MultiIter_DATA(it, 0))[0] = f(state, a_val, b_val) np.PyArray_MultiIter_NEXT(it) @@ -510,7 +510,7 @@ cdef object discrete_broadcast_iii(void *func, prng_t *state, object size, objec 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 long *randoms_data + cdef int64_t *randoms_data cdef np.broadcast it cdef random_uint_iii f = (func) cdef np.npy_intp i, n @@ -525,20 +525,20 @@ cdef object discrete_broadcast_iii(void *func, prng_t *state, object size, objec check_array_constraint(c_arr, c_name, c_constraint) if size is not None: - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) else: it = np.PyArray_MultiIterNew3(a_arr, b_arr, c_arr) - randoms = np.empty(it.shape, np.int) + randoms = np.empty(it.shape, np.int64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] - b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] - c_val = (np.PyArray_MultiIter_DATA(it, 3))[0] + a_val = (np.PyArray_MultiIter_DATA(it, 1))[0] + b_val = (np.PyArray_MultiIter_DATA(it, 2))[0] + c_val = (np.PyArray_MultiIter_DATA(it, 3))[0] randoms_data[i] = f(state, a_val, b_val, c_val) np.PyArray_MultiIter_NEXT(it) @@ -548,7 +548,7 @@ cdef object discrete_broadcast_iii(void *func, prng_t *state, object size, objec cdef object discrete_broadcast_i(void *func, prng_t *state, object size, object lock, np.ndarray a_arr, object a_name, constraint_type a_constraint): cdef np.ndarray randoms - cdef long *randoms_data + cdef int64_t *randoms_data cdef np.broadcast it cdef random_uint_i f = (func) cdef np.npy_intp i, n @@ -557,32 +557,32 @@ cdef object discrete_broadcast_i(void *func, prng_t *state, object size, object check_array_constraint(a_arr, a_name, a_constraint) if size is not None: - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) else: - randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_LONG) + randoms = np.PyArray_SimpleNew(np.PyArray_NDIM(a_arr), np.PyArray_DIMS(a_arr), np.NPY_INT64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + a_val = (np.PyArray_MultiIter_DATA(it, 1))[0] randoms_data[i] = f(state, a_val) np.PyArray_MultiIter_NEXT(it) return randoms -# Needs double , double-double , double-long, long , long-long-long +# Needs double , double-double , double-int64_t, int64_t , int64_t-int64_t-int64_t cdef object disc(void *func, prng_t *state, object size, object lock, - int narg_double, int narg_long, + 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 long _ia = 0, _ib = 0 , _ic = 0 + cdef int64_t _ia = 0, _ib = 0 , _ic = 0 cdef bint is_scalar = True if narg_double > 0: a_arr = np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED) @@ -590,22 +590,22 @@ cdef object disc(void *func, prng_t *state, object size, object lock, if narg_double > 1: b_arr = np.PyArray_FROM_OTF(b, np.NPY_DOUBLE, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0 - elif narg_long == 1: - b_arr = np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED) + elif narg_int64 == 1: + b_arr = 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_long > 0: - a_arr = np.PyArray_FROM_OTF(a, np.NPY_LONG, np.NPY_ALIGNED) + if narg_int64 > 0: + a_arr = np.PyArray_FROM_OTF(a, np.NPY_INT64, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(a_arr) == 0 - if narg_long > 1: - b_arr = np.PyArray_FROM_OTF(b, np.NPY_LONG, np.NPY_ALIGNED) + if narg_int64 > 1: + b_arr = np.PyArray_FROM_OTF(b, np.NPY_INT64, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(b_arr) == 0 - if narg_long > 2 : - c_arr = np.PyArray_FROM_OTF(c, np.NPY_LONG, np.NPY_ALIGNED) + if narg_int64 > 2 : + c_arr = 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_long == 0: + if narg_int64 == 0: if narg_double == 1: return discrete_broadcast_d(func, state, size, lock, a_arr, a_name, a_constraint) @@ -613,7 +613,7 @@ cdef object disc(void *func, prng_t *state, object size, object lock, return discrete_broadcast_dd(func, state, size, lock, a_arr, a_name, a_constraint, b_arr, b_name, b_constraint) - elif narg_long == 1: + elif narg_int64 == 1: if narg_double == 0: return discrete_broadcast_i(func, state, size, lock, a_arr, a_name, a_constraint) @@ -634,34 +634,34 @@ cdef object disc(void *func, prng_t *state, object size, object lock, _db = PyFloat_AsDouble(b) if b_constraint != CONS_NONE and is_scalar: check_constraint(_db, b_name, b_constraint) - elif narg_long == 1: + elif narg_int64 == 1: _ib = PyInt_AsLong(b) if b_constraint != CONS_NONE and is_scalar: check_constraint(_ib, b_name, b_constraint) else: - if narg_long > 0: + if narg_int64 > 0: _ia = PyInt_AsLong(a) if a_constraint != CONS_NONE and is_scalar: check_constraint(_ia, a_name, a_constraint) - if narg_long > 1: + if narg_int64 > 1: _ib = PyInt_AsLong(b) if b_constraint != CONS_NONE and is_scalar: check_constraint(_ib, b_name, b_constraint) - if narg_long > 2 : + if narg_int64 > 2 : _ic = PyInt_AsLong(c) if c_constraint != CONS_NONE and is_scalar: check_constraint(_ic, c_name, c_constraint) if size is None: with lock: - if narg_long == 0: + if narg_int64 == 0: if narg_double == 0: return (func)(state) elif narg_double == 1: return (func)(state, _da) elif narg_double == 2: return (func)(state, _da, _db) - elif narg_long == 1: + elif narg_int64 == 1: if narg_double == 0: return (func)(state, _ia) if narg_double == 1: @@ -670,8 +670,8 @@ cdef object disc(void *func, prng_t *state, object size, object lock, return (func)(state, _ia, _ib, _ic) cdef np.npy_intp i, n - cdef np.ndarray randoms = np.empty(size, np.int) - cdef np.int_t *randoms_data + cdef np.ndarray randoms = 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; @@ -680,10 +680,10 @@ cdef object disc(void *func, prng_t *state, object size, object lock, cdef random_uint_iii fiii; n = np.PyArray_SIZE(randoms) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) with lock, nogil: - if narg_long == 0: + if narg_int64 == 0: if narg_double == 0: f0 = (func) for i in range(n): @@ -696,7 +696,7 @@ cdef object disc(void *func, prng_t *state, object size, object lock, fdd = (func) for i in range(n): randoms_data[i] = fdd(state, _da, _db) - elif narg_long == 1: + elif narg_int64 == 1: if narg_double == 0: fi = (func) for i in range(n): diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd index 29dc5f114fa3..44f3520690ef 100644 --- a/_randomgen/core_prng/distributions.pxd +++ b/_randomgen/core_prng/distributions.pxd @@ -8,11 +8,11 @@ cdef extern from "src/distributions/distributions.h": struct s_binomial_t: int has_binomial double psave - long nsave + int64_t nsave double r double q double fm - long m + int64_t m double p1 double xm double xl @@ -50,8 +50,8 @@ cdef extern from "src/distributions/distributions.h": int64_t random_positive_int64(prng_t *prng_state) nogil int32_t random_positive_int32(prng_t *prng_state) nogil - long random_positive_int(prng_t *prng_state) nogil - unsigned long random_uint(prng_t *prng_state) nogil + int64_t random_positive_int(prng_t *prng_state) nogil + uint64_t random_uint(prng_t *prng_state) nogil double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil @@ -82,17 +82,17 @@ cdef extern from "src/distributions/distributions.h": double random_triangular(prng_t *prng_state, double left, double mode, double right) nogil - long random_poisson(prng_t *prng_state, double lam) nogil - long random_negative_binomial(prng_t *prng_state, double n, double p) nogil - long random_binomial(prng_t *prng_state, double p, long n, binomial_t *binomial) nogil - long random_logseries(prng_t *prng_state, double p) nogil - long random_geometric_search(prng_t *prng_state, double p) nogil - long random_geometric_inversion(prng_t *prng_state, double p) nogil - long random_geometric(prng_t *prng_state, double p) nogil - long random_zipf(prng_t *prng_state, double a) nogil - long random_hypergeometric(prng_t *prng_state, long good, long bad, - long sample) nogil - unsigned long random_interval(prng_t *prng_state, unsigned long max) nogil + int64_t random_poisson(prng_t *prng_state, double lam) nogil + int64_t random_negative_binomial(prng_t *prng_state, double n, double p) nogil + int64_t random_binomial(prng_t *prng_state, double p, int64_t n, binomial_t *binomial) nogil + int64_t random_logseries(prng_t *prng_state, double p) nogil + int64_t random_geometric_search(prng_t *prng_state, double p) nogil + int64_t random_geometric_inversion(prng_t *prng_state, double p) nogil + int64_t random_geometric(prng_t *prng_state, double p) nogil + int64_t random_zipf(prng_t *prng_state, double a) nogil + int64_t random_hypergeometric(prng_t *prng_state, int64_t good, int64_t bad, + int64_t sample) nogil + uint64_t random_interval(prng_t *prng_state, uint64_t max) nogil uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, uint64_t rng, uint64_t mask) nogil uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index 51cdebc19550..ec52a1839f0b 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -487,14 +487,14 @@ cdef class RandomGenerator: """ cdef np.npy_intp n cdef np.ndarray randoms - cdef long *randoms_data + cdef int64_t *randoms_data if size is None: with self.lock: return random_positive_int(self._prng) - randoms = np.empty(size, dtype=np.int) - randoms_data = np.PyArray_DATA(randoms) + randoms = np.empty(size, dtype=np.int64) + randoms_data = np.PyArray_DATA(randoms) n = np.PyArray_SIZE(randoms) for i in range(n): @@ -776,7 +776,7 @@ cdef class RandomGenerator: 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=np.int64) flat_found = found.ravel() while n_uniq < size: x = self.rand(size - n_uniq) @@ -1039,13 +1039,11 @@ cdef class RandomGenerator: """ random_integers(low, high=None, size=None) - Random integers of type np.int between `low` and `high`, inclusive. + Random integers of type np.int64 between `low` and `high`, inclusive. - Return random integers of type np.int from the "discrete uniform" + Return random integers of type np.int64 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. + None (the default), then results are from [1, `low`]. This function has been deprecated. Use randint instead. @@ -1418,7 +1416,7 @@ cdef class RandomGenerator: it = np.PyArray_MultiIterNew5(randoms, oloc, v_real, v_imag, rho) with self.lock, nogil: - n2 = 2 * n # Avoid compiler noise for cast to long + n2 = 2 * n # Avoid compiler noise for cast for i in range(n2): randoms_data[i] = random_gauss_zig(self._prng) with nogil: @@ -3166,36 +3164,36 @@ cdef class RandomGenerator: # Uses a custom implementation since self._binomial is required cdef double _dp = 0 - cdef long _in = 0 + cdef int64_t _in = 0 cdef bint is_scalar = True cdef np.npy_intp i, cnt cdef np.ndarray randoms - cdef np.int_t *randoms_data + cdef np.int64_t *randoms_data cdef np.broadcast it p_arr = 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.PyArray_FROM_OTF(n, np.NPY_LONG, np.NPY_ALIGNED) + n_arr = 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_NOTNAN) check_array_constraint(n_arr, 'n', CONS_NON_NEGATIVE) if size is not None: - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) else: it = np.PyArray_MultiIterNew2(p_arr, n_arr) - randoms = np.empty(it.shape, np.int) + randoms = np.empty(it.shape, np.int64) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] - _in = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._prng, _dp, _in, self._binomial) + _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._prng, _dp, _in, self._binomial) np.PyArray_MultiIter_NEXT(it) @@ -3210,9 +3208,9 @@ cdef class RandomGenerator: with self.lock: return random_binomial(self._prng, _dp, _in, self._binomial) - randoms = np.empty(size, np.int) + randoms = np.empty(size, np.int64) cnt = np.PyArray_SIZE(randoms) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) with self.lock, nogil: for i in range(cnt): @@ -3334,7 +3332,7 @@ cdef class RandomGenerator: :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. @@ -3589,11 +3587,11 @@ cdef class RandomGenerator: """ cdef bint is_scalar = True cdef np.ndarray ongood, onbad, onsample - cdef long lngood, lnbad, lnsample + cdef int64_t lngood, lnbad, lnsample - ongood = np.PyArray_FROM_OTF(ngood, np.NPY_LONG, np.NPY_ALIGNED) - onbad = np.PyArray_FROM_OTF(nbad, np.NPY_LONG, np.NPY_ALIGNED) - onsample = np.PyArray_FROM_OTF(nsample, np.NPY_LONG, np.NPY_ALIGNED) + ongood = np.PyArray_FROM_OTF(ngood, np.NPY_INT64, np.NPY_ALIGNED) + onbad = np.PyArray_FROM_OTF(nbad, np.NPY_INT64, np.NPY_ALIGNED) + onsample = 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: @@ -3941,7 +3939,7 @@ cdef class RandomGenerator: cdef np.npy_intp d, i, j, dn, sz cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" cdef double *pix - cdef long *mnix + cdef int64_t *mnix cdef double Sum d = len(pvals) @@ -3959,9 +3957,9 @@ cdef class RandomGenerator: except: shape = tuple(size) + (d,) - multin = np.zeros(shape, dtype=np.int) + multin = np.zeros(shape, dtype=np.int64) mnarr = multin - mnix = np.PyArray_DATA(mnarr) + mnix = np.PyArray_DATA(mnarr) sz = np.PyArray_SIZE(mnarr) with self.lock, nogil: diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/core_prng/src/distributions/distributions.c index 3dd83e66d38a..daed964ecc09 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/core_prng/src/distributions/distributions.c @@ -3,13 +3,9 @@ #include "ziggurat_constants.h" /* Random generators for external use */ -float random_sample_f(prng_t *prng_state) { - return random_float(prng_state); -} +float random_sample_f(prng_t *prng_state) { return random_float(prng_state); } -double random_sample(prng_t *prng_state) { - return random_double(prng_state); -} +double random_sample(prng_t *prng_state) { return random_double(prng_state); } double random_standard_exponential(prng_t *prng_state) { return -log(1.0 - random_double(prng_state)); @@ -75,8 +71,7 @@ static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, double x) { if (idx == 0) { return ziggurat_exp_r - log(random_double(prng_state)); - } else if ((fe_double[idx - 1] - fe_double[idx]) * - random_double(prng_state) + + } else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(prng_state) + fe_double[idx] < exp(-x)) { return x; @@ -158,16 +153,14 @@ double random_gauss_zig(prng_t *prng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r * - log(random_double(prng_state)); + xx = -ziggurat_nor_inv_r * log(random_double(prng_state)); yy = -log(random_double(prng_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]) * - random_double(prng_state) + + if (((fi_double[idx - 1] - fi_double[idx]) * random_double(prng_state) + fi_double[idx]) < exp(-0.5 * x * x)) return x; } @@ -402,15 +395,15 @@ int32_t random_positive_int32(prng_t *prng_state) { return random_uint32(prng_state) >> 1; } -long random_positive_int(prng_t *prng_state) { +int64_t random_positive_int(prng_t *prng_state) { #if ULONG_MAX <= 0xffffffffUL - return (long)(random_uint32(prng_state) >> 1); + return (int64_t)(random_uint32(prng_state) >> 1); #else - return (long)(random_uint64(prng_state) >> 1); + return (int64_t)(random_uint64(prng_state) >> 1); #endif } -unsigned long random_uint(prng_t *prng_state) { +uint64_t random_uint(prng_t *prng_state) { #if ULONG_MAX <= 0xffffffffUL return random_uint32(prng_state); #else @@ -425,7 +418,7 @@ unsigned long random_uint(prng_t *prng_state) { */ static double loggam(double x) { double x0, x2, xp, gl, gl0; - long k, n; + int64_t k, n; static double a[10] = {8.333333333333333e-02, -2.777777777777778e-03, 7.936507936507937e-04, -5.952380952380952e-04, @@ -437,7 +430,7 @@ static double loggam(double x) { if ((x == 1.0) || (x == 2.0)) { return 0.0; } else if (x <= 7.0) { - n = (long)(7 - x); + n = (int64_t)(7 - x); x0 = x + n; } x2 = 1.0 / (x0 * x0); @@ -584,8 +577,8 @@ double random_standard_t(prng_t *prng_state, double df) { return sqrt(df / 2) * num / sqrt(denom); } -static long random_poisson_mult(prng_t *prng_state, double lam) { - long X; +static int64_t random_poisson_mult(prng_t *prng_state, double lam) { + int64_t X; double prod, U, enlam; enlam = exp(-lam); @@ -609,8 +602,8 @@ static long random_poisson_mult(prng_t *prng_state, double lam) { */ #define LS2PI 0.91893853320467267 #define TWELFTH 0.083333333333333333333333 -static long random_poisson_ptrs(prng_t *prng_state, double lam) { - long k; +static int64_t random_poisson_ptrs(prng_t *prng_state, double lam) { + int64_t k; double U, V, slam, loglam, a, b, invalpha, vr, us; slam = sqrt(lam); @@ -624,7 +617,7 @@ static long random_poisson_ptrs(prng_t *prng_state, double lam) { U = random_sample(prng_state) - 0.5; V = random_sample(prng_state); us = 0.5 - fabs(U); - k = (long)floor((2 * a / us + b) * U + lam + 0.43); + k = (int64_t)floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { return k; } @@ -638,7 +631,7 @@ static long random_poisson_ptrs(prng_t *prng_state, double lam) { } } -long random_poisson(prng_t *prng_state, double lam) { +int64_t random_poisson(prng_t *prng_state, double lam) { if (lam >= 10) { return random_poisson_ptrs(prng_state, lam); } else if (lam == 0) { @@ -648,18 +641,18 @@ long random_poisson(prng_t *prng_state, double lam) { } } -long random_negative_binomial(prng_t *prng_state, double n, double p) { +int64_t random_negative_binomial(prng_t *prng_state, double n, double p) { double Y = random_gamma(prng_state, n, (1 - p) / p); return random_poisson(prng_state, Y); } -long random_binomial_btpe(prng_t *prng_state, long n, double p, binomial_t* binomial) { +int64_t random_binomial_btpe(prng_t *prng_state, int64_t 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; - long m, y, k, i; + int64_t m, y, k, i; - if (!(binomial->has_binomial) || - (binomial->nsave != n) || + if (!(binomial->has_binomial) || (binomial->nsave != n) || (binomial->psave != p)) { /* initialize */ binomial->nsave = n; @@ -668,9 +661,8 @@ long random_binomial_btpe(prng_t *prng_state, long n, double p, binomial_t* bino binomial->r = r = min(p, 1.0 - p); binomial->q = q = 1.0 - r; binomial->fm = fm = n * r + r; - binomial->m = m = (long)floor(binomial->fm); - binomial->p1 = p1 = - floor(2.195 * sqrt(n * r * q) - 4.6 * q) + 0.5; + binomial->m = m = (int64_t)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; @@ -706,7 +698,7 @@ long random_binomial_btpe(prng_t *prng_state, long n, double p, binomial_t* bino v = random_sample(prng_state); if (u > p1) goto Step20; - y = (long)floor(xm - p1 * v + u); + y = (int64_t)floor(xm - p1 * v + u); goto Step60; Step20: @@ -716,26 +708,26 @@ long random_binomial_btpe(prng_t *prng_state, long n, double p, binomial_t* bino v = v * c + 1.0 - fabs(m - x + 0.5) / p1; if (v > 1.0) goto Step10; - y = (long)floor(x); + y = (int64_t)floor(x); goto Step50; Step30: if (u > p3) goto Step40; - y = (long)floor(xl + log(v) / laml); + y = (int64_t)floor(xl + log(v) / laml); if (y < 0) goto Step10; v = v * (u - p2) * laml; goto Step50; Step40: - y = (long)floor(xr - log(v) / lamr); + y = (int64_t)floor(xr - log(v) / lamr); if (y > n) goto Step10; v = v * (u - p3) * lamr; Step50: - k = labs(y - m); + k = llabs(y - m); if ((k > 20) && (k < ((nrq) / 2.0 - 1))) goto Step52; @@ -794,12 +786,12 @@ long random_binomial_btpe(prng_t *prng_state, long n, double p, binomial_t* bino return y; } -long random_binomial_inversion(prng_t *prng_state, long n, double p, binomial_t* binomial) { +int64_t random_binomial_inversion(prng_t *prng_state, int64_t n, double p, + binomial_t *binomial) { double q, qn, np, px, U; - long X, bound; + int64_t X, bound; - if (!(binomial->has_binomial) || - (binomial->nsave != n) || + if (!(binomial->has_binomial) || (binomial->nsave != n) || (binomial->psave != p)) { binomial->nsave = n; binomial->psave = p; @@ -807,8 +799,7 @@ long random_binomial_inversion(prng_t *prng_state, long n, double p, binomial_t* binomial->q = q = 1.0 - p; binomial->r = qn = exp(n * log(q)); binomial->c = np = n * p; - binomial->m = bound = - (long)min(n, np + 10.0 * sqrt(np * q + 1)); + binomial->m = bound = (int64_t)min(n, np + 10.0 * sqrt(np * q + 1)); } else { q = binomial->q; qn = binomial->r; @@ -832,7 +823,8 @@ long random_binomial_inversion(prng_t *prng_state, long n, double p, binomial_t* return X; } -long random_binomial(prng_t *prng_state, double p, long n, binomial_t * binomial) { +int64_t random_binomial(prng_t *prng_state, double p, int64_t n, + binomial_t *binomial) { double q; if (p <= 0.5) { @@ -860,7 +852,7 @@ double random_noncentral_chisquare(prng_t *prng_state, double df, double nonc) { const double n = random_gauss_zig(prng_state) + sqrt(nonc); return Chi2 + n * n; } else { - const long i = random_poisson(prng_state, nonc / 2.0); + const int64_t i = random_poisson(prng_state, nonc / 2.0); return random_chisquare(prng_state, df + 2 * i); } } @@ -938,9 +930,9 @@ double random_vonmises(prng_t *prng_state, double mu, double kappa) { } } -long random_logseries(prng_t *prng_state, double p) { +int64_t random_logseries(prng_t *prng_state, double p) { double q, r, U, V; - long result; + int64_t result; r = log(1.0 - p); @@ -952,7 +944,7 @@ long random_logseries(prng_t *prng_state, double p) { U = random_sample(prng_state); q = 1.0 - exp(r * U); if (V <= q * q) { - result = (long)floor(1 + log(V) / log(q)); + result = (int64_t)floor(1 + log(V) / log(q)); if (result < 1) { continue; } else { @@ -966,9 +958,9 @@ long random_logseries(prng_t *prng_state, double p) { } } -long random_geometric_search(prng_t *prng_state, double p) { +int64_t random_geometric_search(prng_t *prng_state, double p) { double U; - long X; + int64_t X; double sum, prod, q; X = 1; @@ -983,11 +975,11 @@ long random_geometric_search(prng_t *prng_state, double p) { return X; } -long random_geometric_inversion(prng_t *prng_state, double p) { - return (long)ceil(log(1.0 - random_sample(prng_state)) / log(1.0 - p)); +int64_t random_geometric_inversion(prng_t *prng_state, double p) { + return (int64_t)ceil(log(1.0 - random_sample(prng_state)) / log(1.0 - p)); } -long random_geometric(prng_t *prng_state, double p) { +int64_t random_geometric(prng_t *prng_state, double p) { if (p >= 0.333333333333333333333333) { return random_geometric_search(prng_state, p); } else { @@ -995,9 +987,9 @@ long random_geometric(prng_t *prng_state, double p) { } } -long random_zipf(prng_t *prng_state, double a) { +int64_t random_zipf(prng_t *prng_state, double a) { double T, U, V; - long X; + int64_t X; double am1, b; am1 = a - 1.0; @@ -1005,9 +997,9 @@ long random_zipf(prng_t *prng_state, double a) { do { U = 1.0 - random_sample(prng_state); V = random_sample(prng_state); - X = (long)floor(pow(U, -1.0 / am1)); - /* The real result may be above what can be represented in a signed - * long. It will get casted to -sys.maxint-1. Since this is + X = (int64_t)floor(pow(U, -1.0 / am1)); + /* The real result may be above what can be represented in a int64. + * It will get casted to -sys.maxint-1. Since this is * a straightforward rejection algorithm, we can just reject this value * in the rejection condition below. This function then models a Zipf * distribution truncated to sys.maxint. @@ -1036,9 +1028,9 @@ double random_triangular(prng_t *prng_state, double left, double mode, } } -long random_hypergeometric_hyp(prng_t *prng_state, long good, long bad, - long sample) { - long d1, k, z; +int64_t random_hypergeometric_hyp(prng_t *prng_state, int64_t good, int64_t bad, + int64_t sample) { + int64_t d1, k, z; double d2, u, y; d1 = bad + good - sample; @@ -1048,12 +1040,12 @@ long random_hypergeometric_hyp(prng_t *prng_state, long good, long bad, k = sample; while (y > 0.0) { u = random_sample(prng_state); - y -= (long)floor(u + y / (d1 + k)); + y -= (int64_t)floor(u + y / (d1 + k)); k--; if (k == 0) break; } - z = (long)(d2 - y); + z = (int64_t)(d2 - y); if (good > bad) z = sample - z; return z; @@ -1063,11 +1055,11 @@ long random_hypergeometric_hyp(prng_t *prng_state, long good, long bad, /* D2 = 3 - 2*sqrt(3/e) */ #define D1 1.7155277699214135 #define D2 0.8989161620588988 -long random_hypergeometric_hrua(prng_t *prng_state, long good, long bad, - long sample) { - long mingoodbad, maxgoodbad, popsize, m, d9; +int64_t random_hypergeometric_hrua(prng_t *prng_state, int64_t good, + int64_t bad, int64_t sample) { + int64_t mingoodbad, maxgoodbad, popsize, m, d9; double d4, d5, d6, d7, d8, d10, d11; - long Z; + int64_t Z; double T, W, X, Y; mingoodbad = min(good, bad); @@ -1079,7 +1071,7 @@ long random_hypergeometric_hrua(prng_t *prng_state, long good, long bad, 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)); + d9 = (int64_t)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)); @@ -1094,7 +1086,7 @@ long random_hypergeometric_hrua(prng_t *prng_state, long good, long bad, if ((W < 0.0) || (W >= d11)) continue; - Z = (long)floor(W); + Z = (int64_t)floor(W); T = d10 - (loggam(Z + 1) + loggam(mingoodbad - Z + 1) + loggam(m - Z + 1) + loggam(maxgoodbad - m + Z + 1)); @@ -1123,8 +1115,8 @@ long random_hypergeometric_hrua(prng_t *prng_state, long good, long bad, #undef D1 #undef D2 -long random_hypergeometric(prng_t *prng_state, long good, long bad, - long sample) { +int64_t random_hypergeometric(prng_t *prng_state, int64_t good, int64_t bad, + int64_t sample) { if (sample > 10) { return random_hypergeometric_hrua(prng_state, good, bad, sample); } else { diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h index 9b1a70e9e1fc..c5050d400ea6 100644 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ b/_randomgen/core_prng/src/distributions/distributions.h @@ -18,6 +18,21 @@ typedef int bool; #include "numpy/npy_common.h" #include +#ifdef _WIN32 +#if _MSC_VER == 1500 + +static NPY_INLINE int64_t llabs(int64_t x) { + int64_t o; + if (x < 0) { + o = -x; + } else { + o = x; + } + return o; +} +#endif +#endif + #ifdef DLL_EXPORT #define DECLDIR __declspec(dllexport) #else @@ -36,11 +51,11 @@ typedef int bool; typedef struct s_binomial_t { int has_binomial; /* !=0: following parameters initialized for binomial */ double psave; - long nsave; + int64_t nsave; double r; double q; double fm; - long m; + int64_t m; double p1; double xm; double xl; @@ -83,8 +98,8 @@ DECLDIR double random_sample(prng_t *prng_state); DECLDIR int64_t random_positive_int64(prng_t *prng_state); DECLDIR int32_t random_positive_int32(prng_t *prng_state); -DECLDIR long random_positive_int(prng_t *prng_state); -DECLDIR unsigned long random_uint(prng_t *prng_state); +DECLDIR int64_t random_positive_int(prng_t *prng_state); +DECLDIR uint64_t random_uint(prng_t *prng_state); DECLDIR double random_standard_exponential(prng_t *prng_state); DECLDIR float random_standard_exponential_f(prng_t *prng_state); @@ -137,16 +152,18 @@ DECLDIR double random_vonmises(prng_t *prng_state, double mu, double kappa); DECLDIR double random_triangular(prng_t *prng_state, double left, double mode, double right); -DECLDIR long random_poisson(prng_t *prng_state, double lam); -DECLDIR long random_negative_binomial(prng_t *prng_state, double n, double p); -DECLDIR long random_binomial(prng_t *prng_state, double p, long n, binomial_t* binomial); -DECLDIR long random_logseries(prng_t *prng_state, double p); -DECLDIR long random_geometric_search(prng_t *prng_state, double p); -DECLDIR long random_geometric_inversion(prng_t *prng_state, double p); -DECLDIR long random_geometric(prng_t *prng_state, double p); -DECLDIR long random_zipf(prng_t *prng_state, double a); -DECLDIR long random_hypergeometric(prng_t *prng_state, long good, long bad, - long sample); +DECLDIR int64_t random_poisson(prng_t *prng_state, double lam); +DECLDIR int64_t random_negative_binomial(prng_t *prng_state, double n, + double p); +DECLDIR int64_t random_binomial(prng_t *prng_state, double p, int64_t n, + binomial_t *binomial); +DECLDIR int64_t random_logseries(prng_t *prng_state, double p); +DECLDIR int64_t random_geometric_search(prng_t *prng_state, double p); +DECLDIR int64_t random_geometric_inversion(prng_t *prng_state, double p); +DECLDIR int64_t random_geometric(prng_t *prng_state, double p); +DECLDIR int64_t random_zipf(prng_t *prng_state, double a); +DECLDIR int64_t random_hypergeometric(prng_t *prng_state, int64_t good, + int64_t bad, int64_t sample); DECLDIR uint64_t random_interval(prng_t *prng_state, uint64_t max); DECLDIR uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937.py b/_randomgen/core_prng/tests/test_numpy_mt19937.py index 9ff45504fdb2..dbe25172843a 100644 --- a/_randomgen/core_prng/tests/test_numpy_mt19937.py +++ b/_randomgen/core_prng/tests/test_numpy_mt19937.py @@ -298,16 +298,14 @@ def test_repeatability(self): res = hashlib.md5(val.view(np.int8)).hexdigest() print(tgt[np.dtype(dt).name] == res) - # TODO - # assert_(tgt[np.dtype(dt).name] == res) + assert_(tgt[np.dtype(dt).name] == res) # bools do not depend on endianess mt19937.seed(1234) val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8) res = hashlib.md5(val).hexdigest() print(tgt[np.dtype(bool).name] == res) - # TODO - # assert_(tgt[np.dtype(bool).name] == res) + assert_(tgt[np.dtype(bool).name] == res) def test_repeatability_broadcasting(self): @@ -1082,9 +1080,6 @@ def setup(self): def set_seed(self): random.seed(self.seed) - # TODO: Include test for randint once it can broadcast - # Can steal the test written in PR #6938 - def test_uniform(self): low = [0] high = [1] diff --git a/_randomgen/demo.py b/_randomgen/demo.py deleted file mode 100644 index 30b0984221d2..000000000000 --- a/_randomgen/demo.py +++ /dev/null @@ -1,103 +0,0 @@ -import timeit - -from core_prng import Xoroshiro128, ThreeFry, MT19937, \ - Xorshift1024, PCG64, Philox, DSFMT -from core_prng.generator import RandomGenerator - -print(RandomGenerator().random_integer(32)) -print(RandomGenerator(Xoroshiro128()).random_integer()) -print(RandomGenerator(ThreeFry()).random_integer()) - -print('\n' * 3) -print('Check random_sample') -rg = RandomGenerator() -print(rg.state) -print(rg.random_sample()) -print(rg.state) -print(rg.random_sample()) -print(rg.random_sample((3))) -print(rg.random_sample((3, 1))) -print(rg.state) -import numpy as np - -a = rg.random_sample((1, 1), dtype=np.float32) -print(a) -print(a.dtype) -print(rg.state) - -print('\n' * 3) -print('Check set/get state') -state = rg.state -print(rg.state) -print(rg.random_integer()) -print(rg.state) -rg.state = state -print(rg.random_integer()) - -print(RandomGenerator(Xoroshiro128()).state) -rg = RandomGenerator(ThreeFry()) -print(rg.state) -rg.random_integer() -print(rg.state) -rg = RandomGenerator(MT19937()) -state = rg.state -print(state) -rg.state = state -print(rg.random_integer()) -print(rg.random_integer(32)) -print(rg.random_sample()) - -rg = RandomGenerator(Xorshift1024()) -state = rg.state -print(state) -rg.state = state - -rg = RandomGenerator(PCG64()) -state = rg.state -print(state) -rg.state = state - -rg = RandomGenerator(Philox()) -state = rg.state -print(state) -rg.state = state - -rg = RandomGenerator(DSFMT()) -state = rg.state -print(state) -rg.state = state - - -PRNGS = [MT19937, PCG64, Philox, ThreeFry, Xoroshiro128, Xorshift1024, DSFMT] - -setup = """ -from core_prng import {module} -m = {module}() -m._benchmark(701) -""" -import pandas as pd -res = [] -for p in PRNGS: - module = p.__name__ - print(module) - t = timeit.timeit("m._benchmark(10000000)", setup.format(module=module), - number=10) - res.append(pd.Series({'module': module, 'ms': 1000 * - t / 10, 'rps': int(10000000 / (t/10))})) - #print('{:0.2f} ms'.format()) - # print('{:,} randoms per second'.format())) -res = pd.DataFrame(res) -print(res.set_index('module').sort_values('ms')) - -res = [] -for p in PRNGS: - module = p.__name__ - print(module) - t = timeit.timeit("m._benchmark(10000000, 'double')", setup.format(module=module), - number=10) - res.append(pd.Series({'module': module, 'ms': 1000 * - t / 10, 'rps': int(10000000 / (t/10))})) - #print('{:0.2f} ms'.format()) - # print('{:,} randoms per second'.format())) -res = pd.DataFrame(res) -print(res.set_index('module').sort_values('ms')) From fb98ac56e605e56efae940c996f56b0921921e34 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 00:03:25 +0000 Subject: [PATCH 058/138] DOC: Start documentation Make a start of docs --- _randomgen/core_prng/__init__.py | 11 +- _randomgen/core_prng/common.pxd | 2 +- _randomgen/core_prng/common.pyx | 6 + _randomgen/core_prng/dsfmt.pyx | 276 ++++++++++++++------ _randomgen/core_prng/entropy.pxd | 5 - _randomgen/core_prng/entropy.pyx | 2 +- _randomgen/core_prng/generator.pyx | 254 ++++++++++-------- _randomgen/core_prng/pcg32.pyx | 1 - _randomgen/core_prng/pcg64.pyx | 1 - _randomgen/core_prng/philox.pyx | 5 +- _randomgen/core_prng/threefry.pyx | 5 +- _randomgen/core_prng/threefry32.pyx | 5 +- _randomgen/core_prng/xoroshiro128.pyx | 216 +++++++++++---- _randomgen/core_prng/xorshift1024.pyx | 206 ++++++++++++++- _randomgen/doc/Makefile | 20 ++ _randomgen/doc/make.bat | 36 +++ _randomgen/doc/source/conf.py | 175 +++++++++++++ _randomgen/doc/source/generator.rst | 74 ++++++ _randomgen/doc/source/index.rst | 22 ++ _randomgen/doc/source/prng/dsfmt.rst | 38 +++ _randomgen/doc/source/prng/index.rst | 30 +++ _randomgen/doc/source/prng/xoroshiro128.rst | 38 +++ _randomgen/doc/source/prng/xorshift1024.rst | 38 +++ _randomgen/requirements.txt | 4 + 24 files changed, 1199 insertions(+), 271 deletions(-) delete mode 100644 _randomgen/core_prng/entropy.pxd create mode 100644 _randomgen/doc/Makefile create mode 100644 _randomgen/doc/make.bat create mode 100644 _randomgen/doc/source/conf.py create mode 100644 _randomgen/doc/source/generator.rst create mode 100644 _randomgen/doc/source/index.rst create mode 100644 _randomgen/doc/source/prng/dsfmt.rst create mode 100644 _randomgen/doc/source/prng/index.rst create mode 100644 _randomgen/doc/source/prng/xoroshiro128.rst create mode 100644 _randomgen/doc/source/prng/xorshift1024.rst create mode 100644 _randomgen/requirements.txt diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/core_prng/__init__.py index 9a4b0a1b19a6..6d389ae9604b 100644 --- a/_randomgen/core_prng/__init__.py +++ b/_randomgen/core_prng/__init__.py @@ -1,5 +1,5 @@ from .dsfmt import DSFMT -from .generator import RandomGenerator +from .generator import * from .mt19937 import MT19937 from .pcg32 import PCG32 from .pcg64 import PCG64 @@ -10,7 +10,14 @@ from .xorshift1024 import Xorshift1024 __all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024'] + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', + 'beta', 'binomial', 'bytes', 'chisquare', 'choice', 'complex_normal', 'dirichlet', 'exponential', 'f', + 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', + 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', + 'normal', 'permutation', 'pareto', 'poisson', 'power', 'rand', 'randint', 'randn', + 'random_integers', 'random_raw', 'random_uintegers', 'rayleigh', 'state', 'sample', 'shuffle', + 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', + 'tomaxint', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf'] from ._version import get_versions diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/core_prng/common.pxd index 66d961edc4ef..fce433449729 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/core_prng/common.pxd @@ -1,7 +1,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) from libc.math cimport sqrt -from cpython cimport PyInt_AsLong, PyFloat_AsDouble + from distributions cimport prng_t import numpy as np cimport numpy as np diff --git a/_randomgen/core_prng/common.pyx b/_randomgen/core_prng/common.pyx index b25510e1a955..aad1ad6f10b0 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/core_prng/common.pyx @@ -1,6 +1,8 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +from collections import namedtuple +from cpython cimport PyInt_AsLong, PyFloat_AsDouble import sys import numpy as np cimport numpy as np @@ -8,6 +10,10 @@ from common cimport * np.import_array() +interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', + 'next_uint32', 'next_double', 'prng']) + + cdef double kahan_sum(double *darr, np.npy_intp n): cdef double c, y, t, sum cdef np.npy_intp i diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/core_prng/dsfmt.pyx index 552941b189d1..d1da29127237 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/core_prng/dsfmt.pyx @@ -5,11 +5,11 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle -cimport entropy np.import_array() @@ -65,22 +65,83 @@ cdef uint64_t dsfmt_raw(void *st) nogil: return dsfmt_next_raw(st) cdef class DSFMT: - """ - Prototype Core PRNG using dsfmt + u""" + DSFMT(seed=None) + + Container for the SIMD-based Mersenne Twister pseudo RNG. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + 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] or ``None`` (the default). If `seed` is ``None``, + then ``DSFMT`` will try to read entropy from ``/dev/urandom`` + (or the Windows analog) if available to produce a 64-bit + seed. If unavailable, a 64-bit hash of the time and process + ID is used. Notes ----- - Exposes no user-facing API except `state`. Designed for use in a - `RandomGenerator` object. + ``DSFMT`` directly provides generators for doubles, and unsigned 32 and 64- + bit integers [1]_ . These are not firectly available and must b consumed + via a ``RandomGenerator`` object. + + The Python stdlib module "random" also contains a Mersenne Twister + pseudo-random number generator. + + **Parallel Features** + + ``DSFMT`` can be used in parallel applications by calling the method + ``jump`` which advances the state as-if :math:`2^{128}` random numbers + have been generated [2]_. This allows the original sequence to be split + so that distinct segments can be used in each worker process. All + generators should be initialized with the same seed to ensure that the + segments come from the same sequence. + + >>> from core_prng.entropy import random_entropy + >>> from core_prng import RandomGenerator, DSFMT + >>> seed = random_entropy() + >>> rs = [RandomGenerator(DSFMT(seed)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rs[i].jump() + + **State and Seeding** + + The ``DSFMT`` state vector consists of a 384 element array of + 64-bit unsigned integers plus a single integer value between 0 and 382 + indicating the current position within the main array. The implementation + used here augments this with a 384 element array of doubles which are used + to efficiently access the random numbers produced by the dSFMT generator. + + ``DSFMT`` is seeded using either a single 32-bit unsigned integer + or a vector of 32-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for a hashing function, and the output of the + hashing function is used as the initial state. Using a single 32-bit value + for the seed can only initialize a small range of the possible initial + state values. + + **Compatibility Guarantee** + + ``DSFMT`` does makes a guarantee that a fixed seed and will always + produce the same results. + + References + ---------- + .. [1] Mutsuo Saito and Makoto Matsumoto, "SIMD-oriented Fast Mersenne + Twister: a 128-bit Pseudorandom Number Generator." Monte Carlo + and Quasi-Monte Carlo Methods 2006, Springer, pp. 607 -- 622, 2008. + .. [2] 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. """ cdef dsfmt_state *rng_state cdef prng_t *_prng cdef public object capsule + cdef public object _cffi + cdef public object _ctypes + cdef public object _generator def __init__(self, seed=None): self.rng_state = malloc(sizeof(dsfmt_state)) @@ -97,6 +158,10 @@ cdef class DSFMT: cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) + self._cffi = None + self._ctypes = None + self._generator = None + # Pickling support: def __getstate__(self): return self.state @@ -115,34 +180,6 @@ cdef class DSFMT: free(self.rng_state) free(self._prng) - cdef _reset_state_variables(self): - pass - - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return dsfmt_next64(self.rng_state) - elif bits == 32: - return dsfmt_next32(self.rng_state) - else: - raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i if method==u'uint64': @@ -156,18 +193,20 @@ cdef class DSFMT: def seed(self, seed=None): """ - seed(seed=None, stream=None) + seed(seed=None) Seed the generator. - 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, optional - Seed for ``RandomState``. + seed : {None, int, array_like}, optional + 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] or ``None`` (the default). If `seed` is ``None``, + then ``DSFMT`` will try to read entropy from ``/dev/urandom`` + (or the Windows analog) if available to produce a 64-bit + seed. If unavailable, a 64-bit hash of the time and process + ID is used. Raises ------ @@ -197,61 +236,41 @@ cdef class DSFMT: dsfmt_init_by_array(self.rng_state.state, obj.data, np.PyArray_DIM(obj, 0)) - self._reset_state_variables() - def seed(self, seed=None): + def jump(self, np.npy_intp iter): """ - seed(seed=None, stream=None) - - Seed the generator. + jump(iter = 1) - This method is called when ``RandomState`` is initialized. It can be - called again to re-seed the generator. For details, see - ``RandomState``. + Jumps the state of the random number generator as-if 2**128 random numbers + have been generated. Parameters ---------- - seed : int, optional - Seed for ``RandomState``. - - Raises - ------ - ValueError - If seed values are out of range for the PRNG. + iter : integer, positive + Number of times to jump the state of the prng. + Returns + ------- + self : DSFMT + PRNG jumped iter times """ - cdef np.ndarray obj - try: - if seed is None: - try: - seed = random_entropy(1) - except RuntimeError: - seed = random_entropy(1, 'fallback') - dsfmt_init_gen_rand(self.rng_state.state, seed[0]) - 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") - dsfmt_init_gen_rand(self.rng_state.state, seed) - except TypeError: - obj = np.asarray(seed).astype(np.int64, casting='safe').ravel() - 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') - dsfmt_init_by_array(self.rng_state.state, obj.data, - np.PyArray_DIM(obj, 0)) - - self._reset_state_variables() - - def jump(self): - dsfmt_jump(self.rng_state) + cdef np.npy_intp i + for i in range(iter): + dsfmt_jump(self.rng_state) return self @property def state(self): - """Get or set the PRNG state""" + """ + Get or set the PRNG state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the PRNG + """ + cdef Py_ssize_t i, j, loc = 0 cdef uint64_t[::1] state cdef double[::1] buffered_uniforms @@ -288,4 +307,89 @@ cdef class DSFMT: buffered_uniforms = value['buffered_uniforms'] for i in range(DSFMT_N64): self.rng_state.buffered_uniforms[i] = buffered_uniforms[i] - self.rng_state.buffer_loc = value['buffer_loc'] \ No newline at end of file + self.rng_state.buffer_loc = value['buffer_loc'] + + @property + def ctypes(self): + """ + Cytpes 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 + * prng - pointer to the PRNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&dsfmt_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&dsfmt_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&dsfmt_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._prng)) + 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 + * prng - pointer to the PRNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), + ffi.cast('double (*)(void *)',self._prng.next_double), + ffi.cast('void *',self._prng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : core_prng.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/core_prng/entropy.pxd b/_randomgen/core_prng/entropy.pxd deleted file mode 100644 index c0a1a0e871f7..000000000000 --- a/_randomgen/core_prng/entropy.pxd +++ /dev/null @@ -1,5 +0,0 @@ - -from libc.stdint cimport uint64_t -cimport numpy as np - -cdef np.ndarray seed_by_array(object seed, Py_ssize_t n) \ No newline at end of file diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/core_prng/entropy.pyx index 19dbb0fd20b2..cec1bb9a81b6 100644 --- a/_randomgen/core_prng/entropy.pyx +++ b/_randomgen/core_prng/entropy.pyx @@ -23,7 +23,7 @@ cdef Py_ssize_t compute_numel(size): n = size return n -cdef np.ndarray seed_by_array(object seed, Py_ssize_t n): +def seed_by_array(object seed, Py_ssize_t n): """ Transforms a seed array into an initial state diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/core_prng/generator.pyx index ec52a1839f0b..cb9a001c2669 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/core_prng/generator.pyx @@ -4,7 +4,8 @@ import operator import warnings from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from cpython cimport Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles +from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, PyInt_AsLong, + PyComplex_ImagAsDouble, PyComplex_FromDoubles, PyFloat_AsDouble) from common cimport * from distributions cimport * from bounded_integers cimport * @@ -14,10 +15,6 @@ cimport numpy as np import numpy as np cimport cython -from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer - -from common cimport * - try: from threading import Lock except ImportError: @@ -52,7 +49,7 @@ cdef class RandomGenerator: -------- >>> from core_prng.generator import RandomGenerator >>> rg = RandomGenerator() - >>> rg.random_integer() + >>> rg.standard_normal() """ cdef public object __core_prng cdef prng_t *_prng @@ -226,14 +223,6 @@ cdef class RandomGenerator: randoms_data[i] = self._prng.next_raw(self._prng.state) return randoms - def random_integer(self, bits=64): - if bits == 64: - return self._prng.next_uint64(self._prng.state) - elif bits == 32: - return self._prng.next_uint32(self._prng.state) - else: - raise ValueError('bits must be 32 or 64') - def random_sample(self, size=None, dtype=np.float64, out=None): """ random_sample(size=None, dtype='d', out=None) @@ -269,16 +258,16 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.random_sample() + >>> core_prng.random_sample() 0.47108547995356098 - >>> type(np.random.random_sample()) + >>> type(core_prng.random_sample()) - >>> np.random.random_sample((5,)) + >>> core_prng.random_sample((5,)) array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) Three-by-two array of random numbers from [-5, 0): - >>> 5 * np.random.random_sample((3, 2)) - 5 + >>> 5 * core_prng.random_sample((3, 2)) - 5 array([[-3.99149989, -0.52338984], [-2.99091858, -0.79479508], [-1.23204345, -1.75224494]]) @@ -423,7 +412,7 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = np.random.standard_exponential((3, 8000)) + >>> n = core_prng.standard_exponential((3, 8000)) """ key = np.dtype(dtype).name if key == 'float64': @@ -469,7 +458,7 @@ cdef class RandomGenerator: Examples -------- - >>> RS = np.random.mtrand.RandomState() # need a RandomState object + >>> RS = core_prng.mtrand.RandomState() # need a RandomState object >>> RS.tomaxint((2,2,2)) array([[[1170048599, 1600360186], [ 739731006, 1947757578]], @@ -549,30 +538,30 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.randint(2, size=10) + >>> core_prng.randint(2, size=10) array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) - >>> np.random.randint(1, size=10) + >>> core_prng.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)) + >>> core_prng.randint(5, size=(2, 4)) array([[4, 0, 2, 1], [3, 2, 2, 0]]) Generate a 1 x 3 array with 3 different upper bounds - >>> np.random.randint(1, [3, 5, 10]) + >>> core_prng.randint(1, [3, 5, 10]) array([2, 2, 9]) Generate a 1 by 3 array with 3 different lower bounds - >>> np.random.randint([1, 5, 7], 10) + >>> core_prng.randint([1, 5, 7], 10) array([9, 8, 7]) Generate a 2 by 4 array using broadcasting with dtype of uint8 - >>> np.random.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) + >>> core_prng.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) """ @@ -626,7 +615,7 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.bytes(10) + >>> core_prng.bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ @@ -681,33 +670,33 @@ cdef class RandomGenerator: -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> np.random.choice(5, 3) + >>> core_prng.choice(5, 3) array([0, 3, 4]) - >>> #This is equivalent to np.random.randint(0,5,3) + >>> #This is equivalent to core_prng.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]) + >>> core_prng.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) array([3, 3, 0]) Generate a uniform random sample from np.arange(5) of size 3 without replacement: - >>> np.random.choice(5, 3, replace=False) + >>> core_prng.choice(5, 3, replace=False) array([3,1,0]) - >>> #This is equivalent to np.random.permutation(np.arange(5))[:3] + >>> #This is equivalent to core_prng.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]) + >>> core_prng.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) array([2, 3, 0]) 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]) + >>> core_prng.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], dtype='|S11') @@ -876,7 +865,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = np.random.uniform(-1,0,1000) + >>> s = core_prng.uniform(-1,0,1000) All values are within the given interval: @@ -958,13 +947,13 @@ cdef class RandomGenerator: 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. + a shape-tuple as the first argument, refer to core_prng.random_sample. ``dtype`` can only be changed using a keyword argument. Examples -------- - >>> np.random.rand(3,2) + >>> core_prng.rand(3,2) array([[ 0.14022471, 0.96360618], #random [ 0.37601032, 0.25528411], #random [ 0.49313049, 0.94909878]]) #random @@ -1016,16 +1005,16 @@ cdef class RandomGenerator: ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use: - ``sigma * np.random.randn(...) + mu`` + ``sigma * core_prng.randn(...) + mu`` Examples -------- - >>> np.random.randn() + >>> core_prng.randn() 2.1923875335537315 #random Two-by-four array of samples from N(3, 6.25): - >>> 2.5 * np.random.randn(2, 4) + 3 + >>> 2.5 * core_prng.randn(2, 4) + 3 array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random @@ -1080,15 +1069,15 @@ cdef class RandomGenerator: To sample from N evenly spaced floating-point numbers between a and b, use:: - a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) + a + (b - a) * (core_prng.random_integers(N) - 1) / (N - 1.) Examples -------- - >>> np.random.random_integers(5) + >>> core_prng.random_integers(5) 4 - >>> type(np.random.random_integers(5)) + >>> type(core_prng.random_integers(5)) - >>> np.random.random_integers(5, size=(3.,2.)) + >>> core_prng.random_integers(5, size=(3.,2.)) array([[5, 4], [3, 3], [4, 5]]) @@ -1097,13 +1086,13 @@ cdef class RandomGenerator: numbers between 0 and 2.5, inclusive (*i.e.*, from the set :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - >>> 2.5 * (np.random.random_integers(5, size=(5,)) - 1) / 4. + >>> 2.5 * (core_prng.random_integers(5, size=(5,)) - 1) / 4. array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) Roll two six sided dice 1000 times and sum the results: - >>> d1 = np.random.random_integers(1, 6, 1000) - >>> d2 = np.random.random_integers(1, 6, 1000) + >>> d1 = core_prng.random_integers(1, 6, 1000) + >>> d2 = core_prng.random_integers(1, 6, 1000) >>> dsums = d1 + d2 Display results as a histogram: @@ -1156,13 +1145,13 @@ cdef class RandomGenerator: Examples -------- - >>> s = np.random.standard_normal(8000) + >>> s = core_prng.standard_normal(8000) >>> s 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 = core_prng.standard_normal(size=(3, 4, 2)) >>> s.shape (3, 4, 2) @@ -1245,7 +1234,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = np.random.normal(mu, sigma, 1000) + >>> s = core_prng.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1327,7 +1316,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = np.random.complex_normal(size=1000) + >>> s = core_prng.complex_normal(size=1000) """ cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho cdef double *randoms_data @@ -1496,7 +1485,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = np.random.standard_gamma(shape, 1000000) + >>> s = core_prng.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1583,7 +1572,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean and dispersion - >>> s = np.random.gamma(shape, scale, 1000) + >>> s = core_prng.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1673,7 +1662,7 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = np.random.f(dfnum, dfden, 1000) + >>> s = core_prng.f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : @@ -1748,9 +1737,9 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = core_prng.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, normed=True) - >>> c_vals = np.random.f(dfnum, dfden, 1000000) + >>> c_vals = core_prng.f(dfnum, dfden, 1000000) >>> F = np.histogram(c_vals, bins=50, normed=True) >>> plt.plot(F[1][1:], F[0]) >>> plt.plot(NF[1][1:], NF[0]) @@ -1821,7 +1810,7 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.chisquare(2,4) + >>> core_prng.chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) """ @@ -1886,7 +1875,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(core_prng.noncentral_chisquare(3, 20, 100000), ... bins=200, normed=True) >>> plt.show() @@ -1894,9 +1883,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(np.random.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(core_prng.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), normed=True) - >>> values2 = plt.hist(np.random.chisquare(3, 100000), + >>> values2 = plt.hist(core_prng.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), normed=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1905,7 +1894,7 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(core_prng.noncentral_chisquare(3, 20, 100000), ... bins=200, normed=True) >>> plt.show() @@ -1970,7 +1959,7 @@ cdef class RandomGenerator: -------- Draw samples and plot the distribution: - >>> s = np.random.standard_cauchy(1000000) + >>> s = core_prng.standard_cauchy(1000000) >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well >>> plt.hist(s, bins=100) >>> plt.show() @@ -2043,7 +2032,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = np.random.standard_t(10, size=100000) + >>> s = core_prng.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -2137,7 +2126,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = np.random.vonmises(mu, kappa, 1000) + >>> s = core_prng.vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -2237,7 +2226,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (np.random.pareto(a, 1000) + 1) * m + >>> s = (core_prng.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2330,7 +2319,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = np.random.weibull(a, 1000) + >>> s = core_prng.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2340,7 +2329,7 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(np.random.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(core_prng.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) @@ -2410,7 +2399,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = np.random.power(a, samples) + >>> s = core_prng.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2426,20 +2415,20 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats - >>> rvs = np.random.power(5, 1000000) - >>> rvsp = np.random.pareto(5, 1000000) + >>> rvs = core_prng.power(5, 1000000) + >>> rvsp = core_prng.pareto(5, 1000000) >>> xx = np.linspace(0,1,100) >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() >>> plt.hist(rvs, bins=50, normed=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('np.random.power(5)') + >>> plt.title('core_prng.power(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + np.random.pareto(5)') + >>> plt.title('inverse of 1 + core_prng.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) @@ -2513,7 +2502,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = np.random.laplace(loc, scale, 1000) + >>> s = core_prng.laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2615,7 +2604,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = np.random.gumbel(mu, beta, 1000) + >>> s = core_prng.gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2633,7 +2622,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = np.random.normal(mu, beta, 1000) + ... a = core_prng.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, normed=True) @@ -2715,7 +2704,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = np.random.logistic(loc, scale, 10000) + >>> s = core_prng.logistic(loc, scale, 10000) >>> count, bins, ignored = plt.hist(s, bins=50) # plot against distribution @@ -2797,7 +2786,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = np.random.lognormal(mu, sigma, 1000) + >>> s = core_prng.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2821,7 +2810,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + np.random.random(100) + ... a = 10. + core_prng.random(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -2888,7 +2877,7 @@ cdef class RandomGenerator: -------- Draw values from the distribution and plot the histogram - >>> values = hist(np.random.rayleigh(3, 100000), bins=200, normed=True) + >>> values = hist(core_prng.rayleigh(3, 100000), bins=200, normed=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 @@ -2896,7 +2885,7 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = np.random.rayleigh(modevalue, 1000000) + >>> s = core_prng.rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: @@ -2968,7 +2957,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.wald(3, 2, 100000), bins=200, normed=True) + >>> h = plt.hist(core_prng.wald(3, 2, 100000), bins=200, normed=True) >>> plt.show() """ @@ -3035,7 +3024,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(core_prng.triangular(-3, 0, 8, 100000), bins=200, ... normed=True) >>> plt.show() @@ -3148,7 +3137,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = np.random.binomial(n, p, 1000) + >>> s = core_prng.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 @@ -3158,7 +3147,7 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(np.random.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(core_prng.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ @@ -3285,7 +3274,7 @@ cdef class RandomGenerator: 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.negative_binomial(1, 0.1, 100000) + >>> s = core_prng.negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): ... probability = sum(s>> a = 2. # parameter - >>> s = np.random.zipf(a, 1000) + >>> s = core_prng.zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3484,7 +3473,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = np.random.geometric(p=0.35, size=10000) + >>> z = core_prng.geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3572,7 +3561,7 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = np.random.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = core_prng.hypergeometric(ngood, nbad, nsamp, 1000) >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3580,7 +3569,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = np.random.hypergeometric(15, 15, 15, 100000) + >>> s = core_prng.hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3681,7 +3670,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = np.random.logseries(a, 10000) + >>> s = core_prng.logseries(a, 10000) >>> count, bins, ignored = plt.hist(s) # plot against distribution @@ -3702,8 +3691,7 @@ cdef class RandomGenerator: def multivariate_normal(self, mean, cov, size=None, check_valid='warn', tol=1e-8): """ - multivariate_normal(self, mean, cov, size=None, check_valid='warn', - tol=1e-8) + multivariate_normal(self, mean, cov, size=None, check_valid='warn', tol=1e-8) Draw random samples from a multivariate normal distribution. @@ -3770,7 +3758,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = np.random.multivariate_normal(mean, cov, 5000).T + >>> x, y = core_prng.multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3790,7 +3778,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = np.random.multivariate_normal(mean, cov, (3, 3)) + >>> x = core_prng.multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3902,14 +3890,14 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> np.random.multinomial(20, [1/6.]*6, size=1) + >>> core_prng.multinomial(20, [1/6.]*6, size=1) array([[4, 1, 7, 5, 2, 1]]) 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) + >>> core_prng.multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], [2, 4, 3, 4, 0, 7]]) @@ -3918,7 +3906,7 @@ cdef class RandomGenerator: A loaded die is more likely to land on number 6: - >>> np.random.multinomial(100, [1/7.]*5 + [2/7.]) + >>> core_prng.multinomial(100, [1/7.]*5 + [2/7.]) array([11, 16, 14, 17, 16, 26]) The probability inputs should be normalized. As an implementation @@ -3927,12 +3915,12 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + >>> core_prng.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT array([38, 62]) not like: - >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG + >>> core_prng.multinomial(100, [1.0, 2.0]) # WRONG array([100, 0]) """ @@ -4033,7 +4021,7 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = np.random.dirichlet((10, 5, 3), 20).transpose() + >>> s = core_prng.dirichlet((10, 5, 3), 20).transpose() >>> plt.barh(range(20), s[0]) >>> plt.barh(range(20), s[1], left=s[0], color='g') @@ -4127,14 +4115,14 @@ cdef class RandomGenerator: Examples -------- >>> arr = np.arange(10) - >>> np.random.shuffle(arr) + >>> core_prng.shuffle(arr) >>> arr [1 7 5 2 9 4 3 6 0 8] Multi-dimensional arrays are only shuffled along the first axis: >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.shuffle(arr) + >>> core_prng.shuffle(arr) >>> arr array([[3, 4, 5], [6, 7, 8], @@ -4216,14 +4204,14 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.permutation(10) + >>> core_prng.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) - >>> np.random.permutation([1, 4, 9, 12, 15]) + >>> core_prng.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.permutation(arr) + >>> core_prng.permutation(arr) array([[6, 7, 8], [0, 1, 2], [3, 4, 5]]) @@ -4235,3 +4223,55 @@ cdef class RandomGenerator: arr = np.array(x) self.shuffle(arr) return arr + +_random_generator = RandomGenerator() + +beta = _random_generator.beta +binomial = _random_generator.binomial +bytes = _random_generator.bytes +chisquare = _random_generator.chisquare +choice = _random_generator.choice +complex_normal = _random_generator.complex_normal +dirichlet = _random_generator.dirichlet +exponential = _random_generator.exponential +f = _random_generator.f +gamma = _random_generator.gamma +geometric = _random_generator.geometric +gumbel = _random_generator.gumbel +hypergeometric = _random_generator.hypergeometric +laplace = _random_generator.laplace +logistic = _random_generator.logistic +lognormal = _random_generator.lognormal +logseries = _random_generator.logseries +multinomial = _random_generator.multinomial +multivariate_normal = _random_generator.multivariate_normal +negative_binomial = _random_generator.negative_binomial +noncentral_chisquare = _random_generator.noncentral_chisquare +noncentral_f = _random_generator.noncentral_f +normal = _random_generator.normal +pareto = _random_generator.pareto +permutation = _random_generator.permutation +poisson = _random_generator.poisson +power = _random_generator.power +rand = _random_generator.rand +randint = _random_generator.randint +randn = _random_generator.randn +random_integers = _random_generator.random_integers +random_raw = _random_generator.random_raw +sample = _random_generator.random_sample +random_uintegers = _random_generator.random_uintegers +rayleigh = _random_generator.rayleigh +shuffle = _random_generator.shuffle +standard_cauchy = _random_generator.standard_cauchy +standard_exponential = _random_generator.standard_exponential +standard_gamma = _random_generator.standard_gamma +standard_normal = _random_generator.standard_normal +standard_t = _random_generator.standard_t +state = _random_generator.state +tomaxint = _random_generator.tomaxint +triangular = _random_generator.triangular +uniform = _random_generator.uniform +vonmises = _random_generator.vonmises +wald = _random_generator.wald +weibull = _random_generator.weibull +zipf = _random_generator.zipf \ No newline at end of file diff --git a/_randomgen/core_prng/pcg32.pyx b/_randomgen/core_prng/pcg32.pyx index df97e1a815df..104701142e78 100644 --- a/_randomgen/core_prng/pcg32.pyx +++ b/_randomgen/core_prng/pcg32.pyx @@ -8,7 +8,6 @@ from common cimport * from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle -cimport entropy np.import_array() diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/core_prng/pcg64.pyx index 1d6b504f8038..332553c1b119 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/core_prng/pcg64.pyx @@ -8,7 +8,6 @@ from common cimport * from distributions cimport prng_t from core_prng.entropy import random_entropy import core_prng.pickle -cimport entropy np.import_array() diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/core_prng/philox.pyx index 399c95bfad58..e55bd27bd314 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/core_prng/philox.pyx @@ -5,9 +5,8 @@ import numpy as np from common cimport * from distributions cimport prng_t -from core_prng.entropy import random_entropy +from core_prng.entropy import random_entropy, seed_by_array import core_prng.pickle -cimport entropy np.import_array() @@ -190,7 +189,7 @@ cdef class Philox: state = random_entropy(4, 'fallback') state = state.view(np.uint64) else: - state = entropy.seed_by_array(seed, 2) + state = seed_by_array(seed, 2) for i in range(2): self.rng_state.key.v[i] = state[i] else: diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/core_prng/threefry.pyx index 197fe4aaa703..e2b5b3c71082 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/core_prng/threefry.pyx @@ -5,9 +5,8 @@ import numpy as np from common cimport * from distributions cimport prng_t -from core_prng.entropy import random_entropy +from core_prng.entropy import random_entropy, seed_by_array import core_prng.pickle -cimport entropy np.import_array() @@ -183,7 +182,7 @@ cdef class ThreeFry: state = random_entropy(8, 'fallback') state = state.view(np.uint64) else: - state = entropy.seed_by_array(seed, 4) + state = seed_by_array(seed, 4) for i in range(4): self.rng_state.key.v[i] = state[i] else: diff --git a/_randomgen/core_prng/threefry32.pyx b/_randomgen/core_prng/threefry32.pyx index ef31bfb1b328..376a6e4ded00 100644 --- a/_randomgen/core_prng/threefry32.pyx +++ b/_randomgen/core_prng/threefry32.pyx @@ -5,9 +5,8 @@ import numpy as np from common cimport * from distributions cimport prng_t -from core_prng.entropy import random_entropy +from core_prng.entropy import random_entropy, seed_by_array import core_prng.pickle -cimport entropy np.import_array() @@ -183,7 +182,7 @@ cdef class ThreeFry32: except RuntimeError: state = random_entropy(4, 'fallback') else: - state = entropy.seed_by_array(seed, 2) + state = seed_by_array(seed, 2) state = state.view(np.uint32) for i in range(4): self.rng_state.key.v[i] = state[i] diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/core_prng/xoroshiro128.pyx index 0301c0ea20f3..03535333f795 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/core_prng/xoroshiro128.pyx @@ -1,18 +1,14 @@ -from libc.stdint cimport uint32_t, uint64_t from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New -from collections import namedtuple -interface = namedtuple('interface', ['state_address','state','next_uint64','next_uint32','next_double','prng']) - import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport prng_t -from core_prng.entropy import random_entropy +from core_prng.entropy import random_entropy, seed_by_array import core_prng.pickle -cimport entropy np.import_array() @@ -40,23 +36,95 @@ cdef double xoroshiro128_double(void* st) nogil: cdef class Xoroshiro128: """ - Prototype Core PRNG using xoroshiro128 + Xoroshiro128(seed=None) + + Container for the xoroshiro128+ pseudo-random number generator. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + then ``xoroshiro128plus.RandomState`` will try to read data from + ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. Notes ----- - Exposes no user-facing API except `get_state` and `set_state`. Designed - for use in a `RandomGenerator` object. + xoroshiro128+ is the successor to xorshift128+ written by David Blackman and + Sebastiano Vigna. It is a 64-bit PRNG that uses a carefully handcrafted + shift/rotate-based linear transformation. This change both improves speed and + statistical quality of the PRNG [1]_. xoroshiro128+ has a period of + :math:`2^{128} - 1` and supports jumping the sequence in increments of + :math:`2^{64}`, which allows multiple non-overlapping sequences to be + generated. + + ``Xoroshiro128`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``Xoroshiro128`` guarantees that a fixed seed will always produce the + same results. + + See ``Xorshift1024`` for an related PRNG implementation with a larger + period (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + + **Parallel Features** + + ``Xoroshiro128`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{64}` random numbers have been generated. This + allow the original sequence to be split so that distinct segments can be used + in each worker process. All generators should be initialized with the same + seed to ensure that the segments come from the same sequence. + + >>> from core_prng import RandomGenerator, Xoroshiro128 + >>> rg = [RandomGenerator(Xoroshiro128(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + **State and Seeding** + + The ``Xoroshiro128`` state vector consists of a 2 element array + of 64-bit unsigned integers. + + ``Xoroshiro128`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for another simple random number generator, + Splitmix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. When using an array, the SplitMix64 state + for producing the ith component of the initial state is XORd with the ith + value of the seed array until the seed array is exhausted. When using an array + the initial state for the SplitMix64 state is 0 so that using a single element + array and using the same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from core_prng import RandomGenerator, Xoroshiro128 + >>> rg = RandomGenerator(Xoroshiro128(1234)) + >>> rg.standard_normal() + + Identical method using only Xoroshiro128 + + >>> rg = Xoroshiro128(1234).generator + >>> rg.standard_normal() + + References + ---------- + .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", + http://xorshift.di.unimi.it/ """ cdef xoroshiro128_state *rng_state cdef prng_t *_prng cdef public object capsule cdef object _ctypes cdef object _cffi + cdef object _generator def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) @@ -71,6 +139,7 @@ cdef class Xoroshiro128: self._ctypes = None self._cffi = None + self._generator = None cdef const char *name = "CorePRNG" self.capsule = PyCapsule_New(self._prng, name, NULL) @@ -95,32 +164,8 @@ cdef class Xoroshiro128: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return xoroshiro128_next64(self.rng_state) - elif bits == 32: - return xoroshiro128_next32(self.rng_state) - else: - raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): + """Private benchmark command""" cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): @@ -133,24 +178,23 @@ cdef class Xoroshiro128: def seed(self, seed=None): """ - seed(seed=None, stream=None) + seed(seed=None) Seed the generator. - This method is called when ``RandomState`` is initialized. It can be - called again to re-seed the generator. For details, see - ``RandomState``. + This method is called at initialized. It can be + called again to re-seed the generator. Parameters ---------- - seed : int, optional - Seed for ``RandomState``. + seed : {int, ndarray}, optional + Seed for PRNG. Can be a single 64 biy unsigned integer or an array + of 64 bit unsigned integers. Raises ------ ValueError If seed values are out of range for the PRNG. - """ ub = 2 ** 64 if seed is None: @@ -160,18 +204,50 @@ cdef class Xoroshiro128: state = random_entropy(4, 'fallback') state = state.view(np.uint64) else: - state = entropy.seed_by_array(seed, 2) + state = seed_by_array(seed, 2) self.rng_state.s[0] = int(state[0]) self.rng_state.s[1] = int(state[1]) self._reset_state_variables() - def jump(self): - xoroshiro128_jump(self.rng_state) + def jump(self, np.npy_intp iter=1): + """ + jump(iter = 1) + + Jumps the state of the random number generator as-if 2**64 random numbers + have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : Xoroshiro128 + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is required + to ensure exact reproducibility. + """ + cdef np.npy_intp i + for i in range(iter): + xoroshiro128_jump(self.rng_state) + self._reset_state_variables() return self @property def state(self): - """Get or set the PRNG state""" + """ + Get or set the PRNG state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the PRNG + """ state = np.empty(2, dtype=np.uint64) state[0] = self.rng_state.s[0] state[1] = self.rng_state.s[1] @@ -195,6 +271,22 @@ cdef class Xoroshiro128: @property def ctypes(self): + """ + Cytpes 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 + * prng - pointer to the PRNG struct + """ + if self._ctypes is not None: return self._ctypes @@ -216,6 +308,21 @@ cdef class Xoroshiro128: @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 + * prng - pointer to the PRNG struct + """ if self._cffi is not None: return self._cffi try: @@ -231,3 +338,18 @@ cdef class Xoroshiro128: ffi.cast('double (*)(void *)',self._prng.next_double), ffi.cast('void *',self._prng)) return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : core_prng.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/core_prng/xorshift1024.pyx index 73fa052850bb..761f3403976c 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/core_prng/xorshift1024.pyx @@ -4,11 +4,11 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport prng_t -from core_prng.entropy import random_entropy +from core_prng.entropy import random_entropy, seed_by_array import core_prng.pickle -cimport entropy np.import_array() @@ -36,19 +36,95 @@ cdef double xorshift1024_double(void* st) nogil: return uint64_to_double(xorshift1024_next64(st)) cdef class Xorshift1024: - """ - Prototype Core PRNG using xorshift1024 + u""" + Xorshift1024(seed=None) + + Container for the xorshift1024*φ pseudo-random number generator. + + xorshift1024*φ is a 64-bit implementation of Saito and Matsumoto's XSadd + generator [1]_ (see also [2]_, [3]_, [4]_). xorshift1024* has a period of + :math:`2^{1024} - 1` and supports jumping the sequence in increments of + :math:`2^{512}`, which allows multiple non-overlapping sequences to be + generated. + + ``Xorshift1024`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``Xorshift1024`` guarantees that a fixed seed will always produce the + same results. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + then ``xorshift1024.RandomState`` will try to read data from + ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. Notes ----- - Exposes no user-facing API except `get_state` and `set_state`. Designed - for use in a `RandomGenerator` object. + See ``Xoroshiro128`` for a faster implementation that has a smaller + period. + + **Parallel Features** + + ``Xorshift1024`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{512}` random numbers have been generated. This + allows the original sequence to be split so that distinct segments can be used + in each worker process. All generators should be initialized with the same + seed to ensure that the segments come from the same sequence. + + >>> from core_prng import RandomGenerator, Xorshift1024 + >>> rg = [RandomGenerator(Xorshift1024(1234)) for _ in range(10)] + # Advance rg[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + **State and Seeding** + + The ``Xorshift1024`` state vector consists of a 16 element array + of 64-bit unsigned integers. + + ``Xorshift1024`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for another simple random number generator, + Splitmix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. When using an array, the SplitMix64 state + for producing the ith component of the initial state is XORd with the ith + value of the seed array until the seed array is exhausted. When using an array + the initial state for the SplitMix64 state is 0 so that using a single element + array and using the same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from core_prng import RandomGenerator, Xorshift1024 + >>> rg = RandomGenerator(Xorshift1024(1234)) + >>> rg.standard_normal() + + Identical method using only Xoroshiro128 + + >>> rg = Xorshift10241234).generator + >>> rg.standard_normal() + + References + ---------- + .. [1] "xorshift*/xorshift+ generators and the PRNG shootout", + http://xorshift.di.unimi.it/ + .. [2] Marsaglia, George. "Xorshift RNGs." Journal of Statistical Software + [Online], 8.14, pp. 1 - 6, .2003. + .. [3] Sebastiano Vigna. "An experimental exploration of Marsaglia's xorshift + generators, scrambled." CoRR, abs/1402.6246, 2014. + .. [4] Sebastiano Vigna. "Further scramblings of Marsaglia's xorshift + generators." CoRR, abs/1403.0930, 2014. """ + cdef xorshift1024_state *rng_state cdef prng_t *_prng cdef public object capsule @@ -152,14 +228,37 @@ cdef class Xorshift1024: state = random_entropy(4, 'fallback') state = state.view(np.uint64) else: - state = entropy.seed_by_array(seed, 16) + state = seed_by_array(seed, 16) for i in range(16): self.rng_state.s[i] = int(state[i]) self.rng_state.p = 0 self._reset_state_variables() - def jump(self): - xorshift1024_jump(self.rng_state) + def jump(self, np.npy_intp iter): + """ + jump(iter = 1) + + Jumps the state as-if 2**512 random numbers have been generated + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : Xorshift1024 + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is required + to ensure exact reproducibility. + """ + cdef np.npy_intp i + for i in range(iter): + xorshift1024_jump(self.rng_state) + self._reset_state_variables() return self @property @@ -186,3 +285,88 @@ cdef class Xorshift1024: self.rng_state.p = value['state']['p'] self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] + + @property + def ctypes(self): + """ + Cytpes 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 + * prng - pointer to the PRNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xorshift1024_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&xorshift1024_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&xorshift1024_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._prng)) + 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 + * prng - pointer to the PRNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), + ffi.cast('double (*)(void *)',self._prng.next_double), + ffi.cast('void *',self._prng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : core_prng.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/doc/Makefile b/_randomgen/doc/Makefile new file mode 100644 index 000000000000..ab432f78cf0c --- /dev/null +++ b/_randomgen/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = CorePRNG +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/_randomgen/doc/make.bat b/_randomgen/doc/make.bat new file mode 100644 index 000000000000..4bc049d32ac3 --- /dev/null +++ b/_randomgen/doc/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=CorePRNG + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py new file mode 100644 index 000000000000..18c357a103b0 --- /dev/null +++ b/_randomgen/doc/source/conf.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/stable/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +from distutils.version import LooseVersion +# import guzzle_sphinx_theme +import sphinx_rtd_theme +import core_prng + +# -- Project information ----------------------------------------------------- + +project = 'Core PRNG' +copyright = '2018, Kevin Sheppard' +author = 'Kevin Sheppard' + +# The short X.Y version. +version = '.'.join(map(str,LooseVersion(core_prng.__version__).version[:2])) +# The full version, including alpha/beta/rc tags. +release = core_prng.__version__ + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.napoleon', + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.autosummary', + 'sphinx.ext.mathjax', + 'sphinx.ext.githubpages', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +# html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' +html_theme_path = ["_themes", ] +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'CorePRNGdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'CorePRNG.tex', 'Core PRNG Documentation', + 'Kevin Sheppard', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'coreprng', 'Core PRNG Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'CorePRNG', 'Core PRNG Documentation', + author, 'CorePRNG', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} + +autosummary_generate=True \ No newline at end of file diff --git a/_randomgen/doc/source/generator.rst b/_randomgen/doc/source/generator.rst new file mode 100644 index 000000000000..2b093d9f6569 --- /dev/null +++ b/_randomgen/doc/source/generator.rst @@ -0,0 +1,74 @@ +Random Generator +---------------- + +.. currentmodule:: core_prng.generator + +Random generator +================ +.. autoclass:: + RandomGenerator + +Simple random data +================== +.. autosummary:: + :toctree: generated/ + + ~RandomGenerator.rand + ~RandomGenerator.randn + ~RandomGenerator.randint + ~RandomGenerator.random_integers + ~RandomGenerator.random_sample + ~RandomGenerator.choice + ~RandomGenerator.bytes + ~RandomGenerator.random_uintegers + ~RandomGenerator.random_raw + +Permutations +============ +.. autosummary:: + :toctree: generated/ + + ~RandomGenerator.shuffle + ~RandomGenerator.permutation + +Distributions +============= +.. autosummary:: + :toctree: generated/ + + ~RandomGenerator.beta + ~RandomGenerator.binomial + ~RandomGenerator.chisquare + ~RandomGenerator.complex_normal + ~RandomGenerator.dirichlet + ~RandomGenerator.exponential + ~RandomGenerator.f + ~RandomGenerator.gamma + ~RandomGenerator.geometric + ~RandomGenerator.gumbel + ~RandomGenerator.hypergeometric + ~RandomGenerator.laplace + ~RandomGenerator.logistic + ~RandomGenerator.lognormal + ~RandomGenerator.logseries + ~RandomGenerator.multinomial + ~RandomGenerator.multivariate_normal + ~RandomGenerator.negative_binomial + ~RandomGenerator.noncentral_chisquare + ~RandomGenerator.noncentral_f + ~RandomGenerator.normal + ~RandomGenerator.pareto + ~RandomGenerator.poisson + ~RandomGenerator.power + ~RandomGenerator.rayleigh + ~RandomGenerator.standard_cauchy + ~RandomGenerator.standard_exponential + ~RandomGenerator.standard_gamma + ~RandomGenerator.standard_normal + ~RandomGenerator.standard_t + ~RandomGenerator.triangular + ~RandomGenerator.uniform + ~RandomGenerator.vonmises + ~RandomGenerator.wald + ~RandomGenerator.weibull + ~RandomGenerator.zipf \ No newline at end of file diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst new file mode 100644 index 000000000000..fe1d09abd038 --- /dev/null +++ b/_randomgen/doc/source/index.rst @@ -0,0 +1,22 @@ +.. Core PRNG documentation master file, created by + sphinx-quickstart on Tue Mar 13 20:30:45 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Core PRNG +========= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + Random Generator + Core Pseudo Random Number Generators + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_randomgen/doc/source/prng/dsfmt.rst b/_randomgen/doc/source/prng/dsfmt.rst new file mode 100644 index 000000000000..5d3d747194d9 --- /dev/null +++ b/_randomgen/doc/source/prng/dsfmt.rst @@ -0,0 +1,38 @@ +Double SIMD Mersenne Twister (dSFMT) +------------------------------------ + +.. currentmodule:: core_prng.dsfmt + +Random generator +================ +.. autoclass:: DSFMT + +.. autosummary:: + :toctree: generated/ + + ~DSFMT.seed + ~DSFMT.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~DSFMT.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~DSFMT.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~DSFMT.cffi + ~DSFMT.ctypes + + diff --git a/_randomgen/doc/source/prng/index.rst b/_randomgen/doc/source/prng/index.rst new file mode 100644 index 000000000000..07c1a0f07dea --- /dev/null +++ b/_randomgen/doc/source/prng/index.rst @@ -0,0 +1,30 @@ +Core Pseudo Random Number Generators (PRNG) +------------------------------------------- + +Stable PRNGs +============ +These PRNGs will be included in future releases. + + +.. toctree:: + :maxdepth: 1 + + DSFMT + PCG64 + Philox + ThreeFry + XoroShiro128+ + Xorshift1024*φ + + +Experimental PRNGs +================== + +These PRNGs are currently included for testing but are may not be +permanent. + +.. toctree:: + :maxdepth: 1 + + ThreeFry32 + PCG32 \ No newline at end of file diff --git a/_randomgen/doc/source/prng/xoroshiro128.rst b/_randomgen/doc/source/prng/xoroshiro128.rst new file mode 100644 index 000000000000..871527a5a58d --- /dev/null +++ b/_randomgen/doc/source/prng/xoroshiro128.rst @@ -0,0 +1,38 @@ +Xoroshiro128+ +------------- + +.. currentmodule:: core_prng.xoroshiro128 + +Random generator +================ +.. autoclass:: Xoroshiro128 + +.. autosummary:: + :toctree: generated/ + + ~Xoroshiro128.seed + ~Xoroshiro128.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xoroshiro128.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~Xoroshiro128.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xoroshiro128.cffi + ~Xoroshiro128.ctypes + + diff --git a/_randomgen/doc/source/prng/xorshift1024.rst b/_randomgen/doc/source/prng/xorshift1024.rst new file mode 100644 index 000000000000..1e239733f05d --- /dev/null +++ b/_randomgen/doc/source/prng/xorshift1024.rst @@ -0,0 +1,38 @@ +Xorshift1024*φ +-------------- + +.. currentmodule:: core_prng.xorshift1024 + +Random generator +================ +.. autoclass:: Xorshift1024 + +.. autosummary:: + :toctree: generated/ + + ~Xorshift1024.seed + ~Xorshift1024.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xorshift1024.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~Xorshift1024.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xorshift1024.cffi + ~Xorshift1024.ctypes + + diff --git a/_randomgen/requirements.txt b/_randomgen/requirements.txt new file mode 100644 index 000000000000..a02ebc02a654 --- /dev/null +++ b/_randomgen/requirements.txt @@ -0,0 +1,4 @@ +numpy +cython +cffi +pandas From cb2457570ea10b96af178ef98dac9453c24a6700 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 08:52:30 +0000 Subject: [PATCH 059/138] REF: Rename from Core PRNG to RandomGen Switch canonical name to RandomGen Switch use of prng to brng to indicate basic RNG --- _randomgen/.gitattributes | 2 +- _randomgen/.travis.yml | 6 +- _randomgen/MANIFEST.in | 2 +- _randomgen/README.md | 22 +- _randomgen/appveyor.yml | 2 +- _randomgen/benchmark.py | 12 +- _randomgen/core_prng/distributions.pxd | 123 ----- .../src/distributions/distributions.h | 199 -------- _randomgen/doc/Makefile | 2 +- _randomgen/doc/make.bat | 2 +- _randomgen/doc/source/conf.py | 20 +- _randomgen/doc/source/generator.rst | 2 +- _randomgen/doc/source/index.rst | 6 +- _randomgen/doc/source/prng/dsfmt.rst | 2 +- _randomgen/doc/source/prng/index.rst | 16 +- _randomgen/doc/source/prng/xoroshiro128.rst | 2 +- _randomgen/doc/source/prng/xorshift1024.rst | 2 +- _randomgen/examples/cython/extending.pyx | 18 +- .../cython/extending_distributions.pyx | 10 +- _randomgen/examples/cython/setup.py | 2 +- _randomgen/examples/numba/extending.py | 2 +- .../examples/numba/extending_distributions.py | 18 +- .../{core_prng => randomgen}/__init__.py | 0 .../{core_prng => randomgen}/_testing.py | 0 .../{core_prng => randomgen}/_version.py | 4 +- .../bounded_integers.pxd | 20 +- .../bounded_integers.pxd.in | 4 +- .../bounded_integers.pyx | 54 +- .../bounded_integers.pyx.in | 8 +- .../{core_prng => randomgen}/common.pxd | 50 +- .../{core_prng => randomgen}/common.pyx | 32 +- _randomgen/randomgen/distributions.pxd | 123 +++++ _randomgen/{core_prng => randomgen}/dsfmt.pyx | 64 +-- .../{core_prng => randomgen}/entropy.pyx | 0 .../{core_prng => randomgen}/generator.pyx | 372 +++++++------- .../{core_prng => randomgen}/mt19937.pyx | 48 +- _randomgen/{core_prng => randomgen}/pcg32.pyx | 46 +- _randomgen/{core_prng => randomgen}/pcg64.pyx | 46 +- .../{core_prng => randomgen}/philox.pyx | 46 +- _randomgen/{core_prng => randomgen}/pickle.py | 34 +- .../src/aligned_malloc/aligned_malloc.c | 0 .../src/aligned_malloc/aligned_malloc.h | 0 .../src/common/inttypes.h | 0 .../src/common/stdint.h | 0 .../src/distributions/binomial.h | 0 .../src/distributions/distributions.c | 470 +++++++++--------- .../src/distributions/distributions.h | 199 ++++++++ .../src/distributions/ziggurat.h | 0 .../src/distributions/ziggurat_constants.h | 0 .../src/dsfmt/128-bit-jump.poly.txt | 0 .../src/dsfmt/96-bit-jump.poly.txt | 0 .../src/dsfmt/LICENSE.txt | 0 .../src/dsfmt/calc-jump.cpp | 0 .../src/dsfmt/dSFMT-benchmark.c | 0 .../src/dsfmt/dSFMT-calc-jump.hpp | 0 .../src/dsfmt/dSFMT-common.h | 0 .../src/dsfmt/dSFMT-jump.c | 0 .../src/dsfmt/dSFMT-jump.h | 0 .../src/dsfmt/dSFMT-params.h | 0 .../src/dsfmt/dSFMT-params19937.h | 0 .../src/dsfmt/dSFMT-poly.h | 0 .../src/dsfmt/dSFMT-test-gen.c | 0 .../src/dsfmt/dSFMT.c | 0 .../src/dsfmt/dSFMT.h | 0 .../src/entropy/entropy.c | 0 .../src/entropy/entropy.h | 0 .../src/mt19937/mt19937-benchmark.c | 0 .../src/mt19937/mt19937-jump.c | 0 .../src/mt19937/mt19937-jump.h | 0 .../src/mt19937/mt19937-poly.h | 0 .../src/mt19937/mt19937-test-data-gen.c | 0 .../src/mt19937/mt19937.c | 0 .../src/mt19937/mt19937.h | 0 .../src/mt19937/randomkit.c | 0 .../src/mt19937/randomkit.h | 0 .../src/pcg32/pcg-advance-64.c | 0 .../src/pcg32/pcg32-test-data-gen.c | 0 .../src/pcg32/pcg32.c | 0 .../src/pcg32/pcg32.h | 0 .../src/pcg32/pcg_variants.h | 0 .../src/pcg64/pcg64-benchmark.c | 0 .../src/pcg64/pcg64-test-data-gen.c | 0 .../src/pcg64/pcg64.c | 0 .../src/pcg64/pcg64.h | 0 .../src/pcg64/pcg64.orig.c | 0 .../src/pcg64/pcg64.orig.h | 0 .../src/philox/philox-benchmark.c | 0 .../src/philox/philox-test-data-gen.c | 0 .../src/philox/philox.c | 0 .../src/philox/philox.h | 0 .../src/splitmix64/splitmix64.c | 0 .../src/splitmix64/splitmix64.h | 0 .../src/splitmix64/splitmix64.orig.c | 0 .../src/threefry/threefry-benchmark.c | 0 .../src/threefry/threefry-orig.c | 0 .../src/threefry/threefry-test-data-gen.c | 0 .../src/threefry/threefry.c | 0 .../src/threefry/threefry.h | 0 .../src/threefry32/threefry32-test-data-gen.c | 0 .../src/threefry32/threefry32.c | 0 .../src/threefry32/threefry32.h | 0 .../src/xoroshiro128/xoroshiro128-benchmark.c | 0 .../xoroshiro128/xoroshiro128-test-data-gen.c | 0 .../src/xoroshiro128/xoroshiro128.c | 0 .../src/xoroshiro128/xoroshiro128.h | 0 .../src/xoroshiro128/xoroshiro128plus.orig.c | 0 .../src/xoroshiro128/xoroshiro128plus.orig.h | 0 .../src/xorshift1024/xorshift1024-benchmark.c | 0 .../xorshift1024/xorshift1024-test-data-gen.c | 0 .../src/xorshift1024/xorshift1024.c | 0 .../src/xorshift1024/xorshift1024.h | 0 .../src/xorshift1024/xorshift1024.orig.c | 0 .../src/xorshift1024/xorshift1024.orig.h | 0 .../tests/data/dSFMT-testset-1.csv | 0 .../tests/data/dSFMT-testset-2.csv | 0 .../tests/data/mt19937-testset-1.csv | 0 .../tests/data/mt19937-testset-2.csv | 0 .../tests/data/pcg32-testset-1.csv | 0 .../tests/data/pcg32-testset-2.csv | 0 .../tests/data/pcg64-testset-1.csv | 0 .../tests/data/pcg64-testset-2.csv | 0 .../tests/data/philox-testset-1.csv | 0 .../tests/data/philox-testset-2.csv | 0 .../tests/data/threefry-testset-1.csv | 0 .../tests/data/threefry-testset-2.csv | 0 .../tests/data/threefry32-testset-1.csv | 0 .../tests/data/threefry32-testset-2.csv | 0 .../tests/data/xoroshiro128-testset-1.csv | 0 .../tests/data/xoroshiro128-testset-2.csv | 0 .../tests/data/xorshift1024-testset-1.csv | 0 .../tests/data/xorshift1024-testset-2.csv | 0 .../tests/test_against_numpy.py | 17 +- .../tests/test_direct.py | 81 +-- .../tests/test_numpy_mt19937.py | 44 +- .../tests/test_numpy_mt19937_regressions.py | 7 +- .../tests/test_smoke.py | 78 +-- .../{core_prng => randomgen}/threefry.pyx | 46 +- .../{core_prng => randomgen}/threefry32.pyx | 46 +- .../{core_prng => randomgen}/xoroshiro128.pyx | 62 +-- .../{core_prng => randomgen}/xorshift1024.pyx | 64 +-- _randomgen/setup.cfg | 6 +- _randomgen/setup.py | 60 +-- _randomgen/test.py | 14 - 143 files changed, 1305 insertions(+), 1312 deletions(-) delete mode 100644 _randomgen/core_prng/distributions.pxd delete mode 100644 _randomgen/core_prng/src/distributions/distributions.h rename _randomgen/{core_prng => randomgen}/__init__.py (100%) rename _randomgen/{core_prng => randomgen}/_testing.py (100%) rename _randomgen/{core_prng => randomgen}/_version.py (99%) rename _randomgen/{core_prng => randomgen}/bounded_integers.pxd (65%) rename _randomgen/{core_prng => randomgen}/bounded_integers.pxd.in (94%) rename _randomgen/{core_prng => randomgen}/bounded_integers.pyx (97%) rename _randomgen/{core_prng => randomgen}/bounded_integers.pyx.in (98%) rename _randomgen/{core_prng => randomgen}/common.pxd (66%) rename _randomgen/{core_prng => randomgen}/common.pyx (96%) create mode 100644 _randomgen/randomgen/distributions.pxd rename _randomgen/{core_prng => randomgen}/dsfmt.pyx (89%) rename _randomgen/{core_prng => randomgen}/entropy.pyx (100%) rename _randomgen/{core_prng => randomgen}/generator.pyx (93%) rename _randomgen/{core_prng => randomgen}/mt19937.pyx (82%) rename _randomgen/{core_prng => randomgen}/pcg32.pyx (83%) rename _randomgen/{core_prng => randomgen}/pcg64.pyx (87%) rename _randomgen/{core_prng => randomgen}/philox.pyx (87%) rename _randomgen/{core_prng => randomgen}/pickle.py (65%) rename _randomgen/{core_prng => randomgen}/src/aligned_malloc/aligned_malloc.c (100%) rename _randomgen/{core_prng => randomgen}/src/aligned_malloc/aligned_malloc.h (100%) rename _randomgen/{core_prng => randomgen}/src/common/inttypes.h (100%) rename _randomgen/{core_prng => randomgen}/src/common/stdint.h (100%) rename _randomgen/{core_prng => randomgen}/src/distributions/binomial.h (100%) rename _randomgen/{core_prng => randomgen}/src/distributions/distributions.c (65%) create mode 100644 _randomgen/randomgen/src/distributions/distributions.h rename _randomgen/{core_prng => randomgen}/src/distributions/ziggurat.h (100%) rename _randomgen/{core_prng => randomgen}/src/distributions/ziggurat_constants.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/128-bit-jump.poly.txt (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/96-bit-jump.poly.txt (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/LICENSE.txt (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/calc-jump.cpp (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-calc-jump.hpp (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-common.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-jump.c (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-jump.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-params.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-params19937.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-poly.h (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT-test-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT.c (100%) rename _randomgen/{core_prng => randomgen}/src/dsfmt/dSFMT.h (100%) rename _randomgen/{core_prng => randomgen}/src/entropy/entropy.c (100%) rename _randomgen/{core_prng => randomgen}/src/entropy/entropy.h (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937-jump.c (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937-jump.h (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937-poly.h (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937.c (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/mt19937.h (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/randomkit.c (100%) rename _randomgen/{core_prng => randomgen}/src/mt19937/randomkit.h (100%) rename _randomgen/{core_prng => randomgen}/src/pcg32/pcg-advance-64.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg32/pcg32-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg32/pcg32.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg32/pcg32.h (100%) rename _randomgen/{core_prng => randomgen}/src/pcg32/pcg_variants.h (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64.h (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64.orig.c (100%) rename _randomgen/{core_prng => randomgen}/src/pcg64/pcg64.orig.h (100%) rename _randomgen/{core_prng => randomgen}/src/philox/philox-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/philox/philox-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/philox/philox.c (100%) rename _randomgen/{core_prng => randomgen}/src/philox/philox.h (100%) rename _randomgen/{core_prng => randomgen}/src/splitmix64/splitmix64.c (100%) rename _randomgen/{core_prng => randomgen}/src/splitmix64/splitmix64.h (100%) rename _randomgen/{core_prng => randomgen}/src/splitmix64/splitmix64.orig.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry/threefry-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry/threefry-orig.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry/threefry-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry/threefry.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry/threefry.h (100%) rename _randomgen/{core_prng => randomgen}/src/threefry32/threefry32-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry32/threefry32.c (100%) rename _randomgen/{core_prng => randomgen}/src/threefry32/threefry32.h (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128.c (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128.h (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128plus.orig.c (100%) rename _randomgen/{core_prng => randomgen}/src/xoroshiro128/xoroshiro128plus.orig.h (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024-benchmark.c (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024-test-data-gen.c (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024.c (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024.h (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024.orig.c (100%) rename _randomgen/{core_prng => randomgen}/src/xorshift1024/xorshift1024.orig.h (100%) rename _randomgen/{core_prng => randomgen}/tests/data/dSFMT-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/dSFMT-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/mt19937-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/mt19937-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/pcg32-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/pcg32-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/pcg64-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/pcg64-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/philox-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/philox-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/threefry-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/threefry-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/threefry32-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/threefry32-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/xoroshiro128-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/xoroshiro128-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/xorshift1024-testset-1.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/data/xorshift1024-testset-2.csv (100%) rename _randomgen/{core_prng => randomgen}/tests/test_against_numpy.py (97%) rename _randomgen/{core_prng => randomgen}/tests/test_direct.py (85%) rename _randomgen/{core_prng => randomgen}/tests/test_numpy_mt19937.py (98%) rename _randomgen/{core_prng => randomgen}/tests/test_numpy_mt19937_regressions.py (97%) rename _randomgen/{core_prng => randomgen}/tests/test_smoke.py (94%) rename _randomgen/{core_prng => randomgen}/threefry.pyx (86%) rename _randomgen/{core_prng => randomgen}/threefry32.pyx (86%) rename _randomgen/{core_prng => randomgen}/xoroshiro128.pyx (88%) rename _randomgen/{core_prng => randomgen}/xorshift1024.pyx (88%) delete mode 100644 _randomgen/test.py diff --git a/_randomgen/.gitattributes b/_randomgen/.gitattributes index c5ff9551eda2..9b447556a4c4 100644 --- a/_randomgen/.gitattributes +++ b/_randomgen/.gitattributes @@ -1 +1 @@ -core_prng/_version.py export-subst +randomgen/_version.py export-subst diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 7da8cb80b1ab..e7304ee57454 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -37,8 +37,8 @@ before_install: - PKGS="${PKGS} numpy"; if [ ${NUMPY} ]; then PKGS="${PKGS}=${NUMPY}"; fi - PKGS="${PKGS} Cython"; if [ ${CYTHON} ]; then PKGS="${PKGS}=${CYTHON}"; fi - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi - - conda create -n core-prng-test ${PKGS} pytest setuptools nose --quiet - - source activate core-prng-test + - conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet + - source activate randomgen-test - pip install tempita -q install: @@ -46,7 +46,7 @@ install: script: - set -e - - pytest core_prng + - pytest randomgen - | if [[ -z ${NUMPY} ]]; then python benchmark.py; diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in index 14d24dca926c..929dfdb24725 100644 --- a/_randomgen/MANIFEST.in +++ b/_randomgen/MANIFEST.in @@ -1,2 +1,2 @@ include versioneer.py -include core_prng/_version.py +include randomgen/_version.py diff --git a/_randomgen/README.md b/_randomgen/README.md index 19f216b3eaf4..1fd99e875b45 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -1,9 +1,9 @@ -# Core PRNG +# RandomGen -[![Travis Build Status](https://travis-ci.org/bashtage/ng-numpy-randomstate.svg?branch=master)](https://travis-ci.org/bashtage/core-prng) -[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/core-prng/branch/master) +[![Travis Build Status](https://travis-ci.org/bashtage/ng-numpy-randomstate.svg?branch=master)](https://travis-ci.org/bashtage/randomgen) +[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/randomgen/branch/master) -Experimental Core Pseudo Random Number Generator interface for future +Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. This is a library and generic interface for alternative random @@ -11,7 +11,7 @@ generators in Python and NumPy. ### Compatibility Warning -Core PRNG no longer supports Box-Muller normal variates and so it not +RandomGen no longer supports Box-Muller normal variates and so it not 100% compatible with NumPy (or randomstate). Box-Muller normals are slow to generate and all functions which previously relied on Box-Muller normals now use the faster Ziggurat implementation. @@ -22,7 +22,7 @@ normals now use the faster Ziggurat implementation. ```python # import numpy.random as rnd -from core_prng import RandomGenerator, MT19937 +from randomgen import RandomGenerator, MT19937 rnd = RandomGenerator(MT19937()) x = rnd.standard_normal(100) y = rnd.random_sample(100) @@ -36,7 +36,7 @@ z = rnd.randn(10,10) exponential and standard gamma using the Ziggurat method ```python -from core_prng import RandomGenerator +from randomgen import RandomGenerator # Use Xoroshiro128 rnd = RandomGenerator() w = rnd.standard_normal(10000, method='zig') @@ -110,7 +110,7 @@ PRNG implementation. or 64-bit (`[0, 2**64-1]`) * `jump` - Jumps RNGs that support it. `jump` moves the state a great distance. _Only available if supported by the RNG._ -* `advance` - Advanced the core RNG 'as-if' a number of draws were made, +* `advance` - Advanced the RNG 'as-if' a number of draws were made, without actually drawing the numbers. _Only available if supported by the RNG._ @@ -133,7 +133,7 @@ The version matched the latest version of NumPy where ## Documentation An occasionally updated build of the documentation is available on -[my GitHub pages](http://bashtage.github.io/core-prng/). +[my GitHub pages](http://bashtage.github.io/randomgen/). ## Plans This module is essentially complete. There are a few rough edges that @@ -188,10 +188,10 @@ compiler. ## Using -The separate generators are importable from `core_prng` +The separate generators are importable from `randomgen` ```python -from core_prng import RandomGenerator, ThreeFry, PCG64, MT19937 +from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 rg = RandomGenerator(ThreeFry()) rg.random_sample(100) diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml index 25b2f0c54337..8280f54b64e7 100644 --- a/_randomgen/appveyor.yml +++ b/_randomgen/appveyor.yml @@ -26,7 +26,7 @@ build_script: - set "GIT_DIR=%cd%" test_script: - - pytest core_prng + - pytest randomgen on_success: - cd %GIT_DIR%\ diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 462f405fe5cc..665f63c26570 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -10,12 +10,12 @@ SETUP = ''' import numpy as np -if '{prng}' == 'numpy': +if '{brng}' == 'numpy': import numpy.random rg = numpy.random.RandomState() else: - from core_prng import RandomGenerator, {prng} - rg = RandomGenerator({prng}()) + from randomgen import RandomGenerator, {brng} + rg = RandomGenerator({brng}()) rg.random_sample() ''' @@ -44,9 +44,9 @@ def run_timer(dist, command, numpy_command=None, setup='', random_type=''): numpy_command = command res = {} - for prng in PRNGS: - cmd = numpy_command if prng == 'numpy' else command - res[prng] = timer(cmd, setup=setup.format(prng=prng)) + for brng in PRNGS: + cmd = numpy_command if brng == 'numpy' else command + res[brng] = timer(cmd, setup=setup.format(brng=brng)) s = pd.Series(res) t = s.apply(lambda x: '{0:0.2f} ms'.format(x)) diff --git a/_randomgen/core_prng/distributions.pxd b/_randomgen/core_prng/distributions.pxd deleted file mode 100644 index 44f3520690ef..000000000000 --- a/_randomgen/core_prng/distributions.pxd +++ /dev/null @@ -1,123 +0,0 @@ -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 - -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 - - struct prng: - 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 prng prng_t - - double random_sample(prng_t *prng_state) nogil - double random_standard_exponential(prng_t *prng_state) nogil - double random_standard_exponential_zig(prng_t *prng_state) nogil - double random_gauss_zig(prng_t* prng_state) nogil - double random_standard_gamma_zig(prng_t *prng_state, double shape) nogil - - float random_sample_f(prng_t *prng_state) nogil - float random_standard_exponential_f(prng_t *prng_state) nogil - float random_standard_exponential_zig_f(prng_t *prng_state) nogil - float random_gauss_zig_f(prng_t* prng_state) nogil - float random_standard_gamma_f(prng_t *prng_state, float shape) nogil - float random_standard_gamma_zig_f(prng_t *prng_state, float shape) nogil - - int64_t random_positive_int64(prng_t *prng_state) nogil - int32_t random_positive_int32(prng_t *prng_state) nogil - int64_t random_positive_int(prng_t *prng_state) nogil - uint64_t random_uint(prng_t *prng_state) nogil - - double random_normal_zig(prng_t *prng_state, double loc, double scale) nogil - - double random_gamma(prng_t *prng_state, double shape, double scale) nogil - float random_gamma_float(prng_t *prng_state, float shape, float scale) nogil - - double random_exponential(prng_t *prng_state, double scale) nogil - double random_uniform(prng_t *prng_state, double lower, double range) nogil - double random_beta(prng_t *prng_state, double a, double b) nogil - double random_chisquare(prng_t *prng_state, double df) nogil - double random_f(prng_t *prng_state, double dfnum, double dfden) nogil - double random_standard_cauchy(prng_t *prng_state) nogil - double random_pareto(prng_t *prng_state, double a) nogil - double random_weibull(prng_t *prng_state, double a) nogil - double random_power(prng_t *prng_state, double a) nogil - double random_laplace(prng_t *prng_state, double loc, double scale) nogil - double random_gumbel(prng_t *prng_state, double loc, double scale) nogil - double random_logistic(prng_t *prng_state, double loc, double scale) nogil - double random_lognormal(prng_t *prng_state, double mean, double sigma) nogil - double random_rayleigh(prng_t *prng_state, double mode) nogil - double random_standard_t(prng_t *prng_state, double df) nogil - double random_noncentral_chisquare(prng_t *prng_state, double df, - double nonc) nogil - double random_noncentral_f(prng_t *prng_state, double dfnum, - double dfden, double nonc) nogil - double random_wald(prng_t *prng_state, double mean, double scale) nogil - double random_vonmises(prng_t *prng_state, double mu, double kappa) nogil - double random_triangular(prng_t *prng_state, double left, double mode, - double right) nogil - - int64_t random_poisson(prng_t *prng_state, double lam) nogil - int64_t random_negative_binomial(prng_t *prng_state, double n, double p) nogil - int64_t random_binomial(prng_t *prng_state, double p, int64_t n, binomial_t *binomial) nogil - int64_t random_logseries(prng_t *prng_state, double p) nogil - int64_t random_geometric_search(prng_t *prng_state, double p) nogil - int64_t random_geometric_inversion(prng_t *prng_state, double p) nogil - int64_t random_geometric(prng_t *prng_state, double p) nogil - int64_t random_zipf(prng_t *prng_state, double a) nogil - int64_t random_hypergeometric(prng_t *prng_state, int64_t good, int64_t bad, - int64_t sample) nogil - uint64_t random_interval(prng_t *prng_state, uint64_t max) nogil - uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, - uint64_t rng, uint64_t mask) nogil - uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, - uint32_t rng, uint32_t mask, - int *bcnt, uint32_t *buf) nogil - - uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, - uint16_t rng, uint16_t mask, - int *bcnt, uint32_t *buf) nogil - uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, - uint8_t rng, uint8_t mask, - int *bcnt, uint32_t *buf) nogil - np.npy_bool random_buffered_bounded_bool(prng_t *prng_state, np.npy_bool off, - np.npy_bool rng, np.npy_bool mask, - int *bcnt, uint32_t *buf) nogil - void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, - uint64_t rng, np.npy_intp cnt, - uint64_t *out) nogil - void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, - uint32_t rng, np.npy_intp cnt, - uint32_t *out) nogil - void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, - uint16_t rng, np.npy_intp cnt, - uint16_t *out) nogil - void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, - uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil - void random_bounded_bool_fill(prng_t *prng_state, np.npy_bool off, - np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil diff --git a/_randomgen/core_prng/src/distributions/distributions.h b/_randomgen/core_prng/src/distributions/distributions.h deleted file mode 100644 index c5050d400ea6..000000000000 --- a/_randomgen/core_prng/src/distributions/distributions.h +++ /dev/null @@ -1,199 +0,0 @@ -#include -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/stdint.h" -typedef int bool; -#define false 0 -#define true 1 -#else -#include -#include -#endif -#else -#include -#include -#endif - -#include "Python.h" -#include "numpy/npy_common.h" -#include - -#ifdef _WIN32 -#if _MSC_VER == 1500 - -static NPY_INLINE int64_t llabs(int64_t x) { - int64_t o; - if (x < 0) { - o = -x; - } else { - o = x; - } - return o; -} -#endif -#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; - -typedef struct prng { - 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); -} prng_t; - -/* Inline generators for internal use */ -static NPY_INLINE uint32_t random_uint32(prng_t *prng_state) { - return prng_state->next_uint32(prng_state->state); -} - -static NPY_INLINE uint64_t random_uint64(prng_t *prng_state) { - return prng_state->next_uint64(prng_state->state); -} - -static NPY_INLINE float random_float(prng_t *prng_state) { - return (random_uint32(prng_state) >> 9) * (1.0f / 8388608.0f); -} - -static NPY_INLINE double random_double(prng_t *prng_state) { - return prng_state->next_double(prng_state->state); -} - -DECLDIR float random_sample_f(prng_t *prng_state); -DECLDIR double random_sample(prng_t *prng_state); - -DECLDIR int64_t random_positive_int64(prng_t *prng_state); -DECLDIR int32_t random_positive_int32(prng_t *prng_state); -DECLDIR int64_t random_positive_int(prng_t *prng_state); -DECLDIR uint64_t random_uint(prng_t *prng_state); - -DECLDIR double random_standard_exponential(prng_t *prng_state); -DECLDIR float random_standard_exponential_f(prng_t *prng_state); -DECLDIR double random_standard_exponential_zig(prng_t *prng_state); -DECLDIR float random_standard_exponential_zig_f(prng_t *prng_state); - -/* -DECLDIR double random_gauss(prng_t *prng_state); -DECLDIR float random_gauss_f(prng_t *prng_state); -*/ -DECLDIR double random_gauss_zig(prng_t *prng_state); -DECLDIR float random_gauss_zig_f(prng_t *prng_state); - -/* -DECLDIR double random_standard_gamma(prng_t *prng_state, double shape); -DECLDIR float random_standard_gamma_f(prng_t *prng_state, float shape); -*/ -DECLDIR double random_standard_gamma_zig(prng_t *prng_state, double shape); -DECLDIR float random_standard_gamma_zig_f(prng_t *prng_state, float shape); - -/* -DECLDIR double random_normal(prng_t *prng_state, double loc, double scale); -*/ -DECLDIR double random_normal_zig(prng_t *prng_state, double loc, double scale); - -DECLDIR double random_gamma(prng_t *prng_state, double shape, double scale); -DECLDIR float random_gamma_float(prng_t *prng_state, float shape, float scale); - -DECLDIR double random_exponential(prng_t *prng_state, double scale); -DECLDIR double random_uniform(prng_t *prng_state, double lower, double range); -DECLDIR double random_beta(prng_t *prng_state, double a, double b); -DECLDIR double random_chisquare(prng_t *prng_state, double df); -DECLDIR double random_f(prng_t *prng_state, double dfnum, double dfden); -DECLDIR double random_standard_cauchy(prng_t *prng_state); -DECLDIR double random_pareto(prng_t *prng_state, double a); -DECLDIR double random_weibull(prng_t *prng_state, double a); -DECLDIR double random_power(prng_t *prng_state, double a); -DECLDIR double random_laplace(prng_t *prng_state, double loc, double scale); -DECLDIR double random_gumbel(prng_t *prng_state, double loc, double scale); -DECLDIR double random_logistic(prng_t *prng_state, double loc, double scale); -DECLDIR double random_lognormal(prng_t *prng_state, double mean, double sigma); -DECLDIR double random_rayleigh(prng_t *prng_state, double mode); -DECLDIR double random_standard_t(prng_t *prng_state, double df); -DECLDIR double random_noncentral_chisquare(prng_t *prng_state, double df, - double nonc); -DECLDIR double random_noncentral_f(prng_t *prng_state, double dfnum, - double dfden, double nonc); -DECLDIR double random_wald(prng_t *prng_state, double mean, double scale); -DECLDIR double random_vonmises(prng_t *prng_state, double mu, double kappa); -DECLDIR double random_triangular(prng_t *prng_state, double left, double mode, - double right); - -DECLDIR int64_t random_poisson(prng_t *prng_state, double lam); -DECLDIR int64_t random_negative_binomial(prng_t *prng_state, double n, - double p); -DECLDIR int64_t random_binomial(prng_t *prng_state, double p, int64_t n, - binomial_t *binomial); -DECLDIR int64_t random_logseries(prng_t *prng_state, double p); -DECLDIR int64_t random_geometric_search(prng_t *prng_state, double p); -DECLDIR int64_t random_geometric_inversion(prng_t *prng_state, double p); -DECLDIR int64_t random_geometric(prng_t *prng_state, double p); -DECLDIR int64_t random_zipf(prng_t *prng_state, double a); -DECLDIR int64_t random_hypergeometric(prng_t *prng_state, int64_t good, - int64_t bad, int64_t sample); - -DECLDIR uint64_t random_interval(prng_t *prng_state, uint64_t max); -DECLDIR uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, - uint64_t rng, uint64_t mask); -DECLDIR uint32_t random_buffered_bounded_uint32(prng_t *prng_state, - uint32_t off, uint32_t rng, - uint32_t mask, int *bcnt, - uint32_t *buf); - -DECLDIR uint16_t random_buffered_bounded_uint16(prng_t *prng_state, - uint16_t off, uint16_t rng, - uint16_t mask, int *bcnt, - uint32_t *buf); -DECLDIR uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, - uint8_t rng, uint8_t mask, - int *bcnt, uint32_t *buf); -DECLDIR npy_bool random_buffered_bounded_bool(prng_t *prng_state, npy_bool off, - npy_bool rng, npy_bool mask, - int *bcnt, uint32_t *buf); -DECLDIR void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, - uint64_t rng, npy_intp cnt, - uint64_t *out); -DECLDIR void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, - uint32_t rng, npy_intp cnt, - uint32_t *out); -DECLDIR void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, - uint16_t rng, npy_intp cnt, - uint16_t *out); -DECLDIR void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, - uint8_t rng, npy_intp cnt, uint8_t *out); -DECLDIR void random_bounded_bool_fill(prng_t *prng_state, npy_bool off, - npy_bool rng, npy_intp cnt, - npy_bool *out); diff --git a/_randomgen/doc/Makefile b/_randomgen/doc/Makefile index ab432f78cf0c..1ee9d3660c0d 100644 --- a/_randomgen/doc/Makefile +++ b/_randomgen/doc/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build -SPHINXPROJ = CorePRNG +SPHINXPROJ = RandomGen SOURCEDIR = source BUILDDIR = build diff --git a/_randomgen/doc/make.bat b/_randomgen/doc/make.bat index 4bc049d32ac3..e5a098a3426e 100644 --- a/_randomgen/doc/make.bat +++ b/_randomgen/doc/make.bat @@ -9,7 +9,7 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR=source set BUILDDIR=build -set SPHINXPROJ=CorePRNG +set SPHINXPROJ=RandomGen if "%1" == "" goto help diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py index 18c357a103b0..3ff696214888 100644 --- a/_randomgen/doc/source/conf.py +++ b/_randomgen/doc/source/conf.py @@ -18,18 +18,18 @@ from distutils.version import LooseVersion # import guzzle_sphinx_theme import sphinx_rtd_theme -import core_prng +import randomgen # -- Project information ----------------------------------------------------- -project = 'Core PRNG' +project = 'RandomGen' copyright = '2018, Kevin Sheppard' author = 'Kevin Sheppard' # The short X.Y version. -version = '.'.join(map(str,LooseVersion(core_prng.__version__).version[:2])) +version = '.'.join(map(str, LooseVersion(randomgen.__version__).version[:2])) # The full version, including alpha/beta/rc tags. -release = core_prng.__version__ +release = randomgen.__version__ # -- General configuration --------------------------------------------------- @@ -111,7 +111,7 @@ # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'CorePRNGdoc' +htmlhelp_basename = 'RandomGendoc' # -- Options for LaTeX output ------------------------------------------------ @@ -138,7 +138,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'CorePRNG.tex', 'Core PRNG Documentation', + (master_doc, 'RandomGen.tex', 'RandomGen Documentation', 'Kevin Sheppard', 'manual'), ] @@ -148,7 +148,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'coreprng', 'Core PRNG Documentation', + (master_doc, 'RandomGen', 'RandomGen Documentation', [author], 1) ] @@ -159,8 +159,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'CorePRNG', 'Core PRNG Documentation', - author, 'CorePRNG', 'One line description of project.', + (master_doc, 'RandomGen', 'RandomGen Documentation', + author, 'RandomGen', 'One line description of project.', 'Miscellaneous'), ] @@ -172,4 +172,4 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} -autosummary_generate=True \ No newline at end of file +autosummary_generate = True diff --git a/_randomgen/doc/source/generator.rst b/_randomgen/doc/source/generator.rst index 2b093d9f6569..9f2e69a167b0 100644 --- a/_randomgen/doc/source/generator.rst +++ b/_randomgen/doc/source/generator.rst @@ -1,7 +1,7 @@ Random Generator ---------------- -.. currentmodule:: core_prng.generator +.. currentmodule:: randomgen.generator Random generator ================ diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index fe1d09abd038..067416635ab8 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -1,9 +1,9 @@ -.. Core PRNG documentation master file, created by +.. RandomGen documentation master file, created by sphinx-quickstart on Tue Mar 13 20:30:45 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Core PRNG +RandomGen ========= .. toctree:: @@ -11,7 +11,7 @@ Core PRNG :caption: Contents: Random Generator - Core Pseudo Random Number Generators + Basic Random Number Generators Indices and tables diff --git a/_randomgen/doc/source/prng/dsfmt.rst b/_randomgen/doc/source/prng/dsfmt.rst index 5d3d747194d9..2f5ed0ba77de 100644 --- a/_randomgen/doc/source/prng/dsfmt.rst +++ b/_randomgen/doc/source/prng/dsfmt.rst @@ -1,7 +1,7 @@ Double SIMD Mersenne Twister (dSFMT) ------------------------------------ -.. currentmodule:: core_prng.dsfmt +.. currentmodule:: randomgen.dsfmt Random generator ================ diff --git a/_randomgen/doc/source/prng/index.rst b/_randomgen/doc/source/prng/index.rst index 07c1a0f07dea..8aebf16813e0 100644 --- a/_randomgen/doc/source/prng/index.rst +++ b/_randomgen/doc/source/prng/index.rst @@ -1,9 +1,9 @@ -Core Pseudo Random Number Generators (PRNG) -------------------------------------------- +Basic Random Number Generators +------------------------------ -Stable PRNGs -============ -These PRNGs will be included in future releases. +Stable RNGs +=========== +These RNGs will be included in future releases. .. toctree:: @@ -17,10 +17,10 @@ These PRNGs will be included in future releases. Xorshift1024*φ -Experimental PRNGs -================== +Experimental RNGs +================= -These PRNGs are currently included for testing but are may not be +These RNGs are currently included for testing but are may not be permanent. .. toctree:: diff --git a/_randomgen/doc/source/prng/xoroshiro128.rst b/_randomgen/doc/source/prng/xoroshiro128.rst index 871527a5a58d..768ace408806 100644 --- a/_randomgen/doc/source/prng/xoroshiro128.rst +++ b/_randomgen/doc/source/prng/xoroshiro128.rst @@ -1,7 +1,7 @@ Xoroshiro128+ ------------- -.. currentmodule:: core_prng.xoroshiro128 +.. currentmodule:: randomgen.xoroshiro128 Random generator ================ diff --git a/_randomgen/doc/source/prng/xorshift1024.rst b/_randomgen/doc/source/prng/xorshift1024.rst index 1e239733f05d..87adc9821446 100644 --- a/_randomgen/doc/source/prng/xorshift1024.rst +++ b/_randomgen/doc/source/prng/xorshift1024.rst @@ -1,7 +1,7 @@ Xorshift1024*φ -------------- -.. currentmodule:: core_prng.xorshift1024 +.. currentmodule:: randomgen.xorshift1024 Random generator ================ diff --git a/_randomgen/examples/cython/extending.pyx b/_randomgen/examples/cython/extending.pyx index f09563aff5ee..420bb17eaa37 100644 --- a/_randomgen/examples/cython/extending.pyx +++ b/_randomgen/examples/cython/extending.pyx @@ -3,15 +3,15 @@ cimport numpy as np cimport cython from libc.stdint cimport uint32_t from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from core_prng.common cimport prng_t -from core_prng.xoroshiro128 import Xoroshiro128 +from randomgen.common cimport brng_t +from randomgen.xoroshiro128 import Xoroshiro128 np.import_array() def uniform_mean(Py_ssize_t N): cdef Py_ssize_t i - cdef prng_t *rng - cdef const char *capsule_name = "CorePRNG" + cdef brng_t *rng + cdef const char *capsule_name = "BasicRNG" cdef double[::1] random_values cdef np.ndarray randoms @@ -19,14 +19,14 @@ def uniform_mean(Py_ssize_t N): capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(N) for i in range(N): random_values[i] = rng.next_double(rng.state) randoms = np.asarray(random_values) return randoms.mean() -cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, prng_t *rng): +cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, brng_t *rng): cdef uint32_t mask, delta, val mask = delta = ub - lb mask |= mask >> 1 @@ -45,9 +45,9 @@ cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, prng_t *rng): @cython.wraparound(False) def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): cdef Py_ssize_t i - cdef prng_t *rng + cdef brng_t *rng cdef uint32_t[::1] out - cdef const char *capsule_name = "CorePRNG" + cdef const char *capsule_name = "BasicRNG" x = Xoroshiro128() out = np.empty(n, dtype=np.uint32) @@ -55,7 +55,7 @@ def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) for i in range(n): out[i] = bounded_uint(lb, ub, rng) diff --git a/_randomgen/examples/cython/extending_distributions.pyx b/_randomgen/examples/cython/extending_distributions.pyx index 65ff44f9320f..a5fea174aa49 100644 --- a/_randomgen/examples/cython/extending_distributions.pyx +++ b/_randomgen/examples/cython/extending_distributions.pyx @@ -2,22 +2,22 @@ import numpy as np cimport numpy as np cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from core_prng.common cimport * -from core_prng.xoroshiro128 import Xoroshiro128 +from randomgen.common cimport * +from randomgen.xoroshiro128 import Xoroshiro128 @cython.boundscheck(False) @cython.wraparound(False) def normals_zig(Py_ssize_t n): cdef Py_ssize_t i - cdef prng_t *rng - cdef const char *capsule_name = "CorePRNG" + cdef brng_t *rng + cdef const char *capsule_name = "BasicRNG" cdef double[::1] random_values x = Xoroshiro128() capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) for i in range(n): random_values[i] = random_gauss_zig(rng) diff --git a/_randomgen/examples/cython/setup.py b/_randomgen/examples/cython/setup.py index 61bdc5f606f3..480d5f508f8b 100644 --- a/_randomgen/examples/cython/setup.py +++ b/_randomgen/examples/cython/setup.py @@ -10,7 +10,7 @@ include_dirs=[np.get_include()]) distributions = Extension("extending_distributions", sources=['extending_distributions.pyx', - join('..', '..', 'core_prng', 'src', 'distributions', 'distributions.c')], + join('..', '..', 'randomgen', 'src', 'distributions', 'distributions.c')], include_dirs=[np.get_include()]) extensions = [extending, distributions] diff --git a/_randomgen/examples/numba/extending.py b/_randomgen/examples/numba/extending.py index aa7122c9543a..198c39a29297 100644 --- a/_randomgen/examples/numba/extending.py +++ b/_randomgen/examples/numba/extending.py @@ -1,4 +1,4 @@ -from core_prng import Xoroshiro128 +from randomgen import Xoroshiro128 import numpy as np import numba as nb diff --git a/_randomgen/examples/numba/extending_distributions.py b/_randomgen/examples/numba/extending_distributions.py index 230362747882..07cb074a3177 100644 --- a/_randomgen/examples/numba/extending_distributions.py +++ b/_randomgen/examples/numba/extending_distributions.py @@ -1,5 +1,5 @@ r""" -On *nix, execute in core_prng/src/distributions +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 @@ -16,7 +16,7 @@ import os import numpy as np from cffi import FFI -from core_prng import Xoroshiro128 +from randomgen import Xoroshiro128 import numba as nb ffi = FFI() @@ -28,19 +28,19 @@ raise RuntimeError('Required DLL/so file was not found.') ffi.cdef(""" -double random_gauss_zig(void *prng_state); +double random_gauss_zig(void *brng_state); """) x = Xoroshiro128() xffi = x.cffi -prng = xffi.prng +brng = xffi.brng random_gauss_zig = lib.random_gauss_zig -def normals(n, prng): +def normals(n, brng): out = np.empty(n) for i in range(n): - out[i] = random_gauss_zig(prng) + out[i] = random_gauss_zig(brng) return out @@ -48,7 +48,7 @@ def normals(n, prng): # Numba requires a memory address for void * -# Can also get address from x.ctypes.prng.value -prng_address = int(ffi.cast('uintptr_t', prng)) +# Can also get address from x.ctypes.brng.value +brng_address = int(ffi.cast('uintptr_t', brng)) -norm = normalsj(1000, prng_address) +norm = normalsj(1000, brng_address) diff --git a/_randomgen/core_prng/__init__.py b/_randomgen/randomgen/__init__.py similarity index 100% rename from _randomgen/core_prng/__init__.py rename to _randomgen/randomgen/__init__.py diff --git a/_randomgen/core_prng/_testing.py b/_randomgen/randomgen/_testing.py similarity index 100% rename from _randomgen/core_prng/_testing.py rename to _randomgen/randomgen/_testing.py diff --git a/_randomgen/core_prng/_version.py b/_randomgen/randomgen/_version.py similarity index 99% rename from _randomgen/core_prng/_version.py rename to _randomgen/randomgen/_version.py index 1041669c74ea..e400e3efb65d 100644 --- a/_randomgen/core_prng/_version.py +++ b/_randomgen/randomgen/_version.py @@ -42,8 +42,8 @@ def get_config(): cfg.VCS = "git" cfg.style = "pep440" cfg.tag_prefix = "" - cfg.parentdir_prefix = "core_prng-" - cfg.versionfile_source = "core_prng/_version.py" + cfg.parentdir_prefix = "randomgen-" + cfg.versionfile_source = "randomgen/_version.py" cfg.verbose = False return cfg diff --git a/_randomgen/core_prng/bounded_integers.pxd b/_randomgen/randomgen/bounded_integers.pxd similarity index 65% rename from _randomgen/core_prng/bounded_integers.pxd rename to _randomgen/randomgen/bounded_integers.pxd index 0da686427dec..f15f0f5d9d1e 100644 --- a/_randomgen/core_prng/bounded_integers.pxd +++ b/_randomgen/randomgen/bounded_integers.pxd @@ -1,6 +1,6 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) -from common cimport prng_t +from common cimport brng_t import numpy as np cimport numpy as np ctypedef np.npy_bool bool_t @@ -28,12 +28,12 @@ cdef inline uint64_t _gen_mask(uint64_t max_val) nogil: mask |= mask >> 32 return mask -cdef object _rand_uint64(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_uint32(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_uint16(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_uint8(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_bool(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_int64(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_int32(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_int16(object low, object high, object size, prng_t *state, object lock) -cdef object _rand_int8(object low, object high, object size, prng_t *state, object lock) +cdef object _rand_uint64(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_uint32(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_uint16(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_uint8(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_bool(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_int64(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_int32(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_int16(object low, object high, object size, brng_t *state, object lock) +cdef object _rand_int8(object low, object high, object size, brng_t *state, object lock) diff --git a/_randomgen/core_prng/bounded_integers.pxd.in b/_randomgen/randomgen/bounded_integers.pxd.in similarity index 94% rename from _randomgen/core_prng/bounded_integers.pxd.in rename to _randomgen/randomgen/bounded_integers.pxd.in index 1b87e8d7ed69..4e1a6409146e 100644 --- a/_randomgen/core_prng/bounded_integers.pxd.in +++ b/_randomgen/randomgen/bounded_integers.pxd.in @@ -1,6 +1,6 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) -from common cimport prng_t +from common cimport brng_t import numpy as np cimport numpy as np ctypedef np.npy_bool bool_t @@ -32,5 +32,5 @@ 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, prng_t *state, object lock) +cdef object _rand_{{inttype}}(object low, object high, object size, brng_t *state, object lock) {{endfor}} diff --git a/_randomgen/core_prng/bounded_integers.pyx b/_randomgen/randomgen/bounded_integers.pyx similarity index 97% rename from _randomgen/core_prng/bounded_integers.pyx rename to _randomgen/randomgen/bounded_integers.pyx index e8840d341f6c..fe47bcb8a2e9 100644 --- a/_randomgen/core_prng/bounded_integers.pyx +++ b/_randomgen/randomgen/bounded_integers.pyx @@ -9,7 +9,7 @@ np.import_array() -cdef object _rand_uint32_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_uint32_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint32_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -61,7 +61,7 @@ cdef object _rand_uint32_broadcast(np.ndarray low, np.ndarray high, object size, return out_arr -cdef object _rand_uint16_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_uint16_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint16_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -113,7 +113,7 @@ cdef object _rand_uint16_broadcast(np.ndarray low, np.ndarray high, object size, return out_arr -cdef object _rand_uint8_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_uint8_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint8_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -165,7 +165,7 @@ cdef object _rand_uint8_broadcast(np.ndarray low, np.ndarray high, object size, return out_arr -cdef object _rand_bool_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_bool_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef bool_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -217,7 +217,7 @@ cdef object _rand_bool_broadcast(np.ndarray low, np.ndarray high, object size, p return out_arr -cdef object _rand_int32_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_int32_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint32_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -269,7 +269,7 @@ cdef object _rand_int32_broadcast(np.ndarray low, np.ndarray high, object size, return out_arr -cdef object _rand_int16_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_int16_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint16_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -321,7 +321,7 @@ cdef object _rand_int16_broadcast(np.ndarray low, np.ndarray high, object size, return out_arr -cdef object _rand_int8_broadcast(np.ndarray low, np.ndarray high, object size, prng_t *state, object lock): +cdef object _rand_int8_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef uint8_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -374,7 +374,7 @@ cdef object _rand_int8_broadcast(np.ndarray low, np.ndarray high, object size, p -cdef object _rand_uint64_broadcast(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_uint64_broadcast(object low, object high, object size, brng_t *state, object lock): """Array path for 64-bit integer types""" cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr cdef np.npy_intp i, cnt, n @@ -434,7 +434,7 @@ cdef object _rand_uint64_broadcast(object low, object high, object size, prng_t return out_arr -cdef object _rand_int64_broadcast(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_int64_broadcast(object low, object high, object size, brng_t *state, object lock): """Array path for 64-bit integer types""" cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr cdef np.npy_intp i, cnt, n @@ -496,7 +496,7 @@ cdef object _rand_int64_broadcast(object low, object high, object size, prng_t * -cdef object _rand_uint64(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_uint64(object low, object high, object size, brng_t *state, object lock): """ _rand_uint64(low, high, size, *state, lock) @@ -520,7 +520,7 @@ cdef object _rand_uint64(object low, object high, object size, prng_t *state, ob 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -572,7 +572,7 @@ cdef object _rand_uint64(object low, object high, object size, prng_t *state, ob return out_arr return _rand_uint64_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_uint32(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_uint32(object low, object high, object size, brng_t *state, object lock): """ _rand_uint32(low, high, size, *state, lock) @@ -596,7 +596,7 @@ cdef object _rand_uint32(object low, object high, object size, prng_t *state, ob 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -648,7 +648,7 @@ cdef object _rand_uint32(object low, object high, object size, prng_t *state, ob return out_arr return _rand_uint32_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_uint16(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_uint16(object low, object high, object size, brng_t *state, object lock): """ _rand_uint16(low, high, size, *state, lock) @@ -672,7 +672,7 @@ cdef object _rand_uint16(object low, object high, object size, prng_t *state, ob 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -724,7 +724,7 @@ cdef object _rand_uint16(object low, object high, object size, prng_t *state, ob return out_arr return _rand_uint16_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_uint8(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_uint8(object low, object high, object size, brng_t *state, object lock): """ _rand_uint8(low, high, size, *state, lock) @@ -748,7 +748,7 @@ cdef object _rand_uint8(object low, object high, object size, prng_t *state, obj 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -800,7 +800,7 @@ cdef object _rand_uint8(object low, object high, object size, prng_t *state, obj return out_arr return _rand_uint8_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_bool(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_bool(object low, object high, object size, brng_t *state, object lock): """ _rand_bool(low, high, size, *state, lock) @@ -824,7 +824,7 @@ cdef object _rand_bool(object low, object high, object size, prng_t *state, obje 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -876,7 +876,7 @@ cdef object _rand_bool(object low, object high, object size, prng_t *state, obje return out_arr return _rand_bool_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_int64(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_int64(object low, object high, object size, brng_t *state, object lock): """ _rand_int64(low, high, size, *state, lock) @@ -900,7 +900,7 @@ cdef object _rand_int64(object low, object high, object size, prng_t *state, obj 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -952,7 +952,7 @@ cdef object _rand_int64(object low, object high, object size, prng_t *state, obj return out_arr return _rand_int64_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_int32(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_int32(object low, object high, object size, brng_t *state, object lock): """ _rand_int32(low, high, size, *state, lock) @@ -976,7 +976,7 @@ cdef object _rand_int32(object low, object high, object size, prng_t *state, obj 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -1028,7 +1028,7 @@ cdef object _rand_int32(object low, object high, object size, prng_t *state, obj return out_arr return _rand_int32_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_int16(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_int16(object low, object high, object size, brng_t *state, object lock): """ _rand_int16(low, high, size, *state, lock) @@ -1052,7 +1052,7 @@ cdef object _rand_int16(object low, object high, object size, prng_t *state, obj 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously @@ -1104,7 +1104,7 @@ cdef object _rand_int16(object low, object high, object size, prng_t *state, obj return out_arr return _rand_int16_broadcast(low_arr, high_arr, size, state, lock) -cdef object _rand_int8(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_int8(object low, object high, object size, brng_t *state, object lock): """ _rand_int8(low, high, size, *state, lock) @@ -1128,7 +1128,7 @@ cdef object _rand_int8(object low, object high, object size, prng_t *state, obje 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously diff --git a/_randomgen/core_prng/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in similarity index 98% rename from _randomgen/core_prng/bounded_integers.pyx.in rename to _randomgen/randomgen/bounded_integers.pyx.in index ea0bba028d0b..d464e9e2c841 100644 --- a/_randomgen/core_prng/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -19,7 +19,7 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U {{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, prng_t *state, object lock): +cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): """Array path for smaller integer types""" cdef {{utype}}_t rng, last_rng, off, val, mask, out_val cdef uint32_t buf @@ -78,7 +78,7 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF )}} {{for nptype, utype, npctype, lb, ub in big_type_info}} {{ py: otype = nptype}} -cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, prng_t *state, object lock): +cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brng_t *state, object lock): """Array path for 64-bit integer types""" cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr cdef np.npy_intp i, cnt, n @@ -153,7 +153,7 @@ type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), )}} {{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, prng_t *state, object lock): +cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state, object lock): """ _rand_{{nptype}}(low, high, size, *state, lock) @@ -177,7 +177,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size, prng_t *state 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. - state : augmented random state + state : basic random state State to use in the core random number generators lock : threading.Lock Lock to prevent multiple using a single RandomState simultaneously diff --git a/_randomgen/core_prng/common.pxd b/_randomgen/randomgen/common.pxd similarity index 66% rename from _randomgen/core_prng/common.pxd rename to _randomgen/randomgen/common.pxd index fce433449729..33a7bef2629a 100644 --- a/_randomgen/core_prng/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -2,7 +2,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) from libc.math cimport sqrt -from distributions cimport prng_t +from distributions cimport brng_t import numpy as np cimport numpy as np @@ -30,62 +30,62 @@ cdef extern from "src/aligned_malloc/aligned_malloc.h": cdef void *PyArray_calloc_aligned(size_t n, size_t s); cdef void PyArray_free_aligned(void *p); -ctypedef double (*random_double_0)(prng_t *state) nogil -ctypedef double (*random_double_1)(prng_t *state, double a) nogil -ctypedef double (*random_double_2)(prng_t *state, double a, double b) nogil -ctypedef double (*random_double_3)(prng_t *state, double a, double b, double c) nogil +ctypedef double (*random_double_0)(brng_t *state) nogil +ctypedef double (*random_double_1)(brng_t *state, double a) nogil +ctypedef double (*random_double_2)(brng_t *state, double a, double b) nogil +ctypedef double (*random_double_3)(brng_t *state, double a, double b, double c) nogil -ctypedef float (*random_float_0)(prng_t *state) nogil -ctypedef float (*random_float_1)(prng_t *state, float a) nogil +ctypedef float (*random_float_0)(brng_t *state) nogil +ctypedef float (*random_float_1)(brng_t *state, float a) nogil -ctypedef int64_t (*random_uint_0)(prng_t *state) nogil -ctypedef int64_t (*random_uint_d)(prng_t *state, double a) nogil -ctypedef int64_t (*random_uint_dd)(prng_t *state, double a, double b) nogil -ctypedef int64_t (*random_uint_di)(prng_t *state, double a, uint64_t b) nogil -ctypedef int64_t (*random_uint_i)(prng_t *state, int64_t a) nogil -ctypedef int64_t (*random_uint_iii)(prng_t *state, int64_t a, int64_t b, int64_t c) nogil +ctypedef int64_t (*random_uint_0)(brng_t *state) nogil +ctypedef int64_t (*random_uint_d)(brng_t *state, double a) nogil +ctypedef int64_t (*random_uint_dd)(brng_t *state, double a, double b) nogil +ctypedef int64_t (*random_uint_di)(brng_t *state, double a, uint64_t b) nogil +ctypedef int64_t (*random_uint_i)(brng_t *state, int64_t a) nogil +ctypedef int64_t (*random_uint_iii)(brng_t *state, int64_t a, int64_t b, int64_t c) nogil -ctypedef uint32_t (*random_uint_0_32)(prng_t *state) nogil -ctypedef uint32_t (*random_uint_1_i_32)(prng_t *state, uint32_t a) nogil +ctypedef uint32_t (*random_uint_0_32)(brng_t *state) nogil +ctypedef uint32_t (*random_uint_1_i_32)(brng_t *state, uint32_t a) nogil -ctypedef int32_t (*random_int_2_i_32)(prng_t *state, int32_t a, int32_t b) nogil -ctypedef int64_t (*random_int_2_i)(prng_t *state, int64_t a, int64_t b) nogil +ctypedef int32_t (*random_int_2_i_32)(brng_t *state, int32_t a, int32_t b) nogil +ctypedef int64_t (*random_int_2_i)(brng_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, prng_t *state, object size, object lock, object out) +cdef object double_fill(void *func, brng_t *state, object size, object lock, object out) -cdef object float_fill(void *func, prng_t *state, object size, object lock, object out) +cdef object float_fill(void *func, brng_t *state, object size, object lock, object out) -cdef object float_fill_from_double(void *func, prng_t *state, object size, object lock, object out) +cdef object float_fill_from_double(void *func, brng_t *state, object size, object lock, object out) cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size) -cdef object cont(void *func, prng_t *state, object size, object lock, int narg, +cdef object cont(void *func, brng_t *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, prng_t *state, object size, object lock, +cdef object disc(void *func, brng_t *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, prng_t *state, object size, object lock, +cdef object cont_f(void *func, brng_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out) -cdef object cont_broadcast_3(void *func, prng_t *state, object size, object lock, +cdef object cont_broadcast_3(void *func, brng_t *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, prng_t *state, object size, object lock, +cdef object discrete_broadcast_iii(void *func, brng_t *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/_randomgen/core_prng/common.pyx b/_randomgen/randomgen/common.pyx similarity index 96% rename from _randomgen/core_prng/common.pyx rename to _randomgen/randomgen/common.pyx index aad1ad6f10b0..101a14270635 100644 --- a/_randomgen/core_prng/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -11,7 +11,7 @@ from common cimport * np.import_array() interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', - 'next_uint32', 'next_double', 'prng']) + 'next_uint32', 'next_double', 'brng']) cdef double kahan_sum(double *darr, np.npy_intp n): @@ -69,7 +69,7 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size and out cannot be simultaneously used') -cdef object double_fill(void *func, prng_t *state, object size, object lock, object out): +cdef object double_fill(void *func, brng_t *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef double *out_array_data cdef np.ndarray out_array @@ -92,7 +92,7 @@ cdef object double_fill(void *func, prng_t *state, object size, object lock, obj out_array_data[i] = random_func(state) return out_array -cdef object float_fill(void *func, prng_t *state, object size, object lock, object out): +cdef object float_fill(void *func, brng_t *state, object size, object lock, object out): cdef random_float_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -115,7 +115,7 @@ cdef object float_fill(void *func, prng_t *state, object size, object lock, obje out_array_data[i] = random_func(state) return out_array -cdef object float_fill_from_double(void *func, prng_t *state, object size, object lock, object out): +cdef object float_fill_from_double(void *func, brng_t *state, object size, object lock, object out): cdef random_double_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -199,7 +199,7 @@ cdef int check_constraint(double val, object name, constraint_type cons) except return 0 -cdef object cont_broadcast_1(void *func, prng_t *state, object size, object lock, +cdef object cont_broadcast_1(void *func, brng_t *state, object size, object lock, np.ndarray a_arr, object a_name, constraint_type a_constraint, object out): @@ -233,7 +233,7 @@ cdef object cont_broadcast_1(void *func, prng_t *state, object size, object lock return randoms -cdef object cont_broadcast_2(void *func, prng_t *state, object size, object lock, +cdef object cont_broadcast_2(void *func, brng_t *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 @@ -271,7 +271,7 @@ cdef object cont_broadcast_2(void *func, prng_t *state, object size, object lock return randoms -cdef object cont_broadcast_3(void *func, prng_t *state, object size, object lock, +cdef object cont_broadcast_3(void *func, brng_t *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): @@ -313,7 +313,7 @@ cdef object cont_broadcast_3(void *func, prng_t *state, object size, object lock return randoms -cdef object cont(void *func, prng_t *state, object size, object lock, int narg, +cdef object cont(void *func, brng_t *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, @@ -409,7 +409,7 @@ cdef object cont(void *func, prng_t *state, object size, object lock, int narg, else: return out -cdef object discrete_broadcast_d(void *func, prng_t *state, object size, object lock, +cdef object discrete_broadcast_d(void *func, brng_t *state, object size, object lock, np.ndarray a_arr, object a_name, constraint_type a_constraint): cdef np.ndarray randoms @@ -440,7 +440,7 @@ cdef object discrete_broadcast_d(void *func, prng_t *state, object size, object return randoms -cdef object discrete_broadcast_dd(void *func, prng_t *state, object size, object lock, +cdef object discrete_broadcast_dd(void *func, brng_t *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 @@ -475,7 +475,7 @@ cdef object discrete_broadcast_dd(void *func, prng_t *state, object size, object return randoms -cdef object discrete_broadcast_di(void *func, prng_t *state, object size, object lock, +cdef object discrete_broadcast_di(void *func, brng_t *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 @@ -511,7 +511,7 @@ cdef object discrete_broadcast_di(void *func, prng_t *state, object size, object return randoms -cdef object discrete_broadcast_iii(void *func, prng_t *state, object size, object lock, +cdef object discrete_broadcast_iii(void *func, brng_t *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): @@ -551,7 +551,7 @@ cdef object discrete_broadcast_iii(void *func, prng_t *state, object size, objec return randoms -cdef object discrete_broadcast_i(void *func, prng_t *state, object size, object lock, +cdef object discrete_broadcast_i(void *func, brng_t *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 @@ -581,7 +581,7 @@ cdef object discrete_broadcast_i(void *func, prng_t *state, object size, object return randoms # Needs double , double-double , double-int64_t, int64_t , int64_t-int64_t-int64_t -cdef object disc(void *func, prng_t *state, object size, object lock, +cdef object disc(void *func, brng_t *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, @@ -719,7 +719,7 @@ cdef object disc(void *func, prng_t *state, object size, object lock, return randoms -cdef object cont_broadcast_1_f(void *func, prng_t *state, object size, object lock, +cdef object cont_broadcast_1_f(void *func, brng_t *state, object size, object lock, np.ndarray a_arr, object a_name, constraint_type a_constraint, object out): @@ -755,7 +755,7 @@ cdef object cont_broadcast_1_f(void *func, prng_t *state, object size, object lo return randoms -cdef object cont_f(void *func, prng_t *state, object size, object lock, +cdef object cont_f(void *func, brng_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out): diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd new file mode 100644 index 000000000000..3ac32f210108 --- /dev/null +++ b/_randomgen/randomgen/distributions.pxd @@ -0,0 +1,123 @@ +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 + +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 + + struct brng: + 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 brng brng_t + + double random_sample(brng_t *brng_state) nogil + double random_standard_exponential(brng_t *brng_state) nogil + double random_standard_exponential_zig(brng_t *brng_state) nogil + double random_gauss_zig(brng_t* brng_state) nogil + double random_standard_gamma_zig(brng_t *brng_state, double shape) nogil + + float random_sample_f(brng_t *brng_state) nogil + float random_standard_exponential_f(brng_t *brng_state) nogil + float random_standard_exponential_zig_f(brng_t *brng_state) nogil + float random_gauss_zig_f(brng_t* brng_state) nogil + float random_standard_gamma_f(brng_t *brng_state, float shape) nogil + float random_standard_gamma_zig_f(brng_t *brng_state, float shape) nogil + + int64_t random_positive_int64(brng_t *brng_state) nogil + int32_t random_positive_int32(brng_t *brng_state) nogil + int64_t random_positive_int(brng_t *brng_state) nogil + uint64_t random_uint(brng_t *brng_state) nogil + + double random_normal_zig(brng_t *brng_state, double loc, double scale) nogil + + double random_gamma(brng_t *brng_state, double shape, double scale) nogil + float random_gamma_float(brng_t *brng_state, float shape, float scale) nogil + + double random_exponential(brng_t *brng_state, double scale) nogil + double random_uniform(brng_t *brng_state, double lower, double range) nogil + double random_beta(brng_t *brng_state, double a, double b) nogil + double random_chisquare(brng_t *brng_state, double df) nogil + double random_f(brng_t *brng_state, double dfnum, double dfden) nogil + double random_standard_cauchy(brng_t *brng_state) nogil + double random_pareto(brng_t *brng_state, double a) nogil + double random_weibull(brng_t *brng_state, double a) nogil + double random_power(brng_t *brng_state, double a) nogil + double random_laplace(brng_t *brng_state, double loc, double scale) nogil + double random_gumbel(brng_t *brng_state, double loc, double scale) nogil + double random_logistic(brng_t *brng_state, double loc, double scale) nogil + double random_lognormal(brng_t *brng_state, double mean, double sigma) nogil + double random_rayleigh(brng_t *brng_state, double mode) nogil + double random_standard_t(brng_t *brng_state, double df) nogil + double random_noncentral_chisquare(brng_t *brng_state, double df, + double nonc) nogil + double random_noncentral_f(brng_t *brng_state, double dfnum, + double dfden, double nonc) nogil + double random_wald(brng_t *brng_state, double mean, double scale) nogil + double random_vonmises(brng_t *brng_state, double mu, double kappa) nogil + double random_triangular(brng_t *brng_state, double left, double mode, + double right) nogil + + int64_t random_poisson(brng_t *brng_state, double lam) nogil + int64_t random_negative_binomial(brng_t *brng_state, double n, double p) nogil + int64_t random_binomial(brng_t *brng_state, double p, int64_t n, binomial_t *binomial) nogil + int64_t random_logseries(brng_t *brng_state, double p) nogil + int64_t random_geometric_search(brng_t *brng_state, double p) nogil + int64_t random_geometric_inversion(brng_t *brng_state, double p) nogil + int64_t random_geometric(brng_t *brng_state, double p) nogil + int64_t random_zipf(brng_t *brng_state, double a) nogil + int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, + int64_t sample) nogil + uint64_t random_interval(brng_t *brng_state, uint64_t max) nogil + uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, + uint64_t rng, uint64_t mask) nogil + uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, + uint32_t rng, uint32_t mask, + int *bcnt, uint32_t *buf) nogil + + uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, + uint16_t rng, uint16_t mask, + int *bcnt, uint32_t *buf) nogil + uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, + uint8_t rng, uint8_t mask, + int *bcnt, uint32_t *buf) nogil + np.npy_bool random_buffered_bounded_bool(brng_t *brng_state, np.npy_bool off, + np.npy_bool rng, np.npy_bool mask, + int *bcnt, uint32_t *buf) nogil + void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, + uint64_t rng, np.npy_intp cnt, + uint64_t *out) nogil + void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, + uint32_t rng, np.npy_intp cnt, + uint32_t *out) nogil + void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, + uint16_t rng, np.npy_intp cnt, + uint16_t *out) nogil + void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, + uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil + void random_bounded_bool_fill(brng_t *brng_state, np.npy_bool off, + np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil diff --git a/_randomgen/core_prng/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx similarity index 89% rename from _randomgen/core_prng/dsfmt.pyx rename to _randomgen/randomgen/dsfmt.pyx index d1da29127237..5c979e6e8040 100644 --- a/_randomgen/core_prng/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -7,9 +7,9 @@ cimport numpy as np from common import interface from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy +import randomgen.pickle np.import_array() @@ -99,8 +99,8 @@ cdef class DSFMT: generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from core_prng.entropy import random_entropy - >>> from core_prng import RandomGenerator, DSFMT + >>> from randomgen.entropy import random_entropy + >>> from randomgen import RandomGenerator, DSFMT >>> seed = random_entropy() >>> rs = [RandomGenerator(DSFMT(seed)) for _ in range(10)] # Advance rs[i] by i jumps @@ -137,7 +137,7 @@ cdef class DSFMT: Sequences and Their Applications - SETA, 290--298, 2008. """ cdef dsfmt_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule cdef public object _cffi cdef public object _ctypes @@ -148,15 +148,15 @@ cdef class DSFMT: self.rng_state.state = PyArray_malloc_aligned(sizeof(dsfmt_t)) self.rng_state.buffered_uniforms = PyArray_calloc_aligned(DSFMT_N64, sizeof(double)) self.rng_state.buffer_loc = DSFMT_N64 - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed) - self._prng.state = self.rng_state - self._prng.next_uint64 = &dsfmt_uint64 - self._prng.next_uint32 = &dsfmt_uint32 - self._prng.next_double = &dsfmt_double - self._prng.next_raw = &dsfmt_raw - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + self._brng.state = self.rng_state + self._brng.next_uint64 = &dsfmt_uint64 + self._brng.next_uint32 = &dsfmt_uint32 + self._brng.next_double = &dsfmt_double + self._brng.next_raw = &dsfmt_raw + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) self._cffi = None self._ctypes = None @@ -170,24 +170,24 @@ cdef class DSFMT: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): PyArray_free_aligned(self.rng_state.state) PyArray_free_aligned(self.rng_state.buffered_uniforms) free(self.rng_state) - free(self._prng) + free(self._brng) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -247,7 +247,7 @@ cdef class DSFMT: Parameters ---------- iter : integer, positive - Number of times to jump the state of the prng. + Number of times to jump the state of the brng. Returns ------- @@ -283,7 +283,7 @@ cdef class DSFMT: buffered_uniforms = np.empty(DSFMT_N64,dtype=np.double) for i in range(DSFMT_N64): buffered_uniforms[i] = self.rng_state.buffered_uniforms[i] - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': {'state':np.asarray(state), 'idx':self.rng_state.state.idx}, 'buffer_loc': self.rng_state.buffer_loc, @@ -294,8 +294,8 @@ cdef class DSFMT: cdef Py_ssize_t i, j, loc = 0 if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) state = value['state']['state'] @@ -324,7 +324,7 @@ cdef class DSFMT: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._ctypes is not None: @@ -343,7 +343,7 @@ cdef class DSFMT: ctypes.cast(&dsfmt_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._prng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -361,7 +361,7 @@ cdef class DSFMT: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._cffi is not None: return self._cffi @@ -373,10 +373,10 @@ cdef class DSFMT: ffi = cffi.FFI() self._cffi = interface(self.rng_state, ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), - ffi.cast('double (*)(void *)',self._prng.next_double), - ffi.cast('void *',self._prng)) + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property @@ -386,8 +386,8 @@ cdef class DSFMT: Returns ------- - gen : core_prng.generator.RandomGenerator - Random generator used this instance as the core PRNG + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator diff --git a/_randomgen/core_prng/entropy.pyx b/_randomgen/randomgen/entropy.pyx similarity index 100% rename from _randomgen/core_prng/entropy.pyx rename to _randomgen/randomgen/entropy.pyx diff --git a/_randomgen/core_prng/generator.pyx b/_randomgen/randomgen/generator.pyx similarity index 93% rename from _randomgen/core_prng/generator.pyx rename to _randomgen/randomgen/generator.pyx index cb9a001c2669..0d988f678295 100644 --- a/_randomgen/core_prng/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -20,8 +20,8 @@ try: except ImportError: from dummy_threading import Lock -from core_prng.xoroshiro128 import Xoroshiro128 -import core_prng.pickle +from randomgen.xoroshiro128 import Xoroshiro128 +import randomgen.pickle np.import_array() @@ -38,35 +38,35 @@ _randint_types = {'bool': (0, 2), cdef class RandomGenerator: """ - Prototype Random Generator that consumes randoms from a CorePRNG class + Prototype Random Generator that consumes randoms from a Basic RNG class Parameters ---------- - prng : CorePRNG, optional + brng : BasicRNG, optional Object exposing a PyCapsule containing state and function pointers Examples -------- - >>> from core_prng.generator import RandomGenerator + >>> from randomgen.generator import RandomGenerator >>> rg = RandomGenerator() >>> rg.standard_normal() """ - cdef public object __core_prng - cdef prng_t *_prng + cdef public object _basicrng + cdef brng_t *_brng cdef binomial_t *_binomial cdef object lock poisson_lam_max = POISSON_LAM_MAX - def __init__(self, prng=None): - if prng is None: - prng = Xoroshiro128() - self.__core_prng = prng + def __init__(self, brng=None): + if brng is None: + brng = Xoroshiro128() + self._basicrng = brng - capsule = prng.capsule - cdef const char *anon_name = "CorePRNG" - if not PyCapsule_IsValid(capsule, anon_name): - raise ValueError("Invalid prng. The prng must be instantized.") - self._prng = PyCapsule_GetPointer(capsule, anon_name) + capsule = brng.capsule + cdef const char *name = "BasicRNG" + if not PyCapsule_IsValid(capsule, name): + raise ValueError("Invalid brng. The brng must be instantized.") + self._brng = PyCapsule_GetPointer(capsule, name) self._binomial = malloc(sizeof(binomial_t)) self.lock = Lock() @@ -77,7 +77,7 @@ cdef class RandomGenerator: return self.__str__() + ' at 0x{:X}'.format(id(self)) def __str__(self): - return 'RandomGenerator(' + self.__core_prng.__class__.__name__ + ')' + return 'RandomGenerator(' + self._basicrng.__class__.__name__ + ')' # Pickling support: def __getstate__(self): @@ -87,25 +87,25 @@ cdef class RandomGenerator: self.state = state def __reduce__(self): - return (core_prng.pickle.__generator_ctor, - (self.state['prng'],), + return (randomgen.pickle.__generator_ctor, + (self.state['brng'],), self.state) def seed(self, *args, **kwargs): """ TODO: Should this remain """ - self.__core_prng.seed(*args, **kwargs) + self._basicrng.seed(*args, **kwargs) return self @property def state(self): """Get or set the underlying PRNG's state""" - return self.__core_prng.state + return self._basicrng.state @state.setter def state(self, value): - self.__core_prng.state = value + self._basicrng.state = value def random_uintegers(self, size=None, int bits=64): """ @@ -144,23 +144,23 @@ cdef class RandomGenerator: if bits == 64: if size is None: with self.lock: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) array = np.empty(size, np.uint64) n = np.PyArray_SIZE(array) data64 = np.PyArray_DATA(array) with self.lock, nogil: for i in range(n): - data64[i] = self._prng.next_uint64(self._prng.state) + data64[i] = self._brng.next_uint64(self._brng.state) elif bits == 32: if size is None: with self.lock: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) array = np.empty(size, np.uint32) n = np.PyArray_SIZE(array) data32 = np.PyArray_DATA(array) with self.lock, nogil: for i in range(n): - data32[i] = self._prng.next_uint32(self._prng.state) + data32[i] = self._brng.next_uint32(self._brng.state) else: raise ValueError('Unknown value of bits. Must be either 32 or 64.') @@ -202,17 +202,17 @@ cdef class RandomGenerator: if not output: if size is None: with self.lock: - self._prng.next_raw(self._prng.state) + self._brng.next_raw(self._brng.state) return None n = np.asarray(size).sum() with self.lock, nogil: for i in range(n): - self._prng.next_raw(self._prng.state) + self._brng.next_raw(self._brng.state) return None if size is None: with self.lock: - return self._prng.next_raw(self._prng.state) + return self._brng.next_raw(self._brng.state) randoms = np.empty(size, np.uint64) randoms_data = np.PyArray_DATA(randoms) @@ -220,7 +220,7 @@ cdef class RandomGenerator: with self.lock, nogil: for i in range(n): - randoms_data[i] = self._prng.next_raw(self._prng.state) + randoms_data[i] = self._brng.next_raw(self._brng.state) return randoms def random_sample(self, size=None, dtype=np.float64, out=None): @@ -258,16 +258,16 @@ cdef class RandomGenerator: Examples -------- - >>> core_prng.random_sample() + >>> randomgen.random_sample() 0.47108547995356098 - >>> type(core_prng.random_sample()) + >>> type(randomgen.random_sample()) - >>> core_prng.random_sample((5,)) + >>> randomgen.random_sample((5,)) array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) Three-by-two array of random numbers from [-5, 0): - >>> 5 * core_prng.random_sample((3, 2)) - 5 + >>> 5 * randomgen.random_sample((3, 2)) - 5 array([[-3.99149989, -0.52338984], [-2.99091858, -0.79479508], [-1.23204345, -1.75224494]]) @@ -275,9 +275,9 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_sample, self._prng, size, self.lock, out) + return double_fill(&random_sample, self._brng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_sample_f, self._prng, size, self.lock, out) + return float_fill(&random_sample_f, self._brng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) @@ -319,7 +319,7 @@ cdef class RandomGenerator: Drawn samples from the parameterized beta distribution. """ - return cont(&random_beta, self._prng, size, self.lock, 2, + return cont(&random_beta, self._brng, size, self.lock, 2, a, 'a', CONS_POSITIVE, b, 'b', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -370,7 +370,7 @@ cdef class RandomGenerator: http://en.wikipedia.org/wiki/Exponential_distribution """ - return cont(&random_exponential, self._prng, size, self.lock, 1, + return cont(&random_exponential, self._brng, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -412,19 +412,19 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = core_prng.standard_exponential((3, 8000)) + >>> n = randomgen.standard_exponential((3, 8000)) """ key = np.dtype(dtype).name if key == 'float64': if method == u'zig': - return double_fill(&random_standard_exponential_zig, self._prng, size, self.lock, out) + return double_fill(&random_standard_exponential_zig, self._brng, size, self.lock, out) else: - return double_fill(&random_standard_exponential, self._prng, size, self.lock, out) + return double_fill(&random_standard_exponential, self._brng, size, self.lock, out) elif key == 'float32': if method == u'zig': - return float_fill(&random_standard_exponential_zig_f, self._prng, size, self.lock, out) + return float_fill(&random_standard_exponential_zig_f, self._brng, size, self.lock, out) else: - return float_fill(&random_standard_exponential_f, self._prng, size, self.lock, out) + return float_fill(&random_standard_exponential_f, self._brng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) @@ -458,7 +458,7 @@ cdef class RandomGenerator: Examples -------- - >>> RS = core_prng.mtrand.RandomState() # need a RandomState object + >>> RS = randomgen.mtrand.RandomState() # need a RandomState object >>> RS.tomaxint((2,2,2)) array([[[1170048599, 1600360186], [ 739731006, 1947757578]], @@ -480,7 +480,7 @@ cdef class RandomGenerator: if size is None: with self.lock: - return random_positive_int(self._prng) + return random_positive_int(self._brng) randoms = np.empty(size, dtype=np.int64) randoms_data = np.PyArray_DATA(randoms) @@ -488,7 +488,7 @@ cdef class RandomGenerator: for i in range(n): with self.lock, nogil: - randoms_data[i] = random_positive_int(self._prng) + randoms_data[i] = random_positive_int(self._brng) return randoms def randint(self, low, high=None, size=None, dtype=int): @@ -538,30 +538,30 @@ cdef class RandomGenerator: Examples -------- - >>> core_prng.randint(2, size=10) + >>> randomgen.randint(2, size=10) array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) - >>> core_prng.randint(1, size=10) + >>> randomgen.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: - >>> core_prng.randint(5, size=(2, 4)) + >>> randomgen.randint(5, size=(2, 4)) array([[4, 0, 2, 1], [3, 2, 2, 0]]) Generate a 1 x 3 array with 3 different upper bounds - >>> core_prng.randint(1, [3, 5, 10]) + >>> randomgen.randint(1, [3, 5, 10]) array([2, 2, 9]) Generate a 1 by 3 array with 3 different lower bounds - >>> core_prng.randint([1, 5, 7], 10) + >>> randomgen.randint([1, 5, 7], 10) array([9, 8, 7]) Generate a 2 by 4 array using broadcasting with dtype of uint8 - >>> core_prng.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) + >>> randomgen.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) """ @@ -574,23 +574,23 @@ cdef class RandomGenerator: raise TypeError('Unsupported dtype "%s" for randint' % key) if key == 'int32': - ret = _rand_int32(low, high, size, self._prng, self.lock) + ret = _rand_int32(low, high, size, self._brng, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, self._prng, self.lock) + ret = _rand_int64(low, high, size, self._brng, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, self._prng, self.lock) + ret = _rand_int16(low, high, size, self._brng, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, self._prng, self.lock) + ret = _rand_int8(low, high, size, self._brng, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, self._prng, self.lock) + ret = _rand_uint64(low, high, size, self._brng, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, self._prng, self.lock) + ret = _rand_uint32(low, high, size, self._brng, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, self._prng, self.lock) + ret = _rand_uint16(low, high, size, self._brng, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, self._prng, self.lock) + ret = _rand_uint8(low, high, size, self._brng, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, self._prng, self.lock) + ret = _rand_bool(low, high, size, self._brng, self.lock) if size is None and dtype in (np.bool, np.int, np.long): if np.array(ret).shape == (): @@ -615,7 +615,7 @@ cdef class RandomGenerator: Examples -------- - >>> core_prng.bytes(10) + >>> randomgen.bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ @@ -670,33 +670,33 @@ cdef class RandomGenerator: -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> core_prng.choice(5, 3) + >>> randomgen.choice(5, 3) array([0, 3, 4]) - >>> #This is equivalent to core_prng.randint(0,5,3) + >>> #This is equivalent to randomgen.randint(0,5,3) Generate a non-uniform random sample from np.arange(5) of size 3: - >>> core_prng.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) + >>> randomgen.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) array([3, 3, 0]) Generate a uniform random sample from np.arange(5) of size 3 without replacement: - >>> core_prng.choice(5, 3, replace=False) + >>> randomgen.choice(5, 3, replace=False) array([3,1,0]) - >>> #This is equivalent to core_prng.permutation(np.arange(5))[:3] + >>> #This is equivalent to randomgen.permutation(np.arange(5))[:3] Generate a non-uniform random sample from np.arange(5) of size 3 without replacement: - >>> core_prng.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) + >>> randomgen.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) array([2, 3, 0]) 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'] - >>> core_prng.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) + >>> randomgen.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], dtype='|S11') @@ -865,7 +865,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = core_prng.uniform(-1,0,1000) + >>> s = randomgen.uniform(-1,0,1000) All values are within the given interval: @@ -897,7 +897,7 @@ cdef class RandomGenerator: if not np.isfinite(range): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._prng, size, self.lock, 2, + return cont(&random_uniform, self._brng, size, self.lock, 2, _low, '', CONS_NONE, range, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -909,7 +909,7 @@ cdef class RandomGenerator: arange = np.PyArray_EnsureArray(temp) if not np.all(np.isfinite(arange)): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._prng, size, self.lock, 2, + return cont(&random_uniform, self._brng, size, self.lock, 2, alow, '', CONS_NONE, arange, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -947,13 +947,13 @@ cdef class RandomGenerator: Notes ----- This is a convenience function. If you want an interface that takes - a shape-tuple as the first argument, refer to core_prng.random_sample. + a shape-tuple as the first argument, refer to randomgen.random_sample. ``dtype`` can only be changed using a keyword argument. Examples -------- - >>> core_prng.rand(3,2) + >>> randomgen.rand(3,2) array([[ 0.14022471, 0.96360618], #random [ 0.37601032, 0.25528411], #random [ 0.49313049, 0.94909878]]) #random @@ -1005,16 +1005,16 @@ cdef class RandomGenerator: ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use: - ``sigma * core_prng.randn(...) + mu`` + ``sigma * randomgen.randn(...) + mu`` Examples -------- - >>> core_prng.randn() + >>> randomgen.randn() 2.1923875335537315 #random Two-by-four array of samples from N(3, 6.25): - >>> 2.5 * core_prng.randn(2, 4) + 3 + >>> 2.5 * randomgen.randn(2, 4) + 3 array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random @@ -1069,15 +1069,15 @@ cdef class RandomGenerator: To sample from N evenly spaced floating-point numbers between a and b, use:: - a + (b - a) * (core_prng.random_integers(N) - 1) / (N - 1.) + a + (b - a) * (randomgen.random_integers(N) - 1) / (N - 1.) Examples -------- - >>> core_prng.random_integers(5) + >>> randomgen.random_integers(5) 4 - >>> type(core_prng.random_integers(5)) + >>> type(randomgen.random_integers(5)) - >>> core_prng.random_integers(5, size=(3.,2.)) + >>> randomgen.random_integers(5, size=(3.,2.)) array([[5, 4], [3, 3], [4, 5]]) @@ -1086,13 +1086,13 @@ cdef class RandomGenerator: numbers between 0 and 2.5, inclusive (*i.e.*, from the set :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - >>> 2.5 * (core_prng.random_integers(5, size=(5,)) - 1) / 4. + >>> 2.5 * (randomgen.random_integers(5, size=(5,)) - 1) / 4. array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) Roll two six sided dice 1000 times and sum the results: - >>> d1 = core_prng.random_integers(1, 6, 1000) - >>> d2 = core_prng.random_integers(1, 6, 1000) + >>> d1 = randomgen.random_integers(1, 6, 1000) + >>> d2 = randomgen.random_integers(1, 6, 1000) >>> dsums = d1 + d2 Display results as a histogram: @@ -1145,22 +1145,22 @@ cdef class RandomGenerator: Examples -------- - >>> s = core_prng.standard_normal(8000) + >>> s = randomgen.standard_normal(8000) >>> s array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random -0.38672696, -0.4685006 ]) #random >>> s.shape (8000,) - >>> s = core_prng.standard_normal(size=(3, 4, 2)) + >>> s = randomgen.standard_normal(size=(3, 4, 2)) >>> s.shape (3, 4, 2) """ key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_gauss_zig, self._prng, size, self.lock, out) + return double_fill(&random_gauss_zig, self._brng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_gauss_zig_f, self._prng, size, self.lock, out) + return float_fill(&random_gauss_zig_f, self._brng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_normal' % key) @@ -1234,7 +1234,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = core_prng.normal(mu, sigma, 1000) + >>> s = randomgen.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1255,7 +1255,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_normal_zig, self._prng, size, self.lock, 2, + return cont(&random_normal_zig, self._brng, size, self.lock, 2, loc, '', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, @@ -1316,7 +1316,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = core_prng.complex_normal(size=1000) + >>> s = randomgen.complex_normal(size=1000) """ cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho cdef double *randoms_data @@ -1352,8 +1352,8 @@ cdef class RandomGenerator: raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation** 2)') if size is None: - f_real = random_gauss_zig(self._prng) - f_imag = random_gauss_zig(self._prng) + f_real = random_gauss_zig(self._brng) + f_imag = random_gauss_zig(self._brng) compute_complex(&f_real, &f_imag, floc_r, floc_i, fvar_r, fvar_i, f_rho) return PyComplex_FromDoubles(f_real, f_imag) @@ -1368,8 +1368,8 @@ cdef class RandomGenerator: j = 0 with self.lock, nogil: for i in range(n): - f_real = random_gauss_zig(self._prng) - f_imag = random_gauss_zig(self._prng) + f_real = random_gauss_zig(self._brng) + f_imag = random_gauss_zig(self._brng) randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) randoms_data[j] = floc_r + r_scale * f_real j += 2 @@ -1407,7 +1407,7 @@ cdef class RandomGenerator: with self.lock, nogil: n2 = 2 * n # Avoid compiler noise for cast for i in range(n2): - randoms_data[i] = random_gauss_zig(self._prng) + randoms_data[i] = random_gauss_zig(self._brng) with nogil: j = 0 for i in range(n): @@ -1485,7 +1485,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = core_prng.standard_gamma(shape, 1000000) + >>> s = randomgen.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1501,13 +1501,13 @@ cdef class RandomGenerator: cdef void *func key = np.dtype(dtype).name if key == 'float64': - return cont(&random_standard_gamma_zig, self._prng, size, self.lock, 1, + return cont(&random_standard_gamma_zig, self._brng, 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._prng, size, self.lock, + return cont_f(&random_standard_gamma_zig_f, self._brng, size, self.lock, shape, 'shape', CONS_NON_NEGATIVE, out) else: @@ -1572,7 +1572,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean and dispersion - >>> s = core_prng.gamma(shape, scale, 1000) + >>> s = randomgen.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1586,7 +1586,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_gamma, self._prng, size, self.lock, 2, + return cont(&random_gamma, self._brng, size, self.lock, 2, shape, 'shape', CONS_NON_NEGATIVE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -1662,7 +1662,7 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = core_prng.f(dfnum, dfden, 1000) + >>> s = randomgen.f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : @@ -1674,7 +1674,7 @@ cdef class RandomGenerator: level. """ - return cont(&random_f, self._prng, size, self.lock, 2, + return cont(&random_f, self._brng, size, self.lock, 2, dfnum, 'dfnum', CONS_POSITIVE, dfden, 'dfden', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -1737,16 +1737,16 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = core_prng.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, normed=True) - >>> c_vals = core_prng.f(dfnum, dfden, 1000000) + >>> c_vals = randomgen.f(dfnum, dfden, 1000000) >>> F = np.histogram(c_vals, bins=50, normed=True) >>> plt.plot(F[1][1:], F[0]) >>> plt.plot(NF[1][1:], NF[0]) >>> plt.show() """ - return cont(&random_noncentral_f, self._prng, size, self.lock, 3, + return cont(&random_noncentral_f, self._brng, size, self.lock, 3, dfnum, 'dfnum', CONS_POSITIVE, dfden, 'dfden', CONS_POSITIVE, nonc, 'nonc', CONS_NON_NEGATIVE, None) @@ -1810,11 +1810,11 @@ cdef class RandomGenerator: Examples -------- - >>> core_prng.chisquare(2,4) + >>> randomgen.chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) """ - return cont(&random_chisquare, self._prng, size, self.lock, 1, + return cont(&random_chisquare, self._brng, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -1875,7 +1875,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(core_prng.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), ... bins=200, normed=True) >>> plt.show() @@ -1883,9 +1883,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(core_prng.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), normed=True) - >>> values2 = plt.hist(core_prng.chisquare(3, 100000), + >>> values2 = plt.hist(randomgen.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), normed=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1894,12 +1894,12 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(core_prng.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), ... bins=200, normed=True) >>> plt.show() """ - return cont(&random_noncentral_chisquare, self._prng, size, self.lock, 2, + return cont(&random_noncentral_chisquare, self._brng, size, self.lock, 2, df, 'df', CONS_POSITIVE, nonc, 'nonc', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -1959,13 +1959,13 @@ cdef class RandomGenerator: -------- Draw samples and plot the distribution: - >>> s = core_prng.standard_cauchy(1000000) + >>> s = randomgen.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._prng, size, self.lock, 0, + return cont(&random_standard_cauchy, self._brng, size, self.lock, 0, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) def standard_t(self, df, size=None): @@ -2032,7 +2032,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = core_prng.standard_t(10, size=100000) + >>> s = randomgen.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -2056,7 +2056,7 @@ cdef class RandomGenerator: probability of about 99% of being true. """ - return cont(&random_standard_t, self._prng, size, self.lock, 1, + return cont(&random_standard_t, self._brng, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0, '', CONS_NONE, 0, '', CONS_NONE, @@ -2126,7 +2126,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = core_prng.vonmises(mu, kappa, 1000) + >>> s = randomgen.vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -2140,7 +2140,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_vonmises, self._prng, size, self.lock, 2, + return cont(&random_vonmises, self._brng, size, self.lock, 2, mu, 'mu', CONS_NONE, kappa, 'kappa', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2226,7 +2226,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (core_prng.pareto(a, 1000) + 1) * m + >>> s = (randomgen.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2238,7 +2238,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_pareto, self._prng, size, self.lock, 1, + return cont(&random_pareto, self._brng, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2319,7 +2319,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = core_prng.weibull(a, 1000) + >>> s = randomgen.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2329,14 +2329,14 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(core_prng.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(randomgen.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._prng, size, self.lock, 1, + return cont(&random_weibull, self._brng, size, self.lock, 1, a, 'a', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2399,7 +2399,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = core_prng.power(a, samples) + >>> s = randomgen.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2415,20 +2415,20 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats - >>> rvs = core_prng.power(5, 1000000) - >>> rvsp = core_prng.pareto(5, 1000000) + >>> rvs = randomgen.power(5, 1000000) + >>> rvsp = randomgen.pareto(5, 1000000) >>> xx = np.linspace(0,1,100) >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() >>> plt.hist(rvs, bins=50, normed=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('core_prng.power(5)') + >>> plt.title('randomgen.power(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + core_prng.pareto(5)') + >>> plt.title('inverse of 1 + randomgen.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) @@ -2436,7 +2436,7 @@ cdef class RandomGenerator: >>> plt.title('inverse of stats.pareto(5)') """ - return cont(&random_power, self._prng, size, self.lock, 1, + return cont(&random_power, self._brng, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2502,7 +2502,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = core_prng.laplace(loc, scale, 1000) + >>> s = randomgen.laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2520,7 +2520,7 @@ cdef class RandomGenerator: >>> plt.plot(x,g) """ - return cont(&random_laplace, self._prng, size, self.lock, 2, + return cont(&random_laplace, self._brng, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2604,7 +2604,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = core_prng.gumbel(mu, beta, 1000) + >>> s = randomgen.gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2622,7 +2622,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = core_prng.normal(mu, beta, 1000) + ... a = randomgen.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, normed=True) @@ -2637,7 +2637,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_gumbel, self._prng, size, self.lock, 2, + return cont(&random_gumbel, self._brng, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2704,7 +2704,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = core_prng.logistic(loc, scale, 10000) + >>> s = randomgen.logistic(loc, scale, 10000) >>> count, bins, ignored = plt.hist(s, bins=50) # plot against distribution @@ -2716,7 +2716,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_logistic, self._prng, size, self.lock, 2, + return cont(&random_logistic, self._brng, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -2786,7 +2786,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = core_prng.lognormal(mu, sigma, 1000) + >>> s = randomgen.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2810,7 +2810,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + core_prng.random(100) + ... a = 10. + randomgen.random(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -2826,7 +2826,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_lognormal, self._prng, size, self.lock, 2, + return cont(&random_lognormal, self._brng, size, self.lock, 2, mean, 'mean', CONS_NONE, sigma, 'sigma', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2877,7 +2877,7 @@ cdef class RandomGenerator: -------- Draw values from the distribution and plot the histogram - >>> values = hist(core_prng.rayleigh(3, 100000), bins=200, normed=True) + >>> values = hist(randomgen.rayleigh(3, 100000), bins=200, normed=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 @@ -2885,7 +2885,7 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = core_prng.rayleigh(modevalue, 1000000) + >>> s = randomgen.rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: @@ -2893,7 +2893,7 @@ cdef class RandomGenerator: 0.087300000000000003 """ - return cont(&random_rayleigh, self._prng, size, self.lock, 1, + return cont(&random_rayleigh, self._brng, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2957,11 +2957,11 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(core_prng.wald(3, 2, 100000), bins=200, normed=True) + >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, normed=True) >>> plt.show() """ - return cont(&random_wald, self._prng, size, self.lock, 2, + return cont(&random_wald, self._brng, size, self.lock, 2, mean, 'mean', CONS_POSITIVE, scale, 'scale', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -3024,7 +3024,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(core_prng.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(randomgen.triangular(-3, 0, 8, 100000), bins=200, ... normed=True) >>> plt.show() @@ -3048,7 +3048,7 @@ cdef class RandomGenerator: raise ValueError("mode > right") if fleft == fright: raise ValueError("left == right") - return cont(&random_triangular, self._prng, size, self.lock, 3, + return cont(&random_triangular, self._brng, size, self.lock, 3, fleft, '', CONS_NONE, fmode, '', CONS_NONE, fright, '', CONS_NONE, None) @@ -3060,7 +3060,7 @@ cdef class RandomGenerator: if np.any(np.equal(oleft, oright)): raise ValueError("left == right") - return cont_broadcast_3(&random_triangular, self._prng, size, self.lock, + return cont_broadcast_3(&random_triangular, self._brng, size, self.lock, oleft, '', CONS_NONE, omode, '', CONS_NONE, oright, '', CONS_NONE) @@ -3137,7 +3137,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = core_prng.binomial(n, p, 1000) + >>> s = randomgen.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 @@ -3147,7 +3147,7 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(core_prng.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(randomgen.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ @@ -3182,7 +3182,7 @@ cdef class RandomGenerator: for i in range(cnt): _dp = (np.PyArray_MultiIter_DATA(it, 1))[0] _in = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._prng, _dp, _in, self._binomial) + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._brng, _dp, _in, self._binomial) np.PyArray_MultiIter_NEXT(it) @@ -3195,7 +3195,7 @@ cdef class RandomGenerator: if size is None: with self.lock: - return random_binomial(self._prng, _dp, _in, self._binomial) + return random_binomial(self._brng, _dp, _in, self._binomial) randoms = np.empty(size, np.int64) cnt = np.PyArray_SIZE(randoms) @@ -3203,7 +3203,7 @@ cdef class RandomGenerator: with self.lock, nogil: for i in range(cnt): - randoms_data[i] = random_binomial(self._prng, _dp, _in, + randoms_data[i] = random_binomial(self._brng, _dp, _in, self._binomial) return randoms @@ -3274,13 +3274,13 @@ cdef class RandomGenerator: for each successive well, that is what is the probability of a single success after drilling 5 wells, after 6 wells, etc.? - >>> s = core_prng.negative_binomial(1, 0.1, 100000) + >>> s = randomgen.negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): ... probability = sum(s>> import numpy as np - >>> s = core_prng.poisson(5, 10000) + >>> s = randomgen.poisson(5, 10000) Display histogram of the sample: @@ -3348,10 +3348,10 @@ cdef class RandomGenerator: Draw each 100 values for lambda 100 and 500: - >>> s = core_prng.poisson(lam=(100., 500.), size=(100, 2)) + >>> s = randomgen.poisson(lam=(100., 500.), size=(100, 2)) """ - return disc(&random_poisson, self._prng, size, self.lock, 1, 0, + return disc(&random_poisson, self._brng, size, self.lock, 1, 0, lam, 'lam', CONS_POISSON, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3413,7 +3413,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 2. # parameter - >>> s = core_prng.zipf(a, 1000) + >>> s = randomgen.zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3430,7 +3430,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return disc(&random_zipf, self._prng, size, self.lock, 1, 0, + return disc(&random_zipf, self._brng, size, self.lock, 1, 0, a, 'a', CONS_GT_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3473,7 +3473,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = core_prng.geometric(p=0.35, size=10000) + >>> z = randomgen.geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3481,7 +3481,7 @@ cdef class RandomGenerator: 0.34889999999999999 #random """ - return disc(&random_geometric, self._prng, size, self.lock, 1, 0, + return disc(&random_geometric, self._brng, size, self.lock, 1, 0, p, 'p', CONS_BOUNDED_0_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3561,7 +3561,7 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = core_prng.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = randomgen.hypergeometric(ngood, nbad, nsamp, 1000) >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3569,7 +3569,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = core_prng.hypergeometric(15, 15, 15, 100000) + >>> s = randomgen.hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3596,14 +3596,14 @@ cdef class RandomGenerator: raise ValueError("nsample < 1") if lngood + lnbad < lnsample: raise ValueError("ngood + nbad < nsample") - return disc(&random_hypergeometric, self._prng, size, self.lock, 0, 3, + return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, lngood, 'ngood', CONS_NON_NEGATIVE, lnbad, 'nbad', CONS_NON_NEGATIVE, lnsample, 'nsample', CONS_GTE_1) if np.any(np.less(np.add(ongood, onbad),onsample)): raise ValueError("ngood + nbad < nsample") - return discrete_broadcast_iii(&random_hypergeometric, self._prng, size, self.lock, + return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, ongood, 'ngood', CONS_NON_NEGATIVE, onbad, nbad, CONS_NON_NEGATIVE, onsample, 'nsample', CONS_GTE_1) @@ -3670,7 +3670,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = core_prng.logseries(a, 10000) + >>> s = randomgen.logseries(a, 10000) >>> count, bins, ignored = plt.hist(s) # plot against distribution @@ -3682,7 +3682,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return disc(&random_logseries, self._prng, size, self.lock, 1, 0, + return disc(&random_logseries, self._brng, size, self.lock, 1, 0, p, 'p', CONS_BOUNDED_0_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3758,7 +3758,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = core_prng.multivariate_normal(mean, cov, 5000).T + >>> x, y = randomgen.multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3778,7 +3778,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = core_prng.multivariate_normal(mean, cov, (3, 3)) + >>> x = randomgen.multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3890,14 +3890,14 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> core_prng.multinomial(20, [1/6.]*6, size=1) + >>> randomgen.multinomial(20, [1/6.]*6, size=1) array([[4, 1, 7, 5, 2, 1]]) It landed 4 times on 1, once on 2, etc. Now, throw the dice 20 times, and 20 times again: - >>> core_prng.multinomial(20, [1/6.]*6, size=2) + >>> randomgen.multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], [2, 4, 3, 4, 0, 7]]) @@ -3906,7 +3906,7 @@ cdef class RandomGenerator: A loaded die is more likely to land on number 6: - >>> core_prng.multinomial(100, [1/7.]*5 + [2/7.]) + >>> randomgen.multinomial(100, [1/7.]*5 + [2/7.]) array([11, 16, 14, 17, 16, 26]) The probability inputs should be normalized. As an implementation @@ -3915,12 +3915,12 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> core_prng.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + >>> randomgen.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT array([38, 62]) not like: - >>> core_prng.multinomial(100, [1.0, 2.0]) # WRONG + >>> randomgen.multinomial(100, [1.0, 2.0]) # WRONG array([100, 0]) """ @@ -3956,7 +3956,7 @@ cdef class RandomGenerator: Sum = 1.0 dn = n for j in range(d-1): - mnix[i+j] = random_binomial(self._prng, pix[j]/Sum, dn, + mnix[i+j] = random_binomial(self._brng, pix[j]/Sum, dn, self._binomial) dn = dn - mnix[i+j] if dn <= 0: @@ -4021,7 +4021,7 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = core_prng.dirichlet((10, 5, 3), 20).transpose() + >>> s = randomgen.dirichlet((10, 5, 3), 20).transpose() >>> plt.barh(range(20), s[0]) >>> plt.barh(range(20), s[1], left=s[0], color='g') @@ -4082,7 +4082,7 @@ cdef class RandomGenerator: while i < totsize: acc = 0.0 for j in range(k): - val_data[i+j] = random_standard_gamma_zig(self._prng, + val_data[i+j] = random_standard_gamma_zig(self._brng, alpha_data[j]) acc = acc + val_data[i + j] invacc = 1/acc @@ -4115,14 +4115,14 @@ cdef class RandomGenerator: Examples -------- >>> arr = np.arange(10) - >>> core_prng.shuffle(arr) + >>> randomgen.shuffle(arr) >>> arr [1 7 5 2 9 4 3 6 0 8] Multi-dimensional arrays are only shuffled along the first axis: >>> arr = np.arange(9).reshape((3, 3)) - >>> core_prng.shuffle(arr) + >>> randomgen.shuffle(arr) >>> arr array([[3, 4, 5], [6, 7, 8], @@ -4160,7 +4160,7 @@ cdef class RandomGenerator: buf = np.empty_like(x[0]) with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._prng, i) + j = random_interval(self._brng, i) if i == j : continue # i == j is not needed and memcpy is undefined. buf[...] = x[j] x[j] = x[i] @@ -4169,14 +4169,14 @@ cdef class RandomGenerator: # Untyped path. with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._prng, i) + j = random_interval(self._brng, i) x[i], x[j] = x[j], x[i] 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 = random_interval(self._prng, i) + j = random_interval(self._brng, i) string.memcpy(buf, data + j * stride, itemsize) string.memcpy(data + j * stride, data + i * stride, itemsize) string.memcpy(data + i * stride, buf, itemsize) @@ -4204,14 +4204,14 @@ cdef class RandomGenerator: Examples -------- - >>> core_prng.permutation(10) + >>> randomgen.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) - >>> core_prng.permutation([1, 4, 9, 12, 15]) + >>> randomgen.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) >>> arr = np.arange(9).reshape((3, 3)) - >>> core_prng.permutation(arr) + >>> randomgen.permutation(arr) array([[6, 7, 8], [0, 1, 2], [3, 4, 5]]) diff --git a/_randomgen/core_prng/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx similarity index 82% rename from _randomgen/core_prng/mt19937.pyx rename to _randomgen/randomgen/mt19937.pyx index 9622b725a236..483bd6baa107 100644 --- a/_randomgen/core_prng/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -7,9 +7,9 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t -import core_prng.pickle -from core_prng.entropy import random_entropy +from distributions cimport brng_t +import randomgen.pickle +from randomgen.entropy import random_entropy np.import_array() @@ -42,7 +42,7 @@ cdef uint64_t mt19937_raw(void *st) nogil: cdef class MT19937: """ - Prototype Core PRNG using MT19937 + Prototype Basic RNG using MT19937 Parameters ---------- @@ -55,26 +55,26 @@ cdef class MT19937: `RandomGenerator` object. """ cdef mt19937_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed) - self._prng.state = self.rng_state - self._prng.next_uint64 = &mt19937_uint64 - self._prng.next_uint32 = &mt19937_uint32 - self._prng.next_double = &mt19937_double - self._prng.next_raw = &mt19937_raw + self._brng.state = self.rng_state + self._brng.next_uint64 = &mt19937_uint64 + self._brng.next_uint32 = &mt19937_uint32 + self._brng.next_double = &mt19937_double + self._brng.next_raw = &mt19937_raw - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) def __dealloc__(self): free(self.rng_state) - free(self._prng) + free(self._brng) # Pickling support: def __getstate__(self): @@ -84,8 +84,8 @@ cdef class MT19937: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __random_integer(self, bits=64): @@ -107,9 +107,9 @@ cdef class MT19937: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -117,10 +117,10 @@ cdef class MT19937: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -177,7 +177,7 @@ cdef class MT19937: for i in range(624): key[i] = self.rng_state.key[i] - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': {'key':key, 'pos': self.rng_state.pos}} @state.setter @@ -185,14 +185,14 @@ cdef class MT19937: 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 ={'prng': 'MT19937', + value ={'brng': 'MT19937', 'state':{'key': value[1], 'pos': value[2]}} if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) key = value['state']['key'] diff --git a/_randomgen/core_prng/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx similarity index 83% rename from _randomgen/core_prng/pcg32.pyx rename to _randomgen/randomgen/pcg32.pyx index 104701142e78..d0b57a2b0562 100644 --- a/_randomgen/core_prng/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -5,9 +5,9 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy +import randomgen.pickle np.import_array() @@ -47,7 +47,7 @@ cdef uint64_t pcg32_raw(void* st) nogil: cdef class PCG32: """ - Prototype Core PRNG using pcg64 + Prototype Basic RNG using pcg64 Parameters ---------- @@ -60,23 +60,23 @@ cdef class PCG32: for use in a `RandomGenerator` object. """ cdef pcg32_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg32_state)) self.rng_state.pcg_state = malloc(sizeof(pcg32_random_t)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, inc) - self._prng.state = self.rng_state - self._prng.next_uint64 = &pcg32_uint64 - self._prng.next_uint32 = &pcg32_uint32 - self._prng.next_double = &pcg32_double - self._prng.next_raw = &pcg32_raw + self._brng.state = self.rng_state + self._brng.next_uint64 = &pcg32_uint64 + self._brng.next_uint32 = &pcg32_uint32 + self._brng.next_double = &pcg32_double + self._brng.next_raw = &pcg32_raw - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -86,13 +86,13 @@ cdef class PCG32: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state) - free(self._prng) + free(self._brng) def __random_integer(self, bits=64): """ @@ -113,9 +113,9 @@ cdef class PCG32: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -123,10 +123,10 @@ cdef class PCG32: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -183,7 +183,7 @@ cdef class PCG32: @property def state(self): """Get or set the PRNG state""" - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': {'state': self.rng_state.pcg_state.state, 'inc':self.rng_state.pcg_state.inc}} @@ -191,8 +191,8 @@ cdef class PCG32: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) self.rng_state.pcg_state.state = value['state']['state'] diff --git a/_randomgen/core_prng/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx similarity index 87% rename from _randomgen/core_prng/pcg64.pyx rename to _randomgen/randomgen/pcg64.pyx index 332553c1b119..7afe1266d9f5 100644 --- a/_randomgen/core_prng/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -5,9 +5,9 @@ import numpy as np cimport numpy as np from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy +import randomgen.pickle np.import_array() @@ -62,7 +62,7 @@ cdef double pcg64_double(void* st) nogil: cdef class PCG64: """ - Prototype Core PRNG using pcg64 + Prototype Basic RNG using pcg64 Parameters ---------- @@ -75,23 +75,23 @@ cdef class PCG64: for use in a `RandomGenerator` object. """ cdef pcg64_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg64_state)) self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, inc) - self._prng.state = self.rng_state - self._prng.next_uint64 = &pcg64_uint64 - self._prng.next_uint32 = &pcg64_uint32 - self._prng.next_double = &pcg64_double - self._prng.next_raw = &pcg64_uint64 + self._brng.state = self.rng_state + self._brng.next_uint64 = &pcg64_uint64 + self._brng.next_uint32 = &pcg64_uint32 + self._brng.next_double = &pcg64_double + self._brng.next_raw = &pcg64_uint64 - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -101,13 +101,13 @@ cdef class PCG64: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -132,9 +132,9 @@ cdef class PCG64: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -142,10 +142,10 @@ cdef class PCG64: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -217,7 +217,7 @@ cdef class PCG64: state = self.rng_state.pcg_state.state inc = self.rng_state.pcg_state.inc - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': {'state': state, 'inc':inc}, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -226,8 +226,8 @@ cdef class PCG64: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) IF PCG_EMULATED_MATH==1: diff --git a/_randomgen/core_prng/philox.pyx b/_randomgen/randomgen/philox.pyx similarity index 87% rename from _randomgen/core_prng/philox.pyx rename to _randomgen/randomgen/philox.pyx index e55bd27bd314..a61f785331b4 100644 --- a/_randomgen/core_prng/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -4,9 +4,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy, seed_by_array -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() @@ -52,7 +52,7 @@ cdef double philox_double(void*st) nogil: cdef class Philox: """ - Prototype Core PRNG using philox + Prototype Basic RNG using philox Parameters ---------- @@ -65,7 +65,7 @@ cdef class Philox: a `RandomGenerator` object. """ cdef philox_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None, counter=None, key=None): @@ -74,17 +74,17 @@ cdef class Philox: sizeof(philox4x64_ctr_t)) self.rng_state.key = malloc( sizeof(philox4x64_key_t)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) - self._prng.state = self.rng_state - self._prng.next_uint64 = &philox_uint64 - self._prng.next_uint32 = &philox_uint32 - self._prng.next_double = &philox_double - self._prng.next_raw = &philox_uint64 + self._brng.state = self.rng_state + self._brng.next_uint64 = &philox_uint64 + self._brng.next_uint32 = &philox_uint32 + self._brng.next_double = &philox_double + self._brng.next_raw = &philox_uint64 - cdef const char *name = 'CorePRNG' - self.capsule = PyCapsule_New( self._prng, name, NULL) + cdef const char *name = 'BasicRNG' + self.capsule = PyCapsule_New( self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -94,15 +94,15 @@ cdef class Philox: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -130,9 +130,9 @@ cdef class Philox: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -140,10 +140,10 @@ cdef class Philox: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -217,7 +217,7 @@ cdef class Philox: buffer[i] = self.rng_state.buffer[i] state = {'counter': ctr, 'key': key} - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos, @@ -228,8 +228,8 @@ cdef class Philox: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): diff --git a/_randomgen/core_prng/pickle.py b/_randomgen/randomgen/pickle.py similarity index 65% rename from _randomgen/core_prng/pickle.py rename to _randomgen/randomgen/pickle.py index 40557d63edbd..4ec96663d4a3 100644 --- a/_randomgen/core_prng/pickle.py +++ b/_randomgen/randomgen/pickle.py @@ -20,13 +20,13 @@ 'Xoroshiro128': Xoroshiro128} -def __generator_ctor(prng_name='mt19937'): +def __generator_ctor(brng_name='mt19937'): """ Pickling helper function that returns a mod_name.RandomState object Parameters ---------- - prng_name: str + brng_name: str String containing the core PRNG Returns @@ -35,38 +35,38 @@ def __generator_ctor(prng_name='mt19937'): RandomGenerator using the named core PRNG """ try: - prng_name = prng_name.decode('ascii') + brng_name = brng_name.decode('ascii') except AttributeError: pass - if prng_name in PRNGS: - prng = PRNGS[prng_name] + if brng_name in PRNGS: + brng = PRNGS[brng_name] else: - raise ValueError(str(prng_name) + ' is not a known PRNG module.') + raise ValueError(str(brng_name) + ' is not a known PRNG module.') - return RandomGenerator(prng()) + return RandomGenerator(brng()) -def __prng_ctor(prng_name='mt19937'): +def __brng_ctor(brng_name='mt19937'): """ Pickling helper function that returns a mod_name.RandomState object Parameters ---------- - prng_name: str - String containing the core PRNG + brng_name: str + String containing the name of the Basic RNG Returns ------- - prng: CorePRNG - Core PRNG instance + brng: BasicRNG + Basic RNG instance """ try: - prng_name = prng_name.decode('ascii') + brng_name = brng_name.decode('ascii') except AttributeError: pass - if prng_name in PRNGS: - prng = PRNGS[prng_name] + if brng_name in PRNGS: + brng = PRNGS[brng_name] else: - raise ValueError(str(prng_name) + ' is not a known PRNG module.') + raise ValueError(str(brng_name) + ' is not a known PRNG module.') - return prng() + return brng() diff --git a/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.c b/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.c similarity index 100% rename from _randomgen/core_prng/src/aligned_malloc/aligned_malloc.c rename to _randomgen/randomgen/src/aligned_malloc/aligned_malloc.c diff --git a/_randomgen/core_prng/src/aligned_malloc/aligned_malloc.h b/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h similarity index 100% rename from _randomgen/core_prng/src/aligned_malloc/aligned_malloc.h rename to _randomgen/randomgen/src/aligned_malloc/aligned_malloc.h diff --git a/_randomgen/core_prng/src/common/inttypes.h b/_randomgen/randomgen/src/common/inttypes.h similarity index 100% rename from _randomgen/core_prng/src/common/inttypes.h rename to _randomgen/randomgen/src/common/inttypes.h diff --git a/_randomgen/core_prng/src/common/stdint.h b/_randomgen/randomgen/src/common/stdint.h similarity index 100% rename from _randomgen/core_prng/src/common/stdint.h rename to _randomgen/randomgen/src/common/stdint.h diff --git a/_randomgen/core_prng/src/distributions/binomial.h b/_randomgen/randomgen/src/distributions/binomial.h similarity index 100% rename from _randomgen/core_prng/src/distributions/binomial.h rename to _randomgen/randomgen/src/distributions/binomial.h diff --git a/_randomgen/core_prng/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c similarity index 65% rename from _randomgen/core_prng/src/distributions/distributions.c rename to _randomgen/randomgen/src/distributions/distributions.c index daed964ecc09..c08d5be415dc 100644 --- a/_randomgen/core_prng/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -3,88 +3,88 @@ #include "ziggurat_constants.h" /* Random generators for external use */ -float random_sample_f(prng_t *prng_state) { return random_float(prng_state); } +float random_sample_f(brng_t *brng_state) { return random_float(brng_state); } -double random_sample(prng_t *prng_state) { return random_double(prng_state); } +double random_sample(brng_t *brng_state) { return random_double(brng_state); } -double random_standard_exponential(prng_t *prng_state) { - return -log(1.0 - random_double(prng_state)); +double random_standard_exponential(brng_t *brng_state) { + return -log(1.0 - random_double(brng_state)); } -float random_standard_exponential_f(prng_t *prng_state) { - return -logf(1.0f - random_float(prng_state)); +float random_standard_exponential_f(brng_t *brng_state) { + return -logf(1.0f - random_float(brng_state)); } /* -double random_gauss(prng_t *prng_state) { - if (prng_state->has_gauss) { - const double temp = prng_state->gauss; - prng_state->has_gauss = false; - prng_state->gauss = 0.0; +double random_gauss(brng_t *brng_state) { + if (brng_state->has_gauss) { + const double temp = brng_state->gauss; + brng_state->has_gauss = false; + brng_state->gauss = 0.0; return temp; } else { double f, x1, x2, r2; do { - x1 = 2.0 * random_double(prng_state) - 1.0; - x2 = 2.0 * random_double(prng_state) - 1.0; + x1 = 2.0 * random_double(brng_state) - 1.0; + x2 = 2.0 * random_double(brng_state) - 1.0; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); // Box-Muller transform f = sqrt(-2.0 * log(r2) / r2); // Keep for next call - prng_state->gauss = f * x1; - prng_state->has_gauss = true; + brng_state->gauss = f * x1; + brng_state->has_gauss = true; return f * x2; } } -float random_gauss_f(prng_t *prng_state) { - if (prng_state->has_gauss_f) { - const float temp = prng_state->gauss_f; - prng_state->has_gauss_f = false; - prng_state->gauss_f = 0.0f; +float random_gauss_f(brng_t *brng_state) { + if (brng_state->has_gauss_f) { + const float temp = brng_state->gauss_f; + brng_state->has_gauss_f = false; + brng_state->gauss_f = 0.0f; return temp; } else { float f, x1, x2, r2; do { - x1 = 2.0f * random_float(prng_state) - 1.0f; - x2 = 2.0f * random_float(prng_state) - 1.0f; + x1 = 2.0f * random_float(brng_state) - 1.0f; + x2 = 2.0f * random_float(brng_state) - 1.0f; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); // Box-Muller transform f = sqrtf(-2.0f * logf(r2) / r2); // Keep for next call - prng_state->gauss_f = f * x1; - prng_state->has_gauss_f = true; + brng_state->gauss_f = f * x1; + brng_state->has_gauss_f = true; return f * x2; } } */ -static NPY_INLINE double standard_exponential_zig(prng_t *prng_state); +static NPY_INLINE double standard_exponential_zig(brng_t *brng_state); -static double standard_exponential_zig_unlikely(prng_t *prng_state, uint8_t idx, +static double standard_exponential_zig_unlikely(brng_t *brng_state, uint8_t idx, double x) { if (idx == 0) { - return ziggurat_exp_r - log(random_double(prng_state)); - } else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(prng_state) + + return ziggurat_exp_r - log(random_double(brng_state)); + } else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(brng_state) + fe_double[idx] < exp(-x)) { return x; } else { - return standard_exponential_zig(prng_state); + return standard_exponential_zig(brng_state); } } -static NPY_INLINE double standard_exponential_zig(prng_t *prng_state) { +static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { uint64_t ri; uint8_t idx; double x; - ri = random_uint64(prng_state); + ri = random_uint64(brng_state); ri >>= 3; idx = ri & 0xFF; ri >>= 8; @@ -92,33 +92,33 @@ static NPY_INLINE double standard_exponential_zig(prng_t *prng_state) { if (ri < ke_double[idx]) { return x; // 98.9% of the time we return here 1st try } - return standard_exponential_zig_unlikely(prng_state, idx, x); + return standard_exponential_zig_unlikely(brng_state, idx, x); } -double random_standard_exponential_zig(prng_t *prng_state) { - return standard_exponential_zig(prng_state); +double random_standard_exponential_zig(brng_t *brng_state) { + return standard_exponential_zig(brng_state); } -static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state); +static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state); -static float standard_exponential_zig_unlikely_f(prng_t *prng_state, +static float standard_exponential_zig_unlikely_f(brng_t *brng_state, uint8_t idx, float x) { if (idx == 0) { - return ziggurat_exp_r_f - logf(random_float(prng_state)); - } else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(prng_state) + + return ziggurat_exp_r_f - logf(random_float(brng_state)); + } else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(brng_state) + fe_float[idx] < expf(-x)) { return x; } else { - return standard_exponential_zig_f(prng_state); + return standard_exponential_zig_f(brng_state); } } -static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) { +static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { uint32_t ri; uint8_t idx; float x; - ri = random_uint32(prng_state); + ri = random_uint32(brng_state); ri >>= 1; idx = ri & 0xFF; ri >>= 8; @@ -126,14 +126,14 @@ static NPY_INLINE float standard_exponential_zig_f(prng_t *prng_state) { if (ri < ke_float[idx]) { return x; // 98.9% of the time we return here 1st try } - return standard_exponential_zig_unlikely_f(prng_state, idx, x); + return standard_exponential_zig_unlikely_f(brng_state, idx, x); } -float random_standard_exponential_zig_f(prng_t *prng_state) { - return standard_exponential_zig_f(prng_state); +float random_standard_exponential_zig_f(brng_t *brng_state) { + return standard_exponential_zig_f(brng_state); } -double random_gauss_zig(prng_t *prng_state) { +double random_gauss_zig(brng_t *brng_state) { uint64_t r; int sign; int64_t rabs; @@ -141,7 +141,7 @@ double random_gauss_zig(prng_t *prng_state) { double x, xx, yy; for (;;) { /* r = e3n52sb8 */ - r = random_uint64(prng_state); + r = random_uint64(brng_state); idx = r & 0xff; r >>= 8; sign = r & 0x1; @@ -153,21 +153,21 @@ double random_gauss_zig(prng_t *prng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r * log(random_double(prng_state)); - yy = -log(random_double(prng_state)); + xx = -ziggurat_nor_inv_r * log(random_double(brng_state)); + yy = -log(random_double(brng_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]) * random_double(prng_state) + + if (((fi_double[idx - 1] - fi_double[idx]) * random_double(brng_state) + fi_double[idx]) < exp(-0.5 * x * x)) return x; } } } -float random_gauss_zig_f(prng_t *prng_state) { +float random_gauss_zig_f(brng_t *brng_state) { uint32_t r; int sign; int32_t rabs; @@ -175,7 +175,7 @@ float random_gauss_zig_f(prng_t *prng_state) { float x, xx, yy; for (;;) { /* r = n23sb8 */ - r = random_uint32(prng_state); + r = random_uint32(brng_state); idx = r & 0xff; sign = (r >> 8) & 0x1; rabs = (int32_t)((r >> 9) & 0x0007fffff); @@ -186,14 +186,14 @@ float random_gauss_zig_f(prng_t *prng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r_f * logf(random_float(prng_state)); - yy = -logf(random_float(prng_state)); + xx = -ziggurat_nor_inv_r_f * logf(random_float(brng_state)); + yy = -logf(random_float(brng_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]) * random_float(prng_state) + + if (((fi_float[idx - 1] - fi_float[idx]) * random_float(brng_state) + fi_float[idx]) < exp(-0.5 * x * x)) return x; } @@ -201,16 +201,16 @@ float random_gauss_zig_f(prng_t *prng_state) { } /* -static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { +static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { double b, c; double U, V, X, Y; if (shape == 1.0) { - return random_standard_exponential(prng_state); + return random_standard_exponential(brng_state); } else if (shape < 1.0) { for (;;) { - U = random_double(prng_state); - V = random_standard_exponential(prng_state); + U = random_double(brng_state); + V = random_standard_exponential(brng_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); if (X <= V) { @@ -229,12 +229,12 @@ static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { c = 1. / sqrt(9 * b); for (;;) { do { - X = random_gauss(prng_state); + X = random_gauss(brng_state); V = 1.0 + c * X; } while (V <= 0.0); V = V * V * V; - U = random_sample(prng_state); + U = random_sample(brng_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))) @@ -243,16 +243,16 @@ static NPY_INLINE double standard_gamma(prng_t *prng_state, double shape) { } } -static NPY_INLINE float standard_gamma_float(prng_t *prng_state, float shape) { +static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { float b, c; float U, V, X, Y; if (shape == 1.0f) { - return random_standard_exponential_f(prng_state); + return random_standard_exponential_f(brng_state); } else if (shape < 1.0f) { for (;;) { - U = random_sample_f(prng_state); - V = random_standard_exponential_f(prng_state); + U = random_sample_f(brng_state); + V = random_standard_exponential_f(brng_state); if (U <= 1.0f - shape) { X = powf(U, 1.0f / shape); if (X <= V) { @@ -271,12 +271,12 @@ static NPY_INLINE float standard_gamma_float(prng_t *prng_state, float shape) { c = 1.0f / sqrtf(9.0f * b); for (;;) { do { - X = random_gauss_f(prng_state); + X = random_gauss_f(brng_state); V = 1.0f + c * X; } while (V <= 0.0f); V = V * V * V; - U = random_sample_f(prng_state); + U = random_sample_f(brng_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))) @@ -286,25 +286,25 @@ static NPY_INLINE float standard_gamma_float(prng_t *prng_state, float shape) { } -double random_standard_gamma(prng_t *prng_state, double shape) { - return standard_gamma(prng_state, shape); +double random_standard_gamma(brng_t *brng_state, double shape) { + return standard_gamma(brng_state, shape); } -float random_standard_gamma_f(prng_t *prng_state, float shape) { - return standard_gamma_float(prng_state, shape); +float random_standard_gamma_f(brng_t *brng_state, float shape) { + return standard_gamma_float(brng_state, shape); } */ -static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) { +static NPY_INLINE double standard_gamma_zig(brng_t *brng_state, double shape) { double b, c; double U, V, X, Y; if (shape == 1.0) { - return random_standard_exponential_zig(prng_state); + return random_standard_exponential_zig(brng_state); } else if (shape < 1.0) { for (;;) { - U = random_sample(prng_state); - V = random_standard_exponential_zig(prng_state); + U = random_sample(brng_state); + V = random_standard_exponential_zig(brng_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); if (X <= V) { @@ -323,12 +323,12 @@ static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) { c = 1. / sqrt(9 * b); for (;;) { do { - X = random_gauss_zig(prng_state); + X = random_gauss_zig(brng_state); V = 1.0 + c * X; } while (V <= 0.0); V = V * V * V; - U = random_sample(prng_state); + U = random_sample(brng_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))) @@ -337,16 +337,16 @@ static NPY_INLINE double standard_gamma_zig(prng_t *prng_state, double shape) { } } -static NPY_INLINE float standard_gamma_zig_f(prng_t *prng_state, float shape) { +static NPY_INLINE float standard_gamma_zig_f(brng_t *brng_state, float shape) { float b, c; float U, V, X, Y; if (shape == 1.0f) { - return random_standard_exponential_zig_f(prng_state); + return random_standard_exponential_zig_f(brng_state); } else if (shape < 1.0f) { for (;;) { - U = random_sample_f(prng_state); - V = random_standard_exponential_zig_f(prng_state); + U = random_sample_f(brng_state); + V = random_standard_exponential_zig_f(brng_state); if (U <= 1.0f - shape) { X = powf(U, 1.0f / shape); if (X <= V) { @@ -365,12 +365,12 @@ static NPY_INLINE float standard_gamma_zig_f(prng_t *prng_state, float shape) { c = 1.0f / sqrtf(9.0f * b); for (;;) { do { - X = random_gauss_zig_f(prng_state); + X = random_gauss_zig_f(brng_state); V = 1.0f + c * X; } while (V <= 0.0f); V = V * V * V; - U = random_sample_f(prng_state); + U = random_sample_f(brng_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))) @@ -379,35 +379,35 @@ static NPY_INLINE float standard_gamma_zig_f(prng_t *prng_state, float shape) { } } -double random_standard_gamma_zig(prng_t *prng_state, double shape) { - return standard_gamma_zig(prng_state, shape); +double random_standard_gamma_zig(brng_t *brng_state, double shape) { + return standard_gamma_zig(brng_state, shape); } -float random_standard_gamma_zig_f(prng_t *prng_state, float shape) { - return standard_gamma_zig_f(prng_state, shape); +float random_standard_gamma_zig_f(brng_t *brng_state, float shape) { + return standard_gamma_zig_f(brng_state, shape); } -int64_t random_positive_int64(prng_t *prng_state) { - return random_uint64(prng_state) >> 1; +int64_t random_positive_int64(brng_t *brng_state) { + return random_uint64(brng_state) >> 1; } -int32_t random_positive_int32(prng_t *prng_state) { - return random_uint32(prng_state) >> 1; +int32_t random_positive_int32(brng_t *brng_state) { + return random_uint32(brng_state) >> 1; } -int64_t random_positive_int(prng_t *prng_state) { +int64_t random_positive_int(brng_t *brng_state) { #if ULONG_MAX <= 0xffffffffUL - return (int64_t)(random_uint32(prng_state) >> 1); + return (int64_t)(random_uint32(brng_state) >> 1); #else - return (int64_t)(random_uint64(prng_state) >> 1); + return (int64_t)(random_uint64(brng_state) >> 1); #endif } -uint64_t random_uint(prng_t *prng_state) { +uint64_t random_uint(brng_t *brng_state) { #if ULONG_MAX <= 0xffffffffUL - return random_uint32(prng_state); + return random_uint32(brng_state); #else - return random_uint64(prng_state); + return random_uint64(brng_state); #endif } @@ -451,32 +451,32 @@ static double loggam(double x) { } /* -double random_normal(prng_t *prng_state, double loc, double scale) { - return loc + scale * random_gauss(prng_state); +double random_normal(brng_t *brng_state, double loc, double scale) { + return loc + scale * random_gauss(brng_state); } */ -double random_normal_zig(prng_t *prng_state, double loc, double scale) { - return loc + scale * random_gauss_zig(prng_state); +double random_normal_zig(brng_t *brng_state, double loc, double scale) { + return loc + scale * random_gauss_zig(brng_state); } -double random_exponential(prng_t *prng_state, double scale) { - return scale * random_standard_exponential(prng_state); +double random_exponential(brng_t *brng_state, double scale) { + return scale * random_standard_exponential(brng_state); } -double random_uniform(prng_t *prng_state, double lower, double range) { - return lower + range * random_sample(prng_state); +double random_uniform(brng_t *brng_state, double lower, double range) { + return lower + range * random_sample(brng_state); } -double random_gamma(prng_t *prng_state, double shape, double scale) { - return scale * random_standard_gamma_zig(prng_state, shape); +double random_gamma(brng_t *brng_state, double shape, double scale) { + return scale * random_standard_gamma_zig(brng_state, shape); } -float random_gamma_float(prng_t *prng_state, float shape, float scale) { - return scale * random_standard_gamma_zig_f(prng_state, shape); +float random_gamma_float(brng_t *brng_state, float shape, float scale) { + return scale * random_standard_gamma_zig_f(brng_state, shape); } -double random_beta(prng_t *prng_state, double a, double b) { +double random_beta(brng_t *brng_state, double a, double b) { double Ga, Gb; if ((a <= 1.0) && (b <= 1.0)) { @@ -484,8 +484,8 @@ double random_beta(prng_t *prng_state, double a, double b) { /* Use Johnk's algorithm */ while (1) { - U = random_sample(prng_state); - V = random_sample(prng_state); + U = random_sample(brng_state); + V = random_sample(brng_state); X = pow(U, 1.0 / a); Y = pow(V, 1.0 / b); @@ -504,41 +504,41 @@ double random_beta(prng_t *prng_state, double a, double b) { } } } else { - Ga = random_standard_gamma_zig(prng_state, a); - Gb = random_standard_gamma_zig(prng_state, b); + Ga = random_standard_gamma_zig(brng_state, a); + Gb = random_standard_gamma_zig(brng_state, b); return Ga / (Ga + Gb); } } -double random_chisquare(prng_t *prng_state, double df) { - return 2.0 * random_standard_gamma_zig(prng_state, df / 2.0); +double random_chisquare(brng_t *brng_state, double df) { + return 2.0 * random_standard_gamma_zig(brng_state, df / 2.0); } -double random_f(prng_t *prng_state, double dfnum, double dfden) { - return ((random_chisquare(prng_state, dfnum) * dfden) / - (random_chisquare(prng_state, dfden) * dfnum)); +double random_f(brng_t *brng_state, double dfnum, double dfden) { + return ((random_chisquare(brng_state, dfnum) * dfden) / + (random_chisquare(brng_state, dfden) * dfnum)); } -double random_standard_cauchy(prng_t *prng_state) { - return random_gauss_zig(prng_state) / random_gauss_zig(prng_state); +double random_standard_cauchy(brng_t *brng_state) { + return random_gauss_zig(brng_state) / random_gauss_zig(brng_state); } -double random_pareto(prng_t *prng_state, double a) { - return exp(random_standard_exponential(prng_state) / a) - 1; +double random_pareto(brng_t *brng_state, double a) { + return exp(random_standard_exponential(brng_state) / a) - 1; } -double random_weibull(prng_t *prng_state, double a) { - return pow(random_standard_exponential(prng_state), 1. / a); +double random_weibull(brng_t *brng_state, double a) { + return pow(random_standard_exponential(brng_state), 1. / a); } -double random_power(prng_t *prng_state, double a) { - return pow(1 - exp(-random_standard_exponential(prng_state)), 1. / a); +double random_power(brng_t *brng_state, double a) { + return pow(1 - exp(-random_standard_exponential(brng_state)), 1. / a); } -double random_laplace(prng_t *prng_state, double loc, double scale) { +double random_laplace(brng_t *brng_state, double loc, double scale) { double U; - U = random_sample(prng_state); + U = random_sample(brng_state); if (U < 0.5) { U = loc + scale * log(U + U); } else { @@ -547,37 +547,37 @@ double random_laplace(prng_t *prng_state, double loc, double scale) { return U; } -double random_gumbel(prng_t *prng_state, double loc, double scale) { +double random_gumbel(brng_t *brng_state, double loc, double scale) { double U; - U = 1.0 - random_sample(prng_state); + U = 1.0 - random_sample(brng_state); return loc - scale * log(-log(U)); } -double random_logistic(prng_t *prng_state, double loc, double scale) { +double random_logistic(brng_t *brng_state, double loc, double scale) { double U; - U = random_sample(prng_state); + U = random_sample(brng_state); return loc + scale * log(U / (1.0 - U)); } -double random_lognormal(prng_t *prng_state, double mean, double sigma) { - return exp(random_normal_zig(prng_state, mean, sigma)); +double random_lognormal(brng_t *brng_state, double mean, double sigma) { + return exp(random_normal_zig(brng_state, mean, sigma)); } -double random_rayleigh(prng_t *prng_state, double mode) { - return mode * sqrt(-2.0 * log(1.0 - random_sample(prng_state))); +double random_rayleigh(brng_t *brng_state, double mode) { + return mode * sqrt(-2.0 * log(1.0 - random_sample(brng_state))); } -double random_standard_t(prng_t *prng_state, double df) { +double random_standard_t(brng_t *brng_state, double df) { double num, denom; - num = random_gauss_zig(prng_state); - denom = random_standard_gamma_zig(prng_state, df / 2); + num = random_gauss_zig(brng_state); + denom = random_standard_gamma_zig(brng_state, df / 2); return sqrt(df / 2) * num / sqrt(denom); } -static int64_t random_poisson_mult(prng_t *prng_state, double lam) { +static int64_t random_poisson_mult(brng_t *brng_state, double lam) { int64_t X; double prod, U, enlam; @@ -585,7 +585,7 @@ static int64_t random_poisson_mult(prng_t *prng_state, double lam) { X = 0; prod = 1.0; while (1) { - U = random_sample(prng_state); + U = random_sample(brng_state); prod *= U; if (prod > enlam) { X += 1; @@ -602,7 +602,7 @@ static int64_t random_poisson_mult(prng_t *prng_state, double lam) { */ #define LS2PI 0.91893853320467267 #define TWELFTH 0.083333333333333333333333 -static int64_t random_poisson_ptrs(prng_t *prng_state, double lam) { +static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { int64_t k; double U, V, slam, loglam, a, b, invalpha, vr, us; @@ -614,8 +614,8 @@ static int64_t random_poisson_ptrs(prng_t *prng_state, double lam) { vr = 0.9277 - 3.6224 / (b - 2); while (1) { - U = random_sample(prng_state) - 0.5; - V = random_sample(prng_state); + U = random_sample(brng_state) - 0.5; + V = random_sample(brng_state); us = 0.5 - fabs(U); k = (int64_t)floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { @@ -631,22 +631,22 @@ static int64_t random_poisson_ptrs(prng_t *prng_state, double lam) { } } -int64_t random_poisson(prng_t *prng_state, double lam) { +int64_t random_poisson(brng_t *brng_state, double lam) { if (lam >= 10) { - return random_poisson_ptrs(prng_state, lam); + return random_poisson_ptrs(brng_state, lam); } else if (lam == 0) { return 0; } else { - return random_poisson_mult(prng_state, lam); + return random_poisson_mult(brng_state, lam); } } -int64_t random_negative_binomial(prng_t *prng_state, double n, double p) { - double Y = random_gamma(prng_state, n, (1 - p) / p); - return random_poisson(prng_state, Y); +int64_t random_negative_binomial(brng_t *brng_state, double n, double p) { + double Y = random_gamma(brng_state, n, (1 - p) / p); + return random_poisson(brng_state, Y); } -int64_t random_binomial_btpe(prng_t *prng_state, int64_t n, double p, +int64_t random_binomial_btpe(brng_t *brng_state, int64_t 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; @@ -694,8 +694,8 @@ int64_t random_binomial_btpe(prng_t *prng_state, int64_t n, double p, /* sigh ... */ Step10: nrq = n * r * q; - u = random_sample(prng_state) * p4; - v = random_sample(prng_state); + u = random_sample(brng_state) * p4; + v = random_sample(brng_state); if (u > p1) goto Step20; y = (int64_t)floor(xm - p1 * v + u); @@ -786,7 +786,7 @@ int64_t random_binomial_btpe(prng_t *prng_state, int64_t n, double p, return y; } -int64_t random_binomial_inversion(prng_t *prng_state, int64_t n, double p, +int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, binomial_t *binomial) { double q, qn, np, px, U; int64_t X, bound; @@ -808,13 +808,13 @@ int64_t random_binomial_inversion(prng_t *prng_state, int64_t n, double p, } X = 0; px = qn; - U = random_sample(prng_state); + U = random_sample(brng_state); while (U > px) { X++; if (X > bound) { X = 0; px = qn; - U = random_sample(prng_state); + U = random_sample(brng_state); } else { U -= px; px = ((n - X + 1) * p * px) / (X * q); @@ -823,55 +823,55 @@ int64_t random_binomial_inversion(prng_t *prng_state, int64_t n, double p, return X; } -int64_t random_binomial(prng_t *prng_state, double p, int64_t n, +int64_t random_binomial(brng_t *brng_state, double p, int64_t n, binomial_t *binomial) { double q; if (p <= 0.5) { if (p * n <= 30.0) { - return random_binomial_inversion(prng_state, n, p, binomial); + return random_binomial_inversion(brng_state, n, p, binomial); } else { - return random_binomial_btpe(prng_state, n, p, binomial); + return random_binomial_btpe(brng_state, n, p, binomial); } } else { q = 1.0 - p; if (q * n <= 30.0) { - return n - random_binomial_inversion(prng_state, n, q, binomial); + return n - random_binomial_inversion(brng_state, n, q, binomial); } else { - return n - random_binomial_btpe(prng_state, n, q, binomial); + return n - random_binomial_btpe(brng_state, n, q, binomial); } } } -double random_noncentral_chisquare(prng_t *prng_state, double df, double nonc) { +double random_noncentral_chisquare(brng_t *brng_state, double df, double nonc) { if (nonc == 0) { - return random_chisquare(prng_state, df); + return random_chisquare(brng_state, df); } if (1 < df) { - const double Chi2 = random_chisquare(prng_state, df - 1); - const double n = random_gauss_zig(prng_state) + sqrt(nonc); + const double Chi2 = random_chisquare(brng_state, df - 1); + const double n = random_gauss_zig(brng_state) + sqrt(nonc); return Chi2 + n * n; } else { - const int64_t i = random_poisson(prng_state, nonc / 2.0); - return random_chisquare(prng_state, df + 2 * i); + const int64_t i = random_poisson(brng_state, nonc / 2.0); + return random_chisquare(brng_state, df + 2 * i); } } -double random_noncentral_f(prng_t *prng_state, double dfnum, double dfden, +double random_noncentral_f(brng_t *brng_state, double dfnum, double dfden, double nonc) { - double t = random_noncentral_chisquare(prng_state, dfnum, nonc) * dfden; - return t / (random_chisquare(prng_state, dfden) * dfnum); + double t = random_noncentral_chisquare(brng_state, dfnum, nonc) * dfden; + return t / (random_chisquare(brng_state, dfden) * dfnum); } -double random_wald(prng_t *prng_state, double mean, double scale) { +double random_wald(brng_t *brng_state, double mean, double scale) { double U, X, Y; double mu_2l; mu_2l = mean / (2 * scale); - Y = random_gauss_zig(prng_state); + Y = random_gauss_zig(brng_state); Y = mean * Y * Y; X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y)); - U = random_sample(prng_state); + U = random_sample(brng_state); if (U <= mean / (mean + X)) { return X; } else { @@ -879,14 +879,14 @@ double random_wald(prng_t *prng_state, double mean, double scale) { } } -double random_vonmises(prng_t *prng_state, double mu, double kappa) { +double random_vonmises(brng_t *brng_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 * random_sample(prng_state) - 1); + return M_PI * (2 * random_sample(brng_state) - 1); } else { /* with double precision rho is zero until 1.4e-8 */ if (kappa < 1e-5) { @@ -902,17 +902,17 @@ double random_vonmises(prng_t *prng_state, double mu, double kappa) { } while (1) { - U = random_sample(prng_state); + U = random_sample(brng_state); Z = cos(M_PI * U); W = (1 + s * Z) / (s + Z); Y = kappa * (s - W); - V = random_sample(prng_state); + V = random_sample(brng_state); if ((Y * (2 - Y) - V >= 0) || (log(Y / V) + 1 - Y >= 0)) { break; } } - U = random_sample(prng_state); + U = random_sample(brng_state); result = acos(W); if (U < 0.5) { @@ -930,18 +930,18 @@ double random_vonmises(prng_t *prng_state, double mu, double kappa) { } } -int64_t random_logseries(prng_t *prng_state, double p) { +int64_t random_logseries(brng_t *brng_state, double p) { double q, r, U, V; int64_t result; r = log(1.0 - p); while (1) { - V = random_sample(prng_state); + V = random_sample(brng_state); if (V >= p) { return 1; } - U = random_sample(prng_state); + U = random_sample(brng_state); q = 1.0 - exp(r * U); if (V <= q * q) { result = (int64_t)floor(1 + log(V) / log(q)); @@ -958,7 +958,7 @@ int64_t random_logseries(prng_t *prng_state, double p) { } } -int64_t random_geometric_search(prng_t *prng_state, double p) { +int64_t random_geometric_search(brng_t *brng_state, double p) { double U; int64_t X; double sum, prod, q; @@ -966,7 +966,7 @@ int64_t random_geometric_search(prng_t *prng_state, double p) { X = 1; sum = prod = p; q = 1.0 - p; - U = random_sample(prng_state); + U = random_sample(brng_state); while (U > sum) { prod *= q; sum += prod; @@ -975,19 +975,19 @@ int64_t random_geometric_search(prng_t *prng_state, double p) { return X; } -int64_t random_geometric_inversion(prng_t *prng_state, double p) { - return (int64_t)ceil(log(1.0 - random_sample(prng_state)) / log(1.0 - p)); +int64_t random_geometric_inversion(brng_t *brng_state, double p) { + return (int64_t)ceil(log(1.0 - random_sample(brng_state)) / log(1.0 - p)); } -int64_t random_geometric(prng_t *prng_state, double p) { +int64_t random_geometric(brng_t *brng_state, double p) { if (p >= 0.333333333333333333333333) { - return random_geometric_search(prng_state, p); + return random_geometric_search(brng_state, p); } else { - return random_geometric_inversion(prng_state, p); + return random_geometric_inversion(brng_state, p); } } -int64_t random_zipf(prng_t *prng_state, double a) { +int64_t random_zipf(brng_t *brng_state, double a) { double T, U, V; int64_t X; double am1, b; @@ -995,8 +995,8 @@ int64_t random_zipf(prng_t *prng_state, double a) { am1 = a - 1.0; b = pow(2.0, am1); do { - U = 1.0 - random_sample(prng_state); - V = random_sample(prng_state); + U = 1.0 - random_sample(brng_state); + V = random_sample(brng_state); X = (int64_t)floor(pow(U, -1.0 / am1)); /* The real result may be above what can be represented in a int64. * It will get casted to -sys.maxint-1. Since this is @@ -1009,7 +1009,7 @@ int64_t random_zipf(prng_t *prng_state, double a) { return X; } -double random_triangular(prng_t *prng_state, double left, double mode, +double random_triangular(brng_t *brng_state, double left, double mode, double right) { double base, leftbase, ratio, leftprod, rightprod; double U; @@ -1020,7 +1020,7 @@ double random_triangular(prng_t *prng_state, double left, double mode, leftprod = leftbase * base; rightprod = (right - mode) * base; - U = random_sample(prng_state); + U = random_sample(brng_state); if (U <= ratio) { return left + sqrt(U * leftprod); } else { @@ -1028,7 +1028,7 @@ double random_triangular(prng_t *prng_state, double left, double mode, } } -int64_t random_hypergeometric_hyp(prng_t *prng_state, int64_t good, int64_t bad, +int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample) { int64_t d1, k, z; double d2, u, y; @@ -1039,7 +1039,7 @@ int64_t random_hypergeometric_hyp(prng_t *prng_state, int64_t good, int64_t bad, y = d2; k = sample; while (y > 0.0) { - u = random_sample(prng_state); + u = random_sample(brng_state); y -= (int64_t)floor(u + y / (d1 + k)); k--; if (k == 0) @@ -1055,7 +1055,7 @@ int64_t random_hypergeometric_hyp(prng_t *prng_state, int64_t good, int64_t bad, /* D2 = 3 - 2*sqrt(3/e) */ #define D1 1.7155277699214135 #define D2 0.8989161620588988 -int64_t random_hypergeometric_hrua(prng_t *prng_state, int64_t good, +int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample) { int64_t mingoodbad, maxgoodbad, popsize, m, d9; double d4, d5, d6, d7, d8, d10, d11; @@ -1078,8 +1078,8 @@ int64_t random_hypergeometric_hrua(prng_t *prng_state, int64_t good, /* 16 for 16-decimal-digit precision in D1 and D2 */ while (1) { - X = random_sample(prng_state); - Y = random_sample(prng_state); + X = random_sample(brng_state); + Y = random_sample(brng_state); W = d6 + d8 * (Y - 0.5) / X; /* fast rejection: */ @@ -1115,16 +1115,16 @@ int64_t random_hypergeometric_hrua(prng_t *prng_state, int64_t good, #undef D1 #undef D2 -int64_t random_hypergeometric(prng_t *prng_state, int64_t good, int64_t bad, +int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample) { if (sample > 10) { - return random_hypergeometric_hrua(prng_state, good, bad, sample); + return random_hypergeometric_hrua(brng_state, good, bad, sample); } else { - return random_hypergeometric_hyp(prng_state, good, bad, sample); + return random_hypergeometric_hyp(brng_state, good, bad, sample); } } -uint64_t random_interval(prng_t *prng_state, uint64_t max) { +uint64_t random_interval(brng_t *brng_state, uint64_t max) { uint64_t mask, value; if (max == 0) { return 0; @@ -1142,10 +1142,10 @@ uint64_t random_interval(prng_t *prng_state, uint64_t max) { /* Search a random value in [0..mask] <= max */ if (max <= 0xffffffffUL) { - while ((value = (random_uint32(prng_state) & mask)) > max) + while ((value = (random_uint32(brng_state) & mask)) > max) ; } else { - while ((value = (random_uint64(prng_state) & mask)) > max) + while ((value = (random_uint64(brng_state) & mask)) > max) ; } return value; @@ -1167,28 +1167,28 @@ static NPY_INLINE uint64_t gen_mask(uint64_t max) { * inclusive. The numbers wrap if rng is sufficiently large. */ -static NPY_INLINE uint64_t bounded_uint64(prng_t *prng_state, uint64_t off, +static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, uint64_t off, uint64_t rng, uint64_t mask) { uint64_t val; if (rng == 0) return off; if (rng <= 0xffffffffUL) { - while ((val = (random_uint32(prng_state) & mask)) > rng) + while ((val = (random_uint32(brng_state) & mask)) > rng) ; } else { - while ((val = (random_uint64(prng_state) & mask)) > rng) + while ((val = (random_uint64(brng_state) & mask)) > rng) ; } return off + val; } -uint64_t random_bounded_uint64(prng_t *prng_state, uint64_t off, uint64_t rng, +uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, uint64_t rng, uint64_t mask) { - return bounded_uint64(prng_state, off, rng, mask); + return bounded_uint64(brng_state, off, rng, mask); } -static NPY_INLINE uint32_t bounded_uint32(prng_t *prng_state, uint32_t off, +static NPY_INLINE uint32_t bounded_uint32(brng_t *brng_state, uint32_t off, uint32_t rng, uint32_t mask) { /* * The buffer and buffer count are not used here but are included to allow @@ -1200,22 +1200,22 @@ static NPY_INLINE uint32_t bounded_uint32(prng_t *prng_state, uint32_t off, if (rng == 0) return off; - while ((val = (random_uint32(prng_state) & mask)) > rng) + while ((val = (random_uint32(brng_state) & mask)) > rng) ; return off + val; } -uint32_t random_buffered_bounded_uint32(prng_t *prng_state, uint32_t off, +uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf) { /* * Unused bcnt and buf are here only to allow templating with other uint * generators */ - return bounded_uint32(prng_state, off, rng, mask); + return bounded_uint32(brng_state, off, rng, mask); } -static NPY_INLINE uint16_t buffered_bounded_uint16(prng_t *prng_state, +static NPY_INLINE uint16_t buffered_bounded_uint16(brng_t *brng_state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf) { @@ -1225,7 +1225,7 @@ static NPY_INLINE uint16_t buffered_bounded_uint16(prng_t *prng_state, do { if (!(bcnt[0])) { - buf[0] = random_uint32(prng_state); + buf[0] = random_uint32(brng_state); bcnt[0] = 1; } else { buf[0] >>= 16; @@ -1236,13 +1236,13 @@ static NPY_INLINE uint16_t buffered_bounded_uint16(prng_t *prng_state, return off + val; } -uint16_t random_buffered_bounded_uint16(prng_t *prng_state, uint16_t off, +uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf) { - return buffered_bounded_uint16(prng_state, off, rng, mask, bcnt, buf); + return buffered_bounded_uint16(brng_state, off, rng, mask, bcnt, buf); } -static NPY_INLINE uint8_t buffered_bounded_uint8(prng_t *prng_state, +static NPY_INLINE uint8_t buffered_bounded_uint8(brng_t *brng_state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf) { @@ -1251,7 +1251,7 @@ static NPY_INLINE uint8_t buffered_bounded_uint8(prng_t *prng_state, return off; do { if (!(bcnt[0])) { - buf[0] = random_uint32(prng_state); + buf[0] = random_uint32(brng_state); bcnt[0] = 3; } else { buf[0] >>= 8; @@ -1262,20 +1262,20 @@ static NPY_INLINE uint8_t buffered_bounded_uint8(prng_t *prng_state, return off + val; } -uint8_t random_buffered_bounded_uint8(prng_t *prng_state, uint8_t off, +uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, uint8_t rng, uint8_t mask, int *bcnt, uint32_t *buf) { - return buffered_bounded_uint8(prng_state, off, rng, mask, bcnt, buf); + return buffered_bounded_uint8(brng_state, off, rng, mask, bcnt, buf); } -static NPY_INLINE npy_bool buffered_bounded_bool(prng_t *prng_state, +static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_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] = random_uint32(prng_state); + buf[0] = random_uint32(brng_state); bcnt[0] = 31; } else { buf[0] >>= 1; @@ -1284,13 +1284,13 @@ static NPY_INLINE npy_bool buffered_bounded_bool(prng_t *prng_state, return (buf[0] & 0x00000001UL) != 0; } -npy_bool random_buffered_bounded_bool(prng_t *prng_state, npy_bool off, +npy_bool random_buffered_bounded_bool(brng_t *brng_state, npy_bool off, npy_bool rng, npy_bool mask, int *bcnt, uint32_t *buf) { - return buffered_bounded_bool(prng_state, off, rng, mask, bcnt, buf); + return buffered_bounded_bool(brng_state, off, rng, mask, bcnt, buf); } -void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, uint64_t rng, +void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t rng, npy_intp cnt, uint64_t *out) { uint64_t mask; npy_intp i; @@ -1298,7 +1298,7 @@ void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, uint64_t rng, /* Smallest bit mask >= max */ mask = gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = bounded_uint64(prng_state, off, rng, mask); + out[i] = bounded_uint64(brng_state, off, rng, mask); } } @@ -1306,7 +1306,7 @@ void random_bounded_uint64_fill(prng_t *prng_state, uint64_t off, uint64_t 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(prng_t *prng_state, uint32_t off, uint32_t rng, +void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, uint32_t rng, npy_intp cnt, uint32_t *out) { uint32_t mask; npy_intp i; @@ -1314,7 +1314,7 @@ void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, uint32_t rng, /* Smallest bit mask >= max */ mask = (uint32_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = bounded_uint32(prng_state, off, rng, mask); + out[i] = bounded_uint32(brng_state, off, rng, mask); } } @@ -1322,7 +1322,7 @@ void random_bounded_uint32_fill(prng_t *prng_state, uint32_t off, uint32_t rng, * 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(prng_t *prng_state, uint16_t off, uint16_t rng, +void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, npy_intp cnt, uint16_t *out) { uint16_t mask; npy_intp i; @@ -1332,7 +1332,7 @@ void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, uint16_t rng, /* Smallest bit mask >= max */ mask = (uint16_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = buffered_bounded_uint16(prng_state, off, rng, mask, &bcnt, &buf); + out[i] = buffered_bounded_uint16(brng_state, off, rng, mask, &bcnt, &buf); } } @@ -1340,7 +1340,7 @@ void random_bounded_uint16_fill(prng_t *prng_state, uint16_t off, uint16_t rng, * 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(prng_t *prng_state, uint8_t off, uint8_t rng, +void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, npy_intp cnt, uint8_t *out) { uint8_t mask; npy_intp i; @@ -1350,7 +1350,7 @@ void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, uint8_t rng, /* Smallest bit mask >= max */ mask = (uint8_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = buffered_bounded_uint8(prng_state, off, rng, mask, &bcnt, &buf); + out[i] = buffered_bounded_uint8(brng_state, off, rng, mask, &bcnt, &buf); } } @@ -1358,7 +1358,7 @@ void random_bounded_uint8_fill(prng_t *prng_state, uint8_t off, uint8_t rng, * Fills an array with cnt random npy_bool between off and off + rng * inclusive. */ -void random_bounded_bool_fill(prng_t *prng_state, npy_bool off, npy_bool rng, +void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, npy_intp cnt, npy_bool *out) { npy_bool mask = 0; npy_intp i; @@ -1366,6 +1366,6 @@ void random_bounded_bool_fill(prng_t *prng_state, npy_bool off, npy_bool rng, int bcnt = 0; for (i = 0; i < cnt; i++) { - out[i] = buffered_bounded_bool(prng_state, off, rng, mask, &bcnt, &buf); + out[i] = buffered_bounded_bool(brng_state, off, rng, mask, &bcnt, &buf); } } diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h new file mode 100644 index 000000000000..f3a5448b3479 --- /dev/null +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -0,0 +1,199 @@ +#include +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/stdint.h" +typedef int bool; +#define false 0 +#define true 1 +#else +#include +#include +#endif +#else +#include +#include +#endif + +#include "Python.h" +#include "numpy/npy_common.h" +#include + +#ifdef _WIN32 +#if _MSC_VER == 1500 + +static NPY_INLINE int64_t llabs(int64_t x) { + int64_t o; + if (x < 0) { + o = -x; + } else { + o = x; + } + return o; +} +#endif +#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; + +typedef struct brng { + 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); +} brng_t; + +/* Inline generators for internal use */ +static NPY_INLINE uint32_t random_uint32(brng_t *brng_state) { + return brng_state->next_uint32(brng_state->state); +} + +static NPY_INLINE uint64_t random_uint64(brng_t *brng_state) { + return brng_state->next_uint64(brng_state->state); +} + +static NPY_INLINE float random_float(brng_t *brng_state) { + return (random_uint32(brng_state) >> 9) * (1.0f / 8388608.0f); +} + +static NPY_INLINE double random_double(brng_t *brng_state) { + return brng_state->next_double(brng_state->state); +} + +DECLDIR float random_sample_f(brng_t *brng_state); +DECLDIR double random_sample(brng_t *brng_state); + +DECLDIR int64_t random_positive_int64(brng_t *brng_state); +DECLDIR int32_t random_positive_int32(brng_t *brng_state); +DECLDIR int64_t random_positive_int(brng_t *brng_state); +DECLDIR uint64_t random_uint(brng_t *brng_state); + +DECLDIR double random_standard_exponential(brng_t *brng_state); +DECLDIR float random_standard_exponential_f(brng_t *brng_state); +DECLDIR double random_standard_exponential_zig(brng_t *brng_state); +DECLDIR float random_standard_exponential_zig_f(brng_t *brng_state); + +/* +DECLDIR double random_gauss(brng_t *brng_state); +DECLDIR float random_gauss_f(brng_t *brng_state); +*/ +DECLDIR double random_gauss_zig(brng_t *brng_state); +DECLDIR float random_gauss_zig_f(brng_t *brng_state); + +/* +DECLDIR double random_standard_gamma(brng_t *brng_state, double shape); +DECLDIR float random_standard_gamma_f(brng_t *brng_state, float shape); +*/ +DECLDIR double random_standard_gamma_zig(brng_t *brng_state, double shape); +DECLDIR float random_standard_gamma_zig_f(brng_t *brng_state, float shape); + +/* +DECLDIR double random_normal(brng_t *brng_state, double loc, double scale); +*/ +DECLDIR double random_normal_zig(brng_t *brng_state, double loc, double scale); + +DECLDIR double random_gamma(brng_t *brng_state, double shape, double scale); +DECLDIR float random_gamma_float(brng_t *brng_state, float shape, float scale); + +DECLDIR double random_exponential(brng_t *brng_state, double scale); +DECLDIR double random_uniform(brng_t *brng_state, double lower, double range); +DECLDIR double random_beta(brng_t *brng_state, double a, double b); +DECLDIR double random_chisquare(brng_t *brng_state, double df); +DECLDIR double random_f(brng_t *brng_state, double dfnum, double dfden); +DECLDIR double random_standard_cauchy(brng_t *brng_state); +DECLDIR double random_pareto(brng_t *brng_state, double a); +DECLDIR double random_weibull(brng_t *brng_state, double a); +DECLDIR double random_power(brng_t *brng_state, double a); +DECLDIR double random_laplace(brng_t *brng_state, double loc, double scale); +DECLDIR double random_gumbel(brng_t *brng_state, double loc, double scale); +DECLDIR double random_logistic(brng_t *brng_state, double loc, double scale); +DECLDIR double random_lognormal(brng_t *brng_state, double mean, double sigma); +DECLDIR double random_rayleigh(brng_t *brng_state, double mode); +DECLDIR double random_standard_t(brng_t *brng_state, double df); +DECLDIR double random_noncentral_chisquare(brng_t *brng_state, double df, + double nonc); +DECLDIR double random_noncentral_f(brng_t *brng_state, double dfnum, + double dfden, double nonc); +DECLDIR double random_wald(brng_t *brng_state, double mean, double scale); +DECLDIR double random_vonmises(brng_t *brng_state, double mu, double kappa); +DECLDIR double random_triangular(brng_t *brng_state, double left, double mode, + double right); + +DECLDIR int64_t random_poisson(brng_t *brng_state, double lam); +DECLDIR int64_t random_negative_binomial(brng_t *brng_state, double n, + double p); +DECLDIR int64_t random_binomial(brng_t *brng_state, double p, int64_t n, + binomial_t *binomial); +DECLDIR int64_t random_logseries(brng_t *brng_state, double p); +DECLDIR int64_t random_geometric_search(brng_t *brng_state, double p); +DECLDIR int64_t random_geometric_inversion(brng_t *brng_state, double p); +DECLDIR int64_t random_geometric(brng_t *brng_state, double p); +DECLDIR int64_t random_zipf(brng_t *brng_state, double a); +DECLDIR int64_t random_hypergeometric(brng_t *brng_state, int64_t good, + int64_t bad, int64_t sample); + +DECLDIR uint64_t random_interval(brng_t *brng_state, uint64_t max); +DECLDIR uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, + uint64_t rng, uint64_t mask); +DECLDIR uint32_t random_buffered_bounded_uint32(brng_t *brng_state, + uint32_t off, uint32_t rng, + uint32_t mask, int *bcnt, + uint32_t *buf); + +DECLDIR uint16_t random_buffered_bounded_uint16(brng_t *brng_state, + uint16_t off, uint16_t rng, + uint16_t mask, int *bcnt, + uint32_t *buf); +DECLDIR uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, + uint8_t rng, uint8_t mask, + int *bcnt, uint32_t *buf); +DECLDIR npy_bool random_buffered_bounded_bool(brng_t *brng_state, npy_bool off, + npy_bool rng, npy_bool mask, + int *bcnt, uint32_t *buf); +DECLDIR void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, + uint64_t rng, npy_intp cnt, + uint64_t *out); +DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, + uint32_t rng, npy_intp cnt, + uint32_t *out); +DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, + uint16_t rng, npy_intp cnt, + uint16_t *out); +DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, + uint8_t rng, npy_intp cnt, uint8_t *out); +DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, + npy_bool rng, npy_intp cnt, + npy_bool *out); diff --git a/_randomgen/core_prng/src/distributions/ziggurat.h b/_randomgen/randomgen/src/distributions/ziggurat.h similarity index 100% rename from _randomgen/core_prng/src/distributions/ziggurat.h rename to _randomgen/randomgen/src/distributions/ziggurat.h diff --git a/_randomgen/core_prng/src/distributions/ziggurat_constants.h b/_randomgen/randomgen/src/distributions/ziggurat_constants.h similarity index 100% rename from _randomgen/core_prng/src/distributions/ziggurat_constants.h rename to _randomgen/randomgen/src/distributions/ziggurat_constants.h diff --git a/_randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt b/_randomgen/randomgen/src/dsfmt/128-bit-jump.poly.txt similarity index 100% rename from _randomgen/core_prng/src/dsfmt/128-bit-jump.poly.txt rename to _randomgen/randomgen/src/dsfmt/128-bit-jump.poly.txt diff --git a/_randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt b/_randomgen/randomgen/src/dsfmt/96-bit-jump.poly.txt similarity index 100% rename from _randomgen/core_prng/src/dsfmt/96-bit-jump.poly.txt rename to _randomgen/randomgen/src/dsfmt/96-bit-jump.poly.txt diff --git a/_randomgen/core_prng/src/dsfmt/LICENSE.txt b/_randomgen/randomgen/src/dsfmt/LICENSE.txt similarity index 100% rename from _randomgen/core_prng/src/dsfmt/LICENSE.txt rename to _randomgen/randomgen/src/dsfmt/LICENSE.txt diff --git a/_randomgen/core_prng/src/dsfmt/calc-jump.cpp b/_randomgen/randomgen/src/dsfmt/calc-jump.cpp similarity index 100% rename from _randomgen/core_prng/src/dsfmt/calc-jump.cpp rename to _randomgen/randomgen/src/dsfmt/calc-jump.cpp diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c b/_randomgen/randomgen/src/dsfmt/dSFMT-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-benchmark.c rename to _randomgen/randomgen/src/dsfmt/dSFMT-benchmark.c diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp b/_randomgen/randomgen/src/dsfmt/dSFMT-calc-jump.hpp similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-calc-jump.hpp rename to _randomgen/randomgen/src/dsfmt/dSFMT-calc-jump.hpp diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-common.h b/_randomgen/randomgen/src/dsfmt/dSFMT-common.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-common.h rename to _randomgen/randomgen/src/dsfmt/dSFMT-common.h diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.c b/_randomgen/randomgen/src/dsfmt/dSFMT-jump.c similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-jump.c rename to _randomgen/randomgen/src/dsfmt/dSFMT-jump.c diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-jump.h b/_randomgen/randomgen/src/dsfmt/dSFMT-jump.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-jump.h rename to _randomgen/randomgen/src/dsfmt/dSFMT-jump.h diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-params.h b/_randomgen/randomgen/src/dsfmt/dSFMT-params.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-params.h rename to _randomgen/randomgen/src/dsfmt/dSFMT-params.h diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-params19937.h b/_randomgen/randomgen/src/dsfmt/dSFMT-params19937.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-params19937.h rename to _randomgen/randomgen/src/dsfmt/dSFMT-params19937.h diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-poly.h b/_randomgen/randomgen/src/dsfmt/dSFMT-poly.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-poly.h rename to _randomgen/randomgen/src/dsfmt/dSFMT-poly.h diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c b/_randomgen/randomgen/src/dsfmt/dSFMT-test-gen.c similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT-test-gen.c rename to _randomgen/randomgen/src/dsfmt/dSFMT-test-gen.c diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.c b/_randomgen/randomgen/src/dsfmt/dSFMT.c similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT.c rename to _randomgen/randomgen/src/dsfmt/dSFMT.c diff --git a/_randomgen/core_prng/src/dsfmt/dSFMT.h b/_randomgen/randomgen/src/dsfmt/dSFMT.h similarity index 100% rename from _randomgen/core_prng/src/dsfmt/dSFMT.h rename to _randomgen/randomgen/src/dsfmt/dSFMT.h diff --git a/_randomgen/core_prng/src/entropy/entropy.c b/_randomgen/randomgen/src/entropy/entropy.c similarity index 100% rename from _randomgen/core_prng/src/entropy/entropy.c rename to _randomgen/randomgen/src/entropy/entropy.c diff --git a/_randomgen/core_prng/src/entropy/entropy.h b/_randomgen/randomgen/src/entropy/entropy.h similarity index 100% rename from _randomgen/core_prng/src/entropy/entropy.h rename to _randomgen/randomgen/src/entropy/entropy.h diff --git a/_randomgen/core_prng/src/mt19937/mt19937-benchmark.c b/_randomgen/randomgen/src/mt19937/mt19937-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937-benchmark.c rename to _randomgen/randomgen/src/mt19937/mt19937-benchmark.c diff --git a/_randomgen/core_prng/src/mt19937/mt19937-jump.c b/_randomgen/randomgen/src/mt19937/mt19937-jump.c similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937-jump.c rename to _randomgen/randomgen/src/mt19937/mt19937-jump.c diff --git a/_randomgen/core_prng/src/mt19937/mt19937-jump.h b/_randomgen/randomgen/src/mt19937/mt19937-jump.h similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937-jump.h rename to _randomgen/randomgen/src/mt19937/mt19937-jump.h diff --git a/_randomgen/core_prng/src/mt19937/mt19937-poly.h b/_randomgen/randomgen/src/mt19937/mt19937-poly.h similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937-poly.h rename to _randomgen/randomgen/src/mt19937/mt19937-poly.h diff --git a/_randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c b/_randomgen/randomgen/src/mt19937/mt19937-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937-test-data-gen.c rename to _randomgen/randomgen/src/mt19937/mt19937-test-data-gen.c diff --git a/_randomgen/core_prng/src/mt19937/mt19937.c b/_randomgen/randomgen/src/mt19937/mt19937.c similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937.c rename to _randomgen/randomgen/src/mt19937/mt19937.c diff --git a/_randomgen/core_prng/src/mt19937/mt19937.h b/_randomgen/randomgen/src/mt19937/mt19937.h similarity index 100% rename from _randomgen/core_prng/src/mt19937/mt19937.h rename to _randomgen/randomgen/src/mt19937/mt19937.h diff --git a/_randomgen/core_prng/src/mt19937/randomkit.c b/_randomgen/randomgen/src/mt19937/randomkit.c similarity index 100% rename from _randomgen/core_prng/src/mt19937/randomkit.c rename to _randomgen/randomgen/src/mt19937/randomkit.c diff --git a/_randomgen/core_prng/src/mt19937/randomkit.h b/_randomgen/randomgen/src/mt19937/randomkit.h similarity index 100% rename from _randomgen/core_prng/src/mt19937/randomkit.h rename to _randomgen/randomgen/src/mt19937/randomkit.h diff --git a/_randomgen/core_prng/src/pcg32/pcg-advance-64.c b/_randomgen/randomgen/src/pcg32/pcg-advance-64.c similarity index 100% rename from _randomgen/core_prng/src/pcg32/pcg-advance-64.c rename to _randomgen/randomgen/src/pcg32/pcg-advance-64.c diff --git a/_randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c b/_randomgen/randomgen/src/pcg32/pcg32-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/pcg32/pcg32-test-data-gen.c rename to _randomgen/randomgen/src/pcg32/pcg32-test-data-gen.c diff --git a/_randomgen/core_prng/src/pcg32/pcg32.c b/_randomgen/randomgen/src/pcg32/pcg32.c similarity index 100% rename from _randomgen/core_prng/src/pcg32/pcg32.c rename to _randomgen/randomgen/src/pcg32/pcg32.c diff --git a/_randomgen/core_prng/src/pcg32/pcg32.h b/_randomgen/randomgen/src/pcg32/pcg32.h similarity index 100% rename from _randomgen/core_prng/src/pcg32/pcg32.h rename to _randomgen/randomgen/src/pcg32/pcg32.h diff --git a/_randomgen/core_prng/src/pcg32/pcg_variants.h b/_randomgen/randomgen/src/pcg32/pcg_variants.h similarity index 100% rename from _randomgen/core_prng/src/pcg32/pcg_variants.h rename to _randomgen/randomgen/src/pcg32/pcg_variants.h diff --git a/_randomgen/core_prng/src/pcg64/pcg64-benchmark.c b/_randomgen/randomgen/src/pcg64/pcg64-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64-benchmark.c rename to _randomgen/randomgen/src/pcg64/pcg64-benchmark.c diff --git a/_randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c b/_randomgen/randomgen/src/pcg64/pcg64-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64-test-data-gen.c rename to _randomgen/randomgen/src/pcg64/pcg64-test-data-gen.c diff --git a/_randomgen/core_prng/src/pcg64/pcg64.c b/_randomgen/randomgen/src/pcg64/pcg64.c similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64.c rename to _randomgen/randomgen/src/pcg64/pcg64.c diff --git a/_randomgen/core_prng/src/pcg64/pcg64.h b/_randomgen/randomgen/src/pcg64/pcg64.h similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64.h rename to _randomgen/randomgen/src/pcg64/pcg64.h diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.c b/_randomgen/randomgen/src/pcg64/pcg64.orig.c similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64.orig.c rename to _randomgen/randomgen/src/pcg64/pcg64.orig.c diff --git a/_randomgen/core_prng/src/pcg64/pcg64.orig.h b/_randomgen/randomgen/src/pcg64/pcg64.orig.h similarity index 100% rename from _randomgen/core_prng/src/pcg64/pcg64.orig.h rename to _randomgen/randomgen/src/pcg64/pcg64.orig.h diff --git a/_randomgen/core_prng/src/philox/philox-benchmark.c b/_randomgen/randomgen/src/philox/philox-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/philox/philox-benchmark.c rename to _randomgen/randomgen/src/philox/philox-benchmark.c diff --git a/_randomgen/core_prng/src/philox/philox-test-data-gen.c b/_randomgen/randomgen/src/philox/philox-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/philox/philox-test-data-gen.c rename to _randomgen/randomgen/src/philox/philox-test-data-gen.c diff --git a/_randomgen/core_prng/src/philox/philox.c b/_randomgen/randomgen/src/philox/philox.c similarity index 100% rename from _randomgen/core_prng/src/philox/philox.c rename to _randomgen/randomgen/src/philox/philox.c diff --git a/_randomgen/core_prng/src/philox/philox.h b/_randomgen/randomgen/src/philox/philox.h similarity index 100% rename from _randomgen/core_prng/src/philox/philox.h rename to _randomgen/randomgen/src/philox/philox.h diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.c b/_randomgen/randomgen/src/splitmix64/splitmix64.c similarity index 100% rename from _randomgen/core_prng/src/splitmix64/splitmix64.c rename to _randomgen/randomgen/src/splitmix64/splitmix64.c diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.h b/_randomgen/randomgen/src/splitmix64/splitmix64.h similarity index 100% rename from _randomgen/core_prng/src/splitmix64/splitmix64.h rename to _randomgen/randomgen/src/splitmix64/splitmix64.h diff --git a/_randomgen/core_prng/src/splitmix64/splitmix64.orig.c b/_randomgen/randomgen/src/splitmix64/splitmix64.orig.c similarity index 100% rename from _randomgen/core_prng/src/splitmix64/splitmix64.orig.c rename to _randomgen/randomgen/src/splitmix64/splitmix64.orig.c diff --git a/_randomgen/core_prng/src/threefry/threefry-benchmark.c b/_randomgen/randomgen/src/threefry/threefry-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/threefry/threefry-benchmark.c rename to _randomgen/randomgen/src/threefry/threefry-benchmark.c diff --git a/_randomgen/core_prng/src/threefry/threefry-orig.c b/_randomgen/randomgen/src/threefry/threefry-orig.c similarity index 100% rename from _randomgen/core_prng/src/threefry/threefry-orig.c rename to _randomgen/randomgen/src/threefry/threefry-orig.c diff --git a/_randomgen/core_prng/src/threefry/threefry-test-data-gen.c b/_randomgen/randomgen/src/threefry/threefry-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/threefry/threefry-test-data-gen.c rename to _randomgen/randomgen/src/threefry/threefry-test-data-gen.c diff --git a/_randomgen/core_prng/src/threefry/threefry.c b/_randomgen/randomgen/src/threefry/threefry.c similarity index 100% rename from _randomgen/core_prng/src/threefry/threefry.c rename to _randomgen/randomgen/src/threefry/threefry.c diff --git a/_randomgen/core_prng/src/threefry/threefry.h b/_randomgen/randomgen/src/threefry/threefry.h similarity index 100% rename from _randomgen/core_prng/src/threefry/threefry.h rename to _randomgen/randomgen/src/threefry/threefry.h diff --git a/_randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c b/_randomgen/randomgen/src/threefry32/threefry32-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/threefry32/threefry32-test-data-gen.c rename to _randomgen/randomgen/src/threefry32/threefry32-test-data-gen.c diff --git a/_randomgen/core_prng/src/threefry32/threefry32.c b/_randomgen/randomgen/src/threefry32/threefry32.c similarity index 100% rename from _randomgen/core_prng/src/threefry32/threefry32.c rename to _randomgen/randomgen/src/threefry32/threefry32.c diff --git a/_randomgen/core_prng/src/threefry32/threefry32.h b/_randomgen/randomgen/src/threefry32/threefry32.h similarity index 100% rename from _randomgen/core_prng/src/threefry32/threefry32.h rename to _randomgen/randomgen/src/threefry32/threefry32.h diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128-benchmark.c rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128-test-data-gen.c rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.c similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128.c rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128.c diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128.h b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128.h rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128.h diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.c rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c diff --git a/_randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h similarity index 100% rename from _randomgen/core_prng/src/xoroshiro128/xoroshiro128plus.orig.h rename to _randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c b/_randomgen/randomgen/src/xorshift1024/xorshift1024-benchmark.c similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024-benchmark.c rename to _randomgen/randomgen/src/xorshift1024/xorshift1024-benchmark.c diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c b/_randomgen/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024-test-data-gen.c rename to _randomgen/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.c b/_randomgen/randomgen/src/xorshift1024/xorshift1024.c similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024.c rename to _randomgen/randomgen/src/xorshift1024/xorshift1024.c diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.h b/_randomgen/randomgen/src/xorshift1024/xorshift1024.h similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024.h rename to _randomgen/randomgen/src/xorshift1024/xorshift1024.h diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.c b/_randomgen/randomgen/src/xorshift1024/xorshift1024.orig.c similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024.orig.c rename to _randomgen/randomgen/src/xorshift1024/xorshift1024.orig.c diff --git a/_randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h b/_randomgen/randomgen/src/xorshift1024/xorshift1024.orig.h similarity index 100% rename from _randomgen/core_prng/src/xorshift1024/xorshift1024.orig.h rename to _randomgen/randomgen/src/xorshift1024/xorshift1024.orig.h diff --git a/_randomgen/core_prng/tests/data/dSFMT-testset-1.csv b/_randomgen/randomgen/tests/data/dSFMT-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/dSFMT-testset-1.csv rename to _randomgen/randomgen/tests/data/dSFMT-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/dSFMT-testset-2.csv b/_randomgen/randomgen/tests/data/dSFMT-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/dSFMT-testset-2.csv rename to _randomgen/randomgen/tests/data/dSFMT-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/mt19937-testset-1.csv b/_randomgen/randomgen/tests/data/mt19937-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/mt19937-testset-1.csv rename to _randomgen/randomgen/tests/data/mt19937-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/mt19937-testset-2.csv b/_randomgen/randomgen/tests/data/mt19937-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/mt19937-testset-2.csv rename to _randomgen/randomgen/tests/data/mt19937-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/pcg32-testset-1.csv b/_randomgen/randomgen/tests/data/pcg32-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/pcg32-testset-1.csv rename to _randomgen/randomgen/tests/data/pcg32-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/pcg32-testset-2.csv b/_randomgen/randomgen/tests/data/pcg32-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/pcg32-testset-2.csv rename to _randomgen/randomgen/tests/data/pcg32-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/pcg64-testset-1.csv b/_randomgen/randomgen/tests/data/pcg64-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/pcg64-testset-1.csv rename to _randomgen/randomgen/tests/data/pcg64-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/pcg64-testset-2.csv b/_randomgen/randomgen/tests/data/pcg64-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/pcg64-testset-2.csv rename to _randomgen/randomgen/tests/data/pcg64-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/philox-testset-1.csv b/_randomgen/randomgen/tests/data/philox-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/philox-testset-1.csv rename to _randomgen/randomgen/tests/data/philox-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/philox-testset-2.csv b/_randomgen/randomgen/tests/data/philox-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/philox-testset-2.csv rename to _randomgen/randomgen/tests/data/philox-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/threefry-testset-1.csv b/_randomgen/randomgen/tests/data/threefry-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/threefry-testset-1.csv rename to _randomgen/randomgen/tests/data/threefry-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/threefry-testset-2.csv b/_randomgen/randomgen/tests/data/threefry-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/threefry-testset-2.csv rename to _randomgen/randomgen/tests/data/threefry-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/threefry32-testset-1.csv b/_randomgen/randomgen/tests/data/threefry32-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/threefry32-testset-1.csv rename to _randomgen/randomgen/tests/data/threefry32-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/threefry32-testset-2.csv b/_randomgen/randomgen/tests/data/threefry32-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/threefry32-testset-2.csv rename to _randomgen/randomgen/tests/data/threefry32-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv b/_randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/xoroshiro128-testset-1.csv rename to _randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv b/_randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/xoroshiro128-testset-2.csv rename to _randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv diff --git a/_randomgen/core_prng/tests/data/xorshift1024-testset-1.csv b/_randomgen/randomgen/tests/data/xorshift1024-testset-1.csv similarity index 100% rename from _randomgen/core_prng/tests/data/xorshift1024-testset-1.csv rename to _randomgen/randomgen/tests/data/xorshift1024-testset-1.csv diff --git a/_randomgen/core_prng/tests/data/xorshift1024-testset-2.csv b/_randomgen/randomgen/tests/data/xorshift1024-testset-2.csv similarity index 100% rename from _randomgen/core_prng/tests/data/xorshift1024-testset-2.csv rename to _randomgen/randomgen/tests/data/xorshift1024-testset-2.csv diff --git a/_randomgen/core_prng/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py similarity index 97% rename from _randomgen/core_prng/tests/test_against_numpy.py rename to _randomgen/randomgen/tests/test_against_numpy.py index 61a7a10206df..1bffe3f78fb3 100644 --- a/_randomgen/core_prng/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -3,7 +3,7 @@ from numpy.testing import assert_allclose, assert_array_equal, assert_equal import pytest -from core_prng import RandomGenerator, MT19937 +from randomgen import RandomGenerator, MT19937 def compare_0_input(f1, f2): @@ -38,8 +38,10 @@ def compare_2_input(f1, f2, is_np=False, is_scalar=False): ((np.array([a] * 10), b), {}), ((a, np.array([b] * 10)), {}), ((a, np.array([b] * 10)), {'size': 10}), - ((np.reshape(np.array([[a] * 100]), (100, 1)), np.array([b] * 10)), {'size': (100, 10)}), - ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (7, 31)}), + ((np.reshape(np.array([[a] * 100]), (100, 1)), + np.array([b] * 10)), {'size': (100, 10)}), + ((np.ones((7, 31), dtype=dtype) * a, + np.array([b] * 31)), {'size': (7, 31)}), ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (10, 7, 31)})] if is_scalar: @@ -81,9 +83,9 @@ class TestAgainstNumPy(object): @classmethod def setup_class(cls): cls.np = numpy.random - cls.prng = MT19937 + cls.brng = MT19937 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.nprs = cls.np.RandomState(*cls.seed) cls.initial_state = cls.rg.state cls._set_common_state() @@ -430,7 +432,8 @@ def test_multinomial(self): p = [.1, .3, .4, .2] assert_equal(f(100, p), g(100, p)) assert_equal(f(100, np.array(p)), g(100, np.array(p))) - assert_equal(f(100, np.array(p), size=(7, 23)), g(100, np.array(p), size=(7, 23))) + assert_equal(f(100, np.array(p), size=(7, 23)), + g(100, np.array(p), size=(7, 23))) self._is_state_common() def test_choice(self): @@ -525,7 +528,7 @@ def test_array(self): def test_dir(self): nprs_d = set(dir(self.nprs)) rs_d = dir(self.rg) - excluded = {'get_state', 'poisson_lam_max','set_state'} + excluded = {'get_state', 'poisson_lam_max', 'set_state'} nprs_d.difference_update(excluded) assert (len(nprs_d.difference(rs_d)) == 0) diff --git a/_randomgen/core_prng/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py similarity index 85% rename from _randomgen/core_prng/tests/test_direct.py rename to _randomgen/randomgen/tests/test_direct.py index 1bd5deafebdc..c6cd00bd56d4 100644 --- a/_randomgen/core_prng/tests/test_direct.py +++ b/_randomgen/randomgen/tests/test_direct.py @@ -7,7 +7,7 @@ assert_raises import pytest -from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ +from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 if (sys.version_info > (3, 0)): @@ -25,7 +25,7 @@ def uniform32_from_uint64(x): out = (joined >> np.uint32(9)) * (1.0 / 2 ** 23) return out.astype(np.float32) - + def uniform32_from_uint63(x): x = np.uint64(x) x = np.uint32(x >> np.uint64(32)) @@ -121,7 +121,7 @@ class Base(object): @classmethod def setup_class(cls): - cls.prng = Xoroshiro128 + cls.brng = Xoroshiro128 cls.bits = 64 cls.dtype = np.uint64 cls.seed_error_type = TypeError @@ -138,48 +138,48 @@ def _read_csv(cls, filename): return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)} def test_raw(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) uints = rs.random_raw(1000) assert_equal(uints, self.data1['data']) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) uints = rs.random_raw(1000) assert_equal(uints, self.data2['data']) @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gauss_inv(self): n = 25 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, self.bits)) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*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 = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) vals = uniform_from_uint(self.data1['data'], self.bits) uniforms = rs.random_sample(len(vals)) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float64) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) vals = uniform_from_uint(self.data2['data'], self.bits) uniforms = rs.random_sample(len(vals)) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float64) def test_uniform_float(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) vals = uniform32_from_uint(self.data1['data'], self.bits) uniforms = rs.random_sample(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) vals = uniform32_from_uint(self.data2['data'], self.bits) uniforms = rs.random_sample(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) @@ -187,13 +187,13 @@ def test_uniform_float(self): def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(self.seed_error_type, rs.seed, np.pi) assert_raises(self.seed_error_type, rs.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) assert_raises(ValueError, rs.seed, np.array([np.pi, -np.pi])) @@ -203,13 +203,13 @@ def test_seed_float_array(self): def test_seed_out_of_range(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) assert_raises(ValueError, rs.seed, -1) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(ValueError, rs.seed, [2 ** (2 * self.bits + 1)]) assert_raises(ValueError, rs.seed, [-1]) @@ -217,7 +217,7 @@ def test_seed_out_of_range_array(self): class TestXoroshiro128(Base): @classmethod def setup_class(cls): - cls.prng = Xoroshiro128 + cls.brng = Xoroshiro128 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -230,7 +230,7 @@ def setup_class(cls): class TestXorshift1024(Base): @classmethod def setup_class(cls): - cls.prng = Xorshift1024 + cls.brng = Xorshift1024 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -243,7 +243,7 @@ def setup_class(cls): class TestThreeFry(Base): @classmethod def setup_class(cls): - cls.prng = ThreeFry + cls.brng = ThreeFry cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -256,7 +256,7 @@ def setup_class(cls): class TestPCG64(Base): @classmethod def setup_class(cls): - cls.prng = PCG64 + cls.brng = PCG64 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv(join(pwd, './data/pcg64-testset-1.csv')) @@ -264,7 +264,7 @@ def setup_class(cls): cls.seed_error_type = TypeError def test_seed_float_array(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) assert_raises(self.seed_error_type, rs.seed, np.array([np.pi, -np.pi])) @@ -273,15 +273,16 @@ def test_seed_float_array(self): assert_raises(self.seed_error_type, rs.seed, [0, np.pi]) def test_seed_out_of_range_array(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.seed, [2 ** (2 * self.bits + 1)]) + rs = RandomGenerator(self.brng(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.seed, + [2 ** (2 * self.bits + 1)]) assert_raises(self.seed_error_type, rs.seed, [-1]) class TestPhilox(Base): @classmethod def setup_class(cls): - cls.prng = Philox + cls.brng = Philox cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -294,7 +295,7 @@ def setup_class(cls): class TestMT19937(Base): @classmethod def setup_class(cls): - cls.prng = MT19937 + cls.brng = MT19937 cls.bits = 32 cls.dtype = np.uint32 cls.data1 = cls._read_csv(join(pwd, './data/mt19937-testset-1.csv')) @@ -303,27 +304,27 @@ def setup_class(cls): def test_seed_out_of_range(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(ValueError, rs.seed, 2 ** (self.bits + 1)) assert_raises(ValueError, rs.seed, -1) assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) assert_raises(ValueError, rs.seed, [-1]) assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(TypeError, rs.seed, np.pi) assert_raises(TypeError, rs.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(TypeError, rs.seed, np.array([np.pi])) assert_raises(TypeError, rs.seed, np.array([-np.pi])) assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) @@ -335,7 +336,7 @@ def test_seed_float_array(self): class TestDSFMT(Base): @classmethod def setup_class(cls): - cls.prng = DSFMT + cls.brng = DSFMT cls.bits = 53 cls.dtype = np.uint64 cls.data1 = cls._read_csv(join(pwd, './data/dSFMT-testset-1.csv')) @@ -343,43 +344,43 @@ def setup_class(cls): cls.seed_error_type = TypeError def test_uniform_double(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_array_equal(uniform_from_dsfmt(self.data1['data']), rs.random_sample(1000)) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) assert_equal(uniform_from_dsfmt(self.data2['data']), rs.random_sample(1000)) @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gauss_inv(self): n = 25 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, 'dsfmt')) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, 'dsfmt')) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) assert_raises(ValueError, rs.seed, [-1]) assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(TypeError, rs.seed, np.pi) assert_raises(TypeError, rs.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(TypeError, rs.seed, np.array([np.pi])) assert_raises(TypeError, rs.seed, np.array([-np.pi])) assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) @@ -388,13 +389,13 @@ def test_seed_float_array(self): assert_raises(TypeError, rs.seed, [0, np.pi]) def test_uniform_float(self): - rs = RandomGenerator(self.prng(*self.data1['seed'])) + rs = RandomGenerator(self.brng(*self.data1['seed'])) vals = uniform32_from_uint(self.data1['data'], self.bits) uniforms = rs.random_sample(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) - rs = RandomGenerator(self.prng(*self.data2['seed'])) + rs = RandomGenerator(self.brng(*self.data2['seed'])) vals = uniform32_from_uint(self.data2['data'], self.bits) uniforms = rs.random_sample(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) @@ -404,7 +405,7 @@ def test_uniform_float(self): class TestThreeFry32(Base): @classmethod def setup_class(cls): - cls.prng = ThreeFry32 + cls.brng = ThreeFry32 cls.bits = 32 cls.dtype = np.uint32 cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) @@ -415,7 +416,7 @@ def setup_class(cls): class TestPCG32(TestPCG64): @classmethod def setup_class(cls): - cls.prng = PCG32 + cls.brng = PCG32 cls.bits = 32 cls.dtype = np.uint32 cls.data1 = cls._read_csv(join(pwd, './data/pcg32-testset-1.csv')) diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py similarity index 98% rename from _randomgen/core_prng/tests/test_numpy_mt19937.py rename to _randomgen/randomgen/tests/test_numpy_mt19937.py index dbe25172843a..85419b2172bf 100644 --- a/_randomgen/core_prng/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -10,8 +10,8 @@ assert_array_almost_equal) import pytest -from core_prng._testing import suppress_warnings -from core_prng import RandomGenerator, MT19937 +from randomgen._testing import suppress_warnings +from randomgen import RandomGenerator, MT19937 random = mt19937 = RandomGenerator(MT19937()) @@ -92,34 +92,34 @@ def test_size(self): class TestSetState(object): def setup(self): self.seed = 1234567890 - self.prng = RandomGenerator(MT19937(self.seed)) - self.state = self.prng.state - self.legacy_state = (self.state['prng'], + self.brng = RandomGenerator(MT19937(self.seed)) + self.state = self.brng.state + self.legacy_state = (self.state['brng'], self.state['state']['key'], self.state['state']['pos']) def test_basic(self): - old = self.prng.tomaxint(16) - self.prng.state = self.state - new = self.prng.tomaxint(16) + old = self.brng.tomaxint(16) + self.brng.state = self.state + new = self.brng.tomaxint(16) assert_(np.all(old == new)) def test_gaussian_reset(self): # Make sure the cached every-other-Gaussian is reset. - old = self.prng.standard_normal(size=3) - self.prng.state = self.state - new = self.prng.standard_normal(size=3) + old = self.brng.standard_normal(size=3) + self.brng.state = self.state + new = self.brng.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.prng.standard_normal() - state = self.prng.state - old = self.prng.standard_normal(size=3) - self.prng.state = state - new = self.prng.standard_normal(size=3) + self.brng.standard_normal() + state = self.brng.state + old = self.brng.standard_normal(size=3) + self.brng.state = state + new = self.brng.standard_normal(size=3) assert_(np.all(old == new)) @pytest.mark.skip(reason='Box-Muller no longer supported') @@ -127,18 +127,18 @@ def test_backwards_compatibility(self): # Make sure we can accept old state tuples that do not have the # cached Gaussian value. old_state = self.legacy_state[:-2] - x1 = self.prng.standard_normal(size=16) - self.prng.state = old_state - x2 = self.prng.standard_normal(size=16) - self.prng.state = self.state - x3 = self.prng.standard_normal(size=16) + x1 = self.brng.standard_normal(size=16) + self.brng.state = old_state + x2 = self.brng.standard_normal(size=16) + self.brng.state = self.state + x3 = self.brng.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.prng.negative_binomial(0.5, 0.5) + self.brng.negative_binomial(0.5, 0.5) class TestRandint(object): diff --git a/_randomgen/core_prng/tests/test_numpy_mt19937_regressions.py b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py similarity index 97% rename from _randomgen/core_prng/tests/test_numpy_mt19937_regressions.py rename to _randomgen/randomgen/tests/test_numpy_mt19937_regressions.py index 37ca9aa77f00..4a972462d2a4 100644 --- a/_randomgen/core_prng/tests/test_numpy_mt19937_regressions.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py @@ -6,10 +6,11 @@ from numpy.compat import long import numpy as np import pytest -from core_prng import RandomGenerator, MT19937 +from randomgen import RandomGenerator, MT19937 mt19937 = RandomGenerator(MT19937()) + class TestRegression(object): def test_VonMises_range(self): @@ -30,7 +31,8 @@ def test_hypergeometric_range(self): ] 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_(mt19937.hypergeometric(*arg) > 0) @@ -136,5 +138,6 @@ def test_shuffle_of_array_of_objects(self): import gc gc.collect() + if __name__ == "__main__": run_module_suite() diff --git a/_randomgen/core_prng/tests/test_smoke.py b/_randomgen/randomgen/tests/test_smoke.py similarity index 94% rename from _randomgen/core_prng/tests/test_smoke.py rename to _randomgen/randomgen/tests/test_smoke.py index a5f35390da45..cc720f1f0d2e 100644 --- a/_randomgen/core_prng/tests/test_smoke.py +++ b/_randomgen/randomgen/tests/test_smoke.py @@ -8,9 +8,9 @@ from numpy.testing import assert_almost_equal, assert_equal, assert_, \ assert_array_equal -from core_prng import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ +from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 -from core_prng import entropy +from randomgen import entropy @pytest.fixture(scope='module', @@ -110,7 +110,7 @@ def _reset_state(self): self.rg.state = self.initial_state def test_init(self): - rg = RandomGenerator(self.prng()) + rg = RandomGenerator(self.brng()) state = rg.state rg.standard_normal(1) rg.standard_normal(1) @@ -208,13 +208,13 @@ def test_reset_state(self): assert_(int_1 == int_2) def test_entropy_init(self): - rg = RandomGenerator(self.prng()) - rg2 = RandomGenerator(self.prng()) + rg = RandomGenerator(self.brng()) + rg2 = RandomGenerator(self.brng()) assert_(not comp_state(rg.state, rg2.state)) def test_seed(self): - rg = RandomGenerator(self.prng(*self.seed)) - rg2 = RandomGenerator(self.prng(*self.seed)) + rg = RandomGenerator(self.brng(*self.seed)) + rg2 = RandomGenerator(self.brng(*self.seed)) rg.random_sample() rg2.random_sample() if not comp_state(rg.state, rg2.state): @@ -225,31 +225,31 @@ def test_seed(self): assert_(comp_state(rg.state, rg2.state)) def test_reset_state_gauss(self): - rg = RandomGenerator(self.prng(*self.seed)) + rg = RandomGenerator(self.brng(*self.seed)) rg.standard_normal() state = rg.state n1 = rg.standard_normal(size=10) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) rg2.state = state n2 = rg2.standard_normal(size=10) assert_array_equal(n1, n2) def test_reset_state_uint32(self): - rg = RandomGenerator(self.prng(*self.seed)) + rg = RandomGenerator(self.brng(*self.seed)) rg.randint(0, 2 ** 24, 120, dtype=np.uint32) state = rg.state n1 = rg.randint(0, 2 ** 24, 10, dtype=np.uint32) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) rg2.state = state n2 = rg2.randint(0, 2 ** 24, 10, dtype=np.uint32) assert_array_equal(n1, n2) def test_reset_state_uintegers(self): - rg = RandomGenerator(self.prng(*self.seed)) + rg = RandomGenerator(self.brng(*self.seed)) rg.random_uintegers(bits=32) state = rg.state n1 = rg.random_uintegers(bits=32, size=10) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) rg2.state = state n2 = rg2.random_uintegers(bits=32, size=10) assert_((n1 == n2).all()) @@ -603,11 +603,11 @@ def test_seed_array_error(self): self.rg.seed(seed) def test_uniform_float(self): - rg = RandomGenerator(self.prng(12345)) + rg = RandomGenerator(self.brng(12345)) warmup(rg) state = rg.state r1 = rg.random_sample(11, dtype=np.float32) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) warmup(rg2) rg2.state = state r2 = rg2.random_sample(11, dtype=np.float32) @@ -616,11 +616,11 @@ def test_uniform_float(self): assert_(comp_state(rg.state, rg2.state)) def test_gamma_floats(self): - rg = RandomGenerator(self.prng()) + rg = RandomGenerator(self.brng()) warmup(rg) state = rg.state r1 = rg.standard_gamma(4.0, 11, dtype=np.float32) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) warmup(rg2) rg2.state = state r2 = rg2.standard_gamma(4.0, 11, dtype=np.float32) @@ -629,11 +629,11 @@ def test_gamma_floats(self): assert_(comp_state(rg.state, rg2.state)) def test_normal_floats(self): - rg = RandomGenerator(self.prng()) + rg = RandomGenerator(self.brng()) warmup(rg) state = rg.state r1 = rg.standard_normal(11, dtype=np.float32) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) warmup(rg2) rg2.state = state r2 = rg2.standard_normal(11, dtype=np.float32) @@ -642,11 +642,11 @@ def test_normal_floats(self): assert_(comp_state(rg.state, rg2.state)) def test_normal_zig_floats(self): - rg = RandomGenerator(self.prng()) + rg = RandomGenerator(self.brng()) warmup(rg) state = rg.state r1 = rg.standard_normal(11, dtype=np.float32) - rg2 = RandomGenerator(self.prng()) + rg2 = RandomGenerator(self.brng()) warmup(rg2) rg2.state = state r2 = rg2.standard_normal(11, dtype=np.float32) @@ -835,10 +835,10 @@ def test_randint_broadcast_errors(self, dtype): class TestMT19937(RNG): @classmethod def setup_class(cls): - cls.prng = MT19937 + cls.brng = MT19937 cls.advance = None cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 32 cls._extra_setup() @@ -857,11 +857,11 @@ def test_numpy_state(self): class TestPCG64(RNG): @classmethod def setup_class(cls): - cls.prng = PCG64 + cls.brng = PCG64 cls.advance = 2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = None cls._extra_setup() @@ -894,10 +894,10 @@ def test_seed_array_error(self): class TestPhilox(RNG): @classmethod def setup_class(cls): - cls.prng = Philox + cls.brng = Philox cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -906,10 +906,10 @@ def setup_class(cls): class TestThreeFry(RNG): @classmethod def setup_class(cls): - cls.prng = ThreeFry + cls.brng = ThreeFry cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -918,10 +918,10 @@ def setup_class(cls): class TestXoroshiro128(RNG): @classmethod def setup_class(cls): - cls.prng = Xoroshiro128 + cls.brng = Xoroshiro128 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -930,10 +930,10 @@ def setup_class(cls): class TestXorshift1024(RNG): @classmethod def setup_class(cls): - cls.prng = Xorshift1024 + cls.brng = Xorshift1024 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -942,10 +942,10 @@ def setup_class(cls): class TestDSFMT(RNG): @classmethod def setup_class(cls): - cls.prng = DSFMT + cls.brng = DSFMT cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls._extra_setup() cls.seed_vector_bits = 32 @@ -954,10 +954,10 @@ def setup_class(cls): class TestThreeFry32(RNG): @classmethod def setup_class(cls): - cls.prng = ThreeFry32 + cls.brng = ThreeFry32 cls.advance = [2 ** 96 + 2 ** 16 + 2 ** 5 + 1] cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -986,11 +986,11 @@ def test_fallback(self): class TestPCG32(TestPCG64): @classmethod def setup_class(cls): - cls.prng = PCG32 + cls.brng = PCG32 cls.advance = 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.prng(*cls.seed)) + cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state cls.seed_vector_bits = None cls._extra_setup() diff --git a/_randomgen/core_prng/threefry.pyx b/_randomgen/randomgen/threefry.pyx similarity index 86% rename from _randomgen/core_prng/threefry.pyx rename to _randomgen/randomgen/threefry.pyx index e2b5b3c71082..ffcc754171f0 100644 --- a/_randomgen/core_prng/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -4,9 +4,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy, seed_by_array -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() @@ -48,7 +48,7 @@ cdef double threefry_double(void* st) nogil: cdef class ThreeFry: """ - Prototype Core PRNG using threefry + Prototype Basic RNG using threefry Parameters ---------- @@ -61,24 +61,24 @@ cdef class ThreeFry: a `RandomGenerator` object. """ cdef threefry_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry_state)) self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) - self._prng.state = self.rng_state - self._prng.next_uint64 = &threefry_uint64 - self._prng.next_uint32 = &threefry_uint32 - self._prng.next_double = &threefry_double - self._prng.next_raw = &threefry_uint64 + self._brng.state = self.rng_state + self._brng.next_uint64 = &threefry_uint64 + self._brng.next_uint32 = &threefry_uint32 + self._brng.next_double = &threefry_double + self._brng.next_raw = &threefry_uint64 - cdef const char *name = 'CorePRNG' - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = 'BasicRNG' + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -88,15 +88,15 @@ cdef class ThreeFry: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -124,9 +124,9 @@ cdef class ThreeFry: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -134,10 +134,10 @@ cdef class ThreeFry: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -209,7 +209,7 @@ cdef class ThreeFry: for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] state = {'counter':ctr,'key':key} - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos, @@ -220,8 +220,8 @@ cdef class ThreeFry: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): diff --git a/_randomgen/core_prng/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx similarity index 86% rename from _randomgen/core_prng/threefry32.pyx rename to _randomgen/randomgen/threefry32.pyx index 376a6e4ded00..86f9c4f656c3 100644 --- a/_randomgen/core_prng/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -4,9 +4,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy, seed_by_array -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() @@ -51,7 +51,7 @@ cdef uint64_t threefry32_raw(void *st) nogil: cdef class ThreeFry32: """ - Prototype Core PRNG using threefry + Prototype Basic RNG using threefry Parameters ---------- @@ -64,24 +64,24 @@ cdef class ThreeFry32: a `RandomGenerator` object. """ cdef threefry32_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry32_state)) self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) - self._prng.state = self.rng_state - self._prng.next_uint64 = &threefry32_uint64 - self._prng.next_uint32 = &threefry32_uint32 - self._prng.next_double = &threefry32_double - self._prng.next_raw = &threefry32_raw + self._brng.state = self.rng_state + self._brng.next_uint64 = &threefry32_uint64 + self._brng.next_uint32 = &threefry32_uint32 + self._brng.next_double = &threefry32_double + self._brng.next_raw = &threefry32_raw - cdef const char *name = 'CorePRNG' - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = 'BasicRNG' + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -91,15 +91,15 @@ cdef class ThreeFry32: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state.ctr) free(self.rng_state.key) free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE @@ -125,9 +125,9 @@ cdef class ThreeFry32: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -135,10 +135,10 @@ cdef class ThreeFry32: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -210,7 +210,7 @@ cdef class ThreeFry32: for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] state = {'counter':ctr,'key':key} - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos} @@ -219,8 +219,8 @@ cdef class ThreeFry32: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): diff --git a/_randomgen/core_prng/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx similarity index 88% rename from _randomgen/core_prng/xoroshiro128.pyx rename to _randomgen/randomgen/xoroshiro128.pyx index 03535333f795..46058e9ca13b 100644 --- a/_randomgen/core_prng/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -6,9 +6,9 @@ cimport numpy as np from common import interface from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy, seed_by_array -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() @@ -81,7 +81,7 @@ cdef class Xoroshiro128: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from core_prng import RandomGenerator, Xoroshiro128 + >>> from randomgen import RandomGenerator, Xoroshiro128 >>> rg = [RandomGenerator(Xoroshiro128(1234)) for _ in range(10)] # Advance rs[i] by i jumps >>> for i in range(10): @@ -105,7 +105,7 @@ cdef class Xoroshiro128: Examples -------- - >>> from core_prng import RandomGenerator, Xoroshiro128 + >>> from randomgen import RandomGenerator, Xoroshiro128 >>> rg = RandomGenerator(Xoroshiro128(1234)) >>> rg.standard_normal() @@ -120,7 +120,7 @@ cdef class Xoroshiro128: http://xorshift.di.unimi.it/ """ cdef xoroshiro128_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi @@ -128,21 +128,21 @@ cdef class Xoroshiro128: def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed) - self._prng.state = self.rng_state - self._prng.next_uint64 = &xoroshiro128_uint64 - self._prng.next_uint32 = &xoroshiro128_uint32 - self._prng.next_double = &xoroshiro128_double - self._prng.next_raw = &xoroshiro128_uint64 + self._brng.state = self.rng_state + self._brng.next_uint64 = &xoroshiro128_uint64 + self._brng.next_uint32 = &xoroshiro128_uint32 + self._brng.next_double = &xoroshiro128_double + self._brng.next_raw = &xoroshiro128_uint64 self._ctypes = None self._cffi = None self._generator = None - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -152,13 +152,13 @@ cdef class Xoroshiro128: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -169,10 +169,10 @@ cdef class Xoroshiro128: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -251,7 +251,7 @@ cdef class Xoroshiro128: state = np.empty(2, dtype=np.uint64) state[0] = self.rng_state.s[0] state[1] = self.rng_state.s[1] - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 's': state, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -260,8 +260,8 @@ cdef class Xoroshiro128: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) self.rng_state.s[0] = value['s'][0] @@ -284,7 +284,7 @@ cdef class Xoroshiro128: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._ctypes is not None: @@ -303,7 +303,7 @@ cdef class Xoroshiro128: ctypes.cast(&xoroshiro128_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._prng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -321,7 +321,7 @@ cdef class Xoroshiro128: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._cffi is not None: return self._cffi @@ -333,10 +333,10 @@ cdef class Xoroshiro128: ffi = cffi.FFI() self._cffi = interface(self.rng_state, ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), - ffi.cast('double (*)(void *)',self._prng.next_double), - ffi.cast('void *',self._prng)) + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property @@ -346,8 +346,8 @@ cdef class Xoroshiro128: Returns ------- - gen : core_prng.generator.RandomGenerator - Random generator used this instance as the core PRNG + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator diff --git a/_randomgen/core_prng/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx similarity index 88% rename from _randomgen/core_prng/xorshift1024.pyx rename to _randomgen/randomgen/xorshift1024.pyx index 761f3403976c..210702358fd8 100644 --- a/_randomgen/core_prng/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -6,9 +6,9 @@ cimport numpy as np from common import interface from common cimport * -from distributions cimport prng_t -from core_prng.entropy import random_entropy, seed_by_array -import core_prng.pickle +from distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() @@ -80,7 +80,7 @@ cdef class Xorshift1024: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from core_prng import RandomGenerator, Xorshift1024 + >>> from randomgen import RandomGenerator, Xorshift1024 >>> rg = [RandomGenerator(Xorshift1024(1234)) for _ in range(10)] # Advance rg[i] by i jumps >>> for i in range(10): @@ -104,7 +104,7 @@ cdef class Xorshift1024: Examples -------- - >>> from core_prng import RandomGenerator, Xorshift1024 + >>> from randomgen import RandomGenerator, Xorshift1024 >>> rg = RandomGenerator(Xorshift1024(1234)) >>> rg.standard_normal() @@ -126,22 +126,22 @@ cdef class Xorshift1024: """ cdef xorshift1024_state *rng_state - cdef prng_t *_prng + cdef brng_t *_brng cdef public object capsule def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) - self._prng = malloc(sizeof(prng_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed) - self._prng.state = self.rng_state - self._prng.next_uint64 = &xorshift1024_uint64 - self._prng.next_uint32 = &xorshift1024_uint32 - self._prng.next_double = &xorshift1024_double - self._prng.next_raw = &xorshift1024_uint64 + self._brng.state = self.rng_state + self._brng.next_uint64 = &xorshift1024_uint64 + self._brng.next_uint32 = &xorshift1024_uint32 + self._brng.next_double = &xorshift1024_double + self._brng.next_raw = &xorshift1024_uint64 - cdef const char *name = "CorePRNG" - self.capsule = PyCapsule_New(self._prng, name, NULL) + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -151,13 +151,13 @@ cdef class Xorshift1024: self.state = state def __reduce__(self): - return (core_prng.pickle.__prng_ctor, - (self.state['prng'],), + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), self.state) def __dealloc__(self): free(self.rng_state) - free(self._prng) + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -182,9 +182,9 @@ cdef class Xorshift1024: Testing only """ if bits == 64: - return self._prng.next_uint64(self._prng.state) + return self._brng.next_uint64(self._brng.state) elif bits == 32: - return self._prng.next_uint32(self._prng.state) + return self._brng.next_uint32(self._brng.state) else: raise ValueError('bits must be 32 or 64') @@ -192,10 +192,10 @@ cdef class Xorshift1024: cdef Py_ssize_t i if method==u'uint64': for i in range(cnt): - self._prng.next_uint64(self._prng.state) + self._brng.next_uint64(self._brng.state) elif method==u'double': for i in range(cnt): - self._prng.next_double(self._prng.state) + self._brng.next_double(self._brng.state) else: raise ValueError('Unknown method') @@ -267,7 +267,7 @@ cdef class Xorshift1024: s = np.empty(16, dtype=np.uint64) for i in range(16): s[i] = self.rng_state.s[i] - return {'prng': self.__class__.__name__, + return {'brng': self.__class__.__name__, 'state': {'s':s,'p':self.rng_state.p}, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -276,8 +276,8 @@ cdef class Xorshift1024: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - prng = value.get('prng', '') - if prng != self.__class__.__name__: + brng = value.get('brng', '') + if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(16): @@ -301,7 +301,7 @@ cdef class Xorshift1024: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._ctypes is not None: @@ -320,7 +320,7 @@ cdef class Xorshift1024: ctypes.cast(&xorshift1024_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._prng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -338,7 +338,7 @@ cdef class Xorshift1024: * 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 - * prng - pointer to the PRNG struct + * brng - pointer to the Basic RNG struct """ if self._cffi is not None: return self._cffi @@ -350,10 +350,10 @@ cdef class Xorshift1024: ffi = cffi.FFI() self._cffi = interface(self.rng_state, ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._prng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._prng.next_uint32), - ffi.cast('double (*)(void *)',self._prng.next_double), - ffi.cast('void *',self._prng)) + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property @@ -363,7 +363,7 @@ cdef class Xorshift1024: Returns ------- - gen : core_prng.generator.RandomGenerator + gen : randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/_randomgen/setup.cfg b/_randomgen/setup.cfg index d622db893c08..d6b61d347b3d 100644 --- a/_randomgen/setup.cfg +++ b/_randomgen/setup.cfg @@ -1,7 +1,7 @@ [versioneer] VCS = git style = pep440 -versionfile_source = core_prng/_version.py -versionfile_build = core_prng/_version.py +versionfile_source = randomgen/_version.py +versionfile_build = randomgen/_version.py tag_prefix = -parentdir_prefix = core_prng- +parentdir_prefix = randomgen- diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 6508bde6473c..9c73c3d70e05 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -24,7 +24,7 @@ Cython.Compiler.Options.annotate = True USE_SSE2 = True if not '--no-sse2' in sys.argv else False -MOD_DIR = './core_prng' +MOD_DIR = './randomgen' DEBUG = False PCG_EMULATED_MATH = False @@ -53,7 +53,7 @@ if struct.calcsize('P') < 8: PCG_EMULATED_MATH = True -files = glob.glob('./core_prng/*.in') +files = glob.glob('./randomgen/*.in') for templated_file in files: output_file_name = os.path.splitext(templated_file)[0] if (os.path.exists(output_file_name) and @@ -65,7 +65,7 @@ output_file.write(template.substitute()) -extensions = [Extension('core_prng.entropy', +extensions = [Extension('randomgen.entropy', sources=[join(MOD_DIR, 'entropy.pyx'), join(MOD_DIR, 'src', 'entropy', 'entropy.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), @@ -74,8 +74,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.dsfmt", - ["core_prng/dsfmt.pyx", + Extension("randomgen.dsfmt", + ["randomgen/dsfmt.pyx", join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c'), join(MOD_DIR, 'src', 'dsfmt', 'dSFMT-jump.c'), join(MOD_DIR, 'src', 'aligned_malloc', 'aligned_malloc.c')], @@ -86,8 +86,8 @@ extra_link_args=EXTRA_LINK_ARGS, define_macros=DSFMT_DEFS, ), - Extension("core_prng.mt19937", - ["core_prng/mt19937.pyx", + Extension("randomgen.mt19937", + ["randomgen/mt19937.pyx", join(MOD_DIR, 'src', 'mt19937', 'mt19937.c'), join(MOD_DIR, 'src', 'mt19937', 'mt19937-jump.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), @@ -96,8 +96,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.philox", - ["core_prng/philox.pyx", + Extension("randomgen.philox", + ["randomgen/philox.pyx", join(MOD_DIR, 'src', 'philox', 'philox.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', @@ -105,8 +105,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.pcg64", - ["core_prng/pcg64.pyx", + Extension("randomgen.pcg64", + ["randomgen/pcg64.pyx", join(MOD_DIR, 'src', 'pcg64', 'pcg64.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', @@ -114,8 +114,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.pcg32", - ["core_prng/pcg32.pyx", + Extension("randomgen.pcg32", + ["randomgen/pcg32.pyx", join(MOD_DIR, 'src', 'pcg32', 'pcg32.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', @@ -123,8 +123,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.threefry", - ["core_prng/threefry.pyx", + Extension("randomgen.threefry", + ["randomgen/threefry.pyx", join(MOD_DIR, 'src', 'threefry', 'threefry.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', @@ -132,8 +132,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.threefry32", - ["core_prng/threefry32.pyx", + Extension("randomgen.threefry32", + ["randomgen/threefry32.pyx", join(MOD_DIR, 'src', 'threefry32', 'threefry32.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', @@ -141,8 +141,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.xoroshiro128", - ["core_prng/xoroshiro128.pyx", + Extension("randomgen.xoroshiro128", + ["randomgen/xoroshiro128.pyx", join(MOD_DIR, 'src', 'xoroshiro128', 'xoroshiro128.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), @@ -152,8 +152,8 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.xorshift1024", - ["core_prng/xorshift1024.pyx", + Extension("randomgen.xorshift1024", + ["randomgen/xorshift1024.pyx", join(MOD_DIR, 'src', 'xorshift1024', 'xorshift1024.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), @@ -162,22 +162,22 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.generator", - ["core_prng/generator.pyx", + Extension("randomgen.generator", + ["randomgen/generator.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.common", - ["core_prng/common.pyx"], + Extension("randomgen.common", + ["randomgen/common.pyx"], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), - Extension("core_prng.bounded_integers", - ["core_prng/bounded_integers.pyx", + Extension("randomgen.bounded_integers", + ["randomgen/bounded_integers.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], @@ -197,9 +197,9 @@ def is_pure(self): cmdclass=versioneer.get_cmdclass(), ext_modules=cythonize(extensions, compile_time_env={ "PCG_EMULATED_MATH": PCG_EMULATED_MATH}), - name='core_prng', + name='randomgen', packages=find_packages(), - package_dir={'core_prng': './core_prng'}, + package_dir={'randomgen': './randomgen'}, package_data={'': ['*.c', '*.h', '*.pxi', '*.pyx', '*.pxd']}, include_package_data=True, license='NSCA', @@ -207,7 +207,7 @@ def is_pure(self): author_email='kevin.k.sheppard@gmail.com', distclass=BinaryDistribution, description='Next-gen RandomState supporting multiple PRNGs', - url='https://github.com/bashtage/core-prng', + url='https://github.com/bashtage/randomgen', keywords=['pseudo random numbers', 'PRNG', 'Python'], zip_safe=False ) diff --git a/_randomgen/test.py b/_randomgen/test.py deleted file mode 100644 index 38ffa02b05c4..000000000000 --- a/_randomgen/test.py +++ /dev/null @@ -1,14 +0,0 @@ -import core_prng as c -rg = c.RandomGenerator() -print(rg.state) -rg.random_integer(32) -print(rg.state) -rg.random_integer(32) -print(rg.state) - -rg.random_integer(64) -print(rg.state) -rg.random_integer(32) -print(rg.state) -rg.random_integer(64) -print(rg.state) From c722f441581044eeb9d1f41c8e6dd5c6abefeb7e Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 12:40:45 +0000 Subject: [PATCH 060/138] DOC: Update docs --- _randomgen/MANIFEST.in | 4 + _randomgen/README.md | 4 +- .../doc/source/{prng => brng}/dsfmt.rst | 2 + .../doc/source/{prng => brng}/index.rst | 3 +- _randomgen/doc/source/brng/mt19937.rst | 40 +++ _randomgen/doc/source/brng/pcg32.rst | 41 +++ _randomgen/doc/source/brng/pcg64.rst | 41 +++ _randomgen/doc/source/brng/philox.rst | 41 +++ _randomgen/doc/source/brng/threefry.rst | 41 +++ _randomgen/doc/source/brng/threefry32.rst | 41 +++ .../source/{prng => brng}/xoroshiro128.rst | 2 + .../source/{prng => brng}/xorshift1024.rst | 2 + _randomgen/doc/source/change-log.rst | 4 + _randomgen/doc/source/conf.py | 13 +- _randomgen/doc/source/entropy.rst | 6 + _randomgen/doc/source/extending.rst | 163 +++++++++ _randomgen/doc/source/index.rst | 164 ++++++++- _randomgen/doc/source/multithreading.rst | 130 +++++++ _randomgen/doc/source/new-or-different.rst | 95 +++++ _randomgen/doc/source/parallel.rst | 141 ++++++++ _randomgen/doc/source/performance.py | 73 ++++ _randomgen/doc/source/performance.rst | 75 ++++ _randomgen/randomgen/dsfmt.pyx | 6 +- .../examples/cython/extending.pyx | 0 .../cython/extending_distributions.pyx | 23 ++ .../{ => randomgen}/examples/cython/setup.py | 0 .../examples/numba/extending.py | 54 +-- .../examples/numba/extending_distributions.py | 9 +- _randomgen/randomgen/generator.pyx | 60 +++- _randomgen/randomgen/mt19937.pyx | 93 +++++ _randomgen/randomgen/pcg32.pyx | 228 +++++++++++- _randomgen/randomgen/pcg64.pyx | 250 ++++++++++++- _randomgen/randomgen/philox.pyx | 300 +++++++++++++--- .../randomgen/tests/test_against_numpy.py | 18 +- _randomgen/randomgen/threefry.pyx | 307 +++++++++++++--- _randomgen/randomgen/threefry32.pyx | 336 +++++++++++++++--- _randomgen/randomgen/xoroshiro128.pyx | 2 +- _randomgen/randomgen/xorshift1024.pyx | 21 +- _randomgen/setup.py | 6 +- 39 files changed, 2604 insertions(+), 235 deletions(-) rename _randomgen/doc/source/{prng => brng}/dsfmt.rst (94%) rename _randomgen/doc/source/{prng => brng}/index.rst (92%) create mode 100644 _randomgen/doc/source/brng/mt19937.rst create mode 100644 _randomgen/doc/source/brng/pcg32.rst create mode 100644 _randomgen/doc/source/brng/pcg64.rst create mode 100644 _randomgen/doc/source/brng/philox.rst create mode 100644 _randomgen/doc/source/brng/threefry.rst create mode 100644 _randomgen/doc/source/brng/threefry32.rst rename _randomgen/doc/source/{prng => brng}/xoroshiro128.rst (93%) rename _randomgen/doc/source/{prng => brng}/xorshift1024.rst (93%) create mode 100644 _randomgen/doc/source/change-log.rst create mode 100644 _randomgen/doc/source/entropy.rst create mode 100644 _randomgen/doc/source/extending.rst create mode 100644 _randomgen/doc/source/multithreading.rst create mode 100644 _randomgen/doc/source/new-or-different.rst create mode 100644 _randomgen/doc/source/parallel.rst create mode 100644 _randomgen/doc/source/performance.py create mode 100644 _randomgen/doc/source/performance.rst rename _randomgen/{ => randomgen}/examples/cython/extending.pyx (100%) rename _randomgen/{ => randomgen}/examples/cython/extending_distributions.pyx (51%) rename _randomgen/{ => randomgen}/examples/cython/setup.py (100%) rename _randomgen/{ => randomgen}/examples/numba/extending.py (52%) rename _randomgen/{ => randomgen}/examples/numba/extending_distributions.py (94%) diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in index 929dfdb24725..c961f9101cd4 100644 --- a/_randomgen/MANIFEST.in +++ b/_randomgen/MANIFEST.in @@ -1,2 +1,6 @@ include versioneer.py include randomgen/_version.py +recursive-include randomgen *.py *.pyx *.px[di] *.h *.in +recursive-include randomgen/src *.c + + diff --git a/_randomgen/README.md b/_randomgen/README.md index 1fd99e875b45..93b0e461b0be 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -1,7 +1,7 @@ # RandomGen -[![Travis Build Status](https://travis-ci.org/bashtage/ng-numpy-randomstate.svg?branch=master)](https://travis-ci.org/bashtage/randomgen) -[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/randomgen/branch/master) +[![Travis Build Status](https://travis-ci.org/bashtage/core-prng.svg?branch=master)](https://travis-ci.org/bashtage/core-prng) +[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/core-prng/branch/master) Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. diff --git a/_randomgen/doc/source/prng/dsfmt.rst b/_randomgen/doc/source/brng/dsfmt.rst similarity index 94% rename from _randomgen/doc/source/prng/dsfmt.rst rename to _randomgen/doc/source/brng/dsfmt.rst index 2f5ed0ba77de..3432d4d043ce 100644 --- a/_randomgen/doc/source/prng/dsfmt.rst +++ b/_randomgen/doc/source/brng/dsfmt.rst @@ -1,6 +1,8 @@ Double SIMD Mersenne Twister (dSFMT) ------------------------------------ +.. module:: randomgen.dsfmt + .. currentmodule:: randomgen.dsfmt Random generator diff --git a/_randomgen/doc/source/prng/index.rst b/_randomgen/doc/source/brng/index.rst similarity index 92% rename from _randomgen/doc/source/prng/index.rst rename to _randomgen/doc/source/brng/index.rst index 8aebf16813e0..8bd29c1ca622 100644 --- a/_randomgen/doc/source/prng/index.rst +++ b/_randomgen/doc/source/brng/index.rst @@ -10,6 +10,7 @@ These RNGs will be included in future releases. :maxdepth: 1 DSFMT + MT19937 PCG64 Philox ThreeFry @@ -26,5 +27,5 @@ permanent. .. toctree:: :maxdepth: 1 + PCG32 ThreeFry32 - PCG32 \ No newline at end of file diff --git a/_randomgen/doc/source/brng/mt19937.rst b/_randomgen/doc/source/brng/mt19937.rst new file mode 100644 index 000000000000..3fbc8f0994c4 --- /dev/null +++ b/_randomgen/doc/source/brng/mt19937.rst @@ -0,0 +1,40 @@ +Mersenne Twister (MT19937) +-------------------------- + +.. module:: randomgen.mt19937 + +.. currentmodule:: randomgen.mt19937 + +Random generator +================ +.. autoclass:: MT19937 + +.. autosummary:: + :toctree: generated/ + + ~MT19937.seed + ~MT19937.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~MT19937.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~MT19937.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~MT19937.cffi + ~MT19937.ctypes + + diff --git a/_randomgen/doc/source/brng/pcg32.rst b/_randomgen/doc/source/brng/pcg32.rst new file mode 100644 index 000000000000..97bb341ad45b --- /dev/null +++ b/_randomgen/doc/source/brng/pcg32.rst @@ -0,0 +1,41 @@ +Parallel Congruent Generator (32-bit, PCG32) +-------------------------------------------- + +.. module:: randomgen.pcg32 + +.. currentmodule:: randomgen.pcg32 + +Random generator +================ +.. autoclass:: PCG32 + +.. autosummary:: + :toctree: generated/ + + ~PCG32.seed + ~PCG32.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~PCG32.advance + ~PCG32.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~PCG32.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~PCG32.cffi + ~PCG32.ctypes + + diff --git a/_randomgen/doc/source/brng/pcg64.rst b/_randomgen/doc/source/brng/pcg64.rst new file mode 100644 index 000000000000..2ef19abb2123 --- /dev/null +++ b/_randomgen/doc/source/brng/pcg64.rst @@ -0,0 +1,41 @@ +Parallel Congruent Generator (64-bit, PCG64) +-------------------------------------------- + +.. module:: randomgen.pcg64 + +.. currentmodule:: randomgen.pcg64 + +Random generator +================ +.. autoclass:: PCG64 + +.. autosummary:: + :toctree: generated/ + + ~PCG64.seed + ~PCG64.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~PCG64.advance + ~PCG64.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~PCG64.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~PCG64.cffi + ~PCG64.ctypes + + diff --git a/_randomgen/doc/source/brng/philox.rst b/_randomgen/doc/source/brng/philox.rst new file mode 100644 index 000000000000..e12de40531a9 --- /dev/null +++ b/_randomgen/doc/source/brng/philox.rst @@ -0,0 +1,41 @@ +Philox Counter-based RNG +------------------------ + +.. module:: randomgen.philox + +.. currentmodule:: randomgen.philox + +Random generator +================ +.. autoclass:: Philox + +.. autosummary:: + :toctree: generated/ + + ~Philox.seed + ~Philox.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Philox.advance + ~Philox.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~Philox.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Philox.cffi + ~Philox.ctypes + + diff --git a/_randomgen/doc/source/brng/threefry.rst b/_randomgen/doc/source/brng/threefry.rst new file mode 100644 index 000000000000..6c1ff5387a5a --- /dev/null +++ b/_randomgen/doc/source/brng/threefry.rst @@ -0,0 +1,41 @@ +ThreeFry Counter-based RNG +-------------------------- + +.. module:: randomgen.threefry + +.. currentmodule:: randomgen.threefry + +Random generator +================ +.. autoclass:: ThreeFry + +.. autosummary:: + :toctree: generated/ + + ~ThreeFry.seed + ~ThreeFry.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~ThreeFry.advance + ~ThreeFry.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~ThreeFry.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~ThreeFry.cffi + ~ThreeFry.ctypes + + diff --git a/_randomgen/doc/source/brng/threefry32.rst b/_randomgen/doc/source/brng/threefry32.rst new file mode 100644 index 000000000000..96576413c535 --- /dev/null +++ b/_randomgen/doc/source/brng/threefry32.rst @@ -0,0 +1,41 @@ +ThreeFry32 Counter-based RNG +---------------------------- + +.. module:: randomgen.threefry32 + +.. currentmodule:: randomgen.threefry32 + +Random generator +================ +.. autoclass:: ThreeFry32 + +.. autosummary:: + :toctree: generated/ + + ~ThreeFry32.seed + ~ThreeFry32.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~ThreeFry32.advance + ~ThreeFry32.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~ThreeFry32.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~ThreeFry32.cffi + ~ThreeFry32.ctypes + + diff --git a/_randomgen/doc/source/prng/xoroshiro128.rst b/_randomgen/doc/source/brng/xoroshiro128.rst similarity index 93% rename from _randomgen/doc/source/prng/xoroshiro128.rst rename to _randomgen/doc/source/brng/xoroshiro128.rst index 768ace408806..9f8b2dfadc65 100644 --- a/_randomgen/doc/source/prng/xoroshiro128.rst +++ b/_randomgen/doc/source/brng/xoroshiro128.rst @@ -1,6 +1,8 @@ Xoroshiro128+ ------------- +.. module:: randomgen.xoroshiro128 + .. currentmodule:: randomgen.xoroshiro128 Random generator diff --git a/_randomgen/doc/source/prng/xorshift1024.rst b/_randomgen/doc/source/brng/xorshift1024.rst similarity index 93% rename from _randomgen/doc/source/prng/xorshift1024.rst rename to _randomgen/doc/source/brng/xorshift1024.rst index 87adc9821446..5340579c0f8a 100644 --- a/_randomgen/doc/source/prng/xorshift1024.rst +++ b/_randomgen/doc/source/brng/xorshift1024.rst @@ -1,6 +1,8 @@ Xorshift1024*φ -------------- +.. module:: randomgen.xorshift1024 + .. currentmodule:: randomgen.xorshift1024 Random generator diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst new file mode 100644 index 000000000000..36c46223ad4c --- /dev/null +++ b/_randomgen/doc/source/change-log.rst @@ -0,0 +1,4 @@ +Change Log +---------- + +The project is too new for a change log. \ No newline at end of file diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py index 3ff696214888..b832553cb218 100644 --- a/_randomgen/doc/source/conf.py +++ b/_randomgen/doc/source/conf.py @@ -48,6 +48,8 @@ 'sphinx.ext.autosummary', 'sphinx.ext.mathjax', 'sphinx.ext.githubpages', + 'IPython.sphinxext.ipython_console_highlighting', + 'IPython.sphinxext.ipython_directive' ] # Add any paths that contain templates here, relative to this directory. @@ -170,6 +172,15 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = { + 'statsmodels': ('http://www.statsmodels.org/dev/', None), + 'matplotlib': ('https://matplotlib.org', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), + 'python': ('https://docs.python.org/3', None), + 'numpy': ('https://docs.scipy.org/doc/numpy', None), + 'np': ('https://docs.scipy.org/doc/numpy', None), + 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), + 'pd': ('https://pandas.pydata.org/pandas-docs/stable/', None), +} autosummary_generate = True diff --git a/_randomgen/doc/source/entropy.rst b/_randomgen/doc/source/entropy.rst new file mode 100644 index 000000000000..3e50c892fc1d --- /dev/null +++ b/_randomgen/doc/source/entropy.rst @@ -0,0 +1,6 @@ +System Entropy +============== + +.. module:: randomgen.entropy + +.. autofunction:: random_entropy diff --git a/_randomgen/doc/source/extending.rst b/_randomgen/doc/source/extending.rst new file mode 100644 index 000000000000..aacfab393289 --- /dev/null +++ b/_randomgen/doc/source/extending.rst @@ -0,0 +1,163 @@ +Extending +--------- +The basic RNGs have been designed to be extendable using standard tools for +high-performance Python -- numba and Cython. +The :class:`randomgen.generator.RandomGenerator` object can also be used with +user-provided basic RNGs as long as these export a small set of required +functions. + +Numba +===== +Numba can be used with either CTypes or CFFI. The current iteration of the +basic RNGs all export a small set of functions through both interfaces. + +This example shows how numba can be used to produce Box-Muller normals using +a pure Python implementation which is then compiled. The random numbers are +provided by ``ctypes.next_double``. + +.. ipython:: python + + from randomgen import Xoroshiro128 + import numpy as np + import numba as nb + + x = Xoroshiro128() + f = x.ctypes.next_double + s = x.ctypes.state + state_addr = x.ctypes.state_address + + def normals(n, state): + out = np.empty(n) + for i in range((n+1)//2): + x1 = 2.0*f(state) - 1.0 + x2 = 2.0*f(state) - 1.0 + r2 = x1*x1 + x2*x2 + while r2 >= 1.0 or r2 == 0.0: + x1 = 2.0*f(state) - 1.0 + x2 = 2.0*f(state) - 1.0 + r2 = x1*x1 + x2*x2 + g = np.sqrt(-2.0*np.log(r2)/r2) + out[2*i] = g*x1 + if 2*i+1 < n: + out[2*i+1] = g*x2 + return out + + # Compile using Numba + print(normals(10, s).var()) + # Warm up + normalsj = nb.jit(normals, nopython=True) + # Must use state address not state with numba + normalsj(1, state_addr) + %timeit normalsj(1000000, state_addr) + print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms') + %timeit np.random.standard_normal(1000000) + print('1,000,000 Box-Muller (NumPy) randoms') + + +Both CTypes and CFFI allow the more complicated distributions to be used +directly in Numba after compiling the file distributions.c into a DLL or so. +An example showing the use of a more complicated distribution is in the +examples folder. + +Cython +====== + +Cython can be used to unpack the ``PyCapsule`` provided by a basic RNG. +This example uses :class:`~randomgen.xoroshiro128.Xoroshiro128` and +``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an +array. The usual caveats for writing high-performance code using Cython -- +removing bounds checks and wrap around, providing array alignment information +-- still apply. + +.. code-block:: cython + + import numpy as np + cimport numpy as np + cimport cython + from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer + from randomgen.common cimport * + from randomgen.distributions import random_gauss_zig + from randomgen.xoroshiro128 import Xoroshiro128 + + + @cython.boundscheck(False) + @cython.wraparound(False) + def normals_zig(Py_ssize_t n): + cdef Py_ssize_t i + cdef brng_t *rng + cdef const char *capsule_name = "BasicRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + # Optional check that the capsule if from a Basic RNG + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + # Cast the pointer + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + for i in range(n): + # Call the function + random_values[i] = random_gauss_zig(rng) + randoms = np.asarray(random_values) + return randoms + + +The basic RNG can also be directly accessed using the members of the basic +RNG structure. + +.. code-block:: cython + + @cython.boundscheck(False) + @cython.wraparound(False) + def uniforms(Py_ssize_t n): + cdef Py_ssize_t i + cdef brng_t *rng + cdef const char *capsule_name = "BasicRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + # Optional check that the capsule if from a Basic RNG + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + # Cast the pointer + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + for i in range(n): + # Call the function + random_values[i] = rng.next_double(rng.state) + randoms = np.asarray(random_values) + return randoms + +These functions along with a minimal setup file are included in the +examples folder. + +New Basic RNGs +============== +:class:`~randomgen.generator.RandomGenerator` can be used with other +user-provided basic RNGs. The simplest way to write a new basic RNG is to +examine the pyx file of one of the existing basic RNGs. The key structure +that must be provided is the ``capsule`` which contains a ``PyCapsule`` to a +struct pointer of type ``brng_t``, + +.. code-block:: c + + typedef struct brng { + 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); + } brng_t; + +which provides 5 pointers. The first is an opaque pointer to the data structure +used by the basic RNG. The next three are function pointers which return the +next 64- and 32-bit unsigned integers, the next random double and the next +raw value. This final function is used for testing and so can be set to +the next 64-bit unsigned integer function if not needed. Functions inside +:class:`~randomgen.generator.RandomGenerator` use this structure as in + +.. code-block:: c + + brng_state->next_uint64(brng_state->state) diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index 067416635ab8..b89679a29e62 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -1,21 +1,171 @@ -.. RandomGen documentation master file, created by - sphinx-quickstart on Tue Mar 13 20:30:45 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - RandomGen ========= +This package contains replacements for the NumPy +:class:`~numpy.random.RandomState` object that allows the core random number +generator be be changed. + +Introduction +------------ +RandomGen takes a different approach to producing random numbers from the +:class:`numpy.random.RandomState` object used in NumPy. Random number +generation is separated into two components, a basic RNG and a random +generator. + +The basic RNG has a limited set of responsibilities -- it manages the +underlying RNG state and provides functions to produce random doubles and +random unsigned 32- and 64-bit values. The basic random generator also handles +all seeding since this varies when using alternative basic RNGs. + +The random generator (:class:`~randomgen.generator.RandomGenerator`) takes the +basic RNG-provided functions and transforms them into more useful +distributions, e.g., simulated normal random values. This structure allows +alternative basic RNGs to be used without code duplication. + +The :class:`~randomgen.generator.RandomGenerator` is the user-facing object +that is nearly identical to :class:`~numpy.random.RandomState`. The canonical +method to initialize a generator passes a basic RNG -- +:class:`~randomgen.mt19937.MT19937`, the underlying RNG in NumPy -- as the +sole argument. Note that the basic RNG must be instantized. + +.. ipython:: python + + from randomgen import RandomGenerator, MT19937 + rg = RandomGenerator(MT19937()) + rg.random_sample() + +Seed information is directly passed to the basic RNG. + +.. ipython:: python + + rg = RandomGenerator(MT19937(12345)) + rg.random_sample() + +A shorthand method is also available which uses the +:meth:`~randomgen.mt19937.MT19937.generator` property from a basic RNG to +access an embedded random generator. + +.. ipython:: python + + rg = MT19937(12345).generator + rg.random_sample() + +What's New or Different +~~~~~~~~~~~~~~~~~~~~~~~ +.. warning:: + + The Box-Muller method used to produce NumPy's normals is no longer available. + It is not possible to exactly reproduce the random values produced from NumPy + for the normal distribution or any other distribution that relies on the + normal such as the gamma or student's t. + +* The normal, exponential and gamma generators use 256-step Ziggurat + methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF + implementations. +* Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64`` + to produce either single or double prevision uniform random variables for + select distributions +* Optional ``out`` argument that allows existing arrays to be filled for + select distributions +* Simulate from the complex normal distribution + (:meth:`~randomgen.generator.RandomGenerator.complex_normal`) +* :func:`~randomgen.entropy.random_entropy` provides access to the system + source of randomness that is used in cryptographic applications (e.g., + ``/dev/urandom`` on Unix). +* All basic random generators functions to produce doubles, uint64s and + uint32s via CTypes (:meth:`~randomgen.xoroshiro128.Xoroshiro128.ctypes`) + and CFFI (:meth:`~randomgen.xoroshiro128.Xoroshiro128.cffi`). This allows + these basic RNGs to be used in numba. +* The basic random number generators can be used in downstream projects via + Cython. + +See :ref:`new-or-different` for a complete list of improvements and +differences. +Parallel Generation +~~~~~~~~~~~~~~~~~~~ + +The included generators can be used in parallel, distributed applications in +one of two ways: + +* :ref:`independent-streams` +* :ref:`jump-and-advance` + +Supported Generators +-------------------- +The main innovation is the inclusion of a number of alternative pseudo-random number +generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are: + +* MT19937 - The standard NumPy generator. Produces identical results to NumPy + using the same seed/state. Adds a jump function that advances the generator + as-if 2**128 draws have been made (:meth:`~randomgen.mt19937.MT19937.jump`). + See `NumPy's documentation`_. +* dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically + the same, but with a different state and so it is not possible to produce a + sequence identical to MT19937. Supports ``jump`` and so can + be used in parallel applications. See the `dSFMT authors' page`_. +* XoroShiro128+ - Improved version of XorShift128+ with better performance + and statistical quality. Like the XorShift generators, it can be jumped + to produce multiple streams in parallel applications. See + :meth:`~randomgen.xoroshiro128.Xoroshiro128.jump` for details. + More information about this PRNG is available at the + `xorshift and xoroshiro authors' page`_. +* XorShift1024*φ - Vast fast generator based on the XSadd + generator. Supports ``jump`` and so can be used in + parallel applications. See the documentation for + :meth:`~randomgen.xorshift1024.Xorshift1024.jump` for details. More information + about these PRNGs is available at the + `xorshift and xoroshiro authors' page`_. +* PCG-64 - Fast generator that support many parallel streams and + can be advanced by an arbitrary amount. See the documentation for + :meth:`~randomgen.pcg64.PCG64.advance`. PCG-64 has a period of + :math:`2^{128}`. See the `PCG author's page`_ for more details about + this class of PRNG. +* ThreeFry and Philox - counter-based generators capable of being advanced an + arbitrary number of steps or generating independent streams. See the + `Random123`_ page for more details about this class of PRNG. + +.. _`NumPy's documentation`: https://docs.scipy.org/doc/numpy/reference/routines.random.html +.. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ +.. _`xorshift and xoroshiro authors' page`: http://xoroshiro.di.unimi.it/ +.. _`PCG author's page`: http://www.pcg-random.org/ +.. _`Random123`: https://www.deshawresearch.com/resources_random123.html + +New Features +------------ .. toctree:: :maxdepth: 2 - :caption: Contents: + + Parallel Applications + Multithreaded Generation + new-or-different + Reading System Entropy + Comparing Performance + extending + +Random Generator +---------------- +.. toctree:: + :maxdepth: 1 Random Generator + +Basic Random Number Generators +------------------------------ + +.. toctree:: + :maxdepth: 3 + Basic Random Number Generators +Changes +~~~~~~~ +.. toctree:: + :maxdepth: 2 + + Change Log Indices and tables -================== +~~~~~~~~~~~~~~~~~~ * :ref:`genindex` * :ref:`modindex` diff --git a/_randomgen/doc/source/multithreading.rst b/_randomgen/doc/source/multithreading.rst new file mode 100644 index 000000000000..ef8d710dff26 --- /dev/null +++ b/_randomgen/doc/source/multithreading.rst @@ -0,0 +1,130 @@ +Multithreaded Generation +======================== + +The four core distributions all allow existing arrays to be filled using the +``out`` keyword argument. Existing arrays need to be contiguous and +well-behaved (writable and aligned). Under normal circumstances, arrays +created using the common constructors such as :meth:`numpy.empty` will satisfy +these requirements. + +This example makes use of Python 3 :mod:`concurrent.futures` to fill an array +using multiple threads. Threads are long-lived so that repeated calls do not +require any additional overheads from thread creation. The underlying PRNG is +xorshift2014 which is fast, has a long period and supports using ``jump`` to +advance the state. The random numbers generated are reproducible in the sense +that the same seed will produce the same outputs. + +.. code-block:: python + + from randomgen import Xorshift1024 + import multiprocessing + import concurrent.futures + import numpy as np + + class MultithreadedRNG(object): + def __init__(self, n, seed=None, threads=None): + rg = Xorshift1024(seed) + if threads is None: + threads = multiprocessing.cpu_count() + self.threads = threads + + self._random_generators = [] + for _ in range(0, threads-1): + _rg = Xorshift1024() + _rg.state = rg.state + self._random_generators.append(_rg.generator) + rg.jump() + self._random_generators.append(rg.generator) + + self.n = n + self.executor = concurrent.futures.ThreadPoolExecutor(threads) + self.values = np.empty(n) + self.step = np.ceil(n / threads).astype(np.int) + + def fill(self): + def _fill(random_state, out, first, last): + random_state.standard_normal(out=out[first:last]) + + futures = {} + for i in range(self.threads): + args = (_fill, self._random_generators[i], self.values, i * self.step, (i + 1) * self.step) + futures[self.executor.submit(*args)] = i + concurrent.futures.wait(futures) + + def __del__(self): + self.executor.shutdown(False) + + +.. ipython:: python + :suppress: + + + In [1]: from randomgen import Xorshift1024 + ....: import multiprocessing + ....: import concurrent.futures + ....: import numpy as np + ....: class MultithreadedRNG(object): + ....: def __init__(self, n, seed=None, threads=None): + ....: rg = Xorshift1024(seed) + ....: if threads is None: + ....: threads = multiprocessing.cpu_count() + ....: self.threads = threads + ....: self._random_generators = [] + ....: for _ in range(0, threads-1): + ....: _rg = Xorshift1024() + ....: _rg.state = rg.state + ....: self._random_generators.append(_rg.generator) + ....: rg.jump() + ....: self._random_generators.append(rg.generator) + ....: self.n = n + ....: self.executor = concurrent.futures.ThreadPoolExecutor(threads) + ....: self.values = np.empty(n) + ....: self.step = np.ceil(n / threads).astype(np.int) + ....: def fill(self): + ....: def _fill(random_state, out, first, last): + ....: random_state.standard_normal(out=out[first:last]) + ....: futures = {} + ....: for i in range(self.threads): + ....: args = (_fill, self._random_generators[i], self.values, i * self.step, (i + 1) * self.step) + ....: futures[self.executor.submit(*args)] = i + ....: concurrent.futures.wait(futures) + ....: def __del__(self): + ....: self.executor.shutdown(False) + ....: + +The multithreaded random number generator can be used to fill an array. +The ``values`` attributes shows the zero-value before the fill and the +random value after. + +.. ipython:: python + + mrng = MultithreadedRNG(10000000, seed=0) + print(mrng.values[-1]) + mrng.fill() + print(mrng.values[-1]) + +The time required to produce using multiple threads can be compared to +the time required to generate using a single thread. + +.. ipython:: python + + print(mrng.threads) + %timeit mrng.fill() + + +The single threaded call directly uses the PRNG. + +.. ipython:: python + + values = np.empty(10000000) + rg = Xorshift1024().generator + %timeit rg.standard_normal(out=values) + +The gains are substantial and the scaling is reasonable even for large that +are only moderately large. The gains are even larger when compared to a call +that does not use an existing array due to array creation overhead. + +.. ipython:: python + + rg = Xorshift1024().generator + %timeit rg.standard_normal(10000000) diff --git a/_randomgen/doc/source/new-or-different.rst b/_randomgen/doc/source/new-or-different.rst new file mode 100644 index 000000000000..7fb70ed1ab66 --- /dev/null +++ b/_randomgen/doc/source/new-or-different.rst @@ -0,0 +1,95 @@ +.. _new-or-different: + +What's New or Different +----------------------- + +.. warning:: + + The Box-Muller method used to produce NumPy's normals is no longer available. + It is not possible to exactly reproduce the random values produced from NumPy + for the normal distribution or any other distribution that relies on the + normal such as the gamma or student's t. + + +* :func:`~randomgen.entropy.random_entropy` provides access to the system + source of randomness that is used in cryptographic applications (e.g., + ``/dev/urandom`` on Unix). +* Simulate from the complex normal distribution + (:meth:`~randomgen.generator.RandomGenerator.complex_normal`) +* The normal, exponential and gamma generators use 256-step Ziggurat + methods which are 2-10 times faster than NumPy's default implementation in + :meth:`~randomgen.generator.RandomGenerator.standard_normal`, + :meth:`~randomgen.generator.RandomGenerator.standard_exponential` or + :meth:`~randomgen.generator.RandomGenerator.standard_gamma`. +* The Box-Muller used to produce NumPy's normals is no longer available. +* All basic random generators functions to produce doubles, uint64s and + uint32s via CTypes (:meth:`~randomgen.xoroshiro128.Xoroshiro128.ctypes`) + and CFFI (:meth:`~randomgen.xoroshiro128.Xoroshiro128.cffi`). This allows + these basic RNGs to be used in numba. +* The basic random number generators can be used in downstream projects via + Cython. + +.. ipython:: python + + from randomgen import Xoroshiro128 + rg = Xoroshiro128().generator + %timeit rg.standard_normal(1000000) + from numpy.random import standard_normal + %timeit standard_normal(1000000) + +.. ipython:: python + + from randomgen import Xoroshiro128 + rg = Xoroshiro128().generator + %timeit rg.standard_exponential(1000000) + from numpy.random import standard_exponential + %timeit standard_exponential(1000000) + +.. ipython:: python + + from randomgen import Xoroshiro128 + rg = Xoroshiro128().generator + %timeit rg.standard_gamma(3.0, 1000000) + from numpy.random import standard_gamma + %timeit standard_gamma(3.0, 1000000) + +* Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64`` + to produce either single or double prevision uniform random variables for + select distributions + + * Uniforms (:meth:`~randomgen.generator.RandomGenerator.random_sample` and + :meth:`~randomgen.generator.RandomGenerator.rand`) + * Normals (:meth:`~randomgen.generator.RandomGenerator.standard_normal` and + :meth:`~randomgen.generator.RandomGenerator.randn`) + * Standard Gammas (:meth:`~randomgen.generator.RandomGenerator.standard_gamma`) + * Standard Exponentials (:meth:`~randomgen.generator.RandomGenerator.standard_exponential`) + +.. ipython:: python + + from randomgen import Xoroshiro128 + rg = Xoroshiro128().generator + rg.seed(0) + rg.random_sample(3, dtype='d') + rg.seed(0) + rg.random_sample(3, dtype='f') + +* Optional ``out`` argument that allows existing arrays to be filled for + select distributions + + * Uniforms (:meth:`~randomgen.generator.RandomGenerator.random_sample`) + * Normals (:meth:`~randomgen.generator.RandomGenerator.standard_normal`) + * Standard Gammas (:meth:`~randomgen.generator.RandomGenerator.standard_gamma`) + * Standard Exponentials (:meth:`~randomgen.generator.RandomGenerator.standard_exponential`) + + This allows multithreading to fill large arrays in chunks using suitable + PRNGs in parallel. + +.. ipython:: python + + from randomgen import Xoroshiro128 + rg = Xoroshiro128(0).generator + existing = np.zeros(4) + rg.random_sample(out=existing[:2]) + print(existing) + +.. * For changes since the previous release, see the :ref:`change-log` diff --git a/_randomgen/doc/source/parallel.rst b/_randomgen/doc/source/parallel.rst new file mode 100644 index 000000000000..df6f58d75a9b --- /dev/null +++ b/_randomgen/doc/source/parallel.rst @@ -0,0 +1,141 @@ +Parallel Random Number Generation +================================= + +There are three strategies implemented that can be used to produce +repeatable pseudo-random numbers across multiple processes (local +or distributed). + +.. _independent-streams: + +Independent Streams +------------------- + +:class:`~randomgen.pcg64.PCG64`, :class:`~randomgen.threefry.ThreeFry` +and :class:`~randomgen.philox.Philox` support independent streams. This +example shows how many streams can be created by passing in different index +values in the second input while using the same seed in the first. + +.. code-block:: python + + from randomgen.entropy import random_entropy + from randomgen import PCG64 + + entropy = random_entropy(4) + # 128-bit number as a seed + seed = sum([int(entropy[i]) * 2 ** (32 * i) for i in range(4)]) + streams = [PCG64(seed, stream) for stream in range(10)] + + +:class:`~randomgen.philox.Philox` and :class:`~randomgen.threefry.ThreeFry` are +counter-based RNGs which use a counter and key. Different keys can be used +to produce independent streams. + +.. code-block:: python + + import numpy as np + from randomgen import ThreeFry + + key = random_entropy(8) + key = key.view(np.uint64) + key[0] = 0 + step = np.zeros(4, dtype=np.uint64) + step[0] = 1 + streams = [ThreeFry(key=key + stream * step) for stream in range(10)] + +.. _jump-and-advance: + +Jump/Advance the PRNG state +--------------------------- + +Jump +**** + +``jump`` advances the state of the PRNG *as-if* a large number of random +numbers have been drawn. The specific number of draws varies by PRNG, and +ranges from :math:`2^{64}` to :math:`2^{512}`. Additionally, the *as-if* +draws also depend on the size of the default random number produced by the +specific PRNG. The PRNGs that support ``jump``, along with the period of +the PRNG, the size of the jump and the bits in the default unsigned random +are listed below. + ++-----------------+-------------------------+-------------------------+-------------------------+ +| PRNG | Period | Jump Size | Bits | ++=================+=========================+=========================+=========================+ +| DSFMT | :math:`2^{19937}` | :math:`2^{128}` | 53 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| MT19937 | :math:`2^{19937}` | :math:`2^{128}` | 32 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| PCG64 | :math:`2^{128}` | :math:`2^{64}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| Philox | :math:`2^{256}` | :math:`2^{128}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| Xoroshiro128 | :math:`2^{128}` | :math:`2^{64}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ + +``jump`` can be used to produce long blocks which should be long enough to not +overlap. + +.. code-block:: python + + from randomgen.entropy import random_entropy + from randomgen import Xorshift1024 + + entropy = random_entropy(2).astype(np.uint64) + # 64-bit number as a seed + seed = entropy[0] * 2**32 + entropy[1] + blocked_rng = [] + for i in range(10): + rng = Xorshift1024(seed) + rng.jump(i) + blocked_rng.append(rng) + + +Advance +******* +``advance`` can be used to jump the state an arbitrary number of steps, and so +is a more general approach than ``jump``. :class:`~randomgen.pcg64.PCG64`, +:class:`~randomgen.threefry.ThreeFry` and :class:`~randomgen.philox.Philox` +support ``advance``, and since these also support independent +streams, it is not usually necessary to use ``advance``. + +Advancing a PRNG updates the underlying PRNG state as-if a given number of +calls to the underlying PRNG 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 PRNG. +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 + PRNG 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 + PRNG. For example, two 16-bit integer values can be simulated + from a single draw of a 32-bit PRNG. + +Advancing the PRNG state resets any pre-computed random numbers. This is +required to ensure exact reproducibility. + +This example uses ``advance`` to advance a :class:`~randomgen.pcg64.PCG64` +generator 2 ** 127 steps to set a sequence of random number generators. + +.. code-block:: python + + from randomgen import PCG64 + brng = PCG64() + brng_copy = PCG64() + brng_copy.state = brng.state + + advance = 2**127 + brngs = [brng] + for _ in range(9): + brng_copy.advance(advance) + brng = PCG64() + brng.state = brng_copy.state + brngs.append(brng) + +.. end block + diff --git a/_randomgen/doc/source/performance.py b/_randomgen/doc/source/performance.py new file mode 100644 index 000000000000..d84c3147e398 --- /dev/null +++ b/_randomgen/doc/source/performance.py @@ -0,0 +1,73 @@ +import numpy as np +from timeit import timeit, repeat +import pandas as pd + +from randomgen import MT19937, DSFMT, ThreeFry, PCG64, Xoroshiro128, \ + Xorshift1024, Philox + +PRNGS = [DSFMT, MT19937, Philox, PCG64, ThreeFry, Xoroshiro128, Xorshift1024] + +funcs = {'32-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', + '64-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', + 'Uniforms': 'random_sample(size=1000000)', + 'Complex Normals': 'complex_normal(size=1000000)', + 'Normals': 'standard_normal(size=1000000)', + 'Exponentials': 'standard_exponential(size=1000000)', + 'Gammas': 'standard_gamma(3.0,size=1000000)', + 'Binomials': 'binomial(9, .1, size=1000000)', + 'Laplaces': 'laplace(size=1000000)', + 'Poissons': 'poisson(3.0, size=1000000)', } + +setup = """ +from randomgen import {prng} +rg = {prng}().generator +""" + +test = "rg.{func}" +table = {} +for prng in PRNGS: + print(prng) + col = {} + for key in funcs: + t = repeat(test.format(func=funcs[key]), + setup.format(prng=prng().__class__.__name__), + number=1, repeat=3) + col[key]= 1000 * min(t) + col = pd.Series(col) + table[prng().__class__.__name__] = col + + +npfuncs = {} +npfuncs.update(funcs) +npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)' +npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)' +del npfuncs['Complex Normals'] +setup = """ +from numpy.random import RandomState +rg = RandomState() +""" +col = {} +for key in npfuncs: + t = repeat(test.format(func=npfuncs[key]), + setup.format(prng=prng().__class__.__name__), + number=1, repeat=3) + col[key] = 1000 * min(t) +table['NumPy'] = pd.Series(col) + + +table = pd.DataFrame(table) +table = table.reindex(table.mean(1).sort_values().index) +order = np.log(table).mean().sort_values().index +table = table.T +table = table.reindex(order) +table = table.T +print(table.to_csv(float_format='%0.1f')) + +rel = table / (table.iloc[:,[0]].values @ np.ones((1,8))) +rel.pop(rel.columns[0]) +rel = rel.T +rel['Overall'] = np.exp(np.log(rel).mean(1)) +rel *= 100 +rel = np.round(rel) +rel = rel.T +print(rel.to_csv(float_format='%0d')) \ No newline at end of file diff --git a/_randomgen/doc/source/performance.rst b/_randomgen/doc/source/performance.rst new file mode 100644 index 000000000000..2dfb32101c5e --- /dev/null +++ b/_randomgen/doc/source/performance.rst @@ -0,0 +1,75 @@ +Performance +----------- + +.. py:module:: randomgen + +Recommendation +************** +The recommended generator for single use is +:class:`~randomgen.xoroshiro128.Xoroshiro128`. The recommended generator +for use in large-scale parallel applications is +:class:`~randomgen.xorshift1024.Xorshift1024` +where the `jump` method is used to advance the state. For very large scale +applications -- requiring 1,000+ independent streams, +:class:`~randomgen.pcg64.PCG64` or :class:`~randomgen.threefry.ThreeFry` are +the best choices. + +Timings +******* + +The timings below are the time in ms to produce 1,000,000 random values from a +specific distribution. :class:`~randomgen.xoroshiro128.Xoroshiro128` is the +fastest, followed by :class:`~randomgen.xorshift1024.Xorshift1024` and +:class:`~randomgen.pcg64.PCG64`. The original :class:`~randomgen.mt19937.MT19937` +generator is much slower since it requires 2 32-bit values to equal the output +of the faster generators. + +Integer performance has a similar ordering although `dSFMT` is slower since +it generates 53-bit floating point values rather than integer values. On the +other hand, it is very fast for uniforms, although slower than `xoroshiro128+`. + +The pattern is similar for other, more complex generators. The normal +performance of NumPy's MT19937 is much lower than the other since it +uses the Box-Muller transformation rather than the Ziggurat generator. The +performance gap for Exponentials is also large due to the cost of computing +the log function to invert the CDF. + +.. csv-table:: + :header: ,Xoroshiro128,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy + :widths: 14,14,14,14,14,14,14,14,14 + + 32-bit Unsigned Ints,3.0,3.0,3.0,3.5,3.7,6.8,6.6,3.3 + 64-bit Unsigned Ints,2.6,3.0,3.1,3.4,3.8,6.9,6.6,8.8 + Uniforms,3.2,3.8,4.4,5.0,7.4,8.9,9.9,8.8 + Normals,11.0,13.9,13.7,15.8,16.9,17.8,18.8,63.0 + Exponentials,7.0,8.4,9.0,11.2,12.5,14.1,15.0,102.2 + Binomials,20.9,22.6,22.0,21.2,26.7,27.7,29.2,26.5 + Complex Normals,23.2,28.7,29.1,33.2,35.4,37.6,38.6, + Gammas,35.3,38.6,39.2,41.3,46.7,49.4,51.2,98.8 + Laplaces,97.8,99.9,99.8,96.2,104.1,104.6,104.8,104.1 + Poissons,104.8,113.2,113.3,107.6,129.7,135.6,138.1,131.9 + + +The next table presents the performance relative to `xoroshiro128+` in +percentage. The overall performance was computed using a geometric mean. + +.. csv-table:: + :header: ,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy + :widths: 14,14,14,14,14,14,14,14 + + 32-bit Unsigned Ints,102,99,118,125,229,221,111 + 64-bit Unsigned Ints,114,116,129,143,262,248,331 + Uniforms,116,137,156,231,275,306,274 + Normals,126,124,143,153,161,170,572 + Exponentials,121,130,161,179,203,215,1467 + Binomials,108,105,101,128,133,140,127 + Complex Normals,124,125,143,153,162,166, + Gammas,109,111,117,132,140,145,280 + Laplaces,102,102,98,106,107,107,106 + Poissons,108,108,103,124,129,132,126 + Overall,113,115,125,144,172,177,251 + + +.. note:: + + All timings were taken using Linux on a i5-3570 processor. diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index 5c979e6e8040..cec90994346c 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -131,7 +131,7 @@ cdef class DSFMT: ---------- .. [1] Mutsuo Saito and Makoto Matsumoto, "SIMD-oriented Fast Mersenne Twister: a 128-bit Pseudorandom Number Generator." Monte Carlo - and Quasi-Monte Carlo Methods 2006, Springer, pp. 607 -- 622, 2008. + and Quasi-Monte Carlo Methods 2006, Springer, pp. 607--622, 2008. .. [2] 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. @@ -237,9 +237,9 @@ cdef class DSFMT: obj.data, np.PyArray_DIM(obj, 0)) - def jump(self, np.npy_intp iter): + def jump(self, np.npy_intp iter=1): """ - jump(iter = 1) + jump(iter=1) Jumps the state of the random number generator as-if 2**128 random numbers have been generated. diff --git a/_randomgen/examples/cython/extending.pyx b/_randomgen/randomgen/examples/cython/extending.pyx similarity index 100% rename from _randomgen/examples/cython/extending.pyx rename to _randomgen/randomgen/examples/cython/extending.pyx diff --git a/_randomgen/examples/cython/extending_distributions.pyx b/_randomgen/randomgen/examples/cython/extending_distributions.pyx similarity index 51% rename from _randomgen/examples/cython/extending_distributions.pyx rename to _randomgen/randomgen/examples/cython/extending_distributions.pyx index a5fea174aa49..630d952bf75e 100644 --- a/_randomgen/examples/cython/extending_distributions.pyx +++ b/_randomgen/randomgen/examples/cython/extending_distributions.pyx @@ -3,6 +3,7 @@ cimport numpy as np cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from randomgen.common cimport * +from randomgen.distributions cimport random_gauss_zig from randomgen.xoroshiro128 import Xoroshiro128 @cython.boundscheck(False) @@ -23,3 +24,25 @@ def normals_zig(Py_ssize_t 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 brng_t *rng + cdef const char *capsule_name = "BasicRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + # Optional check that the capsule if from a Basic RNG + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + # Cast the pointer + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + for i in range(n): + # Call the function + random_values[i] = rng.next_double(rng.state) + randoms = np.asarray(random_values) + return randoms \ No newline at end of file diff --git a/_randomgen/examples/cython/setup.py b/_randomgen/randomgen/examples/cython/setup.py similarity index 100% rename from _randomgen/examples/cython/setup.py rename to _randomgen/randomgen/examples/cython/setup.py diff --git a/_randomgen/examples/numba/extending.py b/_randomgen/randomgen/examples/numba/extending.py similarity index 52% rename from _randomgen/examples/numba/extending.py rename to _randomgen/randomgen/examples/numba/extending.py index 198c39a29297..09e07a437674 100644 --- a/_randomgen/examples/numba/extending.py +++ b/_randomgen/randomgen/examples/numba/extending.py @@ -1,7 +1,8 @@ -from randomgen import Xoroshiro128 import numpy as np import numba as nb +from randomgen import Xoroshiro128 + x = Xoroshiro128() f = x.ctypes.next_uint32 s = x.ctypes.state @@ -35,7 +36,6 @@ def bounded_uints(lb, ub, n, state): bounded_uints(323, 2394691, 10000000, s.value) - g = x.cffi.next_double cffi_state = x.cffi.state state_addr = x.cffi.state_address @@ -43,33 +43,35 @@ def bounded_uints(lb, ub, n, state): def normals(n, state): out = np.empty(n) - for i in range(n//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 - out[2*i+1] = f*x2 - - if n % 2 == 1: - x1 = 2.0*g(state) - 1.0 - x2 = 2.0*g(state) - 1.0 - r2 = x1*x1 + x2*x2 + 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[n] = f*x1 + 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) +import datetime as dt + +start = dt.datetime.now() +normalsj(1000000, state_addr) +ms = 1000 * (dt.datetime.now() - start).total_seconds() +print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms in ' + '{ms:0.1f}ms'.format(ms=ms)) + +import numpy as np -print(normalsj(10000000, state_addr).var()) +start = dt.datetime.now() +np.random.standard_normal(1000000) +ms = 1000 * (dt.datetime.now() - start).total_seconds() +print('1,000,000 Box-Muller (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms)) diff --git a/_randomgen/examples/numba/extending_distributions.py b/_randomgen/randomgen/examples/numba/extending_distributions.py similarity index 94% rename from _randomgen/examples/numba/extending_distributions.py rename to _randomgen/randomgen/examples/numba/extending_distributions.py index 07cb074a3177..47f811c06d54 100644 --- a/_randomgen/examples/numba/extending_distributions.py +++ b/_randomgen/randomgen/examples/numba/extending_distributions.py @@ -4,20 +4,22 @@ 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/ +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/ +move distributions.dll ../../examples/numba/ """ import os + +import numba as nb import numpy as np from cffi import FFI + from randomgen import Xoroshiro128 -import numba as nb ffi = FFI() if os.path.exists('./distributions.dll'): @@ -46,7 +48,6 @@ def normals(n, brng): normalsj = nb.jit(normals, nopython=True) - # Numba requires a memory address for void * # Can also get address from x.ctypes.brng.value brng_address = int(ffi.cast('uintptr_t', brng)) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 0d988f678295..3c5006b6d8a8 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -38,18 +38,55 @@ _randint_types = {'bool': (0, 2), cdef class RandomGenerator: """ - Prototype Random Generator that consumes randoms from a Basic RNG class + RandomGenerator(brng=None) + + Container for the Basic Random Number Generators. + + ``RandomGenerator`` 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. + + **No Compatibility Guarantee** + + ``RandomGenerator`` is evolving and so it isn't possible to provide a + compatibility guarantee like NumPy does. In particular, better algorithms + have already been added. This will change once ``RandomGenerator`` + stabilizes. Parameters ---------- - brng : BasicRNG, optional - Object exposing a PyCapsule containing state and function pointers + brng : Basic RNG, optional + Basic RNG to use as the core generator. If none is provided, uses + Xoroshiro128. + + Notes + ----- + The Python stdlib module "random" contains pseudo-random number generator + with a number of methods that are similar to the ones available in + ``RandomGenerator``. It uses Mersenne Twister, and this basic RNG can be + accessed using ``MT19937``. ``RandomGenerator``, besides being + NumPy-aware, has the advantage that it provides a much larger number + of probability distributions to choose from. Examples -------- - >>> from randomgen.generator import RandomGenerator + >>> from randomgen import RandomGenerator >>> rg = RandomGenerator() >>> rg.standard_normal() + + Using a specific generator + + >>> from randomgen import MT19937 + >>> rg = RandomGenerator(MT19937()) + + The generator is also directly avialable from basic RNGs + + >>> rg = MT19937().generator + >>> rg.standard_normal() """ cdef public object _basicrng cdef brng_t *_brng @@ -93,14 +130,25 @@ cdef class RandomGenerator: def seed(self, *args, **kwargs): """ - TODO: Should this remain + Reseed the basic RNG. + + Parameters depend on the basic RNG used. """ + # TODO: Should this remain self._basicrng.seed(*args, **kwargs) return self @property def state(self): - """Get or set the underlying PRNG's state""" + """ + Get or set the Basic RNG's state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the Basic RNG + """ return self._basicrng.state @state.setter diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index 483bd6baa107..c66f89a03e95 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -6,6 +6,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport brng_t import randomgen.pickle @@ -57,6 +58,9 @@ cdef class MT19937: cdef mt19937_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) @@ -69,6 +73,10 @@ cdef class MT19937: self._brng.next_double = &mt19937_double self._brng.next_raw = &mt19937_raw + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = "BasicRNG" self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -199,3 +207,88 @@ cdef class MT19937: for i in range(624): self.rng_state.key[i] = key[i] self.rng_state.pos = value['state']['pos'] + + @property + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&mt19937_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&mt19937_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&mt19937_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index d0b57a2b0562..a2cb4c71ec23 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -4,6 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport brng_t from randomgen.entropy import random_entropy @@ -46,22 +47,80 @@ cdef uint64_t pcg32_raw(void* st) nogil: cdef class PCG32: - """ - Prototype Basic RNG using pcg64 + u""" + PCG32(seed=None, inc=0) + + Container for the PCG-32 pseudo-random number generator. + + PCG-32 is a 64-bit implementation of O'Neill's permutation congruential + generator ([1]_, [2]_). PCG-32 has a period of :math:`2^{64}` and supports + advancing an arbitrary number of steps as well as :math:`2^{63}` streams. + + ``PCG32`` exposes no user-facing API except ``generator``,``state``, + ``cffi`` and ``ctypes``. Designed for use in a ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``PCG32`` makes a guarantee that a fixed seed will always produce the same + results. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, long}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64] or ``None`` (the default). + If `seed` is ``None``, then ``PCG32`` will try to read data + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + inc : {None, int}, optional + Stream to return. + Can be an integer in [0, 2**64] or ``None`` (the default). If `inc` is + ``None``, then 0 is used. Can be used with the same seed to + produce multiple streams using other values of inc. Notes ----- - Exposes no user-facing API except `get_state` and `set_state`. Designed - for use in a `RandomGenerator` object. + Supports the method advance to advance the PRNG an arbitrary number of + steps. The state of the PCG-32 PRNG is represented by 2 128-bit unsigned + integers. + + See ``PCG32`` for a similar implementation with a smaller period. + + **Parallel Features** + + ``PCG32`` can be used in parallel applications in one of two ways. + The preferable method is to use sub-streams, which are generated by using the + same value of ``seed`` and incrementing the second value, ``inc``. + + >>> from randomgen import RandomGenerator, PCG32 + >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] + + The alternative method is to call ``advance`` on a single RandomState to + produce non-overlapping sequences. + + >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] + >>> for i in range(10): + ... rg[i].advance(i * 2**32) + + **State and Seeding** + + The ``PCG32`` state vector consists of 2 unsigned 64-bit values/ + ``PCG32`` is seeded using a single 64-bit unsigned integer. In addition, + a second 64-bit unsigned integer is used to set the 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" """ cdef pcg32_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg32_state)) @@ -75,6 +134,10 @@ cdef class PCG32: self._brng.next_double = &pcg32_double self._brng.next_raw = &pcg32_raw + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = "BasicRNG" self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -133,7 +196,7 @@ cdef class PCG32: def seed(self, seed=None, inc=0): """ - seed(seed=None, stream=None) + seed(seed=None, inc=0) Seed the generator. @@ -152,7 +215,6 @@ cdef class PCG32: ------ ValueError If seed values are out of range for the PRNG. - """ ub = 2 ** 64 if seed is None: @@ -182,7 +244,15 @@ cdef class PCG32: @property def state(self): - """Get or set the PRNG state""" + """ + Get or set the PRNG state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the PRNG + """ return {'brng': self.__class__.__name__, 'state': {'state': self.rng_state.pcg_state.state, 'inc':self.rng_state.pcg_state.inc}} @@ -198,9 +268,141 @@ cdef class PCG32: self.rng_state.pcg_state.state = value['state']['state'] self.rng_state.pcg_state.inc = value['state']['inc'] - def advance(self, step): - pcg32_advance_state(self.rng_state, step) + 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 : PCG32 + 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. + """ + pcg32_advance_state(self.rng_state, delta) return self - def jump(self): - return self.advance(2**32) + def jump(self, np.npy_intp iter=1): + """ + jump(iter=1) + + Jumps the state as-if 2**32 random numbers have been generated + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : PCG32 + RNG jumped iter times + """ + return self.advance(iter * 2**32) + + @property + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&pcg32_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&pcg32_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&pcg32_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index 7afe1266d9f5..bd3a24440c44 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -4,6 +4,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np +from common import interface from common cimport * from distributions cimport brng_t from randomgen.entropy import random_entropy @@ -61,22 +62,82 @@ cdef double pcg64_double(void* st) nogil: return uint64_to_double(pcg64_next64(st)) cdef class PCG64: - """ - Prototype Basic RNG using pcg64 + u""" + PCG64(seed=None, inc=0) + + Container for the PCG-64 pseudo-random number generator. + + 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. + + ``PCG64`` exposes no user-facing API except ``generator``,``state``, + ``cffi`` and ``ctypes``. Designed for use in a ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``PCG64`` makes a guarantee that a fixed seed will always produce the same + results. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, long}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**128] or ``None`` (the default). + If `seed` is ``None``, then ``PCG64`` will try to read data + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + inc : {None, int}, optional + Stream to return. + Can be an integer in [0, 2**128] or ``None`` (the default). If `inc` is + ``None``, then 0 is used. Can be used with the same seed to + produce multiple streams using other values of inc. Notes ----- - Exposes no user-facing API except `get_state` and `set_state`. Designed - for use in a `RandomGenerator` object. + Supports the method 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. + + See ``PCG32`` for a similar implementation with a smaller period. + + **Parallel Features** + + ``PCG64`` can be used in parallel applications in one of two ways. + The preferable method is to use sub-streams, which are generated by using the + same value of ``seed`` and incrementing the second value, ``inc``. + + >>> from randomgen import RandomGenerator, PCG64 + >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] + + The alternative method is to call ``advance`` on a single RandomState to + produce non-overlapping sequences. + + >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] + >>> for i in range(10): + ... rg[i].advance(i * 2**64) + + **State and Seeding** + + The ``PCG64`` state vector consists of 2 unsigned 128-bit values, + which are represented externally as python longs (2.x) or ints (Python 3+). + ``PCG64`` is seeded using a single 128-bit unsigned integer + (Python long/int). In addition, a second 128-bit unsigned integer is used + to set the 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" """ cdef pcg64_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg64_state)) @@ -90,6 +151,10 @@ cdef class PCG64: self._brng.next_double = &pcg64_double self._brng.next_raw = &pcg64_uint64 + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = "BasicRNG" self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -115,7 +180,7 @@ cdef class PCG64: def __random_integer(self, bits=64): """ - 64-bit Random Integers from the PRNG + 64-bit Random Integers from the RNG Parameters ---------- @@ -152,7 +217,7 @@ cdef class PCG64: def seed(self, seed=None, inc=0): """ - seed(seed=None, stream=None) + seed(seed=None, inc=0) Seed the generator. @@ -170,7 +235,7 @@ cdef class PCG64: Raises ------ ValueError - If seed values are out of range for the PRNG. + If seed values are out of range for the RNG. """ cdef np.ndarray _seed, _inc @@ -207,7 +272,15 @@ cdef class PCG64: @property def state(self): - """Get or set the PRNG state""" + """ + Get or set the RNG state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the RNG + """ IF PCG_EMULATED_MATH==1: state = 2 **64 * self.rng_state.pcg_state.state.high state += self.rng_state.pcg_state.state.low @@ -229,7 +302,7 @@ cdef class PCG64: brng = value.get('brng', '') if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' - 'PRNG'.format(self.__class__.__name__)) + 'RNG'.format(self.__class__.__name__)) IF PCG_EMULATED_MATH==1: self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 @@ -242,12 +315,153 @@ cdef class PCG64: self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] - def advance(self, step): - cdef np.ndarray delta = np.empty(2,dtype=np.uint64) - delta[0] = step // 2**64 - delta[1] = step % 2**64 - pcg64_advance(self.rng_state, delta.data) + 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. + """ + 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, d.data) + self._reset_state_variables() return self - def jump(self): - return self.advance(2**64) + def jump(self, np.npy_intp iter=1): + """ + jump(iter=1) + + Jumps the state as-if 2**64 random numbers have been generated + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : PCG64 + RNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is required + to ensure exact reproducibility. + """ + return self.advance(iter * 2**64) + + @property + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&pcg64_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&pcg64_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&pcg64_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator using this instance as the core RNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index a61f785331b4..75213ef5aa58 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -3,6 +3,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np +from common import interface from common cimport * from distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array @@ -52,21 +53,115 @@ cdef double philox_double(void*st) nogil: cdef class Philox: """ - Prototype Basic RNG using philox + Philox(seed=None, counter=None, key=None) + + Container for the Philox (4x64) pseudo-random number generator. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + data will be read from ``/dev/urandom`` (or the Windows analog) + if available. If unavailable, a hash of the time and process ID is + used. + 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, which is run through + another RNG before use, the value in key is directly set. Can be either + a Python int (long in 2.x) in [0, 2**128) or a 2-element uint64 array. + key and seed cannot both be used. Notes ----- - Exposes no user-facing API except `state`. Designed for use in - a `RandomGenerator` object. + 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`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``Philox`` guarantees that a fixed seed will always produce the + same results. + + See ``Philox`` for a closely related PRNG implementation. + + **Parallel Features** + + ``Philox`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{128}` random numbers have been generated. Alternatively, + ``advance`` can be used to advance the counter for an abritrary number of + positive steps in [0, 2**256). When using ``jump``, all generators should + be initialized with the same seed to ensure that the segments come from + the same sequence. Alternatively, ``Philox`` can be used + in parallel applications by using a sequence of distinct keys where each + instance uses different key. + + >>> from randomgen import RandomGenerator, Philox + >>> rg = [RandomGenerator(Philox(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + Using distinct keys produces independent streams + + >>> key = 2**196 + 2**132 + 2**65 + 2**33 + 2**17 + 2**9 + >>> rg = [RandomGenerator(Philox(key=key+i)) for i in range(10)] + + **State and Seeding** + + The ``Philox`` state vector consists of a 256-bit counter encoded as a + 4-element uint64 array and a 128-bit key encoded as a 2-element uint64 + array. The counter is incremented by 1 for every 4 64-bit randoms + produced. The key determines the sequence produced. Using different + keys produces independent sequences. + + ``Philox`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for another simple random number generator, + Splitmix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. When using an array, the SplitMix64 state + for producing the ith component of the initial state is XORd with the ith + value of the seed array until the seed array is exhausted. When using an array + the initial state for the SplitMix64 state is 0 so that using a single element + array and using the same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from randomgen import RandomGenerator, Philox + >>> rg = RandomGenerator(Philox(1234)) + >>> rg.standard_normal() + + Identical method using only Philox + + >>> rg = Philox(1234).generator + >>> rg.standard_normal() + + 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 brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(philox_state)) @@ -83,6 +178,10 @@ cdef class Philox: self._brng.next_double = &philox_double self._brng.next_raw = &philox_uint64 + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = 'BasicRNG' self.capsule = PyCapsule_New( self._brng, name, NULL) @@ -111,31 +210,6 @@ cdef class Philox: for i in range(PHILOX_BUFFER_SIZE): self.rng_state.buffer[i] = 0 - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i if method==u'uint64': @@ -205,7 +279,15 @@ cdef class Philox: @property def state(self): - """Get or set the PRNG state""" + """ + 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) @@ -243,14 +325,152 @@ cdef class Philox: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self): - """Jump the state as-if 2**128 draws have been made""" - return self.advance(2**128) + def jump(self, np.npy_intp iter): + """ + jump(iter=1) + + Jumps the state of the random number generator as-if 2**128 random + numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. - def advance(self, step): - """Advance the state as-if a specific number of draws have been made""" - cdef np.ndarray step_a - step_a = int_to_array(step, 'step', 256, 64) - loc = 0 - philox_advance( step_a.data, self.rng_state) + Returns + ------- + self : Philox + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is + required to ensure exact reproducibility. + """ + return self.advance(iter * 2 ** 128) + + 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. + """ + cdef np.ndarray delta_a + delta_a = int_to_array(delta, 'step', 256, 64) + philox_advance( delta_a.data, self.rng_state) + self._reset_state_variables() return self + + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&philox_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&philox_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&philox_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index 1bffe3f78fb3..c4673c2d2306 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -4,7 +4,7 @@ import pytest from randomgen import RandomGenerator, MT19937 - +import randomgen def compare_0_input(f1, f2): inputs = [(tuple([]), {}), (tuple([]), {'size': 10}), @@ -532,11 +532,11 @@ def test_dir(self): nprs_d.difference_update(excluded) assert (len(nprs_d.difference(rs_d)) == 0) - # npmod = dir(numpy.random) - # mod = dir(randomstate) - # known_exlcuded = ['__all__', 'Tester', 'info', 'bench', - # '__RandomState_ctor', 'mtrand', 'test', - # '__warningregistry__', '_numpy_tester'] - # mod += known_exlcuded - # diff = set(npmod).difference(mod) - # assert_equal(len(diff), 0) + npmod = dir(numpy.random) + mod = dir(randomgen) + known_exlcuded = ['__all__', 'Tester', 'info', 'bench', + '__RandomState_ctor', 'mtrand', 'test', + '__warningregistry__', '_numpy_tester'] + mod += known_exlcuded + diff = set(npmod).difference(mod) + assert_equal(len(diff), 0) diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index ffcc754171f0..47dde07e0bd2 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -3,6 +3,7 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np +from common import interface from common cimport * from distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array @@ -48,21 +49,116 @@ cdef double threefry_double(void* st) nogil: cdef class ThreeFry: """ - Prototype Basic RNG using threefry + ThreeFry(seed=None, counter=None, key=None) + + Container for the ThreeFry (4x64) pseudo-random number generator. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + data will be read from ``/dev/urandom`` (or the Windows analog) + if available. If unavailable, a hash of the time and process ID is + used. + counter : {None, int, array_like}, optional + Counter to use in the ThreeFry 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 ThreeFry state. Unlike seed, which is run through + another RNG before use, the value in key is directly set. Can be either + a Python int (long in 2.x) in [0, 2**256) or a 4-element uint64 array. + key and seed cannot both be used. Notes ----- - Exposes no user-facing API except `state`. Designed for use in - a `RandomGenerator` object. + ThreeFry 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. ThreeFry 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. + + ``ThreeFry`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``ThreeFry`` guarantees that a fixed seed will always produce the + same results. + + See ``Philox`` for a closely related PRNG implementation. + + **Parallel Features** + + ``ThreeFry`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{128}` random numbers have been generated. Alternatively, + ``advance`` can be used to advance the counter for an abritrary number of + positive steps in [0, 2**256). When using ``jump``, all generators should + be initialized with the same seed to ensure that the segments come from + the same sequence. Alternatively, ``ThreeFry`` can be used + in parallel applications by using a sequence of distinct keys where each + instance uses different key. + + >>> from randomgen import RandomGenerator, ThreeFry + >>> rg = [RandomGenerator(ThreeFry(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + Using distinct keys produces independent streams + + >>> key = 2**196 + 2**132 + 2**65 + 2**33 + 2**17 + 2**9 + >>> rg = [RandomGenerator(ThreeFry(key=key+i)) for i in range(10)] + + **State and Seeding** + + The ``ThreeFry`` state vector consists of a 2 256-bit values encoded as + 4-element uint64 arrays. One 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. + + ``ThreeFry`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for another simple random number generator, + Splitmix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. When using an array, the SplitMix64 state + for producing the ith component of the initial state is XORd with the ith + value of the seed array until the seed array is exhausted. When using an array + the initial state for the SplitMix64 state is 0 so that using a single element + array and using the same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from randomgen import RandomGenerator, ThreeFry + >>> rg = RandomGenerator(ThreeFry(1234)) + >>> rg.standard_normal() + + Identical method using only ThreeFry + + >>> rg = ThreeFry(1234).generator + >>> rg.standard_normal() + + 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 threefry_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator + def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry_state)) @@ -77,6 +173,10 @@ cdef class ThreeFry: self._brng.next_double = &threefry_double self._brng.next_raw = &threefry_uint64 + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = 'BasicRNG' self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -105,31 +205,6 @@ cdef class ThreeFry: for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i if method==u'uint64': @@ -155,12 +230,13 @@ cdef class ThreeFry: ---------- seed : int, optional Seed for ``RandomState``. - counter : {int array}, optional + counter : {None, int array}, optional Positive integer less than 2**256 containing the counter position or a 4 element array of uint64 containing the counter - key : {int, array}, options + key : {None, int, array}, optional Positive integer less than 2**256 containing the key - or a 4 element array of uint64 containing the key + or a 4 element array of uint64 containing the key. key and + seed cannot be simultaneously used. Raises ------ @@ -199,7 +275,15 @@ cdef class ThreeFry: @property def state(self): - """Get or set the PRNG state""" + """ + 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(4, dtype=np.uint64) buffer = np.empty(THREEFRY_BUFFER_SIZE, dtype=np.uint64) @@ -233,14 +317,153 @@ cdef class ThreeFry: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self): - """Jump the state as-if 2**128 draws have been made""" - return self.advance(2**128) + def jump(self, np.npy_intp iter): + """ + jump(iter=1) + + Jumps the state of the random number generator as-if 2**128 random + numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : ThreeFry + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is + required to ensure exact reproducibility. + """ + return self.advance(iter * 2**128) + + 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 : ThreeFry + RNG advanced delta steps - def advance(self, step): - """Advance the state as-if a specific number of draws have been made""" - cdef np.ndarray step_a - step_a = int_to_array(step, 'step', 256, 64) + 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. + """ + cdef np.ndarray delta_a + delta_a = int_to_array(delta, 'step', 256, 64) loc = 0 - threefry_advance(step_a.data, self.rng_state) + threefry_advance(delta_a.data, self.rng_state) + self._reset_state_variables() return self + + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&threefry_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&threefry_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&threefry_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index 86f9c4f656c3..70210910c6d0 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -1,12 +1,12 @@ -from libc.stdlib cimport malloc, free -from cpython.pycapsule cimport PyCapsule_New - import numpy as np +from cpython.pycapsule cimport PyCapsule_New +from distributions cimport brng_t +from libc.stdlib cimport malloc, free +import randomgen.pickle from common cimport * -from distributions cimport brng_t +from common import interface from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle np.import_array() @@ -51,37 +51,136 @@ cdef uint64_t threefry32_raw(void *st) nogil: cdef class ThreeFry32: """ - Prototype Basic RNG using threefry + ThreeFry32(seed=None, counter=None, key=None) + + Container for the ThreeFry (4x32) pseudo-random number generator. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + data will be read from ``/dev/urandom`` (or the Windows analog) + if available. If unavailable, a hash of the time and process ID is + used. + counter : {None, int, array_like}, optional + Counter to use in the ThreeFry32 state. Can be either + a Python int (long in 2.x) in [0, 2**128) or a 4-element uint32 array. + If not provided, the RNG is initialized at 0. + key : {None, int, array_like}, optional + Key to use in the ThreeFry32 state. Unlike seed, which is run through + another RNG before use, the value in key is directly set. Can be either + a Python int (long in 2.x) in [0, 2**128) or a 4-element uint32 array. + key and seed cannot both be used. Notes ----- - Exposes no user-facing API except `state`. Designed for use in - a `RandomGenerator` object. + ThreeFry32 is a 32-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. ThreeFry32 + has a period of :math:`2^{128} - 1` and supports arbitrary advancing and + jumping the sequence in increments of :math:`2^{64}`. These features allow + multiple non-overlapping sequences to be generated. + + ``ThreeFry32`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``ThreeFry32`` guarantees that a fixed seed will always produce the + same results. + + See ``TheeFry`` and ``Philox`` closely related PRNG implementations. + + **Parallel Features** + + ``ThreeFry32`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{64}` random numbers have been generated. Alternatively, + ``advance`` can be used to advance the counter for an arbitrary number of + positive steps in [0, 2**128). When using ``jump``, all generators should + be initialized with the same seed to ensure that the segments come from + the same sequence. Alternatively, ``ThreeFry32`` can be used + in parallel applications by using a sequence of distinct keys where each + instance uses different key. + + >>> from randomgen import RandomGenerator, ThreeFry32 + >>> rg = [RandomGenerator(ThreeFry32(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + Using distinct keys produces independent streams + + >>> key = 2**65 + 2**33 + 2**17 + 2**9 + >>> rg = [RandomGenerator(ThreeFry32(key=key+i)) for i in range(10)] + + **State and Seeding** + + The ``ThreeFry32`` state vector consists of a 2 128-bit values encoded as + 4-element uint32 arrays. One is a counter which is incremented by 1 for + every 4 32-bit randoms produced. The second is a key which determined + the sequence produced. Using different keys produces independent + sequences. + + ``ThreeFry32`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for another simple random number generator, + Splitmix64, and the output of this PRNG function is used as the initial + state. Using a single 64-bit value for the seed can only initialize a small + range of the possible initial state values. When using an array, the + SplitMix64 state for producing the ith component of the initial state is + XORd with the ith value of the seed array until the seed array is + exhausted. When using an array the initial state for the SplitMix64 state + is 0 so that using a single element array and using the same value as a + scalar will produce the same initial state. + + Examples + -------- + >>> from randomgen import RandomGenerator, ThreeFry32 + >>> rg = RandomGenerator(ThreeFry32(1234)) + >>> rg.standard_normal() + + Identical method using only ThreeFry32 + + >>> rg = ThreeFry32(1234).generator + >>> rg.standard_normal() + + 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 threefry32_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None, counter=None, key=None): - self.rng_state = malloc(sizeof(threefry32_state)) - self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) - self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) - self._brng = malloc(sizeof(brng_t)) + self.rng_state = malloc(sizeof(threefry32_state)) + self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) + self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) + self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) - self._brng.state = self.rng_state + self._brng.state = self.rng_state self._brng.next_uint64 = &threefry32_uint64 self._brng.next_uint32 = &threefry32_uint32 self._brng.next_double = &threefry32_double self._brng.next_raw = &threefry32_raw + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = 'BasicRNG' - self.capsule = PyCapsule_New(self._brng, name, NULL) + self.capsule = PyCapsule_New( self._brng, name, NULL) # Pickling support: def __getstate__(self): @@ -106,37 +205,12 @@ cdef class ThreeFry32: for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 - def __random_integer(self, bits=64): - """ - 64-bit Random Integers from the PRNG - - Parameters - ---------- - bits : {32, 64} - Number of random bits to return - - Returns - ------- - rv : int - Next random value - - Notes - ----- - Testing only - """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i - if method==u'uint64': + if method == u'uint64': for i in range(cnt): self._brng.next_uint64(self._brng.state) - elif method==u'double': + elif method == u'double': for i in range(cnt): self._brng.next_double(self._brng.state) else: @@ -200,7 +274,15 @@ cdef class ThreeFry32: @property def state(self): - """Get or set the PRNG state""" + """ + 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.uint32) key = np.empty(4, dtype=np.uint32) buffer = np.empty(THREEFRY_BUFFER_SIZE, dtype=np.uint32) @@ -209,7 +291,7 @@ cdef class ThreeFry32: key[i] = self.rng_state.key.v[i] for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] - state = {'counter':ctr,'key':key} + state = {'counter': ctr, 'key': key} return {'brng': self.__class__.__name__, 'state': state, 'buffer': buffer, @@ -224,20 +306,162 @@ cdef class ThreeFry32: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) for i in range(4): - self.rng_state.ctr.v[i] = value['state']['counter'][i] - self.rng_state.key.v[i] = value['state']['key'][i] + self.rng_state.ctr.v[i] = value['state']['counter'][i] + self.rng_state.key.v[i] = value['state']['key'][i] for i in range(THREEFRY_BUFFER_SIZE): - self.rng_state.buffer[i] = value['buffer'][i] + self.rng_state.buffer[i] = value['buffer'][i] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self): - """Jump the state as-if 2**64draws have been made""" - return self.advance(2**64) + def jump(self, np.npy_intp iter): + """ + jump(iter=1) + + Jumps the state of the random number generator as-if 2**64 random + numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : ThreeFry32 + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is + required to ensure exact reproducibility. + """ + return self.advance(iter * 2 ** 64) + + 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. - def advance(self, step): - """Advance the state as-if a specific number of draws have been made""" - cdef np.ndarray step_a - step_a = int_to_array(step, 'step', 128, 32) + Returns + ------- + self : ThreeFry32 + 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. + """ + cdef np.ndarray delta_a + delta_a = int_to_array(delta, 'step', 128, 32) loc = 0 - threefry32_advance(step_a.data, self.rng_state) + threefry32_advance( delta_a.data, self.rng_state) + self._reset_state_variables() return self + + def ctypes(self): + """ + Cytpes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface( self.rng_state, + ctypes.c_void_p( self.rng_state), + ctypes.cast( &threefry32_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast( &threefry32_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast( &threefry32_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p( self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface( self.rng_state, + ffi.cast('void *', self.rng_state), + ffi.cast('uint64_t (*)(void *)', + self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)', + self._brng.next_uint32), + ffi.cast('double (*)(void *)', + self._brng.next_double), + ffi.cast('void *', self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the core PRNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index 46058e9ca13b..ae02372898df 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -211,7 +211,7 @@ cdef class Xoroshiro128: def jump(self, np.npy_intp iter=1): """ - jump(iter = 1) + jump(iter=1) Jumps the state of the random number generator as-if 2**64 random numbers have been generated. diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index 210702358fd8..86fd5d5f1346 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -128,6 +128,9 @@ cdef class Xorshift1024: cdef xorshift1024_state *rng_state cdef brng_t *_brng cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) @@ -140,6 +143,10 @@ cdef class Xorshift1024: self._brng.next_double = &xorshift1024_double self._brng.next_raw = &xorshift1024_uint64 + self._ctypes = None + self._cffi = None + self._generator = None + cdef const char *name = "BasicRNG" self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -234,9 +241,9 @@ cdef class Xorshift1024: self.rng_state.p = 0 self._reset_state_variables() - def jump(self, np.npy_intp iter): + def jump(self, np.npy_intp iter=1): """ - jump(iter = 1) + jump(iter=1) Jumps the state as-if 2**512 random numbers have been generated @@ -263,7 +270,15 @@ cdef class Xorshift1024: @property def state(self): - """Get or set the PRNG state""" + """ + Get or set the PRNG state + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the PRNG + """ s = np.empty(16, dtype=np.uint64) for i in range(16): s[i] = self.rng_state.s[i] diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 9c73c3d70e05..11704f3516cc 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -200,14 +200,14 @@ def is_pure(self): name='randomgen', packages=find_packages(), package_dir={'randomgen': './randomgen'}, - package_data={'': ['*.c', '*.h', '*.pxi', '*.pyx', '*.pxd']}, + package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in']}, include_package_data=True, license='NSCA', author='Kevin Sheppard', author_email='kevin.k.sheppard@gmail.com', distclass=BinaryDistribution, - description='Next-gen RandomState supporting multiple PRNGs', - url='https://github.com/bashtage/randomgen', + description='Random generator supporting multiple PRNGs', + url='https://github.com/bashtage/core-prng', keywords=['pseudo random numbers', 'PRNG', 'Python'], zip_safe=False ) From e69d24ca01b839dbb4ef4a35bc4fd566cae31e31 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 17:39:01 +0000 Subject: [PATCH 061/138] TST: Improve travis --- _randomgen/.travis.yml | 20 ++++++++++++++++++- .../github_deploy_key_bashtage_core_prng.enc | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 _randomgen/github_deploy_key_bashtage_core_prng.enc diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index e7304ee57454..bda3bb228036 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -7,6 +7,11 @@ dist: trusty sudo: required language: python +env: + global: + # Doctr deploy key for bashtage/core-prng + - secure: "urckknKH5lkUNjXuVCQGVEZYQfSQrAAvdp8sWAKlYJwJLT8iB439KrCUQu8InzcZAA9chPp3syCoT4E0NGkCVPhtJSs/7+LhG+aY/iU6Jp7bwpn5QHCNHQ5jwdc8A0ryqEoQhTiDauRtdzLWPtG5iliz+hr5SOB22w563Le3cx9w0vw9Jy36q+DHe91KEKeF4l464MHhx8aNTmSTBfxPUYyaPHn7/0Wi227PChKMbqnbtoNRcnRwNPjXbRIEs5w2VKtj9m+pvb+DGVjNeSrRBP7aaPgYY+WH+eBOsXrZNuYwF3LEcKx8edVGcEYf2CUKf1VWC2uug/BStY2PU2ZUu/ij3qh+tk2GKhFCc61OPiq7rpeG8Alp5b7IWyFzEjV8IahpdOwa81uGv8B52KD3REOJf8N28s1/WzPlOqRm/9ne+txUZHFk7abE69JK2cBjWGrhBLPxXZSumzhkrpZDyzNb0qZYQSAuAuxUdWhI1gdUJXhmlf4UUqM9vTp7129SbO4wrUK3TIZDIt+7tUuLJYfIm6pOdJBNfrTk4mtvwLh/hsNezd/Vv1BOqrvZ6ZGPMM9eDBh+tMvAfVBe6T6rDoSLUQzYf3GEfp/yJP+QrH9AD46s/DRNL/rAiyOW4oDhMiS+S5EVb/CEu4Ud82HyIZNFAi42gx0jJNkaK2gN8hE=" + matrix: fast_finish: true include: @@ -39,7 +44,7 @@ before_install: - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi - conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet - source activate randomgen-test - - pip install tempita -q + - pip install tempita sphinx guzzle_sphinx_theme ipython pandas doctr coverage coveralls pytest-cov codecov -q install: - python setup.py develop @@ -51,3 +56,16 @@ script: if [[ -z ${NUMPY} ]]; then python benchmark.py; fi + - | + if [[ -z ${NUMPY} ]]; then + if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then + cd ${BUILD_DIR}/doc + make html + make html + cd ${BUILD_DIR} + doctr deploy --built-docs doc --no-require-master + if [[ ${TRAVIS_TAG}} ]]; then + doctr deploy --built-docs doc --no-require-master + fi; + fi; + fi; diff --git a/_randomgen/github_deploy_key_bashtage_core_prng.enc b/_randomgen/github_deploy_key_bashtage_core_prng.enc new file mode 100644 index 000000000000..9487482f0020 --- /dev/null +++ b/_randomgen/github_deploy_key_bashtage_core_prng.enc @@ -0,0 +1 @@ +gAAAAABaqV7yewp22viHuCymP0zVSCFUAlMJZNQH8yFM6OA7KVDd3CIx2b0SLNfMMq6--IyeHF7Gi5wg7UtT6dRo60F7h5-PrZx8iJjA9hqR0ovbZMPaXOQuLlnWYdw9oIBO976w93pDojwv_3QxUsDgRgmUOG7mERkitM8ihvDN17YbAZ_yyh5aX7NTbRr6DoaeL6UQkqfkaZpoflTRRRVIiJoI3aDi8jEDwhEhS_KeDP1fOnJEaJH7nR-zvRveAgbotla4XlW8IUiUP6hiOyGbk3mXZd9J0W6CPAoKbe2CV_6J4rkKd0IteJN2jsYIeNlvBf2BJ5kaIIXte6afejhyrSYcCzEgun5EuiDkqan4f0qgQSN7jjNX9vHNZ0aHNJ8HfvNFTN4fGF2xL3bPAJtGXaqIHEMF5USTRnNN5p0gKxCI5eeD73V-lpE4_LKV5OiWxC4zVFIL6BAEIdF5-cZ9Ikzqtklia17yZna3Rfbhc-0R8YYlpXWyT04c1FIIbHqNk6wsGYNyINTPTloJ6WWjwVD3oTmvFIJOBtR8Rfyk6GYM1PU2ybdbdUJc0iUXv2aL535IpnrK5Fnw4Q-lWSvI6VowJ5aY8GrnQJSyui8kA8BCkE1oblWtR6vmSwFZPjzvkZG2jUwnnaOluCjIzAm70llCO4_4b9IQkdsnNuBlVj1EYDYZQTMe4QJnBoCvB9joFp5dYauoODPcmjrXBCb8Eglg8PAAvVfLeldX2MkFGrv80pxIcN0xsI5qZmmJQOCidHEFSRLCq5Txu7OBOPCtbefs_C4mJdf7iF-F8F0DEOfr5g9CnmbIFzLomsYTzW_M4rqpkF8fxxgd5JwqRsSS36Pm6U8fb8ufpY_e4kUOd3F4qjhFK7PmPYLFdoTAaJobcgMHYNW4Y0KNTKuJM0tf51ysH4Br0EoR3CnzbBcKsgkb74OWzdgbwCdV5zvJl_b36tdd-CRZwA5A85yacuZzrVDJVYrPGwG_7Hsl7WXw-O4sVBaG_yumS1U2nC8y-gTomkvLOHq-fs27mSzcPRApC8d9C2KU9lmvgQPd7OtkPRPeypRPzU5A5UJ_EJVyG4ETUiw-bBLn_viz2HIKEg9wz0i16RSWZkpXHMzMzui2B14vp-RSjSXxK-Ou8dkTDbmw68yIzs4nHUoFA8ZN1CxUzQ2DpUzN9AcLy7q3KGh-XEIBYofsFkPbWYw-KdJi3mOYijShG-4hLGq7YI1r6VGj5Pc9Arh5zdZ_yx8PTz-g6e2-N0dvFfmNmX-bPAsIA5F8UwUVBKFP50vuJ19s8eqsnkrgTSbbF6BTOAifugLODKMeI5UANi-hCUhX3CXRIaOSzg54Ym6e-0suEQ1QygdRsVR4RU1mDf8Za6ZVEYbhuXRVwNnuSzljBjm-ejVAEcgMiTR-lzmu3kcFH_ciHLkO2kJRvv7JkFuDzux1IHM5gcBVYujIMuSFrnAUnuL2vgMfEr2DscSFmezEJz_V1R9NuY3y7hIDitQEAeXUJyUTFwDrFufGqF3IaS2nc6J-aAKVzyGm7JInrpNPH5yyMzEhVLk2V-H-kHSkCZAe240nQ2C0-eKtNCblbOVbfSCkFk2iohUkWK4A8sXSvcDELjCKzkctIANtusdFFEBEu0RswoBouQOICoP7d8ySyGs3XMDDBU_WL_TQk2TAXkVvMEvLLfDxj80JTtqyylD0XDblww6wgVt23KQpvCEpYQB_Ho0NIfkT3qgoDvUuMlz6k8L48AN58mUkqv1a6mhvc86KXsLcYYvwKO33-ErSd6FJKrEKPWr51v6RWpoO5J3ubqSxG_zekchPQ7EnJpHomTlCFK9u-_v4Tr_lTLtDW3vFIfWOyA4LvSVGp05x_HO4MBxL_XNwNzqG8tNJ5fDkOtLxCKWhoHpeA-_zIEFlfGPsfY2j8P-FAR6VyFTecTIFGJGb6ygZL-dGwJeH-FXjdRPMlD_dHxEqxx-JGHlTM297w7yTue80FosiiCkmwJ6BNQJCf-0gom2_ahJgNY_wj0psjLEkIK3pAijICcbZHBYYLyvVDn7llaUc4ziWt-TBego-Nd-5LMl9St0AdBLbGQ0AQqvm5F6MUxnp-KiDNcW0imWXePbqo7Eb4_3SE7mkeHIQY3Tssm_G7sAd6O6Q-V68tfWP8fHWOilaDeIJlahDpUbN3ygLMZwAjaDA0O6g6rSbYGSJtNIBh1VdDGBDOG9pyaRsLIMlxgtjQ7lQPQ44JQzwSa-93tpJQbA2-S_f4SaXt15HVbfr5YeJKcgHJQZfV_Ibi9cWFRp-v12wbPXJ2CkBZXUfzRiW0yR1tlsIxJUreL6SuMvnGulCsw5pbPXvyGOBPhQmKi_JCsanm1_OqQV_5-3p3g2MriHai48kbueoAwV06H9hXFtgZmDcnu8h_99Ld6vpI346xoDo4ShvJC9fU8sGf07zf9zKfpHUberx0mOU4hpyfx4xpAtPJS2ZKni2x2HJuVJkeyPWDIT2kNOOW5G04AnXhrve9CGXDRNIsjeV_q96i1hEaelLGdGkylkHQCJesJDXGN2Kc5QtYaEwRYV7MOdPiaLbPhXwrh2O25UyE-Zjc0UtV-uTCVlQon1nJWk-qyHllDZYxt1AUcwF8EXlG9G1nO7zHFnm68SmC7-Rv6z374YEio3q6PmJzAISd9I4JCPWxrnEPdUtUo8xChttRHys2AzNLRt_WbEtewf5jUeLCtmaRdLbgG-LxBa8IXRLTaQuEw1MH5nsewdoylt-0besWoyhKDtT7oQit7b3gHnCEP3BNSlqmQHodIw0KCC4YH4g4MOVB3YjvBO7lYVCNVyKFQvk2mwo0mKa_H9laljd95pikVuUphoTcbA_fneij-yaUFDu0lVFtio5Tjp7ek2ASxjzuaOgFcdY8LZmCkCx8D0ss8TOsph1JfkIA_rkkOElDc6EROJ-5eTBhQQekcIURltgRjKdrql0T8pD3FPC2Qsv6VMHyFMEpIW7qykJLwoxoendlc7bLNM7DSoIBeqOzY1vRQK1Z1fLFZVwxmtM8P6Up-Lf0aHMpe1jMkKASmj6Xtt-6jiFwS5gTSD_1tiALLgD75HZM88Hrk8zYzfr9MDTEMOiPHIjYfubsO4sve8BD12kh3CyQV26S8573TdaNRlLmTRt4YBi49--xlSrNBP6sqqoN6ZT_S0uA1JAgMHmf4Jr7DRxTfp_qpbjXvCtq7HWowhAsw4oQuF8VSx-PZZM_uzEwjHaR6TpHR3_OkjlbRBL8xR84qCgNjhFze_NxAqIbSuMoRt-n3Dv18Z7bjfokJfPTXS6FA618fZNnryIAyTZsmxjFvywwRRpiFNg6PgXB2LKHGOxpxP8nenfBJAWXD9NodI_sTS7QyaEqUp4lGEcADgLYNNDe77HyhZV1tirHesUE9CwbX-X3Nx_KQ6MhSzIZQn6AiAar5JzenyJV2kRX7Pg_tXYLQLaahnobpCBXpHuDe2_p933SdMU5xsNXQEE4ldJ_R9wfEqlgur5JCiXagLRxjzdrQIBMDXA2pfxu75ow0x7k3-Q9NrNKQQnt7R8HKItSg3m8k0XKSzJ4qgkHeRDdyzlZdA70qcCin4SiF1dYQPRinUjhEiiYdAuxOqOSNJeynwhw3-1NgitiPg03ORP0HAwlUF_SilOjhhCvTG6qQwBLjCIXjsGRNi8HDloIr2JD0gO-pfOsi89QzEm4LkdnQISmVOUFSHQsO4vGtQsnysHpccpNbo63PIEAIX9N9Cnwpi_3ZXcppUfT5FD3s_0R20sqCchys680bRVJivQh3eE79ROHKest_Uxusp14efvKocldd5B8pT9UPh5Y3ZSB2pnFBESYX0Zae3quRF6atlqbtfocixF78a4Rb1H1ZU9opJUbE5YKyQkmWtbbtDsV0OueN2ckC2gyeHtmaJmgne7oxm6JP1f1C68_-YBOGEHaG2MLW1ZS5a5F-3IGLwl6DboRRcV44Q7H5GKr-WuhjTnAlKPB-4ZfxpxCkFd9NKF3LFkrozvsJsKUqC0MdTw0oDNkO3wIxnhmJkAxJbHK0H-XQ7hDRNf_1ajj71kgP3Iv36qQdLqTvH1EBj1Buqe6T5tfKs-ijAmP8Z0ycJ45RMeAf-PEd67NKqdQHSwbhjw0FsP1LTaBQ5TUDjmITPp_nkpmhjRx70o4mm11D_05YwS3qf7-Avf2emZUGY8Ql7lSqFqblWG4DX1pqD15k4f0Vl38M6BysRu-nd7PqERV-KkvRo-LhhTbR313AtptTurr9BXnB4UN_7s86S22m8RAwMDAXURYVv-Dvy6KuITJTd8AP46Z9f0veQUpidA7wGlApOliDZezM_2qskKnF0lmp3ujuO2H2yPGIj7en0s3VwqXTC4fE8dggF6q2mgfBcrBCSd1Mf9lEs= \ No newline at end of file From a85ee48f215189577583570085a282175628cce3 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 18:02:42 +0000 Subject: [PATCH 062/138] BUG: Fix failing test Correct list of expected methods Rename random_sample to random_double to allow random_sample to be used by Python --- _randomgen/.gitignore | 13 ++ _randomgen/.travis.yml | 26 ++-- _randomgen/randomgen/__init__.py | 2 +- _randomgen/randomgen/distributions.pxd | 4 +- _randomgen/randomgen/generator.pyx | 6 +- .../src/distributions/distributions.c | 146 +++++++++--------- .../src/distributions/distributions.h | 14 +- .../randomgen/tests/test_against_numpy.py | 17 +- 8 files changed, 125 insertions(+), 103 deletions(-) diff --git a/_randomgen/.gitignore b/_randomgen/.gitignore index 613fc1bf498c..df53d2597f1b 100644 --- a/_randomgen/.gitignore +++ b/_randomgen/.gitignore @@ -9,3 +9,16 @@ build/ **/Random123 settings.json *.so +randomgen/bounded_integers.c +randomgen/common.c +randomgen/dsfmt.c +randomgen/entropy.c +randomgen/generator.c +randomgen/mt19937.c +randomgen/pcg32.c +randomgen/pcg64.c +randomgen/philox.c +randomgen/threefry.c +randomgen/threefry32.c +randomgen/xoroshiro128.c +randomgen/xorshift1024.c diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index bda3bb228036..0f2da0e20c1d 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -44,7 +44,11 @@ before_install: - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi - conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet - source activate randomgen-test - - pip install tempita sphinx guzzle_sphinx_theme ipython pandas doctr coverage coveralls pytest-cov codecov -q + - pip install tempita coverage coveralls pytest-cov codecov -q + # Docbuild + - if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi + - if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then conda install numba pandas matplotlib --quiet; fi + - export BUILD_DIR=${PWD} install: - python setup.py develop @@ -57,15 +61,15 @@ script: python benchmark.py; fi - | - if [[ -z ${NUMPY} ]]; then - if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then - cd ${BUILD_DIR}/doc - make html - make html - cd ${BUILD_DIR} - doctr deploy --built-docs doc --no-require-master - if [[ ${TRAVIS_TAG}} ]]; then - doctr deploy --built-docs doc --no-require-master - fi; + if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then + ls + echo $PWD + cd ${BUILD_DIR}/doc + make html + make html + cd ${BUILD_DIR} + doctr deploy doc + if [[ ${TRAVIS_TAG}} ]]; then + doctr deploy doc --no-require-master fi; fi; diff --git a/_randomgen/randomgen/__init__.py b/_randomgen/randomgen/__init__.py index 6d389ae9604b..fdddc4ab40d8 100644 --- a/_randomgen/randomgen/__init__.py +++ b/_randomgen/randomgen/__init__.py @@ -15,7 +15,7 @@ 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'permutation', 'pareto', 'poisson', 'power', 'rand', 'randint', 'randn', - 'random_integers', 'random_raw', 'random_uintegers', 'rayleigh', 'state', 'sample', 'shuffle', + 'random_integers', 'random_raw', 'random_sample', 'random_uintegers', 'rayleigh', 'state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'tomaxint', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf'] diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index 3ac32f210108..29ee591e3a4d 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -35,13 +35,13 @@ cdef extern from "src/distributions/distributions.h": ctypedef brng brng_t - double random_sample(brng_t *brng_state) nogil + double random_double(brng_t *brng_state) nogil double random_standard_exponential(brng_t *brng_state) nogil double random_standard_exponential_zig(brng_t *brng_state) nogil double random_gauss_zig(brng_t* brng_state) nogil double random_standard_gamma_zig(brng_t *brng_state, double shape) nogil - float random_sample_f(brng_t *brng_state) nogil + float random_float(brng_t *brng_state) nogil float random_standard_exponential_f(brng_t *brng_state) nogil float random_standard_exponential_zig_f(brng_t *brng_state) nogil float random_gauss_zig_f(brng_t* brng_state) nogil diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 3c5006b6d8a8..5ae857e9c425 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -323,9 +323,9 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_sample, self._brng, size, self.lock, out) + return double_fill(&random_double, self._brng, size, self.lock, out) elif key == 'float32': - return float_fill(&random_sample_f, self._brng, size, self.lock, out) + return float_fill(&random_float, self._brng, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for random_sample' % key) @@ -4306,7 +4306,7 @@ randint = _random_generator.randint randn = _random_generator.randn random_integers = _random_generator.random_integers random_raw = _random_generator.random_raw -sample = _random_generator.random_sample +random_sample = _random_generator.random_sample random_uintegers = _random_generator.random_uintegers rayleigh = _random_generator.rayleigh shuffle = _random_generator.shuffle diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index c08d5be415dc..2ed6d26c3dfe 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -3,16 +3,16 @@ #include "ziggurat_constants.h" /* Random generators for external use */ -float random_sample_f(brng_t *brng_state) { return random_float(brng_state); } +float random_float(brng_t *brng_state) { return next_float(brng_state); } -double random_sample(brng_t *brng_state) { return random_double(brng_state); } +double random_double(brng_t *brng_state) { return next_double(brng_state); } double random_standard_exponential(brng_t *brng_state) { - return -log(1.0 - random_double(brng_state)); + return -log(1.0 - next_double(brng_state)); } float random_standard_exponential_f(brng_t *brng_state) { - return -logf(1.0f - random_float(brng_state)); + return -logf(1.0f - next_float(brng_state)); } /* @@ -26,8 +26,8 @@ double random_gauss(brng_t *brng_state) { double f, x1, x2, r2; do { - x1 = 2.0 * random_double(brng_state) - 1.0; - x2 = 2.0 * random_double(brng_state) - 1.0; + x1 = 2.0 * next_double(brng_state) - 1.0; + x2 = 2.0 * next_double(brng_state) - 1.0; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); @@ -50,8 +50,8 @@ float random_gauss_f(brng_t *brng_state) { float f, x1, x2, r2; do { - x1 = 2.0f * random_float(brng_state) - 1.0f; - x2 = 2.0f * random_float(brng_state) - 1.0f; + x1 = 2.0f * next_float(brng_state) - 1.0f; + x2 = 2.0f * next_float(brng_state) - 1.0f; r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); @@ -70,8 +70,8 @@ static NPY_INLINE double standard_exponential_zig(brng_t *brng_state); static double standard_exponential_zig_unlikely(brng_t *brng_state, uint8_t idx, double x) { if (idx == 0) { - return ziggurat_exp_r - log(random_double(brng_state)); - } else if ((fe_double[idx - 1] - fe_double[idx]) * random_double(brng_state) + + return ziggurat_exp_r - log(next_double(brng_state)); + } else if ((fe_double[idx - 1] - fe_double[idx]) * next_double(brng_state) + fe_double[idx] < exp(-x)) { return x; @@ -84,7 +84,7 @@ static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { uint64_t ri; uint8_t idx; double x; - ri = random_uint64(brng_state); + ri = next_uint64(brng_state); ri >>= 3; idx = ri & 0xFF; ri >>= 8; @@ -104,8 +104,8 @@ static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state); static float standard_exponential_zig_unlikely_f(brng_t *brng_state, uint8_t idx, float x) { if (idx == 0) { - return ziggurat_exp_r_f - logf(random_float(brng_state)); - } else if ((fe_float[idx - 1] - fe_float[idx]) * random_float(brng_state) + + return ziggurat_exp_r_f - logf(next_float(brng_state)); + } else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(brng_state) + fe_float[idx] < expf(-x)) { return x; @@ -118,7 +118,7 @@ static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { uint32_t ri; uint8_t idx; float x; - ri = random_uint32(brng_state); + ri = next_uint32(brng_state); ri >>= 1; idx = ri & 0xFF; ri >>= 8; @@ -141,7 +141,7 @@ double random_gauss_zig(brng_t *brng_state) { double x, xx, yy; for (;;) { /* r = e3n52sb8 */ - r = random_uint64(brng_state); + r = next_uint64(brng_state); idx = r & 0xff; r >>= 8; sign = r & 0x1; @@ -153,14 +153,14 @@ double random_gauss_zig(brng_t *brng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r * log(random_double(brng_state)); - yy = -log(random_double(brng_state)); + xx = -ziggurat_nor_inv_r * log(next_double(brng_state)); + yy = -log(next_double(brng_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]) * random_double(brng_state) + + if (((fi_double[idx - 1] - fi_double[idx]) * next_double(brng_state) + fi_double[idx]) < exp(-0.5 * x * x)) return x; } @@ -175,7 +175,7 @@ float random_gauss_zig_f(brng_t *brng_state) { float x, xx, yy; for (;;) { /* r = n23sb8 */ - r = random_uint32(brng_state); + r = next_uint32(brng_state); idx = r & 0xff; sign = (r >> 8) & 0x1; rabs = (int32_t)((r >> 9) & 0x0007fffff); @@ -186,14 +186,14 @@ float random_gauss_zig_f(brng_t *brng_state) { return x; // # 99.3% of the time return here if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r_f * logf(random_float(brng_state)); - yy = -logf(random_float(brng_state)); + xx = -ziggurat_nor_inv_r_f * logf(next_float(brng_state)); + yy = -logf(next_float(brng_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]) * random_float(brng_state) + + if (((fi_float[idx - 1] - fi_float[idx]) * next_float(brng_state) + fi_float[idx]) < exp(-0.5 * x * x)) return x; } @@ -209,7 +209,7 @@ static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { return random_standard_exponential(brng_state); } else if (shape < 1.0) { for (;;) { - U = random_double(brng_state); + U = next_double(brng_state); V = random_standard_exponential(brng_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); @@ -234,7 +234,7 @@ static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { } while (V <= 0.0); V = V * V * V; - U = random_sample(brng_state); + U = next_double(brng_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))) @@ -251,7 +251,7 @@ static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { return random_standard_exponential_f(brng_state); } else if (shape < 1.0f) { for (;;) { - U = random_sample_f(brng_state); + U = next_float(brng_state); V = random_standard_exponential_f(brng_state); if (U <= 1.0f - shape) { X = powf(U, 1.0f / shape); @@ -276,7 +276,7 @@ static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { } while (V <= 0.0f); V = V * V * V; - U = random_sample_f(brng_state); + U = next_float(brng_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))) @@ -303,7 +303,7 @@ static NPY_INLINE double standard_gamma_zig(brng_t *brng_state, double shape) { return random_standard_exponential_zig(brng_state); } else if (shape < 1.0) { for (;;) { - U = random_sample(brng_state); + U = next_double(brng_state); V = random_standard_exponential_zig(brng_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); @@ -328,7 +328,7 @@ static NPY_INLINE double standard_gamma_zig(brng_t *brng_state, double shape) { } while (V <= 0.0); V = V * V * V; - U = random_sample(brng_state); + U = next_double(brng_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))) @@ -345,7 +345,7 @@ static NPY_INLINE float standard_gamma_zig_f(brng_t *brng_state, float shape) { return random_standard_exponential_zig_f(brng_state); } else if (shape < 1.0f) { for (;;) { - U = random_sample_f(brng_state); + U = next_float(brng_state); V = random_standard_exponential_zig_f(brng_state); if (U <= 1.0f - shape) { X = powf(U, 1.0f / shape); @@ -370,7 +370,7 @@ static NPY_INLINE float standard_gamma_zig_f(brng_t *brng_state, float shape) { } while (V <= 0.0f); V = V * V * V; - U = random_sample_f(brng_state); + U = next_float(brng_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))) @@ -388,26 +388,26 @@ float random_standard_gamma_zig_f(brng_t *brng_state, float shape) { } int64_t random_positive_int64(brng_t *brng_state) { - return random_uint64(brng_state) >> 1; + return next_uint64(brng_state) >> 1; } int32_t random_positive_int32(brng_t *brng_state) { - return random_uint32(brng_state) >> 1; + return next_uint32(brng_state) >> 1; } int64_t random_positive_int(brng_t *brng_state) { #if ULONG_MAX <= 0xffffffffUL - return (int64_t)(random_uint32(brng_state) >> 1); + return (int64_t)(next_uint32(brng_state) >> 1); #else - return (int64_t)(random_uint64(brng_state) >> 1); + return (int64_t)(next_uint64(brng_state) >> 1); #endif } uint64_t random_uint(brng_t *brng_state) { #if ULONG_MAX <= 0xffffffffUL - return random_uint32(brng_state); + return next_uint32(brng_state); #else - return random_uint64(brng_state); + return next_uint64(brng_state); #endif } @@ -465,7 +465,7 @@ double random_exponential(brng_t *brng_state, double scale) { } double random_uniform(brng_t *brng_state, double lower, double range) { - return lower + range * random_sample(brng_state); + return lower + range * next_double(brng_state); } double random_gamma(brng_t *brng_state, double shape, double scale) { @@ -484,8 +484,8 @@ double random_beta(brng_t *brng_state, double a, double b) { /* Use Johnk's algorithm */ while (1) { - U = random_sample(brng_state); - V = random_sample(brng_state); + U = next_double(brng_state); + V = next_double(brng_state); X = pow(U, 1.0 / a); Y = pow(V, 1.0 / b); @@ -538,7 +538,7 @@ double random_power(brng_t *brng_state, double a) { double random_laplace(brng_t *brng_state, double loc, double scale) { double U; - U = random_sample(brng_state); + U = next_double(brng_state); if (U < 0.5) { U = loc + scale * log(U + U); } else { @@ -550,14 +550,14 @@ double random_laplace(brng_t *brng_state, double loc, double scale) { double random_gumbel(brng_t *brng_state, double loc, double scale) { double U; - U = 1.0 - random_sample(brng_state); + U = 1.0 - next_double(brng_state); return loc - scale * log(-log(U)); } double random_logistic(brng_t *brng_state, double loc, double scale) { double U; - U = random_sample(brng_state); + U = next_double(brng_state); return loc + scale * log(U / (1.0 - U)); } @@ -566,7 +566,7 @@ double random_lognormal(brng_t *brng_state, double mean, double sigma) { } double random_rayleigh(brng_t *brng_state, double mode) { - return mode * sqrt(-2.0 * log(1.0 - random_sample(brng_state))); + return mode * sqrt(-2.0 * log(1.0 - next_double(brng_state))); } double random_standard_t(brng_t *brng_state, double df) { @@ -585,7 +585,7 @@ static int64_t random_poisson_mult(brng_t *brng_state, double lam) { X = 0; prod = 1.0; while (1) { - U = random_sample(brng_state); + U = next_double(brng_state); prod *= U; if (prod > enlam) { X += 1; @@ -614,8 +614,8 @@ static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { vr = 0.9277 - 3.6224 / (b - 2); while (1) { - U = random_sample(brng_state) - 0.5; - V = random_sample(brng_state); + U = next_double(brng_state) - 0.5; + V = next_double(brng_state); us = 0.5 - fabs(U); k = (int64_t)floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { @@ -694,8 +694,8 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, /* sigh ... */ Step10: nrq = n * r * q; - u = random_sample(brng_state) * p4; - v = random_sample(brng_state); + u = next_double(brng_state) * p4; + v = next_double(brng_state); if (u > p1) goto Step20; y = (int64_t)floor(xm - p1 * v + u); @@ -808,13 +808,13 @@ int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, } X = 0; px = qn; - U = random_sample(brng_state); + U = next_double(brng_state); while (U > px) { X++; if (X > bound) { X = 0; px = qn; - U = random_sample(brng_state); + U = next_double(brng_state); } else { U -= px; px = ((n - X + 1) * p * px) / (X * q); @@ -871,7 +871,7 @@ double random_wald(brng_t *brng_state, double mean, double scale) { Y = random_gauss_zig(brng_state); Y = mean * Y * Y; X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y)); - U = random_sample(brng_state); + U = next_double(brng_state); if (U <= mean / (mean + X)) { return X; } else { @@ -886,7 +886,7 @@ double random_vonmises(brng_t *brng_state, double mu, double kappa) { int neg; if (kappa < 1e-8) { - return M_PI * (2 * random_sample(brng_state) - 1); + return M_PI * (2 * next_double(brng_state) - 1); } else { /* with double precision rho is zero until 1.4e-8 */ if (kappa < 1e-5) { @@ -902,17 +902,17 @@ double random_vonmises(brng_t *brng_state, double mu, double kappa) { } while (1) { - U = random_sample(brng_state); + U = next_double(brng_state); Z = cos(M_PI * U); W = (1 + s * Z) / (s + Z); Y = kappa * (s - W); - V = random_sample(brng_state); + V = next_double(brng_state); if ((Y * (2 - Y) - V >= 0) || (log(Y / V) + 1 - Y >= 0)) { break; } } - U = random_sample(brng_state); + U = next_double(brng_state); result = acos(W); if (U < 0.5) { @@ -937,11 +937,11 @@ int64_t random_logseries(brng_t *brng_state, double p) { r = log(1.0 - p); while (1) { - V = random_sample(brng_state); + V = next_double(brng_state); if (V >= p) { return 1; } - U = random_sample(brng_state); + U = next_double(brng_state); q = 1.0 - exp(r * U); if (V <= q * q) { result = (int64_t)floor(1 + log(V) / log(q)); @@ -966,7 +966,7 @@ int64_t random_geometric_search(brng_t *brng_state, double p) { X = 1; sum = prod = p; q = 1.0 - p; - U = random_sample(brng_state); + U = next_double(brng_state); while (U > sum) { prod *= q; sum += prod; @@ -976,7 +976,7 @@ int64_t random_geometric_search(brng_t *brng_state, double p) { } int64_t random_geometric_inversion(brng_t *brng_state, double p) { - return (int64_t)ceil(log(1.0 - random_sample(brng_state)) / log(1.0 - p)); + return (int64_t)ceil(log(1.0 - next_double(brng_state)) / log(1.0 - p)); } int64_t random_geometric(brng_t *brng_state, double p) { @@ -995,8 +995,8 @@ int64_t random_zipf(brng_t *brng_state, double a) { am1 = a - 1.0; b = pow(2.0, am1); do { - U = 1.0 - random_sample(brng_state); - V = random_sample(brng_state); + U = 1.0 - next_double(brng_state); + V = next_double(brng_state); X = (int64_t)floor(pow(U, -1.0 / am1)); /* The real result may be above what can be represented in a int64. * It will get casted to -sys.maxint-1. Since this is @@ -1020,7 +1020,7 @@ double random_triangular(brng_t *brng_state, double left, double mode, leftprod = leftbase * base; rightprod = (right - mode) * base; - U = random_sample(brng_state); + U = next_double(brng_state); if (U <= ratio) { return left + sqrt(U * leftprod); } else { @@ -1039,7 +1039,7 @@ int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, y = d2; k = sample; while (y > 0.0) { - u = random_sample(brng_state); + u = next_double(brng_state); y -= (int64_t)floor(u + y / (d1 + k)); k--; if (k == 0) @@ -1078,8 +1078,8 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, /* 16 for 16-decimal-digit precision in D1 and D2 */ while (1) { - X = random_sample(brng_state); - Y = random_sample(brng_state); + X = next_double(brng_state); + Y = next_double(brng_state); W = d6 + d8 * (Y - 0.5) / X; /* fast rejection: */ @@ -1142,10 +1142,10 @@ uint64_t random_interval(brng_t *brng_state, uint64_t max) { /* Search a random value in [0..mask] <= max */ if (max <= 0xffffffffUL) { - while ((value = (random_uint32(brng_state) & mask)) > max) + while ((value = (next_uint32(brng_state) & mask)) > max) ; } else { - while ((value = (random_uint64(brng_state) & mask)) > max) + while ((value = (next_uint64(brng_state) & mask)) > max) ; } return value; @@ -1174,10 +1174,10 @@ static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, uint64_t off, return off; if (rng <= 0xffffffffUL) { - while ((val = (random_uint32(brng_state) & mask)) > rng) + while ((val = (next_uint32(brng_state) & mask)) > rng) ; } else { - while ((val = (random_uint64(brng_state) & mask)) > rng) + while ((val = (next_uint64(brng_state) & mask)) > rng) ; } return off + val; @@ -1200,7 +1200,7 @@ static NPY_INLINE uint32_t bounded_uint32(brng_t *brng_state, uint32_t off, if (rng == 0) return off; - while ((val = (random_uint32(brng_state) & mask)) > rng) + while ((val = (next_uint32(brng_state) & mask)) > rng) ; return off + val; } @@ -1225,7 +1225,7 @@ static NPY_INLINE uint16_t buffered_bounded_uint16(brng_t *brng_state, do { if (!(bcnt[0])) { - buf[0] = random_uint32(brng_state); + buf[0] = next_uint32(brng_state); bcnt[0] = 1; } else { buf[0] >>= 16; @@ -1251,7 +1251,7 @@ static NPY_INLINE uint8_t buffered_bounded_uint8(brng_t *brng_state, return off; do { if (!(bcnt[0])) { - buf[0] = random_uint32(brng_state); + buf[0] = next_uint32(brng_state); bcnt[0] = 3; } else { buf[0] >>= 8; @@ -1275,7 +1275,7 @@ static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_state, if (rng == 0) return off; if (!(bcnt[0])) { - buf[0] = random_uint32(brng_state); + buf[0] = next_uint32(brng_state); bcnt[0] = 31; } else { buf[0] >>= 1; diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index f3a5448b3479..6bbbcd8f0f05 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -77,24 +77,24 @@ typedef struct brng { } brng_t; /* Inline generators for internal use */ -static NPY_INLINE uint32_t random_uint32(brng_t *brng_state) { +static NPY_INLINE uint32_t next_uint32(brng_t *brng_state) { return brng_state->next_uint32(brng_state->state); } -static NPY_INLINE uint64_t random_uint64(brng_t *brng_state) { +static NPY_INLINE uint64_t next_uint64(brng_t *brng_state) { return brng_state->next_uint64(brng_state->state); } -static NPY_INLINE float random_float(brng_t *brng_state) { - return (random_uint32(brng_state) >> 9) * (1.0f / 8388608.0f); +static NPY_INLINE float next_float(brng_t *brng_state) { + return (next_uint32(brng_state) >> 9) * (1.0f / 8388608.0f); } -static NPY_INLINE double random_double(brng_t *brng_state) { +static NPY_INLINE double next_double(brng_t *brng_state) { return brng_state->next_double(brng_state->state); } -DECLDIR float random_sample_f(brng_t *brng_state); -DECLDIR double random_sample(brng_t *brng_state); +DECLDIR float random_float(brng_t *brng_state); +DECLDIR double random_double(brng_t *brng_state); DECLDIR int64_t random_positive_int64(brng_t *brng_state); DECLDIR int32_t random_positive_int32(brng_t *brng_state); diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index c4673c2d2306..dd187f25d8db 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -1,10 +1,11 @@ import numpy as np import numpy.random -from numpy.testing import assert_allclose, assert_array_equal, assert_equal import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_equal -from randomgen import RandomGenerator, MT19937 import randomgen +from randomgen import RandomGenerator, MT19937 + def compare_0_input(f1, f2): inputs = [(tuple([]), {}), (tuple([]), {'size': 10}), @@ -42,7 +43,8 @@ def compare_2_input(f1, f2, is_np=False, is_scalar=False): np.array([b] * 10)), {'size': (100, 10)}), ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (7, 31)}), - ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), {'size': (10, 7, 31)})] + ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), + {'size': (10, 7, 31)})] if is_scalar: inputs = inputs[:3] @@ -528,15 +530,18 @@ def test_array(self): def test_dir(self): nprs_d = set(dir(self.nprs)) rs_d = dir(self.rg) - excluded = {'get_state', 'poisson_lam_max', 'set_state'} + excluded = {'get_state', 'set_state'} nprs_d.difference_update(excluded) assert (len(nprs_d.difference(rs_d)) == 0) npmod = dir(numpy.random) mod = dir(randomgen) known_exlcuded = ['__all__', 'Tester', 'info', 'bench', - '__RandomState_ctor', 'mtrand', 'test', - '__warningregistry__', '_numpy_tester'] + '__RandomState_ctor', 'mtrand', 'test', + '__warningregistry__', '_numpy_tester', 'division', + 'get_state', 'set_state', 'seed', 'ranf', 'random', + 'sample', 'absolute_import', 'print_function', + 'RandomState'] mod += known_exlcuded diff = set(npmod).difference(mod) assert_equal(len(diff), 0) From 701326e9a0f975a98bb1a75ec14faa9a3cb4579c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 19:43:07 +0000 Subject: [PATCH 063/138] DOC: Fix location of tagged docs --- _randomgen/.travis.yml | 9 +++++---- _randomgen/github_deploy_key_bashtage_randomgen.enc | 1 + _randomgen/setup.cfg | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 _randomgen/github_deploy_key_bashtage_randomgen.enc diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 0f2da0e20c1d..94c17b200c19 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -9,8 +9,8 @@ language: python env: global: - # Doctr deploy key for bashtage/core-prng - - secure: "urckknKH5lkUNjXuVCQGVEZYQfSQrAAvdp8sWAKlYJwJLT8iB439KrCUQu8InzcZAA9chPp3syCoT4E0NGkCVPhtJSs/7+LhG+aY/iU6Jp7bwpn5QHCNHQ5jwdc8A0ryqEoQhTiDauRtdzLWPtG5iliz+hr5SOB22w563Le3cx9w0vw9Jy36q+DHe91KEKeF4l464MHhx8aNTmSTBfxPUYyaPHn7/0Wi227PChKMbqnbtoNRcnRwNPjXbRIEs5w2VKtj9m+pvb+DGVjNeSrRBP7aaPgYY+WH+eBOsXrZNuYwF3LEcKx8edVGcEYf2CUKf1VWC2uug/BStY2PU2ZUu/ij3qh+tk2GKhFCc61OPiq7rpeG8Alp5b7IWyFzEjV8IahpdOwa81uGv8B52KD3REOJf8N28s1/WzPlOqRm/9ne+txUZHFk7abE69JK2cBjWGrhBLPxXZSumzhkrpZDyzNb0qZYQSAuAuxUdWhI1gdUJXhmlf4UUqM9vTp7129SbO4wrUK3TIZDIt+7tUuLJYfIm6pOdJBNfrTk4mtvwLh/hsNezd/Vv1BOqrvZ6ZGPMM9eDBh+tMvAfVBe6T6rDoSLUQzYf3GEfp/yJP+QrH9AD46s/DRNL/rAiyOW4oDhMiS+S5EVb/CEu4Ud82HyIZNFAi42gx0jJNkaK2gN8hE=" + # Doctr deploy key for bashtage/randomgen + - secure: "czwFlflS1lcfbSQ9ktv+pLAPV9/6+wmwiMTyIYyv5xgQVWRL5NRebWH+ZhQ6s2T5x17wFMtlafcAvkdV0CHQZLru34V2UNldCapuEtQ8b32EDHBXHKbs45b7SSkLx4TFXdjiJurleY4ZIKle0gX6BW21zYBwaHJqbN6I8nRv9Rp47XEU1UV1Mdf/PhfTnxY31rFrPYL77xeWJzoFfT8zao39V4gQds+1Ag7FjdNVdSDVKwDduF4kS7tIbKqb4M+jsbc3PIKyP9nyQpEQF5ebJuG7mqXJhVJGEL83rBx8MLFPA/1X3cUzKacgKyp2+Wmlt0EVhwCa1aRf9cSK6I7TbMC7/eGtDnC2ToiRlFJurVRblaEmhzVQS1yQ4Dkooqsj9hNVl6nhu7JfR52GLogns33Ec/yYuRcWcULKSlR5Cerfef/5YijBEhlr9X76SJiOpjvS4lwWFYX+h8xzuVhRLGwIVB9oQNllxYItzcDSGmRx+EOMXWASHmoUDnBOZg4GMVukqOcF5l0ynoepiA1YHLdZlMy6SB3P7BZKF/aNCOn9nXw+N9X4U/yUpkM3Pb7HoGdNrC8RO4SwrNjGrarkdEB6e1lBReK/dqcylaF/mpK9VLpfQszDI8xnR4VCmlEM+le0xOsyHfeGciabdI4KH0i0SfYl4ls5XrN+CaqFWdo=" matrix: fast_finish: true @@ -31,6 +31,7 @@ matrix: before_install: + - git fetch --tags - if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda3.sh; fi - if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi - chmod +x miniconda3.sh @@ -69,7 +70,7 @@ script: make html cd ${BUILD_DIR} doctr deploy doc - if [[ ${TRAVIS_TAG}} ]]; then - doctr deploy doc --no-require-master + if [[ -n ${TRAVIS_TAG}} ]]; then + doctr deploy . --build-tags fi; fi; diff --git a/_randomgen/github_deploy_key_bashtage_randomgen.enc b/_randomgen/github_deploy_key_bashtage_randomgen.enc new file mode 100644 index 000000000000..ec025c4808eb --- /dev/null +++ b/_randomgen/github_deploy_key_bashtage_randomgen.enc @@ -0,0 +1 @@ +gAAAAABaqYcL3y2gmKPwdhTQvWbDmqvTV9VyGXrEJI0HFVB3ZcmhgwRY_2L9_k7wALgsaQ9-FOqKreKMagBvAiS8IYhW4dUhJ1_6MO0bb8l_fdvkiKY7NH4DXKpO6sGmOg5YPfx44agTLtnI9yuZHo_LgYTkXFS2MQISZJvpmmtgC7fv_ydaRDG3v9c4a4zi7futr6zk0jAlxw29gjyFaReWJQgH6hJTVUVvOq30RJwjpa87jf45mVTsyPdVfHRqn6rcwvGsRKCW6hFnPRsJEP6-ivdjMFbzK6uK1TrswAJ2ZZIGcH84Kaph8kQayMZRL5FUoWsonkGK_SHwiPjmmHRXVMYxSJqNAtjxDgcznzmuazUOwdWCUIkxe0FtJieW5rLwTjT2u1cgcCQ2MKkBiCjO4tORCT0JGCyhOZdsJx6_5i2s1OKaCEb6Uur07itpI2IAEreA38u7CiU150Q7D8zinpPLWuXIrsk9nKfr1YjwXBSVtOBUOuh4Sy9MjcpQuavwJPYVSpNi6_BeIclxP45wjFF5Ai2P8IgaHxSFlMJNfze9H1U-2eTyQaykuZ2WrZBPoGYFRaQExU6jnXOdPMC5FqaO5DV5tvN56fLx9UFXaCqf_UknJRvYnLi94H__nZJWhN6XfCeNaUuPZuuiOFXekK-LC5VFAWXTN84pOesek0-zESKDffFozITTjA-4cvzppUnsSZNm5cXBUdr3wszkNlrQqDVZhP_HU2B8QSilBnnfVEsbKr_-SVQ0s3ipFohPS_GTFKtn8467vvIRgCkks8J1ba5xHb6QMlt2Y2L7yunLh0vmKwqZTVtU-4L4Xm2kKvgHi1kxAaApQiEX2bM-xX7TGNnzRFLKAxpHX4EvO72K2CcQXKu0XkRNc-_c-XcxsWZ7XtvyTCBXNnPtvj26B-FW8XyJH_u0HblrB-AKRgmpRuAhDNh1l_OAcOFHpUrH5t64t6lwOYCR3lXUJJytW-UEz-Nx9j32VX4Ep1IsGjkNuM3FtW4E-iVoGPwYwT3jsGo5rsO6MzrzoEKJbFdgQHnqe3NaxpF6rEVweQTNN2E1LFFuYHnRgo2LuMdK7IDXJ66MCxqEBRMH6Gcne-b5RHEpWoCQAvgyKwU5MclS4M3zLhGnXbtO-q4OL3JV1a-wx9e4vHZJrAolMjvw7a8l5vCDj-FqT5nJIVpG5eKwB_JL24O5d4xUSbgqBm6i1h51L---brkWg9i9YXsjZj5Inf2ZuU3hasZPyXFbTZbpBXN7BMalszLadCOWWsnDJMvl-UJeX2aDDATy5M_4-9Yjt70G1ZJNxZ8K2F6UdXwVifGJGa7jHU9nteCWZVfUdkiexqkLqKebZAlPBpzisrEQw6PmokKP2UO27NBFYTlfYL1NiCahXkOUMPiTKhjQ0_JSqdlUl2igNlNUFSip-63Rk4WtgodQo9iI4icfV5TFkR0h-LPD1m9lIamruWvAQWLU-_daZcN8rdqCWsysuo1ryp80UHHvyTiwloCa2f0ZKr78RIaD_QCkHmevywprNNuMd0ErbAOD7v3dUKjnlvpf8gLpUnu4ZfR1u86OPqsyt2b5tmwB6TWdpaCBNRAjlbFOU8aHDpPDVCAKf1AcEZ1B6p36YgNf5yxmKwc1QEmzXPr1KnSWJRps_QRBX-hEuBu8Q_BUQCjlInJVLcpSgt2lTuJPwwQzdxm5CeU1xdpeWCztSxfghmfE7mzhYizIYa1WaYs32xfZQglEG_O8oXCaU524vyh6cBnIytY3cF1FlwfbKQvbKyKkq8p5YSWe8HX8XRJGVe1bBNM2RYZO5BfLLl5cENIUSbb-REs6j8E61HGgJ9cLBG4-l2QbivSEhKsa4fI0JNVGEL_kwaEOVNHa85y_4oFAQuC4eYOMdgrwGfcD-J-XkE_J6khiLCOaZRcFhFNUfTjghPYzO37D24cAQ9fGnFFehQU-08Ie8SMV2O3fmUV2RbX_h6FXYKZ5Ptp3l2wP5wcuwhPFxPPJ279pswQw9NlHBF3gdtu3_cisqwNfc_HZQ6GXYzbcE7nwTGOY03LN3RjghJgkkeaNs6e0iIxfTJjIqG6-ZWNRNOJKdotjMLVqlhfk0KNZjO5rKEfDfYW_Lbiylgu7I7O-wy-Xn60OTu7na0ObYl-Y9tXkRTZPMNasjDWpfTXKZRp8EX45W-35VKmb0ERj0ee9uXgZxiPGLd3OP8cxIiXqZdZYKwJnD09zZuXwaTa2AAp2WmLYLiF-pDIISNxVF7mCxU9G0AWl0Ml1d5pS5zadM1OYB5yfjx09hlVasaiPaGqIptNtdz8tDQ1ngH-QBPV8wNvSxHwdU4w96pJIY9jG5Z3k-PVO26NNKjZ_KMZhO-3TgQXMJI0GHSyfYFHEMGJuUbeS4ThGyAt2Z6pVKTu7WFjgceseLMmwevJQeyScvtD22t8bpSuqfgxrAGSP5O2-e1UEl_12umZZG3sSd8jc_WNBgX7nSa6LeGAmlY0z_h9SblVl63r2qZi7-Ur0Y7O4JH4rHMDkf07tMU-foCiDDppvZkPRuvPlYgzLmnyOXePN0_1aiou9qbMWmzyJwhrqnt5uZXVHpRwCKKdXRBAcBebuKU-LKqMhWWowf1OUm240628OmQL2oTOaVWBlS3x1XKHMv18_ucbgWB4KaQdidSKMwIXE_LRfhr17g-h2CTQFsfImGKU36ECJHk35K9qr3aZI5X2MLUsOJjdbQiVJsLpdCDbr_HfPDNnux0QiVRZhslKnqOlcv8_6MeKtcqcxDJTi1v1430tpiZj-A2dp3F9YXi_PvCcKD4GheUwN8TUJgEZF3m9Vc80pAWWFDN7Obof_0zCcv7HrXgXCVJHnFzJn0J4AqW6db-DvYAzdejDnLTsTZK9ctJmWxHAWWXYi35aAjj6nalFk97T7EvOr2zS6f_xSUyPeNPs2fIP1lY3togmjPRvwbIN-ZxqLzkfjmxARrLJpqAxK_AvOz2vNlEosQd3zJxk7hEQWRfkTmakvDPgkd5fNsfIGfAt8B_PWnmz41DWKeOlsSQguPAqCE40NSszmyjSBhde8uHN8tGwdQpdcjPt01kgmrdD2GHfLs8zeyNWRzE3qmLT46S1dq1kfQX2j20LXDck9Ox0nFDUXYwaz6pVDPymhPqzh4EHtg0QKePJ5qpY2RDTW3S8UK3YkE3pa_C_-BPcNLVGr_k7WaMWGx0JJ72W2MqcoXgq3bZq_CZeseeKm3rH3YiaibidLk4WqMblcWUurHW09vFCNSOyQ28jkBeMSgadJ2zEbK9M1QmsDxxSCzWtIn_y7nDLCGh0NzD2alVp4QfxwjF5ZEYSXZOYXdhRBkd3pRX9perJT_zlQf7Ag2otXUZE-J6TkDAAwhWxxUFQ0iUIKNKtO-ocM8YevCyl0EK06AzX6jmShrE5eZpej7o7DA2dCoLYksacloBbonqDjkpXR1uZcGJSnhZm29UeSSGQN7cqgR5DDCHkthvOn8gZxS8vr1fQiswazUaMCClHUD_O88IlLXnqXj4n-84TMT9iBGN3iaab4P-fb2t1Azcd8uSGl3CwNEouEekdvVWHSp3bhMkwpPuvakJheLOGfX7npwWo5iIEvdA0VhesiEV8ZVJYCt3zmOwQtI-Sk5uAVAWAieB6-up9KWtwoF89C64CLp99srzLkaPddQJKtTruYQER5l3hL1LBe5g8XPEBNMrFjp2xIN8mNYpZRt41nFxsHoA9xnsv4NXWbwqnkyImP0Wm9HmclvwTOZ9xdT5Ryj8u97XSOz4y8T5Ql5UPwRBujiBI91GQnEKz3FPmUzS70Bbrg3XIirpbPqcRp_VnnxXT8AX0zGZiuWvx94NFa5h4a11vYpeLnKzQ2RyTHB96CSpxxdXHAHfMvc9ib3XzlKRUUfDX0x0tDBj3BkV5UMgLtn2RRCgT1PydLn13wYbeNwfb5GlGutiqQY_QTuUOqSII-2vyNzA5FUPpzofXGYwAz52pGwpZ7w0s4fBpXocxWt0gGW5wxDzTEX3UdkbRsN1GXs5tYkdbcCW_jPrVcq7pUGgOyGXMEYnZUA1ack2h6nSwlxbx_Aka_VyxZCJFYJW9S165lIhm7KkDCfRpQdoA4Fx27aAXwWL70ipNCyNHFOERXD5SoVMJDcz3-cXkttEddXooygKoXojR4epBuxhSkUNxgnd70faZaIC8_L5_ZlZIBn-lH3jLT5Yuzt8-weKpAyczteZ8eLB0YlnYlqhIVFYy4QBR8iejRZBXABKiuIWz_Xf4qu6UGwHTQ-1BBfl9mr0RxULn7NGtfbQ72Xwad-HlT1MnEd_6o95MkFvHbdINlpkaeVwiAgUSFbITPh7x8JaQKlAzjROJQdhGvT4j42woumzQtuqr9UnDWtf8aECkrJP_-AEy1BLbXmUo= \ No newline at end of file diff --git a/_randomgen/setup.cfg b/_randomgen/setup.cfg index d6b61d347b3d..7e46c5c532af 100644 --- a/_randomgen/setup.cfg +++ b/_randomgen/setup.cfg @@ -3,5 +3,5 @@ VCS = git style = pep440 versionfile_source = randomgen/_version.py versionfile_build = randomgen/_version.py -tag_prefix = +tag_prefix = v parentdir_prefix = randomgen- From f0606145c465200576969e6ed00eb41a8224f984 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 14 Mar 2018 22:28:18 +0000 Subject: [PATCH 064/138] DOC: Update docs and building --- _randomgen/.gitignore | 2 + _randomgen/.travis.yml | 33 +- _randomgen/MANIFEST.in | 11 +- _randomgen/README.md | 17 +- _randomgen/README.rst | 281 ++++++++++++++++++ _randomgen/doc/source/brng/dsfmt.rst | 6 +- _randomgen/doc/source/brng/index.rst | 7 + _randomgen/doc/source/brng/mt19937.rst | 5 +- _randomgen/doc/source/brng/pcg32.rst | 5 +- _randomgen/doc/source/brng/pcg64.rst | 5 +- _randomgen/doc/source/brng/philox.rst | 5 +- _randomgen/doc/source/brng/threefry.rst | 5 +- _randomgen/doc/source/brng/threefry32.rst | 5 +- _randomgen/doc/source/brng/xoroshiro128.rst | 5 +- _randomgen/doc/source/brng/xorshift1024.rst | 5 +- _randomgen/doc/source/conf.py | 38 ++- _randomgen/doc/source/generator.rst | 13 +- _randomgen/doc/source/index.rst | 69 ++++- .../github_deploy_key_bashtage_core_prng.enc | 1 - _randomgen/randomgen/__init__.py | 29 +- _randomgen/randomgen/bounded_integers.pyx | 18 +- _randomgen/randomgen/bounded_integers.pyx.in | 2 +- _randomgen/randomgen/dsfmt.pyx | 5 +- _randomgen/randomgen/entropy.pyx | 2 +- _randomgen/randomgen/generator.pyx | 10 +- _randomgen/randomgen/mt19937.pyx | 116 +++++++- _randomgen/randomgen/pcg32.pyx | 8 +- _randomgen/randomgen/pcg64.pyx | 8 +- _randomgen/randomgen/philox.pyx | 9 +- _randomgen/randomgen/pickle.py | 4 +- .../randomgen/tests/test_against_numpy.py | 15 +- _randomgen/randomgen/threefry.pyx | 9 +- _randomgen/randomgen/threefry32.pyx | 9 +- _randomgen/randomgen/xoroshiro128.pyx | 7 +- _randomgen/randomgen/xorshift1024.pyx | 10 +- _randomgen/requirements.txt | 8 +- _randomgen/setup.py | 52 +++- 37 files changed, 668 insertions(+), 171 deletions(-) create mode 100644 _randomgen/README.rst delete mode 100644 _randomgen/github_deploy_key_bashtage_core_prng.enc diff --git a/_randomgen/.gitignore b/_randomgen/.gitignore index df53d2597f1b..381421b399e9 100644 --- a/_randomgen/.gitignore +++ b/_randomgen/.gitignore @@ -9,6 +9,8 @@ build/ **/Random123 settings.json *.so +randomgen/bounded_integers.pyx +randomgen/bounded_integers.pxd randomgen/bounded_integers.c randomgen/common.c randomgen/dsfmt.c diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 94c17b200c19..1c950fdab6b9 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -24,7 +24,7 @@ matrix: - os: linux env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.26] - os: linux - env: [PYTHON=3.6] + env: [PYTHON=3.6, DOCBUILD=true] - os: osx language: generic env: [PYTHON=3.6] @@ -46,10 +46,9 @@ before_install: - conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet - source activate randomgen-test - pip install tempita coverage coveralls pytest-cov codecov -q - # Docbuild - - if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi - - if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then conda install numba pandas matplotlib --quiet; fi - export BUILD_DIR=${PWD} + - if [[ ${DOCBUILD} == true ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi + - if [[ ${DOCBUILD} == true ]]; then conda install numba pandas matplotlib --quiet; fi install: - python setup.py develop @@ -58,19 +57,23 @@ script: - set -e - pytest randomgen - | - if [[ -z ${NUMPY} ]]; then - python benchmark.py; - fi - - | - if [[ -z ${NUMPY} && ${TRAVIS_OS_NAME} == "linux" ]]; then - ls - echo $PWD + if [[ ${DOCBUILD} == true ]]; then cd ${BUILD_DIR}/doc make html make html cd ${BUILD_DIR} - doctr deploy doc - if [[ -n ${TRAVIS_TAG}} ]]; then + doctr deploy devel --build-tags + if [[ -z ${TRAVIS_TAG} ]]; then + echo "Not a tagged build." + else doctr deploy . --build-tags - fi; - fi; + fi + fi + +after_success: + - | + if [[ ${DOCBUILD} == true ]]; then + cd ${BUILD_DIR} + python benchmark.py; + fi + \ No newline at end of file diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in index c961f9101cd4..b6a20a4feaa1 100644 --- a/_randomgen/MANIFEST.in +++ b/_randomgen/MANIFEST.in @@ -1,6 +1,9 @@ +exclude randomgen/entropy.c +recursive-exclude randomgen *.c include versioneer.py include randomgen/_version.py -recursive-include randomgen *.py *.pyx *.px[di] *.h *.in -recursive-include randomgen/src *.c - - +include requirements.txt +include README.md +include README.rst +recursive-include randomgen *.py *.pyx *.px[di] *.h *.in *.csv +graft randomgen/src diff --git a/_randomgen/README.md b/_randomgen/README.md index 93b0e461b0be..036af1b619b1 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -1,7 +1,7 @@ # RandomGen -[![Travis Build Status](https://travis-ci.org/bashtage/core-prng.svg?branch=master)](https://travis-ci.org/bashtage/core-prng) -[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/core-prng/branch/master) +[![Travis Build Status](https://travis-ci.org/bashtage/randomgen.svg?branch=master)](https://travis-ci.org/bashtage/randomgen) +[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/randomgen/branch/master) Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -116,13 +116,10 @@ the RNG._ ## Status -* Replacement for `numpy.random.RandomState`. The - `MT19937` generator is identical to `numpy.random.RandomState`, and - will produce an identical sequence of random numbers for a given seed. * Builds and passes all tests on: * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 (probably works on 2.6 and 3.3) * PC-BSD (FreeBSD) 64-bit, Python 2.7 - * OSX 64-bit, Python 2.7 + * OSX 64-bit, Python 3.6 * Windows 32/64 bit (only tested on Python 2.7, 3.5 and 3.6, but should work on 3.3/3.4) @@ -132,14 +129,16 @@ The version matched the latest version of NumPy where ## Documentation -An occasionally updated build of the documentation is available on -[my GitHub pages](http://bashtage.github.io/randomgen/). +Documentation for the latest release is available on +[my GitHub pages](http://bashtage.github.io/randomgen/). Documentation for +the latest commit (unreleased) is available under +[devel](http://bashtage.github.io/randomgen/devel/). ## Plans This module is essentially complete. There are a few rough edges that need to be smoothed. -* Creation of additional streams from a RandomState where supported +* Creation of additional streams from where supported (i.e. a `next_stream()` method) ## Requirements diff --git a/_randomgen/README.rst b/_randomgen/README.rst new file mode 100644 index 000000000000..b9a0ad5f5053 --- /dev/null +++ b/_randomgen/README.rst @@ -0,0 +1,281 @@ +RandomGen +========= + +|Travis Build Status| |Appveyor Build Status| + +Random Number Generator using settable Basic RNG interface for future +NumPy RandomState evolution. + +This is a library and generic interface for alternative random +generators in Python and NumPy. + +Compatibility Warning +~~~~~~~~~~~~~~~~~~~~~ + +RandomGen no longer supports Box-Muller normal variates and so it not +100% compatible with NumPy (or randomstate). Box-Muller normals are slow +to generate and all functions which previously relied on Box-Muller +normals now use the faster Ziggurat implementation. + +Features +-------- + +- Replacement for NumPy's RandomState + +.. code:: python + + # import numpy.random as rnd + from randomgen import RandomGenerator, MT19937 + rnd = RandomGenerator(MT19937()) + x = rnd.standard_normal(100) + y = rnd.random_sample(100) + z = rnd.randn(10,10) + +- Default random generator is a fast generator called Xoroshiro128plus +- Support for random number generators that support independent streams + and jumping ahead so that sub-streams can be generated +- Faster random number generation, especially for normal, standard + exponential and standard gamma using the Ziggurat method + +.. code:: python + + from randomgen import RandomGenerator + # Use Xoroshiro128 + rnd = RandomGenerator() + w = rnd.standard_normal(10000, method='zig') + x = rnd.standard_exponential(10000, method='zig') + y = rnd.standard_gamma(5.5, 10000, method='zig') + +- Support for 32-bit floating randoms for core generators. Currently + supported: + + - Uniforms (``random_sample``) + - Exponentials (``standard_exponential``, both Inverse CDF and + Ziggurat) + - Normals (``standard_normal``) + - Standard Gammas (via ``standard_gamma``) + +**WARNING**: The 32-bit generators are **experimental** and subject to +change. + +**Note**: There are *no* plans to extend the alternative precision +generation to all distributions. + +- Support for filling existing arrays using ``out`` keyword argument. + Currently supported in (both 32- and 64-bit outputs) + + - Uniforms (``random_sample``) + - Exponentials (``standard_exponential``) + - Normals (``standard_normal``) + - Standard Gammas (via ``standard_gamma``) + +Included Pseudo Random Number Generators +---------------------------------------- + +This module includes a number of alternative random number generators in +addition to the MT19937 that is included in NumPy. The RNGs include: + +- `MT19937 `__, + the NumPy rng +- `dSFMT `__ a + SSE2-aware version of the MT19937 generator that is especially fast + at generating doubles +- `xoroshiro128+ `__ and + `xorshift1024\*φ `__ +- `PCG64 `__ +- ThreeFry and Philox from + `Random123 `__ + ## Differences from ``numpy.random.RandomState`` + +New Features +~~~~~~~~~~~~ + +- ``standard_normal``, ``normal``, ``randn`` and + ``multivariate_normal`` all use the much faster (100%+) Ziggurat + method. +- ``standard_gamma`` and ``gamma`` both use the much faster Ziggurat + method. +- ``standard_exponential`` ``exponential`` both support an additional + ``method`` keyword argument which can be ``inv`` or ``zig`` where + ``inv`` corresponds to the current method using the inverse CDF and + ``zig`` uses the much faster (100%+) Ziggurat method. +- Core random number generators can produce either single precision + (``np.float32``) or double precision (``np.float64``, the default) + using the optional keyword argument ``dtype`` +- Core random number generators can fill existing arrays using the + ``out`` keyword argument +- Standardizes integer-values random values as int64 for all platforms. + +New Functions +~~~~~~~~~~~~~ + +- ``random_entropy`` - Read from the system entropy provider, which is + commonly used in cryptographic applications +- ``random_raw`` - Direct access to the values produced by the + underlying PRNG. The range of the values returned depends on the + specifics of the PRNG implementation. +- ``random_uintegers`` - unsigned integers, either 32- + (``[0, 2**32-1]``) or 64-bit (``[0, 2**64-1]``) +- ``jump`` - Jumps RNGs that support it. ``jump`` moves the state a + great distance. *Only available if supported by the RNG.* +- ``advance`` - Advanced the RNG 'as-if' a number of draws were made, + without actually drawing the numbers. *Only available if supported by + the RNG.* + +Status +------ + +- Builds and passes all tests on: +- Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 (probably works on 2.6 and + 3.3) +- PC-BSD (FreeBSD) 64-bit, Python 2.7 +- OSX 64-bit, Python 3.6 +- Windows 32/64 bit (only tested on Python 2.7, 3.5 and 3.6, but should + work on 3.3/3.4) + +Version +------- + +The version matched the latest version of NumPy where +``RandoMGenerator(MT19937())`` passes all NumPy test. + +Documentation +------------- + +| Documentation for the latest release is available on `my GitHub + pages `__. Documentation for the + latest commit (unreleased) is available under +| `devel `__. + +Plans +----- + +This module is essentially complete. There are a few rough edges that +need to be smoothed. + +- Creation of additional streams from where supported (i.e. a + ``next_stream()`` method) + +Requirements +------------ + +Building requires: + +- Python (2.7, 3.4, 3.5, 3.6) +- NumPy (1.10, 1.11, 1.12, 1.13, 1.14) +- Cython (0.25+) +- tempita (0.5+), if not provided by Cython + +Testing requires pytest (3.0+). + +**Note:** it might work with other versions but only tested with these +versions. + +Development and Testing +----------------------- + +All development has been on 64-bit Linux, and it is regularly tested on +Travis-CI (Linux/OSX) and Appveyor (Windows). The library is +occasionally tested on Linux 32-bit and Free BSD 11.1. + +Basic tests are in place for all RNGs. The MT19937 is tested against +NumPy's implementation for identical results. It also passes NumPy's +test suite where still relevant. + +Installing +---------- + +.. code:: bash + + python setup.py install + +SSE2 +~~~~ + +``dSFTM`` makes use of SSE2 by default. If you have a very old computer +or are building on non-x86, you can install using: + +.. code:: bash + + python setup.py install --no-sse2 + +Windows +~~~~~~~ + +Either use a binary installer, or if building from scratch, use Python +3.6 with Visual Studio 2015 Community Edition. It can also be build +using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7, +although some modifications may be needed to ``distutils`` to find the +compiler. + +Using +----- + +The separate generators are importable from ``randomgen`` + +.. code:: python + + from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 + rg = RandomGenerator(ThreeFry()) + rg.random_sample(100) + + rg = RandomGenerator(PCG64()) + rg.random_sample(100) + + # Identical to NumPy + rg = RandomGenerator(MT19937()) + rg.random_sample(100) + +License +------- + +Standard NCSA, plus sub licenses for components. + +Performance +----------- + +Performance is promising, and even the mt19937 seems to be faster than +NumPy's mt19937. + +:: + + Speed-up relative to NumPy (Uniform Doubles) + ************************************************************ + DSFMT 137.1% + MT19937 21.0% + PCG32 101.2% + PCG64 110.7% + Philox -2.7% + ThreeFry -11.4% + ThreeFry32 -62.3% + Xoroshiro128 181.4% + Xorshift1024 141.8% + + Speed-up relative to NumPy (64-bit unsigned integers) + ************************************************************ + DSFMT 24.8% + MT19937 15.0% + PCG32 92.6% + PCG64 99.0% + Philox -20.4% + ThreeFry -21.7% + ThreeFry32 -64.4% + Xoroshiro128 164.2% + Xorshift1024 120.8% + + Speed-up relative to NumPy (Standard normals) + ************************************************************ + DSFMT 299.4% + MT19937 271.2% + PCG32 364.5% + PCG64 364.2% + Philox 256.9% + ThreeFry 236.0% + ThreeFry32 97.0% + Xoroshiro128 477.4% + Xorshift1024 360.7% + +.. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master + :target: https://travis-ci.org/bashtage/randomgen +.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true + :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master diff --git a/_randomgen/doc/source/brng/dsfmt.rst b/_randomgen/doc/source/brng/dsfmt.rst index 3432d4d043ce..bd660c938d54 100644 --- a/_randomgen/doc/source/brng/dsfmt.rst +++ b/_randomgen/doc/source/brng/dsfmt.rst @@ -5,10 +5,12 @@ Double SIMD Mersenne Twister (dSFMT) .. currentmodule:: randomgen.dsfmt -Random generator -================ + .. autoclass:: DSFMT +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/index.rst b/_randomgen/doc/source/brng/index.rst index 8bd29c1ca622..709151696272 100644 --- a/_randomgen/doc/source/brng/index.rst +++ b/_randomgen/doc/source/brng/index.rst @@ -1,6 +1,13 @@ Basic Random Number Generators ------------------------------ +The random values produced by :class:`~randomgen.generator.RandomGenerator` +are produced by a basic RNG. These basic RNGs do not directly provide +random numbers and only contains methods used for seeding, getting or +setting the state, jumping or advancing the state, and for accessing +low-level wrappers for consumption by code that can efficiently +access the functions provided, e.g., `numba `_. + Stable RNGs =========== These RNGs will be included in future releases. diff --git a/_randomgen/doc/source/brng/mt19937.rst b/_randomgen/doc/source/brng/mt19937.rst index 3fbc8f0994c4..23f8e45940a0 100644 --- a/_randomgen/doc/source/brng/mt19937.rst +++ b/_randomgen/doc/source/brng/mt19937.rst @@ -5,10 +5,11 @@ Mersenne Twister (MT19937) .. currentmodule:: randomgen.mt19937 -Random generator -================ .. autoclass:: MT19937 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/pcg32.rst b/_randomgen/doc/source/brng/pcg32.rst index 97bb341ad45b..1854b4c68dd9 100644 --- a/_randomgen/doc/source/brng/pcg32.rst +++ b/_randomgen/doc/source/brng/pcg32.rst @@ -5,10 +5,11 @@ Parallel Congruent Generator (32-bit, PCG32) .. currentmodule:: randomgen.pcg32 -Random generator -================ .. autoclass:: PCG32 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/pcg64.rst b/_randomgen/doc/source/brng/pcg64.rst index 2ef19abb2123..496825dc456a 100644 --- a/_randomgen/doc/source/brng/pcg64.rst +++ b/_randomgen/doc/source/brng/pcg64.rst @@ -5,10 +5,11 @@ Parallel Congruent Generator (64-bit, PCG64) .. currentmodule:: randomgen.pcg64 -Random generator -================ .. autoclass:: PCG64 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/philox.rst b/_randomgen/doc/source/brng/philox.rst index e12de40531a9..c2ffc44eb1fa 100644 --- a/_randomgen/doc/source/brng/philox.rst +++ b/_randomgen/doc/source/brng/philox.rst @@ -5,10 +5,11 @@ Philox Counter-based RNG .. currentmodule:: randomgen.philox -Random generator -================ .. autoclass:: Philox +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/threefry.rst b/_randomgen/doc/source/brng/threefry.rst index 6c1ff5387a5a..98141d6486c5 100644 --- a/_randomgen/doc/source/brng/threefry.rst +++ b/_randomgen/doc/source/brng/threefry.rst @@ -5,10 +5,11 @@ ThreeFry Counter-based RNG .. currentmodule:: randomgen.threefry -Random generator -================ .. autoclass:: ThreeFry +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/threefry32.rst b/_randomgen/doc/source/brng/threefry32.rst index 96576413c535..2869cbac887c 100644 --- a/_randomgen/doc/source/brng/threefry32.rst +++ b/_randomgen/doc/source/brng/threefry32.rst @@ -5,10 +5,11 @@ ThreeFry32 Counter-based RNG .. currentmodule:: randomgen.threefry32 -Random generator -================ .. autoclass:: ThreeFry32 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/xoroshiro128.rst b/_randomgen/doc/source/brng/xoroshiro128.rst index 9f8b2dfadc65..3d6735c621d2 100644 --- a/_randomgen/doc/source/brng/xoroshiro128.rst +++ b/_randomgen/doc/source/brng/xoroshiro128.rst @@ -5,10 +5,11 @@ Xoroshiro128+ .. currentmodule:: randomgen.xoroshiro128 -Random generator -================ .. autoclass:: Xoroshiro128 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/brng/xorshift1024.rst b/_randomgen/doc/source/brng/xorshift1024.rst index 5340579c0f8a..38b293dcd6f8 100644 --- a/_randomgen/doc/source/brng/xorshift1024.rst +++ b/_randomgen/doc/source/brng/xorshift1024.rst @@ -5,10 +5,11 @@ Xorshift1024*φ .. currentmodule:: randomgen.xorshift1024 -Random generator -================ .. autoclass:: Xorshift1024 +Seeding and State +================= + .. autosummary:: :toctree: generated/ diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py index b832553cb218..c89900b5579f 100644 --- a/_randomgen/doc/source/conf.py +++ b/_randomgen/doc/source/conf.py @@ -16,8 +16,8 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) from distutils.version import LooseVersion -# import guzzle_sphinx_theme -import sphinx_rtd_theme +import guzzle_sphinx_theme +# import sphinx_rtd_theme import randomgen # -- Project information ----------------------------------------------------- @@ -27,11 +27,14 @@ author = 'Kevin Sheppard' # The short X.Y version. -version = '.'.join(map(str, LooseVersion(randomgen.__version__).version[:2])) + +version = randomgen.__version__ +if '+' in version: + version = version.split('+') + version = ''.join((version[0], ' (+', version[1].split('.')[0], ')')) # The full version, including alpha/beta/rc tags. release = randomgen.__version__ - # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -44,6 +47,9 @@ extensions = [ 'sphinx.ext.napoleon', 'sphinx.ext.autodoc', + 'sphinx.ext.extlinks', + 'sphinx.ext.todo', + 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.autosummary', 'sphinx.ext.mathjax', @@ -86,14 +92,27 @@ # a list of builtin themes. # # html_theme = 'alabaster' -html_theme = 'sphinx_rtd_theme' -html_theme_path = ["_themes", ] +# html_theme = 'sphinx_rtd_theme' +# html_theme_path = ["_themes", ] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} +html_translator_class = 'guzzle_sphinx_theme.HTMLTranslator' +html_theme_path = guzzle_sphinx_theme.html_theme_path() +html_theme = 'guzzle_sphinx_theme' + +# Register the theme as an extension to generate a sitemap.xml +extensions.append("guzzle_sphinx_theme") + +# Guzzle theme options (see theme.conf for more information) +html_theme_options = { + # Set the name of the project to appear in the sidebar + "project_nav_name": project + u" " + version, +} + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". @@ -108,7 +127,12 @@ # 'searchbox.html']``. # # html_sidebars = {} +html_sidebars = { + '**': ['logo-text.html', 'globaltoc.html', 'searchbox.html'] +} +# If false, no module index is generated. +html_domain_indices = True # -- Options for HTMLHelp output --------------------------------------------- @@ -162,7 +186,7 @@ # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'RandomGen', 'RandomGen Documentation', - author, 'RandomGen', 'One line description of project.', + author, 'RandomGen', 'Alternative random number generators for Python.', 'Miscellaneous'), ] diff --git a/_randomgen/doc/source/generator.rst b/_randomgen/doc/source/generator.rst index 9f2e69a167b0..2fedc8f58b72 100644 --- a/_randomgen/doc/source/generator.rst +++ b/_randomgen/doc/source/generator.rst @@ -1,10 +1,19 @@ Random Generator ---------------- +The :class:`~randomgen.generator.RandomGenerator` provides access to +a wide range of distributions, and served as a replacement for +:class:`~numpy.random.RandomState`. The main difference between +the two is that :class:`~randomgen.generator.RandomGenerator` relies +on an additional basic RNG to manage state and generate the random +bits which are then transformed into random values from useful +distributions. The default basic RNG used by +:class:`~randomgen.generator.RandomGenerator` is +:class:`~randomgen.xoroshiro128.Xoroshiro128`. The basic RNG can be +changed by passing an instantized basic RNG to +:class:`~randomgen.generator.RandomGenerator`. .. currentmodule:: randomgen.generator -Random generator -================ .. autoclass:: RandomGenerator diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index b89679a29e62..2e9ce44d94e8 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -4,6 +4,45 @@ This package contains replacements for the NumPy :class:`~numpy.random.RandomState` object that allows the core random number generator be be changed. +Quick Start +----------- + +Like :mod:`numpy.random`, RandomGen can be used at the module level. +This uses the default :class:`~randomgen.generator.RandomGenerator` which +uses normals provided by :class:`~randomgen.xoroshiro128.Xoroshiro128`. + +.. code-block:: python + + # As replacement for numpy.random + import randomgen.generator as random + random.standard_normal() + +:class:`~randomgen.generator.RandomGenerator` can also be used as a +replacement for :class:`~numpy.random.RandomState`, although the random +values are generated by :class:`~randomgen.xoroshiro128.Xoroshiro128`. It +also isn't possible to directly seed a +:class:`~randomgen.generator.RandomGenerator`. + + +.. code-block:: python + + # As replacement for RandomState() + from randomgen import RandomGenerator + rg = RandomGenerator() + rg.standard_normal() + + +Seeds can be passed to any of the basic RNGs. Here :class:`~randomgen.mt19937.MT19937` +is used and the :class:`~randomgen.generator.RandomGenerator` is accessed via +the property :attr:`~randomgen.mt19937.MT19937.generator`. + +.. code-block:: python + + from randomgen import MT19937 + rg = MT19937(12345).generator + rg.standard_normal() + + Introduction ------------ RandomGen takes a different approach to producing random numbers from the @@ -27,7 +66,7 @@ method to initialize a generator passes a basic RNG -- :class:`~randomgen.mt19937.MT19937`, the underlying RNG in NumPy -- as the sole argument. Note that the basic RNG must be instantized. -.. ipython:: python +.. code-block:: python from randomgen import RandomGenerator, MT19937 rg = RandomGenerator(MT19937()) @@ -35,7 +74,7 @@ sole argument. Note that the basic RNG must be instantized. Seed information is directly passed to the basic RNG. -.. ipython:: python +.. code-block:: python rg = RandomGenerator(MT19937(12345)) rg.random_sample() @@ -44,7 +83,7 @@ A shorthand method is also available which uses the :meth:`~randomgen.mt19937.MT19937.generator` property from a basic RNG to access an embedded random generator. -.. ipython:: python +.. code-block:: python rg = MT19937(12345).generator rg.random_sample() @@ -130,18 +169,6 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are .. _`PCG author's page`: http://www.pcg-random.org/ .. _`Random123`: https://www.deshawresearch.com/resources_random123.html -New Features ------------- -.. toctree:: - :maxdepth: 2 - - Parallel Applications - Multithreaded Generation - new-or-different - Reading System Entropy - Comparing Performance - extending - Random Generator ---------------- .. toctree:: @@ -157,6 +184,18 @@ Basic Random Number Generators Basic Random Number Generators +New Features +------------ +.. toctree:: + :maxdepth: 2 + + Parallel Applications + Multithreaded Generation + new-or-different + Comparing Performance + extending + Reading System Entropy + Changes ~~~~~~~ .. toctree:: diff --git a/_randomgen/github_deploy_key_bashtage_core_prng.enc b/_randomgen/github_deploy_key_bashtage_core_prng.enc deleted file mode 100644 index 9487482f0020..000000000000 --- a/_randomgen/github_deploy_key_bashtage_core_prng.enc +++ /dev/null @@ -1 +0,0 @@ -gAAAAABaqV7yewp22viHuCymP0zVSCFUAlMJZNQH8yFM6OA7KVDd3CIx2b0SLNfMMq6--IyeHF7Gi5wg7UtT6dRo60F7h5-PrZx8iJjA9hqR0ovbZMPaXOQuLlnWYdw9oIBO976w93pDojwv_3QxUsDgRgmUOG7mERkitM8ihvDN17YbAZ_yyh5aX7NTbRr6DoaeL6UQkqfkaZpoflTRRRVIiJoI3aDi8jEDwhEhS_KeDP1fOnJEaJH7nR-zvRveAgbotla4XlW8IUiUP6hiOyGbk3mXZd9J0W6CPAoKbe2CV_6J4rkKd0IteJN2jsYIeNlvBf2BJ5kaIIXte6afejhyrSYcCzEgun5EuiDkqan4f0qgQSN7jjNX9vHNZ0aHNJ8HfvNFTN4fGF2xL3bPAJtGXaqIHEMF5USTRnNN5p0gKxCI5eeD73V-lpE4_LKV5OiWxC4zVFIL6BAEIdF5-cZ9Ikzqtklia17yZna3Rfbhc-0R8YYlpXWyT04c1FIIbHqNk6wsGYNyINTPTloJ6WWjwVD3oTmvFIJOBtR8Rfyk6GYM1PU2ybdbdUJc0iUXv2aL535IpnrK5Fnw4Q-lWSvI6VowJ5aY8GrnQJSyui8kA8BCkE1oblWtR6vmSwFZPjzvkZG2jUwnnaOluCjIzAm70llCO4_4b9IQkdsnNuBlVj1EYDYZQTMe4QJnBoCvB9joFp5dYauoODPcmjrXBCb8Eglg8PAAvVfLeldX2MkFGrv80pxIcN0xsI5qZmmJQOCidHEFSRLCq5Txu7OBOPCtbefs_C4mJdf7iF-F8F0DEOfr5g9CnmbIFzLomsYTzW_M4rqpkF8fxxgd5JwqRsSS36Pm6U8fb8ufpY_e4kUOd3F4qjhFK7PmPYLFdoTAaJobcgMHYNW4Y0KNTKuJM0tf51ysH4Br0EoR3CnzbBcKsgkb74OWzdgbwCdV5zvJl_b36tdd-CRZwA5A85yacuZzrVDJVYrPGwG_7Hsl7WXw-O4sVBaG_yumS1U2nC8y-gTomkvLOHq-fs27mSzcPRApC8d9C2KU9lmvgQPd7OtkPRPeypRPzU5A5UJ_EJVyG4ETUiw-bBLn_viz2HIKEg9wz0i16RSWZkpXHMzMzui2B14vp-RSjSXxK-Ou8dkTDbmw68yIzs4nHUoFA8ZN1CxUzQ2DpUzN9AcLy7q3KGh-XEIBYofsFkPbWYw-KdJi3mOYijShG-4hLGq7YI1r6VGj5Pc9Arh5zdZ_yx8PTz-g6e2-N0dvFfmNmX-bPAsIA5F8UwUVBKFP50vuJ19s8eqsnkrgTSbbF6BTOAifugLODKMeI5UANi-hCUhX3CXRIaOSzg54Ym6e-0suEQ1QygdRsVR4RU1mDf8Za6ZVEYbhuXRVwNnuSzljBjm-ejVAEcgMiTR-lzmu3kcFH_ciHLkO2kJRvv7JkFuDzux1IHM5gcBVYujIMuSFrnAUnuL2vgMfEr2DscSFmezEJz_V1R9NuY3y7hIDitQEAeXUJyUTFwDrFufGqF3IaS2nc6J-aAKVzyGm7JInrpNPH5yyMzEhVLk2V-H-kHSkCZAe240nQ2C0-eKtNCblbOVbfSCkFk2iohUkWK4A8sXSvcDELjCKzkctIANtusdFFEBEu0RswoBouQOICoP7d8ySyGs3XMDDBU_WL_TQk2TAXkVvMEvLLfDxj80JTtqyylD0XDblww6wgVt23KQpvCEpYQB_Ho0NIfkT3qgoDvUuMlz6k8L48AN58mUkqv1a6mhvc86KXsLcYYvwKO33-ErSd6FJKrEKPWr51v6RWpoO5J3ubqSxG_zekchPQ7EnJpHomTlCFK9u-_v4Tr_lTLtDW3vFIfWOyA4LvSVGp05x_HO4MBxL_XNwNzqG8tNJ5fDkOtLxCKWhoHpeA-_zIEFlfGPsfY2j8P-FAR6VyFTecTIFGJGb6ygZL-dGwJeH-FXjdRPMlD_dHxEqxx-JGHlTM297w7yTue80FosiiCkmwJ6BNQJCf-0gom2_ahJgNY_wj0psjLEkIK3pAijICcbZHBYYLyvVDn7llaUc4ziWt-TBego-Nd-5LMl9St0AdBLbGQ0AQqvm5F6MUxnp-KiDNcW0imWXePbqo7Eb4_3SE7mkeHIQY3Tssm_G7sAd6O6Q-V68tfWP8fHWOilaDeIJlahDpUbN3ygLMZwAjaDA0O6g6rSbYGSJtNIBh1VdDGBDOG9pyaRsLIMlxgtjQ7lQPQ44JQzwSa-93tpJQbA2-S_f4SaXt15HVbfr5YeJKcgHJQZfV_Ibi9cWFRp-v12wbPXJ2CkBZXUfzRiW0yR1tlsIxJUreL6SuMvnGulCsw5pbPXvyGOBPhQmKi_JCsanm1_OqQV_5-3p3g2MriHai48kbueoAwV06H9hXFtgZmDcnu8h_99Ld6vpI346xoDo4ShvJC9fU8sGf07zf9zKfpHUberx0mOU4hpyfx4xpAtPJS2ZKni2x2HJuVJkeyPWDIT2kNOOW5G04AnXhrve9CGXDRNIsjeV_q96i1hEaelLGdGkylkHQCJesJDXGN2Kc5QtYaEwRYV7MOdPiaLbPhXwrh2O25UyE-Zjc0UtV-uTCVlQon1nJWk-qyHllDZYxt1AUcwF8EXlG9G1nO7zHFnm68SmC7-Rv6z374YEio3q6PmJzAISd9I4JCPWxrnEPdUtUo8xChttRHys2AzNLRt_WbEtewf5jUeLCtmaRdLbgG-LxBa8IXRLTaQuEw1MH5nsewdoylt-0besWoyhKDtT7oQit7b3gHnCEP3BNSlqmQHodIw0KCC4YH4g4MOVB3YjvBO7lYVCNVyKFQvk2mwo0mKa_H9laljd95pikVuUphoTcbA_fneij-yaUFDu0lVFtio5Tjp7ek2ASxjzuaOgFcdY8LZmCkCx8D0ss8TOsph1JfkIA_rkkOElDc6EROJ-5eTBhQQekcIURltgRjKdrql0T8pD3FPC2Qsv6VMHyFMEpIW7qykJLwoxoendlc7bLNM7DSoIBeqOzY1vRQK1Z1fLFZVwxmtM8P6Up-Lf0aHMpe1jMkKASmj6Xtt-6jiFwS5gTSD_1tiALLgD75HZM88Hrk8zYzfr9MDTEMOiPHIjYfubsO4sve8BD12kh3CyQV26S8573TdaNRlLmTRt4YBi49--xlSrNBP6sqqoN6ZT_S0uA1JAgMHmf4Jr7DRxTfp_qpbjXvCtq7HWowhAsw4oQuF8VSx-PZZM_uzEwjHaR6TpHR3_OkjlbRBL8xR84qCgNjhFze_NxAqIbSuMoRt-n3Dv18Z7bjfokJfPTXS6FA618fZNnryIAyTZsmxjFvywwRRpiFNg6PgXB2LKHGOxpxP8nenfBJAWXD9NodI_sTS7QyaEqUp4lGEcADgLYNNDe77HyhZV1tirHesUE9CwbX-X3Nx_KQ6MhSzIZQn6AiAar5JzenyJV2kRX7Pg_tXYLQLaahnobpCBXpHuDe2_p933SdMU5xsNXQEE4ldJ_R9wfEqlgur5JCiXagLRxjzdrQIBMDXA2pfxu75ow0x7k3-Q9NrNKQQnt7R8HKItSg3m8k0XKSzJ4qgkHeRDdyzlZdA70qcCin4SiF1dYQPRinUjhEiiYdAuxOqOSNJeynwhw3-1NgitiPg03ORP0HAwlUF_SilOjhhCvTG6qQwBLjCIXjsGRNi8HDloIr2JD0gO-pfOsi89QzEm4LkdnQISmVOUFSHQsO4vGtQsnysHpccpNbo63PIEAIX9N9Cnwpi_3ZXcppUfT5FD3s_0R20sqCchys680bRVJivQh3eE79ROHKest_Uxusp14efvKocldd5B8pT9UPh5Y3ZSB2pnFBESYX0Zae3quRF6atlqbtfocixF78a4Rb1H1ZU9opJUbE5YKyQkmWtbbtDsV0OueN2ckC2gyeHtmaJmgne7oxm6JP1f1C68_-YBOGEHaG2MLW1ZS5a5F-3IGLwl6DboRRcV44Q7H5GKr-WuhjTnAlKPB-4ZfxpxCkFd9NKF3LFkrozvsJsKUqC0MdTw0oDNkO3wIxnhmJkAxJbHK0H-XQ7hDRNf_1ajj71kgP3Iv36qQdLqTvH1EBj1Buqe6T5tfKs-ijAmP8Z0ycJ45RMeAf-PEd67NKqdQHSwbhjw0FsP1LTaBQ5TUDjmITPp_nkpmhjRx70o4mm11D_05YwS3qf7-Avf2emZUGY8Ql7lSqFqblWG4DX1pqD15k4f0Vl38M6BysRu-nd7PqERV-KkvRo-LhhTbR313AtptTurr9BXnB4UN_7s86S22m8RAwMDAXURYVv-Dvy6KuITJTd8AP46Z9f0veQUpidA7wGlApOliDZezM_2qskKnF0lmp3ujuO2H2yPGIj7en0s3VwqXTC4fE8dggF6q2mgfBcrBCSd1Mf9lEs= \ No newline at end of file diff --git a/_randomgen/randomgen/__init__.py b/_randomgen/randomgen/__init__.py index fdddc4ab40d8..49094dffcd16 100644 --- a/_randomgen/randomgen/__init__.py +++ b/_randomgen/randomgen/__init__.py @@ -1,23 +1,16 @@ -from .dsfmt import DSFMT -from .generator import * -from .mt19937 import MT19937 -from .pcg32 import PCG32 -from .pcg64 import PCG64 -from .philox import Philox -from .threefry import ThreeFry -from .threefry32 import ThreeFry32 -from .xoroshiro128 import Xoroshiro128 -from .xorshift1024 import Xorshift1024 +from randomgen.dsfmt import DSFMT +from randomgen.generator import RandomGenerator +from randomgen.mt19937 import MT19937 +from randomgen.pcg32 import PCG32 +from randomgen.pcg64 import PCG64 +from randomgen.philox import Philox +from randomgen.threefry import ThreeFry +from randomgen.threefry32 import ThreeFry32 +from randomgen.xoroshiro128 import Xoroshiro128 +from randomgen.xorshift1024 import Xorshift1024 __all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'beta', 'binomial', 'bytes', 'chisquare', 'choice', 'complex_normal', 'dirichlet', 'exponential', 'f', - 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', - 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', - 'normal', 'permutation', 'pareto', 'poisson', 'power', 'rand', 'randint', 'randn', - 'random_integers', 'random_raw', 'random_sample', 'random_uintegers', 'rayleigh', 'state', 'shuffle', - 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', - 'tomaxint', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf'] + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024'] from ._version import get_versions diff --git a/_randomgen/randomgen/bounded_integers.pyx b/_randomgen/randomgen/bounded_integers.pyx index fe47bcb8a2e9..c9fb310c64ff 100644 --- a/_randomgen/randomgen/bounded_integers.pyx +++ b/_randomgen/randomgen/bounded_integers.pyx @@ -523,7 +523,7 @@ cdef object _rand_uint64(object low, object high, object size, brng_t *state, ob state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -599,7 +599,7 @@ cdef object _rand_uint32(object low, object high, object size, brng_t *state, ob state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -675,7 +675,7 @@ cdef object _rand_uint16(object low, object high, object size, brng_t *state, ob state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -751,7 +751,7 @@ cdef object _rand_uint8(object low, object high, object size, brng_t *state, obj state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -827,7 +827,7 @@ cdef object _rand_bool(object low, object high, object size, brng_t *state, obje state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -903,7 +903,7 @@ cdef object _rand_int64(object low, object high, object size, brng_t *state, obj state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -979,7 +979,7 @@ cdef object _rand_int32(object low, object high, object size, brng_t *state, obj state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -1055,7 +1055,7 @@ cdef object _rand_int16(object low, object high, object size, brng_t *state, obj state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- @@ -1131,7 +1131,7 @@ cdef object _rand_int8(object low, object high, object size, brng_t *state, obje state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index d464e9e2c841..ff4885130cf8 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -180,7 +180,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state state : basic random state State to use in the core random number generators lock : threading.Lock - Lock to prevent multiple using a single RandomState simultaneously + Lock to prevent multiple using a single generator simultaneously Returns ------- diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index cec90994346c..13ab087668d4 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -84,7 +84,7 @@ cdef class DSFMT: Notes ----- ``DSFMT`` directly provides generators for doubles, and unsigned 32 and 64- - bit integers [1]_ . These are not firectly available and must b consumed + bit integers [1]_ . These are not firectly available and must be consumed via a ``RandomGenerator`` object. The Python stdlib module "random" also contains a Mersenne Twister @@ -241,8 +241,7 @@ cdef class DSFMT: """ jump(iter=1) - Jumps the state of the random number generator as-if 2**128 random numbers - have been generated. + Jumps the state as-if 2**128 random numbers have been generated. Parameters ---------- diff --git a/_randomgen/randomgen/entropy.pyx b/_randomgen/randomgen/entropy.pyx index cec1bb9a81b6..bb1c14b4b32d 100644 --- a/_randomgen/randomgen/entropy.pyx +++ b/_randomgen/randomgen/entropy.pyx @@ -118,7 +118,7 @@ def random_entropy(size=None, source='system'): This function reads from the system entropy pool and so samples are not reproducible. In particular, it does *NOT* make use of a - RandomState, and so ``seed``, ``get_state`` and ``set_state`` have no + basic RNG, and so ``seed`` and setting ``state`` have no effect. Raises RuntimeError if the command fails. diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 5ae857e9c425..488f8152b198 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -506,8 +506,8 @@ cdef class RandomGenerator: Examples -------- - >>> RS = randomgen.mtrand.RandomState() # need a RandomState object - >>> RS.tomaxint((2,2,2)) + >>> rg = randomgen.RandomGenerator() # need a RandomGenerator object + >>> rg.tomaxint((2,2,2)) array([[[1170048599, 1600360186], [ 739731006, 1947757578]], [[1871712945, 752307660], @@ -515,7 +515,7 @@ cdef class RandomGenerator: >>> import sys >>> sys.maxint 2147483647 - >>> RS.tomaxint((2,2,2)) < sys.maxint + >>> rg.tomaxint((2,2,2)) < sys.maxint array([[[ True, True], [ True, True]], [[ True, True], @@ -4315,7 +4315,9 @@ standard_exponential = _random_generator.standard_exponential standard_gamma = _random_generator.standard_gamma standard_normal = _random_generator.standard_normal standard_t = _random_generator.standard_t -state = _random_generator.state +get_state = lambda: _random_generator.state +def set_state(state): + _random_generator.state = state tomaxint = _random_generator.tomaxint triangular = _random_generator.triangular uniform = _random_generator.uniform diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index c66f89a03e95..ca52b119c4ce 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -43,17 +43,76 @@ cdef uint64_t mt19937_raw(void *st) nogil: cdef class MT19937: """ - Prototype Basic RNG using MT19937 + MT19937(seed=None) + + Container for the Mersenne Twister pseudo-random number generator. Parameters ---------- - seed : int, array of int - Integer or array of integers between 0 and 2**64 - 1 + 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 will attempt to read data from ``/dev/urandom`` + (or the Windows analog) if available or seed from the clock otherwise. Notes ----- - Exposes no user-facing API except `state`. Designed for use in a - `RandomGenerator` object. + ``MT19937`` directly provides generators for doubles, and unsigned 32 and 64- + bit integers [1]_ . These are not firectly available and must be consumed + via a ``RandomGenerator`` object. + + The Python stdlib module "random" also contains a Mersenne Twister + pseudo-random number generator. + + **State and Seeding** + + The ``MT19937`` state vector consists of a 768 element array of + 32-bit unsigned integers plus a single integer value between 0 and 768 + indicating the current position within the main array. + + ``MT19937`` is seeded using either a single 32-bit unsigned integer + or a vector of 32-bit unsigned integers. In either case, the input seed is + used as an input (or inputs) for a hashing function, and the output of the + hashing function is used as the initial state. Using a single 32-bit value + for the seed can only initialize a small range of the possible initial + state values. + + **Compatibility Guarantee** + + ``MT19937`` make a compatibility guarantee. A fixed seed and a fixed + series of calls to ``MT19937`` methods will always produce the same + results up to roundoff error except when the values were incorrect. + Incorrect values will be fixed and the version in which the fix was + made will be noted in the relevant docstring. + + **Parallel Features** + + ``MT19937`` can be used in parallel applications by + calling the method ``jump`` 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 initialized with the same seed to ensure that the + segments come from the same sequence. + + >>> from randomgen.entropy import random_entropy + >>> from randomgen import RandomGenerator, MT19937 + >>> seed = random_entropy() + >>> rs = [RandomGenerator(MT19937(seed) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + rs[i].jump(i) + + 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 cdef brng_t *_brng @@ -134,18 +193,20 @@ cdef class MT19937: def seed(self, seed=None): """ - seed(seed=None, stream=None) + seed(seed=None) Seed the generator. - 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, optional - Seed for ``RandomState``. + seed : {None, int, array_like}, optional + 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] or ``None`` (the default). If `seed` is ``None``, + then ``MT19937`` will try to read entropy from ``/dev/urandom`` + (or the Windows analog) if available to produce a 64-bit + seed. If unavailable, a 64-bit hash of the time and process + ID is used. Raises ------ @@ -174,13 +235,38 @@ cdef class MT19937: obj = obj.astype(np.uint32, casting='unsafe', order='C') mt19937_init_by_array(self.rng_state, obj.data, np.PyArray_DIM(obj, 0)) - def jump(self): - mt19937_jump(self.rng_state) + def jump(self, np.npy_intp iter=1): + """ + jump(iter=1) + + Jumps the state as-if 2**128 random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the brng. + + Returns + ------- + self : DSFMT + PRNG jumped iter times + """ + cdef np.npy_intp i + for i in range(iter): + mt19937_jump(self.rng_state) return self @property def state(self): - """Get or set the PRNG state""" + """ + 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] diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index a2cb4c71ec23..b739a12b5d7f 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -95,7 +95,7 @@ cdef class PCG32: >>> from randomgen import RandomGenerator, PCG32 >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] - The alternative method is to call ``advance`` on a single RandomState to + The alternative method is to call ``advance`` on a instance to produce non-overlapping sequences. >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] @@ -200,14 +200,14 @@ cdef class PCG32: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``PCG32`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``PCG32``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``PCG32``. inc : int, optional Increment to use for PCG stream diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index bd3a24440c44..249587a49e5d 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -110,7 +110,7 @@ cdef class PCG64: >>> from randomgen import RandomGenerator, PCG64 >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] - The alternative method is to call ``advance`` on a single RandomState to + The alternative method is to call ``advance`` on a single instance to produce non-overlapping sequences. >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] @@ -221,14 +221,14 @@ cdef class PCG64: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``PCG64`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``PCG64``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``PCG64``. inc : int, optional Increment to use for PCG stream diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index 75213ef5aa58..f79bb4ca3d93 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -227,14 +227,14 @@ cdef class Philox: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``Philox`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``Philox``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``Philox``. counter : {int array}, optional Positive integer less than 2**256 containing the counter position or a 4 element array of uint64 containing the counter @@ -329,8 +329,7 @@ cdef class Philox: """ jump(iter=1) - Jumps the state of the random number generator as-if 2**128 random - numbers have been generated. + Jumps the state as-if 2**128 random numbers have been generated. Parameters ---------- diff --git a/_randomgen/randomgen/pickle.py b/_randomgen/randomgen/pickle.py index 4ec96663d4a3..dbb5324e40dc 100644 --- a/_randomgen/randomgen/pickle.py +++ b/_randomgen/randomgen/pickle.py @@ -22,7 +22,7 @@ def __generator_ctor(brng_name='mt19937'): """ - Pickling helper function that returns a mod_name.RandomState object + Pickling helper function that returns a RandomGenerator object Parameters ---------- @@ -48,7 +48,7 @@ def __generator_ctor(brng_name='mt19937'): def __brng_ctor(brng_name='mt19937'): """ - Pickling helper function that returns a mod_name.RandomState object + Pickling helper function that returns a basic RNG object Parameters ---------- diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index dd187f25d8db..2e49c1f18ff6 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -535,13 +535,14 @@ def test_dir(self): assert (len(nprs_d.difference(rs_d)) == 0) npmod = dir(numpy.random) - mod = dir(randomgen) - known_exlcuded = ['__all__', 'Tester', 'info', 'bench', - '__RandomState_ctor', 'mtrand', 'test', - '__warningregistry__', '_numpy_tester', 'division', - 'get_state', 'set_state', 'seed', 'ranf', 'random', - 'sample', 'absolute_import', 'print_function', - 'RandomState'] + mod = dir(randomgen.generator) + known_exlcuded = ['__all__', '__cached__', '__path__', 'Tester', + 'info', 'bench', '__RandomState_ctor', 'mtrand', + 'test', '__warningregistry__', '_numpy_tester', + 'division', 'get_state', 'set_state', 'seed', + 'ranf', 'random', 'sample', 'absolute_import', + 'print_function', 'RandomState'] mod += known_exlcuded diff = set(npmod).difference(mod) + print(diff) assert_equal(len(diff), 0) diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index 47dde07e0bd2..50e6b9ecd5ee 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -222,14 +222,14 @@ cdef class ThreeFry: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``ThreeFry`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``ThreeFry``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``ThreeFry``. counter : {None, int array}, optional Positive integer less than 2**256 containing the counter position or a 4 element array of uint64 containing the counter @@ -321,8 +321,7 @@ cdef class ThreeFry: """ jump(iter=1) - Jumps the state of the random number generator as-if 2**128 random - numbers have been generated. + Jumps the state as-if 2**128 random numbers have been generated. Parameters ---------- diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index 70210910c6d0..41de1688860f 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -222,14 +222,14 @@ cdef class ThreeFry32: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``ThreeFry32`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``ThreeFry32``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``ThreeFry32``. counter : {int array}, optional Positive integer less than 2**128 containing the counter position or a 4 element array of uint32 containing the counter @@ -316,8 +316,7 @@ cdef class ThreeFry32: """ jump(iter=1) - Jumps the state of the random number generator as-if 2**64 random - numbers have been generated. + Jumps the state as-if 2**64 random numbers have been generated. Parameters ---------- diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index ae02372898df..edddf4232b56 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -46,13 +46,13 @@ cdef class Xoroshiro128: Random seed initializing the pseudo-random number generator. Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``xoroshiro128plus.RandomState`` will try to read data from + then ``Xoroshiro128`` will try to read data from ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a 64-bit hash of the time and process ID is used. Notes ----- - xoroshiro128+ is the successor to xorshift128+ written by David Blackman and + xoroshiro128+ is the successor to xorshift128+ written by David Blackman and Sebastiano Vigna. It is a 64-bit PRNG that uses a carefully handcrafted shift/rotate-based linear transformation. This change both improves speed and statistical quality of the PRNG [1]_. xoroshiro128+ has a period of @@ -213,8 +213,7 @@ cdef class Xoroshiro128: """ jump(iter=1) - Jumps the state of the random number generator as-if 2**64 random numbers - have been generated. + Jumps the state as-if 2**64 random numbers have been generated. Parameters ---------- diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index 86fd5d5f1346..b9149f277736 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -42,7 +42,7 @@ cdef class Xorshift1024: Container for the xorshift1024*φ pseudo-random number generator. xorshift1024*φ is a 64-bit implementation of Saito and Matsumoto's XSadd - generator [1]_ (see also [2]_, [3]_, [4]_). xorshift1024* has a period of + generator [1]_ (see also [2]_, [3]_, [4]_). xorshift1024*φ has a period of :math:`2^{1024} - 1` and supports jumping the sequence in increments of :math:`2^{512}`, which allows multiple non-overlapping sequences to be generated. @@ -62,7 +62,7 @@ cdef class Xorshift1024: Random seed initializing the pseudo-random number generator. Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``xorshift1024.RandomState`` will try to read data from + then ``Xorshift1024`` will try to read data from ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a 64-bit hash of the time and process ID is used. @@ -212,14 +212,14 @@ cdef class Xorshift1024: Seed the generator. - This method is called when ``RandomState`` is initialized. It can be + This method is called when ``Xorshift1024`` is initialized. It can be called again to re-seed the generator. For details, see - ``RandomState``. + ``Xorshift1024``. Parameters ---------- seed : int, optional - Seed for ``RandomState``. + Seed for ``Xorshift1024``. Raises ------ diff --git a/_randomgen/requirements.txt b/_randomgen/requirements.txt index a02ebc02a654..f2f2e06ad0aa 100644 --- a/_randomgen/requirements.txt +++ b/_randomgen/requirements.txt @@ -1,4 +1,4 @@ -numpy -cython -cffi -pandas +numpy>=1.10 +cython>=0.24 +setuptools +wheel \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 11704f3516cc..2fc6f49b519e 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -19,8 +19,21 @@ raise ImportError('tempita required to install, ' 'use pip install tempita') +try: + import pypandoc + # With an input file: it will infer the input format from the filename + with open('README.rst', 'w') as readme: + readme.write(pypandoc.convert_file('README.md', 'rst')) +except ImportError: + import warnings + warnings.warn( + 'Unable to import pypandoc. Do not use this as a release build!') + import versioneer +with open('requirements.txt') as f: + required = f.read().splitlines() + Cython.Compiler.Options.annotate = True USE_SSE2 = True if not '--no-sse2' in sys.argv else False @@ -187,17 +200,43 @@ ] +classifiers = ['Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: End Users/Desktop', + 'Intended Audience :: Financial and Insurance Industry', + 'Intended Audience :: Information Technology', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX :: Linux', + 'Operating System :: Unix', + 'Programming Language :: C', + 'Programming Language :: Cython', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Topic :: Adaptive Technologies', + 'Topic :: Artistic Software', + 'Topic :: Office/Business :: Financial', + 'Topic :: Scientific/Engineering', + 'Topic :: Security :: Cryptography'] + + class BinaryDistribution(Distribution): def is_pure(self): return False setup( + name='randomgen', version=versioneer.get_version(), + classifiers=classifiers, cmdclass=versioneer.get_cmdclass(), ext_modules=cythonize(extensions, compile_time_env={ "PCG_EMULATED_MATH": PCG_EMULATED_MATH}), - name='randomgen', packages=find_packages(), package_dir={'randomgen': './randomgen'}, package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in']}, @@ -206,8 +245,13 @@ def is_pure(self): author='Kevin Sheppard', author_email='kevin.k.sheppard@gmail.com', distclass=BinaryDistribution, + long_description=open('README.rst').read(), description='Random generator supporting multiple PRNGs', - url='https://github.com/bashtage/core-prng', - keywords=['pseudo random numbers', 'PRNG', 'Python'], - zip_safe=False + url='https://github.com/bashtage/randomgen', + keywords=['pseudo random numbers', 'PRNG', 'RNG', 'RandomState', 'random', + 'random numbers', 'parallel random numbers', 'PCG', + 'XorShift', 'dSFMT', 'MT19937', 'Random123', 'ThreeFry', + 'Philox'], + zip_safe=False, + install_requires=required ) From 5d3d9550dddcdd928e179c02cb8dea9a04446d95 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 15 Mar 2018 16:20:46 +0000 Subject: [PATCH 065/138] ENH: Restore filler Swap double filler for old version Restore fillers to distributions Replace pointer size Switch to uintptr_t for 32 bit platforms --- _randomgen/randomgen/common.pxd | 4 +- _randomgen/randomgen/common.pyx | 9 ++-- _randomgen/randomgen/distributions.pxd | 4 ++ _randomgen/randomgen/dsfmt.pyx | 24 +++++----- _randomgen/randomgen/generator.pyx | 8 ++-- _randomgen/randomgen/mt19937.pyx | 24 +++++----- _randomgen/randomgen/pcg32.pyx | 24 +++++----- _randomgen/randomgen/pcg64.pyx | 24 +++++----- _randomgen/randomgen/philox.pyx | 24 +++++----- .../src/distributions/distributions.c | 45 ++++++++++++++++++- .../src/distributions/distributions.h | 4 ++ _randomgen/randomgen/threefry.pyx | 24 +++++----- _randomgen/randomgen/xoroshiro128.pyx | 24 +++++----- _randomgen/randomgen/xorshift1024.pyx | 24 +++++----- 14 files changed, 159 insertions(+), 107 deletions(-) diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd index 33a7bef2629a..e4ce62818370 100644 --- a/_randomgen/randomgen/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -1,5 +1,6 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, - int8_t, int16_t, int32_t, int64_t, intptr_t) + int8_t, int16_t, int32_t, int64_t, intptr_t, + uintptr_t) from libc.math cimport sqrt from distributions cimport brng_t @@ -30,6 +31,7 @@ cdef extern from "src/aligned_malloc/aligned_malloc.h": cdef void *PyArray_calloc_aligned(size_t n, size_t s); cdef void PyArray_free_aligned(void *p); +ctypedef double (*random_double_fill)(brng_t *state, np.npy_intp count, double* out) nogil ctypedef double (*random_double_0)(brng_t *state) nogil ctypedef double (*random_double_1)(brng_t *state, double a) nogil ctypedef double (*random_double_2)(brng_t *state, double a, double b) nogil diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index 101a14270635..e28342e68442 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -70,14 +70,16 @@ cdef check_output(object out, object dtype, object size): cdef object double_fill(void *func, brng_t *state, object size, object lock, object out): - cdef random_double_0 random_func = (func) + cdef random_double_fill random_func = (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: - return random_func(state) + random_func(state, 1, &out_val) + return out_val if out is not None: check_output(out, np.float64, size) @@ -88,8 +90,7 @@ cdef object double_fill(void *func, brng_t *state, object size, object lock, obj n = np.PyArray_SIZE(out_array) out_array_data = np.PyArray_DATA(out_array) with lock, nogil: - for i in range(n): - out_array_data[i] = random_func(state) + random_func(state, n, out_array_data) return out_array cdef object float_fill(void *func, brng_t *state, object size, object lock, object out): diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index 29ee591e3a4d..202c7439de0a 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -36,9 +36,13 @@ cdef extern from "src/distributions/distributions.h": ctypedef brng brng_t double random_double(brng_t *brng_state) nogil + void random_double_fill(brng_t* brng_state, np.npy_intp cnt, double *out) double random_standard_exponential(brng_t *brng_state) nogil + void random_standard_exponential_fill(brng_t *brng_state, np.npy_intp cnt, double *out) double random_standard_exponential_zig(brng_t *brng_state) nogil + void random_standard_exponential_zig_fill(brng_t *brng_state, np.npy_intp cnt, double *out) double random_gauss_zig(brng_t* brng_state) nogil + void random_gauss_zig_fill(brng_t *brng_state, np.npy_intp count, double *out) nogil double random_standard_gamma_zig(brng_t *brng_state, double shape) nogil float random_float(brng_t *brng_state) nogil diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index 13ab087668d4..fa70b4ef52b4 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -331,18 +331,18 @@ cdef class DSFMT: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&dsfmt_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&dsfmt_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&dsfmt_uint32, + ctypes.cast(&dsfmt_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&dsfmt_double, + ctypes.cast(&dsfmt_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -370,12 +370,12 @@ cdef class DSFMT: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 488f8152b198..1aa630dfdaa6 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -323,7 +323,7 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double, self._brng, size, self.lock, out) + return double_fill(&random_double_fill, self._brng, size, self.lock, out) elif key == 'float32': return float_fill(&random_float, self._brng, size, self.lock, out) else: @@ -465,9 +465,9 @@ cdef class RandomGenerator: key = np.dtype(dtype).name if key == 'float64': if method == u'zig': - return double_fill(&random_standard_exponential_zig, self._brng, size, self.lock, out) + return double_fill(&random_standard_exponential_zig_fill, self._brng, size, self.lock, out) else: - return double_fill(&random_standard_exponential, self._brng, size, self.lock, out) + return double_fill(&random_standard_exponential_fill, self._brng, size, self.lock, out) elif key == 'float32': if method == u'zig': return float_fill(&random_standard_exponential_zig_f, self._brng, size, self.lock, out) @@ -1206,7 +1206,7 @@ cdef class RandomGenerator: """ key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_gauss_zig, self._brng, size, self.lock, out) + return double_fill(&random_gauss_zig_fill, self._brng, size, self.lock, out) elif key == 'float32': return float_fill(&random_gauss_zig_f, self._brng, size, self.lock, out) diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index ca52b119c4ce..e05a78e481ff 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -317,18 +317,18 @@ cdef class MT19937: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&mt19937_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&mt19937_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&mt19937_uint32, + ctypes.cast(&mt19937_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&mt19937_double, + ctypes.cast(&mt19937_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -356,12 +356,12 @@ cdef class MT19937: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index b739a12b5d7f..5043db8c66a4 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -345,18 +345,18 @@ cdef class PCG32: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&pcg32_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&pcg32_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&pcg32_uint32, + ctypes.cast(&pcg32_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&pcg32_double, + ctypes.cast(&pcg32_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -384,12 +384,12 @@ cdef class PCG32: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index 249587a49e5d..c00d91966864 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -404,18 +404,18 @@ cdef class PCG64: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&pcg64_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&pcg64_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&pcg64_uint32, + ctypes.cast(&pcg64_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&pcg64_double, + ctypes.cast(&pcg64_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -443,12 +443,12 @@ cdef class PCG64: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index f79bb4ca3d93..7c27467e9bd3 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -412,18 +412,18 @@ cdef class Philox: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&philox_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&philox_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&philox_uint32, + ctypes.cast(&philox_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&philox_double, + ctypes.cast(&philox_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -451,12 +451,12 @@ cdef class Philox: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index 2ed6d26c3dfe..246cddb444e8 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -7,14 +7,34 @@ float random_float(brng_t *brng_state) { return next_float(brng_state); } double random_double(brng_t *brng_state) { return next_double(brng_state); } +static NPY_INLINE double next_standard_exponential(brng_t *brng_state) +{ + return -log(1.0 - next_double(brng_state)); +} + double random_standard_exponential(brng_t *brng_state) { - return -log(1.0 - next_double(brng_state)); + return next_standard_exponential(brng_state); +} + +void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, double *out) +{ + npy_intp i; + for (i = 0; i < cnt; i++) { + out[i] = next_standard_exponential(brng_state); + } } float random_standard_exponential_f(brng_t *brng_state) { return -logf(1.0f - next_float(brng_state)); } +void random_double_fill(brng_t* brng_state, npy_intp cnt, double *out) +{ + npy_intp i; + for (i = 0; i < cnt; i++) { + out[i] = next_double(brng_state); + } +} /* double random_gauss(brng_t *brng_state) { if (brng_state->has_gauss) { @@ -99,6 +119,16 @@ double random_standard_exponential_zig(brng_t *brng_state) { return standard_exponential_zig(brng_state); } + +void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, double *out) +{ + npy_intp i; + for (i = 0; i < cnt; i++) { + out[i] = standard_exponential_zig(brng_state); + } +} + + static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state); static float standard_exponential_zig_unlikely_f(brng_t *brng_state, @@ -133,7 +163,7 @@ float random_standard_exponential_zig_f(brng_t *brng_state) { return standard_exponential_zig_f(brng_state); } -double random_gauss_zig(brng_t *brng_state) { +static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { uint64_t r; int sign; int64_t rabs; @@ -167,6 +197,17 @@ double random_gauss_zig(brng_t *brng_state) { } } +double random_gauss_zig(brng_t *brng_state) { + return next_gauss_zig(brng_state); +} + +void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, double *out) { + npy_intp i; + for (i = 0; i < cnt; i++) { + out[i] = next_gauss_zig(brng_state); + } +} + float random_gauss_zig_f(brng_t *brng_state) { uint32_t r; int sign; diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index 6bbbcd8f0f05..6785405c7aa0 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -95,6 +95,7 @@ static NPY_INLINE double next_double(brng_t *brng_state) { DECLDIR float random_float(brng_t *brng_state); DECLDIR double random_double(brng_t *brng_state); +DECLDIR void random_double_fill(brng_t* brng_state, npy_intp cnt, double *out); DECLDIR int64_t random_positive_int64(brng_t *brng_state); DECLDIR int32_t random_positive_int32(brng_t *brng_state); @@ -102,8 +103,10 @@ DECLDIR int64_t random_positive_int(brng_t *brng_state); DECLDIR uint64_t random_uint(brng_t *brng_state); DECLDIR double random_standard_exponential(brng_t *brng_state); +DECLDIR void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, double *out); DECLDIR float random_standard_exponential_f(brng_t *brng_state); DECLDIR double random_standard_exponential_zig(brng_t *brng_state); +DECLDIR void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, double *out); DECLDIR float random_standard_exponential_zig_f(brng_t *brng_state); /* @@ -112,6 +115,7 @@ DECLDIR float random_gauss_f(brng_t *brng_state); */ DECLDIR double random_gauss_zig(brng_t *brng_state); DECLDIR float random_gauss_zig_f(brng_t *brng_state); +DECLDIR void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, double *out); /* DECLDIR double random_standard_gamma(brng_t *brng_state, double shape); diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index 50e6b9ecd5ee..e347959c3aad 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -405,18 +405,18 @@ cdef class ThreeFry: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&threefry_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&threefry_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&threefry_uint32, + ctypes.cast(&threefry_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&threefry_double, + ctypes.cast(&threefry_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -444,12 +444,12 @@ cdef class ThreeFry: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index edddf4232b56..01b51376a38b 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -291,18 +291,18 @@ cdef class Xoroshiro128: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoroshiro128_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoroshiro128_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_uint32, + ctypes.cast(&xoroshiro128_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_double, + ctypes.cast(&xoroshiro128_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -330,12 +330,12 @@ cdef class Xoroshiro128: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index b9149f277736..aef61e9abed7 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -324,18 +324,18 @@ cdef class Xorshift1024: import ctypes - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xorshift1024_uint64, + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xorshift1024_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&xorshift1024_uint32, + ctypes.cast(&xorshift1024_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&xorshift1024_double, + ctypes.cast(&xorshift1024_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) + ctypes.c_void_p(self._brng)) return self.ctypes @property @@ -363,12 +363,12 @@ cdef class Xorshift1024: raise ImportError('cffi is cannot be imported.') ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) return self.cffi @property From 9e18b77c125dc37358082fd1d35fa6706411ffed Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 16 Mar 2018 23:32:17 +0000 Subject: [PATCH 066/138] BLD: Ensure emulated math is used in 32 bit platforms Ensure 32 bit platforms emulate Fix missing static in pcg --- _randomgen/randomgen/src/pcg32/pcg32.h | 21 +++++++------- _randomgen/randomgen/src/pcg64/pcg64.h | 38 ++++++++++++++------------ _randomgen/setup.py | 10 +++++-- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/_randomgen/randomgen/src/pcg32/pcg32.h b/_randomgen/randomgen/src/pcg32/pcg32.h index 5ab59cc85105..15410bd821c7 100644 --- a/_randomgen/randomgen/src/pcg32/pcg32.h +++ b/_randomgen/randomgen/src/pcg32/pcg32.h @@ -15,7 +15,7 @@ struct pcg_state_setseq_64 { uint64_t inc; }; -inline uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) { +static 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; @@ -24,15 +24,15 @@ inline uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) { #endif } -inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) { +static inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) { rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc; } -inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { +static inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u); } -inline uint32_t +static inline uint32_t pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) { uint64_t oldstate; oldstate = rng->state; @@ -40,8 +40,9 @@ pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) { return pcg_output_xsh_rr_64_32(oldstate); } -inline void pcg_setseq_64_srandom_r(struct pcg_state_setseq_64 *rng, - uint64_t initstate, uint64_t initseq) { +static 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); @@ -52,8 +53,8 @@ inline void pcg_setseq_64_srandom_r(struct pcg_state_setseq_64 *rng, extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, uint64_t cur_plus); -inline void pcg_setseq_64_advance_r(struct pcg_state_setseq_64 *rng, - uint64_t delta) { +static 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); } @@ -63,9 +64,7 @@ typedef struct pcg_state_setseq_64 pcg32_random_t; #define pcg32_srandom_r pcg_setseq_64_srandom_r #define pcg32_advance_r pcg_setseq_64_advance_r -typedef struct s_pcg32_state { - pcg32_random_t *pcg_state; -} pcg32_state; +typedef struct s_pcg32_state { pcg32_random_t *pcg_state; } pcg32_state; static inline uint64_t pcg32_next64(pcg32_state *state) { return (uint64_t)(pcg32_random_r(state->pcg_state)) << 32 | diff --git a/_randomgen/randomgen/src/pcg64/pcg64.h b/_randomgen/randomgen/src/pcg64/pcg64.h index df265cb1a3a4..f3611ce08d2f 100644 --- a/_randomgen/randomgen/src/pcg64/pcg64.h +++ b/_randomgen/randomgen/src/pcg64/pcg64.h @@ -51,7 +51,7 @@ typedef struct { uint64_t low; } pcg128_t; -inline pcg128_t PCG_128BIT_CONSTANT(uint64_t high, uint64_t low) { +static inline pcg128_t PCG_128BIT_CONSTANT(uint64_t high, uint64_t low) { pcg128_t result; result.high = high; result.low = low; @@ -78,13 +78,13 @@ typedef struct { , PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) \ } -inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { +static inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) { return (value >> rot) | (value << ((-rot) & 63)); } #ifdef PCG_EMULATED_128BIT_MATH -inline pcg128_t _pcg128_add(pcg128_t a, pcg128_t b) { +static inline pcg128_t _pcg128_add(pcg128_t a, pcg128_t b) { pcg128_t result; result.low = a.low + b.low; @@ -92,7 +92,8 @@ inline pcg128_t _pcg128_add(pcg128_t a, pcg128_t b) { return result; } -inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, uint64_t *z0) { +static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, + uint64_t *z0) { uint64_t x0, x1, y0, y1; uint64_t w0, w1, w2, t; /* Lower 64 bits are straightforward clock-arithmetic. */ @@ -110,7 +111,7 @@ inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, uint64_t *z0) { *z1 = x1 * y1 + w2 + (w1 >> 32); } -inline pcg128_t _pcg128_mult(pcg128_t a, pcg128_t b) { +static inline pcg128_t _pcg128_mult(pcg128_t a, pcg128_t b) { uint64_t h1; pcg128_t result; @@ -120,17 +121,18 @@ inline pcg128_t _pcg128_mult(pcg128_t a, pcg128_t b) { return result; } -inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { +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); } -inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { +static inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { return pcg_rotr_64(state.high ^ state.low, state.high >> 58u); } -inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng, - pcg128_t initstate, pcg128_t initseq) { +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 & 0x800000000000ULL; @@ -142,17 +144,18 @@ inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng, #else /* PCG_EMULATED_128BIT_MATH */ -inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { +static inline void pcg_setseq_128_step_r(pcg_state_setseq_128 *rng) { rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; } -inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) { +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); } -inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng, - pcg128_t initstate, pcg128_t initseq) { +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); @@ -162,12 +165,13 @@ inline void pcg_setseq_128_srandom_r(pcg_state_setseq_128 *rng, #endif /* PCG_EMULATED_128BIT_MATH */ -inline uint64_t pcg_setseq_128_xsl_rr_64_random_r(pcg_state_setseq_128 *rng) { +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); } -inline uint64_t +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; @@ -181,8 +185,8 @@ pcg_setseq_128_xsl_rr_64_boundedrand_r(pcg_state_setseq_128 *rng, extern pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult, pcg128_t cur_plus); -inline void pcg_setseq_128_advance_r(pcg_state_setseq_128 *rng, - pcg128_t delta) { +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); } diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 2fc6f49b519e..2bd987367eba 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -44,15 +44,20 @@ EXTRA_INCLUDE_DIRS = [] EXTRA_LINK_ARGS = [] -EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99'] +# Undef for manylinux +EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99', '-U__GNUC_GNU_INLINE__'] if os.name == 'nt': EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] - PCG_EMULATED_MATH = True if DEBUG: EXTRA_LINK_ARGS += ['-debug'] EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] if sys.version_info < (3, 0): EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] +PCG64_DEFS = [] +if sys.maxsize < 2 ** 32 or os.name == 'nt': + # Force emulated mode here + PCG_EMULATED_MATH = True + PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] DSFMT_DEFS = [('DSFMT_MEXP', '19937')] if USE_SSE2: @@ -125,6 +130,7 @@ join(MOD_DIR, 'src', 'pcg64')], extra_compile_args=EXTRA_COMPILE_ARGS, + define_macros=PCG64_DEFS, extra_link_args=EXTRA_LINK_ARGS ), Extension("randomgen.pcg32", From ce30b74be2c8cd3de7ac2c85021d64aa99b8dd09 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 17 Mar 2018 00:03:51 +0000 Subject: [PATCH 067/138] TST: Improve testing and build --- _randomgen/.travis.yml | 6 + _randomgen/randomgen/bounded_integers.pxd | 39 - _randomgen/randomgen/bounded_integers.pyx | 1181 ------------------- _randomgen/randomgen/tests/__init__.py | 0 _randomgen/randomgen/tests/data/__init__.py | 0 _randomgen/setup.py | 3 +- 6 files changed, 8 insertions(+), 1221 deletions(-) delete mode 100644 _randomgen/randomgen/bounded_integers.pxd delete mode 100644 _randomgen/randomgen/bounded_integers.pyx create mode 100644 _randomgen/randomgen/tests/__init__.py create mode 100644 _randomgen/randomgen/tests/data/__init__.py diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 1c950fdab6b9..b11f5b73055a 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -12,6 +12,10 @@ env: # Doctr deploy key for bashtage/randomgen - secure: "czwFlflS1lcfbSQ9ktv+pLAPV9/6+wmwiMTyIYyv5xgQVWRL5NRebWH+ZhQ6s2T5x17wFMtlafcAvkdV0CHQZLru34V2UNldCapuEtQ8b32EDHBXHKbs45b7SSkLx4TFXdjiJurleY4ZIKle0gX6BW21zYBwaHJqbN6I8nRv9Rp47XEU1UV1Mdf/PhfTnxY31rFrPYL77xeWJzoFfT8zao39V4gQds+1Ag7FjdNVdSDVKwDduF4kS7tIbKqb4M+jsbc3PIKyP9nyQpEQF5ebJuG7mqXJhVJGEL83rBx8MLFPA/1X3cUzKacgKyp2+Wmlt0EVhwCa1aRf9cSK6I7TbMC7/eGtDnC2ToiRlFJurVRblaEmhzVQS1yQ4Dkooqsj9hNVl6nhu7JfR52GLogns33Ec/yYuRcWcULKSlR5Cerfef/5YijBEhlr9X76SJiOpjvS4lwWFYX+h8xzuVhRLGwIVB9oQNllxYItzcDSGmRx+EOMXWASHmoUDnBOZg4GMVukqOcF5l0ynoepiA1YHLdZlMy6SB3P7BZKF/aNCOn9nXw+N9X4U/yUpkM3Pb7HoGdNrC8RO4SwrNjGrarkdEB6e1lBReK/dqcylaF/mpK9VLpfQszDI8xnR4VCmlEM+le0xOsyHfeGciabdI4KH0i0SfYl4ls5XrN+CaqFWdo=" +cache: + directories: + - $HOME/.cache/pip + matrix: fast_finish: true include: @@ -49,6 +53,8 @@ before_install: - export BUILD_DIR=${PWD} - if [[ ${DOCBUILD} == true ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi - if [[ ${DOCBUILD} == true ]]; then conda install numba pandas matplotlib --quiet; fi + - gcc --version || true + - clang --version || true install: - python setup.py develop diff --git a/_randomgen/randomgen/bounded_integers.pxd b/_randomgen/randomgen/bounded_integers.pxd deleted file mode 100644 index f15f0f5d9d1e..000000000000 --- a/_randomgen/randomgen/bounded_integers.pxd +++ /dev/null @@ -1,39 +0,0 @@ -from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, - int8_t, int16_t, int32_t, int64_t, intptr_t) -from common cimport brng_t -import numpy as np -cimport numpy as np -ctypedef np.npy_bool bool_t - -_randint_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) - } - -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 - -cdef object _rand_uint64(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_uint32(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_uint16(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_uint8(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_bool(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_int64(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_int32(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_int16(object low, object high, object size, brng_t *state, object lock) -cdef object _rand_int8(object low, object high, object size, brng_t *state, object lock) diff --git a/_randomgen/randomgen/bounded_integers.pyx b/_randomgen/randomgen/bounded_integers.pyx deleted file mode 100644 index c9fb310c64ff..000000000000 --- a/_randomgen/randomgen/bounded_integers.pyx +++ /dev/null @@ -1,1181 +0,0 @@ -#!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True - -import numpy as np -cimport numpy as np -from distributions cimport * -np.import_array() - - - - -cdef object _rand_uint32_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint32_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint32_t *out_data - cdef uint64_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, 0)): - raise ValueError('low is out of bounds for uint32') - if np.any(np.greater(high_arr, 0X100000000ULL)): - raise ValueError('high is out of bounds for uint32') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.uint32) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.uint32) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint32(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_uint16_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint16_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint16_t *out_data - cdef uint32_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, 0)): - raise ValueError('low is out of bounds for uint16') - if np.any(np.greater(high_arr, 0X10000UL)): - raise ValueError('high is out of bounds for uint16') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT32, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT32, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.uint16) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.uint16) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint16(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_uint8_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint8_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint8_t *out_data - cdef uint16_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, 0)): - raise ValueError('low is out of bounds for uint8') - if np.any(np.greater(high_arr, 0X100UL)): - raise ValueError('high is out of bounds for uint8') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT16, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT16, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.uint8) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.uint8) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint8(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_bool_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef bool_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef bool_t *out_data - cdef uint8_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, 0)): - raise ValueError('low is out of bounds for bool') - if np.any(np.greater(high_arr, 0x2UL)): - raise ValueError('high is out of bounds for bool') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT8, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_UINT8, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.bool_) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.bool_) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_bool(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_int32_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint32_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint32_t *out_data - cdef uint64_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, -0x80000000LL)): - raise ValueError('low is out of bounds for int32') - if np.any(np.greater(high_arr, 0x80000000LL)): - raise ValueError('high is out of bounds for int32') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.int32) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.int32) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint32(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_int16_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint16_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint16_t *out_data - cdef uint32_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, -0x8000LL)): - raise ValueError('low is out of bounds for int16') - if np.any(np.greater(high_arr, 0x8000LL)): - raise ValueError('high is out of bounds for int16') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT32, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT32, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.int16) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.int16) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint16(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - -cdef object _rand_int8_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" - cdef uint8_t rng, last_rng, off, val, mask, out_val - cdef uint32_t buf - cdef uint8_t *out_data - cdef uint16_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 - low_arr = low - high_arr = high - if np.any(np.less(low_arr, -0x80LL)): - raise ValueError('low is out of bounds for int8') - if np.any(np.greater(high_arr, 0x80LL)): - raise ValueError('high is out of bounds for int8') - if np.any(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') - - low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT16, np.NPY_ALIGNED | np.NPY_FORCECAST) - high_arr = np.PyArray_FROM_OTF(high, np.NPY_INT16, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.int8) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.int8) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = ((high_v - 1) - low_v) - off = (low_v) - - if rng != last_rng: - # Smallest bit mask >= max - mask = _gen_mask(rng) - - out_data[i] = random_buffered_bounded_uint8(state, off, rng, mask, &buf_rem, &buf) - - np.PyArray_MultiIter_NEXT(it) - return out_arr - - - -cdef object _rand_uint64_broadcast(object low, object high, object size, brng_t *state, object lock): - """Array path for 64-bit integer types""" - 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 uint64_t *highm1_data - cdef uint64_t low_v, high_v - cdef uint64_t rng, last_rng, val, mask, off, out_val - - low_arr = low - high_arr = high - - if np.any(np.less(low_arr, 0x0ULL)): - raise ValueError('low is out of bounds for uint64') - - highm1_arr = np.empty_like(high_arr, dtype=np.uint64) - highm1_data = np.PyArray_DATA(highm1_arr) - cnt = np.PyArray_SIZE(high_arr) - flat = high_arr.flat - for i in range(cnt): - closed_upper = int(flat[i]) - 1 - if closed_upper > 0xFFFFFFFFFFFFFFFFULL: - raise ValueError('high is out of bounds for uint64') - if closed_upper < 0x0ULL: - raise ValueError('low >= high') - highm1_data[i] = closed_upper - - if np.any(np.greater(low_arr, highm1_arr)): - raise ValueError('low >= high') - - high_arr = highm1_arr - low_arr = np.PyArray_FROM_OTF(low, np.NPY_UINT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.uint64) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.uint64) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = (high_v - low_v) # No -1 here since implemented above - off = (low_v) - - if rng != last_rng: - mask = _gen_mask(rng) - out_data[i] = random_bounded_uint64(state, off, rng, mask) - - np.PyArray_MultiIter_NEXT(it) - - return out_arr - -cdef object _rand_int64_broadcast(object low, object high, object size, brng_t *state, object lock): - """Array path for 64-bit integer types""" - 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 int64_t *highm1_data - cdef int64_t low_v, high_v - cdef uint64_t rng, last_rng, val, mask, off, out_val - - low_arr = low - high_arr = high - - if np.any(np.less(low_arr, -0x8000000000000000LL)): - raise ValueError('low is out of bounds for int64') - - highm1_arr = np.empty_like(high_arr, dtype=np.int64) - highm1_data = np.PyArray_DATA(highm1_arr) - cnt = np.PyArray_SIZE(high_arr) - flat = high_arr.flat - for i in range(cnt): - closed_upper = int(flat[i]) - 1 - if closed_upper > 0x7FFFFFFFFFFFFFFFLL: - raise ValueError('high is out of bounds for int64') - if closed_upper < -0x8000000000000000LL: - raise ValueError('low >= high') - highm1_data[i] = closed_upper - - if np.any(np.greater(low_arr, highm1_arr)): - raise ValueError('low >= high') - - high_arr = highm1_arr - low_arr = np.PyArray_FROM_OTF(low, np.NPY_INT64, np.NPY_ALIGNED | np.NPY_FORCECAST) - - if size is not None: - out_arr = np.empty(size, np.int64) - else: - it = np.PyArray_MultiIterNew2(low_arr, high_arr) - out_arr = np.empty(it.shape, np.int64) - - it = np.PyArray_MultiIterNew3(low_arr, high_arr, out_arr) - out_data = 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 = (np.PyArray_MultiIter_DATA(it, 0))[0] - high_v = (np.PyArray_MultiIter_DATA(it, 1))[0] - rng = (high_v - low_v) # No -1 here since implemented above - off = (low_v) - - if rng != last_rng: - mask = _gen_mask(rng) - out_data[i] = random_bounded_uint64(state, off, rng, mask) - - np.PyArray_MultiIter_NEXT(it) - - return out_arr - - - -cdef object _rand_uint64(object low, object high, object size, brng_t *state, object lock): - """ - _rand_uint64(low, high, size, *state, lock) - - Return random np.uint64 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.uint64 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, 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. - state : basic random state - 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.uint64 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint64_t rng, off, out_val - cdef uint64_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.uint64) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < 0x0ULL: - raise ValueError("low is out of bounds for uint64") - if high > 0xFFFFFFFFFFFFFFFFULL: - raise ValueError("high is out of bounds for uint64") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint64_fill(state, off, rng, 1, &out_val) - return np.uint64(out_val) - else: - out_arr = np.empty(size, np.uint64) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint64_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_uint64_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_uint32(object low, object high, object size, brng_t *state, object lock): - """ - _rand_uint32(low, high, size, *state, lock) - - Return random np.uint32 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.uint32 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, 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. - state : basic random state - 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.uint32 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint32_t rng, off, out_val - cdef uint32_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.uint32) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < 0x0UL: - raise ValueError("low is out of bounds for uint32") - if high > 0XFFFFFFFFUL: - raise ValueError("high is out of bounds for uint32") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint32_fill(state, off, rng, 1, &out_val) - return np.uint32(out_val) - else: - out_arr = np.empty(size, np.uint32) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint32_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_uint32_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_uint16(object low, object high, object size, brng_t *state, object lock): - """ - _rand_uint16(low, high, size, *state, lock) - - Return random np.uint16 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.uint16 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, 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. - state : basic random state - 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.uint16 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint16_t rng, off, out_val - cdef uint16_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.uint16) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < 0x0UL: - raise ValueError("low is out of bounds for uint16") - if high > 0XFFFFUL: - raise ValueError("high is out of bounds for uint16") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint16_fill(state, off, rng, 1, &out_val) - return np.uint16(out_val) - else: - out_arr = np.empty(size, np.uint16) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint16_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_uint16_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_uint8(object low, object high, object size, brng_t *state, object lock): - """ - _rand_uint8(low, high, size, *state, lock) - - Return random np.uint8 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.uint8 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, 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. - state : basic random state - 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.uint8 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint8_t rng, off, out_val - cdef uint8_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.uint8) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < 0x0UL: - raise ValueError("low is out of bounds for uint8") - if high > 0XFFUL: - raise ValueError("high is out of bounds for uint8") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint8_fill(state, off, rng, 1, &out_val) - return np.uint8(out_val) - else: - out_arr = np.empty(size, np.uint8) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint8_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_uint8_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_bool(object low, object high, object size, brng_t *state, object lock): - """ - _rand_bool(low, high, size, *state, lock) - - Return random np.bool integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.bool 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, 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. - state : basic random state - 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.bool - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef bool_t rng, off, out_val - cdef bool_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.bool) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < 0x0UL: - raise ValueError("low is out of bounds for bool") - if high > 0x1UL: - raise ValueError("high is out of bounds for bool") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_bool_fill(state, off, rng, 1, &out_val) - return np.bool_(out_val) - else: - out_arr = np.empty(size, np.bool) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_bool_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_bool_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_int64(object low, object high, object size, brng_t *state, object lock): - """ - _rand_int64(low, high, size, *state, lock) - - Return random np.int64 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.int64 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, 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. - state : basic random state - 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.int64 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint64_t rng, off, out_val - cdef uint64_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.int64) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < -0x8000000000000000LL: - raise ValueError("low is out of bounds for int64") - if high > 0x7FFFFFFFFFFFFFFFL: - raise ValueError("high is out of bounds for int64") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint64_fill(state, off, rng, 1, &out_val) - return np.int64(out_val) - else: - out_arr = np.empty(size, np.int64) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint64_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_int64_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_int32(object low, object high, object size, brng_t *state, object lock): - """ - _rand_int32(low, high, size, *state, lock) - - Return random np.int32 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.int32 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, 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. - state : basic random state - 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.int32 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint32_t rng, off, out_val - cdef uint32_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.int32) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < -0x80000000L: - raise ValueError("low is out of bounds for int32") - if high > 0x7FFFFFFFL: - raise ValueError("high is out of bounds for int32") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint32_fill(state, off, rng, 1, &out_val) - return np.int32(out_val) - else: - out_arr = np.empty(size, np.int32) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint32_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_int32_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_int16(object low, object high, object size, brng_t *state, object lock): - """ - _rand_int16(low, high, size, *state, lock) - - Return random np.int16 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.int16 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, 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. - state : basic random state - 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.int16 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint16_t rng, off, out_val - cdef uint16_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.int16) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < -0x8000L: - raise ValueError("low is out of bounds for int16") - if high > 0x7FFFL: - raise ValueError("high is out of bounds for int16") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint16_fill(state, off, rng, 1, &out_val) - return np.int16(out_val) - else: - out_arr = np.empty(size, np.int16) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint16_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_int16_broadcast(low_arr, high_arr, size, state, lock) - -cdef object _rand_int8(object low, object high, object size, brng_t *state, object lock): - """ - _rand_int8(low, high, size, *state, lock) - - Return random np.int8 integers between `low` and `high`, inclusive. - - Return random integers from the "discrete uniform" distribution in the - closed 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.int8 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, 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. - state : basic random state - 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.int8 - `size`-shaped array of random integers from the appropriate - distribution, or a single such random int if `size` not provided. - """ - cdef np.ndarray out_arr, low_arr, high_arr - cdef uint8_t rng, off, out_val - cdef uint8_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.int8) - - low_arr = np.array(low, copy=False) - high_arr = 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) - high -= 1 - - if low < -0x80L: - raise ValueError("low is out of bounds for int8") - if high > 0x7FL: - raise ValueError("high is out of bounds for int8") - if low > high: # -1 already subtracted, closed interval - raise ValueError("low >= high") - - rng = (high - low) - off = (low) - if size is None: - with lock: - random_bounded_uint8_fill(state, off, rng, 1, &out_val) - return np.int8(out_val) - else: - out_arr = np.empty(size, np.int8) - cnt = np.PyArray_SIZE(out_arr) - out_data = np.PyArray_DATA(out_arr) - with lock, nogil: - random_bounded_uint8_fill(state, off, rng, cnt, out_data) - return out_arr - return _rand_int8_broadcast(low_arr, high_arr, size, state, lock) diff --git a/_randomgen/randomgen/tests/__init__.py b/_randomgen/randomgen/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/randomgen/tests/data/__init__.py b/_randomgen/randomgen/tests/data/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 2bd987367eba..f4a0902c1472 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -245,7 +245,8 @@ def is_pure(self): "PCG_EMULATED_MATH": PCG_EMULATED_MATH}), packages=find_packages(), package_dir={'randomgen': './randomgen'}, - package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in']}, + package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in'], + 'randomgen.tests.data': ['*.csv']}, include_package_data=True, license='NSCA', author='Kevin Sheppard', From 447e6b3383725d2c4407f58eed474fc7ac122838 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 17 Mar 2018 10:49:58 +0000 Subject: [PATCH 068/138] DOC: Update change-log and docs --- _randomgen/README.md | 2 +- _randomgen/README.rst | 4 +++- _randomgen/doc/source/change-log.rst | 9 ++++++++- _randomgen/setup.py | 7 ++++--- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index 036af1b619b1..836ef131539d 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -2,6 +2,7 @@ [![Travis Build Status](https://travis-ci.org/bashtage/randomgen.svg?branch=master)](https://travis-ci.org/bashtage/randomgen) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/randomgen/branch/master) +[![PyPI version](https://badge.fury.io/py/randomgen.svg)](https://pypi.org/project/randomgen/) Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -9,7 +10,6 @@ NumPy RandomState evolution. This is a library and generic interface for alternative random generators in Python and NumPy. - ### Compatibility Warning RandomGen no longer supports Box-Muller normal variates and so it not 100% compatible with NumPy (or randomstate). Box-Muller normals are slow diff --git a/_randomgen/README.rst b/_randomgen/README.rst index b9a0ad5f5053..7448523d8838 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -1,7 +1,7 @@ RandomGen ========= -|Travis Build Status| |Appveyor Build Status| +|Travis Build Status| |Appveyor Build Status| |PyPI version| Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -279,3 +279,5 @@ NumPy's mt19937. :target: https://travis-ci.org/bashtage/randomgen .. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master +.. |PyPI version| image:: https://badge.fury.io/py/randomgen.svg + :target: https://pypi.org/project/randomgen/ diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 36c46223ad4c..c59718b9c7f5 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,4 +1,11 @@ Change Log ---------- -The project is too new for a change log. \ No newline at end of file +Changes since v1.14 +=================== + +- Switch to array-fillers for 0 parameter distribution to improve performance +- Small changes to build on manylinux +- Build wheels using multibuild + + diff --git a/_randomgen/setup.py b/_randomgen/setup.py index f4a0902c1472..c010cfc9bff5 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -22,8 +22,8 @@ try: import pypandoc # With an input file: it will infer the input format from the filename - with open('README.rst', 'w') as readme: - readme.write(pypandoc.convert_file('README.md', 'rst')) + with open('README.rst', 'wb') as readme: + readme.write(pypandoc.convert_file('README.md', 'rst').encode('utf8')) except ImportError: import warnings warnings.warn( @@ -45,7 +45,8 @@ EXTRA_INCLUDE_DIRS = [] EXTRA_LINK_ARGS = [] # Undef for manylinux -EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else ['-std=c99', '-U__GNUC_GNU_INLINE__'] +EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ + '-std=c99', '-U__GNUC_GNU_INLINE__'] if os.name == 'nt': EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] if DEBUG: From 50e72425335c830298649cd371749e66aa4b1fef Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 21 Mar 2018 21:08:07 +0000 Subject: [PATCH 069/138] BUG: Restore nogil for fillers Use nogil for fillers --- _randomgen/randomgen/distributions.pxd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index 202c7439de0a..6b13733d3e25 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -36,11 +36,11 @@ cdef extern from "src/distributions/distributions.h": ctypedef brng brng_t double random_double(brng_t *brng_state) nogil - void random_double_fill(brng_t* brng_state, np.npy_intp cnt, double *out) + void random_double_fill(brng_t* brng_state, np.npy_intp cnt, double *out) nogil double random_standard_exponential(brng_t *brng_state) nogil - void random_standard_exponential_fill(brng_t *brng_state, np.npy_intp cnt, double *out) + void random_standard_exponential_fill(brng_t *brng_state, np.npy_intp cnt, double *out) nogil double random_standard_exponential_zig(brng_t *brng_state) nogil - void random_standard_exponential_zig_fill(brng_t *brng_state, np.npy_intp cnt, double *out) + void random_standard_exponential_zig_fill(brng_t *brng_state, np.npy_intp cnt, double *out) nogil double random_gauss_zig(brng_t* brng_state) nogil void random_gauss_zig_fill(brng_t *brng_state, np.npy_intp count, double *out) nogil double random_standard_gamma_zig(brng_t *brng_state, double shape) nogil From 3e69d17435bfea21ac16ac23bfe552e38b73c6bb Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 22 Mar 2018 10:56:46 +0000 Subject: [PATCH 070/138] CLN: Remove references to long Replace conversion to long with int64 --- _randomgen/randomgen/common.pyx | 10 +++++----- _randomgen/randomgen/generator.pyx | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index e28342e68442..8e2f69c5d8a8 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -2,7 +2,7 @@ #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True from collections import namedtuple -from cpython cimport PyInt_AsLong, PyFloat_AsDouble +from cpython cimport PyFloat_AsDouble import sys import numpy as np cimport numpy as np @@ -642,20 +642,20 @@ cdef object disc(void *func, brng_t *state, object size, object lock, if b_constraint != CONS_NONE and is_scalar: check_constraint(_db, b_name, b_constraint) elif narg_int64 == 1: - _ib = PyInt_AsLong(b) + _ib = b if b_constraint != CONS_NONE and is_scalar: check_constraint(_ib, b_name, b_constraint) else: if narg_int64 > 0: - _ia = PyInt_AsLong(a) + _ia = a if a_constraint != CONS_NONE and is_scalar: check_constraint(_ia, a_name, a_constraint) if narg_int64 > 1: - _ib = PyInt_AsLong(b) + _ib = b if b_constraint != CONS_NONE and is_scalar: check_constraint(_ib, b_name, b_constraint) if narg_int64 > 2 : - _ic = PyInt_AsLong(c) + _ic = c if c_constraint != CONS_NONE and is_scalar: check_constraint(_ic, c_name, c_constraint) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 1aa630dfdaa6..c9d7659945a6 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -4,7 +4,7 @@ import operator import warnings from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, PyInt_AsLong, +from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles, PyFloat_AsDouble) from common cimport * from distributions cimport * @@ -3237,7 +3237,7 @@ cdef class RandomGenerator: return randoms _dp = PyFloat_AsDouble(p) - _in = PyInt_AsLong(n) + _in = n check_constraint(_dp, 'p', CONS_BOUNDED_0_1_NOTNAN) check_constraint(_in, 'n', CONS_NON_NEGATIVE) @@ -3632,9 +3632,9 @@ cdef class RandomGenerator: if np.PyArray_NDIM(ongood) == np.PyArray_NDIM(onbad) == np.PyArray_NDIM(onsample) == 0: - lngood = PyInt_AsLong(ngood) - lnbad = PyInt_AsLong(nbad) - lnsample = PyInt_AsLong(nsample) + lngood = ngood + lnbad = nbad + lnsample = nsample if lngood < 0: raise ValueError("ngood < 0") From 489015fe7a49c13d2d3c46697a0b3fc58d34c535 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 21 Mar 2018 20:59:59 +0000 Subject: [PATCH 071/138] ENH: Add Box-Muller gauss Add legacy distributions through new generator --- _randomgen/.travis.yml | 4 +- _randomgen/README.md | 2 +- _randomgen/README.rst | 2 +- _randomgen/doc/source/change-log.rst | 2 + _randomgen/doc/source/extending.rst | 2 +- _randomgen/doc/source/index.rst | 3 +- _randomgen/doc/source/legacy.rst | 95 + _randomgen/doc/source/multithreading.rst | 96 +- _randomgen/doc/source/new-or-different.rst | 25 +- _randomgen/randomgen/common.pxd | 28 +- _randomgen/randomgen/common.pyx | 20 +- _randomgen/randomgen/legacy/__init__.py | 3 + _randomgen/randomgen/legacy/legacy.pyx | 1953 +++++++++++++++++ .../randomgen/legacy/legacy_distributions.pxd | 40 + .../src/distributions/distributions.c | 26 +- .../src/distributions/distributions.h | 12 +- .../src/legacy/distributions-boxmuller.c | 201 ++ .../src/legacy/distributions-boxmuller.h | 34 + .../randomgen/tests/test_against_numpy.py | 327 +-- .../randomgen/tests/test_numpy_mt19937.py | 223 +- _randomgen/requirements.txt | 2 +- _randomgen/setup.py | 10 + 22 files changed, 2710 insertions(+), 400 deletions(-) create mode 100644 _randomgen/doc/source/legacy.rst create mode 100644 _randomgen/randomgen/legacy/__init__.py create mode 100644 _randomgen/randomgen/legacy/legacy.pyx create mode 100644 _randomgen/randomgen/legacy/legacy_distributions.pxd create mode 100644 _randomgen/randomgen/src/legacy/distributions-boxmuller.c create mode 100644 _randomgen/randomgen/src/legacy/distributions-boxmuller.h diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index b11f5b73055a..052681727ab9 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -20,11 +20,11 @@ matrix: fast_finish: true include: - os: linux - env: [PYTHON=2.7, NUMPY=1.10, CYTHON=0.24] + env: [PYTHON=2.7, NUMPY=1.10, CYTHON=0.26] - os: linux env: [PYTHON=3.5, NUMPY=1.11] - os: linux - env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.25] + env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.27] - os: linux env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.26] - os: linux diff --git a/_randomgen/README.md b/_randomgen/README.md index 836ef131539d..e1fe7cbd4df0 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -146,7 +146,7 @@ Building requires: * Python (2.7, 3.4, 3.5, 3.6) * NumPy (1.10, 1.11, 1.12, 1.13, 1.14) - * Cython (0.25+) + * Cython (0.26+) * tempita (0.5+), if not provided by Cython Testing requires pytest (3.0+). diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 7448523d8838..e37a7193cf64 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -163,7 +163,7 @@ Building requires: - Python (2.7, 3.4, 3.5, 3.6) - NumPy (1.10, 1.11, 1.12, 1.13, 1.14) -- Cython (0.25+) +- Cython (0.26+) - tempita (0.5+), if not provided by Cython Testing requires pytest (3.0+). diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index c59718b9c7f5..9029981e3ed5 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -4,6 +4,8 @@ Change Log Changes since v1.14 =================== +- Add legacy generator which allows NumPy replication +- Improve type handling of integers - Switch to array-fillers for 0 parameter distribution to improve performance - Small changes to build on manylinux - Build wheels using multibuild diff --git a/_randomgen/doc/source/extending.rst b/_randomgen/doc/source/extending.rst index aacfab393289..764e3428b066 100644 --- a/_randomgen/doc/source/extending.rst +++ b/_randomgen/doc/source/extending.rst @@ -15,7 +15,7 @@ This example shows how numba can be used to produce Box-Muller normals using a pure Python implementation which is then compiled. The random numbers are provided by ``ctypes.next_double``. -.. ipython:: python +.. code-block:: python from randomgen import Xoroshiro128 import numpy as np diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index 2e9ce44d94e8..c0b55f5cb215 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -174,7 +174,8 @@ Random Generator .. toctree:: :maxdepth: 1 - Random Generator + Random Generation + legacy Basic Random Number Generators ------------------------------ diff --git a/_randomgen/doc/source/legacy.rst b/_randomgen/doc/source/legacy.rst new file mode 100644 index 000000000000..8a73f9029c92 --- /dev/null +++ b/_randomgen/doc/source/legacy.rst @@ -0,0 +1,95 @@ +Legacy Random Generation +------------------------ +The :class:`~randomgen.legacy.LegacyGenerator` provides access to +some legacy generators. These all depend on Box-Muller normals or +inverse CDF exponentials or gammas. This class should only be used +if it is essential to have randoms that are identical to what +would have been produced by NumPy. + +:class:`~randomgen.legacy.LegacyGenerator` add additional information +to the state which is required when using Box-Muller normals since these +are produced in pairs. It is important to use +:attr:`~randomgen.legacy.LegacyGenerator.state` +when accessing the state so that these extra values are saved. + +.. warning:: + + :class:`~randomgen.legacy.LegacyGenerator` only contains functions + that have changed. Since it does not contain other functions, it + is not direclty possible to replace :class:`~numpy.random.RandomState`. + In order to full replace :class:`~numpy.random.RandomState`, it is + necessary to use both :class:`~randomgen.legacy.LegacyGenerator` + and :class:`~randomgen.generator.RandomGenerator` both driven + by the same basic RNG. Methods present in :class:`~randomgen.legacy.LegacyGenerator` + must be called from :class:`~randomgen.legacy.LegacyGenerator`. Other Methods + should be called from :class:`~randomgen.generator.RandomGenerator`. + + +.. code-block:: python + + from randomgen import RandomGenerator, MT19937 + from randomgen.legacy import LegacyGenerator + from numpy.random import RandomState + # Use same seed + rs = RandomState(12345) + mt19937 = MT19937(12345) + rg = RandomGenerator(mt19937) + lg = LegacyGenerator(mt19937) + + # Identical output + rs.standard_normal() + lg.standard_normal() + + rs.random_sample() + rg.random_sample() + + rs.standard_exponential() + lg.standard_exponential() + + +.. currentmodule:: randomgen.legacy + +.. autoclass:: + LegacyGenerator + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~LegacyGenerator.state + +Simple random data +================== +.. autosummary:: + :toctree: generated/ + + ~LegacyGenerator.randn + +Distributions +============= +.. autosummary:: + :toctree: generated/ + + ~LegacyGenerator.beta + ~LegacyGenerator.chisquare + ~LegacyGenerator.dirichlet + ~LegacyGenerator.exponential + ~LegacyGenerator.f + ~LegacyGenerator.gamma + ~LegacyGenerator.lognormal + ~LegacyGenerator.multivariate_normal + ~LegacyGenerator.negative_binomial + ~LegacyGenerator.noncentral_chisquare + ~LegacyGenerator.noncentral_f + ~LegacyGenerator.normal + ~LegacyGenerator.pareto + ~LegacyGenerator.power + ~LegacyGenerator.standard_cauchy + ~LegacyGenerator.standard_exponential + ~LegacyGenerator.standard_gamma + ~LegacyGenerator.standard_normal + ~LegacyGenerator.standard_t + ~LegacyGenerator.wald + ~LegacyGenerator.weibull diff --git a/_randomgen/doc/source/multithreading.rst b/_randomgen/doc/source/multithreading.rst index ef8d710dff26..253764632c77 100644 --- a/_randomgen/doc/source/multithreading.rst +++ b/_randomgen/doc/source/multithreading.rst @@ -14,20 +14,20 @@ xorshift2014 which is fast, has a long period and supports using ``jump`` to advance the state. The random numbers generated are reproducible in the sense that the same seed will produce the same outputs. -.. code-block:: python +.. code-block:: ipython from randomgen import Xorshift1024 import multiprocessing import concurrent.futures import numpy as np - + class MultithreadedRNG(object): def __init__(self, n, seed=None, threads=None): rg = Xorshift1024(seed) if threads is None: threads = multiprocessing.cpu_count() self.threads = threads - + self._random_generators = [] for _ in range(0, threads-1): _rg = Xorshift1024() @@ -35,96 +35,70 @@ that the same seed will produce the same outputs. self._random_generators.append(_rg.generator) rg.jump() self._random_generators.append(rg.generator) - + self.n = n self.executor = concurrent.futures.ThreadPoolExecutor(threads) self.values = np.empty(n) self.step = np.ceil(n / threads).astype(np.int) - + def fill(self): def _fill(random_state, out, first, last): random_state.standard_normal(out=out[first:last]) - + futures = {} for i in range(self.threads): - args = (_fill, self._random_generators[i], self.values, i * self.step, (i + 1) * self.step) + args = (_fill, + self._random_generators[i], + self.values, + i * self.step, + (i + 1) * self.step) futures[self.executor.submit(*args)] = i concurrent.futures.wait(futures) - + def __del__(self): self.executor.shutdown(False) -.. ipython:: python - :suppress: - - - In [1]: from randomgen import Xorshift1024 - ....: import multiprocessing - ....: import concurrent.futures - ....: import numpy as np - ....: class MultithreadedRNG(object): - ....: def __init__(self, n, seed=None, threads=None): - ....: rg = Xorshift1024(seed) - ....: if threads is None: - ....: threads = multiprocessing.cpu_count() - ....: self.threads = threads - ....: self._random_generators = [] - ....: for _ in range(0, threads-1): - ....: _rg = Xorshift1024() - ....: _rg.state = rg.state - ....: self._random_generators.append(_rg.generator) - ....: rg.jump() - ....: self._random_generators.append(rg.generator) - ....: self.n = n - ....: self.executor = concurrent.futures.ThreadPoolExecutor(threads) - ....: self.values = np.empty(n) - ....: self.step = np.ceil(n / threads).astype(np.int) - ....: def fill(self): - ....: def _fill(random_state, out, first, last): - ....: random_state.standard_normal(out=out[first:last]) - ....: futures = {} - ....: for i in range(self.threads): - ....: args = (_fill, self._random_generators[i], self.values, i * self.step, (i + 1) * self.step) - ....: futures[self.executor.submit(*args)] = i - ....: concurrent.futures.wait(futures) - ....: def __del__(self): - ....: self.executor.shutdown(False) - ....: - The multithreaded random number generator can be used to fill an array. The ``values`` attributes shows the zero-value before the fill and the random value after. -.. ipython:: python +.. code-block:: ipython - mrng = MultithreadedRNG(10000000, seed=0) - print(mrng.values[-1]) - mrng.fill() - print(mrng.values[-1]) + In [2]: mrng = MultithreadedRNG(10000000, seed=0) + ...: print(mrng.values[-1]) + 0.0 + + In [3]: mrng.fill() + ...: print(mrng.values[-1]) + 3.296046120254392 The time required to produce using multiple threads can be compared to the time required to generate using a single thread. -.. ipython:: python - - print(mrng.threads) - %timeit mrng.fill() +.. code-block:: ipython + In [4]: print(mrng.threads) + ...: %timeit mrng.fill() + 4 + 42.9 ms ± 2.55 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) The single threaded call directly uses the PRNG. -.. ipython:: python +.. code-block:: ipython - values = np.empty(10000000) - rg = Xorshift1024().generator - %timeit rg.standard_normal(out=values) + In [5]: values = np.empty(10000000) + ...: rg = Xorshift1024().generator + ...: %timeit rg.standard_normal(out=values) + 220 ms ± 27.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) The gains are substantial and the scaling is reasonable even for large that are only moderately large. The gains are even larger when compared to a call that does not use an existing array due to array creation overhead. -.. ipython:: python +.. code-block:: ipython - rg = Xorshift1024().generator - %timeit rg.standard_normal(10000000) + In [6]: rg = Xorshift1024().generator + ...: %timeit rg.standard_normal(10000000) + ...: + 256 ms ± 41.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) diff --git a/_randomgen/doc/source/new-or-different.rst b/_randomgen/doc/source/new-or-different.rst index 7fb70ed1ab66..fdff589461e5 100644 --- a/_randomgen/doc/source/new-or-different.rst +++ b/_randomgen/doc/source/new-or-different.rst @@ -29,29 +29,24 @@ What's New or Different * The basic random number generators can be used in downstream projects via Cython. + .. ipython:: python from randomgen import Xoroshiro128 + import numpy.random rg = Xoroshiro128().generator - %timeit rg.standard_normal(1000000) - from numpy.random import standard_normal - %timeit standard_normal(1000000) + %timeit rg.standard_normal(100000) + %timeit numpy.random.standard_normal(100000) .. ipython:: python - from randomgen import Xoroshiro128 - rg = Xoroshiro128().generator - %timeit rg.standard_exponential(1000000) - from numpy.random import standard_exponential - %timeit standard_exponential(1000000) + %timeit rg.standard_exponential(100000) + %timeit numpy.random.standard_exponential(100000) .. ipython:: python - from randomgen import Xoroshiro128 - rg = Xoroshiro128().generator - %timeit rg.standard_gamma(3.0, 1000000) - from numpy.random import standard_gamma - %timeit standard_gamma(3.0, 1000000) + %timeit rg.standard_gamma(3.0, 100000) + %timeit numpy.random.standard_gamma(3.0, 100000) * Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64`` to produce either single or double prevision uniform random variables for @@ -66,8 +61,6 @@ What's New or Different .. ipython:: python - from randomgen import Xoroshiro128 - rg = Xoroshiro128().generator rg.seed(0) rg.random_sample(3, dtype='d') rg.seed(0) @@ -86,8 +79,6 @@ What's New or Different .. ipython:: python - from randomgen import Xoroshiro128 - rg = Xoroshiro128(0).generator existing = np.zeros(4) rg.random_sample(out=existing[:2]) print(existing) diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd index e4ce62818370..5a661dfb3db1 100644 --- a/_randomgen/randomgen/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -32,20 +32,20 @@ cdef extern from "src/aligned_malloc/aligned_malloc.h": cdef void PyArray_free_aligned(void *p); ctypedef double (*random_double_fill)(brng_t *state, np.npy_intp count, double* out) nogil -ctypedef double (*random_double_0)(brng_t *state) nogil -ctypedef double (*random_double_1)(brng_t *state, double a) nogil -ctypedef double (*random_double_2)(brng_t *state, double a, double b) nogil -ctypedef double (*random_double_3)(brng_t *state, double a, double b, double c) 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)(brng_t *state) nogil ctypedef float (*random_float_1)(brng_t *state, float a) nogil -ctypedef int64_t (*random_uint_0)(brng_t *state) nogil -ctypedef int64_t (*random_uint_d)(brng_t *state, double a) nogil -ctypedef int64_t (*random_uint_dd)(brng_t *state, double a, double b) nogil -ctypedef int64_t (*random_uint_di)(brng_t *state, double a, uint64_t b) nogil -ctypedef int64_t (*random_uint_i)(brng_t *state, int64_t a) nogil -ctypedef int64_t (*random_uint_iii)(brng_t *state, int64_t a, int64_t b, int64_t c) 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)(brng_t *state) nogil ctypedef uint32_t (*random_uint_1_i_32)(brng_t *state, uint32_t a) nogil @@ -66,13 +66,13 @@ cdef object float_fill_from_double(void *func, brng_t *state, object size, objec cdef np.ndarray int_to_array(object value, object name, object bits, object uint_size) -cdef object cont(void *func, brng_t *state, object size, object lock, int narg, +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, brng_t *state, object size, object lock, +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, @@ -82,12 +82,12 @@ cdef object cont_f(void *func, brng_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out) -cdef object cont_broadcast_3(void *func, brng_t *state, object size, object lock, +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, brng_t *state, object size, object lock, +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/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index 8e2f69c5d8a8..6189ba19920b 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -200,7 +200,7 @@ cdef int check_constraint(double val, object name, constraint_type cons) except return 0 -cdef object cont_broadcast_1(void *func, brng_t *state, object size, object lock, +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): @@ -234,7 +234,7 @@ cdef object cont_broadcast_1(void *func, brng_t *state, object size, object lock return randoms -cdef object cont_broadcast_2(void *func, brng_t *state, object size, object lock, +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 @@ -272,7 +272,7 @@ cdef object cont_broadcast_2(void *func, brng_t *state, object size, object lock return randoms -cdef object cont_broadcast_3(void *func, brng_t *state, object size, object lock, +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): @@ -314,7 +314,7 @@ cdef object cont_broadcast_3(void *func, brng_t *state, object size, object lock return randoms -cdef object cont(void *func, brng_t *state, object size, object lock, int narg, +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, @@ -410,7 +410,7 @@ cdef object cont(void *func, brng_t *state, object size, object lock, int narg, else: return out -cdef object discrete_broadcast_d(void *func, brng_t *state, object size, object lock, +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 @@ -441,7 +441,7 @@ cdef object discrete_broadcast_d(void *func, brng_t *state, object size, object return randoms -cdef object discrete_broadcast_dd(void *func, brng_t *state, object size, object lock, +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 @@ -476,7 +476,7 @@ cdef object discrete_broadcast_dd(void *func, brng_t *state, object size, object return randoms -cdef object discrete_broadcast_di(void *func, brng_t *state, object size, object lock, +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 @@ -512,7 +512,7 @@ cdef object discrete_broadcast_di(void *func, brng_t *state, object size, object return randoms -cdef object discrete_broadcast_iii(void *func, brng_t *state, object size, object lock, +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): @@ -552,7 +552,7 @@ cdef object discrete_broadcast_iii(void *func, brng_t *state, object size, objec return randoms -cdef object discrete_broadcast_i(void *func, brng_t *state, object size, object lock, +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 @@ -582,7 +582,7 @@ cdef object discrete_broadcast_i(void *func, brng_t *state, object size, object return randoms # Needs double , double-double , double-int64_t, int64_t , int64_t-int64_t-int64_t -cdef object disc(void *func, brng_t *state, object size, object lock, +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, diff --git a/_randomgen/randomgen/legacy/__init__.py b/_randomgen/randomgen/legacy/__init__.py new file mode 100644 index 000000000000..b59b221b49bc --- /dev/null +++ b/_randomgen/randomgen/legacy/__init__.py @@ -0,0 +1,3 @@ +from randomgen.legacy.legacy import LegacyGenerator + +__all__ = ['LegacyGenerator'] diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx new file mode 100644 index 000000000000..0a5a67bcf867 --- /dev/null +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -0,0 +1,1953 @@ +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +import warnings +import operator + +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from libc.stdlib cimport malloc, free +cimport numpy as np +import numpy as np +cimport cython + +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + +from randomgen.common cimport cont, disc, CONS_NONE, CONS_POSITIVE, CONS_NON_NEGATIVE, CONS_BOUNDED_0_1 +from randomgen.distributions cimport brng_t +from randomgen.legacy.legacy_distributions cimport * +from randomgen.xoroshiro128 import Xoroshiro128 +import randomgen.pickle + +np.import_array() + +cdef class LegacyGenerator: + """ + LegacyGenerator(brng=None) + + Container providing legacy generators. + + ``LegacyGenerator`` exposes a number of methods for generating random + numbers for a set of distributions where the method used to produce random + samples has changed. Three core generators have changed: normals, exponentials + and gammas. These have been replaced by fster Ziggurat-based methds in + ``RadnomGenerator``. ``LegacyGenerator`` retains the slower methods + to produce samples from these distributions as well as from distributions + that depend on these such as the Chi-square, power or Weibull. + + **No Compatibility Guarantee** + + ``LegacyGenerator`` is evolving and so it isn't possible to provide a + compatibility guarantee like NumPy does. In particular, better algorithms + have already been added. This will change once ``RandomGenerator`` + stabilizes. + + Parameters + ---------- + brng : Basic RNG, optional + Basic RNG to use as the core generator. If none is provided, uses + Xoroshiro128. + + + Examples + -------- + Exactly reproducing a NumPy stream requires both a ``RandomGenerator`` + and a ``LegacyGenerator``. These must share a common ``MT19937`` basic + RNG. Functions that are available in LegacyGenerator must be called + from ``LegacyGenerator``, and other functions must be called from + ``RandomGenerator``. + + >>> from randomgen import RandomGenerator, MT19937 + >>> from randomgen.legacy import LegacyGenerator + >>> mt = MT19937(12345) + >>> lg = LegacyGenerator(mt) + >>> rg = RandomGenerator(mt) + >>> x = lg.standard_normal(10) + >>> rg.shuffle(x) + >>> x[0] + 0.09290787674371767 + >>> lg.standard_exponential() + 1.6465621229906502 + + The equivalent commands from NumPy produce identical output. + + >>> from numpy.random import RandomState + >>> rs = RandomState(12345) + >>> x = rs.standard_normal(10) + >>> rs.shuffle(x) + >>> x[0] + 0.09290787674371767 + >>> rs.standard_exponential() + 1.6465621229906502 + """ + cdef public object _basicrng + cdef brng_t *_brng + cdef aug_brng_t *_aug_state + cdef object lock + + def __init__(self, brng=None): + if brng is None: + brng = Xoroshiro128() + self._basicrng = brng + + capsule = brng.capsule + cdef const char *name = "BasicRNG" + if not PyCapsule_IsValid(capsule, name): + raise ValueError("Invalid brng. The brng must be instantized.") + self._brng = PyCapsule_GetPointer(capsule, name) + self._aug_state = malloc(sizeof(aug_brng_t)) + self._aug_state.basicrng = self._brng + self._reset_gauss() + self.lock = Lock() + + def __dealloc__(self): + free(self._aug_state) + + def __repr__(self): + return self.__str__() + ' at 0x{:X}'.format(id(self)) + + def __str__(self): + return 'RandomGenerator(' + self._basicrng.__class__.__name__ + ')' + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (randomgen.pickle.__generator_ctor, + (self.state['brng'],), + self.state) + + cdef _reset_gauss(self): + self._aug_state.has_gauss = 0 + self._aug_state.gauss = 0.0 + + def seed(self, *args, **kwargs): + """ + Reseed the basic RNG. + + Parameters depend on the basic RNG used. + """ + # TODO: Should this remain + self._basicrng.seed(*args, **kwargs) + self._reset_gauss() + return self + + @property + def state(self): + """ + Get or set the augmented state + + Returns the basic RNGs state as well as two values added to track + normal generation using the Box-Muller method. + + Returns + ------- + state : dict + Dictionary containing the information required to describe the + state of the Basic RNG with two additional fields, gauss and + has_gauss, required to store generated Box-Muller normals. + """ + st = self._basicrng.state + st['has_gauss'] = self._aug_state.has_gauss + st['gauss'] = self._aug_state.gauss + return st + + @state.setter + def state(self, value): + if isinstance(value, tuple): + if value[0] != 'MT19937': + raise ValueError('tuple only supported for MT19937') + st = {'brng': value[0], + 'state': {'key': value[1], 'pos': value[2]}} + if len(value) > 3: + st['has_gauss'] = value[3] + st['gauss'] = value[4] + value = st + + self._aug_state.gauss = value.get('gauss', 0.0) + self._aug_state.has_gauss = value.get('has_gauss', 0) + self._basicrng.state = value + + # Complicated, continuous distributions: + def standard_normal(self, size=None): + """ + standard_normal(size=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. + + Returns + ------- + out : float or ndarray + Drawn samples. + + Examples + -------- + >>> s = randomgen.standard_normal(8000) + >>> s + array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random + -0.38672696, -0.4685006 ]) #random + >>> s.shape + (8000,) + >>> s = randomgen.standard_normal(size=(3, 4, 2)) + >>> s.shape + (3, 4, 2) + + """ + 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 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 : int or array_like of ints + Degrees of freedom, should 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" + http://en.wikipedia.org/wiki/Student's_t-distribution + + Examples + -------- + From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 + women in 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 = randomgen.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, normed=True) + + For a one-sided t-test, how far out in the distribution does the t + statistic appear? + + >>> np.sum(s>> mu, sigma = 3., 1. # mean and standard deviation + >>> s = randomgen.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, normed=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. + >>> b = [] + >>> for i in range(1000): + ... a = 10. + randomgen.random(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, normed=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(&legacy_lognormal, self._aug_state, size, self.lock, 2, + mean, 'mean', CONS_NONE, + sigma, 'sigma', CONS_NON_NEGATIVE, + 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, should be > 0. + scale : float or array_like of floats + Scale parameter, should 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, + http://www.brighton-webs.co.uk/distributions/wald.asp + .. [2] Chhikara, Raj S., and Folks, J. Leroy, "The Inverse Gaussian + Distribution: Theory : Methodology, and Applications", CRC Press, + 1988. + .. [3] Wikipedia, "Wald distribution" + http://en.wikipedia.org/wiki/Wald_distribution + + Examples + -------- + Draw values from the distribution and plot the histogram: + + >>> import matplotlib.pyplot as plt + >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, normed=True) + >>> plt.show() + + """ + 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 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. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Pareto_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> a, m = 3., 2. # shape and mode + >>> s = (randomgen.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, normed=True) + >>> fit = a*m**a / bins**(a+1) + >>> plt.plot(bins, max(count)*fit/max(fit), linewidth=2, color='r') + >>> plt.show() + + """ + 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): + """ + 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 of the distribution. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Weibull_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> a = 5. # shape + >>> s = randomgen.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(randomgen.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(&legacy_weibull, self._aug_state, size, self.lock, 1, + a, 'a', CONS_NON_NEGATIVE, + 0.0, '', CONS_NONE, + 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 : int or array_like of ints + Parameter, should be > 1. + dfden : int or array_like of ints + Parameter, should be > 1. + nonc : float or array_like of floats + Parameter, should 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", + http://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. + + >>> dfnum = 3 # between group deg of freedom + >>> dfden = 20 # within groups degrees of freedom + >>> nonc = 3.0 + >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> NF = np.histogram(nc_vals, bins=50, normed=True) + >>> c_vals = randomgen.f(dfnum, dfden, 1000000) + >>> F = np.histogram(c_vals, bins=50, normed=True) + >>> plt.plot(F[1][1:], F[0]) + >>> plt.plot(NF[1][1:], NF[0]) + >>> plt.show() + + """ + 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): + """ + 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 : int or array_like of ints + Number of degrees of freedom. + 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" + http://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm + + Examples + -------- + >>> randomgen.chisquare(2,4) + array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) + + """ + 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): + """ + noncentral_chisquare(df, nonc, size=None) + + Draw samples from a noncentral chi-square distribution. + + The noncentral :math:`\\chi^2` distribution is a generalisation of + the :math:`\\chi^2` distribution. + + Parameters + ---------- + df : int or array_like of ints + Degrees of freedom, should be > 0 as of NumPy 1.10.0, + should be > 1 for earlier versions. + nonc : float or array_like of floats + Non-centrality, should 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. + + 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-square distribution" + http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution + + Examples + -------- + Draw values from the distribution and plot the histogram + + >>> import matplotlib.pyplot as plt + >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), + ... bins=200, normed=True) + >>> plt.show() + + Draw values from a noncentral chisquare with very small noncentrality, + and compare to a chisquare. + + >>> plt.figure() + >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), + ... bins=np.arange(0., 25, .1), normed=True) + >>> values2 = plt.hist(randomgen.chisquare(3, 100000), + ... bins=np.arange(0., 25, .1), normed=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(randomgen.noncentral_chisquare(3, 20, 100000), + ... bins=200, normed=True) + >>> plt.show() + + """ + 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): + """ + 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", + http://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" + http://en.wikipedia.org/wiki/Cauchy_distribution + + Examples + -------- + Draw samples and plot the distribution: + + >>> s = randomgen.standard_cauchy(1000000) + >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well + >>> plt.hist(s, bins=100) + >>> plt.show() + + """ + 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_gamma(self, shape, size=None): + """ + standard_gamma(shape, size=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, should 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 ``shape`` is a scalar. Otherwise, + ``np.array(shape).size`` samples are drawn. + + 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", + http://en.wikipedia.org/wiki/Gamma_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> shape, scale = 2., 1. # mean and width + >>> s = randomgen.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 + >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ + ... (sps.gamma(shape) * scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + """ + 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): + """ + 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. Should be greater than zero. + scale : float or array_like of floats, optional + The scale of the gamma distribution. Should be greater than zero. + 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", + http://en.wikipedia.org/wiki/Gamma_distribution + + Examples + -------- + Draw samples from the distribution: + + >>> shape, scale = 2., 2. # mean and dispersion + >>> s = randomgen.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 + >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> y = bins**(shape-1)*(np.exp(-bins/scale) / + ... (sps.gamma(shape)*scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + + """ + 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 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, non-negative. + b : float or array_like of floats + Beta, 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`` 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 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 should 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 : int or array_like of ints + Degrees of freedom in numerator. Should be greater than zero. + dfden : int or array_like of ints + Degrees of freedom in denominator. Should be greater than zero. + 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", + http://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 = randomgen.f(dfnum, dfden, 1000) + + The lower bound for the top 1% of the samples is : + + >>> sort(s)[-10] + 7.61988120985 + + 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(&legacy_f, self._aug_state, size, self.lock, 2, + dfnum, 'dfnum', CONS_POSITIVE, + dfden, 'dfden', CONS_POSITIVE, + 0.0, '', CONS_NONE, None) + + + 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. + 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 + `numpy.random.normal` is more likely to return samples lying close to + the mean, rather than those far away. + + References + ---------- + .. [1] Wikipedia, "Normal distribution", + http://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 = randomgen.normal(mu, sigma, 1000) + + Verify the mean and the variance: + + >>> abs(mu - np.mean(s)) < 0.01 + True + + >>> abs(sigma - np.std(s, ddof=1)) < 0.01 + True + + Display the histogram of the samples, along with + the probability density function: + + >>> import matplotlib.pyplot as plt + >>> count, bins, ignored = plt.hist(s, 30, normed=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() + + """ + 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 randn(self, *args): + """ + randn(d0, d1, ..., dn) + + 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. + + This is a convenience function. If you want an interface that takes a + tuple as the first argument, use `numpy.random.standard_normal` instead. + + Parameters + ---------- + d0, d1, ..., dn : int, optional + The dimensions of the returned array, should be all positive. + If no argument is given a single Python float is returned. + + Returns + ------- + Z : ndarray or float + A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from + the standard normal distribution, or a single such float if + no parameters were supplied. + + See Also + -------- + random.standard_normal : Similar, but takes a tuple as its argument. + + Notes + ----- + For random samples from :math:`N(\\mu, \\sigma^2)`, use: + + ``sigma * randomgen.randn(...) + mu`` + + Examples + -------- + >>> randomgen.randn() + 2.1923875335537315 #random + + Two-by-four array of samples from N(3, 6.25): + + >>> 2.5 * randomgen.randn(2, 4) + 3 + 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(size=args) + + 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` trials and `p` probability of success where `n` is an + integer > 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. + 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 trials it took to + achieve n - 1 successes, N - (n - 1) failures, and a success on the, + (N + n)th trial. + + Notes + ----- + The probability density for the negative binomial distribution is + + .. math:: P(N;n,p) = \\binom{N+n-1}{n-1}p^{n}(1-p)^{N}, + + where :math:`n-1` is the number of successes, :math:`p` is the + probability of success, and :math:`N+n-1` is the number of trials. + The negative binomial distribution gives the probability of n-1 + successes and N failures in N+n-1 trials, and success on the (N+n)th + 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", + http://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 = randomgen.negative_binomial(1, 0.1, 100000) + >>> for i in range(1, 11): + ... probability = sum(s>> s = randomgen.dirichlet((10, 5, 3), 20).transpose() + + >>> 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 + cdef np.npy_intp totsize + cdef np.ndarray alpha_arr, val_arr + cdef double *alpha_data + cdef double *val_data + cdef np.npy_intp i, j + cdef double acc, invacc + + k = len(alpha) + alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) + if np.any(np.less_equal(alpha_arr, 0)): + raise ValueError('alpha <= 0') + alpha_data = 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 = diric + val_data= 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] = 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 + + + def multivariate_normal(self, mean, cov, size=None, check_valid='warn', + tol=1e-8): + """ + multivariate_normal(self, 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. + + 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 = randomgen.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 = randomgen.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] + + """ + 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 + # symmetrical and the singular value of the corresponding row is + # not zero. We continue to use the SVD rather than Cholesky in + # order to preserve current outputs. Note that symmetry has not + # been checked. + + (u, s, v) = svd(cov) + + 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 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 = randomgen.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 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", + http://en.wikipedia.org/wiki/Poisson_process + .. [3] Wikipedia, "Exponential distribution", + http://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 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. Should be greater than zero. + 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. + http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf + + Examples + -------- + Draw samples from the distribution: + + >>> a = 5. # shape + >>> samples = 1000 + >>> s = randomgen.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 + >>> rvs = randomgen.power(5, 1000000) + >>> rvsp = randomgen.pareto(5, 1000000) + >>> xx = np.linspace(0,1,100) + >>> powpdf = stats.powerlaw.pdf(xx,5) + + >>> plt.figure() + >>> plt.hist(rvs, bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('randomgen.power(5)') + + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of 1 + randomgen.pareto(5)') + + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of stats.pareto(5)') + + """ + return cont(&legacy_power, self._aug_state, size, self.lock, 1, + a, 'a', CONS_POSITIVE, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE, None) diff --git a/_randomgen/randomgen/legacy/legacy_distributions.pxd b/_randomgen/randomgen/legacy/legacy_distributions.pxd new file mode 100644 index 000000000000..d22d6a73aacf --- /dev/null +++ b/_randomgen/randomgen/legacy/legacy_distributions.pxd @@ -0,0 +1,40 @@ +from libc.stdint cimport uint64_t + +import numpy as np +cimport numpy as np + +from randomgen.distributions cimport brng_t + +cdef extern from "../src/legacy/distributions-boxmuller.h": + + struct aug_brng: + brng_t *basicrng + int has_gauss + double gauss + + ctypedef aug_brng aug_brng_t + + double legacy_gauss(aug_brng_t *aug_state) nogil + double legacy_pareto(aug_brng_t *aug_state, double a) nogil + double legacy_weibull(aug_brng_t *aug_state, double a) nogil + double legacy_standard_gamma(aug_brng_t *aug_state, double shape) nogil + double legacy_normal(aug_brng_t *aug_state, double loc, double scale) nogil + double legacy_standard_t(aug_brng_t *aug_state, double df) nogil + + double legacy_standard_exponential(aug_brng_t *aug_state) nogil + double legacy_power(aug_brng_t *aug_state, double a) nogil + double legacy_gamma(aug_brng_t *aug_state, double shape, double scale) nogil + double legacy_power(aug_brng_t *aug_state, double a) nogil + double legacy_chisquare(aug_brng_t *aug_state, double df) nogil + double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, + double nonc) nogil + double legacy_noncentral_f(aug_brng_t *aug_state, double dfnum, double dfden, + double nonc) nogil + double legacy_wald(aug_brng_t *aug_state, double mean, double scale) nogil + double legacy_lognormal(aug_brng_t *aug_state, double mean, double sigma) nogil + uint64_t legacy_negative_binomial(aug_brng_t *aug_state, double n, double p) nogil + double legacy_standard_cauchy(aug_brng_t *state) nogil + double legacy_beta(aug_brng_t *aug_state, double a, double b) nogil + double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden) nogil + double legacy_exponential(aug_brng_t *aug_state, double scale) nogil + double legacy_power(aug_brng_t *state, double a) nogil diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index 246cddb444e8..0e6e9cd578f5 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -7,17 +7,16 @@ float random_float(brng_t *brng_state) { return next_float(brng_state); } double random_double(brng_t *brng_state) { return next_double(brng_state); } -static NPY_INLINE double next_standard_exponential(brng_t *brng_state) -{ - return -log(1.0 - next_double(brng_state)); +static NPY_INLINE double next_standard_exponential(brng_t *brng_state) { + return -log(1.0 - next_double(brng_state)); } double random_standard_exponential(brng_t *brng_state) { return next_standard_exponential(brng_state); } -void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, double *out) -{ +void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, + double *out) { npy_intp i; for (i = 0; i < cnt; i++) { out[i] = next_standard_exponential(brng_state); @@ -28,8 +27,7 @@ float random_standard_exponential_f(brng_t *brng_state) { return -logf(1.0f - next_float(brng_state)); } -void random_double_fill(brng_t* brng_state, npy_intp cnt, double *out) -{ +void random_double_fill(brng_t *brng_state, npy_intp cnt, double *out) { npy_intp i; for (i = 0; i < cnt; i++) { out[i] = next_double(brng_state); @@ -119,16 +117,14 @@ double random_standard_exponential_zig(brng_t *brng_state) { return standard_exponential_zig(brng_state); } - -void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, double *out) -{ +void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, + double *out) { npy_intp i; for (i = 0; i < cnt; i++) { out[i] = standard_exponential_zig(brng_state); } } - static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state); static float standard_exponential_zig_unlikely_f(brng_t *brng_state, @@ -502,7 +498,7 @@ double random_normal_zig(brng_t *brng_state, double loc, double scale) { } double random_exponential(brng_t *brng_state, double scale) { - return scale * random_standard_exponential(brng_state); + return scale * standard_exponential_zig(brng_state); } double random_uniform(brng_t *brng_state, double lower, double range) { @@ -565,15 +561,15 @@ double random_standard_cauchy(brng_t *brng_state) { } double random_pareto(brng_t *brng_state, double a) { - return exp(random_standard_exponential(brng_state) / a) - 1; + return exp(standard_exponential_zig(brng_state) / a) - 1; } double random_weibull(brng_t *brng_state, double a) { - return pow(random_standard_exponential(brng_state), 1. / a); + return pow(standard_exponential_zig(brng_state), 1. / a); } double random_power(brng_t *brng_state, double a) { - return pow(1 - exp(-random_standard_exponential(brng_state)), 1. / a); + return pow(1 - exp(-standard_exponential_zig(brng_state)), 1. / a); } double random_laplace(brng_t *brng_state, double loc, double scale) { diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index 6785405c7aa0..2dd453d3a734 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -1,3 +1,4 @@ +#pragma once #include #ifdef _WIN32 #if _MSC_VER == 1500 @@ -95,7 +96,7 @@ static NPY_INLINE double next_double(brng_t *brng_state) { DECLDIR float random_float(brng_t *brng_state); DECLDIR double random_double(brng_t *brng_state); -DECLDIR void random_double_fill(brng_t* brng_state, npy_intp cnt, double *out); +DECLDIR void random_double_fill(brng_t *brng_state, npy_intp cnt, double *out); DECLDIR int64_t random_positive_int64(brng_t *brng_state); DECLDIR int32_t random_positive_int32(brng_t *brng_state); @@ -103,10 +104,12 @@ DECLDIR int64_t random_positive_int(brng_t *brng_state); DECLDIR uint64_t random_uint(brng_t *brng_state); DECLDIR double random_standard_exponential(brng_t *brng_state); -DECLDIR void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, double *out); +DECLDIR void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, + double *out); DECLDIR float random_standard_exponential_f(brng_t *brng_state); DECLDIR double random_standard_exponential_zig(brng_t *brng_state); -DECLDIR void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, double *out); +DECLDIR void random_standard_exponential_zig_fill(brng_t *brng_state, + npy_intp cnt, double *out); DECLDIR float random_standard_exponential_zig_f(brng_t *brng_state); /* @@ -115,7 +118,8 @@ DECLDIR float random_gauss_f(brng_t *brng_state); */ DECLDIR double random_gauss_zig(brng_t *brng_state); DECLDIR float random_gauss_zig_f(brng_t *brng_state); -DECLDIR void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, double *out); +DECLDIR void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, + double *out); /* DECLDIR double random_standard_gamma(brng_t *brng_state, double shape); diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c new file mode 100644 index 000000000000..8d3d94095cc8 --- /dev/null +++ b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c @@ -0,0 +1,201 @@ +#include "distributions-boxmuller.h" + +static NPY_INLINE double legacy_double(aug_brng_t *aug_state) { + return aug_state->basicrng->next_double(aug_state->basicrng->state); +} + +double legacy_gauss(aug_brng_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); + + /* Box-Muller transform */ + 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_brng_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_brng_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 < 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_brng_t *aug_state, double shape, double scale) { + return scale * legacy_standard_gamma(aug_state, shape); +} + +double legacy_pareto(aug_brng_t *aug_state, double a) { + return exp(legacy_standard_exponential(aug_state) / a) - 1; +} + +double legacy_weibull(aug_brng_t *aug_state, double a) { + return pow(legacy_standard_exponential(aug_state), 1. / a); +} + +double legacy_power(aug_brng_t *aug_state, double a) { + return pow(1 - exp(-legacy_standard_exponential(aug_state)), 1. / a); +} + +double legacy_chisquare(aug_brng_t *aug_state, double df) { + return 2.0 * legacy_standard_gamma(aug_state, df / 2.0); +} + +double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, + double nonc) { + 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->basicrng, nonc / 2.0); + return legacy_chisquare(aug_state, df + 2 * i); + } +} + +double legacy_noncentral_f(aug_brng_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_brng_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_brng_t *aug_state, double loc, double scale) { + return loc + scale * legacy_gauss(aug_state); +} + +double legacy_lognormal(aug_brng_t *aug_state, double mean, double sigma) { + return exp(legacy_normal(aug_state, mean, sigma)); +} + +double legacy_standard_t(aug_brng_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_brng_t *aug_state, double n, double p) { + double Y = legacy_gamma(aug_state, n, (1 - p) / p); + return random_poisson(aug_state->basicrng, Y); +} + +double legacy_standard_cauchy(aug_brng_t *aug_state) { + return legacy_gauss(aug_state) / legacy_gauss(aug_state); +} + +double legacy_beta(aug_brng_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_brng_t *aug_state, double dfnum, double dfden) { + return ((legacy_chisquare(aug_state, dfnum) * dfden) / + (legacy_chisquare(aug_state, dfden) * dfnum)); +} + +double legacy_exponential(aug_brng_t *aug_state, double scale) { + return scale * legacy_standard_exponential(aug_state); +} diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.h b/_randomgen/randomgen/src/legacy/distributions-boxmuller.h new file mode 100644 index 000000000000..2c0615bdb868 --- /dev/null +++ b/_randomgen/randomgen/src/legacy/distributions-boxmuller.h @@ -0,0 +1,34 @@ +#include "../distributions/distributions.h" + +typedef struct aug_brng { + brng_t *basicrng; + int has_gauss; + double gauss; +} aug_brng_t; + +extern double legacy_gauss(aug_brng_t *aug_state); +extern double legacy_standard_exponential(aug_brng_t *aug_state); +extern double legacy_pareto(aug_brng_t *aug_state, double a); +extern double legacy_weibull(aug_brng_t *aug_state, double a); +extern double legacy_power(aug_brng_t *aug_state, double a); +extern double legacy_gamma(aug_brng_t *aug_state, double shape, double scale); +extern double legacy_pareto(aug_brng_t *aug_state, double a); +extern double legacy_weibull(aug_brng_t *aug_state, double a); +extern double legacy_chisquare(aug_brng_t *aug_state, double df); +extern double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, + double nonc); + +extern double legacy_noncentral_f(aug_brng_t *aug_state, double dfnum, + double dfden, double nonc); +extern double legacy_wald(aug_brng_t *aug_state, double mean, double scale); +extern double legacy_lognormal(aug_brng_t *aug_state, double mean, + double sigma); +extern double legacy_standard_t(aug_brng_t *aug_state, double df); +extern int64_t legacy_negative_binomial(aug_brng_t *aug_state, double n, + double p); +extern double legacy_standard_cauchy(aug_brng_t *state); +extern double legacy_beta(aug_brng_t *aug_state, double a, double b); +extern double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden); +extern double legacy_normal(aug_brng_t *aug_state, double loc, double scale); +extern double legacy_standard_gamma(aug_brng_t *aug_state, double shape); +extern double legacy_exponential(aug_brng_t *aug_state, double scale); diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index 2e49c1f18ff6..a7da65d5997b 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -5,6 +5,7 @@ import randomgen from randomgen import RandomGenerator, MT19937 +from randomgen.legacy import LegacyGenerator def compare_0_input(f1, f2): @@ -88,6 +89,7 @@ def setup_class(cls): cls.brng = MT19937 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) + cls.lg = LegacyGenerator(cls.brng(*cls.seed)) cls.nprs = cls.np.RandomState(*cls.seed) cls.initial_state = cls.rg.state cls._set_common_state() @@ -103,12 +105,31 @@ def _set_common_state(cls): st[4] = 0.0 cls.nprs.set_state(st) + @classmethod + def _set_common_state_legacy(cls): + state = cls.lg.state + st = [[]] * 5 + st[0] = 'MT19937' + st[1] = state['state']['key'] + st[2] = state['state']['pos'] + st[3] = state['has_gauss'] + st[4] = state['gauss'] + cls.nprs.set_state(st) + def _is_state_common(self): state = self.nprs.get_state() state2 = self.rg.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) + def _is_state_common_legacy(self): + state = self.nprs.get_state() + state2 = self.lg.state + assert (state[1] == state2['state']['key']).all() + assert (state[2] == state2['state']['pos']) + assert (state[3] == state2['has_gauss']) + assert (state[4] == state2['gauss']) + def test_common_seed(self): self.rg.seed(1234) self.nprs.seed(1234) @@ -162,37 +183,6 @@ def test_tomaxint(self): self.rg.tomaxint) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_chisquare(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.chisquare, - self.rg.chisquare) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_standard_gamma(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.standard_gamma, - self.rg.standard_gamma) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_standard_t(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.standard_t, - self.rg.standard_t) - self._is_state_common() - - def test_pareto(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.pareto, - self.rg.pareto) - self._is_state_common() - def test_poisson(self): self._set_common_state() self._is_state_common() @@ -200,13 +190,6 @@ def test_poisson(self): self.rg.poisson) self._is_state_common() - def test_power(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.power, - self.rg.power) - self._is_state_common() - def test_rayleigh(self): self._set_common_state() self._is_state_common() @@ -214,13 +197,6 @@ def test_rayleigh(self): self.rg.rayleigh) self._is_state_common() - def test_weibull(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.weibull, - self.rg.weibull) - self._is_state_common() - def test_zipf(self): self._set_common_state() self._is_state_common() @@ -244,37 +220,6 @@ def test_geometric(self): is_small=True) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_beta(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.beta, - self.rg.beta) - self._is_state_common() - - def test_exponential(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.exponential, - self.rg.exponential) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_f(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.f, - self.rg.f) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_gamma(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.gamma, - self.rg.gamma) - self._is_state_common() - def test_logistic(self): self._set_common_state() self._is_state_common() @@ -296,30 +241,6 @@ def test_laplace(self): self.rg.laplace) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_lognormal(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.lognormal, - self.rg.lognormal) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_noncentral_chisquare(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.noncentral_chisquare, - self.rg.noncentral_chisquare) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_normal(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.normal, - self.rg.normal) - self._is_state_common() - def test_uniform(self): self._set_common_state() self._is_state_common() @@ -334,14 +255,6 @@ def test_vonmises(self): self.rg.vonmises) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_wald(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.wald, - self.rg.wald) - self._is_state_common() - def test_random_integers(self): self._set_common_state() self._is_state_common() @@ -358,22 +271,6 @@ def test_binomial(self): is_np=True) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_negative_binomial(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.negative_binomial, - self.rg.negative_binomial, - is_np=True) - self._is_state_common() - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_randn(self): - f = self.rg.randn - g = self.nprs.randn - assert_allclose(f(10), g(10)) - assert_allclose(f(3, 4, 5), g(3, 4, 5)) - def test_rand(self): self._set_common_state() self._is_state_common() @@ -385,23 +282,6 @@ def test_rand(self): def test_poisson_lam_max(self): assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_dirichlet(self): - f = self.rg.dirichlet - g = self.nprs.dirichlet - a = [3, 4, 5, 6, 7, 10] - assert_allclose(f(a), g(a)) - assert_allclose(f(np.array(a), 10), g(np.array(a), 10)) - assert_allclose(f(np.array(a), (3, 37)), g(np.array(a), (3, 37))) - - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_noncentral_f(self): - self._set_common_state() - self._is_state_common() - compare_3_input(self.nprs.noncentral_f, - self.rg.noncentral_f) - self._is_state_common() - def test_triangular(self): self._set_common_state() self._is_state_common() @@ -473,22 +353,6 @@ def test_shuffle(self): assert_equal(fa, ga) self._is_state_common() - @pytest.mark.skip(reason='Box-Muller no longer supported') - def test_multivariate_normal(self): - self._set_common_state() - self._is_state_common() - mu = [1, 2, 3] - cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] - f = self.rg.multivariate_normal - g = self.nprs.multivariate_normal - assert_allclose(f(mu, cov), g(mu, cov)) - assert_allclose(f(np.array(mu), cov), g(np.array(mu), cov)) - assert_allclose(f(np.array(mu), np.array(cov)), - g(np.array(mu), np.array(cov))) - assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31)), - g(np.array(mu), np.array(cov), size=(7, 31))) - self._is_state_common() - def test_randint(self): self._set_common_state() self._is_state_common() @@ -546,3 +410,152 @@ def test_dir(self): diff = set(npmod).difference(mod) print(diff) assert_equal(len(diff), 0) + + # Tests using legacy generator + def test_chisquare(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.chisquare, + self.lg.chisquare) + self._is_state_common_legacy() + + def test_standard_gamma(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.standard_gamma, + self.lg.standard_gamma) + self._is_state_common_legacy() + + def test_standard_t(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.standard_t, + self.lg.standard_t) + self._is_state_common_legacy() + + def test_pareto(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.pareto, + self.lg.pareto) + self._is_state_common_legacy() + + def test_power(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.power, + self.lg.power) + self._is_state_common_legacy() + + def test_weibull(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.weibull, + self.lg.weibull) + self._is_state_common_legacy() + + def test_beta(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.beta, + self.lg.beta) + self._is_state_common_legacy() + + def test_exponential(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_1_input(self.nprs.exponential, + self.lg.exponential) + self._is_state_common_legacy() + + def test_f(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.f, + self.lg.f) + self._is_state_common_legacy() + + def test_gamma(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.gamma, + self.lg.gamma) + self._is_state_common_legacy() + + def test_lognormal(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.lognormal, + self.lg.lognormal) + self._is_state_common_legacy() + + def test_noncentral_chisquare(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.noncentral_chisquare, + self.lg.noncentral_chisquare) + self._is_state_common_legacy() + + def test_normal(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.normal, + self.lg.normal) + self._is_state_common_legacy() + + def test_wald(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.wald, + self.lg.wald) + self._is_state_common_legacy() + + def test_negative_binomial(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_2_input(self.nprs.negative_binomial, + self.lg.negative_binomial, + is_np=True) + self._is_state_common_legacy() + + def test_randn(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + f = self.lg.randn + g = self.nprs.randn + assert_allclose(f(10), g(10)) + assert_allclose(f(3, 4, 5), g(3, 4, 5)) + self._is_state_common_legacy() + + def test_dirichlet(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + f = self.lg.dirichlet + g = self.nprs.dirichlet + a = [3, 4, 5, 6, 7, 10] + assert_allclose(f(a), g(a)) + assert_allclose(f(np.array(a), 10), g(np.array(a), 10)) + assert_allclose(f(np.array(a), (3, 37)), g(np.array(a), (3, 37))) + self._is_state_common_legacy() + + def test_noncentral_f(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + compare_3_input(self.nprs.noncentral_f, + self.lg.noncentral_f) + self._is_state_common_legacy() + + def test_multivariate_normal(self): + self._set_common_state_legacy() + self._is_state_common_legacy() + mu = [1, 2, 3] + cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] + f = self.lg.multivariate_normal + g = self.nprs.multivariate_normal + assert_allclose(f(mu, cov), g(mu, cov)) + assert_allclose(f(np.array(mu), cov), g(np.array(mu), cov)) + assert_allclose(f(np.array(mu), np.array(cov)), + g(np.array(mu), np.array(cov))) + assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31)), + g(np.array(mu), np.array(cov), size=(7, 31))) + self._is_state_common_legacy() diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 85419b2172bf..c22aa35808f7 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -12,8 +12,11 @@ from randomgen._testing import suppress_warnings from randomgen import RandomGenerator, MT19937 +from randomgen.legacy import LegacyGenerator random = mt19937 = RandomGenerator(MT19937()) +legacy = LegacyGenerator(MT19937()) + class TestSeed(object): def test_scalar(self): @@ -122,16 +125,16 @@ def test_gaussian_reset_in_media_res(self): new = self.brng.standard_normal(size=3) assert_(np.all(old == new)) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_backwards_compatibility(self): # Make sure we can accept old state tuples that do not have the # cached Gaussian value. - old_state = self.legacy_state[:-2] - x1 = self.brng.standard_normal(size=16) - self.brng.state = old_state - x2 = self.brng.standard_normal(size=16) - self.brng.state = self.state - x3 = self.brng.standard_normal(size=16) + old_state = self.legacy_state + legacy.state = old_state + x1 = legacy.standard_normal(size=16) + legacy.state = old_state + x2 = legacy.standard_normal(size=16) + legacy.state = old_state + (0, 0.0) + x3 = legacy.standard_normal(size=16) assert_(np.all(x1 == x2)) assert_(np.all(x1 == x3)) @@ -169,8 +172,10 @@ def test_bounds_checking_array(self): 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 - assert_raises(ValueError, self.rfunc, [lbnd - 1] * 2, [ubnd] * 2, dtype=dt) - assert_raises(ValueError, self.rfunc, [lbnd] * 2, [ubnd + 1] * 2, dtype=dt) + assert_raises(ValueError, self.rfunc, [ + lbnd - 1] * 2, [ubnd] * 2, dtype=dt) + assert_raises(ValueError, self.rfunc, [ + lbnd] * 2, [ubnd + 1] * 2, dtype=dt) assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2, dtype=dt) assert_raises(ValueError, self.rfunc, [1] * 2, 0, dtype=dt) @@ -189,7 +194,8 @@ def test_rng_zero_and_extremes(self): tgt = (lbnd + ubnd) // 2 assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt) - assert_equal(self.rfunc([tgt], [tgt + 1], size=1000, dtype=dt), tgt) + assert_equal(self.rfunc([tgt], [tgt + 1], + size=1000, dtype=dt), tgt) def test_rng_zero_and_extremes_array(self): size = 1000 @@ -198,19 +204,28 @@ def test_rng_zero_and_extremes_array(self): ubnd = 2 if dt is bool else np.iinfo(dt).max + 1 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) + 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) + 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) + 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): # Test for ticket #1690 @@ -268,7 +283,8 @@ def test_scalar_array_equiv(self): scalar_array = self.rfunc([lbnd], [ubnd], size=size, dtype=dt) mt19937.seed(1234) - array = self.rfunc([lbnd] * size, [ubnd] * size, size=size, dtype=dt) + array = self.rfunc([lbnd] * size, [ubnd] * + size, size=size, dtype=dt) assert_array_equal(scalar, scalar_array) assert_array_equal(scalar, array) @@ -297,21 +313,20 @@ def test_repeatability(self): val = self.rfunc(0, 6, size=1000, dtype=dt).byteswap() res = hashlib.md5(val.view(np.int8)).hexdigest() - print(tgt[np.dtype(dt).name] == res) assert_(tgt[np.dtype(dt).name] == res) # bools do not depend on endianess mt19937.seed(1234) val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8) res = hashlib.md5(val).hexdigest() - print(tgt[np.dtype(bool).name] == res) assert_(tgt[np.dtype(bool).name] == res) def test_repeatability_broadcasting(self): 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 = 2 if dt in ( + np.bool, bool, np.bool_) else np.iinfo(dt).max + 1 # view as little endian for hash mt19937.seed(1234) @@ -405,10 +420,9 @@ def test_rand(self): [0.4575674820298663, 0.7781880808593471]]) assert_array_almost_equal(actual, desired, decimal=15) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_randn(self): - mt19937.seed(self.seed) - actual = mt19937.randn(3, 2) + legacy.seed(self.seed) + actual = legacy.randn(3, 2) desired = np.array([[1.34016345771863121, 1.73759122771936081], [1.498988344300628, -0.2286433324536169], [2.031033998682787, 2.17032494605655257]]) @@ -612,20 +626,18 @@ def test_binomial(self): [46, 45]]) assert_array_equal(actual, desired) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_chisquare(self): - mt19937.seed(self.seed) - actual = mt19937.chisquare(50, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_dirichlet(self): - mt19937.seed(self.seed) + legacy.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) - actual = mt19937.dirichlet(alpha, size=(3, 2)) + actual = legacy.dirichlet(alpha, size=(3, 2)) desired = np.array([[[0.54539444573611562, 0.45460555426388438], [0.62345816822039413, 0.37654183177960598]], [[0.55206000085785778, 0.44793999914214233], @@ -654,8 +666,8 @@ def test_dirichlet_bad_alpha(self): assert_raises(ValueError, mt19937.dirichlet, alpha) def test_exponential(self): - mt19937.seed(self.seed) - actual = mt19937.exponential(1.1234, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.exponential(1.1234, size=(3, 2)) desired = np.array([[1.08342649775011624, 1.00607889924557314], [2.46628830085216721, 2.49668106809923884], [0.68717433461363442, 1.69175666993575979]]) @@ -665,19 +677,17 @@ def test_exponential_0(self): assert_equal(mt19937.exponential(scale=0), 0) assert_raises(ValueError, mt19937.exponential, scale=-0.) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_f(self): - mt19937.seed(self.seed) - actual = mt19937.f(12, 77, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gamma(self): - mt19937.seed(self.seed) - actual = mt19937.gamma(5, 3, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.gamma(5, 3, size=(3, 2)) desired = np.array([[24.60509188649287182, 28.54993563207210627], [26.13476110204064184, 12.56988482927716078], [31.71863275789960568, 33.30143302795922011]]) @@ -753,10 +763,9 @@ def test_logistic(self): [-0.21682183359214885, 2.63373365386060332]]) assert_array_almost_equal(actual, desired, decimal=15) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_lognormal(self): - mt19937.seed(self.seed) - actual = mt19937.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) desired = np.array([[16.50698631688883822, 36.54846706092654784], [22.67886599981281748, 0.71617561058995771], [65.72798501792723869, 86.84341601437161273]]) @@ -785,13 +794,12 @@ def test_multinomial(self): [4, 3, 4, 2, 3, 4]]]) assert_array_equal(actual, desired) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_multivariate_normal(self): - mt19937.seed(self.seed) + legacy.seed(self.seed) mean = (.123456789, 10) cov = [[1, 0], [0, 1]] size = (3, 2) - actual = mt19937.multivariate_normal(mean, cov, size) + actual = legacy.multivariate_normal(mean, cov, size) desired = np.array([[[1.463620246718631, 11.73759122771936], [1.622445133300628, 9.771356667546383]], [[2.154490787682787, 12.170324946056553], @@ -802,7 +810,7 @@ def test_multivariate_normal(self): assert_array_almost_equal(actual, desired, decimal=15) # Check for default size, was raising deprecation warning - actual = mt19937.multivariate_normal(mean, cov) + actual = legacy.multivariate_normal(mean, cov) desired = np.array([0.895289569463708, 9.17180864067987]) assert_array_almost_equal(actual, desired, decimal=15) @@ -820,51 +828,47 @@ def test_multivariate_normal(self): assert_raises(ValueError, mt19937.multivariate_normal, mean, cov, check_valid='raise') - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_negative_binomial(self): - mt19937.seed(self.seed) - actual = mt19937.negative_binomial(n=100, p=.12345, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.negative_binomial(n=100, p=.12345, size=(3, 2)) desired = np.array([[848, 841], [892, 611], [779, 647]]) assert_array_equal(actual, desired) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_chisquare(self): - mt19937.seed(self.seed) - actual = mt19937.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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 = mt19937.noncentral_chisquare(df=.5, nonc=.2, size=(3, 2)) + actual = legacy.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) - mt19937.seed(self.seed) - actual = mt19937.noncentral_chisquare(df=5, nonc=0, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_f(self): - mt19937.seed(self.seed) - actual = mt19937.noncentral_f(dfnum=5, dfden=2, nonc=1, - size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_normal(self): - mt19937.seed(self.seed) - actual = mt19937.normal(loc=.123456789, scale=2.0, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.normal(loc=.123456789, scale=2.0, size=(3, 2)) desired = np.array([[2.80378370443726244, 3.59863924443872163], [3.121433477601256, -0.33382987590723379], [4.18552478636557357, 4.46410668111310471]]) @@ -875,8 +879,8 @@ def test_normal_0(self): assert_raises(ValueError, mt19937.normal, scale=-0.) def test_pareto(self): - mt19937.seed(self.seed) - actual = mt19937.pareto(a=.123456789, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.pareto(a=.123456789, size=(3, 2)) desired = np.array( [[2.46852460439034849e+03, 1.41286880810518346e+03], [5.28287797029485181e+07, 6.57720981047328785e+07], @@ -906,8 +910,8 @@ def test_poisson_exceptions(self): assert_raises(ValueError, mt19937.poisson, [lambig] * 10) def test_power(self): - mt19937.seed(self.seed) - actual = mt19937.power(a=.123456789, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.power(a=.123456789, size=(3, 2)) desired = np.array([[0.02048932883240791, 0.01424192241128213], [0.38446073748535298, 0.39499689943484395], [0.00177699707563439, 0.13115505880863756]]) @@ -925,10 +929,9 @@ def test_rayleigh_0(self): assert_equal(mt19937.rayleigh(scale=0), 0) assert_raises(ValueError, mt19937.rayleigh, scale=-0.) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_cauchy(self): - mt19937.seed(self.seed) - actual = mt19937.standard_cauchy(size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.standard_cauchy(size=(3, 2)) desired = np.array([[0.77127660196445336, -6.55601161955910605], [0.93582023391158309, -2.07479293013759447], [-4.74601644297011926, 0.18338989290760804]]) @@ -942,10 +945,9 @@ def test_standard_exponential(self): [0.6116915921431676, 1.50592546727413201]]) assert_array_almost_equal(actual, desired, decimal=15) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_gamma(self): - mt19937.seed(self.seed) - actual = mt19937.standard_gamma(shape=3, size=(3, 2), method='inv') + legacy.seed(self.seed) + actual = legacy.standard_gamma(shape=3, size=(3, 2)) desired = np.array([[5.50841531318455058, 6.62953470301903103], [5.93988484943779227, 2.31044849402133989], [7.54838614231317084, 8.012756093271868]]) @@ -955,19 +957,17 @@ def test_standard_gamma_0(self): assert_equal(mt19937.standard_gamma(shape=0), 0) assert_raises(ValueError, mt19937.standard_gamma, shape=-0.) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_normal(self): - mt19937.seed(self.seed) - actual = mt19937.standard_normal(size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_t(self): - mt19937.seed(self.seed) - actual = mt19937.standard_t(df=10, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.standard_t(df=10, size=(3, 2)) desired = np.array([[0.97140611862659965, -0.08830486548450577], [1.36311143689505321, -0.55317463909867071], [-0.18473749069684214, 0.61181537341755321]]) @@ -1018,7 +1018,8 @@ def __float__(self): raise TypeError throwing_float = np.array(1.0).view(ThrowingFloat) - assert_raises(TypeError, mt19937.uniform, throwing_float, throwing_float) + assert_raises(TypeError, mt19937.uniform, + throwing_float, throwing_float) class ThrowingInteger(np.ndarray): def __int__(self): @@ -1041,18 +1042,17 @@ def test_vonmises_small(self): r = mt19937.vonmises(mu=0., kappa=1.1e-8, size=10 ** 6) assert_(np.isfinite(r).all()) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_wald(self): - mt19937.seed(self.seed) - actual = mt19937.wald(mean=1.23, scale=1.54, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.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): - mt19937.seed(self.seed) - actual = mt19937.weibull(a=1.23, size=(3, 2)) + legacy.seed(self.seed) + actual = legacy.weibull(a=1.23, size=(3, 2)) desired = np.array([[0.97097342648766727, 0.91422896443565516], [1.89517770034962929, 1.91414357960479564], [0.67057783752390987, 1.39494046635066793]]) @@ -1079,6 +1079,7 @@ def setup(self): def set_seed(self): random.seed(self.seed) + legacy.seed(self.seed) def test_uniform(self): low = [0] @@ -1096,12 +1097,11 @@ def test_uniform(self): actual = uniform(low, high * 3) assert_array_almost_equal(actual, desired, decimal=14) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_normal(self): loc = [0] scale = [1] bad_scale = [-1] - normal = random.normal + normal = legacy.normal desired = np.array([2.2129019979039612, 2.1283977976520019, 1.8417114045748335]) @@ -1116,13 +1116,12 @@ def test_normal(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, normal, loc, bad_scale * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_beta(self): a = [1] b = [2] bad_a = [-1] bad_b = [-2] - beta = random.beta + beta = legacy.beta desired = np.array([0.19843558305989056, 0.075230336409423643, 0.24976865978980844]) @@ -1142,7 +1141,7 @@ def test_beta(self): def test_exponential(self): scale = [1] bad_scale = [-1] - exponential = random.exponential + exponential = legacy.exponential desired = np.array([0.76106853658845242, 0.76386282278691653, 0.71243813125891797]) @@ -1152,27 +1151,25 @@ def test_exponential(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, exponential, bad_scale * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_gamma(self): shape = [1] bad_shape = [-1] - std_gamma = random.standard_gamma + std_gamma = legacy.standard_gamma desired = np.array([0.76106853658845242, 0.76386282278691653, 0.71243813125891797]) self.set_seed() - actual = std_gamma(shape * 3, method='inv') + actual = std_gamma(shape * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, std_gamma, bad_shape * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_gamma(self): shape = [1] scale = [2] bad_shape = [-1] bad_scale = [-2] - gamma = random.gamma + gamma = legacy.gamma desired = np.array([1.5221370731769048, 1.5277256455738331, 1.4248762625178359]) @@ -1189,13 +1186,12 @@ def test_gamma(self): assert_raises(ValueError, gamma, bad_shape, scale * 3) assert_raises(ValueError, gamma, shape, bad_scale * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_f(self): dfnum = [1] dfden = [2] bad_dfnum = [-1] bad_dfden = [-2] - f = random.f + f = legacy.f desired = np.array([0.80038951638264799, 0.86768719635363512, 2.7251095168386801]) @@ -1212,7 +1208,6 @@ def test_f(self): assert_raises(ValueError, f, bad_dfnum, dfden * 3) assert_raises(ValueError, f, dfnum, bad_dfden * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_f(self): dfnum = [2] dfden = [3] @@ -1220,7 +1215,7 @@ def test_noncentral_f(self): bad_dfnum = [0] bad_dfden = [-1] bad_nonc = [-2] - nonc_f = random.noncentral_f + nonc_f = legacy.noncentral_f desired = np.array([9.1393943263705211, 13.025456344595602, 8.8018098359100545]) @@ -1259,13 +1254,12 @@ def test_chisquare(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, chisquare, bad_df * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_noncentral_chisquare(self): df = [1] nonc = [2] bad_df = [-1] bad_nonc = [-2] - nonc_chi = random.noncentral_chisquare + nonc_chi = legacy.noncentral_chisquare desired = np.array([9.0015599467913763, 4.5804135049718742, 6.0872302432834564]) @@ -1282,11 +1276,10 @@ def test_noncentral_chisquare(self): assert_raises(ValueError, nonc_chi, bad_df, nonc * 3) assert_raises(ValueError, nonc_chi, df, bad_nonc * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_standard_t(self): df = [1] bad_df = [-1] - t = random.standard_t + t = legacy.standard_t desired = np.array([3.0702872575217643, 5.8560725167361607, 1.0274791436474273]) @@ -1318,7 +1311,7 @@ def test_vonmises(self): def test_pareto(self): a = [1] bad_a = [-1] - pareto = random.pareto + pareto = legacy.pareto desired = np.array([1.1405622680198362, 1.1465519762044529, 1.0389564467453547]) @@ -1331,7 +1324,7 @@ def test_pareto(self): def test_weibull(self): a = [1] bad_a = [-1] - weibull = random.weibull + weibull = legacy.weibull desired = np.array([0.76106853658845242, 0.76386282278691653, 0.71243813125891797]) @@ -1344,7 +1337,7 @@ def test_weibull(self): def test_power(self): a = [1] bad_a = [-1] - power = random.power + power = legacy.power desired = np.array([0.53283302478975902, 0.53413660089041659, 0.50955303552646702]) @@ -1411,12 +1404,11 @@ def test_logistic(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, logistic, loc, bad_scale * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_lognormal(self): mean = [0] sigma = [1] bad_sigma = [-1] - lognormal = random.lognormal + lognormal = legacy.lognormal desired = np.array([9.1422086044848427, 8.4013952870126261, 6.3073234116578671]) @@ -1444,13 +1436,12 @@ def test_rayleigh(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, rayleigh, bad_scale * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') def test_wald(self): mean = [0.5] scale = [1] bad_mean = [0] bad_scale = [-2] - wald = random.wald + wald = legacy.wald desired = np.array([0.11873681120271318, 0.12450084820795027, 0.9096122728408238]) @@ -1484,21 +1475,24 @@ def test_triangular(self): 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.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) + 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, bad_left_two, + bad_mode_two, right * 3) def test_binomial(self): n = [1] @@ -1523,14 +1517,13 @@ def test_binomial(self): assert_raises(ValueError, binom, n, bad_p_one * 3) assert_raises(ValueError, binom, n, bad_p_two * 3) - @pytest.mark.skip(reason='Box-Muller no longer supported') 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 + neg_binom = legacy.negative_binomial desired = np.array([1, 0, 1]) self.set_seed() diff --git a/_randomgen/requirements.txt b/_randomgen/requirements.txt index f2f2e06ad0aa..6c3af8ca3a6b 100644 --- a/_randomgen/requirements.txt +++ b/_randomgen/requirements.txt @@ -1,4 +1,4 @@ numpy>=1.10 -cython>=0.24 +cython>=0.26 setuptools wheel \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index c010cfc9bff5..219db375e159 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -204,6 +204,16 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("randomgen.legacy.legacy", + ["randomgen/legacy/legacy.pyx", + join(MOD_DIR, 'src', 'legacy', + 'distributions-boxmuller.c'), + join(MOD_DIR, 'src', 'distributions', 'distributions.c')], + include_dirs=EXTRA_INCLUDE_DIRS + + [np.get_include()] + [join(MOD_DIR, 'legacy')], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), ] From 8711b32506886f3f3edda75f50b67fad7b8f64db Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 27 Mar 2018 10:43:21 +0100 Subject: [PATCH 072/138] DOC: Update multithreading doc Update performance comp --- _randomgen/doc/source/multithreading.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/_randomgen/doc/source/multithreading.rst b/_randomgen/doc/source/multithreading.rst index 253764632c77..6efbcdbe76e3 100644 --- a/_randomgen/doc/source/multithreading.rst +++ b/_randomgen/doc/source/multithreading.rst @@ -80,8 +80,9 @@ the time required to generate using a single thread. In [4]: print(mrng.threads) ...: %timeit mrng.fill() + 4 - 42.9 ms ± 2.55 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) + 32.8 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) The single threaded call directly uses the PRNG. @@ -90,7 +91,8 @@ The single threaded call directly uses the PRNG. In [5]: values = np.empty(10000000) ...: rg = Xorshift1024().generator ...: %timeit rg.standard_normal(out=values) - 220 ms ± 27.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) + + 99.6 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) The gains are substantial and the scaling is reasonable even for large that are only moderately large. The gains are even larger when compared to a call @@ -100,5 +102,5 @@ that does not use an existing array due to array creation overhead. In [6]: rg = Xorshift1024().generator ...: %timeit rg.standard_normal(10000000) - ...: - 256 ms ± 41.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) + + 125 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) From 018faf72565902a5dd27056a3fc95879406c1cf1 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 27 Mar 2018 10:55:40 +0100 Subject: [PATCH 073/138] CLN: Remove set/get state for system generator Remove ability to set or get the state of the default generator --- _randomgen/randomgen/generator.pyx | 3 --- 1 file changed, 3 deletions(-) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index c9d7659945a6..7c9e1699484f 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -4315,9 +4315,6 @@ standard_exponential = _random_generator.standard_exponential standard_gamma = _random_generator.standard_gamma standard_normal = _random_generator.standard_normal standard_t = _random_generator.standard_t -get_state = lambda: _random_generator.state -def set_state(state): - _random_generator.state = state tomaxint = _random_generator.tomaxint triangular = _random_generator.triangular uniform = _random_generator.uniform From 75025d98a85feff614644044e40a3f47e2285d86 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 27 Mar 2018 11:28:34 +0100 Subject: [PATCH 074/138] TST: Fix tailing test on 32bit platofrms Relax check for 32 bit platforms --- _randomgen/randomgen/tests/test_against_numpy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index a7da65d5997b..480e1a2d110c 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -128,7 +128,7 @@ def _is_state_common_legacy(self): assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) assert (state[3] == state2['has_gauss']) - assert (state[4] == state2['gauss']) + assert_allclose(state[4], state2['gauss'], atol=1e-10) def test_common_seed(self): self.rg.seed(1234) From 4f3749970d4ba1ebdd470df0935fce96a66d8c48 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Mar 2018 13:01:00 +0100 Subject: [PATCH 075/138] CLN: Fix str for RandomGenerator Update __str__ to use class name to solve oop naming issue in LegacyGen --- _randomgen/randomgen/generator.pyx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 7c9e1699484f..724ebdcdb33f 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -114,7 +114,9 @@ cdef class RandomGenerator: return self.__str__() + ' at 0x{:X}'.format(id(self)) def __str__(self): - return 'RandomGenerator(' + self._basicrng.__class__.__name__ + ')' + _str = self.__class__.__name__ + _str += '(' + self._basicrng.__class__.__name__ + ')' + return _str # Pickling support: def __getstate__(self): From 7d37f5f292bd35d8cd2822670b768601a69b8b2b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Mar 2018 21:19:59 +0100 Subject: [PATCH 076/138] DOC: Update legacy docs Update documentation about legacy generation --- _randomgen/README.md | 9 ++++--- _randomgen/README.rst | 15 ++++++----- _randomgen/doc/source/generator.rst | 8 ++++++ _randomgen/doc/source/index.rst | 11 +++++--- _randomgen/doc/source/legacy.rst | 2 +- _randomgen/doc/source/new-or-different.rst | 9 ++++--- _randomgen/randomgen/generator.pyx | 29 ++++++++++++++++++++++ 7 files changed, 66 insertions(+), 17 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index e1fe7cbd4df0..fbcc1f6d25bc 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -10,11 +10,14 @@ NumPy RandomState evolution. This is a library and generic interface for alternative random generators in Python and NumPy. -### Compatibility Warning -RandomGen no longer supports Box-Muller normal variates and so it not +## Compatibility Warning + +`RandomGenerator` does notsupports Box-Muller normal variates and so it not 100% compatible with NumPy (or randomstate). Box-Muller normals are slow to generate and all functions which previously relied on Box-Muller -normals now use the faster Ziggurat implementation. +normals now use the faster Ziggurat implementation. If you require backward +compatibility, a legacy generator, ``LegacyGenerator``, has been created +which can fully reproduce the sequence produced by NumPy. ## Features diff --git a/_randomgen/README.rst b/_randomgen/README.rst index e37a7193cf64..587d73f82231 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -10,12 +10,15 @@ This is a library and generic interface for alternative random generators in Python and NumPy. Compatibility Warning -~~~~~~~~~~~~~~~~~~~~~ - -RandomGen no longer supports Box-Muller normal variates and so it not -100% compatible with NumPy (or randomstate). Box-Muller normals are slow -to generate and all functions which previously relied on Box-Muller -normals now use the faster Ziggurat implementation. +--------------------- + +``RandomGenerator`` does notsupports Box-Muller normal variates and so +it not 100% compatible with NumPy (or randomstate). Box-Muller normals +are slow to generate and all functions which previously relied on +Box-Muller normals now use the faster Ziggurat implementation. If you +require backward compatibility, a legacy generator, ``LegacyGenerator``, +has been created which can fully reproduce the sequence produced by +NumPy. Features -------- diff --git a/_randomgen/doc/source/generator.rst b/_randomgen/doc/source/generator.rst index 2fedc8f58b72..4e8e46718d7c 100644 --- a/_randomgen/doc/source/generator.rst +++ b/_randomgen/doc/source/generator.rst @@ -17,6 +17,14 @@ changed by passing an instantized basic RNG to .. autoclass:: RandomGenerator +Seed and State Manipulation +================== +.. autosummary:: + :toctree: generated/ + + ~RandomGenerator.seed + ~RandomGenerator.state + Simple random data ================== .. autosummary:: diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index c0b55f5cb215..0885666c8826 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -92,11 +92,14 @@ What's New or Different ~~~~~~~~~~~~~~~~~~~~~~~ .. warning:: - The Box-Muller method used to produce NumPy's normals is no longer available. - It is not possible to exactly reproduce the random values produced from NumPy + The Box-Muller method used to produce NumPy's normals is no longer available + in :class:`~randomgen.generator.RandomGenerator`. It is not possible to + reproduce the random values using :class:`~randomgen.generator.RandomGenerator` for the normal distribution or any other distribution that relies on the - normal such as the gamma or student's t. - + normal such as the gamma or student's t. If you require backward compatibility, a + legacy generator, :class:`~randomgen.legacy.LegacyGenerator`, has been created + which can fully reproduce the sequence produced by NumPy. + * The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF implementations. diff --git a/_randomgen/doc/source/legacy.rst b/_randomgen/doc/source/legacy.rst index 8a73f9029c92..befd7abb5fd9 100644 --- a/_randomgen/doc/source/legacy.rst +++ b/_randomgen/doc/source/legacy.rst @@ -47,7 +47,7 @@ when accessing the state so that these extra values are saved. lg.standard_exponential() -.. currentmodule:: randomgen.legacy +.. currentmodule:: randomgen.legacy.legacy .. autoclass:: LegacyGenerator diff --git a/_randomgen/doc/source/new-or-different.rst b/_randomgen/doc/source/new-or-different.rst index fdff589461e5..c94d95c7c094 100644 --- a/_randomgen/doc/source/new-or-different.rst +++ b/_randomgen/doc/source/new-or-different.rst @@ -5,10 +5,13 @@ What's New or Different .. warning:: - The Box-Muller method used to produce NumPy's normals is no longer available. - It is not possible to exactly reproduce the random values produced from NumPy + The Box-Muller method used to produce NumPy's normals is no longer available + in :class:`~randomgen.generator.RandomGenerator`. It is not possible to + reproduce the random values using :class:`~randomgen.generator.RandomGenerator` for the normal distribution or any other distribution that relies on the - normal such as the gamma or student's t. + normal such as the gamma or student's t. If you require backward compatibility, a + legacy generator, :class:`~randomgen.legacy.LegacyGenerator`, has been created + which can fully reproduce the sequence produced by NumPy. * :func:`~randomgen.entropy.random_entropy` provides access to the system diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 724ebdcdb33f..773f34d61bfc 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -135,6 +135,30 @@ cdef class RandomGenerator: Reseed the basic RNG. Parameters depend on the basic RNG used. + + Notes + ----- + Arguments are directly passed to the basic RNG. This is a convenience + function. + + The best method to access seed is to directly use a basic RNG instance. + This example demonstrates this best practice. + + >>> from randomgen import RandomGenerator, PCG64 + >>> brng = PCG64(1234567891011) + >>> rg = brng.generator + >>> brng.seed(1110987654321) + + The method used to create the generator is not important. + + >>> brng = PCG64(1234567891011) + >>> rg = RandomGenerator(brng) + >>> brng.seed(1110987654321) + + These best practice examples are equivalent to + + >>> rg = RandomGenerator(PCG64(1234567891011)) + >>> rg.seed(1110987654321) """ # TODO: Should this remain self._basicrng.seed(*args, **kwargs) @@ -150,6 +174,11 @@ cdef class RandomGenerator: state : dict Dictionary containing the information required to describe the state of the Basic RNG + + Notes + ----- + This is a trivial pass-through function. RandomGenerator does not + directly contain or manipulate the basic RNG's state. """ return self._basicrng.state From a2e21e62904d1f5b7c103ffa48bedc9d3cf37787 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Mar 2018 22:54:18 +0100 Subject: [PATCH 077/138] BUG: Fix pickle for LegacyGenerator --- _randomgen/doc/source/generator.rst | 2 +- _randomgen/randomgen/legacy/legacy.pyx | 29 +++++++++++++++++-- .../randomgen/tests/test_against_numpy.py | 1 - _randomgen/randomgen/tests/test_legacy.py | 12 ++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 _randomgen/randomgen/tests/test_legacy.py diff --git a/_randomgen/doc/source/generator.rst b/_randomgen/doc/source/generator.rst index 4e8e46718d7c..dba51eb6d00f 100644 --- a/_randomgen/doc/source/generator.rst +++ b/_randomgen/doc/source/generator.rst @@ -18,7 +18,7 @@ changed by passing an instantized basic RNG to RandomGenerator Seed and State Manipulation -================== +=========================== .. autosummary:: :toctree: generated/ diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index 0a5a67bcf867..00ee0c6d72fe 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -108,7 +108,7 @@ cdef class LegacyGenerator: return self.__str__() + ' at 0x{:X}'.format(id(self)) def __str__(self): - return 'RandomGenerator(' + self._basicrng.__class__.__name__ + ')' + return self.__class__.__name__ + '(' + self._basicrng.__class__.__name__ + ')' # Pickling support: def __getstate__(self): @@ -131,7 +131,33 @@ cdef class LegacyGenerator: Reseed the basic RNG. Parameters depend on the basic RNG used. + + Notes + ----- + Arguments are directly passed to the basic RNG. This is a convenience + function. + + The best method to access seed is to directly use a basic RNG instance. + This example demonstrates this best practice. + + >>> from randomgen import MT19937 + >>> from randomgen.legacy import LegacyGenerator + >>> brng = MT19937(123456789) + >>> lg = brng.generator + >>> brng.seed(987654321) + + The method used to create the generator is not important. + + >>> brng = MT19937(123456789) + >>> lg = LegacyGenerator(brng) + >>> brng.seed(987654321) + + These best practice examples are equivalent to + + >>> lg = LegacyGenerator(MT19937(123456789)) + >>> lg.seed(987654321) """ + # TODO: Should this remain self._basicrng.seed(*args, **kwargs) self._reset_gauss() @@ -168,7 +194,6 @@ cdef class LegacyGenerator: st['has_gauss'] = value[3] st['gauss'] = value[4] value = st - self._aug_state.gauss = value.get('gauss', 0.0) self._aug_state.has_gauss = value.get('has_gauss', 0) self._basicrng.state = value diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index 480e1a2d110c..cce6228a33d7 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -408,7 +408,6 @@ def test_dir(self): 'print_function', 'RandomState'] mod += known_exlcuded diff = set(npmod).difference(mod) - print(diff) assert_equal(len(diff), 0) # Tests using legacy generator diff --git a/_randomgen/randomgen/tests/test_legacy.py b/_randomgen/randomgen/tests/test_legacy.py new file mode 100644 index 000000000000..e45ba3619796 --- /dev/null +++ b/_randomgen/randomgen/tests/test_legacy.py @@ -0,0 +1,12 @@ +import pickle + +from randomgen.legacy import LegacyGenerator + + +def test_pickle(): + lg = LegacyGenerator() + lg.random_sample(100) + lg.standard_normal() + lg2 = pickle.loads(pickle.dumps(lg)) + assert lg.standard_normal() == lg2.standard_normal() + assert lg.random_sample() == lg2.random_sample() From 799e20bfd5fad3a44cc0f6514655d208cdfc8f29 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 28 Mar 2018 23:52:41 +0100 Subject: [PATCH 078/138] TST: Make test more verbose, clean up noise --- _randomgen/randomgen/bounded_integers.pyx.in | 1 + _randomgen/randomgen/common.pyx | 1 + _randomgen/randomgen/dsfmt.pyx | 2 ++ _randomgen/randomgen/entropy.pyx | 2 ++ _randomgen/randomgen/generator.pyx | 2 ++ _randomgen/randomgen/legacy/legacy.pyx | 2 ++ _randomgen/randomgen/mt19937.pyx | 2 ++ _randomgen/randomgen/pcg32.pyx | 2 ++ _randomgen/randomgen/pcg64.pyx | 2 ++ _randomgen/randomgen/philox.pyx | 2 ++ _randomgen/randomgen/tests/test_numpy_mt19937.py | 3 ++- _randomgen/randomgen/threefry.pyx | 2 ++ _randomgen/randomgen/threefry32.pyx | 2 ++ _randomgen/randomgen/xoroshiro128.pyx | 2 ++ _randomgen/randomgen/xorshift1024.pyx | 2 ++ 15 files changed, 28 insertions(+), 1 deletion(-) diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index ff4885130cf8..adeaa70059aa 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -1,5 +1,6 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +from __future__ import absolute_import import numpy as np cimport numpy as np diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index 6189ba19920b..e627d798363b 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -1,5 +1,6 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +from __future__ import absolute_import from collections import namedtuple from cpython cimport PyFloat_AsDouble diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index fa70b4ef52b4..5fcd3fccd043 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import operator from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/entropy.pyx b/_randomgen/randomgen/entropy.pyx index bb1c14b4b32d..2c85066c1d9d 100644 --- a/_randomgen/randomgen/entropy.pyx +++ b/_randomgen/randomgen/entropy.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import operator cimport numpy as np diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 773f34d61bfc..abc352eced05 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -1,5 +1,7 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +from __future__ import absolute_import + import operator import warnings diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index 00ee0c6d72fe..ce62216a646f 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -1,5 +1,7 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +from __future__ import absolute_import + import warnings import operator diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index e05a78e481ff..18caeb9ac4fd 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import operator from libc.stdlib cimport malloc, free diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index 5043db8c66a4..2479cd66eb22 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index c00d91966864..3bf2a1051476 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index 7c27467e9bd3..70a1b9677690 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index c22aa35808f7..468a6232e290 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -56,7 +56,8 @@ def test_n_zero(self): # This test addresses issue #3480. zeros = np.zeros(2, dtype='int') for p in [0, .5, 1]: - assert_(random.binomial(0, p) == 0) + val = random.binomial(0, p) + assert val == 0 assert_array_equal(random.binomial(zeros, p), zeros) def test_p_is_nan(self): diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index e347959c3aad..84cf7d9a69d3 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index 41de1688860f..a308417828df 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import numpy as np from cpython.pycapsule cimport PyCapsule_New from distributions cimport brng_t diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index 01b51376a38b..4a5d98fe9deb 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index aef61e9abed7..b254351cc5d5 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New From 80a3fe1a977d6b43d7b11eb303d16f5085fc6548 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 2 Apr 2018 09:31:35 +0100 Subject: [PATCH 079/138] BUG: Fix absolute_import Use full import paths to resolve absolute_import bug --- _randomgen/randomgen/bounded_integers.pxd.in | 5 ++++- _randomgen/randomgen/bounded_integers.pyx.in | 4 +++- _randomgen/randomgen/common.pxd | 4 +++- _randomgen/randomgen/common.pyx | 3 ++- _randomgen/randomgen/dsfmt.pyx | 6 +++--- _randomgen/randomgen/generator.pyx | 6 +++--- _randomgen/randomgen/mt19937.pyx | 8 ++++---- _randomgen/randomgen/pcg32.pyx | 6 +++--- _randomgen/randomgen/pcg64.pyx | 6 +++--- _randomgen/randomgen/philox.pyx | 6 +++--- _randomgen/randomgen/threefry.pyx | 6 +++--- _randomgen/randomgen/threefry32.pyx | 8 ++++---- _randomgen/randomgen/xoroshiro128.pyx | 6 +++--- _randomgen/randomgen/xorshift1024.pyx | 6 +++--- 14 files changed, 44 insertions(+), 36 deletions(-) diff --git a/_randomgen/randomgen/bounded_integers.pxd.in b/_randomgen/randomgen/bounded_integers.pxd.in index 4e1a6409146e..69d2fc0e7242 100644 --- a/_randomgen/randomgen/bounded_integers.pxd.in +++ b/_randomgen/randomgen/bounded_integers.pxd.in @@ -1,10 +1,13 @@ +from __future__ import absolute_import + from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, intptr_t) -from common cimport brng_t import numpy as np cimport numpy as np ctypedef np.npy_bool bool_t +from randomgen.common cimport brng_t + _randint_types = {'bool': (0, 2), 'int8': (-2**7, 2**7), 'int16': (-2**15, 2**15), diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index adeaa70059aa..bdd31a84410c 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -4,7 +4,9 @@ from __future__ import absolute_import import numpy as np cimport numpy as np -from distributions cimport * + +from randomgen.distributions cimport * + np.import_array() {{ diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd index 5a661dfb3db1..f6017c0d7504 100644 --- a/_randomgen/randomgen/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -1,9 +1,11 @@ +from __future__ import absolute_import + 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 -from distributions cimport brng_t +from randomgen.distributions cimport brng_t import numpy as np cimport numpy as np diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index e627d798363b..73638aaa32bb 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -7,7 +7,8 @@ from cpython cimport PyFloat_AsDouble import sys import numpy as np cimport numpy as np -from common cimport * + +from randomgen.common cimport * np.import_array() diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index 5fcd3fccd043..ef813f10ff7e 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -7,9 +7,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy import randomgen.pickle diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index abc352eced05..4abe1e54d12e 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -8,9 +8,6 @@ import warnings from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles, PyFloat_AsDouble) -from common cimport * -from distributions cimport * -from bounded_integers cimport * from libc cimport string from libc.stdlib cimport malloc, free cimport numpy as np @@ -22,6 +19,9 @@ try: except ImportError: from dummy_threading import Lock +from randomgen.bounded_integers cimport * +from randomgen.common cimport * +from randomgen.distributions cimport * from randomgen.xoroshiro128 import Xoroshiro128 import randomgen.pickle diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index 18caeb9ac4fd..df3d03b0bc71 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -8,11 +8,11 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t -import randomgen.pickle +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy +import randomgen.pickle np.import_array() diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index 2479cd66eb22..0148c4ec18f9 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -6,9 +6,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy import randomgen.pickle diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index 3bf2a1051476..226c47a272a0 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -6,9 +6,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy import randomgen.pickle diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index 70a1b9677690..610f3d055586 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -5,9 +5,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array import randomgen.pickle diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index 84cf7d9a69d3..789c50c44146 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -5,9 +5,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array import randomgen.pickle diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index a308417828df..4a11ce693653 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -2,13 +2,13 @@ from __future__ import absolute_import import numpy as np from cpython.pycapsule cimport PyCapsule_New -from distributions cimport brng_t from libc.stdlib cimport malloc, free -import randomgen.pickle -from common cimport * -from common import interface +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle np.import_array() diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index 4a5d98fe9deb..061e03f5ff00 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -6,9 +6,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array import randomgen.pickle diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index b254351cc5d5..98065d447a90 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -6,9 +6,9 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from common import interface -from common cimport * -from distributions cimport brng_t +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t from randomgen.entropy import random_entropy, seed_by_array import randomgen.pickle From d13f398a30884552ac11d626f73d01e21fd069a0 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 2 Apr 2018 10:20:06 +0100 Subject: [PATCH 080/138] DOC: Spelling changes --- _randomgen/README.md | 4 ++-- _randomgen/README.rst | 4 ++-- _randomgen/doc/source/change-log.rst | 1 + _randomgen/randomgen/dsfmt.pyx | 4 ++-- _randomgen/randomgen/generator.pyx | 4 ++-- _randomgen/randomgen/legacy/legacy.pyx | 6 +++--- _randomgen/randomgen/mt19937.pyx | 4 ++-- _randomgen/randomgen/pcg32.pyx | 2 +- _randomgen/randomgen/pcg64.pyx | 2 +- _randomgen/randomgen/philox.pyx | 2 +- _randomgen/randomgen/threefry.pyx | 6 +++--- _randomgen/randomgen/threefry32.pyx | 2 +- _randomgen/randomgen/xoroshiro128.pyx | 2 +- _randomgen/randomgen/xorshift1024.pyx | 2 +- 14 files changed, 23 insertions(+), 22 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index fbcc1f6d25bc..c90d9e2256ce 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -12,7 +12,7 @@ generators in Python and NumPy. ## Compatibility Warning -`RandomGenerator` does notsupports Box-Muller normal variates and so it not +`RandomGenerator` does not support Box-Muller normal variates and so it not 100% compatible with NumPy (or randomstate). Box-Muller normals are slow to generate and all functions which previously relied on Box-Muller normals now use the faster Ziggurat implementation. If you require backward @@ -128,7 +128,7 @@ the RNG._ ## Version The version matched the latest version of NumPy where -`RandoMGenerator(MT19937())` passes all NumPy test. +`RandomGenerator(MT19937())` passes all NumPy test. ## Documentation diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 587d73f82231..79252abc4347 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -12,7 +12,7 @@ generators in Python and NumPy. Compatibility Warning --------------------- -``RandomGenerator`` does notsupports Box-Muller normal variates and so +``RandomGenerator`` does not support Box-Muller normal variates and so it not 100% compatible with NumPy (or randomstate). Box-Muller normals are slow to generate and all functions which previously relied on Box-Muller normals now use the faster Ziggurat implementation. If you @@ -140,7 +140,7 @@ Version ------- The version matched the latest version of NumPy where -``RandoMGenerator(MT19937())`` passes all NumPy test. +``RandomGenerator(MT19937())`` passes all NumPy test. Documentation ------------- diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 9029981e3ed5..271ee5647e13 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -4,6 +4,7 @@ Change Log Changes since v1.14 =================== +- Added absolute_import to avoid import noise on Python 2.7 - Add legacy generator which allows NumPy replication - Improve type handling of integers - Switch to array-fillers for 0 parameter distribution to improve performance diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index ef813f10ff7e..c83ade5cdf2f 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -86,7 +86,7 @@ cdef class DSFMT: Notes ----- ``DSFMT`` directly provides generators for doubles, and unsigned 32 and 64- - bit integers [1]_ . These are not firectly available and must be consumed + bit integers [1]_ . These are not directly available and must be consumed via a ``RandomGenerator`` object. The Python stdlib module "random" also contains a Mersenne Twister @@ -313,7 +313,7 @@ cdef class DSFMT: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 4abe1e54d12e..c996f905de4a 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -85,7 +85,7 @@ cdef class RandomGenerator: >>> from randomgen import MT19937 >>> rg = RandomGenerator(MT19937()) - The generator is also directly avialable from basic RNGs + The generator is also directly available from basic RNGs >>> rg = MT19937().generator >>> rg.standard_normal() @@ -375,7 +375,7 @@ cdef class RandomGenerator: .. 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, + where the normalization, B, is the beta function, .. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1} (1 - t)^{\\beta - 1} dt. diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index ce62216a646f..22b80d2d8bd3 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -32,9 +32,9 @@ cdef class LegacyGenerator: ``LegacyGenerator`` exposes a number of methods for generating random numbers for a set of distributions where the method used to produce random - samples has changed. Three core generators have changed: normals, exponentials - and gammas. These have been replaced by fster Ziggurat-based methds in - ``RadnomGenerator``. ``LegacyGenerator`` retains the slower methods + samples has changed. Three core generators have changed: normal, exponential + and gamma. These have been replaced by faster Ziggurat-based methods in + ``RandomGenerator``. ``_LegacyGenerator`` retains the slower methods to produce samples from these distributions as well as from distributions that depend on these such as the Chi-square, power or Weibull. diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index df3d03b0bc71..14ab24f39878 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -61,7 +61,7 @@ cdef class MT19937: Notes ----- ``MT19937`` directly provides generators for doubles, and unsigned 32 and 64- - bit integers [1]_ . These are not firectly available and must be consumed + bit integers [1]_ . These are not directly available and must be consumed via a ``RandomGenerator`` object. The Python stdlib module "random" also contains a Mersenne Twister @@ -299,7 +299,7 @@ cdef class MT19937: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/pcg32.pyx b/_randomgen/randomgen/pcg32.pyx index 0148c4ec18f9..5c83b1040b1d 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/_randomgen/randomgen/pcg32.pyx @@ -327,7 +327,7 @@ cdef class PCG32: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index 226c47a272a0..ae553d3a542a 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -386,7 +386,7 @@ cdef class PCG64: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index 610f3d055586..c08f54496317 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -394,7 +394,7 @@ cdef class Philox: def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index 789c50c44146..e8971ff42161 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -99,8 +99,8 @@ cdef class ThreeFry: ``ThreeFry`` can be used in parallel applications by calling the method ``jump`` which advances the state as-if :math:`2^{128}` random numbers have been generated. Alternatively, - ``advance`` can be used to advance the counter for an abritrary number of - positive steps in [0, 2**256). When using ``jump``, all generators should + ``advance`` can be used to advance the counter for an any + positive step in [0, 2**256). When using ``jump``, all generators should be initialized with the same seed to ensure that the segments come from the same sequence. Alternatively, ``ThreeFry`` can be used in parallel applications by using a sequence of distinct keys where each @@ -387,7 +387,7 @@ cdef class ThreeFry: def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index 4a11ce693653..512ce9d00d3b 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -382,7 +382,7 @@ cdef class ThreeFry32: def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index 061e03f5ff00..d9891e590334 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -273,7 +273,7 @@ cdef class Xoroshiro128: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index 98065d447a90..bf8f32e90de4 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -306,7 +306,7 @@ cdef class Xorshift1024: @property def ctypes(self): """ - Cytpes interface + Ctypes interface Returns ------- From df1758d22d5ae01ffeb03ce9a8c1feafd530d0ff Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 2 Apr 2018 17:05:31 +0100 Subject: [PATCH 081/138] CLN: Remove redeclared type Remove duplicate pcg128_t declaration --- _randomgen/randomgen/pcg64.pyx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index ae553d3a542a..e7939314e626 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -27,12 +27,6 @@ ELSE: cdef extern from "src/pcg64/pcg64.h": ctypedef __uint128_t pcg128_t -cdef extern from "src/pcg64/pcg64.h": - - ctypedef struct pcg128_t: - uint64_t high - uint64_t low - cdef extern from "src/pcg64/pcg64.h": cdef struct pcg_state_setseq_128: From 412e908724ec183c46d4f153e600073c3898c362 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 3 Apr 2018 12:19:51 +0100 Subject: [PATCH 082/138] BLD: Enable no-sse2 flag Enable no-sse2 flag to be set --- _randomgen/setup.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 219db375e159..828e0aa3f0c3 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -1,5 +1,6 @@ import os import glob +import platform import struct import sys from os.path import join @@ -36,7 +37,16 @@ Cython.Compiler.Options.annotate = True -USE_SSE2 = True if not '--no-sse2' in sys.argv else False +# Make a guess as to whether SSE2 is present for now, TODO: Improve +USE_SSE2 = False +for k in platform.uname(): + for val in ('x86', 'i686', 'i386', 'amd64'): + USE_SSE2 = USE_SSE2 or val in k.lower() +print('Building with SSE?: {0}'.format(USE_SSE2)) +if '--no-sse2' in sys.argv: + USE_SSE2 = False + sys.argv.remove('--no-sse2') + MOD_DIR = './randomgen' DEBUG = False From 87b52f2755e0eec51942d047e17ae5b1262817d9 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 16 Apr 2018 22:03:29 +0100 Subject: [PATCH 083/138] SYNC/CLN: Sync with upstream changes --- _randomgen/randomgen/examples/cython/setup.py | 3 +- .../randomgen/examples/numba/extending.py | 8 +- .../examples/numba/extending_distributions.py | 13 ++- _randomgen/randomgen/generator.pyx | 83 +++++++++---------- _randomgen/randomgen/legacy/legacy.pyx | 54 ++++++------ .../randomgen/tests/test_against_numpy.py | 33 ++++---- .../randomgen/tests/test_numpy_mt19937.py | 9 +- .../tests/test_numpy_mt19937_regressions.py | 7 +- _randomgen/randomgen/tests/test_smoke.py | 4 +- 9 files changed, 107 insertions(+), 107 deletions(-) diff --git a/_randomgen/randomgen/examples/cython/setup.py b/_randomgen/randomgen/examples/cython/setup.py index 480d5f508f8b..bf6fb81486c6 100644 --- a/_randomgen/randomgen/examples/cython/setup.py +++ b/_randomgen/randomgen/examples/cython/setup.py @@ -10,7 +10,8 @@ include_dirs=[np.get_include()]) distributions = Extension("extending_distributions", sources=['extending_distributions.pyx', - join('..', '..', 'randomgen', 'src', 'distributions', 'distributions.c')], + join('..', '..', 'randomgen', 'src', + 'distributions', 'distributions.c')], include_dirs=[np.get_include()]) extensions = [extending, distributions] diff --git a/_randomgen/randomgen/examples/numba/extending.py b/_randomgen/randomgen/examples/numba/extending.py index 09e07a437674..866b4070d05a 100644 --- a/_randomgen/randomgen/examples/numba/extending.py +++ b/_randomgen/randomgen/examples/numba/extending.py @@ -1,3 +1,5 @@ +import datetime as dt + import numpy as np import numba as nb @@ -31,7 +33,7 @@ def bounded_uint(lb, ub, state): def bounded_uints(lb, ub, n, state): out = np.empty(n, dtype=np.uint32) for i in range(n): - bounded_uint(lb, ub, state) + out[i] = bounded_uint(lb, ub, state) bounded_uints(323, 2394691, 10000000, s.value) @@ -57,11 +59,11 @@ def normals(n, state): 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) -import datetime as dt start = dt.datetime.now() normalsj(1000000, state_addr) @@ -69,8 +71,6 @@ def normals(n, state): print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms in ' '{ms:0.1f}ms'.format(ms=ms)) -import numpy as np - start = dt.datetime.now() np.random.standard_normal(1000000) ms = 1000 * (dt.datetime.now() - start).total_seconds() diff --git a/_randomgen/randomgen/examples/numba/extending_distributions.py b/_randomgen/randomgen/examples/numba/extending_distributions.py index 47f811c06d54..c0094bf1b882 100644 --- a/_randomgen/randomgen/examples/numba/extending_distributions.py +++ b/_randomgen/randomgen/examples/numba/extending_distributions.py @@ -1,16 +1,21 @@ 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} +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 +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 diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index c996f905de4a..40a876aa48d3 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -552,7 +552,7 @@ cdef class RandomGenerator: array([[[ True, True], [ True, True]], [[ True, True], - [ True, True]]], dtype=bool) + [ True, True]]]) """ cdef np.npy_intp n @@ -959,7 +959,7 @@ cdef class RandomGenerator: probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 15, normed=True) + >>> count, bins, ignored = plt.hist(s, 15, density=True) >>> plt.plot(bins, np.ones_like(bins), linewidth=2, color='r') >>> plt.show() """ @@ -1059,7 +1059,7 @@ cdef class RandomGenerator: argument is provided. This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `numpy.random.standard_normal` instead. + tuple as the first argument, use `standard_normal` instead. Parameters ---------- @@ -1080,7 +1080,7 @@ cdef class RandomGenerator: See Also -------- - random.standard_normal : Similar, but takes a tuple as its argument. + standard_normal : Similar, but takes a tuple as its argument. Notes ----- @@ -1141,7 +1141,7 @@ cdef class RandomGenerator: See Also -------- - random.randint : Similar to `random_integers`, only for the half-open + randint : Similar to `random_integers`, only for the half-open interval [`low`, `high`), and 0 is the lowest value if `high` is omitted. @@ -1179,7 +1179,7 @@ cdef class RandomGenerator: Display results as a histogram: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(dsums, 11, normed=True) + >>> count, bins, ignored = plt.hist(dsums, 11, density=True) >>> plt.show() """ @@ -1329,7 +1329,7 @@ cdef class RandomGenerator: the probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 30, normed=True) + >>> 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') @@ -1573,7 +1573,7 @@ cdef class RandomGenerator: >>> import matplotlib.pyplot as plt >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> count, bins, ignored = plt.hist(s, 50, density=True) >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ ... (sps.gamma(shape) * scale**shape)) >>> plt.plot(bins, y, linewidth=2, color='r') @@ -1660,7 +1660,7 @@ cdef class RandomGenerator: >>> import matplotlib.pyplot as plt >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> count, bins, ignored = plt.hist(s, 50, density=True) >>> y = bins**(shape-1)*(np.exp(-bins/scale) / ... (sps.gamma(shape)*scale**shape)) >>> plt.plot(bins, y, linewidth=2, color='r') @@ -1819,9 +1819,9 @@ cdef class RandomGenerator: >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) - >>> NF = np.histogram(nc_vals, bins=50, normed=True) + >>> NF = np.histogram(nc_vals, bins=50, density=True) >>> c_vals = randomgen.f(dfnum, dfden, 1000000) - >>> F = np.histogram(c_vals, bins=50, normed=True) + >>> F = np.histogram(c_vals, bins=50, density=True) >>> plt.plot(F[1][1:], F[0]) >>> plt.plot(NF[1][1:], NF[0]) >>> plt.show() @@ -1957,7 +1957,7 @@ cdef class RandomGenerator: >>> import matplotlib.pyplot as plt >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), - ... bins=200, normed=True) + ... bins=200, density=True) >>> plt.show() Draw values from a noncentral chisquare with very small noncentrality, @@ -1965,9 +1965,9 @@ cdef class RandomGenerator: >>> plt.figure() >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), - ... bins=np.arange(0., 25, .1), normed=True) + ... bins=np.arange(0., 25, .1), density=True) >>> values2 = plt.hist(randomgen.chisquare(3, 100000), - ... bins=np.arange(0., 25, .1), normed=True) + ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1976,7 +1976,7 @@ cdef class RandomGenerator: >>> plt.figure() >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), - ... bins=200, normed=True) + ... bins=200, density=True) >>> plt.show() """ @@ -2125,7 +2125,7 @@ cdef class RandomGenerator: >>> t = (np.mean(intake)-7725)/(intake.std(ddof=1)/np.sqrt(len(intake))) >>> import matplotlib.pyplot as plt - >>> h = plt.hist(s, bins=100, normed=True) + >>> 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? @@ -2214,7 +2214,7 @@ cdef class RandomGenerator: >>> import matplotlib.pyplot as plt >>> from scipy.special import i0 - >>> plt.hist(s, 50, normed=True) + >>> 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') @@ -2313,7 +2313,7 @@ cdef class RandomGenerator: density function: >>> import matplotlib.pyplot as plt - >>> count, bins, _ = plt.hist(s, 100, normed=True) + >>> 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() @@ -2502,17 +2502,17 @@ cdef class RandomGenerator: >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() - >>> plt.hist(rvs, bins=50, normed=True) + >>> plt.hist(rvs, bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('randomgen.power(5)') >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('inverse of 1 + randomgen.pareto(5)') >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('inverse of stats.pareto(5)') @@ -2589,7 +2589,7 @@ cdef class RandomGenerator: the probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 30, normed=True) + >>> 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) @@ -2691,7 +2691,7 @@ cdef class RandomGenerator: the probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 30, normed=True) + >>> 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') @@ -2706,7 +2706,7 @@ cdef class RandomGenerator: ... a = randomgen.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) - >>> count, bins, ignored = plt.hist(maxima, 30, normed=True) + >>> 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) @@ -2873,7 +2873,7 @@ cdef class RandomGenerator: the probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 100, normed=True, align='mid') + >>> 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)) @@ -2895,7 +2895,7 @@ cdef class RandomGenerator: ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive - >>> count, bins, ignored = plt.hist(b, 100, normed=True, align='mid') + >>> count, bins, ignored = plt.hist(b, 100, density=True, align='mid') >>> sigma = np.std(np.log(b)) >>> mu = np.mean(np.log(b)) @@ -2958,7 +2958,7 @@ cdef class RandomGenerator: -------- Draw values from the distribution and plot the histogram - >>> values = hist(randomgen.rayleigh(3, 100000), bins=200, normed=True) + >>> values = hist(randomgen.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 @@ -3038,7 +3038,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, normed=True) + >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ @@ -3106,7 +3106,7 @@ cdef class RandomGenerator: >>> import matplotlib.pyplot as plt >>> h = plt.hist(randomgen.triangular(-3, 0, 8, 100000), bins=200, - ... normed=True) + ... density=True) >>> plt.show() """ @@ -3297,7 +3297,7 @@ cdef class RandomGenerator: Draw samples from a negative binomial distribution. Samples are drawn from a negative binomial distribution with specified - parameters, `n` trials and `p` probability of success where `n` is an + parameters, `n` trials and `p` probability of failure where `n` is an integer > 0 and `p` is in the interval [0, 1]. Parameters @@ -3317,20 +3317,19 @@ cdef class RandomGenerator: ------- out : ndarray or scalar Drawn samples from the parameterized negative binomial distribution, - where each sample is equal to N, the number of trials it took to - achieve n - 1 successes, N - (n - 1) failures, and a success on the, - (N + n)th trial. + where each sample is equal to N, the number of successes that + occurred before n failures, and a failure on the (N + n)th trial. Notes ----- The probability density for the negative binomial distribution is - .. math:: P(N;n,p) = \\binom{N+n-1}{n-1}p^{n}(1-p)^{N}, + .. math:: P(N;n,p) = \\binom{N+n-1}{N}p^{n}(1-p)^{N}, - where :math:`n-1` is the number of successes, :math:`p` is the - probability of success, and :math:`N+n-1` is the number of trials. - The negative binomial distribution gives the probability of n-1 - successes and N failures in N+n-1 trials, and success on the (N+n)th + where :math:`n` is the number of successes, :math:`p` is the + probability of failure, and :math:`N+n` is the number of trials. + The negative binomial distribution gives the probability of n + successes and N failures in N+n trials, and a success on the (N+n)th trial. If one throws a die repeatedly until the third time a "1" appears, @@ -3355,7 +3354,7 @@ cdef class RandomGenerator: for each successive well, that is what is the probability of a single success after drilling 5 wells, after 6 wells, etc.? - >>> s = randomgen.negative_binomial(1, 0.1, 100000) + >>> s = np.random.negative_binomial(1, 0.9, 100000) >>> for i in range(1, 11): ... probability = sum(s>> import matplotlib.pyplot as plt - >>> count, bins, _ = plt.hist(s, 100, normed=True) + >>> 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() @@ -765,9 +765,9 @@ cdef class LegacyGenerator: >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) - >>> NF = np.histogram(nc_vals, bins=50, normed=True) + >>> NF = np.histogram(nc_vals, bins=50, density=True) >>> c_vals = randomgen.f(dfnum, dfden, 1000000) - >>> F = np.histogram(c_vals, bins=50, normed=True) + >>> F = np.histogram(c_vals, bins=50, density=True) >>> plt.plot(F[1][1:], F[0]) >>> plt.plot(NF[1][1:], NF[0]) >>> plt.show() @@ -903,7 +903,7 @@ cdef class LegacyGenerator: >>> import matplotlib.pyplot as plt >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), - ... bins=200, normed=True) + ... bins=200, density=True) >>> plt.show() Draw values from a noncentral chisquare with very small noncentrality, @@ -911,9 +911,9 @@ cdef class LegacyGenerator: >>> plt.figure() >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), - ... bins=np.arange(0., 25, .1), normed=True) + ... bins=np.arange(0., 25, .1), density=True) >>> values2 = plt.hist(randomgen.chisquare(3, 100000), - ... bins=np.arange(0., 25, .1), normed=True) + ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -922,7 +922,7 @@ cdef class LegacyGenerator: >>> plt.figure() >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), - ... bins=200, normed=True) + ... bins=200, density=True) >>> plt.show() """ @@ -1058,7 +1058,7 @@ cdef class LegacyGenerator: >>> import matplotlib.pyplot as plt >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> count, bins, ignored = plt.hist(s, 50, density=True) >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ ... (sps.gamma(shape) * scale**shape)) >>> plt.plot(bins, y, linewidth=2, color='r') @@ -1136,7 +1136,7 @@ cdef class LegacyGenerator: >>> import matplotlib.pyplot as plt >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, normed=True) + >>> count, bins, ignored = plt.hist(s, 50, density=True) >>> y = bins**(shape-1)*(np.exp(-bins/scale) / ... (sps.gamma(shape)*scale**shape)) >>> plt.plot(bins, y, linewidth=2, color='r') @@ -1362,7 +1362,7 @@ cdef class LegacyGenerator: the probability density function: >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(s, 30, normed=True) + >>> 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') @@ -1390,7 +1390,7 @@ cdef class LegacyGenerator: argument is provided. This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `numpy.random.standard_normal` instead. + tuple as the first argument, use `standard_normal` instead. Parameters ---------- @@ -1407,7 +1407,7 @@ cdef class LegacyGenerator: See Also -------- - random.standard_normal : Similar, but takes a tuple as its argument. + standard_normal : Similar, but takes a tuple as its argument. Notes ----- @@ -1770,24 +1770,26 @@ cdef class LegacyGenerator: # # Also check that cov is positive-semidefinite. If so, the u.T and v # matrices should be equal up to roundoff error if cov is - # symmetrical and the singular value of the corresponding row is + # 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. + # order to preserve current outputs. (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'") + 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) + warnings.warn( + "covariance is not positive-semidefinite.", + RuntimeWarning) else: - raise ValueError("covariance is not positive-semidefinite.") + raise ValueError( + "covariance is not positive-semidefinite.") x = np.dot(x, np.sqrt(s)[:, None] * v) x += mean @@ -1959,17 +1961,17 @@ cdef class LegacyGenerator: >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() - >>> plt.hist(rvs, bins=50, normed=True) + >>> plt.hist(rvs, bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('randomgen.power(5)') >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('inverse of 1 + randomgen.pareto(5)') >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, normed=True) + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') >>> plt.title('inverse of stats.pareto(5)') diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index cce6228a33d7..46350cdd0127 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -1,6 +1,5 @@ import numpy as np import numpy.random -import pytest from numpy.testing import assert_allclose, assert_array_equal, assert_equal import randomgen @@ -9,10 +8,16 @@ def compare_0_input(f1, f2): - inputs = [(tuple([]), {}), (tuple([]), {'size': 10}), + inputs = [(tuple([]), {}), + (tuple([]), {'size': 10}), (tuple([]), {'size': (20, 31)}), (tuple([]), {'size': (20, 31, 5)})] + for i in inputs: + v1 = f1(*i[0], **i[1]) + v2 = f2(*i[0], **i[1]) + assert_allclose(v1, v2) + def compare_1_input(f1, f2, is_small=False): a = 0.3 if is_small else 10 @@ -156,25 +161,25 @@ def test_random_sample(self): assert_array_equal(v1, v2) def test_standard_normal(self): - self._set_common_state() - self._is_state_common() + self._set_common_state_legacy() + self._is_state_common_legacy() compare_0_input(self.nprs.standard_normal, - self.rg.standard_normal) - self._is_state_common() + self.lg.standard_normal) + self._is_state_common_legacy() def test_standard_cauchy(self): - self._set_common_state() - self._is_state_common() + self._set_common_state_legacy() + self._is_state_common_legacy() compare_0_input(self.nprs.standard_cauchy, - self.rg.standard_cauchy) - self._is_state_common() + self.lg.standard_cauchy) + self._is_state_common_legacy() def test_standard_exponential(self): - self._set_common_state() - self._is_state_common() + self._set_common_state_legacy() + self._is_state_common_legacy() compare_0_input(self.nprs.standard_exponential, - self.rg.standard_exponential) - self._is_state_common() + self.lg.standard_exponential) + self._is_state_common_legacy() def test_tomaxint(self): self._set_common_state() diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 468a6232e290..7fb2008cd8a4 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -5,10 +5,9 @@ import numpy as np from numpy.testing import ( - run_module_suite, assert_, assert_raises, assert_equal, + assert_, assert_raises, assert_equal, assert_warns, assert_no_warnings, assert_array_equal, assert_array_almost_equal) -import pytest from randomgen._testing import suppress_warnings from randomgen import RandomGenerator, MT19937 @@ -316,7 +315,7 @@ def test_repeatability(self): res = hashlib.md5(val.view(np.int8)).hexdigest() assert_(tgt[np.dtype(dt).name] == res) - # bools do not depend on endianess + # bools do not depend on endianness mt19937.seed(1234) val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8) res = hashlib.md5(val).hexdigest() @@ -1760,7 +1759,3 @@ def test_three_arg_funcs(self): out = func(self.argOne, self.argTwo[0], self.argThree) assert_equal(out.shape, self.tgtShape) - - -if __name__ == "__main__": - run_module_suite() diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py index 4a972462d2a4..1f082925e589 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py @@ -1,8 +1,7 @@ from __future__ import division, absolute_import, print_function import sys -from numpy.testing import (run_module_suite, assert_, - assert_array_equal, assert_raises) +from numpy.testing import (assert_, assert_array_equal) from numpy.compat import long import numpy as np import pytest @@ -137,7 +136,3 @@ def test_shuffle_of_array_of_objects(self): # Force Garbage Collection - should not segfault. import gc gc.collect() - - -if __name__ == "__main__": - run_module_suite() diff --git a/_randomgen/randomgen/tests/test_smoke.py b/_randomgen/randomgen/tests/test_smoke.py index cc720f1f0d2e..34f95bc10cb0 100644 --- a/_randomgen/randomgen/tests/test_smoke.py +++ b/_randomgen/randomgen/tests/test_smoke.py @@ -424,10 +424,8 @@ def test_randn(self): assert_equal(vals, self.rg.standard_normal((10, 10, 10))) state = self.rg.state - vals_inv = self.rg.randn(10, 10, 10) + self.rg.randn(10, 10, 10) self.rg.state = state - vals_zig = self.rg.randn(10, 10, 10) - vals = self.rg.randn(10, 10, 10, dtype=np.float32) assert_(vals.shape == (10, 10, 10)) From db87d7d16ff7b45898eee22d19fe457dece1e9a2 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Wed, 2 May 2018 09:14:46 +0100 Subject: [PATCH 084/138] BLD: Add lm flag for non-windows platforms Should be gcc only --- _randomgen/setup.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 828e0aa3f0c3..5a1f5f9eff10 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -54,6 +54,7 @@ EXTRA_INCLUDE_DIRS = [] EXTRA_LINK_ARGS = [] +EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] # Undef for manylinux EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ '-std=c99', '-U__GNUC_GNU_INLINE__'] @@ -64,6 +65,7 @@ EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] if sys.version_info < (3, 0): EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] + PCG64_DEFS = [] if sys.maxsize < 2 ** 32 or os.name == 'nt': # Force emulated mode here @@ -100,6 +102,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'entropy')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -111,6 +114,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'dsfmt')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, define_macros=DSFMT_DEFS, @@ -122,6 +126,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'mt19937')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -131,6 +136,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'philox')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -140,6 +146,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'pcg64')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, define_macros=PCG64_DEFS, extra_link_args=EXTRA_LINK_ARGS @@ -150,6 +157,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'pcg32')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -159,6 +167,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'threefry')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -168,6 +177,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'threefry32')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -179,6 +189,7 @@ join( MOD_DIR, 'src', 'xoroshiro128')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -189,6 +200,7 @@ include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), join(MOD_DIR, 'src', 'xorshift1024')], + libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), @@ -196,12 +208,14 @@ ["randomgen/generator.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], + libraries=EXTRA_LIBRARIES, include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), Extension("randomgen.common", ["randomgen/common.pyx"], + libraries=EXTRA_LIBRARIES, include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS @@ -210,6 +224,7 @@ ["randomgen/bounded_integers.pyx", join(MOD_DIR, 'src', 'distributions', 'distributions.c')], + libraries=EXTRA_LIBRARIES, include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS @@ -219,6 +234,7 @@ join(MOD_DIR, 'src', 'legacy', 'distributions-boxmuller.c'), join(MOD_DIR, 'src', 'distributions', 'distributions.c')], + libraries=EXTRA_LIBRARIES, include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()] + [join(MOD_DIR, 'legacy')], extra_compile_args=EXTRA_COMPILE_ARGS, From d780f063790a27bdac1750da70bda3a10c101851 Mon Sep 17 00:00:00 2001 From: Pierre de Buyl Date: Tue, 22 May 2018 13:24:06 +0200 Subject: [PATCH 085/138] DOC: Fix doc and example error Ensure cython example works Add cimport for cython example --- _randomgen/README.md | 4 ++-- _randomgen/doc/source/extending.rst | 2 +- _randomgen/randomgen/examples/cython/setup.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index c90d9e2256ce..f42150fdcd92 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -82,8 +82,8 @@ The RNGs include: generating doubles * [xoroshiro128+](http://xoroshiro.di.unimi.it/) and [xorshift1024*φ](http://xorshift.di.unimi.it/) -* [PCG64](http:w//www.pcg-random.org/) -* ThreeFry and Philox from [Random123](https://www.deshawrsearch.com/resources_random123.html) +* [PCG64](http://www.pcg-random.org/) +* ThreeFry and Philox from [Random123](https://www.deshawresearch.com/resources_random123.html) ## Differences from `numpy.random.RandomState` ### New Features diff --git a/_randomgen/doc/source/extending.rst b/_randomgen/doc/source/extending.rst index 764e3428b066..c9d987b59ece 100644 --- a/_randomgen/doc/source/extending.rst +++ b/_randomgen/doc/source/extending.rst @@ -76,7 +76,7 @@ removing bounds checks and wrap around, providing array alignment information cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from randomgen.common cimport * - from randomgen.distributions import random_gauss_zig + from randomgen.distributions cimport random_gauss_zig from randomgen.xoroshiro128 import Xoroshiro128 diff --git a/_randomgen/randomgen/examples/cython/setup.py b/_randomgen/randomgen/examples/cython/setup.py index bf6fb81486c6..d7a04f75a6c6 100644 --- a/_randomgen/randomgen/examples/cython/setup.py +++ b/_randomgen/randomgen/examples/cython/setup.py @@ -10,7 +10,7 @@ include_dirs=[np.get_include()]) distributions = Extension("extending_distributions", sources=['extending_distributions.pyx', - join('..', '..', 'randomgen', 'src', + join('..', '..', '..', 'randomgen', 'src', 'distributions', 'distributions.c')], include_dirs=[np.get_include()]) From fdd029f4c07184ccfbaa67b87f75e41251b852b8 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 14 Jun 2018 23:51:22 +0100 Subject: [PATCH 086/138] REF: Rename min and max macros Use MIN and MAX to avoid issues with c++ compilation --- .../randomgen/src/distributions/distributions.c | 14 +++++++------- .../randomgen/src/distributions/distributions.h | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index 0e6e9cd578f5..a0966b6b0635 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -695,7 +695,7 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, binomial->nsave = n; binomial->psave = p; binomial->has_binomial = 1; - binomial->r = r = min(p, 1.0 - p); + binomial->r = r = MIN(p, 1.0 - p); binomial->q = q = 1.0 - r; binomial->fm = fm = n * r + r; binomial->m = m = (int64_t)floor(binomial->fm); @@ -836,7 +836,7 @@ int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, binomial->q = q = 1.0 - p; binomial->r = qn = exp(n * log(q)); binomial->c = np = n * p; - binomial->m = bound = (int64_t)min(n, np + 10.0 * sqrt(np * q + 1)); + binomial->m = bound = (int64_t)MIN(n, np + 10.0 * sqrt(np * q + 1)); } else { q = binomial->q; qn = binomial->r; @@ -1071,7 +1071,7 @@ int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, double d2, u, y; d1 = bad + good - sample; - d2 = (double)min(bad, good); + d2 = (double)MIN(bad, good); y = d2; k = sample; @@ -1099,10 +1099,10 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, int64_t Z; double T, W, X, Y; - mingoodbad = min(good, bad); + mingoodbad = MIN(good, bad); popsize = good + bad; - maxgoodbad = max(good, bad); - m = min(sample, popsize - sample); + maxgoodbad = MAX(good, bad); + m = MIN(sample, popsize - sample); d4 = ((double)mingoodbad) / popsize; d5 = 1.0 - d4; d6 = m * d4 + 0.5; @@ -1111,7 +1111,7 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, d9 = (int64_t)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)); + d11 = MIN(MIN(m, mingoodbad) + 1.0, floor(d6 + 16 * d7)); /* 16 for 16-decimal-digit precision in D1 and D2 */ while (1) { diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index 2dd453d3a734..707f3b455e35 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -40,9 +40,9 @@ static NPY_INLINE int64_t llabs(int64_t x) { #define DECLDIR extern #endif -#ifndef min -#define min(x, y) ((x < y) ? x : y) -#define max(x, y) ((x > y) ? x : y) +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? x : y) +#define MAX(x, y) (((x) > (y)) ? x : y) #endif #ifndef M_PI From 3dba22d42a40df48867aa2c3e800d20216b4c873 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 19 Jun 2018 18:16:07 +0100 Subject: [PATCH 087/138] MAINT: Sync with NumPy changes Sync documentation changes from NumPy for 1.15 release --- _randomgen/README.md | 15 ++-- _randomgen/README.rst | 18 ++--- _randomgen/doc/source/change-log.rst | 2 + _randomgen/randomgen/generator.pyx | 106 ++++++++++++++------------- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index f42150fdcd92..c2472dc76367 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -120,11 +120,10 @@ the RNG._ ## Status * Builds and passes all tests on: - * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 (probably works on 2.6 and 3.3) + * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 * PC-BSD (FreeBSD) 64-bit, Python 2.7 * OSX 64-bit, Python 3.6 - * Windows 32/64 bit (only tested on Python 2.7, 3.5 and 3.6, but - should work on 3.3/3.4) + * Windows 32/64 bit, Python 2.7, 3.5 and 3.6 ## Version The version matched the latest version of NumPy where @@ -148,7 +147,7 @@ need to be smoothed. Building requires: * Python (2.7, 3.4, 3.5, 3.6) - * NumPy (1.10, 1.11, 1.12, 1.13, 1.14) + * NumPy (1.11, 1.12, 1.13, 1.14, 1.15) * Cython (0.26+) * tempita (0.5+), if not provided by Cython @@ -183,10 +182,10 @@ python setup.py install --no-sse2 ### Windows Either use a binary installer, or if building from scratch, use -Python 3.6 with Visual Studio 2015 Community Edition. It can also be -build using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7, -although some modifications may be needed to `distutils` to find the -compiler. +Python 3.6 with Visual Studio 2015/2017 Community Edition. It can also +be build using Microsoft Visual C++ Compiler for Python 2.7 and +Python 2.7. + ## Using diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 79252abc4347..b3fbc5fd0423 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -85,9 +85,9 @@ addition to the MT19937 that is included in NumPy. The RNGs include: at generating doubles - `xoroshiro128+ `__ and `xorshift1024\*φ `__ -- `PCG64 `__ +- `PCG64 `__ - ThreeFry and Philox from - `Random123 `__ + `Random123 `__ ## Differences from ``numpy.random.RandomState`` New Features @@ -129,12 +129,10 @@ Status ------ - Builds and passes all tests on: -- Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 (probably works on 2.6 and - 3.3) +- Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 - PC-BSD (FreeBSD) 64-bit, Python 2.7 - OSX 64-bit, Python 3.6 -- Windows 32/64 bit (only tested on Python 2.7, 3.5 and 3.6, but should - work on 3.3/3.4) +- Windows 32/64 bit, Python 2.7, 3.5 and 3.6 Version ------- @@ -165,7 +163,7 @@ Requirements Building requires: - Python (2.7, 3.4, 3.5, 3.6) -- NumPy (1.10, 1.11, 1.12, 1.13, 1.14) +- NumPy (1.11, 1.12, 1.13, 1.14, 1.15) - Cython (0.26+) - tempita (0.5+), if not provided by Cython @@ -206,10 +204,8 @@ Windows ~~~~~~~ Either use a binary installer, or if building from scratch, use Python -3.6 with Visual Studio 2015 Community Edition. It can also be build -using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7, -although some modifications may be needed to ``distutils`` to find the -compiler. +3.6 with Visual Studio 2015/2017 Community Edition. It can also be build +using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7. Using ----- diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 271ee5647e13..6084925289ac 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -4,6 +4,8 @@ Change Log Changes since v1.14 =================== +- Synced upstream changes in permutation +- Synced upstream doc fixes - Added absolute_import to avoid import noise on Python 2.7 - Add legacy generator which allows NumPy replication - Improve type handling of integers diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 40a876aa48d3..1f51e6f48f7e 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -446,9 +446,9 @@ cdef class RandomGenerator: .. [1] Peyton Z. Peebles Jr., "Probability, Random Variables and Random Signal Principles", 4th ed, 2001, p. 57. .. [2] Wikipedia, "Poisson process", - http://en.wikipedia.org/wiki/Poisson_process + https://en.wikipedia.org/wiki/Poisson_process .. [3] Wikipedia, "Exponential distribution", - http://en.wikipedia.org/wiki/Exponential_distribution + https://en.wikipedia.org/wiki/Exponential_distribution """ return cont(&random_exponential, self._brng, size, self.lock, 1, @@ -612,7 +612,7 @@ cdef class RandomGenerator: See Also -------- - random.random_integers : similar to `randint`, only for the closed + 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. @@ -1305,7 +1305,7 @@ cdef class RandomGenerator: References ---------- .. [1] Wikipedia, "Normal distribution", - http://en.wikipedia.org/wiki/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. @@ -1559,7 +1559,7 @@ cdef class RandomGenerator: Wolfram Web Resource. http://mathworld.wolfram.com/GammaDistribution.html .. [2] Wikipedia, "Gamma distribution", - http://en.wikipedia.org/wiki/Gamma_distribution + https://en.wikipedia.org/wiki/Gamma_distribution Examples -------- @@ -1646,7 +1646,7 @@ cdef class RandomGenerator: Wolfram Web Resource. http://mathworld.wolfram.com/GammaDistribution.html .. [2] Wikipedia, "Gamma distribution", - http://en.wikipedia.org/wiki/Gamma_distribution + https://en.wikipedia.org/wiki/Gamma_distribution Examples -------- @@ -1725,7 +1725,7 @@ cdef class RandomGenerator: .. [1] Glantz, Stanton A. "Primer of Biostatistics.", McGraw-Hill, Fifth Edition, 2002. .. [2] Wikipedia, "F-distribution", - http://en.wikipedia.org/wiki/F-distribution + https://en.wikipedia.org/wiki/F-distribution Examples -------- @@ -1805,7 +1805,7 @@ cdef class RandomGenerator: From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/NoncentralF-Distribution.html .. [2] Wikipedia, "Noncentral F-distribution", - http://en.wikipedia.org/wiki/Noncentral_F-distribution + https://en.wikipedia.org/wiki/Noncentral_F-distribution Examples -------- @@ -1887,7 +1887,7 @@ cdef class RandomGenerator: References ---------- .. [1] NIST "Engineering Statistics Handbook" - http://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm + https://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm Examples -------- @@ -1949,7 +1949,7 @@ cdef class RandomGenerator: the analysis of weapon systems effectiveness", Metrika, Volume 15, Number 1 / December, 1970. .. [2] Wikipedia, "Noncentral chi-square distribution" - http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution + https://en.wikipedia.org/wiki/Noncentral_chi-square_distribution Examples -------- @@ -2034,7 +2034,7 @@ cdef class RandomGenerator: Wolfram Web Resource. http://mathworld.wolfram.com/CauchyDistribution.html .. [3] Wikipedia, "Cauchy distribution" - http://en.wikipedia.org/wiki/Cauchy_distribution + https://en.wikipedia.org/wiki/Cauchy_distribution Examples -------- @@ -2097,7 +2097,7 @@ cdef class RandomGenerator: .. [1] Dalgaard, Peter, "Introductory Statistics With R", Springer, 2002. .. [2] Wikipedia, "Student's t-distribution" - http://en.wikipedia.org/wiki/Student's_t-distribution + https://en.wikipedia.org/wiki/Student's_t-distribution Examples -------- @@ -2300,7 +2300,7 @@ cdef class RandomGenerator: .. [3] Reiss, R.D., Thomas, M.(2001), Statistical Analysis of Extreme Values, Birkhauser Verlag, Basel, pp 23-30. .. [4] Wikipedia, "Pareto distribution", - http://en.wikipedia.org/wiki/Pareto_distribution + https://en.wikipedia.org/wiki/Pareto_distribution Examples -------- @@ -2393,7 +2393,7 @@ cdef class RandomGenerator: Wide Applicability", Journal Of Applied Mechanics ASME Paper 1951. .. [3] Wikipedia, "Weibull distribution", - http://en.wikipedia.org/wiki/Weibull_distribution + https://en.wikipedia.org/wiki/Weibull_distribution Examples -------- @@ -2576,7 +2576,7 @@ cdef class RandomGenerator: From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/LaplaceDistribution.html .. [4] Wikipedia, "Laplace distribution", - http://en.wikipedia.org/wiki/Laplace_distribution + https://en.wikipedia.org/wiki/Laplace_distribution Examples -------- @@ -2778,7 +2778,7 @@ cdef class RandomGenerator: MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/LogisticDistribution.html .. [3] Wikipedia, "Logistic-distribution", - http://en.wikipedia.org/wiki/Logistic_distribution + https://en.wikipedia.org/wiki/Logistic_distribution Examples -------- @@ -2858,7 +2858,7 @@ cdef class RandomGenerator: .. [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. - http://stat.ethz.ch/~stahel/lognormal/bioscience.pdf + 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. @@ -2950,9 +2950,9 @@ cdef class RandomGenerator: References ---------- .. [1] Brighton Webs Ltd., "Rayleigh Distribution," - http://www.brighton-webs.co.uk/distributions/rayleigh.asp + https://web.archive.org/web/20090514091424/http://brighton-webs.co.uk:80/distributions/rayleigh.asp .. [2] Wikipedia, "Rayleigh distribution" - http://en.wikipedia.org/wiki/Rayleigh_distribution + https://en.wikipedia.org/wiki/Rayleigh_distribution Examples -------- @@ -3026,12 +3026,12 @@ cdef class RandomGenerator: References ---------- .. [1] Brighton Webs Ltd., Wald Distribution, - http://www.brighton-webs.co.uk/distributions/wald.asp + 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, "Wald distribution" - http://en.wikipedia.org/wiki/Wald_distribution + https://en.wikipedia.org/wiki/Wald_distribution Examples -------- @@ -3098,7 +3098,7 @@ cdef class RandomGenerator: References ---------- .. [1] Wikipedia, "Triangular distribution" - http://en.wikipedia.org/wiki/Triangular_distribution + https://en.wikipedia.org/wiki/Triangular_distribution Examples -------- @@ -3211,7 +3211,7 @@ cdef class RandomGenerator: Wolfram Web Resource. http://mathworld.wolfram.com/BinomialDistribution.html .. [5] Wikipedia, "Binomial distribution", - http://en.wikipedia.org/wiki/Binomial_distribution + https://en.wikipedia.org/wiki/Binomial_distribution Examples -------- @@ -3297,7 +3297,7 @@ cdef class RandomGenerator: Draw samples from a negative binomial distribution. Samples are drawn from a negative binomial distribution with specified - parameters, `n` trials and `p` probability of failure where `n` is an + parameters, `n` successes and `p` probability of success where `n` is an integer > 0 and `p` is in the interval [0, 1]. Parameters @@ -3317,8 +3317,8 @@ cdef class RandomGenerator: ------- out : ndarray or scalar Drawn samples from the parameterized negative binomial distribution, - where each sample is equal to N, the number of successes that - occurred before n failures, and a failure on the (N + n)th trial. + where each sample is equal to N, the number of failures that + occurred before a total of n successes was reached. Notes ----- @@ -3327,10 +3327,9 @@ cdef class RandomGenerator: .. math:: P(N;n,p) = \\binom{N+n-1}{N}p^{n}(1-p)^{N}, where :math:`n` is the number of successes, :math:`p` is the - probability of failure, and :math:`N+n` is the number of trials. - The negative binomial distribution gives the probability of n - successes and N failures in N+n trials, and a success on the (N+n)th - trial. + 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. 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 @@ -3342,7 +3341,7 @@ cdef class RandomGenerator: MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/NegativeBinomialDistribution.html .. [2] Wikipedia, "Negative binomial distribution", - http://en.wikipedia.org/wiki/Negative_binomial_distribution + https://en.wikipedia.org/wiki/Negative_binomial_distribution Examples -------- @@ -3411,7 +3410,7 @@ cdef class RandomGenerator: From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/PoissonDistribution.html .. [2] Wikipedia, "Poisson distribution", - http://en.wikipedia.org/wiki/Poisson_distribution + https://en.wikipedia.org/wiki/Poisson_distribution Examples -------- @@ -3633,7 +3632,7 @@ cdef class RandomGenerator: MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/HypergeometricDistribution.html .. [3] Wikipedia, "Hypergeometric distribution", - http://en.wikipedia.org/wiki/Hypergeometric_distribution + https://en.wikipedia.org/wiki/Hypergeometric_distribution Examples -------- @@ -3743,7 +3742,7 @@ cdef class RandomGenerator: .. [3] D. J. Hand, F. Daly, D. Lunn, E. Ostrowski, A Handbook of Small Data Sets, CRC Press, 1994. .. [4] Wikipedia, "Logarithmic distribution", - http://en.wikipedia.org/wiki/Logarithmic_distribution + https://en.wikipedia.org/wiki/Logarithmic_distribution Examples -------- @@ -4089,9 +4088,9 @@ cdef class RandomGenerator: ---------- .. [1] David McKay, "Information Theory, Inference and Learning Algorithms," chapter 23, - http://www.inference.phy.cam.ac.uk/mackay/ + http://www.inference.org.uk/mackay/itila/ .. [2] Wikipedia, "Dirichlet distribution", - http://en.wikipedia.org/wiki/Dirichlet_distribution + https://en.wikipedia.org/wiki/Dirichlet_distribution Examples -------- @@ -4264,45 +4263,50 @@ cdef class RandomGenerator: 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 -------- - >>> randomgen.permutation(10) + >>> np.random.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) - - >>> randomgen.permutation([1, 4, 9, 12, 15]) + >>> np.random.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) - >>> arr = np.arange(9).reshape((3, 3)) - >>> randomgen.permutation(arr) + >>> np.random.permutation(arr) array([[6, 7, 8], [0, 1, 2], [3, 4, 5]]) - """ if isinstance(x, (int, long, np.integer)): arr = np.arange(x) - else: - arr = np.array(x) - self.shuffle(arr) - return arr + self.shuffle(arr) + return arr + + arr = np.asarray(x) + + # shuffle has fast-path for 1-d + if arr.ndim == 1: + # must return a copy + if arr is 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] _random_generator = RandomGenerator() From f2ace10386b95980f181549bf37b87aff6cb9d37 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 3 Jul 2018 17:26:27 +0100 Subject: [PATCH 088/138] ENH: Allow empty choice Allow empty choices to sync with upstream changes --- _randomgen/README.md | 193 ++++++++++-------- _randomgen/README.rst | 184 +++++++++-------- _randomgen/randomgen/generator.pyx | 16 +- .../randomgen/tests/test_numpy_mt19937.py | 8 + 4 files changed, 223 insertions(+), 178 deletions(-) diff --git a/_randomgen/README.md b/_randomgen/README.md index c2472dc76367..eec9bdc753e5 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -23,14 +23,13 @@ which can fully reproduce the sequence produced by NumPy. * Replacement for NumPy's RandomState -```python -# import numpy.random as rnd -from randomgen import RandomGenerator, MT19937 -rnd = RandomGenerator(MT19937()) -x = rnd.standard_normal(100) -y = rnd.random_sample(100) -z = rnd.randn(10,10) -``` + ```python + from randomgen import RandomGenerator, MT19937 + rnd = RandomGenerator(MT19937()) + x = rnd.standard_normal(100) + y = rnd.random_sample(100) + z = rnd.randn(10,10) + ``` * Default random generator is a fast generator called Xoroshiro128plus * Support for random number generators that support independent streams @@ -38,22 +37,22 @@ z = rnd.randn(10,10) * Faster random number generation, especially for normal, standard exponential and standard gamma using the Ziggurat method -```python -from randomgen import RandomGenerator -# Use Xoroshiro128 -rnd = RandomGenerator() -w = rnd.standard_normal(10000, method='zig') -x = rnd.standard_exponential(10000, method='zig') -y = rnd.standard_gamma(5.5, 10000, method='zig') -``` + ```python + from randomgen import RandomGenerator + # Default basic PRNG is Xoroshiro128 + rnd = RandomGenerator() + w = rnd.standard_normal(10000, method='zig') + x = rnd.standard_exponential(10000, method='zig') + y = rnd.standard_gamma(5.5, 10000, method='zig') + ``` * Support for 32-bit floating randoms for core generators. Currently supported: - * Uniforms (`random_sample`) - * Exponentials (`standard_exponential`, both Inverse CDF and Ziggurat) - * Normals (`standard_normal`) - * Standard Gammas (via `standard_gamma`) + * Uniforms (`random_sample`) + * Exponentials (`standard_exponential`, both Inverse CDF and Ziggurat) + * Normals (`standard_normal`) + * Standard Gammas (via `standard_gamma`) **WARNING**: The 32-bit generators are **experimental** and subject to change. @@ -64,10 +63,10 @@ y = rnd.standard_gamma(5.5, 10000, method='zig') * Support for filling existing arrays using `out` keyword argument. Currently supported in (both 32- and 64-bit outputs) - * Uniforms (`random_sample`) - * Exponentials (`standard_exponential`) - * Normals (`standard_normal`) - * Standard Gammas (via `standard_gamma`) + * Uniforms (`random_sample`) + * Exponentials (`standard_exponential`) + * Normals (`standard_normal`) + * Standard Gammas (via `standard_gamma`) ## Included Pseudo Random Number Generators @@ -84,9 +83,11 @@ The RNGs include: [xorshift1024*φ](http://xorshift.di.unimi.it/) * [PCG64](http://www.pcg-random.org/) * ThreeFry and Philox from [Random123](https://www.deshawresearch.com/resources_random123.html) + ## Differences from `numpy.random.RandomState` ### New Features + * `standard_normal`, `normal`, `randn` and `multivariate_normal` all use the much faster (100%+) Ziggurat method. * `standard_gamma` and `gamma` both use the much faster Ziggurat method. @@ -101,21 +102,20 @@ The RNGs include: `out` keyword argument * Standardizes integer-values random values as int64 for all platforms. - ### New Functions -* `random_entropy` - Read from the system entropy provider, which is -commonly used in cryptographic applications -* `random_raw` - Direct access to the values produced by the underlying -PRNG. The range of the values returned depends on the specifics of the -PRNG implementation. +* `random_entropy` - Read from the system entropy provider, which is + commonly used in cryptographic applications +* `random_raw` - Direct access to the values produced by the underlying + PRNG. The range of the values returned depends on the specifics of the + PRNG implementation. * `random_uintegers` - unsigned integers, either 32- (`[0, 2**32-1]`) -or 64-bit (`[0, 2**64-1]`) -* `jump` - Jumps RNGs that support it. `jump` moves the state a great -distance. _Only available if supported by the RNG._ -* `advance` - Advanced the RNG 'as-if' a number of draws were made, -without actually drawing the numbers. _Only available if supported by -the RNG._ + or 64-bit (`[0, 2**64-1]`) +* `jump` - Jumps RNGs that support it. `jump` moves the state a great + distance. _Only available if supported by the RNG._ +* `advance` - Advanced the RNG 'as-if' a number of draws were made, + without actually drawing the numbers. _Only available if supported by + the RNG._ ## Status @@ -126,53 +126,70 @@ the RNG._ * Windows 32/64 bit, Python 2.7, 3.5 and 3.6 ## Version -The version matched the latest version of NumPy where + +The version matched the latest version of NumPy where `RandomGenerator(MT19937())` passes all NumPy test. ## Documentation Documentation for the latest release is available on -[my GitHub pages](http://bashtage.github.io/randomgen/). Documentation for -the latest commit (unreleased) is available under +[my GitHub pages](http://bashtage.github.io/randomgen/). Documentation for +the latest commit (unreleased) is available under [devel](http://bashtage.github.io/randomgen/devel/). ## Plans + This module is essentially complete. There are a few rough edges that need to be smoothed. -* Creation of additional streams from where supported +* Creation of additional streams from where supported (i.e. a `next_stream()` method) ## Requirements Building requires: - * Python (2.7, 3.4, 3.5, 3.6) - * NumPy (1.11, 1.12, 1.13, 1.14, 1.15) - * Cython (0.26+) - * tempita (0.5+), if not provided by Cython +* Python (2.7, 3.4, 3.5, 3.6) +* NumPy (1.11, 1.12, 1.13, 1.14, 1.15) +* Cython (0.26+) +* tempita (0.5+), if not provided by Cython Testing requires pytest (3.0+). -**Note:** it might work with other versions but only tested with these -versions. +**Note:** it might work with other versions but only tested with these +versions. ## Development and Testing -All development has been on 64-bit Linux, and it is regularly tested on +All development has been on 64-bit Linux, and it is regularly tested on Travis-CI (Linux/OSX) and Appveyor (Windows). The library is occasionally tested on Linux 32-bit and Free BSD 11.1. -Basic tests are in place for all RNGs. The MT19937 is tested against +Basic tests are in place for all RNGs. The MT19937 is tested against NumPy's implementation for identical results. It also passes NumPy's test suite where still relevant. ## Installing +Either install from PyPi using + +```bash +pip install randomgen +``` + +or, if you want the latest version, + +```bash +pip install git+https://github.com/bashtage/randomgen.git +``` + +or from a cloned repo, + ```bash python setup.py install ``` ### SSE2 + `dSFTM` makes use of SSE2 by default. If you have a very old computer or are building on non-x86, you can install using: @@ -181,12 +198,12 @@ python setup.py install --no-sse2 ``` ### Windows + Either use a binary installer, or if building from scratch, use Python 3.6 with Visual Studio 2015/2017 Community Edition. It can also be build using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7. - ## Using The separate generators are importable from `randomgen` @@ -205,46 +222,46 @@ rg.random_sample(100) ``` ## License + Standard NCSA, plus sub licenses for components. ## Performance -Performance is promising, and even the mt19937 seems to be faster than -NumPy's mt19937. -``` -Speed-up relative to NumPy (Uniform Doubles) -************************************************************ -DSFMT 137.1% -MT19937 21.0% -PCG32 101.2% -PCG64 110.7% -Philox -2.7% -ThreeFry -11.4% -ThreeFry32 -62.3% -Xoroshiro128 181.4% -Xorshift1024 141.8% - -Speed-up relative to NumPy (64-bit unsigned integers) -************************************************************ -DSFMT 24.8% -MT19937 15.0% -PCG32 92.6% -PCG64 99.0% -Philox -20.4% -ThreeFry -21.7% -ThreeFry32 -64.4% -Xoroshiro128 164.2% -Xorshift1024 120.8% - -Speed-up relative to NumPy (Standard normals) -************************************************************ -DSFMT 299.4% -MT19937 271.2% -PCG32 364.5% -PCG64 364.2% -Philox 256.9% -ThreeFry 236.0% -ThreeFry32 97.0% -Xoroshiro128 477.4% -Xorshift1024 360.7% -``` +Performance is promising, and even the mt19937 seems to be faster than +NumPy's mt19937. + + Speed-up relative to NumPy (Uniform Doubles) + ************************************************************ + DSFMT 137.1% + MT19937 21.0% + PCG32 101.2% + PCG64 110.7% + Philox -2.7% + ThreeFry -11.4% + ThreeFry32 -62.3% + Xoroshiro128 181.4% + Xorshift1024 141.8% + + Speed-up relative to NumPy (64-bit unsigned integers) + ************************************************************ + DSFMT 24.8% + MT19937 15.0% + PCG32 92.6% + PCG64 99.0% + Philox -20.4% + ThreeFry -21.7% + ThreeFry32 -64.4% + Xoroshiro128 164.2% + Xorshift1024 120.8% + + Speed-up relative to NumPy (Standard normals) + ************************************************************ + DSFMT 299.4% + MT19937 271.2% + PCG32 364.5% + PCG64 364.2% + Philox 256.9% + ThreeFry 236.0% + ThreeFry32 97.0% + Xoroshiro128 477.4% + Xorshift1024 360.7% diff --git a/_randomgen/README.rst b/_randomgen/README.rst index b3fbc5fd0423..335a678b1a19 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -1,7 +1,10 @@ RandomGen ========= -|Travis Build Status| |Appveyor Build Status| |PyPI version| +`Travis Build Status `__ +`Appveyor Build +Status `__ +`PyPI version `__ Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -23,16 +26,15 @@ NumPy. Features -------- -- Replacement for NumPy's RandomState +- Replacement for NumPy’s RandomState -.. code:: python + .. code:: python - # import numpy.random as rnd - from randomgen import RandomGenerator, MT19937 - rnd = RandomGenerator(MT19937()) - x = rnd.standard_normal(100) - y = rnd.random_sample(100) - z = rnd.randn(10,10) + from randomgen import RandomGenerator, MT19937 + rnd = RandomGenerator(MT19937()) + x = rnd.standard_normal(100) + y = rnd.random_sample(100) + z = rnd.randn(10,10) - Default random generator is a fast generator called Xoroshiro128plus - Support for random number generators that support independent streams @@ -40,14 +42,14 @@ Features - Faster random number generation, especially for normal, standard exponential and standard gamma using the Ziggurat method -.. code:: python + .. code:: python - from randomgen import RandomGenerator - # Use Xoroshiro128 - rnd = RandomGenerator() - w = rnd.standard_normal(10000, method='zig') - x = rnd.standard_exponential(10000, method='zig') - y = rnd.standard_gamma(5.5, 10000, method='zig') + from randomgen import RandomGenerator + # Default basic PRNG is Xoroshiro128 + rnd = RandomGenerator() + w = rnd.standard_normal(10000, method='zig') + x = rnd.standard_exponential(10000, method='zig') + y = rnd.standard_gamma(5.5, 10000, method='zig') - Support for 32-bit floating randoms for core generators. Currently supported: @@ -58,11 +60,11 @@ Features - Normals (``standard_normal``) - Standard Gammas (via ``standard_gamma``) -**WARNING**: The 32-bit generators are **experimental** and subject to -change. + **WARNING**: The 32-bit generators are **experimental** and subject + to change. -**Note**: There are *no* plans to extend the alternative precision -generation to all distributions. + **Note**: There are *no* plans to extend the alternative precision + generation to all distributions. - Support for filling existing arrays using ``out`` keyword argument. Currently supported in (both 32- and 64-bit outputs) @@ -84,11 +86,13 @@ addition to the MT19937 that is included in NumPy. The RNGs include: SSE2-aware version of the MT19937 generator that is especially fast at generating doubles - `xoroshiro128+ `__ and - `xorshift1024\*φ `__ + `xorshift1024*φ `__ - `PCG64 `__ - ThreeFry and Philox from `Random123 `__ - ## Differences from ``numpy.random.RandomState`` + +Differences from ``numpy.random.RandomState`` +--------------------------------------------- New Features ~~~~~~~~~~~~ @@ -121,7 +125,7 @@ New Functions (``[0, 2**32-1]``) or 64-bit (``[0, 2**64-1]``) - ``jump`` - Jumps RNGs that support it. ``jump`` moves the state a great distance. *Only available if supported by the RNG.* -- ``advance`` - Advanced the RNG 'as-if' a number of draws were made, +- ``advance`` - Advanced the RNG ‘as-if’ a number of draws were made, without actually drawing the numbers. *Only available if supported by the RNG.* @@ -129,10 +133,11 @@ Status ------ - Builds and passes all tests on: -- Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 -- PC-BSD (FreeBSD) 64-bit, Python 2.7 -- OSX 64-bit, Python 3.6 -- Windows 32/64 bit, Python 2.7, 3.5 and 3.6 + + - Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 + - PC-BSD (FreeBSD) 64-bit, Python 2.7 + - OSX 64-bit, Python 3.6 + - Windows 32/64 bit, Python 2.7, 3.5 and 3.6 Version ------- @@ -143,10 +148,10 @@ The version matched the latest version of NumPy where Documentation ------------- -| Documentation for the latest release is available on `my GitHub - pages `__. Documentation for the - latest commit (unreleased) is available under -| `devel `__. +Documentation for the latest release is available on `my GitHub +pages `__. Documentation for the +latest commit (unreleased) is available under +`devel `__. Plans ----- @@ -154,7 +159,7 @@ Plans This module is essentially complete. There are a few rough edges that need to be smoothed. -- Creation of additional streams from where supported (i.e. a +- Creation of additional streams from where supported (i.e. a ``next_stream()`` method) Requirements @@ -180,15 +185,29 @@ Travis-CI (Linux/OSX) and Appveyor (Windows). The library is occasionally tested on Linux 32-bit and Free BSD 11.1. Basic tests are in place for all RNGs. The MT19937 is tested against -NumPy's implementation for identical results. It also passes NumPy's +NumPy’s implementation for identical results. It also passes NumPy’s test suite where still relevant. Installing ---------- +Either install from PyPi using + +.. code:: bash + + pip install randomgen + +or, if you want the latest version, + +.. code:: bash + + pip install git+https://github.com/bashtage/randomgen.git + +or from a cloned repo, + .. code:: bash - python setup.py install + python setup.py install SSE2 ~~~~ @@ -198,7 +217,7 @@ or are building on non-x86, you can install using: .. code:: bash - python setup.py install --no-sse2 + python setup.py install --no-sse2 Windows ~~~~~~~ @@ -214,16 +233,16 @@ The separate generators are importable from ``randomgen`` .. code:: python - from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 - rg = RandomGenerator(ThreeFry()) - rg.random_sample(100) + from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 + rg = RandomGenerator(ThreeFry()) + rg.random_sample(100) - rg = RandomGenerator(PCG64()) - rg.random_sample(100) + rg = RandomGenerator(PCG64()) + rg.random_sample(100) - # Identical to NumPy - rg = RandomGenerator(MT19937()) - rg.random_sample(100) + # Identical to NumPy + rg = RandomGenerator(MT19937()) + rg.random_sample(100) License ------- @@ -234,49 +253,42 @@ Performance ----------- Performance is promising, and even the mt19937 seems to be faster than -NumPy's mt19937. +NumPy’s mt19937. :: - Speed-up relative to NumPy (Uniform Doubles) - ************************************************************ - DSFMT 137.1% - MT19937 21.0% - PCG32 101.2% - PCG64 110.7% - Philox -2.7% - ThreeFry -11.4% - ThreeFry32 -62.3% - Xoroshiro128 181.4% - Xorshift1024 141.8% - - Speed-up relative to NumPy (64-bit unsigned integers) - ************************************************************ - DSFMT 24.8% - MT19937 15.0% - PCG32 92.6% - PCG64 99.0% - Philox -20.4% - ThreeFry -21.7% - ThreeFry32 -64.4% - Xoroshiro128 164.2% - Xorshift1024 120.8% - - Speed-up relative to NumPy (Standard normals) - ************************************************************ - DSFMT 299.4% - MT19937 271.2% - PCG32 364.5% - PCG64 364.2% - Philox 256.9% - ThreeFry 236.0% - ThreeFry32 97.0% - Xoroshiro128 477.4% - Xorshift1024 360.7% - -.. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master - :target: https://travis-ci.org/bashtage/randomgen -.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true - :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master -.. |PyPI version| image:: https://badge.fury.io/py/randomgen.svg - :target: https://pypi.org/project/randomgen/ + Speed-up relative to NumPy (Uniform Doubles) + ************************************************************ + DSFMT 137.1% + MT19937 21.0% + PCG32 101.2% + PCG64 110.7% + Philox -2.7% + ThreeFry -11.4% + ThreeFry32 -62.3% + Xoroshiro128 181.4% + Xorshift1024 141.8% + + Speed-up relative to NumPy (64-bit unsigned integers) + ************************************************************ + DSFMT 24.8% + MT19937 15.0% + PCG32 92.6% + PCG64 99.0% + Philox -20.4% + ThreeFry -21.7% + ThreeFry32 -64.4% + Xoroshiro128 164.2% + Xorshift1024 120.8% + + Speed-up relative to NumPy (Standard normals) + ************************************************************ + DSFMT 299.4% + MT19937 271.2% + PCG32 364.5% + PCG64 364.2% + Philox 256.9% + ThreeFry 236.0% + ThreeFry32 97.0% + Xoroshiro128 477.4% + Xorshift1024 360.7% diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 1f51e6f48f7e..88ca7090be68 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -791,14 +791,14 @@ cdef class RandomGenerator: pop_size = operator.index(a.item()) except TypeError: raise ValueError("a must be 1-dimensional or an integer") - if pop_size <= 0: - raise ValueError("a must be greater than 0") + if pop_size <= 0 and np.prod(size) != 0: + raise ValueError("a must be greater than 0 unless no samples are taken") elif a.ndim != 1: raise ValueError("a must be 1-dimensional") else: pop_size = a.shape[0] - if pop_size is 0: - raise ValueError("a must be non-empty") + if pop_size is 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) @@ -4263,30 +4263,38 @@ cdef class RandomGenerator: 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 -------- >>> np.random.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) + >>> np.random.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) + >>> arr = np.arange(9).reshape((3, 3)) >>> np.random.permutation(arr) array([[6, 7, 8], [0, 1, 2], [3, 4, 5]]) + """ if isinstance(x, (int, long, np.integer)): arr = np.arange(x) diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 7fb2008cd8a4..6b3104d64c53 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -566,6 +566,14 @@ def test_choice_return_shape(self): assert_(mt19937.choice(6, s, replace=False, p=p).shape, s) assert_(mt19937.choice(np.arange(6), s, replace=True).shape, s) + # Check zero-size + assert_equal(mt19937.randint(0,0,(3,0,4)).shape, (3,0,4)) + assert_equal(mt19937.randint(0,-10,0).shape, (0,)) + assert_equal(mt19937.choice(0,0).shape, (0,)) + assert_equal(mt19937.choice([],(0,)).shape, (0,)) + assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, (3, 0, 4)) + assert_raises(ValueError, mt19937.choice, [], 10) + def test_bytes(self): mt19937.seed(self.seed) actual = mt19937.bytes(10) From d0cb1546d6478f7a68e5925322cb107468fad645 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 22 Sep 2018 06:28:02 +0100 Subject: [PATCH 089/138] DOC: Provide a better explanation of bounded int generation Clarify that the internal generator is closed on [low, high-1] even though the external interface is open [low, high) closes #26 --- _randomgen/randomgen/bounded_integers.pyx.in | 36 ++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index bdd31a84410c..d6a764590aa4 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -23,7 +23,14 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U {{ py: otype = nptype + '_' if nptype == 'bool' else nptype }} cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size, brng_t *state, object lock): - """Array path for smaller integer types""" + """ + 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 cdef uint32_t buf cdef {{utype}}_t *out_data @@ -61,6 +68,7 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s 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 - 1) - low_v) off = <{{utype}}_t>(<{{nptype_up}}_t>low_v) @@ -82,7 +90,18 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF {{for nptype, utype, npctype, lb, ub in big_type_info}} {{ py: otype = nptype}} cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brng_t *state, object lock): - """Array path for 64-bit integer types""" + """ + 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 @@ -103,6 +122,7 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brn 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}}') @@ -130,7 +150,8 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brn 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] - rng = <{{utype}}_t>(high_v - low_v) # No -1 here since implemented above + # 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: @@ -190,6 +211,14 @@ cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state 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-1]. 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 @@ -208,6 +237,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state (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] high -= 1 if low < {{lb}}: From 8e6b69f417c9a056a697eb3a25551262bdfd4ea6 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 22 Sep 2018 07:45:02 +0100 Subject: [PATCH 090/138] MAINT: Sync with recent upstream changes Sync with Numpy 1.15 changes --- _randomgen/README.rst | 12 ++++++++---- _randomgen/randomgen/examples/numba/extending.py | 4 ++-- _randomgen/randomgen/generator.pyx | 12 ++++++------ _randomgen/randomgen/legacy/legacy.pyx | 5 +++-- .../randomgen/src/distributions/distributions.c | 16 ++++++++-------- .../src/legacy/distributions-boxmuller.c | 2 +- _randomgen/randomgen/src/mt19937/randomkit.c | 2 +- _randomgen/randomgen/tests/test_against_numpy.py | 9 ++++++--- _randomgen/randomgen/tests/test_direct.py | 4 ++-- _randomgen/randomgen/tests/test_numpy_mt19937.py | 11 ++++++----- _randomgen/randomgen/tests/test_smoke.py | 5 ++++- 11 files changed, 47 insertions(+), 35 deletions(-) diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 335a678b1a19..a0e35d584bc2 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -1,10 +1,7 @@ RandomGen ========= -`Travis Build Status `__ -`Appveyor Build -Status `__ -`PyPI version `__ +|Travis Build Status| |Appveyor Build Status| |PyPI version| Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -292,3 +289,10 @@ NumPy’s mt19937. ThreeFry32 97.0% Xoroshiro128 477.4% Xorshift1024 360.7% + +.. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master + :target: https://travis-ci.org/bashtage/randomgen +.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true + :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master +.. |PyPI version| image:: https://badge.fury.io/py/randomgen.svg + :target: https://pypi.org/project/randomgen/ diff --git a/_randomgen/randomgen/examples/numba/extending.py b/_randomgen/randomgen/examples/numba/extending.py index 866b4070d05a..4dafeb5c4d12 100644 --- a/_randomgen/randomgen/examples/numba/extending.py +++ b/_randomgen/randomgen/examples/numba/extending.py @@ -68,10 +68,10 @@ def normals(n, state): start = dt.datetime.now() normalsj(1000000, state_addr) ms = 1000 * (dt.datetime.now() - start).total_seconds() -print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms in ' +print('1,000,000 Polar-transform (numba/Xoroshiro128) 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 Box-Muller (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms)) +print('1,000,000 Polar-transform (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms)) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 88ca7090be68..a752aa84c285 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -798,7 +798,7 @@ cdef class RandomGenerator: else: pop_size = a.shape[0] if pop_size is 0 and np.prod(size) != 0: - raise ValueError("a cannot be empty unless no samples are taken") + raise ValueError("'a' cannot be empty unless no samples are taken") if p is not None: d = len(p) @@ -2102,7 +2102,7 @@ cdef class RandomGenerator: Examples -------- From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 - women in Kj is: + women in kilojoules (kJ) is: >>> intake = np.array([5260., 5470, 5640, 6180, 6390, 6515, 6805, 7515, \\ ... 7515, 8230, 8770]) @@ -3606,12 +3606,12 @@ cdef class RandomGenerator: ----- The probability density for the Hypergeometric distribution is - .. math:: P(x) = \\frac{\\binom{m}{n}\\binom{N-m}{n-x}}{\\binom{N}{n}}, + .. math:: P(x) = \\frac{\\binom{g}{x}\\binom{b}{n-x}}{\\binom{g+b}{n}}, - where :math:`0 \\le x \\le m` and :math:`n+m-N \\le x \\le n` + where :math:`0 \\le x \\le n` and :math:`n-b \\le x \\le g` - for P(x) the probability of x successes, n = ngood, m = nbad, and - N = number of samples. + for P(x) the probability of x successes, g = ngood, b = nbad, and + n = number of samples. Consider an urn with black and white marbles in it, ngood of them black and nbad are white. If you draw nsample balls without diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index 5b15bff8f6bc..93c3236d9fed 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -171,14 +171,15 @@ cdef class LegacyGenerator: Get or set the augmented state Returns the basic RNGs state as well as two values added to track - normal generation using the Box-Muller method. + normal generation using the Polar (Box-Muller-like) method. Returns ------- state : dict Dictionary containing the information required to describe the state of the Basic RNG with two additional fields, gauss and - has_gauss, required to store generated Box-Muller normals. + has_gauss, required to store generated Polar transformation + (Box-Muller-like) normals. """ st = self._basicrng.state st['has_gauss'] = self._aug_state.has_gauss diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index a0966b6b0635..26b6232c2915 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -49,9 +49,9 @@ double random_gauss(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - // Box-Muller transform + /* Polar method, a more efficient version of the Box-Muller approach. f = sqrt(-2.0 * log(r2) / r2); - // Keep for next call + /* Keep for next call brng_state->gauss = f * x1; brng_state->has_gauss = true; return f * x2; @@ -73,9 +73,9 @@ float random_gauss_f(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - // Box-Muller transform + /* Polar method, a more efficient version of the Box-Muller approach. f = sqrtf(-2.0f * logf(r2) / r2); - // Keep for next call + /* Keep for next call brng_state->gauss_f = f * x1; brng_state->has_gauss_f = true; return f * x2; @@ -108,7 +108,7 @@ static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { 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 x; /* 98.9% of the time we return here 1st try */ } return standard_exponential_zig_unlikely(brng_state, idx, x); } @@ -150,7 +150,7 @@ static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { 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 x; /* 98.9% of the time we return here 1st try */ } return standard_exponential_zig_unlikely_f(brng_state, idx, x); } @@ -176,7 +176,7 @@ static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { if (sign & 0x1) x = -x; if (rabs < ki_double[idx]) - return x; // # 99.3% of the time return here + return x; /* 99.3% of the time return here */ if (idx == 0) { for (;;) { xx = -ziggurat_nor_inv_r * log(next_double(brng_state)); @@ -220,7 +220,7 @@ float random_gauss_zig_f(brng_t *brng_state) { if (sign & 0x1) x = -x; if (rabs < ki_float[idx]) - return x; // # 99.3% of the time return here + return x; /* # 99.3% of the time return here */ if (idx == 0) { for (;;) { xx = -ziggurat_nor_inv_r_f * logf(next_float(brng_state)); diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c index 8d3d94095cc8..7ad1742cc585 100644 --- a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c +++ b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c @@ -19,7 +19,7 @@ double legacy_gauss(aug_brng_t *aug_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + /* 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; diff --git a/_randomgen/randomgen/src/mt19937/randomkit.c b/_randomgen/randomgen/src/mt19937/randomkit.c index 947d2adb1067..f8ed4b49e2fd 100644 --- a/_randomgen/randomgen/src/mt19937/randomkit.c +++ b/_randomgen/randomgen/src/mt19937/randomkit.c @@ -568,7 +568,7 @@ double rk_gauss(rk_state *state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + /* 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; diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/_randomgen/randomgen/tests/test_against_numpy.py index 46350cdd0127..ea2656e83fdc 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/_randomgen/randomgen/tests/test_against_numpy.py @@ -4,6 +4,7 @@ import randomgen from randomgen import RandomGenerator, MT19937 +from randomgen._testing import suppress_warnings from randomgen.legacy import LegacyGenerator @@ -263,9 +264,11 @@ def test_vonmises(self): def test_random_integers(self): self._set_common_state() self._is_state_common() - compare_2_input(self.nprs.random_integers, - self.rg.random_integers, - is_scalar=True) + with suppress_warnings() as sup: + sup.record(DeprecationWarning) + compare_2_input(self.nprs.random_integers, + self.rg.random_integers, + is_scalar=True) self._is_state_common() def test_binomial(self): diff --git a/_randomgen/randomgen/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py index c6cd00bd56d4..be4f533eadc5 100644 --- a/_randomgen/randomgen/tests/test_direct.py +++ b/_randomgen/randomgen/tests/test_direct.py @@ -146,7 +146,7 @@ def test_raw(self): uints = rs.random_raw(1000) assert_equal(uints, self.data2['data']) - @pytest.mark.skip(reason='Box-Muller no longer supported') + @pytest.mark.skip(reason='Polar transform no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -352,7 +352,7 @@ def test_uniform_double(self): assert_equal(uniform_from_dsfmt(self.data2['data']), rs.random_sample(1000)) - @pytest.mark.skip(reason='Box-Muller no longer supported') + @pytest.mark.skip(reason='Polar transform no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.brng(*self.data1['seed'])) diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 6b3104d64c53..2ab6bd2d326f 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -567,12 +567,13 @@ def test_choice_return_shape(self): assert_(mt19937.choice(np.arange(6), s, replace=True).shape, s) # Check zero-size - assert_equal(mt19937.randint(0,0,(3,0,4)).shape, (3,0,4)) - assert_equal(mt19937.randint(0,-10,0).shape, (0,)) - assert_equal(mt19937.choice(0,0).shape, (0,)) - assert_equal(mt19937.choice([],(0,)).shape, (0,)) + assert_equal(mt19937.randint(0, 0, size=(3, 0, 4)).shape, (3, 0, 4)) + assert_equal(mt19937.randint(0, -10, size=0).shape, (0,)) + assert_equal(mt19937.randint(10, 10, size=0).shape, (0,)) + assert_equal(mt19937.choice(0, size=0).shape, (0,)) + assert_equal(mt19937.choice([], size=(0,)).shape, (0,)) assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, (3, 0, 4)) - assert_raises(ValueError, mt19937.choice, [], 10) + assert_raises(ValueError, mt19937.choice, [], 10) def test_bytes(self): mt19937.seed(self.seed) diff --git a/_randomgen/randomgen/tests/test_smoke.py b/_randomgen/randomgen/tests/test_smoke.py index 34f95bc10cb0..99f218181d89 100644 --- a/_randomgen/randomgen/tests/test_smoke.py +++ b/_randomgen/randomgen/tests/test_smoke.py @@ -8,6 +8,7 @@ from numpy.testing import assert_almost_equal, assert_equal, assert_, \ assert_array_equal +from randomgen._testing import suppress_warnings from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 from randomgen import entropy @@ -467,7 +468,9 @@ def test_randint(self): assert_(len(vals) == 10) def test_random_integers(self): - vals = self.rg.random_integers(10, 20, 10) + with suppress_warnings() as sup: + sup.record(DeprecationWarning) + vals = self.rg.random_integers(10, 20, 10) assert_(len(vals) == 10) def test_rayleigh(self): From 99bf1a057ff74d6b5d445d07335f6a54974574e8 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 22 Sep 2018 08:07:49 +0100 Subject: [PATCH 091/138] DOC: Update docs for 1.15 release [skip ci] --- _randomgen/doc/source/change-log.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 6084925289ac..9cb5f0128081 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,9 +1,10 @@ Change Log ---------- -Changes since v1.14 -=================== - +v1.15 +===== +- Synced empty choice changes +- Synced upstream docstring changes - Synced upstream changes in permutation - Synced upstream doc fixes - Added absolute_import to avoid import noise on Python 2.7 @@ -12,5 +13,3 @@ Changes since v1.14 - Switch to array-fillers for 0 parameter distribution to improve performance - Small changes to build on manylinux - Build wheels using multibuild - - From 8dba0e9127f9c519e945168b981fb9ffe504eff4 Mon Sep 17 00:00:00 2001 From: bduvenhage Date: Wed, 3 Oct 2018 07:41:47 +0200 Subject: [PATCH 092/138] ENH: Added an alternative interval generator using Lemire's algorithm. The interval generator is used when generating 32-bit bounded random numbers. The speedup is 10% to 220% across the various RNGs compared to my pip Numpy. Added a param to RandomGenerator.randint(...) to allow one to choose which algorithm to use to generate a random number in an interval. Fix C errors on VS. Setup travis to run fewer environments while testing. Restore travis and appveyor settings. 1) Made the parameter order and randint callees consistent. 2) Rename use_masked_generator to use_masked. 3) Added tests for generating uint32 numbers in an interval using the masked and lemire algorithms. --- _randomgen/benchmark.py | 24 +++ _randomgen/randomgen/bounded_integers.pxd.in | 2 +- _randomgen/randomgen/bounded_integers.pyx.in | 32 ++-- _randomgen/randomgen/distributions.pxd | 71 ++++---- _randomgen/randomgen/generator.pyx | 27 +-- .../src/distributions/distributions.c | 156 +++++++++++++----- .../src/distributions/distributions.h | 53 +++--- .../randomgen/tests/test_numpy_mt19937.py | 18 ++ 8 files changed, 270 insertions(+), 113 deletions(-) diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 665f63c26570..3c86f72959f0 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -93,6 +93,29 @@ def timer_32bit(): run_timer(dist, command, command_numpy, SETUP, '32-bit unsigned integers') +def timer_32bit_bounded(): + # info = np.iinfo(np.uint32) + # min, max = info.min, info.max + min, max = 0, 1024 # Worst case for masking & rejection algorithm! + + dist = 'random_uintegers' + + # Note on performance of generating random numbers in an interval: + # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. + # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. + # Lemire's algorithm has improved performance when {max}+1 is not a power of two. + + # command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=True)' # Use masking & rejection. + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=False)' # Use Lemire's algo. + + command = command.format(min=min, max=max) + + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' + command_numpy = command_numpy.format(min=min, max=max) + + run_timer(dist, command, command_numpy, SETUP, '32-bit bounded unsigned integers') + + def timer_64bit(): info = np.iinfo(np.uint64) min, max = info.min, info.max @@ -121,5 +144,6 @@ def timer_normal_zig(): if args.full: timer_raw() timer_32bit() + timer_32bit_bounded() timer_64bit() timer_normal_zig() diff --git a/_randomgen/randomgen/bounded_integers.pxd.in b/_randomgen/randomgen/bounded_integers.pxd.in index 69d2fc0e7242..5f723733cca6 100644 --- a/_randomgen/randomgen/bounded_integers.pxd.in +++ b/_randomgen/randomgen/bounded_integers.pxd.in @@ -35,5 +35,5 @@ 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, brng_t *state, object lock) +cdef object _rand_{{inttype}}(object low, object high, object size, bint use_masked, brng_t *state, object lock) {{endfor}} diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index d6a764590aa4..becf18a1afae 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -22,7 +22,9 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U {{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, brng_t *state, object lock): +cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object size, + bint use_masked, + brng_t *state, object lock): """ Array path for smaller integer types @@ -76,7 +78,7 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s # Smallest bit mask >= max mask = <{{utype}}_t>_gen_mask(rng) - out_data[i] = random_buffered_bounded_{{utype}}(state, off, rng, mask, &buf_rem, &buf) + out_data[i] = random_buffered_bounded_{{utype}}(state, off, rng, mask, use_masked, &buf_rem, &buf) np.PyArray_MultiIter_NEXT(it) return out_arr @@ -89,7 +91,9 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF )}} {{for nptype, utype, npctype, lb, ub in big_type_info}} {{ py: otype = nptype}} -cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brng_t *state, object lock): +cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, + bint use_masked, + brng_t *state, object lock): """ Array path for 64-bit integer types @@ -100,6 +104,8 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, brn 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. + + Note: use_masked currently ignored for 64bit generators. """ cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr @@ -177,14 +183,16 @@ type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), )}} {{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, brng_t *state, object lock): +cdef object _rand_{{nptype}}(object low, object high, object size, + bint use_masked, + brng_t *state, object lock): """ - _rand_{{nptype}}(low, high, size, *state, lock) + _rand_{{nptype}}(low, high, size, use_masked, *state, lock) - Return random np.{{nptype}} integers between `low` and `high`, inclusive. + Return random np.{{nptype}} integers from `low` (inclusive) to `high` (exclusive). Return random integers from the "discrete uniform" distribution in the - closed interval [`low`, `high`). If `high` is None (the default), + 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. @@ -195,12 +203,14 @@ cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state ``high=None``, in which case this parameter is the *highest* such integer). high : int or array-like - If provided, the largest (signed) integer to be drawn from the + 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. state : basic random state State to use in the core random number generators lock : threading.Lock @@ -251,14 +261,14 @@ cdef object _rand_{{nptype}}(object low, object high, object size, brng_t *state off = <{{utype}}_t>(<{{nptype}}_t>low) if size is None: with lock: - random_bounded_{{utype}}_fill(state, off, rng, 1, &out_val) + random_bounded_{{utype}}_fill(state, off, rng, 1, use_masked, &out_val) return np.{{otype}}(<{{nptype}}_t>out_val) else: out_arr = 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, out_data) + random_bounded_{{utype}}_fill(state, off, rng, cnt, use_masked, out_data) return out_arr - return _rand_{{nptype}}_broadcast(low_arr, high_arr, size, state, lock) + return _rand_{{nptype}}_broadcast(low_arr, high_arr, size, use_masked, state, lock) {{endfor}} diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index 6b13733d3e25..67835cde697d 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -96,32 +96,47 @@ cdef extern from "src/distributions/distributions.h": int64_t random_zipf(brng_t *brng_state, double a) nogil int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample) nogil + uint64_t random_interval(brng_t *brng_state, uint64_t max) nogil - uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, - uint64_t rng, uint64_t mask) nogil - uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, - uint32_t rng, uint32_t mask, - int *bcnt, uint32_t *buf) nogil - - uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, - uint16_t rng, uint16_t mask, - int *bcnt, uint32_t *buf) nogil - uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, - uint8_t rng, uint8_t mask, - int *bcnt, uint32_t *buf) nogil - np.npy_bool random_buffered_bounded_bool(brng_t *brng_state, np.npy_bool off, - np.npy_bool rng, np.npy_bool mask, - int *bcnt, uint32_t *buf) nogil - void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, - uint64_t rng, np.npy_intp cnt, - uint64_t *out) nogil - void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, - uint32_t rng, np.npy_intp cnt, - uint32_t *out) nogil - void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, - uint16_t rng, np.npy_intp cnt, - uint16_t *out) nogil - void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, - uint8_t rng, np.npy_intp cnt, uint8_t *out) nogil - void random_bounded_bool_fill(brng_t *brng_state, np.npy_bool off, - np.npy_bool rng, np.npy_intp cnt, np.npy_bool *out) nogil + + uint64_t random_bounded_uint64(brng_t *brng_state, + uint64_t off, uint64_t rng, + uint64_t mask) nogil + + uint32_t random_buffered_bounded_uint32(brng_t *brng_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(brng_t *brng_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(brng_t *brng_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(brng_t *brng_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(brng_t *brng_state, + uint64_t off, uint64_t rng, np.npy_intp cnt, + bint use_masked, + uint64_t *out) nogil + void random_bounded_uint32_fill(brng_t *brng_state, + uint32_t off, uint32_t rng, np.npy_intp cnt, + bint use_masked, + uint32_t *out) nogil + void random_bounded_uint16_fill(brng_t *brng_state, + uint16_t off, uint16_t rng, np.npy_intp cnt, + bint use_masked, + uint16_t *out) nogil + void random_bounded_uint8_fill(brng_t *brng_state, + uint8_t off, uint8_t rng, np.npy_intp cnt, + bint use_masked, + uint8_t *out) nogil + void random_bounded_bool_fill(brng_t *brng_state, + np.npy_bool off, np.npy_bool rng, np.npy_intp cnt, + bint use_masked, + np.npy_bool *out) nogil diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index a752aa84c285..1e87f001f59b 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -572,7 +572,7 @@ cdef class RandomGenerator: randoms_data[i] = random_positive_int(self._brng) return randoms - def randint(self, low, high=None, size=None, dtype=int): + def randint(self, low, high=None, size=None, dtype=int, use_masked=True): """ randint(low, high=None, size=None, dtype='l') @@ -604,6 +604,13 @@ cdef class RandomGenerator: .. versionadded:: 1.11.0 + use_masked : bool + If True the generator uses rejection sampling with a bit mask to + reject random numbers that are out of bounds. If False the generator + will use Lemire's rejection sampling algorithm when available. + + .. versionadded:: 1.15.1 + Returns ------- out : int or ndarray of ints @@ -655,23 +662,23 @@ cdef class RandomGenerator: raise TypeError('Unsupported dtype "%s" for randint' % key) if key == 'int32': - ret = _rand_int32(low, high, size, self._brng, self.lock) + ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, self._brng, self.lock) + ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, self._brng, self.lock) + ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, self._brng, self.lock) + ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, self._brng, self.lock) + ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, self._brng, self.lock) + ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, self._brng, self.lock) + ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, self._brng, self.lock) + ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, self._brng, self.lock) + ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) if size is None and dtype in (np.bool, np.int, np.long): if np.array(ret).shape == (): diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index 26b6232c2915..b16367325c55 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -2,6 +2,7 @@ #include "ziggurat.h" #include "ziggurat_constants.h" + /* Random generators for external use */ float random_float(brng_t *brng_state) { return next_float(brng_state); } @@ -1204,8 +1205,9 @@ static NPY_INLINE uint64_t gen_mask(uint64_t max) { * inclusive. The numbers wrap if rng is sufficiently large. */ -static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, uint64_t off, - uint64_t rng, uint64_t mask) { +static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, + uint64_t off, uint64_t rng, + uint64_t mask) { uint64_t val; if (rng == 0) return off; @@ -1220,42 +1222,86 @@ static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, uint64_t off, return off + val; } -uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, uint64_t rng, +uint64_t random_bounded_uint64(brng_t *brng_state, + uint64_t off, uint64_t rng, uint64_t mask) { return bounded_uint64(brng_state, off, rng, mask); } -static NPY_INLINE uint32_t bounded_uint32(brng_t *brng_state, uint32_t off, - uint32_t rng, uint32_t mask) { +static NPY_INLINE uint32_t bounded_masked_uint32(brng_t *brng_state, + uint32_t off, uint32_t rng, + uint32_t mask) { /* * 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; - if (rng == 0) - return off; while ((val = (next_uint32(brng_state) & mask)) > rng) ; return off + val; } -uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, - uint32_t rng, uint32_t mask, int *bcnt, - uint32_t *buf) { +static NPY_INLINE uint32_t bounded_lemire_uint32(brng_t *brng_state, + uint32_t off, uint32_t rng) { + /* + * 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 + */ + const uint32_t rng_excl = rng + 1; + uint64_t m; + uint32_t leftover; + + if (rng == 0xFFFFFFFF) { + return next_uint32(brng_state); + /* ToDo: Move this code to caller to prevent this check on each call when generating arrays of numbers. */ + } + + /* Generate a scaled random number. */ + m = ((uint64_t)next_uint32(brng_state)) * rng_excl; + + /* Rejection sampling to remove any bias */ + leftover = m & ((uint32_t)((1ULL << 32) - 1)); + + if (leftover < rng_excl) { + const uint32_t threshold = ((uint32_t)((1ULL << 32) - rng_excl)) % rng_excl; + + while (leftover < threshold) { + m = ((uint64_t)next_uint32(brng_state)) * rng_excl; + leftover = m & ((uint32_t)((1ULL << 32) - 1)); + } + } + + return off + (m >> 32); +} + +uint32_t random_buffered_bounded_uint32(brng_t *brng_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 */ - return bounded_uint32(brng_state, off, rng, mask); + if (rng == 0) { + return off; + } else { + if (use_masked) { + return bounded_masked_uint32(brng_state, off, rng, mask); + } else { + return bounded_lemire_uint32(brng_state, off, rng); + } + } } static NPY_INLINE uint16_t buffered_bounded_uint16(brng_t *brng_state, uint16_t off, uint16_t rng, - uint16_t mask, int *bcnt, - uint32_t *buf) { + uint16_t mask, + int *bcnt, uint32_t *buf) { uint16_t val; if (rng == 0) return off; @@ -1273,16 +1319,17 @@ static NPY_INLINE uint16_t buffered_bounded_uint16(brng_t *brng_state, return off + val; } -uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, - uint16_t rng, uint16_t mask, int *bcnt, - uint32_t *buf) { +uint16_t random_buffered_bounded_uint16(brng_t *brng_state, + uint16_t off, uint16_t rng, + uint16_t mask, bool use_masked, + int *bcnt, uint32_t *buf) { return buffered_bounded_uint16(brng_state, off, rng, mask, bcnt, buf); } static NPY_INLINE uint8_t buffered_bounded_uint8(brng_t *brng_state, uint8_t off, uint8_t rng, - uint8_t mask, int *bcnt, - uint32_t *buf) { + uint8_t mask, + int *bcnt, uint32_t *buf) { uint8_t val; if (rng == 0) return off; @@ -1299,16 +1346,17 @@ static NPY_INLINE uint8_t buffered_bounded_uint8(brng_t *brng_state, return off + val; } -uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, - uint8_t rng, uint8_t mask, int *bcnt, - uint32_t *buf) { +uint8_t random_buffered_bounded_uint8(brng_t *brng_state, + uint8_t off, uint8_t rng, + uint8_t mask, bool use_masked, + int *bcnt, uint32_t *buf) { return buffered_bounded_uint8(brng_state, off, rng, mask, bcnt, buf); } static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_state, npy_bool off, npy_bool rng, - npy_bool mask, int *bcnt, - uint32_t *buf) { + npy_bool mask, + int *bcnt, uint32_t *buf) { if (rng == 0) return off; if (!(bcnt[0])) { @@ -1321,14 +1369,17 @@ static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_state, return (buf[0] & 0x00000001UL) != 0; } -npy_bool random_buffered_bounded_bool(brng_t *brng_state, npy_bool off, - npy_bool rng, npy_bool mask, int *bcnt, - uint32_t *buf) { +npy_bool random_buffered_bounded_bool(brng_t *brng_state, + npy_bool off, npy_bool rng, + npy_bool mask, bool use_masked, + int *bcnt, uint32_t *buf) { return buffered_bounded_bool(brng_state, off, rng, mask, bcnt, buf); } -void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t rng, - npy_intp cnt, uint64_t *out) { +void random_bounded_uint64_fill(brng_t *brng_state, + uint64_t off, uint64_t rng, npy_intp cnt, + bool use_masked, + uint64_t *out) { uint64_t mask; npy_intp i; @@ -1343,15 +1394,30 @@ void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t 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(brng_t *brng_state, uint32_t off, uint32_t rng, - npy_intp cnt, uint32_t *out) { - uint32_t mask; +void random_bounded_uint32_fill(brng_t *brng_state, + uint32_t off, uint32_t rng, npy_intp cnt, + bool use_masked, + uint32_t *out) { npy_intp i; - /* Smallest bit mask >= max */ - mask = (uint32_t)gen_mask(rng); - for (i = 0; i < cnt; i++) { - out[i] = bounded_uint32(brng_state, off, rng, mask); + if (rng == 0) { + for (i = 0; i < cnt; i++) { + out[i] = off; + } + return; + } + + if (use_masked) { + uint32_t mask; + // Smallest bit mask >= max + mask = (uint32_t)gen_mask(rng); + for (i = 0; i < cnt; i++) { + out[i] = bounded_masked_uint32(brng_state, off, rng, mask); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = bounded_lemire_uint32(brng_state, off, rng); + } } } @@ -1359,8 +1425,10 @@ void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, uint32_t rng, * 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(brng_t *brng_state, uint16_t off, uint16_t rng, - npy_intp cnt, uint16_t *out) { +void random_bounded_uint16_fill(brng_t *brng_state, + uint16_t off, uint16_t rng, npy_intp cnt, + bool use_masked, + uint16_t *out) { uint16_t mask; npy_intp i; uint32_t buf = 0; @@ -1377,8 +1445,10 @@ void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, * 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(brng_t *brng_state, uint8_t off, uint8_t rng, - npy_intp cnt, uint8_t *out) { +void random_bounded_uint8_fill(brng_t *brng_state, + uint8_t off, uint8_t rng, npy_intp cnt, + bool use_masked, + uint8_t *out) { uint8_t mask; npy_intp i; uint32_t buf = 0; @@ -1395,8 +1465,10 @@ void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, * Fills an array with cnt random npy_bool between off and off + rng * inclusive. */ -void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, - npy_intp cnt, npy_bool *out) { +void random_bounded_bool_fill(brng_t *brng_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; diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index 707f3b455e35..bbd80ac8ee71 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -174,34 +174,45 @@ DECLDIR int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample); DECLDIR uint64_t random_interval(brng_t *brng_state, uint64_t max); -DECLDIR uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, - uint64_t rng, uint64_t mask); + +DECLDIR uint64_t random_bounded_uint64(brng_t *brng_state, + uint64_t off, uint64_t rng, + uint64_t mask); + DECLDIR uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, uint32_t rng, - uint32_t mask, int *bcnt, - uint32_t *buf); - + uint32_t mask, bool use_masked, + int *bcnt, uint32_t *buf); DECLDIR uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, uint16_t rng, - uint16_t mask, int *bcnt, - uint32_t *buf); -DECLDIR uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, - uint8_t rng, uint8_t mask, + uint16_t mask, bool use_masked, + int *bcnt, uint32_t *buf); +DECLDIR uint8_t random_buffered_bounded_uint8(brng_t *brng_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(brng_t *brng_state, npy_bool off, - npy_bool rng, npy_bool mask, +DECLDIR npy_bool random_buffered_bounded_bool(brng_t *brng_state, + npy_bool off, npy_bool rng, + npy_bool mask, bool use_masked, int *bcnt, uint32_t *buf); -DECLDIR void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, - uint64_t rng, npy_intp cnt, + +DECLDIR void random_bounded_uint64_fill(brng_t *brng_state, + uint64_t off, uint64_t rng, npy_intp cnt, + bool use_masked, uint64_t *out); -DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, - uint32_t rng, npy_intp cnt, +DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, + uint32_t off, uint32_t rng, npy_intp cnt, + bool use_masked, uint32_t *out); -DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, - uint16_t rng, npy_intp cnt, +DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, + uint16_t off, uint16_t rng, npy_intp cnt, + bool use_masked, uint16_t *out); -DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, - uint8_t rng, npy_intp cnt, uint8_t *out); -DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, - npy_bool rng, npy_intp cnt, +DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, + npy_bool off, uint8_t rng, npy_intp cnt, + bool use_masked, + uint8_t *out); +DECLDIR void random_bounded_bool_fill(brng_t *brng_state, + npy_bool off, npy_bool rng, npy_intp cnt, + bool use_masked, npy_bool *out); diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 2ab6bd2d326f..01c51c449114 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -436,6 +436,24 @@ def test_randint(self): [-48, -66]]) assert_array_equal(actual, desired) + def test_randint_masked(self): + """ Test masked rejection sampling algorithm to generate array of uint32 in an interval. """ + mt19937.seed(self.seed) + actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=True) + desired = np.array([[2, 47], + [12, 51], + [33, 43]], dtype=np.uint32) + assert_array_equal(actual, desired) + + def test_randint_lemire(self): + """ Test lemire algorithm to generate array of uint32 in an interval. """ + mt19937.seed(self.seed) + actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=False) + desired = np.array([[61, 33], + [58, 14], + [87, 23]], dtype=np.uint32) + assert_array_equal(actual, desired) + def test_random_integers(self): mt19937.seed(self.seed) with suppress_warnings() as sup: From 13d8999fb5c58164a0463efc30af51cf3f834bc4 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 5 Oct 2018 09:16:21 +0100 Subject: [PATCH 093/138] DOC: Add license files Add license files for project and components Use raw string to avoid escape warning in regex --- _randomgen/LICENSE.md | 71 +++++++++++++++++++ _randomgen/MANIFEST.in | 3 +- _randomgen/randomgen/_testing.py | 4 +- _randomgen/randomgen/src/common/LICENSE.md | 29 ++++++++ .../randomgen/src/distributions/LICENSE.md | 30 ++++++++ .../src/dsfmt/{LICENSE.txt => LICENSE.md} | 22 +++--- _randomgen/randomgen/src/entropy/LICENSE.md | 25 +++++++ _randomgen/randomgen/src/legacy/LICENSE.md | 30 ++++++++ _randomgen/randomgen/src/mt19937/LICENSE.md | 61 ++++++++++++++++ _randomgen/randomgen/src/pcg32/LICENSE.md | 22 ++++++ _randomgen/randomgen/src/pcg64/LICENSE.md | 22 ++++++ _randomgen/randomgen/src/philox/LICENSE.md | 31 ++++++++ .../randomgen/src/splitmix64/LICENSE.md | 9 +++ _randomgen/randomgen/src/threefry/LICENSE.md | 31 ++++++++ .../randomgen/src/threefry32/LICENSE.md | 31 ++++++++ .../randomgen/src/xoroshiro128/LICENSE.md | 9 +++ .../randomgen/src/xorshift1024/LICENSE.md | 9 +++ _randomgen/setup.cfg | 4 ++ 18 files changed, 430 insertions(+), 13 deletions(-) create mode 100644 _randomgen/LICENSE.md create mode 100644 _randomgen/randomgen/src/common/LICENSE.md create mode 100644 _randomgen/randomgen/src/distributions/LICENSE.md rename _randomgen/randomgen/src/dsfmt/{LICENSE.txt => LICENSE.md} (65%) create mode 100644 _randomgen/randomgen/src/entropy/LICENSE.md create mode 100644 _randomgen/randomgen/src/legacy/LICENSE.md create mode 100644 _randomgen/randomgen/src/mt19937/LICENSE.md create mode 100644 _randomgen/randomgen/src/pcg32/LICENSE.md create mode 100644 _randomgen/randomgen/src/pcg64/LICENSE.md create mode 100644 _randomgen/randomgen/src/philox/LICENSE.md create mode 100644 _randomgen/randomgen/src/splitmix64/LICENSE.md create mode 100644 _randomgen/randomgen/src/threefry/LICENSE.md create mode 100644 _randomgen/randomgen/src/threefry32/LICENSE.md create mode 100644 _randomgen/randomgen/src/xoroshiro128/LICENSE.md create mode 100644 _randomgen/randomgen/src/xorshift1024/LICENSE.md diff --git a/_randomgen/LICENSE.md b/_randomgen/LICENSE.md new file mode 100644 index 000000000000..e159d505e845 --- /dev/null +++ b/_randomgen/LICENSE.md @@ -0,0 +1,71 @@ +**Copyright (c) 2018 Kevin Sheppard. All rights reserved.** + +Developed by: Kevin Sheppard (, +) +[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.** + +## NumPy + +Many parts of this module have been derived from 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. + +## Components + +Many of the components have their own license terms which are stored +with the source for the component. \ No newline at end of file diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in index b6a20a4feaa1..61fffb8db518 100644 --- a/_randomgen/MANIFEST.in +++ b/_randomgen/MANIFEST.in @@ -5,5 +5,6 @@ include randomgen/_version.py include requirements.txt include README.md include README.rst -recursive-include randomgen *.py *.pyx *.px[di] *.h *.in *.csv +include LICENSE.md +recursive-include randomgen *.py *.pyx *.px[di] *.h *.in *.csv *.md graft randomgen/src diff --git a/_randomgen/randomgen/_testing.py b/_randomgen/randomgen/_testing.py index 86c5ea2b157a..07d41677b7c4 100644 --- a/_randomgen/randomgen/_testing.py +++ b/_randomgen/randomgen/_testing.py @@ -136,7 +136,7 @@ def _filter(self, category=Warning, message="", module=None, warnings.filterwarnings( "always", category=category, message=message) else: - module_regex = module.__name__.replace('.', '\.') + '$' + module_regex = module.__name__.replace('.', r'\.') + '$' warnings.filterwarnings( "always", category=category, message=message, module=module_regex) @@ -224,7 +224,7 @@ def __enter__(self): warnings.filterwarnings( "always", category=cat, message=mess) else: - module_regex = mod.__name__.replace('.', '\.') + '$' + module_regex = mod.__name__.replace('.', r'\.') + '$' warnings.filterwarnings( "always", category=cat, message=mess, module=module_regex) diff --git a/_randomgen/randomgen/src/common/LICENSE.md b/_randomgen/randomgen/src/common/LICENSE.md new file mode 100644 index 000000000000..71bf8cf4624b --- /dev/null +++ b/_randomgen/randomgen/src/common/LICENSE.md @@ -0,0 +1,29 @@ +ISO C9x compliant stdint.h for Microsoft Visual Studio +Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 + +Copyright (c) 2006-2013 Alexander Chemeris + +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 product 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 AUTHOR ``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 AUTHOR 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. \ No newline at end of file diff --git a/_randomgen/randomgen/src/distributions/LICENSE.md b/_randomgen/randomgen/src/distributions/LICENSE.md new file mode 100644 index 000000000000..88b1791b200f --- /dev/null +++ b/_randomgen/randomgen/src/distributions/LICENSE.md @@ -0,0 +1,30 @@ +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. diff --git a/_randomgen/randomgen/src/dsfmt/LICENSE.txt b/_randomgen/randomgen/src/dsfmt/LICENSE.md similarity index 65% rename from _randomgen/randomgen/src/dsfmt/LICENSE.txt rename to _randomgen/randomgen/src/dsfmt/LICENSE.md index 4570c4603b21..d59568f6b16c 100644 --- a/_randomgen/randomgen/src/dsfmt/LICENSE.txt +++ b/_randomgen/randomgen/src/dsfmt/LICENSE.md @@ -1,3 +1,5 @@ +# DSFMT + Copyright (c) 2007, 2008, 2009 Mutsuo Saito, Makoto Matsumoto and Hiroshima University. Copyright (c) 2011, 2002 Mutsuo Saito, Makoto Matsumoto, Hiroshima @@ -8,16 +10,16 @@ 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 Hiroshima University nor the names of - its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. +* 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 Hiroshima University 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 diff --git a/_randomgen/randomgen/src/entropy/LICENSE.md b/_randomgen/randomgen/src/entropy/LICENSE.md new file mode 100644 index 000000000000..b7276aad786e --- /dev/null +++ b/_randomgen/randomgen/src/entropy/LICENSE.md @@ -0,0 +1,25 @@ +# ENTROPY + +_Parts of this module were derived from PCG_ + + +PCG Random Number Generation for C. + +Copyright 2014 Melissa O'Neill + +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 diff --git a/_randomgen/randomgen/src/legacy/LICENSE.md b/_randomgen/randomgen/src/legacy/LICENSE.md new file mode 100644 index 000000000000..88b1791b200f --- /dev/null +++ b/_randomgen/randomgen/src/legacy/LICENSE.md @@ -0,0 +1,30 @@ +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. diff --git a/_randomgen/randomgen/src/mt19937/LICENSE.md b/_randomgen/randomgen/src/mt19937/LICENSE.md new file mode 100644 index 000000000000..f65c3d46e624 --- /dev/null +++ b/_randomgen/randomgen/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/_randomgen/randomgen/src/pcg32/LICENSE.md b/_randomgen/randomgen/src/pcg32/LICENSE.md new file mode 100644 index 000000000000..3db2ac2e8e78 --- /dev/null +++ b/_randomgen/randomgen/src/pcg32/LICENSE.md @@ -0,0 +1,22 @@ +# PCG32 + +PCG Random Number Generation for C. + +Copyright 2014 Melissa O'Neill + +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 diff --git a/_randomgen/randomgen/src/pcg64/LICENSE.md b/_randomgen/randomgen/src/pcg64/LICENSE.md new file mode 100644 index 000000000000..dd6a17ee8a86 --- /dev/null +++ b/_randomgen/randomgen/src/pcg64/LICENSE.md @@ -0,0 +1,22 @@ +# PCG64 + +PCG Random Number Generation for C. + +Copyright 2014 Melissa O'Neill + +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 diff --git a/_randomgen/randomgen/src/philox/LICENSE.md b/_randomgen/randomgen/src/philox/LICENSE.md new file mode 100644 index 000000000000..4a9f6bb29490 --- /dev/null +++ b/_randomgen/randomgen/src/philox/LICENSE.md @@ -0,0 +1,31 @@ +# THREEFRY + +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/_randomgen/randomgen/src/splitmix64/LICENSE.md b/_randomgen/randomgen/src/splitmix64/LICENSE.md new file mode 100644 index 000000000000..3c4d73b920f6 --- /dev/null +++ b/_randomgen/randomgen/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 . \ No newline at end of file diff --git a/_randomgen/randomgen/src/threefry/LICENSE.md b/_randomgen/randomgen/src/threefry/LICENSE.md new file mode 100644 index 000000000000..4a9f6bb29490 --- /dev/null +++ b/_randomgen/randomgen/src/threefry/LICENSE.md @@ -0,0 +1,31 @@ +# THREEFRY + +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/_randomgen/randomgen/src/threefry32/LICENSE.md b/_randomgen/randomgen/src/threefry32/LICENSE.md new file mode 100644 index 000000000000..591cd75f4e79 --- /dev/null +++ b/_randomgen/randomgen/src/threefry32/LICENSE.md @@ -0,0 +1,31 @@ +# THREEFRY32 + +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/_randomgen/randomgen/src/xoroshiro128/LICENSE.md b/_randomgen/randomgen/src/xoroshiro128/LICENSE.md new file mode 100644 index 000000000000..969430149615 --- /dev/null +++ b/_randomgen/randomgen/src/xoroshiro128/LICENSE.md @@ -0,0 +1,9 @@ +# XOROSHIRO128 + +Written in 2016 by David Blackman and 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 . \ No newline at end of file diff --git a/_randomgen/randomgen/src/xorshift1024/LICENSE.md b/_randomgen/randomgen/src/xorshift1024/LICENSE.md new file mode 100644 index 000000000000..3ca8ed4b9898 --- /dev/null +++ b/_randomgen/randomgen/src/xorshift1024/LICENSE.md @@ -0,0 +1,9 @@ +# XORSHIFT1024 + +Written in 2017 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 . \ No newline at end of file diff --git a/_randomgen/setup.cfg b/_randomgen/setup.cfg index 7e46c5c532af..b25ab5078a40 100644 --- a/_randomgen/setup.cfg +++ b/_randomgen/setup.cfg @@ -1,3 +1,7 @@ +[metadata] +description-file = README.md +license_file = LICENSE.md + [versioneer] VCS = git style = pep440 From 707371d3d696e7b7e2c50f611f0701d711d990cf Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 5 Oct 2018 21:19:05 +0100 Subject: [PATCH 094/138] REF: Add path using umul Add umul128 intrinsic support for 64bit windows --- _randomgen/randomgen/src/pcg64/pcg64.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/_randomgen/randomgen/src/pcg64/pcg64.h b/_randomgen/randomgen/src/pcg64/pcg64.h index f3611ce08d2f..854930176f09 100644 --- a/_randomgen/randomgen/src/pcg64/pcg64.h +++ b/_randomgen/randomgen/src/pcg64/pcg64.h @@ -32,6 +32,10 @@ #define inline __inline __forceinline #else #include +#if _MSC_VER >= 1900 && _M_AMD64 +#include +#pragma intrinsic(_umul128) +#endif #endif #if __GNUC_GNU_INLINE__ && !defined(__cplusplus) @@ -94,6 +98,10 @@ static inline pcg128_t _pcg128_add(pcg128_t a, pcg128_t b) { 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. */ @@ -109,6 +117,8 @@ static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, 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) { From 15bebed83d23cfd865b703fd020e6daff1796d76 Mon Sep 17 00:00:00 2001 From: bduvenhage Date: Thu, 11 Oct 2018 12:12:46 +0200 Subject: [PATCH 095/138] ENH: Added Lemire algorithms for generating random numbers --- _randomgen/.travis.yml | 1 - _randomgen/appveyor.yml | 2 +- _randomgen/benchmark.py | 110 +++- _randomgen/randomgen/bounded_integers.pyx.in | 4 +- _randomgen/randomgen/distributions.pxd | 4 +- _randomgen/randomgen/generator.pyx | 2 +- .../src/distributions/distributions.c | 598 +++++++++++++----- .../src/distributions/distributions.h | 61 +- .../randomgen/tests/test_numpy_mt19937.py | 11 +- 9 files changed, 604 insertions(+), 189 deletions(-) diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 052681727ab9..bc483fb97ec4 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -82,4 +82,3 @@ after_success: cd ${BUILD_DIR} python benchmark.py; fi - \ No newline at end of file diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml index 8280f54b64e7..88544620de73 100644 --- a/_randomgen/appveyor.yml +++ b/_randomgen/appveyor.yml @@ -30,4 +30,4 @@ test_script: on_success: - cd %GIT_DIR%\ - - python benchmark.py \ No newline at end of file + - python benchmark.py diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 3c86f72959f0..52c8980616b2 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -83,6 +83,54 @@ def timer_uniform(): run_timer(dist, command, None, SETUP, 'Uniforms') +def timer_8bit_bounded(max=95, use_masked=True): + min = 0 + + dist = 'random_uintegers' + + # Note on performance of generating random numbers in an interval: + # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. + # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. + # Lemire's algorithm has improved performance when {max}+1 is not a power of two. + + if use_masked: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8, use_masked=True)' # Use masking & rejection. + else: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8, use_masked=False)' # Use Lemire's algo. + + command = command.format(min=min, max=max) + + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8)' + command_numpy = command_numpy.format(min=min, max=max) + + run_timer(dist, command, command_numpy, SETUP, + '8-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) + + +def timer_16bit_bounded(max=1535, use_masked=True): + min = 0 + + dist = 'random_uintegers' + + # Note on performance of generating random numbers in an interval: + # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. + # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. + # Lemire's algorithm has improved performance when {max}+1 is not a power of two. + + if use_masked: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16, use_masked=True)' # Use masking & rejection. + else: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16, use_masked=False)' # Use Lemire's algo. + + command = command.format(min=min, max=max) + + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16)' + command_numpy = command_numpy.format(min=min, max=max) + + run_timer(dist, command, command_numpy, SETUP, + '16-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) + + def timer_32bit(): info = np.iinfo(np.uint32) min, max = info.min, info.max @@ -93,10 +141,8 @@ def timer_32bit(): run_timer(dist, command, command_numpy, SETUP, '32-bit unsigned integers') -def timer_32bit_bounded(): - # info = np.iinfo(np.uint32) - # min, max = info.min, info.max - min, max = 0, 1024 # Worst case for masking & rejection algorithm! +def timer_32bit_bounded(max=1535, use_masked=True): + min = 0 dist = 'random_uintegers' @@ -105,15 +151,18 @@ def timer_32bit_bounded(): # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. # Lemire's algorithm has improved performance when {max}+1 is not a power of two. - # command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=True)' # Use masking & rejection. - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=False)' # Use Lemire's algo. + if use_masked: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=True)' # Use masking & rejection. + else: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=False)' # Use Lemire's algo. command = command.format(min=min, max=max) command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' command_numpy = command_numpy.format(min=min, max=max) - run_timer(dist, command, command_numpy, SETUP, '32-bit bounded unsigned integers') + run_timer(dist, command, command_numpy, SETUP, + '32-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) def timer_64bit(): @@ -126,6 +175,30 @@ def timer_64bit(): run_timer(dist, command, command_numpy, SETUP, '64-bit unsigned integers') +def timer_64bit_bounded(max=1535, use_masked=True): + min = 0 + + dist = 'random_uintegers' + + # Note on performance of generating random numbers in an interval: + # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. + # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. + # Lemire's algorithm has improved performance when {max}+1 is not a power of two. + + if use_masked: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64, use_masked=True)' # Use masking & rejection. + else: + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64, use_masked=False)' # Use Lemire's algo. + + command = command.format(min=min, max=max) + + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64)' + command_numpy = command_numpy.format(min=min, max=max) + + run_timer(dist, command, command_numpy, SETUP, + '64-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) + + def timer_normal_zig(): dist = 'standard_normal' command = 'rg.standard_normal(1000000)' @@ -143,7 +216,28 @@ def timer_normal_zig(): timer_uniform() if args.full: timer_raw() + timer_8bit_bounded(use_masked=True) + timer_8bit_bounded(max=64, use_masked=False) # Worst case for Numpy. + timer_8bit_bounded(max=95, use_masked=False) # Typ. avrg. case for Numpy. + timer_8bit_bounded(max=127, use_masked=False) # Best case for Numpy. + + timer_16bit_bounded(use_masked=True) + timer_16bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. + timer_16bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_16bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + timer_32bit() - timer_32bit_bounded() + + timer_32bit_bounded(use_masked=True) + timer_32bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. + timer_32bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_32bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + timer_64bit() + + timer_64bit_bounded(use_masked=True) + timer_64bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. + timer_64bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_64bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + timer_normal_zig() diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/_randomgen/randomgen/bounded_integers.pyx.in index becf18a1afae..eb8555b310d0 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/_randomgen/randomgen/bounded_integers.pyx.in @@ -104,8 +104,6 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, 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. - - Note: use_masked currently ignored for 64bit generators. """ cdef np.ndarray low_arr, high_arr, out_arr, highm1_arr @@ -162,7 +160,7 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, if rng != last_rng: mask = _gen_mask(rng) - out_data[i] = random_bounded_uint64(state, off, rng, mask) + out_data[i] = random_bounded_uint64(state, off, rng, mask, use_masked) np.PyArray_MultiIter_NEXT(it) diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index 67835cde697d..a50d5d821173 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -99,10 +99,12 @@ cdef extern from "src/distributions/distributions.h": uint64_t random_interval(brng_t *brng_state, uint64_t max) nogil + # Generate random uint64 numbers in closed interval [off, off + rng]. uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, uint64_t rng, - uint64_t mask) nogil + uint64_t mask, bint use_masked) nogil + # Generate random uint32 numbers in closed interval [off, off + rng]. uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, uint32_t rng, uint32_t mask, bint use_masked, diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 1e87f001f59b..dda4fa38a67a 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -607,7 +607,7 @@ cdef class RandomGenerator: use_masked : bool If True the generator uses rejection sampling with a bit mask to reject random numbers that are out of bounds. If False the generator - will use Lemire's rejection sampling algorithm when available. + will use Lemire's rejection sampling algorithm. .. versionadded:: 1.15.1 diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index b16367325c55..e04259136e93 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -2,11 +2,18 @@ #include "ziggurat.h" #include "ziggurat_constants.h" +#if defined(_MSC_VER) && defined(_WIN64) +#include +#endif /* Random generators for external use */ -float random_float(brng_t *brng_state) { return next_float(brng_state); } +float random_float(brng_t *brng_state) { + return next_float(brng_state); +} -double random_double(brng_t *brng_state) { return next_double(brng_state); } +double random_double(brng_t *brng_state) { + return next_double(brng_state); +} static NPY_INLINE double next_standard_exponential(brng_t *brng_state) { return -log(1.0 - next_double(brng_state)); @@ -1200,163 +1207,396 @@ static NPY_INLINE uint64_t gen_mask(uint64_t max) { return mask; } -/* - * Fills an array with cnt random npy_uint64 between off and off + rng - * inclusive. The numbers wrap if rng is sufficiently large. - */ +/* Generate 16 bit random numbers using a 32 bit buffer. */ +static NPY_INLINE uint16_t buffered_uint16(brng_t *brng_state, int *bcnt, + uint32_t *buf) { + if (!(bcnt[0])) { + buf[0] = next_uint32(brng_state); + bcnt[0] = 1; + } else { + buf[0] >>= 16; + bcnt[0] -= 1; + } -static NPY_INLINE uint64_t bounded_uint64(brng_t *brng_state, - uint64_t off, uint64_t rng, - uint64_t mask) { - uint64_t val; - if (rng == 0) - return off; + return (uint16_t)buf[0]; +} - if (rng <= 0xffffffffUL) { - while ((val = (next_uint32(brng_state) & mask)) > rng) - ; +/* Generate 8 bit random numbers using a 32 bit buffer. */ +static NPY_INLINE uint8_t buffered_uint8(brng_t *brng_state, int *bcnt, + uint32_t *buf) { + if (!(bcnt[0])) { + buf[0] = next_uint32(brng_state); + bcnt[0] = 3; } else { - while ((val = (next_uint64(brng_state) & mask)) > rng) - ; + buf[0] >>= 8; + bcnt[0] -= 1; } - return off + val; + + return (uint8_t)buf[0]; } -uint64_t random_bounded_uint64(brng_t *brng_state, - uint64_t off, uint64_t rng, - uint64_t mask) { - return bounded_uint64(brng_state, off, rng, mask); +/* Static `masked rejection` function called by random_bounded_uint64(...) */ +static NPY_INLINE uint64_t bounded_masked_uint64(brng_t *brng_state, + uint64_t rng, uint64_t mask) { + uint64_t val; + + while ((val = (next_uint64(brng_state) & mask)) > rng) + ; + + return val; } -static NPY_INLINE uint32_t bounded_masked_uint32(brng_t *brng_state, - uint32_t off, uint32_t rng, - uint32_t mask) { +/* Static `masked rejection` function called by + * random_buffered_bounded_uint32(...) */ +static NPY_INLINE uint32_t buffered_bounded_masked_uint32( + brng_t *brng_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(brng_state) & mask)) > rng) ; - return off + val; + + return val; +} + +/* Static `masked rejection` function called by + * random_buffered_bounded_uint16(...) */ +static NPY_INLINE uint16_t buffered_bounded_masked_uint16( + brng_t *brng_state, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf) { + uint16_t val; + + while ((val = (buffered_uint16(brng_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(brng_t *brng_state, + uint8_t rng, + uint8_t mask, int *bcnt, + uint32_t *buf) { + uint8_t val; + + while ((val = (buffered_uint8(brng_state, bcnt, buf) & mask)) > rng) + ; + + return val; +} + +/* Static `Lemire rejection` function called by random_bounded_uint64(...) */ +static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_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(brng_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(brng_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(brng_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(brng_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 NPY_INLINE uint32_t bounded_lemire_uint32(brng_t *brng_state, - uint32_t off, uint32_t rng) { +/* Static `Lemire rejection` function called by + * random_buffered_bounded_uint32(...) */ +static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(brng_t *brng_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; - if (rng == 0xFFFFFFFF) { - return next_uint32(brng_state); - /* ToDo: Move this code to caller to prevent this check on each call when generating arrays of numbers. */ + /* Generate a scaled random number. */ + m = ((uint64_t)next_uint32(brng_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(brng_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(brng_t *brng_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 = ((uint64_t)next_uint32(brng_state)) * rng_excl; + m = ((uint32_t)buffered_uint16(brng_state, bcnt, buf)) * rng_excl; /* Rejection sampling to remove any bias */ - leftover = m & ((uint32_t)((1ULL << 32) - 1)); + leftover = m & 0xFFFFUL; if (leftover < rng_excl) { - const uint32_t threshold = ((uint32_t)((1ULL << 32) - rng_excl)) % 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 = ((uint64_t)next_uint32(brng_state)) * rng_excl; - leftover = m & ((uint32_t)((1ULL << 32) - 1)); - } + while (leftover < threshold) { + m = ((uint32_t)buffered_uint16(brng_state, bcnt, buf)) * rng_excl; + leftover = m & 0xFFFFUL; + } } - return off + (m >> 32); + return (m >> 16); } -uint32_t random_buffered_bounded_uint32(brng_t *brng_state, - uint32_t off, uint32_t rng, - uint32_t mask, bool use_masked, - int *bcnt, uint32_t *buf) { +/* Static `Lemire rejection` function called by + * random_buffered_bounded_uint8(...) */ +static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(brng_t *brng_state, + uint8_t rng, int *bcnt, + uint32_t *buf) { /* - * Unused bcnt and buf are here only to allow templating with other uint - * generators + * 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(brng_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(brng_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(brng_t *brng_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(brng_state, rng, mask, NULL, NULL); + } else { + return off + buffered_bounded_lemire_uint32(brng_state, rng, NULL, NULL); + } + } else if (rng == 0xFFFFFFFFFFFFFFFFULL) { + /* Lemire64 doesn't support inclusive rng = 0xFFFFFFFFFFFFFFFF. */ + return off + next_uint64(brng_state); } else { if (use_masked) { - return bounded_masked_uint32(brng_state, off, rng, mask); + return off + bounded_masked_uint64(brng_state, rng, mask); } else { - return bounded_lemire_uint32(brng_state, off, rng); + return off + bounded_lemire_uint64(brng_state, rng); } } } -static NPY_INLINE uint16_t buffered_bounded_uint16(brng_t *brng_state, - uint16_t off, uint16_t rng, - uint16_t mask, - int *bcnt, uint32_t *buf) { - uint16_t val; - if (rng == 0) +/* + * 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(brng_t *brng_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; - - do { - if (!(bcnt[0])) { - buf[0] = next_uint32(brng_state); - bcnt[0] = 1; + } else if (rng == 0xFFFFFFFFUL) { + /* Lemire32 doesn't support inclusive rng = 0xFFFFFFFF. */ + return off + next_uint32(brng_state); + } else { + if (use_masked) { + return off + + buffered_bounded_masked_uint32(brng_state, rng, mask, bcnt, buf); } else { - buf[0] >>= 16; - bcnt[0] -= 1; + return off + buffered_bounded_lemire_uint32(brng_state, rng, bcnt, buf); } - val = (uint16_t)buf[0] & mask; - } while (val > rng); - return off + val; -} - -uint16_t random_buffered_bounded_uint16(brng_t *brng_state, - uint16_t off, uint16_t rng, - uint16_t mask, bool use_masked, - int *bcnt, uint32_t *buf) { - return buffered_bounded_uint16(brng_state, off, rng, mask, bcnt, buf); + } } -static NPY_INLINE uint8_t buffered_bounded_uint8(brng_t *brng_state, - uint8_t off, uint8_t rng, - uint8_t mask, - int *bcnt, uint32_t *buf) { - uint8_t val; - if (rng == 0) +/* + * 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(brng_t *brng_state, uint16_t off, + uint16_t rng, uint16_t mask, + bool use_masked, int *bcnt, + uint32_t *buf) { + if (rng == 0) { return off; - do { - if (!(bcnt[0])) { - buf[0] = next_uint32(brng_state); - bcnt[0] = 3; + } else if (rng == 0xFFFFUL) { + /* Lemire16 doesn't support inclusive rng = 0xFFFF. */ + return off + buffered_uint16(brng_state, bcnt, buf); + } else { + if (use_masked) { + return off + + buffered_bounded_masked_uint16(brng_state, rng, mask, bcnt, buf); } else { - buf[0] >>= 8; - bcnt[0] -= 1; + return off + buffered_bounded_lemire_uint16(brng_state, rng, bcnt, buf); } - val = (uint8_t)buf[0] & mask; - } while (val > rng); - return off + val; + } } -uint8_t random_buffered_bounded_uint8(brng_t *brng_state, - uint8_t off, uint8_t rng, - uint8_t mask, bool use_masked, - int *bcnt, uint32_t *buf) { - return buffered_bounded_uint8(brng_state, off, rng, mask, 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(brng_t *brng_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(brng_state, bcnt, buf); + } else { + if (use_masked) { + return off + + buffered_bounded_masked_uint8(brng_state, rng, mask, bcnt, buf); + } else { + return off + buffered_bounded_lemire_uint8(brng_state, rng, bcnt, buf); + } + } } static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_state, npy_bool off, npy_bool rng, - npy_bool mask, - int *bcnt, uint32_t *buf) { + npy_bool mask, int *bcnt, + uint32_t *buf) { if (rng == 0) return off; if (!(bcnt[0])) { @@ -1369,24 +1609,62 @@ static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_state, return (buf[0] & 0x00000001UL) != 0; } -npy_bool random_buffered_bounded_bool(brng_t *brng_state, - npy_bool off, npy_bool rng, - npy_bool mask, bool use_masked, - int *bcnt, uint32_t *buf) { +npy_bool random_buffered_bounded_bool(brng_t *brng_state, npy_bool off, + npy_bool rng, npy_bool mask, + bool use_masked, int *bcnt, + uint32_t *buf) { return buffered_bounded_bool(brng_state, off, rng, mask, bcnt, buf); } -void random_bounded_uint64_fill(brng_t *brng_state, - uint64_t off, uint64_t rng, npy_intp cnt, - bool use_masked, - uint64_t *out) { - uint64_t mask; +/* + * 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(brng_t *brng_state, uint64_t off, uint64_t rng, + npy_intp cnt, bool use_masked, uint64_t *out) { npy_intp i; - /* Smallest bit mask >= max */ - mask = gen_mask(rng); - for (i = 0; i < cnt; i++) { - out[i] = bounded_uint64(brng_state, off, rng, mask); + 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(brng_state, rng, mask, + &bcnt, &buf); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = + off + buffered_bounded_lemire_uint32(brng_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(brng_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(brng_state, rng, mask); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = off + bounded_lemire_uint64(brng_state, rng); + } + } } } @@ -1394,29 +1672,35 @@ void random_bounded_uint64_fill(brng_t *brng_state, * 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(brng_t *brng_state, - uint32_t off, uint32_t rng, npy_intp cnt, - bool use_masked, - uint32_t *out) { +void random_bounded_uint32_fill(brng_t *brng_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; } - return; - } - - if (use_masked) { - uint32_t mask; - // Smallest bit mask >= max - mask = (uint32_t)gen_mask(rng); + } else if (rng == 0xFFFFFFFFUL) { + /* Lemire32 doesn't support rng = 0xFFFFFFFF. */ for (i = 0; i < cnt; i++) { - out[i] = bounded_masked_uint32(brng_state, off, rng, mask); + out[i] = off + next_uint32(brng_state); } } else { - for (i = 0; i < cnt; i++) { - out[i] = bounded_lemire_uint32(brng_state, off, rng); + 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(brng_state, rng, mask, + &bcnt, &buf); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = + off + buffered_bounded_lemire_uint32(brng_state, rng, &bcnt, &buf); + } } } } @@ -1425,19 +1709,36 @@ void random_bounded_uint32_fill(brng_t *brng_state, * 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(brng_t *brng_state, - uint16_t off, uint16_t rng, npy_intp cnt, - bool use_masked, - uint16_t *out) { - uint16_t mask; +void random_bounded_uint16_fill(brng_t *brng_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; - /* Smallest bit mask >= max */ - mask = (uint16_t)gen_mask(rng); - for (i = 0; i < cnt; i++) { - out[i] = buffered_bounded_uint16(brng_state, off, rng, mask, &bcnt, &buf); + 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(brng_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(brng_state, rng, mask, + &bcnt, &buf); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = + off + buffered_bounded_lemire_uint16(brng_state, rng, &bcnt, &buf); + } + } } } @@ -1445,19 +1746,36 @@ void random_bounded_uint16_fill(brng_t *brng_state, * 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(brng_t *brng_state, - uint8_t off, uint8_t rng, npy_intp cnt, - bool use_masked, - uint8_t *out) { - uint8_t mask; +void random_bounded_uint8_fill(brng_t *brng_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; - /* Smallest bit mask >= max */ - mask = (uint8_t)gen_mask(rng); - for (i = 0; i < cnt; i++) { - out[i] = buffered_bounded_uint8(brng_state, off, rng, mask, &bcnt, &buf); + 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(brng_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(brng_state, rng, mask, + &bcnt, &buf); + } + } else { + for (i = 0; i < cnt; i++) { + out[i] = + off + buffered_bounded_lemire_uint8(brng_state, rng, &bcnt, &buf); + } + } } } @@ -1465,10 +1783,8 @@ void random_bounded_uint8_fill(brng_t *brng_state, * Fills an array with cnt random npy_bool between off and off + rng * inclusive. */ -void random_bounded_bool_fill(brng_t *brng_state, - npy_bool off, npy_bool rng, npy_intp cnt, - bool use_masked, - npy_bool *out) { +void random_bounded_bool_fill(brng_t *brng_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; diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index bbd80ac8ee71..7a417b11710d 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -175,10 +175,12 @@ DECLDIR int64_t random_hypergeometric(brng_t *brng_state, int64_t good, DECLDIR uint64_t random_interval(brng_t *brng_state, uint64_t max); -DECLDIR uint64_t random_bounded_uint64(brng_t *brng_state, - uint64_t off, uint64_t rng, - uint64_t mask); +/* Generate random uint64 numbers in closed interval [off, off + rng]. */ +DECLDIR uint64_t random_bounded_uint64(brng_t *brng_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(brng_t *brng_state, uint32_t off, uint32_t rng, uint32_t mask, bool use_masked, @@ -187,32 +189,27 @@ DECLDIR uint16_t random_buffered_bounded_uint16(brng_t *brng_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(brng_t *brng_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(brng_t *brng_state, - npy_bool off, npy_bool rng, - npy_bool mask, bool use_masked, - int *bcnt, uint32_t *buf); - -DECLDIR void random_bounded_uint64_fill(brng_t *brng_state, - uint64_t off, uint64_t rng, npy_intp cnt, - bool use_masked, - uint64_t *out); -DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, - uint32_t off, uint32_t rng, npy_intp cnt, - bool use_masked, - uint32_t *out); -DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, - uint16_t off, uint16_t rng, npy_intp cnt, - bool use_masked, - uint16_t *out); -DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, - npy_bool off, uint8_t rng, npy_intp cnt, - bool use_masked, - uint8_t *out); -DECLDIR void random_bounded_bool_fill(brng_t *brng_state, - npy_bool off, npy_bool rng, npy_intp cnt, - bool use_masked, - npy_bool *out); +DECLDIR uint8_t random_buffered_bounded_uint8(brng_t *brng_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(brng_t *brng_state, npy_bool off, + npy_bool rng, npy_bool mask, + bool use_masked, int *bcnt, + uint32_t *buf); + +DECLDIR void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, + uint64_t rng, npy_intp cnt, + bool use_masked, uint64_t *out); +DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, + uint32_t rng, npy_intp cnt, + bool use_masked, uint32_t *out); +DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, + uint16_t rng, npy_intp cnt, + bool use_masked, uint16_t *out); +DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, npy_bool off, + uint8_t rng, npy_intp cnt, + bool use_masked, uint8_t *out); +DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, + npy_bool rng, npy_intp cnt, + bool use_masked, npy_bool *out); diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 01c51c449114..7ee896d352fa 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -445,7 +445,7 @@ def test_randint_masked(self): [33, 43]], dtype=np.uint32) assert_array_equal(actual, desired) - def test_randint_lemire(self): + def test_randint_lemire_32(self): """ Test lemire algorithm to generate array of uint32 in an interval. """ mt19937.seed(self.seed) actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=False) @@ -454,6 +454,15 @@ def test_randint_lemire(self): [87, 23]], dtype=np.uint32) assert_array_equal(actual, desired) + def test_randint_lemire_64(self): + """ Test lemire algorithm to generate array of uint64 in an interval. """ + mt19937.seed(self.seed) + actual = mt19937.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), dtype=np.uint64, use_masked=False) + desired = np.array([[42523252834, 40656066204], + [61069871386, 61274051182], + [31443797706, 53476677934]], dtype=np.uint64) + assert_array_equal(actual, desired) + def test_random_integers(self): mt19937.seed(self.seed) with suppress_warnings() as sup: From 734fbfb4f4adc5b460d24996ec27ece8dd548c1f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 22 Oct 2018 00:20:13 +0100 Subject: [PATCH 096/138] CLN: Add guards to headers Add header guards --- _randomgen/randomgen/src/aligned_malloc/aligned_malloc.h | 7 ++++++- _randomgen/randomgen/src/distributions/distributions.h | 5 +++++ _randomgen/randomgen/src/entropy/entropy.h | 5 +++++ _randomgen/randomgen/src/legacy/distributions-boxmuller.h | 6 ++++++ _randomgen/randomgen/src/philox/philox.h | 5 +++++ _randomgen/randomgen/src/threefry/threefry.h | 4 ++++ _randomgen/randomgen/src/threefry32/threefry32.h | 4 ++++ _randomgen/randomgen/src/xoroshiro128/xoroshiro128.h | 5 +++++ _randomgen/randomgen/src/xorshift1024/xorshift1024.h | 5 +++++ 9 files changed, 45 insertions(+), 1 deletion(-) diff --git a/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h b/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h index 55716525338b..ea24f6d23052 100644 --- a/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h +++ b/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h @@ -1,3 +1,6 @@ +#ifndef _RANDOMDGEN__ALIGNED_MALLOC_H_ +#define _RANDOMDGEN__ALIGNED_MALLOC_H_ + #include "Python.h" #include "numpy/npy_common.h" @@ -46,4 +49,6 @@ static NPY_INLINE void PyArray_free_aligned(void *p) { void *base = *(((void **)p) - 1); PyMem_Free(base); -} \ No newline at end of file +} + +#endif diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index 7a417b11710d..e618052c1a00 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -1,3 +1,6 @@ +#ifndef _RANDOMDGEN__DISTRIBUTIONS_H_ +#define _RANDOMDGEN__DISTRIBUTIONS_H_ + #pragma once #include #ifdef _WIN32 @@ -213,3 +216,5 @@ DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, npy_bool off, DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, npy_intp cnt, bool use_masked, npy_bool *out); + +#endif diff --git a/_randomgen/randomgen/src/entropy/entropy.h b/_randomgen/randomgen/src/entropy/entropy.h index 0c33edbe4b5e..785603dd3d75 100644 --- a/_randomgen/randomgen/src/entropy/entropy.h +++ b/_randomgen/randomgen/src/entropy/entropy.h @@ -1,3 +1,5 @@ +#ifndef _RANDOMDGEN__ENTROPY_H_ +#define _RANDOMDGEN__ENTROPY_H_ /* * PCG Random Number Generation for C. * @@ -20,6 +22,7 @@ * * http://www.pcg-random.org */ + #include #ifdef _WIN32 #if _MSC_VER == 1500 @@ -41,3 +44,5 @@ 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/_randomgen/randomgen/src/legacy/distributions-boxmuller.h b/_randomgen/randomgen/src/legacy/distributions-boxmuller.h index 2c0615bdb868..445686e6c85b 100644 --- a/_randomgen/randomgen/src/legacy/distributions-boxmuller.h +++ b/_randomgen/randomgen/src/legacy/distributions-boxmuller.h @@ -1,3 +1,7 @@ +#ifndef _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_ +#define _RANDOMDGEN__DISTRIBUTIONS_LEGACY_H_ + + #include "../distributions/distributions.h" typedef struct aug_brng { @@ -32,3 +36,5 @@ extern double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden); extern double legacy_normal(aug_brng_t *aug_state, double loc, double scale); extern double legacy_standard_gamma(aug_brng_t *aug_state, double shape); extern double legacy_exponential(aug_brng_t *aug_state, double scale); + +#endif diff --git a/_randomgen/randomgen/src/philox/philox.h b/_randomgen/randomgen/src/philox/philox.h index a130010e626b..411404b55787 100644 --- a/_randomgen/randomgen/src/philox/philox.h +++ b/_randomgen/randomgen/src/philox/philox.h @@ -1,3 +1,6 @@ +#ifndef _RANDOMDGEN__PHILOX_H_ +#define _RANDOMDGEN__PHILOX_H_ + #include #ifdef _WIN32 @@ -246,3 +249,5 @@ static INLINE uint32_t philox_next32(philox_state *state) { extern void philox_jump(philox_state *state); extern void philox_advance(uint64_t *step, philox_state *state); + +#endif diff --git a/_randomgen/randomgen/src/threefry/threefry.h b/_randomgen/randomgen/src/threefry/threefry.h index e0e4c21a57b7..297c1241a698 100644 --- a/_randomgen/randomgen/src/threefry/threefry.h +++ b/_randomgen/randomgen/src/threefry/threefry.h @@ -1,6 +1,8 @@ /* Adapted from random123's threefry.h */ +#ifndef _RANDOMDGEN__THREEFRY_H_ +#define _RANDOMDGEN__THREEFRY_H_ #ifdef _WIN32 #if _MSC_VER == 1500 @@ -335,3 +337,5 @@ static INLINE uint32_t threefry_next32(threefry_state *state) { extern void threefry_jump(threefry_state *state); extern void threefry_advance(uint64_t *step, threefry_state *state); + +#endif diff --git a/_randomgen/randomgen/src/threefry32/threefry32.h b/_randomgen/randomgen/src/threefry32/threefry32.h index 9e4cdf2fc3ac..74a85c42b453 100644 --- a/_randomgen/randomgen/src/threefry32/threefry32.h +++ b/_randomgen/randomgen/src/threefry32/threefry32.h @@ -1,6 +1,8 @@ /* Adapted from random123's threefry.h */ +#ifndef _RANDOMDGEN__THREEFRY32_H_ +#define _RANDOMDGEN__THREEFRY32_H_ #ifdef _WIN32 #if _MSC_VER == 1500 @@ -836,3 +838,5 @@ static INLINE double threefry32_next_double(threefry32_state *state) { extern void threefry32_jump(threefry32_state *state); extern void threefry32_advance(uint32_t *step, threefry32_state *state); + +#endif diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h index 3fa5b32e9a46..40cb39218908 100644 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h +++ b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h @@ -1,3 +1,6 @@ +#ifndef _RANDOMDGEN__XOROSHIRO128_H_ +#define _RANDOMDGEN__XOROSHIRO128_H_ + #ifdef _WIN32 #if _MSC_VER == 1500 #include "../common/inttypes.h" @@ -50,3 +53,5 @@ static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) { } void xoroshiro128_jump(xoroshiro128_state *state); + +#endif diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024.h b/_randomgen/randomgen/src/xorshift1024/xorshift1024.h index 998dde06c6b3..e0ef7782652f 100644 --- a/_randomgen/randomgen/src/xorshift1024/xorshift1024.h +++ b/_randomgen/randomgen/src/xorshift1024/xorshift1024.h @@ -1,3 +1,6 @@ +#ifndef _RANDOMDGEN__XORSHIFT1024_H_ +#define _RANDOMDGEN__XORSHIFT1024_H_ + #ifdef _WIN32 #if _MSC_VER == 1500 #include "../common/inttypes.h" @@ -43,3 +46,5 @@ static INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { } void xorshift1024_jump(xorshift1024_state *state); + +#endif From c4ed60ee392431e8f09dd4fa7bf62ac79cd7ee52 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 21 Oct 2018 00:05:09 +0100 Subject: [PATCH 097/138] ENH/BUG: Add Xoshiro256starstar generator --- _randomgen/README.md | 66 +- _randomgen/README.rst | 66 +- _randomgen/benchmark.py | 3 +- _randomgen/doc/source/brng/index.rst | 2 + .../doc/source/brng/xoshiro256starstar.rst | 41 + .../doc/source/brng/xoshiro512starstar.rst | 41 + _randomgen/doc/source/change-log.rst | 7 + _randomgen/doc/source/index.rst | 14 +- _randomgen/randomgen/__init__.py | 5 +- _randomgen/randomgen/common.pyx | 2 +- .../examples/numba/extending_distributions.py | 2 +- _randomgen/randomgen/generator.pyx | 2 +- _randomgen/randomgen/legacy/legacy.pyx | 2 +- _randomgen/randomgen/philox.pyx | 2 +- _randomgen/randomgen/pickle.py | 6 +- .../src/xoshiro256starstar/LICENSE.md | 9 + .../xoshiro256starstar-test-data-gen.c | 72 ++ .../xoshiro256starstar/xoshiro256starstar.c | 55 + .../xoshiro256starstar/xoshiro256starstar.h | 63 ++ .../xoshiro256starstar.orig.c | 103 ++ .../xoshiro256starstar.orig.h | 5 + .../src/xoshiro512starstar/LICENSE.md | 9 + .../xoshiro512starstar-test-data-gen.c | 72 ++ .../xoshiro512starstar/xoshiro512starstar.c | 53 + .../xoshiro512starstar/xoshiro512starstar.h | 75 ++ .../xoshiro512starstar.orig.c | 67 ++ .../xoshiro512starstar.orig.h | 6 + .../data/xoshiro256starstar-testset-1.csv | 1001 +++++++++++++++++ .../data/xoshiro256starstar-testset-2.csv | 1001 +++++++++++++++++ .../data/xoshiro512starstar-testset-1.csv | 1001 +++++++++++++++++ .../data/xoshiro512starstar-testset-2.csv | 1001 +++++++++++++++++ _randomgen/randomgen/tests/test_direct.py | 29 +- .../randomgen/tests/test_numpy_mt19937.py | 3 +- _randomgen/randomgen/tests/test_smoke.py | 64 +- _randomgen/randomgen/threefry.pyx | 2 +- _randomgen/randomgen/threefry32.pyx | 2 +- _randomgen/randomgen/xoshiro256starstar.pyx | 362 ++++++ _randomgen/randomgen/xoshiro512starstar.pyx | 356 ++++++ _randomgen/setup.py | 29 +- 39 files changed, 5612 insertions(+), 89 deletions(-) create mode 100644 _randomgen/doc/source/brng/xoshiro256starstar.rst create mode 100644 _randomgen/doc/source/brng/xoshiro512starstar.rst create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/LICENSE.md create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c create mode 100644 _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/LICENSE.md create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c create mode 100644 _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h create mode 100644 _randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv create mode 100644 _randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv create mode 100644 _randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv create mode 100644 _randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv create mode 100644 _randomgen/randomgen/xoshiro256starstar.pyx create mode 100644 _randomgen/randomgen/xoshiro512starstar.pyx diff --git a/_randomgen/README.md b/_randomgen/README.md index eec9bdc753e5..de392c52801e 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -79,8 +79,10 @@ The RNGs include: * [dSFMT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/) a SSE2-aware version of the MT19937 generator that is especially fast at generating doubles -* [xoroshiro128+](http://xoroshiro.di.unimi.it/) and - [xorshift1024*φ](http://xorshift.di.unimi.it/) +* [xoroshiro128+](http://xoroshiro.di.unimi.it/), + [xorshift1024*φ](http://xorshift.di.unimi.it/), + [xoshiro256**](http://xorshift.di.unimi.it/), + and [xoshiro512**](http://xorshift.di.unimi.it/) * [PCG64](http://www.pcg-random.org/) * ThreeFry and Philox from [Random123](https://www.deshawresearch.com/resources_random123.html) @@ -232,36 +234,42 @@ NumPy's mt19937. Speed-up relative to NumPy (Uniform Doubles) ************************************************************ - DSFMT 137.1% - MT19937 21.0% - PCG32 101.2% - PCG64 110.7% - Philox -2.7% - ThreeFry -11.4% - ThreeFry32 -62.3% - Xoroshiro128 181.4% - Xorshift1024 141.8% + DSFMT 184.9% + MT19937 17.3% + PCG32 83.3% + PCG64 108.3% + Philox -4.9% + ThreeFry -12.0% + ThreeFry32 -63.9% + Xoroshiro128 159.5% + Xorshift1024 150.4% + Xoshiro256StarStar 145.7% + Xoshiro512StarStar 113.1% Speed-up relative to NumPy (64-bit unsigned integers) ************************************************************ - DSFMT 24.8% - MT19937 15.0% - PCG32 92.6% - PCG64 99.0% - Philox -20.4% - ThreeFry -21.7% - ThreeFry32 -64.4% - Xoroshiro128 164.2% - Xorshift1024 120.8% + DSFMT 17.4% + MT19937 7.8% + PCG32 60.3% + PCG64 73.5% + Philox -25.5% + ThreeFry -30.5% + ThreeFry32 -67.8% + Xoroshiro128 124.0% + Xorshift1024 109.4% + Xoshiro256StarStar 100.3% + Xoshiro512StarStar 63.5% Speed-up relative to NumPy (Standard normals) ************************************************************ - DSFMT 299.4% - MT19937 271.2% - PCG32 364.5% - PCG64 364.2% - Philox 256.9% - ThreeFry 236.0% - ThreeFry32 97.0% - Xoroshiro128 477.4% - Xorshift1024 360.7% + DSFMT 183.0% + MT19937 169.0% + PCG32 240.7% + PCG64 231.6% + Philox 131.3% + ThreeFry 118.3% + ThreeFry32 21.6% + Xoroshiro128 332.1% + Xorshift1024 232.4% + Xoshiro256StarStar 306.6% + Xoshiro512StarStar 274.6% diff --git a/_randomgen/README.rst b/_randomgen/README.rst index a0e35d584bc2..814b1272b817 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -82,8 +82,10 @@ addition to the MT19937 that is included in NumPy. The RNGs include: - `dSFMT `__ a SSE2-aware version of the MT19937 generator that is especially fast at generating doubles -- `xoroshiro128+ `__ and - `xorshift1024*φ `__ +- `xoroshiro128+ `__, + `xorshift1024*φ `__, + `xoshiro256*\* `__, and + `xoshiro512*\* `__ - `PCG64 `__ - ThreeFry and Philox from `Random123 `__ @@ -256,39 +258,45 @@ NumPy’s mt19937. Speed-up relative to NumPy (Uniform Doubles) ************************************************************ - DSFMT 137.1% - MT19937 21.0% - PCG32 101.2% - PCG64 110.7% - Philox -2.7% - ThreeFry -11.4% - ThreeFry32 -62.3% - Xoroshiro128 181.4% - Xorshift1024 141.8% + DSFMT 184.9% + MT19937 17.3% + PCG32 83.3% + PCG64 108.3% + Philox -4.9% + ThreeFry -12.0% + ThreeFry32 -63.9% + Xoroshiro128 159.5% + Xorshift1024 150.4% + Xoshiro256StarStar 145.7% + Xoshiro512StarStar 113.1% Speed-up relative to NumPy (64-bit unsigned integers) ************************************************************ - DSFMT 24.8% - MT19937 15.0% - PCG32 92.6% - PCG64 99.0% - Philox -20.4% - ThreeFry -21.7% - ThreeFry32 -64.4% - Xoroshiro128 164.2% - Xorshift1024 120.8% + DSFMT 17.4% + MT19937 7.8% + PCG32 60.3% + PCG64 73.5% + Philox -25.5% + ThreeFry -30.5% + ThreeFry32 -67.8% + Xoroshiro128 124.0% + Xorshift1024 109.4% + Xoshiro256StarStar 100.3% + Xoshiro512StarStar 63.5% Speed-up relative to NumPy (Standard normals) ************************************************************ - DSFMT 299.4% - MT19937 271.2% - PCG32 364.5% - PCG64 364.2% - Philox 256.9% - ThreeFry 236.0% - ThreeFry32 97.0% - Xoroshiro128 477.4% - Xorshift1024 360.7% + DSFMT 183.0% + MT19937 169.0% + PCG32 240.7% + PCG64 231.6% + Philox 131.3% + ThreeFry 118.3% + ThreeFry32 21.6% + Xoroshiro128 332.1% + Xorshift1024 232.4% + Xoshiro256StarStar 306.6% + Xoshiro512StarStar 274.6% .. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master :target: https://travis-ci.org/bashtage/randomgen diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 52c8980616b2..860134de1289 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -27,7 +27,8 @@ scale_64 = 2 PRNGS = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', 'Xorshift1024', - 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] + 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'Philox', 'ThreeFry', + 'ThreeFry32', 'numpy'] def timer(code, setup): diff --git a/_randomgen/doc/source/brng/index.rst b/_randomgen/doc/source/brng/index.rst index 709151696272..aceecc792a6c 100644 --- a/_randomgen/doc/source/brng/index.rst +++ b/_randomgen/doc/source/brng/index.rst @@ -23,6 +23,8 @@ These RNGs will be included in future releases. ThreeFry XoroShiro128+ Xorshift1024*φ + Xoshiro256** + Xoshiro512** Experimental RNGs diff --git a/_randomgen/doc/source/brng/xoshiro256starstar.rst b/_randomgen/doc/source/brng/xoshiro256starstar.rst new file mode 100644 index 000000000000..903e76bbbd20 --- /dev/null +++ b/_randomgen/doc/source/brng/xoshiro256starstar.rst @@ -0,0 +1,41 @@ +Xoshiro256** +------------ + +.. module:: randomgen.xoshiro256starstar + +.. currentmodule:: randomgen.xoshiro256starstar + +.. autoclass:: Xoshiro256StarStar + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256StarStar.seed + ~Xoshiro256StarStar.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256StarStar.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256StarStar.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256StarStar.cffi + ~Xoshiro256StarStar.ctypes + + diff --git a/_randomgen/doc/source/brng/xoshiro512starstar.rst b/_randomgen/doc/source/brng/xoshiro512starstar.rst new file mode 100644 index 000000000000..3501b2c9c85e --- /dev/null +++ b/_randomgen/doc/source/brng/xoshiro512starstar.rst @@ -0,0 +1,41 @@ +Xoshiro512** +------------ + +.. module:: randomgen.xoshiro512starstar + +.. currentmodule:: randomgen.xoshiro512starstar + +.. autoclass:: Xoshiro512StarStar + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512StarStar.seed + ~Xoshiro512StarStar.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512StarStar.jump + +Random Generator +================ +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512StarStar.generator + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512StarStar.cffi + ~Xoshiro512StarStar.ctypes + + diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 9cb5f0128081..29876a4b99b7 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,6 +1,13 @@ Change Log ---------- +After v1.15 +=========== +- Added Xoshiro256** and Xoshiro512**, the preferred generators of this class +- Fixed bug in `jump` method of Random123 generators which did nto specify a default value + + + v1.15 ===== - Synced empty choice changes diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index 0885666c8826..7db6cbd5b428 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -150,13 +150,19 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are to produce multiple streams in parallel applications. See :meth:`~randomgen.xoroshiro128.Xoroshiro128.jump` for details. More information about this PRNG is available at the - `xorshift and xoroshiro authors' page`_. -* XorShift1024*φ - Vast fast generator based on the XSadd + `xorshift, xoroshiro and xoshiro authors' page`_. +* XorShift1024*φ - Fast fast generator based on the XSadd generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for :meth:`~randomgen.xorshift1024.Xorshift1024.jump` for details. More information about these PRNGs is available at the - `xorshift and xoroshiro authors' page`_. + `xorshift, xoroshiro and xoshiro authors' page`_. +* Xorshiro256** and Xorshiro512** - The most recently introduced XOR, + shift, and rotate generator. Supports ``jump`` and so can be used in + parallel applications. See the documentation for + :meth:`~randomgen.xoshiro256starstar.Xoshirt256StarStar.jump` for details. More + information about these PRNGs is available at the + `xorshift, xoroshiro and xoshiro authors' page`_. * PCG-64 - Fast generator that support many parallel streams and can be advanced by an arbitrary amount. See the documentation for :meth:`~randomgen.pcg64.PCG64.advance`. PCG-64 has a period of @@ -168,7 +174,7 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are .. _`NumPy's documentation`: https://docs.scipy.org/doc/numpy/reference/routines.random.html .. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ -.. _`xorshift and xoroshiro authors' page`: http://xoroshiro.di.unimi.it/ +.. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/ .. _`PCG author's page`: http://www.pcg-random.org/ .. _`Random123`: https://www.deshawresearch.com/resources_random123.html diff --git a/_randomgen/randomgen/__init__.py b/_randomgen/randomgen/__init__.py index 49094dffcd16..7529922195b0 100644 --- a/_randomgen/randomgen/__init__.py +++ b/_randomgen/randomgen/__init__.py @@ -8,9 +8,12 @@ from randomgen.threefry32 import ThreeFry32 from randomgen.xoroshiro128 import Xoroshiro128 from randomgen.xorshift1024 import Xorshift1024 +from randomgen.xoshiro256starstar import Xoshiro256StarStar +from randomgen.xoshiro512starstar import Xoshiro512StarStar __all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024'] + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', + 'Xoshiro256StarStar', 'Xoshiro512StarStar'] from ._version import get_versions diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index 73638aaa32bb..b152099eb0cb 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 from __future__ import absolute_import from collections import namedtuple diff --git a/_randomgen/randomgen/examples/numba/extending_distributions.py b/_randomgen/randomgen/examples/numba/extending_distributions.py index c0094bf1b882..17ba2704c2e4 100644 --- a/_randomgen/randomgen/examples/numba/extending_distributions.py +++ b/_randomgen/randomgen/examples/numba/extending_distributions.py @@ -14,7 +14,7 @@ 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%\lib\site-packages\numpy\core\include \ -I%PYTHON_HOME%\include %PYTHON_HOME%\libs\python36.lib move distributions.dll ../../examples/numba/ """ diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index dda4fa38a67a..ca6c6af24896 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 from __future__ import absolute_import import operator diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index 93c3236d9fed..a342dbcfa515 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -1,5 +1,5 @@ #!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 from __future__ import absolute_import import warnings diff --git a/_randomgen/randomgen/philox.pyx b/_randomgen/randomgen/philox.pyx index c08f54496317..26ece5e14b2c 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/_randomgen/randomgen/philox.pyx @@ -327,7 +327,7 @@ cdef class Philox: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter): + def jump(self, np.npy_intp iter=1): """ jump(iter=1) diff --git a/_randomgen/randomgen/pickle.py b/_randomgen/randomgen/pickle.py index dbb5324e40dc..459f9c2fcd99 100644 --- a/_randomgen/randomgen/pickle.py +++ b/_randomgen/randomgen/pickle.py @@ -17,8 +17,10 @@ 'ThreeFry': ThreeFry, 'ThreeFry32': ThreeFry32, 'Xorshift1024': Xorshift1024, - 'Xoroshiro128': Xoroshiro128} - + 'Xoroshiro128': Xoroshiro128, + 'Xoshiro256StarStar': Xoshiro256StarStar, + 'Xoshiro512StarStar': Xoshiro512StarStar, + } def __generator_ctor(brng_name='mt19937'): """ diff --git a/_randomgen/randomgen/src/xoshiro256starstar/LICENSE.md b/_randomgen/randomgen/src/xoshiro256starstar/LICENSE.md new file mode 100644 index 000000000000..d863f3b29a79 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/LICENSE.md @@ -0,0 +1,9 @@ +# XOSHIRO256STARSTAR + +Written in 2018 by David Blackman and 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 . \ No newline at end of file diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c new file mode 100644 index 000000000000..8522229ddd89 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c @@ -0,0 +1,72 @@ +/* + * Generate testing csv files + * + * cl xoshiro256starstar-test-data-gen.c xoshiro256starstar.orig.c / + * ../splitmix64/splitmix64.c /Ox + * xoshiro256starstar-test-data-gen.exe * + * + * gcc xoshiro256starstar-test-data-gen.c xoshiro256starstar.orig.c / + * ../splitmix64/splitmix64.c -o xoshiro256starstar-test-data-gen + * ./xoshiro256starstar-test-data-gen + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "../splitmix64/splitmix64.h" +#include "xoshiro256starstar.orig.h" +#include +#include + +#define N 1000 + +int main() { + uint64_t sum = 0; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + int i; + for (i = 0; i < 4; i++) { + s[i] = splitmix64_next(&state); + } + uint64_t store[N]; + for (i = 0; i < N; i++) { + store[i] = next(); + } + + FILE *fp; + fp = fopen("xoshiro256starstar-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); + + seed = state = 0; + for (i = 0; i < 4; i++) { + s[i] = splitmix64_next(&state); + } + for (i = 0; i < N; i++) { + store[i] = next(); + } + fp = fopen("xoshiro256starstar-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/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c new file mode 100644 index 000000000000..30b6c7d85aef --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c @@ -0,0 +1,55 @@ +/* Written in 2018 by David Blackman and 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 . */ + +#include "xoshiro256starstar.h" + +/* This is xoshiro256** 1.0, our all-purpose, rock-solid generator. It has + excellent (sub-ns) speed, a state (256 bits) that is large enough for + any parallel application, and it passes all tests we are aware of. + + For generating just floating-point numbers, xoshiro256+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +extern INLINE uint64_t xoshiro256starstar_next64(xoshiro256starstar_state *state); + +extern INLINE uint32_t xoshiro256starstar_next32(xoshiro256starstar_state *state); + +/* This is the jump function for the generator. It is equivalent + to 2^128 calls to next(); it can be used to generate 2^128 + non-overlapping subsequences for parallel computations. */ + +void xoshiro256starstar_jump(xoshiro256starstar_state *state) +{ + int i, b; + static const uint64_t JUMP[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c}; + + uint64_t s0 = 0; + uint64_t s1 = 0; + uint64_t s2 = 0; + uint64_t s3 = 0; + for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (b = 0; b < 64; b++) + { + if (JUMP[i] & UINT64_C(1) << b) + { + s0 ^= state->s[0]; + s1 ^= state->s[1]; + s2 ^= state->s[2]; + s3 ^= state->s[3]; + } + xoshiro256starstar_next(&state->s[0]); + } + + state->s[0] = s0; + state->s[1] = s1; + state->s[2] = s2; + state->s[3] = s3; +} diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h new file mode 100644 index 000000000000..1d7d8ea40485 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h @@ -0,0 +1,63 @@ +#ifndef _RANDOMDGEN__XOSHIRO256STARSTAR_H_ +#define _RANDOMDGEN__XOSHIRO256STARSTAR_H_ + +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include +#define INLINE __inline __forceinline +#endif +#else +#include +#define INLINE inline +#endif + +typedef struct s_xoshiro256starstar_state { + uint64_t s[4]; + int has_uint32; + uint32_t uinteger; +} xoshiro256starstar_state; + +static INLINE uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +static INLINE uint64_t xoshiro256starstar_next(uint64_t *s) { + const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; + const uint64_t t = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + + s[3] = rotl(s[3], 45); + + return result_starstar; +} + +static INLINE uint64_t +xoshiro256starstar_next64(xoshiro256starstar_state *state) { + return xoshiro256starstar_next(&state->s[0]); +} + +static INLINE uint32_t +xoshiro256starstar_next32(xoshiro256starstar_state *state) { + uint64_t next; + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + next = xoshiro256starstar_next(&state->s[0]); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); +} + +void xoshiro256starstar_jump(xoshiro256starstar_state *state); + +#endif diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c new file mode 100644 index 000000000000..ecf87bab95bb --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c @@ -0,0 +1,103 @@ +/* Written in 2018 by David Blackman and 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 . */ + +#include + +/* This is xoshiro256** 1.0, our all-purpose, rock-solid generator. It has + excellent (sub-ns) speed, a state (256 bits) that is large enough for + any parallel application, and it passes all tests we are aware of. + + For generating just floating-point numbers, xoshiro256+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + + +uint64_t s[4]; + +uint64_t next(void) { + const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; + + const uint64_t t = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + + s[3] = rotl(s[3], 45); + + return result_starstar; +} + + +/* This is the jump function for the generator. It is equivalent + to 2^128 calls to next(); it can be used to generate 2^128 + non-overlapping subsequences for parallel computations. */ + +void jump(void) { + static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c }; + + uint64_t s0 = 0; + uint64_t s1 = 0; + uint64_t s2 = 0; + uint64_t s3 = 0; + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for(int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + s2 ^= s[2]; + s3 ^= s[3]; + } + next(); + } + + s[0] = s0; + s[1] = s1; + s[2] = s2; + s[3] = s3; +} + + + +/* This is the long-jump function for the generator. It is equivalent to + 2^192 calls to next(); it can be used to generate 2^64 starting points, + from each of which jump() will generate 2^64 non-overlapping + subsequences for parallel distributed computations. */ + +void long_jump(void) { + static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; + + uint64_t s0 = 0; + uint64_t s1 = 0; + uint64_t s2 = 0; + uint64_t s3 = 0; + for(int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) + for(int b = 0; b < 64; b++) { + if (LONG_JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + s2 ^= s[2]; + s3 ^= s[3]; + } + next(); + } + + s[0] = s0; + s[1] = s1; + s[2] = s2; + s[3] = s3; +} \ No newline at end of file diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h new file mode 100644 index 000000000000..3aa788ec92e0 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h @@ -0,0 +1,5 @@ +#include + +uint64_t s[4]; +uint64_t next(void); +void jump(void); diff --git a/_randomgen/randomgen/src/xoshiro512starstar/LICENSE.md b/_randomgen/randomgen/src/xoshiro512starstar/LICENSE.md new file mode 100644 index 000000000000..aa34c1966a40 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/LICENSE.md @@ -0,0 +1,9 @@ +# XOSHIRO512STARSTAR + +Written in 2018 by David Blackman and 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 . diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c new file mode 100644 index 000000000000..bcc3574e4a6c --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c @@ -0,0 +1,72 @@ +/* + * Generate testing csv files + * + * cl xoshiro512starstar-test-data-gen.c xoshiro512starstar.orig.c / + * ../splitmix64/splitmix64.c /Ox + * xoshiro512starstar-test-data-gen.exe * + * + * gcc xoshiro512starstar-test-data-gen.c xoshiro512starstar.orig.c / + * ../splitmix64/splitmix64.c -o xoshiro512starstar-test-data-gen + * ./xoshiro512starstar-test-data-gen + * + * Requres the Random123 directory containing header files to be located in the + * same directory (not included). + * + */ + +#include "../splitmix64/splitmix64.h" +#include "xoshiro512starstar.orig.h" +#include +#include + +#define N 1000 + +int main() { + uint64_t sum = 0; + uint64_t state, seed = 0xDEADBEAF; + state = seed; + int i; + for (i = 0; i < 8; i++) { + s[i] = splitmix64_next(&state); + } + uint64_t store[N]; + for (i = 0; i < N; i++) { + store[i] = next(); + } + + FILE *fp; + fp = fopen("xoshiro512starstar-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); + + seed = state = 0; + for (i = 0; i < 8; i++) { + s[i] = splitmix64_next(&state); + } + for (i = 0; i < N; i++) { + store[i] = next(); + } + fp = fopen("xoshiro512starstar-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/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c new file mode 100644 index 000000000000..a9f56699f51d --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c @@ -0,0 +1,53 @@ +/* Written in 2018 by David Blackman and 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 . */ + +#include "xoshiro512starstar.h" + +/* This is xoshiro512** 1.0, an all-purpose, rock-solid generator. It has + excellent (about 1ns) speed, an increased state (512 bits) that is + large enough for any parallel application, and it passes all tests we + are aware of. + + For generating just floating-point numbers, xoshiro512+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +extern INLINE uint64_t +xoshiro512starstar_next64(xoshiro512starstar_state *state); + +extern INLINE uint32_t +xoshiro512starstar_next32(xoshiro512starstar_state *state); + +/* This is the jump function for the generator. It is equivalent + to 2^256 calls to next(); it can be used to generate 2^256 + non-overlapping subsequences for parallel computations. */ + +static uint64_t s_placeholder[8]; + +void xoshiro512starstar_jump(xoshiro512starstar_state *state) { + + int i, b, w; + static const uint64_t JUMP[] = {0x33ed89b6e7a353f9, 0x760083d7955323be, + 0x2837f2fbb5f22fae, 0x4b8c5674d309511c, + 0xb11ac47a7ba28c25, 0xf1be7667092bcc1c, + 0x53851efdb6df0aaf, 0x1ebbc8b23eaf25db}; + + uint64_t t[sizeof s_placeholder / sizeof *s_placeholder]; + memset(t, 0, sizeof t); + for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) + for (w = 0; w < sizeof s_placeholder / sizeof *s_placeholder; w++) + t[w] ^= state->s[w]; + xoshiro512starstar_next(&state->s[0]); + } + + memcpy(state->s, t, sizeof s_placeholder); +} diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h new file mode 100644 index 000000000000..0fa0ba3cda1a --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h @@ -0,0 +1,75 @@ +#ifndef _RANDOMDGEN__XOSHIRO512STARSTAR_H_ +#define _RANDOMDGEN__XOSHIRO512STARSTAR_H_ + +#ifdef _WIN32 +#if _MSC_VER == 1500 +#include "../common/inttypes.h" +#define INLINE __forceinline +#else +#include +#define INLINE __inline __forceinline +#endif +#else +#include +#define INLINE inline +#endif +#include + +typedef struct s_xoshiro512starstar_state +{ + uint64_t s[8]; + int has_uint32; + uint32_t uinteger; +} xoshiro512starstar_state; + +static INLINE uint64_t rotl(const uint64_t x, int k) +{ + return (x << k) | (x >> (64 - k)); +} + +static INLINE uint64_t xoshiro512starstar_next(uint64_t *s) +{ + const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; + + const uint64_t t = s[1] << 11; + + s[2] ^= s[0]; + s[5] ^= s[1]; + s[1] ^= s[2]; + s[7] ^= s[3]; + s[3] ^= s[4]; + s[4] ^= s[5]; + s[0] ^= s[6]; + s[6] ^= s[7]; + + s[6] ^= t; + + s[7] = rotl(s[7], 21); + + return result_starstar; +} + +static INLINE uint64_t +xoshiro512starstar_next64(xoshiro512starstar_state *state) +{ + return xoshiro512starstar_next(&state->s[0]); +} + +static INLINE uint32_t +xoshiro512starstar_next32(xoshiro512starstar_state *state) +{ + uint64_t next; + if (state->has_uint32) + { + state->has_uint32 = 0; + return state->uinteger; + } + next = xoshiro512starstar_next(&state->s[0]); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); +} + +void xoshiro512starstar_jump(xoshiro512starstar_state *state); + +#endif diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c new file mode 100644 index 000000000000..0cf884edb036 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c @@ -0,0 +1,67 @@ +/* Written in 2018 by David Blackman and 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 . */ + +#include "xoshiro512starstar.orig.h" + +/* This is xoshiro512** 1.0, an all-purpose, rock-solid generator. It has + excellent (about 1ns) speed, an increased state (512 bits) that is + large enough for any parallel application, and it passes all tests we + are aware of. + + For generating just floating-point numbers, xoshiro512+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + + +uint64_t next(void) { + const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; + + const uint64_t t = s[1] << 11; + + s[2] ^= s[0]; + s[5] ^= s[1]; + s[1] ^= s[2]; + s[7] ^= s[3]; + s[3] ^= s[4]; + s[4] ^= s[5]; + s[0] ^= s[6]; + s[6] ^= s[7]; + + s[6] ^= t; + + s[7] = rotl(s[7], 21); + + return result_starstar; +} + + +/* This is the jump function for the generator. It is equivalent + to 2^256 calls to next(); it can be used to generate 2^256 + non-overlapping subsequences for parallel computations. */ + +void jump(void) { + static const uint64_t JUMP[] = { 0x33ed89b6e7a353f9, 0x760083d7955323be, 0x2837f2fbb5f22fae, 0x4b8c5674d309511c, 0xb11ac47a7ba28c25, 0xf1be7667092bcc1c, 0x53851efdb6df0aaf, 0x1ebbc8b23eaf25db }; + + uint64_t t[sizeof s / sizeof *s]; + memset(t, 0, sizeof t); + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for(int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) + for(int w = 0; w < sizeof s / sizeof *s; w++) + t[w] ^= s[w]; + next(); + } + + memcpy(s, t, sizeof s); +} \ No newline at end of file diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h new file mode 100644 index 000000000000..0b7892473d44 --- /dev/null +++ b/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h @@ -0,0 +1,6 @@ +#include +#include + +uint64_t s[8]; +uint64_t next(void); +void jump(void); diff --git a/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv b/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv new file mode 100644 index 000000000000..534799b04281 --- /dev/null +++ b/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x876912846bc23b4b +1, 0xc392a0d7b1e2ce1d +2, 0x3a77bd8137033383 +3, 0x3f9bb87b973f5364 +4, 0x512bacc4fc06efaa +5, 0xd46c8d8fcbdcf201 +6, 0x377867a5134b9398 +7, 0xaaad55c3f16b804f +8, 0x8d0073c1156e04b3 +9, 0x636fbcd73be174a3 +10, 0x5e1b4e1dee91170e +11, 0x730f46db723ad8c7 +12, 0x10b330f0fad1bf5c +13, 0x88cc7f11032dbf1 +14, 0x988c1508b1baf298 +15, 0xe95976be578a5817 +16, 0x858fe732639b48ec +17, 0x5b64491ba03516e1 +18, 0x3546e28c5de1358a +19, 0x384c66cde49bd1a6 +20, 0xdbc3ca974f85cf87 +21, 0xf540c65c435d9ae0 +22, 0xe037047fd8120ac6 +23, 0x9970c031b58d7d63 +24, 0x5dae4898619ad11e +25, 0xdf3232cc92ccc65e +26, 0xa16beb0132ddff72 +27, 0x34d1995264d4c508 +28, 0x62da0bb6460ac302 +29, 0x40d2691b6746a05 +30, 0x7fb2ff58185cd1c0 +31, 0xc6e06bc2fe11d4b4 +32, 0x7116e104e2f75ff0 +33, 0xb1595e1cedf7141e +34, 0x29ebcf708d3bd9b +35, 0x628b49afc2d944cc +36, 0xab104fe5d2bf804d +37, 0x57ee3653bf484fe2 +38, 0xbf4d601f70f7f9ac +39, 0x2af4545067b5c32c +40, 0x34f14b2f8fa98e75 +41, 0x9b585ee1c787c12a +42, 0xc2e4f8a4e27f80e +43, 0xeb9876161a0b619d +44, 0x8ea0af67974da802 +45, 0x6e003252a09ed65 +46, 0x97526de03c99ffc5 +47, 0xb8bcd950ba3f2913 +48, 0x5da355c049c286b8 +49, 0xb50e613d8186312a +50, 0x945c21f6c4d7ed77 +51, 0xa7239005836ad3fd +52, 0x2129afecc78a928f +53, 0x9ae55d1d91c75ac6 +54, 0xf50bb42f77b43ad5 +55, 0x576f324976a7672b +56, 0xfa6df7e9660cfeff +57, 0x806144cc58601f9d +58, 0x85b39b38330f7af8 +59, 0xb7d0c116d3f9e866 +60, 0x35dfac0003ca608e +61, 0x9b6320f46d3926c4 +62, 0x4242bbd0776236d7 +63, 0x8aebcd05dd117b2 +64, 0x70df852ded653924 +65, 0x11ae5f39da26fe1c +66, 0x312e11e7aa00c4f9 +67, 0x1f038c235ae539f1 +68, 0xb997522615f4a73b +69, 0xb51bd427274c0935 +70, 0x55e7843d0749c8c2 +71, 0x37c3a6b0d4352cb5 +72, 0x2df190f46312134 +73, 0xc2ecce075d612185 +74, 0x6b490f64cd1f6d92 +75, 0x8a548dad9af41d4a +76, 0xc7a4454c7debc6bd +77, 0xdc2892cd77b00030 +78, 0xb760ac60c94d2b18 +79, 0xe35231cb73492527 +80, 0x55c9f1ee4910e683 +81, 0x97a202d0ad5fdb1 +82, 0x8ff5184631a2b156 +83, 0xcf942173d034770b +84, 0x9a06010116e675d9 +85, 0xa217423b96ae34c0 +86, 0x722e29ffb7567065 +87, 0xbea7d7060cd1a4c0 +88, 0xbcbad83a19de8545 +89, 0xa88c0985b701818c +90, 0x6c1fb7fc4ca8034 +91, 0xb9e24b68f54fb1b0 +92, 0xd925a8a4b8277771 +93, 0xc33beadd812f9876 +94, 0x7b512eae51ab25c7 +95, 0x3a5436f701a0064 +96, 0x6fa2dbfe047f973d +97, 0xa21076a7f59bef78 +98, 0x3c45f50a3e6f06d4 +99, 0x6cd17ca1a4fe09d +100, 0x8121cf3ffc6a1dd7 +101, 0x7b74926ec6d5a7e7 +102, 0x51eb9833ab8da289 +103, 0xaeb2a89fc9beff8 +104, 0x9fcd9cd992f8c183 +105, 0x5190d2596093217c +106, 0xf954156453009abc +107, 0x2bc45642def07a82 +108, 0xa8e3aaff7419393d +109, 0xff66dbc36b6f4899 +110, 0x7b4481a28034b8fb +111, 0xfc1c059bcaf7021 +112, 0x699b4509593d9079 +113, 0xf2c3cd6bb60ad015 +114, 0x76d11b5fc81c9ead +115, 0x5f28d4878bb011e4 +116, 0x62384630f3e25d61 +117, 0x260445ad18a3738 +118, 0xf92f0a2148f340d2 +119, 0xcb502f1bbdf45006 +120, 0xed89ca318747a00f +121, 0x37597ed2125b038e +122, 0xaee1e4927f412f8d +123, 0x18168368f58eccd9 +124, 0x89db16f70186a9c6 +125, 0x6f428e8fcc8a6ad9 +126, 0xb3865b982fe6b986 +127, 0xc1fae9d75ee9bda2 +128, 0xa0b8256d2615e34 +129, 0xd15c4642cc470639 +130, 0xf7f644305154bb69 +131, 0x65592281bae36127 +132, 0x840ebd2e2d314c8c +133, 0xdb08b0bec618b8de +134, 0xaec9540e4eabc7a1 +135, 0x2473da693e1ec36e +136, 0x6be6fdcfccd55dc2 +137, 0xce279e14163df56b +138, 0xc55baabca12406eb +139, 0x7283920d8e00779e +140, 0xea67175f9bd0ce52 +141, 0xe86bc373ed2f7e55 +142, 0xac3acc2569a30892 +143, 0xc749fc876e37766f +144, 0xddc74e16941b8d6e +145, 0xb9c8f5b769849f7b +146, 0xbab826c423a209a5 +147, 0xf1c1b54021fe6418 +148, 0xdad8586480fd30b0 +149, 0x8f713802438a6a1c +150, 0xc3c2f2b83c7d60c9 +151, 0x9697fdffad622052 +152, 0xcb72a8d5150d0507 +153, 0xc1371661bc3c9721 +154, 0x88ca5be46f1d728e +155, 0xdeb9ae3295bb0e4 +156, 0x2d83f4159ad3e2b8 +157, 0xb30c4ada3b396a15 +158, 0x5aac4c5e77f1d4d4 +159, 0x529374c779ee531 +160, 0xb5919e58de0d772a +161, 0x820809cc936741fb +162, 0x53bbba6d2a08acde +163, 0x9a59ed5a21be8fc0 +164, 0x88aa7be1658d60ef +165, 0xbcb7fc1ad8c7d828 +166, 0x11ab2e78229e89fa +167, 0x2056ea8f9c5867f3 +168, 0xfa27e3857ecc3b94 +169, 0x1e42b81f1d84f464 +170, 0x5e1014b09c812c14 +171, 0x9aaa9d8468d9e341 +172, 0x1bfb091f9815ee21 +173, 0x5caacbb9cc7aa2fe +174, 0x58d8a864c538e3c5 +175, 0x539382e5be9cc79 +176, 0xbd89db78d603a58 +177, 0x39e1a6cbda31f0e0 +178, 0x466a59433990edbf +179, 0x56d18c76058e2ce7 +180, 0x2602ce3675d0bdc1 +181, 0x1739af88af931f1b +182, 0x862a947f2809512e +183, 0x6f18216e0710069d +184, 0x5f6e251768ff8b2a +185, 0x3a3be0c1955b088a +186, 0x22b96dd914c79b47 +187, 0x18051e8fcfce2edf +188, 0x80b0f2cceec301d9 +189, 0x868586cb1388e737 +190, 0x22f7c668c6e0da2d +191, 0x13509ef57125f1e7 +192, 0xb91dce92077fb2d1 +193, 0x31b4841411853ad0 +194, 0x32e2ddc8b722c29f +195, 0x5ca01b204c0b166f +196, 0xa2e337cd3dd5a9d1 +197, 0x4131b472c753075d +198, 0x7efcc7a894c9a981 +199, 0xc1d9c33d90e01db3 +200, 0x9053f0abe677615d +201, 0xd2034c8d4e1aa8af +202, 0x227275362bffc8f8 +203, 0x8d5a9d405ecd0179 +204, 0x7b30ddf5440f02d1 +205, 0x3620f9d1867ad68d +206, 0x747ed65beeeba258 +207, 0x1691d5d4a7786e03 +208, 0xf50455cc65243abb +209, 0x4aa91863da8b65d5 +210, 0xa69807c0a08dfafe +211, 0x4fcc33b50b00b3d3 +212, 0xe0671f97db7a35d +213, 0x263f8eabf8f9044a +214, 0x27c85ae64e97e89 +215, 0x4520b74f57c7df51 +216, 0xa37c38ec047eb0b8 +217, 0xcabd6e3e95e72d25 +218, 0xe4bb620d2e3a16d9 +219, 0xda87a4272a6ad108 +220, 0xc867f3fbecd0384b +221, 0x8691f46246273ef7 +222, 0x5ce4229e2422943e +223, 0x8c40ee86a9691904 +224, 0xcb9b83f846c9c9e4 +225, 0xa931ac81531e1529 +226, 0x534cebd4cd8fd2d9 +227, 0x2e3cf1c29aeaba0d +228, 0xa3d2e692301343dc +229, 0x1ef408da84681a8c +230, 0x64f7f2f7d3c02da7 +231, 0x541c50b180553eec +232, 0x536194b38f566c5b +233, 0xbb7a282cd9f36f9d +234, 0x527010351098538b +235, 0xfe30504c6e499b4d +236, 0xa7c3602410a59e53 +237, 0x8f44cacb7b7d1267 +238, 0xe40bf315dc5df184 +239, 0xde7eb3b70c1f41c1 +240, 0xc41aecca30a4bb9c +241, 0x3bc0e028ccb19d93 +242, 0xe166010bfe275442 +243, 0xa70abd28e44af7ca +244, 0xd4504f4548d0d888 +245, 0xa55e4eecb4d88bb5 +246, 0xb6ec6442a017ef5c +247, 0x1c62a5d488494ff6 +248, 0x1c09e177b467f30d +249, 0xb9c90e7ad2f47ecd +250, 0xde2c186b02cc341e +251, 0x1a82ff0a466db4dc +252, 0x61db3602688eb096 +253, 0x920df7c1d2b0e8f1 +254, 0x34a2f18c92e9b6ff +255, 0x14830c36acd9ae19 +256, 0xc321ad1ffbfc54ff +257, 0x9e4b1c6799ff696f +258, 0x1780ce1f22fd9395 +259, 0x26c50c518a484cc1 +260, 0x7461330b1fe01211 +261, 0xd81e75bc84a15cf1 +262, 0x86ca81452380da38 +263, 0xe6b956498fa9f351 +264, 0x9ac04fe965ce35cd +265, 0xa4ec6641c5518519 +266, 0xa03e3054f706bb49 +267, 0xacb9b452fd8267ed +268, 0x302282d4ce222225 +269, 0x8b56489048399d5 +270, 0x1feadce5b06b509b +271, 0x7cee1475ce616c7f +272, 0xd414bce3075397b3 +273, 0xc71f6a8a8eff334a +274, 0x99b3df4a89d93e +275, 0xc702c1e101f4f2dd +276, 0xfe3a7177f2ec77c2 +277, 0xe080a478564afac9 +278, 0x665d0087841f481b +279, 0x4dab6f59d3c1a144 +280, 0x1ce185d7d140c8f5 +281, 0xb007fa8eca9036c0 +282, 0xf18f48ac88312c95 +283, 0x79550ca0c88204cc +284, 0x9970ba85bdb15f27 +285, 0x2b55457ead5f009e +286, 0xc4f24923b930e27a +287, 0x8c3018e3bad3b6d6 +288, 0x790837a25c10ee7 +289, 0xb2dd8ab9f1def8a8 +290, 0x363ec10ac55a521a +291, 0x971af7eb3b1560ad +292, 0xe1a3cb1562833819 +293, 0x6e60e9949b6af18a +294, 0xc379834ba34f6820 +295, 0xb668c3b288a5f926 +296, 0x9ffa1bd130c914c9 +297, 0xe6b93d5188a06452 +298, 0x9c520f67b97dfdf0 +299, 0x50c2a9973c08139a +300, 0x59851ffaf533706e +301, 0x2e5eff12d660fb5c +302, 0xeaa1ff394919a29 +303, 0x9846f6684ff28cd2 +304, 0xeda270a0cd0cd09d +305, 0xc0a319acd516a45d +306, 0x6b5e013c4c4e1efa +307, 0x76faab2a47dc7b68 +308, 0x10d5c15c81514814 +309, 0x3783ee8be5024e54 +310, 0xa4cdb957e5844ce2 +311, 0xd20ca72588a28e27 +312, 0xd7f16a0dcc7f77dc +313, 0xd7e945262b79f2b6 +314, 0xe789e1213d3c62ed +315, 0xba2cbc2fa27b9806 +316, 0x1d39cb2e5d96965 +317, 0x4526e9965c23273a +318, 0x23b4c26eb5166240 +319, 0xaf0f404d70dc5638 +320, 0x8933061cb36229e0 +321, 0x69cec3a72559600 +322, 0xf891d9d259e44209 +323, 0x2e49b1c932ba1d66 +324, 0x333f1bc8321c60f +325, 0x53bad1fb53c8c7cd +326, 0x392f1562e71aac52 +327, 0xa9f6d47f02e8b0d7 +328, 0x39f9c3b1feec67d8 +329, 0x669009ed80083055 +330, 0xab063271b9538170 +331, 0x56678abcd6d3864c +332, 0xde74b0617e61cbd8 +333, 0xbb4f24b9395938a6 +334, 0xc56dfbd143423466 +335, 0x4cb5a4a7ff276754 +336, 0xfb7b814159202ccc +337, 0xf7bbd8fce5320160 +338, 0x218d0ad6343402e7 +339, 0xc8f1bb14eea39aa7 +340, 0x92d7e7256dcab678 +341, 0x8f13ff680747d33 +342, 0x7706151f442ce1dd +343, 0xe902f2633656eb91 +344, 0x69cdf1a57b9424bb +345, 0x9775cad17cd05d1b +346, 0xccf9b27b7dd64f7f +347, 0x1a912eedead72feb +348, 0xc1e26527c077acbd +349, 0xc71692a375f3c720 +350, 0xef1e5b57c2054419 +351, 0xa6b72781c1fc92c0 +352, 0x38318f277f1ef07e +353, 0xe5ba934657bd23b4 +354, 0x792b67250dbc761f +355, 0x785df3106f3610ff +356, 0xfa80a926eae8d94f +357, 0x2c0a95d66d691c70 +358, 0x5c7006e181d4a6ac +359, 0x43e8b7dee8fe5379 +360, 0x87f509b549c83695 +361, 0x32599937b8fcd560 +362, 0xb9931fed6f066f24 +363, 0xf2a6ebcb697508ba +364, 0xc0a3c1ba9a67600a +365, 0xc8badd949bd0e30a +366, 0xcafc4c1611c002a7 +367, 0xc4b5310f493c8f20 +368, 0xc51ff1b5bdb380ac +369, 0xa9c73b25f03868f5 +370, 0x9edfdcc90d558540 +371, 0xd3d6333855161133 +372, 0xcbbd5d9ace516738 +373, 0xcb7e692a0f9fe6fa +374, 0x6a21b61cd8fbb617 +375, 0xfc31d9554c519f86 +376, 0x76ea0f8ef0a354a3 +377, 0xadc8a62ec6b08390 +378, 0x66eeb2fe10131429 +379, 0x12ee14e3a238353a +380, 0xbe3447a29c425e72 +381, 0xaaa368536635fb9a +382, 0xad2ed0d14e4c413f +383, 0x217b489205384ccc +384, 0x4f22392204e47cb6 +385, 0x9b073c7bc6fc086 +386, 0x291abda48636aa3c +387, 0x755ecf4077a77de2 +388, 0x34a5d238de636b33 +389, 0x8989d30fc37b325 +390, 0xd0b9fa38231bdf67 +391, 0x72461fe9b5055361 +392, 0xb25bd2fd4a1bfd09 +393, 0x9ed651e16289afac +394, 0xd02d8c13301d3d2e +395, 0x3d5bbed8ed8856bf +396, 0xc44f594ac43fdbb2 +397, 0x9ada629d96abe651 +398, 0x901bec1095df9927 +399, 0x8597db9a0e29e2f0 +400, 0x97194dc163ca609 +401, 0x90c00a05f753a86b +402, 0x426af3db2a4ac0fb +403, 0x8acda542a69f22c2 +404, 0x674cf92ffcd455ac +405, 0x6136bc48b45959d5 +406, 0xb90b38cd1ff9279d +407, 0x4e6c9b5ecae724d9 +408, 0xcf30abb9df98cc0 +409, 0xddee0179acdaf635 +410, 0xafc739ce5a1e5b9c +411, 0x646a8817ddc44ab5 +412, 0xd34ab42bcb8cdb93 +413, 0xdee4cbee62f81c86 +414, 0xc2221ab03185fdfa +415, 0x7c9f570c313fab96 +416, 0xf1b366adbfee1326 +417, 0x7f096df1a4b284e3 +418, 0x41ed5c325a684c02 +419, 0x177d8012ec68bf1e +420, 0x723ef03bbc899b8d +421, 0x4b133232b7b75961 +422, 0xdf26aaf400d56c4 +423, 0xdfdb1c617a5a9794 +424, 0x9ff2f6d5ff5ce426 +425, 0xa902670b191b5b6b +426, 0x6c9b17049b00578e +427, 0x698c0c675043a17b +428, 0x7a39ef3ca26d128d +429, 0x684d4a467f04e43f +430, 0xe2650c63fde538c8 +431, 0xd68d21f5390269e1 +432, 0x128f6856693a6f91 +433, 0xf16e391706e58b04 +434, 0x77487c06bb8213fb +435, 0x6fcd5a620a122728 +436, 0x505c93b08cca8734 +437, 0x9a1132efe64d531c +438, 0x7fffd4b9c31c6ecb +439, 0x18974137a14e2c8 +440, 0x2aff5858af3e3dec +441, 0x37c2c46feb19f7f1 +442, 0x69ff86ca141d00c9 +443, 0x94dabd547190bf71 +444, 0x5fbb969adddaa7c0 +445, 0xa0775e468c054ab8 +446, 0x632e6a69a80b7be4 +447, 0xba23d74ff6f179a6 +448, 0xdc80b0b9a70432a7 +449, 0xe012f4b1362a90f4 +450, 0x7f132473e42cbef +451, 0xfb182eefc0dad8ac +452, 0xf3fb712546ae256c +453, 0x8ac69f2735229dac +454, 0x564cafdaad77f80c +455, 0x876c4ab2647401d0 +456, 0x2baf5f31018e5c1e +457, 0xae1aaf82b13b7597 +458, 0x65944d8b8cabbb95 +459, 0xc7c01bfe1e0fbc00 +460, 0xf6dd901e7bbe8365 +461, 0x94e1050634114f11 +462, 0x47cab1cd353b7f81 +463, 0xa8775049b2696902 +464, 0xb186dc021a9110ea +465, 0xf28259ce664afa40 +466, 0x67558a2beab5b7b1 +467, 0xb117438f266ec05e +468, 0xf9da8468bb4cb968 +469, 0x2af756738bfc47b +470, 0xd5842c66749f950e +471, 0x953373bd7e97e4b +472, 0x49a929314667f184 +473, 0xe64daee7102ddb89 +474, 0xe459bd3f9acdea67 +475, 0x5b9b04066b20c49d +476, 0x5d82abef2d8487fc +477, 0x4f6236c778a5ed31 +478, 0xdcee2584cd287c46 +479, 0x31c53b48310c8c84 +480, 0xb9cd90102e158a63 +481, 0xe57be85d8e42deeb +482, 0x6582541962888815 +483, 0x845fd1538efbe310 +484, 0xaedc7db39263eaad +485, 0xc0ea0704dea093fd +486, 0x7d3e5c4a245ef295 +487, 0xfe651efbca41d1d8 +488, 0x5275c62cc60f26c1 +489, 0x4eb23a86fd35bd79 +490, 0xd3fccb059f30bb9d +491, 0xc9b6267a16be945a +492, 0x8fa963e267e0791a +493, 0x64e7ef9097602cad +494, 0x13a0d7ba848311ef +495, 0x88878d9ebd8381f +496, 0x4556a6258ccd7aa8 +497, 0x1321af0ffa57b4b2 +498, 0x271c1fc481143191 +499, 0xb09b8888fc206dae +500, 0x1fdb714c88aa8318 +501, 0xdadb65138cf1a785 +502, 0x5c25349014f20584 +503, 0xdde1241c9c5a58cd +504, 0xd93741fab3d630e1 +505, 0xe895c89a575d11f5 +506, 0x4f0b79334c81403c +507, 0xd8a9850c307c591a +508, 0x3621e4b8e12c9a19 +509, 0xb9db6231c6fa3793 +510, 0x659a34f2e8b13a30 +511, 0x3f7f65d4138a3ece +512, 0xc68a3b4193c7ddb +513, 0xfedb2ff6f59b308d +514, 0x91a49785126b2707 +515, 0xcd897846c2da401c +516, 0x3174aeb2ef45125a +517, 0xfc93e91769875bea +518, 0x20dc156b32d376bc +519, 0x55b332e7395ae006 +520, 0x898b4d9889ab42d7 +521, 0x80e8b4fa60d67e52 +522, 0x751bb9a5c4f43263 +523, 0x4ef12c7d48b02305 +524, 0xe9b2f6da9932279c +525, 0x28166b1bb0083fe +526, 0xd66ede9e1175436c +527, 0xe1600bfe3543967c +528, 0x9e82c1de27917b7e +529, 0x1a6a6a36eee4e0d3 +530, 0x4fd5e445d2ff89a6 +531, 0xb167da8a45a041b4 +532, 0x90421abd6d6b657 +533, 0xac2d084ffe30c155 +534, 0xaf6d71f79d0250a +535, 0x2d2ba07fc90eaba2 +536, 0xee44751087f49162 +537, 0xd9a125da1f2bcd5b +538, 0x1710b671e85149e2 +539, 0x6345319547b83ad1 +540, 0x68b4495241b6c0e7 +541, 0x74fa064e23915490 +542, 0x994254c5ef7484ff +543, 0x767ce73cb64a3828 +544, 0xc44be811238ec768 +545, 0x49bcfd08e26f93ca +546, 0x8506215301976fbe +547, 0x17d72c4c22b48cc9 +548, 0xf482dc265fc66423 +549, 0x81515cd9ee472156 +550, 0xffc3716cab24bdce +551, 0x4f272ed4fdd1cc65 +552, 0xa5fbe307e8a95706 +553, 0x4f489ae4435d271a +554, 0xc32af641a427871e +555, 0x481501cd6e76b046 +556, 0x7fdb10595e105959 +557, 0xc231d1fbcd7f9905 +558, 0x7f8af2f02dc96527 +559, 0xee1829cff220d07f +560, 0x69cec4a31d43a06a +561, 0x7ec964a98e091334 +562, 0x267d4751786ed827 +563, 0x3ff2a3fa95f49992 +564, 0x4db020a1aaa91126 +565, 0xf0a52fbc2ecbe5e6 +566, 0x22b4a6f29b420436 +567, 0x3baee23caf4332c7 +568, 0xf25b4154d1337b22 +569, 0xa1fc227fdb94fd5c +570, 0x1c8d1858a14c79c7 +571, 0xdee05236f275cd72 +572, 0xbd2feb9b5bfea570 +573, 0x96d3d6d1189b458c +574, 0xbfe1c60f48c2a834 +575, 0x590b91cf41e7f1c +576, 0xa230cd61d4aace50 +577, 0x9b15a3dbd0129922 +578, 0x5a6cd3333e77adea +579, 0x41825f9a09221129 +580, 0x713d20fbbb133600 +581, 0xde695bc734434fc2 +582, 0x80022a312ccfd484 +583, 0xfebe989fbe2d7f33 +584, 0xeacb2fc50aa3ce4b +585, 0xb7bde6fa12d0db67 +586, 0xc5e52e74fd2fcf5e +587, 0xccc74d9803ec269f +588, 0x9f9f1bd42ceed664 +589, 0x5892c340c9b3e3f3 +590, 0x306260b57f475e42 +591, 0x20ba283b7feec8fd +592, 0x8258f0179d4c1aac +593, 0xf4f89922b5afe031 +594, 0xfdba45233cdd04a +595, 0xce0f81c48bfd0d58 +596, 0x4b0cbebe17263b16 +597, 0xfee1fd8f3abf3ee0 +598, 0xfc5194839696ca5d +599, 0xb2106fc284f8cfed +600, 0x3be13181cdac454f +601, 0x1dfea888cdb8755 +602, 0xe1df7e41e646b676 +603, 0x72e16234c51caa19 +604, 0x367a508bf361b3c9 +605, 0x3e8d10a40879846d +606, 0x72540d5ed7c59a5e +607, 0x49d00e4543ebd93d +608, 0xf889e0dfb47c5a24 +609, 0xf6b166031a98e3f0 +610, 0x6ec9c4ac1f367f6e +611, 0x81c322bfb5b4963b +612, 0xe43618859ee305b6 +613, 0x5c0849263dff8bd8 +614, 0xca60ef338ca33c75 +615, 0x96dc953cd8229dfb +616, 0xd33d8edd653f9411 +617, 0x398f97e5a17e9d21 +618, 0xa679fb8f7359cdd3 +619, 0x1a079b224822d2ae +620, 0xd6f973d320aea3bd +621, 0x8147d823ddca9fdb +622, 0x7a15b31891283335 +623, 0x1ddff9012d02fbd7 +624, 0xf8822faf5627a945 +625, 0x41be97afe83c9b99 +626, 0xfc6c03f323a40cf0 +627, 0x40a3547fbda709fa +628, 0xdabf18e62533b8dc +629, 0x3df9047875ad057 +630, 0xaf3cb3461b5ce9a1 +631, 0x372859b34b493176 +632, 0x2fca17f51fa0f9eb +633, 0xc7029f122beba37f +634, 0x3f4e9ea4b4f4e36e +635, 0x63d22717f8c9118d +636, 0xc85fff0d3f30946f +637, 0xfaf6a8680c3327b7 +638, 0x7cc6ff76d32736cf +639, 0xed7066e55443e1d5 +640, 0xf8698e4c0986e3a4 +641, 0xfd8d1e5a65a86bae +642, 0xe52f0012446decc8 +643, 0x5057fe700548fd6c +644, 0x4529015264cdb296 +645, 0xf0bfc50ab6700a9b +646, 0xf42ac8161980025d +647, 0xd4eda173955d8472 +648, 0x37b042b1e5a10dd +649, 0xe325a690ab12eb81 +650, 0x7fcf9f4d85db4127 +651, 0xbacbd13cba440c75 +652, 0xbaaab45fa3ec6721 +653, 0x621a8fb360e704d7 +654, 0x8e97eb1966466330 +655, 0xda7f0a06440024c0 +656, 0xe32b44177201fb54 +657, 0x81426b2259d306df +658, 0xcc12d49f57a2a60d +659, 0x43d840cb2c1b96f3 +660, 0x2f5190397dd5f5fc +661, 0x37ca67cb906f8840 +662, 0x84bdcca3f926b24d +663, 0x833e6cc4f6846646 +664, 0x3d046e6375412bf0 +665, 0x8678ca4ef2e3f721 +666, 0x62d9c438d39748cd +667, 0x750fb4b000895aaf +668, 0x7b760b873d0bfce0 +669, 0x3cc79186f7e7528e +670, 0xe1e304d26bc14e90 +671, 0xe855ed09d88a5b86 +672, 0x99ae65ccd9d9ff9 +673, 0xd9bea1d3d04c6432 +674, 0x6871fc86fccce7a5 +675, 0xca6f22983e5d892b +676, 0x7e29222169c094bc +677, 0xbb6bb434e7225ce2 +678, 0x3b907684d5342268 +679, 0x5e5328163653a332 +680, 0xf56453da8399ea50 +681, 0x4691e0f9a0c6625 +682, 0x11a6cee0f014d630 +683, 0xdff740d94007b83a +684, 0x6744032172a60cb1 +685, 0x8d311639fb358a47 +686, 0xe77ae7a767d74301 +687, 0x994184353b84ffd5 +688, 0x9faa8b6852c8b9ec +689, 0xed5d549c40fd7b31 +690, 0x6bff41b829143500 +691, 0x95cd1f944b72360e +692, 0x966e8976a79bd4f7 +693, 0x5f73608f2069b1f3 +694, 0x20c03970af7c205f +695, 0x9a0e0928bc29f5fa +696, 0xdc80d66b7ec92bc3 +697, 0x558745e23c9e413d +698, 0x32dae13bef9e4398 +699, 0x1af3f745e7ca19b4 +700, 0x1cbb10f2f21417a2 +701, 0x37c03955556e6f6 +702, 0x852afdad0d2459fc +703, 0xee72e7019e217ec4 +704, 0x6854606758560380 +705, 0x9284eba641a65dfc +706, 0x446b92d6b8f3f53a +707, 0xbe360ebdf10ded26 +708, 0x1048ecaabfe15b93 +709, 0x25d1762c447cca8c +710, 0x6cf6151bdd266aa8 +711, 0x2e8fcc480b9d228 +712, 0xeb6b1cbea3c65d63 +713, 0x7a883b88ef974ee5 +714, 0x9f52f4081ea085f0 +715, 0x75fa5e7cbf0c55a5 +716, 0x2bfedfe0e029b818 +717, 0xebaec3bcde2e43b1 +718, 0xeaa3aa06bf8a67e1 +719, 0x4deacc579051e8c0 +720, 0xec44abbc73b62bf4 +721, 0xb9a339ae805270b7 +722, 0xf9eb47d4cba2877 +723, 0x6105cdeb6a7e678e +724, 0x242351322affd465 +725, 0x111fe30cf81b2f70 +726, 0x25b5ae64c741738a +727, 0xfb425508ba96049e +728, 0xe0fbf9619e3a1aee +729, 0xa0fcb4f5f0c32ee9 +730, 0x1e69787a387b30a +731, 0xe89a8480884263d9 +732, 0x4c02fe1f82aac874 +733, 0xb576e8a44017bee9 +734, 0x5e7b98878c6537ab +735, 0x6d291feb307f3740 +736, 0x7d00feb09e768b54 +737, 0x71bb0170d659119a +738, 0x7bb2ff7d0a61dda3 +739, 0x2c6a16824290b7f3 +740, 0xb96623628a2917ea +741, 0x14489300ff071e92 +742, 0xdedd6422224f3748 +743, 0xa6e1071c454da244 +744, 0x1c4b1edef803ffec +745, 0xa5f8e7c79d02be10 +746, 0x9b8309dddcbd21bc +747, 0x6f57e425d2808563 +748, 0xd7d49cab22729386 +749, 0xd0dab40fd019b301 +750, 0x6808b10401cda8fb +751, 0xfa51b53ceceb08b8 +752, 0xb90e4574b2745b68 +753, 0x470707ab3da1f1a2 +754, 0xbc76e852147fe684 +755, 0x82f7e418e4454b7e +756, 0x6aa5fec0a5dbb4b9 +757, 0x2695d285a10e05c2 +758, 0xd15219b5dcc6db09 +759, 0x8ece31d881c4e1e5 +760, 0x1bea39be5b09c080 +761, 0x19e1d4897394d0f8 +762, 0x8bb735c6dcade9e9 +763, 0x5df3789e52d93a64 +764, 0xcd6aae13791d95df +765, 0x188ce0105b17920a +766, 0x3fa30c09840f615e +767, 0x7c201465bc6301e4 +768, 0xa9a00e2757807982 +769, 0x122e0fc0c79782fe +770, 0xabff396bc21271b +771, 0x7d54d41d59c99fe4 +772, 0xe2d5b1393b081928 +773, 0x45165a925412ed4e +774, 0x96c945ed58ba2bab +775, 0xde05a1d6fb9ced45 +776, 0x496cad57600fe9ff +777, 0xc3846b63bfc1062c +778, 0x9055ccd5f729b1f7 +779, 0x8fa87030e7e623a4 +780, 0x7e6ee59d4fb11784 +781, 0xb5b151c0d892955e +782, 0xeeaa87699ff69dfc +783, 0xa6d485e04ce2dd71 +784, 0x69c53b89eec70119 +785, 0x3732533c7df25f53 +786, 0x275d37a0c68e7a42 +787, 0x3a88f16ac812bad8 +788, 0xb0f92536c7c763 +789, 0x27a32d261274ee83 +790, 0x3fd5ae8a771adf89 +791, 0x23feb68f4819e4f +792, 0x4d4c7be0e84aa024 +793, 0x41a80d994fc0a41c +794, 0x718321ae9282c3b3 +795, 0xd551e149c01af06c +796, 0xbcb93735c6eac744 +797, 0xe59f03655f9180f8 +798, 0x6e96a0431ed2e0cb +799, 0x5866d0755ecf3c6e +800, 0xd9f473c16bbec85f +801, 0x38b2070194506205 +802, 0x98aaa714c80a21af +803, 0xdb7853e1515cb5b +804, 0x32532dd0c0e1920b +805, 0xf5d440e12b584cfc +806, 0xe67397ec029cda3e +807, 0x2d51f19fcbc86346 +808, 0xb5e46840c44c80b0 +809, 0x6d39c237e90744be +810, 0x3535938a21e6e293 +811, 0x7b8a87d2b539e50 +812, 0xf4e74d0346ccdb48 +813, 0x1640fb85b5f11965 +814, 0x2a99ba02ff6b5ccd +815, 0x12dbbd81a6ca75ad +816, 0xff72053bbfd9490f +817, 0xf5470d1e0ff5888f +818, 0xd7d3e1ca8d79382d +819, 0xd437182225fda535 +820, 0xde44396868fad24c +821, 0xeafa4c86c0c578b4 +822, 0x788a1e34983fc51f +823, 0x396563f750981e64 +824, 0xeee9e79937487d52 +825, 0x12871390ffe443a9 +826, 0x96b07429b4a54778 +827, 0xb0506605d66bebce +828, 0x1b5878bc242f0158 +829, 0xea46c8e2d9ca3dbe +830, 0xa94a8750612bc68 +831, 0x864ccfa5796f590b +832, 0x4d1d2609563b8063 +833, 0xec62387e7f258abe +834, 0xb2726f3d37ba75b1 +835, 0x2067494d0dd41024 +836, 0xf75839382e176d99 +837, 0xf0c83dd9ed0aaf23 +838, 0xfa8a581e28780483 +839, 0xc461e40cda6d4ba4 +840, 0xaebdb6c7da47946b +841, 0xd380bbdf27718424 +842, 0xd31504078e3a9a9 +843, 0x4fc0eee024e9a5a9 +844, 0x18714e84611ae719 +845, 0x7503c0ee7ce5608c +846, 0xef1abc4a7543b398 +847, 0xd1e7ad19597d9cb5 +848, 0x77fb8e61dec1dff5 +849, 0x6d6504f8f1cd19ff +850, 0x7d7e1a6b8d21b29a +851, 0xc0504f78e1744ba0 +852, 0xbe3aefe760c2025f +853, 0xbeba2fd08acd9166 +854, 0x5c140d358435d3b9 +855, 0xc550467f426d4bb9 +856, 0xfcf1c8674b415f75 +857, 0xc81721303ee733e0 +858, 0xe4b0c096d8c54e7e +859, 0xa963e1fa39f44bc +860, 0xfc6fb6ad0317aa76 +861, 0xdf7c4217eeb378f9 +862, 0x69639f8b6c1c765e +863, 0x23d8874dfac843f4 +864, 0x323e6cfed1af5406 +865, 0xdf34a5b2df24c44f +866, 0x52c88f39e1f1017c +867, 0x9b780cb0ffd8e0ae +868, 0x17bdfe024bf483fe +869, 0x1bdc2d6b57afb0d7 +870, 0xe5cfe8cf4f301238 +871, 0x466caae45214f84b +872, 0xefa9e39d81d0f263 +873, 0xf9e330742b518177 +874, 0xea36033c02f97e71 +875, 0x37f90271cfa76be9 +876, 0x313e5ad81eb57d98 +877, 0xc0741d6410e19347 +878, 0x77567253b48ea919 +879, 0xa0b196d776905b46 +880, 0x81848e866c958c22 +881, 0x5defd26f7e313de1 +882, 0xebbf740f85d0a413 +883, 0xb43c6ca7dda9c7c3 +884, 0x3a38024f6076bce1 +885, 0xc9a4d739dd7a58d5 +886, 0x4a0036e594c30291 +887, 0xb67d467a13271850 +888, 0x26d4333f67ec5658 +889, 0x8683441959b6fca0 +890, 0xb4c3173d217788e1 +891, 0x3fca2876508b0037 +892, 0x4fd7ac0912a08d26 +893, 0x3990c299fd77d3cd +894, 0x388bfe456f0ee713 +895, 0xa17d56851d0aa9ad +896, 0xae6e173a38e92688 +897, 0xcae6f7387868f4c0 +898, 0x5deb567e87b682ed +899, 0x5bb2a3cbc6ad9aa7 +900, 0x4054518b25a4e546 +901, 0x8399534e3156fcc1 +902, 0x288ff48845b1cd34 +903, 0xc7d6f2e48f1799d0 +904, 0x968a3ed47b71e9c5 +905, 0xc06011209519bbee +906, 0xe2a80df93233bcf5 +907, 0x20b9afd489292293 +908, 0xf0ce32e84bdf040a +909, 0xbed405bc7fe1e795 +910, 0x86f7b1542f6b195e +911, 0xcbb6cb657318a436 +912, 0xcabf1276e3e6d85a +913, 0x42a331a4b5939d3c +914, 0x80cfa20e1ca1d0fa +915, 0x768bb2ab2504a2cb +916, 0x38a6f71b6865c85c +917, 0xdc4142ff4a656c94 +918, 0x91541ea1cece2095 +919, 0xbe03be2fc0073de0 +920, 0xe21d0d35ce487214 +921, 0x4681e310b4117bd7 +922, 0xf2253c6efd0ed606 +923, 0x702db3cd3ba7c127 +924, 0x8d3175ccb5e08f38 +925, 0xdafca1a22f02d177 +926, 0xb6fb797078eed6d6 +927, 0x10120f45ab02ea09 +928, 0xfd4cd6ff70fe60d6 +929, 0xaf70101012b33e44 +930, 0x6e4321ef1a47aed2 +931, 0x859676a49e1dca4f +932, 0x8065316b96ff29a0 +933, 0x44d05376ed2d0fdc +934, 0x7343def61d2425cc +935, 0x86113b555152aac5 +936, 0xba339a0e137c5ce6 +937, 0x1d2d89d9de5460d8 +938, 0x7ed9d48c61257119 +939, 0xcad2b91ab20da148 +940, 0x656377284c5e195c +941, 0x94e734e8a480a4a7 +942, 0x5bdacbc607ec7c4f +943, 0xec1241717db1ad5b +944, 0xe6eb7fbcf5b4b66b +945, 0x3512345a3554e6b6 +946, 0x58c77d926e9a528b +947, 0xf3e782be535f9b9 +948, 0x9d3b3a53ea1530a5 +949, 0x3df1eddab09a2ac2 +950, 0x86440868ee975e20 +951, 0x35e2f24867978c7 +952, 0xd3a6219dec1a447d +953, 0x4427eaeeb50643d3 +954, 0x1eac58507e33223e +955, 0x10fb299eab3112ac +956, 0xaa01a8b779062117 +957, 0x552c4559a7e5c22c +958, 0x2e10ac501d21242a +959, 0xbabf9866c8d7d061 +960, 0x94f03b79de712060 +961, 0x4a70ef01b76bf68e +962, 0xd1fcf4d2226ae986 +963, 0xcc53d27dcb2ab8bb +964, 0xe169d46e9a968cd2 +965, 0xdd3baeab560e1eb7 +966, 0x62e325462270d89 +967, 0x717dade9cf46c1ff +968, 0x229552ce0bb04970 +969, 0xa6ebda4d2eca3cbc +970, 0x80d3bd7426882137 +971, 0xfbc3243079309847 +972, 0x664f4a88f2c7bc55 +973, 0x750baa49d93df131 +974, 0x8f0a87416f41c64f +975, 0x5d01ca38b0484512 +976, 0x743fdfbdd79e82f3 +977, 0x69c3c2f9296fecaf +978, 0x3d945260849578e7 +979, 0x21aadd4d1956a540 +980, 0x17a2d7868afbf606 +981, 0xa945ff7af593e961 +982, 0x499c7abc8df892fc +983, 0x599c1a937b547e43 +984, 0xc6f0c1d6eec5cf12 +985, 0x425c576116b8bf5d +986, 0x5a9d64a33ba615a6 +987, 0x85f1341ef79fc27f +988, 0x75c151fd5787305a +989, 0xf56789cbc4c1a1ed +990, 0x1d547a0b47eab748 +991, 0xccc539d7a777e60c +992, 0x39d3177b7f18e15e +993, 0x9d9911afa8441757 +994, 0xe163b0cae65e074c +995, 0xb75ff4c843626bed +996, 0x696089f87bf020b5 +997, 0x78c5c7971b74ce1e +998, 0x2ed5aa6e489c3684 +999, 0xaf1b049e483011c3 diff --git a/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv b/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv new file mode 100644 index 000000000000..b688fcb2a551 --- /dev/null +++ b/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x99ec5f36cb75f2b4 +1, 0xbf6e1f784956452a +2, 0x1a5f849d4933e6e0 +3, 0x6aa594f1262d2d2c +4, 0xbba5ad4a1f842e59 +5, 0xffef8375d9ebcaca +6, 0x6c160deed2f54c98 +7, 0x8920ad648fc30a3f +8, 0xdb032c0ba7539731 +9, 0xeb3a475a3e749a3d +10, 0x1d42993fa43f2a54 +11, 0x11361bf526a14bb5 +12, 0x1b4f07a5ab3d8e9c +13, 0xa7a3257f6986db7f +14, 0x7efdaa95605dfc9c +15, 0x4bde97c0a78eaab8 +16, 0xb455eac43518666c +17, 0x304dbf6c06730690 +18, 0x8cbe7776598a798c +19, 0xecbdf7ffcd727e5 +20, 0x4ff52157533fe270 +21, 0x7e61475b87242f2e +22, 0x52558c68a9316824 +23, 0xa0bd00c592471176 +24, 0xfc9b83a3a0c63b9e +25, 0x4d786c0f0a8b88ef +26, 0xa52473c4f62f2338 +27, 0xe9dc0037db25d6d9 +28, 0xfce5eba9d25094c3 +29, 0xe3dbe61ee2d64b51 +30, 0x23f62e432b1272df +31, 0x4ac7443a342c4913 +32, 0xc31cf1a9658c1991 +33, 0x290c97ffce918b1d +34, 0xf54455e02e90636a +35, 0xf57745758bb8f33f +36, 0xe5e1b685122823d9 +37, 0x2c16cde0fd8097ec +38, 0x3cdebc44a5bc1936 +39, 0x6833bafa723c2dbd +40, 0xb6fa6c4ba1d3d39e +41, 0xe5b932b656c2edc3 +42, 0x9cf0b6121615c9f +43, 0x214e25d57fc636d5 +44, 0xcf3d1721806e2537 +45, 0xcf796fc6335ddc02 +46, 0x353c8b86489b0322 +47, 0xfc4865822547b6aa +48, 0xe8c93d84ee8b3f8c +49, 0xd1b42120a323f2d6 +50, 0xa73a11d247ff36b2 +51, 0xae42236958bba58c +52, 0xb622679e2affcf3a +53, 0xcc3bab0060f645f4 +54, 0x2e01e45c78f0daa7 +55, 0x8566c5f16be948a +56, 0x73beac2187e1f640 +57, 0x8e903d752c1b5d6e +58, 0x5b34681094d7511d +59, 0x70ebad382047f5c1 +60, 0xeae5ca1448d4e9cc +61, 0x3d2d62775b631bd5 +62, 0x8cb72ebc5b4f7dc3 +63, 0x99c2939ea690a80 +64, 0xf9d3061a3006c84b +65, 0xd0872c394d734a5f +66, 0xbf768c2fb70d5c2a +67, 0x9b5a7e27e4c57259 +68, 0x8e00b050a0489404 +69, 0x72ae4545fe9d40f3 +70, 0x2bdcc8dcb50cf5a +71, 0x7b20239fe07cd664 +72, 0x37b037a8ea138f13 +73, 0xa52f51f9e9cd65b0 +74, 0x5ee0b72fd581557a +75, 0x527ebb9ac92c6fa7 +76, 0xb64f03fc892955da +77, 0x972c4feb529a9045 +78, 0xa5ee146b2461a795 +79, 0xaaef1049a5bb9b07 +80, 0xbcf5f38ab6cfe9 +81, 0x16398fd1538acdd +82, 0x8a0744fd7315cae2 +83, 0xa4bf1e39de6657a6 +84, 0x685247449d0de2ef +85, 0xa48d5c8c364fb1dd +86, 0x7fbcaafb1f2b65b5 +87, 0x96f0967f55ddec48 +88, 0x30d43cfe4a788a1a +89, 0xf7b15bed8038c711 +90, 0x8db82a6db9261a2a +91, 0x94eb6a77a00e5b2e +92, 0x3e19490dbfd221a4 +93, 0x9644e15b5d0a6b54 +94, 0xe235ca3fdaeca1a7 +95, 0x2db8e0001ea7c79e +96, 0x1d82fb1d7674fc75 +97, 0x65039b3b4805404d +98, 0xd73a9fc3e975791b +99, 0x3cb72d021fba219c +100, 0x134f43cf382ea87a +101, 0x32806c8d66cf621f +102, 0xaaddf99cd62686db +103, 0x1b3e5fe6476a54d8 +104, 0xd0a2a5e803c27068 +105, 0xacfb9437a3b64c17 +106, 0x514a55b2ce7f4982 +107, 0xe0b9ee39938c909 +108, 0x66d449a98f1052d2 +109, 0x639a3b248f7b37e8 +110, 0xf0ef1ed4a65619a5 +111, 0xf010ee5ad7e74a11 +112, 0x3fbfb63d884eca59 +113, 0xdbed473e4efad8bb +114, 0x49c9bb8f88e373e4 +115, 0x251f496458b6360c +116, 0xd91a4850fddb72cb +117, 0x610f58fad3c217c1 +118, 0xbcb05e51100ad235 +119, 0xdebf8d6ccb4a94db +120, 0x297499be7e8fe7cb +121, 0xade854104ecd6600 +122, 0xe8924c68f96b97ba +123, 0xea4332df583b4cdf +124, 0x3c5950e1726a6684 +125, 0xe78baf12ad096b30 +126, 0x130e9517756e2908 +127, 0x2519a50a14a2bdaa +128, 0x548b96fa23c310bb +129, 0x689bea6fcb7a7b18 +130, 0xe500c168143be7b8 +131, 0x6615695d45714ed3 +132, 0xf58a87a6e82fcbdf +133, 0x77d9730cc4ebf311 +134, 0x9b3a449299c50530 +135, 0xfb5d93b0b60f022b +136, 0x31bb49a47b615ca7 +137, 0x5be9713f591556b +138, 0xec54b51a1185183c +139, 0x4dca5482711b4718 +140, 0x4cbe1b130e66cc8d +141, 0xe5ab874359671f11 +142, 0xadb342dee0eaaae5 +143, 0x7a9f5af1a3e89a24 +144, 0x83656d5ed37512b6 +145, 0xced3c2b8c231d286 +146, 0x575139132aafc520 +147, 0x2fc986b84ae150d0 +148, 0xf1e782d83e9bc699 +149, 0x1855c5fab454eb48 +150, 0x8c397cc4dfbdac0 +151, 0xca53a1df39daca62 +152, 0x8df17bc285c6c2d4 +153, 0xcc409e9c492ef29e +154, 0xc6609bf8eaeaf753 +155, 0x4f0e6d330e6647cc +156, 0x32a255fd34f2b58f +157, 0x26352ca3cc29b31d +158, 0x695c88b11a7e549c +159, 0xd91ec977523e201a +160, 0xd8e5a42958325ba0 +161, 0x481223fcbeec1f35 +162, 0x601cfbb9aad67313 +163, 0xfdcac7d3cb1091ef +164, 0x7fdc76c0a076d6fd +165, 0x394266448a75927c +166, 0x63243918d6fc4774 +167, 0x6ccfae907e52cc2e +168, 0xd4ce6176046ae4a2 +169, 0xa9818d710c31aa3 +170, 0xb8e803b82ca561b9 +171, 0x620b905a8425a1cd +172, 0x2443dea6bd2bd617 +173, 0x447fd94cd80faf23 +174, 0xd4f30e2a5c7767f2 +175, 0x11298de19077eccf +176, 0x35154fb0148fa69a +177, 0xed42b9c24ebc4d19 +178, 0x422724f98f4c3a1b +179, 0xd81cc933854afa52 +180, 0x54e2a03657411d03 +181, 0x8f12d5fcccdafb4a +182, 0xd91ebb398426414b +183, 0xb5555a96d9221341 +184, 0x6073189316d5f1f +185, 0x8a488d8d9c40366a +186, 0x109f57d19c71381a +187, 0x4e043cb3d78b4fdb +188, 0xa541464ecc30b27d +189, 0x15c2bf30d64900 +190, 0xa65cd77083ee4f66 +191, 0x1b98efd8729f2197 +192, 0xe954f9556e7cd0db +193, 0xb775e8ed94ede03b +194, 0xc3ef1f33db52eb8a +195, 0x21eec6afc3a045bc +196, 0x3d09338405d07ee1 +197, 0x501d08ca80daedff +198, 0x855f69bea1e262cc +199, 0xc88e6c97b5071d6c +200, 0xad42750a0f79e135 +201, 0x19171caa21061657 +202, 0xa337869a65c8d18f +203, 0xfb0cfae4b3cd24a3 +204, 0x43140ea8817faf71 +205, 0x895807fdf0d19712 +206, 0xb0c14c560e178c2d +207, 0xc47b4af3c3bb4789 +208, 0x60cafedf6696b7a2 +209, 0xf658b394f9697989 +210, 0x45d29b40a0ca3f86 +211, 0xb881cbe06cf6c2e3 +212, 0x2f045611c5d42ecf +213, 0xf011ca853c07b2a6 +214, 0xe078befb5dffff49 +215, 0xc2d1b7728fbc0ef7 +216, 0xb3ee6d8225161ee6 +217, 0x82e51268e2c152e0 +218, 0x6d79b320e5c33a15 +219, 0x1be56b3144ecab7c +220, 0x8e341dd781b3dffc +221, 0x50310327c0b03198 +222, 0x22ab06d620970b0e +223, 0x6b542de2f5625eb +224, 0xaacc9d5de070b881 +225, 0x21581365a4307e9c +226, 0x1a09b3443a155c66 +227, 0x2941d8614648c4cc +228, 0xbc4175b682a7f884 +229, 0x9cc92ed166c9cf23 +230, 0xc765ebe7eb3911b2 +231, 0x2d169ff7cc4369ee +232, 0xa3070da6835f0a0c +233, 0x827d253009c5d376 +234, 0xf23489deaf0450f2 +235, 0xc5e5b1ba6d4550ec +236, 0xa42ce77e33e206a3 +237, 0xc096f2576edc6a17 +238, 0xc4fa32113d4200d +239, 0x9bf6baf90bdf4ac +240, 0x47dc4d9bb5714a26 +241, 0xd58f0327551e948e +242, 0x9b1926b404a93ae9 +243, 0x6034442c56b4a50f +244, 0xe29e9c6881a89f9b +245, 0x79e49c426f3d4f3f +246, 0x75ba2077148ff864 +247, 0xf5dec8c46426e9c3 +248, 0x6affed5e72eacc9e +249, 0x1e4dcd0029679920 +250, 0x6470439685e44054 +251, 0xb156aa42e8413254 +252, 0xf6529f57a03df828 +253, 0xd706ceb3bd1c5f22 +254, 0xf8a3b615eaf44c9f +255, 0xfb33215a60fc88a +256, 0x53b93d040f72e76f +257, 0x4f67360a5c6ed447 +258, 0x600e87c4cbe6910f +259, 0x729ea44a3706a389 +260, 0x924cbabe379237ec +261, 0x618aeada6735f6cf +262, 0x12b4a8b32ecefaef +263, 0x7b129ddb43b182c +264, 0xd5466dc1e1de15cb +265, 0xc2e35a196a6e1efc +266, 0x8cdbacc1fc81c786 +267, 0x28b96b91b1ca9672 +268, 0x10e2a0174fc6f81c +269, 0x35ae5c9a74f2e2d8 +270, 0xc18f6c052b7f28e4 +271, 0x4f0abb08fa0bc2d1 +272, 0x84ab0e1b7c7cd062 +273, 0x29dca86fd5f5927d +274, 0x50fb63fccba90590 +275, 0xb7a60466af0de98c +276, 0x47baf40463bbd343 +277, 0xc72942184061bb8a +278, 0x2d55077237a2ce6e +279, 0x2f6b743bc35768e7 +280, 0x96975e80bfd6f74e +281, 0x77f334f2537aba60 +282, 0x8364264d2947b429 +283, 0x7e62c258f591189f +284, 0xe1a0962ad2d4f7ea +285, 0xf7a81d56b651d434 +286, 0xcbb9abcb6ec96876 +287, 0x7028c3ceffdccec1 +288, 0xa0049e182130928a +289, 0x79dab180c238f06a +290, 0x1eb3c704ecfa28db +291, 0xf9db38cf45524135 +292, 0xbf8f3bccec0609a3 +293, 0x5f0f2a25bb3ed38e +294, 0xe365cff62ec9287f +295, 0x9f5481118acd2a76 +296, 0x99296bb12e697f0a +297, 0x76aaf656bbbf9067 +298, 0x7d81ce20bb4461cb +299, 0xefb436add3cace0f +300, 0xf3ba4a29ed722849 +301, 0xc4cde39ff82317d +302, 0xad2bc44d417453af +303, 0xb36a704f170f7edd +304, 0xcdf268d6b5e2b5fb +305, 0x91aed4730adf51f2 +306, 0xeb2a37825e8a3de +307, 0xe79d586186766a28 +308, 0xc8bc6d8a5660356c +309, 0xafeeee51b23f4a5e +310, 0xfea1ecb5f9b17114 +311, 0xf0882ad449c3a225 +312, 0x8c0d387e9b4bbd68 +313, 0x39f2c8fdbdd00e8f +314, 0x830705f2260c2ef2 +315, 0x9bff6be123cc50bf +316, 0x99e33829b97434e4 +317, 0x6059a38e8957661f +318, 0xa77e6d06957108cf +319, 0x1e719fd3e756823 +320, 0x4564dd6be166e176 +321, 0x6f6a8c540e054563 +322, 0xc800237b21dc0e2c +323, 0xc6c3f2586f8d3062 +324, 0x85c469664e405a28 +325, 0xf5771300e8da6169 +326, 0x5f79c23a5e6807e2 +327, 0x593bbb0ce26b72b1 +328, 0x7e2e976e8309dff5 +329, 0xa543c50aecd30c5e +330, 0x7b71758289d403bc +331, 0x4a01dbff8cf37014 +332, 0xf1dee5472a53176f +333, 0xd82c78d69f2bef7a +334, 0xb63903647ded6604 +335, 0xe695634a32b0d1fe +336, 0xf89cec17a9792c77 +337, 0xcbb131921e8fad4d +338, 0x9425521c6c62076d +339, 0x18fa2dc92d99a3bc +340, 0x5d84f4a98055086f +341, 0xcaa5980ecaba579 +342, 0x2fd8a209612e2b2 +343, 0x1be8b333fae80866 +344, 0x99cd4808ba7c60f1 +345, 0x107242d94ac9d491 +346, 0x873838793d69cb0d +347, 0xce87b21b6eeea0a5 +348, 0x6831420da8fb877c +349, 0x1f51fe6670631366 +350, 0x9c093d89ef323dda +351, 0x3384d45cc9aec1b9 +352, 0x144970e9a0e6f741 +353, 0x3d8deffd6db78721 +354, 0x272f876c2821800a +355, 0x66eede1f8eb0bba9 +356, 0x6b85a48c6fd8dfac +357, 0xdeed765c9682da9 +358, 0x5956688ac942fe9c +359, 0x408147c1fe103dba +360, 0x8a5545b07bd7d483 +361, 0x2c8379adb00ea5c2 +362, 0xb9f96c9acd18c563 +363, 0x18e6e515e8c11ad3 +364, 0xf4c78395a36665f3 +365, 0x9319b999d50f42f6 +366, 0x1d9e89e8d5e22c8e +367, 0x7df15c14581535d2 +368, 0x214e3cf405b8b36f +369, 0xe11a168e3a824980 +370, 0x74998ef104966497 +371, 0xd6fc353bdca37cef +372, 0x48a55220b4fa6e1a +373, 0xbe2c7cfc7c08dc03 +374, 0x26c837223b6cfd46 +375, 0x22163b501aed055d +376, 0x946537d01e261110 +377, 0x39b4c0b78a79402c +378, 0xa68b2d66140ef79e +379, 0x8dc84a722b56fd9d +380, 0x6f32f10229bd5c83 +381, 0x722074979bca28dc +382, 0xd942d9911e43d52 +383, 0xf720ad0e5adada4a +384, 0x69fe38d6baa562de +385, 0x29a7488cb00fbc49 +386, 0x4d40dbe4a23b6c94 +387, 0x6bb39808bbae9d62 +388, 0x8b80231a7369e915 +389, 0x14bf8e755f80b050 +390, 0xf19bb00604d00336 +391, 0x552db8387eea31a7 +392, 0xe9ec067b59dd95e4 +393, 0x3d71f663886c520 +394, 0x97bb54095cd331e4 +395, 0xea3e829f0695cfc7 +396, 0xa93188e41583162f +397, 0xeeaabd3e3df2f07c +398, 0x291f70992ab1c5b5 +399, 0x55183a8b5857a080 +400, 0x7df148caba2c4978 +401, 0x84f178764bffc05e +402, 0x5acea77fb3139b5e +403, 0xcf57693ff3aa5f39 +404, 0xa0867abf8c89ce6 +405, 0x597f8192569e2971 +406, 0xf90a8e47c1271e18 +407, 0xbe5346e3fd0c12a4 +408, 0x524aeaa307d4b03b +409, 0xef3d68937d8270c8 +410, 0x3e73d03007156d55 +411, 0x94cc96dfeb586897 +412, 0x14e7a22da35e8923 +413, 0xca6ecc61d3cea9bd +414, 0x6044eca5a760cfb6 +415, 0xf4ed4f4f21933f13 +416, 0x99b923d7f9925de3 +417, 0x394b054ab147ae41 +418, 0x9afb74bbca1dcec6 +419, 0x830b9ee9e52b9234 +420, 0x83712e27c87cc4c6 +421, 0x7f025017de598df8 +422, 0xb3ea4ab92495a788 +423, 0x602a7c66750a2047 +424, 0xa15ca212f5002047 +425, 0x8aa5d8a19b1b7efb +426, 0x2852eaeb46dd9d21 +427, 0x605f261b8b77d3ee +428, 0xeb27c54d4359e1fc +429, 0x77e4aa530fbb27c8 +430, 0xaf06ddf2d74745bc +431, 0xe88964e4b8d79ede +432, 0x2192553c0ce6a4d4 +433, 0x90997c5c0cf3b6ae +434, 0x1153fc6436d48bb2 +435, 0x1703c60eb24cf506 +436, 0x116d8f4e35d51cbc +437, 0x5045a10f0131f6d0 +438, 0x1fbb76ef3c622e03 +439, 0x7d33bb57dcf79365 +440, 0x1ef362b02c379673 +441, 0xdf7a4a6801ca903a +442, 0xc784df93dcbb07f1 +443, 0xbc566896f2d86db9 +444, 0x72a169884d76aa42 +445, 0xcb65ab4ad4c8a6ba +446, 0xd810c9a3ee62ed3d +447, 0x7652322c4f6520d6 +448, 0x3ad4dc2bd6e4c8dd +449, 0xb2269d6e73a22c6c +450, 0xcbfdf90c34925001 +451, 0x2bb66613fbf8044 +452, 0xae9c53e815bc69d1 +453, 0x452d886b5a7407ae +454, 0xa7f3f05dfb111951 +455, 0xbe05cb088f4dc330 +456, 0x9b740a460b6ed662 +457, 0xd77a324b60f8c74 +458, 0x60ae94f69dce3f29 +459, 0xd04859db7833712a +460, 0xb90030c4a70c588a +461, 0x25dd21f6ac7df8d7 +462, 0x162154fcf4832a15 +463, 0x15947a2bbf844bae +464, 0xa20559f3a662a753 +465, 0x6dce918dd48cad0b +466, 0x32c5a086331216f4 +467, 0x3a683208ae4f86c4 +468, 0x1ecc2982d1720167 +469, 0x2b3017d572f5c7e7 +470, 0xd7861e549dc1fdcf +471, 0xcead2c572db0b00d +472, 0xbbb4afca7e873a92 +473, 0xada92286d14a0d26 +474, 0x7af00766c03cfd0d +475, 0x2353443fbef8f013 +476, 0x35291d9ea26217d9 +477, 0x9d907261f3f7ea54 +478, 0x6f11649f6c3b69fd +479, 0x36d9e3bf31b6b209 +480, 0x5f420540094e6bb9 +481, 0x980dc001315d9d33 +482, 0x1e6023baca982809 +483, 0x28441f8357769aa6 +484, 0x4acebf5fd0e84d43 +485, 0x9991e19a0f1ffddb +486, 0xea4f7c944b325d2a +487, 0x9e44a24cb37572c8 +488, 0x2949063600779260 +489, 0x313e58e1433ffa40 +490, 0x6eea07e56604152e +491, 0x47dee53a41fe61c7 +492, 0x21e6dc482e5df531 +493, 0x4c43131087191e79 +494, 0xb378e632ee28fb31 +495, 0xc1b106afa1c14816 +496, 0xba150956e0c630bb +497, 0xc5b64d8037dbaab6 +498, 0x47325510456ecc3 +499, 0x61a6f425ff2b555 +500, 0xabb9fcb3865a8ce0 +501, 0x7eaf52f3aa10b66f +502, 0xd91cf6b8600c7115 +503, 0x18eb54dcfb1b20fe +504, 0xc8911ada29a3162e +505, 0x6cb29138cb1ac68a +506, 0x4d0e9884ade85482 +507, 0x4cad40d37b3ec8f7 +508, 0x9467d7a7b34753a6 +509, 0x45f84f5e5a26175a +510, 0xd8753f7613d5ce77 +511, 0x86d400a246e8d128 +512, 0xcb8946c9f2c10785 +513, 0x89cb7c5c5ab35ff3 +514, 0x7bb60eaebc69a3ad +515, 0x534f554712b34d6a +516, 0x5667fa5c9b731343 +517, 0xeadb76ebcdeb49b +518, 0x3485b0afe8caa42e +519, 0xc78c543b4603f643 +520, 0xa8f3fc1217b9b77c +521, 0x44ff6333a229924d +522, 0x426e31b858cfcbd1 +523, 0xed5964b45b66718c +524, 0xac18d6cbcbca89ee +525, 0xc78a8bf4beffcb0e +526, 0xbd0d95b77da79de9 +527, 0xac7b69c368ad88ff +528, 0xbb729daeb9f32b7d +529, 0x6d5dcb59284675b +530, 0x4aa9af065367853c +531, 0x40de557a4730f8dc +532, 0x6b35765ddcb83237 +533, 0x7c4cdacf0801f9aa +534, 0xcd723c55ccc75d2f +535, 0x86c67f52807c3f64 +536, 0xc597a5d9141cf5eb +537, 0x6c50d3307da89da9 +538, 0xb2e259cf10ef27ff +539, 0xcf6862f7235a11e3 +540, 0xb60e07d1d6190673 +541, 0x69de7facea0c2233 +542, 0x19e548a3950a2d1b +543, 0x6028bcf0501a1d75 +544, 0xbe060ad84380878a +545, 0x425f528fa11f5584 +546, 0xeb64fdc71b8a0369 +547, 0xdb1d4fd9af7fc48 +548, 0xc32ea3df9267e071 +549, 0x9f0b4d409a6b7db6 +550, 0xe8e1ccce740c6369 +551, 0x8d0939433ef9c005 +552, 0x7b1a1969142d70f7 +553, 0xbe055803167b4dd9 +554, 0x3d525b7f29e2a20f +555, 0x2b58ca2bf659dfcc +556, 0x1884346d743d5753 +557, 0x3e5e6a992abcc639 +558, 0x334bed0210a5a1b9 +559, 0x545bd4a1c6a6ea3a +560, 0xdc1d84e28f8b4ff0 +561, 0xf3608d9fea1e61d +562, 0x639fadfda3d29b81 +563, 0x1a4195ffb607cd4d +564, 0x823bdad2efff1975 +565, 0x5fe15698d33ad156 +566, 0x961e7fcba86b8dfa +567, 0x9b7536cd3c368430 +568, 0xf9b9c01121a82eaf +569, 0xa3f39bdf6f8668f4 +570, 0x100ae93ca508d02e +571, 0x88de050245f0f9b2 +572, 0x4ca1e3a7fce0a942 +573, 0xce0366d47e60adce +574, 0x3f00fa3b552ef6c4 +575, 0x718ca18c97de55ec +576, 0x2705ca3caa5f047b +577, 0x8e9a4530bbabc87e +578, 0x57f73f76c2365c1f +579, 0x5783c7e50c89e813 +580, 0xeb0899277d5a0925 +581, 0xdc28a57fafb04818 +582, 0x7cc97832d2b3509e +583, 0xe937c3407bc84cdb +584, 0xaa2714014f14802f +585, 0xaa0b844baf434250 +586, 0x98f6097049cb2931 +587, 0x65d93055db2280e2 +588, 0x401e59aa74e005c4 +589, 0x8540018c086c5678 +590, 0x1ebd2b7c3093183a +591, 0xb015ff173910186c +592, 0x628d0a7cdcb5ee78 +593, 0xe6bcce512cb94fba +594, 0xf2112d66f4ad825e +595, 0x143ca3c833cc6119 +596, 0x141f17377db25eda +597, 0x2b5abd96ffa1cbff +598, 0xffbc3baec2fce0ae +599, 0xfb7ef6be757ecaf +600, 0xdec0e0b34488795e +601, 0x4b0cb9bfd1759241 +602, 0xc1ec90140a15b4e +603, 0xfc16386442e70156 +604, 0xe3f12f2adf688d91 +605, 0xd53b2d7bea9c8380 +606, 0x81cc446202a2ed5c +607, 0xe70e3ad34c0b8ea7 +608, 0x5f33526009e7fab2 +609, 0x6e33d20305b8c75c +610, 0xd6d534dd9461ac91 +611, 0x40cf8974d7c931ef +612, 0xb051886f44a85f34 +613, 0xbee99cf63e9e4ec6 +614, 0x80d5c210e7e8f3b5 +615, 0x182817a277213ba5 +616, 0xb57e1fcc3fa01e29 +617, 0x21ef9e484821c685 +618, 0x40e0bdb94b52f6b8 +619, 0x3993c9973c999499 +620, 0x324fe4cdacd0c7f8 +621, 0x2f276173f8434ce3 +622, 0x16f1f99b426e931 +623, 0xed2148eb554f6965 +624, 0x2f164f3156c8ab9a +625, 0x8fa66f8b7bdd6fbb +626, 0xa7facbbc6906343e +627, 0x4903fc405e661d8f +628, 0xd5e01a117658e004 +629, 0x327b0a3517b49e0d +630, 0xaa7f3a3a33033899 +631, 0x8e978760d337249e +632, 0xe4706aca37516d8b +633, 0xd3cb6f75b94f094f +634, 0xd2b9ab9715999627 +635, 0x807694f77b219f34 +636, 0x33b79cb95dc4bc0c +637, 0xc50b1dd63a993db +638, 0xfee37af82faaec9b +639, 0x9fdacc70effcef2a +640, 0x1bf998ee028c7d6 +641, 0xfbdff299a6531fef +642, 0xa108675116536b22 +643, 0x1527b4dc58905dce +644, 0xa7707694303577ce +645, 0x9b13fbc46e340e5e +646, 0xd020c010ec0baa5b +647, 0x384c228b30f40579 +648, 0xdc323bc7fdd5453b +649, 0x4011efb021d86d0e +650, 0x73540e72fd3d5c1a +651, 0x9584873c3d070ab8 +652, 0x5b49b14248e8bf2a +653, 0x9ac40d57d39d5919 +654, 0xe0c05768df113539 +655, 0x139cd4f88a7574b7 +656, 0xb9b32474195fd2cc +657, 0x77da8950d9fb2c98 +658, 0xdff0beffbdaa4b7 +659, 0x7d7c9554dc45fa9c +660, 0x105c2efbf8116c04 +661, 0xe62b22435244a315 +662, 0x59a1e2fe06fd3544 +663, 0x328af98625a31053 +664, 0x7e03a7ec81d1a078 +665, 0x94fe2cf6653e116c +666, 0x333fc9ecf8a43b6c +667, 0xb3828218cd24f83a +668, 0x9c3fd7d848f20cb1 +669, 0x92ce295ca15436f4 +670, 0x6f088c41b55b1c1 +671, 0x57392e60bd643a69 +672, 0x6e02f429d6a11733 +673, 0x2ebecbf5bd43e0ca +674, 0x8dd7afdc5552894 +675, 0x2114803fc6503fcd +676, 0x38b1873ed0ca3e65 +677, 0xf32c628f60a36bf5 +678, 0x8552202e20fb7342 +679, 0x4741fe855aa0336 +680, 0xca4d638854de9454 +681, 0x183078fda5d360cd +682, 0x6ae60d39e68650d8 +683, 0xfd0a1e80aa46b9f0 +684, 0xdc14a1d6b0901901 +685, 0xe54df01d09b44bb8 +686, 0x309de938e8d717bb +687, 0xa5a2a2e49b9c36fb +688, 0xb38be8c575c56063 +689, 0x770e5929cffdf3e2 +690, 0xcee13e2c47cf9f56 +691, 0xdfc2db4af23da4a8 +692, 0xe1c7dcefa31d46ba +693, 0x350e999c00e252cc +694, 0xaaffdb6ca58b7dfc +695, 0x313d23d88402948e +696, 0xc3ac1498a730309 +697, 0x69350ea02740c143 +698, 0xec0d5c624376e45b +699, 0x9b49e00d551bea96 +700, 0xe6427840614e80e2 +701, 0xea27953175e05f6d +702, 0xa2861b02743e8d50 +703, 0x35b2fbf59ddfe5ca +704, 0xf25726ec3bdfbdd9 +705, 0x71aa4383b0aa4630 +706, 0x4cf3f7708d98f205 +707, 0xa6e0108f77f1318 +708, 0xcaf0b81e3222bd69 +709, 0x6b18e84e511d1b43 +710, 0x2a53e20b2f706858 +711, 0xe14599cf85db7644 +712, 0xb7a31525aecbbf69 +713, 0xfce7e9b5211df2e9 +714, 0x3f71617fc291625a +715, 0x6164e5c8ede33272 +716, 0x43a0878da9fba4f3 +717, 0x491992fb5ce344d3 +718, 0x204b93918277c357 +719, 0x31189377f32f958c +720, 0xa8522eef63ec4e04 +721, 0x52cb2d449d63dae1 +722, 0xd3ab20f38e44122f +723, 0x9738796a2cf5f72e +724, 0x61335538636be0f2 +725, 0x4dbd8fd3e18d9368 +726, 0xc4d395b525170e36 +727, 0x363d2b24bcb72ea3 +728, 0xfcedc59fa0ac0b2f +729, 0xa00cfc5984f4c62b +730, 0xaf0ca1028edd76ba +731, 0x4fdf988297f27aec +732, 0x891a876ecfe4a5d +733, 0xb638f6971c14c255 +734, 0xff63c7ca4d499307 +735, 0x1ea43f18f530449 +736, 0xdbed5a3109ff48e6 +737, 0x2b01c0495e6edab7 +738, 0x87c1b49da18fb9b8 +739, 0x79356a301557c23e +740, 0x3d83db604937cb9 +741, 0xda4471e873ed75ae +742, 0x7a9bff590c3ea65a +743, 0x63ed127445a08bec +744, 0xaa232e05b3fda15f +745, 0x643873aa525504f4 +746, 0xfa708f34ec5c9692 +747, 0x4817b5bfefae32b7 +748, 0x5c7c79edec1297bf +749, 0xf06513dfd2d4a290 +750, 0x7f0cd3ca9c36631d +751, 0xdebf1b00e7838d3a +752, 0xe46004c03a6468 +753, 0x6b1ee341cf3319c5 +754, 0x765793cd734155d8 +755, 0xddc037ee2976777b +756, 0x7d30119e994c6d06 +757, 0x372937236b1f1f03 +758, 0xbb2aa1c9ed2b0dc0 +759, 0xd0962de2eab2b6d7 +760, 0x7f80047fbd8ee81 +761, 0xab546293b8136f47 +762, 0x71b74ffd91794bc +763, 0x3fc7c2e20a88d11b +764, 0xedbbba9528be628c +765, 0x4c29f32b97788b8 +766, 0xe721ed4b5dfb4aac +767, 0xf1877d8e4eb87386 +768, 0xf399f60aa3ffdcab +769, 0x73c7f48a0571873d +770, 0x89a1c8b247a63fc1 +771, 0xb3f3a37f25f0eb9f +772, 0x24dc12bfb6030b32 +773, 0xd070cbfd0e221c15 +774, 0x47dd6c8f9e3ec6c5 +775, 0x18b5e8a79e8c2717 +776, 0x46762bb85de44be0 +777, 0x4aed493495d044dd +778, 0xc70422a4f09c5594 +779, 0x128787d3470d0a3a +780, 0xf6a925f9e15a22a5 +781, 0x86e93253485db4a4 +782, 0x5023f2e2dd23e974 +783, 0xbdb6aa877c3fdde +784, 0xa0e3237b79a5b74c +785, 0x1eb41a88cfb42b8a +786, 0x49a511f7a0a022a8 +787, 0x85596ed41f1986ac +788, 0x5e572dac0265d4c4 +789, 0xf573b46d65cac12c +790, 0x33427b16cca1ac0f +791, 0x8d4d024f8bde011c +792, 0x91dddd48b91c52da +793, 0xbc5b67a1104d4c2e +794, 0x104e90822e17122a +795, 0x8be8c4e394ce3a1f +796, 0x581426b9c905f36b +797, 0x2666efb9cac21f5d +798, 0xbf8d3e5f295060d1 +799, 0xa04598c9d6e237dc +800, 0xa9fbf5516c7b8911 +801, 0x4c6ec7e0401140f6 +802, 0xb50cc45e1895ff0b +803, 0x453c3801b4bbf75d +804, 0xde80964dde83a7ad +805, 0x1e17250043629e63 +806, 0x84d3aac71f95b6e2 +807, 0x38176666a55a3fd3 +808, 0x6433ac841c48a95e +809, 0x5ba64539f33f48a +810, 0x48e5e074f832729 +811, 0x3d1fb01607adc32e +812, 0x63b22681ceb343af +813, 0x868b07d09e57b86b +814, 0xf98212b744a71fca +815, 0x797843f3fd5e0ef5 +816, 0x6355bb33b59c84e3 +817, 0x6a6a1203c7944f31 +818, 0x177a4be397cbf761 +819, 0xea8fb29d82135b94 +820, 0x689c505eed27c67f +821, 0x50cf765dcfd4e619 +822, 0x948e20aaaeb69e93 +823, 0x660761db84df481c +824, 0xac2c2e1ebaa60049 +825, 0x81f9a054209afa66 +826, 0x66ba9ec387a82b65 +827, 0xfd602aca17e4932b +828, 0xa4aac8d6b22f5705 +829, 0x994f7b582d826f84 +830, 0x9312d16bbe890581 +831, 0x3079b18f5f44e9bc +832, 0x8ef5489a07ee6327 +833, 0x6c9f0fc8ecd29e94 +834, 0x7c603b09eafe66a3 +835, 0xc084c72299ff49c9 +836, 0x10459931d6387460 +837, 0x97908e3a98efa125 +838, 0xd7c84c45ecc2531f +839, 0x90c7eb8b1c222f5f +840, 0x74781389c601e45c +841, 0x176e7351d5f5489a +842, 0xa8d555a9197d890d +843, 0xdf3035da9ec119a7 +844, 0xf2cfdd14cc4b7db6 +845, 0x70aed924a5a1fdc0 +846, 0x4b993be0711bc5f2 +847, 0xb712037cce51b6fd +848, 0x97ca679baabf594f +849, 0xde014850ea7b8e93 +850, 0x39be8272136c2a28 +851, 0xdd6ce923c7574ba2 +852, 0xb999537b19fc106e +853, 0x3e421eaf2d0ae00c +854, 0x3ee73eab1c009f68 +855, 0xb6c3187e644c0ec6 +856, 0x32375e8c4fd12e29 +857, 0xacc6dde27d3ab697 +858, 0xd0c6da152a9d13dc +859, 0x2d93991d56d475b1 +860, 0x91f676a136ea942e +861, 0xdba3c630477ef627 +862, 0x9832442c2743f71d +863, 0x327f4b8d08f42ad6 +864, 0xb11d32b9aa369c95 +865, 0x8f3b53aa390b4e05 +866, 0xdd2b5c796526856 +867, 0x5f4a6d26e7266e74 +868, 0x92fc04aa4519deb5 +869, 0xaf5d104350902604 +870, 0xe92ee9d9eb83d48e +871, 0x92e49c24b74d10c1 +872, 0xbbcb775e1df3dd9f +873, 0xa778bc4153b74d87 +874, 0x2c5cb1cb460778d +875, 0x204b96da5ca032a3 +876, 0xf8ed00512b2c8054 +877, 0xecea085421d30bd5 +878, 0x9b9b2f6891954ee0 +879, 0x210f39a3b60388e2 +880, 0x71cf1d4f49716e96 +881, 0x831f11200be69b03 +882, 0x47cf8470f8e9f115 +883, 0xb0b9621c996452dd +884, 0xf5511dede5b32628 +885, 0xd48b9e4296cd4180 +886, 0x6ab70c3334f11aa1 +887, 0x4ebd26c8decac629 +888, 0x71aefa349216bbb9 +889, 0x37a5967b8b366498 +890, 0xc825ba8bb37e04d0 +891, 0x3411fa5b43243230 +892, 0x32ce54ba8dd0106e +893, 0xa8a0446814fa43f4 +894, 0x9905b5e6d05924df +895, 0xb226af8b15ce9a5b +896, 0x594bed79eed4e4d4 +897, 0xeb6c283c67b0eb18 +898, 0xde5cb33d3dc1d629 +899, 0x1b57482ededa779e +900, 0x1d07de9f3796453e +901, 0x3d1b093a3b2f673f +902, 0x7138dfb52b1e19f9 +903, 0xefd791255568c006 +904, 0x5e9f6ea3fd02d382 +905, 0xada1ec576dedd60c +906, 0x894f3cd4d0463181 +907, 0xf8e46d0e8c179157 +908, 0x53234c91c74681f +909, 0x458491d26dc655b6 +910, 0x2dce3244020c6219 +911, 0x6815f50060ce3a58 +912, 0x13ec2d1c70067d9d +913, 0xe252832edd6cf225 +914, 0xd6656ac22edd7a1e +915, 0x818d3bb5d04315a8 +916, 0x36c302529a73033f +917, 0x1a9c6b44ccefb355 +918, 0x99e5dac400256022 +919, 0xdcf849ba5115f17c +920, 0xdf9c1238c38b6ad8 +921, 0xf7d9422477cc5cf8 +922, 0x6e3ccc5e484db3f0 +923, 0xf9f5dc3936d5ce41 +924, 0x4e42a060e0fc7c13 +925, 0x9789adf2f7e0b250 +926, 0xd12a569e95979840 +927, 0x14b652c51eadd0c8 +928, 0x2d8d9baea2c7a8ab +929, 0x9589291913c9345e +930, 0xc3e994adc95fa2ed +931, 0x30ef4019e04f22c2 +932, 0xae4d6ac24e6a42fa +933, 0x14bf6dd1873be03f +934, 0x48e3731b4088a6df +935, 0x66b6f14a28de0cb6 +936, 0x825b0e7560fd526d +937, 0x334b0c5989386158 +938, 0x5a4a0353e701405a +939, 0x11844bcfdda17e36 +940, 0x737420216b683159 +941, 0xcdfda9150023d465 +942, 0x3ccb1da83154f7d1 +943, 0xca0ed9ba34067fd7 +944, 0x5ca93550b1ccb1ef +945, 0xd52bf628b920563 +946, 0x239147f7b5d9e31 +947, 0x70457bc990dade04 +948, 0xec5a8e4749adada3 +949, 0xd1aed177de970226 +950, 0x537d06d8885531c1 +951, 0x4f83c7fc8e711e0f +952, 0x412b2d578e62a0ab +953, 0xcce8d0bc4f4d4e57 +954, 0xabd3b7802f2d051d +955, 0x76721bb6d8b97e0 +956, 0x217c77ff302ff9f1 +957, 0x19ea31efebc3350f +958, 0xf4a3f147857e5cb9 +959, 0xe802bf7f519cd61a +960, 0x1c8d02dba97d6e3d +961, 0x78bfb57b9bb0518e +962, 0x8a48af98c6df1ca5 +963, 0xdfac5ac680503f7 +964, 0x4a9e3e96d9ea260 +965, 0x5f1931c9a7dff2a2 +966, 0xc1968e6cbed5f888 +967, 0x8eb493f97aad3ec4 +968, 0x90f2abe998c8ef87 +969, 0xc6aba12513cfbb3e +970, 0x2c0ed550f9c796f +971, 0x444fa35f7d9fe383 +972, 0xb5f04f695ecab10 +973, 0x3385d267df3349fe +974, 0x4c70e55fa2bbbeca +975, 0xd10dec43a2c0bf05 +976, 0x1ca77c39862fc552 +977, 0x9cbd688dfab24fc4 +978, 0xb7fd22171296a3d1 +979, 0x1183b02b50271be2 +980, 0x883a7e16e7e0a424 +981, 0x10d83194ac141f1a +982, 0xebe3d57aed64b429 +983, 0x50b227d667b4cab7 +984, 0x5ea269feb856345d +985, 0xb7b31144fa8d0f75 +986, 0xb2a4ee8f1fe24113 +987, 0xe630bafdf1401749 +988, 0x2a5fa38d1f97c355 +989, 0x26ce612a57a75fc8 +990, 0x657f3a8955ebe69f +991, 0x6ce0b006f4ee7ad5 +992, 0xb2394f5046b31e22 +993, 0xe778365c658b2739 +994, 0x98fd9744990f5bc7 +995, 0x46218fb884bca27 +996, 0xe1b5e671a5fa3f4a +997, 0xcde973df241f948d +998, 0xa797c49a69f2eaee +999, 0x7aac8c483a2edd2f diff --git a/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv b/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv new file mode 100644 index 000000000000..78fb903ee274 --- /dev/null +++ b/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x876912846bc23b4b +1, 0xc392a0d7b1e2ce1d +2, 0xd280aa92dbaf6c20 +3, 0x9a545c48769bcb4 +4, 0xba901708334ed1da +5, 0x5d5c05bee6575bba +6, 0xdd35b1a2950ba097 +7, 0xa683f4f912b2de7b +8, 0x9bc8ba4aaf061f16 +9, 0x592c9c1eb898e661 +10, 0xd4c45a31e8d0ea2e +11, 0xd0f486ff8d15aa20 +12, 0x9f476a2094cf2e20 +13, 0x5dfeca30beb341f2 +14, 0xd148d9f7909fce1b +15, 0x77dee98756ef7ccb +16, 0xadc9df01bd7ca503 +17, 0x3d3395384db35e21 +18, 0xedb29f73f3497e33 +19, 0xe8064a9d95ad523 +20, 0xf371e0481aaac707 +21, 0x20ceb788ef6cc7b0 +22, 0x322843da066393d1 +23, 0xff5b70b598091031 +24, 0xbf92dd18de3e50b0 +25, 0x34c53c75dfb462e9 +26, 0x862b38ba34e2074c +27, 0x71d7fccd15ff2980 +28, 0x57659fb10e0a2e70 +29, 0x504aff6ae76bca79 +30, 0x241e0010547d002a +31, 0x6887bf03dd4578e +32, 0x3b74f448c5b5503e +33, 0x893c36f91ae88b29 +34, 0xc997f52382a03491 +35, 0x64d70ecd46d0d3d4 +36, 0x7391b3e2b46ab3b +37, 0xad0cb7eb249d1562 +38, 0xad8c488df7a6abd8 +39, 0x821201a7bfd18bfb +40, 0x13281b52ed3db7ca +41, 0x5fb74a1925cdbbad +42, 0xa0a82244150ebae7 +43, 0x33a699202c3e9777 +44, 0xaffd2aad50ab609a +45, 0xd0b2cf8e469a6ca1 +46, 0x9642269993d293a4 +47, 0x4726480893b8003d +48, 0x43927da186b7c458 +49, 0x48bea40a5f99f533 +50, 0xe378848ac37e2376 +51, 0xf9b1f0de5818b090 +52, 0x963368da3e372d75 +53, 0x94d760894d8d59fe +54, 0xed6a9730e9f9d10a +55, 0x78c870cc88e05f99 +56, 0xe4b4445bb8ec2548 +57, 0xf2d2c9524d47c49d +58, 0x3e326b4eb1e18a59 +59, 0xc9ed2185d3b07552 +60, 0x37312e94b1a19e86 +61, 0xe2e44446e72437ae +62, 0x3e5541807ba68504 +63, 0x64fc4a8e251ba4a0 +64, 0x95cae7337b2cef03 +65, 0x4ffc22e6cee5a43a +66, 0xd1220fcfcd2b91c3 +67, 0x951e666e2b35250f +68, 0x49a6bf7293bfeb76 +69, 0x2f572a06be223951 +70, 0xa6ef2f83e4ab699c +71, 0x3c779b06245bef11 +72, 0x7ca2068971303e22 +73, 0x99181930c623a0b +74, 0x23870cb8e351237b +75, 0x4b3b096b31c0970 +76, 0x34567d210e095de +77, 0xad2d302293c080b6 +78, 0x2b9912fc65270b03 +79, 0x9d83c41c4a03c97d +80, 0xe595f5a6818c6843 +81, 0xf4de1eaa641abd16 +82, 0x2fd5d26fa4e8fda +83, 0x20228869fa37cafe +84, 0x2f5aaadbc5ed7917 +85, 0xc5a5411d976295d1 +86, 0x50860eb0a32883e2 +87, 0x9671e47f29c3fde5 +88, 0xb405167f98de3d42 +89, 0xeb9e4ab5b6277a34 +90, 0x30cb8055425283f5 +91, 0xd16fd04051825def +92, 0x9dad7dc043f76efd +93, 0x4efb0d073fa86b85 +94, 0x41f9a8f57a4c5441 +95, 0x261b340edbdfc85d +96, 0xe1770e8f6417f4b8 +97, 0xcda740ac5492b7cb +98, 0x421852a55f5fbd17 +99, 0x6b5e600ff816480e +100, 0x6f810e2bc14ef783 +101, 0x3ac30d12dbe74179 +102, 0x6e6f55e8da77d1c +103, 0xb3c1b3198ba1edd +104, 0xd42a70884e0b4885 +105, 0xe5b8554e1a265456 +106, 0x984728fa61cde5e8 +107, 0x22a8631dea8491ab +108, 0x7dde04d2623c5280 +109, 0x56ca5fa13744f021 +110, 0xa07c4dccd62318c0 +111, 0x7643fbf3cb825b82 +112, 0xb514293ac755d9ab +113, 0x976a42d4d7d5603f +114, 0xc89c841ed969a429 +115, 0xd3b58bd283d84deb +116, 0x48b0cb54ef4045de +117, 0x2aac0bed41855b31 +118, 0x84f602d6f7e8f8bb +119, 0xffb8359b5c955803 +120, 0x50a030999c6b5a41 +121, 0xf5affea03223e801 +122, 0x480fca3d8b71f253 +123, 0x78f46d086436f38d +124, 0xe55f321bb366b5c5 +125, 0x6a62bdcf97975049 +126, 0x4ba1b23acb2b30a4 +127, 0xaa8fab62162096ff +128, 0x9df7f50611bbbe05 +129, 0x8c41f29908880a54 +130, 0x5ca1036a33aef749 +131, 0x749341c5a1836f3e +132, 0x20d782c11d500c36 +133, 0x2aa089b1c26c888d +134, 0xb20781d123d61f05 +135, 0x786a566307a0e29e +136, 0xd7098641e929f68b +137, 0x8ef02287eec14ac5 +138, 0x9e3aba8329a8901f +139, 0x60f1e7d84742be3f +140, 0xc5292e6425256ab7 +141, 0xdcbf5736a8f911fe +142, 0x52ad9d372e4bd44b +143, 0xffebb934b4bfe199 +144, 0x7b5914f9b9052873 +145, 0xab29298e00ae9e7b +146, 0x3f02c3b7c59d121f +147, 0xdfa607db43e83fd5 +148, 0x1d8b966bd15e43cd +149, 0x25505363d4cf3ea6 +150, 0xc7f96d3a547efd4f +151, 0xa76458b01561c500 +152, 0x88760cde8e7f1522 +153, 0x67fe6b33586a089a +154, 0x5f0cc55ccd9dcbad +155, 0xaf32ec846865364f +156, 0x8f475ab26161ac5f +157, 0x92f00c5e55d0f3fd +158, 0x70488866e54bd9fc +159, 0xa2579ad851925266 +160, 0x1f2d66d6ab9a6467 +161, 0x18f0e12487296a55 +162, 0xca46bd4045b88b1e +163, 0xa48926a8c9ae6ddb +164, 0x70cf4b02a878020 +165, 0x3c827fe43ccf6e84 +166, 0x7b90b8b99390d7fe +167, 0x239e42fba10e8dfa +168, 0xdd950d180b5554c9 +169, 0xc219887acba392dc +170, 0xfb0cea050c6b5cfc +171, 0xa0235db93ab17388 +172, 0xce4e9a6697f39fa4 +173, 0xa77bc206c26b62aa +174, 0x6c4c0d77659b8d3a +175, 0xccf68dae535cdfce +176, 0xb774203a9c3697ec +177, 0x8f9603ede62970e0 +178, 0x73466a6c08f5c621 +179, 0xe4acd501298142da +180, 0xc1dc6d50d19ce4d0 +181, 0xf4d7157f3385da90 +182, 0xb03a1668d58ccc1e +183, 0x6c1ec730cdc15ff2 +184, 0x22b33428cf6f7b6e +185, 0x86771ba36131beb7 +186, 0x5c6f1dfb5df9a773 +187, 0x83d0e480faf79e2f +188, 0xb574e4f020a5c2f2 +189, 0x1037336e206cdac5 +190, 0xd358d3bd2f84dc07 +191, 0xe4ab7d65f5359d88 +192, 0x575e10beab6ed90d +193, 0x92b392d9011fec7a +194, 0x3743566cd03a5632 +195, 0xd84d08e20ab24432 +196, 0x264edbb98ea18981 +197, 0xb02ec336d3439df8 +198, 0x98dca28ef3481cd0 +199, 0x4c7b36c3d5a92ee8 +200, 0xea3a5d8c0656562a +201, 0x84df1e0b04e16ffb +202, 0x4033a0901c5b99b2 +203, 0xd655e52a52f95806 +204, 0x877a6c6e491f65c2 +205, 0xc7c0476aa3b57914 +206, 0xdaeb947a7ea2bffd +207, 0x9f353a9a44bb3542 +208, 0x4c6149547cb86c21 +209, 0x476f38042f81f574 +210, 0x73ae5842de15b837 +211, 0x56d08498c32a3ca1 +212, 0x3a29bd1e56c4a455 +213, 0xd4a039af15c94e2a +214, 0xd7e99d87726f6b7d +215, 0x11c8799497348055 +216, 0xf301a2a414f75291 +217, 0x61ef21e4369a33b5 +218, 0xbfebae360aed836f +219, 0x77b268e02299116e +220, 0x1d97ecb5b5ff1390 +221, 0x8931baa8bbac229 +222, 0x3e0a9cd01623e25e +223, 0x241849e522393124 +224, 0x4cac9db644404e9f +225, 0xf1b301aaaf6ee36f +226, 0xc6f3b0e23ed765f +227, 0xa721a93561fdb2fb +228, 0xec5d2fe7bdd570b6 +229, 0xaac87fcd59a92a17 +230, 0x21f96034df83ca3e +231, 0x39168b96c29637b2 +232, 0x2285e7b1962b20c4 +233, 0xe05877c5e64e80a0 +234, 0xa6e5e068434197b8 +235, 0x9953d6ba338c81ce +236, 0xc44dc6a3db952698 +237, 0xfa5494d4815d3152 +238, 0x467f7c752a541c4b +239, 0xb1a4872d1fbb6953 +240, 0x53fd30ae98ca00d7 +241, 0xc70a548b87054598 +242, 0x9d8a20c63463d5ea +243, 0x4cecb6becf778a54 +244, 0x887087ebdaca7461 +245, 0x6d518861d1cbc12 +246, 0xb8e717a809a31912 +247, 0x2d36ba962e509fe4 +248, 0x9bf46721bb113d5f +249, 0x2269b9c4c443667a +250, 0x979d9b4e6a4036c4 +251, 0x97543e06d384fa7e +252, 0x75ad7d2c23b6b570 +253, 0x43de810a5ea78624 +254, 0x80927c6293498a84 +255, 0x45a8ad9bb8f0dc2b +256, 0xabc320ec65a09cd5 +257, 0xcad9c0647042cd93 +258, 0xe84acb1bd3f3c9a0 +259, 0x76879458f63a57b9 +260, 0x49832792c9e03bc2 +261, 0x363459686faf7f24 +262, 0x1953702db3bc481e +263, 0x7fe6ba3b5a71fc59 +264, 0x1b17d2f961567f8b +265, 0x4ad033e1a4976f6e +266, 0xfcc0a6a6ba63fe49 +267, 0x841ac723afca1b63 +268, 0x6c1e91e669a97e7b +269, 0x5bd742d77c4ffc4d +270, 0x2a4ee5d86d2c240 +271, 0xe6d74f8546c38065 +272, 0x8bf207da18d16f8a +273, 0x9d1c2a99dce927c +274, 0xcba190db5ac2bc23 +275, 0xbabffcd557568ce9 +276, 0xa299e5d76f753e2f +277, 0x1d9b7854688000dc +278, 0xb77578a80be855c5 +279, 0xed5ca1b150fe57ee +280, 0x45ee175cab6988fc +281, 0x909e1e69be99cc5a +282, 0xeb19bad3b280f6eb +283, 0x183e05016ba8278b +284, 0x353ac3c6b09909cd +285, 0x52acc5f973291d01 +286, 0xf34bf118d4119a02 +287, 0x9374f1c812dd0b4d +288, 0x3cde5e29ca458381 +289, 0xa273cf101a664a2c +290, 0x3853d177648e274 +291, 0xd56392bd92a668f7 +292, 0x1a1668b6f658e0df +293, 0xcf91598b7f111669 +294, 0x9de820277a8591ab +295, 0x13e814a02eae1592 +296, 0xc6327921c4c8e137 +297, 0x4552a0478447893e +298, 0x90599b2c47bd6a68 +299, 0x6c6e379db4c5bd45 +300, 0xaddd155f6abe63fb +301, 0x16db9bcfefb79d09 +302, 0xadca159b2d4590c +303, 0xea280435e2e8ce04 +304, 0x267dde359f765411 +305, 0xc864e3d28e62e7f4 +306, 0xe1fb3b84699cb288 +307, 0x736e511cbe0a901b +308, 0x8ab9371873aa48d0 +309, 0xee14f5d0455642dc +310, 0xf46227f274aa445e +311, 0xf2ffe9298c22aaa8 +312, 0xb252d7080d3d64e5 +313, 0xf028d588f8bf09a3 +314, 0x51cf0c448bceb8a1 +315, 0x78d514cb6eb97a24 +316, 0xd35f14eeb72a2a52 +317, 0x2517e47da9fc019b +318, 0xa489556e41ab02a4 +319, 0x656545c76c5c5ad4 +320, 0x492cb4aead67db01 +321, 0xe67564b20bcd1500 +322, 0x52902e9ddd3736ff +323, 0x5fce2d6101c2d2f4 +324, 0xd6f3518a5c17b71f +325, 0xcea602751388c642 +326, 0x7c457e009571d1cb +327, 0x227cfe2d67db803d +328, 0xe6ba583bae3ce6ed +329, 0xbfede024874e2353 +330, 0x9d3f741ad2fb1c3a +331, 0xc92d955fdc49e35b +332, 0xe69f6bd427cb55c9 +333, 0x25154cf96eca70f2 +334, 0x8ada45f19fb5f353 +335, 0xc53b729eceb66699 +336, 0xad1ffe3b331399d2 +337, 0x26fa10d0ebb11981 +338, 0x4421bf4042ab1aff +339, 0xa33e3522a639e3f9 +340, 0xb27e6a340f2ae673 +341, 0xfbc848389681b76e +342, 0x87c9b594466133f1 +343, 0x5599811888d255be +344, 0xd125be5eadf51857 +345, 0xcfeddf66c3515e41 +346, 0x4e0e7d52bf2d41e7 +347, 0x7350bd89ecaa448b +348, 0x757b947295bb2315 +349, 0x9f75502e97420690 +350, 0xe507886c40a0d5d4 +351, 0xffb51fce9b6dc784 +352, 0x99c25bc884a07f13 +353, 0xae344dc6a0b5166d +354, 0x6e40f70fd2ae8839 +355, 0x549899226f83a618 +356, 0x183534a08628f76d +357, 0x13dbc72806e9cd8a +358, 0xc451b9a7f19a7148 +359, 0xf3ddd00aa2b77694 +360, 0xbbbf6a41f2637562 +361, 0x915549fda9129f5f +362, 0x6fb5452e819db506 +363, 0xc5122da2374c0ca6 +364, 0x9f418bff6eca6a59 +365, 0xad3988d59c836956 +366, 0xea3a5d086c5fe4d3 +367, 0x11a982723a4fa262 +368, 0x7f8bc4b1e17c14b2 +369, 0x4ce7986a6f72da2d +370, 0x41a50493a56271df +371, 0x477f24559f89ebfd +372, 0xc572ffc3e23521cb +373, 0xa9f628071811e1be +374, 0xcff02944927dc1bc +375, 0xd9f3bc4c212e939a +376, 0x21ffd91aafaf2c40 +377, 0x787f6ed5a2bab7b4 +378, 0x4609e004f9f4b1dc +379, 0x35ab1b27ca8c420e +380, 0xcca7c9a1b9c3b92b +381, 0xca101f017408e01a +382, 0x839abfc61cd0e8ef +383, 0x4c9cbb325badd3b7 +384, 0x5461826c9f315581 +385, 0xad20102aca3d9965 +386, 0xb649a32f64ab0793 +387, 0x725876dd5ff27c65 +388, 0xf2b14bbba3426942 +389, 0x5435afdbc2d685ae +390, 0x9c82ffffcdaabf8f +391, 0x20cdae1036653261 +392, 0x750c8fc5e91ea522 +393, 0x2360b1ebcd9d5b1c +394, 0x565e847ea6e9cacf +395, 0x8cfbc0c6bb12629b +396, 0xb26a10d6f12d2655 +397, 0xef86d9c5378690bb +398, 0xe23f3de5c1b799f6 +399, 0x31414ecd6ad5c5ef +400, 0x2921e71b83de7f45 +401, 0xebb98f34ab50544d +402, 0x6a412a4e053db405 +403, 0xddbfe7ee3e59a7d6 +404, 0xf05a0b36f67b9d5d +405, 0x849702c7806eb90 +406, 0x2203171eecce2095 +407, 0xb35c4db941a0ad7b +408, 0x9935496450296948 +409, 0x25f6a856fb1eb5d6 +410, 0x1dbb88d4fec8e2aa +411, 0xc60d3d3e39a26b96 +412, 0xf056684ba3a744d5 +413, 0x9572bd538afc7a32 +414, 0x254a093ab05dc0fa +415, 0xba6097f07c855fa9 +416, 0xf8b4dccfdb80e63e +417, 0xd2847b228bac28b +418, 0x8a8fab7c6031ab8c +419, 0xec08987d742c44bd +420, 0x133e3fff1c3c3412 +421, 0x6530ebd39d7b0f3 +422, 0xdeabc74a2373434f +423, 0x7815e18e47103e3d +424, 0xf9055ff370764f53 +425, 0x5a0d1345d2a9cc8f +426, 0x4de989802f34160a +427, 0x28a18124bdac81e5 +428, 0xeb45ab441afbb912 +429, 0x8f5a312fe7a0aadd +430, 0x7314071d14857900 +431, 0x6409cb66fa1e53ef +432, 0xfaf96ce7d2ac6c00 +433, 0x76e7a4baea8c663b +434, 0xb6e304f2a50a0321 +435, 0xa9ea300fd24f020 +436, 0xf35c396e30b7101 +437, 0x81c58595f98f6fbe +438, 0xc0a7e9607a117181 +439, 0xed09111f23a46ac4 +440, 0xb54c0bb2f0c1a3ae +441, 0x43467aba9df3e0a5 +442, 0xe8339c39a322db8c +443, 0x51c577fe5ec19d36 +444, 0x4f3b14d68f848502 +445, 0x686cd92e19b79dd4 +446, 0xdc741863e36fae80 +447, 0xd43d6b68d8b201e9 +448, 0x2c50554b76cef087 +449, 0x56c381d91bf8b46d +450, 0xd127daceb8ff95be +451, 0xd0ea2f226b20d165 +452, 0xdd905744fa9202c5 +453, 0xfe1a9600438aff20 +454, 0x5d1abb8492e2e820 +455, 0x8e39cb8cc6fa2c06 +456, 0x9f1dd3396c6629c9 +457, 0x9d03c31afb79a214 +458, 0x22010d4e60bdda86 +459, 0x80ed07d705582e63 +460, 0x4f62b3e2e44b8571 +461, 0x101943c84597f33c +462, 0x4b4345de91b98294 +463, 0xc2ac56211ca6ee2c +464, 0x3cb95b436ece64d3 +465, 0x7a44a3c791671dcc +466, 0xc8bf29ce122b9d18 +467, 0x7943b142841bea04 +468, 0xfa2cc19a05924ff4 +469, 0xf9ad7238096bedb9 +470, 0xe63a166ab147220a +471, 0x6290dc36e53827e3 +472, 0xb21625ceb1014816 +473, 0xc4e932b9872d1e1f +474, 0xb1acf7e2a966bbb5 +475, 0xb9acdda48ec54590 +476, 0x336d528109c184a7 +477, 0x11316b2094f4d127 +478, 0x9e336afa73ba2faa +479, 0xd01fbf09ceeb6b24 +480, 0xcf97f3d08a634c2 +481, 0x72366953156c6a32 +482, 0x6db4bfd8113532e5 +483, 0x420d662640c9c82d +484, 0xef483fc8418f98b8 +485, 0x8f94c007d9e7d764 +486, 0xa920478806e51718 +487, 0xd4ff1f37c4402973 +488, 0xddbc1ff65d2e4944 +489, 0x1e358eaa42485b6a +490, 0x56cb2d0f9bab7e7 +491, 0x78965a1fc3ca2f1e +492, 0xb674cef0c1fd959e +493, 0xabba2d9a65e8a159 +494, 0x2c831ed46e02e9e6 +495, 0x96813fe5b0baca53 +496, 0x344cad935e02fc84 +497, 0xfb6e6b235ddf773c +498, 0x29947186532b0ac +499, 0x39446d366a46f449 +500, 0x270064563611ed55 +501, 0x9134963540c148bf +502, 0x46e72242d92ace70 +503, 0xbb588070df8c323 +504, 0x7656b60e47229e4b +505, 0xa1515367c8182e88 +506, 0x67194c7e83f0be6a +507, 0x8019b59794f3ec41 +508, 0x9346f2071da5e890 +509, 0xbf2968158965aa88 +510, 0x23234e9079cc8067 +511, 0x52480f9037e18c77 +512, 0x28849338ded11a2c +513, 0xdee551c607d5934a +514, 0x7378da20ad9165f4 +515, 0x8c913ef9e355a530 +516, 0xe2fe80181a74edd +517, 0xf1c99e6c3b0ca5b9 +518, 0x9ed9759b0ec64466 +519, 0x651dfcfc1fefa43a +520, 0x36d83fe0802969c1 +521, 0x288a70061165d01d +522, 0x5b9ff38ba4551eb8 +523, 0xb14b82c0d9052f6 +524, 0xa4af53cf1da019e8 +525, 0x562782be5655f97d +526, 0x87f92290b4f40131 +527, 0xe18168d9d140e801 +528, 0xbdacd598ad865c11 +529, 0xc0f4fe27f0884385 +530, 0xc034cd89bb7f0f42 +531, 0x3591756fece4a5fe +532, 0x1a73abbcbdbbc237 +533, 0x9af0782b54c0527b +534, 0xee5e13f65e7b76d5 +535, 0x16b7de36f37d2dc2 +536, 0xda6e3700f7987cf7 +537, 0x88b1a7a50bb8d03c +538, 0x73e0f21f7e240cec +539, 0xaf3de5598cd8ae24 +540, 0xb48ac453d9a452b8 +541, 0x67c7769e42377756 +542, 0x29d1c81c990639c4 +543, 0x5315f99dcc1926aa +544, 0x25e2df9a59623d48 +545, 0x17088168b2d6335d +546, 0x48929f9995cf0b8d +547, 0x9c80ce435ecb9b7d +548, 0xa6dbed42aca888a0 +549, 0x95d7ce284511406 +550, 0xc98a600e73fdf6b +551, 0x144dacadb5dcae70 +552, 0xf1c57aef0ced3fd0 +553, 0x4d7e9370bf5326e1 +554, 0x60eaec9ceddb9bbc +555, 0x40b99b3647bdec5d +556, 0x23451cd70ba654dd +557, 0x9e1e45a64320a108 +558, 0x572b629749dd059c +559, 0x370b84536cf92fbf +560, 0xa53c15e1b8e6930a +561, 0xff01f2d42f396a5 +562, 0xe4ce127c2371d1f4 +563, 0x964b007fd911f9d8 +564, 0xe8ad752ca4201d78 +565, 0xec150ec1bcea7899 +566, 0x3a98196d39a146e0 +567, 0xa13a6d24b065154d +568, 0x208f8f86fce0ffb7 +569, 0x48f3f5a286b8e61 +570, 0x231fc95324da4f0 +571, 0x4a912cc8c1145073 +572, 0xf55643f746f7c8 +573, 0x981b50355641f3aa +574, 0xf5cd5ca76785adf5 +575, 0x26809313bad9613e +576, 0x8b3bc2cbe2257a8a +577, 0xe7190ca66630f33d +578, 0xd678cb7a88ceea26 +579, 0xa82e3b2a968f54a1 +580, 0x9f495544f523a642 +581, 0x542ea223014d5724 +582, 0x976e7bc0aec4f3db +583, 0x6a4936ec50a7744f +584, 0x30ee4d2e234675bf +585, 0x7668a3489b46baab +586, 0x69b5bfddb0c219ce +587, 0x6cdf31a1621b4ee5 +588, 0xd47c5fa7524889e8 +589, 0x5ea77c458ed6b908 +590, 0x9f46aeb5373d4f5a +591, 0x2436d30afa02fb0f +592, 0xf75b5b183a82b399 +593, 0x2a0d4f653d5fb2b +594, 0xbaa369f3cee66a53 +595, 0x3b86f73fe2f8a1e3 +596, 0x6d7bb0961e1fd2c7 +597, 0xe0ea2803b75bb089 +598, 0xdad50e588726a5ed +599, 0xaad4c6349ef8c9bd +600, 0xac89692a9d19027f +601, 0x9128ccf4627bc207 +602, 0x84d06846beb2e304 +603, 0x7e8f78333abbc3d3 +604, 0x3f60914f5bd7e556 +605, 0x1d1304a8114ca709 +606, 0x140e3ae0d71cd49 +607, 0xd11427f5452fd9b4 +608, 0xf5ab3e8a0298f3be +609, 0x6b9e13c2d33aac45 +610, 0x855e2a9d17dca5af +611, 0x1578bc2441980cb9 +612, 0xb6d79ee20056c9a2 +613, 0x8becbe9a399154b5 +614, 0x7dcbfacd30d88c84 +615, 0xd9d2e48917b7010c +616, 0xfc72160892a21efd +617, 0xc7034a2a63410f42 +618, 0xbfdfa5eaeac7f80d +619, 0x89ced96a0e78f3c0 +620, 0x8afc51dfec588d2f +621, 0x6cd965499ebd9c86 +622, 0x86ca64414acae86b +623, 0x235defd7163050fa +624, 0x8350429671c8a0c5 +625, 0x86242291e8c4ad95 +626, 0x479275615cc7ab91 +627, 0xa6f410c0e2a26b2e +628, 0x3855e7ac300d255a +629, 0x46db9d9dc4109474 +630, 0x4ea0b44c4fe5b658 +631, 0x5433d83c0590d49e +632, 0x326ad33d53e5cb0 +633, 0x2ad4e88d8b8f4865 +634, 0xc0b971ea67fc2c1b +635, 0xd4db06ac68087267 +636, 0x35375c34999616ca +637, 0x7f313fa01760e4fc +638, 0x1f8b7ae8938e7d90 +639, 0x68aedc55512291e3 +640, 0x71e13848edee765a +641, 0x83feb5bccb136a0 +642, 0xec115ea084398beb +643, 0xdecd12d25159994a +644, 0x6ef3f928b79e1d15 +645, 0xc910824824961e9b +646, 0x6e56798f305fba9d +647, 0x9f2a78709ae8321a +648, 0x83673dba510e8329 +649, 0x38ee325de51bee33 +650, 0x6dde848944ff5c19 +651, 0xe990435690783cd8 +652, 0x4ef2b8fdf3a31076 +653, 0xb35c280054e321d1 +654, 0x2d66f077be780ce5 +655, 0xf003d07f5e8d24f1 +656, 0x63286f306d80f9e7 +657, 0x749e66588e9d5bdb +658, 0xf296e9d13eb97fdc +659, 0x8cc6e45328cecc17 +660, 0x4b35bc27b7d27225 +661, 0xea1f0b0e7cb3f20b +662, 0xccddb348221b89a8 +663, 0x8a2b674dbe8732 +664, 0x90a2fe18fc860a2b +665, 0xee92bfccb4c6986 +666, 0x55bfc65eef023c41 +667, 0x61e082760147dced +668, 0x2cf7af28fb253ab7 +669, 0x58dec379fe82b794 +670, 0xfe6d8ec391ba7af0 +671, 0x3f96cf458d50cc0f +672, 0xb97a170ccb8094d7 +673, 0xca876f8a8ee27019 +674, 0xa03a1b9f8c2c3595 +675, 0x8ce5c48735932234 +676, 0x5bcbfeda6a7099dd +677, 0x32ffcf8fc39ebdda +678, 0x945d734289b83a9a +679, 0x8824610f5d088bdf +680, 0x9259056e8d773859 +681, 0xf4b40ae4f8ec9d59 +682, 0x78be6102d44b8198 +683, 0x7dce883504ae3027 +684, 0x3bcbac86d37993e +685, 0x334af10e3ce0cb50 +686, 0x12b3fe24d1df167c +687, 0xfa17184c24036cb +688, 0x200d27e144d9f60c +689, 0xcb1fd05755672423 +690, 0xd5ad76956dced3a5 +691, 0x7e54849c6a87880d +692, 0x359af4d5828b1f79 +693, 0x26453ccc43829d09 +694, 0x871808b8e5cb05b9 +695, 0x955a1ebf98da9d59 +696, 0xf5893da12ea014e8 +697, 0xae43111b363eaf7b +698, 0xc6dddd603e4b5cca +699, 0xe1cc643e404fe108 +700, 0xfcbe2e95831db0bd +701, 0xdc01ec9e93e54c55 +702, 0x380c88bd4fa28495 +703, 0x8bd7bfd49c7d768 +704, 0x6489b7ae98113f23 +705, 0xce19f0dd365e3544 +706, 0xf5a58147d87d3083 +707, 0x81efbadc3c88a2f0 +708, 0xad91664c2e7da0b8 +709, 0x8b78dda657eb421b +710, 0x6e552452af7e258f +711, 0xb260660b01d6650d +712, 0x27a45a1cfbd98603 +713, 0xa8f620c73f0ffb4 +714, 0x7e43f2dd4c476ebc +715, 0x7d4e51c6a3614d8c +716, 0x3d5300002b65077d +717, 0xc24e7491fa70d4db +718, 0xf2bcd733a1d21f0c +719, 0x8d5bb04c5273eab8 +720, 0xf9cd01ba63f92da1 +721, 0x64d29462217baa90 +722, 0xcaa1fc3b19b00a05 +723, 0xc9fae87d7026e4ce +724, 0x40120cb2e2680cb6 +725, 0xcc83d069bdfa6caf +726, 0x6a11b1724a9404cf +727, 0x8c24bc538308e19b +728, 0x2be028ae22c66d3d +729, 0xae2a94a920547418 +730, 0xd0c9c729c0d0fdf9 +731, 0x79855e445226f087 +732, 0xa467118788c6ae21 +733, 0x18a67b3f737ac66c +734, 0x9f0422fbf1704575 +735, 0x3cb380445380b25f +736, 0xe16d37c484cd8232 +737, 0x39403a33ed4f833d +738, 0xfea5df032f093e41 +739, 0x47b5d65b30a245a2 +740, 0x5711e2c4cd1bbc2e +741, 0x4b17a868719ff611 +742, 0x12d79e4df14b55e1 +743, 0xb759adb60f0a5110 +744, 0xc495633b8df72a7a +745, 0xc0053b2671187190 +746, 0x8d3924968e71608f +747, 0x1523ade2927ac191 +748, 0x1cfcaf3b0bc57fa +749, 0xb91a7984235eaad3 +750, 0xfc5c6cb849eb3a5e +751, 0xe5d427fef5d314bb +752, 0xb714878d2c853b41 +753, 0xbaf47a81594ca957 +754, 0x3de6e218723fcbab +755, 0x30ee829bf38ab024 +756, 0xb374a5ca939b2a77 +757, 0x689ca34206e9d827 +758, 0x5b639ed104818c6e +759, 0xd4e8fb1ae2cba92a +760, 0x1e74a4554b198ff0 +761, 0x8554e6fe30612ac5 +762, 0xf8078efbafaf7941 +763, 0xb60b6cde7161bfbc +764, 0xe81e0e93e0dea073 +765, 0xac02d3f3b697c994 +766, 0xd10bab917e4348e4 +767, 0xe6fa834ca7e7aa0b +768, 0x6eba49968d0d5254 +769, 0x4a94152838ad62fa +770, 0xe8789cecbaad60cb +771, 0xa970ebd7a89905df +772, 0xe49e4d76fac277ef +773, 0xb8adb96bd78e0d22 +774, 0x3691be969b56ec80 +775, 0x566a22004cdf18be +776, 0xd4da2618b9171235 +777, 0x8dd6f2f32503d141 +778, 0xfe199681d91e5178 +779, 0xed5891007cf409eb +780, 0xd5d999f9d416f32c +781, 0xa5f9a414434cd178 +782, 0x3cd8de680cb84094 +783, 0x2c70c158a5f08368 +784, 0xfd4c6d304ad80f14 +785, 0x1b3555f90f0fa209 +786, 0xbfc5397a69a4335d +787, 0xe51459f0861790fc +788, 0x173d12cdb0c70d44 +789, 0x6c88b6cb9a439159 +790, 0x9e3d527583959951 +791, 0x8974610167fb3d0e +792, 0x8ddec067f7d91a2 +793, 0xda0a0394d476a41 +794, 0xb4bc6f905125bb13 +795, 0x26647355ce93705 +796, 0x6e77d00e7d59f697 +797, 0x8a52c90d219277f8 +798, 0x9a9d112119a2ca00 +799, 0x78a4507edbc0c338 +800, 0xc1a70ab377af5b48 +801, 0x36a1278bed1d15a4 +802, 0xf0f6fe034ce240bd +803, 0x3774f55f64722926 +804, 0x63e4e477803ed6bf +805, 0x2b631b9e6e3dff6d +806, 0xc4c2268f2eb0bf1a +807, 0xb0b910cedfb4eec2 +808, 0x491781f6e8f5078d +809, 0x2db574eaecd44693 +810, 0x397d8904141cb1b4 +811, 0x2848d2ad2a224e0f +812, 0x41f9fae31cf93d56 +813, 0x68bca8f51877387a +814, 0xb43114eb511ba30 +815, 0x6811c33595351f9b +816, 0xf7c9b154b26a6501 +817, 0xa35317f4e4369356 +818, 0x2bbb3809e211de1b +819, 0xbf95e8ce2588f5c5 +820, 0x951b4fc9a159b558 +821, 0xbedaf5970dad8ce2 +822, 0xd79d52c7fc92c15d +823, 0x2b1440cba83e0a6f +824, 0x968f7f07b4a36640 +825, 0xddb5d48949a8258e +826, 0xc679b204042b05f1 +827, 0x9d00c9fbd7edbeb4 +828, 0xafb601b2be4c9a97 +829, 0xc35a1adfe92039b1 +830, 0x4392c71aff19cdfb +831, 0x1ab34fdb1e3f94fa +832, 0xe8e3bad693ee9d2b +833, 0x78ae4836d1711383 +834, 0xcb764bcf9104bd66 +835, 0xcb80c3c2286af3b0 +836, 0x5c1d4bb3d36d0deb +837, 0xa2071886b21e6c32 +838, 0x137909746a058350 +839, 0xa2a196ae5a9845b6 +840, 0xc0776cc50ba681ee +841, 0x8101ae19ebcdf8cb +842, 0x253846a45a1bea0a +843, 0x945829fdcac6cc2a +844, 0x28dcc868b896b986 +845, 0x336d9114936baa1d +846, 0x4bdf4ed2bfd5d8ef +847, 0x7f43f8324a743507 +848, 0xb721732c35266109 +849, 0x5654184a7879a5a +850, 0x932e5c33053debc8 +851, 0x6c8a42cb4bb07c7e +852, 0x3e2853cb7367a326 +853, 0xf670fcefeaf352e0 +854, 0x2f0ed63118ecfeee +855, 0x22b32d6a6fcaaabc +856, 0xa8df4f57af993b14 +857, 0xc4fbcdfec94e25fc +858, 0x7855b5802cd2d6e6 +859, 0xd31ec992392792cf +860, 0x499b4022955ae602 +861, 0xb1d9df2a56d1d9b5 +862, 0x2be020670c2ba9ad +863, 0x4f51c9ac114691f6 +864, 0x43db97ee34cb6585 +865, 0xf7889fa1c3372662 +866, 0x7428ebb0889ce59a +867, 0xf69778b6c2a803b1 +868, 0x68c7f79994d68355 +869, 0x49b31b833c1fe002 +870, 0x14823830b7aa93f1 +871, 0xfa3fe89a5d2be21e +872, 0xd75217b26deb1860 +873, 0x5e49f031d805df72 +874, 0x9d3c204122e892db +875, 0xe4f71314f6bce3c +876, 0x2ac5f8fa64ab428f +877, 0x71a8ee18efa4b447 +878, 0x38170f177f7babce +879, 0x77cbc1adc5a7104e +880, 0x45b756a5c674ed37 +881, 0x3da29002dd3a1dfe +882, 0xcb645f42a1a2df5f +883, 0xb733e9942b4c7ed0 +884, 0xbe1c3292f348b4bf +885, 0x78d11d13c10c2099 +886, 0xf73fa04c2283e128 +887, 0x87e719305bc8ed51 +888, 0x6566b3860eed926 +889, 0xea271a89df9f7896 +890, 0xcace2b0b23f6e8f3 +891, 0x53e2280362cfc833 +892, 0x33ee7d314d33fa14 +893, 0xc033d8359b0de79e +894, 0xec1687b4cf771683 +895, 0x7e9971fdb5f45106 +896, 0xc9e3c5777bb561be +897, 0x17d1a55af8659714 +898, 0x312ba0a1f36f469b +899, 0x74c8f6caac97449 +900, 0x951c3d8e2f973859 +901, 0xff5de9a5079d8908 +902, 0x839fe3f7bc5dc4d9 +903, 0x5a21de4667516721 +904, 0x38ec459dc4da82f9 +905, 0x7a72aa7877678423 +906, 0x9839c4f3ff159ed2 +907, 0x338c7af893a226e4 +908, 0xe057270bd63d90e1 +909, 0x74382261608dab72 +910, 0xc62804f051b15437 +911, 0xd761a1ef0c5db73a +912, 0x496ab0869f08c505 +913, 0xc8b021a098da8e32 +914, 0x6dfe12239acc8048 +915, 0x2e7a263485f52b8f +916, 0xd5e9ddf81a37d37d +917, 0x5de50454fb933d95 +918, 0x431900d5526e3d9 +919, 0x77476c947d99e745 +920, 0x31827e1ae78d0df6 +921, 0xedd8155bcff2a247 +922, 0x1e850adc3c67d0fb +923, 0x661108b21735dd75 +924, 0x352812aa0035019 +925, 0xb927385f13660903 +926, 0x9a516de262c20354 +927, 0xef7bc11900eaff94 +928, 0xf57add7357601ba5 +929, 0x80e7a452cf0b3215 +930, 0xcf6f3fdfdd010a89 +931, 0xb06e98efb8c4cf8d +932, 0xdaa9088d73c8469a +933, 0x2932275de82cf904 +934, 0xae4fe81ef1f2ea6d +935, 0x8f55ad1c108ecd7b +936, 0x4d36deb616fe60d5 +937, 0x129d84b87e28cbfd +938, 0x3d9b18404e0d716c +939, 0x5576067b39672db7 +940, 0x7e57c5806e5bd926 +941, 0xdb86a738b0df1c15 +942, 0xc4263370c4ff9fdd +943, 0x57d5bba42942542 +944, 0x2b2be3e9fa816534 +945, 0x54c1ba10ca97f953 +946, 0xd89c1f14d9805c3b +947, 0xcdad0af12830e5d +948, 0xef8a4e05bb7939a0 +949, 0x10a02cfa077c64cd +950, 0x37dd082b003ba023 +951, 0xbd52decb5ba0259d +952, 0xf07939e0ac9edc13 +953, 0xf14dce84156215f9 +954, 0x4ff635c6efd4c0d1 +955, 0x8273d381b00d1da2 +956, 0x2fe4aee0a7dab542 +957, 0x79a485b897698801 +958, 0x8d3f9726bfdec8ce +959, 0x6daea7b39c0baf5a +960, 0x8508a8b168841669 +961, 0x4dec7955aa28c99c +962, 0x6bd02c3a6e4496aa +963, 0x2c13959a34e93763 +964, 0x1ccace54fdfeb05e +965, 0x34cad73846788c6f +966, 0xabb7d3e684c062bd +967, 0x69c236a70240069c +968, 0xa53398808da493b2 +969, 0x2b4cfa32cf2603f0 +970, 0x903cde2693c3b0f9 +971, 0x5d556925830a020b +972, 0x90a63eab0db9352f +973, 0x351c2d2838792525 +974, 0xe85ceb3486eefb16 +975, 0xfa275cecec8d524d +976, 0x9f1b20f0dd3ce0d7 +977, 0xceb1490022a7a9cd +978, 0x1e7b51c976ea3265 +979, 0x5fa85864c857568e +980, 0x1e7b06ae95db5660 +981, 0xfee282a9657ed8d6 +982, 0x1f2a6fde4761b6b5 +983, 0x1568cbeaba398cdf +984, 0xe185d2c2cef2cc9c +985, 0x2933556aa7be334d +986, 0xec1d06dc69a8a107 +987, 0xa9683634651f5552 +988, 0x8f448642e633fc86 +989, 0xa39ca103aaae4c10 +990, 0x11ca0212139029ff +991, 0xdea595418a51693d +992, 0x1b96d86565401fa7 +993, 0x9876432af1ab5f2a +994, 0xc9630e117c574a52 +995, 0xdc6b6eaa00873b8d +996, 0xd4456b90b2690f82 +997, 0x38374bbd586d9905 +998, 0x47c96bd123a5f3b4 +999, 0x72ef78391219eb11 diff --git a/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv b/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv new file mode 100644 index 000000000000..264308f1af4f --- /dev/null +++ b/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x99ec5f36cb75f2b4 +1, 0xbf6e1f784956452a +2, 0x3832e5e4541959a2 +3, 0x25715bafdf7a6b43 +4, 0x8b67fc19f1c8e17f +5, 0xe950e894acc448c1 +6, 0x940554d2c9b256b2 +7, 0xf9eadc87da09ac92 +8, 0x4bfa499f878ac962 +9, 0x383336b0082c3c49 +10, 0x2863cf13af79512e +11, 0x498c25ccc5953380 +12, 0xacde7669d72ac701 +13, 0xd8582a2fdda30a73 +14, 0xddae8a5a57c3302 +15, 0x39b75e8fb865dff5 +16, 0x6946963b565b2ba9 +17, 0xa67ec91e011a1aa3 +18, 0xf88116863cba9c94 +19, 0xc3a3c692211c54f8 +20, 0x62e1a84548f3272d +21, 0x48bfac565faea7dc +22, 0xe8ec2b5f2ee41403 +23, 0x9f4081dab8c56846 +24, 0x7cf256729df79a61 +25, 0xeede53016acd39f2 +26, 0xb37e90df69310b9c +27, 0x2975a99504c56251 +28, 0xdb9416723df2752b +29, 0xc189e2089a8ee16c +30, 0x39fb60f3d17db683 +31, 0x2b60dda991df7c61 +32, 0x5749b739403062bc +33, 0xbe7379e4398257e7 +34, 0x21adce8625781175 +35, 0xf9ca19cb6ff09a4a +36, 0x27689fd07f617a32 +37, 0x656290d3433d9077 +38, 0xc6fba3291a5d6372 +39, 0x8794d1a1bb955db7 +40, 0xc8b037815aab3077 +41, 0x23a02093b144d169 +42, 0x267ad8c80f9caad3 +43, 0x5970a90562008761 +44, 0x7419aa839b2828b6 +45, 0x52dc309a0dfe0f33 +46, 0x10564d319fe055b8 +47, 0xad925ebe373170b0 +48, 0xc38f00ef7258c162 +49, 0x19e6805cbf134b02 +50, 0xa3368cb52e0919a +51, 0xa543ded14e49d4b6 +52, 0x2cebe96c5f0a953 +53, 0xfd2f810919931d8d +54, 0x8181b29c373ad4cc +55, 0x5a03097378f059d6 +56, 0x8e9be6b21fec37b7 +57, 0x37bd0c6e705b5df2 +58, 0x8f1e22e2eb0a869e +59, 0x1abded820c714cf8 +60, 0xdfc917d8b2bed11 +61, 0xc8d119482cead771 +62, 0xee4b670743624ba5 +63, 0x55fbc8a194bf56e6 +64, 0xb21bc8ce5c709989 +65, 0x77abbb291a079826 +66, 0xabb7e9f7bd35d5be +67, 0x479866e6b1a66f15 +68, 0xec82d785eae5a82c +69, 0x2e5d3b0aa0158dc4 +70, 0x2fec4f8b5a8efbfe +71, 0x885293aa43f8645b +72, 0x816c016dc41f2dd7 +73, 0x832f06eae4dd19ed +74, 0xaabacaf4c7840bb7 +75, 0x84e0fd247b0b2412 +76, 0x4ecf02bbf93c2647 +77, 0x1ecf4e8fbab848f8 +78, 0xa7618244187427a +79, 0xc51c7d4d76a4b4e0 +80, 0x44b7b83127f6cb2 +81, 0x13e717ce99868f93 +82, 0x571466622b4e94e4 +83, 0x6086c22ca249714e +84, 0x15d182d77b18a109 +85, 0x2b5cbbf2e8092148 +86, 0x33b31ee2e36f9cdd +87, 0x5ba30dc0c04b381f +88, 0xf855a989b1146877 +89, 0x8f85aef1e22fcae8 +90, 0x7bb6f96d4b652fb7 +91, 0xf3a2e2b45a2619c9 +92, 0x49bcf25f4d6260a +93, 0x26640d4f8e246f16 +94, 0x3b3ca907ab2abb1a +95, 0x2f7a9a3d75f59615 +96, 0xdb63eb1c6172e7fb +97, 0x1569afee9f7a840d +98, 0x4fd1b0162e59bc8a +99, 0x4649428b04932d2b +100, 0xc504f1aa5e5dea73 +101, 0xc2ccb667a4325d31 +102, 0x9afbfdd5ad3a5204 +103, 0xcc07392e231e5553 +104, 0x6f4d6d195fd22ebb +105, 0xeb292b5127fb6e18 +106, 0xfe1f960a70442ded +107, 0x4447c330b74b5933 +108, 0xd21d4046f002efae +109, 0x8bc90cc78187c57e +110, 0x4f67494bf7cecee2 +111, 0xbc33ce353c1ddcfd +112, 0xb891c0a04b0e88f4 +113, 0x8f689f4d0ed5342c +114, 0xda219cd14be3d102 +115, 0x7c1ddbb38629b680 +116, 0x6c70aa3b93c4f52a +117, 0x29ec9e21b1dd5d9e +118, 0xcaeedac16be11bbf +119, 0x35b5110345859bbf +120, 0x439d41ea67b37ebb +121, 0xc6d8d0b7b4f1486a +122, 0xc52385db44d09080 +123, 0x5f99c2e9ca57b52a +124, 0xe3254276e855d800 +125, 0xefbd9049da09502c +126, 0xe6ff8ac6ad006271 +127, 0x2c930e30cb747267 +128, 0x4830da263ba45758 +129, 0x8c60b7ab98006775 +130, 0x7a57c0ea2b570c5a +131, 0xf70f75d3119e0efd +132, 0x3e522394beeed598 +133, 0xb7df8f82912f9695 +134, 0x2abb69f78de3c4f1 +135, 0xd51a5b2c0a7bb5cb +136, 0x89920a17d1de9528 +137, 0xa9d3b9cc614ce21a +138, 0xddd991172b564698 +139, 0xb4a4642875502ea0 +140, 0x8ddcf309cbfe223e +141, 0xb08ba3624d1c66b1 +142, 0x54f027d2804b5a93 +143, 0xb07c3b2d04832f27 +144, 0x848ac9c736770aba +145, 0xc341815ec6b12bf8 +146, 0x3983885191aac395 +147, 0x2c50047012e39883 +148, 0x35762e00ddd30f52 +149, 0x7592ad5f45512761 +150, 0x171247b019c3b822 +151, 0xdf2f59197f67bf2 +152, 0x3d32b07deb6ea68d +153, 0x333e4f44e437159b +154, 0x41a72372d89d3e17 +155, 0x8540ef3654d90ba2 +156, 0x87bd219a8adf77f0 +157, 0x81f0bc1fca841bb3 +158, 0xd3200d827a384d0f +159, 0xd8a9825fadc0be67 +160, 0xe05a6530036bea30 +161, 0xf142901dd1444861 +162, 0xda7d20911dad993d +163, 0x872847376d5e1231 +164, 0x3907389fdf521b33 +165, 0x90fcc779c427a50a +166, 0xb49366477e2b48c8 +167, 0xa04ebd5074accf86 +168, 0x3c92343f5469f7c +169, 0x2b84435bd09b4cb3 +170, 0xb8d4734885fece80 +171, 0xe2fca98eb7e3dc90 +172, 0x5a7f0f454e525193 +173, 0xcc0b1333129c5d2 +174, 0x6433a5896a07730a +175, 0x892937b8a1f1c314 +176, 0xe4a5b385d69dfb7d +177, 0xd8cb9ca239d53aef +178, 0x2cd7af2df788e262 +179, 0x177745f129e94f6c +180, 0x6a6db6c1ebf163e8 +181, 0x58f2f2e255caafeb +182, 0x227c81b75d181eb +183, 0x516d0226e079dbf9 +184, 0x6f66bc3efe0970ed +185, 0xb295db10d97abd08 +186, 0x99d30a4e4ace9fad +187, 0xd9d6a16104bd47d0 +188, 0xdc4c2ea12903a427 +189, 0x6334e1f5f5e03adc +190, 0x9a0cff45fc1bcee8 +191, 0x10874d542fbeec4e +192, 0x3819c7e7fba3b9bf +193, 0x1ee786f49b45924b +194, 0x54723c4712cfb62 +195, 0x3bcca5b2905fb708 +196, 0xf393a7f6ff6a667 +197, 0xaa06af9ce17f62b +198, 0x48c8f05f3e9d463c +199, 0x3479d0238b587b2b +200, 0xa8d8c6670104be96 +201, 0x55814d99b9dfe921 +202, 0xe1ce0f01000d20bd +203, 0x1014d96a94bf3326 +204, 0x582949045ca618f0 +205, 0x223bae0c2e7f5bc0 +206, 0x4bb41f7d1d9fb622 +207, 0xe1f3e2fd4021d8fd +208, 0x5ebccfc61d09c4c9 +209, 0xcfdef40545198b7 +210, 0x4ba8ccc2f8c60a64 +211, 0xba1b4fd748b5061 +212, 0x66e32eba41e0939a +213, 0xa18eed1669d9d315 +214, 0x87c02cfa0ee04b88 +215, 0xfb7c0dfe47ff10b4 +216, 0x865e22c3cbf93ed9 +217, 0xf61e66796f8889b1 +218, 0x3ce89e1af1f9c49c +219, 0x5df6d8fd03e50c56 +220, 0xe2d84d5a77047da7 +221, 0xf1e4983c4900285f +222, 0x1c4fdae662cf9ccf +223, 0x21e8d690e68e9a1a +224, 0x8bc4a83d32b939b9 +225, 0xca02b1f22175c5ff +226, 0x38c7e9f4818bb02d +227, 0x1a0849515278434f +228, 0x9b5ba0111c7e913c +229, 0x7f262e2236221eec +230, 0xbb50a7892f4f3289 +231, 0x61bf32a67a8a37ba +232, 0x8857a179391d0935 +233, 0xe6e89e905c2c838d +234, 0x42a4ac61146bc5a3 +235, 0x709439ac10ef9068 +236, 0x101b793f07cebbdb +237, 0xa15d15f938b270f5 +238, 0xb82363d829a5c246 +239, 0xf472088457296606 +240, 0xa637655483f6a118 +241, 0x8413c67139637302 +242, 0x84e91307377687b7 +243, 0x519f2fdc21adca74 +244, 0x2a57efb29d83c66b +245, 0x5061e889dbf1432f +246, 0xffb74ef07814a287 +247, 0xd82936d72d9838e7 +248, 0xfded7b21dc383d9f +249, 0xc28e1e820fa2d7f3 +250, 0xdad0ba8ae4409211 +251, 0xd7d5ed00366f754 +252, 0xc8f007b6d6161d36 +253, 0x1c4187a9c90e7d87 +254, 0x49fa2c16e3c78424 +255, 0xf3d899da10e89521 +256, 0x89aeb0ade569e3e1 +257, 0x56d3219edcc04b14 +258, 0x5853167abe7fa125 +259, 0x239b40146df96622 +260, 0xa2a70ed13e55aa13 +261, 0x452c6fd65a31f946 +262, 0x771cdf487bb8ea39 +263, 0x458020e1e0355a3 +264, 0x86b71c8ac351f40f +265, 0x4518b905912e4b44 +266, 0xe59809fb72b59f51 +267, 0xf52f08fabdb424ab +268, 0x98729bc24ae9b930 +269, 0xd18bea8f222ae2fd +270, 0xaa5bff6ddbe6cd39 +271, 0x5e6564bdf9d27a0 +272, 0xc1c4658d6d27e065 +273, 0x31d66edddd8655ed +274, 0x6af3bc60e2b4af07 +275, 0x399c4af6041796ab +276, 0x17bb479a69a6ed73 +277, 0x2784fe93a28ecaa3 +278, 0xf21f2428f04f3562 +279, 0x8400c729e4bbcaaa +280, 0xc7b9912613e2277b +281, 0x4100a49d29d132d8 +282, 0xe83d287fada879af +283, 0x20512ca7b1735a2e +284, 0x16d172b52cee39f4 +285, 0x932f40c6356b0681 +286, 0x73b173d7394ebe2f +287, 0x621f4add757fccb6 +288, 0x7724a21d6908f4b +289, 0x82723dadae7a25f +290, 0x917c3b165505d87f +291, 0x317789982769846d +292, 0x9118ac495eb78d26 +293, 0xf52b2e19d3ef473 +294, 0xa846c997a4f8604e +295, 0xf316fca50e1bf909 +296, 0x5fd613d38169c705 +297, 0xfa2c8ac49a16f4d +298, 0x19382f84f73cc4c5 +299, 0xbbbdf4d883438e9e +300, 0xd0c0b36f4d4ef8fc +301, 0x5b57967a9e761eaf +302, 0x8003a747f3cdc264 +303, 0x67245a0a751da7ad +304, 0xc8ddd03ef82a0a33 +305, 0xa7c93a1bfd6c820c +306, 0xf8c05bc5f6fdd20e +307, 0xd9879192f8295663 +308, 0x180c2ff3e2771469 +309, 0xb17b2159870533e6 +310, 0x34d6c12c9be34bc9 +311, 0x664eb6de3c27d98d +312, 0xdbb5b1ba134b9d90 +313, 0x68ce417ee1e96b76 +314, 0x2fb7a10f525e5e08 +315, 0xf4d92c47b9a37cad +316, 0x3fd6bf82bb631c2d +317, 0x269eb1cd345e8a31 +318, 0xbe940cb0cffd51ee +319, 0x17f4afb78aad2719 +320, 0xe6418d546742ed86 +321, 0xbbddf550be83c008 +322, 0x21f5abc27624453d +323, 0xa9c23d6d0fc4cc4a +324, 0x51dd98db43adfa45 +325, 0x768debf45d278d3a +326, 0x3c66726469c6d78a +327, 0x19720ca3ec5c95fe +328, 0x647128339a9de240 +329, 0x2283bfd5ff7fca46 +330, 0x491c02359844cc18 +331, 0x759e770b8b4ab91e +332, 0xca1335607f9cb5c8 +333, 0x57622ba5e6ab8e31 +334, 0xe2631640efa27ee1 +335, 0x9a374481132fdcc3 +336, 0xead08fc06ebe7d6e +337, 0x51f6e040be74899f +338, 0xef020a2644eea66b +339, 0xd08de860251ea1af +340, 0xbbd4224fef793ab5 +341, 0xe32c1f5a20c14b49 +342, 0x41a9c20ee9ab12ff +343, 0xa4f28d0065e07695 +344, 0x29f6a06ee894dde4 +345, 0xf892525b2a6eacd5 +346, 0xf014392e71ac28e +347, 0x95fc7879ae3930da +348, 0x4f6d3fbc928edb34 +349, 0x827c5e01824069df +350, 0xcc71b97aaf28952b +351, 0x34ea77a8fee21c5a +352, 0x1060da2bf2eb6e5d +353, 0xb5c810ce92166853 +354, 0xe4a3a54ee402b549 +355, 0xfccad41d569a68ba +356, 0xef7cdfbe1a1dc930 +357, 0xa4fc3447ec16869c +358, 0x38fd0381051d225d +359, 0x4588436100fb4666 +360, 0x315ee0679f95d75d +361, 0xdb3ebac7a80ce68a +362, 0x711776d978e4144f +363, 0x76335f1760bf6c69 +364, 0xa0e43f3a570985d8 +365, 0x4acd44aa515c8a2a +366, 0xeae99aa23e380173 +367, 0x64db0d85601f3581 +368, 0xb251dc038cc5c88d +369, 0x416acb242805830 +370, 0xc58c8a6f0c958ee5 +371, 0xfca9023592ef2492 +372, 0xe0b53c925afac1d +373, 0x59ab2f382172a153 +374, 0x5b32526cf9ffddf7 +375, 0xe8f7da4d2ee7d446 +376, 0x54ebb0fad0b278a6 +377, 0xdb347dac25d9f210 +378, 0xe439a5295e5218a7 +379, 0xee108ec20ca6d955 +380, 0xcaeb3ae75ca6a426 +381, 0xd626b91bed8e3cfe +382, 0xf594cc47bb420358 +383, 0xcb8c06c63f602631 +384, 0xea1bbf343755e2a6 +385, 0x769f8ad9e3e9dd82 +386, 0x5d0004d1952f258b +387, 0xf696d68c507351d1 +388, 0xcdfd3bef68eeb52f +389, 0x3d400e8af4240cca +390, 0x8662dfc98da8bbba +391, 0x5127c718b4533d93 +392, 0x1628510427094b54 +393, 0xb6d294f5979c4b17 +394, 0x6d03a41585865ea1 +395, 0x96728b5b88e3b111 +396, 0xea45bc46ab6d1e06 +397, 0x53ce57a324130f26 +398, 0x59e439b690174051 +399, 0x7c143c4e625949df +400, 0xc764c808c3e166a3 +401, 0x6263f53fa2405763 +402, 0x71952cf69bb08e58 +403, 0xfec4e83b29280505 +404, 0xce28f5ba58ef8f6e +405, 0xebd9e7ab671427a6 +406, 0x4a91ba373ed1de6e +407, 0xb22b200125627341 +408, 0x8c111548e4a162e5 +409, 0xf4345a7b421b34aa +410, 0x40ba35f569a690a4 +411, 0xf1031a09b5e1d223 +412, 0xbe1c1a131386bbc +413, 0x216f8598d1be1586 +414, 0xef45f48c338d8db0 +415, 0xf57e9f4e168b19c8 +416, 0x56e06748363954b6 +417, 0xccd0b383991896f9 +418, 0x4b40d308361e4d23 +419, 0x1ee49bb107ccb9b9 +420, 0xcdfd1ccf20e46b0b +421, 0x55089ad213e2c33e +422, 0x2852c242329b05a8 +423, 0xa46180d6534b97ef +424, 0xbfb5bbe8b1bd13cd +425, 0xb0bcb564e00214a0 +426, 0x6e9d330e742cf634 +427, 0x7b5b292cfa1b9430 +428, 0x5441cad8cf303e85 +429, 0x1762008ea3eefc9e +430, 0xa9ade7d73cb4296 +431, 0x98a6316562c0ea4f +432, 0xc51574eccad0e9fb +433, 0x677ec01be6893139 +434, 0xb0c7982fbaaee4a2 +435, 0xe07ed42cbb34d46c +436, 0xafc4634fa786c32d +437, 0xdaf8b97e6ad7e018 +438, 0x6267f0706ae3a607 +439, 0xca07bd40f70c2e9e +440, 0x4b25e8c7869abc8e +441, 0xabbb474aa737636e +442, 0x410f530d20a6769f +443, 0xee7d10dba29880d5 +444, 0x61f91eb2ebc3c39e +445, 0xc02d21d44c280731 +446, 0x7ca6f8eb9d6d3abe +447, 0x5e3fc57fc5b3ab03 +448, 0xc4b0f5d5d2655632 +449, 0x9b57a16a81ad63b9 +450, 0xc4732d2261781084 +451, 0xbd26679e27f54c19 +452, 0x8eef61d7a56c9d2d +453, 0x950e4be078a1d146 +454, 0x672e35b94cfafe9 +455, 0x79076d70ef347878 +456, 0x8d0158c3b7af319a +457, 0x9f9f475701b78fbd +458, 0x15768b3aabdb75e1 +459, 0x9f00af1f73d4209c +460, 0x680f425ca7814aa5 +461, 0x4501ef424a132af8 +462, 0xc57a90ca7cec1f2f +463, 0x708bfd7448c14dd1 +464, 0x3bfcbe7c8840456 +465, 0x6f97402f07bde0a0 +466, 0x8027440e4b178a21 +467, 0x94e947eb94a1c33f +468, 0xa99d1ab0d9e32c23 +469, 0x3240cb605f629e2a +470, 0x414086506367a711 +471, 0xb9186fe6279d4965 +472, 0x3f21caccdeb1c91a +473, 0x13554b8865e173ec +474, 0x867beb29cf375a21 +475, 0x1f27821ee23885b7 +476, 0xc64f09efbf1b5c69 +477, 0xc8f96ad307b1eaee +478, 0xea9040a44f9765f2 +479, 0xdf9c784d488953c8 +480, 0xa010bdbdce78972f +481, 0xbb8ab6017fcb7e5c +482, 0x8584f4844ad95ef6 +483, 0xc319e59b7efd9aad +484, 0x7ab487076c4a148f +485, 0xe5d8c47faa0488a0 +486, 0x4077092e33a0457a +487, 0x1bf7e7c4f615d7c4 +488, 0xea03b4fb0f4c3902 +489, 0xee72742384d93cc +490, 0x5bdae630f24c703b +491, 0x4d47db7fd176b322 +492, 0x4457f591923d3714 +493, 0x4a5cb51e0ce52280 +494, 0x16021446e36cf9ab +495, 0x87c563540c39d952 +496, 0x18c0cbfa66b443eb +497, 0xa3edd3ce7632c1f2 +498, 0x2921b28c42e77852 +499, 0xc72e3be0072541bf +500, 0x988c2deed5403283 +501, 0x510b8765988cd3ad +502, 0xa86ee406bfa09364 +503, 0xae5e6c62df70a308 +504, 0x28d4790520331444 +505, 0xbb1a0474b2f407d4 +506, 0x6bcfae4cf73c59cd +507, 0x36695e04107a9f5f +508, 0x5b1e9ad38395f724 +509, 0xd3157c290d299f2 +510, 0xd084175fa8220b7b +511, 0x76b0399bdfb66af2 +512, 0x29c3425c62e361ca +513, 0xe4bf2b3494a19bd8 +514, 0xc9d57df374baba6b +515, 0xdcee5e50619bf223 +516, 0xa3ba78fa885e6a72 +517, 0xbf34ea44695a8f30 +518, 0x5ddde2254aff3d06 +519, 0x6d1f3041e9879f3 +520, 0xaccd25b0875c2d89 +521, 0xefa539c60700018d +522, 0x7d3764e10c6d733b +523, 0x367d61076fe9c3c0 +524, 0x4657ab485775ed78 +525, 0x1ba7888d4f32d223 +526, 0x24ee78667fd08a50 +527, 0xfad3ba97460fae93 +528, 0x4dd200f3b026d7dc +529, 0x9d4e33c5fef7953f +530, 0x2ca6fd68615253c9 +531, 0xe3d16805a894838e +532, 0x10db3a0c972ecdc8 +533, 0x4090524fc5355e3c +534, 0x27385eae6f429d47 +535, 0x50af78ddc8681d35 +536, 0x1ebe6ea924bcd104 +537, 0x75423f64f5df83e7 +538, 0x876c4860427c720f +539, 0x8dc8f9407e27a179 +540, 0xedcd4c67c2676676 +541, 0x3341e48a470ebdb8 +542, 0xd4f63685f508ba66 +543, 0x3f6e375d68e34845 +544, 0x11b33ca59e6c3241 +545, 0x40189f7217f8137a +546, 0x916b0c45129e9a53 +547, 0xc1e91440f5b713bb +548, 0x414652f46a900767 +549, 0x33310db43b11e46f +550, 0xff1503c244b4b868 +551, 0x669e43bc981f4223 +552, 0xe27d487e222dc483 +553, 0xb2ae0efe4fef9eae +554, 0xd8dd8b215c1cfe79 +555, 0x16a80138d4ddcedd +556, 0xbc6a70ac7a4bcda5 +557, 0x18d80787abf2acfc +558, 0xecd0532537c2d3cc +559, 0x993800a80d4446f4 +560, 0x4ea5aeea9f43526 +561, 0x5a8031685b0c1463 +562, 0x31f108fa80921689 +563, 0xb9709186be75599f +564, 0x3adff9562a928b69 +565, 0x190d15108d41eb7 +566, 0xea7591506a38e4c7 +567, 0x4c91ea0a6340a8c3 +568, 0x919c67ef7a244bbf +569, 0xe6a76f184ad3d2b +570, 0x3a9640c5bed1edbc +571, 0x506ebd2fe9ef89e8 +572, 0x4d0796896388d9c4 +573, 0x2de4c110f7d7d112 +574, 0xe46c7b927d9f79a9 +575, 0xbf0ae3712f8eeae1 +576, 0x3b2984ee35da6a32 +577, 0xc59345b1697baef0 +578, 0xa3473fb9f81cc2df +579, 0x4454c552a21d642f +580, 0xca1636a3e911c77f +581, 0x2d9b63fde30e80fc +582, 0xaef85088f4d559f1 +583, 0x46544642eecad016 +584, 0x4da4f3f6afd9956 +585, 0xe6e375ac0867fc0a +586, 0x37d32889b072031e +587, 0x83fc712194bb9b4f +588, 0x9fa04dcc1f546c93 +589, 0x11c7883dc79aa96f +590, 0x1a71d76e8ea10b7c +591, 0x718279514561c06a +592, 0xc664454f1de48c18 +593, 0x945794f5dbc5b9b9 +594, 0x3cb32ee274775b53 +595, 0x571676c238e946b6 +596, 0x903cb8f8a39a1994 +597, 0xe63cdce42313cb65 +598, 0xddf3163b47ec269d +599, 0xb2c5a360383dd417 +600, 0x7bbf55331e3acb3e +601, 0x5c03cfbcc662c4b3 +602, 0x8cee8a1ce27b0fd0 +603, 0xb3e4f5dcce5e41de +604, 0xa3c560c653f8d148 +605, 0x9b0803f47ddbbd92 +606, 0x73598c03ae44f0c5 +607, 0xeda1ffa390632e00 +608, 0x1110571306d5e9c0 +609, 0x41ed218f2f65a1b5 +610, 0xe07441e90b230c6e +611, 0xcde6847873992446 +612, 0xb7d9b5ee4e941a3f +613, 0x5c9e0ac35e79e606 +614, 0x168d3790aca61ccc +615, 0x1846981baa478e7c +616, 0xc1689be15fa49372 +617, 0xddcb4e9701381927 +618, 0xa01ea97bce8344ff +619, 0xbaf44781cab34255 +620, 0xec241fa1a79901d1 +621, 0xea98acc2951f15ac +622, 0x1494afaba64e4697 +623, 0xda5136456a210ac1 +624, 0x5fa20a363997390d +625, 0xb53bbf197e19ce07 +626, 0xde0f31128a00cca2 +627, 0xc605fd5f98698e2a +628, 0x6796d5719b95d97c +629, 0xee44914e65e92f5a +630, 0xb0054098c1bddbe2 +631, 0xad7700d59df9004b +632, 0xcdf1288400a36d30 +633, 0x8b0f55466049fde1 +634, 0xab9410d6a2a28f3e +635, 0x4b5adce26df9bbee +636, 0xb16dcc4180dc7bb7 +637, 0x7657f9213f0dc5e2 +638, 0xc1eb5760b0852f85 +639, 0x8fb3fe1d0faec1d9 +640, 0x2dbbb8a4882f96dd +641, 0xf4ecd3eaf395f8fa +642, 0xb258df3c504f12e0 +643, 0x7ac9b40c8f945ed6 +644, 0x8f134be6970b05d9 +645, 0x6ecc9666da7fa595 +646, 0x133361dfb73314dd +647, 0xb8721ed39e997436 +648, 0x656883492dc738b9 +649, 0x174a3c8f99bf9b85 +650, 0xc09ef0f2df044a07 +651, 0x28c7a240745dff8c +652, 0x176441c5299c7c50 +653, 0x8f42c91c5e888ade +654, 0x1512801d9d3d0953 +655, 0x443640b3f1c700f +656, 0xd83f359def440e5f +657, 0x9fe61cf5cc1c3aa2 +658, 0xff32bae693ac2f8c +659, 0xb4c4595dd221d70a +660, 0xd3437b597e7286c8 +661, 0x2510f2ff588244d8 +662, 0x886154af6e3c0192 +663, 0xd6725d1af0c4a779 +664, 0x4874ef6b5ef6f9e3 +665, 0xbb987030fc6d4ede +666, 0xa0143e44289ccb48 +667, 0xca3de9e602373a89 +668, 0x78a50b8eed52c7c +669, 0x7bc6b4f801904167 +670, 0x9d14d691cb0acee5 +671, 0x53d9784fdefd3fa7 +672, 0x2b5457b8912e9095 +673, 0x41f3614d5840ec5 +674, 0xdb1d447cd66f3375 +675, 0x80f3770ee7d84b3f +676, 0xab9863f7e5a52eae +677, 0xfc078f48c4b21252 +678, 0xd360cf3d61a05da2 +679, 0xb31a15784218b1b6 +680, 0xdc0a6e5e7a89bf5a +681, 0xea18995b334e9d69 +682, 0x3e07c668b1f71a31 +683, 0x4ecf7c96be3b06e7 +684, 0xeb3f4dbab3912a0c +685, 0xf3adfd6a616308c5 +686, 0x7478bc40793ad794 +687, 0xeedca7d9bc381ea9 +688, 0x7b5a77d7b42cc04e +689, 0xd66ffb33bd6e5616 +690, 0x48d8ef97ac2d0ff7 +691, 0xb1c85985725cab07 +692, 0x669a9762479ad88f +693, 0x22e49f0ceddf433c +694, 0xb78bf3ac7e020fc9 +695, 0x3c4939f7654e38d7 +696, 0x6ba6b31e431bf01 +697, 0xe55d5f4848c9e979 +698, 0x5e943e51c4223664 +699, 0x7385c2084ba55b84 +700, 0xedae6a69b96c4181 +701, 0x5498b7fd55f464b4 +702, 0xd889c1a2eb452455 +703, 0x189fd7411f0f9003 +704, 0xd26ce80a290a614a +705, 0xe17114fdc506bf73 +706, 0xe9e4b0ef791be2f7 +707, 0xcf9fa23043d230e5 +708, 0x3a8dac60f4791a0b +709, 0xbefc5e64f0603b04 +710, 0x41e622805a016bb2 +711, 0x8a57df661b57fa6f +712, 0x13a30bb387257625 +713, 0x52a45137bdc9d9d7 +714, 0x6385fcd7f91189f0 +715, 0xb18c44ec584e6de7 +716, 0x6335807f6d6b86fd +717, 0xd573fb71853ef93a +718, 0xf6171462c9f74a61 +719, 0x10089f2cad628d2f +720, 0x96b8d5937d722b85 +721, 0x7376821fe68a497f +722, 0xb752bcac1c64da57 +723, 0x2a043c4fd7c56683 +724, 0xb9acd886078b8ca8 +725, 0xa137bfd64a2aabfa +726, 0x7b616af852cfb604 +727, 0x851d36fd60a7a376 +728, 0x1f6612c681686473 +729, 0xeb70d6175c3f21a3 +730, 0x38df2476423bb985 +731, 0x1c8946a1d708676a +732, 0xe3857fbe776fbcf0 +733, 0x4bccfabc6a7aa9f6 +734, 0xaa79d49af3fb0ad9 +735, 0x8a90ac2c9062949 +736, 0x1bef9e17f6abd7ac +737, 0x5f834c276df092ed +738, 0x57451b8f37c655de +739, 0x9b37a62f91df1c6b +740, 0xfea0e5e928521dd1 +741, 0x30ae26af2d3d3066 +742, 0x90c7f4fe041cc96f +743, 0xae3d8a1af5e89491 +744, 0x8654f2cadce2dce3 +745, 0x45b460f2bd49bf46 +746, 0xbb29582042d003d3 +747, 0x29cd1be694c5c95f +748, 0xbc0ae7374b735c03 +749, 0x4db1a0bc64758878 +750, 0x122c278b74b518c4 +751, 0x4a94e6b50bf51213 +752, 0xf408489bdda60454 +753, 0x791c5da3bf67cb99 +754, 0x83b85caa737261f3 +755, 0x619fe26f59c92f28 +756, 0x6f24d7563749d335 +757, 0x4d5224b378f4356d +758, 0xa80dece2650eccfe +759, 0xc537fb63fd483efd +760, 0x28c5c3cdb5ae2df7 +761, 0xcd66fbab1368c7aa +762, 0xf2abd0adff7069ca +763, 0x152fee808d76d3ab +764, 0x2f21b3a82acb2d08 +765, 0x7eafb15d34cfad1e +766, 0xa7f1608a241eab5e +767, 0xe030095ce12c4c10 +768, 0xa0d6ae018a94f4fb +769, 0x908e2ddca49b6b27 +770, 0x160e2f0b13791c01 +771, 0xc94bcaab64d37b36 +772, 0x9b6d2771f3cab823 +773, 0x877e720beca0fa5e +774, 0xeab6a692db2c4bb2 +775, 0xbe7c0b35f9c454dd +776, 0xafd9faefc3c2e26f +777, 0xc0b313e172484781 +778, 0x802ab792f708ee16 +779, 0x9bb8a1c513145652 +780, 0xb3bb6fbd9ac8b1f5 +781, 0xfd1222d31160e2ac +782, 0x9e8def9378eb0567 +783, 0x4cb5047d3e7613e9 +784, 0xe870feca80e56b98 +785, 0xa6b53c45c84d5b1b +786, 0x2cccb2ab07159ff1 +787, 0xbc1532a0b621d08c +788, 0xc17f60e6e631228c +789, 0xe231bf2fa4ed9790 +790, 0x9650d2546468aea4 +791, 0x78ed0341e62b1f36 +792, 0x564786e0f06f2136 +793, 0xad67f8e36f21e2a6 +794, 0x14aca551dc2007f4 +795, 0xdaaf21ba99a85718 +796, 0x801993a2b9ccd054 +797, 0xc081b520e3351ae4 +798, 0xb4c2c3a575d98933 +799, 0xee0febb05021f5d9 +800, 0xa8e9bf042c8524c2 +801, 0x62a4e29d5e5b0e32 +802, 0xca47dc23b3267d2d +803, 0x7dcda2032acfb297 +804, 0x707edefabc363d8c +805, 0x66ae33b39d40cc26 +806, 0x29af2f7a0dbe3c6c +807, 0x45bd35e7e7fe3fc8 +808, 0xe2be9934a9386886 +809, 0x1369a648c1f66d4 +810, 0x36771ede37f6912d +811, 0x29f125e90e92f06a +812, 0xdf2517a841fe4c35 +813, 0xa07e77e5ac2fa24d +814, 0xaafc1ab2e8914f7e +815, 0x64d602ea8eab3138 +816, 0x7dcc67358db459b7 +817, 0x18b3c0f3e2ddc176 +818, 0x3186ebc761499532 +819, 0x26eae2da284bf1fc +820, 0x2fce764273c3afe8 +821, 0x8d14d487425c3e78 +822, 0x515162b0ca58a70e +823, 0xc9a51fd0466b0019 +824, 0x6928f5af5674a4a2 +825, 0x23aec98e1759caa1 +826, 0x438f9a8f033d4511 +827, 0x8a6314a76994c55e +828, 0xa3bef565e65855a2 +829, 0x251c36d1deb6face +830, 0x221f06d4847ef177 +831, 0x29741abb3ab9b4e4 +832, 0x93c9827eacaa262f +833, 0x9d91f19aace9c4c9 +834, 0x30038d3da09b76e +835, 0xcddf978db05ec6cb +836, 0x798aa80467245bdf +837, 0x9c26179d57a6263b +838, 0x2cbdb745276e1c2b +839, 0xee549998a174e7c5 +840, 0x707933d84e48e90 +841, 0xc1925775d969b667 +842, 0xbac030db93b43a38 +843, 0xa478f204b04d5963 +844, 0xecfc1e66fa00531b +845, 0x4771b36479d16c0c +846, 0xfa28373c9c035622 +847, 0xc89c89a3ee2b5365 +848, 0x88a4066f98fa60a2 +849, 0x3d3395c78b0a0111 +850, 0xed59a448861220b6 +851, 0x97574be1b4fbf7cc +852, 0xe63d52a637907a6b +853, 0x5ba45d5ae3d14fcd +854, 0xecfff9b9ce46e911 +855, 0x1aff395024e1670f +856, 0x80735f71f452b8d0 +857, 0xb35665e1a7090637 +858, 0xb6fc2f8eafbdb100 +859, 0x1f72a04d1ac1ec24 +860, 0xdc6a743a6dfc9a65 +861, 0xc1f2e21f56bf953b +862, 0x3861b9573b9b211f +863, 0x1b0b5ebe315c8de6 +864, 0x4a2474209eefeb20 +865, 0x8bf700bea8771d57 +866, 0x5c826e1b9d96e021 +867, 0x3c550882c3e60dd3 +868, 0xbcfc1b474082e0b +869, 0x36328eb420971300 +870, 0x31f955615998d5c0 +871, 0xefc881172a488a7a +872, 0x8ae7f46c694723a3 +873, 0x71642de55998b04a +874, 0x43af19c9ce33d752 +875, 0xb489c13374abc234 +876, 0x3691de307b663328 +877, 0xeef765a5e6839de2 +878, 0xdceb9040010939ee +879, 0xc402cd11b98f0ab7 +880, 0x714e9a2cb8f045e +881, 0xf0cabb6fe1a41f30 +882, 0xcf41bc2a41ecfb57 +883, 0x62c24ff5eeb1048b +884, 0x74a62a4266a09c41 +885, 0xa6ddcbcf7c7af5f4 +886, 0x8534a3d967991eb1 +887, 0xe43dbafd0a4c9311 +888, 0xc0d713b3b8d9dd68 +889, 0x174a9b2d277e1f +890, 0x8573edcbab177db6 +891, 0x1bcff4d3595158e6 +892, 0x84e938887e7c6066 +893, 0x354130c60d728871 +894, 0xb8dd477ccc07d2a0 +895, 0xc1e30214f9d75b60 +896, 0xce4977c3d243d7fb +897, 0xf93ba43fa22155b7 +898, 0x1cd39a9065bed6c4 +899, 0x1677daec8a3647cc +900, 0xce08f421c19266ae +901, 0xca3ca9ebd2a2669d +902, 0x7eb68405132fca15 +903, 0x18168b0f0ce8d315 +904, 0xdf241f3d574a968e +905, 0xe2fa2207e0dbc86a +906, 0xb8bfb68c1ee88be6 +907, 0xc386a425a0e8ec8b +908, 0xf60e7ea66674e122 +909, 0xd6b7820405c40e8 +910, 0x84bd5fac533797e7 +911, 0x5acfd875363dcfdb +912, 0xd0cab73b1d04d65d +913, 0x8d5cd9a81de7cc92 +914, 0x816b262b71097355 +915, 0x2d28470f662f3ef7 +916, 0xc7ef80c95a450030 +917, 0x18be275d375e8d38 +918, 0x4ebbb686e2fe3832 +919, 0xa15f1c5068711bf +920, 0x6e3e14f47aab4b11 +921, 0x51d2f11208103b72 +922, 0x4083a7d5788b72f5 +923, 0x5037780b542dc8ce +924, 0x1df9802ce8610192 +925, 0xba270a3bcbb59d80 +926, 0xce0459574f8a37c +927, 0x543aaf1a28480574 +928, 0xea92b1cf98896d16 +929, 0x6bfd3baae08a2060 +930, 0x5d9a2b2b76d4ed11 +931, 0x8de7686a95d09d5 +932, 0x392e959b78286928 +933, 0x98fc7a7d1a82e0b5 +934, 0x23f25d04738d1d6d +935, 0x507922d324dd1207 +936, 0xef809cf741419ad7 +937, 0x3a3ffc65ef3365f3 +938, 0x3eb258435905713f +939, 0x242386e52078bd9c +940, 0xa3941556020beac4 +941, 0xbbb020f8e5f4aee2 +942, 0x3373440701bbd45e +943, 0xa6a36308592401f3 +944, 0x20e5642bed30990a +945, 0x6c3cce6f512f0c30 +946, 0x61b470467a590ea3 +947, 0xff15bf7dc3ffccb2 +948, 0x23a3c0663725715f +949, 0x197ea4c617f88f31 +950, 0x6412abc6b559972e +951, 0x5e963b8491f05790 +952, 0x7b837bd7e43c7b83 +953, 0xccde4023d6b2ba81 +954, 0xa39f9c1d210fdfed +955, 0xa413f619bdd49c28 +956, 0xd2096d2202caee6c +957, 0xbbdbb1f4178b9ec4 +958, 0x77d3deb9828dc7ec +959, 0xdb311ba28eb9b8bf +960, 0x781905616be8bc25 +961, 0xf7b401fdce0928ac +962, 0xa29286d380c51201 +963, 0x4f6790854c5fcf9e +964, 0x95b7e3793eceab8f +965, 0x77097d01be05b8fd +966, 0xea6645235d898393 +967, 0xc260212650bb4196 +968, 0xab028439386af2a1 +969, 0xb9c99c6cb6bac542 +970, 0x44597a7ac513a707 +971, 0x7c3503863d73196a +972, 0x5310606fb739afa0 +973, 0x2b9a1a30b2b82283 +974, 0x442c9600d98d3fd4 +975, 0x56dbbb72bd2fb227 +976, 0x9e137b63c9dfbd47 +977, 0x8c432826c8059484 +978, 0x2a581bd76096803 +979, 0x9bced11dd3da15d4 +980, 0x448d0782fa0e2d56 +981, 0x6fe223ed7981de88 +982, 0xa11abc8ebee400d0 +983, 0x70cfca3c8008b197 +984, 0x6de64d935456ab83 +985, 0x726bdd86810c0d6a +986, 0x1077e0584ccc4150 +987, 0x64fa38092b2316f9 +988, 0xe3ef337ecdc3b8c5 +989, 0xebc0452bc41c192a +990, 0x2a81ecd193ab45f9 +991, 0xeb6038f45a865c3a +992, 0xe7f1e1b3600ec5d2 +993, 0x16897e3406fe264c +994, 0x2768a1d17fb81ddb +995, 0x9965317d69c47896 +996, 0x949e16bd19a6c53b +997, 0x81cc74cdf8fe59ea +998, 0x180ade029d93ddc6 +999, 0xcfe8717315f3ca1f diff --git a/_randomgen/randomgen/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py index be4f533eadc5..ee69d54163b1 100644 --- a/_randomgen/randomgen/tests/test_direct.py +++ b/_randomgen/randomgen/tests/test_direct.py @@ -8,7 +8,8 @@ import pytest from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 + PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ + Xoshiro512StarStar if (sys.version_info > (3, 0)): long = int @@ -227,6 +228,32 @@ def setup_class(cls): cls.seed_error_type = TypeError +class TestXoshiro256StarStar(Base): + @classmethod + def setup_class(cls): + cls.brng = Xoshiro256StarStar + cls.bits = 64 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv( + join(pwd, './data/xoshiro256starstar-testset-1.csv')) + cls.data2 = cls._read_csv( + join(pwd, './data/xoshiro256starstar-testset-2.csv')) + cls.seed_error_type = TypeError + + +class TestXoshiro512StarStar(Base): + @classmethod + def setup_class(cls): + cls.brng = Xoshiro512StarStar + cls.bits = 64 + cls.dtype = np.uint64 + cls.data1 = cls._read_csv( + join(pwd, './data/xoshiro512starstar-testset-1.csv')) + cls.data2 = cls._read_csv( + join(pwd, './data/xoshiro512starstar-testset-2.csv')) + cls.seed_error_type = TypeError + + class TestXorshift1024(Base): @classmethod def setup_class(cls): diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 7ee896d352fa..747e10b394c9 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -599,7 +599,8 @@ def test_choice_return_shape(self): assert_equal(mt19937.randint(10, 10, size=0).shape, (0,)) assert_equal(mt19937.choice(0, size=0).shape, (0,)) assert_equal(mt19937.choice([], size=(0,)).shape, (0,)) - assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, (3, 0, 4)) + assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, + (3, 0, 4)) assert_raises(ValueError, mt19937.choice, [], 10) def test_bytes(self): diff --git a/_randomgen/randomgen/tests/test_smoke.py b/_randomgen/randomgen/tests/test_smoke.py index 99f218181d89..5a9882a16aed 100644 --- a/_randomgen/randomgen/tests/test_smoke.py +++ b/_randomgen/randomgen/tests/test_smoke.py @@ -10,7 +10,8 @@ from randomgen._testing import suppress_warnings from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 + PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ + Xoshiro512StarStar from randomgen import entropy @@ -100,6 +101,17 @@ def warmup(rg, n=None): class RNG(object): + @classmethod + def setup_class(cls): + # Overridden in test classes. Place holder to silence IDE noise + cls.brng = Xoshiro256StarStar + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.brng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + @classmethod def _extra_setup(cls): cls.vec_1d = np.arange(2.0, 102.0) @@ -121,25 +133,27 @@ def test_init(self): def test_advance(self): state = self.rg.state - if hasattr(self.rg, 'advance'): - self.rg.advance(self.advance) + if hasattr(self.rg._basicrng, 'advance'): + self.rg._basicrng.advance(self.advance) assert_(not comp_state(state, self.rg.state)) else: - pytest.skip() + brng_name = self.rg._basicrng.__class__.__name__ + pytest.skip('Advance is not supported by {0}'.format(brng_name)) def test_jump(self): state = self.rg.state - if hasattr(self.rg, 'jump'): - self.rg.jump() + if hasattr(self.rg._basicrng, 'jump'): + self.rg._basicrng.jump() jumped_state = self.rg.state assert_(not comp_state(state, jumped_state)) self.rg.random_sample(2 * 3 * 5 * 7 * 11 * 13 * 17) self.rg.state = state - self.rg.jump() + self.rg._basicrng.jump() rejumped_state = self.rg.state assert_(comp_state(jumped_state, rejumped_state)) else: - pytest.skip() + brng_name = self.rg._basicrng.__class__.__name__ + pytest.skip('Jump is not supported by {0}'.format(brng_name)) def test_random_uintegers(self): assert_(len(self.rg.random_uintegers(10)) == 10) @@ -546,7 +560,9 @@ def test_pickle(self): def test_seed_array(self): if self.seed_vector_bits is None: - pytest.skip() + brng_name = self.brng.__name__ + pytest.skip('Vector seeding is not supported by ' + '{0}'.format(brng_name)) if self.seed_vector_bits == 32: dtype = np.uint32 @@ -896,7 +912,7 @@ class TestPhilox(RNG): @classmethod def setup_class(cls): cls.brng = Philox - cls.advance = None + cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state @@ -908,7 +924,7 @@ class TestThreeFry(RNG): @classmethod def setup_class(cls): cls.brng = ThreeFry - cls.advance = None + cls.advance = 2 ** 63 + 2 ** 31 + 2 ** 15 + 1 cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state @@ -928,6 +944,30 @@ def setup_class(cls): cls._extra_setup() +class TestXoshiro256StarStar(RNG): + @classmethod + def setup_class(cls): + cls.brng = Xoshiro256StarStar + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.brng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + +class TestXoshiro512StarStar(RNG): + @classmethod + def setup_class(cls): + cls.brng = Xoshiro512StarStar + cls.advance = None + cls.seed = [12345] + cls.rg = RandomGenerator(cls.brng(*cls.seed)) + cls.initial_state = cls.rg.state + cls.seed_vector_bits = 64 + cls._extra_setup() + + class TestXorshift1024(RNG): @classmethod def setup_class(cls): @@ -956,7 +996,7 @@ class TestThreeFry32(RNG): @classmethod def setup_class(cls): cls.brng = ThreeFry32 - cls.advance = [2 ** 96 + 2 ** 16 + 2 ** 5 + 1] + cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.initial_state = cls.rg.state diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index e8971ff42161..cb3c78f5bfbf 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -319,7 +319,7 @@ cdef class ThreeFry: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter): + def jump(self, np.npy_intp iter=1): """ jump(iter=1) diff --git a/_randomgen/randomgen/threefry32.pyx b/_randomgen/randomgen/threefry32.pyx index 512ce9d00d3b..62c0e9cd8c92 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/_randomgen/randomgen/threefry32.pyx @@ -314,7 +314,7 @@ cdef class ThreeFry32: self.rng_state.buffer[i] = value['buffer'][i] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter): + def jump(self, np.npy_intp iter=1): """ jump(iter=1) diff --git a/_randomgen/randomgen/xoshiro256starstar.pyx b/_randomgen/randomgen/xoshiro256starstar.pyx new file mode 100644 index 000000000000..33ecb50f1a88 --- /dev/null +++ b/_randomgen/randomgen/xoshiro256starstar.pyx @@ -0,0 +1,362 @@ +from __future__ import absolute_import + +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle + +np.import_array() + +cdef extern from "src/xoshiro256starstar/xoshiro256starstar.h": + + struct s_xoshiro256starstar_state: + uint64_t s[4] + int has_uint32 + uint32_t uinteger + + ctypedef s_xoshiro256starstar_state xoshiro256starstar_state + + uint64_t xoshiro256starstar_next64(xoshiro256starstar_state *state) nogil + uint32_t xoshiro256starstar_next32(xoshiro256starstar_state *state) nogil + void xoshiro256starstar_jump(xoshiro256starstar_state *state) + +cdef uint64_t xoshiro256starstar_uint64(void* st) nogil: + return xoshiro256starstar_next64(st) + +cdef uint32_t xoshiro256starstar_uint32(void *st) nogil: + return xoshiro256starstar_next32( st) + +cdef double xoshiro256starstar_double(void* st) nogil: + return uint64_to_double(xoshiro256starstar_next64(st)) + +cdef class Xoshiro256StarStar: + """ + Xoshiro256StarStar(seed=None) + + Container for the xoshiro256** pseudo-random number generator. + + Parameters + ---------- + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + then ``Xoshiro256StarStar`` will try to read data from + ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + + Notes + ----- + xoshiro256** is written by David Blackman and Sebastiano Vigna. + It is a 64-bit PRNG that uses a carefully linear transformation. + This produces a fast PRNG with excellent statistical quality + [1]_. xoshiro256** has a period of :math:`2^{256} - 1` + and supports jumping the sequence in increments of :math:`2^{128}`, + which allows multiple non-overlapping sequences to be generated. + + ``Xoshiro256StarStar`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``Xoshiro256StarStar`` guarantees that a fixed seed will always produce the + same results. + + See ``Xorshift1024`` for a related PRNG with different periods + (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + + **Parallel Features** + + ``Xoshiro256StarStar`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{128}` random numbers have been generated. This + allow the original sequence to be split so that distinct segments can be used + in each worker process. All generators should be initialized with the same + seed to ensure that the segments come from the same sequence. + + >>> from randomgen import RandomGenerator, Xoshiro256StarStar + >>> rg = [RandomGenerator(Xoshiro256StarStar(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + **State and Seeding** + + The ``Xoshiro256StarStar`` state vector consists of a 4 element array + of 64-bit unsigned integers. + + ``Xoshiro256StarStar`` is seeded using either a single 64-bit unsigned + integer or a vector of 64-bit unsigned integers. In either case, the + input seed is used as an input (or inputs) for another simple random + number generator, Splitmix64, and the output of this PRNG function is + used as the initial state. Using a single 64-bit value for the seed can + only initialize a small range of the possible initial state values. When + using an array, the SplitMix64 state for producing the ith component of + the initial state is XORd with the ith value of the seed array until the + seed array is exhausted. When using an array the initial state for the + SplitMix64 state is 0 so that using a single element array and using the + same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from randomgen import RandomGenerator, Xoshiro256StarStar + >>> rg = RandomGenerator(Xoshiro256StarStar(1234)) + >>> rg.standard_normal() + + Identical method using only Xoshiro256StarStar + + >>> rg = Xoshiro256StarStar(1234).generator + >>> rg.standard_normal() + + References + ---------- + .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", + http://xorshift.di.unimi.it/ + """ + cdef xoshiro256starstar_state *rng_state + cdef brng_t *_brng + cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(xoshiro256starstar_state)) + self._brng = malloc(sizeof(brng_t)) + self.seed(seed) + + self._brng.state = self.rng_state + self._brng.next_uint64 = &xoshiro256starstar_uint64 + self._brng.next_uint32 = &xoshiro256starstar_uint32 + self._brng.next_double = &xoshiro256starstar_double + self._brng.next_raw = &xoshiro256starstar_uint64 + + self._ctypes = None + self._cffi = None + self._generator = None + + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state) + free(self._brng) + + cdef _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): + """Private benchmark command""" + cdef Py_ssize_t i + if method==u'uint64': + for i in range(cnt): + self._brng.next_uint64(self._brng.state) + elif method==u'double': + for i in range(cnt): + self._brng.next_double(self._brng.state) + else: + raise ValueError('Unknown method') + + def seed(self, seed=None): + """ + seed(seed=None) + + Seed the generator. + + This method is called at initialized. It can be called again to + re-seed the generator. + + Parameters + ---------- + seed : {int, ndarray}, optional + Seed for PRNG. Can be a single 64 bit unsigned integer or an array + of 64 bit unsigned integers. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(8) + except RuntimeError: + state = random_entropy(8, 'fallback') + state = state.view(np.uint64) + else: + state = seed_by_array(seed, 4) + self.rng_state.s[0] = int(state[0]) + self.rng_state.s[1] = int(state[1]) + self.rng_state.s[2] = int(state[2]) + self.rng_state.s[3] = int(state[3]) + self._reset_state_variables() + + def jump(self, np.npy_intp iter=1): + """ + jump(iter=1) + + Jumps the state as-if 2**128 random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : Xoshiro256StarStar + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is required + to ensure exact reproducibility. + """ + cdef np.npy_intp i + for i in range(iter): + xoshiro256starstar_jump(self.rng_state) + self._reset_state_variables() + return self + + @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 + """ + state = np.empty(4, dtype=np.uint64) + state[0] = self.rng_state.s[0] + state[1] = self.rng_state.s[1] + state[2] = self.rng_state.s[2] + state[3] = self.rng_state.s[3] + return {'brng': self.__class__.__name__, + 's': state, + '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') + brng = value.get('brng', '') + if brng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + self.rng_state.s[0] = value['s'][0] + self.rng_state.s[1] = value['s'][1] + self.rng_state.s[2] = value['s'][2] + self.rng_state.s[3] = value['s'][3] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] + + @property + def ctypes(self): + """ + Ctypes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoshiro256starstar_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&xoshiro256starstar_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&xoshiro256starstar_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the basic RNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/randomgen/xoshiro512starstar.pyx b/_randomgen/randomgen/xoshiro512starstar.pyx new file mode 100644 index 000000000000..b4ab76158929 --- /dev/null +++ b/_randomgen/randomgen/xoshiro512starstar.pyx @@ -0,0 +1,356 @@ +from __future__ import absolute_import + +from libc.stdlib cimport malloc, free +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + +from randomgen.common import interface +from randomgen.common cimport * +from randomgen.distributions cimport brng_t +from randomgen.entropy import random_entropy, seed_by_array +import randomgen.pickle + +np.import_array() + +cdef extern from "src/xoshiro512starstar/xoshiro512starstar.h": + + struct s_xoshiro512starstar_state: + uint64_t s[8] + int has_uint32 + uint32_t uinteger + + ctypedef s_xoshiro512starstar_state xoshiro512starstar_state + + uint64_t xoshiro512starstar_next64(xoshiro512starstar_state *state) nogil + uint32_t xoshiro512starstar_next32(xoshiro512starstar_state *state) nogil + void xoshiro512starstar_jump(xoshiro512starstar_state *state) + +cdef uint64_t xoshiro512starstar_uint64(void* st) nogil: + return xoshiro512starstar_next64(st) + +cdef uint32_t xoshiro512starstar_uint32(void *st) nogil: + return xoshiro512starstar_next32( st) + +cdef double xoshiro512starstar_double(void* st) nogil: + return uint64_to_double(xoshiro512starstar_next64(st)) + +cdef class Xoshiro512StarStar: + """ + Xoshiro512StarStar(seed=None) + + Container for the xoshiro512** pseudo-random number generator. + + Parameters + ---------- + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in + [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, + then ``Xoshiro512StarStar`` will try to read data from + ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + + Notes + ----- + xoshiro512** is written by David Blackman and Sebastiano Vigna. + It is a 64-bit PRNG that uses a carefully linear transformation. + This produces a fast PRNG with excellent statistical quality + [1]_. xoshiro512** has a period of :math:`2^{512} - 1` + and supports jumping the sequence in increments of :math:`2^{256}`, + which allows multiple non-overlapping sequences to be generated. + + ``Xoshiro512StarStar`` exposes no user-facing API except ``generator``, + ``state``, ``cffi`` and ``ctypes``. Designed for use in a + ``RandomGenerator`` object. + + **Compatibility Guarantee** + + ``Xoshiro512StarStar`` guarantees that a fixed seed will always produce the + same results. + + See ``Xorshift1024`` for a related PRNG with different periods + (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + + **Parallel Features** + + ``Xoshiro512StarStar`` can be used in parallel applications by + calling the method ``jump`` which advances the state as-if + :math:`2^{128}` random numbers have been generated. This + allow the original sequence to be split so that distinct segments can be used + in each worker process. All generators should be initialized with the same + seed to ensure that the segments come from the same sequence. + + >>> from randomgen import RandomGenerator, Xoshiro512StarStar + >>> rg = [RandomGenerator(Xoshiro512StarStar(1234)) for _ in range(10)] + # Advance rs[i] by i jumps + >>> for i in range(10): + ... rg[i].jump(i) + + **State and Seeding** + + The ``Xoshiro512StarStar`` state vector consists of a 4 element array + of 64-bit unsigned integers. + + ``Xoshiro512StarStar`` is seeded using either a single 64-bit unsigned + integer or a vector of 64-bit unsigned integers. In either case, the + input seed is used as an input (or inputs) for another simple random + number generator, Splitmix64, and the output of this PRNG function is + used as the initial state. Using a single 64-bit value for the seed can + only initialize a small range of the possible initial state values. When + using an array, the SplitMix64 state for producing the ith component of + the initial state is XORd with the ith value of the seed array until the + seed array is exhausted. When using an array the initial state for the + SplitMix64 state is 0 so that using a single element array and using the + same value as a scalar will produce the same initial state. + + Examples + -------- + >>> from randomgen import RandomGenerator, Xoshiro512StarStar + >>> rg = RandomGenerator(Xoshiro512StarStar(1234)) + >>> rg.standard_normal() + + Identical method using only Xoshiro512StarStar + + >>> rg = Xoshiro512StarStar(1234).generator + >>> rg.standard_normal() + + References + ---------- + .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", + http://xorshift.di.unimi.it/ + """ + cdef xoshiro512starstar_state *rng_state + cdef brng_t *_brng + cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef object _generator + + def __init__(self, seed=None): + self.rng_state = malloc(sizeof(xoshiro512starstar_state)) + self._brng = malloc(sizeof(brng_t)) + self.seed(seed) + + self._brng.state = self.rng_state + self._brng.next_uint64 = &xoshiro512starstar_uint64 + self._brng.next_uint32 = &xoshiro512starstar_uint32 + self._brng.next_double = &xoshiro512starstar_double + self._brng.next_raw = &xoshiro512starstar_uint64 + + self._ctypes = None + self._cffi = None + self._generator = None + + cdef const char *name = "BasicRNG" + self.capsule = PyCapsule_New(self._brng, name, NULL) + + # Pickling support: + def __getstate__(self): + return self.state + + def __setstate__(self, state): + self.state = state + + def __reduce__(self): + return (randomgen.pickle.__brng_ctor, + (self.state['brng'],), + self.state) + + def __dealloc__(self): + free(self.rng_state) + free(self._brng) + + cdef _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): + """Private benchmark command""" + cdef Py_ssize_t i + if method==u'uint64': + for i in range(cnt): + self._brng.next_uint64(self._brng.state) + elif method==u'double': + for i in range(cnt): + self._brng.next_double(self._brng.state) + else: + raise ValueError('Unknown method') + + def seed(self, seed=None): + """ + seed(seed=None) + + Seed the generator. + + This method is called at initialized. It can be called again to + re-seed the generator. + + Parameters + ---------- + seed : {int, ndarray}, optional + Seed for PRNG. Can be a single 64 bit unsigned integer or an array + of 64 bit unsigned integers. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + ub = 2 ** 64 + if seed is None: + try: + state = random_entropy(2 * 8) + except RuntimeError: + state = random_entropy(8, 'fallback') + state = state.view(np.uint64) + else: + state = seed_by_array(seed, 8) + for i in range(8): + self.rng_state.s[i] = int(state[i]) + self._reset_state_variables() + + def jump(self, np.npy_intp iter=1): + """ + jump(iter=1) + + Jumps the state as-if 2**256 random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the rng. + + Returns + ------- + self : Xoshiro512StarStar + PRNG jumped iter times + + Notes + ----- + Jumping the rng state resets any pre-computed random numbers. This is required + to ensure exact reproducibility. + """ + cdef np.npy_intp i + for i in range(iter): + xoshiro512starstar_jump(self.rng_state) + self._reset_state_variables() + return self + + @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 + """ + state = np.empty(8, dtype=np.uint64) + for i in range(8): + state[i] = self.rng_state.s[i] + return {'brng': self.__class__.__name__, + 's': state, + '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') + brng = value.get('brng', '') + if brng != self.__class__.__name__: + raise ValueError('state must be for a {0} ' + 'PRNG'.format(self.__class__.__name__)) + for i in range(8): + self.rng_state.s[i] = value['s'][i] + self.rng_state.has_uint32 = value['has_uint32'] + self.rng_state.uinteger = value['uinteger'] + + @property + def ctypes(self): + """ + Ctypes 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 + * brng - pointer to the Basic RNG struct + """ + + if self._ctypes is not None: + return self._ctypes + + import ctypes + + self._ctypes = interface(self.rng_state, + ctypes.c_void_p(self.rng_state), + ctypes.cast(&xoshiro512starstar_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(&xoshiro512starstar_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(&xoshiro512starstar_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(self._brng)) + 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 + * brng - pointer to the Basic RNG struct + """ + if self._cffi is not None: + return self._cffi + try: + import cffi + except ImportError: + raise ImportError('cffi is cannot be imported.') + + ffi = cffi.FFI() + self._cffi = interface(self.rng_state, + ffi.cast('void *',self.rng_state), + ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), + ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), + ffi.cast('double (*)(void *)',self._brng.next_double), + ffi.cast('void *',self._brng)) + return self.cffi + + @property + def generator(self): + """ + Return a RandomGenerator object + + Returns + ------- + gen : randomgen.generator.RandomGenerator + Random generator used this instance as the basic RNG + """ + if self._generator is None: + from .generator import RandomGenerator + self._generator = RandomGenerator(self) + return self._generator \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 5a1f5f9eff10..47e1eb583a6b 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -204,6 +204,30 @@ extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS ), + Extension("randomgen.xoshiro256starstar", + ["randomgen/xoshiro256starstar.pyx", + join(MOD_DIR, 'src', 'xoshiro256starstar', + 'xoshiro256starstar.c')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join( + MOD_DIR, 'src', + 'xoshiro256starstar')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), + Extension("randomgen.xoshiro512starstar", + ["randomgen/xoshiro512starstar.pyx", + join(MOD_DIR, 'src', 'xoshiro512starstar', + 'xoshiro512starstar.c')], + include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), + join( + MOD_DIR, 'src', + 'xoshiro512starstar')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS + ), Extension("randomgen.generator", ["randomgen/generator.pyx", join(MOD_DIR, 'src', 'distributions', @@ -278,8 +302,9 @@ def is_pure(self): version=versioneer.get_version(), classifiers=classifiers, cmdclass=versioneer.get_cmdclass(), - ext_modules=cythonize(extensions, compile_time_env={ - "PCG_EMULATED_MATH": PCG_EMULATED_MATH}), + ext_modules=cythonize(extensions, + compile_time_env={"PCG_EMULATED_MATH": PCG_EMULATED_MATH}, + compiler_directives={'language_level': '3'}), packages=find_packages(), package_dir={'randomgen': './randomgen'}, package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in'], From 9dac6a5bb80cf7e9904154f24a486659837b9919 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 5 Nov 2018 23:32:22 +0000 Subject: [PATCH 098/138] MAINT: Sync with upstream changes Sync upstream changes in numpy/numpy#11613, numpy/numpy#11771, and numpy/numpy#12089 Update to NumPy 1.12 as the minimum version Fix documentation Add information about Lemire generator Update change log Fix docstring for randint Refactor benchmark with more options Clean code for PEP8 violations Improve performance testing --- _randomgen/.travis.yml | 10 +- _randomgen/README.md | 11 +- _randomgen/README.rst | 11 +- _randomgen/benchmark.py | 173 +++++++----------- _randomgen/doc/source/change-log.rst | 12 +- _randomgen/doc/source/conf.py | 2 - _randomgen/doc/source/index.rst | 5 + _randomgen/doc/source/new-or-different.rst | 9 + _randomgen/doc/source/performance.py | 23 +-- _randomgen/doc/source/references.rst | 5 + _randomgen/randomgen/common.pxd | 1 + _randomgen/randomgen/common.pyx | 5 +- _randomgen/randomgen/generator.pyx | 18 +- .../randomgen/tests/test_numpy_mt19937.py | 20 +- .../tests/test_numpy_mt19937_regressions.py | 22 +++ 15 files changed, 177 insertions(+), 150 deletions(-) create mode 100644 _randomgen/doc/source/references.rst diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index bc483fb97ec4..10eba96d243b 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -20,15 +20,15 @@ matrix: fast_finish: true include: - os: linux - env: [PYTHON=2.7, NUMPY=1.10, CYTHON=0.26] + env: [PYTHON=2.7, NUMPY=1.13, CYTHON=0.26] - os: linux - env: [PYTHON=3.5, NUMPY=1.11] + env: [PYTHON=3.5, NUMPY=1.13] - os: linux - env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.27] + env: [PYTHON=3.6, NUMPY=1.14, CYTHON=0.27] - os: linux - env: [PYTHON=3.6, NUMPY=1.13, CYTHON=0.26] + env: [PYTHON=3.6, NUMPY=1.15, CYTHON=0.28] - os: linux - env: [PYTHON=3.6, DOCBUILD=true] + env: [PYTHON=3.7, DOCBUILD=true] - os: osx language: generic env: [PYTHON=3.6] diff --git a/_randomgen/README.md b/_randomgen/README.md index de392c52801e..34986ebdb45d 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -68,6 +68,9 @@ which can fully reproduce the sequence produced by NumPy. * Normals (`standard_normal`) * Standard Gammas (via `standard_gamma`) +* Support for Lemire's method of generating uniform integers on an + arbitrary interval by setting `use_masked=True`. + ## Included Pseudo Random Number Generators This module includes a number of alternative random @@ -103,6 +106,10 @@ The RNGs include: * Core random number generators can fill existing arrays using the `out` keyword argument * Standardizes integer-values random values as int64 for all platforms. +* `randint` supports generating using rejection sampling on masked + values (the default) or Lemire's method. Lemire's method can be much + faster when the required interval length is much smaller than the + closes power of 2. ### New Functions @@ -150,8 +157,8 @@ need to be smoothed. ## Requirements Building requires: -* Python (2.7, 3.4, 3.5, 3.6) -* NumPy (1.11, 1.12, 1.13, 1.14, 1.15) +* Python (2.7, 3.5, 3.6, 3.7) +* NumPy (1.13, 1.14, 1.15) * Cython (0.26+) * tempita (0.5+), if not provided by Cython diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 814b1272b817..69de75ab3811 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -71,6 +71,9 @@ Features - Normals (``standard_normal``) - Standard Gammas (via ``standard_gamma``) +- Support for Lemire’s method of generating uniform integers on an + arbitrary interval by setting ``use_masked=True``. + Included Pseudo Random Number Generators ---------------------------------------- @@ -111,6 +114,10 @@ New Features - Core random number generators can fill existing arrays using the ``out`` keyword argument - Standardizes integer-values random values as int64 for all platforms. +- ``randint`` supports generating using rejection sampling on masked + values (the default) or Lemire’s method. Lemire’s method can be much + faster when the required interval length is much smaller than the + closes power of 2. New Functions ~~~~~~~~~~~~~ @@ -166,8 +173,8 @@ Requirements Building requires: -- Python (2.7, 3.4, 3.5, 3.6) -- NumPy (1.11, 1.12, 1.13, 1.14, 1.15) +- Python (2.7, 3.5, 3.6, 3.7) +- NumPy (1.13, 1.14, 1.15) - Cython (0.26+) - tempita (0.5+), if not provided by Cython diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py index 860134de1289..c4c4ab93d8f6 100644 --- a/_randomgen/benchmark.py +++ b/_randomgen/benchmark.py @@ -84,122 +84,67 @@ def timer_uniform(): run_timer(dist, command, None, SETUP, 'Uniforms') -def timer_8bit_bounded(max=95, use_masked=True): - min = 0 +def timer_bounded(bits=8, max=95, use_masked=True): + """ + Timer for 8-bit bounded values. + + Parameters + ---------- + bits : {8, 16, 32, 64} + Bit width of unsigned output type + max : int + Upper bound for range. Lower is always 0. Must be <= 2**bits. + use_masked: bool + If True, masking and rejection sampling is used to generate a random + number in an interval. If False, Lemire's algorithm is used if + available to generate a random number in an interval. + + Notes + ----- + Lemire's algorithm has improved performance when {max}+1 is not a + power of two. + """ + if bits not in (8, 16, 32, 64): + raise ValueError('bits must be one of 8, 16, 32, 64.') + minimum = 0 dist = 'random_uintegers' - # Note on performance of generating random numbers in an interval: - # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. - # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. - # Lemire's algorithm has improved performance when {max}+1 is not a power of two. + if use_masked: # Use masking & rejection. + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits}, use_masked=True)' + else: # Use Lemire's algo. + command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits}, use_masked=False)' - if use_masked: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8, use_masked=True)' # Use masking & rejection. - else: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8, use_masked=False)' # Use Lemire's algo. + command = command.format(min=minimum, max=max, bits=bits) - command = command.format(min=min, max=max) - - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint8)' - command_numpy = command_numpy.format(min=min, max=max) + command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits})' + command_numpy = command_numpy.format(min=minimum, max=max, bits=bits) run_timer(dist, command, command_numpy, SETUP, - '8-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) - - -def timer_16bit_bounded(max=1535, use_masked=True): - min = 0 - - dist = 'random_uintegers' - - # Note on performance of generating random numbers in an interval: - # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. - # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. - # Lemire's algorithm has improved performance when {max}+1 is not a power of two. - - if use_masked: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16, use_masked=True)' # Use masking & rejection. - else: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16, use_masked=False)' # Use Lemire's algo. - - command = command.format(min=min, max=max) - - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint16)' - command_numpy = command_numpy.format(min=min, max=max) - - run_timer(dist, command, command_numpy, SETUP, - '16-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) + '{bits}-bit bounded unsigned integers (max={max}, ' + 'use_masked={use_masked})'.format(max=max, use_masked=use_masked, bits=bits)) def timer_32bit(): info = np.iinfo(np.uint32) - min, max = info.min, info.max + minimum, maximum = info.min, info.max dist = 'random_uintegers' command = 'rg.random_uintegers(1000000, 32)' command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' - command_numpy = command_numpy.format(min=min, max=max) + command_numpy = command_numpy.format(min=minimum, max=maximum) run_timer(dist, command, command_numpy, SETUP, '32-bit unsigned integers') -def timer_32bit_bounded(max=1535, use_masked=True): - min = 0 - - dist = 'random_uintegers' - - # Note on performance of generating random numbers in an interval: - # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. - # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. - # Lemire's algorithm has improved performance when {max}+1 is not a power of two. - - if use_masked: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=True)' # Use masking & rejection. - else: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32, use_masked=False)' # Use Lemire's algo. - - command = command.format(min=min, max=max) - - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' - command_numpy = command_numpy.format(min=min, max=max) - - run_timer(dist, command, command_numpy, SETUP, - '32-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) - - def timer_64bit(): info = np.iinfo(np.uint64) - min, max = info.min, info.max + minimum, maximum = info.min, info.max dist = 'random_uintegers' command = 'rg.random_uintegers(1000000)' command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64)' - command_numpy = command_numpy.format(min=min, max=max) + command_numpy = command_numpy.format(min=minimum, max=maximum) run_timer(dist, command, command_numpy, SETUP, '64-bit unsigned integers') -def timer_64bit_bounded(max=1535, use_masked=True): - min = 0 - - dist = 'random_uintegers' - - # Note on performance of generating random numbers in an interval: - # use_masked=True : masking and rejection sampling is used to generate a random number in an interval. - # use_masked=False : Lemire's algorithm is used if available to generate a random number in an interval. - # Lemire's algorithm has improved performance when {max}+1 is not a power of two. - - if use_masked: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64, use_masked=True)' # Use masking & rejection. - else: - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64, use_masked=False)' # Use Lemire's algo. - - command = command.format(min=min, max=max) - - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64)' - command_numpy = command_numpy.format(min=min, max=max) - - run_timer(dist, command, command_numpy, SETUP, - '64-bit bounded unsigned integers (max={max}, use_masked={use_masked})'.format(max=max, use_masked=use_masked)) - - def timer_normal_zig(): dist = 'standard_normal' command = 'rg.standard_normal(1000000)' @@ -210,35 +155,47 @@ def timer_normal_zig(): if __name__ == '__main__': import argparse + parser = argparse.ArgumentParser() - parser.add_argument('--full', dest='full', action='store_true') + parser.add_argument('-f', '--full', + help='Run benchmarks for a wide range of distributions.' + ' If not provided, only tests the production of ' + 'uniform values.', + dest='full', action='store_true') + parser.add_argument('-bi', '--bounded-ints', + help='Included benchmark coverage of the bounded ' + 'integer generators in a full run.', + dest='bounded_ints', action='store_true') args = parser.parse_args() timer_uniform() if args.full: timer_raw() - timer_8bit_bounded(use_masked=True) - timer_8bit_bounded(max=64, use_masked=False) # Worst case for Numpy. - timer_8bit_bounded(max=95, use_masked=False) # Typ. avrg. case for Numpy. - timer_8bit_bounded(max=127, use_masked=False) # Best case for Numpy. + if args.bounded_ints: + timer_bounded(use_masked=True) + timer_bounded(max=64, use_masked=False) # Worst case for Numpy. + timer_bounded(max=95, use_masked=False) # Typ. avrg. case for Numpy. + timer_bounded(max=127, use_masked=False) # Best case for Numpy. - timer_16bit_bounded(use_masked=True) - timer_16bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. - timer_16bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_16bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + timer_bounded(16, use_masked=True) + timer_bounded(16, max=1024, use_masked=False) # Worst case for Numpy. + timer_bounded(16, max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_bounded(16, max=2047, use_masked=False) # Best case for Numpy. timer_32bit() - timer_32bit_bounded(use_masked=True) - timer_32bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. - timer_32bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_32bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + if args.bounded_ints: + timer_bounded(32, use_masked=True) + timer_bounded(32, max=1024, use_masked=False) # Worst case for Numpy. + timer_bounded(32, max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_bounded(32, max=2047, use_masked=False) # Best case for Numpy. timer_64bit() - timer_64bit_bounded(use_masked=True) - timer_64bit_bounded(max=1024, use_masked=False) # Worst case for Numpy. - timer_64bit_bounded(max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_64bit_bounded(max=2047, use_masked=False) # Best case for Numpy. + if args.bounded_ints: + timer_bounded(64, use_masked=True) + timer_bounded(64, max=1024, use_masked=False) # Worst case for Numpy. + timer_bounded(64, max=1535, use_masked=False) # Typ. avrg. case for Numpy. + timer_bounded(64, max=2047, use_masked=False) # Best case for Numpy. timer_normal_zig() diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 29876a4b99b7..629dd000281d 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,12 +1,12 @@ Change Log ---------- -After v1.15 -=========== -- Added Xoshiro256** and Xoshiro512**, the preferred generators of this class -- Fixed bug in `jump` method of Random123 generators which did nto specify a default value - - +v1.15.1 +======= +- Added Xoshiro256** and Xoshiro512**, the preferred generators of this class. +- Fixed bug in `jump` method of Random123 generators which did nto specify a default value. +- Added support for generating bounded uniform integers using Lemire's method. +- Synchronized with upstream changes, which requires moving the minimum supported NumPy to 1.13. v1.15 ===== diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py index c89900b5579f..4b38c42d5370 100644 --- a/_randomgen/doc/source/conf.py +++ b/_randomgen/doc/source/conf.py @@ -15,9 +15,7 @@ # import os # import sys # sys.path.insert(0, os.path.abspath('.')) -from distutils.version import LooseVersion import guzzle_sphinx_theme -# import sphinx_rtd_theme import randomgen # -- Project information ----------------------------------------------------- diff --git a/_randomgen/doc/source/index.rst b/_randomgen/doc/source/index.rst index 7db6cbd5b428..eac8c1ef12e8 100644 --- a/_randomgen/doc/source/index.rst +++ b/_randomgen/doc/source/index.rst @@ -119,6 +119,10 @@ What's New or Different these basic RNGs to be used in numba. * The basic random number generators can be used in downstream projects via Cython. +* Support for Lemire’s method [Lemire]_ of generating uniform integers on an + arbitrary interval by setting ``use_masked=True`` in + (:meth:`~randomgen.generator.RandomGenerator.randint`). + See :ref:`new-or-different` for a complete list of improvements and differences. @@ -205,6 +209,7 @@ New Features Comparing Performance extending Reading System Entropy + references Changes ~~~~~~~ diff --git a/_randomgen/doc/source/new-or-different.rst b/_randomgen/doc/source/new-or-different.rst index c94d95c7c094..6598c13feb36 100644 --- a/_randomgen/doc/source/new-or-different.rst +++ b/_randomgen/doc/source/new-or-different.rst @@ -87,3 +87,12 @@ What's New or Different print(existing) .. * For changes since the previous release, see the :ref:`change-log` + +* Support for Lemire’s method of generating uniform integers on an + arbitrary interval by setting ``use_masked=True`` in + (:meth:`~randomgen.generator.RandomGenerator.randint`). + +.. ipython:: python + + %timeit rg.randint(0, 1535, use_masked=False) + %timeit numpy.random.randint(0, 1535) diff --git a/_randomgen/doc/source/performance.py b/_randomgen/doc/source/performance.py index d84c3147e398..12cbbc5d38f0 100644 --- a/_randomgen/doc/source/performance.py +++ b/_randomgen/doc/source/performance.py @@ -1,11 +1,14 @@ +from collections import OrderedDict +from timeit import repeat + import numpy as np -from timeit import timeit, repeat import pandas as pd from randomgen import MT19937, DSFMT, ThreeFry, PCG64, Xoroshiro128, \ - Xorshift1024, Philox + Xorshift1024, Philox, Xoshiro256StarStar, Xoshiro512StarStar -PRNGS = [DSFMT, MT19937, Philox, PCG64, ThreeFry, Xoroshiro128, Xorshift1024] +PRNGS = [DSFMT, MT19937, Philox, PCG64, ThreeFry, Xoroshiro128, Xorshift1024, + Xoshiro256StarStar, Xoshiro512StarStar] funcs = {'32-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', '64-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', @@ -24,20 +27,19 @@ """ test = "rg.{func}" -table = {} +table = OrderedDict() for prng in PRNGS: print(prng) - col = {} + col = OrderedDict() for key in funcs: t = repeat(test.format(func=funcs[key]), setup.format(prng=prng().__class__.__name__), number=1, repeat=3) - col[key]= 1000 * min(t) + col[key] = 1000 * min(t) col = pd.Series(col) table[prng().__class__.__name__] = col - -npfuncs = {} +npfuncs = OrderedDict() npfuncs.update(funcs) npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)' npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)' @@ -54,7 +56,6 @@ col[key] = 1000 * min(t) table['NumPy'] = pd.Series(col) - table = pd.DataFrame(table) table = table.reindex(table.mean(1).sort_values().index) order = np.log(table).mean().sort_values().index @@ -63,11 +64,11 @@ table = table.T print(table.to_csv(float_format='%0.1f')) -rel = table / (table.iloc[:,[0]].values @ np.ones((1,8))) +rel = table.loc[:, ['NumPy']].values @ np.ones((1, table.shape[1])) / table rel.pop(rel.columns[0]) rel = rel.T rel['Overall'] = np.exp(np.log(rel).mean(1)) rel *= 100 rel = np.round(rel) rel = rel.T -print(rel.to_csv(float_format='%0d')) \ No newline at end of file +print(rel.to_csv(float_format='%0d')) diff --git a/_randomgen/doc/source/references.rst b/_randomgen/doc/source/references.rst new file mode 100644 index 000000000000..0dc99868f1e5 --- /dev/null +++ b/_randomgen/doc/source/references.rst @@ -0,0 +1,5 @@ +References +---------- + +.. [Lemire] Daniel Lemire., "Fast Random Integer Generation in an Interval", + CoRR, Aug. 13, 2018, http://arxiv.org/abs/1805.10941. diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd index f6017c0d7504..62163ad62a0d 100644 --- a/_randomgen/randomgen/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -18,6 +18,7 @@ cdef enum ConstraintType: CONS_POSITIVE CONS_BOUNDED_0_1 CONS_BOUNDED_0_1_NOTNAN + CONS_BOUNDED_GT_0_1 CONS_GT_1 CONS_GTE_1 CONS_POISSON diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index b152099eb0cb..eb872d02f15b 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -155,10 +155,13 @@ cdef int check_array_constraint(np.ndarray val, object name, constraint_type con raise ValueError(name + " <= 0") elif cons == CONS_BOUNDED_0_1 or cons == CONS_BOUNDED_0_1_NOTNAN: if np.any(np.less(val, 0)) or np.any(np.greater(val, 1)): - raise ValueError(name + " <= 0 or " + name + " >= 1") + raise ValueError(name + " < 0 or " + name + " > 1") if cons == CONS_BOUNDED_0_1_NOTNAN: if np.any(np.isnan(val)): raise ValueError(name + ' contains NaNs') + elif cons == CONS_BOUNDED_GT_0_1: + if np.any(np.less_equal(val, 0)) or np.any(np.greater(val, 1)): + raise ValueError(name + " <= 0 or " + name + " > 1") elif cons == CONS_GT_1: if np.any(np.less_equal(val, 1)): raise ValueError(name + " <= 1") diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index ca6c6af24896..5d239c725f76 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -574,7 +574,7 @@ cdef class RandomGenerator: def randint(self, low, high=None, size=None, dtype=int, use_masked=True): """ - randint(low, high=None, size=None, dtype='l') + randint(low, high=None, size=None, dtype='l', use_masked=True) Return random integers from `low` (inclusive) to `high` (exclusive). @@ -652,6 +652,11 @@ cdef class RandomGenerator: >>> randomgen.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) + + References + ---------- + .. [1] Daniel Lemire., "Fast Random Integer Generation in an Interval", + CoRR, Aug. 13, 2018, http://arxiv.org/abs/1805.10941. """ if high is None: high = low @@ -3568,7 +3573,7 @@ cdef class RandomGenerator: """ return disc(&random_geometric, self._brng, size, self.lock, 1, 0, - p, 'p', CONS_BOUNDED_0_1, + p, 'p', CONS_BOUNDED_GT_0_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -4241,9 +4246,8 @@ cdef class RandomGenerator: 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 > 1 and x.size: - # Multidimensional ndarrays require a bounce buffer. - buf = np.empty_like(x[0]) + 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._brng, i) @@ -4312,8 +4316,8 @@ cdef class RandomGenerator: # shuffle has fast-path for 1-d if arr.ndim == 1: - # must return a copy - if arr is x: + # Return a copy if same memory + if np.may_share_memory(arr, x): arr = np.array(arr) self.shuffle(arr) return arr diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 747e10b394c9..888baf92f296 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -437,27 +437,31 @@ def test_randint(self): assert_array_equal(actual, desired) def test_randint_masked(self): - """ Test masked rejection sampling algorithm to generate array of uint32 in an interval. """ + # Test masked rejection sampling algorithm to generate array of + # uint32 in an interval. mt19937.seed(self.seed) - actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=True) + actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, + use_masked=True) desired = np.array([[2, 47], [12, 51], [33, 43]], dtype=np.uint32) assert_array_equal(actual, desired) def test_randint_lemire_32(self): - """ Test lemire algorithm to generate array of uint32 in an interval. """ + # Test lemire algorithm to generate array of uint32 in an interval. mt19937.seed(self.seed) - actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=False) + actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, + use_masked=False) desired = np.array([[61, 33], [58, 14], [87, 23]], dtype=np.uint32) assert_array_equal(actual, desired) def test_randint_lemire_64(self): - """ Test lemire algorithm to generate array of uint64 in an interval. """ + # Test lemire algorithm to generate array of uint64 in an interval. mt19937.seed(self.seed) - actual = mt19937.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), dtype=np.uint64, use_masked=False) + actual = mt19937.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), + dtype=np.uint64, use_masked=False) desired = np.array([[42523252834, 40656066204], [61069871386, 61274051182], [31443797706, 53476677934]], dtype=np.uint64) @@ -621,6 +625,10 @@ def test_shuffle(self): 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), diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py index 1f082925e589..4e51327aa160 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py @@ -136,3 +136,25 @@ def test_shuffle_of_array_of_objects(self): # Force Garbage Collection - should not segfault. import gc gc.collect() + + def test_permutation_subclass(self): + class N(np.ndarray): + pass + + mt19937.seed(1) + orig = np.arange(3).view(N) + perm = mt19937.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 + + mt19937.seed(1) + m = M() + perm = mt19937.permutation(m) + assert_array_equal(perm, np.array([2, 1, 4, 0, 3])) + assert_array_equal(m.__array__(), np.arange(5)) From 578889bf65adedbbee9af8125dab35a965d4b6fa Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 4 Feb 2019 15:41:04 +0000 Subject: [PATCH 099/138] BUG: Ensure buffer_loc is reset in DSFMT Ensure buffer location is reset after reseed or jump to ensure that values are produced from the new state and not reused from the old. Ensure that the fallback path uses the correct number of bytes in Xor* Small doc fixes. Update dirichlet documentation Update beta docstring Fix weibull for a=0 --- _randomgen/doc/source/change-log.rst | 11 ++++++ _randomgen/randomgen/common.pxd | 2 + _randomgen/randomgen/distributions.pxd | 2 + _randomgen/randomgen/dsfmt.pyx | 18 ++++++--- _randomgen/randomgen/generator.pyx | 38 +++++++++++++------ .../randomgen/legacy/legacy_distributions.pxd | 2 + _randomgen/randomgen/mt19937.pyx | 4 +- .../src/distributions/distributions.c | 3 ++ _randomgen/randomgen/tests/test_direct.py | 6 +++ .../randomgen/tests/test_numpy_mt19937.py | 3 +- _randomgen/randomgen/xorshift1024.pyx | 2 +- _randomgen/randomgen/xoshiro512starstar.pyx | 4 +- 12 files changed, 73 insertions(+), 22 deletions(-) diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 629dd000281d..eb884c7f3fd7 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,5 +1,16 @@ Change Log ---------- +v1.15.2 +======= +- Fixed a bug that affected :class:`~randomgen.dsfmt.DSFMT` when calling + :func:`~randomgen.dsfmt.DSFMT.jump` or :func:`~randomgen.dsfmt.DSFMT.seed` + that failed to reset the buffer. This resulted in upto 381 values from the + previous state being used before the buffer was refilled at the new state. +- Fixed bugs in :class:`~randomgen.xoshiro512starstar.Xoshiro512StarStar` + and :class:`~randomgen.xorshift1024.Xorshift1024` where the fallback + entropy initialization used too few bytes. This bug is unlikely to be + encountered since this path is only encountered if the system random + number generator fails. v1.15.1 ======= diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd index 62163ad62a0d..63a1b3f7d09f 100644 --- a/_randomgen/randomgen/common.pxd +++ b/_randomgen/randomgen/common.pxd @@ -1,3 +1,5 @@ +#cython: language_level=3 + from __future__ import absolute_import from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd index a50d5d821173..35d92db51bbb 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/_randomgen/randomgen/distributions.pxd @@ -1,3 +1,5 @@ +#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) import numpy as np diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx index c83ade5cdf2f..ee8ef270d000 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/_randomgen/randomgen/dsfmt.pyx @@ -79,8 +79,8 @@ cdef class DSFMT: Can be an integer in [0, 2**32-1], array of integers in [0, 2**32-1] or ``None`` (the default). If `seed` is ``None``, then ``DSFMT`` will try to read entropy from ``/dev/urandom`` - (or the Windows analog) if available to produce a 64-bit - seed. If unavailable, a 64-bit hash of the time and process + (or the Windows analog) if available to produce a 32-bit + seed. If unavailable, a 32-bit hash of the time and process ID is used. Notes @@ -114,7 +114,7 @@ cdef class DSFMT: The ``DSFMT`` state vector consists of a 384 element array of 64-bit unsigned integers plus a single integer value between 0 and 382 indicating the current position within the main array. The implementation - used here augments this with a 384 element array of doubles which are used + used here augments this with a 382 element array of doubles which are used to efficiently access the random numbers produced by the dSFMT generator. ``DSFMT`` is seeded using either a single 32-bit unsigned integer @@ -182,6 +182,10 @@ cdef class DSFMT: free(self.rng_state) free(self._brng) + cdef _reset_state_variables(self): + self.rng_state.buffer_loc = DSFMT_N64 + + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): cdef Py_ssize_t i if method==u'uint64': @@ -206,8 +210,8 @@ cdef class DSFMT: Can be an integer in [0, 2**32-1], array of integers in [0, 2**32-1] or ``None`` (the default). If `seed` is ``None``, then ``DSFMT`` will try to read entropy from ``/dev/urandom`` - (or the Windows analog) if available to produce a 64-bit - seed. If unavailable, a 64-bit hash of the time and process + (or the Windows analog) if available to produce a 32-bit + seed. If unavailable, a 32-bit hash of the time and process ID is used. Raises @@ -238,6 +242,8 @@ cdef class DSFMT: dsfmt_init_by_array(self.rng_state.state, obj.data, np.PyArray_DIM(obj, 0)) + # Clear the buffer + self._reset_state_variables() def jump(self, np.npy_intp iter=1): """ @@ -258,6 +264,8 @@ cdef class DSFMT: cdef np.npy_intp i for i in range(iter): dsfmt_jump(self.rng_state) + # Clear the buffer + self._reset_state_variables() return self @property diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 5d239c725f76..01fa7f1be1b7 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -385,9 +385,9 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Alpha, non-negative. + Alpha, positive (>0). b : float or array_like of floats - Beta, non-negative. + 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), @@ -2355,7 +2355,7 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Shape of the distribution. Should be greater than zero. + 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), @@ -4068,8 +4068,9 @@ cdef class RandomGenerator: 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 ---------- @@ -4086,15 +4087,30 @@ cdef class RandomGenerator: 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 ----- - .. 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`. + + 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. - 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 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 ---------- diff --git a/_randomgen/randomgen/legacy/legacy_distributions.pxd b/_randomgen/randomgen/legacy/legacy_distributions.pxd index d22d6a73aacf..e2157f70605f 100644 --- a/_randomgen/randomgen/legacy/legacy_distributions.pxd +++ b/_randomgen/randomgen/legacy/legacy_distributions.pxd @@ -1,3 +1,5 @@ +#cython: language_level=3 + from libc.stdint cimport uint64_t import numpy as np diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index 14ab24f39878..207ebc4bd578 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -206,8 +206,8 @@ cdef class MT19937: Can be an integer in [0, 2**32-1], array of integers in [0, 2**32-1] or ``None`` (the default). If `seed` is ``None``, then ``MT19937`` will try to read entropy from ``/dev/urandom`` - (or the Windows analog) if available to produce a 64-bit - seed. If unavailable, a 64-bit hash of the time and process + (or the Windows analog) if available to produce a 32-bit + seed. If unavailable, a 32-bit hash of the time and process ID is used. Raises diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index e04259136e93..4e7493afaac0 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -573,6 +573,9 @@ double random_pareto(brng_t *brng_state, double a) { } double random_weibull(brng_t *brng_state, double a) { + if (a == 0.0) { + return 0.0; + } return pow(standard_exponential_zig(brng_state), 1. / a); } diff --git a/_randomgen/randomgen/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py index ee69d54163b1..5d251a3b71e3 100644 --- a/_randomgen/randomgen/tests/test_direct.py +++ b/_randomgen/randomgen/tests/test_direct.py @@ -428,6 +428,12 @@ def test_uniform_float(self): assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) + def test_buffer_reset(self): + rs = RandomGenerator(self.brng(*self.data1['seed'])) + u = rs.random_sample(1) + rs.seed(*self.data1['seed']) + assert rs.state['buffer_loc'] == 382 + class TestThreeFry32(Base): @classmethod diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index 888baf92f296..df458f2eee83 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -1104,7 +1104,8 @@ def test_weibull(self): assert_array_almost_equal(actual, desired, decimal=15) def test_weibull_0(self): - assert_equal(mt19937.weibull(a=0), 0) + mt19937.seed(self.seed) + assert_equal(mt19937.weibull(a=0, size=12), np.zeros(12)) assert_raises(ValueError, mt19937.weibull, a=-0.) def test_zipf(self): diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index bf8f32e90de4..8341985b4c58 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -234,7 +234,7 @@ cdef class Xorshift1024: try: state = random_entropy(32) except RuntimeError: - state = random_entropy(4, 'fallback') + state = random_entropy(32, 'fallback') state = state.view(np.uint64) else: state = seed_by_array(seed, 16) diff --git a/_randomgen/randomgen/xoshiro512starstar.pyx b/_randomgen/randomgen/xoshiro512starstar.pyx index b4ab76158929..17fe3c420192 100644 --- a/_randomgen/randomgen/xoshiro512starstar.pyx +++ b/_randomgen/randomgen/xoshiro512starstar.pyx @@ -201,9 +201,9 @@ cdef class Xoshiro512StarStar: ub = 2 ** 64 if seed is None: try: - state = random_entropy(2 * 8) + state = random_entropy(16) except RuntimeError: - state = random_entropy(8, 'fallback') + state = random_entropy(16, 'fallback') state = state.view(np.uint64) else: state = seed_by_array(seed, 8) From 896f2e468958d6f77c7e8dbdf5a546f4560516ed Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 4 Feb 2019 16:47:07 +0000 Subject: [PATCH 100/138] BUG: Raise on nan probabilities --- _randomgen/.travis.yml | 30 +- _randomgen/README.md | 6 + _randomgen/README.rst | 7 + _randomgen/ci/conda-install.sh | 20 ++ _randomgen/ci/pypi-install.sh | 3 + _randomgen/doc/source/change-log.rst | 3 +- _randomgen/doc/source/conf.py | 13 + _randomgen/randomgen/__init__.py | 3 +- _randomgen/randomgen/entropy.pyx | 4 +- .../randomgen/examples/cython/extending.pyx | 2 +- _randomgen/randomgen/generator.pyx | 280 +++++++++--------- _randomgen/randomgen/legacy/legacy.pyx | 97 +++--- _randomgen/randomgen/mt19937.pyx | 18 +- _randomgen/randomgen/pcg64.pyx | 4 +- _randomgen/randomgen/tests/test_direct.py | 3 +- .../randomgen/tests/test_numpy_mt19937.py | 5 + _randomgen/randomgen/threefry.pyx | 2 +- _randomgen/randomgen/xoroshiro128.pyx | 18 +- _randomgen/randomgen/xorshift1024.pyx | 16 +- _randomgen/requirements.txt | 2 +- _randomgen/setup.py | 3 +- 21 files changed, 298 insertions(+), 241 deletions(-) create mode 100644 _randomgen/ci/conda-install.sh create mode 100644 _randomgen/ci/pypi-install.sh diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml index 10eba96d243b..89c5be3fad84 100644 --- a/_randomgen/.travis.yml +++ b/_randomgen/.travis.yml @@ -1,7 +1,3 @@ -# Travis script that uses miniconda in place of the system installed python -# versions. Allows substantial flexability for choosing versions of -# required packages and is simpler to use to test up-to-date scientific Python -# stack group: edge dist: trusty sudo: required @@ -11,6 +7,7 @@ env: global: # Doctr deploy key for bashtage/randomgen - secure: "czwFlflS1lcfbSQ9ktv+pLAPV9/6+wmwiMTyIYyv5xgQVWRL5NRebWH+ZhQ6s2T5x17wFMtlafcAvkdV0CHQZLru34V2UNldCapuEtQ8b32EDHBXHKbs45b7SSkLx4TFXdjiJurleY4ZIKle0gX6BW21zYBwaHJqbN6I8nRv9Rp47XEU1UV1Mdf/PhfTnxY31rFrPYL77xeWJzoFfT8zao39V4gQds+1Ag7FjdNVdSDVKwDduF4kS7tIbKqb4M+jsbc3PIKyP9nyQpEQF5ebJuG7mqXJhVJGEL83rBx8MLFPA/1X3cUzKacgKyp2+Wmlt0EVhwCa1aRf9cSK6I7TbMC7/eGtDnC2ToiRlFJurVRblaEmhzVQS1yQ4Dkooqsj9hNVl6nhu7JfR52GLogns33Ec/yYuRcWcULKSlR5Cerfef/5YijBEhlr9X76SJiOpjvS4lwWFYX+h8xzuVhRLGwIVB9oQNllxYItzcDSGmRx+EOMXWASHmoUDnBOZg4GMVukqOcF5l0ynoepiA1YHLdZlMy6SB3P7BZKF/aNCOn9nXw+N9X4U/yUpkM3Pb7HoGdNrC8RO4SwrNjGrarkdEB6e1lBReK/dqcylaF/mpK9VLpfQszDI8xnR4VCmlEM+le0xOsyHfeGciabdI4KH0i0SfYl4ls5XrN+CaqFWdo=" + - PYPI=false cache: directories: @@ -22,11 +19,14 @@ matrix: - os: linux env: [PYTHON=2.7, NUMPY=1.13, CYTHON=0.26] - os: linux - env: [PYTHON=3.5, NUMPY=1.13] + env: [PYTHON=2.7] - os: linux - env: [PYTHON=3.6, NUMPY=1.14, CYTHON=0.27] + env: [PYTHON=3.5, NUMPY=1.14] - os: linux - env: [PYTHON=3.6, NUMPY=1.15, CYTHON=0.28] + env: [PYTHON=3.6, NUMPY=1.15, CYTHON=0.27] + - os: linux + python: 3.6 + env: [PYPI=true] - os: linux env: [PYTHON=3.7, DOCBUILD=true] - os: osx @@ -36,23 +36,11 @@ matrix: before_install: - git fetch --tags - - if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda3.sh; fi - - if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi - - chmod +x miniconda3.sh - - ./miniconda3.sh -b - - export PATH=${HOME}/miniconda3/bin:$PATH - - conda config --set always_yes true - - conda update --all --quiet - - PKGS="python=${PYTHON}" - - PKGS="${PKGS} numpy"; if [ ${NUMPY} ]; then PKGS="${PKGS}=${NUMPY}"; fi - - PKGS="${PKGS} Cython"; if [ ${CYTHON} ]; then PKGS="${PKGS}=${CYTHON}"; fi - - PKGS="${PKGS} pandas"; if [ ${PANDAS} ]; then PKGS="${PKGS}=${PANDAS}"; fi - - conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet - - source activate randomgen-test + - if [[ $PYPI = true ]]; then source ci/pypi-install.sh; else source ci/conda-install.sh; fi - pip install tempita coverage coveralls pytest-cov codecov -q + - pip list - export BUILD_DIR=${PWD} - if [[ ${DOCBUILD} == true ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi - - if [[ ${DOCBUILD} == true ]]; then conda install numba pandas matplotlib --quiet; fi - gcc --version || true - clang --version || true diff --git a/_randomgen/README.md b/_randomgen/README.md index 34986ebdb45d..53b58b5b2fd5 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -10,6 +10,12 @@ NumPy RandomState evolution. This is a library and generic interface for alternative random generators in Python and NumPy. +## Python 2.7 Support + +Release 1.16.0 is the final version that supports Python 2.7. Any bugs +in v1.16.0 will be patched until the end of 2019. All future releases +are Python 3, with an initial minimum version of 3.5. + ## Compatibility Warning `RandomGenerator` does not support Box-Muller normal variates and so it not diff --git a/_randomgen/README.rst b/_randomgen/README.rst index 69de75ab3811..cfd447f387bb 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -9,6 +9,13 @@ NumPy RandomState evolution. This is a library and generic interface for alternative random generators in Python and NumPy. +Python 2.7 Support +------------------ + +Release 1.16.0 is the final version that supports Python 2.7. Any bugs +in v1.16.0 will be patched until the end of 2019. All future releases +are Python 3, with an initial minimum version of 3.5. + Compatibility Warning --------------------- diff --git a/_randomgen/ci/conda-install.sh b/_randomgen/ci/conda-install.sh new file mode 100644 index 000000000000..cccb8227dcf0 --- /dev/null +++ b/_randomgen/ci/conda-install.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda3.sh; fi +if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi +chmod +x miniconda3.sh +./miniconda3.sh -b +export PATH=${HOME}/miniconda3/bin:$PATH +conda config --set always_yes true +conda update --all --quiet +conda create -n randomgen-test ${PKGS} pip --quiet +source activate randomgen-test + +PKGS="python=${PYTHON} matplotlib numpy" +if [[ -n ${NUMPY} ]]; then PKGS="${PKGS}=${NUMPY}"; fi +PKGS="${PKGS} Cython"; +if [[ -n ${CYTHON} ]]; then PKGS="${PKGS}=${CYTHON}"; fi +PKGS="${PKGS} pandas"; +if [[ -n ${PANDAS} ]]; then PKGS="${PKGS}=${PANDAS}"; fi +echo conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet +conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet diff --git a/_randomgen/ci/pypi-install.sh b/_randomgen/ci/pypi-install.sh new file mode 100644 index 000000000000..ded8dd9212d2 --- /dev/null +++ b/_randomgen/ci/pypi-install.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +pip install numpy cython pandas pytest setuptools nose matplotlib --quiet diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index eb884c7f3fd7..5be2ea8dd60f 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,6 +1,6 @@ Change Log ---------- -v1.15.2 +v1.16.0 ======= - Fixed a bug that affected :class:`~randomgen.dsfmt.DSFMT` when calling :func:`~randomgen.dsfmt.DSFMT.jump` or :func:`~randomgen.dsfmt.DSFMT.seed` @@ -11,6 +11,7 @@ v1.15.2 entropy initialization used too few bytes. This bug is unlikely to be encountered since this path is only encountered if the system random number generator fails. +- Synchronized with upstream changes. v1.15.1 ======= diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py index 4b38c42d5370..d4290d173d9c 100644 --- a/_randomgen/doc/source/conf.py +++ b/_randomgen/doc/source/conf.py @@ -206,3 +206,16 @@ } autosummary_generate = True + +doctest_global_setup = """ +import numpy as np + +import randomgen + +import matplotlib.pyplot + +def show(*args, **kwargs): + return + +matplotlib.pyplot.show = show +""" diff --git a/_randomgen/randomgen/__init__.py b/_randomgen/randomgen/__init__.py index 7529922195b0..b4c942c8fa8d 100644 --- a/_randomgen/randomgen/__init__.py +++ b/_randomgen/randomgen/__init__.py @@ -13,7 +13,8 @@ __all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar'] + 'Xoshiro256StarStar', 'Xoshiro512StarStar', + 'hypergeometric', 'multinomial', 'random_sample'] from ._version import get_versions diff --git a/_randomgen/randomgen/entropy.pyx b/_randomgen/randomgen/entropy.pyx index 2c85066c1d9d..d7822bfdf412 100644 --- a/_randomgen/randomgen/entropy.pyx +++ b/_randomgen/randomgen/entropy.pyx @@ -28,14 +28,14 @@ cdef Py_ssize_t compute_numel(size): def seed_by_array(object seed, Py_ssize_t n): """ Transforms a seed array into an initial state - + Parameters ---------- seed: array, 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 diff --git a/_randomgen/randomgen/examples/cython/extending.pyx b/_randomgen/randomgen/examples/cython/extending.pyx index 420bb17eaa37..c387a13af4f3 100644 --- a/_randomgen/randomgen/examples/cython/extending.pyx +++ b/_randomgen/randomgen/examples/cython/extending.pyx @@ -52,7 +52,7 @@ def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): x = Xoroshiro128() 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 = PyCapsule_GetPointer(capsule, capsule_name) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 01fa7f1be1b7..2d45f8aca2f0 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -2,11 +2,11 @@ #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 from __future__ import absolute_import -import operator +import operator import warnings from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, +from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, PyComplex_ImagAsDouble, PyComplex_FromDoubles, PyFloat_AsDouble) from libc cimport string from libc.stdlib cimport malloc, free @@ -141,7 +141,7 @@ cdef class RandomGenerator: Notes ----- Arguments are directly passed to the basic RNG. This is a convenience - function. + function. The best method to access seed is to directly use a basic RNG instance. This example demonstrates this best practice. @@ -156,8 +156,8 @@ cdef class RandomGenerator: >>> brng = PCG64(1234567891011) >>> rg = RandomGenerator(brng) >>> brng.seed(1110987654321) - - These best practice examples are equivalent to + + These best practice examples are equivalent to >>> rg = RandomGenerator(PCG64(1234567891011)) >>> rg.seed(1110987654321) @@ -176,10 +176,10 @@ cdef class RandomGenerator: state : dict Dictionary containing the information required to describe the state of the Basic RNG - + Notes ----- - This is a trivial pass-through function. RandomGenerator does not + This is a trivial pass-through function. RandomGenerator does not directly contain or manipulate the basic RNG's state. """ return self._basicrng.state @@ -260,7 +260,7 @@ cdef class RandomGenerator: ``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 + Output values. Used for performance testing since the generated values are not returned. Returns @@ -290,7 +290,7 @@ cdef class RandomGenerator: for i in range(n): self._brng.next_raw(self._brng.state) return None - + if size is None: with self.lock: return self._brng.next_raw(self._brng.state) @@ -339,17 +339,17 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.random_sample() - 0.47108547995356098 - >>> type(randomgen.random_sample()) - - >>> randomgen.random_sample((5,)) - array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) + >>> randomgen.generator.random_sample() + 0.47108547995356098 # random + >>> type(randomgen.generator.random_sample()) + + >>> randomgen.generator.random_sample((5,)) + array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random Three-by-two array of random numbers from [-5, 0): >>> 5 * randomgen.random_sample((3, 2)) - 5 - array([[-3.99149989, -0.52338984], + array([[-3.99149989, -0.52338984], # random [-2.99091858, -0.79479508], [-1.23204345, -1.75224494]]) """ @@ -493,7 +493,7 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = randomgen.standard_exponential((3, 8000)) + >>> n = randomgen.generator.standard_exponential((3, 8000)) """ key = np.dtype(dtype).name if key == 'float64': @@ -541,7 +541,7 @@ cdef class RandomGenerator: -------- >>> rg = randomgen.RandomGenerator() # need a RandomGenerator object >>> rg.tomaxint((2,2,2)) - array([[[1170048599, 1600360186], + array([[[1170048599, 1600360186], # random [ 739731006, 1947757578]], [[1871712945, 752307660], [1601631370, 1479324245]]]) @@ -626,30 +626,30 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.randint(2, size=10) - array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) - >>> randomgen.randint(1, size=10) + >>> randomgen.generator.randint(2, size=10) + array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random + >>> randomgen.generator.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: - >>> randomgen.randint(5, size=(2, 4)) - array([[4, 0, 2, 1], + >>> randomgen.generator.randint(5, size=(2, 4)) + array([[4, 0, 2, 1], # random [3, 2, 2, 0]]) Generate a 1 x 3 array with 3 different upper bounds - >>> randomgen.randint(1, [3, 5, 10]) + >>> randomgen.generator.randint(1, [3, 5, 10]) array([2, 2, 9]) Generate a 1 by 3 array with 3 different lower bounds - >>> randomgen.randint([1, 5, 7], 10) + >>> randomgen.generator.randint([1, 5, 7], 10) array([9, 8, 7]) Generate a 2 by 4 array using broadcasting with dtype of uint8 - >>> randomgen.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) + >>> randomgen.generator.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) @@ -684,7 +684,7 @@ cdef class RandomGenerator: ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) elif key == 'bool': ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) - + if size is None and dtype in (np.bool, np.int, np.long): if np.array(ret).shape == (): return dtype(ret) @@ -708,7 +708,7 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.bytes(10) + >>> randomgen.generator.bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ @@ -763,35 +763,35 @@ cdef class RandomGenerator: -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> randomgen.choice(5, 3) - array([0, 3, 4]) + >>> randomgen.generator.choice(5, 3) + array([0, 3, 4]) # random >>> #This is equivalent to randomgen.randint(0,5,3) Generate a non-uniform random sample from np.arange(5) of size 3: - >>> randomgen.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) - array([3, 3, 0]) + >>> randomgen.generator.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: - >>> randomgen.choice(5, 3, replace=False) - array([3,1,0]) + >>> randomgen.generator.choice(5, 3, replace=False) + array([3,1,0]) # random >>> #This is equivalent to randomgen.permutation(np.arange(5))[:3] Generate a non-uniform random sample from np.arange(5) of size 3 without replacement: - >>> randomgen.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) - array([2, 3, 0]) + >>> randomgen.generator.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'] - >>> randomgen.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) - array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], - dtype='|S11') + >>> randomgen.generator.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) + array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random + dtype='np.PyArray_DATA(p) if p.ndim != 1: - raise ValueError("p must be 1-dimensional") + raise ValueError("'p' must be 1-dimensional") if p.size != pop_size: - raise ValueError("a and p must have same 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(kahan_sum(pix, d) - 1.) > atol: + if abs(p_sum - 1.) > atol: raise ValueError("probabilities do not sum to 1") shape = size @@ -958,7 +961,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = randomgen.uniform(-1,0,1000) + >>> s = randomgen.generator.uniform(-1,0,1000) All values are within the given interval: @@ -1046,7 +1049,7 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.rand(3,2) + >>> randomgen.generator.rand(3,2) array([[ 0.14022471, 0.96360618], #random [ 0.37601032, 0.25528411], #random [ 0.49313049, 0.94909878]]) #random @@ -1102,12 +1105,12 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.randn() + >>> randomgen.generator.randn() 2.1923875335537315 #random Two-by-four array of samples from N(3, 6.25): - >>> 2.5 * randomgen.randn(2, 4) + 3 + >>> 2.5 * randomgen.generator.randn(2, 4) + 3 array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random @@ -1125,7 +1128,7 @@ cdef class RandomGenerator: Return random integers of type np.int64 from the "discrete uniform" distribution in the closed interval [`low`, `high`]. If `high` is - None (the default), then results are from [1, `low`]. + None (the default), then results are from [1, `low`]. This function has been deprecated. Use randint instead. @@ -1166,12 +1169,12 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.random_integers(5) - 4 - >>> type(randomgen.random_integers(5)) - - >>> randomgen.random_integers(5, size=(3.,2.)) - array([[5, 4], + >>> randomgen.generator.random_integers(5) + 4 # random + >>> type(randomgen.generator.random_integers(5)) + + >>> randomgen.generator.random_integers(5, size=(3, 2)) + array([[5, 4], # random [3, 3], [4, 5]]) @@ -1179,13 +1182,13 @@ cdef class RandomGenerator: numbers between 0 and 2.5, inclusive (*i.e.*, from the set :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - >>> 2.5 * (randomgen.random_integers(5, size=(5,)) - 1) / 4. - array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) + >>> 2.5 * (randomgen.generator.random_integers(5, size=(5,)) - 1) / 4. + array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) # random Roll two six sided dice 1000 times and sum the results: - >>> d1 = randomgen.random_integers(1, 6, 1000) - >>> d2 = randomgen.random_integers(1, 6, 1000) + >>> d1 = randomgen.generator.random_integers(1, 6, 1000) + >>> d2 = randomgen.generator.random_integers(1, 6, 1000) >>> dsums = d1 + d2 Display results as a histogram: @@ -1238,13 +1241,13 @@ cdef class RandomGenerator: Examples -------- - >>> s = randomgen.standard_normal(8000) + >>> s = randomgen.generator.standard_normal(8000) >>> s array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random -0.38672696, -0.4685006 ]) #random >>> s.shape (8000,) - >>> s = randomgen.standard_normal(size=(3, 4, 2)) + >>> s = randomgen.generator.standard_normal(size=(3, 4, 2)) >>> s.shape (3, 4, 2) @@ -1327,7 +1330,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = randomgen.normal(mu, sigma, 1000) + >>> s = randomgen.generator.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1389,7 +1392,7 @@ cdef class RandomGenerator: ----- **EXPERIMENTAL** Not part of official NumPy RandomState, may change until formal release on PyPi. - + Complex normals are generated from a bivariate normal where the variance of the real component is 0.5 Re(gamma + relation), the variance of the imaginary component is 0.5 Re(gamma - relation), and @@ -1409,7 +1412,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = randomgen.complex_normal(size=1000) + >>> s = randomgen.generator.complex_normal(size=1000) """ cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho cdef double *randoms_data @@ -1578,7 +1581,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = randomgen.standard_gamma(shape, 1000000) + >>> s = randomgen.generator.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1665,7 +1668,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean and dispersion - >>> s = randomgen.gamma(shape, scale, 1000) + >>> s = randomgen.generator.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1755,12 +1758,12 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = randomgen.f(dfnum, dfden, 1000) + >>> s = randomgen.generator.f(dfnum, dfden, 1000) 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% @@ -1830,10 +1833,11 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = randomgen.generator.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = randomgen.f(dfnum, dfden, 1000000) + >>> c_vals = randomgen.generator.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() @@ -1903,8 +1907,8 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.chisquare(2,4) - array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) + >>> randomgen.generator.chisquare(2,4) + array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ return cont(&random_chisquare, self._brng, size, self.lock, 1, @@ -1968,7 +1972,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -1976,9 +1980,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(randomgen.chisquare(3, 100000), + >>> values2 = plt.hist(randomgen.generator.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1987,7 +1991,7 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -2052,8 +2056,9 @@ cdef class RandomGenerator: -------- Draw samples and plot the distribution: - >>> s = randomgen.standard_cauchy(1000000) + >>> s = randomgen.generator.standard_cauchy(1000000) >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well + >>> import matplotlib.pyplot as plt >>> plt.hist(s, bins=100) >>> plt.show() @@ -2125,7 +2130,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = randomgen.standard_t(10, size=100000) + >>> s = randomgen.generator.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -2219,7 +2224,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = randomgen.vonmises(mu, kappa, 1000) + >>> s = randomgen.generator.vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -2319,7 +2324,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (randomgen.pareto(a, 1000) + 1) * m + >>> s = (randomgen.generator.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2412,7 +2417,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = randomgen.weibull(a, 1000) + >>> s = randomgen.generator.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2422,7 +2427,7 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(randomgen.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(randomgen.generator.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) @@ -2492,7 +2497,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = randomgen.power(a, samples) + >>> s = randomgen.generator.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2508,8 +2513,8 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats - >>> rvs = randomgen.power(5, 1000000) - >>> rvsp = randomgen.pareto(5, 1000000) + >>> rvs = randomgen.generator.power(5, 1000000) + >>> rvsp = randomgen.generator.pareto(5, 1000000) >>> xx = np.linspace(0,1,100) >>> powpdf = stats.powerlaw.pdf(xx,5) @@ -2595,7 +2600,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = randomgen.laplace(loc, scale, 1000) + >>> s = randomgen.generator.laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2697,7 +2702,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = randomgen.gumbel(mu, beta, 1000) + >>> s = randomgen.generator.gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2715,7 +2720,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = randomgen.normal(mu, beta, 1000) + ... a = randomgen.generator.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, density=True) @@ -2797,15 +2802,16 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = randomgen.logistic(loc, scale, 10000) + >>> s = randomgen.generator.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 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) + >>> scale = logist(bins, loc, scale).max() + >>> plt.plot(bins, logist(bins, loc, scale)*count.max()/scale) >>> plt.show() """ @@ -2879,7 +2885,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = randomgen.lognormal(mu, sigma, 1000) + >>> s = randomgen.generator.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2903,7 +2909,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + randomgen.random(100) + ... a = 10. + randomgen.generator.randn(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -2970,7 +2976,8 @@ cdef class RandomGenerator: -------- Draw values from the distribution and plot the histogram - >>> values = hist(randomgen.rayleigh(3, 100000), bins=200, density=True) + >>> from matplotlib.pyplot import hist + >>> values = hist(randomgen.generator.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 @@ -2978,12 +2985,12 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = randomgen.rayleigh(modevalue, 1000000) + >>> s = randomgen.generator.rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: >>> 100.*sum(s>3)/1000000. - 0.087300000000000003 + 0.087300000000000003 # random """ return cont(&random_rayleigh, self._brng, size, self.lock, 1, @@ -3050,7 +3057,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, density=True) + >>> h = plt.hist(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ @@ -3117,7 +3124,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(randomgen.generator.triangular(-3, 0, 8, 100000), bins=200, ... density=True) >>> plt.show() @@ -3230,7 +3237,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = randomgen.binomial(n, p, 1000) + >>> s = randomgen.generator.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 @@ -3240,7 +3247,7 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(randomgen.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(randomgen.generator.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ @@ -3365,10 +3372,10 @@ cdef class RandomGenerator: 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.negative_binomial(1, 0.9, 100000) - >>> for i in range(1, 11): + >>> s = randomgen.generator.negative_binomial(1, 0.9, 100000) + >>> for i in range(1, 11): # doctest: +SKIP ... probability = sum(s>> import numpy as np - >>> s = randomgen.poisson(5, 10000) + >>> s = randomgen.generator.poisson(5, 10000) Display histogram of the sample: @@ -3439,7 +3446,7 @@ cdef class RandomGenerator: Draw each 100 values for lambda 100 and 500: - >>> s = randomgen.poisson(lam=(100., 500.), size=(100, 2)) + >>> s = randomgen.generator.poisson(lam=(100., 500.), size=(100, 2)) """ return disc(&random_poisson, self._brng, size, self.lock, 1, 0, @@ -3504,7 +3511,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 2. # parameter - >>> s = randomgen.zipf(a, 1000) + >>> s = randomgen.generator.zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3564,7 +3571,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = randomgen.geometric(p=0.35, size=10000) + >>> z = randomgen.generator.geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3652,7 +3659,8 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = randomgen.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = randomgen.generator.hypergeometric(ngood, nbad, nsamp, 1000) + >>> from matplotlib.pyplot import hist >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3660,7 +3668,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = randomgen.hypergeometric(15, 15, 15, 100000) + >>> s = randomgen.generator.hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3761,13 +3769,14 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = randomgen.logseries(a, 10000) + >>> s = randomgen.generator.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*log(1-p)) + ... return -p**k/(k*np.log(1-p)) >>> plt.plot(bins, logseries(bins, a)*count.max()/ logseries(bins, a).max(), 'r') >>> plt.show() @@ -3849,7 +3858,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = randomgen.multivariate_normal(mean, cov, 5000).T + >>> x, y = randomgen.generator.multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3869,7 +3878,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = randomgen.multivariate_normal(mean, cov, (3, 3)) + >>> x = randomgen.generator.multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3981,14 +3990,14 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> randomgen.multinomial(20, [1/6.]*6, size=1) + >>> randomgen.generator.multinomial(20, [1/6.]*6, size=1) array([[4, 1, 7, 5, 2, 1]]) It landed 4 times on 1, once on 2, etc. Now, throw the dice 20 times, and 20 times again: - >>> randomgen.multinomial(20, [1/6.]*6, size=2) + >>> randomgen.generator.multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], [2, 4, 3, 4, 0, 7]]) @@ -3997,8 +4006,8 @@ cdef class RandomGenerator: A loaded die is more likely to land on number 6: - >>> randomgen.multinomial(100, [1/7.]*5 + [2/7.]) - array([11, 16, 14, 17, 16, 26]) + >>> randomgen.generator.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 @@ -4006,12 +4015,12 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> randomgen.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT - array([38, 62]) + >>> randomgen.generator.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + array([38, 62]) # random not like: - >>> randomgen.multinomial(100, [1.0, 2.0]) # WRONG + >>> randomgen.generator.multinomial(100, [1.0, 2.0]) # WRONG array([100, 0]) """ @@ -4128,8 +4137,9 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = randomgen.dirichlet((10, 5, 3), 20).transpose() + >>> s = randomgen.generator.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') @@ -4224,14 +4234,14 @@ cdef class RandomGenerator: >>> arr = np.arange(10) >>> randomgen.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)) - >>> randomgen.shuffle(arr) + >>> randomgen.generator.shuffle(arr) >>> arr - array([[3, 4, 5], + array([[3, 4, 5], # random [6, 7, 8], [0, 1, 2]]) @@ -4290,7 +4300,7 @@ cdef class RandomGenerator: 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 @@ -4302,23 +4312,23 @@ cdef class RandomGenerator: 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 -------- - >>> np.random.permutation(10) - array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) - - >>> np.random.permutation([1, 4, 9, 12, 15]) - array([15, 1, 9, 4, 12]) - + >>> randomgen.generator.permutation(10) + array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random + + >>> randomgen.generator.permutation([1, 4, 9, 12, 15]) + array([15, 1, 9, 4, 12]) # random + >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.permutation(arr) - array([[6, 7, 8], + >>> randomgen.generator.permutation(arr) + array([[6, 7, 8], # random [0, 1, 2], [3, 4, 5]]) diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index a342dbcfa515..1a5579098581 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -33,11 +33,11 @@ cdef class LegacyGenerator: ``LegacyGenerator`` exposes a number of methods for generating random numbers for a set of distributions where the method used to produce random samples has changed. Three core generators have changed: normal, exponential - and gamma. These have been replaced by faster Ziggurat-based methods in + and gamma. These have been replaced by faster Ziggurat-based methods in ``RandomGenerator``. ``_LegacyGenerator`` retains the slower methods to produce samples from these distributions as well as from distributions that depend on these such as the Chi-square, power or Weibull. - + **No Compatibility Guarantee** ``LegacyGenerator`` is evolving and so it isn't possible to provide a @@ -71,7 +71,7 @@ cdef class LegacyGenerator: 0.09290787674371767 >>> lg.standard_exponential() 1.6465621229906502 - + The equivalent commands from NumPy produce identical output. >>> from numpy.random import RandomState @@ -98,7 +98,7 @@ cdef class LegacyGenerator: if not PyCapsule_IsValid(capsule, name): raise ValueError("Invalid brng. The brng must be instantized.") self._brng = PyCapsule_GetPointer(capsule, name) - self._aug_state = malloc(sizeof(aug_brng_t)) + self._aug_state = malloc(sizeof(aug_brng_t)) self._aug_state.basicrng = self._brng self._reset_gauss() self.lock = Lock() @@ -137,7 +137,7 @@ cdef class LegacyGenerator: Notes ----- Arguments are directly passed to the basic RNG. This is a convenience - function. + function. The best method to access seed is to directly use a basic RNG instance. This example demonstrates this best practice. @@ -153,8 +153,8 @@ cdef class LegacyGenerator: >>> brng = MT19937(123456789) >>> lg = LegacyGenerator(brng) >>> brng.seed(987654321) - - These best practice examples are equivalent to + + These best practice examples are equivalent to >>> lg = LegacyGenerator(MT19937(123456789)) >>> lg.seed(987654321) @@ -191,7 +191,7 @@ cdef class LegacyGenerator: if isinstance(value, tuple): if value[0] != 'MT19937': raise ValueError('tuple only supported for MT19937') - st = {'brng': value[0], + st = {'brng': value[0], 'state': {'key': value[1], 'pos': value[2]}} if len(value) > 3: st['has_gauss'] = value[3] @@ -222,13 +222,13 @@ cdef class LegacyGenerator: Examples -------- - >>> s = randomgen.standard_normal(8000) + >>> s = randomgen.generator.standard_normal(8000) >>> s array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random -0.38672696, -0.4685006 ]) #random >>> s.shape (8000,) - >>> s = randomgen.standard_normal(size=(3, 4, 2)) + >>> s = randomgen.generator.standard_normal(size=(3, 4, 2)) >>> s.shape (3, 4, 2) @@ -236,7 +236,7 @@ cdef class LegacyGenerator: return cont(&legacy_gauss, self._aug_state, size, self.lock, 0, None, None, CONS_NONE, None, None, CONS_NONE, - None, None, CONS_NONE, + None, None, CONS_NONE, None) def standard_t(self, df, size=None): @@ -303,7 +303,7 @@ cdef class LegacyGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = randomgen.standard_t(10, size=100000) + >>> s = randomgen.generator.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -398,7 +398,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = randomgen.lognormal(mu, sigma, 1000) + >>> s = randomgen.generator.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -422,7 +422,7 @@ cdef class LegacyGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + randomgen.random(100) + ... a = 10. + randomgen.generator.randn(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -502,7 +502,7 @@ cdef class LegacyGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.wald(3, 2, 100000), bins=200, density=True) + >>> h = plt.hist(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ @@ -592,7 +592,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (randomgen.pareto(a, 1000) + 1) * m + >>> s = (randomgen.generator.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -685,7 +685,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = randomgen.weibull(a, 1000) + >>> s = randomgen.generator.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -695,7 +695,7 @@ cdef class LegacyGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(randomgen.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(randomgen.generator.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) @@ -765,10 +765,11 @@ cdef class LegacyGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = randomgen.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = randomgen.generator.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = randomgen.f(dfnum, dfden, 1000000) + >>> c_vals = randomgen.generator.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() @@ -838,7 +839,7 @@ cdef class LegacyGenerator: Examples -------- - >>> randomgen.chisquare(2,4) + >>> randomgen.generator.chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) """ @@ -903,7 +904,7 @@ cdef class LegacyGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -911,9 +912,9 @@ cdef class LegacyGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(randomgen.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(randomgen.chisquare(3, 100000), + >>> values2 = plt.hist(randomgen.generator.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -922,7 +923,7 @@ cdef class LegacyGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(randomgen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -987,8 +988,9 @@ cdef class LegacyGenerator: -------- Draw samples and plot the distribution: - >>> s = randomgen.standard_cauchy(1000000) + >>> s = randomgen.generator.standard_cauchy(1000000) >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well + >>> import matplotlib.pyplot as plt >>> plt.hist(s, bins=100) >>> plt.show() @@ -1052,7 +1054,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = randomgen.standard_gamma(shape, 1000000) + >>> s = randomgen.generator.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1130,7 +1132,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean and dispersion - >>> s = randomgen.gamma(shape, scale, 1000) + >>> s = randomgen.generator.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1263,11 +1265,11 @@ cdef class LegacyGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = randomgen.f(dfnum, dfden, 1000) + >>> s = randomgen.generator.f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : - >>> sort(s)[-10] + >>> np.sort(s)[-10] 7.61988120985 So there is about a 1% chance that the F statistic will exceed 7.62, @@ -1349,7 +1351,7 @@ cdef class LegacyGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = randomgen.normal(mu, sigma, 1000) + >>> s = randomgen.generator.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1414,16 +1416,16 @@ cdef class LegacyGenerator: ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use: - ``sigma * randomgen.randn(...) + mu`` + ``sigma * randomgen.generator.randn(...) + mu`` Examples -------- - >>> randomgen.randn() + >>> randomgen.generator.randn() 2.1923875335537315 #random Two-by-four array of samples from N(3, 6.25): - >>> 2.5 * randomgen.randn(2, 4) + 3 + >>> 2.5 * randomgen.generator.randn(2, 4) + 3 array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random @@ -1498,7 +1500,7 @@ cdef class LegacyGenerator: for each successive well, that is what is the probability of a single success after drilling 5 wells, after 6 wells, etc.? - >>> s = randomgen.negative_binomial(1, 0.1, 100000) + >>> s = randomgen.generator.negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): ... probability = sum(s>> a = 5. # shape >>> samples = 1000 - >>> s = randomgen.power(a, samples) + >>> s = randomgen.generator.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -1956,20 +1959,20 @@ cdef class LegacyGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats - >>> rvs = randomgen.power(5, 1000000) - >>> rvsp = randomgen.pareto(5, 1000000) + >>> rvs = randomgen.generator.power(5, 1000000) + >>> rvsp = randomgen.generator.pareto(5, 1000000) >>> xx = np.linspace(0,1,100) >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() >>> plt.hist(rvs, bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('randomgen.power(5)') + >>> plt.title('randomgen.generator.power(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + randomgen.pareto(5)') + >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx index 207ebc4bd578..c88dd02b9686 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/_randomgen/randomgen/mt19937.pyx @@ -55,7 +55,7 @@ cdef class MT19937: 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 will attempt to read data from ``/dev/urandom`` + ``None``, then will attempt to read data from ``/dev/urandom`` (or the Windows analog) if available or seed from the clock otherwise. Notes @@ -82,10 +82,10 @@ cdef class MT19937: **Compatibility Guarantee** - ``MT19937`` make a compatibility guarantee. A fixed seed and a fixed - series of calls to ``MT19937`` methods will always produce the same - results up to roundoff error except when the values were incorrect. - Incorrect values will be fixed and the version in which the fix was + ``MT19937`` make a compatibility guarantee. A fixed seed and a fixed + series of calls to ``MT19937`` methods will always produce the same + results up to roundoff error except when the values were incorrect. + Incorrect values will be fixed and the version in which the fix was made will be noted in the relevant docstring. **Parallel Features** @@ -109,10 +109,10 @@ cdef class MT19937: ---------- .. [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 + 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, + Random Number Generators", INFORMS JOURNAL ON COMPUTING, Vol. 20, No. 3, Summer 2008, pp. 385-390. """ @@ -253,7 +253,7 @@ cdef class MT19937: self : DSFMT PRNG jumped iter times """ - cdef np.npy_intp i + cdef np.npy_intp i for i in range(iter): mt19937_jump(self.rng_state) return self diff --git a/_randomgen/randomgen/pcg64.pyx b/_randomgen/randomgen/pcg64.pyx index e7939314e626..44e123d4ca24 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/_randomgen/randomgen/pcg64.pyx @@ -254,7 +254,7 @@ cdef class PCG64: _seed = np.empty(2, np.uint64) _seed[0] = int(seed) // 2**64 _seed[1] = int(seed) % 2**64 - + if not np.isscalar(inc): raise TypeError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) if inc < 0 or inc > ub or int(inc) != inc: @@ -262,7 +262,7 @@ cdef class PCG64: _inc = np.empty(2, np.uint64) _inc[0] = int(inc) // 2**64 _inc[1] = int(inc) % 2**64 - + pcg64_set_seed(self.rng_state, _seed.data, _inc.data) self._reset_state_variables() diff --git a/_randomgen/randomgen/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py index 5d251a3b71e3..3f84c4cb69da 100644 --- a/_randomgen/randomgen/tests/test_direct.py +++ b/_randomgen/randomgen/tests/test_direct.py @@ -430,7 +430,8 @@ def test_uniform_float(self): def test_buffer_reset(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) - u = rs.random_sample(1) + rs.random_sample(1) + assert rs.state['buffer_loc'] != 382 rs.seed(*self.data1['seed']) assert rs.state['buffer_loc'] == 382 diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index df458f2eee83..a43d7d601f46 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -607,6 +607,11 @@ def test_choice_return_shape(self): (3, 0, 4)) assert_raises(ValueError, mt19937.choice, [], 10) + def test_choice_nan_probabilities(self): + a = np.array([42, 1, 2]) + p = [None, None, None] + assert_raises(ValueError, mt19937.choice, a, p=p) + def test_bytes(self): mt19937.seed(self.seed) actual = mt19937.bytes(10) diff --git a/_randomgen/randomgen/threefry.pyx b/_randomgen/randomgen/threefry.pyx index cb3c78f5bfbf..96e65f62529e 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/_randomgen/randomgen/threefry.pyx @@ -99,7 +99,7 @@ cdef class ThreeFry: ``ThreeFry`` can be used in parallel applications by calling the method ``jump`` which advances the state as-if :math:`2^{128}` random numbers have been generated. Alternatively, - ``advance`` can be used to advance the counter for an any + ``advance`` can be used to advance the counter for an any positive step in [0, 2**256). When using ``jump``, all generators should be initialized with the same seed to ensure that the segments come from the same sequence. Alternatively, ``ThreeFry`` can be used diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/_randomgen/randomgen/xoroshiro128.pyx index d9891e590334..57760c53a7a1 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/_randomgen/randomgen/xoroshiro128.pyx @@ -142,7 +142,7 @@ cdef class Xoroshiro128: self._ctypes = None self._cffi = None self._generator = None - + cdef const char *name = "BasicRNG" self.capsule = PyCapsule_New(self._brng, name, NULL) @@ -292,17 +292,17 @@ cdef class Xoroshiro128: return self._ctypes import ctypes - + self._ctypes = interface(self.rng_state, ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoroshiro128_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.cast(&xoroshiro128_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.cast(&xoroshiro128_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_double, - ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.cast(&xoroshiro128_double, + ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), ctypes.c_void_p(self._brng)) return self.ctypes @@ -327,7 +327,7 @@ cdef class Xoroshiro128: if self._cffi is not None: return self._cffi try: - import cffi + import cffi except ImportError: raise ImportError('cffi is cannot be imported.') diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx index 8341985b4c58..e7ad546e0ea6 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/_randomgen/randomgen/xorshift1024.pyx @@ -325,17 +325,17 @@ cdef class Xorshift1024: return self._ctypes import ctypes - + self._ctypes = interface(self.rng_state, ctypes.c_void_p(self.rng_state), - ctypes.cast(&xorshift1024_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.cast(&xorshift1024_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(&xorshift1024_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.cast(&xorshift1024_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(&xorshift1024_double, - ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.cast(&xorshift1024_double, + ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), ctypes.c_void_p(self._brng)) return self.ctypes @@ -360,7 +360,7 @@ cdef class Xorshift1024: if self._cffi is not None: return self._cffi try: - import cffi + import cffi except ImportError: raise ImportError('cffi is cannot be imported.') diff --git a/_randomgen/requirements.txt b/_randomgen/requirements.txt index 6c3af8ca3a6b..0d7fe1ba89e7 100644 --- a/_randomgen/requirements.txt +++ b/_randomgen/requirements.txt @@ -1,4 +1,4 @@ -numpy>=1.10 +numpy>=1.13 cython>=0.26 setuptools wheel \ No newline at end of file diff --git a/_randomgen/setup.py b/_randomgen/setup.py index 47e1eb583a6b..9e9517e974c7 100644 --- a/_randomgen/setup.py +++ b/_randomgen/setup.py @@ -281,10 +281,9 @@ 'Programming Language :: C', 'Programming Language :: Cython', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Topic :: Adaptive Technologies', 'Topic :: Artistic Software', 'Topic :: Office/Business :: Financial', From d531f926433711df04491431a2d87652ef010e87 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 18 Feb 2019 12:49:17 +0000 Subject: [PATCH 101/138] BUG: Protect gamma generation from 0 input Add protection for 0 input for gamma random variables Add protection in legacy for gamma random variables Add protection for 0 input in Weibull Add test of 0 protection Ensure tests run on legacy generators for bad values are also run on the current set of generators Use same variable definition in declaration and function Sync doc changes to Wald and Noncentral Chi2 --- _randomgen/randomgen/generator.pyx | 14 ++---- .../src/distributions/distributions.c | 4 ++ .../src/distributions/distributions.h | 2 +- .../src/legacy/distributions-boxmuller.c | 6 +++ _randomgen/randomgen/tests/test_legacy.py | 5 ++ .../randomgen/tests/test_numpy_mt19937.py | 47 ++++++++++++++++++- .../tests/test_numpy_mt19937_regressions.py | 8 ++++ 7 files changed, 72 insertions(+), 14 deletions(-) diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index 2d45f8aca2f0..a4e3dd3a19e8 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -1954,17 +1954,9 @@ cdef class RandomGenerator: 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-square distribution" + .. [1] Wikipedia, "Noncentral chi-square distribution" https://en.wikipedia.org/wiki/Noncentral_chi-square_distribution Examples @@ -3016,9 +3008,9 @@ cdef class RandomGenerator: 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), diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c index 4e7493afaac0..a9d8a308d98f 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/_randomgen/randomgen/src/distributions/distributions.c @@ -346,6 +346,8 @@ static NPY_INLINE double standard_gamma_zig(brng_t *brng_state, double shape) { if (shape == 1.0) { return random_standard_exponential_zig(brng_state); + } else if (shape == 0.0) { + return 0.0; } else if (shape < 1.0) { for (;;) { U = next_double(brng_state); @@ -388,6 +390,8 @@ static NPY_INLINE float standard_gamma_zig_f(brng_t *brng_state, float shape) { if (shape == 1.0f) { return random_standard_exponential_zig_f(brng_state); + } else if (shape == 0.0) { + return 0.0; } else if (shape < 1.0f) { for (;;) { U = next_float(brng_state); diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/_randomgen/randomgen/src/distributions/distributions.h index e618052c1a00..5cf9c72b25bc 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/_randomgen/randomgen/src/distributions/distributions.h @@ -210,7 +210,7 @@ DECLDIR void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, DECLDIR void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, npy_intp cnt, bool use_masked, uint16_t *out); -DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, npy_bool off, +DECLDIR void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, npy_intp cnt, bool use_masked, uint8_t *out); DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c index 7ad1742cc585..768de066ced2 100644 --- a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c +++ b/_randomgen/randomgen/src/legacy/distributions-boxmuller.c @@ -39,6 +39,9 @@ double legacy_standard_gamma(aug_brng_t *aug_state, double shape) { 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); @@ -84,6 +87,9 @@ double legacy_pareto(aug_brng_t *aug_state, double a) { } double legacy_weibull(aug_brng_t *aug_state, double a) { + if (a == 0.0) { + return 0.0; + } return pow(legacy_standard_exponential(aug_state), 1. / a); } diff --git a/_randomgen/randomgen/tests/test_legacy.py b/_randomgen/randomgen/tests/test_legacy.py index e45ba3619796..21c56946f6b8 100644 --- a/_randomgen/randomgen/tests/test_legacy.py +++ b/_randomgen/randomgen/tests/test_legacy.py @@ -10,3 +10,8 @@ def test_pickle(): lg2 = pickle.loads(pickle.dumps(lg)) assert lg.standard_normal() == lg2.standard_normal() assert lg.random_sample() == lg2.random_sample() + + +def test_weibull(): + lg = LegacyGenerator() + assert lg.weibull(0.0) == 0.0 diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index a43d7d601f46..df13820ca7c6 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -1161,11 +1161,13 @@ def test_normal(self): actual = normal(loc * 3, scale) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, normal, loc * 3, bad_scale) + assert_raises(ValueError, mt19937.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) + assert_raises(ValueError, mt19937.normal, loc, bad_scale * 3) def test_beta(self): a = [1] @@ -1182,12 +1184,14 @@ def test_beta(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, beta, bad_a * 3, b) assert_raises(ValueError, beta, a * 3, bad_b) + assert_raises(ValueError, mt19937.beta, bad_a * 3, b) + assert_raises(ValueError, mt19937.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) + assert_raises(ValueError, mt19937.beta, bad_a, b * 3) + assert_raises(ValueError, mt19937.beta, a, bad_b * 3) def test_exponential(self): scale = [1] @@ -1201,6 +1205,7 @@ def test_exponential(self): actual = exponential(scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, exponential, bad_scale * 3) + assert_raises(ValueError, mt19937.exponential, bad_scale * 3) def test_standard_gamma(self): shape = [1] @@ -1214,6 +1219,7 @@ def test_standard_gamma(self): actual = std_gamma(shape * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, std_gamma, bad_shape * 3) + assert_raises(ValueError, mt19937.standard_gamma, bad_shape * 3) def test_gamma(self): shape = [1] @@ -1230,12 +1236,16 @@ def test_gamma(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, gamma, bad_shape * 3, scale) assert_raises(ValueError, gamma, shape * 3, bad_scale) + assert_raises(ValueError, mt19937.gamma, bad_shape * 3, scale) + assert_raises(ValueError, mt19937.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) + assert_raises(ValueError, mt19937.gamma, bad_shape, scale * 3) + assert_raises(ValueError, mt19937.gamma, shape, bad_scale * 3) def test_f(self): dfnum = [1] @@ -1252,12 +1262,16 @@ def test_f(self): assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, f, bad_dfnum * 3, dfden) assert_raises(ValueError, f, dfnum * 3, bad_dfden) + assert_raises(ValueError, mt19937.f, bad_dfnum * 3, dfden) + assert_raises(ValueError, mt19937.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) + assert_raises(ValueError, mt19937.f, bad_dfnum, dfden * 3) + assert_raises(ValueError, mt19937.f, dfnum, bad_dfden * 3) def test_noncentral_f(self): dfnum = [2] @@ -1277,6 +1291,9 @@ def test_noncentral_f(self): 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) + assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum * 3, dfden, nonc) + assert_raises(ValueError, mt19937.noncentral_f, dfnum * 3, bad_dfden, nonc) + assert_raises(ValueError, mt19937.noncentral_f, dfnum * 3, dfden, bad_nonc) self.set_seed() actual = nonc_f(dfnum, dfden * 3, nonc) @@ -1284,6 +1301,9 @@ def test_noncentral_f(self): 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) + assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum, dfden * 3, nonc) + assert_raises(ValueError, mt19937.noncentral_f, dfnum, bad_dfden * 3, nonc) + assert_raises(ValueError, mt19937.noncentral_f, dfnum, dfden * 3, bad_nonc) self.set_seed() actual = nonc_f(dfnum, dfden, nonc * 3) @@ -1291,6 +1311,9 @@ def test_noncentral_f(self): 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) + assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum, dfden, nonc * 3) + assert_raises(ValueError, mt19937.noncentral_f, dfnum, bad_dfden, nonc * 3) + assert_raises(ValueError, mt19937.noncentral_f, dfnum, dfden, bad_nonc * 3) def test_chisquare(self): df = [1] @@ -1320,12 +1343,16 @@ def test_noncentral_chisquare(self): 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) + assert_raises(ValueError, mt19937.noncentral_chisquare, bad_df * 3, nonc) + assert_raises(ValueError, mt19937.noncentral_chisquare, 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) + assert_raises(ValueError, mt19937.noncentral_chisquare, bad_df, nonc * 3) + assert_raises(ValueError, mt19937.noncentral_chisquare, df, bad_nonc * 3) def test_standard_t(self): df = [1] @@ -1339,6 +1366,7 @@ def test_standard_t(self): actual = t(df * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, t, bad_df * 3) + assert_raises(ValueError, mt19937.standard_t, bad_df * 3) def test_vonmises(self): mu = [2] @@ -1371,6 +1399,7 @@ def test_pareto(self): actual = pareto(a * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, pareto, bad_a * 3) + assert_raises(ValueError, mt19937.pareto, bad_a * 3) def test_weibull(self): a = [1] @@ -1384,6 +1413,7 @@ def test_weibull(self): actual = weibull(a * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, weibull, bad_a * 3) + assert_raises(ValueError, mt19937.weibull, bad_a * 3) def test_power(self): a = [1] @@ -1397,6 +1427,7 @@ def test_power(self): actual = power(a * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, power, bad_a * 3) + assert_raises(ValueError, mt19937.power, bad_a * 3) def test_laplace(self): loc = [0] @@ -1468,11 +1499,13 @@ def test_lognormal(self): actual = lognormal(mean * 3, sigma) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, lognormal, mean * 3, bad_sigma) + assert_raises(ValueError, mt19937.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, mt19937.lognormal, mean, bad_sigma * 3) def test_rayleigh(self): scale = [1] @@ -1502,12 +1535,16 @@ def test_wald(self): 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, mt19937.wald, bad_mean * 3, scale) + assert_raises(ValueError, mt19937.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, mt19937.wald, bad_mean, scale * 3) + assert_raises(ValueError, mt19937.wald, mean, bad_scale * 3) def test_triangular(self): left = [1] @@ -1583,6 +1620,9 @@ def test_negative_binomial(self): 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) + assert_raises(ValueError, mt19937.negative_binomial, bad_n * 3, p) + assert_raises(ValueError, mt19937.negative_binomial, n * 3, bad_p_one) + assert_raises(ValueError, mt19937.negative_binomial, n * 3, bad_p_two) self.set_seed() actual = neg_binom(n, p * 3) @@ -1590,6 +1630,9 @@ def test_negative_binomial(self): 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) + assert_raises(ValueError, mt19937.negative_binomial, bad_n, p * 3) + assert_raises(ValueError, mt19937.negative_binomial, n, bad_p_one * 3) + assert_raises(ValueError, mt19937.negative_binomial, n, bad_p_two * 3) def test_poisson(self): max_lam = random.poisson_lam_max diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py index 4e51327aa160..bc644e122439 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py @@ -158,3 +158,11 @@ def __array__(self): perm = mt19937.permutation(m) assert_array_equal(perm, np.array([2, 1, 4, 0, 3])) 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) From 6e386c05c292da49224fcab372013a6d4247ae3b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 19 Feb 2019 18:37:41 +0000 Subject: [PATCH 102/138] DOC/ENH: Update docstring and enhance logistic Update docstring in _legacy.pyx for match generator.pyx Fix docstring in the constaint checker which had ineq rather than eq. Enhance logistic to accept 0 scale Reorder functions in _legacy to match generator to simplify keeping doc strings synchronized. Synchronize the docstring in _legacy --- _randomgen/README-git.md | 26 + _randomgen/README.md | 6 +- _randomgen/README.rst | 8 +- _randomgen/doc/source/change-log.rst | 5 + _randomgen/randomgen/common.pyx | 2 +- _randomgen/randomgen/generator.pyx | 124 +- _randomgen/randomgen/legacy/legacy.pyx | 1804 +++++++++-------- .../randomgen/tests/test_numpy_mt19937.py | 5 + 8 files changed, 1032 insertions(+), 948 deletions(-) create mode 100644 _randomgen/README-git.md diff --git a/_randomgen/README-git.md b/_randomgen/README-git.md new file mode 100644 index 000000000000..c771693902b6 --- /dev/null +++ b/_randomgen/README-git.md @@ -0,0 +1,26 @@ +These are the bash commands used to get the bashtage/randomgen repo into numpy/numpy + +```bash +# from a directory just above a numpy git checkout +git clone https://github.com/bashtage/randomgen.git +cd randomgen +# rewrite the checkout, pushing the content into '_randomgen' +git filter-branch --index-filter ' + git ls-files -s | + sed "s-\t-\t_randomgen/-" | + GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && + mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE +' HEAD +# write this file, commit it +git add _randomgen/README-git.md +git commit -m"Add README-git.md" +git checkout -b randomgen +cd ../numpy +git checkout -b randomgen +git remote add randomgen ../randomgen +git fetch randomgen randomgen +git merge --allow-unrelated-histories randomgen/randomgen +git remote remove randomgen +# Now all the randomgen commits are on the randomgen branch in numpy, +# and there is a subdirectory _randomgen with the content +``` diff --git a/_randomgen/README.md b/_randomgen/README.md index 53b58b5b2fd5..45c33b928924 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -12,8 +12,8 @@ generators in Python and NumPy. ## Python 2.7 Support -Release 1.16.0 is the final version that supports Python 2.7. Any bugs -in v1.16.0 will be patched until the end of 2019. All future releases +v1.16 is the final major version that supports Python 2.7. Any bugs +in v1.16 will be patched until the end of 2019. All future releases are Python 3, with an initial minimum version of 3.5. ## Compatibility Warning @@ -164,7 +164,7 @@ need to be smoothed. Building requires: * Python (2.7, 3.5, 3.6, 3.7) -* NumPy (1.13, 1.14, 1.15) +* NumPy (1.13, 1.14, 1.15, 1.16) * Cython (0.26+) * tempita (0.5+), if not provided by Cython diff --git a/_randomgen/README.rst b/_randomgen/README.rst index cfd447f387bb..f4b886e5f74b 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -12,9 +12,9 @@ generators in Python and NumPy. Python 2.7 Support ------------------ -Release 1.16.0 is the final version that supports Python 2.7. Any bugs -in v1.16.0 will be patched until the end of 2019. All future releases -are Python 3, with an initial minimum version of 3.5. +v1.16 is the final major version that supports Python 2.7. Any bugs in +v1.16 will be patched until the end of 2019. All future releases are +Python 3, with an initial minimum version of 3.5. Compatibility Warning --------------------- @@ -181,7 +181,7 @@ Requirements Building requires: - Python (2.7, 3.5, 3.6, 3.7) -- NumPy (1.13, 1.14, 1.15) +- NumPy (1.13, 1.14, 1.15, 1.16) - Cython (0.26+) - tempita (0.5+), if not provided by Cython diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst index 5be2ea8dd60f..f791c8f5418e 100644 --- a/_randomgen/doc/source/change-log.rst +++ b/_randomgen/doc/source/change-log.rst @@ -1,5 +1,10 @@ Change Log ---------- +v1.16.1 +======= +- Synchronized with upstream changes. +- Fixed a bug in gamma generation if the shape parameters is 0.0. + v1.16.0 ======= - Fixed a bug that affected :class:`~randomgen.dsfmt.DSFMT` when calling diff --git a/_randomgen/randomgen/common.pyx b/_randomgen/randomgen/common.pyx index eb872d02f15b..41d3074f352f 100644 --- a/_randomgen/randomgen/common.pyx +++ b/_randomgen/randomgen/common.pyx @@ -187,7 +187,7 @@ cdef int check_constraint(double val, object name, constraint_type cons) except raise ValueError(name + " <= 0") elif cons == CONS_BOUNDED_0_1 or cons == CONS_BOUNDED_0_1_NOTNAN: if val < 0 or val > 1: - raise ValueError(name + " <= 0 or " + name + " >= 1") + raise ValueError(name + " < 0 or " + name + " > 1") if cons == CONS_BOUNDED_0_1_NOTNAN: if np.isnan(val): raise ValueError(name + ' contains NaNs') diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx index a4e3dd3a19e8..6a68a1905b5c 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/_randomgen/randomgen/generator.pyx @@ -429,7 +429,8 @@ cdef class RandomGenerator: Parameters ---------- scale : float or array_like of floats - The scale parameter, :math:`\\beta = 1/\\lambda`. + 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), @@ -855,6 +856,8 @@ cdef class RandomGenerator: 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: @@ -1017,6 +1020,12 @@ cdef class RandomGenerator: 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)``. @@ -1065,16 +1074,20 @@ cdef class RandomGenerator: 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 + .. 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`. + + 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 (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. + distribution of mean 0 and variance 1. A single float randomly sampled + from the distribution is returned if no argument is provided. This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `standard_normal` instead. + tuple as the first argument, use `numpy.random.standard_normal` instead. Parameters ---------- @@ -1096,6 +1109,7 @@ cdef class RandomGenerator: See Also -------- standard_normal : Similar, but takes a tuple as its argument. + normal : Also accepts mu and sigma arguments Notes ----- @@ -1106,13 +1120,13 @@ cdef class RandomGenerator: Examples -------- >>> randomgen.generator.randn() - 2.1923875335537315 #random + 2.1923875335537315 # random Two-by-four array of samples from N(3, 6.25): - >>> 2.5 * randomgen.generator.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: @@ -1237,20 +1251,43 @@ cdef class RandomGenerator: 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 -------- - >>> s = randomgen.generator.standard_normal(8000) + >>> 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 = randomgen.generator.standard_normal(size=(3, 4, 2)) + >>> 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 + """ key = np.dtype(dtype).name if key == 'float64': @@ -1283,7 +1320,8 @@ cdef class RandomGenerator: 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), @@ -1334,11 +1372,11 @@ cdef class RandomGenerator: 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: @@ -1350,6 +1388,12 @@ cdef class RandomGenerator: ... linewidth=2, color='r') >>> plt.show() + Two-by-four array of samples from N(3, 6.25): + + >>> 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 cont(&random_normal_zig, self._brng, size, self.lock, 2, loc, '', CONS_NONE, @@ -1530,7 +1574,7 @@ cdef class RandomGenerator: 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), @@ -1622,9 +1666,9 @@ cdef class RandomGenerator: 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 @@ -1706,9 +1750,9 @@ cdef class RandomGenerator: Parameters ---------- dfnum : int or array_like of ints - Degrees of freedom in numerator. Should be greater than zero. + Degrees of freedom in numerator. Must be non-negative. dfden : int or array_like of ints - Degrees of freedom in denominator. Should be greater than zero. + Degrees of freedom in denominator. 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), @@ -2262,7 +2306,7 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Shape of the distribution. Should be greater than zero. + Shape of the distribution. All values 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), @@ -2443,7 +2487,7 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Parameter of the distribution. Should be greater than zero. + Parameter 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), @@ -2513,12 +2557,12 @@ cdef class RandomGenerator: >>> plt.figure() >>> plt.hist(rvs, bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('randomgen.power(5)') + >>> plt.title('randomgen.generator.power(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + randomgen.pareto(5)') + >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) @@ -2548,7 +2592,8 @@ cdef class RandomGenerator: 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), @@ -2630,7 +2675,8 @@ cdef class RandomGenerator: 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), @@ -2746,7 +2792,7 @@ cdef class RandomGenerator: 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 >= 0. Default is 1. size : int or tuple of ints, optional Output shape. If the given shape is, e.g., ``(m, n, k)``, then @@ -2809,7 +2855,7 @@ cdef class RandomGenerator: """ return cont(&random_logistic, self._brng, size, self.lock, 2, loc, 'loc', CONS_NONE, - scale, 'scale', CONS_POSITIVE, + scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) def lognormal(self, mean=0.0, sigma=1.0, size=None): @@ -2828,8 +2874,8 @@ cdef class RandomGenerator: 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), @@ -2934,7 +2980,7 @@ cdef class RandomGenerator: 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), @@ -3463,7 +3509,7 @@ cdef class RandomGenerator: 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), diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx index 1a5579098581..33198a624ba4 100644 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ b/_randomgen/randomgen/legacy/legacy.pyx @@ -51,7 +51,6 @@ cdef class LegacyGenerator: Basic RNG to use as the core generator. If none is provided, uses Xoroshiro128. - Examples -------- Exactly reproducing a NumPy stream requires both a ``RandomGenerator`` @@ -201,6 +200,190 @@ cdef class LegacyGenerator: self._aug_state.has_gauss = value.get('has_gauss', 0) self._basicrng.state = value + 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`. + 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 = randomgen.generator.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 randn(self, *args): + """ + randn(d0, d1, ..., dn) + + 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. + + This is a convenience function. If you want an interface that takes a + tuple as the first argument, use `standard_normal` instead. + + Parameters + ---------- + d0, d1, ..., dn : int, optional + The dimensions of the returned array, should be all positive. + If no argument is given a single Python float is returned. + + Returns + ------- + Z : ndarray or float + A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from + the standard normal distribution, or a single such float if + no parameters were supplied. + + See Also + -------- + standard_normal : Similar, but takes a tuple as its argument. + + Notes + ----- + For random samples from :math:`N(\\mu, \\sigma^2)`, use: + + ``sigma * randomgen.generator.randn(...) + mu`` + + Examples + -------- + >>> randomgen.generator.randn() + 2.1923875335537315 #random + + Two-by-four array of samples from N(3, 6.25): + + >>> 2.5 * randomgen.generator.randn(2, 4) + 3 + 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(size=args) + # Complicated, continuous distributions: def standard_normal(self, size=None): """ @@ -239,472 +422,339 @@ cdef class LegacyGenerator: None, None, CONS_NONE, None) - def standard_t(self, df, size=None): + def normal(self, loc=0.0, scale=1.0, size=None): """ - standard_t(df, size=None) + normal(loc=0.0, scale=1.0, size=None) - Draw samples from a standard Student's t distribution with `df` degrees - of freedom. + Draw random samples from a normal (Gaussian) distribution. - A special case of the hyperbolic distribution. As `df` gets - large, the result resembles that of the standard normal - distribution (`standard_normal`). + 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 ---------- - df : int or array_like of ints - Degrees of freedom, should be > 0. + 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. 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. + 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 standard Student's t distribution. + 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 function for the t distribution is + The probability density for the Gaussian 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} + .. math:: p(x) = \\frac{1}{\\sqrt{ 2 \\pi \\sigma^2 }} + e^{ - \\frac{ (x - \\mu)^2 } {2 \\sigma^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. + 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 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. + 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 + `numpy.random.normal` is more likely to return samples lying close to + the mean, rather than those far away. References ---------- - .. [1] Dalgaard, Peter, "Introductory Statistics With R", - Springer, 2002. - .. [2] Wikipedia, "Student's t-distribution" - http://en.wikipedia.org/wiki/Student's_t-distribution + .. [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 -------- - From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 - women in Kj is: + Draw samples from the distribution: - >>> intake = np.array([5260., 5470, 5640, 6180, 6390, 6515, 6805, 7515, \\ - ... 7515, 8230, 8770]) + >>> mu, sigma = 0, 0.1 # mean and standard deviation + >>> s = randomgen.generator.normal(mu, sigma, 1000) - Does their energy intake deviate systematically from the recommended - value of 7725 kJ? + Verify the mean and the variance: - We have 10 degrees of freedom, so is the sample mean within 95% of the - recommended value? + >>> abs(mu - np.mean(s)) < 0.01 + True - >>> s = randomgen.generator.standard_t(10, size=100000) - >>> np.mean(intake) - 6753.636363636364 - >>> intake.std(ddof=1) - 1142.1232221373727 + >>> abs(sigma - np.std(s, ddof=1)) < 0.01 + True - 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. + Display the histogram of the samples, along with + the probability density function: - >>> 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>> 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() """ - return cont(&legacy_standard_t, self._aug_state, size, self.lock, 1, - df, 'df', CONS_POSITIVE, - 0, '', CONS_NONE, - 0, '', CONS_NONE, + 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 lognormal(self, mean=0.0, sigma=1.0, size=None): + def standard_gamma(self, shape, size=None): """ - lognormal(mean=0.0, sigma=1.0, size=None) + standard_gamma(shape, size=None) - Draw samples from a log-normal distribution. + Draw samples from a standard Gamma 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. + Samples are drawn from a Gamma distribution with specified parameters, + shape (sometimes designated "k") and scale=1. 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. Should - be greater than zero. Default is 1. + shape : float or array_like of floats + Parameter, should 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 ``sigma`` are both scalars. - Otherwise, ``np.broadcast(mean, sigma).size`` samples are drawn. + a single value is returned if ``shape`` is a scalar. Otherwise, + ``np.array(shape).size`` samples are drawn. Returns ------- out : ndarray or scalar - Drawn samples from the parameterized log-normal distribution. + Drawn samples from the parameterized standard gamma distribution. See Also -------- - scipy.stats.lognorm : probability density function, distribution, + scipy.stats.gamma : probability density function, distribution or 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: + The probability density for the Gamma distribution is - .. math:: p(x) = \\frac{1}{\\sigma x \\sqrt{2\\pi}} - e^{(-\\frac{(ln(x)-\\mu)^2}{2\\sigma^2})} + .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)}, - 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. + 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] Limpert, E., Stahel, W. A., and Abbt, M., "Log-normal - Distributions across the Sciences: Keys and Clues," - BioScience, Vol. 51, No. 5, May, 2001. - http://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. + .. [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: - >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = randomgen.generator.lognormal(mu, sigma, 1000) + >>> shape, scale = 2., 1. # mean and width + >>> s = randomgen.generator.standard_gamma(shape, 1000000) 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. - >>> b = [] - >>> for i in range(1000): - ... a = 10. + randomgen.generator.randn(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) + >>> import scipy.special as sps + >>> count, bins, ignored = plt.hist(s, 50, density=True) + >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ + ... (sps.gamma(shape) * scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') >>> plt.show() - """ - 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) + 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 wald(self, mean, scale, size=None): + def gamma(self, shape, scale=1.0, size=None): """ - wald(mean, scale, size=None) - - Draw samples from a Wald, or inverse Gaussian, distribution. + gamma(shape, scale=1.0, size=None) - 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. + Draw samples from a Gamma distribution. - 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. + 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 ---------- - mean : float or array_like of floats - Distribution mean, should be > 0. - scale : float or array_like of floats - Scale parameter, should be >= 0. + shape : float or array_like of floats + The shape of the gamma distribution. Should be greater than zero. + scale : float or array_like of floats, optional + The scale of the gamma distribution. Should be greater than zero. + 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 ``mean`` and ``scale`` are both scalars. - Otherwise, ``np.broadcast(mean, scale).size`` samples are drawn. + 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 Wald distribution. + 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 function for the Wald distribution is + The probability density for the Gamma distribution is - .. math:: P(x;mean,scale) = \\sqrt{\\frac{scale}{2\\pi x^3}}e^ - \\frac{-scale(x-mean)^2}{2\\cdotp mean^2x} + .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)}, - 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. + 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] Brighton Webs Ltd., Wald Distribution, - http://www.brighton-webs.co.uk/distributions/wald.asp - .. [2] Chhikara, Raj S., and Folks, J. Leroy, "The Inverse Gaussian - Distribution: Theory : Methodology, and Applications", CRC Press, - 1988. - .. [3] Wikipedia, "Wald distribution" - http://en.wikipedia.org/wiki/Wald_distribution + .. [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 values from the distribution and plot the histogram: + Draw samples from the distribution: + + >>> shape, scale = 2., 2. # mean and dispersion + >>> s = randomgen.generator.gamma(shape, scale, 1000) + + Display the histogram of the samples, along with + the probability density function: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) + >>> import scipy.special as sps + >>> count, bins, ignored = plt.hist(s, 50, density=True) + >>> y = bins**(shape-1)*(np.exp(-bins/scale) / + ... (sps.gamma(shape)*scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') >>> plt.show() """ - return cont(&legacy_wald, self._aug_state, size, self.lock, 2, - mean, 'mean', CONS_POSITIVE, - scale, 'scale', CONS_POSITIVE, + 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 pareto(self, a, size=None): + def f(self, dfnum, dfden, size=None): """ - pareto(a, size=None) + f(dfnum, dfden, size=None) - Draw samples from a Pareto II or Lomax distribution with - specified shape. + Draw samples from an F distribution. - 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. + 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 + 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. + 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 ---------- - a : float or array_like of floats - Shape of the distribution. Should be greater than zero. - size : int or tuple of ints, optional + dfnum : int or array_like of ints + Degrees of freedom in numerator. Should be greater than zero. + dfden : int or array_like of ints + Degrees of freedom in denominator. Should be greater than zero. + 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. + 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 Pareto distribution. + Drawn samples from the parameterized Fisher distribution. See Also -------- - scipy.stats.lomax : probability density function, distribution or - cumulative density function, etc. - scipy.stats.genpareto : probability density function, distribution or + scipy.stats.f : 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. - + 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] 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", - http://en.wikipedia.org/wiki/Pareto_distribution + .. [1] Glantz, Stanton A. "Primer of Biostatistics.", McGraw-Hill, + Fifth Edition, 2002. + .. [2] Wikipedia, "F-distribution", + https://en.wikipedia.org/wiki/F-distribution Examples -------- - Draw samples from the distribution: - - >>> a, m = 3., 2. # shape and mode - >>> s = (randomgen.generator.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(&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): - """ - 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 of the distribution. Should be greater than zero. - 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. + An example from Glantz[1], pp 47-40: - 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", - http://en.wikipedia.org/wiki/Weibull_distribution + 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. - Examples - -------- Draw samples from the distribution: - >>> a = 5. # shape - >>> s = randomgen.generator.weibull(a, 1000) + >>> dfnum = 1. # between group degrees of freedom + >>> dfden = 48. # within groups degrees of freedom + >>> s = randomgen.generator.f(dfnum, dfden, 1000) - Display the histogram of the samples, along with - the probability density function: + The lower bound for the top 1% of the samples is : - >>> 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) + >>> np.sort(s)[-10] + 7.61988120985 # random - >>> count, bins, ignored = plt.hist(randomgen.generator.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() + 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(&legacy_weibull, self._aug_state, size, self.lock, 1, - a, 'a', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE, + 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): @@ -752,7 +802,7 @@ cdef class LegacyGenerator: From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/NoncentralF-Distribution.html .. [2] Wikipedia, "Noncentral F-distribution", - http://en.wikipedia.org/wiki/Noncentral_F-distribution + https://en.wikipedia.org/wiki/Noncentral_F-distribution Examples -------- @@ -835,12 +885,12 @@ cdef class LegacyGenerator: References ---------- .. [1] NIST "Engineering Statistics Handbook" - http://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm + https://www.itl.nist.gov/div898/handbook/eda/section3/eda3666.htm Examples -------- >>> randomgen.generator.chisquare(2,4) - array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) + array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ return cont(&legacy_chisquare, self._aug_state, size, self.lock, 1, @@ -886,18 +936,10 @@ cdef class LegacyGenerator: 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-square distribution" - http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution + .. [1] Wikipedia, "Noncentral chi-square distribution" + https://en.wikipedia.org/wiki/Noncentral_chi-square_distribution Examples -------- @@ -982,7 +1024,7 @@ cdef class LegacyGenerator: Wolfram Web Resource. http://mathworld.wolfram.com/CauchyDistribution.html .. [3] Wikipedia, "Cauchy distribution" - http://en.wikipedia.org/wiki/Cauchy_distribution + https://en.wikipedia.org/wiki/Cauchy_distribution Examples -------- @@ -998,442 +1040,575 @@ cdef class LegacyGenerator: 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_gamma(self, shape, size=None): + def standard_t(self, df, size=None): """ - standard_gamma(shape, size=None) + standard_t(df, size=None) - Draw samples from a standard Gamma distribution. + Draw samples from a standard Student's t distribution with `df` degrees + of freedom. - Samples are drawn from a Gamma distribution with specified parameters, - shape (sometimes designated "k") and scale=1. + A special case of the hyperbolic distribution. As `df` gets + large, the result resembles that of the standard normal + distribution (`standard_normal`). Parameters ---------- - shape : float or array_like of floats - Parameter, should be > 0. + df : int or array_like of ints + Degrees of freedom, should 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 ``shape`` is a scalar. Otherwise, - ``np.array(shape).size`` samples are drawn. + 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 gamma distribution. - - See Also - -------- - scipy.stats.gamma : probability density function, distribution or - cumulative density function, etc. + Drawn samples from the parameterized standard Student's t distribution. Notes ----- - The probability density for the Gamma distribution is + The probability density function for the t distribution is - .. math:: p(x) = x^{k-1}\\frac{e^{-x/\\theta}}{\\theta^k\\Gamma(k)}, + .. 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} - where :math:`k` is the shape and :math:`\\theta` the scale, - and :math:`\\Gamma` is the Gamma function. + 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 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. + 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] Weisstein, Eric W. "Gamma Distribution." From MathWorld--A - Wolfram Web Resource. - http://mathworld.wolfram.com/GammaDistribution.html - .. [2] Wikipedia, "Gamma distribution", - http://en.wikipedia.org/wiki/Gamma_distribution + .. [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 -------- - Draw samples from the distribution: + From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 + women in kilojoules (kJ) is: - >>> shape, scale = 2., 1. # mean and width - >>> s = randomgen.generator.standard_gamma(shape, 1000000) + >>> intake = np.array([5260., 5470, 5640, 6180, 6390, 6515, 6805, 7515, \\ + ... 7515, 8230, 8770]) - Display the histogram of the samples, along with - the probability density function: + Does their energy intake deviate systematically from the recommended + value of 7725 kJ? - >>> import matplotlib.pyplot as plt - >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, density=True) - >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ - ... (sps.gamma(shape) * scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') - >>> plt.show() - """ - 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) + We have 10 degrees of freedom, so is the sample mean within 95% of the + recommended value? - def gamma(self, shape, scale=1.0, size=None): - """ - gamma(shape, scale=1.0, size=None) + >>> s = randomgen.generator.standard_t(10, size=100000) + >>> np.mean(intake) + 6753.636363636364 + >>> intake.std(ddof=1) + 1142.1232221373727 - Draw samples from a Gamma distribution. + 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. - Samples are drawn from a Gamma distribution with specified parameters, - `shape` (sometimes designated "k") and `scale` (sometimes designated - "theta"), where both parameters are > 0. + >>> 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>> shape, scale = 2., 2. # mean and dispersion - >>> s = randomgen.generator.gamma(shape, scale, 1000) + >>> a, m = 3., 2. # shape and mode + >>> s = (randomgen.generator.pareto(a, 1000) + 1) * m - Display the histogram of the samples, along with - the probability density function: + Display the histogram of the samples, along with the probability + density function: >>> import matplotlib.pyplot as plt - >>> import scipy.special as sps - >>> count, bins, ignored = plt.hist(s, 50, density=True) - >>> y = bins**(shape-1)*(np.exp(-bins/scale) / - ... (sps.gamma(shape)*scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') + >>> 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(&legacy_gamma, self._aug_state, size, self.lock, 2, - shape, 'shape', CONS_NON_NEGATIVE, - scale, 'scale', CONS_NON_NEGATIVE, + 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 beta(self, a, b, size=None): + def weibull(self, a, size=None): """ - beta(a, b, size=None) - - Draw samples from a Beta distribution. + weibull(a, size=None) - The Beta distribution is a special case of the Dirichlet distribution, - and is related to the Gamma distribution. It has the probability - distribution function + Draw samples from a Weibull distribution. - .. math:: f(x; a,b) = \\frac{1}{B(\\alpha, \\beta)} x^{\\alpha - 1} - (1 - x)^{\\beta - 1}, + Draw samples from a 1-parameter Weibull distribution with the given + shape parameter `a`. - where the normalisation, B, is the beta function, + .. math:: X = (-ln(U))^{1/a} - .. math:: B(\\alpha, \\beta) = \\int_0^1 t^{\\alpha - 1} - (1 - t)^{\\beta - 1} dt. + Here, U is drawn from the uniform distribution over (0,1]. - It is often seen in Bayesian inference and order statistics. + 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 - Alpha, non-negative. - b : float or array_like of floats - Beta, non-negative. + 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`` and ``b`` are both scalars. - Otherwise, ``np.broadcast(a, b).size`` samples are drawn. + 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 beta distribution. + 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: + + >>> a = 5. # shape + >>> s = randomgen.generator.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(randomgen.generator.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(&legacy_beta, self._aug_state, size, self.lock, 2, - a, 'a', CONS_POSITIVE, - b, 'b', CONS_POSITIVE, + 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 f(self, dfnum, dfden, size=None): + def power(self, a, size=None): """ - f(dfnum, dfden, size=None) - - Draw samples from an F distribution. + power(a, size=None) - 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 - zero. + Draws samples in [0, 1] from a power distribution with positive + exponent a - 1. - 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. + Also known as the power function distribution. Parameters ---------- - dfnum : int or array_like of ints - Degrees of freedom in numerator. Should be greater than zero. - dfden : int or array_like of ints - Degrees of freedom in denominator. Should be greater than zero. + a : float or array_like of floats + Parameter of the distribution. Should be greater than zero. 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. + 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 Fisher distribution. + Drawn samples from the parameterized power distribution. - See Also - -------- - scipy.stats.f : probability density function, distribution or - cumulative density function, etc. + Raises + ------ + ValueError + If a < 1. 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. + 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] Glantz, Stanton A. "Primer of Biostatistics.", McGraw-Hill, - Fifth Edition, 2002. - .. [2] Wikipedia, "F-distribution", - http://en.wikipedia.org/wiki/F-distribution + .. [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. + http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf Examples -------- - An example from Glantz[1], pp 47-40: + Draw samples from the distribution: - 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. + >>> a = 5. # shape + >>> samples = 1000 + >>> s = randomgen.generator.power(a, samples) - Draw samples from the distribution: + Display the histogram of the samples, along with + the probability density function: - >>> dfnum = 1. # between group degrees of freedom - >>> dfden = 48. # within groups degrees of freedom - >>> s = randomgen.generator.f(dfnum, dfden, 1000) + >>> 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() - The lower bound for the top 1% of the samples is : + Compare the power function distribution to the inverse of the Pareto. - >>> np.sort(s)[-10] - 7.61988120985 + >>> from scipy import stats + >>> rvs = randomgen.generator.power(5, 1000000) + >>> rvsp = randomgen.generator.pareto(5, 1000000) + >>> xx = np.linspace(0,1,100) + >>> powpdf = stats.powerlaw.pdf(xx,5) - 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. + >>> plt.figure() + >>> plt.hist(rvs, bins=50, density=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('randomgen.generator.power(5)') - """ - return cont(&legacy_f, self._aug_state, size, self.lock, 2, - dfnum, 'dfnum', CONS_POSITIVE, - dfden, 'dfden', CONS_POSITIVE, - 0.0, '', CONS_NONE, None) + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('inverse of stats.pareto(5)') - def normal(self, loc=0.0, scale=1.0, size=None): """ - normal(loc=0.0, scale=1.0, size=None) + return cont(&legacy_power, self._aug_state, size, self.lock, 1, + a, 'a', CONS_POSITIVE, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE, None) - Draw random samples from a normal (Gaussian) distribution. + def lognormal(self, mean=0.0, sigma=1.0, size=None): + """ + lognormal(mean=0.0, sigma=1.0, size=None) - 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). + Draw samples from a log-normal distribution. - 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]_. + 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 ---------- - 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. + 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. 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. + 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 normal distribution. + Drawn samples from the parameterized log-normal distribution. See Also -------- - scipy.stats.norm : probability density function, distribution or + scipy.stats.lognorm : probability density function, distribution, 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} }, + A variable `x` has a log-normal distribution if `log(x)` is normally + distributed. The probability density function for the log-normal + distribution is: - 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. + .. math:: p(x) = \\frac{1}{\\sigma x \\sqrt{2\\pi}} + e^{(-\\frac{(ln(x)-\\mu)^2}{2\\sigma^2})} - 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 - `numpy.random.normal` is more likely to return samples lying close to - the mean, rather than those far away. + 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] Wikipedia, "Normal distribution", - http://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. + .. [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: - >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = randomgen.generator.normal(mu, sigma, 1000) - - Verify the mean and the variance: - - >>> abs(mu - np.mean(s)) < 0.01 - True - - >>> abs(sigma - np.std(s, ddof=1)) < 0.01 - True + >>> mu, sigma = 3., 1. # mean and standard deviation + >>> s = randomgen.generator.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, 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') + >>> 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. + >>> b = [] + >>> for i in range(1000): + ... a = 10. + randomgen.generator.randn(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(&legacy_normal, self._aug_state, size, self.lock, 2, - loc, '', CONS_NONE, - scale, 'scale', CONS_NON_NEGATIVE, - 0.0, '', CONS_NONE, - None) + 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 randn(self, *args): + def wald(self, mean, scale, size=None): """ - randn(d0, d1, ..., dn) + wald(mean, scale, size=None) - Return a sample (or samples) from the "standard normal" distribution. + Draw samples from a Wald, or inverse Gaussian, 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. + 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. - This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `standard_normal` instead. + 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 ---------- - d0, d1, ..., dn : int, optional - The dimensions of the returned array, should be all positive. - If no argument is given a single Python float is returned. + 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 ------- - Z : ndarray or float - A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from - the standard normal distribution, or a single such float if - no parameters were supplied. - - See Also - -------- - standard_normal : Similar, but takes a tuple as its argument. + out : ndarray or scalar + Drawn samples from the parameterized Wald distribution. Notes ----- - For random samples from :math:`N(\\mu, \\sigma^2)`, use: + The probability density function for the Wald distribution is - ``sigma * randomgen.generator.randn(...) + mu`` + .. 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, "Wald distribution" + https://en.wikipedia.org/wiki/Wald_distribution Examples -------- - >>> randomgen.generator.randn() - 2.1923875335537315 #random - - Two-by-four array of samples from N(3, 6.25): + Draw values from the distribution and plot the histogram: - >>> 2.5 * randomgen.generator.randn(2, 4) + 3 - array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], #random - [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) #random + >>> import matplotlib.pyplot as plt + >>> h = plt.hist(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) + >>> plt.show() """ - if len(args) == 0: - return self.standard_normal() - else: - return self.standard_normal(size=args) + 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 negative_binomial(self, n, p, size=None): """ @@ -1442,7 +1617,7 @@ cdef class LegacyGenerator: Draw samples from a negative binomial distribution. Samples are drawn from a negative binomial distribution with specified - parameters, `n` trials and `p` probability of success where `n` is an + parameters, `n` successes and `p` probability of success where `n` is an integer > 0 and `p` is in the interval [0, 1]. Parameters @@ -1462,21 +1637,19 @@ cdef class LegacyGenerator: ------- out : ndarray or scalar Drawn samples from the parameterized negative binomial distribution, - where each sample is equal to N, the number of trials it took to - achieve n - 1 successes, N - (n - 1) failures, and a success on the, - (N + n)th trial. + where each sample is equal to N, the number of failures that + occurred before a total of n successes was reached. Notes ----- The probability density for the negative binomial distribution is - .. math:: P(N;n,p) = \\binom{N+n-1}{n-1}p^{n}(1-p)^{N}, + .. math:: P(N;n,p) = \\binom{N+n-1}{N}p^{n}(1-p)^{N}, - where :math:`n-1` is the number of successes, :math:`p` is the - probability of success, and :math:`N+n-1` is the number of trials. - The negative binomial distribution gives the probability of n-1 - successes and N failures in N+n-1 trials, and success on the (N+n)th - trial. + 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. 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 @@ -1488,154 +1661,28 @@ cdef class LegacyGenerator: MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/NegativeBinomialDistribution.html .. [2] Wikipedia, "Negative binomial distribution", - http://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 = randomgen.generator.negative_binomial(1, 0.1, 100000) - >>> for i in range(1, 11): - ... probability = sum(s>> s = randomgen.generator.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 - cdef np.npy_intp totsize - cdef np.ndarray alpha_arr, val_arr - cdef double *alpha_data - cdef double *val_data - cdef np.npy_intp i, j - cdef double acc, invacc - - k = len(alpha) - alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) - if np.any(np.less_equal(alpha_arr, 0)): - raise ValueError('alpha <= 0') - alpha_data = np.PyArray_DATA(alpha_arr) - - if size is None: - shape = (k,) - else: - try: - shape = (operator.index(size), k) - except: - shape = tuple(size) + (k,) + https://en.wikipedia.org/wiki/Negative_binomial_distribution - diric = np.zeros(shape, np.float64) - val_arr = diric - val_data= np.PyArray_DATA(val_arr) + Examples + -------- + Draw samples from the distribution: - 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] = 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 + 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.? - return diric + >>> s = randomgen.generator.negative_binomial(1, 0.9, 100000) + >>> for i in range(1, 11): # doctest: +SKIP + ... probability = sum(s>> n = randomgen.generator.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 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", - http://en.wikipedia.org/wiki/Poisson_process - .. [3] Wikipedia, "Exponential distribution", - http://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 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. Should be greater than zero. - 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. + samples : ndarray, + The drawn samples, of shape (size, alpha.ndim). Raises - ------ + ------- ValueError - If a < 1. + If any value in alpha is less than or equal to zero Notes ----- - The probability density function is + 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`. - .. math:: P(x; a) = ax^{a-1}, 0 \\le x \\le 1, a>0. + The probability density function :math:`p` of a + Dirichlet-distributed random vector :math:`X` is + proportional to - 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. + .. math:: p(x) \\propto \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i}, - It is used, for example, in modeling the over-reporting of insurance - claims. + 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] 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. - http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf + .. [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 -------- - Draw samples from the distribution: - - >>> a = 5. # shape - >>> samples = 1000 - >>> s = randomgen.generator.power(a, samples) + 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. - Display the histogram of the samples, along with - the probability density function: + >>> s = randomgen.generator.dirichlet((10, 5, 3), 20).transpose() >>> 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() + >>> 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") - Compare the power function distribution to the inverse of the Pareto. + """ - >>> from scipy import stats - >>> rvs = randomgen.generator.power(5, 1000000) - >>> rvsp = randomgen.generator.pareto(5, 1000000) - >>> xx = np.linspace(0,1,100) - >>> powpdf = stats.powerlaw.pdf(xx,5) + #================= + # Pure python algo + #================= + #alpha = N.atleast_1d(alpha) + #k = alpha.size - >>> plt.figure() - >>> plt.hist(rvs, bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('randomgen.generator.power(5)') + #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 - >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') + #return val - >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of stats.pareto(5)') + cdef np.npy_intp k + cdef np.npy_intp totsize + cdef np.ndarray alpha_arr, val_arr + cdef double *alpha_data + cdef double *val_data + cdef np.npy_intp i, j + cdef double acc, invacc - """ - return cont(&legacy_power, self._aug_state, size, self.lock, 1, - a, 'a', CONS_POSITIVE, - 0.0, '', CONS_NONE, - 0.0, '', CONS_NONE, None) + k = len(alpha) + alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) + if np.any(np.less_equal(alpha_arr, 0)): + raise ValueError('alpha <= 0') + alpha_data = 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 = diric + val_data= 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] = 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 diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py index df13820ca7c6..a19693d815c7 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py @@ -558,6 +558,10 @@ def test_choice_exceptions(self): 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]) @@ -1485,6 +1489,7 @@ def test_logistic(self): actual = logistic(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, logistic, loc, bad_scale * 3) + assert_equal(mt19937.logistic(1.0, 0.0), 1.0) def test_lognormal(self): mean = [0] From fa8af41c9d375072b2c7af66e5f7f01df4754841 Mon Sep 17 00:00:00 2001 From: mattip Date: Wed, 20 Mar 2019 12:39:53 +0200 Subject: [PATCH 103/138] BUILD: move files out of _randomgen first cut at building randomgen upgrade 'cythonize' and fix absolute imports to relative define NPY_NO_DEPRECATED_API and fix other warnings enable pgc64 by always using PCG_EMULATED_MATH refactor so import randomgen works add TODO comments for pcg64 improvements fix imports, module name in setup.py; remove _testing make cythonize non-recursive, restore examples to proper place update to randomgen 7bca296c0b9 replace mtrand with LegacyGenerator, tweak for compatibility port f879ef4 to fix GH10839 minimized difference between generator.pyx and _legacy.pyx fix namespace in doctests, mark results that are random update to randomgen commit 95c8cdd1c Incorporate testing of edge cases into main tests Rename test files to describe their purpose Import import locations to reflect numpy paths Correct tolerance on float32 tests Remove set_printoptions Remove complex normal Remove future imports Pull in BasicRNG source changes from original author Small doc fixes _mtrand => _rand Improve consistency of nan handling Prevent nans prducing values from int functions add randomgen documentation to the tree --- .gitignore | 6 +- _randomgen/MANIFEST.in | 10 - _randomgen/README.md | 16 +- _randomgen/README.rst | 22 +- _randomgen/appveyor.yml | 33 - _randomgen/ci/conda-install.sh | 20 - _randomgen/ci/pypi-install.sh | 3 - _randomgen/doc/Makefile | 20 - _randomgen/doc/make.bat | 36 - _randomgen/doc/source/conf.py | 221 - .../github_deploy_key_bashtage_randomgen.enc | 1 - _randomgen/randomgen/__init__.py | 22 - _randomgen/randomgen/_testing.py | 315 -- .../cython/extending_distributions.pyx | 48 - _randomgen/randomgen/legacy/__init__.py | 3 - _randomgen/randomgen/legacy/legacy.pyx | 1988 -------- .../randomgen/src/xoroshiro128/xoroshiro128.c | 58 - .../src/xoroshiro128/xoroshiro128plus.orig.c | 73 - .../tests/data/xoroshiro128-testset-1.csv | 1001 ---- .../tests/data/xoroshiro128-testset-2.csv | 1001 ---- _randomgen/randomgen/tests/test_legacy.py | 17 - _randomgen/requirements.txt | 4 - _randomgen/setup.cfg | 11 - _randomgen/versioneer.py | 1822 ------- doc/Makefile | 3 +- doc/source/conf.py | 25 +- .../reference/randomgen}/brng/dsfmt.rst | 5 +- .../reference/randomgen}/brng/index.rst | 0 .../reference/randomgen}/brng/mt19937.rst | 5 +- .../reference/randomgen}/brng/pcg32.rst | 5 +- .../reference/randomgen}/brng/pcg64.rst | 5 +- .../reference/randomgen}/brng/philox.rst | 5 +- .../reference/randomgen}/brng/threefry.rst | 5 +- .../reference/randomgen}/brng/threefry32.rst | 5 +- .../randomgen}/brng/xoroshiro128.rst | 5 +- .../randomgen}/brng/xorshift1024.rst | 5 +- .../randomgen}/brng/xoshiro256starstar.rst | 5 +- .../randomgen}/brng/xoshiro512starstar.rst | 5 +- .../reference/randomgen}/change-log.rst | 0 .../source/reference/randomgen}/entropy.rst | 2 +- .../source/reference/randomgen}/extending.rst | 0 .../source/reference/randomgen}/generator.rst | 11 +- .../source/reference/randomgen}/index.rst | 10 +- .../source/reference/randomgen}/legacy.rst | 23 +- .../reference/randomgen}/multithreading.rst | 0 .../reference/randomgen}/new-or-different.rst | 0 .../source/reference/randomgen}/parallel.rst | 0 .../reference/randomgen}/performance.py | 0 .../reference/randomgen}/performance.rst | 0 .../reference/randomgen}/references.rst | 0 doc/source/reference/routines.rst | 1 + numpy/random/__init__.py | 7 +- numpy/random/mtrand/distributions.c | 4 + numpy/random/mtrand/initarray.c | 1 - numpy/random/mtrand/numpy.pxd | 2 - .../random/randomgen}/LICENSE.md | 47 +- numpy/random/randomgen/__init__.py | 21 + .../random/randomgen/_pickle.py | 53 +- .../random}/randomgen/_version.py | 0 .../random}/randomgen/bounded_integers.pxd.in | 17 +- .../random}/randomgen/bounded_integers.pyx.in | 20 +- .../random}/randomgen/common.pxd | 28 +- .../random}/randomgen/common.pyx | 277 +- .../random}/randomgen/distributions.pxd | 8 +- .../random}/randomgen/dsfmt.pyx | 139 +- .../random}/randomgen/entropy.pyx | 7 +- .../randomgen/examples/cython/extending.pyx | 14 +- .../cython/extending_distributions.pyx | 51 + .../randomgen/examples/cython/setup.py | 0 .../randomgen/examples/numba/extending.py | 2 +- .../examples/numba/extending_distributions.py | 0 .../random}/randomgen/generator.pyx | 866 ++-- numpy/random/randomgen/legacy/__init__.py | 3 + .../randomgen/legacy/legacy_distributions.pxd | 6 +- .../random}/randomgen/mt19937.pyx | 126 +- numpy/random/randomgen/mtrand.pyx | 4223 +++++++++++++++++ .../random}/randomgen/pcg32.pyx | 117 +- .../random}/randomgen/pcg64.pyx | 174 +- .../random}/randomgen/philox.pyx | 123 +- numpy/random/randomgen/setup.py | 191 + .../src/aligned_malloc/aligned_malloc.c | 0 .../src/aligned_malloc/aligned_malloc.h | 0 .../random}/randomgen/src/common/LICENSE.md | 0 .../random}/randomgen/src/common/inttypes.h | 0 .../random}/randomgen/src/common/stdint.h | 0 .../randomgen/src/distributions}/LICENSE.md | 31 + .../randomgen/src/distributions/binomial.h | 0 .../src/distributions/distributions.c | 22 +- .../src/distributions/distributions.h | 2 +- .../randomgen/src/distributions/ziggurat.h | 0 .../src/distributions/ziggurat_constants.h | 0 .../randomgen/src/dsfmt/128-bit-jump.poly.txt | 0 .../randomgen/src/dsfmt/96-bit-jump.poly.txt | 0 .../random}/randomgen/src/dsfmt/LICENSE.md | 0 .../random}/randomgen/src/dsfmt/calc-jump.cpp | 0 .../randomgen/src/dsfmt/dSFMT-benchmark.c | 0 .../randomgen/src/dsfmt/dSFMT-calc-jump.hpp | 0 .../randomgen/src/dsfmt/dSFMT-common.h | 0 .../random}/randomgen/src/dsfmt/dSFMT-jump.c | 0 .../random}/randomgen/src/dsfmt/dSFMT-jump.h | 0 .../randomgen/src/dsfmt/dSFMT-params.h | 0 .../randomgen/src/dsfmt/dSFMT-params19937.h | 0 .../random}/randomgen/src/dsfmt/dSFMT-poly.h | 0 .../randomgen/src/dsfmt/dSFMT-test-gen.c | 0 .../random}/randomgen/src/dsfmt/dSFMT.c | 0 .../random}/randomgen/src/dsfmt/dSFMT.h | 0 .../random}/randomgen/src/entropy/LICENSE.md | 0 .../random}/randomgen/src/entropy/entropy.c | 0 .../random}/randomgen/src/entropy/entropy.h | 0 .../random/randomgen/src/legacy}/LICENSE.md | 0 .../src/legacy/distributions-boxmuller.c | 9 +- .../src/legacy/distributions-boxmuller.h | 0 .../random}/randomgen/src/mt19937/LICENSE.md | 0 .../randomgen/src/mt19937/mt19937-benchmark.c | 0 .../randomgen/src/mt19937/mt19937-jump.c | 0 .../randomgen/src/mt19937/mt19937-jump.h | 0 .../randomgen/src/mt19937/mt19937-poly.h | 0 .../src/mt19937/mt19937-test-data-gen.c | 0 .../random}/randomgen/src/mt19937/mt19937.c | 0 .../random}/randomgen/src/mt19937/mt19937.h | 0 .../random}/randomgen/src/mt19937/randomkit.c | 0 .../random}/randomgen/src/mt19937/randomkit.h | 0 .../random}/randomgen/src/pcg32/LICENSE.md | 0 .../randomgen/src/pcg32/pcg-advance-64.c | 0 .../randomgen/src/pcg32/pcg32-test-data-gen.c | 0 .../random}/randomgen/src/pcg32/pcg32.c | 0 .../random}/randomgen/src/pcg32/pcg32.h | 4 + .../randomgen/src/pcg32/pcg_variants.h | 0 .../random}/randomgen/src/pcg64/LICENSE.md | 0 .../randomgen/src/pcg64/pcg64-benchmark.c | 0 .../randomgen/src/pcg64/pcg64-test-data-gen.c | 0 .../random}/randomgen/src/pcg64/pcg64.c | 0 .../random}/randomgen/src/pcg64/pcg64.h | 4 +- .../random}/randomgen/src/pcg64/pcg64.orig.c | 0 .../random}/randomgen/src/pcg64/pcg64.orig.h | 0 .../random}/randomgen/src/philox/LICENSE.md | 0 .../randomgen/src/philox/philox-benchmark.c | 0 .../src/philox/philox-test-data-gen.c | 0 .../random}/randomgen/src/philox/philox.c | 0 .../random}/randomgen/src/philox/philox.h | 0 .../randomgen/src/splitmix64/LICENSE.md | 0 .../randomgen/src/splitmix64/splitmix64.c | 0 .../randomgen/src/splitmix64/splitmix64.h | 0 .../src/splitmix64/splitmix64.orig.c | 0 .../random}/randomgen/src/threefry/LICENSE.md | 0 .../src/threefry/threefry-benchmark.c | 0 .../randomgen/src/threefry/threefry-orig.c | 0 .../src/threefry/threefry-test-data-gen.c | 0 .../random}/randomgen/src/threefry/threefry.c | 0 .../random}/randomgen/src/threefry/threefry.h | 0 .../randomgen/src/threefry32/LICENSE.md | 0 .../src/threefry32/threefry32-test-data-gen.c | 0 .../randomgen/src/threefry32/threefry32.c | 0 .../randomgen/src/threefry32/threefry32.h | 0 .../randomgen/src/xoroshiro128/LICENSE.md | 0 .../src/xoroshiro128/xoroshiro128-benchmark.c | 6 +- .../xoroshiro128/xoroshiro128-test-data-gen.c | 33 +- .../randomgen/src/xoroshiro128/xoroshiro128.c | 60 + .../randomgen/src/xoroshiro128/xoroshiro128.h | 22 +- .../src/xoroshiro128/xoroshiro128plus.orig.c | 102 + .../src/xoroshiro128/xoroshiro128plus.orig.h | 0 .../randomgen/src/xorshift1024/LICENSE.md | 0 .../src/xorshift1024/xorshift1024-benchmark.c | 0 .../xorshift1024/xorshift1024-test-data-gen.c | 0 .../randomgen/src/xorshift1024/xorshift1024.c | 0 .../randomgen/src/xorshift1024/xorshift1024.h | 0 .../src/xorshift1024/xorshift1024.orig.c | 4 +- .../src/xorshift1024/xorshift1024.orig.h | 0 .../src/xoshiro256starstar/LICENSE.md | 0 .../xoshiro256starstar-test-data-gen.c | 0 .../xoshiro256starstar/xoshiro256starstar.c | 0 .../xoshiro256starstar/xoshiro256starstar.h | 0 .../xoshiro256starstar.orig.c | 0 .../xoshiro256starstar.orig.h | 0 .../src/xoshiro512starstar/LICENSE.md | 0 .../xoshiro512starstar-test-data-gen.c | 0 .../xoshiro512starstar/xoshiro512starstar.c | 0 .../xoshiro512starstar/xoshiro512starstar.h | 0 .../xoshiro512starstar.orig.c | 0 .../xoshiro512starstar.orig.h | 0 .../random}/randomgen/tests/__init__.py | 0 .../random}/randomgen/tests/data/__init__.py | 0 .../randomgen/tests/data/dSFMT-testset-1.csv | 0 .../randomgen/tests/data/dSFMT-testset-2.csv | 0 .../tests/data/mt19937-testset-1.csv | 0 .../tests/data/mt19937-testset-2.csv | 0 .../randomgen/tests/data/pcg32-testset-1.csv | 0 .../randomgen/tests/data/pcg32-testset-2.csv | 0 .../randomgen/tests/data/pcg64-testset-1.csv | 0 .../randomgen/tests/data/pcg64-testset-2.csv | 0 .../randomgen/tests/data/philox-testset-1.csv | 0 .../randomgen/tests/data/philox-testset-2.csv | 0 .../tests/data/threefry-testset-1.csv | 0 .../tests/data/threefry-testset-2.csv | 0 .../tests/data/threefry32-testset-1.csv | 0 .../tests/data/threefry32-testset-2.csv | 0 .../tests/data/xoroshiro128-testset-1.csv | 1001 ++++ .../tests/data/xoroshiro128-testset-2.csv | 1001 ++++ .../tests/data/xorshift1024-testset-1.csv | 0 .../tests/data/xorshift1024-testset-2.csv | 0 .../data/xoshiro256starstar-testset-1.csv | 0 .../data/xoshiro256starstar-testset-2.csv | 0 .../data/xoshiro512starstar-testset-1.csv | 0 .../data/xoshiro512starstar-testset-2.csv | 0 .../randomgen/tests/test_against_numpy.py | 88 +- .../random}/randomgen/tests/test_direct.py | 225 +- .../randomgen/tests/test_generator_mt19937.py | 954 ++-- .../test_generator_mt19937_regressions.py | 4 +- .../randomgen/tests/test_randomstate.py | 1808 +++++++ .../tests/test_randomstate_regression.py | 157 + .../random}/randomgen/tests/test_smoke.py | 120 +- .../random}/randomgen/threefry.pyx | 119 +- .../random}/randomgen/threefry32.pyx | 115 +- .../random}/randomgen/xoroshiro128.pyx | 117 +- .../random}/randomgen/xorshift1024.pyx | 120 +- .../random}/randomgen/xoshiro256starstar.pyx | 118 +- .../random}/randomgen/xoshiro512starstar.pyx | 116 +- numpy/random/setup.py | 7 +- setup.py | 13 +- tools/cythonize.py | 85 +- 220 files changed, 10969 insertions(+), 8906 deletions(-) delete mode 100644 _randomgen/MANIFEST.in delete mode 100644 _randomgen/appveyor.yml delete mode 100644 _randomgen/ci/conda-install.sh delete mode 100644 _randomgen/ci/pypi-install.sh delete mode 100644 _randomgen/doc/Makefile delete mode 100644 _randomgen/doc/make.bat delete mode 100644 _randomgen/doc/source/conf.py delete mode 100644 _randomgen/github_deploy_key_bashtage_randomgen.enc delete mode 100644 _randomgen/randomgen/__init__.py delete mode 100644 _randomgen/randomgen/_testing.py delete mode 100644 _randomgen/randomgen/examples/cython/extending_distributions.pyx delete mode 100644 _randomgen/randomgen/legacy/__init__.py delete mode 100644 _randomgen/randomgen/legacy/legacy.pyx delete mode 100644 _randomgen/randomgen/src/xoroshiro128/xoroshiro128.c delete mode 100644 _randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c delete mode 100644 _randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv delete mode 100644 _randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv delete mode 100644 _randomgen/randomgen/tests/test_legacy.py delete mode 100644 _randomgen/requirements.txt delete mode 100644 _randomgen/setup.cfg delete mode 100644 _randomgen/versioneer.py rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/dsfmt.rst (82%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/index.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/mt19937.rst (81%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/pcg32.rst (83%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/pcg64.rst (83%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/philox.rst (82%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/threefry.rst (82%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/threefry32.rst (82%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/xoroshiro128.rst (80%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/xorshift1024.rst (80%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/xoshiro256starstar.rst (80%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/brng/xoshiro512starstar.rst (80%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/change-log.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/entropy.rst (60%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/extending.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/generator.rst (92%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/index.rst (98%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/legacy.rst (85%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/multithreading.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/new-or-different.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/parallel.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/performance.py (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/performance.rst (100%) rename {_randomgen/doc/source => doc/source/reference/randomgen}/references.rst (100%) rename {_randomgen => numpy/random/randomgen}/LICENSE.md (60%) create mode 100644 numpy/random/randomgen/__init__.py rename _randomgen/randomgen/pickle.py => numpy/random/randomgen/_pickle.py (55%) rename {_randomgen => numpy/random}/randomgen/_version.py (100%) rename {_randomgen => numpy/random}/randomgen/bounded_integers.pxd.in (61%) rename {_randomgen => numpy/random}/randomgen/bounded_integers.pyx.in (95%) rename {_randomgen => numpy/random}/randomgen/common.pxd (85%) rename {_randomgen => numpy/random}/randomgen/common.pyx (76%) rename {_randomgen => numpy/random}/randomgen/distributions.pxd (97%) rename {_randomgen => numpy/random}/randomgen/dsfmt.pyx (79%) rename {_randomgen => numpy/random}/randomgen/entropy.pyx (97%) rename {_randomgen => numpy/random}/randomgen/examples/cython/extending.pyx (93%) create mode 100644 numpy/random/randomgen/examples/cython/extending_distributions.pyx rename {_randomgen => numpy/random}/randomgen/examples/cython/setup.py (100%) rename {_randomgen => numpy/random}/randomgen/examples/numba/extending.py (97%) rename {_randomgen => numpy/random}/randomgen/examples/numba/extending_distributions.py (100%) rename {_randomgen => numpy/random}/randomgen/generator.pyx (84%) create mode 100644 numpy/random/randomgen/legacy/__init__.py rename {_randomgen => numpy/random}/randomgen/legacy/legacy_distributions.pxd (95%) rename {_randomgen => numpy/random}/randomgen/mt19937.pyx (76%) create mode 100644 numpy/random/randomgen/mtrand.pyx rename {_randomgen => numpy/random}/randomgen/pcg32.pyx (78%) rename {_randomgen => numpy/random}/randomgen/pcg64.pyx (73%) rename {_randomgen => numpy/random}/randomgen/philox.pyx (85%) create mode 100644 numpy/random/randomgen/setup.py rename {_randomgen => numpy/random}/randomgen/src/aligned_malloc/aligned_malloc.c (100%) rename {_randomgen => numpy/random}/randomgen/src/aligned_malloc/aligned_malloc.h (100%) rename {_randomgen => numpy/random}/randomgen/src/common/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/common/inttypes.h (100%) rename {_randomgen => numpy/random}/randomgen/src/common/stdint.h (100%) rename {_randomgen/randomgen/src/legacy => numpy/random/randomgen/src/distributions}/LICENSE.md (54%) rename {_randomgen => numpy/random}/randomgen/src/distributions/binomial.h (100%) rename {_randomgen => numpy/random}/randomgen/src/distributions/distributions.c (99%) rename {_randomgen => numpy/random}/randomgen/src/distributions/distributions.h (99%) rename {_randomgen => numpy/random}/randomgen/src/distributions/ziggurat.h (100%) rename {_randomgen => numpy/random}/randomgen/src/distributions/ziggurat_constants.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/128-bit-jump.poly.txt (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/96-bit-jump.poly.txt (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/calc-jump.cpp (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-calc-jump.hpp (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-common.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-jump.c (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-jump.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-params.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-params19937.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-poly.h (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT-test-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT.c (100%) rename {_randomgen => numpy/random}/randomgen/src/dsfmt/dSFMT.h (100%) rename {_randomgen => numpy/random}/randomgen/src/entropy/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/entropy/entropy.c (100%) rename {_randomgen => numpy/random}/randomgen/src/entropy/entropy.h (100%) rename {_randomgen/randomgen/src/distributions => numpy/random/randomgen/src/legacy}/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/legacy/distributions-boxmuller.c (96%) rename {_randomgen => numpy/random}/randomgen/src/legacy/distributions-boxmuller.h (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937-jump.c (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937-jump.h (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937-poly.h (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937.c (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/mt19937.h (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/randomkit.c (100%) rename {_randomgen => numpy/random}/randomgen/src/mt19937/randomkit.h (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/pcg-advance-64.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/pcg32-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/pcg32.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/pcg32.h (97%) rename {_randomgen => numpy/random}/randomgen/src/pcg32/pcg_variants.h (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64.h (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64.orig.c (100%) rename {_randomgen => numpy/random}/randomgen/src/pcg64/pcg64.orig.h (100%) rename {_randomgen => numpy/random}/randomgen/src/philox/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/philox/philox-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/philox/philox-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/philox/philox.c (100%) rename {_randomgen => numpy/random}/randomgen/src/philox/philox.h (100%) rename {_randomgen => numpy/random}/randomgen/src/splitmix64/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/splitmix64/splitmix64.c (100%) rename {_randomgen => numpy/random}/randomgen/src/splitmix64/splitmix64.h (100%) rename {_randomgen => numpy/random}/randomgen/src/splitmix64/splitmix64.orig.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/threefry-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/threefry-orig.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/threefry-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/threefry.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry/threefry.h (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry32/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry32/threefry32-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry32/threefry32.c (100%) rename {_randomgen => numpy/random}/randomgen/src/threefry32/threefry32.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xoroshiro128/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c (95%) rename {_randomgen => numpy/random}/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c (83%) create mode 100644 numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c rename {_randomgen => numpy/random}/randomgen/src/xoroshiro128/xoroshiro128.h (77%) create mode 100644 numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c rename {_randomgen => numpy/random}/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024-benchmark.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024.orig.c (95%) rename {_randomgen => numpy/random}/randomgen/src/xorshift1024/xorshift1024.orig.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/xoshiro256starstar.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/xoshiro256starstar.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/LICENSE.md (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/xoshiro512starstar.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/xoshiro512starstar.h (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c (100%) rename {_randomgen => numpy/random}/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h (100%) rename {_randomgen => numpy/random}/randomgen/tests/__init__.py (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/__init__.py (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/dSFMT-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/dSFMT-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/mt19937-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/mt19937-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/pcg32-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/pcg32-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/pcg64-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/pcg64-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/philox-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/philox-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/threefry-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/threefry-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/threefry32-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/threefry32-testset-2.csv (100%) create mode 100644 numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv create mode 100644 numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv rename {_randomgen => numpy/random}/randomgen/tests/data/xorshift1024-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/xorshift1024-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/xoshiro256starstar-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/xoshiro256starstar-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/xoshiro512starstar-testset-1.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/data/xoshiro512starstar-testset-2.csv (100%) rename {_randomgen => numpy/random}/randomgen/tests/test_against_numpy.py (89%) rename {_randomgen => numpy/random}/randomgen/tests/test_direct.py (66%) rename _randomgen/randomgen/tests/test_numpy_mt19937.py => numpy/random/randomgen/tests/test_generator_mt19937.py (66%) rename _randomgen/randomgen/tests/test_numpy_mt19937_regressions.py => numpy/random/randomgen/tests/test_generator_mt19937_regressions.py (98%) create mode 100644 numpy/random/randomgen/tests/test_randomstate.py create mode 100644 numpy/random/randomgen/tests/test_randomstate_regression.py rename {_randomgen => numpy/random}/randomgen/tests/test_smoke.py (90%) rename {_randomgen => numpy/random}/randomgen/threefry.pyx (85%) rename {_randomgen => numpy/random}/randomgen/threefry32.pyx (84%) rename {_randomgen => numpy/random}/randomgen/xoroshiro128.pyx (79%) rename {_randomgen => numpy/random}/randomgen/xorshift1024.pyx (77%) rename {_randomgen => numpy/random}/randomgen/xoshiro256starstar.pyx (80%) rename {_randomgen => numpy/random}/randomgen/xoshiro512starstar.pyx (79%) diff --git a/.gitignore b/.gitignore index 8e96d4154e66..ac5693fad82e 100644 --- a/.gitignore +++ b/.gitignore @@ -168,7 +168,7 @@ numpy/core/src/umath/test_rational.c numpy/core/src/umath/umath_tests.c numpy/distutils/__config__.py numpy/linalg/umath_linalg.c -doc/source/reference/generated +doc/source/**/generated/ benchmarks/results benchmarks/html benchmarks/env @@ -176,4 +176,8 @@ benchmarks/numpy # cythonized files cythonize.dat numpy/random/mtrand/mtrand.c +numpy/random/randomgen/*.c +numpy/random/randomgen/legacy/*.c numpy/random/mtrand/randint_helpers.pxi +numpy/random/randomgen/bounded_integers.pyx +numpy/random/randomgen/bounded_integers.pxd diff --git a/_randomgen/MANIFEST.in b/_randomgen/MANIFEST.in deleted file mode 100644 index 61fffb8db518..000000000000 --- a/_randomgen/MANIFEST.in +++ /dev/null @@ -1,10 +0,0 @@ -exclude randomgen/entropy.c -recursive-exclude randomgen *.c -include versioneer.py -include randomgen/_version.py -include requirements.txt -include README.md -include README.rst -include LICENSE.md -recursive-include randomgen *.py *.pyx *.px[di] *.h *.in *.csv *.md -graft randomgen/src diff --git a/_randomgen/README.md b/_randomgen/README.md index 45c33b928924..2e8073645f30 100644 --- a/_randomgen/README.md +++ b/_randomgen/README.md @@ -47,9 +47,9 @@ which can fully reproduce the sequence produced by NumPy. from randomgen import RandomGenerator # Default basic PRNG is Xoroshiro128 rnd = RandomGenerator() - w = rnd.standard_normal(10000, method='zig') - x = rnd.standard_exponential(10000, method='zig') - y = rnd.standard_gamma(5.5, 10000, method='zig') + w = rnd.standard_normal(10000) + x = rnd.standard_exponential(10000) + y = rnd.standard_gamma(5.5, 10000) ``` * Support for 32-bit floating randoms for core generators. @@ -135,15 +135,15 @@ The RNGs include: ## Status * Builds and passes all tests on: - * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 + * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6, 3.6 * PC-BSD (FreeBSD) 64-bit, Python 2.7 - * OSX 64-bit, Python 3.6 - * Windows 32/64 bit, Python 2.7, 3.5 and 3.6 + * OSX 64-bit, Python 2.7, 3.5, 3.6, 3.7 + * Windows 32/64 bit, Python 2.7, 3.5, 3.6 and 3.7 ## Version The version matched the latest version of NumPy where -`RandomGenerator(MT19937())` passes all NumPy test. +`LegacyGenerator(MT19937())` passes all NumPy test. ## Documentation @@ -168,7 +168,7 @@ Building requires: * Cython (0.26+) * tempita (0.5+), if not provided by Cython -Testing requires pytest (3.0+). +Testing requires pytest (4.0+). **Note:** it might work with other versions but only tested with these versions. diff --git a/_randomgen/README.rst b/_randomgen/README.rst index f4b886e5f74b..7e91b898d17e 100644 --- a/_randomgen/README.rst +++ b/_randomgen/README.rst @@ -12,9 +12,9 @@ generators in Python and NumPy. Python 2.7 Support ------------------ -v1.16 is the final major version that supports Python 2.7. Any bugs in -v1.16 will be patched until the end of 2019. All future releases are -Python 3, with an initial minimum version of 3.5. +Release 1.16.0 is the final version that supports Python 2.7. Any bugs +in v1.16.0 will be patched until the end of 2019. All future releases +are Python 3, with an initial minimum version of 3.5. Compatibility Warning --------------------- @@ -51,9 +51,9 @@ Features from randomgen import RandomGenerator # Default basic PRNG is Xoroshiro128 rnd = RandomGenerator() - w = rnd.standard_normal(10000, method='zig') - x = rnd.standard_exponential(10000, method='zig') - y = rnd.standard_gamma(5.5, 10000, method='zig') + w = rnd.standard_normal(10000) + x = rnd.standard_exponential(10000) + y = rnd.standard_gamma(5.5, 10000) - Support for 32-bit floating randoms for core generators. Currently supported: @@ -147,16 +147,16 @@ Status - Builds and passes all tests on: - - Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6 + - Linux 32/64 bit, Python 2.7, 3.5, 3.6, 3.7 - PC-BSD (FreeBSD) 64-bit, Python 2.7 - - OSX 64-bit, Python 3.6 - - Windows 32/64 bit, Python 2.7, 3.5 and 3.6 + - OSX 64-bit, Python 2.7, 3.5, 3.6, 3.7 + - Windows 32/64 bit, Python 2.7, 3.5, 3.6, and 3.7 Version ------- The version matched the latest version of NumPy where -``RandomGenerator(MT19937())`` passes all NumPy test. +``LegacyGenerator(MT19937())`` passes all NumPy test. Documentation ------------- @@ -185,7 +185,7 @@ Building requires: - Cython (0.26+) - tempita (0.5+), if not provided by Cython -Testing requires pytest (3.0+). +Testing requires pytest (4.0+). **Note:** it might work with other versions but only tested with these versions. diff --git a/_randomgen/appveyor.yml b/_randomgen/appveyor.yml deleted file mode 100644 index 88544620de73..000000000000 --- a/_randomgen/appveyor.yml +++ /dev/null @@ -1,33 +0,0 @@ -skip_tags: true -clone_depth: 50 - -os: Visual Studio 2015 - -environment: - matrix: - - PY_MAJOR_VER: 2 - PYTHON_ARCH: "x86" - - PY_MAJOR_VER: 3 - PYTHON_ARCH: "x86_64" - - PY_MAJOR_VER: 3 - PYTHON_ARCH: "x86" - -platform: - - x64 - -build_script: - - ps: Start-FileDownload "https://repo.continuum.io/miniconda/Miniconda$env:PY_MAJOR_VER-latest-Windows-$env:PYTHON_ARCH.exe" C:\Miniconda.exe; echo "Finished downloading miniconda" - - cmd: C:\Miniconda.exe /S /D=C:\Py - - SET PATH=C:\Py;C:\Py\Scripts;C:\Py\Library\bin;%PATH% - - conda config --set always_yes yes - - conda update conda --quiet - - conda install numpy cython nose pandas pytest --quiet - - python setup.py develop - - set "GIT_DIR=%cd%" - -test_script: - - pytest randomgen - -on_success: - - cd %GIT_DIR%\ - - python benchmark.py diff --git a/_randomgen/ci/conda-install.sh b/_randomgen/ci/conda-install.sh deleted file mode 100644 index cccb8227dcf0..000000000000 --- a/_randomgen/ci/conda-install.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -if [[ ${TRAVIS_OS_NAME} == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda3.sh; fi -if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda3.sh; fi -chmod +x miniconda3.sh -./miniconda3.sh -b -export PATH=${HOME}/miniconda3/bin:$PATH -conda config --set always_yes true -conda update --all --quiet -conda create -n randomgen-test ${PKGS} pip --quiet -source activate randomgen-test - -PKGS="python=${PYTHON} matplotlib numpy" -if [[ -n ${NUMPY} ]]; then PKGS="${PKGS}=${NUMPY}"; fi -PKGS="${PKGS} Cython"; -if [[ -n ${CYTHON} ]]; then PKGS="${PKGS}=${CYTHON}"; fi -PKGS="${PKGS} pandas"; -if [[ -n ${PANDAS} ]]; then PKGS="${PKGS}=${PANDAS}"; fi -echo conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet -conda create -n randomgen-test ${PKGS} pytest setuptools nose --quiet diff --git a/_randomgen/ci/pypi-install.sh b/_randomgen/ci/pypi-install.sh deleted file mode 100644 index ded8dd9212d2..000000000000 --- a/_randomgen/ci/pypi-install.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -pip install numpy cython pandas pytest setuptools nose matplotlib --quiet diff --git a/_randomgen/doc/Makefile b/_randomgen/doc/Makefile deleted file mode 100644 index 1ee9d3660c0d..000000000000 --- a/_randomgen/doc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXPROJ = RandomGen -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/_randomgen/doc/make.bat b/_randomgen/doc/make.bat deleted file mode 100644 index e5a098a3426e..000000000000 --- a/_randomgen/doc/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build -set SPHINXPROJ=RandomGen - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/_randomgen/doc/source/conf.py b/_randomgen/doc/source/conf.py deleted file mode 100644 index d4290d173d9c..000000000000 --- a/_randomgen/doc/source/conf.py +++ /dev/null @@ -1,221 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/stable/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) -import guzzle_sphinx_theme -import randomgen - -# -- Project information ----------------------------------------------------- - -project = 'RandomGen' -copyright = '2018, Kevin Sheppard' -author = 'Kevin Sheppard' - -# The short X.Y version. - -version = randomgen.__version__ -if '+' in version: - version = version.split('+') - version = ''.join((version[0], ' (+', version[1].split('.')[0], ')')) -# The full version, including alpha/beta/rc tags. -release = randomgen.__version__ - -# -- General configuration --------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.napoleon', - 'sphinx.ext.autodoc', - 'sphinx.ext.extlinks', - 'sphinx.ext.todo', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.autosummary', - 'sphinx.ext.mathjax', - 'sphinx.ext.githubpages', - 'IPython.sphinxext.ipython_console_highlighting', - 'IPython.sphinxext.ipython_directive' -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path . -exclude_patterns = [] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'alabaster' -# html_theme = 'sphinx_rtd_theme' -# html_theme_path = ["_themes", ] -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -html_translator_class = 'guzzle_sphinx_theme.HTMLTranslator' -html_theme_path = guzzle_sphinx_theme.html_theme_path() -html_theme = 'guzzle_sphinx_theme' - -# Register the theme as an extension to generate a sitemap.xml -extensions.append("guzzle_sphinx_theme") - -# Guzzle theme options (see theme.conf for more information) -html_theme_options = { - # Set the name of the project to appear in the sidebar - "project_nav_name": project + u" " + version, -} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} -html_sidebars = { - '**': ['logo-text.html', 'globaltoc.html', 'searchbox.html'] -} - -# If false, no module index is generated. -html_domain_indices = True - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'RandomGendoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'RandomGen.tex', 'RandomGen Documentation', - 'Kevin Sheppard', 'manual'), -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'RandomGen', 'RandomGen Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'RandomGen', 'RandomGen Documentation', - author, 'RandomGen', 'Alternative random number generators for Python.', - 'Miscellaneous'), -] - - -# -- Extension configuration ------------------------------------------------- - -# -- Options for intersphinx extension --------------------------------------- - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'statsmodels': ('http://www.statsmodels.org/dev/', None), - 'matplotlib': ('https://matplotlib.org', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), - 'python': ('https://docs.python.org/3', None), - 'numpy': ('https://docs.scipy.org/doc/numpy', None), - 'np': ('https://docs.scipy.org/doc/numpy', None), - 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), - 'pd': ('https://pandas.pydata.org/pandas-docs/stable/', None), -} - -autosummary_generate = True - -doctest_global_setup = """ -import numpy as np - -import randomgen - -import matplotlib.pyplot - -def show(*args, **kwargs): - return - -matplotlib.pyplot.show = show -""" diff --git a/_randomgen/github_deploy_key_bashtage_randomgen.enc b/_randomgen/github_deploy_key_bashtage_randomgen.enc deleted file mode 100644 index ec025c4808eb..000000000000 --- a/_randomgen/github_deploy_key_bashtage_randomgen.enc +++ /dev/null @@ -1 +0,0 @@ -gAAAAABaqYcL3y2gmKPwdhTQvWbDmqvTV9VyGXrEJI0HFVB3ZcmhgwRY_2L9_k7wALgsaQ9-FOqKreKMagBvAiS8IYhW4dUhJ1_6MO0bb8l_fdvkiKY7NH4DXKpO6sGmOg5YPfx44agTLtnI9yuZHo_LgYTkXFS2MQISZJvpmmtgC7fv_ydaRDG3v9c4a4zi7futr6zk0jAlxw29gjyFaReWJQgH6hJTVUVvOq30RJwjpa87jf45mVTsyPdVfHRqn6rcwvGsRKCW6hFnPRsJEP6-ivdjMFbzK6uK1TrswAJ2ZZIGcH84Kaph8kQayMZRL5FUoWsonkGK_SHwiPjmmHRXVMYxSJqNAtjxDgcznzmuazUOwdWCUIkxe0FtJieW5rLwTjT2u1cgcCQ2MKkBiCjO4tORCT0JGCyhOZdsJx6_5i2s1OKaCEb6Uur07itpI2IAEreA38u7CiU150Q7D8zinpPLWuXIrsk9nKfr1YjwXBSVtOBUOuh4Sy9MjcpQuavwJPYVSpNi6_BeIclxP45wjFF5Ai2P8IgaHxSFlMJNfze9H1U-2eTyQaykuZ2WrZBPoGYFRaQExU6jnXOdPMC5FqaO5DV5tvN56fLx9UFXaCqf_UknJRvYnLi94H__nZJWhN6XfCeNaUuPZuuiOFXekK-LC5VFAWXTN84pOesek0-zESKDffFozITTjA-4cvzppUnsSZNm5cXBUdr3wszkNlrQqDVZhP_HU2B8QSilBnnfVEsbKr_-SVQ0s3ipFohPS_GTFKtn8467vvIRgCkks8J1ba5xHb6QMlt2Y2L7yunLh0vmKwqZTVtU-4L4Xm2kKvgHi1kxAaApQiEX2bM-xX7TGNnzRFLKAxpHX4EvO72K2CcQXKu0XkRNc-_c-XcxsWZ7XtvyTCBXNnPtvj26B-FW8XyJH_u0HblrB-AKRgmpRuAhDNh1l_OAcOFHpUrH5t64t6lwOYCR3lXUJJytW-UEz-Nx9j32VX4Ep1IsGjkNuM3FtW4E-iVoGPwYwT3jsGo5rsO6MzrzoEKJbFdgQHnqe3NaxpF6rEVweQTNN2E1LFFuYHnRgo2LuMdK7IDXJ66MCxqEBRMH6Gcne-b5RHEpWoCQAvgyKwU5MclS4M3zLhGnXbtO-q4OL3JV1a-wx9e4vHZJrAolMjvw7a8l5vCDj-FqT5nJIVpG5eKwB_JL24O5d4xUSbgqBm6i1h51L---brkWg9i9YXsjZj5Inf2ZuU3hasZPyXFbTZbpBXN7BMalszLadCOWWsnDJMvl-UJeX2aDDATy5M_4-9Yjt70G1ZJNxZ8K2F6UdXwVifGJGa7jHU9nteCWZVfUdkiexqkLqKebZAlPBpzisrEQw6PmokKP2UO27NBFYTlfYL1NiCahXkOUMPiTKhjQ0_JSqdlUl2igNlNUFSip-63Rk4WtgodQo9iI4icfV5TFkR0h-LPD1m9lIamruWvAQWLU-_daZcN8rdqCWsysuo1ryp80UHHvyTiwloCa2f0ZKr78RIaD_QCkHmevywprNNuMd0ErbAOD7v3dUKjnlvpf8gLpUnu4ZfR1u86OPqsyt2b5tmwB6TWdpaCBNRAjlbFOU8aHDpPDVCAKf1AcEZ1B6p36YgNf5yxmKwc1QEmzXPr1KnSWJRps_QRBX-hEuBu8Q_BUQCjlInJVLcpSgt2lTuJPwwQzdxm5CeU1xdpeWCztSxfghmfE7mzhYizIYa1WaYs32xfZQglEG_O8oXCaU524vyh6cBnIytY3cF1FlwfbKQvbKyKkq8p5YSWe8HX8XRJGVe1bBNM2RYZO5BfLLl5cENIUSbb-REs6j8E61HGgJ9cLBG4-l2QbivSEhKsa4fI0JNVGEL_kwaEOVNHa85y_4oFAQuC4eYOMdgrwGfcD-J-XkE_J6khiLCOaZRcFhFNUfTjghPYzO37D24cAQ9fGnFFehQU-08Ie8SMV2O3fmUV2RbX_h6FXYKZ5Ptp3l2wP5wcuwhPFxPPJ279pswQw9NlHBF3gdtu3_cisqwNfc_HZQ6GXYzbcE7nwTGOY03LN3RjghJgkkeaNs6e0iIxfTJjIqG6-ZWNRNOJKdotjMLVqlhfk0KNZjO5rKEfDfYW_Lbiylgu7I7O-wy-Xn60OTu7na0ObYl-Y9tXkRTZPMNasjDWpfTXKZRp8EX45W-35VKmb0ERj0ee9uXgZxiPGLd3OP8cxIiXqZdZYKwJnD09zZuXwaTa2AAp2WmLYLiF-pDIISNxVF7mCxU9G0AWl0Ml1d5pS5zadM1OYB5yfjx09hlVasaiPaGqIptNtdz8tDQ1ngH-QBPV8wNvSxHwdU4w96pJIY9jG5Z3k-PVO26NNKjZ_KMZhO-3TgQXMJI0GHSyfYFHEMGJuUbeS4ThGyAt2Z6pVKTu7WFjgceseLMmwevJQeyScvtD22t8bpSuqfgxrAGSP5O2-e1UEl_12umZZG3sSd8jc_WNBgX7nSa6LeGAmlY0z_h9SblVl63r2qZi7-Ur0Y7O4JH4rHMDkf07tMU-foCiDDppvZkPRuvPlYgzLmnyOXePN0_1aiou9qbMWmzyJwhrqnt5uZXVHpRwCKKdXRBAcBebuKU-LKqMhWWowf1OUm240628OmQL2oTOaVWBlS3x1XKHMv18_ucbgWB4KaQdidSKMwIXE_LRfhr17g-h2CTQFsfImGKU36ECJHk35K9qr3aZI5X2MLUsOJjdbQiVJsLpdCDbr_HfPDNnux0QiVRZhslKnqOlcv8_6MeKtcqcxDJTi1v1430tpiZj-A2dp3F9YXi_PvCcKD4GheUwN8TUJgEZF3m9Vc80pAWWFDN7Obof_0zCcv7HrXgXCVJHnFzJn0J4AqW6db-DvYAzdejDnLTsTZK9ctJmWxHAWWXYi35aAjj6nalFk97T7EvOr2zS6f_xSUyPeNPs2fIP1lY3togmjPRvwbIN-ZxqLzkfjmxARrLJpqAxK_AvOz2vNlEosQd3zJxk7hEQWRfkTmakvDPgkd5fNsfIGfAt8B_PWnmz41DWKeOlsSQguPAqCE40NSszmyjSBhde8uHN8tGwdQpdcjPt01kgmrdD2GHfLs8zeyNWRzE3qmLT46S1dq1kfQX2j20LXDck9Ox0nFDUXYwaz6pVDPymhPqzh4EHtg0QKePJ5qpY2RDTW3S8UK3YkE3pa_C_-BPcNLVGr_k7WaMWGx0JJ72W2MqcoXgq3bZq_CZeseeKm3rH3YiaibidLk4WqMblcWUurHW09vFCNSOyQ28jkBeMSgadJ2zEbK9M1QmsDxxSCzWtIn_y7nDLCGh0NzD2alVp4QfxwjF5ZEYSXZOYXdhRBkd3pRX9perJT_zlQf7Ag2otXUZE-J6TkDAAwhWxxUFQ0iUIKNKtO-ocM8YevCyl0EK06AzX6jmShrE5eZpej7o7DA2dCoLYksacloBbonqDjkpXR1uZcGJSnhZm29UeSSGQN7cqgR5DDCHkthvOn8gZxS8vr1fQiswazUaMCClHUD_O88IlLXnqXj4n-84TMT9iBGN3iaab4P-fb2t1Azcd8uSGl3CwNEouEekdvVWHSp3bhMkwpPuvakJheLOGfX7npwWo5iIEvdA0VhesiEV8ZVJYCt3zmOwQtI-Sk5uAVAWAieB6-up9KWtwoF89C64CLp99srzLkaPddQJKtTruYQER5l3hL1LBe5g8XPEBNMrFjp2xIN8mNYpZRt41nFxsHoA9xnsv4NXWbwqnkyImP0Wm9HmclvwTOZ9xdT5Ryj8u97XSOz4y8T5Ql5UPwRBujiBI91GQnEKz3FPmUzS70Bbrg3XIirpbPqcRp_VnnxXT8AX0zGZiuWvx94NFa5h4a11vYpeLnKzQ2RyTHB96CSpxxdXHAHfMvc9ib3XzlKRUUfDX0x0tDBj3BkV5UMgLtn2RRCgT1PydLn13wYbeNwfb5GlGutiqQY_QTuUOqSII-2vyNzA5FUPpzofXGYwAz52pGwpZ7w0s4fBpXocxWt0gGW5wxDzTEX3UdkbRsN1GXs5tYkdbcCW_jPrVcq7pUGgOyGXMEYnZUA1ack2h6nSwlxbx_Aka_VyxZCJFYJW9S165lIhm7KkDCfRpQdoA4Fx27aAXwWL70ipNCyNHFOERXD5SoVMJDcz3-cXkttEddXooygKoXojR4epBuxhSkUNxgnd70faZaIC8_L5_ZlZIBn-lH3jLT5Yuzt8-weKpAyczteZ8eLB0YlnYlqhIVFYy4QBR8iejRZBXABKiuIWz_Xf4qu6UGwHTQ-1BBfl9mr0RxULn7NGtfbQ72Xwad-HlT1MnEd_6o95MkFvHbdINlpkaeVwiAgUSFbITPh7x8JaQKlAzjROJQdhGvT4j42woumzQtuqr9UnDWtf8aECkrJP_-AEy1BLbXmUo= \ No newline at end of file diff --git a/_randomgen/randomgen/__init__.py b/_randomgen/randomgen/__init__.py deleted file mode 100644 index b4c942c8fa8d..000000000000 --- a/_randomgen/randomgen/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from randomgen.dsfmt import DSFMT -from randomgen.generator import RandomGenerator -from randomgen.mt19937 import MT19937 -from randomgen.pcg32 import PCG32 -from randomgen.pcg64 import PCG64 -from randomgen.philox import Philox -from randomgen.threefry import ThreeFry -from randomgen.threefry32 import ThreeFry32 -from randomgen.xoroshiro128 import Xoroshiro128 -from randomgen.xorshift1024 import Xorshift1024 -from randomgen.xoshiro256starstar import Xoshiro256StarStar -from randomgen.xoshiro512starstar import Xoshiro512StarStar - -__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar', - 'hypergeometric', 'multinomial', 'random_sample'] - -from ._version import get_versions - -__version__ = get_versions()['version'] -del get_versions diff --git a/_randomgen/randomgen/_testing.py b/_randomgen/randomgen/_testing.py deleted file mode 100644 index 07d41677b7c4..000000000000 --- a/_randomgen/randomgen/_testing.py +++ /dev/null @@ -1,315 +0,0 @@ -""" -Shim for NumPy's suppress_warnings -""" - - -try: - from numpy.testing import suppress_warnings -except ImportError: - - # The following two classes are copied from python 2.6 warnings module - # (context manager) - class WarningMessage(object): - - """ - Holds the result of a single showwarning() call. - Deprecated in 1.8.0 - Notes - ----- - `WarningMessage` is copied from the Python 2.6 warnings module, - so it can be used in NumPy with older Python versions. - """ - - _WARNING_DETAILS = ("message", "category", "filename", "lineno", - "file", "line") - - def __init__(self, message, category, filename, lineno, file=None, - line=None): - local_values = locals() - for attr in self._WARNING_DETAILS: - setattr(self, attr, local_values[attr]) - if category: - self._category_name = category.__name__ - else: - self._category_name = None - - def __str__(self): - return ("{message : %r, category : %r, " - "filename : %r, lineno : %s, " - "line : %r}" % (self.message, self._category_name, - self.filename, self.lineno, self.line)) - - import re - import warnings - from functools import wraps - - class suppress_warnings(object): - """ - Context manager and decorator doing much the same as - ``warnings.catch_warnings``. - However, it also provides a filter mechanism to work around - http://bugs.python.org/issue4180. - This bug causes Python before 3.4 to not reliably show warnings again - after they have been ignored once (even within catch_warnings). It - means that no "ignore" filter can be used easily, since following - tests might need to see the warning. Additionally it allows easier - specificity for testing warnings and can be nested. - Parameters - ---------- - forwarding_rule : str, optional - One of "always", "once", "module", or "location". Analogous to - the usual warnings module filter mode, it is useful to reduce - noise mostly on the outmost level. Unsuppressed and unrecorded - warnings will be forwarded based on this rule. Defaults to - "always". "location" is equivalent to the warnings "default", match - by exact location the warning warning originated from. - Notes - ----- - Filters added inside the context manager will be discarded again - when leaving it. Upon entering all filters defined outside a - context will be applied automatically. - When a recording filter is added, matching warnings are stored in the - ``log`` attribute as well as in the list returned by ``record``. - If filters are added and the ``module`` keyword is given, the - warning registry of this module will additionally be cleared when - applying it, entering the context, or exiting it. This could cause - warnings to appear a second time after leaving the context if they - were configured to be printed once (default) and were already - printed before the context was entered. - Nesting this context manager will work as expected when the - forwarding rule is "always" (default). Unfiltered and unrecorded - warnings will be passed out and be matched by the outer level. - On the outmost level they will be printed (or caught by another - warnings context). The forwarding rule argument can modify this - behaviour. - Like ``catch_warnings`` this context manager is not threadsafe. - Examples - -------- - >>> with suppress_warnings() as sup: - ... sup.filter(DeprecationWarning, "Some text") - ... sup.filter(module=np.ma.core) - ... log = sup.record(FutureWarning, "Does this occur?") - ... command_giving_warnings() - ... # The FutureWarning was given once, the filtered warnings were - ... # ignored. All other warnings abide outside settings (may be - ... # printed/error) - ... assert_(len(log) == 1) - ... assert_(len(sup.log) == 1) # also stored in log attribute - Or as a decorator: - >>> sup = suppress_warnings() - >>> sup.filter(module=np.ma.core) # module must match exact - >>> @sup - >>> def some_function(): - ... # do something which causes a warning in np.ma.core - ... pass - """ - def __init__(self, forwarding_rule="always"): - self._entered = False - - # Suppressions are instance or defined inside one with block: - self._suppressions = [] - - if forwarding_rule not in {"always", "module", "once", "location"}: - raise ValueError("unsupported forwarding rule.") - self._forwarding_rule = forwarding_rule - - def _clear_registries(self): - if hasattr(warnings, "_filters_mutated"): - # clearing the registry should not be necessary on new pythons, - # instead the filters should be mutated. - warnings._filters_mutated() - return - # Simply clear the registry, this should normally be harmless, - # note that on new pythons it would be invalidated anyway. - for module in self._tmp_modules: - if hasattr(module, "__warningregistry__"): - module.__warningregistry__.clear() - - def _filter(self, category=Warning, message="", module=None, - record=False): - if record: - record = [] # The log where to store warnings - else: - record = None - if self._entered: - if module is None: - warnings.filterwarnings( - "always", category=category, message=message) - else: - module_regex = module.__name__.replace('.', r'\.') + '$' - warnings.filterwarnings( - "always", category=category, message=message, - module=module_regex) - self._tmp_modules.add(module) - self._clear_registries() - - self._tmp_suppressions.append( - (category, message, re.compile(message, re.I), module, - record)) - else: - self._suppressions.append( - (category, message, re.compile(message, re.I), module, - record)) - - return record - - def filter(self, category=Warning, message="", module=None): - """ - Add a new suppressing filter or apply it if the state is entered. - Parameters - ---------- - category : class, optional - Warning class to filter - message : string, optional - Regular expression matching the warning message. - module : module, optional - Module to filter for. Note that the module (and its file) - must match exactly and cannot be a submodule. This may make - it unreliable for external modules. - Notes - ----- - When added within a context, filters are only added inside - the context and will be forgotten when the context is exited. - """ - self._filter(category=category, message=message, module=module, - record=False) - - def record(self, category=Warning, message="", module=None): - """ - Append a new recording filter or apply it if the state is entered. - All warnings matching will be appended to the ``log`` attribute. - Parameters - ---------- - category : class, optional - Warning class to filter - message : string, optional - Regular expression matching the warning message. - module : module, optional - Module to filter for. Note that the module (and its file) - must match exactly and cannot be a submodule. This may make - it unreliable for external modules. - Returns - ------- - log : list - A list which will be filled with all matched warnings. - Notes - ----- - When added within a context, filters are only added inside - the context and will be forgotten when the context is exited. - """ - return self._filter(category=category, message=message, - module=module, record=True) - - def __enter__(self): - if self._entered: - raise RuntimeError("cannot enter suppress_warnings twice.") - - self._orig_show = warnings.showwarning - if hasattr(warnings, "_showwarnmsg"): - self._orig_showmsg = warnings._showwarnmsg - self._filters = warnings.filters - warnings.filters = self._filters[:] - - self._entered = True - self._tmp_suppressions = [] - self._tmp_modules = set() - self._forwarded = set() - - self.log = [] # reset global log (no need to keep same list) - - for cat, mess, _, mod, log in self._suppressions: - if log is not None: - del log[:] # clear the log - if mod is None: - warnings.filterwarnings( - "always", category=cat, message=mess) - else: - module_regex = mod.__name__.replace('.', r'\.') + '$' - warnings.filterwarnings( - "always", category=cat, message=mess, - module=module_regex) - self._tmp_modules.add(mod) - warnings.showwarning = self._showwarning - if hasattr(warnings, "_showwarnmsg"): - warnings._showwarnmsg = self._showwarnmsg - self._clear_registries() - - return self - - def __exit__(self, *exc_info): - warnings.showwarning = self._orig_show - if hasattr(warnings, "_showwarnmsg"): - warnings._showwarnmsg = self._orig_showmsg - warnings.filters = self._filters - self._clear_registries() - self._entered = False - del self._orig_show - del self._filters - - def _showwarnmsg(self, msg): - self._showwarning(msg.message, msg.category, msg.filename, - msg.lineno, msg.file, msg.line, use_warnmsg=msg) - - def _showwarning(self, message, category, filename, lineno, - *args, **kwargs): - use_warnmsg = kwargs.pop("use_warnmsg", None) - for cat, _, pattern, mod, rec in ( - self._suppressions + self._tmp_suppressions)[::-1]: - if (issubclass(category, cat) and - pattern.match(message.args[0]) is not None): - if mod is None: - # Message and category match, recorded or ignored - if rec is not None: - msg = WarningMessage(message, category, filename, - lineno, **kwargs) - self.log.append(msg) - rec.append(msg) - return - # Use startswith, because warnings strips the c or o from - # .pyc/.pyo files. - elif mod.__file__.startswith(filename): - # The message and module (filename) match - if rec is not None: - msg = WarningMessage(message, category, filename, - lineno, **kwargs) - self.log.append(msg) - rec.append(msg) - return - - # There is no filter in place, so pass to the outside handler - # unless we should only pass it once - if self._forwarding_rule == "always": - if use_warnmsg is None: - self._orig_show(message, category, filename, lineno, - *args, **kwargs) - else: - self._orig_showmsg(use_warnmsg) - return - - if self._forwarding_rule == "once": - signature = (message.args, category) - elif self._forwarding_rule == "module": - signature = (message.args, category, filename) - elif self._forwarding_rule == "location": - signature = (message.args, category, filename, lineno) - - if signature in self._forwarded: - return - self._forwarded.add(signature) - if use_warnmsg is None: - self._orig_show(message, category, filename, lineno, *args, - **kwargs) - else: - self._orig_showmsg(use_warnmsg) - - def __call__(self, func): - """ - Function decorator to apply certain suppressions to a whole - function. - """ - @wraps(func) - def new_func(*args, **kwargs): - with self: - return func(*args, **kwargs) - - return new_func diff --git a/_randomgen/randomgen/examples/cython/extending_distributions.pyx b/_randomgen/randomgen/examples/cython/extending_distributions.pyx deleted file mode 100644 index 630d952bf75e..000000000000 --- a/_randomgen/randomgen/examples/cython/extending_distributions.pyx +++ /dev/null @@ -1,48 +0,0 @@ -import numpy as np -cimport numpy as np -cimport cython -from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from randomgen.common cimport * -from randomgen.distributions cimport random_gauss_zig -from randomgen.xoroshiro128 import Xoroshiro128 - -@cython.boundscheck(False) -@cython.wraparound(False) -def normals_zig(Py_ssize_t n): - cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" - cdef double[::1] random_values - - x = Xoroshiro128() - capsule = x.capsule - if not PyCapsule_IsValid(capsule, capsule_name): - raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(n) - 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 brng_t *rng - cdef const char *capsule_name = "BasicRNG" - cdef double[::1] random_values - - x = Xoroshiro128() - capsule = x.capsule - # Optional check that the capsule if from a Basic RNG - if not PyCapsule_IsValid(capsule, capsule_name): - raise ValueError("Invalid pointer to anon_func_state") - # Cast the pointer - rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(n) - for i in range(n): - # Call the function - random_values[i] = rng.next_double(rng.state) - randoms = np.asarray(random_values) - return randoms \ No newline at end of file diff --git a/_randomgen/randomgen/legacy/__init__.py b/_randomgen/randomgen/legacy/__init__.py deleted file mode 100644 index b59b221b49bc..000000000000 --- a/_randomgen/randomgen/legacy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from randomgen.legacy.legacy import LegacyGenerator - -__all__ = ['LegacyGenerator'] diff --git a/_randomgen/randomgen/legacy/legacy.pyx b/_randomgen/randomgen/legacy/legacy.pyx deleted file mode 100644 index 33198a624ba4..000000000000 --- a/_randomgen/randomgen/legacy/legacy.pyx +++ /dev/null @@ -1,1988 +0,0 @@ -#!python -#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 -from __future__ import absolute_import - -import warnings -import operator - -from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from libc.stdlib cimport malloc, free -cimport numpy as np -import numpy as np -cimport cython - -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -from randomgen.common cimport cont, disc, CONS_NONE, CONS_POSITIVE, CONS_NON_NEGATIVE, CONS_BOUNDED_0_1 -from randomgen.distributions cimport brng_t -from randomgen.legacy.legacy_distributions cimport * -from randomgen.xoroshiro128 import Xoroshiro128 -import randomgen.pickle - -np.import_array() - -cdef class LegacyGenerator: - """ - LegacyGenerator(brng=None) - - Container providing legacy generators. - - ``LegacyGenerator`` exposes a number of methods for generating random - numbers for a set of distributions where the method used to produce random - samples has changed. Three core generators have changed: normal, exponential - and gamma. These have been replaced by faster Ziggurat-based methods in - ``RandomGenerator``. ``_LegacyGenerator`` retains the slower methods - to produce samples from these distributions as well as from distributions - that depend on these such as the Chi-square, power or Weibull. - - **No Compatibility Guarantee** - - ``LegacyGenerator`` is evolving and so it isn't possible to provide a - compatibility guarantee like NumPy does. In particular, better algorithms - have already been added. This will change once ``RandomGenerator`` - stabilizes. - - Parameters - ---------- - brng : Basic RNG, optional - Basic RNG to use as the core generator. If none is provided, uses - Xoroshiro128. - - Examples - -------- - Exactly reproducing a NumPy stream requires both a ``RandomGenerator`` - and a ``LegacyGenerator``. These must share a common ``MT19937`` basic - RNG. Functions that are available in LegacyGenerator must be called - from ``LegacyGenerator``, and other functions must be called from - ``RandomGenerator``. - - >>> from randomgen import RandomGenerator, MT19937 - >>> from randomgen.legacy import LegacyGenerator - >>> mt = MT19937(12345) - >>> lg = LegacyGenerator(mt) - >>> rg = RandomGenerator(mt) - >>> x = lg.standard_normal(10) - >>> rg.shuffle(x) - >>> x[0] - 0.09290787674371767 - >>> lg.standard_exponential() - 1.6465621229906502 - - The equivalent commands from NumPy produce identical output. - - >>> from numpy.random import RandomState - >>> rs = RandomState(12345) - >>> x = rs.standard_normal(10) - >>> rs.shuffle(x) - >>> x[0] - 0.09290787674371767 - >>> rs.standard_exponential() - 1.6465621229906502 - """ - cdef public object _basicrng - cdef brng_t *_brng - cdef aug_brng_t *_aug_state - cdef object lock - - def __init__(self, brng=None): - if brng is None: - brng = Xoroshiro128() - self._basicrng = brng - - capsule = brng.capsule - cdef const char *name = "BasicRNG" - if not PyCapsule_IsValid(capsule, name): - raise ValueError("Invalid brng. The brng must be instantized.") - self._brng = PyCapsule_GetPointer(capsule, name) - self._aug_state = malloc(sizeof(aug_brng_t)) - self._aug_state.basicrng = self._brng - self._reset_gauss() - self.lock = Lock() - - def __dealloc__(self): - free(self._aug_state) - - def __repr__(self): - return self.__str__() + ' at 0x{:X}'.format(id(self)) - - def __str__(self): - return self.__class__.__name__ + '(' + self._basicrng.__class__.__name__ + ')' - - # Pickling support: - def __getstate__(self): - return self.state - - def __setstate__(self, state): - self.state = state - - def __reduce__(self): - return (randomgen.pickle.__generator_ctor, - (self.state['brng'],), - self.state) - - cdef _reset_gauss(self): - self._aug_state.has_gauss = 0 - self._aug_state.gauss = 0.0 - - def seed(self, *args, **kwargs): - """ - Reseed the basic RNG. - - Parameters depend on the basic RNG used. - - Notes - ----- - Arguments are directly passed to the basic RNG. This is a convenience - function. - - The best method to access seed is to directly use a basic RNG instance. - This example demonstrates this best practice. - - >>> from randomgen import MT19937 - >>> from randomgen.legacy import LegacyGenerator - >>> brng = MT19937(123456789) - >>> lg = brng.generator - >>> brng.seed(987654321) - - The method used to create the generator is not important. - - >>> brng = MT19937(123456789) - >>> lg = LegacyGenerator(brng) - >>> brng.seed(987654321) - - These best practice examples are equivalent to - - >>> lg = LegacyGenerator(MT19937(123456789)) - >>> lg.seed(987654321) - """ - - # TODO: Should this remain - self._basicrng.seed(*args, **kwargs) - self._reset_gauss() - return self - - @property - def state(self): - """ - Get or set the augmented state - - Returns the basic RNGs state as well as two values added to track - normal generation using the Polar (Box-Muller-like) method. - - Returns - ------- - state : dict - Dictionary containing the information required to describe the - state of the Basic RNG with two additional fields, gauss and - has_gauss, required to store generated Polar transformation - (Box-Muller-like) normals. - """ - st = self._basicrng.state - st['has_gauss'] = self._aug_state.has_gauss - st['gauss'] = self._aug_state.gauss - return st - - @state.setter - def state(self, value): - if isinstance(value, tuple): - if value[0] != 'MT19937': - raise ValueError('tuple only supported for MT19937') - st = {'brng': value[0], - 'state': {'key': value[1], 'pos': value[2]}} - if len(value) > 3: - st['has_gauss'] = value[3] - st['gauss'] = value[4] - value = st - self._aug_state.gauss = value.get('gauss', 0.0) - self._aug_state.has_gauss = value.get('has_gauss', 0) - self._basicrng.state = value - - 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`. - 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 = randomgen.generator.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 randn(self, *args): - """ - randn(d0, d1, ..., dn) - - 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. - - This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `standard_normal` instead. - - Parameters - ---------- - d0, d1, ..., dn : int, optional - The dimensions of the returned array, should be all positive. - If no argument is given a single Python float is returned. - - Returns - ------- - Z : ndarray or float - A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from - the standard normal distribution, or a single such float if - no parameters were supplied. - - See Also - -------- - standard_normal : Similar, but takes a tuple as its argument. - - Notes - ----- - For random samples from :math:`N(\\mu, \\sigma^2)`, use: - - ``sigma * randomgen.generator.randn(...) + mu`` - - Examples - -------- - >>> randomgen.generator.randn() - 2.1923875335537315 #random - - Two-by-four array of samples from N(3, 6.25): - - >>> 2.5 * randomgen.generator.randn(2, 4) + 3 - 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(size=args) - - # Complicated, continuous distributions: - def standard_normal(self, size=None): - """ - standard_normal(size=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. - - Returns - ------- - out : float or ndarray - Drawn samples. - - Examples - -------- - >>> s = randomgen.generator.standard_normal(8000) - >>> s - array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, #random - -0.38672696, -0.4685006 ]) #random - >>> s.shape - (8000,) - >>> s = randomgen.generator.standard_normal(size=(3, 4, 2)) - >>> s.shape - (3, 4, 2) - - """ - 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): - """ - 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. - 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 - `numpy.random.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 = randomgen.generator.normal(mu, sigma, 1000) - - Verify the mean and the variance: - - >>> abs(mu - np.mean(s)) < 0.01 - True - - >>> abs(sigma - np.std(s, ddof=1)) < 0.01 - True - - 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() - - """ - 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): - """ - standard_gamma(shape, size=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, should 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 ``shape`` is a scalar. Otherwise, - ``np.array(shape).size`` samples are drawn. - - 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 = randomgen.generator.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 - >>> count, bins, ignored = plt.hist(s, 50, density=True) - >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ - ... (sps.gamma(shape) * scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') - >>> plt.show() - """ - 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): - """ - 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. Should be greater than zero. - scale : float or array_like of floats, optional - The scale of the gamma distribution. Should be greater than zero. - 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 and dispersion - >>> s = randomgen.generator.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 - >>> count, bins, ignored = plt.hist(s, 50, density=True) - >>> y = bins**(shape-1)*(np.exp(-bins/scale) / - ... (sps.gamma(shape)*scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') - >>> plt.show() - - """ - 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): - """ - 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 should 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 : int or array_like of ints - Degrees of freedom in numerator. Should be greater than zero. - dfden : int or array_like of ints - Degrees of freedom in denominator. Should be greater than zero. - 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 = randomgen.generator.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(&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): - """ - 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 : int or array_like of ints - Parameter, should be > 1. - dfden : int or array_like of ints - Parameter, should be > 1. - nonc : float or array_like of floats - Parameter, should 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. - - >>> dfnum = 3 # between group deg of freedom - >>> dfden = 20 # within groups degrees of freedom - >>> nonc = 3.0 - >>> nc_vals = randomgen.generator.noncentral_f(dfnum, dfden, nonc, 1000000) - >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = randomgen.generator.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(&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): - """ - 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 : int or array_like of ints - Number of degrees of freedom. - 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 - -------- - >>> randomgen.generator.chisquare(2,4) - array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random - - """ - 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): - """ - noncentral_chisquare(df, nonc, size=None) - - Draw samples from a noncentral chi-square distribution. - - The noncentral :math:`\\chi^2` distribution is a generalisation of - the :math:`\\chi^2` distribution. - - Parameters - ---------- - df : int or array_like of ints - Degrees of freedom, should be > 0 as of NumPy 1.10.0, - should be > 1 for earlier versions. - nonc : float or array_like of floats - Non-centrality, should 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-square distribution" - https://en.wikipedia.org/wiki/Noncentral_chi-square_distribution - - Examples - -------- - Draw values from the distribution and plot the histogram - - >>> import matplotlib.pyplot as plt - >>> values = plt.hist(randomgen.generator.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(randomgen.generator.noncentral_chisquare(3, .0000001, 100000), - ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(randomgen.generator.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(randomgen.generator.noncentral_chisquare(3, 20, 100000), - ... bins=200, density=True) - >>> plt.show() - - """ - 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): - """ - 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", - http://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: - - >>> s = randomgen.generator.standard_cauchy(1000000) - >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well - >>> import matplotlib.pyplot as plt - >>> plt.hist(s, bins=100) - >>> plt.show() - - """ - 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): - """ - 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 : int or array_like of ints - Degrees of freedom, should 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 = randomgen.generator.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>> a, m = 3., 2. # shape and mode - >>> s = (randomgen.generator.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(&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): - """ - 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: - - >>> a = 5. # shape - >>> s = randomgen.generator.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(randomgen.generator.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(&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): - """ - 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. Should be greater than zero. - 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. - http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf - - Examples - -------- - Draw samples from the distribution: - - >>> a = 5. # shape - >>> samples = 1000 - >>> s = randomgen.generator.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 - >>> rvs = randomgen.generator.power(5, 1000000) - >>> rvsp = randomgen.generator.pareto(5, 1000000) - >>> xx = np.linspace(0,1,100) - >>> powpdf = stats.powerlaw.pdf(xx,5) - - >>> plt.figure() - >>> plt.hist(rvs, bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('randomgen.generator.power(5)') - - >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') - - >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of stats.pareto(5)') - - """ - 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 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. Should - be greater than zero. 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: - - >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = randomgen.generator.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. - >>> b = [] - >>> for i in range(1000): - ... a = 10. + randomgen.generator.randn(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(&legacy_lognormal, self._aug_state, size, self.lock, 2, - mean, 'mean', CONS_NONE, - sigma, 'sigma', CONS_NON_NEGATIVE, - 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, "Wald distribution" - https://en.wikipedia.org/wiki/Wald_distribution - - Examples - -------- - Draw values from the distribution and plot the histogram: - - >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) - >>> plt.show() - - """ - 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 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 an - integer > 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. - 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 density for the negative binomial distribution is - - .. math:: P(N;n,p) = \\binom{N+n-1}{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. - - 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 = randomgen.generator.negative_binomial(1, 0.9, 100000) - >>> for i in range(1, 11): # doctest: +SKIP - ... probability = sum(s>> 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 = randomgen.generator.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 = randomgen.generator.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] - - """ - 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. - - (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 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 = randomgen.generator.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 - cdef np.npy_intp totsize - cdef np.ndarray alpha_arr, val_arr - cdef double *alpha_data - cdef double *val_data - cdef np.npy_intp i, j - cdef double acc, invacc - - k = len(alpha) - alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) - if np.any(np.less_equal(alpha_arr, 0)): - raise ValueError('alpha <= 0') - alpha_data = 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 = diric - val_data= 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] = 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 diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.c deleted file mode 100644 index 981aeab8478c..000000000000 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Written in 2016 by David Blackman and 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 . */ - -/* This is the successor to xorshift128+. It is the fastest full-period - generator passing BigCrush without systematic failures, but due to the - relatively short period it is acceptable only for applications with a - mild amount of parallelism; otherwise, use a xorshift1024* generator. - - Beside passing BigCrush, this generator passes the PractRand test suite - up to (and included) 16TB, with the exception of binary rank tests, as - the lowest bit of this generator is an LFSR of degree 128. The next bit - can be described by an LFSR of degree 8256, but in the long run it will - fail linearity tests, too. The other bits needs a much higher degree to - be represented as LFSRs. - - We suggest to use a sign test to extract a random Boolean value, and - right shifts to extract subsets of bits. - - Note that the generator uses a simulated rotate operation, which most C - compilers will turn into a single instruction. In Java, you can use - Long.rotateLeft(). In languages that do not make low-level rotation - instructions accessible xorshift128+ could be faster. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s. */ - -#include "xoroshiro128.h" - -extern INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); - -extern INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); - -void xoroshiro128_jump(xoroshiro128_state *state) { - int i, b; - uint64_t s0; - uint64_t s1; - static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; - - s0 = 0; - s1 = 0; - for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= state->s[0]; - s1 ^= state->s[1]; - } - xoroshiro128_next(&state->s[0]); - } - - state->s[0] = s0; - state->s[1] = s1; -} diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c b/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c deleted file mode 100644 index c0293cc2b586..000000000000 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Written in 2016 by David Blackman and 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 . */ - -#include - -/* This is the successor to xorshift128+. It is the fastest full-period - generator passing BigCrush without systematic failures, but due to the - relatively short period it is acceptable only for applications with a - mild amount of parallelism; otherwise, use a xorshift1024* generator. - - Beside passing BigCrush, this generator passes the PractRand test suite - up to (and included) 16TB, with the exception of binary rank tests, as - the lowest bit of this generator is an LFSR of degree 128. The next bit - can be described by an LFSR of degree 8256, but in the long run it will - fail linearity tests, too. The other bits needs a much higher degree to - be represented as LFSRs. - - We suggest to use a sign test to extract a random Boolean value, and - right shifts to extract subsets of bits. - - Note that the generator uses a simulated rotate operation, which most C - compilers will turn into a single instruction. In Java, you can use - Long.rotateLeft(). In languages that do not make low-level rotation - instructions accessible xorshift128+ could be faster. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s. */ - -uint64_t s[2]; - -static inline uint64_t rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); -} - -uint64_t next(void) { - const uint64_t s0 = s[0]; - uint64_t s1 = s[1]; - const uint64_t result = s0 + s1; - - s1 ^= s0; - s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b - s[1] = rotl(s1, 36); // c - - return result; -} - -/* This is the jump function for the generator. It is equivalent - to 2^64 calls to next(); it can be used to generate 2^64 - non-overlapping subsequences for parallel computations. */ - -void jump(void) { - static const uint64_t JUMP[] = {0xbeac0467eba5facb, 0xd86b048b86aa9922}; - - uint64_t s0 = 0; - uint64_t s1 = 0; - for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (int b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= s[0]; - s1 ^= s[1]; - } - next(); - } - - s[0] = s0; - s[1] = s1; -} diff --git a/_randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv b/_randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv deleted file mode 100644 index 8289ff27eb96..000000000000 --- a/_randomgen/randomgen/tests/data/xoroshiro128-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0x86f9f4feeebed928 -1, 0xcd2c9d2d1dc1c071 -2, 0x94741e0555641979 -3, 0x81eed88d38a9138e -4, 0x54b9f49cd0035507 -5, 0x8c112b85821a173a -6, 0x51f4c2eabf05c192 -7, 0xefa6a9ad4ca56d94 -8, 0xd3bd969b3aeb5457 -9, 0xcd4f28af5618e25a -10, 0xa20fd197fb60aad -11, 0x796b5146f61afc52 -12, 0xf6fe619effce6d62 -13, 0x763ed6613d00e8bd -14, 0x333d357571b249c -15, 0xc2a39f35ba8f4ce6 -16, 0xae35d916c6cf8a2b -17, 0xfdfaa6b7eb9591d3 -18, 0x52668584489de943 -19, 0xca982b4b760effb8 -20, 0x32c7256797c26f09 -21, 0x3115b9539d722cc -22, 0x5183f1d23dd2f56e -23, 0xa0a2a2c524e6650c -24, 0x3191f4b5260e5a2d -25, 0x1eebe2655fb4f190 -26, 0x5781c6b75a253a88 -27, 0xae45a39543b4140d -28, 0xfc62724b20d2df78 -29, 0x3770290ba157dc9c -30, 0xc4731569807dbff4 -31, 0xd42ec771a7a0a08f -32, 0x743276e0eb868d75 -33, 0x37f95d1ba1faebc6 -34, 0x3b4800b089a323cf -35, 0x437fa9c71af61839 -36, 0x1cab936dd28c6f1c -37, 0xe9d60347286dd9f0 -38, 0x716625cbd57bbd63 -39, 0xbd6c0f5e6aea7288 -40, 0x7c782d5b111a89f3 -41, 0xaeb1b9478b99970 -42, 0xbdffccb6a96cb533 -43, 0x9423e6ea789f29f1 -44, 0x53df9a7a0ea73fe6 -45, 0x7d9bec5c15c7e349 -46, 0xd1fc83fcf223aea5 -47, 0xd1dce35338ad3bab -48, 0x297bd5f1cf79e758 -49, 0x19ec39a6191419da -50, 0x45e57323ad58071b -51, 0x395bcbebe1ddf611 -52, 0x22d9065efb013222 -53, 0x4ea2d534fd9fecb3 -54, 0x9b9779e1edeb2e27 -55, 0x1ba777ba576a236e -56, 0x23cf95e34d62dd3f -57, 0x6d1689730795e6bd -58, 0x24e510f9d2f65379 -59, 0x1e12d607e78701e8 -60, 0x3347fe3ddc50a23e -61, 0x331754f825305d97 -62, 0xf21a675c0344709c -63, 0xcc9bd2062ae5fb39 -64, 0xd2dcd3a1ee6afe9e -65, 0xbdb0388382c408d1 -66, 0x19476497aaef64ad -67, 0x906dfff3b1181dd7 -68, 0x47edd3c528f4c753 -69, 0xba2a0f289279aec2 -70, 0x710bc73fd1c732a9 -71, 0xe0238b1ab604610d -72, 0x10f68d7eb0d19e19 -73, 0xc13654f8b8f3d9b7 -74, 0x112c76bf71ad04a9 -75, 0x4b9d965062e9a0fd -76, 0xe0b13496fec19aa8 -77, 0x999493dababe73c8 -78, 0x87104db5240f12fb -79, 0x8fc8dff016c96a13 -80, 0x3eff4853e8b167a8 -81, 0x438b6f5c3d10b85d -82, 0xc2f94a0707d949f5 -83, 0x87981b13beefb01f -84, 0x1718db5072923bb2 -85, 0xbe7ae4310234b5f1 -86, 0x3ad4306f2b2b3b47 -87, 0x9de166baaf152f81 -88, 0xebca2cf057a00802 -89, 0x99bfd19b5e0a87b2 -90, 0x5ae7b3ab9d2623c0 -91, 0x8de5811587a53d2e -92, 0x629a57a87d068ee4 -93, 0xfd80a82607740601 -94, 0x5758bfc8610d0b8b -95, 0x8f0c00fab932c1f5 -96, 0x3d49bd296a34582d -97, 0xc99c1bb8319ce526 -98, 0x1dd5ba47ac1443ba -99, 0xb5a40a33c9ca1cf9 -100, 0xa1025156b711394c -101, 0xdb3ef94ee8bc71a4 -102, 0x6d3292123ffa9bc9 -103, 0x4b9683ebf2f98d1f -104, 0x4d1a4709b547bfe7 -105, 0x3623a9c4054355b1 -106, 0xed15f8852d329b4d -107, 0x60ef76852f40e346 -108, 0xe64c2bfc6d0ef2dc -109, 0xf286f874cfb68ee2 -110, 0xb1b07a7ca9268329 -111, 0xf618a9bfe00b7cdd -112, 0x54a40c4f52cab527 -113, 0x5007a4d41eaf0af1 -114, 0x6fa7f2210a7b7f3a -115, 0x7b448faa473ad765 -116, 0x901b6276232cb3c2 -117, 0xd69d06b85d118dfd -118, 0xf8fb03c5dfef937a -119, 0x5a53e96d5ebc4689 -120, 0xe24e81bbd9772b3c -121, 0xa996ed94405e1811 -122, 0x7d8712833a4cbd96 -123, 0xd8b81a509f392481 -124, 0x76b52a270551424b -125, 0x4c854325eaa4ef23 -126, 0xc8823e5a74757b2f -127, 0x9ac8deb0aa215a3f -128, 0x89641160b3eeafdd -129, 0x17781aba3d908856 -130, 0xd12e5f215de0a3b4 -131, 0xd94cd412b8bef057 -132, 0x40e85ebd5844b9e8 -133, 0xa581cf7ef62e70a2 -134, 0x74953df639f8a9a2 -135, 0xaa92c9804434caa6 -136, 0xf186398542a15448 -137, 0xa0888e1233d64da3 -138, 0x277d14f22bc64c91 -139, 0x2851b3b5fc49ad5 -140, 0x68182666788909 -141, 0x5ea068625e49839 -142, 0x63bac5a5d225e8db -143, 0x2dd9db0ad24aff05 -144, 0x3f637e71528ad6ad -145, 0xe3b7ba911c4fe47 -146, 0xe4bcf50c8ada7ab6 -147, 0x4470ffb01cd6980c -148, 0x377cfdbe8e810731 -149, 0xdb33ff37954849c7 -150, 0xb622ead14010ad64 -151, 0x6c44d65c7a81a5cb -152, 0xd99a3fca5a5d9fce -153, 0x24e7360e1ee2efd4 -154, 0xbd927a3fb576d81 -155, 0x1ea3f2b7c909ffb7 -156, 0x48aedb2bec244a7e -157, 0xc17d9539cf53a5f7 -158, 0xe4ea45fcf4de590b -159, 0xe1d863ebb77cb7de -160, 0x8ecf0bc8d88fefe4 -161, 0xa881cef3b3209e05 -162, 0x8f34a14a6978afb6 -163, 0xed4e2e5e1f4966fe -164, 0xede897e11cbe230d -165, 0xd344af5e50042d6 -166, 0xb2739594ba906c81 -167, 0x83c0bbde6d95b632 -168, 0x6b7ae9d1c4af98b2 -169, 0xc4b8f6816eae17f -170, 0xf8e3a6bf7855bd3b -171, 0x9f64ff72d6357488 -172, 0x50b6a304f9543f58 -173, 0x330e8281e591cc6e -174, 0x15dfdd5af7b421e3 -175, 0x8d3224e62524222c -176, 0x90d89d139a75b44f -177, 0xf6efb68e15639dce -178, 0x98cf64777861f844 -179, 0xa031e78e4b3a7b3a -180, 0xa3647dbd85c538eb -181, 0x73656c8c77d9c56 -182, 0x88840b683d4fdb72 -183, 0x3b84749774eac55 -184, 0xb9b753a86ec15b39 -185, 0x31ab026ace06b686 -186, 0x4fd37ef5b5b1d284 -187, 0x7cc6c46fb114a76 -188, 0x463ff22f392dbd4c -189, 0x188c3718f2068889 -190, 0x769892f97d895302 -191, 0x9838246e76757b6f -192, 0x546a68f394c391ee -193, 0xc9e32a7d2a7fb559 -194, 0xd84ac91984217239 -195, 0x82ef273042519aaf -196, 0x79650a2c9bf2a812 -197, 0xb7aa6dc1c23eaecb -198, 0x60326b9e25b055d -199, 0x6b17c296feac0e6a -200, 0x7813f405baa0d85 -201, 0xb9d52400dcb399d2 -202, 0xfb588178727e0012 -203, 0x448763bafa3d9095 -204, 0xd63fd1757e94e19f -205, 0x2bc98e05f296e73 -206, 0x9e05ff0a641889cb -207, 0x1e1716c76c9a8990 -208, 0x9e2f67e555f5389 -209, 0x430a8a612033934b -210, 0xd49a74a4d8743bf -211, 0x7b08085a0b4aee34 -212, 0x2c0482984960e7c1 -213, 0xae26bcde5d8fe8fa -214, 0x8f40022b951f98c9 -215, 0xcc59b599dd0383a6 -216, 0xb6833d7a5e00c373 -217, 0x3e025759aba46bdb -218, 0x2558a3dd775dee09 -219, 0xdcd8370368d091a8 -220, 0x9e55348e5734fa9f -221, 0x1061a08056830eea -222, 0xdca96b36adc5ed23 -223, 0x8563d7d016fe5d7b -224, 0xa3fb6b79b0095ee3 -225, 0xb887cd180ae6f882 -226, 0x670e10186fda74a9 -227, 0xa25f08a01b69032e -228, 0x5d90bfde7e21c0c8 -229, 0xb1b154f328250786 -230, 0xe0050135775487f3 -231, 0xbd7001fa00656593 -232, 0xcb6136e259180b69 -233, 0xf7480387c0872215 -234, 0x2e478a3efc5a7ec4 -235, 0xeb1cad9cb7d82f45 -236, 0x5d4c127c6c060ca3 -237, 0x1f9efe7a0bc11db5 -238, 0x59b9712ac8f24207 -239, 0xb94edcfe7b8e7ded -240, 0x474b672b27aef61b -241, 0xc2150760d3da0859 -242, 0x1146d26c90b6becb -243, 0x52926b0e9e820413 -244, 0x24f2b065f78bdaa5 -245, 0xf94b5372ca68e5e -246, 0xfdf3e645313db1fa -247, 0x181af7ab689d2ec7 -248, 0x1e275b8f25520a3 -249, 0x1f287f3ff3d55dc8 -250, 0xa035801d4747cae9 -251, 0xba6ed878f55ebd -252, 0x74d6598302a5c786 -253, 0xe92ce6198f39ded4 -254, 0x7b811ab7cda273c9 -255, 0x9d17fb60483addd4 -256, 0xf2b457f77ba326f -257, 0x32e5956d2a580c90 -258, 0xcba559493cdd2b6 -259, 0x59276c178ca0e7a6 -260, 0x509681deb2f0160b -261, 0x1bc2df48eb8f2a3a -262, 0xbe7f17f92c808cd8 -263, 0xebbcd3a312ab80b7 -264, 0xef85e7595c591a83 -265, 0x914028c61432c620 -266, 0x7d8f67244eb3ea9e -267, 0xa0512684d8ca4355 -268, 0x5a12209ada976a9c -269, 0xfa0cf430c33df55c -270, 0xd514dc8064688736 -271, 0xc5020a78e10201f7 -272, 0x9df7e30707f4591b -273, 0xbc41eeb3c45f4ba2 -274, 0x2b5605d64a470e5d -275, 0x77753b9a125af99a -276, 0x7ba925c3af8e2a4 -277, 0x46c1dadcd05c1165 -278, 0xcb64cd52411f993 -279, 0xa6c3c1f065f7c758 -280, 0xad68088813a0068a -281, 0x6dd039e4b9d4631a -282, 0x528f220f2f54270e -283, 0xfe565ea36805959e -284, 0x3f2edbdc64385933 -285, 0xf0ea2fe07768bf3a -286, 0xd120fe046bfafc74 -287, 0x85c1b029a6d56aa1 -288, 0xb03c986da026593d -289, 0xd126fed2a4ca68a7 -290, 0x7e63d8216bc42201 -291, 0xadbfd88dcf50e179 -292, 0x6c1c1308ee42ca66 -293, 0xf5415a024cbf5458 -294, 0x4e50d4d388352815 -295, 0x38949c203a1a34ab -296, 0x3a35d5ff38274f23 -297, 0xc96c009af2982c00 -298, 0x581691437bf0b1e7 -299, 0x793d1a61f0b0dcf8 -300, 0xa36a3b1c3e39c61e -301, 0xff2938c1b78db0fc -302, 0x1e82a7fc6b7c4725 -303, 0xd91883febcf4672e -304, 0x22c55d5c95f1d985 -305, 0x3fc97236c50bfce1 -306, 0x28a3e0c7a4380bcb -307, 0x2c072113ce5f2570 -308, 0x9c816b6af1d912a3 -309, 0x83698f6af8e41daa -310, 0xa7b1b189d398eae5 -311, 0xb5b44ce05dd0867e -312, 0x5ceaebf68b501f84 -313, 0xdf384c2545db9168 -314, 0xa75eae42ad85396f -315, 0x88273ff551afa924 -316, 0xda2c47046eabd9f0 -317, 0x18d83b83988fa9bb -318, 0xeed5ad076674a6ac -319, 0x28d969bd36a0d5e8 -320, 0x9259eebb564cfd98 -321, 0xdc2e175377ffcd6a -322, 0xcdb19c84396bc51d -323, 0xeaa3a7674b5e5da8 -324, 0x9bd54f94110b36a -325, 0x88d96179c0a35528 -326, 0xea1536654ceee668 -327, 0xdd1cc9d40ad3ea60 -328, 0xe9106bddc3221293 -329, 0xe096d5b5acd9ff46 -330, 0x4cb27170156f9265 -331, 0xd0d3e5b9edadb2bb -332, 0xf75347484f2af9b4 -333, 0x6170333a4e6885d5 -334, 0x99a50b6b702b80ba -335, 0x10629a67c9781899 -336, 0x374a33743030da9d -337, 0x289fdbd0bc89f257 -338, 0xa67c56d1bc5dc5dc -339, 0x38e90cd1dd6d64f2 -340, 0xcc5ed5dc4955655e -341, 0x723d33bae999723d -342, 0x46af17f0c981605a -343, 0xd1d3a915f899b0ff -344, 0x9a60c9bee03dcb43 -345, 0x11753a29a1d9201 -346, 0x491c99adde4e0a73 -347, 0x634437d6dc4388ea -348, 0x5f4cf58d810069e0 -349, 0x8d950ed29ac1703d -350, 0xa6330099182b17e3 -351, 0xfc9bf9a5cd4ea35d -352, 0x4560dc5769ff741b -353, 0x374a9ff29ee966ba -354, 0x16a9bd5c9214e40d -355, 0x46fdfb2899af3e80 -356, 0xe2eff8b6ad57da07 -357, 0xa67c709690485024 -358, 0x87551c8907b62ead -359, 0xde03a75e08382365 -360, 0x6744ad2be09ed2c1 -361, 0xb34ec9f71efb1f48 -362, 0x4fb71847ea9a525a -363, 0x10ffcd51ebb2f5b9 -364, 0x489431753bfacc7b -365, 0x7a9cc00b29aa7802 -366, 0x8017011d2285ce9d -367, 0xd54d90e061d61b87 -368, 0xa41a40e4a81526a -369, 0x47b5ba075adc3b4c -370, 0xb8cbbc5498cc428b -371, 0x6165fcf1ef4795b -372, 0x57926a7aebb26866 -373, 0x226ec9794dd0714f -374, 0x2759cca87ce9a2ed -375, 0xb41a74ac376c84d3 -376, 0x3e8101b52e2518a6 -377, 0xc8f18bb165e3db1d -378, 0x187f3ef2ff1093d2 -379, 0xb5c1069cdbe57e46 -380, 0xd3f342f3104a5902 -381, 0xf32e59c6c7b8458 -382, 0xfdb39f79b5b1f574 -383, 0x526dce2fc3115682 -384, 0x1a2e8128c0180ae -385, 0x5eead6a0e587e4c6 -386, 0x450e7d15d282c580 -387, 0x931a6cd04be42fe5 -388, 0xb4d321f03fb71277 -389, 0x32479d856fd9bdfa -390, 0xa28dc713e419022a -391, 0x6c8dcea6b5adbb14 -392, 0x4ae7b8d58ef7aa3d -393, 0x49903e3fbd56493e -394, 0x5238b0c9ee856f3b -395, 0x77deab4c733cb2 -396, 0xea5d74aec663c8dc -397, 0x899afbc707b0899 -398, 0x56a9418f18219182 -399, 0xb42801a6445d852a -400, 0xd8462e581c7cd53b -401, 0x802701332acff0c8 -402, 0x309618a5c049ddaf -403, 0x66f6d281cd986fa -404, 0x53f089859dd3e861 -405, 0x497078aabbed67cd -406, 0x9cdc9d89a2e1cc9 -407, 0x871b1721c6f463c4 -408, 0xe9f8872d8f113d84 -409, 0x48e03acc1ff301b -410, 0x79d5f73993eb02ef -411, 0x5ac76f9f2329e39b -412, 0x878c2c8d84a9643a -413, 0xd1d0786d40a7391d -414, 0xf024ad81eea63787 -415, 0x9f96b1146e5354b3 -416, 0xa85fd9a5bc0fc195 -417, 0xafd0522c28edfd2f -418, 0x6c1aa508159a1fcd -419, 0x873f632373719c87 -420, 0x5db129eaa27ff3d1 -421, 0xd81037e5b49f399d -422, 0xa40a347abfc43a81 -423, 0x314452aabf5a95b1 -424, 0x6f8642230a3edee8 -425, 0x2aaa01f7cc73fb09 -426, 0xa0ebf15ee345343 -427, 0x19fddca117f16f35 -428, 0x111be87b23ca2143 -429, 0x46de5fd13663c896 -430, 0x2dacbe0fca5e4efe -431, 0xd534f9dce19043c7 -432, 0x7a548f9a35a6759b -433, 0x3c6f046dd15b6fe3 -434, 0x1f7a17cbfc090519 -435, 0xd8a282357a83d2ce -436, 0x96a8a5cfb5be2843 -437, 0xce416b54c95c6006 -438, 0xcda9d6127cb716cb -439, 0xb062a607b35aef78 -440, 0x141e913718707191 -441, 0xef829605cf4aa346 -442, 0xb9555c4c76d6a7c4 -443, 0xd41bd4a1593170ca -444, 0x2e00143ad3d88b4d -445, 0x1afa722d16ac1d47 -446, 0xa22530a5d53159c8 -447, 0x17f76921e5633a50 -448, 0x8e3ed4b11072799f -449, 0xedb6ace0cb513a05 -450, 0x8dbf3d235449385e -451, 0xd01fb688b01b798f -452, 0x8e3aa7aa93ab0436 -453, 0x8b18ef4c8cc20636 -454, 0xf40181de15f5029a -455, 0xfcf54366f31c924b -456, 0x7b16e64f5c3a1d71 -457, 0x6b5f96df49784c48 -458, 0xcb5914727615bb07 -459, 0xf228f7b32ec2d237 -460, 0x37c51a8a1b854a84 -461, 0x63484491b02c7fac -462, 0x526a9f0a571e170a -463, 0xeb8d59e7fbbe583a -464, 0x4fd1fa3bd32b8c84 -465, 0x825ba1ed08b31e1f -466, 0x644d2cadd8ddeeb2 -467, 0x3874924732d3c6d7 -468, 0xd2679fee287a403a -469, 0x17ddb27712b6cdb9 -470, 0xcce6bed3fa81f460 -471, 0x8a2df0f2ccb3f028 -472, 0x85d166e4456aae72 -473, 0x5dc4ce3fab56777 -474, 0x555b2c69b6eabb7 -475, 0x873bc152fdb3717d -476, 0x5670068eb7d52805 -477, 0x7f776ca61f79e219 -478, 0xa8b51d2bd8c8c939 -479, 0x50345828de969faa -480, 0xbefa083bfbd71b60 -481, 0x883809b883dffdca -482, 0x49ccf930ea76fce8 -483, 0x97cc45c4c2dcf12b -484, 0x4d3aef2e2a4a450b -485, 0xc7ed768e40efd44d -486, 0x5530c69ecdc47b2c -487, 0x2fbb8ad65b3e777a -488, 0x45234e14d9fd969d -489, 0xb6a758912ec87c9d -490, 0xb35f335efeac2d3b -491, 0x21efc82b1e65a1cf -492, 0x897db9fe20a2702f -493, 0x444042b714793c27 -494, 0x37356cc844e57cb7 -495, 0x602ecce617309266 -496, 0x4ea323a5d93363b7 -497, 0x2c2f0344303d7067 -498, 0x983de14baf7a9234 -499, 0xc4edde0900601361 -500, 0x12574e754cf862a8 -501, 0x82eb774465a3a83b -502, 0x115fd6ada32ab10 -503, 0xce23f43213ea118a -504, 0x912e289389130f18 -505, 0x977464bbb2fc0cd9 -506, 0xeb944201e2747c79 -507, 0xa41dae77205e05ee -508, 0x66c91981aba16d08 -509, 0xbd4aefbeb385af57 -510, 0xd7c7d36c0ec75862 -511, 0x492e43720ebee40c -512, 0xf44861d4636833df -513, 0xb9fb92c7203e2a1a -514, 0xd75f7f48e860938b -515, 0x8235d433d3e773f8 -516, 0x36cc65bb70a32774 -517, 0x3898d9516512bffa -518, 0x4f5c36707161dc35 -519, 0xa35e3d81512f0a8e -520, 0x4ae50933ef7bd3b9 -521, 0x641dc03f71dc81f3 -522, 0xc6002d833e1d768e -523, 0x6c7d94f79b7a1956 -524, 0x4027405ac3c6e666 -525, 0xab69f022928e86d8 -526, 0x90272e57839563ab -527, 0x56e78769f743d98 -528, 0xb5c7931145b93a39 -529, 0x253fbe3201939650 -530, 0x5325825cbe56c3a9 -531, 0x159aa2be6163c7bf -532, 0x56b8d5a5ed375c9 -533, 0xbd4b45a7cce10f56 -534, 0x2f799de5fd80339e -535, 0x40232bd30ebb82d2 -536, 0xc10e2198616b20a6 -537, 0x6a13ecc0b52813f -538, 0xfafd5d5b466ee59e -539, 0x810cbf398208d400 -540, 0x7137dc6f08e5b6d3 -541, 0xfe59d9caf7564d0c -542, 0x3117cae7c6ee6927 -543, 0x89e83cf15785a430 -544, 0x386b6daed57236e1 -545, 0xc2e6fb38df98a4dc -546, 0x496513da22e1e53e -547, 0x57efdf29edd94aab -548, 0x3433ac46ce163ef3 -549, 0x296565c39cba14f3 -550, 0x1ce89ad8ff370a6f -551, 0xcb12c5a7db52fd27 -552, 0x8125373ad475530a -553, 0x75ed8dda02fd5bbc -554, 0xaf2c279596340f93 -555, 0x18c7f80478479a56 -556, 0x14edf2ed871d9c41 -557, 0xf35731f0b8d26e4a -558, 0x2cace2d1996272bd -559, 0x84c3b017f5b12bb8 -560, 0x441c286a303c81c8 -561, 0x92a7c594c92b2353 -562, 0xb175a7a7e0cab31f -563, 0x501d7003cb9e530d -564, 0x1e9d3dea32bb5d6 -565, 0x60756fd6e4b239d2 -566, 0xf979b4c7ddf4bb22 -567, 0x1e5c0ba3d2797a7a -568, 0x94590d4209c70c70 -569, 0xc5dbc6ef6fd8c203 -570, 0x46a0eb4fc61727f2 -571, 0xe3ddaa7f4033fcb0 -572, 0x4fc177555a6b2f9b -573, 0xce0f6ab675596a18 -574, 0xe11a08478844ecec -575, 0x47054780433de44 -576, 0x89a3be9609dc2a34 -577, 0x9ea612c49a4c170f -578, 0x8212e9db2df9ca7d -579, 0xdf1cedac92affa7c -580, 0xc21b0ff068580e5a -581, 0x49168be340b1ade -582, 0xce3a5fd54225a6a9 -583, 0x80ecff24ec6cdb9f -584, 0xd14429e950a1a21e -585, 0xc66a1ad3cad8f9a6 -586, 0xcc76bdca3ded453c -587, 0x748165a5cb8b6bd -588, 0xcc77eb3966db7c5d -589, 0xbaceadcc1db342d6 -590, 0x33b42e3dc005fc38 -591, 0x43b5661eead65675 -592, 0x356821fd43c46e5 -593, 0x4efdd2444e0c5ffa -594, 0xf84ce60e2c0de959 -595, 0x14a4b1dd26583f04 -596, 0x6ffb885f5fe18b87 -597, 0x8233b6a95b1af132 -598, 0x7e2e9c449dd06b71 -599, 0x736bc96174cd4d97 -600, 0x86591ab3ab385777 -601, 0xb7696e3909a91039 -602, 0xda363e1a90c99d9c -603, 0x793cd7e1855b9a43 -604, 0xa9dbce0ccacd24c2 -605, 0x5d9a1d9b06fcf2f2 -606, 0xa7db7fd7c2b50d55 -607, 0x13c85aaefd37bf77 -608, 0xcba5689a383aa436 -609, 0x7dcbc3e297d2bd31 -610, 0x9860da13006164e8 -611, 0xda3be955750ba8a6 -612, 0x57f6a78ac6d2cb3 -613, 0x861ed21955702cef -614, 0x3cfdfb6fa0763186 -615, 0xd075f803b072f140 -616, 0x6b1622638e94a714 -617, 0x6f4b177c0213a295 -618, 0x26c113226bbfa72 -619, 0xbcb962e03d008ba7 -620, 0x1e50555d6e75d9b9 -621, 0xd67082f15ff0086 -622, 0x20766d0fc6bd729b -623, 0xeea24b2ecc4db639 -624, 0x3136637be559ec83 -625, 0xd3f2c641faccfcf8 -626, 0xe43f5bfe95bfb2c2 -627, 0xbc801108984335e3 -628, 0x19ff6b0c435e06a1 -629, 0x7b8f28c44eb5195d -630, 0x375460c52c467757 -631, 0x534f4697a2a2f0d3 -632, 0xbd1aed6c1a94e586 -633, 0x9dec33a59dd000e1 -634, 0x4611fc38e6902126 -635, 0x1296da2fca821b09 -636, 0xce4684ac8861a6b7 -637, 0x16bdaa7a0563d3c8 -638, 0x22a6a8b6de1fcd10 -639, 0xeed5c457b2d2a399 -640, 0xb66c697c0e328f69 -641, 0xe678d6d573b2dc21 -642, 0xd0a78328399774d2 -643, 0x7fee339fadd44eaa -644, 0x32c2da48753c8818 -645, 0x691f87af10bc6f5c -646, 0xe382722ac6ebdbb3 -647, 0x28bb87557931a39f -648, 0xc3aba948d7d22fa6 -649, 0x3ce7016f24e2f50b -650, 0x863b408ab8161d28 -651, 0x1e3d2d6746c16b31 -652, 0xe5a21dc5843a37d6 -653, 0x8ecb559ea375c81d -654, 0xff2681b83a599f98 -655, 0xcd9893140d02b725 -656, 0x80294d390a4e1a08 -657, 0x254166d362613f84 -658, 0xd2c336ba5b4ae618 -659, 0xef79a05286b75aaf -660, 0x704140e00e02ea9f -661, 0xa2623b124bb92365 -662, 0x2225846e393c249b -663, 0x95676d7c7aae81a3 -664, 0xe0cbe12ba194b3d9 -665, 0xda8ca3d800ea6152 -666, 0x8b2c2f63db05c887 -667, 0xf14012751ef435e9 -668, 0x33820fbd9a06d78 -669, 0xf37375a008192ae8 -670, 0xaa2c34f4b405589e -671, 0xd26bbda155ac158b -672, 0x418b108b101ea70d -673, 0xb9648a82ca0617d7 -674, 0xae6e2213c8c0d3e3 -675, 0xda7335c158d64615 -676, 0x78f175a4a89cdf5b -677, 0xac7a07b66a84f751 -678, 0x266019228d3bdb87 -679, 0x3a7798913c66d5a -680, 0x2aa9c173879dc048 -681, 0x67453dc96c3642da -682, 0xbe9ea095f8333cda -683, 0x10998be0d5702361 -684, 0x77a4e1af57a6b02e -685, 0x66356334d32ab0fe -686, 0x2df9585cb5ea1b34 -687, 0x51159b44acaa000f -688, 0xbc433d2fbb8a4953 -689, 0x5a533a3838335feb -690, 0xd57ffb6f839fc89d -691, 0xe7cd85b8d026e706 -692, 0xdd4acea5a81530e7 -693, 0xd7af04b51606fa0f -694, 0xe31e683c116deb37 -695, 0x4e2adf78e2a88fd1 -696, 0xc58b907a61dee8f -697, 0x673e1a4b00b0a2de -698, 0x36b639fa8091f63 -699, 0x7782c303339e2f0a -700, 0xfd84e0fb7774b0be -701, 0x2a6ac41e094d6e25 -702, 0xcf221a0187c8ca32 -703, 0x4e457ef8a6a528dd -704, 0x9a7714c8913ac3a2 -705, 0x5a6513aaec56ddf0 -706, 0x254fc4d74dc56a5 -707, 0x93e1bd37d16ee5f2 -708, 0xd1a16a2aa652c2ce -709, 0xa66ab34e5262848 -710, 0x5e6f429f482e4a2d -711, 0x198eeff9e36608ec -712, 0x3bea433a42228c7b -713, 0x1a85a30f51e1ad8 -714, 0xe80b6a4fdb0d0482 -715, 0xc3e8d0c13f8879e -716, 0xbaa3c52bb9413a89 -717, 0xc2d4614798d79e2e -718, 0xbbd3f6abc551b6a3 -719, 0x282e112e6bdf2de8 -720, 0x615cc8613f4d4518 -721, 0x53b2627138d76555 -722, 0x1b19126726fd77a1 -723, 0x915c0a108cd2d357 -724, 0x1061822da93d9907 -725, 0xe79aee77f55dc17a -726, 0x7b367a3165fbeba7 -727, 0x1894d6a0059bc074 -728, 0x876235ba0475437c -729, 0x2b8f64a5357907dd -730, 0xadabbbf775f4c3a2 -731, 0xf70d7e73e0914757 -732, 0x50c1494071662c91 -733, 0xae3cc90ade2512c8 -734, 0xd73f9d2b66333aa8 -735, 0x46342e130d23dc94 -736, 0x6c8307abda3d568a -737, 0x235d9a334f4eae0c -738, 0x33d0ccce19e66c93 -739, 0xd83559cfbc7acb8 -740, 0x430f65543bfcfad6 -741, 0x5dbe2eb34c5b25cd -742, 0xdcad606d1b515392 -743, 0x6376bc62812519c9 -744, 0xf292cdcbab076b52 -745, 0x5b6669c53c3e9b1 -746, 0xbd5a95d4d51f18ec -747, 0xf71d40c0b07b0a16 -748, 0xa51966e8052a050d -749, 0x7fd18ced5be2d350 -750, 0x82727df4050382b7 -751, 0x7c10a4e48f664caa -752, 0x3712f2d7d2e6bdba -753, 0x2535b833ad6b4ef6 -754, 0x420577375164ff95 -755, 0x68c40b08f579888f -756, 0x8922d2a586203dcd -757, 0xf317b95e3aff246a -758, 0xbbd1c166e380207d -759, 0x9303601189dfdda1 -760, 0xef342abd93377a47 -761, 0x499773d085e7de1a -762, 0xd204bb687ac202ea -763, 0x19ffb5b90619622a -764, 0xc59bff0531dfbe98 -765, 0x8c6d480a717445db -766, 0x8c3c030ca187e2f4 -767, 0x53f0740df18d7b6a -768, 0x1a5eed54662e3c6e -769, 0xbb29a94e32f03c3c -770, 0xdb0df407c4bbc009 -771, 0x6c0a9f4598ac0ba8 -772, 0x2e0ac7251648f892 -773, 0xb4555f7c1e3fe8ac -774, 0x2cd8ce106d8e441d -775, 0x608e38e439a239d5 -776, 0x1bb66d4c2a2ca5a8 -777, 0xc32ec47253591fa6 -778, 0xd3974f6f2b8b038a -779, 0xdcbfd9eb4a9b1626 -780, 0x8589b3e6fc1ba06b -781, 0x81f34f1da9f27f9a -782, 0xd3bdd7496dcc21bd -783, 0x7c963559e1c47305 -784, 0x5817e571d2fcc113 -785, 0x4f35fea60a0582c8 -786, 0xb851f167a0bda1c2 -787, 0xf57e13249380eddb -788, 0x570e69bf38151a56 -789, 0x117feac919f19d69 -790, 0x49ce46af93025c96 -791, 0x4220f6c18e8e1f9a -792, 0xf082699d8fd5070b -793, 0xccd31756abff1928 -794, 0xbf9d4ab46de14d1 -795, 0xf2e0be2c2bbbc823 -796, 0x6e9b495ef22563ed -797, 0x9a609cdcff6e3152 -798, 0xbbd2e5dafc83fcd4 -799, 0xac153055d6c5770c -800, 0x312bbcdd6b681016 -801, 0x3ed60c24fd5a2f3a -802, 0xc7f3b2948dcdf5c9 -803, 0x8cc631df1fac1c1d -804, 0x77f4aab62a657d61 -805, 0x2f43e30323829573 -806, 0x5b7d20ab0ef901b6 -807, 0x7fa99ec817785705 -808, 0x5c95cf94241f1e3c -809, 0xafa2d371f8f579e1 -810, 0xe4c314c4017e2e77 -811, 0xf672b575a585c0b3 -812, 0x6600a50a45d6ecdb -813, 0xe06c0d7edb63485b -814, 0xf1b45b82f4d0e8f1 -815, 0x41581d87cc1b759b -816, 0x8807b689eddf602e -817, 0x9e11d2949076d4c0 -818, 0x9f3b430319e48bb1 -819, 0xb27fa37d89396b64 -820, 0xd930a0cc6723c8b0 -821, 0x935fe6e9c7a57eaf -822, 0x184f5dba2f19591a -823, 0x513f86165d0adb73 -824, 0x4f2cd09cb85aef51 -825, 0xda66728c1901a11c -826, 0x2445b8938b33db42 -827, 0x98fd86e4b89be5e8 -828, 0x2f752d8769747705 -829, 0x2cb9b42b98ce0c0a -830, 0xf3314e0e0c57d31b -831, 0xf9c382d55868b2df -832, 0x83264a41539ec2c6 -833, 0xa2b3674f0adc1d0f -834, 0x2dd7ad1d92001e7e -835, 0xee210f6047a94713 -836, 0x71a18140729bbcfa -837, 0x415058c01e01384b -838, 0x6cc2e2079c9de72a -839, 0x8561a9093d2b5d72 -840, 0xd6c276d566895b2 -841, 0x57cb2804836f4867 -842, 0x78becdfda7fd91d6 -843, 0x4046a94c8377a3 -844, 0xadaaaa0d558d261a -845, 0x56ef182050db8865 -846, 0xbc28289519f6ebe5 -847, 0xbe7b95e4334540fe -848, 0x384b9838c105f8c8 -849, 0xecfb823fc8815c7e -850, 0xafdbbb2bfa8bdff8 -851, 0xed33653dbeb638b8 -852, 0xf4164289a7a6dc1 -853, 0x6e5cc51c2a3a8b20 -854, 0xdd59a99d16116f34 -855, 0xd48f95ba89787b5 -856, 0xacf9753586b8be7d -857, 0xc0430da7c73bf373 -858, 0x25320aec467ee989 -859, 0x5108e8f4be4f8d8 -860, 0x69b1c7d23ff502c1 -861, 0x7c08bd62caea3313 -862, 0x4285d5b8ce1d19fc -863, 0xbe03dc19cc3be0ad -864, 0x182cdb615e4d4147 -865, 0xf75270e6096d5d1a -866, 0x467b7ac524d17060 -867, 0xb0960b398a111ec3 -868, 0x126c099178f50090 -869, 0x19980d353ddb289d -870, 0xd4b394e2c0305403 -871, 0x5972d7c748938602 -872, 0x276461c9da39bec4 -873, 0x6b3a2046d6ebdce3 -874, 0x4c55d74597c27388 -875, 0x363bf469f4f673be -876, 0x9b26d4e69d36f584 -877, 0x21d441f573e56b6f -878, 0xc29509f2a1e9c4c8 -879, 0x5178088ff6e62d5e -880, 0x902f8ecd57128a7 -881, 0x479fddd275330bae -882, 0xf56ac8b6f6364526 -883, 0x4904060a896d759f -884, 0x1c0f1f4e800bbfe6 -885, 0x9b03bcb77880240d -886, 0x2f35904d9867379d -887, 0xf88a05a4dd6928e7 -888, 0xb5341282b6781021 -889, 0x225910a217522b71 -890, 0xa76bac3bf3675285 -891, 0xf19973940d9a57d -892, 0x9f6ef608ed4291d6 -893, 0xec63cdbf5911fb10 -894, 0x8a359dd4ec3b41ec -895, 0x8373d0d4e6af7261 -896, 0xfc6a14169335e7d5 -897, 0xf06ff499b6856cda -898, 0x71f5ce76943ec9e8 -899, 0x9417034d7879b92b -900, 0xfa0e3c78f47c0276 -901, 0xea9ebf817a3e3b93 -902, 0x7c08ff3d42e19a10 -903, 0x8697e5798f9bab52 -904, 0x10eb4dab88e4ce59 -905, 0xbd11bc073298b46c -906, 0xf46483b5fea2427b -907, 0xafed38960dd33a59 -908, 0xf7a00b0413eb47f6 -909, 0x4233464f10e7666c -910, 0x7ce6db32b60aba3a -911, 0xf9ae9414469308da -912, 0xf5c4e8e04c008924 -913, 0xb89c735c89bdafde -914, 0x8b815ec319546463 -915, 0xdd57dedbf1fa66e -916, 0xdc0bba0705548598 -917, 0x1ed685fb6c966b2f -918, 0xd9afc3ac4319d72a -919, 0xed7c7e9407e71351 -920, 0x585b44a509258719 -921, 0xdf9eac3020de19aa -922, 0x102102d94b983d57 -923, 0x85dbeaa806a02e79 -924, 0x4bacf4194786b961 -925, 0x32bf2fed8ab9b611 -926, 0xce94384eb215dd1f -927, 0xfd1da2a7795c4801 -928, 0x149b31c0a14f7d02 -929, 0x4e01962d69248840 -930, 0x41d509a1c742473c -931, 0x46105403c2b4e56d -932, 0xe6fca820341c56e4 -933, 0xf1982bf03572ac79 -934, 0x9f99e2fb3cc2715e -935, 0x6e3bd2ca3d50faf2 -936, 0xd0aea8d0fee1014 -937, 0xda0ededd067cc72b -938, 0x56c42899c5af28b7 -939, 0x8c4883568ff28ba2 -940, 0xad9019516b75c1d3 -941, 0x3aa1b33682aaf348 -942, 0x31187b962cf65f58 -943, 0x7f2cc27ce4c8459a -944, 0xb75ee9bbf97014c3 -945, 0x8eb8f42b9a9c3024 -946, 0x5b7dcf683a3c14c5 -947, 0xa258b18ccb7cb3c4 -948, 0x7587bc7015c145f5 -949, 0x7536427aff38edd3 -950, 0x437b33489ef425b7 -951, 0x22febd7e96538bfd -952, 0x9fefcc49d567b35e -953, 0xfd756268183d7d6d -954, 0x480df3a7112b2eea -955, 0xfd02a24b1eed9e6a -956, 0xcb3b6c96d65ab879 -957, 0x19f8b328f365f6c8 -958, 0x7d5d20e6328ef6cd -959, 0x8d74057415768152 -960, 0xcba11867467079a2 -961, 0xf86138cf35f091fb -962, 0xdb3204b36a02eb61 -963, 0x8974a7786d5f6894 -964, 0xc8445cca1175a023 -965, 0x1523bfeb2f088c15 -966, 0x4e39bb650d7c4de0 -967, 0x91c9e9ff5b823702 -968, 0x7c3a6850a7c143e7 -969, 0x131999c480253f47 -970, 0x3ac336af37f6a4e7 -971, 0xb057ae911b406d5a -972, 0xde0b70c5f9d5be60 -973, 0x93fd54e75618a86a -974, 0x3955e207acb1f65c -975, 0xa33450c2890b0b61 -976, 0xc6294720e971cd52 -977, 0x89cb13a5b1364169 -978, 0xa6fbc61118b44104 -979, 0xba0651279f93958b -980, 0x6995c30cf06ed3dd -981, 0xd75cd3472c5f86a9 -982, 0xb18d90ce11dfe2ad -983, 0xd69200ae86d53222 -984, 0xe73fc25107e53e90 -985, 0xc1edc96f67bcb096 -986, 0x587cc0fc53992abe -987, 0x2139d74bc6f3edff -988, 0x1b4609bbfa08b543 -989, 0x564e5d7acb190539 -990, 0x1099ce214921efbf -991, 0x7764cd537ccb1b55 -992, 0x4232db7dbdad3998 -993, 0x54c970b3ca338f24 -994, 0xf28c8f460244de6a -995, 0xbd37dcd3829c5a4b -996, 0xefbfe21ef1ab13ae -997, 0x6df8dfc0a865d4a3 -998, 0x5e65a5bfa3f4d555 -999, 0xf6affb932cc9f3f2 diff --git a/_randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv b/_randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv deleted file mode 100644 index 6c513476bbef..000000000000 --- a/_randomgen/randomgen/tests/data/xoroshiro128-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0x509946a41cd733a3 -1, 0x885667b1934bfa -2, 0x1061f9ad258fd5d5 -3, 0x3f8be44897a4317c -4, 0x60da683bea50e6ab -5, 0xd6b52f5379de1de0 -6, 0x2608bc9fedc5b750 -7, 0xb9fac9c7ec9de02a -8, 0xc1942c64262d8742 -9, 0xc2c334fa4c2214b4 -10, 0xe53cfba26ba5ce93 -11, 0xf01f0c9d5398a979 -12, 0x1bfa2ef194eeb86d -13, 0xc9df57572868239 -14, 0x728e35871474105a -15, 0xdc7b1e93de9e112a -16, 0xc4d930cafb32002b -17, 0xf18b0bd68577e055 -18, 0x4929ceed7e690239 -19, 0x3b7a547b356b29d8 -20, 0x660f1cebb7affd72 -21, 0xf850e6052cc5f5c3 -22, 0x931512b017c71f1 -23, 0x8d88b7af3b8731e7 -24, 0x3050de537e8e84e0 -25, 0xc917230b8bd3d552 -26, 0xf58da0814356b478 -27, 0xcfc06b804972be32 -28, 0xe3892682eff28645 -29, 0x55bc734a03ca4fa6 -30, 0xe2f7700a020152b9 -31, 0xcba5a308a8d40969 -32, 0x928b63592b6b2f55 -33, 0xa372b4e0293d90c1 -34, 0xd73e00b1c0fdbb6 -35, 0x43c712d398019cad -36, 0x295d994760c6501b -37, 0xe94236abdd256f1d -38, 0xed4566687d847ec0 -39, 0xd3a838dfcbcb5df1 -40, 0xf4ac54b3d79aae61 -41, 0xcabd8f089de74dc8 -42, 0xd58e132a2cd64b6d -43, 0x4eb8bc55f8993dd2 -44, 0x8e4ee152013579ca -45, 0x1aa7c7e058e02a75 -46, 0x5038184ea8f1dfbe -47, 0xa9af7da9879e99ed -48, 0x267567fe1128a585 -49, 0x3a3d637084865189 -50, 0x35179207577f3a88 -51, 0xc323e40ec505a4a7 -52, 0xd2ff171e3203c51f -53, 0xf524706a4db15f35 -54, 0xbff297a90126dd1c -55, 0xec7517f97c47dbf7 -56, 0xf56604fd9a8a7f3e -57, 0x2a63c3bb1635de13 -58, 0x9c22f64a9b9acfc -59, 0x6fc94c63f4e1b311 -60, 0x955820d474d00924 -61, 0x5a4d25256934ab74 -62, 0x95ea0cf2b73da09e -63, 0x8e21647894c89a8d -64, 0xa6ffd9037f6627ae -65, 0xca5d03082b0007fd -66, 0x2ee116ac7bdd65ce -67, 0xa9e6e172042fa80e -68, 0x4763c82d6e7c3d8d -69, 0x325169a3ff49a8fe -70, 0xe0be054ea126080c -71, 0x4ccc1794542607ba -72, 0x58c480dddafc29d4 -73, 0xedab421340a8d4d -74, 0xd28d8f3c2ab241cc -75, 0xb2a89fabba9566c3 -76, 0x1b12fc8b30a80b49 -77, 0x65e178e0065959ef -78, 0x4adc931b03e25f55 -79, 0xefb7b250b854feff -80, 0xe024be0a14bf3da2 -81, 0x60c2285324a5a642 -82, 0x280dfcde16655ff -83, 0x18c2cbf4c0ba9bb0 -84, 0xcbeea642049c68c -85, 0xa1b19b0b60833fa9 -86, 0x10f72a22ef81e27f -87, 0x5cc3db165dde75b2 -88, 0x947a3c40223e6bd0 -89, 0x5d469f487abb870f -90, 0x1b1f4fea711c039d -91, 0x63b22d9e9616b06c -92, 0x689aa9d9808ffa7c -93, 0x2164f59dcc5f3e03 -94, 0xbdfc99e1f2c1193b -95, 0xdc9e85a6a6b8f61e -96, 0x11ad0ede8657e961 -97, 0x73a69427c838bafa -98, 0xfa4b98f49849cc62 -99, 0x5ccb852e4e18aad9 -100, 0xae102d1e06ad3569 -101, 0x4be41a104f8d8463 -102, 0x723f50acab4314fc -103, 0xd3b7b694a6bb6c38 -104, 0x8bfd1fbedfb8f092 -105, 0x3d5d9aea4d80f37f -106, 0x28cd19af64bfc553 -107, 0xceba7e81e5ec8edc -108, 0xd8c0513fca3ca719 -109, 0xfefef4fd2a0896f0 -110, 0x1aa7320084a97662 -111, 0xf63c0bb8fdae24ea -112, 0x497a5e9d0a13c0d5 -113, 0x37fabc943a07639 -114, 0xb5be9f1d19096cc1 -115, 0x4385acd2ed447c52 -116, 0x8e146c6874b731fd -117, 0x553c3c72c9e05a64 -118, 0xb9cca017a8d4be34 -119, 0x8f8e09bbd56564ef -120, 0xcf6da1a96df67f67 -121, 0x5882a27646d3189e -122, 0x1554cc47896d846f -123, 0x105600be06e72171 -124, 0x95a04162a7ec3791 -125, 0xadeb00515f0d6be0 -126, 0x22ed3d1ca5ebc008 -127, 0x312629837e981334 -128, 0xca916e4cef410dd2 -129, 0x18556a16bdff0e5 -130, 0xfab80417581d6927 -131, 0x40f7ecce118881b5 -132, 0x6a12fe0d0c5f3ca2 -133, 0xd3e2ba4104a669f5 -134, 0xdeb3d714e1fd921b -135, 0x32cc61dc107d240a -136, 0x1a79efae30dbd860 -137, 0xebd6029e65fcefa9 -138, 0x94289c890d17c9b4 -139, 0xd91bbe374cb9f243 -140, 0x3352bdd3eccaa300 -141, 0x5cc9a4bf3127b238 -142, 0xebd9f454d96adb59 -143, 0xd5f61261bb7089ff -144, 0xa743f21be20ce5f2 -145, 0x3d2a78d45bfb1da9 -146, 0x9ebbad453112c987 -147, 0xff48b7b97e3f597b -148, 0x2b57be29ae160a9f -149, 0x90df488fada68e76 -150, 0x785b4250ae46cc0 -151, 0x1c4fdcb6c66db255 -152, 0x3567f33a12172e96 -153, 0xc173a5f010dbe48c -154, 0x859eac8b59dd2bc0 -155, 0x532809d8c8b5378b -156, 0x656f93a00428ed0e -157, 0xd4ee7e2199473a09 -158, 0x9bc701f16ecf35a4 -159, 0xcea39cb296d32304 -160, 0x43fbb2333d392310 -161, 0xc9d66a1062247d -162, 0x271a83a113c42b2f -163, 0xee17f7585ab05734 -164, 0x5e98cde55d0b8ae9 -165, 0x488cc07f036165b3 -166, 0xd78481d7416f6724 -167, 0x681436c7434b6260 -168, 0xc53bd2c997a04ce5 -169, 0x61b5951080b80e26 -170, 0x48f285546280fec1 -171, 0x87ff976327bf74ce -172, 0xc10c08c9bc8b05ee -173, 0xa62f879a73bf12a2 -174, 0x31d7cbb6f9c1acf -175, 0x3e522645e518ee29 -176, 0xb85967a95e811cf8 -177, 0x99f8643751545edd -178, 0x3f962076f920dd9 -179, 0xc92abe52da7ed89c -180, 0xc1fe02e7dba484c9 -181, 0x7904149975239b19 -182, 0x5bfaad7ac409b74b -183, 0xb915e6eba7685946 -184, 0x8b2291b29fd71d66 -185, 0xe57e5709ad0bd967 -186, 0x3fe55bb3338f0f1d -187, 0xf41f8f7a981c05d6 -188, 0x80d3d9160712aa45 -189, 0x2da872bdd8bbffe7 -190, 0x6698441241fe0a4e -191, 0x4870fc969dc6676c -192, 0xd420fc68814fe867 -193, 0x6aa0500b9d8bacb5 -194, 0x55078d31633dcd47 -195, 0x6d758a56c80bd405 -196, 0x122149ae571cb397 -197, 0x22d1134c99ac507b -198, 0xe7d9e27ae05a47d1 -199, 0xd18a73dc45e5a290 -200, 0xb5bc1909e08803e2 -201, 0xe9a1e3ee93f2e109 -202, 0xf040a8f79841c101 -203, 0x9a705a608899152d -204, 0x4f7783a0dab4290f -205, 0x11c5bad24bb23af3 -206, 0x58545a19a22fb881 -207, 0xeeaf5ab573077828 -208, 0x9e036466fd858142 -209, 0xef70bf26fdd6bc94 -210, 0xcc3a2971056cb9f7 -211, 0xef120c86e84d643f -212, 0xa499226ab42f6d7a -213, 0xa85cae4acfa0a29d -214, 0xc8280371e2c25d89 -215, 0x246336f7e63ac4e6 -216, 0x76561f7777c7b915 -217, 0x704f83c71583f0b8 -218, 0x489db8592a76cd3b -219, 0x268d584af17550c3 -220, 0x350e989762428fe -221, 0x6857adc12d13f1bb -222, 0xde62c7d9517260e2 -223, 0xc1f37ee8baac988e -224, 0x714732f71cdd5374 -225, 0x56f01487bfa58c5 -226, 0x5163b23d41d95f14 -227, 0x745150434b747a38 -228, 0xdcf7cd6c6b14b1b -229, 0xd853cc6bc2580f81 -230, 0x693562e66b579775 -231, 0x8f15d6369dbe6678 -232, 0x464c1791098ad19d -233, 0xeeba6610f16ac2b9 -234, 0x3b307cc3c5bf5859 -235, 0x7e82177c4dcb75e0 -236, 0xae5978c33dd3e817 -237, 0xec3c0128360b0b2 -238, 0x2c325b630e904749 -239, 0x237ff1d19b4e7ead -240, 0x3c82e47b67a33956 -241, 0xf38b46203355a168 -242, 0x4df09cfda8d5774c -243, 0x4b06980b33ad6226 -244, 0x7afc1e940df03034 -245, 0xaa093355c596ecb7 -246, 0xbbb5100165d1445f -247, 0x599c0f30608a36d -248, 0xd35999534e29986d -249, 0xd0cae757abc97c36 -250, 0x9ec9f2c24bbe3b70 -251, 0x76b96e93352c2960 -252, 0x4dd3acf1c01ae06c -253, 0x71ebb829cb09312a -254, 0x3234f4c24cdbb897 -255, 0x9b0930936363bc6 -256, 0x2ede98b9aacc3672 -257, 0x7388672bfb4c92c8 -258, 0x53011e6a80763bca -259, 0x69eb6ca56f23129a -260, 0x59d98a723f847ad5 -261, 0x234af2de04ba218 -262, 0x589b028bf0830748 -263, 0x525da4a281c641e5 -264, 0x47ceb48568778c5f -265, 0xa2d73af3a884d972 -266, 0xdc6fab52b39bfe68 -267, 0x7f1a5e5ea6139484 -268, 0x70571bee802a1fa1 -269, 0x489f1d18d9c61c4a -270, 0xd781c38aa8aafbc -271, 0x5aa610ad2539aa57 -272, 0xd71a2a69974ae4a0 -273, 0xe4479465870487bb -274, 0xf714dacd7fc4475b -275, 0x5cb9c32e10d39249 -276, 0x746650ada73de1a3 -277, 0xbdd059359907cd53 -278, 0x38352adeaf41c72a -279, 0x330a370593019b35 -280, 0xc75ff9305bdaf3c3 -281, 0xc64723389b0bd56e -282, 0xbafccbf3fae88f31 -283, 0x3fc2c4b1d35da1fc -284, 0xd9414b4382f59e69 -285, 0xec31e6d32a58f7e1 -286, 0x4763fb9ad6cadb98 -287, 0x5e9817762a380e57 -288, 0x9a670c79b387ff5b -289, 0x467beb71ab258339 -290, 0x23cafda15a336768 -291, 0xe42ebf79e2d170e0 -292, 0xced716e4bbfe75ea -293, 0x1057597f33a23633 -294, 0x563d3fb59a847744 -295, 0x1a3f85cf84ea5e0a -296, 0x7630855876b41b32 -297, 0xb59e3eecb52851b2 -298, 0x26aed463d3769fd2 -299, 0x530d3898b8d043c6 -300, 0x28fa6b7cdc76ae94 -301, 0x99591569d7464343 -302, 0xa46da7d9e275579a -303, 0x30f6e5979a92bcfe -304, 0xaf345d66f7e756d6 -305, 0xdfad061213a92b33 -306, 0x2843134719ff646 -307, 0xbc8699b6d3f04313 -308, 0xacb08fbaeaedce6 -309, 0xe8fd50dc65724bc7 -310, 0x956d0436e93242fd -311, 0xa9c3e3eee8a80b9 -312, 0x9bf71b03710af171 -313, 0xbd61bd65edf3d9ad -314, 0x531b6865fc4f810d -315, 0x58ca69e7da1ea2f2 -316, 0x4946f99ec03e8adf -317, 0x3b9d4f48b1eb484b -318, 0x605be28093b8144a -319, 0xa7a4c6c8f2ade7af -320, 0x729f97c8057a21f6 -321, 0xc97d9d778a4e2932 -322, 0xc173b6c3d0c5168f -323, 0xd400c6f451c927fa -324, 0x611d96eb9e70ecdf -325, 0x3ad1a1709255cd86 -326, 0xf85d02d9fd5678eb -327, 0x495bd5eb58af79ab -328, 0x977bc4282d97381e -329, 0x9a5b1811cde9f133 -330, 0x49b2b9d26ba0977b -331, 0xf6c4e846b99bb87a -332, 0xc399d5f8661b0c8 -333, 0xaf9a91415ddeb79f -334, 0xb93df0259e6f3c5e -335, 0x80ad075b109611b5 -336, 0xf3004a806f25186b -337, 0x89a86842ef14b472 -338, 0xba53e5942ca79cdd -339, 0xc4cd49237032e3a0 -340, 0xb39700c89fc1109d -341, 0xc35fd5106aa40bf7 -342, 0xa0ff3091df2010c7 -343, 0xd4970cd890097774 -344, 0x39e7db9319a17976 -345, 0x56306e9316a184b7 -346, 0xe4d218267f28a145 -347, 0xbaa24a30caf53ebe -348, 0xf4811ee0d51ce11d -349, 0xccb9ece4a25b129d -350, 0x132b2d1c4f092d60 -351, 0x7d5e7a59f14dd113 -352, 0x8ed30762f02d3098 -353, 0x8a92bb806bf9a4c0 -354, 0xd1957618db32f95 -355, 0x3ae37701b1db294a -356, 0xc29e705f675713ad -357, 0x3d12dc6fc3dcc569 -358, 0x7bc096e1e2ca2e43 -359, 0xf58f4f816e71b16d -360, 0x23e6f93c7d0f1050 -361, 0xacaf403b80890da3 -362, 0x7a5e19bf92de04ec -363, 0x72b3638076a857e8 -364, 0xb87601882acb1f3d -365, 0xb51d157f2576ac70 -366, 0x7ef0c2f1ae02af0f -367, 0xd519f6224fb2866 -368, 0xe00a80d729843eab -369, 0x3c95b55c523d0871 -370, 0x81dcfef1772a151f -371, 0xa5b20337760a602d -372, 0xf36049e3e0f98eac -373, 0x21bc3e0f1083016a -374, 0xd8f295098597530f -375, 0x78a2582906003e78 -376, 0x1c5cf0f434493262 -377, 0x2228d56b7da9cc80 -378, 0xc3d7eaedd0f36349 -379, 0xc9ca575c3b6dfe54 -380, 0xb5f03d2d974c91b3 -381, 0xb2f7ce70c56a865c -382, 0x98f33d64e66602ec -383, 0x559904911cb8b69c -384, 0x19c426ae3d196913 -385, 0x818fcd24869feeec -386, 0xf4c52f4b00f4295e -387, 0xbdb808d5fe34cb3f -388, 0x5014922c0ca80ee9 -389, 0x9f7e4c8068fb96d2 -390, 0xec99128e620a2df8 -391, 0xfcbb4fc594857a59 -392, 0x6aebf62bc7c79e4f -393, 0xde8cba80e35ed831 -394, 0x55bb9ced0fcb6fd7 -395, 0xbe7534a18c050ef7 -396, 0xed2e6d1767c7ed5c -397, 0xc88e18ac1064dd88 -398, 0xf71fbae1105d8324 -399, 0xb4431f0a4b807ea4 -400, 0x78de56556e1272d7 -401, 0x34d3e7e84ceed376 -402, 0x72f0ca866b3b182b -403, 0x4747a9b5faaa6dfe -404, 0x5a0f85d879e90288 -405, 0xbecbea458ec061f1 -406, 0x5e0bcff71b1911e3 -407, 0xc2e32dc60548a6ca -408, 0xfa76a9a3d449b8c2 -409, 0x81303b7e225dea8b -410, 0x4aa42b413ca5c63c -411, 0x4d7372d31df5b70d -412, 0x2a408f03bb0499d1 -413, 0xd75529b610d56d9c -414, 0xa6e9d1356654ffbd -415, 0xe10bdb510c440754 -416, 0x8fce6a25abf05e69 -417, 0x21aaf272093d6081 -418, 0xcc18cf69f0f0b2bd -419, 0xbb4e0a1cda31a035 -420, 0x70128e6522fe238d -421, 0xaaeae87b79d223da -422, 0x6882e6705d12bc8f -423, 0x8e110abf1ccb274e -424, 0xb7ebac3cfca55a39 -425, 0x909705e2a6e584ce -426, 0x3b54f18e8f7708cf -427, 0xcac28674d5caa98e -428, 0xdde0e042ad4107a5 -429, 0xfc2ca3a740f903ac -430, 0x9aae84ca64051770 -431, 0x858a0d2d879442e -432, 0x75b3e7d29e357b39 -433, 0x9f6f5487d5ec5ac1 -434, 0xfd95986f2765eed4 -435, 0x2899b60770693140 -436, 0xb8ab9650b7300ee8 -437, 0xaa772209ef643b16 -438, 0x9c98fb4b5946fc61 -439, 0x6f614d64e4a38b84 -440, 0xbe0099b53347a13f -441, 0xe8d05eabf7db8a0e -442, 0x4c849670c59692d5 -443, 0x421d2e32838ebba6 -444, 0x1fb1f7427466dd6b -445, 0xd79d9987fd12fa15 -446, 0xc195d5fedaa613c1 -447, 0xfecdf6c6fb6c4924 -448, 0xd8536233459d6d65 -449, 0xaed30f22454f593c -450, 0x14d427078bb818c1 -451, 0xf7235f42e291617a -452, 0xb1fc436bdb2efb83 -453, 0x21cc3fd0fb82e07b -454, 0x2df968f572e077bb -455, 0xe1b76c513528f8c3 -456, 0x955681442083db83 -457, 0x2e009197f295008c -458, 0x2c258d6b1935587a -459, 0xd10fda2d14ce8e70 -460, 0xd21cdc7f5db09825 -461, 0xe39168a7b3a080cc -462, 0xc82c2a353a812026 -463, 0x6adc63d4bb7f26b0 -464, 0x5d2acdd2deaed807 -465, 0x47c39719b79aee01 -466, 0x5b6351daac993e69 -467, 0x1e2d2cf25d029df -468, 0x671c43218ccc62b -469, 0x783093122682b9c8 -470, 0x8055e091219d2263 -471, 0xa6e7f6bc43717757 -472, 0x91855fe232480a87 -473, 0x554030e74824042 -474, 0xd0c14f8ff34b1a30 -475, 0x13aa852fdea8bca8 -476, 0x27ed292b1a4fa598 -477, 0x3e56548b7095af08 -478, 0x47432aa82a4bfcfc -479, 0xadddde35537dc4c8 -480, 0xadb0d103d29faa1f -481, 0x14818cb71d4cdaf9 -482, 0x31507bcc3d46a5d -483, 0x7407577173399611 -484, 0xac03706bbe4da972 -485, 0x4efb0cae8499469c -486, 0xc6d4bcbc4396a20b -487, 0xd7581757d38762c3 -488, 0x6308e217f7e69120 -489, 0x6931392a2fcf3756 -490, 0xb5a5b36744f09886 -491, 0x8da8292d0bf2ed08 -492, 0x13e0aa8d5a24bd3d -493, 0x1131dbe7a2b97139 -494, 0x2098efd4a1e7108c -495, 0x9c470e15e690e574 -496, 0xe60e3aeb65560eb8 -497, 0x4ae5444669ffc65f -498, 0x911fc7e6820923b8 -499, 0x25b3fbb125c1ae19 -500, 0xa8b6c812471f37f0 -501, 0xe6d9aec89655113e -502, 0x59d24e18c48dd532 -503, 0xc9b320756e0d6c35 -504, 0xb70a2316319c8e2a -505, 0x328a0b16ff39152c -506, 0xc2088e4c8a3298 -507, 0x10bce05ac0971264 -508, 0xe26b5b7655fd4ad5 -509, 0xfb1d818177211481 -510, 0x98d83c41a7196f86 -511, 0x45801b77072aace8 -512, 0x563268328ebfb870 -513, 0x4d26e320a51123fa -514, 0xf531c63a3438f527 -515, 0xd94525fda256c193 -516, 0x883de65d7957b025 -517, 0x7be095e05de1599b -518, 0xd27792977b3a11dd -519, 0xfd179d3c4a5f06fe -520, 0xfbe066b302e09da2 -521, 0xb841424fbd2c7249 -522, 0x566dc3e3f2345fc1 -523, 0x14e8cfa0ee0ab392 -524, 0xf1e11e1841884ad7 -525, 0xc895b028b3b7df26 -526, 0x70f727baee1dc909 -527, 0xc2f4bcd3f8c7905a -528, 0x6d294a99118f9f47 -529, 0x18a723a0ddcf902e -530, 0xac36efa0258143c4 -531, 0xc558a61c40490895 -532, 0x430341fd196a18e7 -533, 0x27fea5b52f4178c7 -534, 0xd0d628d45d51e088 -535, 0xc016cdc47158510a -536, 0x925a6cdd446f0555 -537, 0x5e5a30a2f1d9bd08 -538, 0x918ad9cea082da5b -539, 0x23bb26bfaa0e79d8 -540, 0xf667bd79197706ca -541, 0x9ae3d6e8290fa1d5 -542, 0x20a15e60e0007e64 -543, 0x7d88beb1713a320b -544, 0x2d8b1728e392a6c3 -545, 0xb4cc0ae2c22afad3 -546, 0x749fe3524435e61f -547, 0x137bc8f57e7060a3 -548, 0x8070ee0def7571b -549, 0x2d5cacc36c121329 -550, 0x8408aeea38281006 -551, 0xc05e54af2206ce49 -552, 0xd547b24a26ebd3c2 -553, 0xc66d83645d95b57d -554, 0x8f4187e81ac31f25 -555, 0xe2878187a7ffa7e2 -556, 0xf7802760e1a8b9e9 -557, 0xd7f135ce1d83b5d -558, 0x4e2d5eee2bbad34c -559, 0x9b73503bcada0bcc -560, 0xc3fb41b2fdd2b56e -561, 0xc5958ed587dca76f -562, 0x1029b90ef3fa1e44 -563, 0xeb52236cba057b2f -564, 0xd411396dfa523c6d -565, 0xccb05527609c690f -566, 0xe73e27fd2c6295e0 -567, 0x363628b4f2a7bd3a -568, 0x443bcaaab9b67c72 -569, 0x1142926c0ff02a91 -570, 0x6d7fe0d6fbcb7265 -571, 0xea31775a5191e8a2 -572, 0xc44a633ed2339375 -573, 0x261bfdb83fc7a23b -574, 0x4cb967260869e0e7 -575, 0xf3b7134ffac658c0 -576, 0x97b266a6b95e219a -577, 0x18a5be54082669aa -578, 0x9adbdbfe1ad667c -579, 0x6fd02995faae35b0 -580, 0x9e62832c534ef39f -581, 0xb89e8229d7a85aec -582, 0xa46c8670446a0539 -583, 0x6960eeea3b3a4c70 -584, 0x27901b708cbb4f97 -585, 0xde1abdbbffa9cf6c -586, 0xcadb304d56e1ad33 -587, 0x579b5110955d30c9 -588, 0x77b57f59d61ebdbb -589, 0x900adb153a8037c0 -590, 0x1f5200f1f8be5a4a -591, 0xc491a76e1cefe1f1 -592, 0x6724370243b5d0c9 -593, 0x6cc8e3b9fbb98c87 -594, 0xca1722c5183b2b57 -595, 0xe9a61a3f20c59fec -596, 0x91723ba5418ed1b5 -597, 0x4299a43bd28daf49 -598, 0x8dc266e15f1f32b1 -599, 0x91a22c16ad09703b -600, 0xfe36e6cd32ebd06c -601, 0x30c0d9f9a60a11ae -602, 0xfad538e8bf1a0f03 -603, 0x47c2a0261dc808f6 -604, 0x9148743d0cdc81a -605, 0x17c3f4257197c037 -606, 0xdc8b06b5220c01a7 -607, 0xf9ad586eb09e30f4 -608, 0x702600c123b400c6 -609, 0x9218eef469b0db7e -610, 0xce16c9bac0969bb4 -611, 0xa758408742a37457 -612, 0x2eb094509e812e4a -613, 0x28440b87ce1e0e21 -614, 0xab48eb01ee07e56a -615, 0x85e69345a3649100 -616, 0x517927d4a415e569 -617, 0xd02de9b703206f93 -618, 0x5cae9cf67b9d62a9 -619, 0x8b0e1e0c2623250d -620, 0xce893eb84c72510b -621, 0xd97bdcd1e00f8c3d -622, 0x106c1721a5e8546 -623, 0xb4fc0554e61e059a -624, 0x5fad1bc4c54c3136 -625, 0xd09dc05514ba4ad3 -626, 0xc934e2153df00372 -627, 0x3cff94fa0fa2967a -628, 0x4e7ca152c113e934 -629, 0xc5ccf2350fb82ffc -630, 0x10aa453d349b70df -631, 0xf8270070253de14 -632, 0x412b14bc12ef4538 -633, 0xaf83140fc27938c2 -634, 0xf342d1c8c97c7e74 -635, 0x693b4b07b79cfdc2 -636, 0xe859c76fde1be4aa -637, 0x90ac4aa1c012a971 -638, 0xeca381124c9bf23b -639, 0x1f544598d356ab2f -640, 0xbcd78485f20f8339 -641, 0x6b8eb4bf854dcdf5 -642, 0xdb231419a9323609 -643, 0xb2f0167ca051a61a -644, 0x9806e89e8d3ebd15 -645, 0x69ce87797a14c206 -646, 0x143ecc33c23e61f5 -647, 0x3be37d8fbcfc396f -648, 0x2a4336f50c851387 -649, 0xe665ed14a40c6400 -650, 0xc229fc93c03a6a24 -651, 0xb7f27088c74af74 -652, 0x8a8da4fbf5fb90a6 -653, 0x8c54684d5db6a600 -654, 0x11ef0e952c8ad4ec -655, 0x928a518e677b87a6 -656, 0x6b6c8ebe9db7253e -657, 0x9feecd8eaf8a8101 -658, 0x4f270f30f3ad2d0b -659, 0x23798146bff58d75 -660, 0x7d9134e4005b9246 -661, 0x18b5eb6833bb921e -662, 0xff0ef41f6c734814 -663, 0x388b18f678774f4e -664, 0xa51646467be5785e -665, 0x9f96bbe291c9361 -666, 0xce39cac00148c7b1 -667, 0x69d41ab8914f944f -668, 0x579ca60b75dbf4e5 -669, 0x352f2b89c968d81 -670, 0x181d45a561c05553 -671, 0x5a6aeaa048d6a494 -672, 0xd7938433b99408ca -673, 0x13bd6696806f0800 -674, 0x2ca8e35e87037dbb -675, 0x70d9d33ef79088a1 -676, 0xcdcb45940c9ba3e7 -677, 0x2546f21a69a29dc -678, 0xc674c5afa1f9abdf -679, 0x856dfa52fdff93b5 -680, 0x614b66daa02187bb -681, 0x55ce165aee2e205e -682, 0xf34d6cf856f941e3 -683, 0xa4a0ec51b4f25b25 -684, 0x83e6bf89bfe39762 -685, 0xb559b9a68edf3381 -686, 0x9259778b54c31479 -687, 0x4e4e21e81138cacd -688, 0xbbb990cd25c2fb2d -689, 0x38a85ad84d9e31e -690, 0x5b4f4081ffba398d -691, 0xfb12eb300dada910 -692, 0x6975328f3eebcb34 -693, 0x3db017218a6478f0 -694, 0x9397aca7eaa5de14 -695, 0x6f7318d0d9ffed6 -696, 0x40cf276103c34010 -697, 0xeacef8ae2095ec8a -698, 0x80f7593e9ddaa152 -699, 0x8d4bc01f7e5c6520 -700, 0xbbc9606e7518e199 -701, 0xfe71ef90abbaca29 -702, 0x528edfe3e467ed43 -703, 0x52b322c36f60627d -704, 0x9946be5ea3beac73 -705, 0x890745d71a02c404 -706, 0x5570d1bde8bb7993 -707, 0x563fceeff8466dcc -708, 0x62a9ca23db6e4d62 -709, 0x89d6038410c92e8 -710, 0x16bc3b1ea7b90a89 -711, 0x12ff3e9c30d8dde6 -712, 0xe78cb53e8dd40a77 -713, 0x643722181b85d5a -714, 0x73e26524635d78e3 -715, 0x941ccfc41d47c53b -716, 0xadbedec82c31e57c -717, 0x2addd39e7a36aad6 -718, 0xe64d81fa432bb65d -719, 0x1e2e63d01399ca82 -720, 0x760a3c0edbbef3a6 -721, 0x801131e88419a79c -722, 0xa2a75136213dbb6 -723, 0x83e576905753c3ff -724, 0xdbbdab8007c4ea0 -725, 0xbb73b13358898c2d -726, 0x5818372d8fe036f7 -727, 0x3aa052cd647e29d1 -728, 0x235219635ff4abb6 -729, 0xe24e07311fa76b65 -730, 0x4967574b62c3efb8 -731, 0xb04b4c210022e795 -732, 0x3d48e77713ef3fda -733, 0xf4ec1050775fd3b1 -734, 0x38953c604d35190d -735, 0xf731a6450c1e23fe -736, 0xac66ae73ecc6b9dd -737, 0x442e2bcbca5bbaa8 -738, 0xa74a741bd02570bf -739, 0xa85473cbf3b4c45e -740, 0x24d43199c69cdda -741, 0x59f78fa87f895d36 -742, 0x78f5513621dc1813 -743, 0x226c2606635698c9 -744, 0xea39babbad3df384 -745, 0x2f178b076f08f80d -746, 0xaee482470bd9acb5 -747, 0x48571d8c4235c1f6 -748, 0x6569395eec2df1d7 -749, 0xa9b7408c1d67a372 -750, 0x3b9c5ba01aecae9d -751, 0xb047b26325765767 -752, 0x9bb1968c8b6149d4 -753, 0xbba4038fdd341986 -754, 0xc1d23b5b89beaa88 -755, 0xaa9a341db334c8ac -756, 0xaa9337dd1fddf923 -757, 0x9fdf160ed939d68b -758, 0xbf48cdd432d0f148 -759, 0x2a01743f1f7b581b -760, 0xb68d5c631e9fb70a -761, 0xe9ab844ec026cc7b -762, 0x1fabd46f0d5266f0 -763, 0x29e53ae817eec5b -764, 0xeffbebc07500ad4d -765, 0x432ae3b596c1589b -766, 0x48d44f3895d6dc23 -767, 0xcc3a5576e24ec2bf -768, 0xc8f4a042462e95d9 -769, 0x24c12cd6ef57b6 -770, 0xa7896ae26675f69 -771, 0xb98a1790d429c90b -772, 0x71f7ac96dea8ffb6 -773, 0x7878c64cad319f72 -774, 0x65586d63156e1a05 -775, 0xa70ef198e61e2a11 -776, 0xf5a84f622d490449 -777, 0x7789e1c1927e82c6 -778, 0xfe053fdbb586b8fd -779, 0x59a94b735df951c3 -780, 0xdf5e72909ff2bfbd -781, 0x34dc2bd8876a92e5 -782, 0x7e408900bfa3b282 -783, 0x844176cb62d5008b -784, 0x7406e9e156cddc9c -785, 0x6a6d87de33056193 -786, 0x20c388365359e4c -787, 0xdbda2eee6499be64 -788, 0x3574cf8bc4840b47 -789, 0xc2d904ac50e44ee3 -790, 0xb9edf042b0d96102 -791, 0x2ac087f3922dd11e -792, 0xeaf244df29c2a8ae -793, 0xb4243528d8d0649c -794, 0xed67e39d9217e6cd -795, 0xcbdcd1620727437 -796, 0xcc00dec8485d0dfb -797, 0x2e5411679d89f548 -798, 0xdd355c299c05131e -799, 0x6fc81e1e9beb2c8 -800, 0x205ac04eedc0085c -801, 0x8bf73a08c5240640 -802, 0xec6f8daf06673cae -803, 0x6e29f78f0a59638e -804, 0x8c530fd613aeccda -805, 0x58b99ce19626ee04 -806, 0xb16f71c11f209bb9 -807, 0xea1d7ee0e82f9146 -808, 0x5641482551d357fa -809, 0x13fb8eff6efa4b89 -810, 0xca4bdfac87e46ce0 -811, 0x9e2babf08f33b6ad -812, 0x482633792e270729 -813, 0xd5c17bce83e146e9 -814, 0xf8df8169c7ff4df6 -815, 0xad974ea8b3bb7e7d -816, 0x8ad356322d6c0a26 -817, 0x5ba5a24cff70d235 -818, 0xb604ea125e469d44 -819, 0xecb90d0ca42445d9 -820, 0x9c499d3f441e6eb3 -821, 0x2aed9e67fc701d26 -822, 0xb3476334028bed9 -823, 0xba079723415a89fd -824, 0x8684b0e124ebd181 -825, 0x6effee2741402b37 -826, 0x15e734115d68f8a4 -827, 0xafc15b8a9fa93205 -828, 0x9749e35360fcd91 -829, 0x8ffbf6ba4b02bacd -830, 0x2f107b6a820f44ba -831, 0x230cdb06c5f7422b -832, 0x2149918883f7c858 -833, 0x3e8eb9dbfb832b71 -834, 0x871f0b4369d3dbc3 -835, 0x3553e06132e55fa4 -836, 0x1ec19fd1ce7a5823 -837, 0xf3908fc23446b3a2 -838, 0xe300b55305c8d7f3 -839, 0x61e4ab3372dce7dc -840, 0xb50f68be3632604f -841, 0xd6d2993fa6d155b9 -842, 0xf9c8d0fed0c90246 -843, 0xdd1b49530387141f -844, 0xd1db9818546e095c -845, 0xb91885ccff43ee8c -846, 0x8d704dca3b7fdb63 -847, 0x8309c9077939df4 -848, 0x6536739d7ae608f7 -849, 0xdab8a503cb9b94a6 -850, 0xc504248b8f69f733 -851, 0xb0ccfb81eb67e3e4 -852, 0x45ac4f949c418493 -853, 0x7763a70137c01376 -854, 0x7f08d6362b17c470 -855, 0xb190bb422946ad46 -856, 0xdafe7dfcb0d71320 -857, 0xec415ea4c54398f5 -858, 0x5955b81204c5657c -859, 0xff1f983c56d6d7cb -860, 0xb25b4a0de0bf393d -861, 0x3a90222bef45f3fc -862, 0xf0eb0903e3695f44 -863, 0x405ecabf26817b33 -864, 0xccf01a062f2351eb -865, 0xa62a5f63e31545b1 -866, 0x673d1baf237668d3 -867, 0xd15db3cddfb0a161 -868, 0xa8adebfc9b5351f6 -869, 0xc297fae49f0b2d08 -870, 0xe5ed1156ab569225 -871, 0xf4aa4bab70aa8c11 -872, 0x8e32dd1eb44c6363 -873, 0xc7aa250f1492e86d -874, 0xc645795d705914cf -875, 0xfdd8a48c0fb81c53 -876, 0x6ad1401f539799fe -877, 0xa157e71b6bdd4254 -878, 0x4cc09814465a6c9e -879, 0xed1f66bd824e39ec -880, 0x6b74f7f6f2d4c16b -881, 0xa3391c0100010ae4 -882, 0xe0f384530c0e7eb -883, 0xf6aeb9f0d64c7159 -884, 0x3d7f6bd980e07a17 -885, 0x8b4e1bd3e782ea4e -886, 0x7b005009d95b7d38 -887, 0xf43f001d5e7326c0 -888, 0x16600ff7361a1721 -889, 0x13778aceafd72087 -890, 0x85d3359c37907c58 -891, 0x7374f768c968d0f -892, 0x2373d89b9b8f9e9a -893, 0x21a3fe7e4dc5cc35 -894, 0xb02abcad4f4ae60 -895, 0xb9eb579582666e3b -896, 0x9c12186973b91695 -897, 0x1bd25ac6911295e7 -898, 0x9f5a90e0fc16ffa2 -899, 0xe3e8f10ce7fbb9e1 -900, 0x5867e566887d2d16 -901, 0xd569aaf2ffead057 -902, 0x678359b93dfd07f1 -903, 0x9fb73a4f1b777d94 -904, 0x5c6b0bcc70df3a54 -905, 0x66fd71a67ed5e59d -906, 0x62f21a6fe936b212 -907, 0x86922151e4b251c4 -908, 0xbfdee56cdeabe8bd -909, 0xbe3bc7c4c2380ffc -910, 0xd09ebebb0e786d49 -911, 0x4951a83005aa22de -912, 0xc1b7da6cf08630c4 -913, 0x8b294b5fef04b0af -914, 0xaca7a47f7fda4d5f -915, 0x70bbddc64b4b1a91 -916, 0xad306a764087085c -917, 0x19b9f11c14adb74a -918, 0xbf1a7d2c83fbbbe -919, 0xb78da8a53fa857 -920, 0x5b614c5060a543b7 -921, 0xb6f32557404d475f -922, 0x9fc53dfe5281f084 -923, 0x43ad9d302c10a475 -924, 0xa4575be2c10fbc13 -925, 0xe58c4c02d5b2bc8a -926, 0xaa838a3e5a16bb55 -927, 0x95c39373858011e1 -928, 0x17a6be18c1801fa -929, 0x835e6c3d99898c27 -930, 0x9af26334bd726505 -931, 0x7addf56712a22afb -932, 0xf619281f6d4d37d0 -933, 0x310c6b1e29ca7eaa -934, 0xe8106bbe1ea0f3c9 -935, 0xc89add421cfe7bb9 -936, 0xe01b7a6885180236 -937, 0xda8cd608ee0eee61 -938, 0x3bb2f5f40a8f4880 -939, 0xd434cddc85946350 -940, 0x6390806f8d1465f -941, 0x2a5f0150c8362cf3 -942, 0xcc6980e968b75f37 -943, 0xd86756899b2c95d2 -944, 0x95ab76b54f439605 -945, 0x1e0d6f6a99569ffc -946, 0xd47b20b72c0f02e3 -947, 0xcd9fff1462fe8a25 -948, 0x71867c57f009bc8b -949, 0x85238c818139a22b -950, 0x58247991b6447ce7 -951, 0x3b41a627153bcc9f -952, 0xa3ddf05f18153e13 -953, 0x21a3d47762fbdbe4 -954, 0x8ee55f20e5c5b14 -955, 0xc3ed8e23589b365f -956, 0xbd12efde1b5e8afc -957, 0x35b81175f738edc8 -958, 0x16b2627c28c952c0 -959, 0xb16a5009047b002b -960, 0x5e4c769bd80bed26 -961, 0x96174863aa73bf6b -962, 0xb3bfe6a2d7d05881 -963, 0x5c0a1757302c3fb6 -964, 0xfcc52e2da058ae67 -965, 0x12b26055c0ea26e8 -966, 0x87d8126b14b8417b -967, 0xc87745c58eaa597f -968, 0xb38b4b4b579ab55 -969, 0x559ece2bb0ca0b32 -970, 0xecbf6af7914a6435 -971, 0xd994b534e3f46c42 -972, 0x67301d5555cbaf1 -973, 0x4b2222c098aecb6a -974, 0x2f1b7acadaa10ffc -975, 0x4c48c65a542d56f4 -976, 0xf3fbde71409cd64c -977, 0xb32e3ef1dc24a7cb -978, 0x229321ce5bcd85 -979, 0xcad7e7dfee447d7a -980, 0x7fddd28936d166a5 -981, 0x928bfb0027da2715 -982, 0x97b17752c6aaa82b -983, 0x3eaca529c941d7c1 -984, 0x91937555520265e -985, 0x8e7e5c3786ee3588 -986, 0x27162348b08a9aca -987, 0x302165a3d76eab04 -988, 0x94111b7672c6bd95 -989, 0x7a471169035fc35a -990, 0xe850ed94b0be86e1 -991, 0xf7a3721d6c85c1cc -992, 0x6727a68e16268dfc -993, 0x65433e82f0e19d29 -994, 0x6109fd616c977544 -995, 0x7068ef83a29cdc70 -996, 0xcef2deae0fccb574 -997, 0xee2a2ee021a6ad5a -998, 0x5195005fba78706c -999, 0x31364d630d333f34 diff --git a/_randomgen/randomgen/tests/test_legacy.py b/_randomgen/randomgen/tests/test_legacy.py deleted file mode 100644 index 21c56946f6b8..000000000000 --- a/_randomgen/randomgen/tests/test_legacy.py +++ /dev/null @@ -1,17 +0,0 @@ -import pickle - -from randomgen.legacy import LegacyGenerator - - -def test_pickle(): - lg = LegacyGenerator() - lg.random_sample(100) - lg.standard_normal() - lg2 = pickle.loads(pickle.dumps(lg)) - assert lg.standard_normal() == lg2.standard_normal() - assert lg.random_sample() == lg2.random_sample() - - -def test_weibull(): - lg = LegacyGenerator() - assert lg.weibull(0.0) == 0.0 diff --git a/_randomgen/requirements.txt b/_randomgen/requirements.txt deleted file mode 100644 index 0d7fe1ba89e7..000000000000 --- a/_randomgen/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -numpy>=1.13 -cython>=0.26 -setuptools -wheel \ No newline at end of file diff --git a/_randomgen/setup.cfg b/_randomgen/setup.cfg deleted file mode 100644 index b25ab5078a40..000000000000 --- a/_randomgen/setup.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[metadata] -description-file = README.md -license_file = LICENSE.md - -[versioneer] -VCS = git -style = pep440 -versionfile_source = randomgen/_version.py -versionfile_build = randomgen/_version.py -tag_prefix = v -parentdir_prefix = randomgen- diff --git a/_randomgen/versioneer.py b/_randomgen/versioneer.py deleted file mode 100644 index 64fea1c89272..000000000000 --- a/_randomgen/versioneer.py +++ /dev/null @@ -1,1822 +0,0 @@ - -# Version: 0.18 - -"""The Versioneer - like a rocketeer, but for versions. - -The Versioneer -============== - -* like a rocketeer, but for versions! -* https://github.com/warner/python-versioneer -* Brian Warner -* License: Public Domain -* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy -* [![Latest Version] -(https://pypip.in/version/versioneer/badge.svg?style=flat) -](https://pypi.python.org/pypi/versioneer/) -* [![Build Status] -(https://travis-ci.org/warner/python-versioneer.png?branch=master) -](https://travis-ci.org/warner/python-versioneer) - -This is a tool for managing a recorded version number in distutils-based -python projects. The goal is to remove the tedious and error-prone "update -the embedded version string" step from your release process. Making a new -release should be as easy as recording a new tag in your version-control -system, and maybe making new tarballs. - - -## Quick Install - -* `pip install versioneer` to somewhere to your $PATH -* add a `[versioneer]` section to your setup.cfg (see below) -* run `versioneer install` in your source tree, commit the results - -## Version Identifiers - -Source trees come from a variety of places: - -* a version-control system checkout (mostly used by developers) -* a nightly tarball, produced by build automation -* a snapshot tarball, produced by a web-based VCS browser, like github's - "tarball from tag" feature -* a release tarball, produced by "setup.py sdist", distributed through PyPI - -Within each source tree, the version identifier (either a string or a number, -this tool is format-agnostic) can come from a variety of places: - -* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows - about recent "tags" and an absolute revision-id -* the name of the directory into which the tarball was unpacked -* an expanded VCS keyword ($Id$, etc) -* a `_version.py` created by some earlier build step - -For released software, the version identifier is closely related to a VCS -tag. Some projects use tag names that include more than just the version -string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool -needs to strip the tag prefix to extract the version identifier. For -unreleased software (between tags), the version identifier should provide -enough information to help developers recreate the same tree, while also -giving them an idea of roughly how old the tree is (after version 1.2, before -version 1.3). Many VCS systems can report a description that captures this, -for example `git describe --tags --dirty --always` reports things like -"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the -0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has -uncommitted changes. - -The version identifier is used for multiple purposes: - -* to allow the module to self-identify its version: `myproject.__version__` -* to choose a name and prefix for a 'setup.py sdist' tarball - -## Theory of Operation - -Versioneer works by adding a special `_version.py` file into your source -tree, where your `__init__.py` can import it. This `_version.py` knows how to -dynamically ask the VCS tool for version information at import time. - -`_version.py` also contains `$Revision$` markers, and the installation -process marks `_version.py` to have this marker rewritten with a tag name -during the `git archive` command. As a result, generated tarballs will -contain enough information to get the proper version. - -To allow `setup.py` to compute a version too, a `versioneer.py` is added to -the top level of your source tree, next to `setup.py` and the `setup.cfg` -that configures it. This overrides several distutils/setuptools commands to -compute the version when invoked, and changes `setup.py build` and `setup.py -sdist` to replace `_version.py` with a small static file that contains just -the generated version data. - -## Installation - -See [INSTALL.md](./INSTALL.md) for detailed installation instructions. - -## Version-String Flavors - -Code which uses Versioneer can learn about its version string at runtime by -importing `_version` from your main `__init__.py` file and running the -`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can -import the top-level `versioneer.py` and run `get_versions()`. - -Both functions return a dictionary with different flavors of version -information: - -* `['version']`: A condensed version string, rendered using the selected - style. This is the most commonly used value for the project's version - string. The default "pep440" style yields strings like `0.11`, - `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section - below for alternative styles. - -* `['full-revisionid']`: detailed revision identifier. For Git, this is the - full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". - -* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the - commit date in ISO 8601 format. This will be None if the date is not - available. - -* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that - this is only accurate if run in a VCS checkout, otherwise it is likely to - be False or None - -* `['error']`: if the version string could not be computed, this will be set - to a string describing the problem, otherwise it will be None. It may be - useful to throw an exception in setup.py if this is set, to avoid e.g. - creating tarballs with a version string of "unknown". - -Some variants are more useful than others. Including `full-revisionid` in a -bug report should allow developers to reconstruct the exact code being tested -(or indicate the presence of local changes that should be shared with the -developers). `version` is suitable for display in an "about" box or a CLI -`--version` output: it can be easily compared against release notes and lists -of bugs fixed in various releases. - -The installer adds the following text to your `__init__.py` to place a basic -version in `YOURPROJECT.__version__`: - - from ._version import get_versions - __version__ = get_versions()['version'] - del get_versions - -## Styles - -The setup.cfg `style=` configuration controls how the VCS information is -rendered into a version string. - -The default style, "pep440", produces a PEP440-compliant string, equal to the -un-prefixed tag name for actual releases, and containing an additional "local -version" section with more detail for in-between builds. For Git, this is -TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags ---dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the -tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and -that this commit is two revisions ("+2") beyond the "0.11" tag. For released -software (exactly equal to a known tag), the identifier will only contain the -stripped tag, e.g. "0.11". - -Other styles are available. See [details.md](details.md) in the Versioneer -source tree for descriptions. - -## Debugging - -Versioneer tries to avoid fatal errors: if something goes wrong, it will tend -to return a version of "0+unknown". To investigate the problem, run `setup.py -version`, which will run the version-lookup code in a verbose mode, and will -display the full contents of `get_versions()` (including the `error` string, -which may help identify what went wrong). - -## Known Limitations - -Some situations are known to cause problems for Versioneer. This details the -most significant ones. More can be found on Github -[issues page](https://github.com/warner/python-versioneer/issues). - -### Subprojects - -Versioneer has limited support for source trees in which `setup.py` is not in -the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are -two common reasons why `setup.py` might not be in the root: - -* Source trees which contain multiple subprojects, such as - [Buildbot](https://github.com/buildbot/buildbot), which contains both - "master" and "slave" subprojects, each with their own `setup.py`, - `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI - distributions (and upload multiple independently-installable tarballs). -* Source trees whose main purpose is to contain a C library, but which also - provide bindings to Python (and perhaps other langauges) in subdirectories. - -Versioneer will look for `.git` in parent directories, and most operations -should get the right version string. However `pip` and `setuptools` have bugs -and implementation details which frequently cause `pip install .` from a -subproject directory to fail to find a correct version string (so it usually -defaults to `0+unknown`). - -`pip install --editable .` should work correctly. `setup.py install` might -work too. - -Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in -some later version. - -[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking -this issue. The discussion in -[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the -issue from the Versioneer side in more detail. -[pip PR#3176](https://github.com/pypa/pip/pull/3176) and -[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve -pip to let Versioneer work correctly. - -Versioneer-0.16 and earlier only looked for a `.git` directory next to the -`setup.cfg`, so subprojects were completely unsupported with those releases. - -### Editable installs with setuptools <= 18.5 - -`setup.py develop` and `pip install --editable .` allow you to install a -project into a virtualenv once, then continue editing the source code (and -test) without re-installing after every change. - -"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a -convenient way to specify executable scripts that should be installed along -with the python package. - -These both work as expected when using modern setuptools. When using -setuptools-18.5 or earlier, however, certain operations will cause -`pkg_resources.DistributionNotFound` errors when running the entrypoint -script, which must be resolved by re-installing the package. This happens -when the install happens with one version, then the egg_info data is -regenerated while a different version is checked out. Many setup.py commands -cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into -a different virtualenv), so this can be surprising. - -[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes -this one, but upgrading to a newer version of setuptools should probably -resolve it. - -### Unicode version strings - -While Versioneer works (and is continually tested) with both Python 2 and -Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. -Newer releases probably generate unicode version strings on py2. It's not -clear that this is wrong, but it may be surprising for applications when then -write these strings to a network connection or include them in bytes-oriented -APIs like cryptographic checksums. - -[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates -this question. - - -## Updating Versioneer - -To upgrade your project to a new release of Versioneer, do the following: - -* install the new Versioneer (`pip install -U versioneer` or equivalent) -* edit `setup.cfg`, if necessary, to include any new configuration settings - indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. -* re-run `versioneer install` in your source tree, to replace - `SRC/_version.py` -* commit any changed files - -## Future Directions - -This tool is designed to make it easily extended to other version-control -systems: all VCS-specific components are in separate directories like -src/git/ . The top-level `versioneer.py` script is assembled from these -components by running make-versioneer.py . In the future, make-versioneer.py -will take a VCS name as an argument, and will construct a version of -`versioneer.py` that is specific to the given VCS. It might also take the -configuration arguments that are currently provided manually during -installation by editing setup.py . Alternatively, it might go the other -direction and include code from all supported VCS systems, reducing the -number of intermediate scripts. - - -## License - -To make Versioneer easier to embed, all its code is dedicated to the public -domain. The `_version.py` that it creates is also in the public domain. -Specifically, both are released under the Creative Commons "Public Domain -Dedication" license (CC0-1.0), as described in -https://creativecommons.org/publicdomain/zero/1.0/ . - -""" - -from __future__ import print_function -try: - import configparser -except ImportError: - import ConfigParser as configparser -import errno -import json -import os -import re -import subprocess -import sys - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_root(): - """Get the project root directory. - - We require that all commands are run from the project root, i.e. the - directory that contains setup.py, setup.cfg, and versioneer.py . - """ - root = os.path.realpath(os.path.abspath(os.getcwd())) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - # allow 'python path/to/setup.py COMMAND' - root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - err = ("Versioneer was unable to run the project root directory. " - "Versioneer requires setup.py to be executed from " - "its immediate directory (like 'python setup.py COMMAND'), " - "or in a way that lets it use sys.argv[0] to find the root " - "(like 'python path/to/setup.py COMMAND').") - raise VersioneerBadRootError(err) - try: - # Certain runtime workflows (setup.py install/develop in a setuptools - # tree) execute all dependencies in a single python process, so - # "versioneer" may be imported multiple times, and python's shared - # module-import table will cache the first one. So we can't use - # os.path.dirname(__file__), as that will find whichever - # versioneer.py was first imported, even in later projects. - me = os.path.realpath(os.path.abspath(__file__)) - me_dir = os.path.normcase(os.path.splitext(me)[0]) - vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) - if me_dir != vsr_dir: - print("Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(me), versioneer_py)) - except NameError: - pass - return root - - -def get_config_from_root(root): - """Read the project setup.cfg file to determine Versioneer config.""" - # This might raise EnvironmentError (if setup.cfg is missing), or - # configparser.NoSectionError (if it lacks a [versioneer] section), or - # configparser.NoOptionError (if it lacks "VCS="). See the docstring at - # the top of versioneer.py for instructions on writing your setup.cfg . - setup_cfg = os.path.join(root, "setup.cfg") - parser = configparser.SafeConfigParser() - with open(setup_cfg, "r") as f: - parser.readfp(f) - VCS = parser.get("versioneer", "VCS") # mandatory - - def get(parser, name): - if parser.has_option("versioneer", name): - return parser.get("versioneer", name) - return None - cfg = VersioneerConfig() - cfg.VCS = VCS - cfg.style = get(parser, "style") or "" - cfg.versionfile_source = get(parser, "versionfile_source") - cfg.versionfile_build = get(parser, "versionfile_build") - cfg.tag_prefix = get(parser, "tag_prefix") - if cfg.tag_prefix in ("''", '""'): - cfg.tag_prefix = "" - cfg.parentdir_prefix = get(parser, "parentdir_prefix") - cfg.verbose = get(parser, "verbose") - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -# these dictionaries contain VCS-specific tools -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode - - -LONG_VERSION_PY['git'] = ''' -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" - git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" - git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "%(STYLE)s" - cfg.tag_prefix = "%(TAG_PREFIX)s" - cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" - cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %%s" %% dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %%s" %% (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %%s (error)" %% dispcmd) - print("stdout was %%s" %% stdout) - return None, p.returncode - return stdout, p.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %%s but none started with prefix %%s" %% - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %%d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%%s', no digits" %% ",".join(refs - tags)) - if verbose: - print("likely tags: %%s" %% ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %%s" %% r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %%s not under git control" %% root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%%s*" %% tag_prefix], - cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%%s'" - %% describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%%s' doesn't start with prefix '%%s'" - print(fmt %% (full_tag, tag_prefix)) - pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" - %% (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], - cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%%d" %% pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%%d" %% pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%%s" %% pieces["short"] - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%%s" %% pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%%s'" %% style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): - root = os.path.dirname(root) - except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} -''' - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def do_vcs_install(manifest_in, versionfile_source, ipy): - """Git-specific installation logic for Versioneer. - - For Git, this means creating/changing .gitattributes to mark _version.py - for export-subst keyword substitution. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - files = [manifest_in, versionfile_source] - if ipy: - files.append(ipy) - try: - me = __file__ - if me.endswith(".pyc") or me.endswith(".pyo"): - me = os.path.splitext(me)[0] + ".py" - versioneer_file = os.path.relpath(me) - except NameError: - versioneer_file = "versioneer.py" - files.append(versioneer_file) - present = False - try: - f = open(".gitattributes", "r") - for line in f.readlines(): - if line.strip().startswith(versionfile_source): - if "export-subst" in line.strip().split()[1:]: - present = True - f.close() - except EnvironmentError: - pass - if not present: - f = open(".gitattributes", "a+") - f.write("%s export-subst\n" % versionfile_source) - f.close() - files.append(".gitattributes") - run_command(GITS, ["add", "--"] + files) - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -SHORT_VERSION_PY = """ -# This file was generated by 'versioneer.py' (0.18) from -# revision-control system data, or from the parent directory name of an -# unpacked source archive. Distribution tarballs contain a pre-generated copy -# of this file. - -import json - -version_json = ''' -%s -''' # END VERSION_JSON - - -def get_versions(): - return json.loads(version_json) -""" - - -def versions_from_file(filename): - """Try to determine the version from _version.py if present.""" - try: - with open(filename) as f: - contents = f.read() - except EnvironmentError: - raise NotThisMethod("unable to read _version.py") - mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - raise NotThisMethod("no version_json in _version.py") - return json.loads(mo.group(1)) - - -def write_to_version_file(filename, versions): - """Write the given version number to the given _version.py file.""" - os.unlink(filename) - contents = json.dumps(versions, sort_keys=True, - indent=1, separators=(",", ": ")) - with open(filename, "w") as f: - f.write(SHORT_VERSION_PY % contents) - - print("set %s to '%s'" % (filename, versions["version"])) - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -class VersioneerBadRootError(Exception): - """The project root directory is unknown or missing key files.""" - - -def get_versions(verbose=False): - """Get the project version from whatever source is available. - - Returns dict with two keys: 'version' and 'full'. - """ - if "versioneer" in sys.modules: - # see the discussion in cmdclass.py:get_cmdclass() - del sys.modules["versioneer"] - - root = get_root() - cfg = get_config_from_root(root) - - assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" - handlers = HANDLERS.get(cfg.VCS) - assert handlers, "unrecognized VCS '%s'" % cfg.VCS - verbose = verbose or cfg.verbose - assert cfg.versionfile_source is not None, \ - "please set versioneer.versionfile_source" - assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" - - versionfile_abs = os.path.join(root, cfg.versionfile_source) - - # extract version from first of: _version.py, VCS command (e.g. 'git - # describe'), parentdir. This is meant to work for developers using a - # source checkout, for users of a tarball created by 'setup.py sdist', - # and for users of a tarball/zipball created by 'git archive' or github's - # download-from-tag feature or the equivalent in other VCSes. - - get_keywords_f = handlers.get("get_keywords") - from_keywords_f = handlers.get("keywords") - if get_keywords_f and from_keywords_f: - try: - keywords = get_keywords_f(versionfile_abs) - ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) - if verbose: - print("got version from expanded keyword %s" % ver) - return ver - except NotThisMethod: - pass - - try: - ver = versions_from_file(versionfile_abs) - if verbose: - print("got version from file %s %s" % (versionfile_abs, ver)) - return ver - except NotThisMethod: - pass - - from_vcs_f = handlers.get("pieces_from_vcs") - if from_vcs_f: - try: - pieces = from_vcs_f(cfg.tag_prefix, root, verbose) - ver = render(pieces, cfg.style) - if verbose: - print("got version from VCS %s" % ver) - return ver - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - if verbose: - print("got version from parentdir %s" % ver) - return ver - except NotThisMethod: - pass - - if verbose: - print("unable to compute version") - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, "error": "unable to compute version", - "date": None} - - -def get_version(): - """Get the short version string for this project.""" - return get_versions()["version"] - - -def get_cmdclass(): - """Get the custom setuptools/distutils subclasses used by Versioneer.""" - if "versioneer" in sys.modules: - del sys.modules["versioneer"] - # this fixes the "python setup.py develop" case (also 'install' and - # 'easy_install .'), in which subdependencies of the main project are - # built (using setup.py bdist_egg) in the same python process. Assume - # a main project A and a dependency B, which use different versions - # of Versioneer. A's setup.py imports A's Versioneer, leaving it in - # sys.modules by the time B's setup.py is executed, causing B to run - # with the wrong versioneer. Setuptools wraps the sub-dep builds in a - # sandbox that restores sys.modules to it's pre-build state, so the - # parent is protected against the child's "import versioneer". By - # removing ourselves from sys.modules here, before the child build - # happens, we protect the child from the parent's versioneer too. - # Also see https://github.com/warner/python-versioneer/issues/52 - - cmds = {} - - # we add "version" to both distutils and setuptools - from distutils.core import Command - - class cmd_version(Command): - description = "report generated version string" - user_options = [] - boolean_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - vers = get_versions(verbose=True) - print("Version: %s" % vers["version"]) - print(" full-revisionid: %s" % vers.get("full-revisionid")) - print(" dirty: %s" % vers.get("dirty")) - print(" date: %s" % vers.get("date")) - if vers["error"]: - print(" error: %s" % vers["error"]) - cmds["version"] = cmd_version - - # we override "build_py" in both distutils and setuptools - # - # most invocation pathways end up running build_py: - # distutils/build -> build_py - # distutils/install -> distutils/build ->.. - # setuptools/bdist_wheel -> distutils/install ->.. - # setuptools/bdist_egg -> distutils/install_lib -> build_py - # setuptools/install -> bdist_egg ->.. - # setuptools/develop -> ? - # pip install: - # copies source tree to a tempdir before running egg_info/etc - # if .git isn't copied too, 'git describe' will fail - # then does setup.py bdist_wheel, or sometimes setup.py install - # setup.py egg_info -> ? - - # we override different "build_py" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.build_py import build_py as _build_py - else: - from distutils.command.build_py import build_py as _build_py - - class cmd_build_py(_build_py): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - _build_py.run(self) - # now locate _version.py in the new build/ directory and replace - # it with an updated value - if cfg.versionfile_build: - target_versionfile = os.path.join(self.build_lib, - cfg.versionfile_build) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - cmds["build_py"] = cmd_build_py - - if "cx_Freeze" in sys.modules: # cx_freeze enabled? - from cx_Freeze.dist import build_exe as _build_exe - # nczeczulin reports that py2exe won't like the pep440-style string - # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. - # setup(console=[{ - # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION - # "product_version": versioneer.get_version(), - # ... - - class cmd_build_exe(_build_exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _build_exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["build_exe"] = cmd_build_exe - del cmds["build_py"] - - if 'py2exe' in sys.modules: # py2exe enabled? - try: - from py2exe.distutils_buildexe import py2exe as _py2exe # py3 - except ImportError: - from py2exe.build_exe import py2exe as _py2exe # py2 - - class cmd_py2exe(_py2exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _py2exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["py2exe"] = cmd_py2exe - - # we override different "sdist" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.sdist import sdist as _sdist - else: - from distutils.command.sdist import sdist as _sdist - - class cmd_sdist(_sdist): - def run(self): - versions = get_versions() - self._versioneer_generated_versions = versions - # unless we update this, the command will keep using the old - # version - self.distribution.metadata.version = versions["version"] - return _sdist.run(self) - - def make_release_tree(self, base_dir, files): - root = get_root() - cfg = get_config_from_root(root) - _sdist.make_release_tree(self, base_dir, files) - # now locate _version.py in the new base_dir directory - # (remembering that it may be a hardlink) and replace it with an - # updated value - target_versionfile = os.path.join(base_dir, cfg.versionfile_source) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, - self._versioneer_generated_versions) - cmds["sdist"] = cmd_sdist - - return cmds - - -CONFIG_ERROR = """ -setup.cfg is missing the necessary Versioneer configuration. You need -a section like: - - [versioneer] - VCS = git - style = pep440 - versionfile_source = src/myproject/_version.py - versionfile_build = myproject/_version.py - tag_prefix = - parentdir_prefix = myproject- - -You will also need to edit your setup.py to use the results: - - import versioneer - setup(version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), ...) - -Please read the docstring in ./versioneer.py for configuration instructions, -edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. -""" - -SAMPLE_CONFIG = """ -# See the docstring in versioneer.py for instructions. Note that you must -# re-run 'versioneer.py setup' after changing this section, and commit the -# resulting files. - -[versioneer] -#VCS = git -#style = pep440 -#versionfile_source = -#versionfile_build = -#tag_prefix = -#parentdir_prefix = - -""" - -INIT_PY_SNIPPET = """ -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions -""" - - -def do_setup(): - """Main VCS-independent setup function for installing Versioneer.""" - root = get_root() - try: - cfg = get_config_from_root(root) - except (EnvironmentError, configparser.NoSectionError, - configparser.NoOptionError) as e: - if isinstance(e, (EnvironmentError, configparser.NoSectionError)): - print("Adding sample versioneer config to setup.cfg", - file=sys.stderr) - with open(os.path.join(root, "setup.cfg"), "a") as f: - f.write(SAMPLE_CONFIG) - print(CONFIG_ERROR, file=sys.stderr) - return 1 - - print(" creating %s" % cfg.versionfile_source) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - - ipy = os.path.join(os.path.dirname(cfg.versionfile_source), - "__init__.py") - if os.path.exists(ipy): - try: - with open(ipy, "r") as f: - old = f.read() - except EnvironmentError: - old = "" - if INIT_PY_SNIPPET not in old: - print(" appending to %s" % ipy) - with open(ipy, "a") as f: - f.write(INIT_PY_SNIPPET) - else: - print(" %s unmodified" % ipy) - else: - print(" %s doesn't exist, ok" % ipy) - ipy = None - - # Make sure both the top-level "versioneer.py" and versionfile_source - # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so - # they'll be copied into source distributions. Pip won't be able to - # install the package without this. - manifest_in = os.path.join(root, "MANIFEST.in") - simple_includes = set() - try: - with open(manifest_in, "r") as f: - for line in f: - if line.startswith("include "): - for include in line.split()[1:]: - simple_includes.add(include) - except EnvironmentError: - pass - # That doesn't cover everything MANIFEST.in can do - # (http://docs.python.org/2/distutils/sourcedist.html#commands), so - # it might give some false negatives. Appending redundant 'include' - # lines is safe, though. - if "versioneer.py" not in simple_includes: - print(" appending 'versioneer.py' to MANIFEST.in") - with open(manifest_in, "a") as f: - f.write("include versioneer.py\n") - else: - print(" 'versioneer.py' already in MANIFEST.in") - if cfg.versionfile_source not in simple_includes: - print(" appending versionfile_source ('%s') to MANIFEST.in" % - cfg.versionfile_source) - with open(manifest_in, "a") as f: - f.write("include %s\n" % cfg.versionfile_source) - else: - print(" versionfile_source already in MANIFEST.in") - - # Make VCS-specific changes. For git, this means creating/changing - # .gitattributes to mark _version.py for export-subst keyword - # substitution. - do_vcs_install(manifest_in, cfg.versionfile_source, ipy) - return 0 - - -def scan_setup_py(): - """Validate the contents of setup.py against Versioneer's expectations.""" - found = set() - setters = False - errors = 0 - with open("setup.py", "r") as f: - for line in f.readlines(): - if "import versioneer" in line: - found.add("import") - if "versioneer.get_cmdclass()" in line: - found.add("cmdclass") - if "versioneer.get_version()" in line: - found.add("get_version") - if "versioneer.VCS" in line: - setters = True - if "versioneer.versionfile_source" in line: - setters = True - if len(found) != 3: - print("") - print("Your setup.py appears to be missing some important items") - print("(but I might be wrong). Please make sure it has something") - print("roughly like the following:") - print("") - print(" import versioneer") - print(" setup( version=versioneer.get_version(),") - print(" cmdclass=versioneer.get_cmdclass(), ...)") - print("") - errors += 1 - if setters: - print("You should remove lines like 'versioneer.VCS = ' and") - print("'versioneer.versionfile_source = ' . This configuration") - print("now lives in setup.cfg, and should be removed from setup.py") - print("") - errors += 1 - return errors - - -if __name__ == "__main__": - cmd = sys.argv[1] - if cmd == "setup": - errors = do_setup() - errors += scan_setup_py() - if errors: - sys.exit(1) diff --git a/doc/Makefile b/doc/Makefile index 4db17b297df0..776f9b7782a9 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -46,7 +46,8 @@ help: @echo " upload USERNAME=... RELEASE=... to upload built docs to docs.scipy.org" clean: - -rm -rf build/* source/reference/generated + -rm -rf build/* + find . -name generated -type d -prune -exec rm -rf "{}" ";" version-check: ifeq "$(GITVER)" "Unknown" diff --git a/doc/source/conf.py b/doc/source/conf.py index 072a3b44e5dc..dec8fff05b2f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -19,11 +19,19 @@ sys.path.insert(0, os.path.abspath('../sphinxext')) -extensions = ['sphinx.ext.autodoc', 'numpydoc', - 'sphinx.ext.intersphinx', 'sphinx.ext.coverage', - 'sphinx.ext.doctest', 'sphinx.ext.autosummary', - 'sphinx.ext.graphviz', 'sphinx.ext.ifconfig', - 'matplotlib.sphinxext.plot_directive'] +extensions = [ + 'sphinx.ext.autodoc', + 'numpydoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.coverage', + 'sphinx.ext.doctest', + 'sphinx.ext.autosummary', + 'sphinx.ext.graphviz', + 'sphinx.ext.ifconfig', + 'matplotlib.sphinxext.plot_directive', + 'IPython.sphinxext.ipython_console_highlighting', + 'IPython.sphinxext.ipython_directive', +] if sphinx.__version__ >= "1.4": extensions.append('sphinx.ext.imgmath') @@ -234,7 +242,7 @@ def setup(app): # ----------------------------------------------------------------------------- import glob -autosummary_generate = glob.glob("reference/*.rst") +autosummary_generate = True # ----------------------------------------------------------------------------- # Coverage checker @@ -355,3 +363,8 @@ def linkcode_resolve(domain, info): else: return "https://github.com/numpy/numpy/blob/v%s/numpy/%s%s" % ( numpy.__version__, fn, linespec) + +doctest_global_setup = ''' +import numpy as np +from numpy.random import randomgen +''' diff --git a/_randomgen/doc/source/brng/dsfmt.rst b/doc/source/reference/randomgen/brng/dsfmt.rst similarity index 82% rename from _randomgen/doc/source/brng/dsfmt.rst rename to doc/source/reference/randomgen/brng/dsfmt.rst index bd660c938d54..f9de48d61dcf 100644 --- a/_randomgen/doc/source/brng/dsfmt.rst +++ b/doc/source/reference/randomgen/brng/dsfmt.rst @@ -1,12 +1,13 @@ Double SIMD Mersenne Twister (dSFMT) ------------------------------------ -.. module:: randomgen.dsfmt +.. module:: numpy.random.randomgen.dsfmt -.. currentmodule:: randomgen.dsfmt +.. currentmodule:: numpy.random.randomgen.dsfmt .. autoclass:: DSFMT + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/index.rst b/doc/source/reference/randomgen/brng/index.rst similarity index 100% rename from _randomgen/doc/source/brng/index.rst rename to doc/source/reference/randomgen/brng/index.rst diff --git a/_randomgen/doc/source/brng/mt19937.rst b/doc/source/reference/randomgen/brng/mt19937.rst similarity index 81% rename from _randomgen/doc/source/brng/mt19937.rst rename to doc/source/reference/randomgen/brng/mt19937.rst index 23f8e45940a0..7739e16ce1b5 100644 --- a/_randomgen/doc/source/brng/mt19937.rst +++ b/doc/source/reference/randomgen/brng/mt19937.rst @@ -1,11 +1,12 @@ Mersenne Twister (MT19937) -------------------------- -.. module:: randomgen.mt19937 +.. module:: numpy.random.randomgen.mt19937 -.. currentmodule:: randomgen.mt19937 +.. currentmodule:: numpy.random.randomgen.mt19937 .. autoclass:: MT19937 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/pcg32.rst b/doc/source/reference/randomgen/brng/pcg32.rst similarity index 83% rename from _randomgen/doc/source/brng/pcg32.rst rename to doc/source/reference/randomgen/brng/pcg32.rst index 1854b4c68dd9..aaf3929e87b3 100644 --- a/_randomgen/doc/source/brng/pcg32.rst +++ b/doc/source/reference/randomgen/brng/pcg32.rst @@ -1,11 +1,12 @@ Parallel Congruent Generator (32-bit, PCG32) -------------------------------------------- -.. module:: randomgen.pcg32 +.. module:: numpy.random.randomgen.pcg32 -.. currentmodule:: randomgen.pcg32 +.. currentmodule:: numpy.random.randomgen.pcg32 .. autoclass:: PCG32 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/pcg64.rst b/doc/source/reference/randomgen/brng/pcg64.rst similarity index 83% rename from _randomgen/doc/source/brng/pcg64.rst rename to doc/source/reference/randomgen/brng/pcg64.rst index 496825dc456a..94e73e491910 100644 --- a/_randomgen/doc/source/brng/pcg64.rst +++ b/doc/source/reference/randomgen/brng/pcg64.rst @@ -1,11 +1,12 @@ Parallel Congruent Generator (64-bit, PCG64) -------------------------------------------- -.. module:: randomgen.pcg64 +.. module:: numpy.random.randomgen.pcg64 -.. currentmodule:: randomgen.pcg64 +.. currentmodule:: numpy.random.randomgen.pcg64 .. autoclass:: PCG64 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/philox.rst b/doc/source/reference/randomgen/brng/philox.rst similarity index 82% rename from _randomgen/doc/source/brng/philox.rst rename to doc/source/reference/randomgen/brng/philox.rst index c2ffc44eb1fa..091c4d3e0e8e 100644 --- a/_randomgen/doc/source/brng/philox.rst +++ b/doc/source/reference/randomgen/brng/philox.rst @@ -1,11 +1,12 @@ Philox Counter-based RNG ------------------------ -.. module:: randomgen.philox +.. module:: numpy.random.randomgen.philox -.. currentmodule:: randomgen.philox +.. currentmodule:: numpy.random.randomgen.philox .. autoclass:: Philox + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/threefry.rst b/doc/source/reference/randomgen/brng/threefry.rst similarity index 82% rename from _randomgen/doc/source/brng/threefry.rst rename to doc/source/reference/randomgen/brng/threefry.rst index 98141d6486c5..4f5c56bae866 100644 --- a/_randomgen/doc/source/brng/threefry.rst +++ b/doc/source/reference/randomgen/brng/threefry.rst @@ -1,11 +1,12 @@ ThreeFry Counter-based RNG -------------------------- -.. module:: randomgen.threefry +.. module:: numpy.random.randomgen.threefry -.. currentmodule:: randomgen.threefry +.. currentmodule:: numpy.random.randomgen.threefry .. autoclass:: ThreeFry + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/threefry32.rst b/doc/source/reference/randomgen/brng/threefry32.rst similarity index 82% rename from _randomgen/doc/source/brng/threefry32.rst rename to doc/source/reference/randomgen/brng/threefry32.rst index 2869cbac887c..bd85db4a7141 100644 --- a/_randomgen/doc/source/brng/threefry32.rst +++ b/doc/source/reference/randomgen/brng/threefry32.rst @@ -1,11 +1,12 @@ ThreeFry32 Counter-based RNG ---------------------------- -.. module:: randomgen.threefry32 +.. module:: numpy.random.randomgen.threefry32 -.. currentmodule:: randomgen.threefry32 +.. currentmodule:: numpy.random.randomgen.threefry32 .. autoclass:: ThreeFry32 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/xoroshiro128.rst b/doc/source/reference/randomgen/brng/xoroshiro128.rst similarity index 80% rename from _randomgen/doc/source/brng/xoroshiro128.rst rename to doc/source/reference/randomgen/brng/xoroshiro128.rst index 3d6735c621d2..6796c44577c0 100644 --- a/_randomgen/doc/source/brng/xoroshiro128.rst +++ b/doc/source/reference/randomgen/brng/xoroshiro128.rst @@ -1,11 +1,12 @@ Xoroshiro128+ ------------- -.. module:: randomgen.xoroshiro128 +.. module:: numpy.random.randomgen.xoroshiro128 -.. currentmodule:: randomgen.xoroshiro128 +.. currentmodule:: numpy.random.randomgen.xoroshiro128 .. autoclass:: Xoroshiro128 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/xorshift1024.rst b/doc/source/reference/randomgen/brng/xorshift1024.rst similarity index 80% rename from _randomgen/doc/source/brng/xorshift1024.rst rename to doc/source/reference/randomgen/brng/xorshift1024.rst index 38b293dcd6f8..64df7e050d01 100644 --- a/_randomgen/doc/source/brng/xorshift1024.rst +++ b/doc/source/reference/randomgen/brng/xorshift1024.rst @@ -1,11 +1,12 @@ Xorshift1024*φ -------------- -.. module:: randomgen.xorshift1024 +.. module:: numpy.random.randomgen.xorshift1024 -.. currentmodule:: randomgen.xorshift1024 +.. currentmodule:: numpy.random.randomgen.xorshift1024 .. autoclass:: Xorshift1024 + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/xoshiro256starstar.rst b/doc/source/reference/randomgen/brng/xoshiro256starstar.rst similarity index 80% rename from _randomgen/doc/source/brng/xoshiro256starstar.rst rename to doc/source/reference/randomgen/brng/xoshiro256starstar.rst index 903e76bbbd20..7603e6f1beba 100644 --- a/_randomgen/doc/source/brng/xoshiro256starstar.rst +++ b/doc/source/reference/randomgen/brng/xoshiro256starstar.rst @@ -1,11 +1,12 @@ Xoshiro256** ------------ -.. module:: randomgen.xoshiro256starstar +.. module:: numpy.random.randomgen.xoshiro256starstar -.. currentmodule:: randomgen.xoshiro256starstar +.. currentmodule:: numpy.random.randomgen.xoshiro256starstar .. autoclass:: Xoshiro256StarStar + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/brng/xoshiro512starstar.rst b/doc/source/reference/randomgen/brng/xoshiro512starstar.rst similarity index 80% rename from _randomgen/doc/source/brng/xoshiro512starstar.rst rename to doc/source/reference/randomgen/brng/xoshiro512starstar.rst index 3501b2c9c85e..64f95f7509c2 100644 --- a/_randomgen/doc/source/brng/xoshiro512starstar.rst +++ b/doc/source/reference/randomgen/brng/xoshiro512starstar.rst @@ -1,11 +1,12 @@ Xoshiro512** ------------ -.. module:: randomgen.xoshiro512starstar +.. module:: numpy.random.randomgen.xoshiro512starstar -.. currentmodule:: randomgen.xoshiro512starstar +.. currentmodule:: numpy.random.randomgen.xoshiro512starstar .. autoclass:: Xoshiro512StarStar + :exclude-members: Seeding and State ================= diff --git a/_randomgen/doc/source/change-log.rst b/doc/source/reference/randomgen/change-log.rst similarity index 100% rename from _randomgen/doc/source/change-log.rst rename to doc/source/reference/randomgen/change-log.rst diff --git a/_randomgen/doc/source/entropy.rst b/doc/source/reference/randomgen/entropy.rst similarity index 60% rename from _randomgen/doc/source/entropy.rst rename to doc/source/reference/randomgen/entropy.rst index 3e50c892fc1d..6814edfbe752 100644 --- a/_randomgen/doc/source/entropy.rst +++ b/doc/source/reference/randomgen/entropy.rst @@ -1,6 +1,6 @@ System Entropy ============== -.. module:: randomgen.entropy +.. module:: numpy.random.randomgen.entropy .. autofunction:: random_entropy diff --git a/_randomgen/doc/source/extending.rst b/doc/source/reference/randomgen/extending.rst similarity index 100% rename from _randomgen/doc/source/extending.rst rename to doc/source/reference/randomgen/extending.rst diff --git a/_randomgen/doc/source/generator.rst b/doc/source/reference/randomgen/generator.rst similarity index 92% rename from _randomgen/doc/source/generator.rst rename to doc/source/reference/randomgen/generator.rst index dba51eb6d00f..d59efd68c802 100644 --- a/_randomgen/doc/source/generator.rst +++ b/doc/source/reference/randomgen/generator.rst @@ -12,10 +12,10 @@ distributions. The default basic RNG used by changed by passing an instantized basic RNG to :class:`~randomgen.generator.RandomGenerator`. -.. currentmodule:: randomgen.generator +.. currentmodule:: numpy.random.randomgen.generator -.. autoclass:: - RandomGenerator +.. autoclass:: RandomGenerator + :exclude-members: Seed and State Manipulation =========================== @@ -37,8 +37,6 @@ Simple random data ~RandomGenerator.random_sample ~RandomGenerator.choice ~RandomGenerator.bytes - ~RandomGenerator.random_uintegers - ~RandomGenerator.random_raw Permutations ============ @@ -56,7 +54,6 @@ Distributions ~RandomGenerator.beta ~RandomGenerator.binomial ~RandomGenerator.chisquare - ~RandomGenerator.complex_normal ~RandomGenerator.dirichlet ~RandomGenerator.exponential ~RandomGenerator.f @@ -88,4 +85,4 @@ Distributions ~RandomGenerator.vonmises ~RandomGenerator.wald ~RandomGenerator.weibull - ~RandomGenerator.zipf \ No newline at end of file + ~RandomGenerator.zipf diff --git a/_randomgen/doc/source/index.rst b/doc/source/reference/randomgen/index.rst similarity index 98% rename from _randomgen/doc/source/index.rst rename to doc/source/reference/randomgen/index.rst index eac8c1ef12e8..67d0441a2de4 100644 --- a/_randomgen/doc/source/index.rst +++ b/doc/source/reference/randomgen/index.rst @@ -1,9 +1,11 @@ -RandomGen -========= +Randomgen.RandomGen +=================== This package contains replacements for the NumPy :class:`~numpy.random.RandomState` object that allows the core random number generator be be changed. +.. current_module numpy.random.randomgen + Quick Start ----------- @@ -187,14 +189,14 @@ Random Generator .. toctree:: :maxdepth: 1 - Random Generation + generator legacy Basic Random Number Generators ------------------------------ .. toctree:: - :maxdepth: 3 + :maxdepth: 1 Basic Random Number Generators diff --git a/_randomgen/doc/source/legacy.rst b/doc/source/reference/randomgen/legacy.rst similarity index 85% rename from _randomgen/doc/source/legacy.rst rename to doc/source/reference/randomgen/legacy.rst index befd7abb5fd9..7e87f871cc10 100644 --- a/_randomgen/doc/source/legacy.rst +++ b/doc/source/reference/randomgen/legacy.rst @@ -47,10 +47,10 @@ when accessing the state so that these extra values are saved. lg.standard_exponential() -.. currentmodule:: randomgen.legacy.legacy +.. currentmodule:: numpy.random.randomgen.legacy -.. autoclass:: - LegacyGenerator +.. autoclass:: LegacyGenerator + :exclude-members: Seeding and State ================= @@ -58,7 +58,8 @@ Seeding and State .. autosummary:: :toctree: generated/ - ~LegacyGenerator.state + ~LegacyGenerator.get_state + ~LegacyGenerator.set_state Simple random data ================== @@ -66,6 +67,19 @@ Simple random data :toctree: generated/ ~LegacyGenerator.randn + ~LegacyGenerator.randint + ~LegacyGenerator.random_integers + ~LegacyGenerator.random_sample + ~LegacyGenerator.choice + ~LegacyGenerator.bytes + +Permutations +============ +.. autosummary:: + :toctree: generated/ + + ~LegacyGenerator.shuffle + ~LegacyGenerator.permutation Distributions ============= @@ -93,3 +107,4 @@ Distributions ~LegacyGenerator.standard_t ~LegacyGenerator.wald ~LegacyGenerator.weibull + ~LegacyGenerator.zipf diff --git a/_randomgen/doc/source/multithreading.rst b/doc/source/reference/randomgen/multithreading.rst similarity index 100% rename from _randomgen/doc/source/multithreading.rst rename to doc/source/reference/randomgen/multithreading.rst diff --git a/_randomgen/doc/source/new-or-different.rst b/doc/source/reference/randomgen/new-or-different.rst similarity index 100% rename from _randomgen/doc/source/new-or-different.rst rename to doc/source/reference/randomgen/new-or-different.rst diff --git a/_randomgen/doc/source/parallel.rst b/doc/source/reference/randomgen/parallel.rst similarity index 100% rename from _randomgen/doc/source/parallel.rst rename to doc/source/reference/randomgen/parallel.rst diff --git a/_randomgen/doc/source/performance.py b/doc/source/reference/randomgen/performance.py similarity index 100% rename from _randomgen/doc/source/performance.py rename to doc/source/reference/randomgen/performance.py diff --git a/_randomgen/doc/source/performance.rst b/doc/source/reference/randomgen/performance.rst similarity index 100% rename from _randomgen/doc/source/performance.rst rename to doc/source/reference/randomgen/performance.rst diff --git a/_randomgen/doc/source/references.rst b/doc/source/reference/randomgen/references.rst similarity index 100% rename from _randomgen/doc/source/references.rst rename to doc/source/reference/randomgen/references.rst diff --git a/doc/source/reference/routines.rst b/doc/source/reference/routines.rst index a9e80480b870..0ed99cbdac36 100644 --- a/doc/source/reference/routines.rst +++ b/doc/source/reference/routines.rst @@ -42,6 +42,7 @@ indentation. routines.padding routines.polynomials routines.random + randomgen/index routines.set routines.sort routines.statistics diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 965ab5ea9b75..53e9477975c0 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -86,8 +86,6 @@ """ from __future__ import division, absolute_import, print_function -import warnings - __all__ = [ 'beta', 'binomial', @@ -138,9 +136,8 @@ 'zipf' ] -with warnings.catch_warnings(): - warnings.filterwarnings("ignore", message="numpy.ndarray size changed") - from .mtrand import * +from .randomgen import mtrand +from .randomgen.mtrand import * # Some aliases: ranf = random = sample = random_sample diff --git a/numpy/random/mtrand/distributions.c b/numpy/random/mtrand/distributions.c index 2b1f5e7a935c..1b410db57444 100644 --- a/numpy/random/mtrand/distributions.c +++ b/numpy/random/mtrand/distributions.c @@ -447,6 +447,10 @@ long rk_binomial(rk_state *state, long n, double p) { double q; + if ((n == 0LL) || (p == 0.0f)) { + return 0; + } + if (p <= 0.5) { if (p*n <= 30.0) diff --git a/numpy/random/mtrand/initarray.c b/numpy/random/mtrand/initarray.c index 21f1dc05a931..beff7851002a 100644 --- a/numpy/random/mtrand/initarray.c +++ b/numpy/random/mtrand/initarray.c @@ -71,7 +71,6 @@ * 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" diff --git a/numpy/random/mtrand/numpy.pxd b/numpy/random/mtrand/numpy.pxd index 1b4fe6c10491..e146054b117d 100644 --- a/numpy/random/mtrand/numpy.pxd +++ b/numpy/random/mtrand/numpy.pxd @@ -3,8 +3,6 @@ # :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: diff --git a/_randomgen/LICENSE.md b/numpy/random/randomgen/LICENSE.md similarity index 60% rename from _randomgen/LICENSE.md rename to numpy/random/randomgen/LICENSE.md index e159d505e845..caa665373a6e 100644 --- a/_randomgen/LICENSE.md +++ b/numpy/random/randomgen/LICENSE.md @@ -1,4 +1,8 @@ -**Copyright (c) 2018 Kevin Sheppard. All rights reserved.** +**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 (, ) @@ -30,11 +34,43 @@ 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.** -## NumPy -Many parts of this module have been derived from NumPy. +# 3-Clause BSD License +**Copyright (c) 2019 Kevin Sheppard. All rights reserved.** -Copyright (c) 2005-2017, NumPy Developers. +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.** + +# NumPy and Other Components + +Many parts of this module have been derived from NumPy. Other parts have been +derived from original sources, often the algorithm's designer. The NumPy license +is reproduced below. Component licenses are located with the component code. + +Copyright (c) 2005-2019, NumPy Developers. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -68,4 +104,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## Components Many of the components have their own license terms which are stored -with the source for the component. \ No newline at end of file +with the source for the component. + diff --git a/numpy/random/randomgen/__init__.py b/numpy/random/randomgen/__init__.py new file mode 100644 index 000000000000..1af2fc3b200c --- /dev/null +++ b/numpy/random/randomgen/__init__.py @@ -0,0 +1,21 @@ +from .dsfmt import DSFMT +from .generator import RandomGenerator +from .mt19937 import MT19937 +from .pcg32 import PCG32 +from .pcg64 import PCG64 +from .philox import Philox +from .threefry import ThreeFry +from .threefry32 import ThreeFry32 +from .xoroshiro128 import Xoroshiro128 +from .xorshift1024 import Xorshift1024 +from .xoshiro256starstar import Xoshiro256StarStar +from .xoshiro512starstar import Xoshiro512StarStar +from .mtrand import RandomState +__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', + 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState'] + +#from ._version import get_versions + +#__version__ = get_versions()['version'] +#del get_versions diff --git a/_randomgen/randomgen/pickle.py b/numpy/random/randomgen/_pickle.py similarity index 55% rename from _randomgen/randomgen/pickle.py rename to numpy/random/randomgen/_pickle.py index 459f9c2fcd99..1c365b0c7c8a 100644 --- a/_randomgen/randomgen/pickle.py +++ b/numpy/random/randomgen/_pickle.py @@ -8,19 +8,23 @@ from .threefry32 import ThreeFry32 from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 +from .xoshiro256starstar import Xoshiro256StarStar +from .xoshiro512starstar import Xoshiro512StarStar +from .mtrand import RandomState + +BasicRNGS = {'MT19937': MT19937, + 'DSFMT': DSFMT, + 'PCG32': PCG32, + 'PCG64': PCG64, + 'Philox': Philox, + 'ThreeFry': ThreeFry, + 'ThreeFry32': ThreeFry32, + 'Xorshift1024': Xorshift1024, + 'Xoroshiro128': Xoroshiro128, + 'Xoshiro256StarStar': Xoshiro256StarStar, + 'Xoshiro512StarStar': Xoshiro512StarStar, + } -PRNGS = {'MT19937': MT19937, - 'DSFMT': DSFMT, - 'PCG32': PCG32, - 'PCG64': PCG64, - 'Philox': Philox, - 'ThreeFry': ThreeFry, - 'ThreeFry32': ThreeFry32, - 'Xorshift1024': Xorshift1024, - 'Xoroshiro128': Xoroshiro128, - 'Xoshiro256StarStar': Xoshiro256StarStar, - 'Xoshiro512StarStar': Xoshiro512StarStar, - } def __generator_ctor(brng_name='mt19937'): """ @@ -72,3 +76,28 @@ def __brng_ctor(brng_name='mt19937'): raise ValueError(str(brng_name) + ' is not a known PRNG module.') return brng() + +def __randomstate_ctor(brng_name='mt19937'): + """ + Pickling helper function that returns a legacy RandomState-like object + + Parameters + ---------- + brng_name: str + String containing the core BasicRNG + + Returns + ------- + rs: RandomState + Legacy RandomState using the named core BasicRNG + """ + try: + brng_name = brng_name.decode('ascii') + except AttributeError: + pass + if brng_name in BasicRNGS: + brng = BasicRNGS[brng_name] + else: + raise ValueError(str(brng_name) + ' is not a known BasicRNG module.') + + return RandomState(brng()) diff --git a/_randomgen/randomgen/_version.py b/numpy/random/randomgen/_version.py similarity index 100% rename from _randomgen/randomgen/_version.py rename to numpy/random/randomgen/_version.py diff --git a/_randomgen/randomgen/bounded_integers.pxd.in b/numpy/random/randomgen/bounded_integers.pxd.in similarity index 61% rename from _randomgen/randomgen/bounded_integers.pxd.in rename to numpy/random/randomgen/bounded_integers.pxd.in index 5f723733cca6..4ab389fd923e 100644 --- a/_randomgen/randomgen/bounded_integers.pxd.in +++ b/numpy/random/randomgen/bounded_integers.pxd.in @@ -1,23 +1,10 @@ -from __future__ import absolute_import - 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 +cimport numpy as np ctypedef np.npy_bool bool_t -from randomgen.common cimport brng_t - -_randint_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) - } +from .common cimport brng_t cdef inline uint64_t _gen_mask(uint64_t max_val) nogil: """Mask generator for use in bounded random numbers""" diff --git a/_randomgen/randomgen/bounded_integers.pyx.in b/numpy/random/randomgen/bounded_integers.pyx.in similarity index 95% rename from _randomgen/randomgen/bounded_integers.pyx.in rename to numpy/random/randomgen/bounded_integers.pyx.in index eb8555b310d0..03068a8fd088 100644 --- a/_randomgen/randomgen/bounded_integers.pyx.in +++ b/numpy/random/randomgen/bounded_integers.pyx.in @@ -1,14 +1,22 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True -from __future__ import absolute_import import numpy as np cimport numpy as np -from randomgen.distributions cimport * +from .distributions cimport * np.import_array() +_randint_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'), @@ -21,7 +29,6 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U )}} {{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, brng_t *state, object lock): @@ -42,7 +49,6 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s cdef np.broadcast it cdef int buf_rem = 0 - # Array path low_arr = low high_arr = high @@ -83,7 +89,6 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s np.PyArray_MultiIter_NEXT(it) return out_arr {{endfor}} - {{ py: big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), @@ -166,7 +171,6 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, return out_arr {{endfor}} - {{ py: type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), @@ -241,8 +245,8 @@ cdef object _rand_{{nptype}}(object low, object high, object size, high_arr = 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))): + 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] diff --git a/_randomgen/randomgen/common.pxd b/numpy/random/randomgen/common.pxd similarity index 85% rename from _randomgen/randomgen/common.pxd rename to numpy/random/randomgen/common.pxd index 63a1b3f7d09f..f6748e5aa27d 100644 --- a/_randomgen/randomgen/common.pxd +++ b/numpy/random/randomgen/common.pxd @@ -1,13 +1,11 @@ #cython: language_level=3 -from __future__ import absolute_import - 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 -from randomgen.distributions cimport brng_t +from .distributions cimport brng_t import numpy as np cimport numpy as np @@ -18,6 +16,7 @@ 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 @@ -27,14 +26,18 @@ cdef enum ConstraintType: ctypedef ConstraintType constraint_type +cdef object benchmark(brng_t *brng, object lock, Py_ssize_t cnt, object method) +cdef object random_raw(brng_t *brng, object lock, object size, object output) +cdef object prepare_cffi(brng_t *brng) +cdef object prepare_ctypes(brng_t *brng) 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); + 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)(brng_t *state, np.npy_intp count, double* out) nogil ctypedef double (*random_double_0)(void *state) nogil @@ -96,14 +99,3 @@ cdef object discrete_broadcast_iii(void *func, void *state, object size, object 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 inline void compute_complex(double *rv_r, double *rv_i, double loc_r, - double loc_i, double var_r, double var_i, double rho) nogil: - cdef double scale_c, scale_i, scale_r - - scale_c = sqrt(1 - rho * rho) - scale_r = sqrt(var_r) - scale_i = sqrt(var_i) - - rv_i[0] = loc_i + scale_i * (rho * rv_r[0] + scale_c * rv_i[0]) - rv_r[0] = loc_r + scale_r * rv_r[0] diff --git a/_randomgen/randomgen/common.pyx b/numpy/random/randomgen/common.pyx similarity index 76% rename from _randomgen/randomgen/common.pyx rename to numpy/random/randomgen/common.pyx index 41d3074f352f..1f7cd40cac76 100644 --- a/_randomgen/randomgen/common.pyx +++ b/numpy/random/randomgen/common.pyx @@ -1,14 +1,12 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 -from __future__ import absolute_import - from collections import namedtuple from cpython cimport PyFloat_AsDouble import sys import numpy as np cimport numpy as np -from randomgen.common cimport * +from .common cimport * np.import_array() @@ -16,6 +14,150 @@ interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', 'next_uint32', 'next_double', 'brng']) +cdef object benchmark(brng_t *brng, object lock, Py_ssize_t cnt, object method): + """Benchmark command used by BasicRNG""" + cdef Py_ssize_t i + if method==u'uint64': + with lock, nogil: + for i in range(cnt): + brng.next_uint64(brng.state) + elif method==u'double': + with lock, nogil: + for i in range(cnt): + brng.next_double(brng.state) + else: + raise ValueError('Unknown method') + + +cdef object random_raw(brng_t *brng, object lock, object size, object output): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying PRNG + + 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. + """ + cdef np.ndarray randoms + cdef uint64_t *randoms_data + cdef Py_ssize_t i, n + + if not output: + if size is None: + with lock: + brng.next_raw(brng.state) + return None + n = np.asarray(size).sum() + with lock, nogil: + for i in range(n): + brng.next_raw(brng.state) + return None + + if size is None: + with lock: + return brng.next_raw(brng.state) + + randoms = np.empty(size, np.uint64) + randoms_data = np.PyArray_DATA(randoms) + n = np.PyArray_SIZE(randoms) + + with lock, nogil: + for i in range(n): + randoms_data[i] = brng.next_raw(brng.state) + return randoms + +cdef object prepare_cffi(brng_t *brng): + """ + Bundles the interfaces to interact with a Basic RNG using cffi + + Parameters + ---------- + brng : pointer + A pointer to a Basic RNG instance + + Returns + ------- + interface : namedtuple + The functions required to interface with the Basic RNG 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 + * brng - pointer to the Basic RNG struct + """ + try: + import cffi + except ImportError: + raise ImportError('cffi cannot be imported.') + + ffi = cffi.FFI() + _cffi = interface(brng.state, + ffi.cast('void *', brng.state), + ffi.cast('uint64_t (*)(void *)', brng.next_uint64), + ffi.cast('uint32_t (*)(void *)', brng.next_uint32), + ffi.cast('double (*)(void *)', brng.next_double), + ffi.cast('void *', brng)) + return _cffi + +cdef object prepare_ctypes(brng_t *brng): + """ + Bundles the interfaces to interact with a Basic RNG using ctypes + + Parameters + ---------- + brng : pointer + A pointer to a Basic RNG instance + + Returns + ------- + interface : namedtuple + The functions required to interface with the Basic RNG 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 + * brng - pointer to the Basic RNG struct + """ + import ctypes + + _ctypes = interface(brng.state, + ctypes.c_void_p(brng.state), + ctypes.cast(brng.next_uint64, + ctypes.CFUNCTYPE(ctypes.c_uint64, + ctypes.c_void_p)), + ctypes.cast(brng.next_uint32, + ctypes.CFUNCTYPE(ctypes.c_uint32, + ctypes.c_void_p)), + ctypes.cast(brng.next_double, + ctypes.CFUNCTYPE(ctypes.c_double, + ctypes.c_void_p)), + ctypes.c_void_p(brng)) + return _ctypes + cdef double kahan_sum(double *darr, np.npy_intp n): cdef double c, y, t, sum cdef np.npy_intp i @@ -29,6 +171,7 @@ cdef double kahan_sum(double *darr, np.npy_intp n): return sum 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: @@ -67,8 +210,12 @@ cdef check_output(object out, object dtype, object size): raise TypeError('Supplied output array has the wrong type. ' 'Expected {0}, got {0}'.format(dtype, out_array.dtype)) if size is not None: - # TODO: enable this !!! if tuple(size) != out_array.shape: - raise ValueError('size and out cannot be simultaneously used') + 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, brng_t *state, object size, object lock, object out): @@ -148,59 +295,58 @@ cdef uint64_t MAXSIZE = sys.maxsize cdef int check_array_constraint(np.ndarray val, object name, constraint_type cons) except -1: if cons == CONS_NON_NEGATIVE: - if np.any(np.signbit(val)): + if np.any(np.logical_and(np.logical_not(np.isnan(val)), np.signbit(val))): raise ValueError(name + " < 0") - elif cons == CONS_POSITIVE: - if np.any(np.less_equal(val, 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 or cons == CONS_BOUNDED_0_1_NOTNAN: - if np.any(np.less(val, 0)) or np.any(np.greater(val, 1)): - raise ValueError(name + " < 0 or " + name + " > 1") - if cons == CONS_BOUNDED_0_1_NOTNAN: - if np.any(np.isnan(val)): - raise ValueError(name + ' contains NaNs') + 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 np.any(np.less_equal(val, 0)) or np.any(np.greater(val, 1)): - raise ValueError(name + " <= 0 or " + name + " > 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 np.any(np.less_equal(val, 1)): - raise ValueError(name + " <= 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 np.any(np.less(val, 1)): - raise ValueError(name + " < 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 np.any(np.greater(val, POISSON_LAM_MAX)): - raise ValueError(name + " value too large") - if np.any(np.less(val, 0.0)): - raise ValueError(name + " < 0") + 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)) 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 np.signbit(val): + if not np.isnan(val) and np.signbit(val): raise ValueError(name + " < 0") - elif cons == CONS_POSITIVE: - if val <= 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 or cons == CONS_BOUNDED_0_1_NOTNAN: - if val < 0 or val > 1: - raise ValueError(name + " < 0 or " + name + " > 1") - if cons == CONS_BOUNDED_0_1_NOTNAN: - if np.isnan(val): - raise ValueError(name + ' contains NaNs') + 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_GT_1: - if val <= 1: - raise ValueError(name + " <= 1") + if not (val > 1): + raise ValueError("{0} <= 1 or {0} is NaN".format(name)) elif cons == CONS_GTE_1: - if val < 1: - raise ValueError(name + " < 1") + if not (val >= 1): + raise ValueError("{0} < 1 or {0} is NaN".format(name)) elif cons == CONS_POISSON: - if val < 0: - raise ValueError(name + " < 0") - elif val > POISSON_LAM_MAX: + 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") return 0 @@ -262,7 +408,6 @@ cdef object cont_broadcast_2(void *func, void *state, object size, object lock, randoms = np.empty(it.shape, np.double) # randoms = np.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_DOUBLE) - randoms_data = np.PyArray_DATA(randoms) n = np.PyArray_SIZE(randoms) @@ -301,7 +446,7 @@ cdef object cont_broadcast_3(void *func, void *state, object size, object lock, randoms = 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.PyArray_SimpleNew(it.nd, np.PyArray_DIMS(it), np.NPY_DOUBLE) randoms = np.empty(it.shape, np.double) randoms_data = np.PyArray_DATA(randoms) @@ -386,11 +531,11 @@ cdef object cont(void *func, void *state, object size, object lock, int narg, randoms = out n = np.PyArray_SIZE(randoms) - cdef double *randoms_data = np.PyArray_DATA(randoms) - cdef random_double_0 f0; - cdef random_double_1 f1; - cdef random_double_2 f2; - cdef random_double_3 f3; + cdef double *randoms_data = 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: @@ -430,7 +575,7 @@ cdef object discrete_broadcast_d(void *func, void *state, object size, object lo if size is not None: randoms = np.empty(size, np.int64) else: - #randoms = np.empty(np.shape(a_arr), np.double) + # 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 = np.PyArray_DATA(randoms) @@ -490,7 +635,6 @@ cdef object discrete_broadcast_di(void *func, void *state, object size, object l cdef random_uint_di f = (func) cdef np.npy_intp i, n - if a_constraint != CONS_NONE: check_array_constraint(a_arr, a_name, a_constraint) @@ -558,7 +702,7 @@ cdef object discrete_broadcast_iii(void *func, void *state, object size, object 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): + np.ndarray a_arr, object a_name, constraint_type a_constraint): cdef np.ndarray randoms cdef int64_t *randoms_data cdef np.broadcast it @@ -594,7 +738,7 @@ cdef object disc(void *func, void *state, object size, object lock, 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 int64_t _ia = 0, _ib = 0, _ic = 0 cdef bint is_scalar = True if narg_double > 0: a_arr = np.PyArray_FROM_OTF(a, np.NPY_DOUBLE, np.NPY_ALIGNED) @@ -612,7 +756,7 @@ cdef object disc(void *func, void *state, object size, object lock, if narg_int64 > 1: b_arr = 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 : + if narg_int64 > 2: c_arr = np.PyArray_FROM_OTF(c, np.NPY_INT64, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(c_arr) == 0 @@ -636,7 +780,6 @@ cdef object disc(void *func, void *state, object size, object lock, else: raise NotImplementedError("No vector path available") - if narg_double > 0: _da = PyFloat_AsDouble(a) if a_constraint != CONS_NONE and is_scalar: @@ -659,7 +802,7 @@ cdef object disc(void *func, void *state, object size, object lock, _ib = b if b_constraint != CONS_NONE and is_scalar: check_constraint(_ib, b_name, b_constraint) - if narg_int64 > 2 : + if narg_int64 > 2: _ic = c if c_constraint != CONS_NONE and is_scalar: check_constraint(_ic, c_name, c_constraint) @@ -684,15 +827,15 @@ cdef object disc(void *func, void *state, object size, object lock, cdef np.npy_intp i, n cdef np.ndarray randoms = 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; + 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.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) with lock, nogil: if narg_int64 == 0: @@ -726,8 +869,8 @@ cdef object disc(void *func, void *state, object size, object lock, cdef object cont_broadcast_1_f(void *func, brng_t *state, object size, object lock, - np.ndarray a_arr, object a_name, constraint_type a_constraint, - object out): + np.ndarray a_arr, object a_name, constraint_type a_constraint, + object out): cdef np.ndarray randoms cdef float a_val @@ -793,8 +936,8 @@ cdef object cont_f(void *func, brng_t *state, object size, object lock, randoms = out n = np.PyArray_SIZE(randoms) - cdef float *randoms_data = np.PyArray_DATA(randoms) - cdef random_float_1 f1 = func; + cdef float *randoms_data = np.PyArray_DATA(randoms) + cdef random_float_1 f1 = func with lock, nogil: for i in range(n): @@ -803,4 +946,4 @@ cdef object cont_f(void *func, brng_t *state, object size, object lock, if out is None: return randoms else: - return out \ No newline at end of file + return out diff --git a/_randomgen/randomgen/distributions.pxd b/numpy/random/randomgen/distributions.pxd similarity index 97% rename from _randomgen/randomgen/distributions.pxd rename to numpy/random/randomgen/distributions.pxd index 35d92db51bbb..ddb7a84bf190 100644 --- a/_randomgen/randomgen/distributions.pxd +++ b/numpy/random/randomgen/distributions.pxd @@ -3,7 +3,7 @@ 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 +cimport numpy as np cdef extern from "src/distributions/distributions.h": @@ -80,13 +80,13 @@ cdef extern from "src/distributions/distributions.h": double random_rayleigh(brng_t *brng_state, double mode) nogil double random_standard_t(brng_t *brng_state, double df) nogil double random_noncentral_chisquare(brng_t *brng_state, double df, - double nonc) nogil + double nonc) nogil double random_noncentral_f(brng_t *brng_state, double dfnum, - double dfden, double nonc) nogil + double dfden, double nonc) nogil double random_wald(brng_t *brng_state, double mean, double scale) nogil double random_vonmises(brng_t *brng_state, double mu, double kappa) nogil double random_triangular(brng_t *brng_state, double left, double mode, - double right) nogil + double right) nogil int64_t random_poisson(brng_t *brng_state, double lam) nogil int64_t random_negative_binomial(brng_t *brng_state, double n, double p) nogil diff --git a/_randomgen/randomgen/dsfmt.pyx b/numpy/random/randomgen/dsfmt.pyx similarity index 79% rename from _randomgen/randomgen/dsfmt.pyx rename to numpy/random/randomgen/dsfmt.pyx index ee8ef270d000..9a7199e856ec 100644 --- a/_randomgen/randomgen/dsfmt.pyx +++ b/numpy/random/randomgen/dsfmt.pyx @@ -1,39 +1,40 @@ -from __future__ import absolute_import - import operator from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy np.import_array() DEF DSFMT_MEXP = 19937 -DEF DSFMT_N = 191 # ((DSFMT_MEXP - 128) / 104 + 1) -DEF DSFMT_N_PLUS_1 = 192 # DSFMT_N + 1 +DEF DSFMT_N = 191 # ((DSFMT_MEXP - 128) / 104 + 1) +DEF DSFMT_N_PLUS_1 = 192 # DSFMT_N + 1 DEF DSFMT_N64 = DSFMT_N * 2 cdef extern from "src/dsfmt/dSFMT.h": union W128_T: - uint64_t u[2]; - uint32_t u32[4]; - double d[2]; + uint64_t u[2] + uint32_t u32[4] + double d[2] - ctypedef W128_T w128_t; + ctypedef W128_T w128_t struct DSFMT_T: - w128_t status[DSFMT_N_PLUS_1]; - int idx; + w128_t status[DSFMT_N_PLUS_1] + int idx - ctypedef DSFMT_T dsfmt_t; + ctypedef DSFMT_T dsfmt_t struct s_dsfmt_state: dsfmt_t *state @@ -52,7 +53,7 @@ cdef extern from "src/dsfmt/dSFMT.h": void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) - void dsfmt_jump(dsfmt_state *state); + void dsfmt_jump(dsfmt_state *state) cdef uint64_t dsfmt_uint64(void* st) nogil: return dsfmt_next64(st) @@ -101,8 +102,8 @@ cdef class DSFMT: generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen.entropy import random_entropy - >>> from randomgen import RandomGenerator, DSFMT + >>> from numpy.random.randomgen.entropy import random_entropy + >>> from numpy.random.randomgen import RandomGenerator, DSFMT >>> seed = random_entropy() >>> rs = [RandomGenerator(DSFMT(seed)) for _ in range(10)] # Advance rs[i] by i jumps @@ -138,12 +139,13 @@ cdef class DSFMT: Jump Ahead Algorithm for Linear Recurrences in a Polynomial Space", Sequences and Their Applications - SETA, 290--298, 2008. """ - cdef dsfmt_state *rng_state + cdef dsfmt_state *rng_state cdef brng_t *_brng cdef public object capsule cdef public object _cffi cdef public object _ctypes cdef public object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(dsfmt_state)) @@ -152,6 +154,8 @@ cdef class DSFMT: self.rng_state.buffer_loc = DSFMT_N64 self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() + self._brng.state = self.rng_state self._brng.next_uint64 = &dsfmt_uint64 self._brng.next_uint32 = &dsfmt_uint32 @@ -172,7 +176,8 @@ cdef class DSFMT: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -185,17 +190,39 @@ cdef class DSFMT: cdef _reset_state_variables(self): self.rng_state.buffer_loc = DSFMT_N64 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -289,14 +316,14 @@ cdef class DSFMT: for j in range(2): state[loc] = self.rng_state.state.status[i].u[j] loc += 1 - buffered_uniforms = np.empty(DSFMT_N64,dtype=np.double) + buffered_uniforms = np.empty(DSFMT_N64, dtype=np.double) for i in range(DSFMT_N64): buffered_uniforms[i] = self.rng_state.buffered_uniforms[i] return {'brng': self.__class__.__name__, - 'state': {'state':np.asarray(state), - 'idx':self.rng_state.state.idx}, + 'state': {'state': np.asarray(state), + 'idx': self.rng_state.state.idx}, 'buffer_loc': self.rng_state.buffer_loc, - 'buffered_uniforms':np.asarray(buffered_uniforms)} + 'buffered_uniforms': np.asarray(buffered_uniforms)} @state.setter def state(self, value): @@ -321,12 +348,12 @@ cdef class DSFMT: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -335,25 +362,10 @@ cdef class DSFMT: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&dsfmt_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&dsfmt_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&dsfmt_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -374,19 +386,8 @@ cdef class DSFMT: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -395,10 +396,10 @@ cdef class DSFMT: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/entropy.pyx b/numpy/random/randomgen/entropy.pyx similarity index 97% rename from _randomgen/randomgen/entropy.pyx rename to numpy/random/randomgen/entropy.pyx index d7822bfdf412..0e429e9f2631 100644 --- a/_randomgen/randomgen/entropy.pyx +++ b/numpy/random/randomgen/entropy.pyx @@ -1,7 +1,3 @@ -from __future__ import absolute_import - -import operator - cimport numpy as np import numpy as np @@ -25,6 +21,7 @@ cdef Py_ssize_t compute_numel(size): n = size return n + def seed_by_array(object seed, Py_ssize_t n): """ Transforms a seed array into an initial state @@ -150,4 +147,4 @@ def random_entropy(size=None, source='system'): if n == 0: return random - return np.asarray(randoms).reshape(size) \ No newline at end of file + return np.asarray(randoms).reshape(size) diff --git a/_randomgen/randomgen/examples/cython/extending.pyx b/numpy/random/randomgen/examples/cython/extending.pyx similarity index 93% rename from _randomgen/randomgen/examples/cython/extending.pyx rename to numpy/random/randomgen/examples/cython/extending.pyx index c387a13af4f3..b472312b41d8 100644 --- a/_randomgen/randomgen/examples/cython/extending.pyx +++ b/numpy/random/randomgen/examples/cython/extending.pyx @@ -1,13 +1,17 @@ +#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 libc.stdint cimport uint32_t -from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from randomgen.common cimport brng_t -from randomgen.xoroshiro128 import Xoroshiro128 + +from numpy.random.randomgen.common cimport brng_t +from numpy.random.randomgen import Xoroshiro128 np.import_array() + def uniform_mean(Py_ssize_t N): cdef Py_ssize_t i cdef brng_t *rng @@ -26,6 +30,7 @@ def uniform_mean(Py_ssize_t N): randoms = np.asarray(random_values) return randoms.mean() + cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, brng_t *rng): cdef uint32_t mask, delta, val mask = delta = ub - lb @@ -41,6 +46,7 @@ cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, brng_t *rng): return lb + val + @cython.boundscheck(False) @cython.wraparound(False) def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): diff --git a/numpy/random/randomgen/examples/cython/extending_distributions.pyx b/numpy/random/randomgen/examples/cython/extending_distributions.pyx new file mode 100644 index 000000000000..26d749b10c51 --- /dev/null +++ b/numpy/random/randomgen/examples/cython/extending_distributions.pyx @@ -0,0 +1,51 @@ +#cython: language_level=3 +import numpy as np +cimport numpy as np +cimport cython +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from numpy.random.randomgen.common cimport * +from numpy.random.randomgen.distributions cimport random_gauss_zig +from numpy.random.randomgen import Xoroshiro128 + + +@cython.boundscheck(False) +@cython.wraparound(False) +def normals_zig(Py_ssize_t n): + cdef Py_ssize_t i + cdef brng_t *rng + cdef const char *capsule_name = "BasicRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + 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 brng_t *rng + cdef const char *capsule_name = "BasicRNG" + cdef double[::1] random_values + + x = Xoroshiro128() + capsule = x.capsule + # Optional check that the capsule if from a Basic RNG + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + # Cast the pointer + rng = PyCapsule_GetPointer(capsule, capsule_name) + random_values = np.empty(n) + 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/_randomgen/randomgen/examples/cython/setup.py b/numpy/random/randomgen/examples/cython/setup.py similarity index 100% rename from _randomgen/randomgen/examples/cython/setup.py rename to numpy/random/randomgen/examples/cython/setup.py diff --git a/_randomgen/randomgen/examples/numba/extending.py b/numpy/random/randomgen/examples/numba/extending.py similarity index 97% rename from _randomgen/randomgen/examples/numba/extending.py rename to numpy/random/randomgen/examples/numba/extending.py index 4dafeb5c4d12..72e903b1f19a 100644 --- a/_randomgen/randomgen/examples/numba/extending.py +++ b/numpy/random/randomgen/examples/numba/extending.py @@ -26,7 +26,7 @@ def bounded_uint(lb, ub, state): return lb + val -bounded_uint(323, 2394691, s.value) +print(bounded_uint(323, 2394691, s.value)) @nb.jit(nopython=True) diff --git a/_randomgen/randomgen/examples/numba/extending_distributions.py b/numpy/random/randomgen/examples/numba/extending_distributions.py similarity index 100% rename from _randomgen/randomgen/examples/numba/extending_distributions.py rename to numpy/random/randomgen/examples/numba/extending_distributions.py diff --git a/_randomgen/randomgen/generator.pyx b/numpy/random/randomgen/generator.pyx similarity index 84% rename from _randomgen/randomgen/generator.pyx rename to numpy/random/randomgen/generator.pyx index 6a68a1905b5c..a244bca578d3 100644 --- a/_randomgen/randomgen/generator.pyx +++ b/numpy/random/randomgen/generator.pyx @@ -1,42 +1,24 @@ #!python #cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 -from __future__ import absolute_import - import operator import warnings from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from cpython cimport (Py_INCREF, PyComplex_RealAsDouble, - PyComplex_ImagAsDouble, PyComplex_FromDoubles, PyFloat_AsDouble) +from cpython cimport (Py_INCREF, PyFloat_AsDouble) from libc cimport string from libc.stdlib cimport malloc, free cimport numpy as np import numpy as np cimport cython -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -from randomgen.bounded_integers cimport * -from randomgen.common cimport * -from randomgen.distributions cimport * -from randomgen.xoroshiro128 import Xoroshiro128 -import randomgen.pickle +from .bounded_integers cimport * +from .bounded_integers import _randint_types +from .common cimport * +from .distributions cimport * +from .xoroshiro128 import Xoroshiro128 np.import_array() -_randint_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) - } cdef class RandomGenerator: """ @@ -76,13 +58,13 @@ cdef class RandomGenerator: Examples -------- - >>> from randomgen import RandomGenerator + >>> from np.random.randomgen import RandomGenerator >>> rg = RandomGenerator() >>> rg.standard_normal() Using a specific generator - >>> from randomgen import MT19937 + >>> from np.random.randomgen import MT19937 >>> rg = RandomGenerator(MT19937()) The generator is also directly available from basic RNGs @@ -107,7 +89,7 @@ cdef class RandomGenerator: raise ValueError("Invalid brng. The brng must be instantized.") self._brng = PyCapsule_GetPointer(capsule, name) self._binomial = malloc(sizeof(binomial_t)) - self.lock = Lock() + self.lock = brng.lock def __dealloc__(self): free(self._binomial) @@ -128,7 +110,8 @@ cdef class RandomGenerator: self.state = state def __reduce__(self): - return (randomgen.pickle.__generator_ctor, + from ._pickle import __generator_ctor + return (__generator_ctor, (self.state['brng'],), self.state) @@ -146,7 +129,7 @@ cdef class RandomGenerator: The best method to access seed is to directly use a basic RNG instance. This example demonstrates this best practice. - >>> from randomgen import RandomGenerator, PCG64 + >>> from numpy.random.randomgen import RandomGenerator, PCG64 >>> brng = PCG64(1234567891011) >>> rg = brng.generator >>> brng.seed(1110987654321) @@ -161,6 +144,7 @@ cdef class RandomGenerator: >>> rg = RandomGenerator(PCG64(1234567891011)) >>> rg.seed(1110987654321) + """ # TODO: Should this remain self._basicrng.seed(*args, **kwargs) @@ -181,6 +165,7 @@ cdef class RandomGenerator: ----- This is a trivial pass-through function. RandomGenerator does not directly contain or manipulate the basic RNG's state. + """ return self._basicrng.state @@ -188,122 +173,6 @@ cdef class RandomGenerator: def state(self, value): self._basicrng.state = value - def random_uintegers(self, size=None, int bits=64): - """ - random_uintegers(size=None, bits=64) - - Return random unsigned integers - - 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. - bits : int {32, 64} - Size of the unsigned integer to return, either 32 bit or 64 bit. - - Returns - ------- - out : uint or ndarray - Drawn samples. - - Notes - ----- - This method effectively exposes access to the raw underlying - pseudo-random number generator since these all produce unsigned - integers. In practice these are most useful for generating other - random numbers. - - These should not be used to produce bounded random numbers by - simple truncation. - """ - cdef np.npy_intp i, n - cdef np.ndarray array - cdef uint32_t* data32 - cdef uint64_t* data64 - if bits == 64: - if size is None: - with self.lock: - return self._brng.next_uint64(self._brng.state) - array = np.empty(size, np.uint64) - n = np.PyArray_SIZE(array) - data64 = np.PyArray_DATA(array) - with self.lock, nogil: - for i in range(n): - data64[i] = self._brng.next_uint64(self._brng.state) - elif bits == 32: - if size is None: - with self.lock: - return self._brng.next_uint32(self._brng.state) - array = np.empty(size, np.uint32) - n = np.PyArray_SIZE(array) - data32 = np.PyArray_DATA(array) - with self.lock, nogil: - for i in range(n): - data32[i] = self._brng.next_uint32(self._brng.state) - else: - raise ValueError('Unknown value of bits. Must be either 32 or 64.') - - return array - - def random_raw(self, size=None, output=True): - """ - random_raw(self, size=None) - - Return randoms as generated by the underlying PRNG - - 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. - """ - cdef np.ndarray randoms - cdef uint64_t *randoms_data - cdef Py_ssize_t i, n - - if not output: - if size is None: - with self.lock: - self._brng.next_raw(self._brng.state) - return None - n = np.asarray(size).sum() - with self.lock, nogil: - for i in range(n): - self._brng.next_raw(self._brng.state) - return None - - if size is None: - with self.lock: - return self._brng.next_raw(self._brng.state) - - randoms = np.empty(size, np.uint64) - randoms_data = np.PyArray_DATA(randoms) - n = np.PyArray_SIZE(randoms) - - with self.lock, nogil: - for i in range(n): - randoms_data[i] = self._brng.next_raw(self._brng.state) - return randoms - def random_sample(self, size=None, dtype=np.float64, out=None): """ random_sample(size=None, dtype='d', out=None) @@ -339,19 +208,20 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.generator.random_sample() + >>> np.random.random_sample() 0.47108547995356098 # random - >>> type(randomgen.generator.random_sample()) + >>> type(np.random.random_sample()) - >>> randomgen.generator.random_sample((5,)) + >>> np.random.random_sample((5,)) array([ 0.30220482, 0.86820401, 0.1654503 , 0.11659149, 0.54323428]) # random Three-by-two array of random numbers from [-5, 0): - >>> 5 * randomgen.random_sample((3, 2)) - 5 + >>> 5 * np.random.random_sample((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 @@ -405,7 +275,6 @@ cdef class RandomGenerator: b, 'b', CONS_POSITIVE, 0.0, '', CONS_NONE, None) - def exponential(self, scale=1.0, size=None): """ exponential(scale=1.0, size=None) @@ -494,7 +363,8 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = randomgen.generator.standard_exponential((3, 8000)) + >>> n = np.random.standard_exponential((3, 8000)) + """ key = np.dtype(dtype).name if key == 'float64': @@ -515,10 +385,9 @@ cdef class RandomGenerator: """ 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 ---------- @@ -540,16 +409,15 @@ cdef class RandomGenerator: Examples -------- - >>> rg = randomgen.RandomGenerator() # need a RandomGenerator object + >>> rg = np.random.randomgen.RandomGenerator() # need a RandomGenerator object >>> rg.tomaxint((2,2,2)) array([[[1170048599, 1600360186], # random [ 739731006, 1947757578]], [[1871712945, 752307660], [1601631370, 1479324245]]]) - >>> import sys - >>> sys.maxint + >>> np.iinfo(np.int).max 2147483647 - >>> rg.tomaxint((2,2,2)) < sys.maxint + >>> rg.tomaxint((2,2,2)) < np.iinfo(np.int).max array([[[ True, True], [ True, True]], [[ True, True], @@ -627,68 +495,69 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.generator.randint(2, size=10) - array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random - >>> randomgen.generator.randint(1, size=10) + >>> np.random.randint(2, size=10) + 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: - >>> randomgen.generator.randint(5, size=(2, 4)) - array([[4, 0, 2, 1], # random - [3, 2, 2, 0]]) + >>> np.random.randint(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 - >>> randomgen.generator.randint(1, [3, 5, 10]) - array([2, 2, 9]) + >>> np.random.randint(1, [3, 5, 10]) + array([2, 2, 9]) # random Generate a 1 by 3 array with 3 different lower bounds - >>> randomgen.generator.randint([1, 5, 7], 10) - array([9, 8, 7]) + >>> np.random.randint([1, 5, 7], 10) + array([9, 8, 7]) # random Generate a 2 by 4 array using broadcasting with dtype of uint8 - >>> randomgen.generator.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) + >>> np.random.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], - [ 1, 16, 9, 12]], dtype=uint8) + [ 1, 16, 9, 12]], dtype=uint8) # random References ---------- .. [1] Daniel Lemire., "Fast Random Integer Generation in an Interval", CoRR, Aug. 13, 2018, http://arxiv.org/abs/1805.10941. + """ if high is None: high = low low = 0 key = np.dtype(dtype).name - if not key in _randint_types: + if key not in _randint_types: raise TypeError('Unsupported dtype "%s" for randint' % key) if key == 'int32': - ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) if size is None and dtype in (np.bool, np.int, np.long): - if np.array(ret).shape == (): - return dtype(ret) + if np.array(ret).shape == (): + return dtype(ret) return ret def bytes(self, np.npy_intp length): @@ -709,14 +578,13 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.generator.bytes(10) + >>> np.random.bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] - @cython.wraparound(True) def choice(self, a, size=None, replace=True, p=None): """ @@ -764,33 +632,33 @@ cdef class RandomGenerator: -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> randomgen.generator.choice(5, 3) + >>> np.random.choice(5, 3) array([0, 3, 4]) # random - >>> #This is equivalent to randomgen.randint(0,5,3) + >>> #This is equivalent to np.random.randint(0,5,3) Generate a non-uniform random sample from np.arange(5) of size 3: - >>> randomgen.generator.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) + >>> np.random.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: - >>> randomgen.generator.choice(5, 3, replace=False) + >>> np.random.choice(5, 3, replace=False) array([3,1,0]) # random - >>> #This is equivalent to randomgen.permutation(np.arange(5))[:3] + >>> #This is equivalent to np.random.permutation(np.arange(5))[:3] Generate a non-uniform random sample from np.arange(5) of size 3 without replacement: - >>> randomgen.generator.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) + >>> np.random.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'] - >>> randomgen.generator.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) + >>> np.random.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random dtype='>> s = randomgen.generator.uniform(-1,0,1000) + >>> s = np.random.uniform(-1,0,1000) All values are within the given interval: @@ -980,6 +847,7 @@ cdef class RandomGenerator: >>> 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 @@ -1003,8 +871,10 @@ cdef class RandomGenerator: None) temp = np.subtract(ahigh, alow) - Py_INCREF(temp) # needed to get around Pyrex's automatic reference-counting - # rules because EnsureArray steals a reference + # needed to get around Pyrex's automatic reference-counting + # rules because EnsureArray steals a reference + Py_INCREF(temp) + arange = np.PyArray_EnsureArray(temp) if not np.all(np.isfinite(arange)): raise OverflowError('Range exceeds valid bounds') @@ -1033,7 +903,7 @@ cdef class RandomGenerator: 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. dtype : {str, dtype}, optional Desired dtype of the result, either 'd' (or 'float64') or 'f' @@ -1049,19 +919,13 @@ cdef class RandomGenerator: -------- random - Notes - ----- - This is a convenience function. If you want an interface that takes - a shape-tuple as the first argument, refer to randomgen.random_sample. - - ``dtype`` can only be changed using a keyword argument. - Examples -------- - >>> randomgen.generator.rand(3,2) + >>> np.random.rand(3,2) array([[ 0.14022471, 0.96360618], #random [ 0.37601032, 0.25528411], #random [ 0.49313049, 0.94909878]]) #random + """ if len(args) == 0: return self.random_sample(dtype=dtype) @@ -1086,13 +950,10 @@ cdef class RandomGenerator: distribution of mean 0 and variance 1. A single float randomly sampled from the distribution is returned if no argument is provided. - This is a convenience function. If you want an interface that takes a - tuple as the first argument, use `numpy.random.standard_normal` instead. - 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. dtype : {str, dtype}, optional Desired dtype of the result, either 'd' (or 'float64') or 'f' @@ -1109,17 +970,17 @@ cdef class RandomGenerator: See Also -------- standard_normal : Similar, but takes a tuple as its argument. - normal : Also accepts mu and sigma arguments + normal : Also accepts mu and sigma arguments. Notes ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use: - ``sigma * randomgen.randn(...) + mu`` + ``sigma * np.random.randn(...) + mu`` Examples -------- - >>> randomgen.generator.randn() + >>> np.random.randn() 2.1923875335537315 # random Two-by-four array of samples from N(3, 6.25): @@ -1138,11 +999,13 @@ cdef class RandomGenerator: """ random_integers(low, high=None, size=None) - Random integers of type np.int64 between `low` and `high`, inclusive. + Random integers of type np.int between `low` and `high`, inclusive. - Return random integers of type np.int64 from the "discrete uniform" + 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`]. + None (the default), then results are from [1, `low`]. The np.int + type translates to the C long integer type and its precision + is platform dependent. This function has been deprecated. Use randint instead. @@ -1179,15 +1042,15 @@ cdef class RandomGenerator: To sample from N evenly spaced floating-point numbers between a and b, use:: - a + (b - a) * (randomgen.random_integers(N) - 1) / (N - 1.) + a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) Examples -------- - >>> randomgen.generator.random_integers(5) + >>> np.random.random_integers(5) 4 # random - >>> type(randomgen.generator.random_integers(5)) + >>> type(np.random.random_integers(5)) - >>> randomgen.generator.random_integers(5, size=(3, 2)) + >>> np.random.random_integers(5, size=(3,2)) array([[5, 4], # random [3, 3], [4, 5]]) @@ -1196,13 +1059,13 @@ cdef class RandomGenerator: numbers between 0 and 2.5, inclusive (*i.e.*, from the set :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - >>> 2.5 * (randomgen.generator.random_integers(5, size=(5,)) - 1) / 4. + >>> 2.5 * (np.random.random_integers(5, size=(5,)) - 1) / 4. array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) # random Roll two six sided dice 1000 times and sum the results: - >>> d1 = randomgen.generator.random_integers(1, 6, 1000) - >>> d2 = randomgen.generator.random_integers(1, 6, 1000) + >>> d1 = np.random.random_integers(1, 6, 1000) + >>> d2 = np.random.random_integers(1, 6, 1000) >>> dsums = d1 + d2 Display results as a histogram: @@ -1221,8 +1084,9 @@ cdef class RandomGenerator: else: warnings.warn(("This function is deprecated. Please call " - "randint({low}, {high} + 1) instead".format( - low=low, high=high)), DeprecationWarning) + "randint({low}, {high} + 1)" + "instead".format(low=low, high=high)), + DeprecationWarning) return self.randint(low, high + 1, size=size, dtype='l') @@ -1298,7 +1162,6 @@ cdef class RandomGenerator: 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) @@ -1368,7 +1231,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = randomgen.generator.normal(mu, sigma, 1000) + >>> s = np.random.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1401,167 +1264,6 @@ cdef class RandomGenerator: 0.0, '', CONS_NONE, None) - def complex_normal(self, loc=0.0, gamma=1.0, relation=0.0, size=None): - """ - complex_normal(loc=0.0, gamma=1.0, relation=0.0, size=None) - - Draw random samples from a complex normal (Gaussian) distribution. - - Parameters - ---------- - loc : complex or array_like of complex - Mean of the distribution. - gamma : float, complex or array_like of float or complex - Variance of the distribution - relation : float, complex or array_like of float or complex - Relation between the two component normals - 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``, ``gamma`` and ``relation`` - are all scalars. Otherwise, - ``np.broadcast(loc, gamma, relation).size`` samples are drawn. - - Returns - ------- - out : ndarray or scalar - Drawn samples from the parameterized complex normal distribution. - - See Also - -------- - numpy.random.normal : random values from a real-valued normal - distribution - - Notes - ----- - **EXPERIMENTAL** Not part of official NumPy RandomState, may change until - formal release on PyPi. - - Complex normals are generated from a bivariate normal where the - variance of the real component is 0.5 Re(gamma + relation), the - variance of the imaginary component is 0.5 Re(gamma - relation), and - the covariance between the two is 0.5 Im(relation). The implied - covariance matrix must be positive semi-definite and so both variances - must be zero and the covariance must be weakly smaller than the - product of the two standard deviations. - - References - ---------- - .. [1] Wikipedia, "Complex normal distribution", - https://en.wikipedia.org/wiki/Complex_normal_distribution - .. [2] Leigh J. Halliwell, "Complex Random Variables" in "Casualty - Actuarial Society E-Forum", Fall 2015. - - Examples - -------- - Draw samples from the distribution: - - >>> s = randomgen.generator.complex_normal(size=1000) - """ - cdef np.ndarray ogamma, orelation, oloc, randoms, v_real, v_imag, rho - cdef double *randoms_data - cdef double fgamma_r, fgamma_i, frelation_r, frelation_i, frho, fvar_r , fvar_i, \ - floc_r, floc_i, f_real, f_imag, i_r_scale, r_scale, i_scale, f_rho - cdef np.npy_intp i, j, n, n2 - cdef np.broadcast it - - oloc = np.PyArray_FROM_OTF(loc, np.NPY_COMPLEX128, np.NPY_ALIGNED) - ogamma = np.PyArray_FROM_OTF(gamma, np.NPY_COMPLEX128, np.NPY_ALIGNED) - orelation = np.PyArray_FROM_OTF(relation, np.NPY_COMPLEX128, np.NPY_ALIGNED) - - if np.PyArray_NDIM(ogamma) == np.PyArray_NDIM(orelation) == np.PyArray_NDIM(oloc) == 0: - floc_r = PyComplex_RealAsDouble(loc) - floc_i = PyComplex_ImagAsDouble(loc) - fgamma_r = PyComplex_RealAsDouble(gamma) - fgamma_i = PyComplex_ImagAsDouble(gamma) - frelation_r = PyComplex_RealAsDouble(relation) - frelation_i = 0.5 * PyComplex_ImagAsDouble(relation) - - fvar_r = 0.5 * (fgamma_r + frelation_r) - fvar_i = 0.5 * (fgamma_r - frelation_r) - if fgamma_i != 0: - raise ValueError('Im(gamma) != 0') - if fvar_i < 0: - raise ValueError('Re(gamma - relation) < 0') - if fvar_r < 0: - raise ValueError('Re(gamma + relation) < 0') - f_rho = 0.0 - if fvar_i > 0 and fvar_r > 0: - f_rho = frelation_i / sqrt(fvar_i * fvar_r) - if f_rho > 1.0 or f_rho < -1.0: - raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation** 2)') - - if size is None: - f_real = random_gauss_zig(self._brng) - f_imag = random_gauss_zig(self._brng) - - compute_complex(&f_real, &f_imag, floc_r, floc_i, fvar_r, fvar_i, f_rho) - return PyComplex_FromDoubles(f_real, f_imag) - - randoms = np.empty(size, np.complex128) - randoms_data = np.PyArray_DATA(randoms) - n = np.PyArray_SIZE(randoms) - - i_r_scale = sqrt(1 - f_rho * f_rho) - r_scale = sqrt(fvar_r) - i_scale = sqrt(fvar_i) - j = 0 - with self.lock, nogil: - for i in range(n): - f_real = random_gauss_zig(self._brng) - f_imag = random_gauss_zig(self._brng) - randoms_data[j+1] = floc_i + i_scale * (f_rho * f_real + i_r_scale * f_imag) - randoms_data[j] = floc_r + r_scale * f_real - j += 2 - - return randoms - - gpc = ogamma + orelation - gmc = ogamma - orelation - v_real = (0.5 * np.real(gpc)) - if np.any(np.less(v_real, 0)): - raise ValueError('Re(gamma + relation) < 0') - v_imag = (0.5 * np.real(gmc)) - if np.any(np.less(v_imag, 0)): - raise ValueError('Re(gamma - relation) < 0') - if np.any(np.not_equal(np.imag(ogamma), 0)): - raise ValueError('Im(gamma) != 0') - - cov = 0.5 * np.imag(orelation) - rho = np.zeros_like(cov) - idx = (v_real.flat > 0) & (v_imag.flat > 0) - rho.flat[idx] = cov.flat[idx] / np.sqrt(v_real.flat[idx] * v_imag.flat[idx]) - if np.any(cov.flat[~idx] != 0) or np.any(np.abs(rho) > 1): - raise ValueError('Im(relation) ** 2 > Re(gamma ** 2 - relation ** 2)') - - if size is not None: - randoms = np.empty(size, np.complex128) - else: - it = np.PyArray_MultiIterNew4(oloc, v_real, v_imag, rho) - randoms = np.empty(it.shape, np.complex128) - - randoms_data = np.PyArray_DATA(randoms) - n = np.PyArray_SIZE(randoms) - - it = np.PyArray_MultiIterNew5(randoms, oloc, v_real, v_imag, rho) - with self.lock, nogil: - n2 = 2 * n # Avoid compiler noise for cast - for i in range(n2): - randoms_data[i] = random_gauss_zig(self._brng) - with nogil: - j = 0 - for i in range(n): - floc_r= (np.PyArray_MultiIter_DATA(it, 1))[0] - floc_i= (np.PyArray_MultiIter_DATA(it, 1))[1] - fvar_r = (np.PyArray_MultiIter_DATA(it, 2))[0] - fvar_i = (np.PyArray_MultiIter_DATA(it, 3))[0] - f_rho = (np.PyArray_MultiIter_DATA(it, 4))[0] - compute_complex(&randoms_data[j], &randoms_data[j+1], floc_r, floc_i, fvar_r, fvar_i, f_rho) - j += 2 - np.PyArray_MultiIter_NEXT(it) - - return randoms - def standard_gamma(self, shape, size=None, dtype=np.float64, out=None): """ standard_gamma(shape, size=None, dtype='d', out=None) @@ -1625,7 +1327,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = randomgen.generator.standard_gamma(shape, 1000000) + >>> s = np.random.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1637,6 +1339,7 @@ cdef class RandomGenerator: ... (sps.gamma(shape) * scale**shape)) >>> plt.plot(bins, y, linewidth=2, color='r') >>> plt.show() + """ cdef void *func key = np.dtype(dtype).name @@ -1711,8 +1414,8 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> shape, scale = 2., 2. # mean and dispersion - >>> s = randomgen.generator.gamma(shape, scale, 1000) + >>> shape, scale = 2., 2. # mean=4, std=2*sqrt(2) + >>> s = np.random.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1739,7 +1442,7 @@ cdef class RandomGenerator: 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 @@ -1749,10 +1452,10 @@ cdef class RandomGenerator: Parameters ---------- - dfnum : int or array_like of ints - Degrees of freedom in numerator. Must be non-negative. - dfden : int or array_like of ints - Degrees of freedom in denominator. Must be non-negative. + 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), @@ -1802,7 +1505,7 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = randomgen.generator.f(dfnum, dfden, 1000) + >>> s = np.random.f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : @@ -1832,12 +1535,16 @@ cdef class RandomGenerator: Parameters ---------- - dfnum : int or array_like of ints - Parameter, should be > 1. - dfden : int or array_like of ints - Parameter, should be > 1. + 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 - Parameter, should be >= 0. + 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), @@ -1877,9 +1584,9 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = randomgen.generator.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = randomgen.generator.f(dfnum, dfden, 1000000) + >>> c_vals = np.random.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]) @@ -1905,8 +1612,8 @@ cdef class RandomGenerator: Parameters ---------- - df : int or array_like of ints - Number of degrees of freedom. + 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), @@ -1951,7 +1658,7 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.generator.chisquare(2,4) + >>> np.random.chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ @@ -1966,16 +1673,18 @@ cdef class RandomGenerator: 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 : int or array_like of ints - Degrees of freedom, should be > 0 as of NumPy 1.10.0, - should be > 1 for earlier versions. + 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, 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), @@ -1994,21 +1703,21 @@ cdef class RandomGenerator: .. 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. References ---------- - .. [1] Wikipedia, "Noncentral chi-square distribution" - https://en.wikipedia.org/wiki/Noncentral_chi-square_distribution + .. [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 >>> import matplotlib.pyplot as plt - >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -2016,9 +1725,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(np.random.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(randomgen.generator.chisquare(3, 100000), + >>> values2 = plt.hist(np.random.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -2027,7 +1736,7 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(randomgen.generator.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -2081,7 +1790,7 @@ cdef class RandomGenerator: ---------- .. [1] NIST/SEMATECH e-Handbook of Statistical Methods, "Cauchy Distribution", - http://www.itl.nist.gov/div898/handbook/eda/section3/eda3663.htm + 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 @@ -2092,9 +1801,9 @@ cdef class RandomGenerator: -------- Draw samples and plot the distribution: - >>> s = randomgen.generator.standard_cauchy(1000000) - >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well >>> import matplotlib.pyplot as plt + >>> s = np.random.standard_cauchy(1000000) + >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well >>> plt.hist(s, bins=100) >>> plt.show() @@ -2115,8 +1824,8 @@ cdef class RandomGenerator: Parameters ---------- - df : int or array_like of ints - Degrees of freedom, should be > 0. + 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), @@ -2166,7 +1875,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = randomgen.generator.standard_t(10, size=100000) + >>> s = np.random.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -2260,7 +1969,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = randomgen.generator.vonmises(mu, kappa, 1000) + >>> s = np.random.vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -2306,7 +2015,7 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Shape of the distribution. All values must be positive. + 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), @@ -2360,7 +2069,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (randomgen.generator.pareto(a, 1000) + 1) * m + >>> s = (np.random.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2453,7 +2162,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = randomgen.generator.weibull(a, 1000) + >>> s = np.random.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2463,7 +2172,7 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(randomgen.generator.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(np.random.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) @@ -2487,7 +2196,7 @@ cdef class RandomGenerator: Parameters ---------- a : float or array_like of floats - Parameter of the distribution. Must be positive. + 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), @@ -2525,7 +2234,7 @@ cdef class RandomGenerator: Dataplot Reference Manual, Volume 2: Let Subcommands and Library Functions", National Institute of Standards and Technology Handbook Series, June 2003. - http://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf + https://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/powpdf.pdf Examples -------- @@ -2533,7 +2242,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = randomgen.generator.power(a, samples) + >>> s = np.random.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2549,20 +2258,20 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats - >>> rvs = randomgen.generator.power(5, 1000000) - >>> rvsp = randomgen.generator.pareto(5, 1000000) + >>> rvs = np.random.power(5, 1000000) + >>> rvsp = np.random.pareto(5, 1000000) >>> xx = np.linspace(0,1,100) >>> powpdf = stats.powerlaw.pdf(xx,5) >>> plt.figure() >>> plt.hist(rvs, bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('randomgen.generator.power(5)') + >>> plt.title('np.random.power(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('inverse of 1 + randomgen.generator.pareto(5)') + >>> plt.title('inverse of 1 + np.random.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) @@ -2592,8 +2301,8 @@ cdef class RandomGenerator: 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. + :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), @@ -2637,7 +2346,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = randomgen.generator.laplace(loc, scale, 1000) + >>> s = np.random.laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2675,8 +2384,8 @@ cdef class RandomGenerator: 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. + 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), @@ -2740,7 +2449,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = randomgen.generator.gumbel(mu, beta, 1000) + >>> s = np.random.gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2758,7 +2467,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = randomgen.generator.normal(mu, beta, 1000) + ... a = np.random.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, density=True) @@ -2792,7 +2501,7 @@ cdef class RandomGenerator: 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 >= 0. + 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 @@ -2840,7 +2549,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = randomgen.generator.logistic(loc, scale, 10000) + >>> s = np.random.logistic(loc, scale, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s, bins=50) @@ -2848,8 +2557,8 @@ cdef class RandomGenerator: >>> def logist(x, loc, scale): ... return np.exp((loc-x)/scale)/(scale*(1+np.exp((loc-x)/scale))**2) - >>> scale = logist(bins, loc, scale).max() - >>> plt.plot(bins, logist(bins, loc, scale)*count.max()/scale) + >>> lgst_val = logist(bins, loc, scale) + >>> plt.plot(bins, lgst_val * count.max() / lgst_val.max()) >>> plt.show() """ @@ -2923,7 +2632,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = randomgen.generator.lognormal(mu, sigma, 1000) + >>> s = np.random.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2947,7 +2656,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + randomgen.generator.randn(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 @@ -3015,7 +2724,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> from matplotlib.pyplot import hist - >>> values = hist(randomgen.generator.rayleigh(3, 100000), bins=200, density=True) + >>> values = hist(np.random.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 @@ -3023,7 +2732,7 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = randomgen.generator.rayleigh(modevalue, 1000000) + >>> s = np.random.rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: @@ -3087,15 +2796,15 @@ cdef class RandomGenerator: .. [2] Chhikara, Raj S., and Folks, J. Leroy, "The Inverse Gaussian Distribution: Theory : Methodology, and Applications", CRC Press, 1988. - .. [3] Wikipedia, "Wald distribution" - https://en.wikipedia.org/wiki/Wald_distribution + .. [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(randomgen.generator.wald(3, 2, 100000), bins=200, density=True) + >>> h = plt.hist(np.random.wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ @@ -3122,9 +2831,9 @@ cdef class RandomGenerator: 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), @@ -3162,7 +2871,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(randomgen.generator.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(np.random.triangular(-3, 0, 8, 100000), bins=200, ... density=True) >>> plt.show() @@ -3275,7 +2984,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = randomgen.generator.binomial(n, p, 1000) + >>> s = np.random.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 @@ -3285,8 +2994,9 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(randomgen.generator.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(np.random.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. + """ # Uses a custom implementation since self._binomial is required @@ -3304,7 +3014,7 @@ cdef class RandomGenerator: 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_NOTNAN) + 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.empty(size, np.int64) @@ -3328,7 +3038,7 @@ cdef class RandomGenerator: _dp = PyFloat_AsDouble(p) _in = n - check_constraint(_dp, 'p', CONS_BOUNDED_0_1_NOTNAN) + check_constraint(_dp, 'p', CONS_BOUNDED_0_1) check_constraint(_in, 'n', CONS_NON_NEGATIVE) if size is None: @@ -3337,7 +3047,7 @@ cdef class RandomGenerator: randoms = np.empty(size, np.int64) cnt = np.PyArray_SIZE(randoms) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) with self.lock, nogil: for i in range(cnt): @@ -3346,7 +3056,6 @@ cdef class RandomGenerator: return randoms - def negative_binomial(self, n, p, size=None): """ negative_binomial(n, p, size=None) @@ -3354,14 +3063,13 @@ cdef class RandomGenerator: 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 @@ -3379,14 +3087,17 @@ cdef class RandomGenerator: 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 @@ -3410,16 +3121,16 @@ cdef class RandomGenerator: for each successive well, that is what is the probability of a single success after drilling 5 wells, after 6 wells, etc.? - >>> s = randomgen.generator.negative_binomial(1, 0.9, 100000) + >>> s = np.random.negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): # doctest: +SKIP ... probability = sum(s= 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 @@ -3474,7 +3185,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> import numpy as np - >>> s = randomgen.generator.poisson(5, 10000) + >>> s = np.random.poisson(5, 10000) Display histogram of the sample: @@ -3484,13 +3195,13 @@ cdef class RandomGenerator: Draw each 100 values for lambda 100 and 500: - >>> s = randomgen.generator.poisson(lam=(100., 500.), size=(100, 2)) + >>> s = np.random.poisson(lam=(100., 500.), size=(100, 2)) """ return disc(&random_poisson, self._brng, size, self.lock, 1, 0, - lam, 'lam', CONS_POISSON, - 0.0, '', CONS_NONE, - 0.0, '', CONS_NONE) + lam, 'lam', CONS_POISSON, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE) def zipf(self, a, size=None): """ @@ -3549,7 +3260,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 2. # parameter - >>> s = randomgen.generator.zipf(a, 1000) + >>> s = np.random.zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3567,9 +3278,9 @@ cdef class RandomGenerator: """ return disc(&random_zipf, self._brng, size, self.lock, 1, 0, - a, 'a', CONS_GT_1, - 0.0, '', CONS_NONE, - 0.0, '', CONS_NONE) + a, 'a', CONS_GT_1, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE) def geometric(self, p, size=None): """ @@ -3609,7 +3320,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = randomgen.generator.geometric(p=0.35, size=10000) + >>> z = np.random.geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3618,9 +3329,9 @@ cdef class RandomGenerator: """ return disc(&random_geometric, self._brng, size, self.lock, 1, 0, - p, 'p', CONS_BOUNDED_GT_0_1, - 0.0, '', CONS_NONE, - 0.0, '', CONS_NONE) + p, 'p', CONS_BOUNDED_GT_0_1, + 0.0, '', CONS_NONE, + 0.0, '', CONS_NONE) def hypergeometric(self, ngood, nbad, nsample, size=None): """ @@ -3629,9 +3340,9 @@ cdef class RandomGenerator: 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 ---------- @@ -3645,14 +3356,16 @@ cdef class RandomGenerator: 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 -------- @@ -3667,11 +3380,11 @@ cdef class RandomGenerator: 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. @@ -3697,7 +3410,7 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = randomgen.generator.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = np.random.hypergeometric(ngood, nbad, nsamp, 1000) >>> from matplotlib.pyplot import hist >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3706,7 +3419,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = randomgen.generator.hypergeometric(15, 15, 15, 100000) + >>> s = np.random.hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3725,12 +3438,6 @@ cdef class RandomGenerator: lnbad = nbad lnsample = nsample - if lngood < 0: - raise ValueError("ngood < 0") - if lnbad < 0: - raise ValueError("nbad < 0") - if lnsample < 1: - raise ValueError("nsample < 1") if lngood + lnbad < lnsample: raise ValueError("ngood + nbad < nsample") return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, @@ -3738,11 +3445,11 @@ cdef class RandomGenerator: lnbad, 'nbad', CONS_NON_NEGATIVE, lnsample, 'nsample', CONS_GTE_1) - if np.any(np.less(np.add(ongood, onbad),onsample)): + if np.any(np.less(np.add(ongood, onbad), onsample)): raise ValueError("ngood + nbad < nsample") return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, ongood, 'ngood', CONS_NON_NEGATIVE, - onbad, nbad, CONS_NON_NEGATIVE, + onbad, 'nbad', CONS_NON_NEGATIVE, onsample, 'nsample', CONS_GTE_1) def logseries(self, p, size=None): @@ -3776,7 +3483,7 @@ cdef class RandomGenerator: Notes ----- - The probability density for the Log Series distribution is + The probability mass function for the Log Series distribution is .. math:: P(k) = \\frac{-p^k}{k \\ln(1-p)}, @@ -3807,7 +3514,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = randomgen.generator.logseries(a, 10000) + >>> s = np.random.logseries(a, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s) @@ -3815,8 +3522,8 @@ cdef class RandomGenerator: >>> 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.plot(bins, logseries(bins, a) * count.max()/ + ... logseries(bins, a).max(), 'r') >>> plt.show() """ @@ -3829,7 +3536,7 @@ cdef class RandomGenerator: def multivariate_normal(self, mean, cov, size=None, check_valid='warn', tol=1e-8): """ - 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. @@ -3856,6 +3563,7 @@ cdef class RandomGenerator: 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 ------- @@ -3896,7 +3604,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = randomgen.generator.multivariate_normal(mean, cov, 5000).T + >>> x, y = np.random.multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3916,7 +3624,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = randomgen.generator.multivariate_normal(mean, cov, (3, 3)) + >>> x = np.random.multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3924,7 +3632,7 @@ cdef class RandomGenerator: standard deviation: >>> list((x[0,0,:] - mean) < 0.6) - [True, True] + [True, True] # random """ from numpy.dual import svd @@ -3940,11 +3648,11 @@ cdef class RandomGenerator: shape = size if len(mean.shape) != 1: - raise ValueError("mean must be 1 dimensional") + 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") + 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") + 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 @@ -3968,6 +3676,8 @@ cdef class RandomGenerator: # 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': @@ -3993,7 +3703,7 @@ cdef class RandomGenerator: 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 @@ -4007,7 +3717,7 @@ cdef class RandomGenerator: 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 @@ -4028,24 +3738,24 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> randomgen.generator.multinomial(20, [1/6.]*6, size=1) - array([[4, 1, 7, 5, 2, 1]]) + >>> np.random.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: - >>> randomgen.generator.multinomial(20, [1/6.]*6, size=2) + >>> np.random.multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], - [2, 4, 3, 4, 0, 7]]) + [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. A loaded die is more likely to land on number 6: - >>> randomgen.generator.multinomial(100, [1/7.]*5 + [2/7.]) - array([11, 16, 14, 17, 16, 26]) # random + >>> np.random.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 @@ -4053,12 +3763,12 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> randomgen.generator.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT - array([38, 62]) # random + >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + array([38, 62]) # random not like: - >>> randomgen.generator.multinomial(100, [1.0, 2.0]) # WRONG + >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG array([100, 0]) """ @@ -4175,7 +3885,7 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = randomgen.generator.dirichlet((10, 5, 3), 20).transpose() + >>> s = np.random.dirichlet((10, 5, 3), 20).transpose() >>> import matplotlib.pyplot as plt >>> plt.barh(range(20), s[0]) @@ -4185,39 +3895,36 @@ cdef class RandomGenerator: """ - #================= + # ================= # 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 - cdef np.npy_intp totsize - cdef np.ndarray alpha_arr, val_arr - cdef double *alpha_data - cdef double *val_data - cdef np.npy_intp i, j - cdef double acc, invacc - - k = len(alpha) - alpha_arr = np.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) + # ================= + # 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.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) if np.any(np.less_equal(alpha_arr, 0)): raise ValueError('alpha <= 0') - alpha_data = np.PyArray_DATA(alpha_arr) + alpha_data = np.PyArray_DATA(alpha_arr) if size is None: shape = (k,) @@ -4227,7 +3934,7 @@ cdef class RandomGenerator: except: shape = tuple(size) + (k,) - diric = np.zeros(shape, np.float64) + diric = np.zeros(shape, np.float64) val_arr = diric val_data= np.PyArray_DATA(val_arr) @@ -4239,10 +3946,10 @@ cdef class RandomGenerator: for j in range(k): val_data[i+j] = random_standard_gamma_zig(self._brng, alpha_data[j]) - acc = acc + val_data[i + j] - invacc = 1/acc + acc = acc + val_data[i + j] + invacc = 1/acc for j in range(k): - val_data[i + j] = val_data[i + j] * invacc + val_data[i + j] = val_data[i + j] * invacc i = i + k return diric @@ -4270,14 +3977,14 @@ cdef class RandomGenerator: Examples -------- >>> arr = np.arange(10) - >>> randomgen.shuffle(arr) + >>> np.random.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)) - >>> randomgen.generator.shuffle(arr) + >>> np.random.shuffle(arr) >>> arr array([[3, 4, 5], # random [6, 7, 8], @@ -4300,7 +4007,7 @@ cdef class RandomGenerator: # 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 = buf.ctypes.data with self.lock: # We trick gcc into providing a specialized implementation for @@ -4311,11 +4018,13 @@ cdef class RandomGenerator: 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 = random_interval(self._brng, i) - if i == j : continue # i == j is not needed and memcpy is undefined. + if i == j: + # i == j is not needed and memcpy is undefined. + continue buf[...] = x[j] x[j] = x[i] x[i] = buf @@ -4358,14 +4067,14 @@ cdef class RandomGenerator: Examples -------- - >>> randomgen.generator.permutation(10) + >>> np.random.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random - >>> randomgen.generator.permutation([1, 4, 9, 12, 15]) + >>> np.random.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) # random >>> arr = np.arange(9).reshape((3, 3)) - >>> randomgen.generator.permutation(arr) + >>> np.random.permutation(arr) array([[6, 7, 8], # random [0, 1, 2], [3, 4, 5]]) @@ -4398,7 +4107,6 @@ binomial = _random_generator.binomial bytes = _random_generator.bytes chisquare = _random_generator.chisquare choice = _random_generator.choice -complex_normal = _random_generator.complex_normal dirichlet = _random_generator.dirichlet exponential = _random_generator.exponential f = _random_generator.f @@ -4424,9 +4132,7 @@ rand = _random_generator.rand randint = _random_generator.randint randn = _random_generator.randn random_integers = _random_generator.random_integers -random_raw = _random_generator.random_raw random_sample = _random_generator.random_sample -random_uintegers = _random_generator.random_uintegers rayleigh = _random_generator.rayleigh shuffle = _random_generator.shuffle standard_cauchy = _random_generator.standard_cauchy @@ -4440,4 +4146,4 @@ uniform = _random_generator.uniform vonmises = _random_generator.vonmises wald = _random_generator.wald weibull = _random_generator.weibull -zipf = _random_generator.zipf \ No newline at end of file +zipf = _random_generator.zipf diff --git a/numpy/random/randomgen/legacy/__init__.py b/numpy/random/randomgen/legacy/__init__.py new file mode 100644 index 000000000000..9ce1f665dd15 --- /dev/null +++ b/numpy/random/randomgen/legacy/__init__.py @@ -0,0 +1,3 @@ +from ..mtrand import RandomState as LegacyGenerator + +__all__ = ['LegacyGenerator'] diff --git a/_randomgen/randomgen/legacy/legacy_distributions.pxd b/numpy/random/randomgen/legacy/legacy_distributions.pxd similarity index 95% rename from _randomgen/randomgen/legacy/legacy_distributions.pxd rename to numpy/random/randomgen/legacy/legacy_distributions.pxd index e2157f70605f..bc00994dbacb 100644 --- a/_randomgen/randomgen/legacy/legacy_distributions.pxd +++ b/numpy/random/randomgen/legacy/legacy_distributions.pxd @@ -3,16 +3,16 @@ from libc.stdint cimport uint64_t import numpy as np -cimport numpy as np +cimport numpy as np -from randomgen.distributions cimport brng_t +from ..distributions cimport brng_t cdef extern from "../src/legacy/distributions-boxmuller.h": struct aug_brng: brng_t *basicrng int has_gauss - double gauss + double gauss ctypedef aug_brng aug_brng_t diff --git a/_randomgen/randomgen/mt19937.pyx b/numpy/random/randomgen/mt19937.pyx similarity index 76% rename from _randomgen/randomgen/mt19937.pyx rename to numpy/random/randomgen/mt19937.pyx index c88dd02b9686..306ce23e2c40 100644 --- a/_randomgen/randomgen/mt19937.pyx +++ b/numpy/random/randomgen/mt19937.pyx @@ -1,18 +1,19 @@ -from __future__ import absolute_import - import operator from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy np.import_array() @@ -97,8 +98,8 @@ cdef class MT19937: generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen.entropy import random_entropy - >>> from randomgen import RandomGenerator, MT19937 + >>> from numpy.random.randomgen.entropy import random_entropy + >>> from numpy.random.randomgen import RandomGenerator, MT19937 >>> seed = random_entropy() >>> rs = [RandomGenerator(MT19937(seed) for _ in range(10)] # Advance rs[i] by i jumps @@ -122,11 +123,13 @@ cdef class MT19937: cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(mt19937_state)) self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &mt19937_uint64 @@ -153,45 +156,44 @@ cdef class MT19937: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) - def __random_integer(self, bits=64): + def random_raw(self, size=None, output=True): """ - 64-bit Random Integers from the PRNG + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG Parameters ---------- - bits : {32, 64} - Number of random bits to return + 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 ------- - rv : int - Next random value + out : uint or ndarray + Drawn samples. Notes ----- - Testing only + 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. """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') + return random_raw(self._brng, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -231,7 +233,12 @@ cdef class MT19937: raise ValueError("Seed must be between 0 and 2**32 - 1") mt19937_seed(self.rng_state, seed) except TypeError: - obj = np.asarray(seed).astype(np.int64, casting='safe') + 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') @@ -274,16 +281,15 @@ cdef class MT19937: key[i] = self.rng_state.key[i] return {'brng': self.__class__.__name__, - 'state': {'key':key, 'pos': self.rng_state.pos}} + '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') + if value[0] != 'MT19937' or len(value) not in (3, 5): + raise ValueError('state is not a legacy MT19937 state') value ={'brng': 'MT19937', - 'state':{'key': value[1], 'pos': value[2]}} - + 'state': {'key': value[1], 'pos': value[2]}} if not isinstance(value, dict): raise TypeError('state must be a dict') @@ -299,12 +305,12 @@ cdef class MT19937: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -313,25 +319,10 @@ cdef class MT19937: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&mt19937_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&mt19937_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&mt19937_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -352,19 +343,8 @@ cdef class MT19937: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -373,10 +353,10 @@ cdef class MT19937: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/numpy/random/randomgen/mtrand.pyx b/numpy/random/randomgen/mtrand.pyx new file mode 100644 index 000000000000..b5d6ff9bc9b9 --- /dev/null +++ b/numpy/random/randomgen/mtrand.pyx @@ -0,0 +1,4223 @@ +#!python +#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3 +import operator +import warnings + +from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer +from cpython cimport (Py_INCREF, PyFloat_AsDouble) +from libc cimport string +from libc.stdlib cimport malloc, free +cimport numpy as np +import numpy as np +cimport cython + +from .bounded_integers cimport * +from .bounded_integers import _randint_types +from .common cimport * +from .distributions cimport * +from .legacy.legacy_distributions cimport * +from .mt19937 import MT19937 as _MT19937 + +np.import_array() + +cdef class RandomState: + """ + RandomState(brng=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. + + Parameters + ---------- + brng : {None, int, array_like, BasicRNG}, optional + Random seed used to initialize the pseudo-random number generator or + an instantized BasicRNG. If an integer or array, used as a seed for + the MT19937 BasicRNG. 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` + BasicRNG is initialized by reading data from ``/dev/urandom`` + (or the Windows analogue) if available or seed from the clock + otherwise. + + Notes + ----- + The Python stdlib module "random" also contains a Mersenne Twister + pseudo-random number generator with a number of methods that are similar + to the ones available in `RandomState`. `RandomState`, besides being + NumPy-aware, has the advantage that it provides a much larger number + of probability distributions to choose from. + + """ + cdef public object _basicrng + cdef brng_t *_brng + cdef aug_brng_t *_aug_state + cdef binomial_t *_binomial + cdef object lock + poisson_lam_max = POISSON_LAM_MAX + + def __init__(self, brng=None): + if brng is None: + brng = _MT19937() + elif not hasattr(brng, 'capsule'): + brng = _MT19937(brng) + + self._basicrng = brng + capsule = brng.capsule + cdef const char *name = "BasicRNG" + if not PyCapsule_IsValid(capsule, name): + raise ValueError("Invalid brng. The brng must be instantized.") + self._brng = PyCapsule_GetPointer(capsule, name) + self._aug_state = malloc(sizeof(aug_brng_t)) + self._aug_state.basicrng = self._brng + self._binomial = malloc(sizeof(binomial_t)) + self._reset_gauss() + self.lock = brng.lock + + def __dealloc__(self): + free(self._binomial) + free(self._aug_state) + + def __repr__(self): + return self.__str__() + ' at 0x{:X}'.format(id(self)) + + def __str__(self): + _str = self.__class__.__name__ + _str += '(' + self._basicrng.__class__.__name__ + ')' + return _str + + # Pickling support: + def __getstate__(self): + return self.get_state(legacy=False) + + def __setstate__(self, state): + self.set_state(state) + + def __reduce__(self): + state = self.get_state(legacy=False) + from ._pickle import __randomstate_ctor + return (__randomstate_ctor, + (state['brng'],), + state) + + cdef _reset_gauss(self): + self._aug_state.has_gauss = 0 + self._aug_state.gauss = 0.0 + + def seed(self, *args, **kwargs): + """ + seed(self, *args, **kwargs) + + Reseed the basic RNG. + + Parameters depend on the basic RNG used. + + Notes + ----- + Arguments are directly passed to the basic RNG. This is a convenience + function. + + The best method to access seed is to directly use a basic RNG instance. + This example demonstrates this best practice. + + >>> from numpy.random.randomgen import MT19937 + >>> from numpy.random import RandomState + >>> brng = MT19937(123456789) + >>> rs = RandomState(brng) + >>> brng.seed(987654321) + + These best practice examples are equivalent to + + >>> rs = RandomState(MT19937()) + >>> rs.seed(987654321) + """ + self._basicrng.seed(*args, **kwargs) + self._reset_gauss() + + def get_state(self, legacy=True): + """ + get_state() + + Return a tuple representing the internal state of the generator. + + For more details, see `set_state`. + + Returns + ------- + out : {tuple(str, ndarray of 624 uints, int, int, float), dict} + The returned tuple has the following items: + + 1. the string 'MT19937'. + 2. a 1-D array of 624 unsigned integer keys. + 3. an integer ``pos``. + 4. an integer ``has_gauss``. + 5. a float ``cached_gaussian``. + + If `legacy` is False, or the basic RNG is not NT19937, then + state is returned as a dictionary. + + legacy : bool + Flag indicating the return a legacy tuple state when the basic RNG + is MT19937. + + See Also + -------- + set_state + + Notes + ----- + `set_state` and `get_state` are not needed to work with any of the + random distributions in NumPy. If the internal state is manually altered, + the user should know exactly what he/she is doing. + + """ + st = self._basicrng.state + if st['brng'] != 'MT19937' and legacy: + warnings.warn('get_state and legacy can only be used with the ' + 'MT19937 basic RNG. 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['brng'], st['state']['key'], st['state']['pos'], + st['has_gauss'], st['gauss']) + return st + + def set_state(self, state): + """ + set_state(state) + + 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 + Basic RNG 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), dict} + The `state` tuple has the following items: + + 1. the string 'MT19937', specifying the Mersenne Twister algorithm. + 2. a 1-D array of 624 unsigned integers ``keys``. + 3. an integer ``pos``. + 4. an integer ``has_gauss``. + 5. a float ``cached_gaussian``. + + If state is a dictionary, it is directly set using the BasicRNGs + `state` property. + + Returns + ------- + out : None + Returns 'None' on success. + + See Also + -------- + get_state + + Notes + ----- + `set_state` and `get_state` are not needed to work with any of the + random distributions in NumPy. If the internal state is manually altered, + the user should know exactly what he/she is doing. + + For backwards compatibility, the form (str, array of 624 uints, int) is + also accepted although it is missing some information about the cached + Gaussian value: ``state = ('MT19937', keys, pos)``. + + References + ---------- + .. [1] M. Matsumoto and T. Nishimura, "Mersenne Twister: A + 623-dimensionally equidistributed uniform pseudorandom number + generator," *ACM Trans. on Modeling and Computer Simulation*, + Vol. 8, No. 1, pp. 3-30, Jan. 1998. + + """ + if isinstance(state, dict): + if 'brng' not in state or 'state' not in state: + raise ValueError('state dictionary is not valid.') + st = state + else: + 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 = {'brng': 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._basicrng.state = st + + def random_sample(self, size=None): + """ + random_sample(size=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_sample` by `(b-a)` and add `a`:: + + (b - a) * random_sample() + 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. + + 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 + -------- + >>> np.random.random_sample() + 0.47108547995356098 # random + >>> type(np.random.random_sample()) + + >>> np.random.random_sample((5,)) + 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], # random + [-2.99091858, -0.79479508], + [-1.23204345, -1.75224494]]) + + """ + cdef double temp + return double_fill(&random_double_fill, self._brng, size, self.lock, None) + + 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) + + Return a sample of uniformly distributed random integers in the interval + [0, ``np.iinfo(np.int).max``]. The np.int type translates to the C long + integer type and its precision is platform dependent. + + 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 : ndarray + Drawn samples, with shape `size`. + + See Also + -------- + randint : Uniform sampling over a given half-open interval of integers. + random_integers : Uniform sampling over a given closed interval of + integers. + + Examples + -------- + >>> rs = np.random.RandomState() # need a RandomState object + >>> rs.tomaxint((2,2,2)) + array([[[1170048599, 1600360186], # random + [ 739731006, 1947757578]], + [[1871712945, 752307660], + [1601631370, 1479324245]]]) + >>> np.iinfo(np.int).max + 2147483647 + >>> rs.tomaxint((2,2,2)) < np.iinfo(np.int).max + array([[[ True, True], + [ True, True]], + [[ True, True], + [ True, True]]]) + + """ + 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._brng) + + randoms = np.empty(size, dtype=np.int64) + randoms_data = 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._brng) + return randoms + + def randint(self, low, high=None, size=None, dtype=int): + """ + randint(low, high=None, size=None, dtype='l') + + Return random integers from `low` (inclusive) to `high` (exclusive). + + Return random integers from the "discrete uniform" distribution of + the specified dtype in the "half-open" interval [`low`, `high`). If + `high` is None (the default), then results are from [0, `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 one above the + *highest* such integer). + 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 : 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'. + + .. versionadded:: 1.11.0 + + 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. + + See Also + -------- + 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. + + Examples + -------- + >>> np.random.randint(2, size=10) + 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], # 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) + """ + cdef bint use_masked=1 + + if high is None: + high = low + low = 0 + + key = np.dtype(dtype).name + if key not in _randint_types: + raise TypeError('Unsupported dtype "%s" for randint' % key) + + if key == 'int32': + ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) + elif key == 'int64': + ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) + elif key == 'int16': + ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) + elif key == 'int8': + ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) + elif key == 'uint64': + ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) + elif key == 'uint32': + ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) + elif key == 'uint16': + ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) + elif key == 'uint8': + ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) + elif key == 'bool': + ret = _rand_bool(low, high, size, use_masked, self._brng, 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.bytes(10) + ' eh\\x85\\x022SZ\\xbf\\xa4' #random + + """ + cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) + return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] + + @cython.wraparound(True) + def choice(self, a, size=None, replace=True, p=None): + """ + choice(a, size=None, replace=True, p=None) + + Generates a random sample from a given 1-D array + + .. 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) + 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. + 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. + + 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 + probabilities, if a and p have different lengths, or if + replace=False and the sample size is greater than the population + 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]) # 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]) # 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]) # 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]) # 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'], # random + dtype='np.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED) + pix = 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_sample(shape) + idx = cdf.searchsorted(uniform_samples, side='right') + idx = np.array(idx, copy=False) # searchsorted returns a scalar + 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'") + 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.rand(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: + idx = self.permutation(pop_size)[:size] + 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 + + return a[idx] + + 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 + -------- + randint : Discrete uniform distribution, yielding integers. + random_integers : Discrete uniform distribution over the closed + interval ``[low, high]``. + random_sample : Floats uniformly distributed over ``[0, 1)``. + random : Alias for `random_sample`. + rand : Convenience function that accepts dimensions as input, e.g., + ``rand(2,2)`` would generate a 2-by-2 array of floats, + uniformly distributed over ``[0, 1)``. + + 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.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.PyArray_FROM_OTF(low, np.NPY_DOUBLE, np.NPY_ALIGNED) + ahigh = 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._brng, 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.PyArray_EnsureArray(temp) + if not np.all(np.isfinite(arange)): + raise OverflowError('Range exceeds valid bounds') + return cont(&random_uniform, self._brng, size, self.lock, 2, + alow, '', CONS_NONE, + arange, '', CONS_NONE, + 0.0, '', CONS_NONE, + None) + + def rand(self, *args): + """ + rand(d0, d1, ..., dn) + + 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)``. + + Parameters + ---------- + d0, d1, ..., dn : int, optional + The dimensions of the returned array, must be non-negative. + If no argument is given a single Python float is returned. + + Returns + ------- + out : ndarray, shape ``(d0, d1, ..., dn)`` + Random values. + + See Also + -------- + random + + Examples + -------- + >>> np.random.rand(3,2) + array([[ 0.14022471, 0.96360618], #random + [ 0.37601032, 0.25528411], #random + [ 0.49313049, 0.94909878]]) #random + + """ + if len(args) == 0: + return self.random_sample() + else: + return self.random_sample(size=args) + + def randn(self, *args): + """ + randn(d0, d1, ..., dn) + + Return a sample (or samples) from the "standard normal" distribution. + + .. 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`. + + 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, must be non-negative. + If no argument is given a single Python float is returned. + + Returns + ------- + Z : ndarray or float + A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from + the standard normal distribution, or a single such float if + no parameters were supplied. + + See Also + -------- + standard_normal : Similar, but takes a tuple as its argument. + normal : Also accepts mu and sigma arguments. + + Notes + ----- + For random samples from :math:`N(\\mu, \\sigma^2)`, use: + + ``sigma * np.random.randn(...) + mu`` + + Examples + -------- + >>> np.random.randn() + 2.1923875335537315 # random + + Two-by-four array of samples from N(3, 6.25): + + >>> 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(size=args) + + def random_integers(self, low, high=None, size=None): + """ + random_integers(low, high=None, size=None) + + Random integers of type np.int between `low` and `high`, inclusive. + + 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 integer type and its precision + is platform dependent. + + This function has been deprecated. Use randint instead. + + .. deprecated:: 1.11.0 + + Parameters + ---------- + low : int + Lowest (signed) integer to be drawn from the distribution (unless + ``high=None``, in which case this parameter is the *highest* such + integer). + high : int, optional + If provided, the largest (signed) integer to be drawn from the + distribution (see above for behavior if ``high=None``). + size : int or tuple of ints, optional + Output shape. 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 : 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. + + See Also + -------- + randint : Similar to `random_integers`, only for the half-open + interval [`low`, `high`), and 0 is the lowest value if `high` is + omitted. + + Notes + ----- + To sample from N evenly spaced floating-point numbers between a and b, + use:: + + a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) + + Examples + -------- + >>> np.random.random_integers(5) + 4 # random + >>> type(np.random.random_integers(5)) + + >>> np.random.random_integers(5, size=(3,2)) + array([[5, 4], # random + [3, 3], + [4, 5]]) + + Choose five random numbers from the set of five evenly-spaced + numbers between 0 and 2.5, inclusive (*i.e.*, from the set + :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 ]) # random + + Roll two six sided dice 1000 times and sum the results: + + >>> d1 = np.random.random_integers(1, 6, 1000) + >>> d2 = np.random.random_integers(1, 6, 1000) + >>> dsums = d1 + d2 + + Display results as a histogram: + + >>> import matplotlib.pyplot as plt + >>> count, bins, ignored = plt.hist(dsums, 11, density=True) + >>> plt.show() + + """ + if high is None: + warnings.warn(("This function is deprecated. Please call " + "randint(1, {low} + 1) instead".format(low=low)), + DeprecationWarning) + high = low + low = 1 + + 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') + + # Complicated, continuous distributions: + def standard_normal(self, size=None): + """ + standard_normal(size=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. + + 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 * 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 + >>> 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 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): + """ + 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 + `numpy.random.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.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.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(&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): + """ + standard_gamma(shape, size=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. + + 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.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 + >>> count, bins, ignored = plt.hist(s, 50, density=True) + >>> y = bins**(shape-1) * ((np.exp(-bins/scale))/ \\ + ... (sps.gamma(shape) * scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + + """ + 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): + """ + 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.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 + >>> count, bins, ignored = plt.hist(s, 50, density=True) + >>> y = bins**(shape-1)*(np.exp(-bins/scale) / + ... (sps.gamma(shape)*scale**shape)) + >>> plt.plot(bins, y, linewidth=2, color='r') + >>> plt.show() + + """ + 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): + """ + 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.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(&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): + """ + 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. + + >>> dfnum = 3 # between group deg of freedom + >>> dfden = 20 # within groups degrees of freedom + >>> nonc = 3.0 + >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> NF = np.histogram(nc_vals, bins=50, density=True) + >>> c_vals = np.random.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(&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): + """ + 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.chisquare(2,4) + array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random + + """ + 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): + """ + 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 + + >>> import matplotlib.pyplot as plt + >>> values = plt.hist(np.random.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(np.random.noncentral_chisquare(3, .0000001, 100000), + ... bins=np.arange(0., 25, .1), density=True) + >>> values2 = plt.hist(np.random.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(np.random.noncentral_chisquare(3, 20, 100000), + ... bins=200, density=True) + >>> plt.show() + + """ + 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): + """ + 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.standard_cauchy(1000000) + >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well + >>> plt.hist(s, bins=100) + >>> plt.show() + + """ + 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): + """ + 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.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=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.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 + >>> 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') + >>> plt.show() + + """ + return cont(&random_vonmises, self._brng, 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.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(&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): + """ + 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: + + >>> a = 5. # shape + >>> s = np.random.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(np.random.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(&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): + """ + 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: + + >>> a = 5. # shape + >>> samples = 1000 + >>> s = np.random.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 + >>> rvs = np.random.power(5, 1000000) + >>> rvsp = np.random.pareto(5, 1000000) + >>> xx = np.linspace(0,1,100) + >>> powpdf = stats.powerlaw.pdf(xx,5) + + >>> plt.figure() + >>> plt.hist(rvs, bins=50, density=True) + >>> plt.plot(xx,powpdf,'r-') + >>> plt.title('np.random.power(5)') + + >>> plt.figure() + >>> plt.hist(1./(1.+rvsp), bins=50, density=True) + >>> plt.plot(xx,powpdf,'r-') + >>> 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.title('inverse of stats.pareto(5)') + + """ + 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): + """ + 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.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._brng, 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: + + >>> mu, beta = 0, 0.1 # location and scale + >>> s = np.random.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 = np.random.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._brng, 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.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._brng, 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: + + >>> mu, sigma = 3., 1. # mean and standard deviation + >>> s = np.random.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. + >>> b = [] + >>> for i in range(1000): + ... a = 10. + np.random.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(&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): + """ + 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 + >>> values = hist(np.random.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 = np.random.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._brng, 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.wald(3, 2, 100000), bins=200, density=True) + >>> plt.show() + + """ + 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): + """ + 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.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.PyArray_FROM_OTF(left, np.NPY_DOUBLE, np.NPY_ALIGNED) + omode = np.PyArray_FROM_OTF(mode, np.NPY_DOUBLE, np.NPY_ALIGNED) + oright = 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._brng, 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._brng, 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: + + >>> n, p = 10, .5 # number of trials, probability of each trial + >>> s = np.random.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(np.random.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.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED) + is_scalar = is_scalar and np.PyArray_NDIM(p_arr) == 0 + n_arr = 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.empty(size, np.int64) + else: + it = np.PyArray_MultiIterNew2(p_arr, n_arr) + randoms = np.empty(it.shape, np.int64) + + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] + _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._brng, _dp, _in, self._binomial) + + np.PyArray_MultiIter_NEXT(it) + + return randoms + + _dp = PyFloat_AsDouble(p) + _in = n + check_constraint(_dp, 'p', CONS_BOUNDED_0_1) + check_constraint(_in, 'n', CONS_NON_NEGATIVE) + + if size is None: + with self.lock: + return random_binomial(self._brng, _dp, _in, self._binomial) + + randoms = np.empty(size, np.int64) + cnt = np.PyArray_SIZE(randoms) + randoms_data = np.PyArray_DATA(randoms) + + with self.lock, nogil: + for i in range(cnt): + randoms_data[i] = random_binomial(self._brng, _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.negative_binomial(1, 0.1, 100000) + >>> for i in range(1, 11): # doctest: +SKIP + ... probability = sum(s= 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 + >>> s = np.random.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 = np.random.poisson(lam=(100., 500.), size=(100, 2)) + + """ + return disc(&random_poisson, self._brng, 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.zipf(a, 1000) + + Display the histogram of the samples, along with + the probability density function: + + >>> import matplotlib.pyplot as plt + >>> from scipy import special + + 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') + >>> plt.show() + + """ + return disc(&random_zipf, self._brng, 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.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._brng, 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. + nbad : int or array_like of ints + Number of ways to make a bad selection. Must be nonnegative. + nsample : int or array_like of ints + Number of items sampled. Must be at least 1 and at most + ``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. + + 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 + + Examples + -------- + Draw samples from the distribution: + + >>> ngood, nbad, nsamp = 100, 2, 10 + # number of good, number of bad, and number of samples + >>> s = np.random.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 = np.random.hypergeometric(15, 15, 15, 100000) + >>> sum(s>=12)/100000. + sum(s<=3)/100000. + # answer = 0.003 ... pretty unlikely! + + """ + cdef bint is_scalar = True + cdef np.ndarray ongood, onbad, onsample + cdef int64_t lngood, lnbad, lnsample + + ongood = np.PyArray_FROM_OTF(ngood, np.NPY_INT64, np.NPY_ALIGNED) + onbad = np.PyArray_FROM_OTF(nbad, np.NPY_INT64, np.NPY_ALIGNED) + onsample = 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 = ngood + lnbad = nbad + lnsample = nsample + + if lngood + lnbad < lnsample: + raise ValueError("ngood + nbad < nsample") + return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, + lngood, 'ngood', CONS_NON_NEGATIVE, + lnbad, 'nbad', CONS_NON_NEGATIVE, + lnsample, 'nsample', CONS_GTE_1) + + if np.any(np.less(np.add(ongood, onbad), onsample)): + raise ValueError("ngood + nbad < nsample") + return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, + ongood, 'ngood', CONS_NON_NEGATIVE, + onbad, 'nbad', CONS_NON_NEGATIVE, + onsample, 'nsample', CONS_GTE_1) + + 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 density 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.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._brng, 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.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.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, 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 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 + 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: + + >>> np.random.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: + + >>> np.random.multinomial(20, [1/6.]*6, size=2) + 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, + we threw 2 times 1, 4 times 2, etc. + + 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]) # 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: + + >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + array([38, 62]) # random + + not like: + + >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG + array([100, 0]) + + """ + cdef np.npy_intp d, i, j, dn, sz + cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" + cdef double *pix + cdef int64_t *mnix + cdef double Sum + + d = len(pvals) + parr = np.PyArray_FROM_OTF(pvals, np.NPY_DOUBLE, np.NPY_ALIGNED) + pix = np.PyArray_DATA(parr) + + if kahan_sum(pix, d-1) > (1.0 + 1e-12): + raise ValueError("sum(pvals[:-1]) > 1.0") + + 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 = multin + mnix = np.PyArray_DATA(mnarr) + sz = np.PyArray_SIZE(mnarr) + + with self.lock, nogil: + i = 0 + while i < sz: + Sum = 1.0 + dn = n + for j in range(d-1): + mnix[i+j] = random_binomial(self._brng, pix[j]/Sum, dn, + self._binomial) + dn = dn - mnix[i+j] + if dn <= 0: + break + Sum = Sum - pix[j] + if dn > 0: + mnix[i+d-1] = dn + + i = i + d + + return multin + + 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.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.PyArray_FROM_OTF(alpha, np.NPY_DOUBLE, np.NPY_ALIGNED) + if np.any(np.less_equal(alpha_arr, 0)): + raise ValueError('alpha <= 0') + alpha_data = 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 = diric + val_data = 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] = 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 + + # 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 + -------- + >>> arr = np.arange(10) + >>> np.random.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)) + >>> np.random.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 = 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 = 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, 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, ...]) + with self.lock: + for i in reversed(range(1, n)): + j = random_interval(self._brng, i) + if i == j: + continue # i == j is not needed and memcpy is undefined. + 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._brng, i) + x[i], x[j] = x[j], x[i] + + 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 = random_interval(self._brng, i) + string.memcpy(buf, data + j * stride, itemsize) + string.memcpy(data + j * stride, data + i * stride, itemsize) + string.memcpy(data + i * stride, buf, itemsize) + + 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 + -------- + >>> np.random.permutation(10) + 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]) # random + + >>> arr = np.arange(9).reshape((3, 3)) + >>> np.random.permutation(arr) + array([[6, 7, 8], # random + [0, 1, 2], + [3, 4, 5]]) + + """ + if isinstance(x, (int, long, 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] + +_rand = RandomState() + +beta = _rand.beta +binomial = _rand.binomial +bytes = _rand.bytes +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_sample +random_integers = _rand.random_integers +random_sample = _rand.random_sample +ranf = _rand.random_sample +rayleigh = _rand.rayleigh +sample = _rand.random_sample +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 +standard_normal = _rand.standard_normal +standard_t = _rand.standard_t +triangular = _rand.triangular +uniform = _rand.uniform +vonmises = _rand.vonmises +wald = _rand.wald +weibull = _rand.weibull +zipf = _rand.zipf + +__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_integers', + 'random_sample', + 'rayleigh', + 'seed', + 'set_state', + 'shuffle', + 'standard_cauchy', + 'standard_exponential', + 'standard_gamma', + 'standard_normal', + 'standard_t', + 'triangular', + 'uniform', + 'vonmises', + 'wald', + 'weibull', + 'zipf', + 'RandomState', +] + diff --git a/_randomgen/randomgen/pcg32.pyx b/numpy/random/randomgen/pcg32.pyx similarity index 78% rename from _randomgen/randomgen/pcg32.pyx rename to numpy/random/randomgen/pcg32.pyx index 5c83b1040b1d..5f2b34807da2 100644 --- a/_randomgen/randomgen/pcg32.pyx +++ b/numpy/random/randomgen/pcg32.pyx @@ -1,16 +1,17 @@ -from __future__ import absolute_import - from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy np.import_array() @@ -24,14 +25,14 @@ cdef extern from "src/pcg32/pcg32.h": ctypedef pcg_state_setseq_64 pcg32_random_t struct s_pcg32_state: - pcg32_random_t *pcg_state + pcg32_random_t *pcg_state ctypedef s_pcg32_state pcg32_state uint64_t pcg32_next64(pcg32_state *state) nogil uint32_t pcg32_next32(pcg32_state *state) nogil double pcg32_next_double(pcg32_state *state) nogil - void pcg32_jump(pcg32_state *state) + void pcg32_jump(pcg32_state *state) void pcg32_advance_state(pcg32_state *state, uint64_t step) void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) @@ -123,12 +124,14 @@ cdef class PCG32: cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg32_state)) self.rng_state.pcg_state = malloc(sizeof(pcg32_random_t)) self._brng = malloc(sizeof(brng_t)) self.seed(seed, inc) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &pcg32_uint64 @@ -151,7 +154,8 @@ cdef class PCG32: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -159,42 +163,39 @@ cdef class PCG32: free(self.rng_state) free(self._brng) - def __random_integer(self, bits=64): + def random_raw(self, size=None, output=True): """ - 64-bit Random Integers from the PRNG + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG Parameters ---------- - bits : {32, 64} - Number of random bits to return + 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 ------- - rv : int - Next random value + out : uint or ndarray + Drawn samples. Notes ----- - Testing only + 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. """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') + return random_raw(self._brng, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') - + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None, inc=0): """ @@ -218,7 +219,7 @@ cdef class PCG32: ValueError If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + ub = 2 ** 64 if seed is None: try: seed = random_entropy(2) @@ -257,7 +258,7 @@ cdef class PCG32: """ return {'brng': self.__class__.__name__, 'state': {'state': self.rng_state.pcg_state.state, - 'inc':self.rng_state.pcg_state.inc}} + 'inc': self.rng_state.pcg_state.inc}} @state.setter def state(self, value): @@ -267,7 +268,7 @@ cdef class PCG32: if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) - self.rng_state.pcg_state.state = value['state']['state'] + self.rng_state.pcg_state.state = value['state']['state'] self.rng_state.pcg_state.inc = value['state']['inc'] def advance(self, delta): @@ -327,12 +328,12 @@ cdef class PCG32: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -341,25 +342,10 @@ cdef class PCG32: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&pcg32_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&pcg32_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&pcg32_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -380,19 +366,8 @@ cdef class PCG32: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -401,10 +376,10 @@ cdef class PCG32: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/pcg64.pyx b/numpy/random/randomgen/pcg64.pyx similarity index 73% rename from _randomgen/randomgen/pcg64.pyx rename to numpy/random/randomgen/pcg64.pyx index 44e123d4ca24..f67d9623cc33 100644 --- a/_randomgen/randomgen/pcg64.pyx +++ b/numpy/random/randomgen/pcg64.pyx @@ -1,31 +1,32 @@ -from __future__ import absolute_import - from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy np.import_array() -IF PCG_EMULATED_MATH==1: - cdef extern from "src/pcg64/pcg64.h": - - ctypedef struct pcg128_t: - uint64_t high - uint64_t low -ELSE: - cdef extern from "inttypes.h": - ctypedef unsigned long long __uint128_t +# IF PCG_EMULATED_MATH==1: +cdef extern from "src/pcg64/pcg64.h": - cdef extern from "src/pcg64/pcg64.h": - ctypedef __uint128_t pcg128_t + ctypedef struct pcg128_t: + uint64_t high + uint64_t low +# ELSE: +# cdef extern from "inttypes.h": +# ctypedef unsigned long long __uint128_t +# +# cdef extern from "src/pcg64/pcg64.h": +# ctypedef __uint128_t pcg128_t cdef extern from "src/pcg64/pcg64.h": @@ -36,15 +37,15 @@ cdef extern from "src/pcg64/pcg64.h": ctypedef pcg_state_setseq_128 pcg64_random_t struct s_pcg64_state: - pcg64_random_t *pcg_state - int has_uint32 - uint32_t uinteger + 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_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) @@ -134,12 +135,14 @@ cdef class PCG64: cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None, inc=0): self.rng_state = malloc(sizeof(pcg64_state)) self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) self._brng = malloc(sizeof(brng_t)) self.seed(seed, inc) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &pcg64_uint64 @@ -162,7 +165,8 @@ cdef class PCG64: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -174,42 +178,39 @@ cdef class PCG64: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - def __random_integer(self, bits=64): + def random_raw(self, size=None, output=True): """ - 64-bit Random Integers from the RNG + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG Parameters ---------- - bits : {32, 64} - Number of random bits to return + 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 ------- - rv : int - Next random value + out : uint or ndarray + Drawn samples. Notes ----- - Testing only + 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. """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') + return random_raw(self._brng, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') - + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None, inc=0): """ @@ -235,7 +236,7 @@ cdef class PCG64: """ cdef np.ndarray _seed, _inc - ub = 2 ** 128 + ub = 2 ** 128 if seed is None: try: _seed = random_entropy(4) @@ -277,17 +278,18 @@ cdef class PCG64: Dictionary containing the information required to describe the state of the RNG """ - IF PCG_EMULATED_MATH==1: - state = 2 **64 * self.rng_state.pcg_state.state.high - state += self.rng_state.pcg_state.state.low - inc = 2 **64 * self.rng_state.pcg_state.inc.high - inc += self.rng_state.pcg_state.inc.low - ELSE: - state = self.rng_state.pcg_state.state - inc = self.rng_state.pcg_state.inc + # IF PCG_EMULATED_MATH==1: + # TODO: push this into an #ifdef in the C code + state = 2 **64 * self.rng_state.pcg_state.state.high + state += self.rng_state.pcg_state.state.low + inc = 2 **64 * self.rng_state.pcg_state.inc.high + inc += self.rng_state.pcg_state.inc.low + # ELSE: + # state = self.rng_state.pcg_state.state + # inc = self.rng_state.pcg_state.inc return {'brng': self.__class__.__name__, - 'state': {'state': state, 'inc':inc}, + 'state': {'state': state, 'inc': inc}, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -299,14 +301,14 @@ cdef class PCG64: if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'RNG'.format(self.__class__.__name__)) - IF PCG_EMULATED_MATH==1: - self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 - self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 - self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 - self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 - ELSE: - self.rng_state.pcg_state.state = value['state']['state'] - self.rng_state.pcg_state.inc = value['state']['inc'] + # IF PCG_EMULATED_MATH==1: + self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 + self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 + self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 + self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 + # ELSE: + # self.rng_state.pcg_state.state = value['state']['state'] + # self.rng_state.pcg_state.inc = value['state']['inc'] self.rng_state.has_uint32 = value['has_uint32'] self.rng_state.uinteger = value['uinteger'] @@ -380,12 +382,12 @@ cdef class PCG64: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -394,25 +396,10 @@ cdef class PCG64: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&pcg64_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&pcg64_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&pcg64_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -433,19 +420,8 @@ cdef class PCG64: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -454,10 +430,10 @@ cdef class PCG64: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator using this instance as the core RNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/philox.pyx b/numpy/random/randomgen/philox.pyx similarity index 85% rename from _randomgen/randomgen/philox.pyx rename to numpy/random/randomgen/philox.pyx index 26ece5e14b2c..70afd55ab2da 100644 --- a/_randomgen/randomgen/philox.pyx +++ b/numpy/random/randomgen/philox.pyx @@ -1,15 +1,17 @@ -from __future__ import absolute_import - from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array + np.import_array() @@ -25,14 +27,14 @@ cdef extern from 'src/philox/philox.h': ctypedef s_r123array4x64 r123array4x64 ctypedef s_r123array2x64 r123array2x64 - ctypedef r123array4x64 philox4x64_ctr_t; - ctypedef r123array2x64 philox4x64_key_t; + 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]; + philox4x64_ctr_t *ctr + philox4x64_key_t *key + int buffer_pos + uint64_t buffer[PHILOX_BUFFER_SIZE] int has_uint32 uint32_t uinteger @@ -158,12 +160,13 @@ cdef class Philox: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef philox_state *rng_state + cdef philox_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(philox_state)) @@ -173,6 +176,7 @@ cdef class Philox: sizeof(philox4x64_key_t)) self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &philox_uint64 @@ -195,7 +199,8 @@ cdef class Philox: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -212,16 +217,39 @@ cdef class Philox: for i in range(PHILOX_BUFFER_SIZE): self.rng_state.buffer[i] = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -256,7 +284,7 @@ cdef class Philox: """ if seed is not None and key is not None: raise ValueError('seed and key cannot be both used') - ub = 2 ** 64 + ub = 2 ** 64 if key is None: if seed is None: try: @@ -392,14 +420,15 @@ cdef class Philox: self._reset_state_variables() return self + @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -408,25 +437,10 @@ cdef class Philox: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&philox_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&philox_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&philox_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -447,19 +461,8 @@ cdef class Philox: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -468,10 +471,10 @@ cdef class Philox: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/numpy/random/randomgen/setup.py b/numpy/random/randomgen/setup.py new file mode 100644 index 000000000000..5b7be45599c8 --- /dev/null +++ b/numpy/random/randomgen/setup.py @@ -0,0 +1,191 @@ +from os.path import join +import sys +import os +import platform +import struct +from distutils.dep_util import newer +from distutils.msvccompiler import get_build_version as get_msvc_build_version + +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 + + return False + + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration, get_mathlibs + config = Configuration('randomgen', parent_package, top_path) + + def generate_libraries(ext, build_dir): + config_cmd = config.get_config_cmd() + libs = get_mathlibs() + if sys.platform == 'win32': + libs.append('Advapi32') + ext.libraries.extend(libs) + return None + + # enable unix large file support on 32 bit systems + # (64 bit off_t, lseek -> lseek64 etc.) + if sys.platform[:3] == "aix": + defs = [('_LARGE_FILES', None)] + else: + 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 = [] + defs.append(('NPY_NO_DEPRECATED_API', 0)) + config.add_data_dir('tests') + + ############################## + # randomgen + ############################## + + # Make a guess as to whether SSE2 is present for now, TODO: Improve + USE_SSE2 = False + for k in platform.uname(): + for val in ('x86', 'i686', 'i386', 'amd64'): + USE_SSE2 = USE_SSE2 or val in k.lower() + print('Building with SSE?: {0}'.format(USE_SSE2)) + if '--no-sse2' in sys.argv: + USE_SSE2 = False + sys.argv.remove('--no-sse2') + + DEBUG = False + PCG_EMULATED_MATH = False + EXTRA_LINK_ARGS = [] + EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] + EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ + '-std=c99', '-U__GNUC_GNU_INLINE__'] + if os.name == 'nt': + EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] + if DEBUG: + EXTRA_LINK_ARGS += ['-debug'] + EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] + if sys.version_info < (3, 0): + EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] + + PCG64_DEFS = [] + # TODO: remove the unconditional forced emulation, move code from pcg64.pyx + # to an #ifdef + if 1 or sys.maxsize < 2 ** 32 or os.name == 'nt': + # Force emulated mode here + PCG_EMULATED_MATH = True + PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] + + if struct.calcsize('P') < 8: + PCG_EMULATED_MATH = True + defs.append(('PCG_EMULATED_MATH', int(PCG_EMULATED_MATH))) + + DSFMT_DEFS = [('DSFMT_MEXP', '19937')] + if USE_SSE2: + if os.name == 'nt': + EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] + if struct.calcsize('P') < 8: + EXTRA_COMPILE_ARGS += ['/arch:SSE2'] + else: + EXTRA_COMPILE_ARGS += ['-msse2'] + DSFMT_DEFS += [('HAVE_SSE2', '1')] + + config.add_extension('entropy', + sources=['entropy.c', 'src/entropy/entropy.c'], + include_dirs=[join('randomgen', 'src', 'entropy')], + 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, + ) + config.add_extension('dsfmt', + sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', + 'src/dsfmt/dSFMT-jump.c', + 'src/aligned_malloc/aligned_malloc.c'], + include_dirs=[join('src', 'dsfmt')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=[join('src', 'dsfmt', 'dsfmt.h'), + 'dsfmt.pyx', + ], + define_macros=defs + DSFMT_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=[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', 'threefry', 'threefry32', + 'xoroshiro128', 'xorshift1024', 'xoshiro256starstar', + 'xoshiro512starstar', + 'pcg64', 'pcg32', + ]: + # gen.pyx, src/gen/gen.c + if gen == 'pcg64': + _defs = defs + PCG64_DEFS + else: + _defs = defs + config.add_extension(gen, + sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], + include_dirs=[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 ['common']: + # 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, + depends=['%s.pyx' % gen], + define_macros=defs, + ) + for gen in ['generator', 'bounded_integers']: + # gen.pyx, src/distributions/distributions.c + config.add_extension(gen, + sources=['{0}.c'.format(gen), + join('src', 'distributions', + 'distributions.c')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=['%s.pyx' % gen], + define_macros=defs, + ) + config.add_extension('mtrand', + sources=['mtrand.c', + 'src/legacy/distributions-boxmuller.c', + 'src/distributions/distributions.c' ], + include_dirs=['.', 'legacy'], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=['mtrand.pyx'], + define_macros=defs + DSFMT_DEFS, + ) + config.add_subpackage('legacy') + return config +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.c b/numpy/random/randomgen/src/aligned_malloc/aligned_malloc.c similarity index 100% rename from _randomgen/randomgen/src/aligned_malloc/aligned_malloc.c rename to numpy/random/randomgen/src/aligned_malloc/aligned_malloc.c diff --git a/_randomgen/randomgen/src/aligned_malloc/aligned_malloc.h b/numpy/random/randomgen/src/aligned_malloc/aligned_malloc.h similarity index 100% rename from _randomgen/randomgen/src/aligned_malloc/aligned_malloc.h rename to numpy/random/randomgen/src/aligned_malloc/aligned_malloc.h diff --git a/_randomgen/randomgen/src/common/LICENSE.md b/numpy/random/randomgen/src/common/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/common/LICENSE.md rename to numpy/random/randomgen/src/common/LICENSE.md diff --git a/_randomgen/randomgen/src/common/inttypes.h b/numpy/random/randomgen/src/common/inttypes.h similarity index 100% rename from _randomgen/randomgen/src/common/inttypes.h rename to numpy/random/randomgen/src/common/inttypes.h diff --git a/_randomgen/randomgen/src/common/stdint.h b/numpy/random/randomgen/src/common/stdint.h similarity index 100% rename from _randomgen/randomgen/src/common/stdint.h rename to numpy/random/randomgen/src/common/stdint.h diff --git a/_randomgen/randomgen/src/legacy/LICENSE.md b/numpy/random/randomgen/src/distributions/LICENSE.md similarity index 54% rename from _randomgen/randomgen/src/legacy/LICENSE.md rename to numpy/random/randomgen/src/distributions/LICENSE.md index 88b1791b200f..31576ba4b1f2 100644 --- a/_randomgen/randomgen/src/legacy/LICENSE.md +++ b/numpy/random/randomgen/src/distributions/LICENSE.md @@ -1,3 +1,5 @@ +## NumPy + Copyright (c) 2005-2017, NumPy Developers. All rights reserved. @@ -28,3 +30,32 @@ 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/_randomgen/randomgen/src/distributions/binomial.h b/numpy/random/randomgen/src/distributions/binomial.h similarity index 100% rename from _randomgen/randomgen/src/distributions/binomial.h rename to numpy/random/randomgen/src/distributions/binomial.h diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/numpy/random/randomgen/src/distributions/distributions.c similarity index 99% rename from _randomgen/randomgen/src/distributions/distributions.c rename to numpy/random/randomgen/src/distributions/distributions.c index a9d8a308d98f..83806de38997 100644 --- a/_randomgen/randomgen/src/distributions/distributions.c +++ b/numpy/random/randomgen/src/distributions/distributions.c @@ -41,7 +41,7 @@ void random_double_fill(brng_t *brng_state, npy_intp cnt, double *out) { out[i] = next_double(brng_state); } } -/* +#if 0 double random_gauss(brng_t *brng_state) { if (brng_state->has_gauss) { const double temp = brng_state->gauss; @@ -57,9 +57,9 @@ double random_gauss(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Polar method, a more efficient version of the Box-Muller approach. + /* Polar method, a more efficient version of the Box-Muller approach. */ f = sqrt(-2.0 * log(r2) / r2); - /* Keep for next call + /* Keep for next call */ brng_state->gauss = f * x1; brng_state->has_gauss = true; return f * x2; @@ -81,15 +81,15 @@ float random_gauss_f(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Polar method, a more efficient version of the Box-Muller approach. + /* Polar method, a more efficient version of the Box-Muller approach. */ f = sqrtf(-2.0f * logf(r2) / r2); - /* Keep for next call + /* Keep for next call */ brng_state->gauss_f = f * x1; brng_state->has_gauss_f = true; return f * x2; } } -*/ +#endif static NPY_INLINE double standard_exponential_zig(brng_t *brng_state); @@ -879,6 +879,9 @@ int64_t random_binomial(brng_t *brng_state, double p, int64_t 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(brng_state, n, p, binomial); @@ -896,6 +899,9 @@ int64_t random_binomial(brng_t *brng_state, double p, int64_t n, } double random_noncentral_chisquare(brng_t *brng_state, double df, double nonc) { + if (npy_isnan(nonc)){ + return NPY_NAN; + } if (nonc == 0) { return random_chisquare(brng_state, df); } @@ -936,7 +942,9 @@ double random_vonmises(brng_t *brng_state, double mu, double kappa) { 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(brng_state) - 1); } else { diff --git a/_randomgen/randomgen/src/distributions/distributions.h b/numpy/random/randomgen/src/distributions/distributions.h similarity index 99% rename from _randomgen/randomgen/src/distributions/distributions.h rename to numpy/random/randomgen/src/distributions/distributions.h index 5cf9c72b25bc..7ca31a16cba6 100644 --- a/_randomgen/randomgen/src/distributions/distributions.h +++ b/numpy/random/randomgen/src/distributions/distributions.h @@ -20,7 +20,7 @@ typedef int bool; #include "Python.h" #include "numpy/npy_common.h" -#include +#include "numpy/npy_math.h" #ifdef _WIN32 #if _MSC_VER == 1500 diff --git a/_randomgen/randomgen/src/distributions/ziggurat.h b/numpy/random/randomgen/src/distributions/ziggurat.h similarity index 100% rename from _randomgen/randomgen/src/distributions/ziggurat.h rename to numpy/random/randomgen/src/distributions/ziggurat.h diff --git a/_randomgen/randomgen/src/distributions/ziggurat_constants.h b/numpy/random/randomgen/src/distributions/ziggurat_constants.h similarity index 100% rename from _randomgen/randomgen/src/distributions/ziggurat_constants.h rename to numpy/random/randomgen/src/distributions/ziggurat_constants.h diff --git a/_randomgen/randomgen/src/dsfmt/128-bit-jump.poly.txt b/numpy/random/randomgen/src/dsfmt/128-bit-jump.poly.txt similarity index 100% rename from _randomgen/randomgen/src/dsfmt/128-bit-jump.poly.txt rename to numpy/random/randomgen/src/dsfmt/128-bit-jump.poly.txt diff --git a/_randomgen/randomgen/src/dsfmt/96-bit-jump.poly.txt b/numpy/random/randomgen/src/dsfmt/96-bit-jump.poly.txt similarity index 100% rename from _randomgen/randomgen/src/dsfmt/96-bit-jump.poly.txt rename to numpy/random/randomgen/src/dsfmt/96-bit-jump.poly.txt diff --git a/_randomgen/randomgen/src/dsfmt/LICENSE.md b/numpy/random/randomgen/src/dsfmt/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/dsfmt/LICENSE.md rename to numpy/random/randomgen/src/dsfmt/LICENSE.md diff --git a/_randomgen/randomgen/src/dsfmt/calc-jump.cpp b/numpy/random/randomgen/src/dsfmt/calc-jump.cpp similarity index 100% rename from _randomgen/randomgen/src/dsfmt/calc-jump.cpp rename to numpy/random/randomgen/src/dsfmt/calc-jump.cpp diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-benchmark.c b/numpy/random/randomgen/src/dsfmt/dSFMT-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-benchmark.c rename to numpy/random/randomgen/src/dsfmt/dSFMT-benchmark.c diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-calc-jump.hpp b/numpy/random/randomgen/src/dsfmt/dSFMT-calc-jump.hpp similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-calc-jump.hpp rename to numpy/random/randomgen/src/dsfmt/dSFMT-calc-jump.hpp diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-common.h b/numpy/random/randomgen/src/dsfmt/dSFMT-common.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-common.h rename to numpy/random/randomgen/src/dsfmt/dSFMT-common.h diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-jump.c b/numpy/random/randomgen/src/dsfmt/dSFMT-jump.c similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-jump.c rename to numpy/random/randomgen/src/dsfmt/dSFMT-jump.c diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-jump.h b/numpy/random/randomgen/src/dsfmt/dSFMT-jump.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-jump.h rename to numpy/random/randomgen/src/dsfmt/dSFMT-jump.h diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-params.h b/numpy/random/randomgen/src/dsfmt/dSFMT-params.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-params.h rename to numpy/random/randomgen/src/dsfmt/dSFMT-params.h diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-params19937.h b/numpy/random/randomgen/src/dsfmt/dSFMT-params19937.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-params19937.h rename to numpy/random/randomgen/src/dsfmt/dSFMT-params19937.h diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-poly.h b/numpy/random/randomgen/src/dsfmt/dSFMT-poly.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-poly.h rename to numpy/random/randomgen/src/dsfmt/dSFMT-poly.h diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT-test-gen.c b/numpy/random/randomgen/src/dsfmt/dSFMT-test-gen.c similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT-test-gen.c rename to numpy/random/randomgen/src/dsfmt/dSFMT-test-gen.c diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT.c b/numpy/random/randomgen/src/dsfmt/dSFMT.c similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT.c rename to numpy/random/randomgen/src/dsfmt/dSFMT.c diff --git a/_randomgen/randomgen/src/dsfmt/dSFMT.h b/numpy/random/randomgen/src/dsfmt/dSFMT.h similarity index 100% rename from _randomgen/randomgen/src/dsfmt/dSFMT.h rename to numpy/random/randomgen/src/dsfmt/dSFMT.h diff --git a/_randomgen/randomgen/src/entropy/LICENSE.md b/numpy/random/randomgen/src/entropy/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/entropy/LICENSE.md rename to numpy/random/randomgen/src/entropy/LICENSE.md diff --git a/_randomgen/randomgen/src/entropy/entropy.c b/numpy/random/randomgen/src/entropy/entropy.c similarity index 100% rename from _randomgen/randomgen/src/entropy/entropy.c rename to numpy/random/randomgen/src/entropy/entropy.c diff --git a/_randomgen/randomgen/src/entropy/entropy.h b/numpy/random/randomgen/src/entropy/entropy.h similarity index 100% rename from _randomgen/randomgen/src/entropy/entropy.h rename to numpy/random/randomgen/src/entropy/entropy.h diff --git a/_randomgen/randomgen/src/distributions/LICENSE.md b/numpy/random/randomgen/src/legacy/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/distributions/LICENSE.md rename to numpy/random/randomgen/src/legacy/LICENSE.md diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c b/numpy/random/randomgen/src/legacy/distributions-boxmuller.c similarity index 96% rename from _randomgen/randomgen/src/legacy/distributions-boxmuller.c rename to numpy/random/randomgen/src/legacy/distributions-boxmuller.c index 768de066ced2..5d3ba27f8218 100644 --- a/_randomgen/randomgen/src/legacy/distributions-boxmuller.c +++ b/numpy/random/randomgen/src/legacy/distributions-boxmuller.c @@ -103,6 +103,7 @@ double legacy_chisquare(aug_brng_t *aug_state, double df) { double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, double nonc) { + double out; if (nonc == 0) { return legacy_chisquare(aug_state, df); } @@ -112,7 +113,13 @@ double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, return Chi2 + n * n; } else { const long i = random_poisson(aug_state->basicrng, nonc / 2.0); - return legacy_chisquare(aug_state, df + 2 * i); + 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; + } } } diff --git a/_randomgen/randomgen/src/legacy/distributions-boxmuller.h b/numpy/random/randomgen/src/legacy/distributions-boxmuller.h similarity index 100% rename from _randomgen/randomgen/src/legacy/distributions-boxmuller.h rename to numpy/random/randomgen/src/legacy/distributions-boxmuller.h diff --git a/_randomgen/randomgen/src/mt19937/LICENSE.md b/numpy/random/randomgen/src/mt19937/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/mt19937/LICENSE.md rename to numpy/random/randomgen/src/mt19937/LICENSE.md diff --git a/_randomgen/randomgen/src/mt19937/mt19937-benchmark.c b/numpy/random/randomgen/src/mt19937/mt19937-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937-benchmark.c rename to numpy/random/randomgen/src/mt19937/mt19937-benchmark.c diff --git a/_randomgen/randomgen/src/mt19937/mt19937-jump.c b/numpy/random/randomgen/src/mt19937/mt19937-jump.c similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937-jump.c rename to numpy/random/randomgen/src/mt19937/mt19937-jump.c diff --git a/_randomgen/randomgen/src/mt19937/mt19937-jump.h b/numpy/random/randomgen/src/mt19937/mt19937-jump.h similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937-jump.h rename to numpy/random/randomgen/src/mt19937/mt19937-jump.h diff --git a/_randomgen/randomgen/src/mt19937/mt19937-poly.h b/numpy/random/randomgen/src/mt19937/mt19937-poly.h similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937-poly.h rename to numpy/random/randomgen/src/mt19937/mt19937-poly.h diff --git a/_randomgen/randomgen/src/mt19937/mt19937-test-data-gen.c b/numpy/random/randomgen/src/mt19937/mt19937-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937-test-data-gen.c rename to numpy/random/randomgen/src/mt19937/mt19937-test-data-gen.c diff --git a/_randomgen/randomgen/src/mt19937/mt19937.c b/numpy/random/randomgen/src/mt19937/mt19937.c similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937.c rename to numpy/random/randomgen/src/mt19937/mt19937.c diff --git a/_randomgen/randomgen/src/mt19937/mt19937.h b/numpy/random/randomgen/src/mt19937/mt19937.h similarity index 100% rename from _randomgen/randomgen/src/mt19937/mt19937.h rename to numpy/random/randomgen/src/mt19937/mt19937.h diff --git a/_randomgen/randomgen/src/mt19937/randomkit.c b/numpy/random/randomgen/src/mt19937/randomkit.c similarity index 100% rename from _randomgen/randomgen/src/mt19937/randomkit.c rename to numpy/random/randomgen/src/mt19937/randomkit.c diff --git a/_randomgen/randomgen/src/mt19937/randomkit.h b/numpy/random/randomgen/src/mt19937/randomkit.h similarity index 100% rename from _randomgen/randomgen/src/mt19937/randomkit.h rename to numpy/random/randomgen/src/mt19937/randomkit.h diff --git a/_randomgen/randomgen/src/pcg32/LICENSE.md b/numpy/random/randomgen/src/pcg32/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/pcg32/LICENSE.md rename to numpy/random/randomgen/src/pcg32/LICENSE.md diff --git a/_randomgen/randomgen/src/pcg32/pcg-advance-64.c b/numpy/random/randomgen/src/pcg32/pcg-advance-64.c similarity index 100% rename from _randomgen/randomgen/src/pcg32/pcg-advance-64.c rename to numpy/random/randomgen/src/pcg32/pcg-advance-64.c diff --git a/_randomgen/randomgen/src/pcg32/pcg32-test-data-gen.c b/numpy/random/randomgen/src/pcg32/pcg32-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/pcg32/pcg32-test-data-gen.c rename to numpy/random/randomgen/src/pcg32/pcg32-test-data-gen.c diff --git a/_randomgen/randomgen/src/pcg32/pcg32.c b/numpy/random/randomgen/src/pcg32/pcg32.c similarity index 100% rename from _randomgen/randomgen/src/pcg32/pcg32.c rename to numpy/random/randomgen/src/pcg32/pcg32.c diff --git a/_randomgen/randomgen/src/pcg32/pcg32.h b/numpy/random/randomgen/src/pcg32/pcg32.h similarity index 97% rename from _randomgen/randomgen/src/pcg32/pcg32.h rename to numpy/random/randomgen/src/pcg32/pcg32.h index 15410bd821c7..557113d8f6af 100644 --- a/_randomgen/randomgen/src/pcg32/pcg32.h +++ b/numpy/random/randomgen/src/pcg32/pcg32.h @@ -1,3 +1,5 @@ +#ifndef _RANDOMDGEN__PCG32_H_ +#define _RANDOMDGEN__PCG32_H_ #ifdef _WIN32 #ifndef _INTTYPES @@ -83,3 +85,5 @@ static inline double pcg32_next_double(pcg32_state *state) { void pcg32_advance_state(pcg32_state *state, uint64_t step); void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc); + +#endif diff --git a/_randomgen/randomgen/src/pcg32/pcg_variants.h b/numpy/random/randomgen/src/pcg32/pcg_variants.h similarity index 100% rename from _randomgen/randomgen/src/pcg32/pcg_variants.h rename to numpy/random/randomgen/src/pcg32/pcg_variants.h diff --git a/_randomgen/randomgen/src/pcg64/LICENSE.md b/numpy/random/randomgen/src/pcg64/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/pcg64/LICENSE.md rename to numpy/random/randomgen/src/pcg64/LICENSE.md diff --git a/_randomgen/randomgen/src/pcg64/pcg64-benchmark.c b/numpy/random/randomgen/src/pcg64/pcg64-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64-benchmark.c rename to numpy/random/randomgen/src/pcg64/pcg64-benchmark.c diff --git a/_randomgen/randomgen/src/pcg64/pcg64-test-data-gen.c b/numpy/random/randomgen/src/pcg64/pcg64-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64-test-data-gen.c rename to numpy/random/randomgen/src/pcg64/pcg64-test-data-gen.c diff --git a/_randomgen/randomgen/src/pcg64/pcg64.c b/numpy/random/randomgen/src/pcg64/pcg64.c similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64.c rename to numpy/random/randomgen/src/pcg64/pcg64.c diff --git a/_randomgen/randomgen/src/pcg64/pcg64.h b/numpy/random/randomgen/src/pcg64/pcg64.h similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64.h rename to numpy/random/randomgen/src/pcg64/pcg64.h index 854930176f09..156c73a36988 100644 --- a/_randomgen/randomgen/src/pcg64/pcg64.h +++ b/numpy/random/randomgen/src/pcg64/pcg64.h @@ -212,8 +212,6 @@ typedef pcg_state_setseq_128 pcg64_random_t; } #endif -#endif /* PCG64_H_INCLUDED */ - typedef struct s_pcg64_state { pcg64_random_t *pcg_state; int has_uint32; @@ -239,3 +237,5 @@ static inline uint32_t pcg64_next32(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); + +#endif /* PCG64_H_INCLUDED */ diff --git a/_randomgen/randomgen/src/pcg64/pcg64.orig.c b/numpy/random/randomgen/src/pcg64/pcg64.orig.c similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64.orig.c rename to numpy/random/randomgen/src/pcg64/pcg64.orig.c diff --git a/_randomgen/randomgen/src/pcg64/pcg64.orig.h b/numpy/random/randomgen/src/pcg64/pcg64.orig.h similarity index 100% rename from _randomgen/randomgen/src/pcg64/pcg64.orig.h rename to numpy/random/randomgen/src/pcg64/pcg64.orig.h diff --git a/_randomgen/randomgen/src/philox/LICENSE.md b/numpy/random/randomgen/src/philox/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/philox/LICENSE.md rename to numpy/random/randomgen/src/philox/LICENSE.md diff --git a/_randomgen/randomgen/src/philox/philox-benchmark.c b/numpy/random/randomgen/src/philox/philox-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/philox/philox-benchmark.c rename to numpy/random/randomgen/src/philox/philox-benchmark.c diff --git a/_randomgen/randomgen/src/philox/philox-test-data-gen.c b/numpy/random/randomgen/src/philox/philox-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/philox/philox-test-data-gen.c rename to numpy/random/randomgen/src/philox/philox-test-data-gen.c diff --git a/_randomgen/randomgen/src/philox/philox.c b/numpy/random/randomgen/src/philox/philox.c similarity index 100% rename from _randomgen/randomgen/src/philox/philox.c rename to numpy/random/randomgen/src/philox/philox.c diff --git a/_randomgen/randomgen/src/philox/philox.h b/numpy/random/randomgen/src/philox/philox.h similarity index 100% rename from _randomgen/randomgen/src/philox/philox.h rename to numpy/random/randomgen/src/philox/philox.h diff --git a/_randomgen/randomgen/src/splitmix64/LICENSE.md b/numpy/random/randomgen/src/splitmix64/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/splitmix64/LICENSE.md rename to numpy/random/randomgen/src/splitmix64/LICENSE.md diff --git a/_randomgen/randomgen/src/splitmix64/splitmix64.c b/numpy/random/randomgen/src/splitmix64/splitmix64.c similarity index 100% rename from _randomgen/randomgen/src/splitmix64/splitmix64.c rename to numpy/random/randomgen/src/splitmix64/splitmix64.c diff --git a/_randomgen/randomgen/src/splitmix64/splitmix64.h b/numpy/random/randomgen/src/splitmix64/splitmix64.h similarity index 100% rename from _randomgen/randomgen/src/splitmix64/splitmix64.h rename to numpy/random/randomgen/src/splitmix64/splitmix64.h diff --git a/_randomgen/randomgen/src/splitmix64/splitmix64.orig.c b/numpy/random/randomgen/src/splitmix64/splitmix64.orig.c similarity index 100% rename from _randomgen/randomgen/src/splitmix64/splitmix64.orig.c rename to numpy/random/randomgen/src/splitmix64/splitmix64.orig.c diff --git a/_randomgen/randomgen/src/threefry/LICENSE.md b/numpy/random/randomgen/src/threefry/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/threefry/LICENSE.md rename to numpy/random/randomgen/src/threefry/LICENSE.md diff --git a/_randomgen/randomgen/src/threefry/threefry-benchmark.c b/numpy/random/randomgen/src/threefry/threefry-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/threefry/threefry-benchmark.c rename to numpy/random/randomgen/src/threefry/threefry-benchmark.c diff --git a/_randomgen/randomgen/src/threefry/threefry-orig.c b/numpy/random/randomgen/src/threefry/threefry-orig.c similarity index 100% rename from _randomgen/randomgen/src/threefry/threefry-orig.c rename to numpy/random/randomgen/src/threefry/threefry-orig.c diff --git a/_randomgen/randomgen/src/threefry/threefry-test-data-gen.c b/numpy/random/randomgen/src/threefry/threefry-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/threefry/threefry-test-data-gen.c rename to numpy/random/randomgen/src/threefry/threefry-test-data-gen.c diff --git a/_randomgen/randomgen/src/threefry/threefry.c b/numpy/random/randomgen/src/threefry/threefry.c similarity index 100% rename from _randomgen/randomgen/src/threefry/threefry.c rename to numpy/random/randomgen/src/threefry/threefry.c diff --git a/_randomgen/randomgen/src/threefry/threefry.h b/numpy/random/randomgen/src/threefry/threefry.h similarity index 100% rename from _randomgen/randomgen/src/threefry/threefry.h rename to numpy/random/randomgen/src/threefry/threefry.h diff --git a/_randomgen/randomgen/src/threefry32/LICENSE.md b/numpy/random/randomgen/src/threefry32/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/threefry32/LICENSE.md rename to numpy/random/randomgen/src/threefry32/LICENSE.md diff --git a/_randomgen/randomgen/src/threefry32/threefry32-test-data-gen.c b/numpy/random/randomgen/src/threefry32/threefry32-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/threefry32/threefry32-test-data-gen.c rename to numpy/random/randomgen/src/threefry32/threefry32-test-data-gen.c diff --git a/_randomgen/randomgen/src/threefry32/threefry32.c b/numpy/random/randomgen/src/threefry32/threefry32.c similarity index 100% rename from _randomgen/randomgen/src/threefry32/threefry32.c rename to numpy/random/randomgen/src/threefry32/threefry32.c diff --git a/_randomgen/randomgen/src/threefry32/threefry32.h b/numpy/random/randomgen/src/threefry32/threefry32.h similarity index 100% rename from _randomgen/randomgen/src/threefry32/threefry32.h rename to numpy/random/randomgen/src/threefry32/threefry32.h diff --git a/_randomgen/randomgen/src/xoroshiro128/LICENSE.md b/numpy/random/randomgen/src/xoroshiro128/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/xoroshiro128/LICENSE.md rename to numpy/random/randomgen/src/xoroshiro128/LICENSE.md diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c similarity index 95% rename from _randomgen/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c rename to numpy/random/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c index 108058eeb103..9a7b52bfbf29 100644 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c +++ b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c @@ -14,14 +14,16 @@ #define N 1000000000 -int main() { +int main() +{ uint64_t count = 0, sum = 0; uint64_t seed = 0xDEADBEAF; s[0] = splitmix64_next(&seed); s[1] = splitmix64_next(&seed); int i; clock_t begin = clock(); - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) + { sum += next(); count++; } diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c similarity index 83% rename from _randomgen/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c rename to numpy/random/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c index d95260eca176..d50e63f5e6da 100644 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c +++ b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c @@ -21,50 +21,61 @@ #define N 1000 -int main() { +int main() +{ uint64_t sum = 0; uint64_t state, seed = 0xDEADBEAF; state = seed; int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) + { s[i] = splitmix64_next(&state); } uint64_t store[N]; - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) + { store[i] = next(); } FILE *fp; fp = fopen("xoroshiro128-testset-1.csv", "w"); - if (fp == NULL) { + if (fp == NULL) + { printf("Couldn't open file\n"); return -1; } fprintf(fp, "seed, 0x%" PRIx64 "\n", seed); - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) + { fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); - if (i == 999) { + if (i == 999) + { printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } fclose(fp); seed = state = 0; - for (i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) + { s[i] = splitmix64_next(&state); } - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) + { store[i] = next(); } fp = fopen("xoroshiro128-testset-2.csv", "w"); - if (fp == NULL) { + if (fp == NULL) + { printf("Couldn't open file\n"); return -1; } fprintf(fp, "seed, 0x%" PRIx64 "\n", seed); - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) + { fprintf(fp, "%d, 0x%" PRIx64 "\n", i, store[i]); - if (i == 999) { + if (i == 999) + { printf("%d, 0x%" PRIx64 "\n", i, store[i]); } } diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c new file mode 100644 index 000000000000..060eb8a518c1 --- /dev/null +++ b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c @@ -0,0 +1,60 @@ +/* Written in 2016-2018 by David Blackman and 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 . */ + +/* This is xoroshiro128+ 1.0, our best and fastest small-state generator + for floating-point numbers. We suggest to use its upper bits for + floating-point generation, as it is slightly faster than + xoroshiro128**. It passes all tests we are aware of except for the four + lower bits, which might fail linearity tests (and just those), so if + low linear complexity is not considered an issue (as it is usually the + case) it can be used to generate 64-bit outputs, too; moreover, this + generator has a very mild Hamming-weight dependency making our test + (http://prng.di.unimi.it/hwd.php) fail after 5 TB of output; we believe + this slight bias cannot affect any application. If you are concerned, + use xoroshiro128** or xoshiro256+. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. + + NOTE: the parameters (a=24, b=16, b=37) of this version give slightly + better results in our test than the 2016 version (a=55, b=14, c=36). +*/ + +#include "xoroshiro128.h" + +extern INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); + +extern INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); + +void xoroshiro128_jump(xoroshiro128_state *state) +{ + int i, b; + uint64_t s0; + uint64_t s1; + static const uint64_t JUMP[] = {0xdf900294d8f554a5, 0x170865df4b3201fc}; + + s0 = 0; + s1 = 0; + for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (b = 0; b < 64; b++) + { + if (JUMP[i] & UINT64_C(1) << b) + { + s0 ^= state->s[0]; + s1 ^= state->s[1]; + } + xoroshiro128_next(&state->s[0]); + } + + state->s[0] = s0; + state->s[1] = s1; +} diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.h similarity index 77% rename from _randomgen/randomgen/src/xoroshiro128/xoroshiro128.h rename to numpy/random/randomgen/src/xoroshiro128/xoroshiro128.h index 40cb39218908..0db82b173839 100644 --- a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128.h +++ b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.h @@ -14,35 +14,41 @@ #define INLINE inline #endif -typedef struct s_xoroshiro128_state { +typedef struct s_xoroshiro128_state +{ uint64_t s[2]; int has_uint32; uint32_t uinteger; } xoroshiro128_state; -static INLINE uint64_t rotl(const uint64_t x, int k) { +static INLINE uint64_t rotl(const uint64_t x, int k) +{ return (x << k) | (x >> (64 - k)); } -static INLINE uint64_t xoroshiro128_next(uint64_t *s) { +static INLINE uint64_t xoroshiro128_next(uint64_t *s) +{ const uint64_t s0 = s[0]; uint64_t s1 = s[1]; const uint64_t result = s0 + s1; s1 ^= s0; - s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b - s[1] = rotl(s1, 36); // c + s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + s[1] = rotl(s1, 37); // c return result; } -static INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) { +static INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) +{ return xoroshiro128_next(&state->s[0]); } -static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) { +static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) +{ uint64_t next; - if (state->has_uint32) { + if (state->has_uint32) + { state->has_uint32 = 0; return state->uinteger; } diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c new file mode 100644 index 000000000000..1b5f46e4bdb5 --- /dev/null +++ b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c @@ -0,0 +1,102 @@ +/* Written in 2016-2018 by David Blackman and 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 . */ + +#include + +/* This is xoroshiro128+ 1.0, our best and fastest small-state generator + for floating-point numbers. We suggest to use its upper bits for + floating-point generation, as it is slightly faster than + xoroshiro128**. It passes all tests we are aware of except for the four + lower bits, which might fail linearity tests (and just those), so if + low linear complexity is not considered an issue (as it is usually the + case) it can be used to generate 64-bit outputs, too; moreover, this + generator has a very mild Hamming-weight dependency making our test + (http://prng.di.unimi.it/hwd.php) fail after 5 TB of output; we believe + this slight bias cannot affect any application. If you are concerned, + use xoroshiro128** or xoshiro256+. + + We suggest to use a sign test to extract a random Boolean value, and + right shifts to extract subsets of bits. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. + + NOTE: the parameters (a=24, b=16, b=37) of this version give slightly + better results in our test than the 2016 version (a=55, b=14, c=36). +*/ + +uint64_t s[2]; + +static inline uint64_t rotl(const uint64_t x, int k) +{ + return (x << k) | (x >> (64 - k)); +} + +uint64_t next(void) +{ + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; + const uint64_t result = s0 + s1; + + s1 ^= s0; + s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + s[1] = rotl(s1, 37); // c + + return result; +} + +/* This is the jump function for the generator. It is equivalent + to 2^64 calls to next(); it can be used to generate 2^64 + non-overlapping subsequences for parallel computations. */ + +void jump(void) +{ + static const uint64_t JUMP[] = {0xdf900294d8f554a5, 0x170865df4b3201fc}; + + uint64_t s0 = 0; + uint64_t s1 = 0; + for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for (int b = 0; b < 64; b++) + { + if (JUMP[i] & UINT64_C(1) << b) + { + s0 ^= s[0]; + s1 ^= s[1]; + } + next(); + } + s[0] = s0; + s[1] = s1; +} + +/* This is the long-jump function for the generator. It is equivalent to + 2^96 calls to next(); it can be used to generate 2^32 starting points, + from each of which jump() will generate 2^32 non-overlapping + subsequences for parallel distributed computations. */ + +void long_jump(void) +{ + static const uint64_t LONG_JUMP[] = {0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1}; + + uint64_t s0 = 0; + uint64_t s1 = 0; + for (int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) + for (int b = 0; b < 64; b++) + { + if (LONG_JUMP[i] & UINT64_C(1) << b) + { + s0 ^= s[0]; + s1 ^= s[1]; + } + next(); + } + + s[0] = s0; + s[1] = s1; +} diff --git a/_randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h b/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h similarity index 100% rename from _randomgen/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h rename to numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h diff --git a/_randomgen/randomgen/src/xorshift1024/LICENSE.md b/numpy/random/randomgen/src/xorshift1024/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/LICENSE.md rename to numpy/random/randomgen/src/xorshift1024/LICENSE.md diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024-benchmark.c b/numpy/random/randomgen/src/xorshift1024/xorshift1024-benchmark.c similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024-benchmark.c rename to numpy/random/randomgen/src/xorshift1024/xorshift1024-benchmark.c diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c b/numpy/random/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c rename to numpy/random/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024.c b/numpy/random/randomgen/src/xorshift1024/xorshift1024.c similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024.c rename to numpy/random/randomgen/src/xorshift1024/xorshift1024.c diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024.h b/numpy/random/randomgen/src/xorshift1024/xorshift1024.h similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024.h rename to numpy/random/randomgen/src/xorshift1024/xorshift1024.h diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024.orig.c b/numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.c similarity index 95% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024.orig.c rename to numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.c index e4f899fb7b09..03c1c17fe800 100644 --- a/_randomgen/randomgen/src/xorshift1024/xorshift1024.orig.c +++ b/numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.c @@ -14,7 +14,7 @@ See . */ linear dependencies from one of the lowest bits. The previous multiplier was 1181783497276652981 (M_8 in the paper). If you need to tell apart the two generators, you can refer to this generator as - xorshift1024*φ and to the previous one as xorshift1024*M_8. + xorshift1024φ and to the previous one as xorshift1024*M_8. This is a fast, high-quality generator. If 1024 bits of state are too much, try a xoroshiro128+ generator. @@ -36,7 +36,7 @@ int p; uint64_t next(void) { const uint64_t s0 = s[p]; uint64_t s1 = s[p = (p + 1) & 15]; - s1 ^= s1 << 31; // a + s1 ^= s1 << 31; // a s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c return s[p] * 0x9e3779b97f4a7c13; } diff --git a/_randomgen/randomgen/src/xorshift1024/xorshift1024.orig.h b/numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.h similarity index 100% rename from _randomgen/randomgen/src/xorshift1024/xorshift1024.orig.h rename to numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.h diff --git a/_randomgen/randomgen/src/xoshiro256starstar/LICENSE.md b/numpy/random/randomgen/src/xoshiro256starstar/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/LICENSE.md rename to numpy/random/randomgen/src/xoshiro256starstar/LICENSE.md diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c b/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c rename to numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c b/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.c rename to numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.c diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h b/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.h similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.h rename to numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.h diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c b/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c rename to numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c diff --git a/_randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h b/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h similarity index 100% rename from _randomgen/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h rename to numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h diff --git a/_randomgen/randomgen/src/xoshiro512starstar/LICENSE.md b/numpy/random/randomgen/src/xoshiro512starstar/LICENSE.md similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/LICENSE.md rename to numpy/random/randomgen/src/xoshiro512starstar/LICENSE.md diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c b/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c rename to numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c b/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.c rename to numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.c diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h b/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.h similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.h rename to numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.h diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c b/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c rename to numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c diff --git a/_randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h b/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h similarity index 100% rename from _randomgen/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h rename to numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h diff --git a/_randomgen/randomgen/tests/__init__.py b/numpy/random/randomgen/tests/__init__.py similarity index 100% rename from _randomgen/randomgen/tests/__init__.py rename to numpy/random/randomgen/tests/__init__.py diff --git a/_randomgen/randomgen/tests/data/__init__.py b/numpy/random/randomgen/tests/data/__init__.py similarity index 100% rename from _randomgen/randomgen/tests/data/__init__.py rename to numpy/random/randomgen/tests/data/__init__.py diff --git a/_randomgen/randomgen/tests/data/dSFMT-testset-1.csv b/numpy/random/randomgen/tests/data/dSFMT-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/dSFMT-testset-1.csv rename to numpy/random/randomgen/tests/data/dSFMT-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/dSFMT-testset-2.csv b/numpy/random/randomgen/tests/data/dSFMT-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/dSFMT-testset-2.csv rename to numpy/random/randomgen/tests/data/dSFMT-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/mt19937-testset-1.csv b/numpy/random/randomgen/tests/data/mt19937-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/mt19937-testset-1.csv rename to numpy/random/randomgen/tests/data/mt19937-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/mt19937-testset-2.csv b/numpy/random/randomgen/tests/data/mt19937-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/mt19937-testset-2.csv rename to numpy/random/randomgen/tests/data/mt19937-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/pcg32-testset-1.csv b/numpy/random/randomgen/tests/data/pcg32-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/pcg32-testset-1.csv rename to numpy/random/randomgen/tests/data/pcg32-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/pcg32-testset-2.csv b/numpy/random/randomgen/tests/data/pcg32-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/pcg32-testset-2.csv rename to numpy/random/randomgen/tests/data/pcg32-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/pcg64-testset-1.csv b/numpy/random/randomgen/tests/data/pcg64-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/pcg64-testset-1.csv rename to numpy/random/randomgen/tests/data/pcg64-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/pcg64-testset-2.csv b/numpy/random/randomgen/tests/data/pcg64-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/pcg64-testset-2.csv rename to numpy/random/randomgen/tests/data/pcg64-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/philox-testset-1.csv b/numpy/random/randomgen/tests/data/philox-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/philox-testset-1.csv rename to numpy/random/randomgen/tests/data/philox-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/philox-testset-2.csv b/numpy/random/randomgen/tests/data/philox-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/philox-testset-2.csv rename to numpy/random/randomgen/tests/data/philox-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/threefry-testset-1.csv b/numpy/random/randomgen/tests/data/threefry-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/threefry-testset-1.csv rename to numpy/random/randomgen/tests/data/threefry-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/threefry-testset-2.csv b/numpy/random/randomgen/tests/data/threefry-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/threefry-testset-2.csv rename to numpy/random/randomgen/tests/data/threefry-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/threefry32-testset-1.csv b/numpy/random/randomgen/tests/data/threefry32-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/threefry32-testset-1.csv rename to numpy/random/randomgen/tests/data/threefry32-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/threefry32-testset-2.csv b/numpy/random/randomgen/tests/data/threefry32-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/threefry32-testset-2.csv rename to numpy/random/randomgen/tests/data/threefry32-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv b/numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv new file mode 100644 index 000000000000..4ef7172e1735 --- /dev/null +++ b/numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0x86f9f4feeebed928 +1, 0xb3617382bfd2bb33 +2, 0x4314c03ca1908f7a +3, 0xfdbe2ea0213dab80 +4, 0x6076f6f829c64721 +5, 0x6587411cc85fa712 +6, 0x4778e74dc7f92125 +7, 0x6ada4530f4cf01c8 +8, 0xe0ddb30ce61b5172 +9, 0x2998c6e98e79ae50 +10, 0xfb8cb09917a0e99a +11, 0x7df546933cbeabcc +12, 0x972407f8132f16c2 +13, 0x6dcfab42a6d97aaa +14, 0xcbd39869fb69f683 +15, 0xaa789636ea4daf4c +16, 0xe364dbbff8064dbd +17, 0xf639489e242feaca +18, 0xa3454eb3b12942b7 +19, 0xbaa569d8f934bc14 +20, 0xbfe4a0166c493f06 +21, 0x96dec770408b339d +22, 0xc75a3b26b2702eec +23, 0x4752a021254c0915 +24, 0x35edf588263b9bbc +25, 0xa97342f217e541c2 +26, 0xea9bc6a01b4b7d83 +27, 0x93cec444361979b5 +28, 0x8ed5719f5ba9a424 +29, 0x8e1dead734d410b1 +30, 0x1f63a442ce77d4db +31, 0x3c36e0a05da986de +32, 0xc6c10658893be094 +33, 0x196ed853b1167184 +34, 0x8b06218d6a34950a +35, 0xac51e33319f103a4 +36, 0xdf47e4b0ef46c70 +37, 0xf34775455325aea0 +38, 0xf341953786525c76 +39, 0xe9b85d99c1115696 +40, 0x4432daff0305cfed +41, 0x34cc1bfed7b9676f +42, 0x87d19c7db528ca12 +43, 0xaa767030e19682b1 +44, 0xac39890dafd308ef +45, 0x92a6d833ca6a68c2 +46, 0x6626523fdceed4ba +47, 0xa609844feb22593c +48, 0x3d68f39a561a7c78 +49, 0xee2b74bafbe9a80e +50, 0x7f23ba8a58a0226a +51, 0x8900ca1c9d5550b6 +52, 0x781ff936e2d8abfc +53, 0x960fa9c6da5eeab3 +54, 0xdc316a7a5161cd +55, 0x61f6096510d22bdd +56, 0x1c1fc069b6643ce7 +57, 0x3105b8feea7651bb +58, 0x4ea8c76afedfa6e5 +59, 0x55cce3ba46b2ff82 +60, 0x32ce23a4e59a9ddb +61, 0x5d8b33b817a1e1c2 +62, 0x6861f95a5dbc833d +63, 0x1af405acc0346f1e +64, 0x4bea8e5e87e6b3cd +65, 0x6a79d9021478eb80 +66, 0xbd1512cd44c0d03e +67, 0x870719b2e322e44 +68, 0x10eaf80ea8e95a14 +69, 0xad85fdbe2e6d99ec +70, 0x47e9f8f63db20254 +71, 0x69ca77aa6a12ff2d +72, 0x385ec684f96ed9aa +73, 0x573a97f8103f9ea8 +74, 0x57a94ba1ca505197 +75, 0xcb4bbe5444b0b4ae +76, 0xcbe456413a8d1566 +77, 0x67a21dc37357827e +78, 0x992ea6028ade725c +79, 0x89cc89e9570792f2 +80, 0x2b4873ae2a6260c6 +81, 0xec8e07e9204eac1a +82, 0x6bc898204729c23c +83, 0x7d086557a49d391d +84, 0xfa16b7ede631dfd9 +85, 0xf2710cc7516fd414 +86, 0x9aef67d70498456d +87, 0x518f9fc570ea091e +88, 0xe765ca35b2293f35 +89, 0xb06015f656a5ce97 +90, 0xc0154acff67d930 +91, 0x1cb3b41de66b3964 +92, 0x41a024e712b0d577 +93, 0x921572c63007b7a7 +94, 0xb2864274d855fbb9 +95, 0xe555774f7bbf0590 +96, 0x2d15198702e750fc +97, 0x3fb422e738e347c8 +98, 0x8562515206baf50 +99, 0x13dcd174d6640321 +100, 0x2c2d1d739e2243c4 +101, 0xc41b5f458215c274 +102, 0xa6d7e86d348f1f4b +103, 0x9d78f189583149c7 +104, 0x685ac4ec5ac7c326 +105, 0xfb998afb22666cfe +106, 0x5b9df8c77816280b +107, 0x2ebad315b4a6de5e +108, 0xb70f296a67a1ee71 +109, 0x3b714a6ba151c3c0 +110, 0xa0b64d501736310f +111, 0x17f827804629ad52 +112, 0x46ed287bdea3217b +113, 0xb26d12305a6fb5eb +114, 0x184247bba474368b +115, 0x542b93986dd5ea3 +116, 0xb8a0cc8fbd9a193b +117, 0x7a89dcac9c85a621 +118, 0x48d466d072a44c78 +119, 0xada1f7e65a517caa +120, 0xf6febf549d553ec3 +121, 0x19cf94cb14dadd59 +122, 0x9087aeca4e923157 +123, 0x1afb1bb6e2fc9f3e +124, 0x6192b1b315392ddc +125, 0xedcd055d2840341f +126, 0x396cfce39b432fa7 +127, 0x183319afd1d0cf9 +128, 0x917409d968c3620a +129, 0x5868095709377c1b +130, 0x84e1f92faddbb86a +131, 0x45c5ecb0c1bf2a92 +132, 0xc5a7f84f16b52592 +133, 0xb389866b9cca1c35 +134, 0x7924255948cb4bb8 +135, 0x6b4a33d0810f1d99 +136, 0x749800294244b46 +137, 0x4ce2e9d74a34c543 +138, 0x3bf47c412961da25 +139, 0x35ecd46092b0d494 +140, 0x360703f0b4c8fd18 +141, 0xef4f039e6428f8bd +142, 0xfc63479c9833ab9f +143, 0xc660fc00994c3490 +144, 0x57a055abc0afd99c +145, 0xe83bee603058ba87 +146, 0xa6c06409fab71942 +147, 0x8ee4675a90f2eded +148, 0xef7240fbaaa4454e +149, 0x73d0378b4855e043 +150, 0x4039e6cd0da81154 +151, 0x3e4261378314b8ef +152, 0x5f891423c2a77d05 +153, 0xd57c43570ff9cc37 +154, 0x3c69a08bb46e066c +155, 0xe265cba3cabb6fd8 +156, 0xd9bed8fe0179a58a +157, 0x882255210140b153 +158, 0x7d212a20e03003a2 +159, 0x5821c48f435aa8db +160, 0x3ff2fc230e4fc421 +161, 0x7617ac677d8703e2 +162, 0x306c8cf9c6be23ef +163, 0xd7728cfebc614ab4 +164, 0xeddb425f79076eee +165, 0x76e61bc49c5b61e7 +166, 0x803610661e501d33 +167, 0x52c2968fd8b30ba9 +168, 0x56c3d2813aabf019 +169, 0x895c1923a0f7f8b8 +170, 0x2bb50b203d52d465 +171, 0x6987baec87355c0c +172, 0x1186c9e7e524b89a +173, 0xd72695cdee9d1e41 +174, 0x1aed250f3b25eb65 +175, 0x7a98d55cc9b790cf +176, 0xe3f84b1f0a3436a2 +177, 0x929f43e01cdb529b +178, 0xee439860101d371f +179, 0xc30f8f543ea1391 +180, 0x51470330a3a9555c +181, 0x13cbcd8728edb72b +182, 0xc2ff37a63d496acc +183, 0x38a775bab54c9e5 +184, 0xd3b9a106f7cae82e +185, 0x409dbb706362645f +186, 0x6756c88f065e228d +187, 0xfca59c508b33a615 +188, 0x4f1a85c2cf7f70b +189, 0xde05e1f080183683 +190, 0x58cc04c78668d30e +191, 0x29a6cdaabc128bd4 +192, 0x7fd48a7175d7080b +193, 0xf62615d9f1a4c0e0 +194, 0xc0bcdabf943a9882 +195, 0x2e17eaa18c30cbe9 +196, 0x23b0a7bf11059cdf +197, 0x980faafc56997e96 +198, 0x5df31ba1971bc9b +199, 0xf2918ccd892a579b +200, 0x863c265ba908fbd0 +201, 0x6c4d8604d73771f +202, 0x8231891e28337ca1 +203, 0xcf1bca7019e17620 +204, 0xc2914444386dd7b2 +205, 0xb2940f2f54af1342 +206, 0x5f94a7742182144 +207, 0xdd84510e416c55a9 +208, 0xed6cabbc034639b6 +209, 0x8ec7d280a1dc818e +210, 0xff9c27aafcdf6ad8 +211, 0xe4eb67cd34584e9e +212, 0xde9094e8bd9372fc +213, 0xf72c5d7a9f648bff +214, 0xab84eec6625de3ab +215, 0x31401a873557b3f0 +216, 0x3a92ea998fbe33e0 +217, 0x938f51440df1e372 +218, 0x1b8adb3266aa2b20 +219, 0x52614e3f539aa97e +220, 0x8c3910405c2b6db5 +221, 0x5678fa580938f1d0 +222, 0xaecec4c57c393677 +223, 0x25387b15ce263e99 +224, 0xa2064849456b89fc +225, 0xf3d6abe7c5ccbf89 +226, 0x71306e8ce5f15360 +227, 0x9100205404028ff +228, 0x473f2c3ee60b5ff8 +229, 0xa98cccbcb30fd354 +230, 0x150886f18c2a8abe +231, 0x73a10ec9d0a3e5b +232, 0xa04d37f64652298d +233, 0xc47af08c27df64bd +234, 0x127ec96954fef972 +235, 0xd8ce70375554f482 +236, 0xdb2e3388772bb0b3 +237, 0x843d9952b8e93044 +238, 0xb4c50aa1b3ff8dc0 +239, 0x41d43b3662be19e4 +240, 0x5de18309d9cb944c +241, 0xbfcbc63f45cf4998 +242, 0xc58ce67bd9f221ba +243, 0xeb3c7f7349d6876b +244, 0xbd38b8331d766037 +245, 0x5c0de7cf313bef77 +246, 0xe8984144d81c9ab8 +247, 0x42ba3a205f55572 +248, 0x316372b92fd6df46 +249, 0xe7c4b5535873e7fc +250, 0xec4b062406fad890 +251, 0xcb9254c0853f3bc6 +252, 0x6fbb40d1758c5a4c +253, 0xa17b63cb93c12094 +254, 0x3e00a27f4b51696a +255, 0x7dcec0f01bead947 +256, 0x1a8b827e9d0658c4 +257, 0x75929c838a9fc9eb +258, 0x165b162560d5bcc +259, 0x2320fd4ab2fbe43 +260, 0xf0ca89e97c60154b +261, 0x90a3b09348c0caf8 +262, 0xac1516105437f9d0 +263, 0x8f11e6454bea6007 +264, 0x19b8a0c5805ebeec +265, 0x3105e78b4e2f11b0 +266, 0x8c365bc66d26d165 +267, 0xdccf55c3bf85167a +268, 0x926c88470d3a703a +269, 0xe5421ab183b63c89 +270, 0x9fbcfd19c800e684 +271, 0x618b70d50ad85d44 +272, 0xcdc7b4b5f83386e1 +273, 0xb03b91dccaff6125 +274, 0xf470624fdbde22b7 +275, 0xac2f659be06a08ea +276, 0xa49f1af1a29abb77 +277, 0x5c2e94fe6a5d7978 +278, 0xf12b8c7cfa17f5f4 +279, 0xa8c4c5c917203a0e +280, 0xd1ea9aa8c49fa551 +281, 0x7363288bd7b40258 +282, 0xb3668a32f1b36dfe +283, 0xeebdb9e4377e3fc2 +284, 0xa07bf94365ce0a90 +285, 0x49a75731b3efe51b +286, 0x29af2e86886df8db +287, 0x84cab4d861631a0b +288, 0xec45e2345d9c1114 +289, 0x9e0aca51ba3aef2b +290, 0xef6db51f7d2239c0 +291, 0x6bd53260a01e4992 +292, 0x5ff887fc83732499 +293, 0xef39c88e15608f39 +294, 0x166883224e645f35 +295, 0xb296e3561ccc419c +296, 0x342081199780e04b +297, 0xdf24e8c78a472e +298, 0xa64a89e743ae2617 +299, 0x6cc623876bd66b3d +300, 0x45066f03a3fae72d +301, 0x99030d380d113008 +302, 0x891b6637052d6ed2 +303, 0x8ac4de1d3bacdd5c +304, 0x6bd4540970e747b5 +305, 0xb48125e69019055f +306, 0xefc03dc62eee31b8 +307, 0xbb61f62afc671564 +308, 0xf941c67dc61e4f9 +309, 0x58dfbb0f8cdf6857 +310, 0xfdd423db3734d952 +311, 0xddbef0ea939712bc +312, 0x64cb6c97a176d099 +313, 0x57d73985fa34a17e +314, 0xa5241bd90d5a351c +315, 0xc2669439928e2f29 +316, 0x4a00c61ffe77951b +317, 0x562532cdc210a37 +318, 0xe2fb88acfe451d04 +319, 0x8b4053716affaa4a +320, 0x208616d3e2ef242b +321, 0xf830a95da5ba3676 +322, 0xbf01348d4133f007 +323, 0xd44cd6d38e4b2c1a +324, 0xa577c236744b677e +325, 0x1a08ee02ccfaf7d4 +326, 0x94b364baa2e88b22 +327, 0x1278a7e8f3886173 +328, 0x5e5c595c284d8555 +329, 0xe81240395bfc355f +330, 0x5c72a5e76ba9777f +331, 0x30c5587516d5dd3b +332, 0x3a01ab159c61cc3 +333, 0x921a5153ca306f87 +334, 0x499d0410a755a3c3 +335, 0xe35523f8c25a0e36 +336, 0x923135834356ca2e +337, 0xf0d3cfbca4b9c1f6 +338, 0x523ba92f35c890b5 +339, 0x32791ee78e661d2d +340, 0xb8def8bec5d4833f +341, 0x8ddf479407495133 +342, 0x32af2693e93bea72 +343, 0xfe7c577a150a526b +344, 0x29f322d80b5d31e7 +345, 0x770f1c2f276aac75 +346, 0x710d900fa16454bc +347, 0xad35a054b19a6419 +348, 0xf8543705d2221c4d +349, 0x1a208f09dcd992e6 +350, 0xc6fe24f4478fae54 +351, 0x15af9b23589efa5c +352, 0x77c3cdaf72c7974a +353, 0x8b9ee62898b42805 +354, 0x24d86bd194b32df2 +355, 0x8947894a6f9e06bf +356, 0x8f74894e2ebc9e42 +357, 0x30a460a64ac97b89 +358, 0x985f3b650b19bfd1 +359, 0x6b68d65a7decd3b8 +360, 0x33ca1f7082b77691 +361, 0xe16c9da462bcc4c2 +362, 0x85512fb1e448efc1 +363, 0xd23729cdc1fbf8af +364, 0xb4c48c3dd40c6431 +365, 0xc408b5198e25d53d +366, 0x9c3ede789980eac6 +367, 0xea44b85282535bfc +368, 0x8a4ef27cc51a1368 +369, 0x92b1c10cd267b53c +370, 0xe262b216c571e216 +371, 0x9ab945ad23c45d33 +372, 0xf8a6ee8859691e81 +373, 0xb4387e4124b6ede6 +374, 0x67057ebcb0458cba +375, 0xcfea5995ea0d9036 +376, 0xf60e552368e88671 +377, 0x97a744db9ea2a465 +378, 0xf9bdfa8f7765704d +379, 0x4a092a7483623007 +380, 0xd1ec15e72770f23d +381, 0x9f4bddf29a1ec891 +382, 0x7574533dbfd85aef +383, 0xf336b164aa32c8c1 +384, 0xaecebdd3bb1f6273 +385, 0xcdee4c8c59b621f3 +386, 0x4e62a96f422f045e +387, 0x7954b5c0c33402d9 +388, 0x44284a788c4bd72b +389, 0x3f7f331379400e90 +390, 0xbe47722adce724fa +391, 0x202ec17f30c6dfd3 +392, 0x20e6bd8b12ae33ca +393, 0x56ba93c9a6aa537d +394, 0x2ffaed6a56011829 +395, 0x59bf8fb6387acb10 +396, 0x1d092715f75b4731 +397, 0x4f73c9b5945ea6c5 +398, 0x4f9965a9cef20ef1 +399, 0xcce9d598a9ee3128 +400, 0xad6bf86f41263232 +401, 0xb768dbb67c5e35c0 +402, 0xb5c06fa5f590c5c0 +403, 0x2849f01daca38cdb +404, 0xe31daf6540d3c5a2 +405, 0xa462464c813059e0 +406, 0x98cd0da9a864a13c +407, 0xa0bf6269bcb1c79b +408, 0x354467e29dd2415b +409, 0x8760ca9ca2ed96c1 +410, 0xdcbc0296a9d243e8 +411, 0x940f0679c02babd0 +412, 0x4f389795e70c9b32 +413, 0xcad57ca19c578c20 +414, 0x346870e71ed575ad +415, 0x4dc47ca3f25bc1bf +416, 0x636afe20b8e9f185 +417, 0xb47b4b4dbf6ec559 +418, 0x8634686a6ec85170 +419, 0xc176c9709a40fdc0 +420, 0xaf830009e390dfb0 +421, 0x65cb55acd3653031 +422, 0x52d53d142c15219b +423, 0xffe9258ae4b63350 +424, 0xa118cfbbb64e3f6e +425, 0xf0aa49900685c7bd +426, 0xf4a63180c7a493e0 +427, 0xb219297f315c3905 +428, 0xedbe04b3e65cee75 +429, 0x17578b66c9422dcb +430, 0x93341d13d6f3f307 +431, 0x4cb05e69da41bb0a +432, 0x1f1dad0ac8c3b625 +433, 0x4cc0d69392282fe4 +434, 0xa415bcab7a9e9030 +435, 0x49c4bce139b17cd7 +436, 0x70921ec48102ba98 +437, 0xcce784ad8ecc8ef1 +438, 0x1394434e6983851 +439, 0xdceea9694050de81 +440, 0xdd34ce31271e0733 +441, 0xaa722f329463f189 +442, 0xca65b550f35dd0c9 +443, 0x1477d0711156ff76 +444, 0xeff9d7e1e525c056 +445, 0xf425a4a41487a26c +446, 0xd7a62c18f2ce9451 +447, 0x178ad1414c520698 +448, 0xd5fb19755b8a9cd3 +449, 0xf9b662ac336df748 +450, 0x3ab374b95c09392 +451, 0xb1017e23e64343a2 +452, 0x4e38eaa252f0eda8 +453, 0xe50e9e51d4b9abce +454, 0xaa5d9bfb8193c02c +455, 0x823a22b374b70757 +456, 0x31cebbf89930801b +457, 0xd7c29187bcea4c72 +458, 0xe9118fc76c45cbf1 +459, 0x9c71d746e81ad2de +460, 0x61546ce34ed37e5 +461, 0x93cf2b2f08a9dd70 +462, 0xaa8a0e918d246f1a +463, 0xbd35895f4913143c +464, 0xdfe98084bcf724b5 +465, 0x3711d1a09d3b438c +466, 0xef7a4589307c37f9 +467, 0x174de3c95aad64d +468, 0xa66127748de17435 +469, 0xaa7789614da98e6d +470, 0xa01a9a6570b63f02 +471, 0x52e4422529cdf289 +472, 0x5fa480a033fa2eaf +473, 0x8d950f2a0362d44d +474, 0x264fa25f7b50b19e +475, 0x4f2ed2872e35635e +476, 0x1173eaed49ff03d +477, 0x7cbde5b17f7541b1 +478, 0x80913ce7ba0fd00f +479, 0xae85c98e607af8ab +480, 0xd4349f0a1a724b17 +481, 0x436510b9fdbb00b5 +482, 0x345d25f181b23831 +483, 0x360875f99d1dbc3f +484, 0x77657a493413286e +485, 0xdb45294b3f8dab13 +486, 0x25e84d1be5f5c6d6 +487, 0xbb44ba55be3f453 +488, 0x7d7b2c5077ddb248 +489, 0x4c7e02c08f79a63f +490, 0xea589769295ebac7 +491, 0xcf1159ed1fbbabb2 +492, 0x5f0c199a69956db4 +493, 0xb2c190830b28ba75 +494, 0xfef7b55986f49a19 +495, 0x961eb7b425de477b +496, 0xdb31045f05af950c +497, 0x13bc7a5600b306b9 +498, 0xe4834efcc7d8515c +499, 0x6d3ebda0630a9e64 +500, 0xcf453a9b686cbc0 +501, 0xe1048db43e9dc5ec +502, 0x95b3b95608ff12fe +503, 0xdaa8457f1d3bca37 +504, 0x3913e8473f5593ba +505, 0x3afceee33004c5dc +506, 0xd117393f5e9d11f6 +507, 0x7f462da9314f76e +508, 0xa4fc522c19f1f8d6 +509, 0x7429b79b76acdcfd +510, 0x5a570cb8d216a730 +511, 0x705c4c4af10c7ac7 +512, 0x4abf3a808087344e +513, 0xe6313ab9845d433c +514, 0xb038e24fbbfc7716 +515, 0x80a25d4531599d7c +516, 0xb2b75e488f81693b +517, 0x43b8d27a4dbba2a9 +518, 0xa611ff50d23f05e2 +519, 0x872da217d6fa41a6 +520, 0xb153855cda09b36f +521, 0x3c6f5d7d21da31a7 +522, 0x59a63c7ad79be63f +523, 0x27a4679e83422368 +524, 0x4e8bc4d771b0feaa +525, 0x6719469e9cf2c3d9 +526, 0xb56b708a9a915da5 +527, 0x2594e558e515d19 +528, 0xd6df1e4a0bf1b153 +529, 0x4f7f25d38191e1fe +530, 0xaaaf850ad5e538b0 +531, 0x6355175a813e200c +532, 0xbe7544f56eef5ae9 +533, 0x5c516d87bbf779cb +534, 0x23c180f962a3d2a5 +535, 0x5cb1ac1c4261b281 +536, 0x4717bb3567432de1 +537, 0xeb1285580fa935a0 +538, 0xc50894350d82d33a +539, 0xcd0e2cfea37c3245 +540, 0x298bc40ad881a2b5 +541, 0x466df434870604fc +542, 0xbc1eb2d8ebbd351f +543, 0x357534396e12e369 +544, 0x305a159545ad695a +545, 0x63775f2479bae51a +546, 0x44e266968147590e +547, 0xd733336da0cfd6b9 +548, 0x7b1668635266025e +549, 0xe25f2c506843c3de +550, 0xf9635d39029105fe +551, 0x4098dbd2e7b717fe +552, 0xd58848e50b96b32d +553, 0xdf776a82ade5f937 +554, 0xb86fe57c82d76cf3 +555, 0x8cb4f08fb1f46b4e +556, 0x5df5b1c00ab261ac +557, 0x6726d97935f08d31 +558, 0x4cbc02697842c6ac +559, 0x6c0440408a22bcae +560, 0x2327f06b5ef97cf8 +561, 0xabf95d4d77e37c76 +562, 0xc53b4d7aa97f77d6 +563, 0x6964842fd4206b42 +564, 0xee45d852faa5932a +565, 0x607e303bc41e73e8 +566, 0xe604d0952299ff3a +567, 0xd762802eed4cb935 +568, 0x4cf13e77ae1782aa +569, 0x6780f1ac226eb1e7 +570, 0xc102e38a0e8e8199 +571, 0xb97f0632dec2edb1 +572, 0x43b1a8890a987c2a +573, 0x5603f8d9115551a +574, 0xdd523847a2d2346a +575, 0xd9a6c2e9be51ec7e +576, 0x5c87bb42ff344def +577, 0x1c08b83d807a9322 +578, 0x6c79b279737cd049 +579, 0xc75ee98ecd59cd3c +580, 0x318284b03e77d76e +581, 0x6737a1e79456ce1a +582, 0xefe096a77d952f55 +583, 0x37f780c27a9fdd68 +584, 0xfefed1b3b932191e +585, 0xdf552be0dfc09adf +586, 0x4d210f71c1ccfe6a +587, 0xf524993a9f48c96e +588, 0x6fb8c3c46cb1e951 +589, 0x2ac8c28e67eb7b03 +590, 0xefcb311d060d2897 +591, 0x675c6ca4aba62734 +592, 0x1f5f1df09191b5ed +593, 0x177d32b3b4fe46da +594, 0x58f48456e4a88cf2 +595, 0xec0233251bedcbae +596, 0x11046407a9ce0c19 +597, 0x50eccedfa2531ef9 +598, 0x5769c9369f18c53a +599, 0x879442d615c8f67b +600, 0xc7aee966f982a0a7 +601, 0xaadf9a353e6dffd +602, 0x216d2fcfe81b00f7 +603, 0x8b17b3b2a61765b8 +604, 0x7cc969d82c53763e +605, 0x1b1a5d88afda0c8e +606, 0x21ea1e785061959c +607, 0xbbbf45849572539e +608, 0xf84972b569d342a6 +609, 0x85952fc81713400 +610, 0xf6bccc50b5741a48 +611, 0x35106a9ef28f5be +612, 0x785370b833caca28 +613, 0xc6c5c3d1bbe5b4ef +614, 0xda7658fec38bbb8c +615, 0xd3d1e9de94c6f41e +616, 0x73ad91859892dd7a +617, 0x35621a8da5e3fd19 +618, 0x5530b00cd5c63fb2 +619, 0xfa36112a09c088cd +620, 0x302b7f4fc815cd73 +621, 0x1fa4adb717689692 +622, 0x3a15fd5eb37c731a +623, 0xcc854934e21d4cd7 +624, 0x1d11465a34be290e +625, 0x213b3e59f10b1d60 +626, 0xf923efefe3fd28b8 +627, 0x81b56a961626ed7d +628, 0xe4f41f8c283c8fba +629, 0x374ade85b0260e4e +630, 0x4cf71f967d36fcca +631, 0x705b52b4a9d5d174 +632, 0xdc6f883cf909c428 +633, 0x44dd73ed064e8a3a +634, 0xdcff5a374c2641c1 +635, 0xe3177de93b2197ad +636, 0x71f40cde55876808 +637, 0x4c12e600bd6a1b3 +638, 0xc3940e86b962699c +639, 0x133569f533cf1540 +640, 0xcba6db36e8054239 +641, 0xc7c92f14ee34a962 +642, 0x133c8d42f4690453 +643, 0x2a62456f39aa3030 +644, 0x35354ef813ee1dec +645, 0x35e10f4c2f2fb795 +646, 0xf105e888f10c8397 +647, 0xaa22e206ac7652dd +648, 0x65121135905afd4c +649, 0xe2c49866de9626ca +650, 0xeb6ae66e1a605d02 +651, 0x7379ba1f2f16b81e +652, 0x4a3a91e2f22d4d19 +653, 0x30e4af3cd5e5a24 +654, 0xac59e67a483fa52 +655, 0xc4f027dd48c1e37d +656, 0x91263160b58e9e0d +657, 0xc7672b7fbd4ef6b2 +658, 0xf3262da8a7645caa +659, 0x7a5f4990cab96f40 +660, 0xcec55da0937d86a4 +661, 0xd25017295c98b613 +662, 0xc2c9ad08c34fd189 +663, 0xfb6ca6018b1e019f +664, 0x480ee3cc62324c8e +665, 0xab37c56a10ab0519 +666, 0x13fff4e20b1eb15f +667, 0xab25dc0f003e940e +668, 0xdbadd5f2b73aec35 +669, 0xa7b4d6770d19f43 +670, 0xd28144880c1c5434 +671, 0xa435c41dce914dc5 +672, 0x9883a2e3cddd7ad +673, 0xddb29b179c922b28 +674, 0xed3f6669842e0c39 +675, 0xb663238d46b213a7 +676, 0x6346ef1606873452 +677, 0xe7923ae257befe28 +678, 0x848ce090039c77 +679, 0xb77a6da428f4da49 +680, 0x6d9acffa8252ae03 +681, 0xd90d55fd8f8abf1c +682, 0x28718a78a031f802 +683, 0x8305f9005a1b1d6d +684, 0xd065b82167b53418 +685, 0xec65275154e9da5c +686, 0x292c7a783bc2dc04 +687, 0x71aa213998c2c31a +688, 0x114032c57e9fc4a0 +689, 0x67c3675a88faa9d3 +690, 0x7813f653eef4d4fc +691, 0x50004f43e4f4c43c +692, 0x43d3ac5d63714a93 +693, 0x4142e7030323e77a +694, 0x5da693da8e656d6f +695, 0xac696f7b0818c8b +696, 0x910b5df8803af3fb +697, 0x8d89168d50ded4d6 +698, 0x37c31ab0b2635495 +699, 0x66d97616af36f929 +700, 0x2ada02a3c0389bda +701, 0x62eea272c6334ef +702, 0xc8afae44f45ccc49 +703, 0x4978910fb289af22 +704, 0x64590f6a489183f9 +705, 0x594837052d1ee56f +706, 0x8553a88dd84e460c +707, 0x5c11e1d61832edfe +708, 0x7d5b6fde3c05ef8d +709, 0xfaf96bbdea0d6f11 +710, 0x2112b6f8f25fc3b7 +711, 0x6ce347dc5bd8d9f6 +712, 0xb072e2c4076aa185 +713, 0xf4162f4ab453ead3 +714, 0x369789462fc197c7 +715, 0xe732c5b207c55f3c +716, 0x4689ce674194c32c +717, 0x6bcf28130ebd7bbe +718, 0x4d7a25def10edb97 +719, 0xc4a2283e380f5239 +720, 0xab31536a95f7e336 +721, 0x50c1ecd9e4dec3e4 +722, 0x1bbea15462cfde71 +723, 0x1e7c73d56d6e939d +724, 0x7c46fb35982735db +725, 0x83c23f93c4221593 +726, 0xddc566e8005e0e6e +727, 0xd0551a666c088325 +728, 0x2c57b590ab686557 +729, 0xf2e9351a14724fe1 +730, 0x45d25cf2ebb2ee0d +731, 0xbe23d2a8fc7aea1 +732, 0xc721cb7b65d8dd7b +733, 0xe6642683775efcac +734, 0x6c29ca0adc0a83e0 +735, 0xd0de3128954b2eef +736, 0x7abea9b318f9a544 +737, 0x3a63475d59d64b22 +738, 0xb804c9cd589c817 +739, 0xfc4f880ac9dbc246 +740, 0x414d492c8870732f +741, 0x3ee15c71660a8129 +742, 0x57f4ab3a25da00eb +743, 0x5a1d89d6f9eaa29f +744, 0x60139567a3d66313 +745, 0x5759ec448bbaba05 +746, 0x44d3088d8cf1cc1 +747, 0x77d8019fadba610e +748, 0xcdc729417b13904e +749, 0xdc77421f8b2bfb0e +750, 0x47ae0c4222bc1d4a +751, 0x22768d4b89156cbb +752, 0xa60d3ef97eae8ddb +753, 0x7aa22493dbfceff3 +754, 0x2ee0ee06bf9a5fb +755, 0xd54b7701d7afc96f +756, 0x1aa49ed985a53efb +757, 0x97d6fad17caacdd3 +758, 0x1b2f6dcd1d10fe +759, 0x46347f5bcca0f422 +760, 0xb9dc35c224242d3c +761, 0xb5dd657190fa8a03 +762, 0x50ff9434c7862fae +763, 0x7a05cd5c25bc1209 +764, 0xd5aa141a498560a1 +765, 0x73c62b8d0206e8b1 +766, 0x740f369af4ac9f51 +767, 0xe7479d9a0716b94e +768, 0x8b3d0375452d633 +769, 0x6ed58c4d905dfe37 +770, 0xbefb7f1e9c79f6ed +771, 0xe2cd7ee311d7a8c7 +772, 0x932cfb8178492b88 +773, 0x8e39205fbe47711c +774, 0x149ea35973cc055e +775, 0x96b73b6cfad8ad7c +776, 0x572898ff1f967eef +777, 0x795e8172b62cbf69 +778, 0x4e3d34c5bb921c28 +779, 0x7a4c623c7295f4c3 +780, 0x15b7ca7ef7179a7 +781, 0x48340589636b223f +782, 0xfcd61c186913a7aa +783, 0xf4f7f0cb49d78f5c +784, 0xb9591798ca218218 +785, 0xe304bc438ae109a6 +786, 0xe65890c4bed537f4 +787, 0x54719032d537f085 +788, 0x927bbdd2931be349 +789, 0xfd4a852025d02c14 +790, 0x915a7c2bc713221c +791, 0x4adac4a960ecdf9b +792, 0x58133bde7f0edb25 +793, 0x73d00fa5f091794f +794, 0xcb2fe411bfb56cf3 +795, 0x54a4f66f2c5f6220 +796, 0x125bce09ee493ea +797, 0x766ba624e5f3b266 +798, 0x884478527221bba1 +799, 0x8a1920c18ba6676a +800, 0xb0c08f7fbca3cdbb +801, 0xd3b570c49c774405 +802, 0xae4a55264d8e012f +803, 0x91a25b7c5e5872a9 +804, 0xeb65375cda8296ef +805, 0x149f98de1b29f459 +806, 0xe00a81c67b8ba093 +807, 0xbd7da1f6c6be49f3 +808, 0x4ad7c327a630b482 +809, 0x7efc93c60449206a +810, 0xff182d272189a04c +811, 0x4e7892e8adc82e19 +812, 0x1327926bc36b7f99 +813, 0x9b6a8085d12fca4d +814, 0x34a29cb661d313b9 +815, 0x7b3398923572c6a4 +816, 0x8b3ff461c821a464 +817, 0x8e5581286f82448e +818, 0x82a8d223a7b6937a +819, 0x1a0c750d6029237a +820, 0xf19a0a7f578497a5 +821, 0x2e6a85391da4f651 +822, 0x98676879af572d0e +823, 0x50110f1f738507a0 +824, 0xbe88faea0d4f8cf4 +825, 0x183bdc54555acc08 +826, 0x1d4dd72e0c7a82f1 +827, 0xef500f1dd19059f1 +828, 0xad98db5c386d33a8 +829, 0xa17bbcaea00a9361 +830, 0x8b8967126839c74d +831, 0xcc9d0e484a9b1dfc +832, 0x4216966d5af86872 +833, 0xdc3f8b825876e2ef +834, 0x3ef820c11b63f9f9 +835, 0x78da1c113cdca011 +836, 0x7f74559d9177c87 +837, 0xfde51ee31804305a +838, 0xc491d970fa5ce907 +839, 0x89b0ff390723a6ff +840, 0x7452028822f2d7bd +841, 0x3e55cee332d78047 +842, 0x5dabead1e04596ed +843, 0xc4e878a6ba18aec7 +844, 0xa785fac229f7f353 +845, 0xd95155479c867ad0 +846, 0x678fdb174e3774e3 +847, 0x54106e733d27b887 +848, 0x60bdc0fa294764ec +849, 0x55f1d4270179bd54 +850, 0x80165190a3df59ba +851, 0x81b128a7508d2174 +852, 0x831d78b199fe132f +853, 0x80ee7eba239ed866 +854, 0x359f1906550f62bc +855, 0xe293dd490df5f745 +856, 0xf3362af4b0de9c01 +857, 0x9cdc46fbc7f9bee8 +858, 0xe577a13809850692 +859, 0x1490ed2b4ed8ce8c +860, 0x63b861e371a125f4 +861, 0x49916e67be281c2e +862, 0x1a3a8999e60fe603 +863, 0xa373c8ff642e222b +864, 0x8112bea03196843c +865, 0x29c507a4ee61f7c2 +866, 0x4eedd845cd786583 +867, 0x1d9bdbe51c1aa7c7 +868, 0x3e5d043d5ab768ad +869, 0x8a3c0e9801e39bee +870, 0xc49cd378bfb3c516 +871, 0x1b9ebe1f63af91d4 +872, 0xe44afa8dcf0f28f5 +873, 0xf5a7ab4f9a8d8cc5 +874, 0x8ba7cba3af03234 +875, 0xe79397a55e04d4b2 +876, 0xc49014ba09442ad4 +877, 0xe58a5dd949723f3b +878, 0xd67c781ca27169dc +879, 0x409f1435da244c9a +880, 0x7ec9df0b04c17696 +881, 0x8a34c51bafd6e390 +882, 0x2f60cc0ebb4a781d +883, 0x161283264abcb573 +884, 0x9c9db4bf55a46c8a +885, 0x381e6106ff6053cd +886, 0x6e8fd5a7b8ed1c18 +887, 0x89d0da00aecbae85 +888, 0x1baffa4542d298f9 +889, 0xbf53f2e1dc44d359 +890, 0x4c31d9bd148120a8 +891, 0xc36be4d6404a748b +892, 0x400584c614a63b32 +893, 0x6622b75443cfa5dc +894, 0xbbfcae44c8eec3d +895, 0x28dbf6790e9ad12b +896, 0x7779f5d56f2613c3 +897, 0xd221ad0b4c565a5f +898, 0x4949752332a98b9 +899, 0x5bd9931a164b2717 +900, 0xb5108565cbec069b +901, 0x2e8491298f41ecd8 +902, 0xc94483fba700a620 +903, 0x7c1299ec45d1e22 +904, 0xf37c3a7e7e020358 +905, 0x3635565fc484cbf6 +906, 0xa93b65e210af2a2b +907, 0xcf18d773960a3667 +908, 0xa7529ce40290e679 +909, 0xd539e8afab9ff21f +910, 0x44fa456fc4e2908a +911, 0x138e0dfef16de572 +912, 0xb55ac8aa42abe21f +913, 0xc8a7a9ed90a4920a +914, 0xcc0f0dff8f4f1fc0 +915, 0x78c99cc82195feac +916, 0xa7669ab9998bdb89 +917, 0x2bf510028d6ea80a +918, 0x8995287d2a60326c +919, 0xb3c5676e9772daa7 +920, 0xf210121d1f5cf3cf +921, 0x3ec0fa808fe50e83 +922, 0x42f5269fd9717a58 +923, 0x7603ca20951ebe1a +924, 0x7f75e4c3afca107 +925, 0xa08af524629c434d +926, 0x1d144241418f216e +927, 0x7cabc46fab0dfa3b +928, 0x317172e8fe407c21 +929, 0x2694bf3be80d8b3c +930, 0xdf18b4db02b875c5 +931, 0x5df0cb415bc5a2fd +932, 0x954386c3df63e124 +933, 0xf0ad49aa400ee528 +934, 0x2a941df25bb38eb8 +935, 0x3b43af03f2d3eefe +936, 0x7a58932cec64555d +937, 0xabb56ea03deeaec1 +938, 0x33673826e58f9a52 +939, 0x8cb6fb8e42cd9f80 +940, 0xda88c439fe3b9dbe +941, 0x31cb50c4a69d5883 +942, 0xe2164f69f02e57e4 +943, 0xb6ea04dd0ba2811f +944, 0xb3458306841de334 +945, 0xbc6cd1a3cf526a19 +946, 0x9424b50438e687e2 +947, 0xa668fa546aecdd82 +948, 0xb8783bd3623d86f5 +949, 0x6d4341f1dd170d5c +950, 0x1202c1b457913af9 +951, 0xf2b532602b908de1 +952, 0xb15f6354e6482108 +953, 0x4a542e16c973ef2f +954, 0xcef0b8ef4bcbbf64 +955, 0xdd7090f21726ab28 +956, 0xd53de858192a0094 +957, 0x58e723302bf4d675 +958, 0xc3ffb98f745409ec +959, 0x5489e4fa52210035 +960, 0x3a6a10b142c74d43 +961, 0x69436c7b12a2c4c7 +962, 0xccecdcc046f76f03 +963, 0xa6b9793a0660fc0f +964, 0xf114cd63b38756a5 +965, 0xa44ac409c2246f07 +966, 0x65dd5dde54b6aa26 +967, 0x5df21b90d999494a +968, 0xafc3d89336a6d356 +969, 0x1acc23065a7ba8bd +970, 0x87ff903278b23e2f +971, 0x58e4a44f7e4c012f +972, 0xb2eb460bab7744a1 +973, 0x9b1aa5a17ba581c2 +974, 0x90c87a15edc021b4 +975, 0x43369d9b481b28a5 +976, 0xd05dc8b00763dc1 +977, 0x40f058f20d77b5e6 +978, 0x2502c9829f78bdb4 +979, 0xa5ef6729f601b2d7 +980, 0xab49116e5d404023 +981, 0x6b77c686cd653da8 +982, 0xd99e324ce1468143 +983, 0xb338c64071fd5469 +984, 0x94f67b1e04fb4267 +985, 0x16f34d11e280c73f +986, 0x9a6c4cd947bed4e0 +987, 0xd1bf20f05cd068f0 +988, 0x2ced63b15eaa27e4 +989, 0x95989123251dec6a +990, 0x38906e5a3cb4fb01 +991, 0x4b02f03a01180ba3 +992, 0x67d5842c2b13960a +993, 0x45dc1d0f5981374e +994, 0xe6dbf0961817185a +995, 0xf5717f537c683578 +996, 0xf7a689617ffe5002 +997, 0xdbd1595a8ec1ac24 +998, 0x545db9592b492be4 +999, 0x9e1085dc2c3335ed diff --git a/numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv b/numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv new file mode 100644 index 000000000000..2de341ecda94 --- /dev/null +++ b/numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0x509946a41cd733a3 +1, 0xd805fcac6824536e +2, 0xdadc02f3e3cf7be3 +3, 0x622e4dd99d2720e5 +4, 0xaacfd52d630b52bd +5, 0xa94fc32eb4128023 +6, 0x9ee359839e68f625 +7, 0xd9f180e03b686e4f +8, 0xd6825e7d8fc65068 +9, 0x887f15071c20b9d +10, 0x6dc39f8336eeaa66 +11, 0x13d17509661b69b +12, 0xdbe703ea4e61caec +13, 0x1a4deda7c51c5b7b +14, 0xe2f2259fb30bafcc +15, 0x7eb5a4d5f053fcbf +16, 0x4704d55257921919 +17, 0xcfeb1c70eacd6734 +18, 0xed98c92a0d6b8b3e +19, 0x4efb928a052188b7 +20, 0x15617edcea5e98ab +21, 0x8ac022e71a4d1a40 +22, 0xe0ae2cdf81cc05bf +23, 0x11ae6d329bc72f19 +24, 0x5369885a834c1073 +25, 0x7a865692c8495a12 +26, 0xaf752d7df50f6968 +27, 0x4b81c799c968e005 +28, 0x4104e06972751b34 +29, 0x8600214cf598d6f6 +30, 0x444545884a4b0a80 +31, 0x2d13243847e43cfe +32, 0x6064921c3b70601c +33, 0x1b2c2f204185130e +34, 0xac1e21160f7e90f4 +35, 0xa718d564118e2bca +36, 0x25fb8750f330bdc1 +37, 0xcdd8329cb365e06 +38, 0xfdcfbff05c3470e3 +39, 0xcbce143aec5155a5 +40, 0x1d17b5b1e2c3c21 +41, 0x68fe2fbabc30aa23 +42, 0x19086e8dbd448c02 +43, 0xdb7d8126e6f3d1c6 +44, 0x1865e34fb131a69f +45, 0xce3be151debb3e9a +46, 0xdf573313ce569b70 +47, 0x3a7fcf8ef4fd495a +48, 0xe26450c5ec487bcc +49, 0xe99eaeeb35354e +50, 0x959e7e6cb8bf55d4 +51, 0x3ba4778a79b1b758 +52, 0x30e4f35a940c2e04 +53, 0x67717bb8a50f2c22 +54, 0xa9b3e9db4934cd8e +55, 0xe22bc184e5d2ad8d +56, 0x7390583f39dfbb76 +57, 0x19e7ba95b2482b72 +58, 0x549b0c65abc1615f +59, 0x43989e0d7268118a +60, 0x1376e3b4f7319b9c +61, 0x41bc4dd69e4a3eca +62, 0xdb5b777a0a90e830 +63, 0x4885cae86597a2fd +64, 0xe472ab9f66c240b5 +65, 0x387e53bf7d31a3c0 +66, 0xd8826e1be0364bef +67, 0x2a334c6d6f748f84 +68, 0x10c7d9da8f7ba2ce +69, 0x7b23655caa5a3872 +70, 0x4e52d38a6128c877 +71, 0x581cf9ba515b9abc +72, 0x464df6946cf89b19 +73, 0xaf0f20053d807827 +74, 0xddeb1fe3d90b8aa2 +75, 0xccb863176382287e +76, 0x831e79b8d6d91e8b +77, 0x88ed0822fceb3abc +78, 0x66adaa8387e19785 +79, 0x23a5005fb1c9c598 +80, 0x4ab28f3b1585657b +81, 0xd620ca461099e06f +82, 0xf056f4fdf816bab5 +83, 0xeaef5b9b3cdb015c +84, 0xee4f14793695313b +85, 0xaa406259c23ccb33 +86, 0x9ec3e4585b6d933f +87, 0xb5806dfe257e6c7c +88, 0x7bee992cfb5fd41 +89, 0x91a70b316b42bd18 +90, 0x874df34eea24edb5 +91, 0x379a0a3ad79d7db2 +92, 0xeaea9f7eb0292235 +93, 0xf4742d169fbb5198 +94, 0x57a84e20592727d +95, 0x5d8ec89195373de3 +96, 0x22eaeb51baa32533 +97, 0xc3cad6ca8be847bb +98, 0xf316a8b9b6172611 +99, 0xb687d7988a8a2ee5 +100, 0x8635d3f011c6253a +101, 0x2280ec837c98731b +102, 0x2f815c82713ebd61 +103, 0xb2b4c124ac4ea1a9 +104, 0x5db6c0a6a90a1866 +105, 0x3cc317501c96e9f8 +106, 0xd38b689a10819dac +107, 0x1b8a114bbc51341e +108, 0xa276c85761cf5978 +109, 0xe6b3d7d5b3b6dc0c +110, 0x14963fae33e6c2fa +111, 0x88f83f53a67231d7 +112, 0x77aec607b4aacad8 +113, 0x33cddae181b93178 +114, 0xf1bfcef2a7493c7d +115, 0xc4177359c975f669 +116, 0x9d603ef0b6bee8a2 +117, 0xc16ee77a4391d9b1 +118, 0xe93f0736cbd3f398 +119, 0x327500ca9afb0730 +120, 0xd8cba3672638e75d +121, 0xd87f00175eea9770 +122, 0x6680cfd0f0651f47 +123, 0x13287cbd1981e44d +124, 0x9da5fb61bd633e98 +125, 0x2d704f64c4ad5444 +126, 0x4c28b98c2f7349e +127, 0x42d156862c609af0 +128, 0xcbd49a9595d2964e +129, 0x8d54cf464a529131 +130, 0xd6b74f26dd0e313d +131, 0x4ef8b45baf3ec3a7 +132, 0xfc8be973c860481c +133, 0x6112312f08028018 +134, 0x78d492d0049b30bf +135, 0x3160db98b853a1a5 +136, 0x81eb3fabead6d97a +137, 0xfb54ee3224945380 +138, 0x3c62663cd2aa07dd +139, 0xeaa2eff9e2752bb4 +140, 0xbdecb6e8041eccf9 +141, 0x9a135a78514e92a2 +142, 0xacdbb7139969ae66 +143, 0xf71fc98126f511ba +144, 0x1bd6dc2853a20898 +145, 0x6fb80e8eff8b26a3 +146, 0xfff9ba38f9c3664f +147, 0xa4224ddddbe3a700 +148, 0xd76b8f1bc09e35ad +149, 0x1b6c5bdad062aae9 +150, 0xabc5a61088f2a3f4 +151, 0x5160b68fd92f30c +152, 0xb2cd4c619e1cb446 +153, 0xceffe90f16c69c0a +154, 0xd7845f2eb8b1bf67 +155, 0xb6ddd2d76e99be45 +156, 0xf6212b33d0bc1019 +157, 0xdebc75b6e2d6db50 +158, 0x7a6d61de4c4c3a9e +159, 0x473933055a8727a8 +160, 0x83ca458dff43a0aa +161, 0xde2b9e38b321aa3 +162, 0x78ba83864952e9de +163, 0xdb4c6db1049e8406 +164, 0x9c3a30ffdcfac7ee +165, 0xeab6e9a0cf1ecd0a +166, 0x3617b147dd5ce2ca +167, 0xe5c000907864b48e +168, 0x7dcb724b2767b90e +169, 0x4ecd7ad20e75e566 +170, 0xe03be67c421d2942 +171, 0x7e7a68988cd564d3 +172, 0xa8c25e5165919c51 +173, 0xa1d550ed4a39e690 +174, 0x6e7abdcf98453f72 +175, 0xe57eb7d34da3c5b +176, 0x8da6eebbab5ef00a +177, 0x7574363208ed2700 +178, 0xff06b2a934a953b9 +179, 0xf3c8951de92dcabf +180, 0x78b817c0dee711db +181, 0x358522c82c15f627 +182, 0x81d54c2d5ef396b8 +183, 0x1f98c21036a70b27 +184, 0x4d3692ad8d5e5112 +185, 0xb63674f55b06bd46 +186, 0xbf30a7aada9b1cc2 +187, 0x57f75205e81f6b47 +188, 0x37e9ab7e796bd0c9 +189, 0x34aad24654a70694 +190, 0x5602376e46ea14ea +191, 0x3761258bc9e79732 +192, 0xffe7d79561680d75 +193, 0x35b82f78a688b86e +194, 0x42d23cba46456a80 +195, 0xd64f0c226c84d855 +196, 0x6ef5d71859f03982 +197, 0xdb7dabdf5282c818 +198, 0x94ec7253c617acfe +199, 0xcc118236ff2009fd +200, 0x9f91eaee04579472 +201, 0xbf79aadb5a3a4a1e +202, 0xf6ac29ee74fae107 +203, 0xc82643f14e42e045 +204, 0xb08f864a06e4db72 +205, 0x7a2a402f1a000aaf +206, 0x2c2e03247fad91fd +207, 0xe70bb051040fd7bf +208, 0x8d42d479e23862ed +209, 0x3b2b368d659b45f8 +210, 0x96c8d7c31b396bc5 +211, 0x41664c476575aeea +212, 0x303ba0289cd281fa +213, 0x2936193bbe462f68 +214, 0x4a63581937611f45 +215, 0x10f69bed29c2a652 +216, 0xcda3073cb7dd2082 +217, 0x374da8d58157bbdb +218, 0xf3c040dd9a135d51 +219, 0x5ae628cef3e753da +220, 0xafdfa06ac9ed9eda +221, 0x94582756d1cc948b +222, 0xce387a039a43baa5 +223, 0xd9aab74b36032cb4 +224, 0x720e30cbfc81765f +225, 0xba42d487e461d31 +226, 0x445fa16350da585b +227, 0x43a3b57501104e19 +228, 0x55571957e6267eb3 +229, 0x8c1f8cc37a83b2cc +230, 0xdd433be6a0188876 +231, 0xdd0c1053757845fd +232, 0x47d17129bdec523 +233, 0x5fdc39aa7f38cf97 +234, 0x92ab54d8c66e4417 +235, 0xf46a39cdbdee494a +236, 0x6a226e83cc244891 +237, 0xdd2dde8767318719 +238, 0x794e882325646a7 +239, 0xf1d269b9fa82e09b +240, 0x5871ab313f97bbde +241, 0x30a0f742fe7a1746 +242, 0x8f3b8c2ef199341a +243, 0xf280d28fd6ab1ade +244, 0x8b5e8a112798cd0e +245, 0x80cc043e4ace43b +246, 0x1dcd69d6d8f6c527 +247, 0x467dc81c1f462ff8 +248, 0x47e98dba34af7440 +249, 0xae4599c86b11c6d5 +250, 0x4cc5574019676ca9 +251, 0x79b0a34fc332cfbb +252, 0xc5c778c13974e8 +253, 0xa1773cddcb7f3bd +254, 0xae20dcad57acc7e1 +255, 0x11e6e98c02b4ee9f +256, 0xfedb58925c42929 +257, 0x2ab56b3fccf3c5b6 +258, 0x5740e0a90920bbdb +259, 0xe02ea72778a4cc5c +260, 0x7fa9448e7563e3e +261, 0x907603f2ccd28776 +262, 0xc655d1fbe3fbf1e0 +263, 0x40bcc587212acc1b +264, 0x1af8bcb6c4902043 +265, 0xd47a71193454c4ba +266, 0x9e9cb523c3c9dfe9 +267, 0x4b9e107b36ba9f0b +268, 0xc89d86427a63c956 +269, 0x2353f37179b7147 +270, 0x7c6d3c3d67f1f245 +271, 0xf008463da2875270 +272, 0x4494eb9f1d83aca9 +273, 0x84dc57b61ca36077 +274, 0x461480c6f708fec3 +275, 0x6256b05de4b8233c +276, 0x2b02af1084a4dfd5 +277, 0xd4f3bb079fb41a61 +278, 0x83ee412671f4ef78 +279, 0x6c46e97c8f197f8c +280, 0x4d949413ea0d1e9d +281, 0xd7eef89a4d084d17 +282, 0x18f03d6a52592eec +283, 0xaf6fc843c53e63fd +284, 0x551f420f53de9097 +285, 0x4fa8dd599dd1365d +286, 0x399727713519d072 +287, 0xbdf7dbcc18541feb +288, 0x3f2336894ebad1fd +289, 0x903a74b979250389 +290, 0x733313e457a65fe +291, 0xd189b01b9258d1c5 +292, 0xb2d9533680f9a70b +293, 0x2a0929d54aaae5c6 +294, 0x9c6b844de0367b34 +295, 0x341d37b0d1e75bac +296, 0x5cd370014b87cc94 +297, 0x4bdb409173abcb35 +298, 0xafd38d4c9d91240f +299, 0x76d7d551533f344 +300, 0x3779e62cbdef738d +301, 0x211052148f86c129 +302, 0xf2f325e09a17da4e +303, 0x1e874c70b2d62dec +304, 0x412fb842edc1c3f0 +305, 0x23d9f5e6c9d83d27 +306, 0x8e58937e012d3c76 +307, 0xb0ab1175918a765 +308, 0xfc7991f83e0e06fd +309, 0x1066d7c10f16cf5e +310, 0x29a14ec418defe81 +311, 0x20f98e60c158d08f +312, 0x463c0497605efae6 +313, 0xdd02ac91db3f0cb9 +314, 0x434cbbb353edfa66 +315, 0x892ea5a463774836 +316, 0x8e00064e77225923 +317, 0xca7ec8ebe244a404 +318, 0xa9146f68a99e0a77 +319, 0xc85ab0fd6c4c8a99 +320, 0x4a1104cb1287380 +321, 0x25a570b6e2b45828 +322, 0x3e3f5935137b0d61 +323, 0x499d6aa0407317b9 +324, 0x4ab08263445a3fee +325, 0x2dcd45f060d8f5cf +326, 0xa73225adf6418dd1 +327, 0x738ff6caaffb838c +328, 0xa93e4a4d2330026e +329, 0x47421b8206cf7ba8 +330, 0x5d9ad2876b1a4e84 +331, 0x6557edadf965aad3 +332, 0xaeffe33ca45ac0bc +333, 0x2196b20f7074c7d2 +334, 0x351a0c784e1056b4 +335, 0xfefaa1eca46cba97 +336, 0xf58741e34d53876e +337, 0x5942f6de49d5cade +338, 0xe1b0d6514455ac99 +339, 0x456dc6a18b651d36 +340, 0xa8d240033f5c9074 +341, 0x7d758bc84ec678bf +342, 0x21ce28f61ecde645 +343, 0x83b8f058c1b36557 +344, 0xeaf452c4467ea627 +345, 0x60bb8582e53d2f9f +346, 0x9649572eaa40c725 +347, 0x59533356c226c99a +348, 0xc06b7f790fd4fda1 +349, 0xdb7d827921aa5962 +350, 0xd9be204c05438878 +351, 0x67f903bed4fb0450 +352, 0xf8e583b98827118c +353, 0x72c8508fca1e207a +354, 0xcab1df54ae1542dc +355, 0xaaa774d0c8833857 +356, 0x710c4b86e747bbcb +357, 0x8ffc4dd34d5f12db +358, 0x3b1d4fbe64743023 +359, 0x3ca88da03e8d8da2 +360, 0x970b522fdad62c7d +361, 0x7596d74c3e598a71 +362, 0x1e9c86f3b5d93e5b +363, 0x378a3fe78b730c3c +364, 0xfbc82d6ace6346 +365, 0x1eddf6aca48b7ff8 +366, 0xed12c2c2e137a0c6 +367, 0xd2001d92384c365d +368, 0x69a1bad8bc8742eb +369, 0xe1b460d2e65e9a74 +370, 0xeff030a0954e3832 +371, 0x23ac5413d4b3e60 +372, 0x802fffd55c4d2279 +373, 0x1776b952e25fcacb +374, 0x595f3f386b0f524 +375, 0x3f2d5e55b839c40e +376, 0x145202db5650c14d +377, 0xc28858131b702442 +378, 0xa1381d43a4f59fcc +379, 0xb3088835a18600fc +380, 0xca7830bf9187f705 +381, 0xa189dbff019ca64d +382, 0x82ad4b1f88491340 +383, 0x27262f1b70bcc1c7 +384, 0xaa52ad0b4cdc95b9 +385, 0x6898a6e5a791cca8 +386, 0x4c892bd369fb7c7c +387, 0x2c5040316ad789e4 +388, 0x25aceb42f6d853d4 +389, 0x8f3e09dd6e6fcacb +390, 0x35f4e10c7b4e29cf +391, 0x6156e9fcc26a6e83 +392, 0x8a8389e8a9c70fda +393, 0x81219b723a3dd912 +394, 0x631f0c99c62650e +395, 0x9cec1c4f650d6c4c +396, 0x1d3b402d466479aa +397, 0x6d2fc0877f6f8e46 +398, 0x2000b7178225c4c +399, 0xb01c45dca932ffb2 +400, 0x61f25ea549d3b3ef +401, 0xfc0733a134f7bb8c +402, 0xea3ab2a0cc6a366d +403, 0xe26bf2b8fe0db591 +404, 0x3186c9cdd8757ee3 +405, 0x9cb472c0c526cf7b +406, 0xdafe18916dbd33d2 +407, 0xe0b15a3aed330dec +408, 0x7079ae5641dd16cc +409, 0x49b6b9756c347b90 +410, 0xdda875fe11e94d34 +411, 0x8c77fb380278f362 +412, 0x602904b0cd3bc464 +413, 0xd2dc40f56fc531be +414, 0x753175bcc1a93ba0 +415, 0x333a71f4d2d756ea +416, 0x7b862ff73b46e03b +417, 0x9df539d017e9017e +418, 0x4113e5be11f63f2c +419, 0x422942050abc4fd6 +420, 0x737b754e2add8d6a +421, 0x313e6c1ecefdca96 +422, 0x5436d70ed2ee4cdd +423, 0x1db894fde99e34f6 +424, 0xd86bc0b79db9a96f +425, 0x9d904f0aca534217 +426, 0xfb14afbeabfc04df +427, 0x9c4ccba431333edb +428, 0xc7de0af1a5760939 +429, 0x735669225566ce71 +430, 0xf5815dabb0665733 +431, 0xf0a6b7c00d4d569 +432, 0x1448e6fe1432b7af +433, 0x2e0586f6c9e6e7b1 +434, 0x7b75aa00eb44d795 +435, 0x7ba5cfa018a44c87 +436, 0x5854a5f78e636c5e +437, 0xdcbe856037d0228e +438, 0xe8882d90f7259452 +439, 0xcb6ff056c4171c82 +440, 0x4a7bd2245f0e0e32 +441, 0x3e2a40308897a793 +442, 0xe404dfa4d3284167 +443, 0xab022bce6ad8cbc +444, 0xbb5a145064db9976 +445, 0xedd82ddea103ab7e +446, 0xcc906d55fb10a8cc +447, 0x63ba976a36e0cf56 +448, 0xb3ef5ad3129eedba +449, 0x409b01e4107e9dc4 +450, 0x41059d8141efd96e +451, 0x10bc4a29ac5cd941 +452, 0xe2fd0fb5c7787046 +453, 0xba24bd0f8d018cb3 +454, 0xc9cf71f73e6979f5 +455, 0xd79a917354d39e89 +456, 0x44fac8764c14e096 +457, 0x29c2cdcce0ce515c +458, 0x41c6704b232934ac +459, 0x2ace8d883c6ed401 +460, 0x76d37e5aa3c57f87 +461, 0xc7b7ae6275c47624 +462, 0x33e426b3e22bc96d +463, 0x77818a58fdc8b640 +464, 0x49c3b6b021037e35 +465, 0x8a941f067ca1c772 +466, 0x8dac8803caad398f +467, 0x2478a7f23abb4332 +468, 0x98ef79938ccc8b65 +469, 0xdddd5e6776f61726 +470, 0x8d9412cdc85ab90d +471, 0x901946d2c1a63b26 +472, 0xc93fbcced6bacc00 +473, 0xabc3dfbdcc9b8fc +474, 0x6b4ba01186620ec0 +475, 0xbb32573515ef782b +476, 0x174d712e47dc77ee +477, 0xd0528205819fe3ee +478, 0xab1f77e5dc7b0e95 +479, 0x7f86317fcf8bc84a +480, 0xa7806c55ff0b4f49 +481, 0xe8cdce88ac77263 +482, 0x2e497636f939d7c1 +483, 0x9ff5e2c32edc3ee +484, 0x71579e5276731bbf +485, 0x565c679f3f2eb61c +486, 0xc2a747df0c436c +487, 0xfc30f2f9d9489081 +488, 0x74548f1d9581fed5 +489, 0xb5819230ffd9afeb +490, 0x228ff1227ebe13cc +491, 0x38ac137ff54ff158 +492, 0x41ed776d549ca7da +493, 0xb4cfe4cc90297ff +494, 0x17988d6ed8190a5d +495, 0xe27817eb69723f90 +496, 0xbe1cee1533890e29 +497, 0x8ee48e99d9a74f22 +498, 0xa31a5dceb1db5438 +499, 0xeecbbf998e1c0d43 +500, 0x6f8e0b0b2b361b9b +501, 0x2a102fca177728ae +502, 0x55a27f350de42380 +503, 0xc45ace761d5cf37b +504, 0xe14d0182a002d8a6 +505, 0xc05841ad2de5d64 +506, 0xca6b7b7131476892 +507, 0xe4a92da10eada512 +508, 0xf7a33c11f8927959 +509, 0x7b47639e2bcd8c44 +510, 0xaed8ec8dc551d755 +511, 0xba4b5ffd28ad78b7 +512, 0xc30ddd4d1df6ce2b +513, 0xe1b9bd0020b56548 +514, 0x8f73edbced893634 +515, 0x738098d32669cab4 +516, 0x28c03717c5adc3c0 +517, 0xbc044ebe07a8f4f3 +518, 0xc3083814802950fb +519, 0x8639da9ccdd4068 +520, 0x2ac89cfb975e2c41 +521, 0x8e163ccdbc863461 +522, 0x4a60169f9a3648fe +523, 0x6694ab36d7d02548 +524, 0x6b4e5764db952413 +525, 0xbf842329b9a13bfa +526, 0x1c8639cae82e7d92 +527, 0xd5669e818fb34170 +528, 0x1f4df6bc59f9f6aa +529, 0x8b192245d457c5a0 +530, 0xdff62af9d9eb696d +531, 0x53dcf9276ae1ab0f +532, 0xc1c4052d4c9d3c16 +533, 0x5c5f7b33e6aa6e0e +534, 0x482c8e4be2a5d704 +535, 0xc5d1632e532ddf97 +536, 0x92a41d90396b49c6 +537, 0xf895429c172ec71c +538, 0xab3ed20fad9ae896 +539, 0xbecd1ee462ba9dee +540, 0x29e020d2bf854671 +541, 0x4a31b52b2b48d795 +542, 0x14b2c4bf2ff453a2 +543, 0xbd49a5992f3deac2 +544, 0xfe19fe4becf1b1c8 +545, 0xa90ede0ced2811cb +546, 0x409de5d1234b16fb +547, 0x4eb18dd87fdd6cd7 +548, 0x52387faf2214a168 +549, 0x18678b302a911d42 +550, 0x484ccf18cb491bbe +551, 0x8610462c7e48b54d +552, 0xb2b2712e35cc4282 +553, 0x754abdb493e3ce4f +554, 0x352745881ade5eea +555, 0x37d4c7cc6c238692 +556, 0xe7a8061b7c0259d2 +557, 0x187e5ee097b24be1 +558, 0x41af64f7cecc63e0 +559, 0x33612ca0ca35a2bf +560, 0xc8b652dc6cdd0829 +561, 0xd050306acf3314b4 +562, 0x7bb7c4114d5d2347 +563, 0xd583132ce17b2f9c +564, 0x1473fcb33448ece2 +565, 0x5f9d56e869d06300 +566, 0x45c27eae73dd6391 +567, 0x15164b3b33d2c145 +568, 0x32991907d6370c8 +569, 0x9445ff1373a9635b +570, 0xf33ffa711ebc9d97 +571, 0x38dc80e03d8badcf +572, 0xf346f6f42e3c396e +573, 0x47bae2fa3827f514 +574, 0xde0e4fc698e6a6d1 +575, 0xd26d4b4097367afd +576, 0x16dea3bef70fe858 +577, 0x226decb65f433fa0 +578, 0x2e4b7f4915de64c7 +579, 0x4f31a10935fcd415 +580, 0x5e3e420e134d2191 +581, 0x52bf5207327dfe09 +582, 0xd8c4ab9ec015b93a +583, 0x55154818bf1ca7c9 +584, 0xc121666af28dcc9a +585, 0x9904729e1a01bd3c +586, 0x6e9cae3d292339bc +587, 0xf6fb78d385e10840 +588, 0x8fb67f5e56ee1e0b +589, 0xba17083a33230c28 +590, 0x9994a47b97c3dc9f +591, 0x53391314bd23bebb +592, 0x9ad473ee0eacee3b +593, 0xaec807e5cb1f0f18 +594, 0x5d5838c5e16e82ba +595, 0x7c810095640d10df +596, 0x898b9da105d90061 +597, 0x9296de76fe275a73 +598, 0xb118361c5dad2c6d +599, 0x4b9051df7724b504 +600, 0xd91789023183a552 +601, 0xc35ca6285eea0aaf +602, 0xb6fb918229e8bb05 +603, 0x4f3f41b3fe26df66 +604, 0xb63885de73089f64 +605, 0xc55aad297e8db9cc +606, 0x7a5ebc6cbb977bf9 +607, 0x122478e8d6b4b5fa +608, 0x52f69dc782aba318 +609, 0xce068981160e9756 +610, 0x303897ea358b700b +611, 0x9963ff7db9effb75 +612, 0xa3e4224b2372dc4a +613, 0x68d78fde1f0b1e +614, 0xb895f75785c0ec92 +615, 0x3df2981af65f3be6 +616, 0x88b17d18c7584a58 +617, 0x560834beafb27138 +618, 0xfa1d9ee07edbf359 +619, 0xc27c98d528ba33f8 +620, 0x58873114fbc61614 +621, 0x3f8112bff34dd5fc +622, 0xbe7fbc694b26e7a1 +623, 0x323d8907780f85fb +624, 0x7e77f48feec1f69a +625, 0xf6d8ac3573ac4ba4 +626, 0xf013633aaba2cd2c +627, 0x5c3153cd6f9f2fd8 +628, 0x4c3ae3906dc4e92a +629, 0xd2f375cec67af24d +630, 0x31943d0c1139dced +631, 0x95ee9d16c2320163 +632, 0x1c0f03c058441f3b +633, 0xa4dd49a2abbb39a5 +634, 0xcf6c4c9c695783ec +635, 0xbb0ea4c9a55af9ac +636, 0xb6a7a4c82fb232d5 +637, 0xd090cc06191a5d2f +638, 0x653c0a506097397e +639, 0x5a5af47067bba201 +640, 0x23df206d3d6f105 +641, 0x8501560fac79fa17 +642, 0x2b95d59621a424c8 +643, 0xb20ca1d29061c6cd +644, 0x9824922790be5c12 +645, 0xdee7448af6c82ce +646, 0xb57c8ab1b2b0ddb1 +647, 0x9241c7effe12d339 +648, 0xf69967036e960af9 +649, 0xe2e14558fcf89166 +650, 0x23a16c73c276d451 +651, 0x9fdd05ed8828875b +652, 0xc3466fd3814d3253 +653, 0xdfc9c839dc99a11d +654, 0x16693a83f78664fe +655, 0x65da2039561d5402 +656, 0x20b0d78000a063fa +657, 0x6b1346e833500ca1 +658, 0x7aa4a72cf75d077b +659, 0x378c2101d36355d8 +660, 0x95910003849a5839 +661, 0x4ad588ff7fe780cc +662, 0xd64d44efcf333e82 +663, 0x2f16c1742dcd9e7 +664, 0xd52ee978f72d63c2 +665, 0xaebda4339041c968 +666, 0x909d2433eedf9e81 +667, 0x670d7dbb7420f9da +668, 0x2880a01109e20500 +669, 0x7b48c2a4e918f6a1 +670, 0xf38fac2caf78d1c +671, 0x426944a0a0fcca7f +672, 0x24331c63647d4d36 +673, 0xc8e11bd52e232844 +674, 0xe7fb6b0ccc6a867a +675, 0x5c797fb7a7603019 +676, 0x2f6b2971284d996a +677, 0x96a89cf3747fd01f +678, 0x9aaedf8572e12afe +679, 0xdf9e5a2214174223 +680, 0x163ed5bedfd06b59 +681, 0x6c45e87d73677bae +682, 0x97b415906449e5ce +683, 0x53f30cd13d0bca1c +684, 0x86b204c8a1775e1d +685, 0x7ab03915913dbaa3 +686, 0x30767dc8d5a8e96 +687, 0x4b4fd100a4d86d59 +688, 0x65a5dfabb1a06ea1 +689, 0x59632b7fec7ad10e +690, 0x2d436b149509d8 +691, 0x37a45927a3898861 +692, 0x396db74b149f86d4 +693, 0xa1fdf757db1de83 +694, 0x3a08d99d4a60dae3 +695, 0x9df8a778bfd97996 +696, 0xc7196b2c8db56799 +697, 0x9378d20ec50eeffb +698, 0xb9ecc104b558e25c +699, 0x2929a6ddc011e01d +700, 0x5c8e297d48eaa335 +701, 0x9e000149b1821081 +702, 0xa8d080481a874776 +703, 0xedb2e0fcc8695de1 +704, 0x31c38628250d2d1f +705, 0xd92b4c99893c21a0 +706, 0xa56a77e01dffa3e6 +707, 0xa607e4ebc9c39fb5 +708, 0x6c8f5f7df2cddeaa +709, 0x1180c33d565487aa +710, 0xf4c66f402b7c1a21 +711, 0x4bd81bbcbe186a4d +712, 0x623e742bf4cfc10c +713, 0x84074e36e58825dc +714, 0xaa70f6dfdd617ae3 +715, 0xe305ea5aaf5aea74 +716, 0xc4726917aa5914ec +717, 0x317bbc6430cf6442 +718, 0x5b8af46f34f146a2 +719, 0xe4552970afbf97bd +720, 0x20d7a393f8176838 +721, 0x5e4a65ab657c7d2b +722, 0x1e430b0ad9e6fe49 +723, 0xa51866b0155c88d4 +724, 0xf1e2cdf07c51638f +725, 0x50f57c27c4e00a44 +726, 0x23bd9255fbb896d0 +727, 0xa91748820079892f +728, 0xb4d156ae147d6fab +729, 0xb3a474a3480c38a9 +730, 0x45dbbb715f1e3085 +731, 0x585986863049a87c +732, 0x436045cd7d1a9172 +733, 0x236972e814d5a4d +734, 0x2249b5f676f29b8a +735, 0x67fdcd55de80a8a9 +736, 0xd4fe890341189ee6 +737, 0x70e1eac3eb0a498d +738, 0xce1c2beb72f7cff3 +739, 0x50d28189d52b5785 +740, 0x93c740175c287808 +741, 0xf29621c38e8a1044 +742, 0x32d50b2824a59d70 +743, 0x8d595966ab119908 +744, 0xa5750cc7ceb0823 +745, 0xbcdefc996aed9ceb +746, 0xc1d70bb5480e2778 +747, 0x942b3f26a50fec6d +748, 0xa7d4851f6990be3d +749, 0x4086348def6e7c11 +750, 0x18aa95009f903221 +751, 0x3010f2c49ca532ad +752, 0xe9e9b21cd5552b31 +753, 0xd90541d86fbd9566 +754, 0x9240f2d8ffffd945 +755, 0xc7815330b2fd5f62 +756, 0x89040a5ec01115f3 +757, 0x4da5e5bb136d77ec +758, 0xc6a489d50839194b +759, 0x37839dcfaa606c7f +760, 0x8177b7be1443adb8 +761, 0xf588b929a63b0790 +762, 0x900a6482fa22b6de +763, 0x845502c244d08f04 +764, 0xc0a8f114df2a3608 +765, 0x5e201627c73573b9 +766, 0xa371ef9c7fc8ac6c +767, 0xca8a07e82c615463 +768, 0xba00e6e8d1c033db +769, 0xcd76dbe8a10cf399 +770, 0x959fe93180800aec +771, 0x8e77fa85404e4cce +772, 0x7b34e8983b9be1b4 +773, 0x81c0125be3d132bf +774, 0xfdbc9bb181a67f5c +775, 0xf2d7962c98584eaa +776, 0x8922b4291b6d0d41 +777, 0xb8235b21de4093bf +778, 0xc94518b4e632edb7 +779, 0x757f43c099ff5783 +780, 0xc063132013dafb63 +781, 0xfd579036a7030019 +782, 0xa5f0638c9ead0004 +783, 0x7494b34172659deb +784, 0x481772ff25eadcfe +785, 0x72e37428f1e21d99 +786, 0x5cf98e5c40aa77e1 +787, 0xb3ce6c54df0aedf1 +788, 0xf00af8c613bcd8f8 +789, 0xd1237f23a07b0e3a +790, 0xa8fe00d99f32f731 +791, 0x8b85f312af567228 +792, 0xdc2515684772c84d +793, 0x7d11b82c9e31766f +794, 0xf09c8697b3ff95c4 +795, 0xd35ebc77a86212eb +796, 0xadb5a1e95afb5f6d +797, 0x6ed845ef3fcadff1 +798, 0xaeb029f4caacb130 +799, 0x7cce6f1bf0ed8e7c +800, 0x23b6201003d49e50 +801, 0x6dfbf0e3c21a03de +802, 0x4729d4f0e6a9240c +803, 0x40af60788c357e6 +804, 0xcd17f1e93dca508b +805, 0x24a823f6424d2821 +806, 0x35194e11b535d3ef +807, 0x948f055d9436932b +808, 0x4e733969108a5551 +809, 0x3c0816162700c63e +810, 0x7370a331ce8096a2 +811, 0xfcf5caf742e23baf +812, 0xe960bb3fe0308e95 +813, 0x8ef061808248efc7 +814, 0x16c6c5da0fcf1296 +815, 0x14a05c065cffe433 +816, 0x568dd4ba989a423 +817, 0xd20a156a56768914 +818, 0x9872a06bbf694ad8 +819, 0x8ac764e367433878 +820, 0x2453eb53416ca0c4 +821, 0xa59ef657a7de7140 +822, 0x43cb5c3119ddabac +823, 0x645ebee1c5d62133 +824, 0xacf017344a2a6031 +825, 0xc22ebb7b220dba01 +826, 0x9048e327d43fc69c +827, 0xca2319dcd6c49370 +828, 0x63844574971006d8 +829, 0x7ce248cd860d2997 +830, 0x4d5780b45f802359 +831, 0x99798ec46c6536c5 +832, 0x4a42d4a45bdc0a1c +833, 0x75f126405fa990ba +834, 0xa1cf7cf0ee32ac82 +835, 0x12b722bce6d8b9a6 +836, 0x85ace663a1f92677 +837, 0x5f0514135be46137 +838, 0xb86863169f76d2f4 +839, 0x1dfc6f087c8721df +840, 0xde984a38824ac47b +841, 0x249504789c3f7704 +842, 0xaab5d4d12f9df445 +843, 0x863caa50cd8764c9 +844, 0x24cf6ca7a6a8e5ab +845, 0xf293f7488a738c5d +846, 0x2936a321fe93cce5 +847, 0xf5b2504862ce0521 +848, 0x9d6f9350f3a2b4f3 +849, 0x5093102345eb9ef0 +850, 0x20aaace8135cecbb +851, 0x252a8e893ad79698 +852, 0x2c68c7a18c5bb936 +853, 0xf973af891f51cfc0 +854, 0xe5c661b55596bcfd +855, 0x98b08b4904602dbd +856, 0x9fcde37c43372b73 +857, 0xa5d05483d489e6ce +858, 0x8b359f723ae63264 +859, 0xadaa0de5bdbd2d33 +860, 0xa4976d2755a6096 +861, 0x7174d708c2537633 +862, 0x24d86478fd44e33e +863, 0x8a0abcdb74f29fcb +864, 0x1fbf39da74328bcd +865, 0x2c5973fdfcbbf09f +866, 0xe23b300ec45a7b8b +867, 0x69019e93b3633c1d +868, 0x749053f7f30d6029 +869, 0x84aa9ded82b4a5c1 +870, 0xb6bb6cb827d5bcb8 +871, 0x503002036e031d34 +872, 0xba06a59f171023a1 +873, 0x733ccfc01e97abba +874, 0xa34cc599a30202ea +875, 0x7581c12df8a4174 +876, 0x8ee2efea87ff8766 +877, 0x2cd79614de9ff639 +878, 0xb190669d3052a8f0 +879, 0x9f3d98c2c3fc3266 +880, 0x48555e89c5b6184e +881, 0x4b9c73be9c8e8ec2 +882, 0xeee8586bdb309974 +883, 0x823a9e3bb2741bbd +884, 0x94a1a50e42fed547 +885, 0x2d7fcb9382eb1ba1 +886, 0xece0e31c5bb89719 +887, 0x440c75600472ddb2 +888, 0x28990d7882d9563c +889, 0x4e9b55cfdbe05ae9 +890, 0x4dba7e062bc24994 +891, 0x71faedf4414cbab1 +892, 0xb12901b28a65ce11 +893, 0xc0834509da822274 +894, 0x7daf95e13d676f29 +895, 0x6bc8df584cd07431 +896, 0xc614bbb95c749cd6 +897, 0x11d888ab3d6e9f38 +898, 0x8f4b7c7b0bda401b +899, 0x5eae46c2079e6f7d +900, 0x9c6f616b61328d61 +901, 0x9415dd3fea046eeb +902, 0x2b04d5dc9a25c2b2 +903, 0x402fd8a16781cf56 +904, 0xdc0be7170faaf41e +905, 0x23d4fe72e8f2fa1d +906, 0x18909afc53a4bce1 +907, 0xc8cfb6a2c1f230bb +908, 0x8268ee65c393a138 +909, 0x9c6b4210f409a598 +910, 0xe3122eb7e28e1c8a +911, 0xe3f0903f892e2aee +912, 0xc51ead0ad0dd1fb8 +913, 0xb2e7343037d7e6f0 +914, 0x89376733a7d3d9b7 +915, 0x13e1f3b9da7cc130 +916, 0xe1911b0a3fa4089b +917, 0xfdc131f18d761b91 +918, 0x782dbb406f0453f9 +919, 0xa61c1d244fdbea55 +920, 0xa4d2ed4dfd8bf85a +921, 0x3459f746e0a71313 +922, 0xa4f67e188e38d8c9 +923, 0x271dd484aee01e22 +924, 0x1907c912ddab4c06 +925, 0xed295346066663cc +926, 0xbebf878973ec93bb +927, 0x464b6c605cf80b2f +928, 0x924f8c5d8af46c76 +929, 0x8a705a5045a54c51 +930, 0xbe630deef4598083 +931, 0x63a782885bf2ef56 +932, 0x5c408ad85ab683f8 +933, 0x5a35bf59ca6db7f0 +934, 0x995b786bc77fcae8 +935, 0x93ac6c1d806cfe6a +936, 0xdc8ad969faae9220 +937, 0x67eda7e6d2b41375 +938, 0x21d2eeb2f58da10e +939, 0x4209dff5fec899a2 +940, 0x1b30fe5b2d96eddd +941, 0x3959011cb1541a05 +942, 0xfd0400e18394ce3e +943, 0xfff052e033e0ce86 +944, 0x569bb5da57a3cf2e +945, 0x45e0ef9753a2731e +946, 0xf6c64d69371ef3ea +947, 0xff6e5d50e2b29841 +948, 0x57334a6acad31efd +949, 0x3f39b0989b465114 +950, 0x9bf7bda3bc70b5dd +951, 0x44adb420df4b19ae +952, 0xa32ca7df58be9881 +953, 0x1af3b91f5078f255 +954, 0x9b1c0f815dba0781 +955, 0x29a5f5869108b99f +956, 0x890ebd600b286b45 +957, 0x4fdbfbba80a094ba +958, 0xbb42ae41c9679296 +959, 0xf51a153b2e4ea0d2 +960, 0xcb01bcb495a01869 +961, 0x1005c4deb506d28e +962, 0x3e1213bfd6496f47 +963, 0x388f29b4151fb7aa +964, 0xe75b0d72872db802 +965, 0xc764bfae67627d2f +966, 0xb86fd279622fb937 +967, 0x3fc887ebd2afa4e6 +968, 0x850b7ec2436195dc +969, 0x11495c0c0e4d1d34 +970, 0xc98421a7c82ced +971, 0x8337132f8c2eea5a +972, 0x77eb95949a98f2f3 +973, 0xcb325cf4d527f0e3 +974, 0x483192546ec89241 +975, 0x957fba4dd4238c59 +976, 0x6b12c9edf75d9ac6 +977, 0x9e959f3749b97cc4 +978, 0x1d77ee83f6b337c1 +979, 0xf6cf70e9db6bee2a +980, 0x87155a5e5746a82b +981, 0x552b032dc590447e +982, 0xbb939df7cb2dc42d +983, 0x1db106ff15b953c7 +984, 0xcee301b609e43399 +985, 0xe9babbea0fc4b81c +986, 0x8ea4ec5562e67027 +987, 0x422d3637cfb0c29 +988, 0x534c6604cd9cc6c +989, 0x301f4f55a0fdac48 +990, 0xf6c4cc1ea05c27a5 +991, 0xa1f4a4d5b999fbb1 +992, 0x343425e806758ccd +993, 0x9641ccb506ca4b0f +994, 0xa94166fa9641d3f5 +995, 0xf344ca329bff56e1 +996, 0xbc49cac1233860fb +997, 0x9087c97dba7f230 +998, 0xf2acda7714a3d1f6 +999, 0x4d076fb8ea7d9b9a diff --git a/_randomgen/randomgen/tests/data/xorshift1024-testset-1.csv b/numpy/random/randomgen/tests/data/xorshift1024-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xorshift1024-testset-1.csv rename to numpy/random/randomgen/tests/data/xorshift1024-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/xorshift1024-testset-2.csv b/numpy/random/randomgen/tests/data/xorshift1024-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xorshift1024-testset-2.csv rename to numpy/random/randomgen/tests/data/xorshift1024-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv b/numpy/random/randomgen/tests/data/xoshiro256starstar-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xoshiro256starstar-testset-1.csv rename to numpy/random/randomgen/tests/data/xoshiro256starstar-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv b/numpy/random/randomgen/tests/data/xoshiro256starstar-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xoshiro256starstar-testset-2.csv rename to numpy/random/randomgen/tests/data/xoshiro256starstar-testset-2.csv diff --git a/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv b/numpy/random/randomgen/tests/data/xoshiro512starstar-testset-1.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xoshiro512starstar-testset-1.csv rename to numpy/random/randomgen/tests/data/xoshiro512starstar-testset-1.csv diff --git a/_randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv b/numpy/random/randomgen/tests/data/xoshiro512starstar-testset-2.csv similarity index 100% rename from _randomgen/randomgen/tests/data/xoshiro512starstar-testset-2.csv rename to numpy/random/randomgen/tests/data/xoshiro512starstar-testset-2.csv diff --git a/_randomgen/randomgen/tests/test_against_numpy.py b/numpy/random/randomgen/tests/test_against_numpy.py similarity index 89% rename from _randomgen/randomgen/tests/test_against_numpy.py rename to numpy/random/randomgen/tests/test_against_numpy.py index ea2656e83fdc..431c7bd85d24 100644 --- a/_randomgen/randomgen/tests/test_against_numpy.py +++ b/numpy/random/randomgen/tests/test_against_numpy.py @@ -1,11 +1,12 @@ import numpy as np import numpy.random -from numpy.testing import assert_allclose, assert_array_equal, assert_equal +from numpy.testing import (assert_allclose, assert_array_equal, assert_equal, + suppress_warnings) -import randomgen -from randomgen import RandomGenerator, MT19937 -from randomgen._testing import suppress_warnings -from randomgen.legacy import LegacyGenerator +import pytest + +from numpy.random.randomgen import RandomGenerator, MT19937, generator +from numpy.random import RandomState def compare_0_input(f1, f2): @@ -95,7 +96,7 @@ def setup_class(cls): cls.brng = MT19937 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.lg = LegacyGenerator(cls.brng(*cls.seed)) + cls.rs = RandomState(cls.brng(*cls.seed)) cls.nprs = cls.np.RandomState(*cls.seed) cls.initial_state = cls.rg.state cls._set_common_state() @@ -113,7 +114,7 @@ def _set_common_state(cls): @classmethod def _set_common_state_legacy(cls): - state = cls.lg.state + state = cls.rs.get_state(legacy=False) st = [[]] * 5 st[0] = 'MT19937' st[1] = state['state']['key'] @@ -130,7 +131,7 @@ def _is_state_common(self): def _is_state_common_legacy(self): state = self.nprs.get_state() - state2 = self.lg.state + state2 = self.rs.get_state(legacy=False) assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) assert (state[3] == state2['has_gauss']) @@ -165,21 +166,21 @@ def test_standard_normal(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_0_input(self.nprs.standard_normal, - self.lg.standard_normal) + self.rs.standard_normal) self._is_state_common_legacy() def test_standard_cauchy(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_0_input(self.nprs.standard_cauchy, - self.lg.standard_cauchy) + self.rs.standard_cauchy) self._is_state_common_legacy() def test_standard_exponential(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_0_input(self.nprs.standard_exponential, - self.lg.standard_exponential) + self.rs.standard_exponential) self._is_state_common_legacy() def test_tomaxint(self): @@ -407,13 +408,14 @@ def test_dir(self): assert (len(nprs_d.difference(rs_d)) == 0) npmod = dir(numpy.random) - mod = dir(randomgen.generator) + mod = dir(generator) known_exlcuded = ['__all__', '__cached__', '__path__', 'Tester', 'info', 'bench', '__RandomState_ctor', 'mtrand', 'test', '__warningregistry__', '_numpy_tester', 'division', 'get_state', 'set_state', 'seed', 'ranf', 'random', 'sample', 'absolute_import', - 'print_function', 'RandomState'] + 'print_function', 'RandomState', 'randomgen', + 'tests', 'Lock'] mod += known_exlcuded diff = set(npmod).difference(mod) assert_equal(len(diff), 0) @@ -423,112 +425,112 @@ def test_chisquare(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.chisquare, - self.lg.chisquare) + self.rs.chisquare) self._is_state_common_legacy() def test_standard_gamma(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.standard_gamma, - self.lg.standard_gamma) + self.rs.standard_gamma) self._is_state_common_legacy() def test_standard_t(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.standard_t, - self.lg.standard_t) + self.rs.standard_t) self._is_state_common_legacy() def test_pareto(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.pareto, - self.lg.pareto) + self.rs.pareto) self._is_state_common_legacy() def test_power(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.power, - self.lg.power) + self.rs.power) self._is_state_common_legacy() def test_weibull(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.weibull, - self.lg.weibull) + self.rs.weibull) self._is_state_common_legacy() def test_beta(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.beta, - self.lg.beta) + self.rs.beta) self._is_state_common_legacy() def test_exponential(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_1_input(self.nprs.exponential, - self.lg.exponential) + self.rs.exponential) self._is_state_common_legacy() def test_f(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.f, - self.lg.f) + self.rs.f) self._is_state_common_legacy() def test_gamma(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.gamma, - self.lg.gamma) + self.rs.gamma) self._is_state_common_legacy() def test_lognormal(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.lognormal, - self.lg.lognormal) + self.rs.lognormal) self._is_state_common_legacy() def test_noncentral_chisquare(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.noncentral_chisquare, - self.lg.noncentral_chisquare) + self.rs.noncentral_chisquare) self._is_state_common_legacy() def test_normal(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.normal, - self.lg.normal) + self.rs.normal) self._is_state_common_legacy() def test_wald(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.wald, - self.lg.wald) + self.rs.wald) self._is_state_common_legacy() def test_negative_binomial(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_2_input(self.nprs.negative_binomial, - self.lg.negative_binomial, + self.rs.negative_binomial, is_np=True) self._is_state_common_legacy() def test_randn(self): self._set_common_state_legacy() self._is_state_common_legacy() - f = self.lg.randn + f = self.rs.randn g = self.nprs.randn assert_allclose(f(10), g(10)) assert_allclose(f(3, 4, 5), g(3, 4, 5)) @@ -537,7 +539,7 @@ def test_randn(self): def test_dirichlet(self): self._set_common_state_legacy() self._is_state_common_legacy() - f = self.lg.dirichlet + f = self.rs.dirichlet g = self.nprs.dirichlet a = [3, 4, 5, 6, 7, 10] assert_allclose(f(a), g(a)) @@ -549,7 +551,7 @@ def test_noncentral_f(self): self._set_common_state_legacy() self._is_state_common_legacy() compare_3_input(self.nprs.noncentral_f, - self.lg.noncentral_f) + self.rs.noncentral_f) self._is_state_common_legacy() def test_multivariate_normal(self): @@ -557,7 +559,7 @@ def test_multivariate_normal(self): self._is_state_common_legacy() mu = [1, 2, 3] cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] - f = self.lg.multivariate_normal + f = self.rs.multivariate_normal g = self.nprs.multivariate_normal assert_allclose(f(mu, cov), g(mu, cov)) assert_allclose(f(np.array(mu), cov), g(np.array(mu), cov)) @@ -566,3 +568,25 @@ def test_multivariate_normal(self): assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31)), g(np.array(mu), np.array(cov), size=(7, 31))) self._is_state_common_legacy() + + +funcs = [generator.zipf, + generator.logseries, + generator.poisson] +ids = [f.__name__ for f in funcs] + + +@pytest.mark.filterwarnings('ignore:invalid value encountered:RuntimeWarning') +@pytest.mark.parametrize('func', funcs, ids=ids) +def test_nan_guard(func): + with pytest.raises(ValueError): + func([np.nan]) + with pytest.raises(ValueError): + func(np.nan) + + +def test_cons_gte1_nan_guard(): + with pytest.raises(ValueError): + generator.hypergeometric(10, 10, [np.nan]) + with pytest.raises(ValueError): + generator.hypergeometric(10, 10, np.nan) diff --git a/_randomgen/randomgen/tests/test_direct.py b/numpy/random/randomgen/tests/test_direct.py similarity index 66% rename from _randomgen/randomgen/tests/test_direct.py rename to numpy/random/randomgen/tests/test_direct.py index 3f84c4cb69da..6e856de414cb 100644 --- a/_randomgen/randomgen/tests/test_direct.py +++ b/numpy/random/randomgen/tests/test_direct.py @@ -7,9 +7,24 @@ assert_raises import pytest -from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ +from ...randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ - Xoshiro512StarStar + Xoshiro512StarStar, RandomState +from ...randomgen.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 if (sys.version_info > (3, 0)): long = int @@ -17,6 +32,16 @@ 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) @@ -26,14 +51,6 @@ def uniform32_from_uint64(x): out = (joined >> np.uint32(9)) * (1.0 / 2 ** 23) return out.astype(np.float32) - -def uniform32_from_uint63(x): - x = np.uint64(x) - x = np.uint32(x >> np.uint64(32)) - out = (x >> 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)) @@ -48,8 +65,6 @@ def uniform32_from_uint32(x): def uniform32_from_uint(x, bits): if bits == 64: return uniform32_from_uint64(x) - elif bits == 63: - return uniform32_from_uint63(x) elif bits == 53: return uniform32_from_uint53(x) elif bits == 32: @@ -77,16 +92,6 @@ def uniform_from_uint32(x): out[i // 2] = (a * 67108864.0 + b) / 9007199254740992.0 return out - -def uint64_from_uint63(x): - out = np.empty(len(x) // 2, dtype=np.uint64) - for i in range(0, len(x), 2): - a = x[i] & np.uint64(0xffffffff00000000) - b = x[i + 1] >> np.uint64(32) - out[i // 2] = a | b - return out - - def uniform_from_dsfmt(x): return x.view(np.double) - 1.0 @@ -126,6 +131,8 @@ def setup_class(cls): cls.bits = 64 cls.dtype = np.uint64 cls.seed_error_type = TypeError + cls.invalid_seed_types = [] + cls.invalid_seed_values = [] @classmethod def _read_csv(cls, filename): @@ -139,23 +146,33 @@ def _read_csv(cls, filename): return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)} def test_raw(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - uints = rs.random_raw(1000) + brng = self.brng(*self.data1['seed']) + uints = brng.random_raw(1000) assert_equal(uints, self.data1['data']) - rs = RandomGenerator(self.brng(*self.data2['seed'])) - uints = rs.random_raw(1000) + brng = self.brng(*self.data1['seed']) + uints = brng.random_raw() + assert_equal(uints, self.data1['data'][0]) + + brng = self.brng(*self.data2['seed']) + uints = brng.random_raw(1000) assert_equal(uints, self.data2['data']) - @pytest.mark.skip(reason='Polar transform no longer supported') + def test_random_raw(self): + brng = self.brng(*self.data1['seed']) + uints = brng.random_raw(output=False) + assert uints is None + uints = brng.random_raw(1000, output=False) + assert uints is None + def test_gauss_inv(self): n = 25 - rs = RandomGenerator(self.brng(*self.data1['seed'])) + rs = RandomState(self.brng(*self.data1['seed'])) gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, self.bits)) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = RandomState(self.brng(*self.data2['seed'])) gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, self.bits)) @@ -214,6 +231,87 @@ def test_seed_out_of_range_array(self): assert_raises(ValueError, rs.seed, [2 ** (2 * self.bits + 1)]) assert_raises(ValueError, rs.seed, [-1]) + def test_repr(self): + rs = RandomGenerator(self.brng(*self.data1['seed'])) + assert 'RandomGenerator' in rs.__repr__() + assert str(hex(id(rs)))[2:].upper() in rs.__repr__() + + def test_str(self): + rs = RandomGenerator(self.brng(*self.data1['seed'])) + assert 'RandomGenerator' in str(rs) + assert str(self.brng.__name__) in str(rs) + assert str(hex(id(rs)))[2:].upper() not in str(rs) + + def test_generator(self): + brng = self.brng(*self.data1['seed']) + assert isinstance(brng.generator, RandomGenerator) + + def test_pickle(self): + import pickle + + brng = self.brng(*self.data1['seed']) + state = brng.state + brng_pkl = pickle.dumps(brng) + reloaded = pickle.loads(brng_pkl) + reloaded_state = reloaded.state + assert_array_equal(brng.generator.standard_normal(1000), + reloaded.generator.standard_normal(1000)) + assert brng is not reloaded + assert_state_equal(reloaded_state, state) + + def test_invalid_state_type(self): + brng = self.brng(*self.data1['seed']) + with pytest.raises(TypeError): + brng.state = {'1'} + + def test_invalid_state_value(self): + brng = self.brng(*self.data1['seed']) + state = brng.state + state['brng'] = 'otherBRNG' + with pytest.raises(ValueError): + brng.state = state + + def test_invalid_seed_type(self): + brng = self.brng(*self.data1['seed']) + for st in self.invalid_seed_types: + with pytest.raises(TypeError): + brng.seed(*st) + + def test_invalid_seed_values(self): + brng = self.brng(*self.data1['seed']) + for st in self.invalid_seed_values: + with pytest.raises(ValueError): + brng.seed(*st) + + def test_benchmark(self): + brng = self.brng(*self.data1['seed']) + brng._benchmark(1) + brng._benchmark(1, 'double') + with pytest.raises(ValueError): + brng._benchmark(1, 'int32') + + @pytest.mark.skipif(MISSING_CFFI, reason='cffi not available') + def test_cffi(self): + brng = self.brng(*self.data1['seed']) + cffi_interface = brng.cffi + assert isinstance(cffi_interface, interface) + other_cffi_interface = brng.cffi + assert other_cffi_interface is cffi_interface + + @pytest.mark.skipif(MISSING_CTYPES, reason='ctypes not available') + def test_ctypes(self): + brng = self.brng(*self.data1['seed']) + ctypes_interface = brng.ctypes + assert isinstance(ctypes_interface, interface) + other_ctypes_interface = brng.ctypes + assert other_ctypes_interface is ctypes_interface + + def test_getstate(self): + brng = self.brng(*self.data1['seed']) + state = brng.state + alt_state = brng.__getstate__() + assert_state_equal(state, alt_state) + class TestXoroshiro128(Base): @classmethod @@ -226,6 +324,8 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/xoroshiro128-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] + cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] class TestXoshiro256StarStar(Base): @@ -239,6 +339,8 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/xoshiro256starstar-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] + cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] class TestXoshiro512StarStar(Base): @@ -252,6 +354,8 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/xoshiro512starstar-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] + cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] class TestXorshift1024(Base): @@ -265,6 +369,8 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/xorshift1024-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] + cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] class TestThreeFry(Base): @@ -278,6 +384,16 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/threefry-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [] + cls.invalid_seed_values = [(1, None, 1), (-1,), (2 ** 257 + 1,), + (None, None, 2 ** 257 + 1)] + + def test_set_key(self): + brng = self.brng(*self.data1['seed']) + state = brng.state + keyed = self.brng(counter=state['state']['counter'], + key=state['state']['key']) + assert_state_equal(brng.state, keyed.state) class TestPCG64(Base): @@ -289,6 +405,10 @@ def setup_class(cls): 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 = TypeError + cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), + (None, np.zeros(1))] + cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), + (None, 2 ** 129 + 1)] def test_seed_float_array(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -317,6 +437,16 @@ def setup_class(cls): cls.data2 = cls._read_csv( join(pwd, './data/philox-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [] + cls.invalid_seed_values = [(1, None, 1), (-1,), (2 ** 257 + 1,), + (None, None, 2 ** 257 + 1)] + + def test_set_key(self): + brng = self.brng(*self.data1['seed']) + state = brng.state + keyed = self.brng(counter=state['state']['counter'], + key=state['state']['key']) + assert_state_equal(brng.state, keyed.state) class TestMT19937(Base): @@ -328,6 +458,8 @@ def setup_class(cls): 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_seed_types = [] + cls.invalid_seed_values = [(-1,), np.array([2 ** 33])] def test_seed_out_of_range(self): # GH #82 @@ -359,6 +491,19 @@ def test_seed_float_array(self): assert_raises(TypeError, rs.seed, [np.pi]) assert_raises(TypeError, rs.seed, [0, np.pi]) + def test_state_tuple(self): + rs = RandomGenerator(self.brng(*self.data1['seed'])) + state = rs.state + desired = rs.randint(2 ** 16) + tup = (state['brng'], state['state']['key'], state['state']['pos']) + rs.state = tup + actual = rs.randint(2 ** 16) + assert_equal(actual, desired) + tup = tup + (0, 0.0) + rs.state = tup + actual = rs.randint(2 ** 16) + assert_equal(actual, desired) + class TestDSFMT(Base): @classmethod @@ -369,6 +514,9 @@ def setup_class(cls): cls.data1 = cls._read_csv(join(pwd, './data/dSFMT-testset-1.csv')) cls.data2 = cls._read_csv(join(pwd, './data/dSFMT-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [] + cls.invalid_seed_values = [(-1,), np.array([2 ** 33]), + (np.array([2 ** 33, 2 ** 33]),)] def test_uniform_double(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -379,15 +527,14 @@ def test_uniform_double(self): assert_equal(uniform_from_dsfmt(self.data2['data']), rs.random_sample(1000)) - @pytest.mark.skip(reason='Polar transform no longer supported') def test_gauss_inv(self): n = 25 - rs = RandomGenerator(self.brng(*self.data1['seed'])) + rs = RandomState(self.brng(*self.data1['seed'])) gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, 'dsfmt')) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = RandomState(self.brng(*self.data2['seed'])) gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, 'dsfmt')) @@ -445,6 +592,16 @@ def setup_class(cls): cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) cls.data2 = cls._read_csv(join(pwd, './data/threefry32-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [] + cls.invalid_seed_values = [(1, None, 1), (-1,), (2 ** 257 + 1,), + (None, None, 2 ** 129 + 1)] + + def test_set_key(self): + brng = self.brng(*self.data1['seed']) + state = brng.state + keyed = self.brng(counter=state['state']['counter'], + key=state['state']['key']) + assert_state_equal(brng.state, keyed.state) class TestPCG32(TestPCG64): @@ -456,3 +613,7 @@ def setup_class(cls): cls.data1 = cls._read_csv(join(pwd, './data/pcg32-testset-1.csv')) cls.data2 = cls._read_csv(join(pwd, './data/pcg32-testset-2.csv')) cls.seed_error_type = TypeError + cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), + (None, np.zeros(1))] + cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), + (None, 2 ** 129 + 1)] diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/numpy/random/randomgen/tests/test_generator_mt19937.py similarity index 66% rename from _randomgen/randomgen/tests/test_numpy_mt19937.py rename to numpy/random/randomgen/tests/test_generator_mt19937.py index a19693d815c7..cad3ef4d66cd 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937.py +++ b/numpy/random/randomgen/tests/test_generator_mt19937.py @@ -1,5 +1,3 @@ -from __future__ import division, absolute_import, print_function - import sys import warnings @@ -7,14 +5,11 @@ from numpy.testing import ( assert_, assert_raises, assert_equal, assert_warns, assert_no_warnings, assert_array_equal, - assert_array_almost_equal) + assert_array_almost_equal, suppress_warnings) -from randomgen._testing import suppress_warnings -from randomgen import RandomGenerator, MT19937 -from randomgen.legacy import LegacyGenerator +from ...randomgen import RandomGenerator, MT19937 -random = mt19937 = RandomGenerator(MT19937()) -legacy = LegacyGenerator(MT19937()) +random = RandomGenerator(MT19937()) class TestSeed(object): @@ -47,6 +42,9 @@ def test_invalid_array(self): assert_raises(ValueError, MT19937, [1, 2, 4294967296]) assert_raises(ValueError, MT19937, [1, -2, 4294967296]) + def test_noninstantized_brng(self): + assert_raises(ValueError, RandomGenerator, MT19937) + class TestBinomial(object): def test_n_zero(self): @@ -80,17 +78,20 @@ def test_int_negative_interval(self): def test_size(self): # gh-3173 p = [0.5, 0.5] - assert_equal(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.multinomial(1, p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.multinomial(1, p, [2, 2]).shape, (2, 2, 2)) - assert_equal(mt19937.multinomial(1, p, (2, 2)).shape, (2, 2, 2)) - assert_equal(mt19937.multinomial(1, p, np.array((2, 2))).shape, + 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, mt19937.multinomial, 1, p, + assert_raises(TypeError, random.multinomial, 1, p, float(1)) + def test_invalid_prob(self): + assert_raises(ValueError, random.multinomial, 100, [1.1, 0.2]) + class TestSetState(object): def setup(self): @@ -125,19 +126,6 @@ def test_gaussian_reset_in_media_res(self): new = self.brng.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.legacy_state - legacy.state = old_state - x1 = legacy.standard_normal(size=16) - legacy.state = old_state - x2 = legacy.standard_normal(size=16) - legacy.state = old_state + (0, 0.0) - x3 = legacy.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. @@ -145,7 +133,7 @@ def test_negative_binomial(self): class TestRandint(object): - rfunc = mt19937.randint + rfunc = random.randint # valid integer/boolean types itype = [bool, np.int8, np.uint8, np.int16, np.uint16, @@ -257,7 +245,7 @@ def test_full_range_array(self): def test_in_bounds_fuzz(self): # Don't use fixed seed - mt19937.seed() + random.seed() for dt in self.itype[1:]: for ubnd in [4, 8, 16]: @@ -276,13 +264,13 @@ def test_scalar_array_equiv(self): ubnd = 2 if dt is bool else np.iinfo(dt).max + 1 size = 1000 - mt19937.seed(1234) + random.seed(1234) scalar = self.rfunc(lbnd, ubnd, size=size, dtype=dt) - mt19937.seed(1234) + random.seed(1234) scalar_array = self.rfunc([lbnd], [ubnd], size=size, dtype=dt) - mt19937.seed(1234) + random.seed(1234) array = self.rfunc([lbnd] * size, [ubnd] * size, size=size, dtype=dt) assert_array_equal(scalar, scalar_array) @@ -304,7 +292,7 @@ def test_repeatability(self): 'uint8': '27dd30c4e08a797063dffac2490b0be6'} for dt in self.itype[1:]: - mt19937.seed(1234) + random.seed(1234) # view as little endian for hash if sys.byteorder == 'little': @@ -316,7 +304,7 @@ def test_repeatability(self): assert_(tgt[np.dtype(dt).name] == res) # bools do not depend on endianness - mt19937.seed(1234) + 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) @@ -329,15 +317,15 @@ def test_repeatability_broadcasting(self): np.bool, bool, np.bool_) else np.iinfo(dt).max + 1 # view as little endian for hash - mt19937.seed(1234) + random.seed(1234) val = self.rfunc(lbnd, ubnd, size=1000, dtype=dt) - mt19937.seed(1234) + random.seed(1234) val_bc = self.rfunc([lbnd] * 1000, ubnd, dtype=dt) assert_array_equal(val, val_bc) - mt19937.seed(1234) + random.seed(1234) val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, dtype=dt) assert_array_equal(val, val_bc) @@ -362,7 +350,7 @@ def test_int64_uint64_corner_case(self): # None of these function calls should # generate a ValueError now. - actual = mt19937.randint(lbnd, ubnd, dtype=dt) + actual = random.randint(lbnd, ubnd, dtype=dt) assert_equal(actual, tgt) def test_respect_dtype_singleton(self): @@ -413,24 +401,34 @@ def setup(self): self.seed = 1234567890 def test_rand(self): - mt19937.seed(self.seed) - actual = mt19937.rand(3, 2) + 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): - legacy.seed(self.seed) - actual = legacy.randn(3, 2) - desired = np.array([[1.34016345771863121, 1.73759122771936081], - [1.498988344300628, -0.2286433324536169], - [2.031033998682787, 2.17032494605655257]]) + random.seed(self.seed) + actual = random.randn(3, 2) + desired = np.array([[-3.472754000610961, -0.108938564229143], + [-0.245965753396411, -0.704101550261701], + [0.360102487116356, 0.127832101772367]]) 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): - mt19937.seed(self.seed) - actual = mt19937.randint(-99, 99, size=(3, 2)) + random.seed(self.seed) + actual = random.randint(-99, 99, size=(3, 2)) desired = np.array([[31, 3], [-52, 41], [-48, -66]]) @@ -439,9 +437,9 @@ def test_randint(self): def test_randint_masked(self): # Test masked rejection sampling algorithm to generate array of # uint32 in an interval. - mt19937.seed(self.seed) - actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, - use_masked=True) + random.seed(self.seed) + actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, + use_masked=True) desired = np.array([[2, 47], [12, 51], [33, 43]], dtype=np.uint32) @@ -449,9 +447,9 @@ def test_randint_masked(self): def test_randint_lemire_32(self): # Test lemire algorithm to generate array of uint32 in an interval. - mt19937.seed(self.seed) - actual = mt19937.randint(0, 99, size=(3, 2), dtype=np.uint32, - use_masked=False) + random.seed(self.seed) + actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, + use_masked=False) desired = np.array([[61, 33], [58, 14], [87, 23]], dtype=np.uint32) @@ -459,19 +457,19 @@ def test_randint_lemire_32(self): def test_randint_lemire_64(self): # Test lemire algorithm to generate array of uint64 in an interval. - mt19937.seed(self.seed) - actual = mt19937.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), - dtype=np.uint64, use_masked=False) + random.seed(self.seed) + actual = random.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), + dtype=np.uint64, use_masked=False) desired = np.array([[42523252834, 40656066204], [61069871386, 61274051182], [31443797706, 53476677934]], dtype=np.uint64) assert_array_equal(actual, desired) def test_random_integers(self): - mt19937.seed(self.seed) + random.seed(self.seed) with suppress_warnings() as sup: w = sup.record(DeprecationWarning) - actual = mt19937.random_integers(-99, 99, size=(3, 2)) + actual = random.random_integers(-99, 99, size=(3, 2)) assert_(len(w) == 1) desired = np.array([[31, 3], [-52, 41], @@ -486,8 +484,8 @@ def test_random_integers_max_int(self): # to generate this integer. with suppress_warnings() as sup: w = sup.record(DeprecationWarning) - actual = mt19937.random_integers(np.iinfo('l').max, - np.iinfo('l').max) + actual = random.random_integers(np.iinfo('l').max, + np.iinfo('l').max) assert_(len(w) == 1) desired = np.iinfo('l').max @@ -499,55 +497,76 @@ def test_random_integers_deprecated(self): # DeprecationWarning raised with high == None assert_raises(DeprecationWarning, - mt19937.random_integers, + random.random_integers, np.iinfo('l').max) # DeprecationWarning raised with high != None assert_raises(DeprecationWarning, - mt19937.random_integers, + random.random_integers, np.iinfo('l').max, np.iinfo('l').max) def test_random_sample(self): - mt19937.seed(self.seed) - actual = mt19937.random_sample((3, 2)) + 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_random_sample_float(self): + random.seed(self.seed) + actual = random.random_sample((3, 2)) + desired = np.array([[0.6187948, 0.5916236], + [0.8886836, 0.8916548], + [0.4575675, 0.7781881]]) + assert_array_almost_equal(actual, desired, decimal=7) + + def test_random_sample_float_scalar(self): + random.seed(self.seed) + actual = random.random_sample(dtype=np.float32) + desired = 0.6187948 + assert_array_almost_equal(actual, desired, decimal=7) + + def test_random_sample_unsupported_type(self): + assert_raises(TypeError, random.random_sample, dtype='int32') + def test_choice_uniform_replace(self): - mt19937.seed(self.seed) - actual = mt19937.choice(4, 4) + 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): - mt19937.seed(self.seed) - actual = mt19937.choice(4, 4, p=[0.4, 0.4, 0.1, 0.1]) + 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): - mt19937.seed(self.seed) - actual = mt19937.choice(4, 3, replace=False) + 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): - mt19937.seed(self.seed) - actual = mt19937.choice(4, 3, replace=False, - p=[0.1, 0.3, 0.5, 0.1]) + 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): - mt19937.seed(self.seed) - actual = mt19937.choice(['a', 'b', 'c', 'd'], 4) + 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 = mt19937.choice + sample = random.choice assert_raises(ValueError, sample, -1, 3) assert_raises(ValueError, sample, 3., 3) assert_raises(ValueError, sample, [[1, 2], [3, 4]], 3) @@ -568,57 +587,57 @@ def test_choice_exceptions(self): def test_choice_return_shape(self): p = [0.1, 0.9] # Check scalar - assert_(np.isscalar(mt19937.choice(2, replace=True))) - assert_(np.isscalar(mt19937.choice(2, replace=False))) - assert_(np.isscalar(mt19937.choice(2, replace=True, p=p))) - assert_(np.isscalar(mt19937.choice(2, replace=False, p=p))) - assert_(np.isscalar(mt19937.choice([1, 2], replace=True))) - assert_(mt19937.choice([None], replace=True) is None) + 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_(mt19937.choice(arr, replace=True) is a) + assert_(random.choice(arr, replace=True) is a) # Check 0-d array s = tuple() - assert_(not np.isscalar(mt19937.choice(2, s, replace=True))) - assert_(not np.isscalar(mt19937.choice(2, s, replace=False))) - assert_(not np.isscalar(mt19937.choice(2, s, replace=True, p=p))) - assert_(not np.isscalar(mt19937.choice(2, s, replace=False, p=p))) - assert_(not np.isscalar(mt19937.choice([1, 2], s, replace=True))) - assert_(mt19937.choice([None], s, replace=True).ndim == 0) + 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_(mt19937.choice(arr, s, replace=True).item() is 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_(mt19937.choice(6, s, replace=True).shape, s) - assert_(mt19937.choice(6, s, replace=False).shape, s) - assert_(mt19937.choice(6, s, replace=True, p=p).shape, s) - assert_(mt19937.choice(6, s, replace=False, p=p).shape, s) - assert_(mt19937.choice(np.arange(6), s, replace=True).shape, s) + assert_(random.choice(6, s, replace=True).shape, s) + assert_(random.choice(6, s, replace=False).shape, s) + assert_(random.choice(6, s, replace=True, p=p).shape, s) + assert_(random.choice(6, s, replace=False, p=p).shape, s) + assert_(random.choice(np.arange(6), s, replace=True).shape, s) # Check zero-size - assert_equal(mt19937.randint(0, 0, size=(3, 0, 4)).shape, (3, 0, 4)) - assert_equal(mt19937.randint(0, -10, size=0).shape, (0,)) - assert_equal(mt19937.randint(10, 10, size=0).shape, (0,)) - assert_equal(mt19937.choice(0, size=0).shape, (0,)) - assert_equal(mt19937.choice([], size=(0,)).shape, (0,)) - assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, + 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, mt19937.choice, [], 10) + 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, mt19937.choice, a, p=p) + assert_raises(ValueError, random.choice, a, p=p) def test_bytes(self): - mt19937.seed(self.seed) - actual = mt19937.bytes(10) + random.seed(self.seed) + actual = random.bytes(10) desired = b'\x82Ui\x9e\xff\x97+Wf\xa5' assert_equal(actual, desired) @@ -642,9 +661,9 @@ def test_shuffle(self): lambda x: np.asarray([(i, i) for i in x], [("a", object, 1), ("b", np.int32, 1)])]: - mt19937.seed(self.seed) + random.seed(self.seed) alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) - mt19937.shuffle(alist) + random.shuffle(alist) actual = alist desired = conv([0, 1, 9, 6, 2, 4, 5, 8, 7, 3]) assert_array_equal(actual, desired) @@ -656,16 +675,28 @@ def test_shuffle_masked(self): a_orig = a.copy() b_orig = b.copy() for i in range(50): - mt19937.shuffle(a) + random.shuffle(a) assert_equal( sorted(a.data[~a.mask]), sorted(a_orig.data[~a_orig.mask])) - mt19937.shuffle(b) + 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): - mt19937.seed(self.seed) - actual = mt19937.beta(.1, .9, size=(3, 2)) + 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], @@ -673,173 +704,178 @@ def test_beta(self): assert_array_almost_equal(actual, desired, decimal=15) def test_binomial(self): - mt19937.seed(self.seed) - actual = mt19937.binomial(100.123, .456, size=(3, 2)) + 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) def test_chisquare(self): - legacy.seed(self.seed) - actual = legacy.chisquare(50, size=(3, 2)) - desired = np.array([[63.87858175501090585, 68.68407748911370447], - [65.77116116901505904, 47.09686762438974483], - [72.3828403199695174, 74.18408615260374006]]) + random.seed(self.seed) + actual = random.chisquare(50, size=(3, 2)) + desired = np.array([[22.2534560369812, 46.9302393710074], + [52.9974164611614, 85.3559029505718], + [46.1580841240719, 36.1933148548090]]) assert_array_almost_equal(actual, desired, decimal=13) def test_dirichlet(self): - legacy.seed(self.seed) + random.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) - actual = legacy.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]]]) + actual = random.dirichlet(alpha, size=(3, 2)) + desired = np.array([[[0.444382290764855, 0.555617709235145], + [0.468440809291970, 0.531559190708030]], + [[0.613461427360549, 0.386538572639451], + [0.529103072088183, 0.470896927911817]], + [[0.513490650101800, 0.486509349898200], + [0.558550925712797, 0.441449074287203]]]) assert_array_almost_equal(actual, desired, decimal=15) bad_alpha = np.array([5.4e-01, -1.0e-16]) - assert_raises(ValueError, mt19937.dirichlet, bad_alpha) + 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(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.dirichlet(p, np.uint32(1)).shape, (1, 2)) - assert_equal(mt19937.dirichlet(p, [2, 2]).shape, (2, 2, 2)) - assert_equal(mt19937.dirichlet(p, (2, 2)).shape, (2, 2, 2)) - assert_equal(mt19937.dirichlet(p, np.array((2, 2))).shape, (2, 2, 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, 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, mt19937.dirichlet, p, float(1)) + 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, mt19937.dirichlet, alpha) + assert_raises(ValueError, random.dirichlet, alpha) def test_exponential(self): - legacy.seed(self.seed) - actual = legacy.exponential(1.1234, size=(3, 2)) - desired = np.array([[1.08342649775011624, 1.00607889924557314], - [2.46628830085216721, 2.49668106809923884], - [0.68717433461363442, 1.69175666993575979]]) + random.seed(self.seed) + actual = random.exponential(1.1234, size=(3, 2)) + desired = np.array([[5.350682337747634, 1.152307441755771], + [3.867015473358779, 1.538765912839396], + [0.347846818048527, 2.715656549872026]]) assert_array_almost_equal(actual, desired, decimal=15) def test_exponential_0(self): - assert_equal(mt19937.exponential(scale=0), 0) - assert_raises(ValueError, mt19937.exponential, scale=-0.) + assert_equal(random.exponential(scale=0), 0) + assert_raises(ValueError, random.exponential, scale=-0.) def test_f(self): - legacy.seed(self.seed) - actual = legacy.f(12, 77, size=(3, 2)) - desired = np.array([[1.21975394418575878, 1.75135759791559775], - [1.44803115017146489, 1.22108959480396262], - [1.02176975757740629, 1.34431827623300415]]) + random.seed(self.seed) + actual = random.f(12, 77, size=(3, 2)) + desired = np.array([[0.809498839488467, 2.867222762455471], + [0.588036831639353, 1.012185639664636], + [1.147554281917365, 1.150886518432105]]) assert_array_almost_equal(actual, desired, decimal=15) def test_gamma(self): - legacy.seed(self.seed) - actual = legacy.gamma(5, 3, size=(3, 2)) - desired = np.array([[24.60509188649287182, 28.54993563207210627], - [26.13476110204064184, 12.56988482927716078], - [31.71863275789960568, 33.30143302795922011]]) + random.seed(self.seed) + actual = random.gamma(5, 3, size=(3, 2)) + desired = np.array([[12.46569350177219, 16.46580642087044], + [43.65744473309084, 11.98722785682592], + [6.50371499559955, 7.48465689751638]]) assert_array_almost_equal(actual, desired, decimal=14) def test_gamma_0(self): - assert_equal(mt19937.gamma(shape=0, scale=0), 0) - assert_raises(ValueError, mt19937.gamma, shape=-0., scale=-0.) + assert_equal(random.gamma(shape=0, scale=0), 0) + assert_raises(ValueError, random.gamma, shape=-0., scale=-0.) def test_geometric(self): - mt19937.seed(self.seed) - actual = mt19937.geometric(.123456789, size=(3, 2)) + 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_gumbel(self): - mt19937.seed(self.seed) - actual = mt19937.gumbel(loc=.123456789, scale=2.0, size=(3, 2)) + 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(mt19937.gumbel(scale=0), 0) - assert_raises(ValueError, mt19937.gumbel, scale=-0.) + assert_equal(random.gumbel(scale=0), 0) + assert_raises(ValueError, random.gumbel, scale=-0.) def test_hypergeometric(self): - mt19937.seed(self.seed) - actual = mt19937.hypergeometric(10.1, 5.5, 14, size=(3, 2)) + 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 = mt19937.hypergeometric(5, 0, 3, size=4) + actual = random.hypergeometric(5, 0, 3, size=4) desired = np.array([3, 3, 3, 3]) assert_array_equal(actual, desired) - actual = mt19937.hypergeometric(15, 0, 12, size=4) + actual = random.hypergeometric(15, 0, 12, size=4) desired = np.array([12, 12, 12, 12]) assert_array_equal(actual, desired) # Test ngood = 0 - actual = mt19937.hypergeometric(0, 5, 3, size=4) + actual = random.hypergeometric(0, 5, 3, size=4) desired = np.array([0, 0, 0, 0]) assert_array_equal(actual, desired) - actual = mt19937.hypergeometric(0, 15, 12, size=4) + actual = random.hypergeometric(0, 15, 12, size=4) desired = np.array([0, 0, 0, 0]) assert_array_equal(actual, desired) def test_laplace(self): - mt19937.seed(self.seed) - actual = mt19937.laplace(loc=.123456789, scale=2.0, size=(3, 2)) + 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(mt19937.laplace(scale=0), 0) - assert_raises(ValueError, mt19937.laplace, scale=-0.) + assert_equal(random.laplace(scale=0), 0) + assert_raises(ValueError, random.laplace, scale=-0.) def test_logistic(self): - mt19937.seed(self.seed) - actual = mt19937.logistic(loc=.123456789, scale=2.0, size=(3, 2)) + 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): - legacy.seed(self.seed) - actual = legacy.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) - desired = np.array([[16.50698631688883822, 36.54846706092654784], - [22.67886599981281748, 0.71617561058995771], - [65.72798501792723869, 86.84341601437161273]]) + random.seed(self.seed) + actual = random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) + desired = np.array([[1.0894838661036e-03, 9.0990021488311e-01], + [6.9178869932225e-01, 2.7672077560016e-01], + [2.3248645126975e+00, 1.4609997951330e+00]]) assert_array_almost_equal(actual, desired, decimal=13) def test_lognormal_0(self): - assert_equal(mt19937.lognormal(sigma=0), 1) - assert_raises(ValueError, mt19937.lognormal, sigma=-0.) + assert_equal(random.lognormal(sigma=0), 1) + assert_raises(ValueError, random.lognormal, sigma=-0.) def test_logseries(self): - mt19937.seed(self.seed) - actual = mt19937.logseries(p=.923456789, size=(3, 2)) + 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_multinomial(self): - mt19937.seed(self.seed) - actual = mt19937.multinomial(20, [1 / 6.] * 6, size=(3, 2)) + 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], @@ -849,96 +885,112 @@ def test_multinomial(self): assert_array_equal(actual, desired) def test_multivariate_normal(self): - legacy.seed(self.seed) + random.seed(self.seed) mean = (.123456789, 10) cov = [[1, 0], [0, 1]] size = (3, 2) - actual = legacy.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]]]) + actual = random.multivariate_normal(mean, cov, size) + desired = np.array([[[-3.34929721161096100, 9.891061435770858], + [-0.12250896439641100, 9.295898449738300]], + [[0.48355927611635563, 10.127832101772366], + [3.11093021424924300, 10.283109168794352]], + [[-0.20332082341774727, 9.868532121697195], + [-1.33806889550667330, 9.813657233804179]]]) assert_array_almost_equal(actual, desired, decimal=15) # Check for default size, was raising deprecation warning - actual = legacy.multivariate_normal(mean, cov) - desired = np.array([0.895289569463708, 9.17180864067987]) + actual = random.multivariate_normal(mean, cov) + desired = np.array([-1.097443117192574, 10.535787051184261]) 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, mt19937.multivariate_normal, mean, cov) + assert_warns(RuntimeWarning, random.multivariate_normal, mean, cov) # and that it doesn't warn with RuntimeWarning check_valid='ignore' - assert_no_warnings(mt19937.multivariate_normal, mean, cov, + assert_no_warnings(random.multivariate_normal, mean, cov, check_valid='ignore') # and that it raises with RuntimeWarning check_valid='raises' - assert_raises(ValueError, mt19937.multivariate_normal, mean, cov, + 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): - legacy.seed(self.seed) - actual = legacy.negative_binomial(n=100, p=.12345, size=(3, 2)) - desired = np.array([[848, 841], - [892, 611], - [779, 647]]) + random.seed(self.seed) + actual = random.negative_binomial(n=100, p=.12345, size=(3, 2)) + desired = np.array([[521, 736], + [665, 690], + [723, 751]]) assert_array_equal(actual, desired) def test_noncentral_chisquare(self): - legacy.seed(self.seed) - actual = legacy.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) - desired = np.array([[23.91905354498517511, 13.35324692733826346], - [31.22452661329736401, 16.60047399466177254], - [5.03461598262724586, 17.94973089023519464]]) + random.seed(self.seed) + actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) + desired = np.array([[9.47783251920357, 10.02066178260461], + [3.15869984192364, 10.5581565031544], + [5.01652540543548, 13.7689551218441]]) assert_array_almost_equal(actual, desired, decimal=14) - actual = legacy.noncentral_chisquare(df=.5, nonc=.2, size=(3, 2)) - desired = np.array([[1.47145377828516666, 0.15052899268012659], - [0.00943803056963588, 1.02647251615666169], - [0.332334982684171, 0.15451287602753125]]) + actual = random.noncentral_chisquare(df=.5, nonc=.2, size=(3, 2)) + desired = np.array([[0.00145153051285, 0.22432468724778], + [0.02956713468556, 0.00207192946898], + [1.41985055641800, 0.15451287602753]]) assert_array_almost_equal(actual, desired, decimal=14) - legacy.seed(self.seed) - actual = legacy.noncentral_chisquare(df=5, nonc=0, size=(3, 2)) - desired = np.array([[9.597154162763948, 11.725484450296079], - [10.413711048138335, 3.694475922923986], - [13.484222138963087, 14.377255424602957]]) + random.seed(self.seed) + actual = random.noncentral_chisquare(df=5, nonc=0, size=(3, 2)) + desired = np.array([[3.64881368071039, 5.48224544747803], + [20.41999842025404, 3.44075915187367], + [1.29765160605552, 1.64125033268606]]) assert_array_almost_equal(actual, desired, decimal=14) def test_noncentral_f(self): - legacy.seed(self.seed) - actual = legacy.noncentral_f(dfnum=5, dfden=2, nonc=1, + 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]]) + desired = np.array([[1.22680230963236, 2.56457837623956], + [2.7653304499494, 7.4336268865443], + [1.16362730891403, 2.54104276581491]]) assert_array_almost_equal(actual, desired, decimal=14) def test_normal(self): - legacy.seed(self.seed) - actual = legacy.normal(loc=.123456789, scale=2.0, size=(3, 2)) - desired = np.array([[2.80378370443726244, 3.59863924443872163], - [3.121433477601256, -0.33382987590723379], - [4.18552478636557357, 4.46410668111310471]]) + random.seed(self.seed) + actual = random.normal(loc=.123456789, scale=2.0, size=(3, 2)) + desired = np.array([[-6.822051212221923, -0.094420339458285], + [-0.368474717792823, -1.284746311523402], + [0.843661763232711, 0.379120992544734]]) assert_array_almost_equal(actual, desired, decimal=15) def test_normal_0(self): - assert_equal(mt19937.normal(scale=0), 0) - assert_raises(ValueError, mt19937.normal, scale=-0.) + assert_equal(random.normal(scale=0), 0) + assert_raises(ValueError, random.normal, scale=-0.) def test_pareto(self): - legacy.seed(self.seed) - actual = legacy.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]]) + random.seed(self.seed) + actual = random.pareto(a=.123456789, size=(3, 2)) + desired = np.array([[5.6883528121891552e+16, 4.0569373841667057e+03], + [1.2854967019379475e+12, 6.5833156486851483e+04], + [1.1281132447159091e+01, 3.1895968171107006e+08]]) # For some reason on 32-bit x86 Ubuntu 12.10 the [1, 0] entry in this # matrix differs by 24 nulps. Discussion: # http://mail.scipy.org/pipermail/numpy-discussion/2012-September/063801.html @@ -948,8 +1000,8 @@ def test_pareto(self): np.testing.assert_array_almost_equal_nulp(actual, desired, nulp=30) def test_poisson(self): - mt19937.seed(self.seed) - actual = mt19937.poisson(lam=.123456789, size=(3, 2)) + random.seed(self.seed) + actual = random.poisson(lam=.123456789, size=(3, 2)) desired = np.array([[0, 0], [1, 0], [0, 0]]) @@ -958,87 +1010,131 @@ def test_poisson(self): def test_poisson_exceptions(self): lambig = np.iinfo('l').max lamneg = -1 - assert_raises(ValueError, mt19937.poisson, lamneg) - assert_raises(ValueError, mt19937.poisson, [lamneg] * 10) - assert_raises(ValueError, mt19937.poisson, lambig) - assert_raises(ValueError, mt19937.poisson, [lambig] * 10) + 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) def test_power(self): - legacy.seed(self.seed) - actual = legacy.power(a=.123456789, size=(3, 2)) - desired = np.array([[0.02048932883240791, 0.01424192241128213], - [0.38446073748535298, 0.39499689943484395], - [0.00177699707563439, 0.13115505880863756]]) + random.seed(self.seed) + actual = random.power(a=.123456789, size=(3, 2)) + desired = np.array([[9.328833342693975e-01, 2.742250409261003e-02], + [7.684513237993961e-01, 9.297548209160028e-02], + [2.214811188828573e-05, 4.693448360603472e-01]]) assert_array_almost_equal(actual, desired, decimal=15) def test_rayleigh(self): - mt19937.seed(self.seed) - actual = mt19937.rayleigh(scale=10, size=(3, 2)) + 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(mt19937.rayleigh(scale=0), 0) - assert_raises(ValueError, mt19937.rayleigh, scale=-0.) + assert_equal(random.rayleigh(scale=0), 0) + assert_raises(ValueError, random.rayleigh, scale=-0.) def test_standard_cauchy(self): - legacy.seed(self.seed) - actual = legacy.standard_cauchy(size=(3, 2)) - desired = np.array([[0.77127660196445336, -6.55601161955910605], - [0.93582023391158309, -2.07479293013759447], - [-4.74601644297011926, 0.18338989290760804]]) + random.seed(self.seed) + actual = random.standard_cauchy(size=(3, 2)) + desired = np.array([[31.87809592667601, 0.349332782046838], + [2.816995747731641, 10.552372563459114], + [2.485608017991235, 7.843211273201831]]) assert_array_almost_equal(actual, desired, decimal=15) def test_standard_exponential(self): - mt19937.seed(self.seed) - actual = mt19937.standard_exponential(size=(3, 2), method='inv') + random.seed(self.seed) + actual = random.standard_exponential(size=(3, 2), method='inv') 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_expoential_type_error(self): + assert_raises(TypeError, random.standard_exponential, dtype=np.int32) + def test_standard_gamma(self): - legacy.seed(self.seed) - actual = legacy.standard_gamma(shape=3, size=(3, 2)) - desired = np.array([[5.50841531318455058, 6.62953470301903103], - [5.93988484943779227, 2.31044849402133989], - [7.54838614231317084, 8.012756093271868]]) + random.seed(self.seed) + actual = random.standard_gamma(shape=3, size=(3, 2)) + desired = np.array([[2.28483515569645, 3.29899524967824], + [11.12492298902645, 2.16784417297277], + [0.92121813690910, 1.12853552328470]]) assert_array_almost_equal(actual, desired, decimal=14) + def test_standard_gammma_scalar_float(self): + random.seed(self.seed) + actual = random.standard_gamma(3, dtype=np.float32) + desired = 1.3877466 + assert_array_almost_equal(actual, desired, decimal=6) + + def test_standard_gamma_float(self): + random.seed(self.seed) + actual = random.standard_gamma(shape=3, size=(3, 2)) + desired = np.array([[2.2848352, 3.2989952], + [11.124923, 2.1678442], + [0.9212181, 1.1285355]]) + assert_array_almost_equal(actual, desired, decimal=5) + + def test_standard_gammma_float_out(self): + actual = np.zeros((3, 2), dtype=np.float32) + random.seed(self.seed) + random.standard_gamma(10.0, out=actual, dtype=np.float32) + desired = np.array([[6.9824033, 7.3731737], + [14.860578, 7.5327270], + [11.767487, 6.2320185]], dtype=np.float32) + assert_array_almost_equal(actual, desired, decimal=5) + + random.seed(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(mt19937.standard_gamma(shape=0), 0) - assert_raises(ValueError, mt19937.standard_gamma, shape=-0.) + assert_equal(random.standard_gamma(shape=0), 0) + assert_raises(ValueError, random.standard_gamma, shape=-0.) def test_standard_normal(self): - legacy.seed(self.seed) - actual = legacy.standard_normal(size=(3, 2)) - desired = np.array([[1.34016345771863121, 1.73759122771936081], - [1.498988344300628, -0.2286433324536169], - [2.031033998682787, 2.17032494605655257]]) + random.seed(self.seed) + actual = random.standard_normal(size=(3, 2)) + desired = np.array([[-3.472754000610961, -0.108938564229143], + [-0.245965753396411, -0.704101550261701], + [0.360102487116356, 0.127832101772367]]) 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): - legacy.seed(self.seed) - actual = legacy.standard_t(df=10, size=(3, 2)) - desired = np.array([[0.97140611862659965, -0.08830486548450577], - [1.36311143689505321, -0.55317463909867071], - [-0.18473749069684214, 0.61181537341755321]]) + random.seed(self.seed) + actual = random.standard_t(df=10, size=(3, 2)) + desired = np.array([[-3.68722108185508, -0.672031186266171], + [2.900224996448669, -0.199656996187739], + [-1.12179956985969, 1.85668262342106]]) assert_array_almost_equal(actual, desired, decimal=15) def test_triangular(self): - mt19937.seed(self.seed) - actual = mt19937.triangular(left=5.12, mode=10.23, right=20.34, - size=(3, 2)) + 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): - mt19937.seed(self.seed) - actual = mt19937.uniform(low=1.23, high=10.54, size=(3, 2)) + 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]]) @@ -1048,7 +1144,7 @@ def test_uniform_range_bounds(self): fmin = np.finfo('float').min fmax = np.finfo('float').max - func = mt19937.uniform + func = random.uniform assert_raises(OverflowError, func, -np.inf, 0) assert_raises(OverflowError, func, 0, np.inf) assert_raises(OverflowError, func, fmin, fmax) @@ -1058,7 +1154,7 @@ def test_uniform_range_bounds(self): # (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 - mt19937.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17) + random.uniform(low=np.nextafter(fmin, 1), high=fmax / 1e17) def test_scalar_exception_propagation(self): # Tests that exceptions are correctly propagated in distributions @@ -1072,7 +1168,7 @@ def __float__(self): raise TypeError throwing_float = np.array(1.0).view(ThrowingFloat) - assert_raises(TypeError, mt19937.uniform, + assert_raises(TypeError, random.uniform, throwing_float, throwing_float) class ThrowingInteger(np.ndarray): @@ -1080,11 +1176,11 @@ def __int__(self): raise TypeError throwing_int = np.array(1).view(ThrowingInteger) - assert_raises(TypeError, mt19937.hypergeometric, throwing_int, 1, 1) + assert_raises(TypeError, random.hypergeometric, throwing_int, 1, 1) def test_vonmises(self): - mt19937.seed(self.seed) - actual = mt19937.vonmises(mu=1.23, kappa=1.54, size=(3, 2)) + 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]]) @@ -1092,34 +1188,34 @@ def test_vonmises(self): def test_vonmises_small(self): # check infinite loop, gh-4720 - mt19937.seed(self.seed) - r = mt19937.vonmises(mu=0., kappa=1.1e-8, size=10 ** 6) + random.seed(self.seed) + r = random.vonmises(mu=0., kappa=1.1e-8, size=10 ** 6) assert_(np.isfinite(r).all()) def test_wald(self): - legacy.seed(self.seed) - actual = legacy.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]]) + random.seed(self.seed) + actual = random.wald(mean=1.23, scale=1.54, size=(3, 2)) + desired = np.array([[0.10653278160339, 0.98771068102461], + [0.89276055317879, 0.13640126419923], + [0.9194319091599, 0.36037816317472]]) assert_array_almost_equal(actual, desired, decimal=14) def test_weibull(self): - legacy.seed(self.seed) - actual = legacy.weibull(a=1.23, size=(3, 2)) - desired = np.array([[0.97097342648766727, 0.91422896443565516], - [1.89517770034962929, 1.91414357960479564], - [0.67057783752390987, 1.39494046635066793]]) + random.seed(self.seed) + actual = random.weibull(a=1.23, size=(3, 2)) + desired = np.array([[3.557276979846361, 1.020870580998542], + [2.731847777612348, 1.29148068905082], + [0.385531483942839, 2.049551716717254]]) assert_array_almost_equal(actual, desired, decimal=15) def test_weibull_0(self): - mt19937.seed(self.seed) - assert_equal(mt19937.weibull(a=0, size=12), np.zeros(12)) - assert_raises(ValueError, mt19937.weibull, a=-0.) + 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): - mt19937.seed(self.seed) - actual = mt19937.zipf(a=1.23, size=(3, 2)) + random.seed(self.seed) + actual = random.zipf(a=1.23, size=(3, 2)) desired = np.array([[66, 29], [1, 1], [3, 13]]) @@ -1134,7 +1230,6 @@ def setup(self): def set_seed(self): random.seed(self.seed) - legacy.seed(self.seed) def test_uniform(self): low = [0] @@ -1156,126 +1251,112 @@ def test_normal(self): loc = [0] scale = [1] bad_scale = [-1] - normal = legacy.normal - desired = np.array([2.2129019979039612, - 2.1283977976520019, - 1.8417114045748335]) + normal = random.normal + desired = np.array([0.454879818179180, + -0.62749179463661, + -0.06063266769872]) self.set_seed() actual = normal(loc * 3, scale) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, normal, loc * 3, bad_scale) - assert_raises(ValueError, mt19937.normal, loc * 3, bad_scale) + assert_raises(ValueError, random.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) - assert_raises(ValueError, mt19937.normal, loc, bad_scale * 3) + assert_raises(ValueError, random.normal, loc, bad_scale * 3) def test_beta(self): a = [1] b = [2] bad_a = [-1] bad_b = [-2] - beta = legacy.beta - desired = np.array([0.19843558305989056, - 0.075230336409423643, - 0.24976865978980844]) + beta = random.beta + desired = np.array([0.63222080311226, + 0.33310522220774, + 0.64494078460190]) 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) - assert_raises(ValueError, mt19937.beta, bad_a * 3, b) - assert_raises(ValueError, mt19937.beta, a * 3, bad_b) self.set_seed() actual = beta(a, b * 3) assert_array_almost_equal(actual, desired, decimal=14) - assert_raises(ValueError, mt19937.beta, bad_a, b * 3) - assert_raises(ValueError, mt19937.beta, a, bad_b * 3) def test_exponential(self): scale = [1] bad_scale = [-1] - exponential = legacy.exponential - desired = np.array([0.76106853658845242, - 0.76386282278691653, - 0.71243813125891797]) + exponential = random.exponential + desired = np.array([1.68591211640990, + 3.14186859487914, + 0.67717375919228]) self.set_seed() actual = exponential(scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, exponential, bad_scale * 3) - assert_raises(ValueError, mt19937.exponential, bad_scale * 3) def test_standard_gamma(self): shape = [1] bad_shape = [-1] - std_gamma = legacy.standard_gamma - desired = np.array([0.76106853658845242, - 0.76386282278691653, - 0.71243813125891797]) + std_gamma = random.standard_gamma + desired = np.array([1.68591211640990, + 3.14186859487914, + 0.67717375919228]) self.set_seed() actual = std_gamma(shape * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, std_gamma, bad_shape * 3) - assert_raises(ValueError, mt19937.standard_gamma, bad_shape * 3) def test_gamma(self): shape = [1] scale = [2] bad_shape = [-1] bad_scale = [-2] - gamma = legacy.gamma - desired = np.array([1.5221370731769048, - 1.5277256455738331, - 1.4248762625178359]) + gamma = random.gamma + desired = np.array([3.37182423281980, + 6.28373718975827, + 1.35434751838456]) 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) - assert_raises(ValueError, mt19937.gamma, bad_shape * 3, scale) - assert_raises(ValueError, mt19937.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) - assert_raises(ValueError, mt19937.gamma, bad_shape, scale * 3) - assert_raises(ValueError, mt19937.gamma, shape, bad_scale * 3) def test_f(self): dfnum = [1] dfden = [2] bad_dfnum = [-1] bad_dfden = [-2] - f = legacy.f - desired = np.array([0.80038951638264799, - 0.86768719635363512, - 2.7251095168386801]) + f = random.f + desired = np.array([0.84207044881810, + 3.08607209903483, + 3.12823105933169]) 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) - assert_raises(ValueError, mt19937.f, bad_dfnum * 3, dfden) - assert_raises(ValueError, mt19937.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) - assert_raises(ValueError, mt19937.f, bad_dfnum, dfden * 3) - assert_raises(ValueError, mt19937.f, dfnum, bad_dfden * 3) def test_noncentral_f(self): dfnum = [2] @@ -1284,20 +1365,18 @@ def test_noncentral_f(self): bad_dfnum = [0] bad_dfden = [-1] bad_nonc = [-2] - nonc_f = legacy.noncentral_f - desired = np.array([9.1393943263705211, - 13.025456344595602, - 8.8018098359100545]) + nonc_f = random.noncentral_f + desired = np.array([3.83710578542563, + 8.74926819712029, + 0.48892943835401]) self.set_seed() actual = nonc_f(dfnum * 3, dfden, nonc) + mt_nonc_f = random.noncentral_f assert_array_almost_equal(actual, desired, decimal=14) 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) - assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum * 3, dfden, nonc) - assert_raises(ValueError, mt19937.noncentral_f, dfnum * 3, bad_dfden, nonc) - assert_raises(ValueError, mt19937.noncentral_f, dfnum * 3, dfden, bad_nonc) self.set_seed() actual = nonc_f(dfnum, dfden * 3, nonc) @@ -1305,9 +1384,6 @@ def test_noncentral_f(self): 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) - assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum, dfden * 3, nonc) - assert_raises(ValueError, mt19937.noncentral_f, dfnum, bad_dfden * 3, nonc) - assert_raises(ValueError, mt19937.noncentral_f, dfnum, dfden * 3, bad_nonc) self.set_seed() actual = nonc_f(dfnum, dfden, nonc * 3) @@ -1315,9 +1391,9 @@ def test_noncentral_f(self): 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) - assert_raises(ValueError, mt19937.noncentral_f, bad_dfnum, dfden, nonc * 3) - assert_raises(ValueError, mt19937.noncentral_f, dfnum, bad_dfden, nonc * 3) - assert_raises(ValueError, mt19937.noncentral_f, dfnum, dfden, bad_nonc * 3) + assert_raises(ValueError, mt_nonc_f, bad_dfnum, dfden, nonc * 3) + assert_raises(ValueError, mt_nonc_f, dfnum, bad_dfden, nonc * 3) + assert_raises(ValueError, mt_nonc_f, dfnum, dfden, bad_nonc * 3) def test_chisquare(self): df = [1] @@ -1337,40 +1413,41 @@ def test_noncentral_chisquare(self): nonc = [2] bad_df = [-1] bad_nonc = [-2] - nonc_chi = legacy.noncentral_chisquare - desired = np.array([9.0015599467913763, - 4.5804135049718742, - 6.0872302432834564]) + nonc_chi = random.noncentral_chisquare + desired = np.array([2.20478739452297, + 1.45177405755115, + 1.00418921695354]) self.set_seed() actual = nonc_chi(df * 3, nonc) + mt_nonc_chi2 = random.noncentral_chisquare 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) - assert_raises(ValueError, mt19937.noncentral_chisquare, bad_df * 3, nonc) - assert_raises(ValueError, mt19937.noncentral_chisquare, df * 3, bad_nonc) + assert_raises(ValueError, mt_nonc_chi2, bad_df * 3, nonc) + assert_raises(ValueError, mt_nonc_chi2, 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) - assert_raises(ValueError, mt19937.noncentral_chisquare, bad_df, nonc * 3) - assert_raises(ValueError, mt19937.noncentral_chisquare, df, bad_nonc * 3) + assert_raises(ValueError, mt_nonc_chi2, bad_df, nonc * 3) + assert_raises(ValueError, mt_nonc_chi2, df, bad_nonc * 3) def test_standard_t(self): df = [1] bad_df = [-1] - t = legacy.standard_t - desired = np.array([3.0702872575217643, - 5.8560725167361607, - 1.0274791436474273]) + t = random.standard_t + desired = np.array([0.60081050724244, + -0.90380889829210, + -0.64499590504117]) 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, mt19937.standard_t, bad_df * 3) + assert_raises(ValueError, random.standard_t, bad_df * 3) def test_vonmises(self): mu = [2] @@ -1394,44 +1471,44 @@ def test_vonmises(self): def test_pareto(self): a = [1] bad_a = [-1] - pareto = legacy.pareto - desired = np.array([1.1405622680198362, - 1.1465519762044529, - 1.0389564467453547]) + pareto = random.pareto + desired = np.array([4.397371719158540, + 22.14707898642946, + 0.968306954322200]) 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, mt19937.pareto, bad_a * 3) + assert_raises(ValueError, random.pareto, bad_a * 3) def test_weibull(self): a = [1] bad_a = [-1] - weibull = legacy.weibull - desired = np.array([0.76106853658845242, - 0.76386282278691653, - 0.71243813125891797]) + weibull = random.weibull + desired = np.array([1.68591211640990, + 3.14186859487914, + 0.67717375919228]) 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, mt19937.weibull, bad_a * 3) + assert_raises(ValueError, random.weibull, bad_a * 3) def test_power(self): a = [1] bad_a = [-1] - power = legacy.power - desired = np.array([0.53283302478975902, - 0.53413660089041659, - 0.50955303552646702]) + power = random.power + desired = np.array([0.81472463783615, + 0.95679800459547, + 0.49194916077287]) 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, mt19937.power, bad_a * 3) + assert_raises(ValueError, random.power, bad_a * 3) def test_laplace(self): loc = [0] @@ -1489,28 +1566,28 @@ def test_logistic(self): actual = logistic(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, logistic, loc, bad_scale * 3) - assert_equal(mt19937.logistic(1.0, 0.0), 1.0) + assert_equal(random.logistic(1.0, 0.0), 1.0) def test_lognormal(self): mean = [0] sigma = [1] bad_sigma = [-1] - lognormal = legacy.lognormal - desired = np.array([9.1422086044848427, - 8.4013952870126261, - 6.3073234116578671]) + lognormal = random.lognormal + desired = np.array([1.57598396702930, + 0.53392932731280, + 0.94116889802361]) 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, mt19937.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, mt19937.lognormal, mean, bad_sigma * 3) + assert_raises(ValueError, random.lognormal, mean, bad_sigma * 3) def test_rayleigh(self): scale = [1] @@ -1530,26 +1607,26 @@ def test_wald(self): scale = [1] bad_mean = [0] bad_scale = [-2] - wald = legacy.wald - desired = np.array([0.11873681120271318, - 0.12450084820795027, - 0.9096122728408238]) + wald = random.wald + desired = np.array([0.36297361471752, + 0.52190135028254, + 0.55111022040727]) 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, mt19937.wald, bad_mean * 3, scale) - assert_raises(ValueError, mt19937.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, mt19937.wald, bad_mean, scale * 3) - assert_raises(ValueError, mt19937.wald, mean, bad_scale * 3) + assert_raises(ValueError, random.wald, bad_mean, scale * 3) + assert_raises(ValueError, random.wald, mean, bad_scale * 3) def test_triangular(self): left = [1] @@ -1587,6 +1664,10 @@ def test_triangular(self): 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] @@ -1616,8 +1697,8 @@ def test_negative_binomial(self): bad_n = [-1] bad_p_one = [-1] bad_p_two = [1.5] - neg_binom = legacy.negative_binomial - desired = np.array([1, 0, 1]) + neg_binom = random.negative_binomial + desired = np.array([3, 1, 2], dtype=np.int64) self.set_seed() actual = neg_binom(n * 3, p) @@ -1625,9 +1706,6 @@ def test_negative_binomial(self): 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) - assert_raises(ValueError, mt19937.negative_binomial, bad_n * 3, p) - assert_raises(ValueError, mt19937.negative_binomial, n * 3, bad_p_one) - assert_raises(ValueError, mt19937.negative_binomial, n * 3, bad_p_two) self.set_seed() actual = neg_binom(n, p * 3) @@ -1635,9 +1713,6 @@ def test_negative_binomial(self): 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) - assert_raises(ValueError, mt19937.negative_binomial, bad_n, p * 3) - assert_raises(ValueError, mt19937.negative_binomial, n, bad_p_one * 3) - assert_raises(ValueError, mt19937.negative_binomial, n, bad_p_two * 3) def test_poisson(self): max_lam = random.poisson_lam_max @@ -1713,6 +1788,11 @@ def test_hypergeometric(self): 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] @@ -1783,14 +1863,14 @@ def setup(self): self.tgtShape = (1,) def test_one_arg_funcs(self): - funcs = (mt19937.exponential, mt19937.standard_gamma, - mt19937.chisquare, mt19937.standard_t, - mt19937.pareto, mt19937.weibull, - mt19937.power, mt19937.rayleigh, - mt19937.poisson, mt19937.zipf, - mt19937.geometric, mt19937.logseries) + 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 = (mt19937.geometric, mt19937.logseries) + probfuncs = (random.geometric, random.logseries) for func in funcs: if func in probfuncs: # p < 1.0 @@ -1802,15 +1882,15 @@ def test_one_arg_funcs(self): assert_equal(out.shape, self.tgtShape) def test_two_arg_funcs(self): - funcs = (mt19937.uniform, mt19937.normal, - mt19937.beta, mt19937.gamma, - mt19937.f, mt19937.noncentral_chisquare, - mt19937.vonmises, mt19937.laplace, - mt19937.gumbel, mt19937.logistic, - mt19937.lognormal, mt19937.wald, - mt19937.binomial, mt19937.negative_binomial) + 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 = (mt19937.binomial, mt19937.negative_binomial) + probfuncs = (random.binomial, random.negative_binomial) for func in funcs: if func in probfuncs: # p <= 1 @@ -1828,26 +1908,26 @@ def test_two_arg_funcs(self): out = func(self.argOne, argTwo[0]) assert_equal(out.shape, self.tgtShape) - def test_randint(self): - itype = [np.bool, np.int8, np.uint8, np.int16, np.uint16, - np.int32, np.uint32, np.int64, np.uint64] - func = mt19937.randint - high = np.array([1]) - low = np.array([0]) - - for dt in itype: - out = func(low, high, dtype=dt) - assert_equal(out.shape, self.tgtShape) + def test_randint(self): + itype = [np.bool, np.int8, np.uint8, np.int16, np.uint16, + np.int32, np.uint32, np.int64, np.uint64] + func = random.randint + high = np.array([1]) + low = np.array([0]) + + for dt in itype: + out = func(low, high, dtype=dt) + assert_equal(out.shape, self.tgtShape) - out = func(low[0], high, dtype=dt) - assert_equal(out.shape, self.tgtShape) + out = func(low[0], high, dtype=dt) + assert_equal(out.shape, self.tgtShape) - out = func(low, high[0], dtype=dt) - assert_equal(out.shape, self.tgtShape) + out = func(low, high[0], dtype=dt) + assert_equal(out.shape, self.tgtShape) def test_three_arg_funcs(self): - funcs = [mt19937.noncentral_f, mt19937.triangular, - mt19937.hypergeometric] + funcs = [random.noncentral_f, random.triangular, + random.hypergeometric] for func in funcs: out = func(self.argOne, self.argTwo, self.argThree) diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py b/numpy/random/randomgen/tests/test_generator_mt19937_regressions.py similarity index 98% rename from _randomgen/randomgen/tests/test_numpy_mt19937_regressions.py rename to numpy/random/randomgen/tests/test_generator_mt19937_regressions.py index bc644e122439..75064720fb97 100644 --- a/_randomgen/randomgen/tests/test_numpy_mt19937_regressions.py +++ b/numpy/random/randomgen/tests/test_generator_mt19937_regressions.py @@ -1,11 +1,9 @@ -from __future__ import division, absolute_import, print_function - import sys from numpy.testing import (assert_, assert_array_equal) from numpy.compat import long import numpy as np import pytest -from randomgen import RandomGenerator, MT19937 +from ...randomgen import RandomGenerator, MT19937 mt19937 = RandomGenerator(MT19937()) diff --git a/numpy/random/randomgen/tests/test_randomstate.py b/numpy/random/randomgen/tests/test_randomstate.py new file mode 100644 index 000000000000..167d1b0aa545 --- /dev/null +++ b/numpy/random/randomgen/tests/test_randomstate.py @@ -0,0 +1,1808 @@ +import pickle +import sys +import warnings + +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 ...randomgen import MT19937, Xoshiro256StarStar, mtrand as random + + +def assert_mt19937_state_equal(a, b): + assert_equal(a['brng'], b['brng']) + 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_seed_equivalency(self): + rs = random.RandomState(0) + rs2 = random.RandomState(MT19937(0)) + assert_mt19937_state_equal(rs.get_state(legacy=False), + rs2.get_state(legacy=False)) + + 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)) + assert_raises(ValueError, random.multinomial, 1, [1.1, .1]) + + +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(Xoshiro256StarStar()) + with suppress_warnings() as sup: + w = sup.record(RuntimeWarning) + state = rs.get_state() + assert_(len(w) == 1) + assert isinstance(state, dict) + assert state['brng'] == 'Xoshiro256StarStar' + + 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['brng'] + 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): + 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': '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_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) + + 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) + + 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) + + def test_rand_singleton(self): + random.seed(self.seed) + actual = random.rand() + desired = np.array(0.61879477158567997) + assert_array_almost_equal(actual, desired, 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_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_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_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_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) + + 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_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_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_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_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_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) + + 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) + np.testing.assert_(np.isfinite(r).all()) + + 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 setSeed(self): + random.seed(self.seed) + + # TODO: Include test for randint once it can broadcast + # Can steal the test written in PR #6938 + + def test_uniform(self): + low = [0] + high = [1] + uniform = random.uniform + desired = np.array([0.53283302478975902, + 0.53413660089041659, + 0.50955303552646702]) + + self.setSeed() + actual = uniform(low * 3, high) + assert_array_almost_equal(actual, desired, decimal=14) + + self.setSeed() + 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.setSeed() + actual = normal(loc * 3, scale) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, normal, loc * 3, bad_scale) + + self.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + actual = nonc_f(dfnum * 3, dfden, nonc) + assert_array_almost_equal(actual, desired, decimal=14) + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + actual = t(df * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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.setSeed() + actual = vonmises(mu * 3, kappa) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, vonmises, mu * 3, bad_kappa) + + self.setSeed() + 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.setSeed() + actual = pareto(a * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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.setSeed() + actual = weibull(a * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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.setSeed() + actual = power(a * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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.setSeed() + actual = laplace(loc * 3, scale) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, laplace, loc * 3, bad_scale) + + self.setSeed() + 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.setSeed() + actual = gumbel(loc * 3, scale) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, gumbel, loc * 3, bad_scale) + + self.setSeed() + 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.setSeed() + actual = logistic(loc * 3, scale) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, logistic, loc * 3, bad_scale) + + self.setSeed() + actual = logistic(loc, scale * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, logistic, loc, bad_scale * 3) + + def test_lognormal(self): + mean = [0] + sigma = [1] + bad_sigma = [-1] + lognormal = random.lognormal + desired = np.array([9.1422086044848427, + 8.4013952870126261, + 6.3073234116578671]) + + self.setSeed() + actual = lognormal(mean * 3, sigma) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, lognormal, mean * 3, bad_sigma) + + self.setSeed() + actual = lognormal(mean, sigma * 3) + assert_array_almost_equal(actual, desired, decimal=14) + assert_raises(ValueError, 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.setSeed() + 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.setSeed() + 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) + + self.setSeed() + 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.setSeed() + 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.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) + + 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, 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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.setSeed() + 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, 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.setSeed() + 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) + +# TODO: Uncomment once randint can broadcast arguments +# def test_randint(self): +# itype = [bool, np.int8, np.uint8, np.int16, np.uint16, +# np.int32, np.uint32, np.int64, np.uint64] +# func = random.randint +# high = np.array([1]) +# low = np.array([0]) +# +# for dt in itype: +# out = func(low, high, dtype=dt) +# self.assert_equal(out.shape, self.tgtShape) +# +# out = func(low[0], high, dtype=dt) +# self.assert_equal(out.shape, self.tgtShape) +# +# out = func(low, high[0], dtype=dt) +# self.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/randomgen/tests/test_randomstate_regression.py b/numpy/random/randomgen/tests/test_randomstate_regression.py new file mode 100644 index 000000000000..cf21ee756b87 --- /dev/null +++ b/numpy/random/randomgen/tests/test_randomstate_regression.py @@ -0,0 +1,157 @@ +import sys +from numpy.testing import ( + assert_, assert_array_equal, assert_raises, + ) +from numpy.compat import long +import numpy as np + +from ...randomgen 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)) diff --git a/_randomgen/randomgen/tests/test_smoke.py b/numpy/random/randomgen/tests/test_smoke.py similarity index 90% rename from _randomgen/randomgen/tests/test_smoke.py rename to numpy/random/randomgen/tests/test_smoke.py index 5a9882a16aed..816ce6ddcd76 100644 --- a/_randomgen/randomgen/tests/test_smoke.py +++ b/numpy/random/randomgen/tests/test_smoke.py @@ -2,17 +2,15 @@ import pickle import sys import time +from functools import partial import numpy as np import pytest -from numpy.testing import assert_almost_equal, assert_equal, assert_, \ - assert_array_equal - -from randomgen._testing import suppress_warnings -from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ - Xoshiro512StarStar -from randomgen import entropy +from numpy.testing import (assert_almost_equal, assert_equal, assert_, + assert_array_equal, suppress_warnings) +from ...randomgen import (RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, + PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, + Xoshiro512StarStar, entropy) @pytest.fixture(scope='module', @@ -155,13 +153,6 @@ def test_jump(self): brng_name = self.rg._basicrng.__class__.__name__ pytest.skip('Jump is not supported by {0}'.format(brng_name)) - def test_random_uintegers(self): - assert_(len(self.rg.random_uintegers(10)) == 10) - - def test_random_raw(self): - assert_(len(self.rg.random_raw(10)) == 10) - assert_(self.rg.random_raw((10, 10)).shape == (10, 10)) - def test_uniform(self): r = self.rg.uniform(-1.0, 0.0, size=10) assert_(len(r) == 10) @@ -203,6 +194,20 @@ 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) @@ -217,9 +222,9 @@ def test_binomial(self): def test_reset_state(self): state = self.rg.state - int_1 = self.rg.random_raw(1) + int_1 = self.rg.randint(2**31) self.rg.state = state - int_2 = self.rg.random_raw(1) + int_2 = self.rg.randint(2**31) assert_(int_1 == int_2) def test_entropy_init(self): @@ -232,11 +237,6 @@ def test_seed(self): rg2 = RandomGenerator(self.brng(*self.seed)) rg.random_sample() rg2.random_sample() - if not comp_state(rg.state, rg2.state): - for key in rg.state: - print(key) - print(rg.state[key]) - print(rg2.state[key]) assert_(comp_state(rg.state, rg2.state)) def test_reset_state_gauss(self): @@ -259,14 +259,14 @@ def test_reset_state_uint32(self): n2 = rg2.randint(0, 2 ** 24, 10, dtype=np.uint32) assert_array_equal(n1, n2) - def test_reset_state_uintegers(self): + def test_reset_state_float(self): rg = RandomGenerator(self.brng(*self.seed)) - rg.random_uintegers(bits=32) + rg.random_sample(dtype='float32') state = rg.state - n1 = rg.random_uintegers(bits=32, size=10) + n1 = rg.random_sample(size=10, dtype='float32') rg2 = RandomGenerator(self.brng()) rg2.state = state - n2 = rg2.random_uintegers(bits=32, size=10) + n2 = rg2.random_sample(size=10, dtype='float32') assert_((n1 == n2).all()) def test_shuffle(self): @@ -315,70 +315,6 @@ def test_chisquare(self): assert_(len(vals) == 10) params_1(self.rg.chisquare) - def test_complex_normal(self): - st = self.rg.state - vals = self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10) - assert_(len(vals) == 10) - - self.rg.state = st - vals2 = [self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j) for _ in range(10)] - np.testing.assert_allclose(vals, vals2) - - self.rg.state = st - vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j) - np.testing.assert_allclose(vals, vals3) - - self.rg.state = st - norms = self.rg.standard_normal(size=20) - norms = np.reshape(norms, (10, 2)) - cov = 0.5 * (-5.0) - v_real = 7.5 - v_imag = 2.5 - rho = cov / np.sqrt(v_real * v_imag) - imag = 7 + np.sqrt(v_imag) * (rho * - norms[:, 0] + np.sqrt(1 - rho ** 2) * - norms[:, 1]) - real = 2 + np.sqrt(v_real) * norms[:, 0] - vals4 = [re + im * (0 + 1.0j) for re, im in zip(real, imag)] - - np.testing.assert_allclose(vals4, vals) - - def test_complex_normal_bm(self): - st = self.rg.state - vals = self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10) - assert_(len(vals) == 10) - - self.rg.state = st - vals2 = [self.rg.complex_normal( - 2.0 + 7.0j, 10.0, 5.0 - 5.0j) for _ in range(10)] - np.testing.assert_allclose(vals, vals2) - - self.rg.state = st - vals3 = self.rg.complex_normal( - 2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j) - np.testing.assert_allclose(vals, vals3) - - def test_complex_normal_zero_variance(self): - st = self.rg.state - c = self.rg.complex_normal(0, 1.0, 1.0) - assert_almost_equal(c.imag, 0.0) - self.rg.state = st - n = self.rg.standard_normal() - np.testing.assert_allclose(c, n, atol=1e-8) - - st = self.rg.state - c = self.rg.complex_normal(0, 1.0, -1.0) - assert_almost_equal(c.real, 0.0) - self.rg.state = st - self.rg.standard_normal() - n = self.rg.standard_normal() - assert_almost_equal(c.real, 0.0) - np.testing.assert_allclose(c.imag, n, atol=1e-8) - def test_exponential(self): vals = self.rg.exponential(2.0, 10) assert_(len(vals) == 10) @@ -682,6 +618,10 @@ def test_output_fill(self): direct = rg.standard_normal(size=size) assert_equal(direct, existing) + sized = np.empty(size) + rg.state = state + rg.standard_normal(out=sized, size=sized.shape) + existing = np.empty(size, dtype=np.float32) rg.state = state rg.standard_normal(out=existing, dtype=np.float32) diff --git a/_randomgen/randomgen/threefry.pyx b/numpy/random/randomgen/threefry.pyx similarity index 85% rename from _randomgen/randomgen/threefry.pyx rename to numpy/random/randomgen/threefry.pyx index 96e65f62529e..8140c6a9b72a 100644 --- a/_randomgen/randomgen/threefry.pyx +++ b/numpy/random/randomgen/threefry.pyx @@ -1,15 +1,16 @@ -from __future__ import absolute_import - from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + import numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() @@ -25,10 +26,10 @@ cdef extern from 'src/threefry/threefry.h': ctypedef r123array4x64 threefry4x64_ctr_t struct s_threefry_state: - threefry4x64_ctr_t *ctr; - threefry4x64_key_t *key; - int buffer_pos; - uint64_t buffer[THREEFRY_BUFFER_SIZE]; + threefry4x64_ctr_t *ctr + threefry4x64_key_t *key + int buffer_pos + uint64_t buffer[THREEFRY_BUFFER_SIZE] int has_uint32 uint32_t uinteger @@ -154,13 +155,13 @@ cdef class ThreeFry: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef threefry_state *rng_state + cdef threefry_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator - + cdef public object lock def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry_state)) @@ -168,6 +169,7 @@ cdef class ThreeFry: self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &threefry_uint64 @@ -190,7 +192,8 @@ cdef class ThreeFry: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -207,16 +210,39 @@ cdef class ThreeFry: for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -294,7 +320,7 @@ cdef class ThreeFry: key[i] = self.rng_state.key.v[i] for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] - state = {'counter':ctr,'key':key} + state = {'counter': ctr, 'key': key} return {'brng': self.__class__.__name__, 'state': state, 'buffer': buffer, @@ -385,14 +411,15 @@ cdef class ThreeFry: self._reset_state_variables() return self + @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -401,25 +428,10 @@ cdef class ThreeFry: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&threefry_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&threefry_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&threefry_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -440,19 +452,8 @@ cdef class ThreeFry: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -461,10 +462,10 @@ cdef class ThreeFry: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/threefry32.pyx b/numpy/random/randomgen/threefry32.pyx similarity index 84% rename from _randomgen/randomgen/threefry32.pyx rename to numpy/random/randomgen/threefry32.pyx index 62c0e9cd8c92..1fa98eabdd29 100644 --- a/_randomgen/randomgen/threefry32.pyx +++ b/numpy/random/randomgen/threefry32.pyx @@ -1,14 +1,15 @@ -from __future__ import absolute_import +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock import numpy as np from cpython.pycapsule cimport PyCapsule_New from libc.stdlib cimport malloc, free -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() @@ -24,10 +25,10 @@ cdef extern from 'src/threefry32/threefry32.h': ctypedef r123array4x32 threefry4x32_ctr_t struct s_threefry32_state: - threefry4x32_ctr_t *ctr; - threefry4x32_key_t *key; - int buffer_pos; - uint32_t buffer[THREEFRY_BUFFER_SIZE]; + threefry4x32_ctr_t *ctr + threefry4x32_key_t *key + int buffer_pos + uint32_t buffer[THREEFRY_BUFFER_SIZE] ctypedef s_threefry32_state threefry32_state @@ -157,12 +158,13 @@ cdef class ThreeFry32: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef threefry32_state *rng_state + cdef threefry32_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None, counter=None, key=None): self.rng_state = malloc(sizeof(threefry32_state)) @@ -170,6 +172,7 @@ cdef class ThreeFry32: self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) self._brng = malloc(sizeof(brng_t)) self.seed(seed, counter, key) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &threefry32_uint64 @@ -192,7 +195,8 @@ cdef class ThreeFry32: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -207,16 +211,39 @@ cdef class ThreeFry32: for i in range(THREEFRY_BUFFER_SIZE): self.rng_state.buffer[i] = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method == u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method == u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -380,14 +407,15 @@ cdef class ThreeFry32: self._reset_state_variables() return self + @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -396,25 +424,10 @@ cdef class ThreeFry32: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface( self.rng_state, - ctypes.c_void_p( self.rng_state), - ctypes.cast( &threefry32_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast( &threefry32_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast( &threefry32_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p( self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -435,22 +448,8 @@ cdef class ThreeFry32: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface( self.rng_state, - ffi.cast('void *', self.rng_state), - ffi.cast('uint64_t (*)(void *)', - self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)', - self._brng.next_uint32), - ffi.cast('double (*)(void *)', - self._brng.next_double), - ffi.cast('void *', self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -459,7 +458,7 @@ cdef class ThreeFry32: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/_randomgen/randomgen/xoroshiro128.pyx b/numpy/random/randomgen/xoroshiro128.pyx similarity index 79% rename from _randomgen/randomgen/xoroshiro128.pyx rename to numpy/random/randomgen/xoroshiro128.pyx index 57760c53a7a1..7795500e8ea1 100644 --- a/_randomgen/randomgen/xoroshiro128.pyx +++ b/numpy/random/randomgen/xoroshiro128.pyx @@ -1,4 +1,7 @@ -from __future__ import absolute_import +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New @@ -6,26 +9,24 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() cdef extern from "src/xoroshiro128/xoroshiro128.h": struct s_xoroshiro128_state: - uint64_t s[2] - int has_uint32 - uint32_t uinteger + uint64_t s[2] + int has_uint32 + uint32_t uinteger ctypedef s_xoroshiro128_state xoroshiro128_state uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil uint32_t xoroshiro128_next32(xoroshiro128_state *state) nogil - void xoroshiro128_jump(xoroshiro128_state *state) + void xoroshiro128_jump(xoroshiro128_state *state) cdef uint64_t xoroshiro128_uint64(void* st) nogil: return xoroshiro128_next64(st) @@ -121,17 +122,19 @@ cdef class Xoroshiro128: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoroshiro128_state *rng_state + cdef xoroshiro128_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoroshiro128_state)) self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &xoroshiro128_uint64 @@ -154,7 +157,8 @@ cdef class Xoroshiro128: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -166,17 +170,39 @@ cdef class Xoroshiro128: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - """Private benchmark command""" - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -198,7 +224,7 @@ cdef class Xoroshiro128: ValueError If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + ub = 2 ** 64 if seed is None: try: state = random_entropy(4) @@ -273,12 +299,12 @@ cdef class Xoroshiro128: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -288,24 +314,10 @@ cdef class Xoroshiro128: * brng - pointer to the Basic RNG struct """ - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoroshiro128_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&xoroshiro128_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) + + return self._ctypes @property def cffi(self): @@ -326,19 +338,8 @@ cdef class Xoroshiro128: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -347,10 +348,10 @@ cdef class Xoroshiro128: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/xorshift1024.pyx b/numpy/random/randomgen/xorshift1024.pyx similarity index 77% rename from _randomgen/randomgen/xorshift1024.pyx rename to numpy/random/randomgen/xorshift1024.pyx index e7ad546e0ea6..3c7ffac52c54 100644 --- a/_randomgen/randomgen/xorshift1024.pyx +++ b/numpy/random/randomgen/xorshift1024.pyx @@ -1,4 +1,7 @@ -from __future__ import absolute_import +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New @@ -6,27 +9,25 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() cdef extern from "src/xorshift1024/xorshift1024.h": struct s_xorshift1024_state: - uint64_t s[16] - int p - int has_uint32 - uint32_t uinteger + uint64_t s[16] + int p + int has_uint32 + uint32_t uinteger ctypedef s_xorshift1024_state xorshift1024_state uint64_t xorshift1024_next64(xorshift1024_state *state) nogil uint32_t xorshift1024_next32(xorshift1024_state *state) nogil - void xorshift1024_jump(xorshift1024_state *state) + void xorshift1024_jump(xorshift1024_state *state) cdef uint64_t xorshift1024_uint64(void* st) nogil: return xorshift1024_next64(st) @@ -127,17 +128,19 @@ cdef class Xorshift1024: generators." CoRR, abs/1403.0930, 2014. """ - cdef xorshift1024_state *rng_state + cdef xorshift1024_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(xorshift1024_state)) self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &xorshift1024_uint64 @@ -160,7 +163,8 @@ cdef class Xorshift1024: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -172,41 +176,39 @@ cdef class Xorshift1024: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 - def __random_integer(self, bits=64): + def random_raw(self, size=None, output=True): """ - 64-bit Random Integers from the PRNG + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG Parameters ---------- - bits : {32, 64} - Number of random bits to return + 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 ------- - rv : int - Next random value + out : uint or ndarray + Drawn samples. Notes ----- - Testing only + 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. """ - if bits == 64: - return self._brng.next_uint64(self._brng.state) - elif bits == 32: - return self._brng.next_uint32(self._brng.state) - else: - raise ValueError('bits must be 32 or 64') + return random_raw(self._brng, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -229,7 +231,7 @@ cdef class Xorshift1024: If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + ub = 2 ** 64 if seed is None: try: state = random_entropy(32) @@ -285,7 +287,7 @@ cdef class Xorshift1024: for i in range(16): s[i] = self.rng_state.s[i] return {'brng': self.__class__.__name__, - 'state': {'s':s,'p':self.rng_state.p}, + 'state': {'s': s, 'p': self.rng_state.p}, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -306,12 +308,12 @@ cdef class Xorshift1024: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -320,25 +322,10 @@ cdef class Xorshift1024: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xorshift1024_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&xorshift1024_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&xorshift1024_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -359,19 +346,8 @@ cdef class Xorshift1024: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -380,10 +356,10 @@ cdef class Xorshift1024: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/xoshiro256starstar.pyx b/numpy/random/randomgen/xoshiro256starstar.pyx similarity index 80% rename from _randomgen/randomgen/xoshiro256starstar.pyx rename to numpy/random/randomgen/xoshiro256starstar.pyx index 33ecb50f1a88..c3856b6f7651 100644 --- a/_randomgen/randomgen/xoshiro256starstar.pyx +++ b/numpy/random/randomgen/xoshiro256starstar.pyx @@ -1,31 +1,32 @@ -from __future__ import absolute_import - from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() cdef extern from "src/xoshiro256starstar/xoshiro256starstar.h": struct s_xoshiro256starstar_state: - uint64_t s[4] - int has_uint32 - uint32_t uinteger + uint64_t s[4] + int has_uint32 + uint32_t uinteger ctypedef s_xoshiro256starstar_state xoshiro256starstar_state uint64_t xoshiro256starstar_next64(xoshiro256starstar_state *state) nogil uint32_t xoshiro256starstar_next32(xoshiro256starstar_state *state) nogil - void xoshiro256starstar_jump(xoshiro256starstar_state *state) + void xoshiro256starstar_jump(xoshiro256starstar_state *state) cdef uint64_t xoshiro256starstar_uint64(void* st) nogil: return xoshiro256starstar_next64(st) @@ -121,17 +122,19 @@ cdef class Xoshiro256StarStar: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoshiro256starstar_state *rng_state + cdef xoshiro256starstar_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoshiro256starstar_state)) self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &xoshiro256starstar_uint64 @@ -154,7 +157,8 @@ cdef class Xoshiro256StarStar: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -166,17 +170,39 @@ cdef class Xoshiro256StarStar: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - """Private benchmark command""" - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -198,7 +224,7 @@ cdef class Xoshiro256StarStar: ValueError If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + ub = 2 ** 64 if seed is None: try: state = random_entropy(8) @@ -279,12 +305,12 @@ cdef class Xoshiro256StarStar: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -293,25 +319,10 @@ cdef class Xoshiro256StarStar: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoshiro256starstar_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&xoshiro256starstar_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&xoshiro256starstar_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -332,19 +343,8 @@ cdef class Xoshiro256StarStar: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -353,10 +353,10 @@ cdef class Xoshiro256StarStar: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/_randomgen/randomgen/xoshiro512starstar.pyx b/numpy/random/randomgen/xoshiro512starstar.pyx similarity index 79% rename from _randomgen/randomgen/xoshiro512starstar.pyx rename to numpy/random/randomgen/xoshiro512starstar.pyx index 17fe3c420192..761d1f1d0b20 100644 --- a/_randomgen/randomgen/xoshiro512starstar.pyx +++ b/numpy/random/randomgen/xoshiro512starstar.pyx @@ -1,4 +1,7 @@ -from __future__ import absolute_import +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New @@ -6,26 +9,24 @@ from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np -from randomgen.common import interface -from randomgen.common cimport * -from randomgen.distributions cimport brng_t -from randomgen.entropy import random_entropy, seed_by_array -import randomgen.pickle +from .common cimport * +from .distributions cimport brng_t +from .entropy import random_entropy, seed_by_array np.import_array() cdef extern from "src/xoshiro512starstar/xoshiro512starstar.h": struct s_xoshiro512starstar_state: - uint64_t s[8] - int has_uint32 - uint32_t uinteger + uint64_t s[8] + int has_uint32 + uint32_t uinteger ctypedef s_xoshiro512starstar_state xoshiro512starstar_state uint64_t xoshiro512starstar_next64(xoshiro512starstar_state *state) nogil uint32_t xoshiro512starstar_next32(xoshiro512starstar_state *state) nogil - void xoshiro512starstar_jump(xoshiro512starstar_state *state) + void xoshiro512starstar_jump(xoshiro512starstar_state *state) cdef uint64_t xoshiro512starstar_uint64(void* st) nogil: return xoshiro512starstar_next64(st) @@ -121,17 +122,19 @@ cdef class Xoshiro512StarStar: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoshiro512starstar_state *rng_state + cdef xoshiro512starstar_state *rng_state cdef brng_t *_brng cdef public object capsule cdef object _ctypes cdef object _cffi cdef object _generator + cdef public object lock def __init__(self, seed=None): self.rng_state = malloc(sizeof(xoshiro512starstar_state)) self._brng = malloc(sizeof(brng_t)) self.seed(seed) + self.lock = Lock() self._brng.state = self.rng_state self._brng.next_uint64 = &xoshiro512starstar_uint64 @@ -154,7 +157,8 @@ cdef class Xoshiro512StarStar: self.state = state def __reduce__(self): - return (randomgen.pickle.__brng_ctor, + from ._pickle import __brng_ctor + return (__brng_ctor, (self.state['brng'],), self.state) @@ -166,17 +170,39 @@ cdef class Xoshiro512StarStar: self.rng_state.has_uint32 = 0 self.rng_state.uinteger = 0 + def random_raw(self, size=None, output=True): + """ + random_raw(self, size=None) + + Return randoms as generated by the underlying BasicRNG + + 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._brng, self.lock, size, output) + def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - """Private benchmark command""" - cdef Py_ssize_t i - if method==u'uint64': - for i in range(cnt): - self._brng.next_uint64(self._brng.state) - elif method==u'double': - for i in range(cnt): - self._brng.next_double(self._brng.state) - else: - raise ValueError('Unknown method') + return benchmark(self._brng, self.lock, cnt, method) def seed(self, seed=None): """ @@ -198,7 +224,7 @@ cdef class Xoshiro512StarStar: ValueError If seed values are out of range for the PRNG. """ - ub = 2 ** 64 + ub = 2 ** 64 if seed is None: try: state = random_entropy(16) @@ -273,12 +299,12 @@ cdef class Xoshiro512StarStar: @property def ctypes(self): """ - Ctypes interface + ctypes interface Returns ------- interface : namedtuple - Named tuple containing CFFI wrapper + Named tuple containing ctypes wrapper * state_address - Memory address of the state struct * state - pointer to the state struct @@ -287,25 +313,10 @@ cdef class Xoshiro512StarStar: * next_double - function pointer to produce doubles * brng - pointer to the Basic RNG struct """ + if self._ctypes is None: + self._ctypes = prepare_ctypes(self._brng) - if self._ctypes is not None: - return self._ctypes - - import ctypes - - self._ctypes = interface(self.rng_state, - ctypes.c_void_p(self.rng_state), - ctypes.cast(&xoshiro512starstar_uint64, - ctypes.CFUNCTYPE(ctypes.c_uint64, - ctypes.c_void_p)), - ctypes.cast(&xoshiro512starstar_uint32, - ctypes.CFUNCTYPE(ctypes.c_uint32, - ctypes.c_void_p)), - ctypes.cast(&xoshiro512starstar_double, - ctypes.CFUNCTYPE(ctypes.c_double, - ctypes.c_void_p)), - ctypes.c_void_p(self._brng)) - return self.ctypes + return self._ctypes @property def cffi(self): @@ -326,19 +337,8 @@ cdef class Xoshiro512StarStar: """ if self._cffi is not None: return self._cffi - try: - import cffi - except ImportError: - raise ImportError('cffi is cannot be imported.') - - ffi = cffi.FFI() - self._cffi = interface(self.rng_state, - ffi.cast('void *',self.rng_state), - ffi.cast('uint64_t (*)(void *)',self._brng.next_uint64), - ffi.cast('uint32_t (*)(void *)',self._brng.next_uint32), - ffi.cast('double (*)(void *)',self._brng.next_double), - ffi.cast('void *',self._brng)) - return self.cffi + self._cffi = prepare_cffi(self._brng) + return self._cffi @property def generator(self): @@ -347,10 +347,10 @@ cdef class Xoshiro512StarStar: Returns ------- - gen : randomgen.generator.RandomGenerator + gen : numpy.random.randomgen.generator.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: from .generator import RandomGenerator self._generator = RandomGenerator(self) - return self._generator \ No newline at end of file + return self._generator diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 394a70ead371..481c4e380a88 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -2,6 +2,9 @@ from os.path import join import sys +import os +import platform +import struct from distutils.dep_util import newer from distutils.msvccompiler import get_build_version as get_msvc_build_version @@ -16,6 +19,7 @@ def needs_mingw_ftime_workaround(): return False + def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration, get_mathlibs config = Configuration('random', parent_package, top_path) @@ -40,6 +44,7 @@ def generate_libraries(ext, build_dir): defs.append(("NPY_NEEDS_MINGW_TIME_WORKAROUND", None)) libs = [] + defs.append(('NPY_NO_DEPRECATED_API', 0)) # Configure mtrand config.add_extension('mtrand', sources=[join('mtrand', x) for x in @@ -55,9 +60,9 @@ def generate_libraries(ext, build_dir): config.add_data_files(('.', join('mtrand', 'randomkit.h'))) config.add_data_dir('tests') + config.add_subpackage('randomgen') return config - if __name__ == '__main__': from numpy.distutils.core import setup setup(configuration=configuration) diff --git a/setup.py b/setup.py index e887238203c6..d7fa3f544c5e 100755 --- a/setup.py +++ b/setup.py @@ -225,12 +225,13 @@ def run(self): def generate_cython(): cwd = os.path.abspath(os.path.dirname(__file__)) print("Cythonizing sources") - p = subprocess.call([sys.executable, - os.path.join(cwd, 'tools', 'cythonize.py'), - 'numpy/random'], - cwd=cwd) - if p != 0: - raise RuntimeError("Running cythonize failed!") + for d in ('mtrand', 'randomgen', 'randomgen/legacy'): + p = subprocess.call([sys.executable, + os.path.join(cwd, 'tools', 'cythonize.py'), + 'numpy/random/{0}'.format(d)], + cwd=cwd) + if p != 0: + raise RuntimeError("Running cythonize failed!") def parse_setuppy_commands(): diff --git a/tools/cythonize.py b/tools/cythonize.py index 9e2af840dff5..c81b72d2506a 100755 --- a/tools/cythonize.py +++ b/tools/cythonize.py @@ -52,7 +52,7 @@ # Rules # def process_pyx(fromfile, tofile): - flags = ['--fast-fail'] + flags = ['-3', '--fast-fail'] if tofile.endswith('.cxx'): flags += ['--cplus'] @@ -99,6 +99,17 @@ def process_tempita_pyx(fromfile, tofile): process_pyx(pyxfile, tofile) +def process_tempita_pyd(fromfile, tofile): + import npy_tempita as tempita + + assert fromfile.endswith('.pxd.in') + assert tofile.endswith('.pxd') + with open(fromfile, "r") as f: + tmpl = f.read() + pyxcontent = tempita.sub(tmpl) + with open(tofile, "w") as f: + f.write(pyxcontent) + def process_tempita_pxi(fromfile, tofile): import npy_tempita as tempita @@ -110,10 +121,24 @@ def process_tempita_pxi(fromfile, tofile): with open(tofile, "w") as f: f.write(pyxcontent) +def process_tempita_pxd(fromfile, tofile): + import npy_tempita as tempita + + assert fromfile.endswith('.pxd.in') + assert tofile.endswith('.pxd') + with open(fromfile, "r") as f: + tmpl = f.read() + pyxcontent = tempita.sub(tmpl) + with open(tofile, "w") as f: + f.write(pyxcontent) + rules = { - # fromext : function - '.pyx' : process_pyx, - '.pyx.in' : process_tempita_pyx + # fromext : function, toext + '.pyx' : (process_pyx, '.c'), + '.pyx.in' : (process_tempita_pyx, '.c'), + '.pxi.in' : (process_tempita_pxi, '.pxi'), + '.pxd.in' : (process_tempita_pxd, '.pxd'), + '.pyd.in' : (process_tempita_pyd, '.pyd'), } # # Hash db @@ -179,38 +204,32 @@ def process(path, fromfile, tofile, processor_function, hash_db): def find_process_files(root_dir): hash_db = load_hashes(HASH_FILE) - for cur_dir, dirs, files in os.walk(root_dir): - # .pxi or .pxi.in files are most likely dependencies for - # .pyx files, so we need to process them first - files.sort(key=lambda name: (name.endswith('.pxi') or - name.endswith('.pxi.in')), - reverse=True) - - for filename in files: - in_file = os.path.join(cur_dir, filename + ".in") - if filename.endswith('.pyx') and os.path.isfile(in_file): - continue - elif filename.endswith('.pxi.in'): - toext = '.pxi' - fromext = '.pxi.in' + files = [x for x in os.listdir(root_dir) if not os.path.isdir(x)] + # .pxi or .pxi.in files are most likely dependencies for + # .pyx files, so we need to process them first + files.sort(key=lambda name: (name.endswith('.pxi') or + name.endswith('.pxi.in') or + name.endswith('.pxd.in')), + reverse=True) + + for filename in files: + in_file = os.path.join(root_dir, filename + ".in") + for fromext, value in rules.items(): + if filename.endswith(fromext): + if not value: + break + function, toext = value + if toext == '.c': + with open(os.path.join(root_dir, filename), 'rb') as f: + data = f.read() + m = re.search(br"^\s*#\s*distutils:\s*language\s*=\s*c\+\+\s*$", data, re.I|re.M) + if m: + toext = ".cxx" fromfile = filename - function = process_tempita_pxi tofile = filename[:-len(fromext)] + toext - process(cur_dir, fromfile, tofile, function, hash_db) + process(root_dir, fromfile, tofile, function, hash_db) save_hashes(hash_db, HASH_FILE) - else: - for fromext, function in rules.items(): - if filename.endswith(fromext): - toext = ".c" - with open(os.path.join(cur_dir, filename), 'rb') as f: - data = f.read() - m = re.search(br"^\s*#\s*distutils:\s*language\s*=\s*c\+\+\s*$", data, re.I|re.M) - if m: - toext = ".cxx" - fromfile = filename - tofile = filename[:-len(fromext)] + toext - process(cur_dir, fromfile, tofile, function, hash_db) - save_hashes(hash_db, HASH_FILE) + break def main(): try: From 7e8e19f9a3b452fdbd992568348b393c31fba005 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 8 Apr 2019 10:11:07 +0100 Subject: [PATCH 104/138] BUG: Correct handling of nans Improve consistency of nan handling Prevent nans prducing values from int functions Add tests to ensure guards work Synchronize with randomgen Remove comments no longer relevant --- .circleci/config.yml | 2 +- .../reference/randomgen/new-or-different.rst | 2 +- numpy/random/randomgen/common.pyx | 3 + numpy/random/randomgen/tests/test_direct.py | 6 +- .../randomgen/tests/test_generator_mt19937.py | 127 +++++---- .../randomgen/tests/test_randomstate.py | 241 +++++++++++------- 6 files changed, 235 insertions(+), 146 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2a3d826770a3..e7fbf55fe6a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,7 @@ jobs: command: | python3 -m venv venv . venv/bin/activate - pip install cython sphinx==1.8.5 matplotlib + pip install cython sphinx>=1.8.5 matplotlib ipython sudo apt-get update sudo apt-get install -y graphviz texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra texlive-generic-extra latexmk texlive-xetex diff --git a/doc/source/reference/randomgen/new-or-different.rst b/doc/source/reference/randomgen/new-or-different.rst index 6598c13feb36..0a27b9aa158c 100644 --- a/doc/source/reference/randomgen/new-or-different.rst +++ b/doc/source/reference/randomgen/new-or-different.rst @@ -35,7 +35,7 @@ What's New or Different .. ipython:: python - from randomgen import Xoroshiro128 + from numpy.random.randomgen import Xoroshiro128 import numpy.random rg = Xoroshiro128().generator %timeit rg.standard_normal(100000) diff --git a/numpy/random/randomgen/common.pyx b/numpy/random/randomgen/common.pyx index 1f7cd40cac76..ebd2e60d107d 100644 --- a/numpy/random/randomgen/common.pyx +++ b/numpy/random/randomgen/common.pyx @@ -337,6 +337,9 @@ cdef int check_constraint(double val, object name, constraint_type cons) except 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)) diff --git a/numpy/random/randomgen/tests/test_direct.py b/numpy/random/randomgen/tests/test_direct.py index 6e856de414cb..22fdcd865944 100644 --- a/numpy/random/randomgen/tests/test_direct.py +++ b/numpy/random/randomgen/tests/test_direct.py @@ -233,14 +233,14 @@ def test_seed_out_of_range_array(self): def test_repr(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert 'RandomGenerator' in rs.__repr__() - assert str(hex(id(rs)))[2:].upper() in rs.__repr__() + assert 'RandomGenerator' in repr(rs) + assert '{:#x}'.format(id(rs)).upper().replace('X', 'x') in repr(rs) def test_str(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) assert 'RandomGenerator' in str(rs) assert str(self.brng.__name__) in str(rs) - assert str(hex(id(rs)))[2:].upper() not in str(rs) + assert '{:#x}'.format(id(rs)).upper().replace('X', 'x') not in str(rs) def test_generator(self): brng = self.brng(*self.data1['seed']) diff --git a/numpy/random/randomgen/tests/test_generator_mt19937.py b/numpy/random/randomgen/tests/test_generator_mt19937.py index cad3ef4d66cd..10dd8733a8b9 100644 --- a/numpy/random/randomgen/tests/test_generator_mt19937.py +++ b/numpy/random/randomgen/tests/test_generator_mt19937.py @@ -53,8 +53,7 @@ def test_n_zero(self): # This test addresses issue #3480. zeros = np.zeros(2, dtype='int') for p in [0, .5, 1]: - val = random.binomial(0, p) - assert val == 0 + assert_(random.binomial(0, p) == 0) assert_array_equal(random.binomial(zeros, p), zeros) def test_p_is_nan(self): @@ -96,40 +95,40 @@ def test_invalid_prob(self): class TestSetState(object): def setup(self): self.seed = 1234567890 - self.brng = RandomGenerator(MT19937(self.seed)) - self.state = self.brng.state + self.rg = RandomGenerator(MT19937(self.seed)) + self.state = self.rg.state self.legacy_state = (self.state['brng'], self.state['state']['key'], self.state['state']['pos']) def test_basic(self): - old = self.brng.tomaxint(16) - self.brng.state = self.state - new = self.brng.tomaxint(16) + old = self.rg.tomaxint(16) + self.rg.state = self.state + new = self.rg.tomaxint(16) assert_(np.all(old == new)) def test_gaussian_reset(self): # Make sure the cached every-other-Gaussian is reset. - old = self.brng.standard_normal(size=3) - self.brng.state = self.state - new = self.brng.standard_normal(size=3) + old = self.rg.standard_normal(size=3) + self.rg.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.brng.standard_normal() - state = self.brng.state - old = self.brng.standard_normal(size=3) - self.brng.state = state - new = self.brng.standard_normal(size=3) + self.rg.standard_normal() + state = self.rg.state + old = self.rg.standard_normal(size=3) + self.rg.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.brng.negative_binomial(0.5, 0.5) + self.rg.negative_binomial(0.5, 0.5) class TestRandint(object): @@ -554,8 +553,7 @@ def test_choice_uniform_noreplace(self): 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]) + 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) @@ -614,11 +612,11 @@ def test_choice_return_shape(self): # Check multi dimensional array s = (2, 3) p = [0.1, 0.1, 0.1, 0.1, 0.4, 0.2] - assert_(random.choice(6, s, replace=True).shape, s) - assert_(random.choice(6, s, replace=False).shape, s) - assert_(random.choice(6, s, replace=True, p=p).shape, s) - assert_(random.choice(6, s, replace=False, p=p).shape, s) - assert_(random.choice(np.arange(6), s, replace=True).shape, s) + 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)) @@ -711,6 +709,11 @@ def test_binomial(self): [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)) @@ -795,6 +798,16 @@ def test_geometric(self): [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)) @@ -873,6 +886,12 @@ def test_logseries(self): [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)) @@ -943,6 +962,13 @@ def test_negative_binomial(self): [723, 751]]) 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)) @@ -973,6 +999,11 @@ def test_noncentral_f(self): [1.16362730891403, 2.54104276581491]]) 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)) @@ -993,7 +1024,7 @@ def test_pareto(self): [1.1281132447159091e+01, 3.1895968171107006e+08]]) # For some reason on 32-bit x86 Ubuntu 12.10 the [1, 0] entry in this # matrix differs by 24 nulps. Discussion: - # http://mail.scipy.org/pipermail/numpy-discussion/2012-September/063801.html + # 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: @@ -1014,6 +1045,10 @@ def test_poisson_exceptions(self): 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) @@ -1168,8 +1203,8 @@ def __float__(self): raise TypeError throwing_float = np.array(1.0).view(ThrowingFloat) - assert_raises(TypeError, random.uniform, - throwing_float, throwing_float) + assert_raises(TypeError, random.uniform, throwing_float, + throwing_float) class ThrowingInteger(np.ndarray): def __int__(self): @@ -1189,9 +1224,14 @@ def test_vonmises(self): 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) + 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)) @@ -1372,8 +1412,9 @@ def test_noncentral_f(self): self.set_seed() actual = nonc_f(dfnum * 3, dfden, nonc) - mt_nonc_f = random.noncentral_f 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) @@ -1391,9 +1432,12 @@ def test_noncentral_f(self): 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) - assert_raises(ValueError, mt_nonc_f, bad_dfnum, dfden, nonc * 3) - assert_raises(ValueError, mt_nonc_f, dfnum, bad_dfden, nonc * 3) - assert_raises(ValueError, mt_nonc_f, dfnum, dfden, bad_nonc * 3) + + def test_noncentral_f_small_df(self): + self.set_seed() + desired = np.array([21.57878070681719, 1.17110217503908]) + 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] @@ -1420,20 +1464,15 @@ def test_noncentral_chisquare(self): self.set_seed() actual = nonc_chi(df * 3, nonc) - mt_nonc_chi2 = random.noncentral_chisquare 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) - assert_raises(ValueError, mt_nonc_chi2, bad_df * 3, nonc) - assert_raises(ValueError, mt_nonc_chi2, 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) - assert_raises(ValueError, mt_nonc_chi2, bad_df, nonc * 3) - assert_raises(ValueError, mt_nonc_chi2, df, bad_nonc * 3) def test_standard_t(self): df = [1] @@ -1645,24 +1684,24 @@ def test_triangular(self): 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.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) + 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, bad_left_two, bad_mode_two, + right * 3) assert_raises(ValueError, triangular, 10., 0., 20.) assert_raises(ValueError, triangular, 10., 25., 20.) @@ -1739,6 +1778,9 @@ def test_zipf(self): 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] @@ -1809,7 +1851,6 @@ def test_logseries(self): class TestThread(object): # make sure each state produces the same sequence even in threads - def setup(self): self.seeds = range(4) diff --git a/numpy/random/randomgen/tests/test_randomstate.py b/numpy/random/randomgen/tests/test_randomstate.py index 167d1b0aa545..6adde6c2ab33 100644 --- a/numpy/random/randomgen/tests/test_randomstate.py +++ b/numpy/random/randomgen/tests/test_randomstate.py @@ -109,7 +109,9 @@ def test_size(self): assert_raises(TypeError, random.multinomial, 1, p, float(1)) - assert_raises(ValueError, random.multinomial, 1, [1.1, .1]) + + def test_invalid_prob(self): + assert_raises(ValueError, random.multinomial, 100, [1.1, 0.2]) class TestSetState(object): @@ -352,6 +354,12 @@ def test_rand(self): [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) @@ -360,6 +368,10 @@ def test_randn(self): [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)) @@ -443,11 +455,9 @@ def test_random_sample(self): [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 = np.array(0.61879477158567997) - assert_array_almost_equal(actual, desired, decimal=15) + actual = random.random_sample() + assert_array_almost_equal(actual, desired[0, 0], decimal=15) def test_choice_uniform_replace(self): random.seed(self.seed) @@ -582,18 +592,6 @@ def test_shuffle(self): desired = conv([0, 1, 9, 6, 2, 4, 5, 8, 7, 3]) assert_array_equal(actual, desired) - 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_shuffle_masked(self): # gh-3263 a = np.ma.masked_values(np.reshape(range(20), (5, 4)) % 3 - 1, -1) @@ -608,6 +606,18 @@ def test_shuffle_masked(self): 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)) @@ -649,6 +659,8 @@ def test_dirichlet(self): [[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]) @@ -712,6 +724,16 @@ def test_geometric(self): [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)) @@ -790,9 +812,15 @@ def test_logseries(self): [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)) + 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], @@ -843,8 +871,8 @@ def test_multivariate_normal(self): 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, mean, cov, + check_valid='other') assert_raises(ValueError, random.multivariate_normal, np.zeros((2, 1, 1)), cov) assert_raises(ValueError, random.multivariate_normal, @@ -860,6 +888,13 @@ def test_negative_binomial(self): [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)) @@ -890,6 +925,11 @@ def test_noncentral_f(self): [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)) @@ -929,9 +969,13 @@ 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, [lamneg] * 10) assert_raises(ValueError, random.poisson, lambig) - assert_raises(ValueError, random.poisson, [lambig]*10) + 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) @@ -1026,8 +1070,8 @@ def test_uniform_range_bounds(self): 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, 0, np.inf) + assert_raises(OverflowError, func, fmin, fmax) assert_raises(OverflowError, func, [-np.inf], [0]) assert_raises(OverflowError, func, [0], [np.inf]) @@ -1070,7 +1114,12 @@ 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) - np.testing.assert_(np.isfinite(r).all()) + 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) @@ -1108,12 +1157,9 @@ class TestBroadcast(object): def setup(self): self.seed = 123456789 - def setSeed(self): + def set_seed(self): random.seed(self.seed) - # TODO: Include test for randint once it can broadcast - # Can steal the test written in PR #6938 - def test_uniform(self): low = [0] high = [1] @@ -1122,11 +1168,11 @@ def test_uniform(self): 0.53413660089041659, 0.50955303552646702]) - self.setSeed() + self.set_seed() actual = uniform(low * 3, high) assert_array_almost_equal(actual, desired, decimal=14) - self.setSeed() + self.set_seed() actual = uniform(low, high * 3) assert_array_almost_equal(actual, desired, decimal=14) @@ -1139,12 +1185,12 @@ def test_normal(self): 2.1283977976520019, 1.8417114045748335]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = normal(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, normal, loc, bad_scale * 3) @@ -1159,13 +1205,13 @@ def test_beta(self): 0.075230336409423643, 0.24976865978980844]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = beta(a, b * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, beta, bad_a, b * 3) @@ -1179,7 +1225,7 @@ def test_exponential(self): 0.76386282278691653, 0.71243813125891797]) - self.setSeed() + self.set_seed() actual = exponential(scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, exponential, bad_scale * 3) @@ -1192,7 +1238,7 @@ def test_standard_gamma(self): 0.76386282278691653, 0.71243813125891797]) - self.setSeed() + self.set_seed() actual = std_gamma(shape * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, std_gamma, bad_shape * 3) @@ -1207,13 +1253,13 @@ def test_gamma(self): 1.5277256455738331, 1.4248762625178359]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = gamma(shape, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, gamma, bad_shape, scale * 3) @@ -1229,13 +1275,13 @@ def test_f(self): 0.86768719635363512, 2.7251095168386801]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = f(dfnum, dfden * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, f, bad_dfnum, dfden * 3) @@ -1253,21 +1299,23 @@ def test_noncentral_f(self): 13.025456344595602, 8.8018098359100545]) - self.setSeed() + 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.setSeed() + 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.setSeed() + 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) @@ -1275,7 +1323,7 @@ def test_noncentral_f(self): assert_raises(ValueError, nonc_f, dfnum, dfden, bad_nonc * 3) def test_noncentral_f_small_df(self): - self.setSeed() + 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) @@ -1288,7 +1336,7 @@ def test_chisquare(self): 0.51947702108840776, 0.1320969254923558]) - self.setSeed() + self.set_seed() actual = chisquare(df * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, chisquare, bad_df * 3) @@ -1303,13 +1351,13 @@ def test_noncentral_chisquare(self): 4.5804135049718742, 6.0872302432834564]) - self.setSeed() + 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.setSeed() + 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) @@ -1323,10 +1371,11 @@ def test_standard_t(self): 5.8560725167361607, 1.0274791436474273]) - self.setSeed() + 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] @@ -1337,12 +1386,12 @@ def test_vonmises(self): -2.7064099483995943, -1.8672476700665914]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = vonmises(mu, kappa * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, vonmises, mu, bad_kappa * 3) @@ -1355,10 +1404,11 @@ def test_pareto(self): 1.1465519762044529, 1.0389564467453547]) - self.setSeed() + 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] @@ -1368,10 +1418,11 @@ def test_weibull(self): 0.76386282278691653, 0.71243813125891797]) - self.setSeed() + 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] @@ -1381,10 +1432,11 @@ def test_power(self): 0.53413660089041659, 0.50955303552646702]) - self.setSeed() + 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] @@ -1395,12 +1447,12 @@ def test_laplace(self): 0.070715642226971326, 0.019290950698972624]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = laplace(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, laplace, loc, bad_scale * 3) @@ -1414,12 +1466,12 @@ def test_gumbel(self): 0.26936705726291116, 0.33906220393037939]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = gumbel(loc, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, gumbel, loc, bad_scale * 3) @@ -1433,15 +1485,16 @@ def test_logistic(self): 0.13675915696285773, 0.038216792802833396]) - self.setSeed() + 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.setSeed() + 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] @@ -1452,15 +1505,17 @@ def test_lognormal(self): 8.4013952870126261, 6.3073234116578671]) - self.setSeed() + 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.setSeed() + 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] @@ -1470,7 +1525,7 @@ def test_rayleigh(self): 1.2360119924878694, 1.1936818095781789]) - self.setSeed() + self.set_seed() actual = rayleigh(scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, rayleigh, bad_scale * 3) @@ -1485,13 +1540,15 @@ def test_wald(self): 0.12450084820795027, 0.9096122728408238]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = wald(mean, scale * 3) assert_array_almost_equal(actual, desired, decimal=14) assert_raises(ValueError, wald, bad_mean, scale * 3) @@ -1511,7 +1568,7 @@ def test_triangular(self): 2.0347400359389356, 2.0095991069536208]) - self.setSeed() + 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) @@ -1519,7 +1576,7 @@ def test_triangular(self): assert_raises(ValueError, triangular, bad_left_two * 3, bad_mode_two, right) - self.setSeed() + 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) @@ -1527,7 +1584,7 @@ def test_triangular(self): assert_raises(ValueError, triangular, bad_left_two, bad_mode_two * 3, right) - self.setSeed() + 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) @@ -1548,14 +1605,14 @@ def test_binomial(self): binom = random.binomial desired = np.array([1, 1, 1]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = binom(n, p * 3) assert_array_equal(actual, desired) assert_raises(ValueError, binom, bad_n, p * 3) @@ -1571,14 +1628,14 @@ def test_negative_binomial(self): neg_binom = random.negative_binomial desired = np.array([1, 0, 1]) - self.setSeed() + 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.setSeed() + self.set_seed() actual = neg_binom(n, p * 3) assert_array_equal(actual, desired) assert_raises(ValueError, neg_binom, bad_n, p * 3) @@ -1594,7 +1651,7 @@ def test_poisson(self): poisson = random.poisson desired = np.array([1, 1, 0]) - self.setSeed() + self.set_seed() actual = poisson(lam * 3) assert_array_equal(actual, desired) assert_raises(ValueError, poisson, bad_lam_one * 3) @@ -1606,7 +1663,7 @@ def test_zipf(self): zipf = random.zipf desired = np.array([2, 2, 1]) - self.setSeed() + self.set_seed() actual = zipf(a * 3) assert_array_equal(actual, desired) assert_raises(ValueError, zipf, bad_a * 3) @@ -1621,7 +1678,7 @@ def test_geometric(self): geom = random.geometric desired = np.array([2, 2, 2]) - self.setSeed() + self.set_seed() actual = geom(p * 3) assert_array_equal(actual, desired) assert_raises(ValueError, geom, bad_p_one * 3) @@ -1638,7 +1695,7 @@ def test_hypergeometric(self): hypergeom = random.hypergeometric desired = np.array([1, 1, 1]) - self.setSeed() + self.set_seed() actual = hypergeom(ngood * 3, nbad, nsample) assert_array_equal(actual, desired) assert_raises(ValueError, hypergeom, bad_ngood * 3, nbad, nsample) @@ -1646,7 +1703,7 @@ def test_hypergeometric(self): assert_raises(ValueError, hypergeom, ngood * 3, nbad, bad_nsample_one) assert_raises(ValueError, hypergeom, ngood * 3, nbad, bad_nsample_two) - self.setSeed() + self.set_seed() actual = hypergeom(ngood, nbad * 3, nsample) assert_array_equal(actual, desired) assert_raises(ValueError, hypergeom, bad_ngood, nbad * 3, nsample) @@ -1654,7 +1711,7 @@ def test_hypergeometric(self): assert_raises(ValueError, hypergeom, ngood, nbad * 3, bad_nsample_one) assert_raises(ValueError, hypergeom, ngood, nbad * 3, bad_nsample_two) - self.setSeed() + self.set_seed() actual = hypergeom(ngood, nbad, nsample * 3) assert_array_equal(actual, desired) assert_raises(ValueError, hypergeom, bad_ngood, nbad, nsample * 3) @@ -1662,6 +1719,9 @@ def test_hypergeometric(self): 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): @@ -1671,7 +1731,7 @@ def test_logseries(self): logseries = random.logseries desired = np.array([1, 1, 1]) - self.setSeed() + self.set_seed() actual = logseries(p * 3) assert_array_equal(actual, desired) assert_raises(ValueError, logseries, bad_p_one * 3) @@ -1708,16 +1768,19 @@ def check_function(self, function, sz): 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) + out[...] = state.multinomial(10, [1 / 6.] * 6, size=10000) + self.check_function(gen_random, sz=(10000, 6)) @@ -1775,24 +1838,6 @@ def test_two_arg_funcs(self): out = func(self.argOne, argTwo[0]) assert_equal(out.shape, self.tgtShape) -# TODO: Uncomment once randint can broadcast arguments -# def test_randint(self): -# itype = [bool, np.int8, np.uint8, np.int16, np.uint16, -# np.int32, np.uint32, np.int64, np.uint64] -# func = random.randint -# high = np.array([1]) -# low = np.array([0]) -# -# for dt in itype: -# out = func(low, high, dtype=dt) -# self.assert_equal(out.shape, self.tgtShape) -# -# out = func(low[0], high, dtype=dt) -# self.assert_equal(out.shape, self.tgtShape) -# -# out = func(low, high[0], dtype=dt) -# self.assert_equal(out.shape, self.tgtShape) - def test_three_arg_funcs(self): funcs = [random.noncentral_f, random.triangular, random.hypergeometric] From c53b2eb729bae1f248a2654dfcfa4a3dd3e2902b Mon Sep 17 00:00:00 2001 From: mattip Date: Wed, 10 Apr 2019 00:50:42 +0300 Subject: [PATCH 105/138] BENCH: convert bencmarks to asv format remove files that were part of the origal repo rework randomgen docs to integrate with numpy and fix some links remove convenience functions, require explicit call to gen.brng move code out of numpy.random.randomgen into numpy.random --- .circleci/config.yml | 2 +- .gitignore | 10 +- MANIFEST.in | 3 +- _randomgen/.gitattributes | 1 - _randomgen/.gitignore | 26 - _randomgen/.travis.yml | 72 --- _randomgen/README-git.md | 26 - _randomgen/README.md | 288 ---------- _randomgen/README.rst | 320 ----------- _randomgen/benchmark.py | 201 ------- _randomgen/setup.py | 325 ----------- benchmarks/benchmarks/bench_random.py | 99 ++++ doc/source/reference/randomgen/extending.rst | 2 + doc/source/reference/randomgen/generator.rst | 29 +- doc/source/reference/randomgen/index.rst | 120 ++-- .../reference/randomgen/new-or-different.rst | 4 +- numpy/random/{randomgen => }/LICENSE.md | 0 numpy/random/__init__.py | 36 +- numpy/random/{mtrand => _mtrand}/Python.pxi | 0 .../{mtrand => _mtrand}/distributions.c | 0 .../{mtrand => _mtrand}/distributions.h | 0 numpy/random/_mtrand/generate_mtrand_c.py | 42 ++ numpy/random/{mtrand => _mtrand}/initarray.c | 0 numpy/random/{mtrand => _mtrand}/initarray.h | 0 numpy/random/{mtrand => _mtrand}/mtrand.pyx | 0 .../{mtrand => _mtrand}/mtrand_py_helper.h | 0 numpy/random/{mtrand => _mtrand}/numpy.pxd | 0 .../randint_helpers.pxi.in | 0 numpy/random/{mtrand => _mtrand}/randomkit.c | 0 numpy/random/{mtrand => _mtrand}/randomkit.h | 0 numpy/random/{randomgen => }/_pickle.py | 0 .../{randomgen => }/bounded_integers.pxd.in | 0 .../{randomgen => }/bounded_integers.pyx.in | 0 numpy/random/{randomgen => }/common.pxd | 0 numpy/random/{randomgen => }/common.pyx | 0 .../random/{randomgen => }/distributions.pxd | 0 numpy/random/{randomgen => }/dsfmt.pyx | 0 numpy/random/{randomgen => }/entropy.pyx | 0 .../examples/cython/extending.pyx | 0 .../cython/extending_distributions.pyx | 0 .../{randomgen => }/examples/cython/setup.py | 0 .../examples/numba/extending.py | 0 .../examples/numba/extending_distributions.py | 0 numpy/random/{randomgen => }/generator.pyx | 74 +-- .../random/{randomgen => }/legacy/__init__.py | 0 .../legacy/legacy_distributions.pxd | 0 numpy/random/{randomgen => }/mt19937.pyx | 0 numpy/random/{randomgen => }/mtrand.pyx | 0 numpy/random/{randomgen => }/pcg32.pyx | 0 numpy/random/{randomgen => }/pcg64.pyx | 0 numpy/random/{randomgen => }/philox.pyx | 0 numpy/random/randomgen/__init__.py | 21 - numpy/random/randomgen/_version.py | 520 ------------------ numpy/random/randomgen/setup.py | 191 ------- numpy/random/randomgen/tests/data/__init__.py | 0 numpy/random/setup.py | 153 +++++- .../src/aligned_malloc/aligned_malloc.c | 0 .../src/aligned_malloc/aligned_malloc.h | 0 .../{randomgen => }/src/common/LICENSE.md | 0 .../{randomgen => }/src/common/inttypes.h | 0 .../{randomgen => }/src/common/stdint.h | 0 .../src/distributions/LICENSE.md | 0 .../src/distributions/binomial.h | 0 .../src/distributions/distributions.c | 0 .../src/distributions/distributions.h | 0 .../src/distributions/ziggurat.h | 0 .../src/distributions/ziggurat_constants.h | 0 .../src/dsfmt/128-bit-jump.poly.txt | 0 .../src/dsfmt/96-bit-jump.poly.txt | 0 .../{randomgen => }/src/dsfmt/LICENSE.md | 0 .../{randomgen => }/src/dsfmt/calc-jump.cpp | 0 .../src/dsfmt/dSFMT-benchmark.c | 0 .../src/dsfmt/dSFMT-calc-jump.hpp | 0 .../{randomgen => }/src/dsfmt/dSFMT-common.h | 0 .../{randomgen => }/src/dsfmt/dSFMT-jump.c | 0 .../{randomgen => }/src/dsfmt/dSFMT-jump.h | 0 .../{randomgen => }/src/dsfmt/dSFMT-params.h | 0 .../src/dsfmt/dSFMT-params19937.h | 0 .../{randomgen => }/src/dsfmt/dSFMT-poly.h | 0 .../src/dsfmt/dSFMT-test-gen.c | 0 .../random/{randomgen => }/src/dsfmt/dSFMT.c | 0 .../random/{randomgen => }/src/dsfmt/dSFMT.h | 0 .../{randomgen => }/src/entropy/LICENSE.md | 0 .../{randomgen => }/src/entropy/entropy.c | 0 .../{randomgen => }/src/entropy/entropy.h | 0 .../{randomgen => }/src/legacy/LICENSE.md | 0 .../src/legacy/distributions-boxmuller.c | 0 .../src/legacy/distributions-boxmuller.h | 0 .../{randomgen => }/src/mt19937/LICENSE.md | 0 .../src/mt19937/mt19937-benchmark.c | 0 .../src/mt19937/mt19937-jump.c | 0 .../src/mt19937/mt19937-jump.h | 0 .../src/mt19937/mt19937-poly.h | 0 .../src/mt19937/mt19937-test-data-gen.c | 0 .../{randomgen => }/src/mt19937/mt19937.c | 0 .../{randomgen => }/src/mt19937/mt19937.h | 0 .../{randomgen => }/src/mt19937/randomkit.c | 0 .../{randomgen => }/src/mt19937/randomkit.h | 0 .../{randomgen => }/src/pcg32/LICENSE.md | 0 .../src/pcg32/pcg-advance-64.c | 0 .../src/pcg32/pcg32-test-data-gen.c | 0 .../random/{randomgen => }/src/pcg32/pcg32.c | 0 .../random/{randomgen => }/src/pcg32/pcg32.h | 0 .../{randomgen => }/src/pcg32/pcg_variants.h | 0 .../{randomgen => }/src/pcg64/LICENSE.md | 0 .../src/pcg64/pcg64-benchmark.c | 0 .../src/pcg64/pcg64-test-data-gen.c | 0 .../random/{randomgen => }/src/pcg64/pcg64.c | 0 .../random/{randomgen => }/src/pcg64/pcg64.h | 0 .../{randomgen => }/src/pcg64/pcg64.orig.c | 0 .../{randomgen => }/src/pcg64/pcg64.orig.h | 0 .../{randomgen => }/src/philox/LICENSE.md | 0 .../src/philox/philox-benchmark.c | 0 .../src/philox/philox-test-data-gen.c | 0 .../{randomgen => }/src/philox/philox.c | 0 .../{randomgen => }/src/philox/philox.h | 0 .../{randomgen => }/src/splitmix64/LICENSE.md | 0 .../src/splitmix64/splitmix64.c | 0 .../src/splitmix64/splitmix64.h | 0 .../src/splitmix64/splitmix64.orig.c | 0 .../{randomgen => }/src/threefry/LICENSE.md | 0 .../src/threefry/threefry-benchmark.c | 0 .../src/threefry/threefry-orig.c | 0 .../src/threefry/threefry-test-data-gen.c | 0 .../{randomgen => }/src/threefry/threefry.c | 0 .../{randomgen => }/src/threefry/threefry.h | 0 .../{randomgen => }/src/threefry32/LICENSE.md | 0 .../src/threefry32/threefry32-test-data-gen.c | 0 .../src/threefry32/threefry32.c | 0 .../src/threefry32/threefry32.h | 0 .../src/xoroshiro128/LICENSE.md | 0 .../src/xoroshiro128/xoroshiro128-benchmark.c | 0 .../xoroshiro128/xoroshiro128-test-data-gen.c | 0 .../src/xoroshiro128/xoroshiro128.c | 0 .../src/xoroshiro128/xoroshiro128.h | 0 .../src/xoroshiro128/xoroshiro128plus.orig.c | 0 .../src/xoroshiro128/xoroshiro128plus.orig.h | 0 .../src/xorshift1024/LICENSE.md | 0 .../src/xorshift1024/xorshift1024-benchmark.c | 0 .../xorshift1024/xorshift1024-test-data-gen.c | 0 .../src/xorshift1024/xorshift1024.c | 0 .../src/xorshift1024/xorshift1024.h | 0 .../src/xorshift1024/xorshift1024.orig.c | 0 .../src/xorshift1024/xorshift1024.orig.h | 0 .../src/xoshiro256starstar/LICENSE.md | 0 .../xoshiro256starstar-test-data-gen.c | 0 .../xoshiro256starstar/xoshiro256starstar.c | 0 .../xoshiro256starstar/xoshiro256starstar.h | 0 .../xoshiro256starstar.orig.c | 0 .../xoshiro256starstar.orig.h | 0 .../src/xoshiro512starstar/LICENSE.md | 0 .../xoshiro512starstar-test-data-gen.c | 0 .../xoshiro512starstar/xoshiro512starstar.c | 0 .../xoshiro512starstar/xoshiro512starstar.h | 0 .../xoshiro512starstar.orig.c | 0 .../xoshiro512starstar.orig.h | 0 .../tests => tests/data}/__init__.py | 0 .../tests/data/dSFMT-testset-1.csv | 0 .../tests/data/dSFMT-testset-2.csv | 0 .../tests/data/mt19937-testset-1.csv | 0 .../tests/data/mt19937-testset-2.csv | 0 .../tests/data/pcg32-testset-1.csv | 0 .../tests/data/pcg32-testset-2.csv | 0 .../tests/data/pcg64-testset-1.csv | 0 .../tests/data/pcg64-testset-2.csv | 0 .../tests/data/philox-testset-1.csv | 0 .../tests/data/philox-testset-2.csv | 0 .../tests/data/threefry-testset-1.csv | 0 .../tests/data/threefry-testset-2.csv | 0 .../tests/data/threefry32-testset-1.csv | 0 .../tests/data/threefry32-testset-2.csv | 0 .../tests/data/xoroshiro128-testset-1.csv | 0 .../tests/data/xoroshiro128-testset-2.csv | 0 .../tests/data/xorshift1024-testset-1.csv | 0 .../tests/data/xorshift1024-testset-2.csv | 0 .../data/xoshiro256starstar-testset-1.csv | 0 .../data/xoshiro256starstar-testset-2.csv | 0 .../data/xoshiro512starstar-testset-1.csv | 0 .../data/xoshiro512starstar-testset-2.csv | 0 .../tests/test_against_numpy.py | 38 +- .../{randomgen => }/tests/test_direct.py | 108 ++-- .../tests/test_generator_mt19937.py | 169 +++--- .../test_generator_mt19937_regressions.py | 26 +- .../{randomgen => }/tests/test_randomstate.py | 2 +- .../tests/test_randomstate_regression.py | 2 +- .../{randomgen => }/tests/test_smoke.py | 228 ++++---- numpy/random/{randomgen => }/threefry.pyx | 0 numpy/random/{randomgen => }/threefry32.pyx | 0 numpy/random/{randomgen => }/xoroshiro128.pyx | 0 numpy/random/{randomgen => }/xorshift1024.pyx | 0 .../{randomgen => }/xoshiro256starstar.pyx | 0 .../{randomgen => }/xoshiro512starstar.pyx | 0 setup.py | 4 +- 193 files changed, 693 insertions(+), 2449 deletions(-) delete mode 100644 _randomgen/.gitattributes delete mode 100644 _randomgen/.gitignore delete mode 100644 _randomgen/.travis.yml delete mode 100644 _randomgen/README-git.md delete mode 100644 _randomgen/README.md delete mode 100644 _randomgen/README.rst delete mode 100644 _randomgen/benchmark.py delete mode 100644 _randomgen/setup.py rename numpy/random/{randomgen => }/LICENSE.md (100%) rename numpy/random/{mtrand => _mtrand}/Python.pxi (100%) rename numpy/random/{mtrand => _mtrand}/distributions.c (100%) rename numpy/random/{mtrand => _mtrand}/distributions.h (100%) create mode 100644 numpy/random/_mtrand/generate_mtrand_c.py rename numpy/random/{mtrand => _mtrand}/initarray.c (100%) rename numpy/random/{mtrand => _mtrand}/initarray.h (100%) rename numpy/random/{mtrand => _mtrand}/mtrand.pyx (100%) rename numpy/random/{mtrand => _mtrand}/mtrand_py_helper.h (100%) rename numpy/random/{mtrand => _mtrand}/numpy.pxd (100%) rename numpy/random/{mtrand => _mtrand}/randint_helpers.pxi.in (100%) rename numpy/random/{mtrand => _mtrand}/randomkit.c (100%) rename numpy/random/{mtrand => _mtrand}/randomkit.h (100%) rename numpy/random/{randomgen => }/_pickle.py (100%) rename numpy/random/{randomgen => }/bounded_integers.pxd.in (100%) rename numpy/random/{randomgen => }/bounded_integers.pyx.in (100%) rename numpy/random/{randomgen => }/common.pxd (100%) rename numpy/random/{randomgen => }/common.pyx (100%) rename numpy/random/{randomgen => }/distributions.pxd (100%) rename numpy/random/{randomgen => }/dsfmt.pyx (100%) rename numpy/random/{randomgen => }/entropy.pyx (100%) rename numpy/random/{randomgen => }/examples/cython/extending.pyx (100%) rename numpy/random/{randomgen => }/examples/cython/extending_distributions.pyx (100%) rename numpy/random/{randomgen => }/examples/cython/setup.py (100%) rename numpy/random/{randomgen => }/examples/numba/extending.py (100%) rename numpy/random/{randomgen => }/examples/numba/extending_distributions.py (100%) rename numpy/random/{randomgen => }/generator.pyx (98%) rename numpy/random/{randomgen => }/legacy/__init__.py (100%) rename numpy/random/{randomgen => }/legacy/legacy_distributions.pxd (100%) rename numpy/random/{randomgen => }/mt19937.pyx (100%) rename numpy/random/{randomgen => }/mtrand.pyx (100%) rename numpy/random/{randomgen => }/pcg32.pyx (100%) rename numpy/random/{randomgen => }/pcg64.pyx (100%) rename numpy/random/{randomgen => }/philox.pyx (100%) delete mode 100644 numpy/random/randomgen/__init__.py delete mode 100644 numpy/random/randomgen/_version.py delete mode 100644 numpy/random/randomgen/setup.py delete mode 100644 numpy/random/randomgen/tests/data/__init__.py rename numpy/random/{randomgen => }/src/aligned_malloc/aligned_malloc.c (100%) rename numpy/random/{randomgen => }/src/aligned_malloc/aligned_malloc.h (100%) rename numpy/random/{randomgen => }/src/common/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/common/inttypes.h (100%) rename numpy/random/{randomgen => }/src/common/stdint.h (100%) rename numpy/random/{randomgen => }/src/distributions/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/distributions/binomial.h (100%) rename numpy/random/{randomgen => }/src/distributions/distributions.c (100%) rename numpy/random/{randomgen => }/src/distributions/distributions.h (100%) rename numpy/random/{randomgen => }/src/distributions/ziggurat.h (100%) rename numpy/random/{randomgen => }/src/distributions/ziggurat_constants.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/128-bit-jump.poly.txt (100%) rename numpy/random/{randomgen => }/src/dsfmt/96-bit-jump.poly.txt (100%) rename numpy/random/{randomgen => }/src/dsfmt/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/dsfmt/calc-jump.cpp (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-benchmark.c (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-calc-jump.hpp (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-common.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-jump.c (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-jump.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-params.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-params19937.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-poly.h (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT-test-gen.c (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT.c (100%) rename numpy/random/{randomgen => }/src/dsfmt/dSFMT.h (100%) rename numpy/random/{randomgen => }/src/entropy/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/entropy/entropy.c (100%) rename numpy/random/{randomgen => }/src/entropy/entropy.h (100%) rename numpy/random/{randomgen => }/src/legacy/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/legacy/distributions-boxmuller.c (100%) rename numpy/random/{randomgen => }/src/legacy/distributions-boxmuller.h (100%) rename numpy/random/{randomgen => }/src/mt19937/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937-benchmark.c (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937-jump.c (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937-jump.h (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937-poly.h (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937.c (100%) rename numpy/random/{randomgen => }/src/mt19937/mt19937.h (100%) rename numpy/random/{randomgen => }/src/mt19937/randomkit.c (100%) rename numpy/random/{randomgen => }/src/mt19937/randomkit.h (100%) rename numpy/random/{randomgen => }/src/pcg32/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/pcg32/pcg-advance-64.c (100%) rename numpy/random/{randomgen => }/src/pcg32/pcg32-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/pcg32/pcg32.c (100%) rename numpy/random/{randomgen => }/src/pcg32/pcg32.h (100%) rename numpy/random/{randomgen => }/src/pcg32/pcg_variants.h (100%) rename numpy/random/{randomgen => }/src/pcg64/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64-benchmark.c (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64.c (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64.h (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64.orig.c (100%) rename numpy/random/{randomgen => }/src/pcg64/pcg64.orig.h (100%) rename numpy/random/{randomgen => }/src/philox/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/philox/philox-benchmark.c (100%) rename numpy/random/{randomgen => }/src/philox/philox-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/philox/philox.c (100%) rename numpy/random/{randomgen => }/src/philox/philox.h (100%) rename numpy/random/{randomgen => }/src/splitmix64/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/splitmix64/splitmix64.c (100%) rename numpy/random/{randomgen => }/src/splitmix64/splitmix64.h (100%) rename numpy/random/{randomgen => }/src/splitmix64/splitmix64.orig.c (100%) rename numpy/random/{randomgen => }/src/threefry/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/threefry/threefry-benchmark.c (100%) rename numpy/random/{randomgen => }/src/threefry/threefry-orig.c (100%) rename numpy/random/{randomgen => }/src/threefry/threefry-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/threefry/threefry.c (100%) rename numpy/random/{randomgen => }/src/threefry/threefry.h (100%) rename numpy/random/{randomgen => }/src/threefry32/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/threefry32/threefry32-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/threefry32/threefry32.c (100%) rename numpy/random/{randomgen => }/src/threefry32/threefry32.h (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128-benchmark.c (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128.c (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128.h (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128plus.orig.c (100%) rename numpy/random/{randomgen => }/src/xoroshiro128/xoroshiro128plus.orig.h (100%) rename numpy/random/{randomgen => }/src/xorshift1024/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024-benchmark.c (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024.c (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024.h (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024.orig.c (100%) rename numpy/random/{randomgen => }/src/xorshift1024/xorshift1024.orig.h (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/xoshiro256starstar.c (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/xoshiro256starstar.h (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/xoshiro256starstar.orig.c (100%) rename numpy/random/{randomgen => }/src/xoshiro256starstar/xoshiro256starstar.orig.h (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/LICENSE.md (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/xoshiro512starstar.c (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/xoshiro512starstar.h (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/xoshiro512starstar.orig.c (100%) rename numpy/random/{randomgen => }/src/xoshiro512starstar/xoshiro512starstar.orig.h (100%) rename numpy/random/{randomgen/tests => tests/data}/__init__.py (100%) rename numpy/random/{randomgen => }/tests/data/dSFMT-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/dSFMT-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/mt19937-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/mt19937-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/pcg32-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/pcg32-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/pcg64-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/pcg64-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/philox-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/philox-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/threefry-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/threefry-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/threefry32-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/threefry32-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoroshiro128-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoroshiro128-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/xorshift1024-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/xorshift1024-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoshiro256starstar-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoshiro256starstar-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoshiro512starstar-testset-1.csv (100%) rename numpy/random/{randomgen => }/tests/data/xoshiro512starstar-testset-2.csv (100%) rename numpy/random/{randomgen => }/tests/test_against_numpy.py (93%) rename numpy/random/{randomgen => }/tests/test_direct.py (85%) rename numpy/random/{randomgen => }/tests/test_generator_mt19937.py (96%) rename numpy/random/{randomgen => }/tests/test_generator_mt19937_regressions.py (92%) rename numpy/random/{randomgen => }/tests/test_randomstate.py (99%) rename numpy/random/{randomgen => }/tests/test_randomstate_regression.py (99%) rename numpy/random/{randomgen => }/tests/test_smoke.py (86%) rename numpy/random/{randomgen => }/threefry.pyx (100%) rename numpy/random/{randomgen => }/threefry32.pyx (100%) rename numpy/random/{randomgen => }/xoroshiro128.pyx (100%) rename numpy/random/{randomgen => }/xorshift1024.pyx (100%) rename numpy/random/{randomgen => }/xoshiro256starstar.pyx (100%) rename numpy/random/{randomgen => }/xoshiro512starstar.pyx (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index e7fbf55fe6a9..ff26afeb8a89 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,7 @@ jobs: command: | python3 -m venv venv . venv/bin/activate - pip install cython sphinx>=1.8.5 matplotlib ipython + pip install cython sphinx==1.8.5 matplotlib ipython sudo apt-get update sudo apt-get install -y graphviz texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra texlive-generic-extra latexmk texlive-xetex diff --git a/.gitignore b/.gitignore index ac5693fad82e..485f379578cd 100644 --- a/.gitignore +++ b/.gitignore @@ -176,8 +176,8 @@ benchmarks/numpy # cythonized files cythonize.dat numpy/random/mtrand/mtrand.c -numpy/random/randomgen/*.c -numpy/random/randomgen/legacy/*.c -numpy/random/mtrand/randint_helpers.pxi -numpy/random/randomgen/bounded_integers.pyx -numpy/random/randomgen/bounded_integers.pxd +numpy/random/*.c +numpy/random/legacy/*.c +numpy/random/_mtrand/randint_helpers.pxi +numpy/random/bounded_integers.pyx +numpy/random/bounded_integers.pxd diff --git a/MANIFEST.in b/MANIFEST.in index 16d066519a9b..e27b843a9e97 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,7 +9,8 @@ include pytest.ini include *.txt include README.md include site.cfg.example -recursive-include numpy/random/mtrand *.pyx *.pxd +include numpy/random/_mtrand/generate_mtrand_c.py +recursive-include numpy/random *.pyx *.pxd *.pyx.in *.pxd.in # Add build support that should go in sdist, but not go in bdist/be installed # Note that sub-directories that don't have __init__ are apparently not # included by 'recursive-include', so list those separately diff --git a/_randomgen/.gitattributes b/_randomgen/.gitattributes deleted file mode 100644 index 9b447556a4c4..000000000000 --- a/_randomgen/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -randomgen/_version.py export-subst diff --git a/_randomgen/.gitignore b/_randomgen/.gitignore deleted file mode 100644 index 381421b399e9..000000000000 --- a/_randomgen/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -.idea/ -build/ -*.egg-info/ -*.pyd -*.pyc -*.html -*.obj -*.exe -**/Random123 -settings.json -*.so -randomgen/bounded_integers.pyx -randomgen/bounded_integers.pxd -randomgen/bounded_integers.c -randomgen/common.c -randomgen/dsfmt.c -randomgen/entropy.c -randomgen/generator.c -randomgen/mt19937.c -randomgen/pcg32.c -randomgen/pcg64.c -randomgen/philox.c -randomgen/threefry.c -randomgen/threefry32.c -randomgen/xoroshiro128.c -randomgen/xorshift1024.c diff --git a/_randomgen/.travis.yml b/_randomgen/.travis.yml deleted file mode 100644 index 89c5be3fad84..000000000000 --- a/_randomgen/.travis.yml +++ /dev/null @@ -1,72 +0,0 @@ -group: edge -dist: trusty -sudo: required -language: python - -env: - global: - # Doctr deploy key for bashtage/randomgen - - secure: "czwFlflS1lcfbSQ9ktv+pLAPV9/6+wmwiMTyIYyv5xgQVWRL5NRebWH+ZhQ6s2T5x17wFMtlafcAvkdV0CHQZLru34V2UNldCapuEtQ8b32EDHBXHKbs45b7SSkLx4TFXdjiJurleY4ZIKle0gX6BW21zYBwaHJqbN6I8nRv9Rp47XEU1UV1Mdf/PhfTnxY31rFrPYL77xeWJzoFfT8zao39V4gQds+1Ag7FjdNVdSDVKwDduF4kS7tIbKqb4M+jsbc3PIKyP9nyQpEQF5ebJuG7mqXJhVJGEL83rBx8MLFPA/1X3cUzKacgKyp2+Wmlt0EVhwCa1aRf9cSK6I7TbMC7/eGtDnC2ToiRlFJurVRblaEmhzVQS1yQ4Dkooqsj9hNVl6nhu7JfR52GLogns33Ec/yYuRcWcULKSlR5Cerfef/5YijBEhlr9X76SJiOpjvS4lwWFYX+h8xzuVhRLGwIVB9oQNllxYItzcDSGmRx+EOMXWASHmoUDnBOZg4GMVukqOcF5l0ynoepiA1YHLdZlMy6SB3P7BZKF/aNCOn9nXw+N9X4U/yUpkM3Pb7HoGdNrC8RO4SwrNjGrarkdEB6e1lBReK/dqcylaF/mpK9VLpfQszDI8xnR4VCmlEM+le0xOsyHfeGciabdI4KH0i0SfYl4ls5XrN+CaqFWdo=" - - PYPI=false - -cache: - directories: - - $HOME/.cache/pip - -matrix: - fast_finish: true - include: - - os: linux - env: [PYTHON=2.7, NUMPY=1.13, CYTHON=0.26] - - os: linux - env: [PYTHON=2.7] - - os: linux - env: [PYTHON=3.5, NUMPY=1.14] - - os: linux - env: [PYTHON=3.6, NUMPY=1.15, CYTHON=0.27] - - os: linux - python: 3.6 - env: [PYPI=true] - - os: linux - env: [PYTHON=3.7, DOCBUILD=true] - - os: osx - language: generic - env: [PYTHON=3.6] - - -before_install: - - git fetch --tags - - if [[ $PYPI = true ]]; then source ci/pypi-install.sh; else source ci/conda-install.sh; fi - - pip install tempita coverage coveralls pytest-cov codecov -q - - pip list - - export BUILD_DIR=${PWD} - - if [[ ${DOCBUILD} == true ]]; then pip install sphinx sphinx_rtd_theme guzzle_sphinx_theme ipython doctr -q; fi - - gcc --version || true - - clang --version || true - -install: - - python setup.py develop - -script: - - set -e - - pytest randomgen - - | - if [[ ${DOCBUILD} == true ]]; then - cd ${BUILD_DIR}/doc - make html - make html - cd ${BUILD_DIR} - doctr deploy devel --build-tags - if [[ -z ${TRAVIS_TAG} ]]; then - echo "Not a tagged build." - else - doctr deploy . --build-tags - fi - fi - -after_success: - - | - if [[ ${DOCBUILD} == true ]]; then - cd ${BUILD_DIR} - python benchmark.py; - fi diff --git a/_randomgen/README-git.md b/_randomgen/README-git.md deleted file mode 100644 index c771693902b6..000000000000 --- a/_randomgen/README-git.md +++ /dev/null @@ -1,26 +0,0 @@ -These are the bash commands used to get the bashtage/randomgen repo into numpy/numpy - -```bash -# from a directory just above a numpy git checkout -git clone https://github.com/bashtage/randomgen.git -cd randomgen -# rewrite the checkout, pushing the content into '_randomgen' -git filter-branch --index-filter ' - git ls-files -s | - sed "s-\t-\t_randomgen/-" | - GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && - mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE -' HEAD -# write this file, commit it -git add _randomgen/README-git.md -git commit -m"Add README-git.md" -git checkout -b randomgen -cd ../numpy -git checkout -b randomgen -git remote add randomgen ../randomgen -git fetch randomgen randomgen -git merge --allow-unrelated-histories randomgen/randomgen -git remote remove randomgen -# Now all the randomgen commits are on the randomgen branch in numpy, -# and there is a subdirectory _randomgen with the content -``` diff --git a/_randomgen/README.md b/_randomgen/README.md deleted file mode 100644 index 2e8073645f30..000000000000 --- a/_randomgen/README.md +++ /dev/null @@ -1,288 +0,0 @@ -# RandomGen - -[![Travis Build Status](https://travis-ci.org/bashtage/randomgen.svg?branch=master)](https://travis-ci.org/bashtage/randomgen) -[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true)](https://ci.appveyor.com/project/bashtage/randomgen/branch/master) -[![PyPI version](https://badge.fury.io/py/randomgen.svg)](https://pypi.org/project/randomgen/) - -Random Number Generator using settable Basic RNG interface for future -NumPy RandomState evolution. - -This is a library and generic interface for alternative random -generators in Python and NumPy. - -## Python 2.7 Support - -v1.16 is the final major version that supports Python 2.7. Any bugs -in v1.16 will be patched until the end of 2019. All future releases -are Python 3, with an initial minimum version of 3.5. - -## Compatibility Warning - -`RandomGenerator` does not support Box-Muller normal variates and so it not -100% compatible with NumPy (or randomstate). Box-Muller normals are slow -to generate and all functions which previously relied on Box-Muller -normals now use the faster Ziggurat implementation. If you require backward -compatibility, a legacy generator, ``LegacyGenerator``, has been created -which can fully reproduce the sequence produced by NumPy. - -## Features - -* Replacement for NumPy's RandomState - - ```python - from randomgen import RandomGenerator, MT19937 - rnd = RandomGenerator(MT19937()) - x = rnd.standard_normal(100) - y = rnd.random_sample(100) - z = rnd.randn(10,10) - ``` - -* Default random generator is a fast generator called Xoroshiro128plus -* Support for random number generators that support independent streams - and jumping ahead so that sub-streams can be generated -* Faster random number generation, especially for normal, standard - exponential and standard gamma using the Ziggurat method - - ```python - from randomgen import RandomGenerator - # Default basic PRNG is Xoroshiro128 - rnd = RandomGenerator() - w = rnd.standard_normal(10000) - x = rnd.standard_exponential(10000) - y = rnd.standard_gamma(5.5, 10000) - ``` - -* Support for 32-bit floating randoms for core generators. - Currently supported: - - * Uniforms (`random_sample`) - * Exponentials (`standard_exponential`, both Inverse CDF and Ziggurat) - * Normals (`standard_normal`) - * Standard Gammas (via `standard_gamma`) - - **WARNING**: The 32-bit generators are **experimental** and subject - to change. - - **Note**: There are _no_ plans to extend the alternative precision - generation to all distributions. - -* Support for filling existing arrays using `out` keyword argument. Currently - supported in (both 32- and 64-bit outputs) - - * Uniforms (`random_sample`) - * Exponentials (`standard_exponential`) - * Normals (`standard_normal`) - * Standard Gammas (via `standard_gamma`) - -* Support for Lemire's method of generating uniform integers on an - arbitrary interval by setting `use_masked=True`. - -## Included Pseudo Random Number Generators - -This module includes a number of alternative random -number generators in addition to the MT19937 that is included in NumPy. -The RNGs include: - -* [MT19937](https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/), - the NumPy rng -* [dSFMT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/) a - SSE2-aware version of the MT19937 generator that is especially fast at - generating doubles -* [xoroshiro128+](http://xoroshiro.di.unimi.it/), - [xorshift1024*φ](http://xorshift.di.unimi.it/), - [xoshiro256**](http://xorshift.di.unimi.it/), - and [xoshiro512**](http://xorshift.di.unimi.it/) -* [PCG64](http://www.pcg-random.org/) -* ThreeFry and Philox from [Random123](https://www.deshawresearch.com/resources_random123.html) - -## Differences from `numpy.random.RandomState` - -### New Features - -* `standard_normal`, `normal`, `randn` and `multivariate_normal` all - use the much faster (100%+) Ziggurat method. -* `standard_gamma` and `gamma` both use the much faster Ziggurat method. -* `standard_exponential` `exponential` both support an additional - `method` keyword argument which can be `inv` or - `zig` where `inv` corresponds to the current method using the inverse - CDF and `zig` uses the much faster (100%+) Ziggurat method. -* Core random number generators can produce either single precision - (`np.float32`) or double precision (`np.float64`, the default) using - the optional keyword argument `dtype` -* Core random number generators can fill existing arrays using the - `out` keyword argument -* Standardizes integer-values random values as int64 for all platforms. -* `randint` supports generating using rejection sampling on masked - values (the default) or Lemire's method. Lemire's method can be much - faster when the required interval length is much smaller than the - closes power of 2. - -### New Functions - -* `random_entropy` - Read from the system entropy provider, which is - commonly used in cryptographic applications -* `random_raw` - Direct access to the values produced by the underlying - PRNG. The range of the values returned depends on the specifics of the - PRNG implementation. -* `random_uintegers` - unsigned integers, either 32- (`[0, 2**32-1]`) - or 64-bit (`[0, 2**64-1]`) -* `jump` - Jumps RNGs that support it. `jump` moves the state a great - distance. _Only available if supported by the RNG._ -* `advance` - Advanced the RNG 'as-if' a number of draws were made, - without actually drawing the numbers. _Only available if supported by - the RNG._ - -## Status - -* Builds and passes all tests on: - * Linux 32/64 bit, Python 2.7, 3.4, 3.5, 3.6, 3.6 - * PC-BSD (FreeBSD) 64-bit, Python 2.7 - * OSX 64-bit, Python 2.7, 3.5, 3.6, 3.7 - * Windows 32/64 bit, Python 2.7, 3.5, 3.6 and 3.7 - -## Version - -The version matched the latest version of NumPy where -`LegacyGenerator(MT19937())` passes all NumPy test. - -## Documentation - -Documentation for the latest release is available on -[my GitHub pages](http://bashtage.github.io/randomgen/). Documentation for -the latest commit (unreleased) is available under -[devel](http://bashtage.github.io/randomgen/devel/). - -## Plans - -This module is essentially complete. There are a few rough edges that -need to be smoothed. - -* Creation of additional streams from where supported - (i.e. a `next_stream()` method) - -## Requirements -Building requires: - -* Python (2.7, 3.5, 3.6, 3.7) -* NumPy (1.13, 1.14, 1.15, 1.16) -* Cython (0.26+) -* tempita (0.5+), if not provided by Cython - -Testing requires pytest (4.0+). - -**Note:** it might work with other versions but only tested with these -versions. - -## Development and Testing - -All development has been on 64-bit Linux, and it is regularly tested on -Travis-CI (Linux/OSX) and Appveyor (Windows). The library is occasionally -tested on Linux 32-bit and Free BSD 11.1. - -Basic tests are in place for all RNGs. The MT19937 is tested against -NumPy's implementation for identical results. It also passes NumPy's -test suite where still relevant. - -## Installing - -Either install from PyPi using - -```bash -pip install randomgen -``` - -or, if you want the latest version, - -```bash -pip install git+https://github.com/bashtage/randomgen.git -``` - -or from a cloned repo, - -```bash -python setup.py install -``` - -### SSE2 - -`dSFTM` makes use of SSE2 by default. If you have a very old computer -or are building on non-x86, you can install using: - -```bash -python setup.py install --no-sse2 -``` - -### Windows - -Either use a binary installer, or if building from scratch, use -Python 3.6 with Visual Studio 2015/2017 Community Edition. It can also -be build using Microsoft Visual C++ Compiler for Python 2.7 and -Python 2.7. - -## Using - -The separate generators are importable from `randomgen` - -```python -from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 -rg = RandomGenerator(ThreeFry()) -rg.random_sample(100) - -rg = RandomGenerator(PCG64()) -rg.random_sample(100) - -# Identical to NumPy -rg = RandomGenerator(MT19937()) -rg.random_sample(100) -``` - -## License - -Standard NCSA, plus sub licenses for components. - -## Performance - -Performance is promising, and even the mt19937 seems to be faster than -NumPy's mt19937. - - Speed-up relative to NumPy (Uniform Doubles) - ************************************************************ - DSFMT 184.9% - MT19937 17.3% - PCG32 83.3% - PCG64 108.3% - Philox -4.9% - ThreeFry -12.0% - ThreeFry32 -63.9% - Xoroshiro128 159.5% - Xorshift1024 150.4% - Xoshiro256StarStar 145.7% - Xoshiro512StarStar 113.1% - - Speed-up relative to NumPy (64-bit unsigned integers) - ************************************************************ - DSFMT 17.4% - MT19937 7.8% - PCG32 60.3% - PCG64 73.5% - Philox -25.5% - ThreeFry -30.5% - ThreeFry32 -67.8% - Xoroshiro128 124.0% - Xorshift1024 109.4% - Xoshiro256StarStar 100.3% - Xoshiro512StarStar 63.5% - - Speed-up relative to NumPy (Standard normals) - ************************************************************ - DSFMT 183.0% - MT19937 169.0% - PCG32 240.7% - PCG64 231.6% - Philox 131.3% - ThreeFry 118.3% - ThreeFry32 21.6% - Xoroshiro128 332.1% - Xorshift1024 232.4% - Xoshiro256StarStar 306.6% - Xoshiro512StarStar 274.6% diff --git a/_randomgen/README.rst b/_randomgen/README.rst deleted file mode 100644 index 7e91b898d17e..000000000000 --- a/_randomgen/README.rst +++ /dev/null @@ -1,320 +0,0 @@ -RandomGen -========= - -|Travis Build Status| |Appveyor Build Status| |PyPI version| - -Random Number Generator using settable Basic RNG interface for future -NumPy RandomState evolution. - -This is a library and generic interface for alternative random -generators in Python and NumPy. - -Python 2.7 Support ------------------- - -Release 1.16.0 is the final version that supports Python 2.7. Any bugs -in v1.16.0 will be patched until the end of 2019. All future releases -are Python 3, with an initial minimum version of 3.5. - -Compatibility Warning ---------------------- - -``RandomGenerator`` does not support Box-Muller normal variates and so -it not 100% compatible with NumPy (or randomstate). Box-Muller normals -are slow to generate and all functions which previously relied on -Box-Muller normals now use the faster Ziggurat implementation. If you -require backward compatibility, a legacy generator, ``LegacyGenerator``, -has been created which can fully reproduce the sequence produced by -NumPy. - -Features --------- - -- Replacement for NumPy’s RandomState - - .. code:: python - - from randomgen import RandomGenerator, MT19937 - rnd = RandomGenerator(MT19937()) - x = rnd.standard_normal(100) - y = rnd.random_sample(100) - z = rnd.randn(10,10) - -- Default random generator is a fast generator called Xoroshiro128plus -- Support for random number generators that support independent streams - and jumping ahead so that sub-streams can be generated -- Faster random number generation, especially for normal, standard - exponential and standard gamma using the Ziggurat method - - .. code:: python - - from randomgen import RandomGenerator - # Default basic PRNG is Xoroshiro128 - rnd = RandomGenerator() - w = rnd.standard_normal(10000) - x = rnd.standard_exponential(10000) - y = rnd.standard_gamma(5.5, 10000) - -- Support for 32-bit floating randoms for core generators. Currently - supported: - - - Uniforms (``random_sample``) - - Exponentials (``standard_exponential``, both Inverse CDF and - Ziggurat) - - Normals (``standard_normal``) - - Standard Gammas (via ``standard_gamma``) - - **WARNING**: The 32-bit generators are **experimental** and subject - to change. - - **Note**: There are *no* plans to extend the alternative precision - generation to all distributions. - -- Support for filling existing arrays using ``out`` keyword argument. - Currently supported in (both 32- and 64-bit outputs) - - - Uniforms (``random_sample``) - - Exponentials (``standard_exponential``) - - Normals (``standard_normal``) - - Standard Gammas (via ``standard_gamma``) - -- Support for Lemire’s method of generating uniform integers on an - arbitrary interval by setting ``use_masked=True``. - -Included Pseudo Random Number Generators ----------------------------------------- - -This module includes a number of alternative random number generators in -addition to the MT19937 that is included in NumPy. The RNGs include: - -- `MT19937 `__, - the NumPy rng -- `dSFMT `__ a - SSE2-aware version of the MT19937 generator that is especially fast - at generating doubles -- `xoroshiro128+ `__, - `xorshift1024*φ `__, - `xoshiro256*\* `__, and - `xoshiro512*\* `__ -- `PCG64 `__ -- ThreeFry and Philox from - `Random123 `__ - -Differences from ``numpy.random.RandomState`` ---------------------------------------------- - -New Features -~~~~~~~~~~~~ - -- ``standard_normal``, ``normal``, ``randn`` and - ``multivariate_normal`` all use the much faster (100%+) Ziggurat - method. -- ``standard_gamma`` and ``gamma`` both use the much faster Ziggurat - method. -- ``standard_exponential`` ``exponential`` both support an additional - ``method`` keyword argument which can be ``inv`` or ``zig`` where - ``inv`` corresponds to the current method using the inverse CDF and - ``zig`` uses the much faster (100%+) Ziggurat method. -- Core random number generators can produce either single precision - (``np.float32``) or double precision (``np.float64``, the default) - using the optional keyword argument ``dtype`` -- Core random number generators can fill existing arrays using the - ``out`` keyword argument -- Standardizes integer-values random values as int64 for all platforms. -- ``randint`` supports generating using rejection sampling on masked - values (the default) or Lemire’s method. Lemire’s method can be much - faster when the required interval length is much smaller than the - closes power of 2. - -New Functions -~~~~~~~~~~~~~ - -- ``random_entropy`` - Read from the system entropy provider, which is - commonly used in cryptographic applications -- ``random_raw`` - Direct access to the values produced by the - underlying PRNG. The range of the values returned depends on the - specifics of the PRNG implementation. -- ``random_uintegers`` - unsigned integers, either 32- - (``[0, 2**32-1]``) or 64-bit (``[0, 2**64-1]``) -- ``jump`` - Jumps RNGs that support it. ``jump`` moves the state a - great distance. *Only available if supported by the RNG.* -- ``advance`` - Advanced the RNG ‘as-if’ a number of draws were made, - without actually drawing the numbers. *Only available if supported by - the RNG.* - -Status ------- - -- Builds and passes all tests on: - - - Linux 32/64 bit, Python 2.7, 3.5, 3.6, 3.7 - - PC-BSD (FreeBSD) 64-bit, Python 2.7 - - OSX 64-bit, Python 2.7, 3.5, 3.6, 3.7 - - Windows 32/64 bit, Python 2.7, 3.5, 3.6, and 3.7 - -Version -------- - -The version matched the latest version of NumPy where -``LegacyGenerator(MT19937())`` passes all NumPy test. - -Documentation -------------- - -Documentation for the latest release is available on `my GitHub -pages `__. Documentation for the -latest commit (unreleased) is available under -`devel `__. - -Plans ------ - -This module is essentially complete. There are a few rough edges that -need to be smoothed. - -- Creation of additional streams from where supported (i.e. a - ``next_stream()`` method) - -Requirements ------------- - -Building requires: - -- Python (2.7, 3.5, 3.6, 3.7) -- NumPy (1.13, 1.14, 1.15, 1.16) -- Cython (0.26+) -- tempita (0.5+), if not provided by Cython - -Testing requires pytest (4.0+). - -**Note:** it might work with other versions but only tested with these -versions. - -Development and Testing ------------------------ - -All development has been on 64-bit Linux, and it is regularly tested on -Travis-CI (Linux/OSX) and Appveyor (Windows). The library is -occasionally tested on Linux 32-bit and Free BSD 11.1. - -Basic tests are in place for all RNGs. The MT19937 is tested against -NumPy’s implementation for identical results. It also passes NumPy’s -test suite where still relevant. - -Installing ----------- - -Either install from PyPi using - -.. code:: bash - - pip install randomgen - -or, if you want the latest version, - -.. code:: bash - - pip install git+https://github.com/bashtage/randomgen.git - -or from a cloned repo, - -.. code:: bash - - python setup.py install - -SSE2 -~~~~ - -``dSFTM`` makes use of SSE2 by default. If you have a very old computer -or are building on non-x86, you can install using: - -.. code:: bash - - python setup.py install --no-sse2 - -Windows -~~~~~~~ - -Either use a binary installer, or if building from scratch, use Python -3.6 with Visual Studio 2015/2017 Community Edition. It can also be build -using Microsoft Visual C++ Compiler for Python 2.7 and Python 2.7. - -Using ------ - -The separate generators are importable from ``randomgen`` - -.. code:: python - - from randomgen import RandomGenerator, ThreeFry, PCG64, MT19937 - rg = RandomGenerator(ThreeFry()) - rg.random_sample(100) - - rg = RandomGenerator(PCG64()) - rg.random_sample(100) - - # Identical to NumPy - rg = RandomGenerator(MT19937()) - rg.random_sample(100) - -License -------- - -Standard NCSA, plus sub licenses for components. - -Performance ------------ - -Performance is promising, and even the mt19937 seems to be faster than -NumPy’s mt19937. - -:: - - Speed-up relative to NumPy (Uniform Doubles) - ************************************************************ - DSFMT 184.9% - MT19937 17.3% - PCG32 83.3% - PCG64 108.3% - Philox -4.9% - ThreeFry -12.0% - ThreeFry32 -63.9% - Xoroshiro128 159.5% - Xorshift1024 150.4% - Xoshiro256StarStar 145.7% - Xoshiro512StarStar 113.1% - - Speed-up relative to NumPy (64-bit unsigned integers) - ************************************************************ - DSFMT 17.4% - MT19937 7.8% - PCG32 60.3% - PCG64 73.5% - Philox -25.5% - ThreeFry -30.5% - ThreeFry32 -67.8% - Xoroshiro128 124.0% - Xorshift1024 109.4% - Xoshiro256StarStar 100.3% - Xoshiro512StarStar 63.5% - - Speed-up relative to NumPy (Standard normals) - ************************************************************ - DSFMT 183.0% - MT19937 169.0% - PCG32 240.7% - PCG64 231.6% - Philox 131.3% - ThreeFry 118.3% - ThreeFry32 21.6% - Xoroshiro128 332.1% - Xorshift1024 232.4% - Xoshiro256StarStar 306.6% - Xoshiro512StarStar 274.6% - -.. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master - :target: https://travis-ci.org/bashtage/randomgen -.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true - :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master -.. |PyPI version| image:: https://badge.fury.io/py/randomgen.svg - :target: https://pypi.org/project/randomgen/ diff --git a/_randomgen/benchmark.py b/_randomgen/benchmark.py deleted file mode 100644 index c4c4ab93d8f6..000000000000 --- a/_randomgen/benchmark.py +++ /dev/null @@ -1,201 +0,0 @@ -import os -import struct -import timeit - -import numpy as np -import pandas as pd -from numpy.random import RandomState - -rs = RandomState() - -SETUP = ''' -import numpy as np -if '{brng}' == 'numpy': - import numpy.random - rg = numpy.random.RandomState() -else: - from randomgen import RandomGenerator, {brng} - rg = RandomGenerator({brng}()) -rg.random_sample() -''' - -scale_32 = scale_64 = 1 -if struct.calcsize('P') == 8 and os.name != 'nt': - # 64 bit - scale_32 = 0.5 -else: - scale_64 = 2 - -PRNGS = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'Philox', 'ThreeFry', - 'ThreeFry32', 'numpy'] - - -def timer(code, setup): - return 1000 * min(timeit.Timer(code, setup=setup).repeat(10, 10)) / 10.0 - - -def print_legend(legend): - print('\n' + legend + '\n' + '*' * max(60, len(legend))) - - -def run_timer(dist, command, numpy_command=None, setup='', random_type=''): - print('-' * 80) - if numpy_command is None: - numpy_command = command - - res = {} - for brng in PRNGS: - cmd = numpy_command if brng == 'numpy' else command - res[brng] = timer(cmd, setup=setup.format(brng=brng)) - - s = pd.Series(res) - t = s.apply(lambda x: '{0:0.2f} ms'.format(x)) - print_legend('Time to produce 1,000,000 ' + random_type) - print(t.sort_index()) - - p = 1000.0 / s - p = p.apply(lambda x: '{0:0.2f} million'.format(x)) - print_legend(random_type + ' per second') - print(p.sort_index()) - - baseline = [k for k in p.index if 'numpy' in k][0] - p = 1000.0 / s - p = p / p[baseline] * 100 - 100 - p = p.drop(baseline, 0) - p = p.apply(lambda x: '{0:0.1f}%'.format(x)) - print_legend('Speed-up relative to NumPy') - print(p.sort_index()) - print('-' * 80) - - -def timer_raw(): - dist = 'random_raw' - command = 'rg.random_raw(size=1000000, output=False)' - info = np.iinfo(np.int32) - command_numpy = 'rg.random_integers({max},size=1000000)' - command_numpy = command_numpy.format(max=info.max) - run_timer(dist, command, command_numpy, SETUP, 'Raw Values') - - -def timer_uniform(): - dist = 'random_sample' - command = 'rg.random_sample(1000000)' - run_timer(dist, command, None, SETUP, 'Uniforms') - - -def timer_bounded(bits=8, max=95, use_masked=True): - """ - Timer for 8-bit bounded values. - - Parameters - ---------- - bits : {8, 16, 32, 64} - Bit width of unsigned output type - max : int - Upper bound for range. Lower is always 0. Must be <= 2**bits. - use_masked: bool - If True, masking and rejection sampling is used to generate a random - number in an interval. If False, Lemire's algorithm is used if - available to generate a random number in an interval. - - Notes - ----- - Lemire's algorithm has improved performance when {max}+1 is not a - power of two. - """ - if bits not in (8, 16, 32, 64): - raise ValueError('bits must be one of 8, 16, 32, 64.') - minimum = 0 - - dist = 'random_uintegers' - - if use_masked: # Use masking & rejection. - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits}, use_masked=True)' - else: # Use Lemire's algo. - command = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits}, use_masked=False)' - - command = command.format(min=minimum, max=max, bits=bits) - - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint{bits})' - command_numpy = command_numpy.format(min=minimum, max=max, bits=bits) - - run_timer(dist, command, command_numpy, SETUP, - '{bits}-bit bounded unsigned integers (max={max}, ' - 'use_masked={use_masked})'.format(max=max, use_masked=use_masked, bits=bits)) - - -def timer_32bit(): - info = np.iinfo(np.uint32) - minimum, maximum = info.min, info.max - dist = 'random_uintegers' - command = 'rg.random_uintegers(1000000, 32)' - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint32)' - command_numpy = command_numpy.format(min=minimum, max=maximum) - run_timer(dist, command, command_numpy, SETUP, '32-bit unsigned integers') - - -def timer_64bit(): - info = np.iinfo(np.uint64) - minimum, maximum = info.min, info.max - dist = 'random_uintegers' - command = 'rg.random_uintegers(1000000)' - command_numpy = 'rg.randint({min}, {max}+1, 1000000, dtype=np.uint64)' - command_numpy = command_numpy.format(min=minimum, max=maximum) - run_timer(dist, command, command_numpy, SETUP, '64-bit unsigned integers') - - -def timer_normal_zig(): - dist = 'standard_normal' - command = 'rg.standard_normal(1000000)' - command_numpy = 'rg.standard_normal(1000000)' - run_timer(dist, command, command_numpy, SETUP, - 'Standard normals (Ziggurat)') - - -if __name__ == '__main__': - import argparse - - parser = argparse.ArgumentParser() - parser.add_argument('-f', '--full', - help='Run benchmarks for a wide range of distributions.' - ' If not provided, only tests the production of ' - 'uniform values.', - dest='full', action='store_true') - parser.add_argument('-bi', '--bounded-ints', - help='Included benchmark coverage of the bounded ' - 'integer generators in a full run.', - dest='bounded_ints', action='store_true') - args = parser.parse_args() - - timer_uniform() - if args.full: - timer_raw() - if args.bounded_ints: - timer_bounded(use_masked=True) - timer_bounded(max=64, use_masked=False) # Worst case for Numpy. - timer_bounded(max=95, use_masked=False) # Typ. avrg. case for Numpy. - timer_bounded(max=127, use_masked=False) # Best case for Numpy. - - timer_bounded(16, use_masked=True) - timer_bounded(16, max=1024, use_masked=False) # Worst case for Numpy. - timer_bounded(16, max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_bounded(16, max=2047, use_masked=False) # Best case for Numpy. - - timer_32bit() - - if args.bounded_ints: - timer_bounded(32, use_masked=True) - timer_bounded(32, max=1024, use_masked=False) # Worst case for Numpy. - timer_bounded(32, max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_bounded(32, max=2047, use_masked=False) # Best case for Numpy. - - timer_64bit() - - if args.bounded_ints: - timer_bounded(64, use_masked=True) - timer_bounded(64, max=1024, use_masked=False) # Worst case for Numpy. - timer_bounded(64, max=1535, use_masked=False) # Typ. avrg. case for Numpy. - timer_bounded(64, max=2047, use_masked=False) # Best case for Numpy. - - timer_normal_zig() diff --git a/_randomgen/setup.py b/_randomgen/setup.py deleted file mode 100644 index 9e9517e974c7..000000000000 --- a/_randomgen/setup.py +++ /dev/null @@ -1,325 +0,0 @@ -import os -import glob -import platform -import struct -import sys -from os.path import join - -import Cython.Compiler.Options -import numpy as np -from Cython.Build import cythonize -from setuptools import setup, find_packages, Distribution -from setuptools.extension import Extension - -try: - import Cython.Tempita as tempita -except ImportError: - try: - import tempita - except ImportError: - raise ImportError('tempita required to install, ' - 'use pip install tempita') - -try: - import pypandoc - # With an input file: it will infer the input format from the filename - with open('README.rst', 'wb') as readme: - readme.write(pypandoc.convert_file('README.md', 'rst').encode('utf8')) -except ImportError: - import warnings - warnings.warn( - 'Unable to import pypandoc. Do not use this as a release build!') - -import versioneer - -with open('requirements.txt') as f: - required = f.read().splitlines() - -Cython.Compiler.Options.annotate = True - -# Make a guess as to whether SSE2 is present for now, TODO: Improve -USE_SSE2 = False -for k in platform.uname(): - for val in ('x86', 'i686', 'i386', 'amd64'): - USE_SSE2 = USE_SSE2 or val in k.lower() -print('Building with SSE?: {0}'.format(USE_SSE2)) -if '--no-sse2' in sys.argv: - USE_SSE2 = False - sys.argv.remove('--no-sse2') - -MOD_DIR = './randomgen' - -DEBUG = False -PCG_EMULATED_MATH = False - -EXTRA_INCLUDE_DIRS = [] -EXTRA_LINK_ARGS = [] -EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] -# Undef for manylinux -EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ - '-std=c99', '-U__GNUC_GNU_INLINE__'] -if os.name == 'nt': - EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] - if DEBUG: - EXTRA_LINK_ARGS += ['-debug'] - EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] - if sys.version_info < (3, 0): - EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] - -PCG64_DEFS = [] -if sys.maxsize < 2 ** 32 or os.name == 'nt': - # Force emulated mode here - PCG_EMULATED_MATH = True - PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] - -DSFMT_DEFS = [('DSFMT_MEXP', '19937')] -if USE_SSE2: - if os.name == 'nt': - EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] - if struct.calcsize('P') < 8: - EXTRA_COMPILE_ARGS += ['/arch:SSE2'] - else: - EXTRA_COMPILE_ARGS += ['-msse2'] - DSFMT_DEFS += [('HAVE_SSE2', '1')] -if struct.calcsize('P') < 8: - PCG_EMULATED_MATH = True - -files = glob.glob('./randomgen/*.in') -for templated_file in files: - output_file_name = os.path.splitext(templated_file)[0] - if (os.path.exists(output_file_name) and - (os.path.getmtime(templated_file) < os.path.getmtime(output_file_name))): - continue - with open(templated_file, 'r') as source_file: - template = tempita.Template(source_file.read()) - with open(output_file_name, 'w') as output_file: - output_file.write(template.substitute()) - - -extensions = [Extension('randomgen.entropy', - sources=[join(MOD_DIR, 'entropy.pyx'), - join(MOD_DIR, 'src', 'entropy', 'entropy.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'entropy')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.dsfmt", - ["randomgen/dsfmt.pyx", - join(MOD_DIR, 'src', 'dsfmt', 'dSFMT.c'), - join(MOD_DIR, 'src', 'dsfmt', 'dSFMT-jump.c'), - join(MOD_DIR, 'src', 'aligned_malloc', 'aligned_malloc.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'dsfmt')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS, - define_macros=DSFMT_DEFS, - ), - Extension("randomgen.mt19937", - ["randomgen/mt19937.pyx", - join(MOD_DIR, 'src', 'mt19937', 'mt19937.c'), - join(MOD_DIR, 'src', 'mt19937', 'mt19937-jump.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'mt19937')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.philox", - ["randomgen/philox.pyx", - join(MOD_DIR, 'src', 'philox', 'philox.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'philox')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.pcg64", - ["randomgen/pcg64.pyx", - join(MOD_DIR, 'src', 'pcg64', 'pcg64.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'pcg64')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - define_macros=PCG64_DEFS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.pcg32", - ["randomgen/pcg32.pyx", - join(MOD_DIR, 'src', 'pcg32', 'pcg32.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'pcg32')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.threefry", - ["randomgen/threefry.pyx", - join(MOD_DIR, 'src', 'threefry', 'threefry.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'threefry')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.threefry32", - ["randomgen/threefry32.pyx", - join(MOD_DIR, 'src', 'threefry32', 'threefry32.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'threefry32')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.xoroshiro128", - ["randomgen/xoroshiro128.pyx", - join(MOD_DIR, 'src', 'xoroshiro128', - 'xoroshiro128.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join( - MOD_DIR, 'src', - 'xoroshiro128')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.xorshift1024", - ["randomgen/xorshift1024.pyx", - join(MOD_DIR, 'src', 'xorshift1024', - 'xorshift1024.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join(MOD_DIR, 'src', - 'xorshift1024')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.xoshiro256starstar", - ["randomgen/xoshiro256starstar.pyx", - join(MOD_DIR, 'src', 'xoshiro256starstar', - 'xoshiro256starstar.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join( - MOD_DIR, 'src', - 'xoshiro256starstar')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.xoshiro512starstar", - ["randomgen/xoshiro512starstar.pyx", - join(MOD_DIR, 'src', 'xoshiro512starstar', - 'xoshiro512starstar.c')], - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include(), - join( - MOD_DIR, 'src', - 'xoshiro512starstar')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.generator", - ["randomgen/generator.pyx", - join(MOD_DIR, 'src', 'distributions', - 'distributions.c')], - libraries=EXTRA_LIBRARIES, - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.common", - ["randomgen/common.pyx"], - libraries=EXTRA_LIBRARIES, - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.bounded_integers", - ["randomgen/bounded_integers.pyx", - join(MOD_DIR, 'src', 'distributions', - 'distributions.c')], - libraries=EXTRA_LIBRARIES, - include_dirs=EXTRA_INCLUDE_DIRS + [np.get_include()], - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - Extension("randomgen.legacy.legacy", - ["randomgen/legacy/legacy.pyx", - join(MOD_DIR, 'src', 'legacy', - 'distributions-boxmuller.c'), - join(MOD_DIR, 'src', 'distributions', 'distributions.c')], - libraries=EXTRA_LIBRARIES, - include_dirs=EXTRA_INCLUDE_DIRS + - [np.get_include()] + [join(MOD_DIR, 'legacy')], - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS - ), - ] - - -classifiers = ['Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Financial and Insurance Industry', - 'Intended Audience :: Information Technology', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux', - 'Operating System :: Unix', - 'Programming Language :: C', - 'Programming Language :: Cython', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Topic :: Adaptive Technologies', - 'Topic :: Artistic Software', - 'Topic :: Office/Business :: Financial', - 'Topic :: Scientific/Engineering', - 'Topic :: Security :: Cryptography'] - - -class BinaryDistribution(Distribution): - def is_pure(self): - return False - - -setup( - name='randomgen', - version=versioneer.get_version(), - classifiers=classifiers, - cmdclass=versioneer.get_cmdclass(), - ext_modules=cythonize(extensions, - compile_time_env={"PCG_EMULATED_MATH": PCG_EMULATED_MATH}, - compiler_directives={'language_level': '3'}), - packages=find_packages(), - package_dir={'randomgen': './randomgen'}, - package_data={'': ['*.h', '*.pxi', '*.pyx', '*.pxd', '*.in'], - 'randomgen.tests.data': ['*.csv']}, - include_package_data=True, - license='NSCA', - author='Kevin Sheppard', - author_email='kevin.k.sheppard@gmail.com', - distclass=BinaryDistribution, - long_description=open('README.rst').read(), - description='Random generator supporting multiple PRNGs', - url='https://github.com/bashtage/randomgen', - keywords=['pseudo random numbers', 'PRNG', 'RNG', 'RandomState', 'random', - 'random numbers', 'parallel random numbers', 'PCG', - 'XorShift', 'dSFMT', 'MT19937', 'Random123', 'ThreeFry', - 'Philox'], - zip_safe=False, - install_requires=required -) diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index 9d84d83d310a..38a079e84d6c 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -4,6 +4,8 @@ import numpy as np +from numpy.random import RandomState +from numpy.random.randomgen import RandomGenerator class Random(Benchmark): params = ['normal', 'uniform', 'weibull 1', 'binomial 10 0.5', @@ -80,3 +82,100 @@ def time_permutation_2d(self): def time_permutation_int(self): np.random.permutation(self.n) + +nom_size = 100000 + +class RNG(Benchmark): + param_names = ['rng'] + params = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', + 'Xorshift1024', 'Xoshiro256StarStar', 'Xoshiro512StarStar', + 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] + + def setup(self, brng): + if brng == 'numpy': + self.rg = np.random.RandomState() + else: + self.rg = RandomGenerator(getattr(np.random.randomgen, brng)()) + self.rg.random_sample() + self.int32info = np.iinfo(np.int32) + self.uint32info = np.iinfo(np.uint32) + self.uint64info = np.iinfo(np.uint64) + + def time_raw(self, brng): + if brng == 'numpy': + self.rg.random_integers(self.int32info.max, size=nom_size) + else: + self.rg.random_integers(self.int32info.max, size=nom_size) + + def time_32bit(self, brng): + min, max = self.uint32info.min, self.uint32info.max + self.rg.randint(min, max + 1, nom_size, dtype=np.uint32) + + def time_64bit(self, brng): + min, max = self.uint64info.min, self.uint64info.max + self.rg.randint(min, max + 1, nom_size, dtype=np.uint64) + + def time_normal_zig(self, brng): + self.rg.standard_normal(nom_size) + +class Bounded(Benchmark): + u8 = np.uint8 + u16 = np.uint16 + u32 = np.uint32 + u64 = np.uint64 + param_names = ['rng', 'dt_max_masked'] + params = [['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', + 'Xorshift1024', 'Xoshiro256StarStar', 'Xoshiro512StarStar', + 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'], + [[u8, 95, True], + [u8, 64, False], # Worst case for legacy + [u8, 95, False], # Typ. avg. case for legacy + [u8, 127, False], # Best case for legacy + [u16, 95, True], + [u16, 1024, False], # Worst case for legacy + [u16, 1535, False], # Typ. avg. case for legacy + [u16, 2047, False], # Best case for legacy + [u32, 95, True], + [u32, 1024, False], # Worst case for legacy + [u32, 1535, False], # Typ. avg. case for legacy + [u32, 2047, False], # Best case for legacy + [u64, 95, True], + [u64, 1024, False], # Worst case for legacy + [u64, 1535, False], # Typ. avg. case for legacy + [u64, 2047, False], # Best case for legacy + ]] + + def setup(self, brng, args): + if brng == 'numpy': + self.rg = np.random.RandomState() + else: + self.rg = RandomGenerator(getattr(np.random.randomgen, brng)()) + self.rg.random_sample() + + def time_bounded(self, brng, args): + """ + Timer for 8-bit bounded values. + + Parameters (packed as args) + ---------- + dt : {uint8, uint16, uint32, unit64} + output dtype + max : int + Upper bound for range. Lower is always 0. Must be <= 2**bits. + use_masked: bool + If True, masking and rejection sampling is used to generate a random + number in an interval. If False, Lemire's algorithm is used if + available to generate a random number in an interval. + + Notes + ----- + Lemire's algorithm has improved performance when max+1 is not a + power of two. + """ + dt, max, use_masked = args + if brng == 'numpy': + self.rg.randint(0, max + 1, nom_size, dtype=dt) + else: + self.rg.randint(0, max + 1, nom_size, dtype=dt, + use_masked=use_masked) + diff --git a/doc/source/reference/randomgen/extending.rst b/doc/source/reference/randomgen/extending.rst index c9d987b59ece..64f2ddcc16ce 100644 --- a/doc/source/reference/randomgen/extending.rst +++ b/doc/source/reference/randomgen/extending.rst @@ -59,6 +59,8 @@ directly in Numba after compiling the file distributions.c into a DLL or so. An example showing the use of a more complicated distribution is in the examples folder. +.. _randomgen_cython: + Cython ====== diff --git a/doc/source/reference/randomgen/generator.rst b/doc/source/reference/randomgen/generator.rst index d59efd68c802..54325f4d37ee 100644 --- a/doc/source/reference/randomgen/generator.rst +++ b/doc/source/reference/randomgen/generator.rst @@ -1,29 +1,26 @@ +.. currentmodule:: numpy.random.randomgen + Random Generator ---------------- -The :class:`~randomgen.generator.RandomGenerator` provides access to -a wide range of distributions, and served as a replacement for -:class:`~numpy.random.RandomState`. The main difference between -the two is that :class:`~randomgen.generator.RandomGenerator` relies -on an additional basic RNG to manage state and generate the random -bits which are then transformed into random values from useful -distributions. The default basic RNG used by -:class:`~randomgen.generator.RandomGenerator` is -:class:`~randomgen.xoroshiro128.Xoroshiro128`. The basic RNG can be -changed by passing an instantized basic RNG to -:class:`~randomgen.generator.RandomGenerator`. +The :class:`~RandomGenerator` provides access to +a wide range of distributions, and served as a replacement for +:class:`~numpy.random.RandomState`. The main difference between +the two is that ``RandomGenerator`` relies on an additional basic RNG to +manage state and generate the random bits, which are then transformed into +random values from useful distributions. The default basic RNG used by +``RandomGenerator`` is :class:`~xoroshiro128.Xoroshiro128`. The basic RNG can be +changed by passing an instantized basic RNG to ``RandomGenerator``. -.. currentmodule:: numpy.random.randomgen.generator .. autoclass:: RandomGenerator :exclude-members: -Seed and State Manipulation -=========================== +Accessing the RNG +================= .. autosummary:: :toctree: generated/ - ~RandomGenerator.seed - ~RandomGenerator.state + ~RandomGenerator.brng Simple random data ================== diff --git a/doc/source/reference/randomgen/index.rst b/doc/source/reference/randomgen/index.rst index 67d0441a2de4..a8b6f1c9b3ff 100644 --- a/doc/source/reference/randomgen/index.rst +++ b/doc/source/reference/randomgen/index.rst @@ -1,17 +1,21 @@ -Randomgen.RandomGen -=================== -This package contains replacements for the NumPy -:class:`~numpy.random.RandomState` object that allows the core random number -generator be be changed. - .. current_module numpy.random.randomgen +numpy.random.randomgen +====================== + +This package modernizes the legacy +`~numpy.random.RandomState` object and allows changing the core random +number generator (RNG). The `~numpy.random.randomgen.RandomGenerator` can +be initialized with a number of different RNGs, and exposes many different +probability distributions. + + Quick Start ----------- -Like :mod:`numpy.random`, RandomGen can be used at the module level. -This uses the default :class:`~randomgen.generator.RandomGenerator` which -uses normals provided by :class:`~randomgen.xoroshiro128.Xoroshiro128`. +By default, `generator.RandomGenerator` uses normals provided by +`xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in +`numpy.random` .. code-block:: python @@ -19,12 +23,11 @@ uses normals provided by :class:`~randomgen.xoroshiro128.Xoroshiro128`. import randomgen.generator as random random.standard_normal() -:class:`~randomgen.generator.RandomGenerator` can also be used as a -replacement for :class:`~numpy.random.RandomState`, although the random -values are generated by :class:`~randomgen.xoroshiro128.Xoroshiro128`. It -also isn't possible to directly seed a -:class:`~randomgen.generator.RandomGenerator`. - +`numpy.random.randomgen.RandomGenerator` can also be used as a replacement for +`~numpy.random.RandomState`, although the random values are generated by +`~numpyrandom.randomgen.xoroshiro128.Xoroshiro128`. Since ``randomgen`` +separates the `~numpy.random.randomgen.RandomGenerator` from the RNG, it is not +possible to directly seed the generator. .. code-block:: python @@ -34,9 +37,9 @@ also isn't possible to directly seed a rg.standard_normal() -Seeds can be passed to any of the basic RNGs. Here :class:`~randomgen.mt19937.MT19937` -is used and the :class:`~randomgen.generator.RandomGenerator` is accessed via -the property :attr:`~randomgen.mt19937.MT19937.generator`. +Seeds can be passed to any of the basic RNGs. Here `numpy.random.randomgen. +mt19937.MT19937` is used and the `~numpy.random.randomgen.RandomGenerator` is +accessed via the attribute `~numpy.random.randomgen.mt19937.MT19937.generator`. .. code-block:: python @@ -48,24 +51,23 @@ the property :attr:`~randomgen.mt19937.MT19937.generator`. Introduction ------------ RandomGen takes a different approach to producing random numbers from the -:class:`numpy.random.RandomState` object used in NumPy. Random number -generation is separated into two components, a basic RNG and a random -generator. +:class:`numpy.random.RandomState` object. Random number generation is +separated into two components, a basic RNG and a random generator. -The basic RNG has a limited set of responsibilities -- it manages the +The basic RNG has a limited set of responsibilities. It manages the underlying RNG state and provides functions to produce random doubles and random unsigned 32- and 64-bit values. The basic random generator also handles all seeding since this varies when using alternative basic RNGs. -The random generator (:class:`~randomgen.generator.RandomGenerator`) takes the +The `random generator <~numpy.random.randomgen.RandomGenerator>` takes the basic RNG-provided functions and transforms them into more useful distributions, e.g., simulated normal random values. This structure allows alternative basic RNGs to be used without code duplication. -The :class:`~randomgen.generator.RandomGenerator` is the user-facing object +The `~numpy.random.randomgen.RandomGenerator` is the user-facing object that is nearly identical to :class:`~numpy.random.RandomState`. The canonical -method to initialize a generator passes a basic RNG -- -:class:`~randomgen.mt19937.MT19937`, the underlying RNG in NumPy -- as the +method to initialize a generator passes a basic RNG -- `~numpy.random. +randomgen.mt19937.MT19937`, the underlying RNG in NumPy -- as the sole argument. Note that the basic RNG must be instantized. .. code-block:: python @@ -81,9 +83,9 @@ Seed information is directly passed to the basic RNG. rg = RandomGenerator(MT19937(12345)) rg.random_sample() -A shorthand method is also available which uses the -:meth:`~randomgen.mt19937.MT19937.generator` property from a basic RNG to -access an embedded random generator. +A shorthand method is also available which uses the `~numpy.random.randomgen. +mt19937.MT19937.generator` property from a basic RNG to access an embedded +random generator. .. code-block:: python @@ -95,13 +97,14 @@ What's New or Different .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available - in :class:`~randomgen.generator.RandomGenerator`. It is not possible to - reproduce the random values using :class:`~randomgen.generator.RandomGenerator` - for the normal distribution or any other distribution that relies on the - normal such as the gamma or student's t. If you require backward compatibility, a - legacy generator, :class:`~randomgen.legacy.LegacyGenerator`, has been created - which can fully reproduce the sequence produced by NumPy. - + in `~numpy.random.randomgen.RandomGenerator`. It is not possible to + reproduce the random values using `~numpy.random.randomgen.RandomGenerator` + for the normal distribution or any other distribution that + relies on the normal such as the gamma or student's t. If you require + backward compatibility, a legacy generator, `~numpy.random.randomgen.legacy. + LegacyGenerator`, has been created which can fully reproduce the sequence + produced by NumPy. + * The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF implementations. @@ -110,20 +113,18 @@ What's New or Different select distributions * Optional ``out`` argument that allows existing arrays to be filled for select distributions -* Simulate from the complex normal distribution - (:meth:`~randomgen.generator.RandomGenerator.complex_normal`) -* :func:`~randomgen.entropy.random_entropy` provides access to the system +* `~numpy.random.randomgen.entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). -* All basic random generators functions to produce doubles, uint64s and - uint32s via CTypes (:meth:`~randomgen.xoroshiro128.Xoroshiro128.ctypes`) - and CFFI (:meth:`~randomgen.xoroshiro128.Xoroshiro128.cffi`). This allows - these basic RNGs to be used in numba. +* All basic random generators functions can produce doubles, uint64s and + uint32s via CTypes (`~numpy.random.randomgen.xoroshiro128.Xoroshiro128.ctypes`) + and CFFI (:meth:`~numpy.random.randomgen.xoroshiro128.Xoroshiro128.cffi`). + This allows these basic RNGs to be used in numba. * The basic random number generators can be used in downstream projects via - Cython. + :ref:`Cython `. * Support for Lemire’s method [Lemire]_ of generating uniform integers on an arbitrary interval by setting ``use_masked=True`` in - (:meth:`~randomgen.generator.RandomGenerator.randint`). + `~umpy.random.randomgen.generator.RandomGenerator.randint`. See :ref:`new-or-different` for a complete list of improvements and @@ -144,9 +145,9 @@ The main innovation is the inclusion of a number of alternative pseudo-random nu generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are: * MT19937 - The standard NumPy generator. Produces identical results to NumPy - using the same seed/state. Adds a jump function that advances the generator - as-if 2**128 draws have been made (:meth:`~randomgen.mt19937.MT19937.jump`). - See `NumPy's documentation`_. + using the same seed/state. Adds a + `~numpy.random.randomgen.mt19937.MT19937.jump` function that advances the + generator as-if ``2**128`` draws have been made. See `numpy.random`. * dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically the same, but with a different state and so it is not possible to produce a sequence identical to MT19937. Supports ``jump`` and so can @@ -154,31 +155,30 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are * XoroShiro128+ - Improved version of XorShift128+ with better performance and statistical quality. Like the XorShift generators, it can be jumped to produce multiple streams in parallel applications. See - :meth:`~randomgen.xoroshiro128.Xoroshiro128.jump` for details. + `~numpy.random.randomgen.xoroshiro128.Xoroshiro128.jump` for details. More information about this PRNG is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * XorShift1024*φ - Fast fast generator based on the XSadd generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - :meth:`~randomgen.xorshift1024.Xorshift1024.jump` for details. More information - about these PRNGs is available at the + `~numpy.random.randomgen.xorshift1024.Xorshift1024.jump` for details. More + information about these PRNGs is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * Xorshiro256** and Xorshiro512** - The most recently introduced XOR, shift, and rotate generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - :meth:`~randomgen.xoshiro256starstar.Xoshirt256StarStar.jump` for details. More - information about these PRNGs is available at the + `~numpy.random.randomgen.xoshiro256starstar.Xoshirt256StarStar.jump` for + details. More information about these PRNGs is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * PCG-64 - Fast generator that support many parallel streams and can be advanced by an arbitrary amount. See the documentation for - :meth:`~randomgen.pcg64.PCG64.advance`. PCG-64 has a period of + `~numpy.random.randomgen.pcg64.PCG64.advance`. PCG-64 has a period of :math:`2^{128}`. See the `PCG author's page`_ for more details about this class of PRNG. * ThreeFry and Philox - counter-based generators capable of being advanced an arbitrary number of steps or generating independent streams. See the `Random123`_ page for more details about this class of PRNG. -.. _`NumPy's documentation`: https://docs.scipy.org/doc/numpy/reference/routines.random.html .. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ .. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/ .. _`PCG author's page`: http://www.pcg-random.org/ @@ -215,14 +215,12 @@ New Features Changes ~~~~~~~ + +This package was developed independently of NumPy and was integrated in version +1.17.0. The original repo is at https://github.com/bashtage/randomgen. + .. toctree:: :maxdepth: 2 Change Log -Indices and tables -~~~~~~~~~~~~~~~~~~ - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/source/reference/randomgen/new-or-different.rst b/doc/source/reference/randomgen/new-or-different.rst index 0a27b9aa158c..089efd6fb880 100644 --- a/doc/source/reference/randomgen/new-or-different.rst +++ b/doc/source/reference/randomgen/new-or-different.rst @@ -64,9 +64,9 @@ What's New or Different .. ipython:: python - rg.seed(0) + rg.brng.seed(0) rg.random_sample(3, dtype='d') - rg.seed(0) + rg.brng.seed(0) rg.random_sample(3, dtype='f') * Optional ``out`` argument that allows existing arrays to be filled for diff --git a/numpy/random/randomgen/LICENSE.md b/numpy/random/LICENSE.md similarity index 100% rename from numpy/random/randomgen/LICENSE.md rename to numpy/random/LICENSE.md diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 53e9477975c0..89015d6a29e1 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -83,6 +83,22 @@ set_state Set state of generator. ==================== ========================================================= +==================== ========================================================= +Random Number Streams that work with RandomGenerator +============================================================================== +MT19937 +DSFMT +PCG32 +PCG64 +Philox +ThreeFry +ThreeFry32 +Xoroshiro128 +Xoroshift1024 +Xoshiro256StarStar +Xoshiro512StarStar +==================== ========================================================= + """ from __future__ import division, absolute_import, print_function @@ -136,8 +152,24 @@ 'zipf' ] -from .randomgen import mtrand -from .randomgen.mtrand import * +from . import mtrand +from .mtrand import * +from .dsfmt import DSFMT +from .generator import RandomGenerator +from .mt19937 import MT19937 +from .pcg32 import PCG32 +from .pcg64 import PCG64 +from .philox import Philox +from .threefry import ThreeFry +from .threefry32 import ThreeFry32 +from .xoroshiro128 import Xoroshiro128 +from .xorshift1024 import Xorshift1024 +from .xoshiro256starstar import Xoshiro256StarStar +from .xoshiro512starstar import Xoshiro512StarStar +from .mtrand import RandomState +__all__ += ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', + 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', + 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState'] # Some aliases: ranf = random = sample = random_sample diff --git a/numpy/random/mtrand/Python.pxi b/numpy/random/_mtrand/Python.pxi similarity index 100% rename from numpy/random/mtrand/Python.pxi rename to numpy/random/_mtrand/Python.pxi diff --git a/numpy/random/mtrand/distributions.c b/numpy/random/_mtrand/distributions.c similarity index 100% rename from numpy/random/mtrand/distributions.c rename to numpy/random/_mtrand/distributions.c diff --git a/numpy/random/mtrand/distributions.h b/numpy/random/_mtrand/distributions.h similarity index 100% rename from numpy/random/mtrand/distributions.h rename to numpy/random/_mtrand/distributions.h diff --git a/numpy/random/_mtrand/generate_mtrand_c.py b/numpy/random/_mtrand/generate_mtrand_c.py new file mode 100644 index 000000000000..ec935e6ddf09 --- /dev/null +++ b/numpy/random/_mtrand/generate_mtrand_c.py @@ -0,0 +1,42 @@ +#!/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 similarity index 100% rename from numpy/random/mtrand/initarray.c rename to numpy/random/_mtrand/initarray.c diff --git a/numpy/random/mtrand/initarray.h b/numpy/random/_mtrand/initarray.h similarity index 100% rename from numpy/random/mtrand/initarray.h rename to numpy/random/_mtrand/initarray.h diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/_mtrand/mtrand.pyx similarity index 100% rename from numpy/random/mtrand/mtrand.pyx rename to numpy/random/_mtrand/mtrand.pyx diff --git a/numpy/random/mtrand/mtrand_py_helper.h b/numpy/random/_mtrand/mtrand_py_helper.h similarity index 100% rename from numpy/random/mtrand/mtrand_py_helper.h rename to numpy/random/_mtrand/mtrand_py_helper.h diff --git a/numpy/random/mtrand/numpy.pxd b/numpy/random/_mtrand/numpy.pxd similarity index 100% rename from numpy/random/mtrand/numpy.pxd rename to numpy/random/_mtrand/numpy.pxd diff --git a/numpy/random/mtrand/randint_helpers.pxi.in b/numpy/random/_mtrand/randint_helpers.pxi.in similarity index 100% rename from numpy/random/mtrand/randint_helpers.pxi.in rename to numpy/random/_mtrand/randint_helpers.pxi.in diff --git a/numpy/random/mtrand/randomkit.c b/numpy/random/_mtrand/randomkit.c similarity index 100% rename from numpy/random/mtrand/randomkit.c rename to numpy/random/_mtrand/randomkit.c diff --git a/numpy/random/mtrand/randomkit.h b/numpy/random/_mtrand/randomkit.h similarity index 100% rename from numpy/random/mtrand/randomkit.h rename to numpy/random/_mtrand/randomkit.h diff --git a/numpy/random/randomgen/_pickle.py b/numpy/random/_pickle.py similarity index 100% rename from numpy/random/randomgen/_pickle.py rename to numpy/random/_pickle.py diff --git a/numpy/random/randomgen/bounded_integers.pxd.in b/numpy/random/bounded_integers.pxd.in similarity index 100% rename from numpy/random/randomgen/bounded_integers.pxd.in rename to numpy/random/bounded_integers.pxd.in diff --git a/numpy/random/randomgen/bounded_integers.pyx.in b/numpy/random/bounded_integers.pyx.in similarity index 100% rename from numpy/random/randomgen/bounded_integers.pyx.in rename to numpy/random/bounded_integers.pyx.in diff --git a/numpy/random/randomgen/common.pxd b/numpy/random/common.pxd similarity index 100% rename from numpy/random/randomgen/common.pxd rename to numpy/random/common.pxd diff --git a/numpy/random/randomgen/common.pyx b/numpy/random/common.pyx similarity index 100% rename from numpy/random/randomgen/common.pyx rename to numpy/random/common.pyx diff --git a/numpy/random/randomgen/distributions.pxd b/numpy/random/distributions.pxd similarity index 100% rename from numpy/random/randomgen/distributions.pxd rename to numpy/random/distributions.pxd diff --git a/numpy/random/randomgen/dsfmt.pyx b/numpy/random/dsfmt.pyx similarity index 100% rename from numpy/random/randomgen/dsfmt.pyx rename to numpy/random/dsfmt.pyx diff --git a/numpy/random/randomgen/entropy.pyx b/numpy/random/entropy.pyx similarity index 100% rename from numpy/random/randomgen/entropy.pyx rename to numpy/random/entropy.pyx diff --git a/numpy/random/randomgen/examples/cython/extending.pyx b/numpy/random/examples/cython/extending.pyx similarity index 100% rename from numpy/random/randomgen/examples/cython/extending.pyx rename to numpy/random/examples/cython/extending.pyx diff --git a/numpy/random/randomgen/examples/cython/extending_distributions.pyx b/numpy/random/examples/cython/extending_distributions.pyx similarity index 100% rename from numpy/random/randomgen/examples/cython/extending_distributions.pyx rename to numpy/random/examples/cython/extending_distributions.pyx diff --git a/numpy/random/randomgen/examples/cython/setup.py b/numpy/random/examples/cython/setup.py similarity index 100% rename from numpy/random/randomgen/examples/cython/setup.py rename to numpy/random/examples/cython/setup.py diff --git a/numpy/random/randomgen/examples/numba/extending.py b/numpy/random/examples/numba/extending.py similarity index 100% rename from numpy/random/randomgen/examples/numba/extending.py rename to numpy/random/examples/numba/extending.py diff --git a/numpy/random/randomgen/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py similarity index 100% rename from numpy/random/randomgen/examples/numba/extending_distributions.py rename to numpy/random/examples/numba/extending_distributions.py diff --git a/numpy/random/randomgen/generator.pyx b/numpy/random/generator.pyx similarity index 98% rename from numpy/random/randomgen/generator.pyx rename to numpy/random/generator.pyx index a244bca578d3..e68edb98ab15 100644 --- a/numpy/random/randomgen/generator.pyx +++ b/numpy/random/generator.pyx @@ -49,7 +49,7 @@ cdef class RandomGenerator: Notes ----- - The Python stdlib module "random" contains pseudo-random number generator + The Python stdlib module `random` contains pseudo-random number generator with a number of methods that are similar to the ones available in ``RandomGenerator``. It uses Mersenne Twister, and this basic RNG can be accessed using ``MT19937``. ``RandomGenerator``, besides being @@ -72,7 +72,7 @@ cdef class RandomGenerator: >>> rg = MT19937().generator >>> rg.standard_normal() """ - cdef public object _basicrng + cdef public object brng cdef brng_t *_brng cdef binomial_t *_binomial cdef object lock @@ -81,7 +81,7 @@ cdef class RandomGenerator: def __init__(self, brng=None): if brng is None: brng = Xoroshiro128() - self._basicrng = brng + self.brng = brng capsule = brng.capsule cdef const char *name = "BasicRNG" @@ -99,79 +99,21 @@ cdef class RandomGenerator: def __str__(self): _str = self.__class__.__name__ - _str += '(' + self._basicrng.__class__.__name__ + ')' + _str += '(' + self.brng.__class__.__name__ + ')' return _str # Pickling support: def __getstate__(self): - return self.state + return self.brng.state def __setstate__(self, state): - self.state = state + self.brng.state = state def __reduce__(self): from ._pickle import __generator_ctor return (__generator_ctor, - (self.state['brng'],), - self.state) - - def seed(self, *args, **kwargs): - """ - Reseed the basic RNG. - - Parameters depend on the basic RNG used. - - Notes - ----- - Arguments are directly passed to the basic RNG. This is a convenience - function. - - The best method to access seed is to directly use a basic RNG instance. - This example demonstrates this best practice. - - >>> from numpy.random.randomgen import RandomGenerator, PCG64 - >>> brng = PCG64(1234567891011) - >>> rg = brng.generator - >>> brng.seed(1110987654321) - - The method used to create the generator is not important. - - >>> brng = PCG64(1234567891011) - >>> rg = RandomGenerator(brng) - >>> brng.seed(1110987654321) - - These best practice examples are equivalent to - - >>> rg = RandomGenerator(PCG64(1234567891011)) - >>> rg.seed(1110987654321) - - """ - # TODO: Should this remain - self._basicrng.seed(*args, **kwargs) - return self - - @property - def state(self): - """ - Get or set the Basic RNG's state - - Returns - ------- - state : dict - Dictionary containing the information required to describe the - state of the Basic RNG - - Notes - ----- - This is a trivial pass-through function. RandomGenerator does not - directly contain or manipulate the basic RNG's state. - - """ - return self._basicrng.state - - @state.setter - def state(self, value): - self._basicrng.state = value + (self.brng.state['brng'],), + self.brng.state) def random_sample(self, size=None, dtype=np.float64, out=None): """ diff --git a/numpy/random/randomgen/legacy/__init__.py b/numpy/random/legacy/__init__.py similarity index 100% rename from numpy/random/randomgen/legacy/__init__.py rename to numpy/random/legacy/__init__.py diff --git a/numpy/random/randomgen/legacy/legacy_distributions.pxd b/numpy/random/legacy/legacy_distributions.pxd similarity index 100% rename from numpy/random/randomgen/legacy/legacy_distributions.pxd rename to numpy/random/legacy/legacy_distributions.pxd diff --git a/numpy/random/randomgen/mt19937.pyx b/numpy/random/mt19937.pyx similarity index 100% rename from numpy/random/randomgen/mt19937.pyx rename to numpy/random/mt19937.pyx diff --git a/numpy/random/randomgen/mtrand.pyx b/numpy/random/mtrand.pyx similarity index 100% rename from numpy/random/randomgen/mtrand.pyx rename to numpy/random/mtrand.pyx diff --git a/numpy/random/randomgen/pcg32.pyx b/numpy/random/pcg32.pyx similarity index 100% rename from numpy/random/randomgen/pcg32.pyx rename to numpy/random/pcg32.pyx diff --git a/numpy/random/randomgen/pcg64.pyx b/numpy/random/pcg64.pyx similarity index 100% rename from numpy/random/randomgen/pcg64.pyx rename to numpy/random/pcg64.pyx diff --git a/numpy/random/randomgen/philox.pyx b/numpy/random/philox.pyx similarity index 100% rename from numpy/random/randomgen/philox.pyx rename to numpy/random/philox.pyx diff --git a/numpy/random/randomgen/__init__.py b/numpy/random/randomgen/__init__.py deleted file mode 100644 index 1af2fc3b200c..000000000000 --- a/numpy/random/randomgen/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -from .dsfmt import DSFMT -from .generator import RandomGenerator -from .mt19937 import MT19937 -from .pcg32 import PCG32 -from .pcg64 import PCG64 -from .philox import Philox -from .threefry import ThreeFry -from .threefry32 import ThreeFry32 -from .xoroshiro128 import Xoroshiro128 -from .xorshift1024 import Xorshift1024 -from .xoshiro256starstar import Xoshiro256StarStar -from .xoshiro512starstar import Xoshiro512StarStar -from .mtrand import RandomState -__all__ = ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState'] - -#from ._version import get_versions - -#__version__ = get_versions()['version'] -#del get_versions diff --git a/numpy/random/randomgen/_version.py b/numpy/random/randomgen/_version.py deleted file mode 100644 index e400e3efb65d..000000000000 --- a/numpy/random/randomgen/_version.py +++ /dev/null @@ -1,520 +0,0 @@ - -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "$Format:%d$" - git_full = "$Format:%H$" - git_date = "$Format:%ci$" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "pep440" - cfg.tag_prefix = "" - cfg.parentdir_prefix = "randomgen-" - cfg.versionfile_source = "randomgen/_version.py" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): - root = os.path.dirname(root) - except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} diff --git a/numpy/random/randomgen/setup.py b/numpy/random/randomgen/setup.py deleted file mode 100644 index 5b7be45599c8..000000000000 --- a/numpy/random/randomgen/setup.py +++ /dev/null @@ -1,191 +0,0 @@ -from os.path import join -import sys -import os -import platform -import struct -from distutils.dep_util import newer -from distutils.msvccompiler import get_build_version as get_msvc_build_version - -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 - - return False - - -def configuration(parent_package='',top_path=None): - from numpy.distutils.misc_util import Configuration, get_mathlibs - config = Configuration('randomgen', parent_package, top_path) - - def generate_libraries(ext, build_dir): - config_cmd = config.get_config_cmd() - libs = get_mathlibs() - if sys.platform == 'win32': - libs.append('Advapi32') - ext.libraries.extend(libs) - return None - - # enable unix large file support on 32 bit systems - # (64 bit off_t, lseek -> lseek64 etc.) - if sys.platform[:3] == "aix": - defs = [('_LARGE_FILES', None)] - else: - 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 = [] - defs.append(('NPY_NO_DEPRECATED_API', 0)) - config.add_data_dir('tests') - - ############################## - # randomgen - ############################## - - # Make a guess as to whether SSE2 is present for now, TODO: Improve - USE_SSE2 = False - for k in platform.uname(): - for val in ('x86', 'i686', 'i386', 'amd64'): - USE_SSE2 = USE_SSE2 or val in k.lower() - print('Building with SSE?: {0}'.format(USE_SSE2)) - if '--no-sse2' in sys.argv: - USE_SSE2 = False - sys.argv.remove('--no-sse2') - - DEBUG = False - PCG_EMULATED_MATH = False - EXTRA_LINK_ARGS = [] - EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] - EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ - '-std=c99', '-U__GNUC_GNU_INLINE__'] - if os.name == 'nt': - EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] - if DEBUG: - EXTRA_LINK_ARGS += ['-debug'] - EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] - if sys.version_info < (3, 0): - EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] - - PCG64_DEFS = [] - # TODO: remove the unconditional forced emulation, move code from pcg64.pyx - # to an #ifdef - if 1 or sys.maxsize < 2 ** 32 or os.name == 'nt': - # Force emulated mode here - PCG_EMULATED_MATH = True - PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] - - if struct.calcsize('P') < 8: - PCG_EMULATED_MATH = True - defs.append(('PCG_EMULATED_MATH', int(PCG_EMULATED_MATH))) - - DSFMT_DEFS = [('DSFMT_MEXP', '19937')] - if USE_SSE2: - if os.name == 'nt': - EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] - if struct.calcsize('P') < 8: - EXTRA_COMPILE_ARGS += ['/arch:SSE2'] - else: - EXTRA_COMPILE_ARGS += ['-msse2'] - DSFMT_DEFS += [('HAVE_SSE2', '1')] - - config.add_extension('entropy', - sources=['entropy.c', 'src/entropy/entropy.c'], - include_dirs=[join('randomgen', 'src', 'entropy')], - 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, - ) - config.add_extension('dsfmt', - sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', - 'src/dsfmt/dSFMT-jump.c', - 'src/aligned_malloc/aligned_malloc.c'], - include_dirs=[join('src', 'dsfmt')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS, - depends=[join('src', 'dsfmt', 'dsfmt.h'), - 'dsfmt.pyx', - ], - define_macros=defs + DSFMT_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=[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', 'threefry', 'threefry32', - 'xoroshiro128', 'xorshift1024', 'xoshiro256starstar', - 'xoshiro512starstar', - 'pcg64', 'pcg32', - ]: - # gen.pyx, src/gen/gen.c - if gen == 'pcg64': - _defs = defs + PCG64_DEFS - else: - _defs = defs - config.add_extension(gen, - sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], - include_dirs=[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 ['common']: - # 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, - depends=['%s.pyx' % gen], - define_macros=defs, - ) - for gen in ['generator', 'bounded_integers']: - # gen.pyx, src/distributions/distributions.c - config.add_extension(gen, - sources=['{0}.c'.format(gen), - join('src', 'distributions', - 'distributions.c')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS, - depends=['%s.pyx' % gen], - define_macros=defs, - ) - config.add_extension('mtrand', - sources=['mtrand.c', - 'src/legacy/distributions-boxmuller.c', - 'src/distributions/distributions.c' ], - include_dirs=['.', 'legacy'], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS, - depends=['mtrand.pyx'], - define_macros=defs + DSFMT_DEFS, - ) - config.add_subpackage('legacy') - return config -if __name__ == '__main__': - from numpy.distutils.core import setup - setup(configuration=configuration) diff --git a/numpy/random/randomgen/tests/data/__init__.py b/numpy/random/randomgen/tests/data/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 481c4e380a88..088764791bb1 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -46,21 +46,160 @@ def generate_libraries(ext, build_dir): libs = [] defs.append(('NPY_NO_DEPRECATED_API', 0)) # Configure mtrand - config.add_extension('mtrand', - sources=[join('mtrand', x) for x in + 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'),], + depends=[join('_mtrand', '*.h'), + join('_mtrand', '*.pyx'), + join('_mtrand', '*.pxi'),], define_macros=defs, ) - config.add_data_files(('.', join('mtrand', 'randomkit.h'))) + config.add_data_files(('.', join('_mtrand', 'randomkit.h'))) config.add_data_dir('tests') - config.add_subpackage('randomgen') + ############################## + # randomgen + ############################## + + # Make a guess as to whether SSE2 is present for now, TODO: Improve + USE_SSE2 = False + for k in platform.uname(): + for val in ('x86', 'i686', 'i386', 'amd64'): + USE_SSE2 = USE_SSE2 or val in k.lower() + print('Building with SSE?: {0}'.format(USE_SSE2)) + if '--no-sse2' in sys.argv: + USE_SSE2 = False + sys.argv.remove('--no-sse2') + + DEBUG = False + PCG_EMULATED_MATH = False + EXTRA_LINK_ARGS = [] + EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] + EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ + '-std=c99', '-U__GNUC_GNU_INLINE__'] + if os.name == 'nt': + EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] + if DEBUG: + EXTRA_LINK_ARGS += ['-debug'] + EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] + if sys.version_info < (3, 0): + EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] + + PCG64_DEFS = [] + # TODO: remove the unconditional forced emulation, move code from pcg64.pyx + # to an #ifdef + if 1 or sys.maxsize < 2 ** 32 or os.name == 'nt': + # Force emulated mode here + PCG_EMULATED_MATH = True + PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] + + if struct.calcsize('P') < 8: + PCG_EMULATED_MATH = True + defs.append(('PCG_EMULATED_MATH', int(PCG_EMULATED_MATH))) + + DSFMT_DEFS = [('DSFMT_MEXP', '19937')] + if USE_SSE2: + if os.name == 'nt': + EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] + if struct.calcsize('P') < 8: + EXTRA_COMPILE_ARGS += ['/arch:SSE2'] + else: + EXTRA_COMPILE_ARGS += ['-msse2'] + DSFMT_DEFS += [('HAVE_SSE2', '1')] + + config.add_extension('entropy', + sources=['entropy.c', 'src/entropy/entropy.c'], + include_dirs=[join('randomgen', 'src', 'entropy')], + 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, + ) + config.add_extension('dsfmt', + sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', + 'src/dsfmt/dSFMT-jump.c', + 'src/aligned_malloc/aligned_malloc.c'], + include_dirs=[join('src', 'dsfmt')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=[join('src', 'dsfmt', 'dsfmt.h'), + 'dsfmt.pyx', + ], + define_macros=defs + DSFMT_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=[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', 'threefry', 'threefry32', + 'xoroshiro128', 'xorshift1024', 'xoshiro256starstar', + 'xoshiro512starstar', + 'pcg64', 'pcg32', + ]: + # gen.pyx, src/gen/gen.c + if gen == 'pcg64': + _defs = defs + PCG64_DEFS + else: + _defs = defs + config.add_extension(gen, + sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], + include_dirs=[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 ['common']: + # 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, + depends=['%s.pyx' % gen], + define_macros=defs, + ) + for gen in ['generator', 'bounded_integers']: + # gen.pyx, src/distributions/distributions.c + config.add_extension(gen, + sources=['{0}.c'.format(gen), + join('src', 'distributions', + 'distributions.c')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=['%s.pyx' % gen], + define_macros=defs, + ) + config.add_extension('mtrand', + sources=['mtrand.c', + 'src/legacy/distributions-boxmuller.c', + 'src/distributions/distributions.c' ], + include_dirs=['.', 'legacy'], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=['mtrand.pyx'], + define_macros=defs + DSFMT_DEFS, + ) + config.add_subpackage('legacy') return config if __name__ == '__main__': diff --git a/numpy/random/randomgen/src/aligned_malloc/aligned_malloc.c b/numpy/random/src/aligned_malloc/aligned_malloc.c similarity index 100% rename from numpy/random/randomgen/src/aligned_malloc/aligned_malloc.c rename to numpy/random/src/aligned_malloc/aligned_malloc.c diff --git a/numpy/random/randomgen/src/aligned_malloc/aligned_malloc.h b/numpy/random/src/aligned_malloc/aligned_malloc.h similarity index 100% rename from numpy/random/randomgen/src/aligned_malloc/aligned_malloc.h rename to numpy/random/src/aligned_malloc/aligned_malloc.h diff --git a/numpy/random/randomgen/src/common/LICENSE.md b/numpy/random/src/common/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/common/LICENSE.md rename to numpy/random/src/common/LICENSE.md diff --git a/numpy/random/randomgen/src/common/inttypes.h b/numpy/random/src/common/inttypes.h similarity index 100% rename from numpy/random/randomgen/src/common/inttypes.h rename to numpy/random/src/common/inttypes.h diff --git a/numpy/random/randomgen/src/common/stdint.h b/numpy/random/src/common/stdint.h similarity index 100% rename from numpy/random/randomgen/src/common/stdint.h rename to numpy/random/src/common/stdint.h diff --git a/numpy/random/randomgen/src/distributions/LICENSE.md b/numpy/random/src/distributions/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/distributions/LICENSE.md rename to numpy/random/src/distributions/LICENSE.md diff --git a/numpy/random/randomgen/src/distributions/binomial.h b/numpy/random/src/distributions/binomial.h similarity index 100% rename from numpy/random/randomgen/src/distributions/binomial.h rename to numpy/random/src/distributions/binomial.h diff --git a/numpy/random/randomgen/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c similarity index 100% rename from numpy/random/randomgen/src/distributions/distributions.c rename to numpy/random/src/distributions/distributions.c diff --git a/numpy/random/randomgen/src/distributions/distributions.h b/numpy/random/src/distributions/distributions.h similarity index 100% rename from numpy/random/randomgen/src/distributions/distributions.h rename to numpy/random/src/distributions/distributions.h diff --git a/numpy/random/randomgen/src/distributions/ziggurat.h b/numpy/random/src/distributions/ziggurat.h similarity index 100% rename from numpy/random/randomgen/src/distributions/ziggurat.h rename to numpy/random/src/distributions/ziggurat.h diff --git a/numpy/random/randomgen/src/distributions/ziggurat_constants.h b/numpy/random/src/distributions/ziggurat_constants.h similarity index 100% rename from numpy/random/randomgen/src/distributions/ziggurat_constants.h rename to numpy/random/src/distributions/ziggurat_constants.h diff --git a/numpy/random/randomgen/src/dsfmt/128-bit-jump.poly.txt b/numpy/random/src/dsfmt/128-bit-jump.poly.txt similarity index 100% rename from numpy/random/randomgen/src/dsfmt/128-bit-jump.poly.txt rename to numpy/random/src/dsfmt/128-bit-jump.poly.txt diff --git a/numpy/random/randomgen/src/dsfmt/96-bit-jump.poly.txt b/numpy/random/src/dsfmt/96-bit-jump.poly.txt similarity index 100% rename from numpy/random/randomgen/src/dsfmt/96-bit-jump.poly.txt rename to numpy/random/src/dsfmt/96-bit-jump.poly.txt diff --git a/numpy/random/randomgen/src/dsfmt/LICENSE.md b/numpy/random/src/dsfmt/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/dsfmt/LICENSE.md rename to numpy/random/src/dsfmt/LICENSE.md diff --git a/numpy/random/randomgen/src/dsfmt/calc-jump.cpp b/numpy/random/src/dsfmt/calc-jump.cpp similarity index 100% rename from numpy/random/randomgen/src/dsfmt/calc-jump.cpp rename to numpy/random/src/dsfmt/calc-jump.cpp diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-benchmark.c b/numpy/random/src/dsfmt/dSFMT-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-benchmark.c rename to numpy/random/src/dsfmt/dSFMT-benchmark.c diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-calc-jump.hpp b/numpy/random/src/dsfmt/dSFMT-calc-jump.hpp similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-calc-jump.hpp rename to numpy/random/src/dsfmt/dSFMT-calc-jump.hpp diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-common.h b/numpy/random/src/dsfmt/dSFMT-common.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-common.h rename to numpy/random/src/dsfmt/dSFMT-common.h diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-jump.c b/numpy/random/src/dsfmt/dSFMT-jump.c similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-jump.c rename to numpy/random/src/dsfmt/dSFMT-jump.c diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-jump.h b/numpy/random/src/dsfmt/dSFMT-jump.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-jump.h rename to numpy/random/src/dsfmt/dSFMT-jump.h diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-params.h b/numpy/random/src/dsfmt/dSFMT-params.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-params.h rename to numpy/random/src/dsfmt/dSFMT-params.h diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-params19937.h b/numpy/random/src/dsfmt/dSFMT-params19937.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-params19937.h rename to numpy/random/src/dsfmt/dSFMT-params19937.h diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-poly.h b/numpy/random/src/dsfmt/dSFMT-poly.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-poly.h rename to numpy/random/src/dsfmt/dSFMT-poly.h diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT-test-gen.c b/numpy/random/src/dsfmt/dSFMT-test-gen.c similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT-test-gen.c rename to numpy/random/src/dsfmt/dSFMT-test-gen.c diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT.c b/numpy/random/src/dsfmt/dSFMT.c similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT.c rename to numpy/random/src/dsfmt/dSFMT.c diff --git a/numpy/random/randomgen/src/dsfmt/dSFMT.h b/numpy/random/src/dsfmt/dSFMT.h similarity index 100% rename from numpy/random/randomgen/src/dsfmt/dSFMT.h rename to numpy/random/src/dsfmt/dSFMT.h diff --git a/numpy/random/randomgen/src/entropy/LICENSE.md b/numpy/random/src/entropy/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/entropy/LICENSE.md rename to numpy/random/src/entropy/LICENSE.md diff --git a/numpy/random/randomgen/src/entropy/entropy.c b/numpy/random/src/entropy/entropy.c similarity index 100% rename from numpy/random/randomgen/src/entropy/entropy.c rename to numpy/random/src/entropy/entropy.c diff --git a/numpy/random/randomgen/src/entropy/entropy.h b/numpy/random/src/entropy/entropy.h similarity index 100% rename from numpy/random/randomgen/src/entropy/entropy.h rename to numpy/random/src/entropy/entropy.h diff --git a/numpy/random/randomgen/src/legacy/LICENSE.md b/numpy/random/src/legacy/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/legacy/LICENSE.md rename to numpy/random/src/legacy/LICENSE.md diff --git a/numpy/random/randomgen/src/legacy/distributions-boxmuller.c b/numpy/random/src/legacy/distributions-boxmuller.c similarity index 100% rename from numpy/random/randomgen/src/legacy/distributions-boxmuller.c rename to numpy/random/src/legacy/distributions-boxmuller.c diff --git a/numpy/random/randomgen/src/legacy/distributions-boxmuller.h b/numpy/random/src/legacy/distributions-boxmuller.h similarity index 100% rename from numpy/random/randomgen/src/legacy/distributions-boxmuller.h rename to numpy/random/src/legacy/distributions-boxmuller.h diff --git a/numpy/random/randomgen/src/mt19937/LICENSE.md b/numpy/random/src/mt19937/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/mt19937/LICENSE.md rename to numpy/random/src/mt19937/LICENSE.md diff --git a/numpy/random/randomgen/src/mt19937/mt19937-benchmark.c b/numpy/random/src/mt19937/mt19937-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937-benchmark.c rename to numpy/random/src/mt19937/mt19937-benchmark.c diff --git a/numpy/random/randomgen/src/mt19937/mt19937-jump.c b/numpy/random/src/mt19937/mt19937-jump.c similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937-jump.c rename to numpy/random/src/mt19937/mt19937-jump.c diff --git a/numpy/random/randomgen/src/mt19937/mt19937-jump.h b/numpy/random/src/mt19937/mt19937-jump.h similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937-jump.h rename to numpy/random/src/mt19937/mt19937-jump.h diff --git a/numpy/random/randomgen/src/mt19937/mt19937-poly.h b/numpy/random/src/mt19937/mt19937-poly.h similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937-poly.h rename to numpy/random/src/mt19937/mt19937-poly.h diff --git a/numpy/random/randomgen/src/mt19937/mt19937-test-data-gen.c b/numpy/random/src/mt19937/mt19937-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937-test-data-gen.c rename to numpy/random/src/mt19937/mt19937-test-data-gen.c diff --git a/numpy/random/randomgen/src/mt19937/mt19937.c b/numpy/random/src/mt19937/mt19937.c similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937.c rename to numpy/random/src/mt19937/mt19937.c diff --git a/numpy/random/randomgen/src/mt19937/mt19937.h b/numpy/random/src/mt19937/mt19937.h similarity index 100% rename from numpy/random/randomgen/src/mt19937/mt19937.h rename to numpy/random/src/mt19937/mt19937.h diff --git a/numpy/random/randomgen/src/mt19937/randomkit.c b/numpy/random/src/mt19937/randomkit.c similarity index 100% rename from numpy/random/randomgen/src/mt19937/randomkit.c rename to numpy/random/src/mt19937/randomkit.c diff --git a/numpy/random/randomgen/src/mt19937/randomkit.h b/numpy/random/src/mt19937/randomkit.h similarity index 100% rename from numpy/random/randomgen/src/mt19937/randomkit.h rename to numpy/random/src/mt19937/randomkit.h diff --git a/numpy/random/randomgen/src/pcg32/LICENSE.md b/numpy/random/src/pcg32/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/pcg32/LICENSE.md rename to numpy/random/src/pcg32/LICENSE.md diff --git a/numpy/random/randomgen/src/pcg32/pcg-advance-64.c b/numpy/random/src/pcg32/pcg-advance-64.c similarity index 100% rename from numpy/random/randomgen/src/pcg32/pcg-advance-64.c rename to numpy/random/src/pcg32/pcg-advance-64.c diff --git a/numpy/random/randomgen/src/pcg32/pcg32-test-data-gen.c b/numpy/random/src/pcg32/pcg32-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/pcg32/pcg32-test-data-gen.c rename to numpy/random/src/pcg32/pcg32-test-data-gen.c diff --git a/numpy/random/randomgen/src/pcg32/pcg32.c b/numpy/random/src/pcg32/pcg32.c similarity index 100% rename from numpy/random/randomgen/src/pcg32/pcg32.c rename to numpy/random/src/pcg32/pcg32.c diff --git a/numpy/random/randomgen/src/pcg32/pcg32.h b/numpy/random/src/pcg32/pcg32.h similarity index 100% rename from numpy/random/randomgen/src/pcg32/pcg32.h rename to numpy/random/src/pcg32/pcg32.h diff --git a/numpy/random/randomgen/src/pcg32/pcg_variants.h b/numpy/random/src/pcg32/pcg_variants.h similarity index 100% rename from numpy/random/randomgen/src/pcg32/pcg_variants.h rename to numpy/random/src/pcg32/pcg_variants.h diff --git a/numpy/random/randomgen/src/pcg64/LICENSE.md b/numpy/random/src/pcg64/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/pcg64/LICENSE.md rename to numpy/random/src/pcg64/LICENSE.md diff --git a/numpy/random/randomgen/src/pcg64/pcg64-benchmark.c b/numpy/random/src/pcg64/pcg64-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64-benchmark.c rename to numpy/random/src/pcg64/pcg64-benchmark.c diff --git a/numpy/random/randomgen/src/pcg64/pcg64-test-data-gen.c b/numpy/random/src/pcg64/pcg64-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64-test-data-gen.c rename to numpy/random/src/pcg64/pcg64-test-data-gen.c diff --git a/numpy/random/randomgen/src/pcg64/pcg64.c b/numpy/random/src/pcg64/pcg64.c similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64.c rename to numpy/random/src/pcg64/pcg64.c diff --git a/numpy/random/randomgen/src/pcg64/pcg64.h b/numpy/random/src/pcg64/pcg64.h similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64.h rename to numpy/random/src/pcg64/pcg64.h diff --git a/numpy/random/randomgen/src/pcg64/pcg64.orig.c b/numpy/random/src/pcg64/pcg64.orig.c similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64.orig.c rename to numpy/random/src/pcg64/pcg64.orig.c diff --git a/numpy/random/randomgen/src/pcg64/pcg64.orig.h b/numpy/random/src/pcg64/pcg64.orig.h similarity index 100% rename from numpy/random/randomgen/src/pcg64/pcg64.orig.h rename to numpy/random/src/pcg64/pcg64.orig.h diff --git a/numpy/random/randomgen/src/philox/LICENSE.md b/numpy/random/src/philox/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/philox/LICENSE.md rename to numpy/random/src/philox/LICENSE.md diff --git a/numpy/random/randomgen/src/philox/philox-benchmark.c b/numpy/random/src/philox/philox-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/philox/philox-benchmark.c rename to numpy/random/src/philox/philox-benchmark.c diff --git a/numpy/random/randomgen/src/philox/philox-test-data-gen.c b/numpy/random/src/philox/philox-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/philox/philox-test-data-gen.c rename to numpy/random/src/philox/philox-test-data-gen.c diff --git a/numpy/random/randomgen/src/philox/philox.c b/numpy/random/src/philox/philox.c similarity index 100% rename from numpy/random/randomgen/src/philox/philox.c rename to numpy/random/src/philox/philox.c diff --git a/numpy/random/randomgen/src/philox/philox.h b/numpy/random/src/philox/philox.h similarity index 100% rename from numpy/random/randomgen/src/philox/philox.h rename to numpy/random/src/philox/philox.h diff --git a/numpy/random/randomgen/src/splitmix64/LICENSE.md b/numpy/random/src/splitmix64/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/splitmix64/LICENSE.md rename to numpy/random/src/splitmix64/LICENSE.md diff --git a/numpy/random/randomgen/src/splitmix64/splitmix64.c b/numpy/random/src/splitmix64/splitmix64.c similarity index 100% rename from numpy/random/randomgen/src/splitmix64/splitmix64.c rename to numpy/random/src/splitmix64/splitmix64.c diff --git a/numpy/random/randomgen/src/splitmix64/splitmix64.h b/numpy/random/src/splitmix64/splitmix64.h similarity index 100% rename from numpy/random/randomgen/src/splitmix64/splitmix64.h rename to numpy/random/src/splitmix64/splitmix64.h diff --git a/numpy/random/randomgen/src/splitmix64/splitmix64.orig.c b/numpy/random/src/splitmix64/splitmix64.orig.c similarity index 100% rename from numpy/random/randomgen/src/splitmix64/splitmix64.orig.c rename to numpy/random/src/splitmix64/splitmix64.orig.c diff --git a/numpy/random/randomgen/src/threefry/LICENSE.md b/numpy/random/src/threefry/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/threefry/LICENSE.md rename to numpy/random/src/threefry/LICENSE.md diff --git a/numpy/random/randomgen/src/threefry/threefry-benchmark.c b/numpy/random/src/threefry/threefry-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/threefry/threefry-benchmark.c rename to numpy/random/src/threefry/threefry-benchmark.c diff --git a/numpy/random/randomgen/src/threefry/threefry-orig.c b/numpy/random/src/threefry/threefry-orig.c similarity index 100% rename from numpy/random/randomgen/src/threefry/threefry-orig.c rename to numpy/random/src/threefry/threefry-orig.c diff --git a/numpy/random/randomgen/src/threefry/threefry-test-data-gen.c b/numpy/random/src/threefry/threefry-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/threefry/threefry-test-data-gen.c rename to numpy/random/src/threefry/threefry-test-data-gen.c diff --git a/numpy/random/randomgen/src/threefry/threefry.c b/numpy/random/src/threefry/threefry.c similarity index 100% rename from numpy/random/randomgen/src/threefry/threefry.c rename to numpy/random/src/threefry/threefry.c diff --git a/numpy/random/randomgen/src/threefry/threefry.h b/numpy/random/src/threefry/threefry.h similarity index 100% rename from numpy/random/randomgen/src/threefry/threefry.h rename to numpy/random/src/threefry/threefry.h diff --git a/numpy/random/randomgen/src/threefry32/LICENSE.md b/numpy/random/src/threefry32/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/threefry32/LICENSE.md rename to numpy/random/src/threefry32/LICENSE.md diff --git a/numpy/random/randomgen/src/threefry32/threefry32-test-data-gen.c b/numpy/random/src/threefry32/threefry32-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/threefry32/threefry32-test-data-gen.c rename to numpy/random/src/threefry32/threefry32-test-data-gen.c diff --git a/numpy/random/randomgen/src/threefry32/threefry32.c b/numpy/random/src/threefry32/threefry32.c similarity index 100% rename from numpy/random/randomgen/src/threefry32/threefry32.c rename to numpy/random/src/threefry32/threefry32.c diff --git a/numpy/random/randomgen/src/threefry32/threefry32.h b/numpy/random/src/threefry32/threefry32.h similarity index 100% rename from numpy/random/randomgen/src/threefry32/threefry32.h rename to numpy/random/src/threefry32/threefry32.h diff --git a/numpy/random/randomgen/src/xoroshiro128/LICENSE.md b/numpy/random/src/xoroshiro128/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/LICENSE.md rename to numpy/random/src/xoroshiro128/LICENSE.md diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c b/numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128-benchmark.c rename to numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c b/numpy/random/src/xoroshiro128/xoroshiro128-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128-test-data-gen.c rename to numpy/random/src/xoroshiro128/xoroshiro128-test-data-gen.c diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c b/numpy/random/src/xoroshiro128/xoroshiro128.c similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128.c rename to numpy/random/src/xoroshiro128/xoroshiro128.c diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128.h b/numpy/random/src/xoroshiro128/xoroshiro128.h similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128.h rename to numpy/random/src/xoroshiro128/xoroshiro128.h diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c b/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.c rename to numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c diff --git a/numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h b/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h similarity index 100% rename from numpy/random/randomgen/src/xoroshiro128/xoroshiro128plus.orig.h rename to numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h diff --git a/numpy/random/randomgen/src/xorshift1024/LICENSE.md b/numpy/random/src/xorshift1024/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/LICENSE.md rename to numpy/random/src/xorshift1024/LICENSE.md diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024-benchmark.c b/numpy/random/src/xorshift1024/xorshift1024-benchmark.c similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024-benchmark.c rename to numpy/random/src/xorshift1024/xorshift1024-benchmark.c diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c b/numpy/random/src/xorshift1024/xorshift1024-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024-test-data-gen.c rename to numpy/random/src/xorshift1024/xorshift1024-test-data-gen.c diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024.c b/numpy/random/src/xorshift1024/xorshift1024.c similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024.c rename to numpy/random/src/xorshift1024/xorshift1024.c diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024.h b/numpy/random/src/xorshift1024/xorshift1024.h similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024.h rename to numpy/random/src/xorshift1024/xorshift1024.h diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.c b/numpy/random/src/xorshift1024/xorshift1024.orig.c similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.c rename to numpy/random/src/xorshift1024/xorshift1024.orig.c diff --git a/numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.h b/numpy/random/src/xorshift1024/xorshift1024.orig.h similarity index 100% rename from numpy/random/randomgen/src/xorshift1024/xorshift1024.orig.h rename to numpy/random/src/xorshift1024/xorshift1024.orig.h diff --git a/numpy/random/randomgen/src/xoshiro256starstar/LICENSE.md b/numpy/random/src/xoshiro256starstar/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/LICENSE.md rename to numpy/random/src/xoshiro256starstar/LICENSE.md diff --git a/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c b/numpy/random/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c rename to numpy/random/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c diff --git a/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.c b/numpy/random/src/xoshiro256starstar/xoshiro256starstar.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.c rename to numpy/random/src/xoshiro256starstar/xoshiro256starstar.c diff --git a/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.h b/numpy/random/src/xoshiro256starstar/xoshiro256starstar.h similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.h rename to numpy/random/src/xoshiro256starstar/xoshiro256starstar.h diff --git a/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c b/numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.c rename to numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.c diff --git a/numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h b/numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.h similarity index 100% rename from numpy/random/randomgen/src/xoshiro256starstar/xoshiro256starstar.orig.h rename to numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.h diff --git a/numpy/random/randomgen/src/xoshiro512starstar/LICENSE.md b/numpy/random/src/xoshiro512starstar/LICENSE.md similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/LICENSE.md rename to numpy/random/src/xoshiro512starstar/LICENSE.md diff --git a/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c b/numpy/random/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c rename to numpy/random/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c diff --git a/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.c b/numpy/random/src/xoshiro512starstar/xoshiro512starstar.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.c rename to numpy/random/src/xoshiro512starstar/xoshiro512starstar.c diff --git a/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.h b/numpy/random/src/xoshiro512starstar/xoshiro512starstar.h similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.h rename to numpy/random/src/xoshiro512starstar/xoshiro512starstar.h diff --git a/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c b/numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.c similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.c rename to numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.c diff --git a/numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h b/numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.h similarity index 100% rename from numpy/random/randomgen/src/xoshiro512starstar/xoshiro512starstar.orig.h rename to numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.h diff --git a/numpy/random/randomgen/tests/__init__.py b/numpy/random/tests/data/__init__.py similarity index 100% rename from numpy/random/randomgen/tests/__init__.py rename to numpy/random/tests/data/__init__.py diff --git a/numpy/random/randomgen/tests/data/dSFMT-testset-1.csv b/numpy/random/tests/data/dSFMT-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/dSFMT-testset-1.csv rename to numpy/random/tests/data/dSFMT-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/dSFMT-testset-2.csv b/numpy/random/tests/data/dSFMT-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/dSFMT-testset-2.csv rename to numpy/random/tests/data/dSFMT-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/mt19937-testset-1.csv b/numpy/random/tests/data/mt19937-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/mt19937-testset-1.csv rename to numpy/random/tests/data/mt19937-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/mt19937-testset-2.csv b/numpy/random/tests/data/mt19937-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/mt19937-testset-2.csv rename to numpy/random/tests/data/mt19937-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/pcg32-testset-1.csv b/numpy/random/tests/data/pcg32-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/pcg32-testset-1.csv rename to numpy/random/tests/data/pcg32-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/pcg32-testset-2.csv b/numpy/random/tests/data/pcg32-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/pcg32-testset-2.csv rename to numpy/random/tests/data/pcg32-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/pcg64-testset-1.csv b/numpy/random/tests/data/pcg64-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/pcg64-testset-1.csv rename to numpy/random/tests/data/pcg64-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/pcg64-testset-2.csv b/numpy/random/tests/data/pcg64-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/pcg64-testset-2.csv rename to numpy/random/tests/data/pcg64-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/philox-testset-1.csv b/numpy/random/tests/data/philox-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/philox-testset-1.csv rename to numpy/random/tests/data/philox-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/philox-testset-2.csv b/numpy/random/tests/data/philox-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/philox-testset-2.csv rename to numpy/random/tests/data/philox-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/threefry-testset-1.csv b/numpy/random/tests/data/threefry-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/threefry-testset-1.csv rename to numpy/random/tests/data/threefry-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/threefry-testset-2.csv b/numpy/random/tests/data/threefry-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/threefry-testset-2.csv rename to numpy/random/tests/data/threefry-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/threefry32-testset-1.csv b/numpy/random/tests/data/threefry32-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/threefry32-testset-1.csv rename to numpy/random/tests/data/threefry32-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/threefry32-testset-2.csv b/numpy/random/tests/data/threefry32-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/threefry32-testset-2.csv rename to numpy/random/tests/data/threefry32-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv b/numpy/random/tests/data/xoroshiro128-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoroshiro128-testset-1.csv rename to numpy/random/tests/data/xoroshiro128-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv b/numpy/random/tests/data/xoroshiro128-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoroshiro128-testset-2.csv rename to numpy/random/tests/data/xoroshiro128-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/xorshift1024-testset-1.csv b/numpy/random/tests/data/xorshift1024-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xorshift1024-testset-1.csv rename to numpy/random/tests/data/xorshift1024-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/xorshift1024-testset-2.csv b/numpy/random/tests/data/xorshift1024-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xorshift1024-testset-2.csv rename to numpy/random/tests/data/xorshift1024-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/xoshiro256starstar-testset-1.csv b/numpy/random/tests/data/xoshiro256starstar-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoshiro256starstar-testset-1.csv rename to numpy/random/tests/data/xoshiro256starstar-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/xoshiro256starstar-testset-2.csv b/numpy/random/tests/data/xoshiro256starstar-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoshiro256starstar-testset-2.csv rename to numpy/random/tests/data/xoshiro256starstar-testset-2.csv diff --git a/numpy/random/randomgen/tests/data/xoshiro512starstar-testset-1.csv b/numpy/random/tests/data/xoshiro512starstar-testset-1.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoshiro512starstar-testset-1.csv rename to numpy/random/tests/data/xoshiro512starstar-testset-1.csv diff --git a/numpy/random/randomgen/tests/data/xoshiro512starstar-testset-2.csv b/numpy/random/tests/data/xoshiro512starstar-testset-2.csv similarity index 100% rename from numpy/random/randomgen/tests/data/xoshiro512starstar-testset-2.csv rename to numpy/random/tests/data/xoshiro512starstar-testset-2.csv diff --git a/numpy/random/randomgen/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py similarity index 93% rename from numpy/random/randomgen/tests/test_against_numpy.py rename to numpy/random/tests/test_against_numpy.py index 431c7bd85d24..b930fcbff3ce 100644 --- a/numpy/random/randomgen/tests/test_against_numpy.py +++ b/numpy/random/tests/test_against_numpy.py @@ -5,7 +5,7 @@ import pytest -from numpy.random.randomgen import RandomGenerator, MT19937, generator +from numpy.random import RandomGenerator, MT19937, generator from numpy.random import RandomState @@ -98,12 +98,12 @@ def setup_class(cls): cls.rg = RandomGenerator(cls.brng(*cls.seed)) cls.rs = RandomState(cls.brng(*cls.seed)) cls.nprs = cls.np.RandomState(*cls.seed) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls._set_common_state() @classmethod def _set_common_state(cls): - state = cls.rg.state + state = cls.rg.brng.state st = [[]] * 5 st[0] = 'MT19937' st[1] = state['state']['key'] @@ -125,7 +125,7 @@ def _set_common_state_legacy(cls): def _is_state_common(self): state = self.nprs.get_state() - state2 = self.rg.state + state2 = self.rg.brng.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) @@ -138,10 +138,10 @@ def _is_state_common_legacy(self): assert_allclose(state[4], state2['gauss'], atol=1e-10) def test_common_seed(self): - self.rg.seed(1234) + self.rg.brng.seed(1234) self.nprs.seed(1234) self._is_state_common() - self.rg.seed(23456) + self.rg.brng.seed(23456) self.nprs.seed(23456) self._is_state_common() @@ -149,8 +149,8 @@ def test_numpy_state(self): nprs = np.random.RandomState() nprs.standard_normal(99) state = nprs.get_state() - self.rg.state = state - state2 = self.rg.state + self.rg.brng.state = state + state2 = self.rg.brng.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) @@ -383,7 +383,7 @@ def test_scalar(self): assert_equal(s1.randint(1000), 419) assert_equal(s1.randint(1000), s.randint(1000)) - self.rg.seed(4294967295) + self.rg.brng.seed(4294967295) self.nprs.seed(4294967295) self._is_state_common() @@ -400,26 +400,6 @@ def test_array(self): s = RandomGenerator(MT19937([4294967295])) assert_equal(s.randint(1000), 265) - def test_dir(self): - nprs_d = set(dir(self.nprs)) - rs_d = dir(self.rg) - excluded = {'get_state', 'set_state'} - nprs_d.difference_update(excluded) - assert (len(nprs_d.difference(rs_d)) == 0) - - npmod = dir(numpy.random) - mod = dir(generator) - known_exlcuded = ['__all__', '__cached__', '__path__', 'Tester', - 'info', 'bench', '__RandomState_ctor', 'mtrand', - 'test', '__warningregistry__', '_numpy_tester', - 'division', 'get_state', 'set_state', 'seed', - 'ranf', 'random', 'sample', 'absolute_import', - 'print_function', 'RandomState', 'randomgen', - 'tests', 'Lock'] - mod += known_exlcuded - diff = set(npmod).difference(mod) - assert_equal(len(diff), 0) - # Tests using legacy generator def test_chisquare(self): self._set_common_state_legacy() diff --git a/numpy/random/randomgen/tests/test_direct.py b/numpy/random/tests/test_direct.py similarity index 85% rename from numpy/random/randomgen/tests/test_direct.py rename to numpy/random/tests/test_direct.py index 22fdcd865944..d6042100a859 100644 --- a/numpy/random/randomgen/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -7,10 +7,10 @@ assert_raises import pytest -from ...randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ +from numpy.random import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ Xoshiro512StarStar, RandomState -from ...randomgen.common import interface +from numpy.random.common import interface try: import cffi # noqa: F401 @@ -206,30 +206,30 @@ def test_uniform_float(self): def test_seed_float(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.seed, np.pi) - assert_raises(self.seed_error_type, rs.seed, -np.pi) + assert_raises(self.seed_error_type, rs.brng.seed, np.pi) + assert_raises(self.seed_error_type, rs.brng.seed, -np.pi) def test_seed_float_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) - assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) - assert_raises(ValueError, rs.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, rs.seed, np.array([0, np.pi])) - assert_raises(TypeError, rs.seed, [np.pi]) - assert_raises(TypeError, rs.seed, [0, np.pi]) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([-np.pi])) + assert_raises(ValueError, rs.brng.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.brng.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.brng.seed, [np.pi]) + assert_raises(TypeError, rs.brng.seed, [0, np.pi]) def test_seed_out_of_range(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) - assert_raises(ValueError, rs.seed, -1) + assert_raises(ValueError, rs.brng.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.brng.seed, -1) def test_seed_out_of_range_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.seed, [2 ** (2 * self.bits + 1)]) - assert_raises(ValueError, rs.seed, [-1]) + assert_raises(ValueError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.brng.seed, [-1]) def test_repr(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -412,18 +412,18 @@ def setup_class(cls): def test_seed_float_array(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.seed, np.array([np.pi])) - assert_raises(self.seed_error_type, rs.seed, np.array([-np.pi])) - assert_raises(self.seed_error_type, rs.seed, np.array([np.pi, -np.pi])) - assert_raises(self.seed_error_type, rs.seed, np.array([0, np.pi])) - assert_raises(self.seed_error_type, rs.seed, [np.pi]) - assert_raises(self.seed_error_type, rs.seed, [0, np.pi]) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([-np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi, -np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, np.array([0, np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, [np.pi]) + assert_raises(self.seed_error_type, rs.brng.seed, [0, np.pi]) def test_seed_out_of_range_array(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.seed, + assert_raises(self.seed_error_type, rs.brng.seed, [2 ** (2 * self.bits + 1)]) - assert_raises(self.seed_error_type, rs.seed, [-1]) + assert_raises(self.seed_error_type, rs.brng.seed, [-1]) class TestPhilox(Base): @@ -464,43 +464,45 @@ def setup_class(cls): def test_seed_out_of_range(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.seed, 2 ** (self.bits + 1)) - assert_raises(ValueError, rs.seed, -1) - assert_raises(ValueError, rs.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.brng.seed, 2 ** (self.bits + 1)) + assert_raises(ValueError, rs.brng.seed, -1) + assert_raises(ValueError, rs.brng.seed, 2 ** (2 * self.bits + 1)) def test_seed_out_of_range_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) - assert_raises(ValueError, rs.seed, [-1]) - assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.brng.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.brng.seed, [-1]) + assert_raises(TypeError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.seed, np.pi) - assert_raises(TypeError, rs.seed, -np.pi) + assert_raises(TypeError, rs.brng.seed, np.pi) + assert_raises(TypeError, rs.brng.seed, -np.pi) def test_seed_float_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.seed, np.array([np.pi])) - assert_raises(TypeError, rs.seed, np.array([-np.pi])) - assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, rs.seed, np.array([0, np.pi])) - assert_raises(TypeError, rs.seed, [np.pi]) - assert_raises(TypeError, rs.seed, [0, np.pi]) + brng = rs.brng + assert_raises(TypeError, brng.seed, np.array([np.pi])) + assert_raises(TypeError, brng.seed, np.array([-np.pi])) + assert_raises(TypeError, brng.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, brng.seed, np.array([0, np.pi])) + assert_raises(TypeError, brng.seed, [np.pi]) + assert_raises(TypeError, brng.seed, [0, np.pi]) def test_state_tuple(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) - state = rs.state + brng = rs.brng + state = brng.state desired = rs.randint(2 ** 16) tup = (state['brng'], state['state']['key'], state['state']['pos']) - rs.state = tup + brng.state = tup actual = rs.randint(2 ** 16) assert_equal(actual, desired) tup = tup + (0, 0.0) - rs.state = tup + brng.state = tup actual = rs.randint(2 ** 16) assert_equal(actual, desired) @@ -542,25 +544,25 @@ def test_gauss_inv(self): def test_seed_out_of_range_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.seed, [2 ** (self.bits + 1)]) - assert_raises(ValueError, rs.seed, [-1]) - assert_raises(TypeError, rs.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.brng.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.brng.seed, [-1]) + assert_raises(TypeError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.seed, np.pi) - assert_raises(TypeError, rs.seed, -np.pi) + assert_raises(TypeError, rs.brng.seed, np.pi) + assert_raises(TypeError, rs.brng.seed, -np.pi) def test_seed_float_array(self): # GH #82 rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.seed, np.array([np.pi])) - assert_raises(TypeError, rs.seed, np.array([-np.pi])) - assert_raises(TypeError, rs.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, rs.seed, np.array([0, np.pi])) - assert_raises(TypeError, rs.seed, [np.pi]) - assert_raises(TypeError, rs.seed, [0, np.pi]) + assert_raises(TypeError, rs.brng.seed, np.array([np.pi])) + assert_raises(TypeError, rs.brng.seed, np.array([-np.pi])) + assert_raises(TypeError, rs.brng.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.brng.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.brng.seed, [np.pi]) + assert_raises(TypeError, rs.brng.seed, [0, np.pi]) def test_uniform_float(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -578,9 +580,9 @@ def test_uniform_float(self): def test_buffer_reset(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) rs.random_sample(1) - assert rs.state['buffer_loc'] != 382 - rs.seed(*self.data1['seed']) - assert rs.state['buffer_loc'] == 382 + assert rs.brng.state['buffer_loc'] != 382 + rs.brng.seed(*self.data1['seed']) + assert rs.brng.state['buffer_loc'] == 382 class TestThreeFry32(Base): diff --git a/numpy/random/randomgen/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py similarity index 96% rename from numpy/random/randomgen/tests/test_generator_mt19937.py rename to numpy/random/tests/test_generator_mt19937.py index 10dd8733a8b9..3eda84d84d4f 100644 --- a/numpy/random/randomgen/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -7,7 +7,7 @@ assert_warns, assert_no_warnings, assert_array_equal, assert_array_almost_equal, suppress_warnings) -from ...randomgen import RandomGenerator, MT19937 +from numpy.random import RandomGenerator, MT19937 random = RandomGenerator(MT19937()) @@ -96,21 +96,22 @@ class TestSetState(object): def setup(self): self.seed = 1234567890 self.rg = RandomGenerator(MT19937(self.seed)) - self.state = self.rg.state + self.brng = self.rg.brng + self.state = self.brng.state self.legacy_state = (self.state['brng'], self.state['state']['key'], self.state['state']['pos']) def test_basic(self): old = self.rg.tomaxint(16) - self.rg.state = self.state + self.brng.state = self.state new = self.rg.tomaxint(16) assert_(np.all(old == new)) def test_gaussian_reset(self): # Make sure the cached every-other-Gaussian is reset. old = self.rg.standard_normal(size=3) - self.rg.state = self.state + self.brng.state = self.state new = self.rg.standard_normal(size=3) assert_(np.all(old == new)) @@ -119,9 +120,9 @@ def test_gaussian_reset_in_media_res(self): # cached Gaussian is restored. self.rg.standard_normal() - state = self.rg.state + state = self.brng.state old = self.rg.standard_normal(size=3) - self.rg.state = state + self.brng.state = state new = self.rg.standard_normal(size=3) assert_(np.all(old == new)) @@ -244,7 +245,7 @@ def test_full_range_array(self): def test_in_bounds_fuzz(self): # Don't use fixed seed - random.seed() + random.brng.seed() for dt in self.itype[1:]: for ubnd in [4, 8, 16]: @@ -263,13 +264,13 @@ def test_scalar_array_equiv(self): ubnd = 2 if dt is bool else np.iinfo(dt).max + 1 size = 1000 - random.seed(1234) + random.brng.seed(1234) scalar = self.rfunc(lbnd, ubnd, size=size, dtype=dt) - random.seed(1234) + random.brng.seed(1234) scalar_array = self.rfunc([lbnd], [ubnd], size=size, dtype=dt) - random.seed(1234) + random.brng.seed(1234) array = self.rfunc([lbnd] * size, [ubnd] * size, size=size, dtype=dt) assert_array_equal(scalar, scalar_array) @@ -291,7 +292,7 @@ def test_repeatability(self): 'uint8': '27dd30c4e08a797063dffac2490b0be6'} for dt in self.itype[1:]: - random.seed(1234) + random.brng.seed(1234) # view as little endian for hash if sys.byteorder == 'little': @@ -303,7 +304,7 @@ def test_repeatability(self): assert_(tgt[np.dtype(dt).name] == res) # bools do not depend on endianness - random.seed(1234) + random.brng.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) @@ -316,15 +317,15 @@ def test_repeatability_broadcasting(self): np.bool, bool, np.bool_) else np.iinfo(dt).max + 1 # view as little endian for hash - random.seed(1234) + random.brng.seed(1234) val = self.rfunc(lbnd, ubnd, size=1000, dtype=dt) - random.seed(1234) + random.brng.seed(1234) val_bc = self.rfunc([lbnd] * 1000, ubnd, dtype=dt) assert_array_equal(val, val_bc) - random.seed(1234) + random.brng.seed(1234) val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, dtype=dt) assert_array_equal(val, val_bc) @@ -400,7 +401,7 @@ def setup(self): self.seed = 1234567890 def test_rand(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.rand(3, 2) desired = np.array([[0.61879477158567997, 0.59162362775974664], [0.88868358904449662, 0.89165480011560816], @@ -408,25 +409,25 @@ def test_rand(self): assert_array_almost_equal(actual, desired, decimal=15) def test_rand_singleton(self): - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) actual = random.randn(3, 2) desired = np.array([[-3.472754000610961, -0.108938564229143], [-0.245965753396411, -0.704101550261701], [0.360102487116356, 0.127832101772367]]) assert_array_almost_equal(actual, desired, decimal=15) - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.randn() assert_array_almost_equal(actual, desired[0, 0], decimal=15) def test_randint(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.randint(-99, 99, size=(3, 2)) desired = np.array([[31, 3], [-52, 41], @@ -436,7 +437,7 @@ def test_randint(self): def test_randint_masked(self): # Test masked rejection sampling algorithm to generate array of # uint32 in an interval. - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=True) desired = np.array([[2, 47], @@ -446,7 +447,7 @@ def test_randint_masked(self): def test_randint_lemire_32(self): # Test lemire algorithm to generate array of uint32 in an interval. - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, use_masked=False) desired = np.array([[61, 33], @@ -456,7 +457,7 @@ def test_randint_lemire_32(self): def test_randint_lemire_64(self): # Test lemire algorithm to generate array of uint64 in an interval. - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), dtype=np.uint64, use_masked=False) desired = np.array([[42523252834, 40656066204], @@ -465,7 +466,7 @@ def test_randint_lemire_64(self): assert_array_equal(actual, desired) def test_random_integers(self): - random.seed(self.seed) + random.brng.seed(self.seed) with suppress_warnings() as sup: w = sup.record(DeprecationWarning) actual = random.random_integers(-99, 99, size=(3, 2)) @@ -505,19 +506,19 @@ def test_random_integers_deprecated(self): np.iinfo('l').max, np.iinfo('l').max) def test_random_sample(self): - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) actual = random.random_sample() assert_array_almost_equal(actual, desired[0, 0], decimal=15) def test_random_sample_float(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.random_sample((3, 2)) desired = np.array([[0.6187948, 0.5916236], [0.8886836, 0.8916548], @@ -525,7 +526,7 @@ def test_random_sample_float(self): assert_array_almost_equal(actual, desired, decimal=7) def test_random_sample_float_scalar(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.random_sample(dtype=np.float32) desired = 0.6187948 assert_array_almost_equal(actual, desired, decimal=7) @@ -534,31 +535,31 @@ def test_random_sample_unsupported_type(self): assert_raises(TypeError, random.random_sample, dtype='int32') def test_choice_uniform_replace(self): - random.seed(self.seed) + random.brng.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) + random.brng.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) + random.brng.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) + random.brng.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) + random.brng.seed(self.seed) actual = random.choice(['a', 'b', 'c', 'd'], 4) desired = np.array(['c', 'd', 'c', 'd']) assert_array_equal(actual, desired) @@ -634,7 +635,7 @@ def test_choice_nan_probabilities(self): assert_raises(ValueError, random.choice, a, p=p) def test_bytes(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.bytes(10) desired = b'\x82Ui\x9e\xff\x97+Wf\xa5' assert_equal(actual, desired) @@ -659,7 +660,7 @@ def test_shuffle(self): lambda x: np.asarray([(i, i) for i in x], [("a", object, 1), ("b", np.int32, 1)])]: - random.seed(self.seed) + random.brng.seed(self.seed) alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) random.shuffle(alist) actual = alist @@ -681,19 +682,19 @@ def test_shuffle_masked(self): sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) def test_permutation(self): - random.seed(self.seed) + random.brng.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) + random.brng.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) + random.brng.seed(self.seed) actual = random.beta(.1, .9, size=(3, 2)) desired = np.array( [[1.45341850513746058e-02, 5.31297615662868145e-04], @@ -702,20 +703,20 @@ def test_beta(self): assert_array_almost_equal(actual, desired, decimal=15) def test_binomial(self): - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) actual = random.binomial(100.123, .456) desired = 37 assert_array_equal(actual, desired) def test_chisquare(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.chisquare(50, size=(3, 2)) desired = np.array([[22.2534560369812, 46.9302393710074], [52.9974164611614, 85.3559029505718], @@ -723,7 +724,7 @@ def test_chisquare(self): assert_array_almost_equal(actual, desired, decimal=13) def test_dirichlet(self): - random.seed(self.seed) + random.brng.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) actual = random.dirichlet(alpha, size=(3, 2)) desired = np.array([[[0.444382290764855, 0.555617709235145], @@ -736,7 +737,7 @@ def test_dirichlet(self): bad_alpha = np.array([5.4e-01, -1.0e-16]) assert_raises(ValueError, random.dirichlet, bad_alpha) - random.seed(self.seed) + random.brng.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) actual = random.dirichlet(alpha) assert_array_almost_equal(actual, desired[0, 0], decimal=15) @@ -759,7 +760,7 @@ def test_dirichlet_bad_alpha(self): assert_raises(ValueError, random.dirichlet, alpha) def test_exponential(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.exponential(1.1234, size=(3, 2)) desired = np.array([[5.350682337747634, 1.152307441755771], [3.867015473358779, 1.538765912839396], @@ -771,7 +772,7 @@ def test_exponential_0(self): assert_raises(ValueError, random.exponential, scale=-0.) def test_f(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.f(12, 77, size=(3, 2)) desired = np.array([[0.809498839488467, 2.867222762455471], [0.588036831639353, 1.012185639664636], @@ -779,7 +780,7 @@ def test_f(self): assert_array_almost_equal(actual, desired, decimal=15) def test_gamma(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.gamma(5, 3, size=(3, 2)) desired = np.array([[12.46569350177219, 16.46580642087044], [43.65744473309084, 11.98722785682592], @@ -791,7 +792,7 @@ def test_gamma_0(self): assert_raises(ValueError, random.gamma, shape=-0., scale=-0.) def test_geometric(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.geometric(.123456789, size=(3, 2)) desired = np.array([[8, 7], [17, 17], @@ -809,7 +810,7 @@ def test_geometric_exceptions(self): assert_raises(ValueError, random.geometric, [np.nan] * 10) def test_gumbel(self): - random.seed(self.seed) + random.brng.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], @@ -821,7 +822,7 @@ def test_gumbel_0(self): assert_raises(ValueError, random.gumbel, scale=-0.) def test_hypergeometric(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.hypergeometric(10.1, 5.5, 14, size=(3, 2)) desired = np.array([[10, 10], [10, 10], @@ -847,7 +848,7 @@ def test_hypergeometric(self): assert_array_equal(actual, desired) def test_laplace(self): - random.seed(self.seed) + random.brng.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], @@ -859,7 +860,7 @@ def test_laplace_0(self): assert_raises(ValueError, random.laplace, scale=-0.) def test_logistic(self): - random.seed(self.seed) + random.brng.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], @@ -867,7 +868,7 @@ def test_logistic(self): assert_array_almost_equal(actual, desired, decimal=15) def test_lognormal(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) desired = np.array([[1.0894838661036e-03, 9.0990021488311e-01], [6.9178869932225e-01, 2.7672077560016e-01], @@ -879,7 +880,7 @@ def test_lognormal_0(self): assert_raises(ValueError, random.lognormal, sigma=-0.) def test_logseries(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.logseries(p=.923456789, size=(3, 2)) desired = np.array([[2, 2], [6, 17], @@ -893,7 +894,7 @@ def test_logseries_exceptions(self): assert_raises(ValueError, random.logseries, [np.nan] * 10) def test_multinomial(self): - random.seed(self.seed) + random.brng.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]], @@ -904,7 +905,7 @@ def test_multinomial(self): assert_array_equal(actual, desired) def test_multivariate_normal(self): - random.seed(self.seed) + random.brng.seed(self.seed) mean = (.123456789, 10) cov = [[1, 0], [0, 1]] size = (3, 2) @@ -955,7 +956,7 @@ def test_multivariate_normal(self): mu, np.eye(3)) def test_negative_binomial(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.negative_binomial(n=100, p=.12345, size=(3, 2)) desired = np.array([[521, 736], [665, 690], @@ -970,7 +971,7 @@ def test_negative_binomial_exceptions(self): [np.nan] * 10) def test_noncentral_chisquare(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) desired = np.array([[9.47783251920357, 10.02066178260461], [3.15869984192364, 10.5581565031544], @@ -983,7 +984,7 @@ def test_noncentral_chisquare(self): [1.41985055641800, 0.15451287602753]]) assert_array_almost_equal(actual, desired, decimal=14) - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.noncentral_chisquare(df=5, nonc=0, size=(3, 2)) desired = np.array([[3.64881368071039, 5.48224544747803], [20.41999842025404, 3.44075915187367], @@ -991,7 +992,7 @@ def test_noncentral_chisquare(self): assert_array_almost_equal(actual, desired, decimal=14) def test_noncentral_f(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.noncentral_f(dfnum=5, dfden=2, nonc=1, size=(3, 2)) desired = np.array([[1.22680230963236, 2.56457837623956], @@ -1000,12 +1001,12 @@ def test_noncentral_f(self): assert_array_almost_equal(actual, desired, decimal=14) def test_noncentral_f_nan(self): - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) actual = random.normal(loc=.123456789, scale=2.0, size=(3, 2)) desired = np.array([[-6.822051212221923, -0.094420339458285], [-0.368474717792823, -1.284746311523402], @@ -1017,7 +1018,7 @@ def test_normal_0(self): assert_raises(ValueError, random.normal, scale=-0.) def test_pareto(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.pareto(a=.123456789, size=(3, 2)) desired = np.array([[5.6883528121891552e+16, 4.0569373841667057e+03], [1.2854967019379475e+12, 6.5833156486851483e+04], @@ -1031,7 +1032,7 @@ def test_pareto(self): np.testing.assert_array_almost_equal_nulp(actual, desired, nulp=30) def test_poisson(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.poisson(lam=.123456789, size=(3, 2)) desired = np.array([[0, 0], [1, 0], @@ -1051,7 +1052,7 @@ def test_poisson_exceptions(self): assert_raises(ValueError, random.poisson, [np.nan] * 10) def test_power(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.power(a=.123456789, size=(3, 2)) desired = np.array([[9.328833342693975e-01, 2.742250409261003e-02], [7.684513237993961e-01, 9.297548209160028e-02], @@ -1059,7 +1060,7 @@ def test_power(self): assert_array_almost_equal(actual, desired, decimal=15) def test_rayleigh(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.rayleigh(scale=10, size=(3, 2)) desired = np.array([[13.8882496494248393, 13.383318339044731], [20.95413364294492098, 21.08285015800712614], @@ -1071,7 +1072,7 @@ def test_rayleigh_0(self): assert_raises(ValueError, random.rayleigh, scale=-0.) def test_standard_cauchy(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_cauchy(size=(3, 2)) desired = np.array([[31.87809592667601, 0.349332782046838], [2.816995747731641, 10.552372563459114], @@ -1079,7 +1080,7 @@ def test_standard_cauchy(self): assert_array_almost_equal(actual, desired, decimal=15) def test_standard_exponential(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_exponential(size=(3, 2), method='inv') desired = np.array([[0.96441739162374596, 0.89556604882105506], [2.1953785836319808, 2.22243285392490542], @@ -1090,7 +1091,7 @@ def test_standard_expoential_type_error(self): assert_raises(TypeError, random.standard_exponential, dtype=np.int32) def test_standard_gamma(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_gamma(shape=3, size=(3, 2)) desired = np.array([[2.28483515569645, 3.29899524967824], [11.12492298902645, 2.16784417297277], @@ -1098,13 +1099,13 @@ def test_standard_gamma(self): assert_array_almost_equal(actual, desired, decimal=14) def test_standard_gammma_scalar_float(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_gamma(3, dtype=np.float32) desired = 1.3877466 assert_array_almost_equal(actual, desired, decimal=6) def test_standard_gamma_float(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_gamma(shape=3, size=(3, 2)) desired = np.array([[2.2848352, 3.2989952], [11.124923, 2.1678442], @@ -1113,14 +1114,14 @@ def test_standard_gamma_float(self): def test_standard_gammma_float_out(self): actual = np.zeros((3, 2), dtype=np.float32) - random.seed(self.seed) + random.brng.seed(self.seed) random.standard_gamma(10.0, out=actual, dtype=np.float32) desired = np.array([[6.9824033, 7.3731737], [14.860578, 7.5327270], [11.767487, 6.2320185]], dtype=np.float32) assert_array_almost_equal(actual, desired, decimal=5) - random.seed(self.seed) + random.brng.seed(self.seed) random.standard_gamma(10.0, out=actual, size=(3, 2), dtype=np.float32) assert_array_almost_equal(actual, desired, decimal=5) @@ -1140,7 +1141,7 @@ def test_standard_gamma_0(self): assert_raises(ValueError, random.standard_gamma, shape=-0.) def test_standard_normal(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_normal(size=(3, 2)) desired = np.array([[-3.472754000610961, -0.108938564229143], [-0.245965753396411, -0.704101550261701], @@ -1151,7 +1152,7 @@ def test_standard_normal_unsupported_type(self): assert_raises(TypeError, random.standard_normal, dtype=np.int32) def test_standard_t(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.standard_t(df=10, size=(3, 2)) desired = np.array([[-3.68722108185508, -0.672031186266171], [2.900224996448669, -0.199656996187739], @@ -1159,7 +1160,7 @@ def test_standard_t(self): assert_array_almost_equal(actual, desired, decimal=15) def test_triangular(self): - random.seed(self.seed) + random.brng.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], @@ -1168,7 +1169,7 @@ def test_triangular(self): assert_array_almost_equal(actual, desired, decimal=14) def test_uniform(self): - random.seed(self.seed) + random.brng.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], @@ -1214,7 +1215,7 @@ def __int__(self): assert_raises(TypeError, random.hypergeometric, throwing_int, 1, 1) def test_vonmises(self): - random.seed(self.seed) + random.brng.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], @@ -1223,17 +1224,17 @@ def test_vonmises(self): def test_vonmises_small(self): # check infinite loop, gh-4720 - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) r = random.vonmises(mu=0., kappa=np.nan) assert_(np.isnan(r)) def test_wald(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.wald(mean=1.23, scale=1.54, size=(3, 2)) desired = np.array([[0.10653278160339, 0.98771068102461], [0.89276055317879, 0.13640126419923], @@ -1241,7 +1242,7 @@ def test_wald(self): assert_array_almost_equal(actual, desired, decimal=14) def test_weibull(self): - random.seed(self.seed) + random.brng.seed(self.seed) actual = random.weibull(a=1.23, size=(3, 2)) desired = np.array([[3.557276979846361, 1.020870580998542], [2.731847777612348, 1.29148068905082], @@ -1249,12 +1250,12 @@ def test_weibull(self): assert_array_almost_equal(actual, desired, decimal=15) def test_weibull_0(self): - random.seed(self.seed) + random.brng.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) + random.brng.seed(self.seed) actual = random.zipf(a=1.23, size=(3, 2)) desired = np.array([[66, 29], [1, 1], @@ -1269,7 +1270,7 @@ def setup(self): self.seed = 123456789 def set_seed(self): - random.seed(self.seed) + random.brng.seed(self.seed) def test_uniform(self): low = [0] diff --git a/numpy/random/randomgen/tests/test_generator_mt19937_regressions.py b/numpy/random/tests/test_generator_mt19937_regressions.py similarity index 92% rename from numpy/random/randomgen/tests/test_generator_mt19937_regressions.py rename to numpy/random/tests/test_generator_mt19937_regressions.py index 75064720fb97..f9478ccf6455 100644 --- a/numpy/random/randomgen/tests/test_generator_mt19937_regressions.py +++ b/numpy/random/tests/test_generator_mt19937_regressions.py @@ -3,7 +3,7 @@ from numpy.compat import long import numpy as np import pytest -from ...randomgen import RandomGenerator, MT19937 +from numpy.random import RandomGenerator, MT19937 mt19937 = RandomGenerator(MT19937()) @@ -36,7 +36,7 @@ def test_hypergeometric_range(self): def test_logseries_convergence(self): # Test for ticket #923 N = 1000 - mt19937.seed(0) + mt19937.brng.seed(0) rvsn = mt19937.logseries(0.8, size=N) # these two frequency counts should be close to theoretical # numbers with this large sample @@ -50,9 +50,9 @@ def test_logseries_convergence(self): assert_(freq < 0.23, msg) def test_permutation_longs(self): - mt19937.seed(1234) + mt19937.brng.seed(1234) a = mt19937.permutation(12) - mt19937.seed(1234) + mt19937.brng.seed(1234) b = mt19937.permutation(long(12)) assert_array_equal(a, b) @@ -62,7 +62,7 @@ def test_shuffle_mixed_dimension(self): [(1, 1), (2, 2), (3, 3), None], [1, (2, 2), (3, 3), None], [(1, 1), 2, 3, None]]: - mt19937.seed(12345) + mt19937.brng.seed(12345) shuffled = list(t) mt19937.shuffle(shuffled) assert_array_equal(shuffled, [t[0], t[3], t[1], t[2]]) @@ -72,8 +72,8 @@ def test_call_within_randomstate(self): m = RandomGenerator(MT19937()) # mt19937.RandomState() res = np.array([0, 8, 7, 2, 1, 9, 4, 7, 0, 3]) for i in range(3): - mt19937.seed(i) - m.seed(4321) + mt19937.brng.seed(i) + m.brng.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) @@ -88,7 +88,7 @@ def test_multivariate_normal_size_types(self): 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.seed(1234567890) + mt19937.brng.seed(1234567890) x = mt19937.beta(0.0001, 0.0001, size=100) assert_(not np.any(np.isnan(x)), 'Nans in mt19937.beta') @@ -96,7 +96,7 @@ 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.seed(1234) + mt19937.brng.seed(1234) a = [1, 2, 3] counts = [4, 4, 2] for dt in np.float16, np.float32, np.float64: @@ -110,7 +110,7 @@ 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.seed(1234) + mt19937.brng.seed(1234) a = np.array(['a', 'a' * 1000]) @@ -125,7 +125,7 @@ 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.seed(1234) + mt19937.brng.seed(1234) a = np.array([np.arange(1), np.arange(4)]) for _ in range(1000): @@ -139,7 +139,7 @@ def test_permutation_subclass(self): class N(np.ndarray): pass - mt19937.seed(1) + mt19937.brng.seed(1) orig = np.arange(3).view(N) perm = mt19937.permutation(orig) assert_array_equal(perm, np.array([0, 2, 1])) @@ -151,7 +151,7 @@ class M(object): def __array__(self): return self.a - mt19937.seed(1) + mt19937.brng.seed(1) m = M() perm = mt19937.permutation(m) assert_array_equal(perm, np.array([2, 1, 4, 0, 3])) diff --git a/numpy/random/randomgen/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py similarity index 99% rename from numpy/random/randomgen/tests/test_randomstate.py rename to numpy/random/tests/test_randomstate.py index 6adde6c2ab33..d0ad5e794fa8 100644 --- a/numpy/random/randomgen/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -9,7 +9,7 @@ suppress_warnings ) -from ...randomgen import MT19937, Xoshiro256StarStar, mtrand as random +from numpy.random import MT19937, Xoshiro256StarStar, mtrand as random def assert_mt19937_state_equal(a, b): diff --git a/numpy/random/randomgen/tests/test_randomstate_regression.py b/numpy/random/tests/test_randomstate_regression.py similarity index 99% rename from numpy/random/randomgen/tests/test_randomstate_regression.py rename to numpy/random/tests/test_randomstate_regression.py index cf21ee756b87..9c319319e485 100644 --- a/numpy/random/randomgen/tests/test_randomstate_regression.py +++ b/numpy/random/tests/test_randomstate_regression.py @@ -5,7 +5,7 @@ from numpy.compat import long import numpy as np -from ...randomgen import mtrand as random +from numpy.random import mtrand as random class TestRegression(object): diff --git a/numpy/random/randomgen/tests/test_smoke.py b/numpy/random/tests/test_smoke.py similarity index 86% rename from numpy/random/randomgen/tests/test_smoke.py rename to numpy/random/tests/test_smoke.py index 816ce6ddcd76..fa7a0b567ad1 100644 --- a/numpy/random/randomgen/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -8,7 +8,7 @@ import pytest from numpy.testing import (assert_almost_equal, assert_equal, assert_, assert_array_equal, suppress_warnings) -from ...randomgen import (RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, +from numpy.random import (RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, Xoshiro512StarStar, entropy) @@ -106,7 +106,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -118,39 +118,39 @@ def _extra_setup(cls): cls.seed_error = TypeError def _reset_state(self): - self.rg.state = self.initial_state + self.rg.brng.state = self.initial_state def test_init(self): rg = RandomGenerator(self.brng()) - state = rg.state + state = rg.brng.state rg.standard_normal(1) rg.standard_normal(1) - rg.state = state - new_state = rg.state + rg.brng.state = state + new_state = rg.brng.state assert_(comp_state(state, new_state)) def test_advance(self): - state = self.rg.state - if hasattr(self.rg._basicrng, 'advance'): - self.rg._basicrng.advance(self.advance) - assert_(not comp_state(state, self.rg.state)) + state = self.rg.brng.state + if hasattr(self.rg.brng, 'advance'): + self.rg.brng.advance(self.advance) + assert_(not comp_state(state, self.rg.brng.state)) else: - brng_name = self.rg._basicrng.__class__.__name__ + brng_name = self.rg.brng.__class__.__name__ pytest.skip('Advance is not supported by {0}'.format(brng_name)) def test_jump(self): - state = self.rg.state - if hasattr(self.rg._basicrng, 'jump'): - self.rg._basicrng.jump() - jumped_state = self.rg.state + state = self.rg.brng.state + if hasattr(self.rg.brng, 'jump'): + self.rg.brng.jump() + jumped_state = self.rg.brng.state assert_(not comp_state(state, jumped_state)) self.rg.random_sample(2 * 3 * 5 * 7 * 11 * 13 * 17) - self.rg.state = state - self.rg._basicrng.jump() - rejumped_state = self.rg.state + self.rg.brng.state = state + self.rg.brng.jump() + rejumped_state = self.rg.brng.state assert_(comp_state(jumped_state, rejumped_state)) else: - brng_name = self.rg._basicrng.__class__.__name__ + brng_name = self.rg.brng.__class__.__name__ pytest.skip('Jump is not supported by {0}'.format(brng_name)) def test_uniform(self): @@ -221,51 +221,51 @@ def test_binomial(self): assert_(self.rg.binomial(1000, .5) >= 0) def test_reset_state(self): - state = self.rg.state + state = self.rg.brng.state int_1 = self.rg.randint(2**31) - self.rg.state = state + self.rg.brng.state = state int_2 = self.rg.randint(2**31) assert_(int_1 == int_2) def test_entropy_init(self): rg = RandomGenerator(self.brng()) rg2 = RandomGenerator(self.brng()) - assert_(not comp_state(rg.state, rg2.state)) + assert_(not comp_state(rg.brng.state, rg2.brng.state)) def test_seed(self): rg = RandomGenerator(self.brng(*self.seed)) rg2 = RandomGenerator(self.brng(*self.seed)) rg.random_sample() rg2.random_sample() - assert_(comp_state(rg.state, rg2.state)) + assert_(comp_state(rg.brng.state, rg2.brng.state)) def test_reset_state_gauss(self): rg = RandomGenerator(self.brng(*self.seed)) rg.standard_normal() - state = rg.state + state = rg.brng.state n1 = rg.standard_normal(size=10) rg2 = RandomGenerator(self.brng()) - rg2.state = state + rg2.brng.state = state n2 = rg2.standard_normal(size=10) assert_array_equal(n1, n2) def test_reset_state_uint32(self): rg = RandomGenerator(self.brng(*self.seed)) rg.randint(0, 2 ** 24, 120, dtype=np.uint32) - state = rg.state + state = rg.brng.state n1 = rg.randint(0, 2 ** 24, 10, dtype=np.uint32) rg2 = RandomGenerator(self.brng()) - rg2.state = state + rg2.brng.state = state n2 = rg2.randint(0, 2 ** 24, 10, dtype=np.uint32) assert_array_equal(n1, n2) def test_reset_state_float(self): rg = RandomGenerator(self.brng(*self.seed)) rg.random_sample(dtype='float32') - state = rg.state + state = rg.brng.state n1 = rg.random_sample(size=10, dtype='float32') rg2 = RandomGenerator(self.brng()) - rg2.state = state + rg2.brng.state = state n2 = rg2.random_sample(size=10, dtype='float32') assert_((n1 == n2).all()) @@ -354,29 +354,29 @@ def test_negative_binomial(self): assert_(len(vals) == 10) def test_rand(self): - state = self.rg.state + state = self.rg.brng.state vals = self.rg.rand(10, 10, 10) - self.rg.state = state + self.rg.brng.state = state assert_((vals == self.rg.random_sample((10, 10, 10))).all()) assert_(vals.shape == (10, 10, 10)) vals = self.rg.rand(10, 10, 10, dtype=np.float32) assert_(vals.shape == (10, 10, 10)) def test_randn(self): - state = self.rg.state + state = self.rg.brng.state vals = self.rg.randn(10, 10, 10) - self.rg.state = state + self.rg.brng.state = state assert_equal(vals, self.rg.standard_normal((10, 10, 10))) assert_equal(vals.shape, (10, 10, 10)) - state = self.rg.state + state = self.rg.brng.state vals = self.rg.randn(10, 10, 10) - self.rg.state = state + self.rg.brng.state = state assert_equal(vals, self.rg.standard_normal((10, 10, 10))) - state = self.rg.state + state = self.rg.brng.state self.rg.randn(10, 10, 10) - self.rg.state = state + self.rg.brng.state = state vals = self.rg.randn(10, 10, 10, dtype=np.float32) assert_(vals.shape == (10, 10, 10)) @@ -487,12 +487,12 @@ def test_pickle(self): pick = pickle.dumps(self.rg) unpick = pickle.loads(pick) assert_((type(self.rg) == type(unpick))) - assert_(comp_state(self.rg.state, unpick.state)) + assert_(comp_state(self.rg.brng.state, unpick.brng.state)) pick = pickle.dumps(self.rg) unpick = pickle.loads(pick) assert_((type(self.rg) == type(unpick))) - assert_(comp_state(self.rg.state, unpick.state)) + assert_(comp_state(self.rg.brng.state, unpick.brng.state)) def test_seed_array(self): if self.seed_vector_bits is None: @@ -505,32 +505,32 @@ def test_seed_array(self): else: dtype = np.uint64 seed = np.array([1], dtype=dtype) - self.rg.seed(seed) - state1 = self.rg.state - self.rg.seed(1) - state2 = self.rg.state + self.rg.brng.seed(seed) + state1 = self.rg.brng.state + self.rg.brng.seed(1) + state2 = self.rg.brng.state assert_(comp_state(state1, state2)) seed = np.arange(4, dtype=dtype) - self.rg.seed(seed) - state1 = self.rg.state - self.rg.seed(seed[0]) - state2 = self.rg.state + self.rg.brng.seed(seed) + state1 = self.rg.brng.state + self.rg.brng.seed(seed[0]) + state2 = self.rg.brng.state assert_(not comp_state(state1, state2)) seed = np.arange(1500, dtype=dtype) - self.rg.seed(seed) - state1 = self.rg.state - self.rg.seed(seed[0]) - state2 = self.rg.state + self.rg.brng.seed(seed) + state1 = self.rg.brng.state + self.rg.brng.seed(seed[0]) + state2 = self.rg.brng.state assert_(not comp_state(state1, state2)) seed = 2 ** np.mod(np.arange(1500, dtype=dtype), self.seed_vector_bits - 1) + 1 - self.rg.seed(seed) - state1 = self.rg.state - self.rg.seed(seed[0]) - state2 = self.rg.state + self.rg.brng.seed(seed) + state1 = self.rg.brng.state + self.rg.brng.seed(seed[0]) + state2 = self.rg.brng.state assert_(not comp_state(state1, state2)) def test_seed_array_error(self): @@ -541,164 +541,164 @@ def test_seed_array_error(self): seed = -1 with pytest.raises(ValueError): - self.rg.seed(seed) + self.rg.brng.seed(seed) seed = np.array([-1], dtype=np.int32) with pytest.raises(ValueError): - self.rg.seed(seed) + self.rg.brng.seed(seed) seed = np.array([1, 2, 3, -5], dtype=np.int32) with pytest.raises(ValueError): - self.rg.seed(seed) + self.rg.brng.seed(seed) seed = np.array([1, 2, 3, out_of_bounds]) with pytest.raises(ValueError): - self.rg.seed(seed) + self.rg.brng.seed(seed) def test_uniform_float(self): rg = RandomGenerator(self.brng(12345)) warmup(rg) - state = rg.state + state = rg.brng.state r1 = rg.random_sample(11, dtype=np.float32) rg2 = RandomGenerator(self.brng()) warmup(rg2) - rg2.state = state + rg2.brng.state = state r2 = rg2.random_sample(11, dtype=np.float32) assert_array_equal(r1, r2) assert_equal(r1.dtype, np.float32) - assert_(comp_state(rg.state, rg2.state)) + assert_(comp_state(rg.brng.state, rg2.brng.state)) def test_gamma_floats(self): rg = RandomGenerator(self.brng()) warmup(rg) - state = rg.state + state = rg.brng.state r1 = rg.standard_gamma(4.0, 11, dtype=np.float32) rg2 = RandomGenerator(self.brng()) warmup(rg2) - rg2.state = state + rg2.brng.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.state, rg2.state)) + assert_(comp_state(rg.brng.state, rg2.brng.state)) def test_normal_floats(self): rg = RandomGenerator(self.brng()) warmup(rg) - state = rg.state + state = rg.brng.state r1 = rg.standard_normal(11, dtype=np.float32) rg2 = RandomGenerator(self.brng()) warmup(rg2) - rg2.state = state + rg2.brng.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.state, rg2.state)) + assert_(comp_state(rg.brng.state, rg2.brng.state)) def test_normal_zig_floats(self): rg = RandomGenerator(self.brng()) warmup(rg) - state = rg.state + state = rg.brng.state r1 = rg.standard_normal(11, dtype=np.float32) rg2 = RandomGenerator(self.brng()) warmup(rg2) - rg2.state = state + rg2.brng.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.state, rg2.state)) + assert_(comp_state(rg.brng.state, rg2.brng.state)) def test_output_fill(self): rg = self.rg - state = rg.state + state = rg.brng.state size = (31, 7, 97) existing = np.empty(size) - rg.state = state + rg.brng.state = state rg.standard_normal(out=existing) - rg.state = state + rg.brng.state = state direct = rg.standard_normal(size=size) assert_equal(direct, existing) sized = np.empty(size) - rg.state = state + rg.brng.state = state rg.standard_normal(out=sized, size=sized.shape) existing = np.empty(size, dtype=np.float32) - rg.state = state + rg.brng.state = state rg.standard_normal(out=existing, dtype=np.float32) - rg.state = state + rg.brng.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.state + state = rg.brng.state size = (31, 7, 97) existing = np.empty(size) - rg.state = state + rg.brng.state = state rg.random_sample(out=existing) - rg.state = state + rg.brng.state = state direct = rg.random_sample(size=size) assert_equal(direct, existing) existing = np.empty(size, dtype=np.float32) - rg.state = state + rg.brng.state = state rg.random_sample(out=existing, dtype=np.float32) - rg.state = state + rg.brng.state = state direct = rg.random_sample(size=size, dtype=np.float32) assert_equal(direct, existing) def test_output_filling_exponential(self): rg = self.rg - state = rg.state + state = rg.brng.state size = (31, 7, 97) existing = np.empty(size) - rg.state = state + rg.brng.state = state rg.standard_exponential(out=existing) - rg.state = state + rg.brng.state = state direct = rg.standard_exponential(size=size) assert_equal(direct, existing) existing = np.empty(size, dtype=np.float32) - rg.state = state + rg.brng.state = state rg.standard_exponential(out=existing, dtype=np.float32) - rg.state = state + rg.brng.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.state + state = rg.brng.state size = (31, 7, 97) existing = np.zeros(size) - rg.state = state + rg.brng.state = state rg.standard_gamma(1.0, out=existing) - rg.state = state + rg.brng.state = state direct = rg.standard_gamma(1.0, size=size) assert_equal(direct, existing) existing = np.zeros(size, dtype=np.float32) - rg.state = state + rg.brng.state = state rg.standard_gamma(1.0, out=existing, dtype=np.float32) - rg.state = state + rg.brng.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.state + state = rg.brng.state size = (31, 7, 97) mu = np.arange(97.0) + 1.0 existing = np.zeros(size) - rg.state = state + rg.brng.state = state rg.standard_gamma(mu, out=existing) - rg.state = state + rg.brng.state = state direct = rg.standard_gamma(mu, size=size) assert_equal(direct, existing) existing = np.zeros(size, dtype=np.float32) - rg.state = state + rg.brng.state = state rg.standard_gamma(mu, out=existing, dtype=np.float32) - rg.state = state + rg.brng.state = state direct = rg.standard_gamma(mu, size=size, dtype=np.float32) assert_equal(direct, existing) @@ -796,7 +796,7 @@ def setup_class(cls): cls.advance = None cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 32 cls._extra_setup() cls.seed_error = ValueError @@ -805,8 +805,8 @@ def test_numpy_state(self): nprg = np.random.RandomState() nprg.standard_normal(99) state = nprg.get_state() - self.rg.state = state - state2 = self.rg.state + self.rg.brng.state = state + state2 = self.rg.brng.state assert_((state[1] == state2['state']['key']).all()) assert_((state[2] == state2['state']['pos'])) @@ -819,7 +819,7 @@ def setup_class(cls): cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = None cls._extra_setup() @@ -832,20 +832,20 @@ def test_seed_array_error(self): seed = -1 with pytest.raises(ValueError): - self.rg.seed(seed) + self.rg.brng.seed(seed) error_type = ValueError if self.seed_vector_bits else TypeError seed = np.array([-1], dtype=np.int32) with pytest.raises(error_type): - self.rg.seed(seed) + self.rg.brng.seed(seed) seed = np.array([1, 2, 3, -5], dtype=np.int32) with pytest.raises(error_type): - self.rg.seed(seed) + self.rg.brng.seed(seed) seed = np.array([1, 2, 3, out_of_bounds]) with pytest.raises(error_type): - self.rg.seed(seed) + self.rg.brng.seed(seed) class TestPhilox(RNG): @@ -855,7 +855,7 @@ def setup_class(cls): cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -867,7 +867,7 @@ def setup_class(cls): cls.advance = 2 ** 63 + 2 ** 31 + 2 ** 15 + 1 cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -879,7 +879,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -891,7 +891,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -903,7 +903,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -915,7 +915,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -927,7 +927,7 @@ def setup_class(cls): cls.advance = None cls.seed = [12345] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls._extra_setup() cls.seed_vector_bits = 32 @@ -939,7 +939,7 @@ def setup_class(cls): cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = 64 cls._extra_setup() cls.seed_error = ValueError @@ -972,6 +972,6 @@ def setup_class(cls): cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.state + cls.initial_state = cls.rg.brng.state cls.seed_vector_bits = None cls._extra_setup() diff --git a/numpy/random/randomgen/threefry.pyx b/numpy/random/threefry.pyx similarity index 100% rename from numpy/random/randomgen/threefry.pyx rename to numpy/random/threefry.pyx diff --git a/numpy/random/randomgen/threefry32.pyx b/numpy/random/threefry32.pyx similarity index 100% rename from numpy/random/randomgen/threefry32.pyx rename to numpy/random/threefry32.pyx diff --git a/numpy/random/randomgen/xoroshiro128.pyx b/numpy/random/xoroshiro128.pyx similarity index 100% rename from numpy/random/randomgen/xoroshiro128.pyx rename to numpy/random/xoroshiro128.pyx diff --git a/numpy/random/randomgen/xorshift1024.pyx b/numpy/random/xorshift1024.pyx similarity index 100% rename from numpy/random/randomgen/xorshift1024.pyx rename to numpy/random/xorshift1024.pyx diff --git a/numpy/random/randomgen/xoshiro256starstar.pyx b/numpy/random/xoshiro256starstar.pyx similarity index 100% rename from numpy/random/randomgen/xoshiro256starstar.pyx rename to numpy/random/xoshiro256starstar.pyx diff --git a/numpy/random/randomgen/xoshiro512starstar.pyx b/numpy/random/xoshiro512starstar.pyx similarity index 100% rename from numpy/random/randomgen/xoshiro512starstar.pyx rename to numpy/random/xoshiro512starstar.pyx diff --git a/setup.py b/setup.py index d7fa3f544c5e..6680e3b6a0bc 100755 --- a/setup.py +++ b/setup.py @@ -225,10 +225,10 @@ def run(self): def generate_cython(): cwd = os.path.abspath(os.path.dirname(__file__)) print("Cythonizing sources") - for d in ('mtrand', 'randomgen', 'randomgen/legacy'): + for d in ('random/_mtrand', 'random'): p = subprocess.call([sys.executable, os.path.join(cwd, 'tools', 'cythonize.py'), - 'numpy/random/{0}'.format(d)], + 'numpy/{0}'.format(d)], cwd=cwd) if p != 0: raise RuntimeError("Running cythonize failed!") From 9578dcfbe744854312690ea79063e50d67fc88a2 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 12 Apr 2019 10:27:33 +0300 Subject: [PATCH 106/138] BUG: __dealloc__ can be called without __init__ in some error modes skip doctests that require scipy move original mtrand module to _mtrand adjust documentation for namespace change --- .gitignore | 2 +- benchmarks/benchmarks/bench_random.py | 7 +- .../{randomgen => random}/brng/dsfmt.rst | 4 +- .../{randomgen => random}/brng/index.rst | 4 +- .../{randomgen => random}/brng/mt19937.rst | 4 +- .../{randomgen => random}/brng/pcg32.rst | 4 +- .../{randomgen => random}/brng/pcg64.rst | 4 +- .../{randomgen => random}/brng/philox.rst | 4 +- .../{randomgen => random}/brng/threefry.rst | 4 +- .../{randomgen => random}/brng/threefry32.rst | 4 +- .../brng/xoroshiro128.rst | 4 +- .../brng/xorshift1024.rst | 4 +- .../brng/xoshiro256starstar.rst | 4 +- .../brng/xoshiro512starstar.rst | 4 +- .../{randomgen => random}/change-log.rst | 12 +-- .../{randomgen => random}/entropy.rst | 2 +- .../{randomgen => random}/extending.rst | 18 ++-- .../{randomgen => random}/generator.rst | 4 +- .../reference/{randomgen => random}/index.rst | 87 +++++++++---------- .../{randomgen => random}/legacy.rst | 14 +-- .../{randomgen => random}/multithreading.rst | 2 +- .../new-or-different.rst | 55 ++++++------ .../{randomgen => random}/parallel.rst | 26 +++--- .../{randomgen => random}/performance.py | 0 .../{randomgen => random}/performance.rst | 16 ++-- .../{randomgen => random}/references.rst | 0 doc/source/reference/routines.rst | 2 +- .../_mtrand/{mtrand.pyx => _mtrand.pyx} | 4 +- numpy/random/dsfmt.pyx | 20 +++-- numpy/random/generator.pyx | 51 ++++++----- numpy/random/mt19937.pyx | 18 ++-- numpy/random/mtrand.pyx | 44 +++++----- numpy/random/pcg32.pyx | 16 ++-- numpy/random/pcg64.pyx | 16 ++-- numpy/random/philox.pyx | 24 ++--- numpy/random/setup.py | 2 +- numpy/random/threefry.pyx | 22 +++-- numpy/random/threefry32.pyx | 22 +++-- numpy/random/xoroshiro128.pyx | 18 ++-- numpy/random/xorshift1024.pyx | 20 +++-- numpy/random/xoshiro256starstar.pyx | 18 ++-- numpy/random/xoshiro512starstar.pyx | 18 ++-- 42 files changed, 326 insertions(+), 282 deletions(-) rename doc/source/reference/{randomgen => random}/brng/dsfmt.rst (85%) rename doc/source/reference/{randomgen => random}/brng/index.rst (91%) rename doc/source/reference/{randomgen => random}/brng/mt19937.rst (84%) rename doc/source/reference/{randomgen => random}/brng/pcg32.rst (86%) rename doc/source/reference/{randomgen => random}/brng/pcg64.rst (86%) rename doc/source/reference/{randomgen => random}/brng/philox.rst (85%) rename doc/source/reference/{randomgen => random}/brng/threefry.rst (85%) rename doc/source/reference/{randomgen => random}/brng/threefry32.rst (85%) rename doc/source/reference/{randomgen => random}/brng/xoroshiro128.rst (83%) rename doc/source/reference/{randomgen => random}/brng/xorshift1024.rst (83%) rename doc/source/reference/{randomgen => random}/brng/xoshiro256starstar.rst (83%) rename doc/source/reference/{randomgen => random}/brng/xoshiro512starstar.rst (83%) rename doc/source/reference/{randomgen => random}/change-log.rst (77%) rename doc/source/reference/{randomgen => random}/entropy.rst (60%) rename doc/source/reference/{randomgen => random}/extending.rst (91%) rename doc/source/reference/{randomgen => random}/generator.rst (96%) rename doc/source/reference/{randomgen => random}/index.rst (67%) rename doc/source/reference/{randomgen => random}/legacy.rst (87%) rename doc/source/reference/{randomgen => random}/multithreading.rst (98%) rename doc/source/reference/{randomgen => random}/new-or-different.rst (51%) rename doc/source/reference/{randomgen => random}/parallel.rst (88%) rename doc/source/reference/{randomgen => random}/performance.py (100%) rename doc/source/reference/{randomgen => random}/performance.rst (85%) rename doc/source/reference/{randomgen => random}/references.rst (100%) rename numpy/random/_mtrand/{mtrand.pyx => _mtrand.pyx} (99%) diff --git a/.gitignore b/.gitignore index 485f379578cd..ec0430dfef8d 100644 --- a/.gitignore +++ b/.gitignore @@ -175,7 +175,7 @@ benchmarks/env benchmarks/numpy # cythonized files cythonize.dat -numpy/random/mtrand/mtrand.c +numpy/random/_mtrand/_mtrand.c numpy/random/*.c numpy/random/legacy/*.c numpy/random/_mtrand/randint_helpers.pxi diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index 38a079e84d6c..3589c65a387f 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -4,8 +4,7 @@ import numpy as np -from numpy.random import RandomState -from numpy.random.randomgen import RandomGenerator +from numpy.random import RandomState, RandomGenerator class Random(Benchmark): params = ['normal', 'uniform', 'weibull 1', 'binomial 10 0.5', @@ -95,7 +94,7 @@ def setup(self, brng): if brng == 'numpy': self.rg = np.random.RandomState() else: - self.rg = RandomGenerator(getattr(np.random.randomgen, brng)()) + self.rg = RandomGenerator(getattr(np.random, brng)()) self.rg.random_sample() self.int32info = np.iinfo(np.int32) self.uint32info = np.iinfo(np.uint32) @@ -149,7 +148,7 @@ def setup(self, brng, args): if brng == 'numpy': self.rg = np.random.RandomState() else: - self.rg = RandomGenerator(getattr(np.random.randomgen, brng)()) + self.rg = RandomGenerator(getattr(np.random, brng)()) self.rg.random_sample() def time_bounded(self, brng, args): diff --git a/doc/source/reference/randomgen/brng/dsfmt.rst b/doc/source/reference/random/brng/dsfmt.rst similarity index 85% rename from doc/source/reference/randomgen/brng/dsfmt.rst rename to doc/source/reference/random/brng/dsfmt.rst index f9de48d61dcf..a47586a50f5f 100644 --- a/doc/source/reference/randomgen/brng/dsfmt.rst +++ b/doc/source/reference/random/brng/dsfmt.rst @@ -1,9 +1,9 @@ Double SIMD Mersenne Twister (dSFMT) ------------------------------------ -.. module:: numpy.random.randomgen.dsfmt +.. module:: numpy.random.dsfmt -.. currentmodule:: numpy.random.randomgen.dsfmt +.. currentmodule:: numpy.random.dsfmt .. autoclass:: DSFMT diff --git a/doc/source/reference/randomgen/brng/index.rst b/doc/source/reference/random/brng/index.rst similarity index 91% rename from doc/source/reference/randomgen/brng/index.rst rename to doc/source/reference/random/brng/index.rst index aceecc792a6c..5241f9856911 100644 --- a/doc/source/reference/randomgen/brng/index.rst +++ b/doc/source/reference/random/brng/index.rst @@ -1,7 +1,9 @@ Basic Random Number Generators ------------------------------ -The random values produced by :class:`~randomgen.generator.RandomGenerator` +.. currentmodule:: numpy.random + +The random values produced by :class:`~RandomGenerator` are produced by a basic RNG. These basic RNGs do not directly provide random numbers and only contains methods used for seeding, getting or setting the state, jumping or advancing the state, and for accessing diff --git a/doc/source/reference/randomgen/brng/mt19937.rst b/doc/source/reference/random/brng/mt19937.rst similarity index 84% rename from doc/source/reference/randomgen/brng/mt19937.rst rename to doc/source/reference/random/brng/mt19937.rst index 7739e16ce1b5..1bd3597c8a0c 100644 --- a/doc/source/reference/randomgen/brng/mt19937.rst +++ b/doc/source/reference/random/brng/mt19937.rst @@ -1,9 +1,9 @@ Mersenne Twister (MT19937) -------------------------- -.. module:: numpy.random.randomgen.mt19937 +.. module:: numpy.random.mt19937 -.. currentmodule:: numpy.random.randomgen.mt19937 +.. currentmodule:: numpy.random.mt19937 .. autoclass:: MT19937 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/pcg32.rst b/doc/source/reference/random/brng/pcg32.rst similarity index 86% rename from doc/source/reference/randomgen/brng/pcg32.rst rename to doc/source/reference/random/brng/pcg32.rst index aaf3929e87b3..f079f5a8cb17 100644 --- a/doc/source/reference/randomgen/brng/pcg32.rst +++ b/doc/source/reference/random/brng/pcg32.rst @@ -1,9 +1,9 @@ Parallel Congruent Generator (32-bit, PCG32) -------------------------------------------- -.. module:: numpy.random.randomgen.pcg32 +.. module:: numpy.random.pcg32 -.. currentmodule:: numpy.random.randomgen.pcg32 +.. currentmodule:: numpy.random.pcg32 .. autoclass:: PCG32 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/pcg64.rst b/doc/source/reference/random/brng/pcg64.rst similarity index 86% rename from doc/source/reference/randomgen/brng/pcg64.rst rename to doc/source/reference/random/brng/pcg64.rst index 94e73e491910..93f026fcb4ed 100644 --- a/doc/source/reference/randomgen/brng/pcg64.rst +++ b/doc/source/reference/random/brng/pcg64.rst @@ -1,9 +1,9 @@ Parallel Congruent Generator (64-bit, PCG64) -------------------------------------------- -.. module:: numpy.random.randomgen.pcg64 +.. module:: numpy.random.pcg64 -.. currentmodule:: numpy.random.randomgen.pcg64 +.. currentmodule:: numpy.random.pcg64 .. autoclass:: PCG64 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/philox.rst b/doc/source/reference/random/brng/philox.rst similarity index 85% rename from doc/source/reference/randomgen/brng/philox.rst rename to doc/source/reference/random/brng/philox.rst index 091c4d3e0e8e..c1e047c5466d 100644 --- a/doc/source/reference/randomgen/brng/philox.rst +++ b/doc/source/reference/random/brng/philox.rst @@ -1,9 +1,9 @@ Philox Counter-based RNG ------------------------ -.. module:: numpy.random.randomgen.philox +.. module:: numpy.random.philox -.. currentmodule:: numpy.random.randomgen.philox +.. currentmodule:: numpy.random.philox .. autoclass:: Philox :exclude-members: diff --git a/doc/source/reference/randomgen/brng/threefry.rst b/doc/source/reference/random/brng/threefry.rst similarity index 85% rename from doc/source/reference/randomgen/brng/threefry.rst rename to doc/source/reference/random/brng/threefry.rst index 4f5c56bae866..eefe16ea0937 100644 --- a/doc/source/reference/randomgen/brng/threefry.rst +++ b/doc/source/reference/random/brng/threefry.rst @@ -1,9 +1,9 @@ ThreeFry Counter-based RNG -------------------------- -.. module:: numpy.random.randomgen.threefry +.. module:: numpy.random.threefry -.. currentmodule:: numpy.random.randomgen.threefry +.. currentmodule:: numpy.random.threefry .. autoclass:: ThreeFry :exclude-members: diff --git a/doc/source/reference/randomgen/brng/threefry32.rst b/doc/source/reference/random/brng/threefry32.rst similarity index 85% rename from doc/source/reference/randomgen/brng/threefry32.rst rename to doc/source/reference/random/brng/threefry32.rst index bd85db4a7141..f0d3dc281005 100644 --- a/doc/source/reference/randomgen/brng/threefry32.rst +++ b/doc/source/reference/random/brng/threefry32.rst @@ -1,9 +1,9 @@ ThreeFry32 Counter-based RNG ---------------------------- -.. module:: numpy.random.randomgen.threefry32 +.. module:: numpy.random.threefry32 -.. currentmodule:: numpy.random.randomgen.threefry32 +.. currentmodule:: numpy.random.threefry32 .. autoclass:: ThreeFry32 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/xoroshiro128.rst b/doc/source/reference/random/brng/xoroshiro128.rst similarity index 83% rename from doc/source/reference/randomgen/brng/xoroshiro128.rst rename to doc/source/reference/random/brng/xoroshiro128.rst index 6796c44577c0..590552236c26 100644 --- a/doc/source/reference/randomgen/brng/xoroshiro128.rst +++ b/doc/source/reference/random/brng/xoroshiro128.rst @@ -1,9 +1,9 @@ Xoroshiro128+ ------------- -.. module:: numpy.random.randomgen.xoroshiro128 +.. module:: numpy.random.xoroshiro128 -.. currentmodule:: numpy.random.randomgen.xoroshiro128 +.. currentmodule:: numpy.random.xoroshiro128 .. autoclass:: Xoroshiro128 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/xorshift1024.rst b/doc/source/reference/random/brng/xorshift1024.rst similarity index 83% rename from doc/source/reference/randomgen/brng/xorshift1024.rst rename to doc/source/reference/random/brng/xorshift1024.rst index 64df7e050d01..24ed3df04469 100644 --- a/doc/source/reference/randomgen/brng/xorshift1024.rst +++ b/doc/source/reference/random/brng/xorshift1024.rst @@ -1,9 +1,9 @@ Xorshift1024*φ -------------- -.. module:: numpy.random.randomgen.xorshift1024 +.. module:: numpy.random.xorshift1024 -.. currentmodule:: numpy.random.randomgen.xorshift1024 +.. currentmodule:: numpy.random.xorshift1024 .. autoclass:: Xorshift1024 :exclude-members: diff --git a/doc/source/reference/randomgen/brng/xoshiro256starstar.rst b/doc/source/reference/random/brng/xoshiro256starstar.rst similarity index 83% rename from doc/source/reference/randomgen/brng/xoshiro256starstar.rst rename to doc/source/reference/random/brng/xoshiro256starstar.rst index 7603e6f1beba..85c445666c29 100644 --- a/doc/source/reference/randomgen/brng/xoshiro256starstar.rst +++ b/doc/source/reference/random/brng/xoshiro256starstar.rst @@ -1,9 +1,9 @@ Xoshiro256** ------------ -.. module:: numpy.random.randomgen.xoshiro256starstar +.. module:: numpy.random.xoshiro256starstar -.. currentmodule:: numpy.random.randomgen.xoshiro256starstar +.. currentmodule:: numpy.random.xoshiro256starstar .. autoclass:: Xoshiro256StarStar :exclude-members: diff --git a/doc/source/reference/randomgen/brng/xoshiro512starstar.rst b/doc/source/reference/random/brng/xoshiro512starstar.rst similarity index 83% rename from doc/source/reference/randomgen/brng/xoshiro512starstar.rst rename to doc/source/reference/random/brng/xoshiro512starstar.rst index 64f95f7509c2..0c008d56eb44 100644 --- a/doc/source/reference/randomgen/brng/xoshiro512starstar.rst +++ b/doc/source/reference/random/brng/xoshiro512starstar.rst @@ -1,9 +1,9 @@ Xoshiro512** ------------ -.. module:: numpy.random.randomgen.xoshiro512starstar +.. module:: numpy.random.xoshiro512starstar -.. currentmodule:: numpy.random.randomgen.xoshiro512starstar +.. currentmodule:: numpy.random.xoshiro512starstar .. autoclass:: Xoshiro512StarStar :exclude-members: diff --git a/doc/source/reference/randomgen/change-log.rst b/doc/source/reference/random/change-log.rst similarity index 77% rename from doc/source/reference/randomgen/change-log.rst rename to doc/source/reference/random/change-log.rst index f791c8f5418e..af3c266efe7a 100644 --- a/doc/source/reference/randomgen/change-log.rst +++ b/doc/source/reference/random/change-log.rst @@ -1,5 +1,5 @@ -Change Log ----------- +Change Log for the original bashtage/randomgen repo +--------------------------------------------------- v1.16.1 ======= - Synchronized with upstream changes. @@ -7,12 +7,12 @@ v1.16.1 v1.16.0 ======= -- Fixed a bug that affected :class:`~randomgen.dsfmt.DSFMT` when calling - :func:`~randomgen.dsfmt.DSFMT.jump` or :func:`~randomgen.dsfmt.DSFMT.seed` +- Fixed a bug that affected ``randomgen.dsfmt.DSFMT`` when calling + ``~randomgen.dsfmt.DSFMT.jump`` or ``randomgen.dsfmt.DSFMT.seed`` that failed to reset the buffer. This resulted in upto 381 values from the previous state being used before the buffer was refilled at the new state. -- Fixed bugs in :class:`~randomgen.xoshiro512starstar.Xoshiro512StarStar` - and :class:`~randomgen.xorshift1024.Xorshift1024` where the fallback +- Fixed bugs in ``randomgen.xoshiro512starstar.Xoshiro512StarStar`` + and ``randomgen.xorshift1024.Xorshift1024`` where the fallback entropy initialization used too few bytes. This bug is unlikely to be encountered since this path is only encountered if the system random number generator fails. diff --git a/doc/source/reference/randomgen/entropy.rst b/doc/source/reference/random/entropy.rst similarity index 60% rename from doc/source/reference/randomgen/entropy.rst rename to doc/source/reference/random/entropy.rst index 6814edfbe752..0664da6f9a7e 100644 --- a/doc/source/reference/randomgen/entropy.rst +++ b/doc/source/reference/random/entropy.rst @@ -1,6 +1,6 @@ System Entropy ============== -.. module:: numpy.random.randomgen.entropy +.. module:: numpy.random.entropy .. autofunction:: random_entropy diff --git a/doc/source/reference/randomgen/extending.rst b/doc/source/reference/random/extending.rst similarity index 91% rename from doc/source/reference/randomgen/extending.rst rename to doc/source/reference/random/extending.rst index 64f2ddcc16ce..f76e3984f851 100644 --- a/doc/source/reference/randomgen/extending.rst +++ b/doc/source/reference/random/extending.rst @@ -1,8 +1,10 @@ +.. currentmodule:: numpy.random + Extending --------- The basic RNGs have been designed to be extendable using standard tools for high-performance Python -- numba and Cython. -The :class:`randomgen.generator.RandomGenerator` object can also be used with +The `~RandomGenerator` object can also be used with user-provided basic RNGs as long as these export a small set of required functions. @@ -17,7 +19,7 @@ provided by ``ctypes.next_double``. .. code-block:: python - from randomgen import Xoroshiro128 + from numpy.random import Xoroshiro128 import numpy as np import numba as nb @@ -65,7 +67,7 @@ Cython ====== Cython can be used to unpack the ``PyCapsule`` provided by a basic RNG. -This example uses :class:`~randomgen.xoroshiro128.Xoroshiro128` and +This example uses `~xoroshiro128.Xoroshiro128` and ``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an array. The usual caveats for writing high-performance code using Cython -- removing bounds checks and wrap around, providing array alignment information @@ -77,9 +79,9 @@ removing bounds checks and wrap around, providing array alignment information cimport numpy as np cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer - from randomgen.common cimport * - from randomgen.distributions cimport random_gauss_zig - from randomgen.xoroshiro128 import Xoroshiro128 + from numpy.random.common cimport * + from numpy.random.distributions cimport random_gauss_zig + from numpy.random.xoroshiro128 import Xoroshiro128 @cython.boundscheck(False) @@ -137,7 +139,7 @@ examples folder. New Basic RNGs ============== -:class:`~randomgen.generator.RandomGenerator` can be used with other +`~RandomGenerator` can be used with other user-provided basic RNGs. The simplest way to write a new basic RNG is to examine the pyx file of one of the existing basic RNGs. The key structure that must be provided is the ``capsule`` which contains a ``PyCapsule`` to a @@ -158,7 +160,7 @@ used by the basic RNG. The next three are function pointers which return the next 64- and 32-bit unsigned integers, the next random double and the next raw value. This final function is used for testing and so can be set to the next 64-bit unsigned integer function if not needed. Functions inside -:class:`~randomgen.generator.RandomGenerator` use this structure as in +``RandomGenerator`` use this structure as in .. code-block:: c diff --git a/doc/source/reference/randomgen/generator.rst b/doc/source/reference/random/generator.rst similarity index 96% rename from doc/source/reference/randomgen/generator.rst rename to doc/source/reference/random/generator.rst index 54325f4d37ee..9d248732f5c9 100644 --- a/doc/source/reference/randomgen/generator.rst +++ b/doc/source/reference/random/generator.rst @@ -1,8 +1,8 @@ -.. currentmodule:: numpy.random.randomgen +.. currentmodule:: numpy.random Random Generator ---------------- -The :class:`~RandomGenerator` provides access to +The `~RandomGenerator` provides access to a wide range of distributions, and served as a replacement for :class:`~numpy.random.RandomState`. The main difference between the two is that ``RandomGenerator`` relies on an additional basic RNG to diff --git a/doc/source/reference/randomgen/index.rst b/doc/source/reference/random/index.rst similarity index 67% rename from doc/source/reference/randomgen/index.rst rename to doc/source/reference/random/index.rst index a8b6f1c9b3ff..1cbf5c6856e7 100644 --- a/doc/source/reference/randomgen/index.rst +++ b/doc/source/reference/random/index.rst @@ -1,49 +1,46 @@ -.. current_module numpy.random.randomgen +.. currentmodule:: numpy.random -numpy.random.randomgen -====================== +numpy.random +============ -This package modernizes the legacy -`~numpy.random.RandomState` object and allows changing the core random -number generator (RNG). The `~numpy.random.randomgen.RandomGenerator` can -be initialized with a number of different RNGs, and exposes many different -probability distributions. +A `~RandomGenerator` can +be initialized with a number of different Random Number Generators (RNG)s, and +exposes many different probability distributions. Quick Start ----------- -By default, `generator.RandomGenerator` uses normals provided by +By default, `RandomGenerator` uses normals provided by `xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in -`numpy.random` +`numpy.random.RandomState` .. code-block:: python - # As replacement for numpy.random - import randomgen.generator as random + # As replacement for numpy.random.RandomState + from numpy import random random.standard_normal() -`numpy.random.randomgen.RandomGenerator` can also be used as a replacement for -`~numpy.random.RandomState`, although the random values are generated by -`~numpyrandom.randomgen.xoroshiro128.Xoroshiro128`. Since ``randomgen`` -separates the `~numpy.random.randomgen.RandomGenerator` from the RNG, it is not -possible to directly seed the generator. +`RandomGenerator` can be used as a direct replacement for +`~RandomState`, although the random values are generated by +`~xoroshiro128.Xoroshiro128`. The `RandomGenerator` holds an instance of a RNG. +It is accessable as ``gen.brng``. .. code-block:: python # As replacement for RandomState() - from randomgen import RandomGenerator + from numpy.random import RandomGenerator rg = RandomGenerator() rg.standard_normal() -Seeds can be passed to any of the basic RNGs. Here `numpy.random.randomgen. -mt19937.MT19937` is used and the `~numpy.random.randomgen.RandomGenerator` is -accessed via the attribute `~numpy.random.randomgen.mt19937.MT19937.generator`. +Seeds can be passed to any of the basic RNGs. Here `mt19937.MT19937` is used +and the ``RandomGenerator`` is accessed via the attribute `mt19937.MT19937. +generator`. .. code-block:: python - from randomgen import MT19937 + from numpy.random import MT19937 rg = MT19937(12345).generator rg.standard_normal() @@ -59,20 +56,20 @@ underlying RNG state and provides functions to produce random doubles and random unsigned 32- and 64-bit values. The basic random generator also handles all seeding since this varies when using alternative basic RNGs. -The `random generator <~numpy.random.randomgen.RandomGenerator>` takes the +The `random generator <~RandomGenerator>` takes the basic RNG-provided functions and transforms them into more useful distributions, e.g., simulated normal random values. This structure allows alternative basic RNGs to be used without code duplication. -The `~numpy.random.randomgen.RandomGenerator` is the user-facing object -that is nearly identical to :class:`~numpy.random.RandomState`. The canonical -method to initialize a generator passes a basic RNG -- `~numpy.random. -randomgen.mt19937.MT19937`, the underlying RNG in NumPy -- as the -sole argument. Note that the basic RNG must be instantized. +The ``RandomGenerator`` is the user-facing object +that is nearly identical to :class:`~.RandomState`. The canonical +method to initialize a generator passes a basic RNG -- `~mt19937.MT19937`, the +underlying RNG in NumPy -- as the sole argument. Note that the basic RNG must +be instantized. .. code-block:: python - from randomgen import RandomGenerator, MT19937 + from numpy.random import RandomGenerator, MT19937 rg = RandomGenerator(MT19937()) rg.random_sample() @@ -83,9 +80,8 @@ Seed information is directly passed to the basic RNG. rg = RandomGenerator(MT19937(12345)) rg.random_sample() -A shorthand method is also available which uses the `~numpy.random.randomgen. -mt19937.MT19937.generator` property from a basic RNG to access an embedded -random generator. +A shorthand method is also available which uses the `~mt19937.MT19937. +generator` property from a basic RNG to access an embedded random generator. .. code-block:: python @@ -97,11 +93,10 @@ What's New or Different .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available - in `~numpy.random.randomgen.RandomGenerator`. It is not possible to - reproduce the random values using `~numpy.random.randomgen.RandomGenerator` - for the normal distribution or any other distribution that - relies on the normal such as the gamma or student's t. If you require - backward compatibility, a legacy generator, `~numpy.random.randomgen.legacy. + in `~RandomGenerator`. It is not possible to reproduce the random values + using ``RandomGenerator`` for the normal distribution or any other + distribution that relies on the normal such as the gamma or student's t. + If you require backward compatibility, a legacy generator, `~legacy. LegacyGenerator`, has been created which can fully reproduce the sequence produced by NumPy. @@ -113,18 +108,18 @@ What's New or Different select distributions * Optional ``out`` argument that allows existing arrays to be filled for select distributions -* `~numpy.random.randomgen.entropy.random_entropy` provides access to the system +* `~entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). * All basic random generators functions can produce doubles, uint64s and - uint32s via CTypes (`~numpy.random.randomgen.xoroshiro128.Xoroshiro128.ctypes`) - and CFFI (:meth:`~numpy.random.randomgen.xoroshiro128.Xoroshiro128.cffi`). + uint32s via CTypes (`~xoroshiro128.Xoroshiro128.ctypes`) + and CFFI (:meth:`~xoroshiro128.Xoroshiro128.cffi`). This allows these basic RNGs to be used in numba. * The basic random number generators can be used in downstream projects via :ref:`Cython `. * Support for Lemire’s method [Lemire]_ of generating uniform integers on an arbitrary interval by setting ``use_masked=True`` in - `~umpy.random.randomgen.generator.RandomGenerator.randint`. + `~RandomGenerator.randint`. See :ref:`new-or-different` for a complete list of improvements and @@ -146,7 +141,7 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are * MT19937 - The standard NumPy generator. Produces identical results to NumPy using the same seed/state. Adds a - `~numpy.random.randomgen.mt19937.MT19937.jump` function that advances the + `~mt19937.MT19937.jump` function that advances the generator as-if ``2**128`` draws have been made. See `numpy.random`. * dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically the same, but with a different state and so it is not possible to produce a @@ -155,24 +150,24 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are * XoroShiro128+ - Improved version of XorShift128+ with better performance and statistical quality. Like the XorShift generators, it can be jumped to produce multiple streams in parallel applications. See - `~numpy.random.randomgen.xoroshiro128.Xoroshiro128.jump` for details. + `~xoroshiro128.Xoroshiro128.jump` for details. More information about this PRNG is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * XorShift1024*φ - Fast fast generator based on the XSadd generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - `~numpy.random.randomgen.xorshift1024.Xorshift1024.jump` for details. More + `~xorshift1024.Xorshift1024.jump` for details. More information about these PRNGs is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * Xorshiro256** and Xorshiro512** - The most recently introduced XOR, shift, and rotate generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - `~numpy.random.randomgen.xoshiro256starstar.Xoshirt256StarStar.jump` for + `~xoshiro256starstar.Xoshirt256StarStar.jump` for details. More information about these PRNGs is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * PCG-64 - Fast generator that support many parallel streams and can be advanced by an arbitrary amount. See the documentation for - `~numpy.random.randomgen.pcg64.PCG64.advance`. PCG-64 has a period of + `~pcg64.PCG64.advance`. PCG-64 has a period of :math:`2^{128}`. See the `PCG author's page`_ for more details about this class of PRNG. * ThreeFry and Philox - counter-based generators capable of being advanced an diff --git a/doc/source/reference/randomgen/legacy.rst b/doc/source/reference/random/legacy.rst similarity index 87% rename from doc/source/reference/randomgen/legacy.rst rename to doc/source/reference/random/legacy.rst index 7e87f871cc10..b9bfabcc7df4 100644 --- a/doc/source/reference/randomgen/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -1,15 +1,15 @@ Legacy Random Generation ------------------------ -The :class:`~randomgen.legacy.LegacyGenerator` provides access to -some legacy generators. These all depend on Box-Muller normals or +The :class:`~legacy.LegacyGenerator` provides access to +legacy generators. These all depend on Box-Muller normals or inverse CDF exponentials or gammas. This class should only be used if it is essential to have randoms that are identical to what would have been produced by NumPy. -:class:`~randomgen.legacy.LegacyGenerator` add additional information +:class:`~legacy.LegacyGenerator` add additional information to the state which is required when using Box-Muller normals since these are produced in pairs. It is important to use -:attr:`~randomgen.legacy.LegacyGenerator.state` +:attr:`~legacy.LegacyGenerator.state` when accessing the state so that these extra values are saved. .. warning:: @@ -27,8 +27,8 @@ when accessing the state so that these extra values are saved. .. code-block:: python - from randomgen import RandomGenerator, MT19937 - from randomgen.legacy import LegacyGenerator + from numpy.random import MT19937 + from numpy.random.legacy import LegacyGenerator from numpy.random import RandomState # Use same seed rs = RandomState(12345) @@ -47,7 +47,7 @@ when accessing the state so that these extra values are saved. lg.standard_exponential() -.. currentmodule:: numpy.random.randomgen.legacy +.. currentmodule:: numpy.random.legacy .. autoclass:: LegacyGenerator :exclude-members: diff --git a/doc/source/reference/randomgen/multithreading.rst b/doc/source/reference/random/multithreading.rst similarity index 98% rename from doc/source/reference/randomgen/multithreading.rst rename to doc/source/reference/random/multithreading.rst index 6efbcdbe76e3..f7762b73acf8 100644 --- a/doc/source/reference/randomgen/multithreading.rst +++ b/doc/source/reference/random/multithreading.rst @@ -16,7 +16,7 @@ that the same seed will produce the same outputs. .. code-block:: ipython - from randomgen import Xorshift1024 + from numpy.random import Xorshift1024 import multiprocessing import concurrent.futures import numpy as np diff --git a/doc/source/reference/randomgen/new-or-different.rst b/doc/source/reference/random/new-or-different.rst similarity index 51% rename from doc/source/reference/randomgen/new-or-different.rst rename to doc/source/reference/random/new-or-different.rst index 089efd6fb880..7ddebb5b2135 100644 --- a/doc/source/reference/randomgen/new-or-different.rst +++ b/doc/source/reference/random/new-or-different.rst @@ -1,41 +1,44 @@ .. _new-or-different: +.. currentmodule:: numpy.random + What's New or Different ----------------------- .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available - in :class:`~randomgen.generator.RandomGenerator`. It is not possible to - reproduce the random values using :class:`~randomgen.generator.RandomGenerator` - for the normal distribution or any other distribution that relies on the - normal such as the gamma or student's t. If you require backward compatibility, a - legacy generator, :class:`~randomgen.legacy.LegacyGenerator`, has been created - which can fully reproduce the sequence produced by NumPy. + in `~.RandomGenerator`. It is not possible to + reproduce the exact random values using ``RandomGenerator`` for the normal + distribution or any other distribution that relies on the normal such as the + `numpy.random.gamma` or `numpy.random.standard_t`. If you require backward + compatibility, a legacy generator, `~.legacy. + LegacyGenerator`, has been created which can fully reproduce the exact byte + sequence produced by legacy code. -* :func:`~randomgen.entropy.random_entropy` provides access to the system +* `~.entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). * Simulate from the complex normal distribution - (:meth:`~randomgen.generator.RandomGenerator.complex_normal`) + (`~.RandomGenerator.complex_normal`) * The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy's default implementation in - :meth:`~randomgen.generator.RandomGenerator.standard_normal`, - :meth:`~randomgen.generator.RandomGenerator.standard_exponential` or - :meth:`~randomgen.generator.RandomGenerator.standard_gamma`. + `~.RandomGenerator.standard_normal`, + `~.RandomGenerator.standard_exponential` or + `~.RandomGenerator.standard_gamma`. * The Box-Muller used to produce NumPy's normals is no longer available. * All basic random generators functions to produce doubles, uint64s and - uint32s via CTypes (:meth:`~randomgen.xoroshiro128.Xoroshiro128.ctypes`) - and CFFI (:meth:`~randomgen.xoroshiro128.Xoroshiro128.cffi`). This allows - these basic RNGs to be used in numba. + uint32s via CTypes (`~.xoroshiro128.Xoroshiro128. + ctypes`) and CFFI (`~.xoroshiro128.Xoroshiro128.cffi`). + This allows these basic RNGs to be used in numba. * The basic random number generators can be used in downstream projects via Cython. .. ipython:: python - from numpy.random.randomgen import Xoroshiro128 + from numpy.random import Xoroshiro128 import numpy.random rg = Xoroshiro128().generator %timeit rg.standard_normal(100000) @@ -55,12 +58,12 @@ What's New or Different to produce either single or double prevision uniform random variables for select distributions - * Uniforms (:meth:`~randomgen.generator.RandomGenerator.random_sample` and - :meth:`~randomgen.generator.RandomGenerator.rand`) - * Normals (:meth:`~randomgen.generator.RandomGenerator.standard_normal` and - :meth:`~randomgen.generator.RandomGenerator.randn`) - * Standard Gammas (:meth:`~randomgen.generator.RandomGenerator.standard_gamma`) - * Standard Exponentials (:meth:`~randomgen.generator.RandomGenerator.standard_exponential`) + * Uniforms (`~.RandomGenerator.random_sample` and + `~.RandomGenerator.rand`) + * Normals (`~.RandomGenerator.standard_normal` and + `~.RandomGenerator.randn`) + * Standard Gammas (`~.RandomGenerator.standard_gamma`) + * Standard Exponentials (`~.RandomGenerator.standard_exponential`) .. ipython:: python @@ -72,10 +75,10 @@ What's New or Different * Optional ``out`` argument that allows existing arrays to be filled for select distributions - * Uniforms (:meth:`~randomgen.generator.RandomGenerator.random_sample`) - * Normals (:meth:`~randomgen.generator.RandomGenerator.standard_normal`) - * Standard Gammas (:meth:`~randomgen.generator.RandomGenerator.standard_gamma`) - * Standard Exponentials (:meth:`~randomgen.generator.RandomGenerator.standard_exponential`) + * Uniforms (`~.RandomGenerator.random_sample`) + * Normals (`~.RandomGenerator.standard_normal`) + * Standard Gammas (`~.RandomGenerator.standard_gamma`) + * Standard Exponentials (`~.RandomGenerator.standard_exponential`) This allows multithreading to fill large arrays in chunks using suitable PRNGs in parallel. @@ -90,7 +93,7 @@ What's New or Different * Support for Lemire’s method of generating uniform integers on an arbitrary interval by setting ``use_masked=True`` in - (:meth:`~randomgen.generator.RandomGenerator.randint`). + (`~.RandomGenerator.randint`). .. ipython:: python diff --git a/doc/source/reference/randomgen/parallel.rst b/doc/source/reference/random/parallel.rst similarity index 88% rename from doc/source/reference/randomgen/parallel.rst rename to doc/source/reference/random/parallel.rst index df6f58d75a9b..41e47039d534 100644 --- a/doc/source/reference/randomgen/parallel.rst +++ b/doc/source/reference/random/parallel.rst @@ -7,18 +7,20 @@ or distributed). .. _independent-streams: +.. currentmodule:: numpy.random + Independent Streams ------------------- -:class:`~randomgen.pcg64.PCG64`, :class:`~randomgen.threefry.ThreeFry` -and :class:`~randomgen.philox.Philox` support independent streams. This +:class:`~pcg64.PCG64`, :class:`~threefry.ThreeFry` +and :class:`~philox.Philox` support independent streams. This example shows how many streams can be created by passing in different index values in the second input while using the same seed in the first. .. code-block:: python - from randomgen.entropy import random_entropy - from randomgen import PCG64 + from numpy.random.entropy import random_entropy + from numpy.random import PCG64 entropy = random_entropy(4) # 128-bit number as a seed @@ -26,14 +28,14 @@ values in the second input while using the same seed in the first. streams = [PCG64(seed, stream) for stream in range(10)] -:class:`~randomgen.philox.Philox` and :class:`~randomgen.threefry.ThreeFry` are +:class:`~philox.Philox` and :class:`~threefry.ThreeFry` are counter-based RNGs which use a counter and key. Different keys can be used to produce independent streams. .. code-block:: python import numpy as np - from randomgen import ThreeFry + from numpy.random import ThreeFry key = random_entropy(8) key = key.view(np.uint64) @@ -81,8 +83,8 @@ overlap. .. code-block:: python - from randomgen.entropy import random_entropy - from randomgen import Xorshift1024 + from numpy.random.entropy import random_entropy + from numpy.random import Xorshift1024 entropy = random_entropy(2).astype(np.uint64) # 64-bit number as a seed @@ -97,8 +99,8 @@ overlap. Advance ******* ``advance`` can be used to jump the state an arbitrary number of steps, and so -is a more general approach than ``jump``. :class:`~randomgen.pcg64.PCG64`, -:class:`~randomgen.threefry.ThreeFry` and :class:`~randomgen.philox.Philox` +is a more general approach than ``jump``. :class:`~pcg64.PCG64`, +:class:`~threefry.ThreeFry` and :class:`~philox.Philox` support ``advance``, and since these also support independent streams, it is not usually necessary to use ``advance``. @@ -119,12 +121,12 @@ This occurs for two reasons: Advancing the PRNG state resets any pre-computed random numbers. This is required to ensure exact reproducibility. -This example uses ``advance`` to advance a :class:`~randomgen.pcg64.PCG64` +This example uses ``advance`` to advance a :class:`~pcg64.PCG64` generator 2 ** 127 steps to set a sequence of random number generators. .. code-block:: python - from randomgen import PCG64 + from numpy.random import PCG64 brng = PCG64() brng_copy = PCG64() brng_copy.state = brng.state diff --git a/doc/source/reference/randomgen/performance.py b/doc/source/reference/random/performance.py similarity index 100% rename from doc/source/reference/randomgen/performance.py rename to doc/source/reference/random/performance.py diff --git a/doc/source/reference/randomgen/performance.rst b/doc/source/reference/random/performance.rst similarity index 85% rename from doc/source/reference/randomgen/performance.rst rename to doc/source/reference/random/performance.rst index 2dfb32101c5e..321d494547c7 100644 --- a/doc/source/reference/randomgen/performance.rst +++ b/doc/source/reference/random/performance.rst @@ -1,26 +1,28 @@ Performance ----------- -.. py:module:: randomgen +.. py:module:: numpy.random + +.. currentmodule:: numpy.random Recommendation ************** The recommended generator for single use is -:class:`~randomgen.xoroshiro128.Xoroshiro128`. The recommended generator +:class:`~xoroshiro128.Xoroshiro128`. The recommended generator for use in large-scale parallel applications is -:class:`~randomgen.xorshift1024.Xorshift1024` +:class:`~xorshift1024.Xorshift1024` where the `jump` method is used to advance the state. For very large scale applications -- requiring 1,000+ independent streams, -:class:`~randomgen.pcg64.PCG64` or :class:`~randomgen.threefry.ThreeFry` are +:class:`~pcg64.PCG64` or :class:`~threefry.ThreeFry` are the best choices. Timings ******* The timings below are the time in ms to produce 1,000,000 random values from a -specific distribution. :class:`~randomgen.xoroshiro128.Xoroshiro128` is the -fastest, followed by :class:`~randomgen.xorshift1024.Xorshift1024` and -:class:`~randomgen.pcg64.PCG64`. The original :class:`~randomgen.mt19937.MT19937` +specific distribution. :class:`~xoroshiro128.Xoroshiro128` is the +fastest, followed by :class:`~xorshift1024.Xorshift1024` and +:class:`~pcg64.PCG64`. The original :class:`~mt19937.MT19937` generator is much slower since it requires 2 32-bit values to equal the output of the faster generators. diff --git a/doc/source/reference/randomgen/references.rst b/doc/source/reference/random/references.rst similarity index 100% rename from doc/source/reference/randomgen/references.rst rename to doc/source/reference/random/references.rst diff --git a/doc/source/reference/routines.rst b/doc/source/reference/routines.rst index 0ed99cbdac36..e3fbc2be6945 100644 --- a/doc/source/reference/routines.rst +++ b/doc/source/reference/routines.rst @@ -42,7 +42,7 @@ indentation. routines.padding routines.polynomials routines.random - randomgen/index + random/index routines.set routines.sort routines.statistics diff --git a/numpy/random/_mtrand/mtrand.pyx b/numpy/random/_mtrand/_mtrand.pyx similarity index 99% rename from numpy/random/_mtrand/mtrand.pyx rename to numpy/random/_mtrand/_mtrand.pyx index 329d5cd683cc..42e40e87e394 100644 --- a/numpy/random/_mtrand/mtrand.pyx +++ b/numpy/random/_mtrand/_mtrand.pyx @@ -1918,9 +1918,9 @@ 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.show() diff --git a/numpy/random/dsfmt.pyx b/numpy/random/dsfmt.pyx index 9a7199e856ec..709c2c8e8cf2 100644 --- a/numpy/random/dsfmt.pyx +++ b/numpy/random/dsfmt.pyx @@ -102,13 +102,13 @@ cdef class DSFMT: generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from numpy.random.randomgen.entropy import random_entropy - >>> from numpy.random.randomgen import RandomGenerator, DSFMT + >>> from numpy.random.entropy import random_entropy + >>> from numpy.random import RandomGenerator, DSFMT >>> seed = random_entropy() >>> rs = [RandomGenerator(DSFMT(seed)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each DSFMT instance by i jumps >>> for i in range(10): - ... rs[i].jump() + ... rs[i].brng.jump() **State and Seeding** @@ -182,10 +182,12 @@ cdef class DSFMT: self.state) def __dealloc__(self): - PyArray_free_aligned(self.rng_state.state) - PyArray_free_aligned(self.rng_state.buffered_uniforms) - free(self.rng_state) - free(self._brng) + if self.rng_state: + PyArray_free_aligned(self.rng_state.state) + PyArray_free_aligned(self.rng_state.buffered_uniforms) + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.buffer_loc = DSFMT_N64 @@ -396,7 +398,7 @@ cdef class DSFMT: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator # ignore Random generator used this instance as the basic RNG """ if self._generator is None: diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index e68edb98ab15..7f18392a89c3 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -58,19 +58,22 @@ cdef class RandomGenerator: Examples -------- - >>> from np.random.randomgen import RandomGenerator + >>> from numpy.random import RandomGenerator >>> rg = RandomGenerator() >>> rg.standard_normal() + -0.203 # random Using a specific generator - >>> from np.random.randomgen import MT19937 + >>> from numpy.random import MT19937 >>> rg = RandomGenerator(MT19937()) The generator is also directly available from basic RNGs >>> rg = MT19937().generator >>> rg.standard_normal() + -0.203 # random + """ cdef public object brng cdef brng_t *_brng @@ -92,7 +95,8 @@ cdef class RandomGenerator: self.lock = brng.lock def __dealloc__(self): - free(self._binomial) + if self._binomial: + free(self._binomial) def __repr__(self): return self.__str__() + ' at 0x{:X}'.format(id(self)) @@ -351,14 +355,12 @@ cdef class RandomGenerator: Examples -------- - >>> rg = np.random.randomgen.RandomGenerator() # need a RandomGenerator object + >>> rg = np.random.RandomGenerator() # need a RandomGenerator object >>> rg.tomaxint((2,2,2)) array([[[1170048599, 1600360186], # random [ 739731006, 1947757578]], [[1871712945, 752307660], [1601631370, 1479324245]]]) - >>> np.iinfo(np.int).max - 2147483647 >>> rg.tomaxint((2,2,2)) < np.iinfo(np.int).max array([[[ True, True], [ True, True]], @@ -1275,11 +1277,11 @@ cdef class RandomGenerator: 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() """ @@ -1363,11 +1365,11 @@ cdef class RandomGenerator: 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() """ @@ -1917,11 +1919,11 @@ cdef class RandomGenerator: 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() """ @@ -2199,25 +2201,25 @@ cdef class RandomGenerator: 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)') """ @@ -3208,14 +3210,15 @@ cdef class RandomGenerator: 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) + >>> 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() """ diff --git a/numpy/random/mt19937.pyx b/numpy/random/mt19937.pyx index 306ce23e2c40..8ed229984d8e 100644 --- a/numpy/random/mt19937.pyx +++ b/numpy/random/mt19937.pyx @@ -98,13 +98,13 @@ cdef class MT19937: generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from numpy.random.randomgen.entropy import random_entropy - >>> from numpy.random.randomgen import RandomGenerator, MT19937 + >>> from numpy.random.entropy import random_entropy + >>> from numpy.random import RandomGenerator, MT19937 >>> seed = random_entropy() - >>> rs = [RandomGenerator(MT19937(seed) for _ in range(10)] - # Advance rs[i] by i jumps + >>> rs = [RandomGenerator(MT19937(seed)) for _ in range(10)] + # Advance each MT19937 instance by i jumps >>> for i in range(10): - rs[i].jump(i) + ... rs[i].brng.jump(i) References ---------- @@ -145,8 +145,10 @@ cdef class MT19937: self.capsule = PyCapsule_New(self._brng, name, NULL) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) # Pickling support: def __getstate__(self): @@ -353,7 +355,7 @@ cdef class MT19937: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index b5d6ff9bc9b9..145af4c7cdb1 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -90,8 +90,10 @@ cdef class RandomState: self.lock = brng.lock def __dealloc__(self): - free(self._binomial) - free(self._aug_state) + if self._binomial: + free(self._binomial) + if self._aug_state: + free(self._aug_state) def __repr__(self): return self.__str__() + ' at 0x{:X}'.format(id(self)) @@ -135,7 +137,7 @@ cdef class RandomState: The best method to access seed is to directly use a basic RNG instance. This example demonstrates this best practice. - >>> from numpy.random.randomgen import MT19937 + >>> from numpy.random import MT19937 >>> from numpy.random import RandomState >>> brng = MT19937(123456789) >>> rs = RandomState(brng) @@ -479,8 +481,6 @@ cdef class RandomState: [ 739731006, 1947757578]], [[1871712945, 752307660], [1601631370, 1479324245]]]) - >>> np.iinfo(np.int).max - 2147483647 >>> rs.tomaxint((2,2,2)) < np.iinfo(np.int).max array([[[ True, True], [ True, True]], @@ -1358,11 +1358,11 @@ 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() """ @@ -1437,11 +1437,11 @@ 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() """ @@ -1991,11 +1991,11 @@ 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() """ @@ -2273,25 +2273,25 @@ 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)') """ @@ -3282,14 +3282,14 @@ 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() """ diff --git a/numpy/random/pcg32.pyx b/numpy/random/pcg32.pyx index 5f2b34807da2..64e79dfe16f5 100644 --- a/numpy/random/pcg32.pyx +++ b/numpy/random/pcg32.pyx @@ -95,15 +95,15 @@ cdef class PCG32: The preferable method is to use sub-streams, which are generated by using the same value of ``seed`` and incrementing the second value, ``inc``. - >>> from randomgen import RandomGenerator, PCG32 + >>> from numpy.random import RandomGenerator, PCG32 >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] - The alternative method is to call ``advance`` on a instance to - produce non-overlapping sequences. + The alternative method is to call ``advance`` with a different value on + each instance to produce non-overlapping sequences. >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] >>> for i in range(10): - ... rg[i].advance(i * 2**32) + ... rg[i].brng.advance(i * 2**32) **State and Seeding** @@ -160,8 +160,10 @@ cdef class PCG32: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) def random_raw(self, size=None, output=True): """ @@ -376,7 +378,7 @@ cdef class PCG32: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/pcg64.pyx b/numpy/random/pcg64.pyx index f67d9623cc33..726bae02716c 100644 --- a/numpy/random/pcg64.pyx +++ b/numpy/random/pcg64.pyx @@ -104,15 +104,15 @@ cdef class PCG64: The preferable method is to use sub-streams, which are generated by using the same value of ``seed`` and incrementing the second value, ``inc``. - >>> from randomgen import RandomGenerator, PCG64 + >>> from numpy.random import RandomGenerator, PCG64 >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] - The alternative method is to call ``advance`` on a single instance to - produce non-overlapping sequences. + The alternative method is to call ``advance`` with a different value on + each instance to produce non-overlapping sequences. >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] >>> for i in range(10): - ... rg[i].advance(i * 2**64) + ... rg[i].brng.advance(i * 2**64) **State and Seeding** @@ -171,8 +171,10 @@ cdef class PCG64: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -430,7 +432,7 @@ cdef class PCG64: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator using this instance as the core RNG """ if self._generator is None: diff --git a/numpy/random/philox.pyx b/numpy/random/philox.pyx index 70afd55ab2da..4ca38bb11968 100644 --- a/numpy/random/philox.pyx +++ b/numpy/random/philox.pyx @@ -112,15 +112,15 @@ cdef class Philox: in parallel applications by using a sequence of distinct keys where each instance uses different key. - >>> from randomgen import RandomGenerator, Philox + >>> from numpy.random import RandomGenerator, Philox >>> rg = [RandomGenerator(Philox(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each Philox instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) Using distinct keys produces independent streams - >>> key = 2**196 + 2**132 + 2**65 + 2**33 + 2**17 + 2**9 + >>> key = 2**96 + 2**32 + 2**65 + 2**33 + 2**17 + 2**9 >>> rg = [RandomGenerator(Philox(key=key+i)) for i in range(10)] **State and Seeding** @@ -144,14 +144,16 @@ cdef class Philox: Examples -------- - >>> from randomgen import RandomGenerator, Philox + >>> from numpy.random import RandomGenerator, Philox >>> rg = RandomGenerator(Philox(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only Philox >>> rg = Philox(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -205,10 +207,12 @@ cdef class Philox: self.state) def __dealloc__(self): - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state.ctr) + free(self.rng_state.key) + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -471,7 +475,7 @@ cdef class Philox: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 088764791bb1..38d968febb21 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -48,7 +48,7 @@ def generate_libraries(ext, build_dir): # Configure mtrand config.add_extension('_mtrand', sources=[join('_mtrand', x) for x in - ['mtrand.c', 'randomkit.c', 'initarray.c', + ['_mtrand.c', 'randomkit.c', 'initarray.c', 'distributions.c']]+[generate_libraries], libraries=libs, depends=[join('_mtrand', '*.h'), diff --git a/numpy/random/threefry.pyx b/numpy/random/threefry.pyx index 8140c6a9b72a..a8878c6bc4a1 100644 --- a/numpy/random/threefry.pyx +++ b/numpy/random/threefry.pyx @@ -107,11 +107,11 @@ cdef class ThreeFry: in parallel applications by using a sequence of distinct keys where each instance uses different key. - >>> from randomgen import RandomGenerator, ThreeFry + >>> from numpy.random import RandomGenerator, ThreeFry >>> rg = [RandomGenerator(ThreeFry(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each ThreeFry instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) Using distinct keys produces independent streams @@ -139,14 +139,16 @@ cdef class ThreeFry: Examples -------- - >>> from randomgen import RandomGenerator, ThreeFry + >>> from numpy.random import RandomGenerator, ThreeFry >>> rg = RandomGenerator(ThreeFry(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only ThreeFry >>> rg = ThreeFry(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -198,10 +200,12 @@ cdef class ThreeFry: self.state) def __dealloc__(self): - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state.ctr) + free(self.rng_state.key) + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -462,7 +466,7 @@ cdef class ThreeFry: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/threefry32.pyx b/numpy/random/threefry32.pyx index 1fa98eabdd29..b1b4d4c5197e 100644 --- a/numpy/random/threefry32.pyx +++ b/numpy/random/threefry32.pyx @@ -109,11 +109,11 @@ cdef class ThreeFry32: in parallel applications by using a sequence of distinct keys where each instance uses different key. - >>> from randomgen import RandomGenerator, ThreeFry32 + >>> from numpy.random import RandomGenerator, ThreeFry32 >>> rg = [RandomGenerator(ThreeFry32(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each ThreeFry32 instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) Using distinct keys produces independent streams @@ -142,14 +142,16 @@ cdef class ThreeFry32: Examples -------- - >>> from randomgen import RandomGenerator, ThreeFry32 + >>> from numpy.random import RandomGenerator, ThreeFry32 >>> rg = RandomGenerator(ThreeFry32(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only ThreeFry32 >>> rg = ThreeFry32(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -201,10 +203,12 @@ cdef class ThreeFry32: self.state) def __dealloc__(self): - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state.ctr) + free(self.rng_state.key) + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE @@ -458,7 +462,7 @@ cdef class ThreeFry32: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/xoroshiro128.pyx b/numpy/random/xoroshiro128.pyx index 7795500e8ea1..5c4642513b9b 100644 --- a/numpy/random/xoroshiro128.pyx +++ b/numpy/random/xoroshiro128.pyx @@ -84,11 +84,11 @@ cdef class Xoroshiro128: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen import RandomGenerator, Xoroshiro128 + >>> from numpy.random import RandomGenerator, Xoroshiro128 >>> rg = [RandomGenerator(Xoroshiro128(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each Xoroshiro128 instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) **State and Seeding** @@ -108,14 +108,16 @@ cdef class Xoroshiro128: Examples -------- - >>> from randomgen import RandomGenerator, Xoroshiro128 + >>> from numpy.random import RandomGenerator, Xoroshiro128 >>> rg = RandomGenerator(Xoroshiro128(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only Xoroshiro128 >>> rg = Xoroshiro128(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -163,8 +165,10 @@ cdef class Xoroshiro128: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -348,7 +352,7 @@ cdef class Xoroshiro128: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: diff --git a/numpy/random/xorshift1024.pyx b/numpy/random/xorshift1024.pyx index 3c7ffac52c54..04fb542c142a 100644 --- a/numpy/random/xorshift1024.pyx +++ b/numpy/random/xorshift1024.pyx @@ -83,11 +83,11 @@ cdef class Xorshift1024: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen import RandomGenerator, Xorshift1024 + >>> from numpy.random import RandomGenerator, Xorshift1024 >>> rg = [RandomGenerator(Xorshift1024(1234)) for _ in range(10)] - # Advance rg[i] by i jumps + # Advance each Xorshift1024 instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) **State and Seeding** @@ -107,14 +107,16 @@ cdef class Xorshift1024: Examples -------- - >>> from randomgen import RandomGenerator, Xorshift1024 + >>> from numpy.random import RandomGenerator, Xorshift1024 >>> rg = RandomGenerator(Xorshift1024(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only Xoroshiro128 - >>> rg = Xorshift10241234).generator + >>> rg = Xorshift1024(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -169,8 +171,10 @@ cdef class Xorshift1024: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -356,7 +360,7 @@ cdef class Xorshift1024: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the core PRNG """ if self._generator is None: diff --git a/numpy/random/xoshiro256starstar.pyx b/numpy/random/xoshiro256starstar.pyx index c3856b6f7651..278356b05db1 100644 --- a/numpy/random/xoshiro256starstar.pyx +++ b/numpy/random/xoshiro256starstar.pyx @@ -83,11 +83,11 @@ cdef class Xoshiro256StarStar: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen import RandomGenerator, Xoshiro256StarStar + >>> from numpy.random import RandomGenerator, Xoshiro256StarStar >>> rg = [RandomGenerator(Xoshiro256StarStar(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each Xoshiro256StarStar instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) **State and Seeding** @@ -108,14 +108,16 @@ cdef class Xoshiro256StarStar: Examples -------- - >>> from randomgen import RandomGenerator, Xoshiro256StarStar + >>> from numpy.random import RandomGenerator, Xoshiro256StarStar >>> rg = RandomGenerator(Xoshiro256StarStar(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only Xoshiro256StarStar >>> rg = Xoshiro256StarStar(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -163,8 +165,10 @@ cdef class Xoshiro256StarStar: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -353,7 +357,7 @@ cdef class Xoshiro256StarStar: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: diff --git a/numpy/random/xoshiro512starstar.pyx b/numpy/random/xoshiro512starstar.pyx index 761d1f1d0b20..65d4c7c3e298 100644 --- a/numpy/random/xoshiro512starstar.pyx +++ b/numpy/random/xoshiro512starstar.pyx @@ -83,11 +83,11 @@ cdef class Xoshiro512StarStar: in each worker process. All generators should be initialized with the same seed to ensure that the segments come from the same sequence. - >>> from randomgen import RandomGenerator, Xoshiro512StarStar + >>> from numpy.random import RandomGenerator, Xoshiro512StarStar >>> rg = [RandomGenerator(Xoshiro512StarStar(1234)) for _ in range(10)] - # Advance rs[i] by i jumps + # Advance each Xoshiro512StarStar instance by i jumps >>> for i in range(10): - ... rg[i].jump(i) + ... rg[i].brng.jump(i) **State and Seeding** @@ -108,14 +108,16 @@ cdef class Xoshiro512StarStar: Examples -------- - >>> from randomgen import RandomGenerator, Xoshiro512StarStar + >>> from numpy.random import RandomGenerator, Xoshiro512StarStar >>> rg = RandomGenerator(Xoshiro512StarStar(1234)) >>> rg.standard_normal() + 0.123 # random Identical method using only Xoshiro512StarStar >>> rg = Xoshiro512StarStar(1234).generator >>> rg.standard_normal() + 0.123 # random References ---------- @@ -163,8 +165,10 @@ cdef class Xoshiro512StarStar: self.state) def __dealloc__(self): - free(self.rng_state) - free(self._brng) + if self.rng_state: + free(self.rng_state) + if self._brng: + free(self._brng) cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -347,7 +351,7 @@ cdef class Xoshiro512StarStar: Returns ------- - gen : numpy.random.randomgen.generator.RandomGenerator + gen : numpy.random.RandomGenerator Random generator used this instance as the basic RNG """ if self._generator is None: From 0f3dd0650adc82bae0050cbc5a13cb82659c8faf Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 11 Apr 2019 07:59:21 +0100 Subject: [PATCH 107/138] ENH: Extend multinomial and fix zipf Extend multinomial to allow broadcasting Fix zipf changes missed in NumPy Enable 0 as valid input for hypergeometric --- numpy/random/distributions.pxd | 3 + numpy/random/generator.pyx | 71 +++++++++++++------ numpy/random/mtrand.pyx | 30 +++----- .../random/src/distributions/distributions.c | 52 ++++++++++---- .../random/src/distributions/distributions.h | 3 + numpy/random/tests/test_generator_mt19937.py | 34 ++++++--- numpy/random/tests/test_randomstate.py | 4 ++ 7 files changed, 134 insertions(+), 63 deletions(-) diff --git a/numpy/random/distributions.pxd b/numpy/random/distributions.pxd index ddb7a84bf190..5047aed9a325 100644 --- a/numpy/random/distributions.pxd +++ b/numpy/random/distributions.pxd @@ -144,3 +144,6 @@ cdef extern from "src/distributions/distributions.h": np.npy_bool off, np.npy_bool rng, np.npy_intp cnt, bint use_masked, np.npy_bool *out) nogil + + void random_multinomial(brng_t *brng_state, int64_t n, int64_t *mnix, + double *pix, np.npy_intp d, binomial_t *binomial) nogil diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 7f18392a89c3..29a36787ebbc 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -3642,7 +3642,7 @@ cdef class RandomGenerator: x.shape = tuple(final_shape) return x - def multinomial(self, np.npy_intp n, object pvals, size=None): + def multinomial(self, object n, object pvals, size=None): """ multinomial(n, pvals, size=None) @@ -3658,7 +3658,7 @@ cdef class RandomGenerator: Parameters ---------- - n : int + 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 @@ -3697,6 +3697,18 @@ cdef class RandomGenerator: 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: + + >>> np.random.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: >>> np.random.multinomial(100, [1/7.]*5 + [2/7.]) @@ -3717,19 +3729,44 @@ cdef class RandomGenerator: array([100, 0]) """ - cdef np.npy_intp d, i, j, dn, sz - cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" + + cdef np.npy_intp d, i, sz, offset + cdef np.ndarray parr, mnarr, on, temp_arr cdef double *pix cdef int64_t *mnix - cdef double Sum + cdef int64_t ni + cdef np.broadcast it d = len(pvals) + on = np.PyArray_FROM_OTF(n, np.NPY_INT64, np.NPY_ALIGNED) parr = np.PyArray_FROM_OTF(pvals, np.NPY_DOUBLE, np.NPY_ALIGNED) pix = 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 = temp + it = np.PyArray_MultiIterNew2(on, temp_arr) + shape = it.shape + (d,) + multin = np.zeros(shape, dtype=np.int64) + mnarr = multin + mnix = np.PyArray_DATA(mnarr) + offset = 0 + sz = it.size + with self.lock, nogil: + for i in range(sz): + ni = (np.PyArray_MultiIter_DATA(it, 0))[0] + random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + offset += d + np.PyArray_MultiIter_NEXT(it) + return multin + if size is None: shape = (d,) else: @@ -3742,23 +3779,13 @@ cdef class RandomGenerator: mnarr = multin mnix = np.PyArray_DATA(mnarr) sz = np.PyArray_SIZE(mnarr) - + ni = n + check_constraint(ni, 'n', CONS_NON_NEGATIVE) + offset = 0 with self.lock, nogil: - i = 0 - while i < sz: - Sum = 1.0 - dn = n - for j in range(d-1): - mnix[i+j] = random_binomial(self._brng, pix[j]/Sum, dn, - self._binomial) - dn = dn - mnix[i+j] - if dn <= 0: - break - Sum = Sum - pix[j] - if dn > 0: - mnix[i+d-1] = dn - - i = i + d + for i in range(sz // d): + random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + offset += d return multin diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 145af4c7cdb1..351d05e93b97 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3790,16 +3790,16 @@ cdef class RandomState: array([100, 0]) """ - cdef np.npy_intp d, i, j, dn, sz - cdef np.ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" + cdef np.npy_intp d, i, sz, offset + cdef np.ndarray parr, mnarr cdef double *pix cdef int64_t *mnix - cdef double Sum + cdef int64_t ni d = len(pvals) parr = np.PyArray_FROM_OTF(pvals, np.NPY_DOUBLE, np.NPY_ALIGNED) pix = 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") @@ -3815,23 +3815,13 @@ cdef class RandomState: mnarr = multin mnix = np.PyArray_DATA(mnarr) sz = np.PyArray_SIZE(mnarr) - + ni = n + check_constraint(ni, 'n', CONS_NON_NEGATIVE) + offset = 0 with self.lock, nogil: - i = 0 - while i < sz: - Sum = 1.0 - dn = n - for j in range(d-1): - mnix[i+j] = random_binomial(self._brng, pix[j]/Sum, dn, - self._binomial) - dn = dn - mnix[i+j] - if dn <= 0: - break - Sum = Sum - pix[j] - if dn > 0: - mnix[i+d-1] = dn - - i = i + d + for i in range(sz // d): + random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + offset += d return multin diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 83806de38997..5f49b68be4c7 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -1048,25 +1048,31 @@ int64_t random_geometric(brng_t *brng_state, double p) { } int64_t random_zipf(brng_t *brng_state, double a) { - double T, U, V; - int64_t X; double am1, b; am1 = a - 1.0; b = pow(2.0, am1); - do { - U = 1.0 - next_double(brng_state); - V = next_double(brng_state); - X = (int64_t)floor(pow(U, -1.0 / am1)); - /* The real result may be above what can be represented in a int64. - * It will get casted to -sys.maxint-1. Since this is - * a straightforward rejection algorithm, we can just reject this value - * in the rejection condition below. This function then models a Zipf + while (1) { + double T, U, V, X; + + U = 1.0 - random_double(brng_state); + V = random_double(brng_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); - } while (((V * X * (T - 1.0) / (b - 1.0)) > (T / b)) || X < 1); - return X; + if (V * X * (T - 1.0) / (b - 1.0) <= T / b) { + return (long)X; + } + } } double random_triangular(brng_t *brng_state, double left, double mode, @@ -1179,8 +1185,10 @@ int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, int64_t sample) { if (sample > 10) { return random_hypergeometric_hrua(brng_state, good, bad, sample); - } else { + } else if (sample > 0) { return random_hypergeometric_hyp(brng_state, good, bad, sample); + } else { + return 0; } } @@ -1809,3 +1817,21 @@ void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, out[i] = buffered_bounded_bool(brng_state, off, rng, mask, &bcnt, &buf); } } + +void random_multinomial(brng_t *brng_state, int64_t n, int64_t *mnix, + double *pix, npy_intp d, binomial_t *binomial) { + double remaining_p = 1.0; + npy_intp j; + int64_t dn = n; + for (j = 0; j < (d - 1); j++) { + mnix[j] = random_binomial(brng_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 index 7ca31a16cba6..8ec4a83e8b3e 100644 --- a/numpy/random/src/distributions/distributions.h +++ b/numpy/random/src/distributions/distributions.h @@ -217,4 +217,7 @@ DECLDIR void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, npy_intp cnt, bool use_masked, npy_bool *out); +DECLDIR void random_multinomial(brng_t *brng_state, int64_t n, int64_t *mnix, + double *pix, npy_intp d, binomial_t *binomial); + #endif diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 3eda84d84d4f..895e7fc6cf4a 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -90,6 +90,11 @@ def test_size(self): 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]) class TestSetState(object): @@ -804,8 +809,7 @@ def test_geometric_exceptions(self): 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) + with np.errstate(invalid='ignore'): assert_raises(ValueError, random.geometric, np.nan) assert_raises(ValueError, random.geometric, [np.nan] * 10) @@ -888,8 +892,7 @@ def test_logseries(self): assert_array_equal(actual, desired) def test_logseries_exceptions(self): - with suppress_warnings() as sup: - sup.record(RuntimeWarning) + with np.errstate(invalid='ignore'): assert_raises(ValueError, random.logseries, np.nan) assert_raises(ValueError, random.logseries, [np.nan] * 10) @@ -964,8 +967,7 @@ def test_negative_binomial(self): assert_array_equal(actual, desired) def test_negative_binomial_exceptions(self): - with suppress_warnings() as sup: - sup.record(RuntimeWarning) + with np.errstate(invalid='ignore'): assert_raises(ValueError, random.negative_binomial, 100, np.nan) assert_raises(ValueError, random.negative_binomial, 100, [np.nan] * 10) @@ -1046,8 +1048,7 @@ def test_poisson_exceptions(self): 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) + with np.errstate(invalid='ignore'): assert_raises(ValueError, random.poisson, np.nan) assert_raises(ValueError, random.poisson, [np.nan] * 10) @@ -1849,6 +1850,23 @@ def test_logseries(self): assert_raises(ValueError, logseries, bad_p_one * 3) assert_raises(ValueError, logseries, bad_p_two * 3) + def test_multinomial(self): + random.brng.seed(self.seed) + actual = random.multinomial([5, 20], [1 / 6.] * 6, size=(3, 2)) + desired = np.array([[[1, 1, 1, 1, 0, 1], + [4, 5, 1, 4, 3, 3]], + [[1, 1, 1, 0, 0, 2], + [2, 0, 4, 3, 7, 4]], + [[1, 2, 0, 0, 2, 2], + [3, 2, 3, 4, 2, 6]]], dtype=np.int64) + assert_array_equal(actual, desired) + + random.brng.seed(self.seed) + actual = random.multinomial([5, 20], [1 / 6.] * 6) + desired = np.array([[1, 1, 1, 1, 0, 1], + [4, 5, 1, 4, 3, 3]], dtype=np.int64) + assert_array_equal(actual, desired) + class TestThread(object): # make sure each state produces the same sequence even in threads diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index d0ad5e794fa8..8d10823d6a57 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -112,6 +112,10 @@ def test_size(self): 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]) class TestSetState(object): From 8a3c11d17c26dd6f857fe938540e084669f9e31f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 12 Apr 2019 14:47:39 +0100 Subject: [PATCH 108/138] DOC: Add alias docstrings for sample and ranf Add docstring and add to __all__ --- numpy/random/mtrand.pyx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 351d05e93b97..55202b9d2923 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -4142,9 +4142,7 @@ randn = _rand.randn random = _rand.random_sample random_integers = _rand.random_integers random_sample = _rand.random_sample -ranf = _rand.random_sample rayleigh = _rand.rayleigh -sample = _rand.random_sample seed = _rand.seed set_state = _rand.set_state shuffle = _rand.shuffle @@ -4160,6 +4158,21 @@ wald = _rand.wald weibull = _rand.weibull zipf = _rand.zipf +# 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) + +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', @@ -4193,7 +4206,9 @@ __all__ = [ 'randn', 'random_integers', 'random_sample', + 'ranf', 'rayleigh', + 'sample', 'seed', 'set_state', 'shuffle', From bb7abf2d5bff82a48dbd773c31f66164abdd849d Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 12 Apr 2019 17:46:58 +0300 Subject: [PATCH 109/138] ENH: add instance of RandomGenerator(Xoshiro512StarStar) as gen --- numpy/random/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 89015d6a29e1..431d9701376e 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -3,6 +3,11 @@ Random Number Generation ======================== +Instantiate a RandomNumberGenerator (RNG) and wrap it in a RandomGenerator +which will convert the uniform stream to a number of distributions. For +covenience, the module provides an instantiated instance of a RandomGenerator +available as ``gen``. + ==================== ========================================================= Utility functions ============================================================================== @@ -149,7 +154,7 @@ 'vonmises', 'wald', 'weibull', - 'zipf' + 'zipf', ] from . import mtrand @@ -167,9 +172,12 @@ from .xoshiro256starstar import Xoshiro256StarStar from .xoshiro512starstar import Xoshiro512StarStar from .mtrand import RandomState + +gen = RandomGenerator(Xoshiro512StarStar()) + __all__ += ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState'] + 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState', 'gen'] # Some aliases: ranf = random = sample = random_sample From f11921d6f2578a1cc74dc15bd1458c62d180c01f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 12 Apr 2019 17:06:30 +0100 Subject: [PATCH 110/138] MAINT: Simplify return types Standardize returns types for Windows and 32-bit platforms on int64 in choice and randint (default). Refactor tomaxint to call randint --- numpy/random/generator.pyx | 27 +++++--------------- numpy/random/tests/test_against_numpy.py | 1 + numpy/random/tests/test_generator_mt19937.py | 12 +++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 29a36787ebbc..6e5f421afdb0 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -368,26 +368,11 @@ cdef class RandomGenerator: [ True, True]]]) """ - 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._brng) - - randoms = np.empty(size, dtype=np.int64) - randoms_data = 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._brng) - return randoms + return self.randint(0, np.iinfo(np.int).max + 1, dtype=np.int, size=size) - def randint(self, low, high=None, size=None, dtype=int, use_masked=True): + def randint(self, low, high=None, size=None, dtype=np.int64, use_masked=True): """ - randint(low, high=None, size=None, dtype='l', use_masked=True) + randint(low, high=None, size=None, dtype='int64', use_masked=True) Return random integers from `low` (inclusive) to `high` (exclusive). @@ -661,9 +646,9 @@ cdef class RandomGenerator: 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 + idx = np.array(idx, copy=False, dtype=np.int64) # searchsorted returns a scalar else: - idx = self.randint(0, pop_size, size=shape) + idx = self.randint(0, pop_size, size=shape, dtype=np.int64) else: if size > pop_size: raise ValueError("Cannot take a larger sample than " @@ -692,7 +677,7 @@ cdef class RandomGenerator: n_uniq += new.size idx = found else: - idx = self.permutation(pop_size)[:size] + idx = (self.permutation(pop_size)[:size]).astype(np.int64) if shape is not None: idx.shape = shape diff --git a/numpy/random/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py index b930fcbff3ce..9846ba38f77a 100644 --- a/numpy/random/tests/test_against_numpy.py +++ b/numpy/random/tests/test_against_numpy.py @@ -183,6 +183,7 @@ def test_standard_exponential(self): self.rs.standard_exponential) self._is_state_common_legacy() + @pytest.mark.xfail(reason='Stream broken for simplicity') def test_tomaxint(self): self._set_common_state() self._is_state_common() diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 895e7fc6cf4a..d76291d1a125 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -639,6 +639,18 @@ def test_choice_nan_probabilities(self): p = [None, None, None] assert_raises(ValueError, random.choice, a, p=p) + 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_bytes(self): random.brng.seed(self.seed) actual = random.bytes(10) From 0f931b344b2723a21921b927d6bf5548ddd26d02 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 13 Apr 2019 15:20:21 +0100 Subject: [PATCH 111/138] BUG: Fix type in zipf Correct type form long to int64 --- numpy/random/src/distributions/distributions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 5f49b68be4c7..73396a50b317 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -1070,7 +1070,7 @@ int64_t random_zipf(brng_t *brng_state, double a) { T = pow(1.0 + 1.0 / X, am1); if (V * X * (T - 1.0) / (b - 1.0) <= T / b) { - return (long)X; + return (int64_t)X; } } } From b2f9bea1aaa1dfe7c1b007902160ee434762351c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 13 Apr 2019 15:35:52 +0100 Subject: [PATCH 112/138] ENH: Improvce choice without replacement Improve performance in all cases Large improvement with size is small xref numpy/numpy#5299 xref numpy/numpy#2764 xref numpy/numpy#9855 xref numpy/numpy#7810 --- numpy/random/generator.pyx | 95 ++++++++++++++++---- numpy/random/tests/test_against_numpy.py | 1 + numpy/random/tests/test_generator_mt19937.py | 32 +++++-- 3 files changed, 106 insertions(+), 22 deletions(-) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 6e5f421afdb0..ffbfc972e248 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -515,9 +515,9 @@ cdef class RandomGenerator: return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] @cython.wraparound(True) - def choice(self, a, size=None, replace=True, p=None): + def choice(self, a, size=None, replace=True, p=None, axis=0): """ - choice(a, size=None, replace=True, p=None) + choice(a, size=None, replace=True, p=None, axis=0): Generates a random sample from a given 1-D array @@ -538,6 +538,9 @@ cdef class RandomGenerator: 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. Returns ------- @@ -547,11 +550,11 @@ cdef class RandomGenerator: 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 + 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 + size. See Also -------- @@ -592,7 +595,14 @@ cdef class RandomGenerator: dtype=' 200 and (size > 200 or size > (10 * pop_size // size)): + # Tail shuffle size elements + idx = np.arange(pop_size, dtype=np.int64) + idx_ptr = np.PyArray_BYTES(idx) + buf_ptr = &buf + self._shuffle_raw(pop_size_i, max(pop_size_i - size_i,1), + 8, 8, idx_ptr, buf_ptr) + # Copy to allow potentially large array backing idx to be gc + idx = idx[(pop_size - size):].copy() + else: + # Floyds's algorithm with precomputed indices + # Worst case, O(n**2) when size is close to pop_size + idx = np.empty(size, dtype=np.int64) + idx_data = np.PyArray_DATA(idx) + idx_set = set() + loc = 0 + # Sample indices with one pass to avoid reacquiring the lock + with self.lock: + for j in range(pop_size_i - size_i, pop_size_i): + idx_data[loc] = random_interval(self._brng, j) + loc += 1 + loc = 0 + while len(idx_set) < size_i: + for j in range(pop_size_i - size_i, pop_size_i): + if idx_data[loc] not in idx_set: + val = idx_data[loc] + else: + idx_data[loc] = val = j + idx_set.add(val) + loc += 1 if shape is not None: idx.shape = shape @@ -699,7 +739,9 @@ cdef class RandomGenerator: res[()] = a[idx] return res - return a[idx] + # 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): """ @@ -3971,9 +4013,9 @@ cdef class RandomGenerator: # 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, sizeof(np.npy_intp), stride, x_ptr, buf_ptr) + self._shuffle_raw(n, 1, sizeof(np.npy_intp), stride, x_ptr, buf_ptr) else: - self._shuffle_raw(n, itemsize, stride, x_ptr, buf_ptr) + 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: @@ -3992,10 +4034,29 @@ cdef class RandomGenerator: j = random_interval(self._brng, i) x[i], x[j] = x[j], x[i] - cdef inline _shuffle_raw(self, np.npy_intp n, np.npy_intp itemsize, - np.npy_intp stride, char* data, char* buf): + 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(1, n)): + for i in reversed(range(first, n)): j = random_interval(self._brng, i) string.memcpy(buf, data + j * stride, itemsize) string.memcpy(data + j * stride, data + i * stride, itemsize) diff --git a/numpy/random/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py index 9846ba38f77a..3c83932e8bb8 100644 --- a/numpy/random/tests/test_against_numpy.py +++ b/numpy/random/tests/test_against_numpy.py @@ -328,6 +328,7 @@ def test_multinomial(self): g(100, np.array(p), size=(7, 23))) self._is_state_common() + @pytest.mark.xfail(reason='Stream broken for performance') def test_choice(self): self._set_common_state() self._is_state_common() diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index d76291d1a125..d591ca3399e9 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -542,25 +542,25 @@ def test_random_sample_unsupported_type(self): def test_choice_uniform_replace(self): random.brng.seed(self.seed) actual = random.choice(4, 4) - desired = np.array([2, 3, 2, 3]) + desired = np.array([2, 3, 2, 3], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_nonuniform_replace(self): random.brng.seed(self.seed) actual = random.choice(4, 4, p=[0.4, 0.4, 0.1, 0.1]) - desired = np.array([1, 1, 2, 2]) + desired = np.array([1, 1, 2, 2], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_uniform_noreplace(self): random.brng.seed(self.seed) actual = random.choice(4, 3, replace=False) - desired = np.array([0, 1, 3]) + desired = np.array([0, 2, 3], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_nonuniform_noreplace(self): random.brng.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]) + desired = np.array([2, 3, 1], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_noninteger(self): @@ -569,11 +569,22 @@ def test_choice_noninteger(self): desired = np.array(['c', 'd', 'c', 'd']) assert_array_equal(actual, desired) + def test_choice_multidimensional_default_axis(self): + random.brng.seed(self.seed) + actual = random.choice([[0, 1], [2, 3], [4, 5], [6, 7]], 3) + desired = np.array([[4, 5], [6, 7], [4, 5]]) + assert_array_equal(actual, desired) + + def test_choice_multidimensional_custom_axis(self): + random.brng.seed(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, [[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]]) @@ -651,6 +662,17 @@ def test_choice_return_type(self): actual = random.choice(4, 2, p=p, replace=False) assert actual.dtype == np.int64 + def test_choice_large_sample(self): + import hashlib + + choice_hash = '6395868be877d27518c832213c17977c' + random.brng.seed(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.brng.seed(self.seed) actual = random.bytes(10) From 7a4179485e80aac7f39a7d8b4c7d1d7a35bff223 Mon Sep 17 00:00:00 2001 From: mattip Date: Sat, 13 Apr 2019 20:26:09 +0300 Subject: [PATCH 113/138] DOC: fix doctests, move numpy.random -> numpy.random.gen in generator.pyx --- numpy/random/common.pyx | 8 +- numpy/random/generator.pyx | 197 +++++++++++++++++++------------------ numpy/random/mtrand.pyx | 3 +- 3 files changed, 105 insertions(+), 103 deletions(-) diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx index ebd2e60d107d..d5918c3a9ed8 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -305,10 +305,10 @@ cdef int check_array_constraint(np.ndarray val, object name, constraint_type con 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)) + 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)) + 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)) @@ -336,10 +336,10 @@ cdef int check_constraint(double val, object name, constraint_type cons) except 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)) + 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)) + 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)) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index ffbfc972e248..6fa24b967856 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -154,16 +154,16 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.random_sample() + >>> np.random.gen.random_sample() 0.47108547995356098 # random - >>> type(np.random.random_sample()) + >>> type(np.random.gen.random_sample()) - >>> np.random.random_sample((5,)) + >>> np.random.gen.random_sample((5,)) 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 + >>> 5 * np.random.gen.random_sample((3, 2)) - 5 array([[-3.99149989, -0.52338984], # random [-2.99091858, -0.79479508], [-1.23204345, -1.75224494]]) @@ -309,7 +309,7 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = np.random.standard_exponential((3, 8000)) + >>> n = np.random.gen.standard_exponential((3, 8000)) """ key = np.dtype(dtype).name @@ -424,30 +424,30 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.randint(2, size=10) + >>> np.random.gen.randint(2, size=10) array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random - >>> np.random.randint(1, size=10) + >>> np.random.gen.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)) + >>> np.random.gen.randint(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 - >>> np.random.randint(1, [3, 5, 10]) + >>> np.random.gen.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) + >>> np.random.gen.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) + >>> np.random.gen.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) # random @@ -507,7 +507,7 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.bytes(10) + >>> np.random.gen.bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ @@ -564,33 +564,33 @@ cdef class RandomGenerator: -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> np.random.choice(5, 3) + >>> np.random.gen.choice(5, 3) array([0, 3, 4]) # random - >>> #This is equivalent to np.random.randint(0,5,3) + >>> #This is equivalent to np.random.gen.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]) + >>> np.random.gen.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: - >>> np.random.choice(5, 3, replace=False) + >>> np.random.gen.choice(5, 3, replace=False) array([3,1,0]) # random - >>> #This is equivalent to np.random.permutation(np.arange(5))[:3] + >>> #This is equivalent to np.random.gen.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]) + >>> np.random.gen.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'] - >>> np.random.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) + >>> np.random.gen.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random dtype='>> s = np.random.uniform(-1,0,1000) + >>> s = np.random.gen.uniform(-1,0,1000) All values are within the given interval: @@ -863,7 +863,7 @@ cdef class RandomGenerator: .. note:: This is a convenience function for users porting code from Matlab, - and wraps `numpy.random.random_sample`. That function takes a + and wraps `numpy.random.gen.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`. @@ -892,7 +892,7 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.rand(3,2) + >>> np.random.gen.rand(3,2) array([[ 0.14022471, 0.96360618], #random [ 0.37601032, 0.25528411], #random [ 0.49313049, 0.94909878]]) #random @@ -911,7 +911,7 @@ cdef class RandomGenerator: .. note:: This is a convenience function for users porting code from Matlab, - and wraps `numpy.random.standard_normal`. That function takes a + and wraps `numpy.random.gen.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`. @@ -947,16 +947,16 @@ cdef class RandomGenerator: ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use: - ``sigma * np.random.randn(...) + mu`` + ``sigma * np.random.gen.randn(...) + mu`` Examples -------- - >>> np.random.randn() + >>> np.random.gen.randn() 2.1923875335537315 # random Two-by-four array of samples from N(3, 6.25): - >>> 3 + 2.5 * np.random.randn(2, 4) + >>> 3 + 2.5 * np.random.gen.randn(2, 4) array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random @@ -1013,15 +1013,15 @@ cdef class RandomGenerator: To sample from N evenly spaced floating-point numbers between a and b, use:: - a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) + a + (b - a) * (np.random.gen.random_integers(N) - 1) / (N - 1.) Examples -------- - >>> np.random.random_integers(5) + >>> np.random.gen.random_integers(5) 4 # random - >>> type(np.random.random_integers(5)) + >>> type(np.random.gen.random_integers(5)) - >>> np.random.random_integers(5, size=(3,2)) + >>> np.random.gen.random_integers(5, size=(3,2)) array([[5, 4], # random [3, 3], [4, 5]]) @@ -1030,13 +1030,13 @@ cdef class RandomGenerator: numbers between 0 and 2.5, inclusive (*i.e.*, from the set :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - >>> 2.5 * (np.random.random_integers(5, size=(5,)) - 1) / 4. + >>> 2.5 * (np.random.gen.random_integers(5, size=(5,)) - 1) / 4. array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) # random Roll two six sided dice 1000 times and sum the results: - >>> d1 = np.random.random_integers(1, 6, 1000) - >>> d2 = np.random.random_integers(1, 6, 1000) + >>> d1 = np.random.gen.random_integers(1, 6, 1000) + >>> d2 = np.random.gen.random_integers(1, 6, 1000) >>> dsums = d1 + d2 Display results as a histogram: @@ -1093,8 +1093,8 @@ cdef class RandomGenerator: ----- 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=...) + mu + sigma * np.random.gen.standard_normal(size=...) + np.random.gen.normal(mu, sigma, size=...) See Also -------- @@ -1104,22 +1104,22 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.standard_normal() + >>> np.random.gen.standard_normal() 2.1923875335537315 #random - >>> s = np.random.standard_normal(8000) + >>> s = np.random.gen.standard_normal(8000) >>> s 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 = np.random.gen.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)) + >>> 3 + 2.5 * np.random.gen.standard_normal(size=(2, 4)) array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # random [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random @@ -1186,7 +1186,7 @@ cdef class RandomGenerator: 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 - `numpy.random.normal` is more likely to return samples lying close to + `numpy.random.gen.normal` is more likely to return samples lying close to the mean, rather than those far away. References @@ -1202,7 +1202,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = np.random.normal(mu, sigma, 1000) + >>> s = np.random.gen.normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1224,7 +1224,7 @@ cdef class RandomGenerator: Two-by-four array of samples from N(3, 6.25): - >>> np.random.normal(3, 2.5, size=(2, 4)) + >>> np.random.gen.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 @@ -1298,7 +1298,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = np.random.standard_gamma(shape, 1000000) + >>> s = np.random.gen.standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1386,7 +1386,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean=4, std=2*sqrt(2) - >>> s = np.random.gamma(shape, scale, 1000) + >>> s = np.random.gen.gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1476,7 +1476,7 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = np.random.f(dfnum, dfden, 1000) + >>> s = np.random.gen.f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : @@ -1555,9 +1555,9 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = np.random.gen.noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = np.random.f(dfnum, dfden, 1000000) + >>> c_vals = np.random.gen.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]) @@ -1629,7 +1629,7 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.chisquare(2,4) + >>> np.random.gen.chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ @@ -1688,7 +1688,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -1696,9 +1696,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(np.random.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(np.random.chisquare(3, 100000), + >>> values2 = plt.hist(np.random.gen.chisquare(3, 100000), ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1707,7 +1707,7 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(np.random.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -1773,7 +1773,7 @@ cdef class RandomGenerator: Draw samples and plot the distribution: >>> import matplotlib.pyplot as plt - >>> s = np.random.standard_cauchy(1000000) + >>> s = np.random.gen.standard_cauchy(1000000) >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well >>> plt.hist(s, bins=100) >>> plt.show() @@ -1846,7 +1846,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = np.random.standard_t(10, size=100000) + >>> s = np.random.gen.standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -1940,7 +1940,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = np.random.vonmises(mu, kappa, 1000) + >>> s = np.random.gen.vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -2040,7 +2040,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (np.random.pareto(a, 1000) + 1) * m + >>> s = (np.random.gen.pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2133,7 +2133,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = np.random.weibull(a, 1000) + >>> s = np.random.gen.weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2143,7 +2143,7 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(np.random.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(np.random.gen.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) @@ -2213,7 +2213,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = np.random.power(a, samples) + >>> s = np.random.gen.power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2229,20 +2229,20 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats # doctest: +SKIP - >>> rvs = np.random.power(5, 1000000) - >>> rvsp = np.random.pareto(5, 1000000) + >>> rvs = np.random.gen.power(5, 1000000) + >>> rvsp = np.random.gen.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('np.random.power(5)') + >>> plt.title('np.random.gen.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 + np.random.pareto(5)') + >>> plt.title('inverse of 1 + np.random.gen.pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) @@ -2317,7 +2317,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = np.random.laplace(loc, scale, 1000) + >>> s = np.random.gen.laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2420,7 +2420,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = np.random.gumbel(mu, beta, 1000) + >>> s = np.random.gen.gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2438,7 +2438,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = np.random.normal(mu, beta, 1000) + ... a = np.random.gen.normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, density=True) @@ -2520,7 +2520,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = np.random.logistic(loc, scale, 10000) + >>> s = np.random.gen.logistic(loc, scale, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s, bins=50) @@ -2603,7 +2603,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = np.random.lognormal(mu, sigma, 1000) + >>> s = np.random.gen.lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2627,7 +2627,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + np.random.standard_normal(100) + ... a = 10. + np.random.gen.standard_normal(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -2695,7 +2695,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> from matplotlib.pyplot import hist - >>> values = hist(np.random.rayleigh(3, 100000), bins=200, density=True) + >>> values = hist(np.random.gen.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 @@ -2703,7 +2703,7 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = np.random.rayleigh(modevalue, 1000000) + >>> s = np.random.gen.rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: @@ -2775,7 +2775,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.wald(3, 2, 100000), bins=200, density=True) + >>> h = plt.hist(np.random.gen.wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ @@ -2842,7 +2842,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(np.random.gen.triangular(-3, 0, 8, 100000), bins=200, ... density=True) >>> plt.show() @@ -2955,7 +2955,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = np.random.binomial(n, p, 1000) + >>> s = np.random.gen.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 @@ -2965,7 +2965,7 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(np.random.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(np.random.gen.binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ @@ -3092,7 +3092,7 @@ cdef class RandomGenerator: 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.negative_binomial(1, 0.1, 100000) + >>> s = np.random.gen.negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): # doctest: +SKIP ... probability = sum(s>> a = 2. # parameter - >>> s = np.random.zipf(a, 1000) + >>> s = np.random.gen.zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3292,7 +3292,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = np.random.geometric(p=0.35, size=10000) + >>> z = np.random.gen.geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3382,7 +3382,7 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = np.random.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = np.random.gen.hypergeometric(ngood, nbad, nsamp, 1000) >>> from matplotlib.pyplot import hist >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3391,7 +3391,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = np.random.hypergeometric(15, 15, 15, 100000) + >>> s = np.random.gen.hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3486,7 +3486,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = np.random.logseries(a, 10000) + >>> s = np.random.gen.logseries(a, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s) @@ -3576,7 +3576,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = np.random.multivariate_normal(mean, cov, 5000).T + >>> x, y = np.random.gen.multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3596,7 +3596,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = np.random.multivariate_normal(mean, cov, (3, 3)) + >>> x = np.random.gen.multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3710,14 +3710,14 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> np.random.multinomial(20, [1/6.]*6, size=1) + >>> np.random.gen.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: - >>> np.random.multinomial(20, [1/6.]*6, size=2) + >>> np.random.gen.multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], [2, 4, 3, 4, 0, 7]]) # random @@ -3727,7 +3727,7 @@ cdef class RandomGenerator: Now, do one experiment throwing the dice 10 time, and 10 times again, and another throwing the dice 20 times, and 20 times again: - >>> np.random.multinomial([[10], [20]], [1/6.]*6, size=2) + >>> np.random.gen.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], @@ -3738,7 +3738,7 @@ cdef class RandomGenerator: A loaded die is more likely to land on number 6: - >>> np.random.multinomial(100, [1/7.]*5 + [2/7.]) + >>> np.random.gen.multinomial(100, [1/7.]*5 + [2/7.]) array([11, 16, 14, 17, 16, 26]) # random The probability inputs should be normalized. As an implementation @@ -3747,13 +3747,14 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + >>> np.random.gen.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT array([38, 62]) # random not like: - >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG - array([100, 0]) + >>> np.random.gen.multinomial(100, [1.0, 2.0]) # WRONG + Traceback (most recent call last): + ValueError: pvals < 0, pvals > 1 or pvals contains NaNs """ @@ -3884,7 +3885,7 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = np.random.dirichlet((10, 5, 3), 20).transpose() + >>> s = np.random.gen.dirichlet((10, 5, 3), 20).transpose() >>> import matplotlib.pyplot as plt >>> plt.barh(range(20), s[0]) @@ -3976,14 +3977,14 @@ cdef class RandomGenerator: Examples -------- >>> arr = np.arange(10) - >>> np.random.shuffle(arr) + >>> np.random.gen.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)) - >>> np.random.shuffle(arr) + >>> np.random.gen.shuffle(arr) >>> arr array([[3, 4, 5], # random [6, 7, 8], @@ -4085,14 +4086,14 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.permutation(10) + >>> np.random.gen.permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random - >>> np.random.permutation([1, 4, 9, 12, 15]) + >>> np.random.gen.permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) # random >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.permutation(arr) + >>> np.random.gen.permutation(arr) array([[6, 7, 8], # random [0, 1, 2], [3, 4, 5]]) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 55202b9d2923..2d3ea32cba5a 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3787,7 +3787,8 @@ cdef class RandomState: 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 np.npy_intp d, i, sz, offset From edfd3134cda92384aa35f08209bc22d0fae80143 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 13 Apr 2019 23:24:02 +0100 Subject: [PATCH 114/138] ENH: Finish hypergeometric 0 Add changes to alow hypergeometric 0 Small syncs and cleanups Move legacy_distributions.pxd to legacy folder can be deleted --- numpy/random/generator.pyx | 10 ++++------ numpy/random/{legacy => }/legacy_distributions.pxd | 2 +- numpy/random/mtrand.pyx | 6 ++---- numpy/random/tests/test_generator_mt19937.py | 4 ++-- 4 files changed, 9 insertions(+), 13 deletions(-) rename numpy/random/{legacy => }/legacy_distributions.pxd (98%) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 6fa24b967856..fed978e70a9a 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -115,9 +115,7 @@ cdef class RandomGenerator: def __reduce__(self): from ._pickle import __generator_ctor - return (__generator_ctor, - (self.brng.state['brng'],), - self.brng.state) + return __generator_ctor, (self.brng.state['brng'],), self.brng.state def random_sample(self, size=None, dtype=np.float64, out=None): """ @@ -3323,7 +3321,7 @@ cdef class RandomGenerator: nbad : int or array_like of ints Number of ways to make a bad selection. Must be nonnegative. nsample : int or array_like of ints - Number of items sampled. Must be at least 1 and at most + 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 @@ -3415,14 +3413,14 @@ cdef class RandomGenerator: return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, lngood, 'ngood', CONS_NON_NEGATIVE, lnbad, 'nbad', CONS_NON_NEGATIVE, - lnsample, 'nsample', CONS_GTE_1) + lnsample, 'nsample', CONS_NON_NEGATIVE) if np.any(np.less(np.add(ongood, onbad), onsample)): raise ValueError("ngood + nbad < nsample") return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, ongood, 'ngood', CONS_NON_NEGATIVE, onbad, 'nbad', CONS_NON_NEGATIVE, - onsample, 'nsample', CONS_GTE_1) + onsample, 'nsample', CONS_NON_NEGATIVE) def logseries(self, p, size=None): """ diff --git a/numpy/random/legacy/legacy_distributions.pxd b/numpy/random/legacy_distributions.pxd similarity index 98% rename from numpy/random/legacy/legacy_distributions.pxd rename to numpy/random/legacy_distributions.pxd index bc00994dbacb..08dde3315c34 100644 --- a/numpy/random/legacy/legacy_distributions.pxd +++ b/numpy/random/legacy_distributions.pxd @@ -5,7 +5,7 @@ from libc.stdint cimport uint64_t import numpy as np cimport numpy as np -from ..distributions cimport brng_t +from .distributions cimport brng_t cdef extern from "../src/legacy/distributions-boxmuller.h": diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 2d3ea32cba5a..3f73981cd918 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -15,7 +15,7 @@ from .bounded_integers cimport * from .bounded_integers import _randint_types from .common cimport * from .distributions cimport * -from .legacy.legacy_distributions cimport * +from .legacy_distributions cimport * from .mt19937 import MT19937 as _MT19937 np.import_array() @@ -113,9 +113,7 @@ cdef class RandomState: def __reduce__(self): state = self.get_state(legacy=False) from ._pickle import __randomstate_ctor - return (__randomstate_ctor, - (state['brng'],), - state) + return __randomstate_ctor, (state['brng'],), state cdef _reset_gauss(self): self._aug_state.has_gauss = 0 diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index d591ca3399e9..ff5dc01504df 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -1837,7 +1837,7 @@ def test_hypergeometric(self): nsample = [2] bad_ngood = [-1] bad_nbad = [-2] - bad_nsample_one = [0] + bad_nsample_one = [-1] bad_nsample_two = [4] hypergeom = random.hypergeometric desired = np.array([1, 1, 1]) @@ -1868,7 +1868,7 @@ def test_hypergeometric(self): 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, -1) assert_raises(ValueError, hypergeom, 10, 10, 25) def test_logseries(self): From b9b9d70f096875b0afe3b634982ad22bb6c2c815 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Apr 2019 12:51:47 +0300 Subject: [PATCH 115/138] MAINT: remove legacy, refactor legacy -> mtrand in docs --- doc/source/reference/random/change-log.rst | 2 +- doc/source/reference/random/index.rst | 9 +- doc/source/reference/random/legacy.rst | 104 ++++++++++++--------- numpy/random/distributions.pxd | 2 +- numpy/random/legacy/__init__.py | 3 - numpy/random/legacy_distributions.pxd | 2 +- numpy/random/setup.py | 11 ++- 7 files changed, 72 insertions(+), 61 deletions(-) delete mode 100644 numpy/random/legacy/__init__.py diff --git a/doc/source/reference/random/change-log.rst b/doc/source/reference/random/change-log.rst index af3c266efe7a..1d9f2fefc179 100644 --- a/doc/source/reference/random/change-log.rst +++ b/doc/source/reference/random/change-log.rst @@ -32,7 +32,7 @@ v1.15 - Synced upstream changes in permutation - Synced upstream doc fixes - Added absolute_import to avoid import noise on Python 2.7 -- Add legacy generator which allows NumPy replication +- Add legacy generator mtrand which allows NumPy replication - Improve type handling of integers - Switch to array-fillers for 0 parameter distribution to improve performance - Small changes to build on manylinux diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 1cbf5c6856e7..3c9160fb1374 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -13,7 +13,7 @@ Quick Start By default, `RandomGenerator` uses normals provided by `xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in -`numpy.random.RandomState` +`mtrand.RandomState` .. code-block:: python @@ -96,9 +96,8 @@ What's New or Different in `~RandomGenerator`. It is not possible to reproduce the random values using ``RandomGenerator`` for the normal distribution or any other distribution that relies on the normal such as the gamma or student's t. - If you require backward compatibility, a legacy generator, `~legacy. - LegacyGenerator`, has been created which can fully reproduce the sequence - produced by NumPy. + Use the backward-compatible legacy generator, `~mtrand`, which fully + reproduces the sequence produced by pre-1.17.0. * The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF @@ -185,7 +184,7 @@ Random Generator :maxdepth: 1 generator - legacy + legacy mtrand Basic Random Number Generators ------------------------------ diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst index b9bfabcc7df4..23ab1ad8e136 100644 --- a/doc/source/reference/random/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -1,16 +1,16 @@ Legacy Random Generation ------------------------ -The :class:`~legacy.LegacyGenerator` provides access to +The :class:`~mtrand.RandomState` provides access to legacy generators. These all depend on Box-Muller normals or -inverse CDF exponentials or gammas. This class should only be used +inverse CDF exponentials or gammas. This class should only be used if it is essential to have randoms that are identical to what -would have been produced by NumPy. +would have been produced by NumPy. -:class:`~legacy.LegacyGenerator` add additional information +:class:`~mtrand.RandomState` adds additional information to the state which is required when using Box-Muller normals since these -are produced in pairs. It is important to use -:attr:`~legacy.LegacyGenerator.state` -when accessing the state so that these extra values are saved. +are produced in pairs. It is important to use +:attr:`~mtrand.RandomState.get_state` +when accessing the state so that these extra values are saved. .. warning:: @@ -26,9 +26,9 @@ when accessing the state so that these extra values are saved. .. code-block:: python - + from numpy.random import MT19937 - from numpy.random.legacy import LegacyGenerator + from numpy.random._mtrand import RandomState as LegacyGenerator from numpy.random import RandomState # Use same seed rs = RandomState(12345) @@ -45,11 +45,11 @@ when accessing the state so that these extra values are saved. rs.standard_exponential() lg.standard_exponential() - -.. currentmodule:: numpy.random.legacy -.. autoclass:: LegacyGenerator +.. currentmodule:: numpy.random.mtrand + +.. autoclass:: RandomState :exclude-members: Seeding and State @@ -58,53 +58,67 @@ Seeding and State .. autosummary:: :toctree: generated/ - ~LegacyGenerator.get_state - ~LegacyGenerator.set_state - + ~RandomState.get_state + ~RandomState.set_state + Simple random data ================== .. autosummary:: :toctree: generated/ - ~LegacyGenerator.randn - ~LegacyGenerator.randint - ~LegacyGenerator.random_integers - ~LegacyGenerator.random_sample - ~LegacyGenerator.choice - ~LegacyGenerator.bytes + ~RandomState.rand + ~RandomState.randn + ~RandomState.randint + ~RandomState.random_integers + ~RandomState.random_sample + ~RandomState.choice + ~RandomState.bytes Permutations ============ .. autosummary:: :toctree: generated/ - ~LegacyGenerator.shuffle - ~LegacyGenerator.permutation + ~RandomState.shuffle + ~RandomState.permutation Distributions ============= .. autosummary:: :toctree: generated/ - ~LegacyGenerator.beta - ~LegacyGenerator.chisquare - ~LegacyGenerator.dirichlet - ~LegacyGenerator.exponential - ~LegacyGenerator.f - ~LegacyGenerator.gamma - ~LegacyGenerator.lognormal - ~LegacyGenerator.multivariate_normal - ~LegacyGenerator.negative_binomial - ~LegacyGenerator.noncentral_chisquare - ~LegacyGenerator.noncentral_f - ~LegacyGenerator.normal - ~LegacyGenerator.pareto - ~LegacyGenerator.power - ~LegacyGenerator.standard_cauchy - ~LegacyGenerator.standard_exponential - ~LegacyGenerator.standard_gamma - ~LegacyGenerator.standard_normal - ~LegacyGenerator.standard_t - ~LegacyGenerator.wald - ~LegacyGenerator.weibull - ~LegacyGenerator.zipf + ~RandomState.beta + ~RandomState.binomial + ~RandomState.chisquare + ~RandomState.dirichlet + ~RandomState.exponential + ~RandomState.f + ~RandomState.gamma + ~RandomState.geometric + ~RandomState.gumbel + ~RandomState.hypergeometric + ~RandomState.laplace + ~RandomState.logistic + ~RandomState.lognormal + ~RandomState.logseries + ~RandomState.multinomial + ~RandomState.multivariate_normal + ~RandomState.negative_binomial + ~RandomState.noncentral_chisquare + ~RandomState.noncentral_f + ~RandomState.normal + ~RandomState.pareto + ~RandomState.poisson + ~RandomState.power + ~RandomState.rayleigh + ~RandomState.standard_cauchy + ~RandomState.standard_exponential + ~RandomState.standard_gamma + ~RandomState.standard_normal + ~RandomState.standard_t + ~RandomState.triangular + ~RandomState.uniform + ~RandomState.vonmises + ~RandomState.wald + ~RandomState.weibull + ~RandomState.zipf diff --git a/numpy/random/distributions.pxd b/numpy/random/distributions.pxd index 5047aed9a325..841fd32536fe 100644 --- a/numpy/random/distributions.pxd +++ b/numpy/random/distributions.pxd @@ -5,7 +5,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, import numpy as np cimport numpy as np -cdef extern from "src/distributions/distributions.h": +cdef extern from "distributions/distributions.h": struct s_binomial_t: int has_binomial diff --git a/numpy/random/legacy/__init__.py b/numpy/random/legacy/__init__.py deleted file mode 100644 index 9ce1f665dd15..000000000000 --- a/numpy/random/legacy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from ..mtrand import RandomState as LegacyGenerator - -__all__ = ['LegacyGenerator'] diff --git a/numpy/random/legacy_distributions.pxd b/numpy/random/legacy_distributions.pxd index 08dde3315c34..69e5d69be8c1 100644 --- a/numpy/random/legacy_distributions.pxd +++ b/numpy/random/legacy_distributions.pxd @@ -7,7 +7,7 @@ cimport numpy as np from .distributions cimport brng_t -cdef extern from "../src/legacy/distributions-boxmuller.h": +cdef extern from "distributions-boxmuller.h": struct aug_brng: brng_t *basicrng diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 38d968febb21..fc7c9a8863bf 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -126,7 +126,7 @@ def generate_libraries(ext, build_dir): sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', 'src/dsfmt/dSFMT-jump.c', 'src/aligned_malloc/aligned_malloc.c'], - include_dirs=[join('src', 'dsfmt')], + include_dirs=['.', 'src', join('src', 'dsfmt')], libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, @@ -140,7 +140,7 @@ def generate_libraries(ext, build_dir): config.add_extension(gen, sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen), 'src/{0}/{0}-jump.c'.format(gen)], - include_dirs=[join('src', gen)], + include_dirs=['.', 'src', join('src', gen)], libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, @@ -159,7 +159,7 @@ def generate_libraries(ext, build_dir): _defs = defs config.add_extension(gen, sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], - include_dirs=[join('src', gen)], + include_dirs=['.', 'src', join('src', gen)], libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, @@ -173,6 +173,7 @@ def generate_libraries(ext, build_dir): libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, + include_dirs=['.', 'src'], depends=['%s.pyx' % gen], define_macros=defs, ) @@ -184,6 +185,7 @@ def generate_libraries(ext, build_dir): 'distributions.c')], 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, @@ -192,14 +194,13 @@ def generate_libraries(ext, build_dir): sources=['mtrand.c', 'src/legacy/distributions-boxmuller.c', 'src/distributions/distributions.c' ], - include_dirs=['.', 'legacy'], + 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 + DSFMT_DEFS, ) - config.add_subpackage('legacy') return config if __name__ == '__main__': From 2deddc88880c2325288b9e751112e3f758b06cd8 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 14 Apr 2019 16:46:05 +0100 Subject: [PATCH 116/138] MAINT: Remove Cython conditionals Remove Cython conditional compilation and use preprocessor only --- numpy/random/pcg64.pyx | 67 +++++++++++++--------------------- numpy/random/src/pcg64/pcg64.c | 44 ++++++++++++++++++++++ numpy/random/src/pcg64/pcg64.h | 9 ++++- 3 files changed, 77 insertions(+), 43 deletions(-) diff --git a/numpy/random/pcg64.pyx b/numpy/random/pcg64.pyx index 726bae02716c..af98bbd84c30 100644 --- a/numpy/random/pcg64.pyx +++ b/numpy/random/pcg64.pyx @@ -17,24 +17,8 @@ np.import_array() # IF PCG_EMULATED_MATH==1: cdef extern from "src/pcg64/pcg64.h": - - ctypedef struct pcg128_t: - uint64_t high - uint64_t low -# ELSE: -# cdef extern from "inttypes.h": -# ctypedef unsigned long long __uint128_t -# -# cdef extern from "src/pcg64/pcg64.h": -# ctypedef __uint128_t pcg128_t - -cdef extern from "src/pcg64/pcg64.h": - - cdef struct pcg_state_setseq_128: - pcg128_t state - pcg128_t inc - - ctypedef pcg_state_setseq_128 pcg64_random_t + # 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 @@ -48,6 +32,8 @@ cdef extern from "src/pcg64/pcg64.h": 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(st) @@ -280,40 +266,39 @@ cdef class PCG64: Dictionary containing the information required to describe the state of the RNG """ - # IF PCG_EMULATED_MATH==1: - # TODO: push this into an #ifdef in the C code - state = 2 **64 * self.rng_state.pcg_state.state.high - state += self.rng_state.pcg_state.state.low - inc = 2 **64 * self.rng_state.pcg_state.inc.high - inc += self.rng_state.pcg_state.inc.low - # ELSE: - # state = self.rng_state.pcg_state.state - # inc = self.rng_state.pcg_state.inc - + 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.empty(4, dtype=np.uint64) + pcg64_get_state(self.rng_state, state_vec.data, &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 {'brng': self.__class__.__name__, 'state': {'state': state, 'inc': inc}, - 'has_uint32': self.rng_state.has_uint32, - 'uinteger': self.rng_state.uinteger} + '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') brng = value.get('brng', '') if brng != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'RNG'.format(self.__class__.__name__)) - # IF PCG_EMULATED_MATH==1: - self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64 - self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64 - self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64 - self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64 - # ELSE: - # self.rng_state.pcg_state.state = value['state']['state'] - # self.rng_state.pcg_state.inc = value['state']['inc'] - - self.rng_state.has_uint32 = value['has_uint32'] - self.rng_state.uinteger = value['uinteger'] + state_vec = 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, state_vec.data, has_uint32, uinteger) def advance(self, delta): """ diff --git a/numpy/random/src/pcg64/pcg64.c b/numpy/random/src/pcg64/pcg64.c index c7c1eb045a41..faec0c248b60 100644 --- a/numpy/random/src/pcg64/pcg64.c +++ b/numpy/random/src/pcg64/pcg64.c @@ -116,3 +116,47 @@ extern void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc) { #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 + * + */ +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 + * + */ +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 index 156c73a36988..e42dc4d63e70 100644 --- a/numpy/random/src/pcg64/pcg64.h +++ b/numpy/random/src/pcg64/pcg64.h @@ -100,7 +100,7 @@ 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); + z0[0] = _umul128(x, y, z1); #else uint64_t x0, x1, y0, y1; uint64_t w0, w1, w2, t; @@ -118,7 +118,6 @@ static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1, w1 += x0 * y1; *z1 = x1 * y1 + w2 + (w1 >> 32); #endif - } static inline pcg128_t _pcg128_mult(pcg128_t a, pcg128_t b) { @@ -238,4 +237,10 @@ 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 */ From 86212292e5c779447cef25f25e172b051e863861 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 14 Apr 2019 20:17:41 +0300 Subject: [PATCH 117/138] DOC: tighten up documentation, add a table of comparison --- doc/source/reference/random/brng/index.rst | 4 +- doc/source/reference/random/index.rst | 131 +++++++++++++----- doc/source/reference/random/legacy.rst | 9 +- .../reference/random/multithreading.rst | 11 +- .../reference/random/new-or-different.rst | 40 ++++-- doc/source/reference/random/parallel.rst | 49 ++++--- 6 files changed, 169 insertions(+), 75 deletions(-) diff --git a/doc/source/reference/random/brng/index.rst b/doc/source/reference/random/brng/index.rst index 5241f9856911..a7e5ad8730ee 100644 --- a/doc/source/reference/random/brng/index.rst +++ b/doc/source/reference/random/brng/index.rst @@ -1,3 +1,5 @@ +.. _brng: + Basic Random Number Generators ------------------------------ @@ -12,8 +14,6 @@ access the functions provided, e.g., `numba `_. Stable RNGs =========== -These RNGs will be included in future releases. - .. toctree:: :maxdepth: 1 diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 3c9160fb1374..701415920857 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -3,28 +3,64 @@ numpy.random ============ +<<<<<<< HEAD A `~RandomGenerator` can be initialized with a number of different Random Number Generators (RNG)s, and exposes many different probability distributions. +======= +Numpy's random number routines produce psuedo random numbers using +combinations of a `BitGenerator` to create sequences and a `Generator` +to use those sequences to sample from different statistical distributions: + +* BitGenerators: Objects that generate random numbers. These are typically + unsigned integer words filled with sequences of either 32 or 64 random bits. +* Generators: Objects that transform sequences of random bits from a + BitGenerator into sequences of numbers that follow a specific probability + distribution (such as uniform, Normal or Binomial) within a specified + interval. + +Since Numpy version 1.17.0 the Generator can be initialized with a +number of different BitGenerators. It exposes many different probability +distributions. See `NEP 19 `_ for context on the updated random Numpy number +routines. The legacy `RandomState` random number routines are still +available, but limited to a single BitGenerator. + +For convenience and backward compatibility, a single `RandomState` +instance's methods are imported into the numpy.random namespace, see +:ref:`legacy` for the complete list. +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology Quick Start ----------- +<<<<<<< HEAD By default, `RandomGenerator` uses normals provided by `xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in `mtrand.RandomState` +======= +By default, `Generator` uses normals provided by `xoroshiro128.Xoroshiro128` +which will be faster than the legacy methods in `RandomState` +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python - # As replacement for numpy.random.RandomState + # Uses the old numpy.random.RandomState from numpy import random random.standard_normal() +<<<<<<< HEAD `RandomGenerator` can be used as a direct replacement for `~RandomState`, although the random values are generated by `~xoroshiro128.Xoroshiro128`. The `RandomGenerator` holds an instance of a RNG. It is accessable as ``gen.brng``. +======= +`Generator` can be used as a direct replacement for `RandomState`, +although the random values are generated by `~xoroshiro128.Xoroshiro128`. The +`Generator` holds an instance of a BitGenerator. It is accessable as +``gen.bit_generator``. +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python @@ -32,6 +68,7 @@ It is accessable as ``gen.brng``. from numpy.random import RandomGenerator rg = RandomGenerator() rg.standard_normal() + rg.bit_generator Seeds can be passed to any of the basic RNGs. Here `mt19937.MT19937` is used @@ -48,19 +85,30 @@ generator`. Introduction ------------ RandomGen takes a different approach to producing random numbers from the +<<<<<<< HEAD :class:`numpy.random.RandomState` object. Random number generation is separated into two components, a basic RNG and a random generator. +======= +`RandomState` object. Random number generation is separated into two +components, a bit generator and a random generator. +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology The basic RNG has a limited set of responsibilities. It manages the underlying RNG state and provides functions to produce random doubles and random unsigned 32- and 64-bit values. The basic random generator also handles all seeding since this varies when using alternative basic RNGs. +<<<<<<< HEAD The `random generator <~RandomGenerator>` takes the basic RNG-provided functions and transforms them into more useful +======= +The `random generator ` takes the +bit generator-provided stream and transforms them into more useful +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology distributions, e.g., simulated normal random values. This structure allows alternative basic RNGs to be used without code duplication. +<<<<<<< HEAD The ``RandomGenerator`` is the user-facing object that is nearly identical to :class:`~.RandomState`. The canonical method to initialize a generator passes a basic RNG -- `~mt19937.MT19937`, the @@ -74,6 +122,12 @@ be instantized. rg.random_sample() Seed information is directly passed to the basic RNG. +======= +The `Generator` is the user-facing object that is nearly identical to +`RandomState`. The canonical method to initialize a generator passes a +`~mt19937.MT19937` bit generator, the underlying bit generator in Python -- as +the sole argument. Note that the bit generator must be instantiated. +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python @@ -93,13 +147,18 @@ What's New or Different .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available - in `~RandomGenerator`. It is not possible to reproduce the random values - using ``RandomGenerator`` for the normal distribution or any other - distribution that relies on the normal such as the gamma or student's t. - Use the backward-compatible legacy generator, `~mtrand`, which fully - reproduces the sequence produced by pre-1.17.0. - -* The normal, exponential and gamma generators use 256-step Ziggurat +<<<<<<< HEAD + in `~.RandomGenerator`. It is not possible to reproduce the exact random + values using ``RandomGenerator`` for the normal distribution or any other +======= + in `Generator`. It is not possible to reproduce the exact random + values using Generator for the normal distribution or any other +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology + distribution that relies on the normal such as the `numpy.random.gamma` or + `numpy.random.standard_t`. If you require bitwise backward compatible + streams, use `RandomState`. + +* The Generator's normal, exponential and gamma functions use 256-step Ziggurat methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF implementations. * Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64`` @@ -110,6 +169,7 @@ What's New or Different * `~entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). +<<<<<<< HEAD * All basic random generators functions can produce doubles, uint64s and uint32s via CTypes (`~xoroshiro128.Xoroshiro128.ctypes`) and CFFI (:meth:`~xoroshiro128.Xoroshiro128.cffi`). @@ -119,7 +179,23 @@ What's New or Different * Support for Lemire’s method [Lemire]_ of generating uniform integers on an arbitrary interval by setting ``use_masked=True`` in `~RandomGenerator.randint`. +======= +* All BitGenerators can produce doubles, uint64s and uint32s via CTypes + (`~xoroshiro128.Xoroshiro128.ctypes`) and CFFI + (:meth:`~xoroshiro128.Xoroshiro128.cffi`). This allows the bit generators to + be used in numba. +* The bit generators can be used in downstream projects via + :ref:`Cython `. +* `~.Generator.integers` is now the canonical way to generate integer + random numbers from a discrete uniform distribution. The ``rand`` and + ``randn`` methods are only availabe through the legacy `~.RandomState`. + The ``endpoint`` keyword can be used to specify open or closed intervals. + This replaces both ``randint`` and the deprecated ``random_integers``. +* `~.Generator.random` is now the canonical way to generate floating-point + random numbers, which replaces `random_sample`, `sample`, and `ranf`. This + is consistent with Python's `random.random`. +>>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology See :ref:`new-or-different` for a complete list of improvements and differences. @@ -133,15 +209,13 @@ one of two ways: * :ref:`independent-streams` * :ref:`jump-and-advance` -Supported Generators --------------------- -The main innovation is the inclusion of a number of alternative pseudo-random number -generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are: +Supported BitGenerators +----------------------- +The included BitGenerators are: -* MT19937 - The standard NumPy generator. Produces identical results to NumPy - using the same seed/state. Adds a - `~mt19937.MT19937.jump` function that advances the - generator as-if ``2**128`` draws have been made. See `numpy.random`. +* MT19937 - The standard Python BitGenerator. Produces identical results to + Python using the same seed/state. Adds a `~mt19937.MT19937.jumped` function + that returns a new generator with state as-if ``2**128`` draws have been made. * dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically the same, but with a different state and so it is not possible to produce a sequence identical to MT19937. Supports ``jump`` and so can @@ -155,20 +229,15 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are * XorShift1024*φ - Fast fast generator based on the XSadd generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - `~xorshift1024.Xorshift1024.jump` for details. More - information about these PRNGs is available at the + `~xorshift1024.Xorshift1024.jumped` for details. More + information about these bit generators is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * Xorshiro256** and Xorshiro512** - The most recently introduced XOR, shift, and rotate generator. Supports ``jump`` and so can be used in parallel applications. See the documentation for - `~xoshiro256starstar.Xoshirt256StarStar.jump` for - details. More information about these PRNGs is available at the - `xorshift, xoroshiro and xoshiro authors' page`_. -* PCG-64 - Fast generator that support many parallel streams and - can be advanced by an arbitrary amount. See the documentation for - `~pcg64.PCG64.advance`. PCG-64 has a period of - :math:`2^{128}`. See the `PCG author's page`_ for more details about - this class of PRNG. + `~xoshiro256.Xoshirt256.jumped` for details. More information about these bit + generators is available at the `xorshift, xoroshiro and xoshiro authors' + page`_. * ThreeFry and Philox - counter-based generators capable of being advanced an arbitrary number of steps or generating independent streams. See the `Random123`_ page for more details about this class of PRNG. @@ -178,21 +247,21 @@ generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are .. _`PCG author's page`: http://www.pcg-random.org/ .. _`Random123`: https://www.deshawresearch.com/resources_random123.html -Random Generator ----------------- +Generator +--------- .. toctree:: :maxdepth: 1 generator legacy mtrand -Basic Random Number Generators ------------------------------- +BitGenerators +------------- .. toctree:: :maxdepth: 1 - Basic Random Number Generators + BitGenerators New Features ------------ diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst index 23ab1ad8e136..3bf7569b0676 100644 --- a/doc/source/reference/random/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -1,15 +1,17 @@ +.. _legacy: + Legacy Random Generation ------------------------ -The :class:`~mtrand.RandomState` provides access to +The `~mtrand.RandomState` provides access to legacy generators. These all depend on Box-Muller normals or inverse CDF exponentials or gammas. This class should only be used if it is essential to have randoms that are identical to what would have been produced by NumPy. -:class:`~mtrand.RandomState` adds additional information +`~mtrand.RandomState` adds additional information to the state which is required when using Box-Muller normals since these are produced in pairs. It is important to use -:attr:`~mtrand.RandomState.get_state` +`~mtrand.RandomState.get_state` when accessing the state so that these extra values are saved. .. warning:: @@ -60,6 +62,7 @@ Seeding and State ~RandomState.get_state ~RandomState.set_state + ~RandomState.seed Simple random data ================== diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst index f7762b73acf8..d35cafe0620c 100644 --- a/doc/source/reference/random/multithreading.rst +++ b/doc/source/reference/random/multithreading.rst @@ -9,10 +9,11 @@ these requirements. This example makes use of Python 3 :mod:`concurrent.futures` to fill an array using multiple threads. Threads are long-lived so that repeated calls do not -require any additional overheads from thread creation. The underlying PRNG is -xorshift2014 which is fast, has a long period and supports using ``jump`` to -advance the state. The random numbers generated are reproducible in the sense -that the same seed will produce the same outputs. +require any additional overheads from thread creation. The underlying +BitGenerator is `Xorshift1024` which is fast, has a long period and supports +using `Xorshift1024.jumped` to return a new generator while advancing the +state. The random numbers generated are reproducible in the sense that the same +seed will produce the same outputs. .. code-block:: ipython @@ -84,7 +85,7 @@ the time required to generate using a single thread. 4 32.8 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) -The single threaded call directly uses the PRNG. +The single threaded call directly uses the BitGenerator. .. code-block:: ipython diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst index 7ddebb5b2135..4922b6762c6d 100644 --- a/doc/source/reference/random/new-or-different.rst +++ b/doc/source/reference/random/new-or-different.rst @@ -8,14 +8,36 @@ What's New or Different .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available - in `~.RandomGenerator`. It is not possible to - reproduce the exact random values using ``RandomGenerator`` for the normal - distribution or any other distribution that relies on the normal such as the - `numpy.random.gamma` or `numpy.random.standard_t`. If you require backward - compatibility, a legacy generator, `~.legacy. - LegacyGenerator`, has been created which can fully reproduce the exact byte - sequence produced by legacy code. - + in `Generator`. It is not possible to reproduce the exact random + values using ``Generator`` for the normal distribution or any other + distribution that relies on the normal such as the `gamma` or + `standard_t`. If you require bitwise backward compatible + streams, use `RandomState`. + +Quick comparison of legacy `mtrand `_ to the new `Generator` + +================== ==================== ============= +Feature Older Equivalent Notes +------------------ -------------------- ------------- +`Generator` `RandomState` ``Generator`` requires a stream + source, called a `BitGenerator + ` A number of these + are provided. ``RandomState`` uses + only the Box- Muller method. +------------------ -------------------- ------------- +``np.random.`` ``np.random.`` Access the values in a BitGenerator, +``Generator().`` ``random_sample()`` convert them to ``float64`` in the +``random()`` interval ``[0.0.,`` `` 1.0)``. + In addition to the ``size`` kwarg, now + supports ``dtype='d'`` or ``dtype='f'``, + and an ``out`` kwarg to fill a user- + supplied array. + + Many other distributions are also + supported. +=================== =================== ============= + +And in more detail: * `~.entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., @@ -81,7 +103,7 @@ What's New or Different * Standard Exponentials (`~.RandomGenerator.standard_exponential`) This allows multithreading to fill large arrays in chunks using suitable - PRNGs in parallel. + BitGenerators in parallel. .. ipython:: python diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst index 41e47039d534..c831effa29d7 100644 --- a/doc/source/reference/random/parallel.rst +++ b/doc/source/reference/random/parallel.rst @@ -46,22 +46,23 @@ to produce independent streams. .. _jump-and-advance: -Jump/Advance the PRNG state ---------------------------- +Jump/Advance the BitGenerator state +----------------------------------- Jump **** -``jump`` advances the state of the PRNG *as-if* a large number of random -numbers have been drawn. The specific number of draws varies by PRNG, and -ranges from :math:`2^{64}` to :math:`2^{512}`. Additionally, the *as-if* -draws also depend on the size of the default random number produced by the -specific PRNG. The PRNGs that support ``jump``, along with the period of -the PRNG, the size of the jump and the bits in the default unsigned random +``jumped`` advances the state of the BitGenerator *as-if* a large number of +random numbers have been drawn, and returns a new instance with this state. +The specific number of draws varies by BitGenerator, and ranges from +:math:`2^{64}` to :math:`2^{512}`. Additionally, the *as-if* draws also depend +on the size of the default random number produced by the specific BitGenerator. +The BitGenerator that support ``jumped``, along with the period of the +BitGenerator, the size of the jump and the bits in the default unsigned random are listed below. +-----------------+-------------------------+-------------------------+-------------------------+ -| PRNG | Period | Jump Size | Bits | +| BitGenerator | Period | Jump Size | Bits | +=================+=========================+=========================+=========================+ | DSFMT | :math:`2^{19937}` | :math:`2^{128}` | 53 | +-----------------+-------------------------+-------------------------+-------------------------+ @@ -78,7 +79,7 @@ are listed below. | Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ -``jump`` can be used to produce long blocks which should be long enough to not +``jumped`` can be used to produce long blocks which should be long enough to not overlap. .. code-block:: python @@ -90,10 +91,9 @@ overlap. # 64-bit number as a seed seed = entropy[0] * 2**32 + entropy[1] blocked_rng = [] + rng = Xorshift1024(seed) for i in range(10): - rng = Xorshift1024(seed) - rng.jump(i) - blocked_rng.append(rng) + blocked_rng.append(rng.jumped()) Advance @@ -104,22 +104,21 @@ is a more general approach than ``jump``. :class:`~pcg64.PCG64`, support ``advance``, and since these also support independent streams, it is not usually necessary to use ``advance``. -Advancing a PRNG updates the underlying PRNG state as-if a given number of -calls to the underlying PRNG have been made. In general there is not a +Advancing a BitGenerator updates the underlying state as-if a given number of +calls to the BitGenerator 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 PRNG. +particular distribution and the number of draws from the core BitGenerator. 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 - PRNG 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 - PRNG. For example, two 16-bit integer values can be simulated - from a single draw of a 32-bit PRNG. - -Advancing the PRNG state resets any pre-computed random numbers. This is -required to ensure exact reproducibility. + and so more than one value from the underlying BitGenerator can be 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 BitGenerator. For example, two + 16-bit integer values can be simulated from a single draw of a 32-bit value. + +Advancing the BitGenerator state resets any pre-computed random numbers. This +is required to ensure exact reproducibility. This example uses ``advance`` to advance a :class:`~pcg64.PCG64` generator 2 ** 127 steps to set a sequence of random number generators. From 4f06779070d3c87122725a69ac9d3f75440f3fad Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 15 Apr 2019 17:00:03 +0100 Subject: [PATCH 118/138] ENH: Add fast path for randint broadcasting Add path that voids object conversion unless essential Small doc cleanups related to random_integers PEP-8 cleanups --- numpy/random/bounded_integers.pyx.in | 34 +++++++++++++------- numpy/random/generator.pyx | 15 ++++++--- numpy/random/tests/test_direct.py | 5 ++- numpy/random/tests/test_generator_mt19937.py | 27 ++++++++++++++++ 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/numpy/random/bounded_integers.pyx.in b/numpy/random/bounded_integers.pyx.in index 03068a8fd088..a4dbb1f52a37 100644 --- a/numpy/random/bounded_integers.pyx.in +++ b/numpy/random/bounded_integers.pyx.in @@ -125,19 +125,29 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, if np.any(np.less(low_arr, {{lb}})): raise ValueError('low is out of bounds for {{nptype}}') - - highm1_arr = 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}}: + dt = high_arr.dtype + if np.issubdtype(dt, np.integer): + # Avoid object dtype path if already an integer + if np.any(np.less_equal(high_arr, {{lb}})): raise ValueError('low >= high') - highm1_data[i] = <{{nptype}}_t>closed_upper + high_m1 = 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.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.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}}: + raise ValueError('low >= high') + highm1_data[i] = <{{nptype}}_t>closed_upper if np.any(np.greater(low_arr, highm1_arr)): raise ValueError('low >= high') diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index fed978e70a9a..a4ba51b55d46 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -349,7 +349,7 @@ cdef class RandomGenerator: -------- randint : Uniform sampling over a given half-open interval of integers. random_integers : Uniform sampling over a given closed interval of - integers. + integers. Examples -------- @@ -413,12 +413,17 @@ cdef class RandomGenerator: `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]). + See Also -------- - 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. + random_integers : similar to `randint`, only for the closed interval + [`low`, `high`], where 1 is the lowest value if + `high` is omitted. Examples -------- diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index d6042100a859..fd2d7eb9a565 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -51,6 +51,7 @@ def uniform32_from_uint64(x): 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)) @@ -92,6 +93,7 @@ def uniform_from_uint32(x): out[i // 2] = (a * 67108864.0 + b) / 9007199254740992.0 return out + def uniform_from_dsfmt(x): return x.view(np.double) - 1.0 @@ -414,7 +416,8 @@ def test_seed_float_array(self): rs = RandomGenerator(self.brng(*self.data1['seed'])) assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi])) assert_raises(self.seed_error_type, rs.brng.seed, np.array([-np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi, -np.pi])) + assert_raises(self.seed_error_type, rs.brng.seed, + np.array([np.pi, -np.pi])) assert_raises(self.seed_error_type, rs.brng.seed, np.array([0, np.pi])) assert_raises(self.seed_error_type, rs.brng.seed, [np.pi]) assert_raises(self.seed_error_type, rs.brng.seed, [0, np.pi]) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index ff5dc01504df..6503389d5078 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -335,6 +335,33 @@ def test_repeatability_broadcasting(self): assert_array_equal(val, val_bc) + def test_int64_uint64_broadcast_exceptions(self): + 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 + low_a = np.array([[low]*10]) + high_a = np.array([high] * 10) + assert_raises(ValueError, random.randint, low, high, + dtype=dtype) + assert_raises(ValueError, random.randint, low_a, high, + dtype=dtype) + assert_raises(ValueError, random.randint, low, high_a, + dtype=dtype) + assert_raises(ValueError, random.randint, low_a, high_a, + dtype=dtype) + + low_o = np.array([[low]*10], dtype=np.object) + high_o = np.array([high] * 10, dtype=np.object) + assert_raises(ValueError, random.randint, low_o, high, + dtype=dtype) + assert_raises(ValueError, random.randint, low, high_o, + dtype=dtype) + assert_raises(ValueError, random.randint, low_o, high_o, + dtype=dtype) + 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. From ca9c542d24d418b4a203255f3a390c6b7fee4b51 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 15 Apr 2019 17:49:31 +0100 Subject: [PATCH 119/138] BUG: Cast high to Python int to avoid overflow Case high to a Python int to avoid overflow from NumPy types --- numpy/random/mtrand.pyx | 2 +- numpy/random/tests/test_randomstate.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 3f73981cd918..7e81223153d1 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -1130,7 +1130,7 @@ cdef class RandomState: "instead".format(low=low, high=high)), DeprecationWarning) - return self.randint(low, high + 1, size=size, dtype='l') + return self.randint(low, int(high) + 1, size=size, dtype='l') # Complicated, continuous distributions: def standard_normal(self, size=None): diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 8d10823d6a57..50f226386219 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -436,6 +436,14 @@ def test_random_integers_max_int(self): 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(): From dd77ce3cb84986308986974acfe988575323f75a Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Tue, 16 Apr 2019 07:22:22 +0100 Subject: [PATCH 120/138] ENH: Add closed generator to randint Add closed option to randint to simplify some cases --- doc/source/about.rst | 2 +- doc/source/conf.py | 4 - doc/source/reference/random/index.rst | 66 +------ doc/source/reference/routines.random.rst | 83 -------- doc/source/reference/routines.rst | 1 - numpy/random/bounded_integers.pxd.in | 2 +- numpy/random/bounded_integers.pyx.in | 59 ++++-- numpy/random/generator.pyx | 38 ++-- numpy/random/mtrand.pyx | 18 +- numpy/random/tests/test_generator_mt19937.py | 190 ++++++++++++------- numpy/random/tests/test_randomstate.py | 1 - 11 files changed, 191 insertions(+), 273 deletions(-) delete mode 100644 doc/source/reference/routines.random.rst diff --git a/doc/source/about.rst b/doc/source/about.rst index 5ac4facbb4dc..3e83833d178d 100644 --- a/doc/source/about.rst +++ b/doc/source/about.rst @@ -8,7 +8,7 @@ needed for scientific computing with Python. This package contains: - sophisticated :ref:`(broadcasting) functions ` - basic :ref:`linear algebra functions ` - basic :ref:`Fourier transforms ` -- sophisticated :ref:`random number capabilities ` +- sophisticated :ref:`random number capabilities ` - tools for integrating Fortran code - tools for integrating C/C++ code diff --git a/doc/source/conf.py b/doc/source/conf.py index dec8fff05b2f..906a906b6b98 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -364,7 +364,3 @@ def linkcode_resolve(domain, info): return "https://github.com/numpy/numpy/blob/v%s/numpy/%s%s" % ( numpy.__version__, fn, linespec) -doctest_global_setup = ''' -import numpy as np -from numpy.random import randomgen -''' diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 701415920857..9c8c99c38e97 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -1,14 +1,10 @@ +.. _numpyrandom: + .. currentmodule:: numpy.random numpy.random ============ -<<<<<<< HEAD -A `~RandomGenerator` can -be initialized with a number of different Random Number Generators (RNG)s, and -exposes many different probability distributions. - -======= Numpy's random number routines produce psuedo random numbers using combinations of a `BitGenerator` to create sequences and a `Generator` to use those sequences to sample from different statistical distributions: @@ -30,19 +26,12 @@ available, but limited to a single BitGenerator. For convenience and backward compatibility, a single `RandomState` instance's methods are imported into the numpy.random namespace, see :ref:`legacy` for the complete list. ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology Quick Start ----------- -<<<<<<< HEAD -By default, `RandomGenerator` uses normals provided by -`xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in -`mtrand.RandomState` -======= By default, `Generator` uses normals provided by `xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in `RandomState` ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python @@ -50,17 +39,10 @@ which will be faster than the legacy methods in `RandomState` from numpy import random random.standard_normal() -<<<<<<< HEAD -`RandomGenerator` can be used as a direct replacement for -`~RandomState`, although the random values are generated by -`~xoroshiro128.Xoroshiro128`. The `RandomGenerator` holds an instance of a RNG. -It is accessable as ``gen.brng``. -======= `Generator` can be used as a direct replacement for `RandomState`, although the random values are generated by `~xoroshiro128.Xoroshiro128`. The `Generator` holds an instance of a BitGenerator. It is accessable as ``gen.bit_generator``. ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python @@ -85,49 +67,23 @@ generator`. Introduction ------------ RandomGen takes a different approach to producing random numbers from the -<<<<<<< HEAD -:class:`numpy.random.RandomState` object. Random number generation is -separated into two components, a basic RNG and a random generator. -======= `RandomState` object. Random number generation is separated into two components, a bit generator and a random generator. ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology The basic RNG has a limited set of responsibilities. It manages the underlying RNG state and provides functions to produce random doubles and random unsigned 32- and 64-bit values. The basic random generator also handles all seeding since this varies when using alternative basic RNGs. -<<<<<<< HEAD -The `random generator <~RandomGenerator>` takes the -basic RNG-provided functions and transforms them into more useful -======= The `random generator ` takes the bit generator-provided stream and transforms them into more useful ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology distributions, e.g., simulated normal random values. This structure allows alternative basic RNGs to be used without code duplication. -<<<<<<< HEAD -The ``RandomGenerator`` is the user-facing object -that is nearly identical to :class:`~.RandomState`. The canonical -method to initialize a generator passes a basic RNG -- `~mt19937.MT19937`, the -underlying RNG in NumPy -- as the sole argument. Note that the basic RNG must -be instantized. - -.. code-block:: python - - from numpy.random import RandomGenerator, MT19937 - rg = RandomGenerator(MT19937()) - rg.random_sample() - -Seed information is directly passed to the basic RNG. -======= The `Generator` is the user-facing object that is nearly identical to `RandomState`. The canonical method to initialize a generator passes a `~mt19937.MT19937` bit generator, the underlying bit generator in Python -- as the sole argument. Note that the bit generator must be instantiated. ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology .. code-block:: python @@ -147,13 +103,8 @@ What's New or Different .. warning:: The Box-Muller method used to produce NumPy's normals is no longer available -<<<<<<< HEAD - in `~.RandomGenerator`. It is not possible to reproduce the exact random - values using ``RandomGenerator`` for the normal distribution or any other -======= in `Generator`. It is not possible to reproduce the exact random values using Generator for the normal distribution or any other ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology distribution that relies on the normal such as the `numpy.random.gamma` or `numpy.random.standard_t`. If you require bitwise backward compatible streams, use `RandomState`. @@ -169,17 +120,6 @@ What's New or Different * `~entropy.random_entropy` provides access to the system source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). -<<<<<<< HEAD -* All basic random generators functions can produce doubles, uint64s and - uint32s via CTypes (`~xoroshiro128.Xoroshiro128.ctypes`) - and CFFI (:meth:`~xoroshiro128.Xoroshiro128.cffi`). - This allows these basic RNGs to be used in numba. -* The basic random number generators can be used in downstream projects via - :ref:`Cython `. -* Support for Lemire’s method [Lemire]_ of generating uniform integers on an - arbitrary interval by setting ``use_masked=True`` in - `~RandomGenerator.randint`. -======= * All BitGenerators can produce doubles, uint64s and uint32s via CTypes (`~xoroshiro128.Xoroshiro128.ctypes`) and CFFI (:meth:`~xoroshiro128.Xoroshiro128.cffi`). This allows the bit generators to @@ -195,8 +135,6 @@ What's New or Different random numbers, which replaces `random_sample`, `sample`, and `ranf`. This is consistent with Python's `random.random`. ->>>>>>> d7650d9f2... DOC: use more BitGenerator instead of other termonology - See :ref:`new-or-different` for a complete list of improvements and differences. diff --git a/doc/source/reference/routines.random.rst b/doc/source/reference/routines.random.rst deleted file mode 100644 index cda4e2b61b7a..000000000000 --- a/doc/source/reference/routines.random.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. _routines.random: - -.. module:: numpy.random - -Random sampling (:mod:`numpy.random`) -************************************* - -.. currentmodule:: numpy.random - -Simple random data -================== -.. autosummary:: - :toctree: generated/ - - rand - randn - randint - random_integers - random_sample - random - ranf - sample - choice - bytes - -Permutations -============ -.. autosummary:: - :toctree: generated/ - - shuffle - permutation - -Distributions -============= -.. autosummary:: - :toctree: generated/ - - beta - binomial - chisquare - dirichlet - exponential - f - gamma - geometric - gumbel - hypergeometric - laplace - logistic - lognormal - logseries - multinomial - multivariate_normal - negative_binomial - noncentral_chisquare - noncentral_f - normal - pareto - poisson - power - rayleigh - standard_cauchy - standard_exponential - standard_gamma - standard_normal - standard_t - triangular - uniform - vonmises - wald - weibull - zipf - -Random generator -================ -.. autosummary:: - :toctree: generated/ - - RandomState - seed - get_state - set_state diff --git a/doc/source/reference/routines.rst b/doc/source/reference/routines.rst index e3fbc2be6945..7a9b97d771b1 100644 --- a/doc/source/reference/routines.rst +++ b/doc/source/reference/routines.rst @@ -41,7 +41,6 @@ indentation. routines.other routines.padding routines.polynomials - routines.random random/index routines.set routines.sort diff --git a/numpy/random/bounded_integers.pxd.in b/numpy/random/bounded_integers.pxd.in index 4ab389fd923e..ceb09c3c2d06 100644 --- a/numpy/random/bounded_integers.pxd.in +++ b/numpy/random/bounded_integers.pxd.in @@ -22,5 +22,5 @@ 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, brng_t *state, object lock) +cdef object _rand_{{inttype}}(object low, object high, object size, bint use_masked, bint closed, brng_t *state, object lock) {{endfor}} diff --git a/numpy/random/bounded_integers.pyx.in b/numpy/random/bounded_integers.pyx.in index a4dbb1f52a37..5fbd10b4fdac 100644 --- a/numpy/random/bounded_integers.pyx.in +++ b/numpy/random/bounded_integers.pyx.in @@ -30,7 +30,7 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U {{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 use_masked, bint closed, brng_t *state, object lock): """ Array path for smaller integer types @@ -40,7 +40,7 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s 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 + 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 @@ -50,14 +50,23 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s cdef int buf_rem = 0 # Array path + is_open = not closed low_arr = low high_arr = high if np.any(np.less(low_arr, {{lb}})): raise ValueError('low is out of bounds for {{nptype}}') - if np.any(np.greater(high_arr, {{ub}})): + 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(np.greater_equal(low_arr, high_arr)): - raise ValueError('low >= high') + 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.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) high_arr = np.PyArray_FROM_OTF(high, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) @@ -77,7 +86,7 @@ cdef object _rand_{{nptype}}_broadcast(np.ndarray low, np.ndarray high, object s 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 - 1) - low_v) + rng = <{{utype}}_t>((high_v - is_open) - low_v) off = <{{utype}}_t>(<{{nptype_up}}_t>low_v) if rng != last_rng: @@ -97,7 +106,7 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF {{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 use_masked, bint closed, brng_t *state, object lock): """ Array path for 64-bit integer types @@ -126,11 +135,13 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, if np.any(np.less(low_arr, {{lb}})): raise ValueError('low is out of bounds for {{nptype}}') dt = high_arr.dtype - if np.issubdtype(dt, np.integer): + if closed or np.issubdtype(dt, np.integer): # Avoid object dtype path if already an integer - if np.any(np.less_equal(high_arr, {{lb}})): - raise ValueError('low >= high') - high_m1 = high_arr - dt.type(1) + 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.PyArray_FROM_OTF(high_m1, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) @@ -146,11 +157,13 @@ cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, if closed_upper > {{ub}}: raise ValueError('high is out of bounds for {{nptype}}') if closed_upper < {{lb}}: - raise ValueError('low >= high') + 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)): - raise ValueError('low >= high') + comp = '>' if closed else '>=' + raise ValueError('low {comp} high'.format(comp=comp)) high_arr = highm1_arr low_arr = np.PyArray_FROM_OTF(low, np.{{npctype}}, np.NPY_ALIGNED | np.NPY_FORCECAST) @@ -196,7 +209,7 @@ type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), {{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 use_masked, bint closed, brng_t *state, object lock): """ _rand_{{nptype}}(low, high, size, use_masked, *state, lock) @@ -223,6 +236,8 @@ cdef object _rand_{{nptype}}(object low, object high, object size, 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 : basic random state State to use in the core random number generators lock : threading.Lock @@ -237,10 +252,10 @@ cdef object _rand_{{nptype}}(object low, object high, object size, Notes ----- The internal integer generator produces values from the closed - interval [low, high-1]. 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. + 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 @@ -260,14 +275,16 @@ cdef object _rand_{{nptype}}(object low, object high, object size, low = int(low_arr) high = int(high_arr) # Subtract 1 since internal generator produces on closed interval [low, high] - high -= 1 + 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 - raise ValueError("low >= high") + comp = '>' if closed else '>=' + raise ValueError('low {comp} high'.format(comp=comp)) rng = <{{utype}}_t>(high - low) off = <{{utype}}_t>(<{{nptype}}_t>low) @@ -282,5 +299,5 @@ cdef object _rand_{{nptype}}(object low, object high, object size, 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, state, lock) + return _rand_{{nptype}}_broadcast(low_arr, high_arr, size, use_masked, closed, state, lock) {{endfor}} diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index a4ba51b55d46..6910a1e48364 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -368,15 +368,19 @@ cdef class RandomGenerator: """ return self.randint(0, np.iinfo(np.int).max + 1, dtype=np.int, size=size) - def randint(self, low, high=None, size=None, dtype=np.int64, use_masked=True): + def randint(self, low, high=None, size=None, dtype=np.int64, use_masked=True, + closed=False): """ - randint(low, high=None, size=None, dtype='int64', use_masked=True) + randint(low, high=None, size=None, dtype='int64', use_masked=True, closed=False) - Return random integers from `low` (inclusive) to `high` (exclusive). + Return random integers from `low` (inclusive) to `high` (exclusive), or + if closed=True, `low` (inclusive) to `high` (inclusive). Return random integers from the "discrete uniform" distribution of the specified dtype in the "half-open" interval [`low`, `high`). If - `high` is None (the default), then results are from [0, `low`). + `high` is None (the default), then results are from [0, `low`). If + `closed` is True, then samples from the closed interval [`low`, `high`] + or [0, `low`] if `high` is None. Parameters ---------- @@ -402,11 +406,15 @@ cdef class RandomGenerator: use_masked : bool If True the generator uses rejection sampling with a bit mask to - reject random numbers that are out of bounds. If False the generator - will use Lemire's rejection sampling algorithm. + reject random numbers that are out of bounds. If False the + generator will use Lemire's rejection sampling algorithm. .. versionadded:: 1.15.1 + closed : bool + If true, sample from the interval [low, high] instead of the + default [low, high) + Returns ------- out : int or ndarray of ints @@ -469,23 +477,23 @@ cdef class RandomGenerator: raise TypeError('Unsupported dtype "%s" for randint' % key) if key == 'int32': - ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int32(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int64(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int16(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int8(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint64(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint32(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint16(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint8(low, high, size, use_masked, closed, self._brng, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_bool(low, high, size, use_masked, closed, self._brng, self.lock) if size is None and dtype in (np.bool, np.int, np.long): if np.array(ret).shape == (): diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 7e81223153d1..c67e398546af 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -588,23 +588,23 @@ cdef class RandomState: raise TypeError('Unsupported dtype "%s" for randint' % key) if key == 'int32': - ret = _rand_int32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int32(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int64(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int16(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_int8(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint64(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint32(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint16(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_uint8(low, high, size, use_masked, False, self._brng, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, use_masked, self._brng, self.lock) + ret = _rand_bool(low, high, size, use_masked, False, self._brng, self.lock) if size is None and dtype in (np.bool, np.int, np.long): if np.array(ret).shape == (): diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 6503389d5078..ace5c230c677 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -1,6 +1,8 @@ import sys import warnings +import pytest + import numpy as np from numpy.testing import ( assert_, assert_raises, assert_equal, @@ -12,6 +14,11 @@ random = RandomGenerator(MT19937()) +@pytest.fixture(scope='module', params=[True, False]) +def closed(request): + return request.param + + class TestSeed(object): def test_scalar(self): s = RandomGenerator(MT19937(0)) @@ -144,57 +151,77 @@ class TestRandint(object): itype = [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_unsupported_type(self, closed): + assert_raises(TypeError, self.rfunc, 1, closed=closed, dtype=float) - def test_bounds_checking(self): + def test_bounds_checking(self, closed): 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 - 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) - - 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_bounds_checking_array(self): + ubnd = ubnd - 1 if closed else ubnd + assert_raises(ValueError, self.rfunc, lbnd - 1, ubnd, + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, lbnd, ubnd + 1, + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, ubnd, lbnd, + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, 1, 0, closed=closed, + dtype=dt) + + assert_raises(ValueError, self.rfunc, [lbnd - 1], ubnd, + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, [lbnd], [ubnd + 1], + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, [ubnd], [lbnd], + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, 1, [0], + closed=closed, dtype=dt) + + def test_bounds_checking_array(self, closed): 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 = 2 if dt is bool else np.iinfo(dt).max + (not closed) + assert_raises(ValueError, self.rfunc, [ - lbnd - 1] * 2, [ubnd] * 2, dtype=dt) + lbnd - 1] * 2, [ubnd] * 2, closed=closed, dtype=dt) assert_raises(ValueError, self.rfunc, [ - lbnd] * 2, [ubnd + 1] * 2, dtype=dt) - assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2, dtype=dt) - assert_raises(ValueError, self.rfunc, [1] * 2, 0, dtype=dt) + lbnd] * 2, [ubnd + 1] * 2, closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2, + closed=closed, dtype=dt) + assert_raises(ValueError, self.rfunc, [1] * 2, 0, + closed=closed, dtype=dt) - def test_rng_zero_and_extremes(self): + def test_rng_zero_and_extremes(self, closed): 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 closed else ubnd + is_open = not closed tgt = ubnd - 1 - assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt) - assert_equal(self.rfunc([tgt], tgt + 1, size=1000, dtype=dt), tgt) + assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, + closed=closed, dtype=dt), tgt) + assert_equal(self.rfunc([tgt], tgt + is_open, size=1000, + closed=closed, dtype=dt), tgt) tgt = lbnd - assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt) - assert_equal(self.rfunc(tgt, [tgt + 1], size=1000, dtype=dt), tgt) + assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, + closed=closed, dtype=dt), tgt) + assert_equal(self.rfunc(tgt, [tgt + is_open], size=1000, + closed=closed, dtype=dt), tgt) tgt = (lbnd + ubnd) // 2 - assert_equal(self.rfunc(tgt, tgt + 1, size=1000, dtype=dt), tgt) - assert_equal(self.rfunc([tgt], [tgt + 1], - size=1000, dtype=dt), tgt) + assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, + closed=closed, dtype=dt), tgt) + assert_equal(self.rfunc([tgt], [tgt + is_open], + size=1000, closed=closed, dtype=dt), tgt) - def test_rng_zero_and_extremes_array(self): + def test_rng_zero_and_extremes_array(self, closed): 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 closed else ubnd tgt = ubnd - 1 assert_equal(self.rfunc([tgt], [tgt + 1], @@ -220,68 +247,73 @@ def test_rng_zero_and_extremes_array(self): assert_equal(self.rfunc( [tgt] * size, [tgt + 1] * size, size=size, dtype=dt), tgt) - def test_full_range(self): + def test_full_range(self, closed): # 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 closed else ubnd try: - self.rfunc(lbnd, ubnd, dtype=dt) + self.rfunc(lbnd, ubnd, closed=closed, 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): + def test_full_range_array(self, closed): # 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 closed else ubnd try: - self.rfunc([lbnd] * 2, [ubnd], dtype=dt) + self.rfunc([lbnd] * 2, [ubnd], closed=closed, 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): + def test_in_bounds_fuzz(self, closed): # Don't use fixed seed random.brng.seed() for dt in self.itype[1:]: for ubnd in [4, 8, 16]: - vals = self.rfunc(2, ubnd, size=2 ** 16, dtype=dt) + vals = self.rfunc(2, ubnd - closed, size=2 ** 16, + closed=closed, dtype=dt) assert_(vals.max() < ubnd) assert_(vals.min() >= 2) - vals = self.rfunc(0, 2, size=2 ** 16, dtype=bool) - + vals = self.rfunc(0, 2 - closed, size=2 ** 16, closed=closed, + dtype=bool) assert_(vals.max() < 2) assert_(vals.min() >= 0) - def test_scalar_array_equiv(self): + def test_scalar_array_equiv(self, closed): 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 closed else ubnd size = 1000 random.brng.seed(1234) - scalar = self.rfunc(lbnd, ubnd, size=size, dtype=dt) + scalar = self.rfunc(lbnd, ubnd, size=size, closed=closed, dtype=dt) random.brng.seed(1234) - scalar_array = self.rfunc([lbnd], [ubnd], size=size, dtype=dt) + scalar_array = self.rfunc([lbnd], [ubnd], size=size, + closed=closed, dtype=dt) random.brng.seed(1234) array = self.rfunc([lbnd] * size, [ubnd] * - size, size=size, dtype=dt) + size, size=size, closed=closed, dtype=dt) assert_array_equal(scalar, scalar_array) assert_array_equal(scalar, array) - def test_repeatability(self): + def test_repeatability(self, closed): 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 @@ -301,68 +333,73 @@ def test_repeatability(self): # view as little endian for hash if sys.byteorder == 'little': - val = self.rfunc(0, 6, size=1000, dtype=dt) + val = self.rfunc(0, 6 - closed, size=1000, closed=closed, + dtype=dt) else: - val = self.rfunc(0, 6, size=1000, dtype=dt).byteswap() + val = self.rfunc(0, 6 - closed, size=1000, closed=closed, + 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.brng.seed(1234) - val = self.rfunc(0, 2, size=1000, dtype=bool).view(np.int8) + val = self.rfunc(0, 2 - closed, size=1000, closed=closed, + dtype=bool).view(np.int8) res = hashlib.md5(val).hexdigest() assert_(tgt[np.dtype(bool).name] == res) - def test_repeatability_broadcasting(self): - + def test_repeatability_broadcasting(self, closed): 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 closed else ubnd # view as little endian for hash random.brng.seed(1234) - val = self.rfunc(lbnd, ubnd, size=1000, dtype=dt) + val = self.rfunc(lbnd, ubnd, size=1000, closed=closed, dtype=dt) random.brng.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, ubnd, dtype=dt) + val_bc = self.rfunc([lbnd] * 1000, ubnd, closed=closed, dtype=dt) assert_array_equal(val, val_bc) random.brng.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, dtype=dt) + val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, closed=closed, + dtype=dt) assert_array_equal(val, val_bc) - def test_int64_uint64_broadcast_exceptions(self): + def test_int64_uint64_broadcast_exceptions(self, closed): 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 - closed low_a = np.array([[low]*10]) high_a = np.array([high] * 10) assert_raises(ValueError, random.randint, low, high, - dtype=dtype) + closed=closed, dtype=dtype) assert_raises(ValueError, random.randint, low_a, high, - dtype=dtype) + closed=closed, dtype=dtype) assert_raises(ValueError, random.randint, low, high_a, - dtype=dtype) + closed=closed, dtype=dtype) assert_raises(ValueError, random.randint, low_a, high_a, - dtype=dtype) + closed=closed, dtype=dtype) low_o = np.array([[low]*10], dtype=np.object) high_o = np.array([high] * 10, dtype=np.object) assert_raises(ValueError, random.randint, low_o, high, - dtype=dtype) + closed=closed, dtype=dtype) assert_raises(ValueError, random.randint, low, high_o, - dtype=dtype) + closed=closed, dtype=dtype) assert_raises(ValueError, random.randint, low_o, high_o, - dtype=dtype) + closed=closed, dtype=dtype) - def test_int64_uint64_corner_case(self): + def test_int64_uint64_corner_case(self, closed): # 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 @@ -378,51 +415,58 @@ def test_int64_uint64_corner_case(self): 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) + ubnd = np.uint64(np.iinfo(np.int64).max + 1 - closed) # None of these function calls should # generate a ValueError now. - actual = random.randint(lbnd, ubnd, dtype=dt) + actual = random.randint(lbnd, ubnd, closed=closed, dtype=dt) assert_equal(actual, tgt) - def test_respect_dtype_singleton(self): + def test_respect_dtype_singleton(self, closed): # 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 closed else ubnd dt = np.bool_ if dt is bool else dt - sample = self.rfunc(lbnd, ubnd, dtype=dt) + sample = self.rfunc(lbnd, ubnd, closed=closed, 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 closed else ubnd # gh-7284: Ensure that we get Python data types - sample = self.rfunc(lbnd, ubnd, dtype=dt) + sample = self.rfunc(lbnd, ubnd, closed=closed, dtype=dt) assert not hasattr(sample, 'dtype') assert_equal(type(sample), dt) - def test_respect_dtype_array(self): + def test_respect_dtype_array(self, closed): # 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 closed else ubnd dt = np.bool_ if dt is bool else dt - sample = self.rfunc([lbnd], [ubnd], dtype=dt) + sample = self.rfunc([lbnd], [ubnd], closed=closed, dtype=dt) assert_equal(sample.dtype, dt) - sample = self.rfunc([lbnd] * 2, [ubnd] * 2, dtype=dt) + sample = self.rfunc([lbnd] * 2, [ubnd] * 2, closed=closed, + dtype=dt) assert_equal(sample.dtype, dt) - def test_zero_size(self): + def test_zero_size(self, closed): # See gh-7203 for dt in self.itype: - sample = self.rfunc(0, 0, (3, 0, 4), dtype=dt) + sample = self.rfunc(0, 0, (3, 0, 4), closed=closed, dtype=dt) assert sample.shape == (3, 0, 4) assert sample.dtype == dt - assert self.rfunc(0, -10, 0, dtype=dt).shape == (0,) + assert self.rfunc(0, -10, 0, closed=closed, dtype=dt).shape == (0,) + 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,)) class TestRandomDist(object): @@ -2029,7 +2073,7 @@ def test_two_arg_funcs(self): out = func(self.argOne, argTwo[0]) assert_equal(out.shape, self.tgtShape) - def test_randint(self): + def test_randint(self, closed): itype = [np.bool, np.int8, np.uint8, np.int16, np.uint16, np.int32, np.uint32, np.int64, np.uint64] func = random.randint @@ -2037,13 +2081,13 @@ def test_randint(self): low = np.array([0]) for dt in itype: - out = func(low, high, dtype=dt) + out = func(low, high, closed=closed, dtype=dt) assert_equal(out.shape, self.tgtShape) - out = func(low[0], high, dtype=dt) + out = func(low[0], high, closed=closed, dtype=dt) assert_equal(out.shape, self.tgtShape) - out = func(low, high[0], dtype=dt) + out = func(low, high[0], closed=closed, dtype=dt) assert_equal(out.shape, self.tgtShape) def test_three_arg_funcs(self): diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 50f226386219..c5fb5c9b42cf 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -444,7 +444,6 @@ def test_random_integers_max_int(self): assert_(len(w) == 1) assert_equal(actual, desired) - def test_random_integers_deprecated(self): with warnings.catch_warnings(): warnings.simplefilter("error", DeprecationWarning) From 17e0070df93f4262908f884dca4b08cb7d0bba7f Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 13 May 2019 14:17:51 -0700 Subject: [PATCH 121/138] MAINT: Implement API changes for randomgen-derived code remove numpy.random.gen, BRNG.generator, pcg*, rand, randn remove use_mask and Lemire's method, fix benchmarks for PCG removal convert brng to bitgen (in C) and bit_generator (in python) convert base R{NG,andom.*} to BitGenerator, fix last commit randint -> integers, remove rand, randn, random_integers RandomGenerator -> Generator, more "basic RNG" -> BitGenerator random_sample -> random, jump -> jumped, resync with randomgen Remove derived code from entropy Port over changes accepted in upstream to protect log(0.0) where relevant fix doctests for jumped, better document choice Remove Python 2.7 shims Use NPY_INLINE to simplify Fix performance.py to work Renam directory brng to bit_generators Fix examples wiht new directory structure Clarify relationship to historical RandomState Remove references to .generator Rename xoshiro256/512starstar --- benchmarks/benchmarks/bench_random.py | 87 +- doc/neps/nep-0010-new-iterator-ufunc.rst | 4 +- doc/neps/nep-0019-rng-policy.rst | 89 +- .../random/{brng => bit_generators}/dsfmt.rst | 9 +- .../random/{brng => bit_generators}/index.rst | 19 +- .../{brng => bit_generators}/mt19937.rst | 9 +- .../{brng => bit_generators}/philox.rst | 9 +- .../{brng => bit_generators}/threefry.rst | 9 +- .../{brng => bit_generators}/threefry32.rst | 9 +- .../{brng => bit_generators}/xoroshiro128.rst | 9 +- .../{brng => bit_generators}/xorshift1024.rst | 9 +- .../random/bit_generators/xoshiro256.rst | 35 + .../random/bit_generators/xoshiro512.rst | 35 + doc/source/reference/random/brng/pcg32.rst | 43 - doc/source/reference/random/brng/pcg64.rst | 43 - .../random/brng/xoshiro256starstar.rst | 42 - .../random/brng/xoshiro512starstar.rst | 42 - doc/source/reference/random/change-log.rst | 39 - doc/source/reference/random/extending.rst | 55 +- doc/source/reference/random/generator.rst | 103 +- doc/source/reference/random/index.rst | 73 +- doc/source/reference/random/legacy.rst | 21 +- .../reference/random/multithreading.rst | 19 +- .../reference/random/new-or-different.rst | 65 +- doc/source/reference/random/parallel.rst | 52 +- doc/source/reference/random/performance.py | 20 +- doc/source/reference/random/performance.rst | 66 +- doc/source/reference/random/references.rst | 5 - numpy/random/LICENSE.md | 45 +- numpy/random/__init__.py | 76 +- numpy/random/_pickle.py | 91 +- numpy/random/bounded_integers.pxd.in | 4 +- numpy/random/bounded_integers.pyx.in | 12 +- numpy/random/common.pxd | 32 +- numpy/random/common.pyx | 79 +- numpy/random/distributions.pxd | 144 +- numpy/random/dsfmt.pyx | 192 +- numpy/random/entropy.pyx | 9 +- numpy/random/examples/cython/extending.pyx | 20 +- .../cython/extending_distributions.pyx | 22 +- numpy/random/examples/cython/setup.py | 10 +- .../examples/numba/extending_distributions.py | 14 +- numpy/random/generator.pyx | 723 ++---- numpy/random/legacy_distributions.pxd | 56 +- numpy/random/mt19937.pyx | 175 +- numpy/random/mtrand.pyx | 289 ++- numpy/random/pcg32.pyx | 387 --- numpy/random/pcg64.pyx | 426 ---- numpy/random/philox.pyx | 212 +- numpy/random/setup.py | 25 +- numpy/random/src/common/LICENSE.md | 29 - numpy/random/src/common/inttypes.h | 306 --- numpy/random/src/common/stdint.h | 258 -- .../random/src/distributions/distributions.c | 709 +++--- .../random/src/distributions/distributions.h | 170 +- numpy/random/src/entropy/LICENSE.md | 25 - numpy/random/src/entropy/entropy.c | 70 +- numpy/random/src/entropy/entropy.h | 34 - numpy/random/src/legacy/LICENSE.md | 30 - .../src/legacy/distributions-boxmuller.c | 46 +- .../src/legacy/distributions-boxmuller.h | 48 +- numpy/random/src/mt19937/mt19937.h | 8 - numpy/random/src/pcg32/LICENSE.md | 22 - numpy/random/src/pcg32/pcg-advance-64.c | 62 - numpy/random/src/pcg32/pcg32-test-data-gen.c | 59 - numpy/random/src/pcg32/pcg32.c | 30 - numpy/random/src/pcg32/pcg32.h | 89 - numpy/random/src/pcg32/pcg_variants.h | 2210 ----------------- numpy/random/src/pcg64/LICENSE.md | 22 - numpy/random/src/pcg64/pcg64-benchmark.c | 42 - numpy/random/src/pcg64/pcg64-test-data-gen.c | 73 - numpy/random/src/pcg64/pcg64.c | 162 -- numpy/random/src/pcg64/pcg64.h | 246 -- numpy/random/src/pcg64/pcg64.orig.c | 11 - numpy/random/src/pcg64/pcg64.orig.h | 2025 --------------- numpy/random/src/philox/philox.c | 4 +- numpy/random/src/philox/philox.h | 35 +- numpy/random/src/splitmix64/splitmix64.h | 9 - numpy/random/src/threefry/threefry.c | 4 +- numpy/random/src/threefry/threefry.h | 26 +- numpy/random/src/threefry32/threefry32.c | 4 +- numpy/random/src/threefry32/threefry32.h | 34 +- numpy/random/src/xoroshiro128/xoroshiro128.c | 4 +- numpy/random/src/xoroshiro128/xoroshiro128.h | 20 +- numpy/random/src/xorshift1024/xorshift1024.c | 6 +- numpy/random/src/xorshift1024/xorshift1024.h | 18 +- .../LICENSE.md | 0 .../xoshiro256-test-data-gen.c} | 16 +- .../xoshiro256.c} | 11 +- numpy/random/src/xoshiro256/xoshiro256.h | 53 + .../xoshiro256.orig.c} | 0 .../xoshiro256.orig.h} | 0 .../xoshiro256starstar/xoshiro256starstar.h | 63 - .../LICENSE.md | 0 .../xoshiro512-test-data-gen.c} | 16 +- .../xoshiro512.c} | 13 +- .../xoshiro512.h} | 35 +- .../xoshiro512.orig.c} | 2 +- .../xoshiro512.orig.h} | 0 numpy/random/tests/data/pcg32-testset-1.csv | 1001 -------- numpy/random/tests/data/pcg32-testset-2.csv | 1001 -------- numpy/random/tests/data/pcg64-testset-1.csv | 1001 -------- numpy/random/tests/data/pcg64-testset-2.csv | 1001 -------- ...testset-1.csv => xoshiro256-testset-1.csv} | 0 ...testset-2.csv => xoshiro256-testset-2.csv} | 0 ...testset-1.csv => xoshiro512-testset-1.csv} | 0 ...testset-2.csv => xoshiro512-testset-2.csv} | 0 numpy/random/tests/test_against_numpy.py | 74 +- numpy/random/tests/test_direct.py | 364 ++- numpy/random/tests/test_generator_mt19937.py | 513 ++-- .../test_generator_mt19937_regressions.py | 30 +- numpy/random/tests/test_random.py | 4 +- numpy/random/tests/test_randomstate.py | 10 +- numpy/random/tests/test_smoke.py | 459 ++-- numpy/random/threefry.pyx | 223 +- numpy/random/threefry32.pyx | 205 +- numpy/random/xoroshiro128.pyx | 221 +- numpy/random/xorshift1024.pyx | 216 +- ...{xoshiro256starstar.pyx => xoshiro256.pyx} | 245 +- ...{xoshiro512starstar.pyx => xoshiro512.pyx} | 238 +- 120 files changed, 3256 insertions(+), 14772 deletions(-) rename doc/source/reference/random/{brng => bit_generators}/dsfmt.rst (81%) rename doc/source/reference/random/{brng => bit_generators}/index.rst (62%) rename doc/source/reference/random/{brng => bit_generators}/mt19937.rst (80%) rename doc/source/reference/random/{brng => bit_generators}/philox.rst (80%) rename doc/source/reference/random/{brng => bit_generators}/threefry.rst (80%) rename doc/source/reference/random/{brng => bit_generators}/threefry32.rst (80%) rename doc/source/reference/random/{brng => bit_generators}/xoroshiro128.rst (79%) rename doc/source/reference/random/{brng => bit_generators}/xorshift1024.rst (79%) create mode 100644 doc/source/reference/random/bit_generators/xoshiro256.rst create mode 100644 doc/source/reference/random/bit_generators/xoshiro512.rst delete mode 100644 doc/source/reference/random/brng/pcg32.rst delete mode 100644 doc/source/reference/random/brng/pcg64.rst delete mode 100644 doc/source/reference/random/brng/xoshiro256starstar.rst delete mode 100644 doc/source/reference/random/brng/xoshiro512starstar.rst delete mode 100644 doc/source/reference/random/change-log.rst delete mode 100644 doc/source/reference/random/references.rst delete mode 100644 numpy/random/pcg32.pyx delete mode 100644 numpy/random/pcg64.pyx delete mode 100644 numpy/random/src/common/LICENSE.md delete mode 100644 numpy/random/src/common/inttypes.h delete mode 100644 numpy/random/src/common/stdint.h delete mode 100644 numpy/random/src/entropy/LICENSE.md delete mode 100644 numpy/random/src/legacy/LICENSE.md delete mode 100644 numpy/random/src/pcg32/LICENSE.md delete mode 100644 numpy/random/src/pcg32/pcg-advance-64.c delete mode 100644 numpy/random/src/pcg32/pcg32-test-data-gen.c delete mode 100644 numpy/random/src/pcg32/pcg32.c delete mode 100644 numpy/random/src/pcg32/pcg32.h delete mode 100644 numpy/random/src/pcg32/pcg_variants.h delete mode 100644 numpy/random/src/pcg64/LICENSE.md delete mode 100644 numpy/random/src/pcg64/pcg64-benchmark.c delete mode 100644 numpy/random/src/pcg64/pcg64-test-data-gen.c delete mode 100644 numpy/random/src/pcg64/pcg64.c delete mode 100644 numpy/random/src/pcg64/pcg64.h delete mode 100644 numpy/random/src/pcg64/pcg64.orig.c delete mode 100644 numpy/random/src/pcg64/pcg64.orig.h rename numpy/random/src/{xoshiro256starstar => xoshiro256}/LICENSE.md (100%) rename numpy/random/src/{xoshiro256starstar/xoshiro256starstar-test-data-gen.c => xoshiro256/xoshiro256-test-data-gen.c} (74%) rename numpy/random/src/{xoshiro256starstar/xoshiro256starstar.c => xoshiro256/xoshiro256.c} (83%) create mode 100644 numpy/random/src/xoshiro256/xoshiro256.h rename numpy/random/src/{xoshiro256starstar/xoshiro256starstar.orig.c => xoshiro256/xoshiro256.orig.c} (100%) rename numpy/random/src/{xoshiro256starstar/xoshiro256starstar.orig.h => xoshiro256/xoshiro256.orig.h} (100%) delete mode 100644 numpy/random/src/xoshiro256starstar/xoshiro256starstar.h rename numpy/random/src/{xoshiro512starstar => xoshiro512}/LICENSE.md (100%) rename numpy/random/src/{xoshiro512starstar/xoshiro512starstar-test-data-gen.c => xoshiro512/xoshiro512-test-data-gen.c} (74%) rename numpy/random/src/{xoshiro512starstar/xoshiro512starstar.c => xoshiro512/xoshiro512.c} (84%) rename numpy/random/src/{xoshiro512starstar/xoshiro512starstar.h => xoshiro512/xoshiro512.h} (50%) rename numpy/random/src/{xoshiro512starstar/xoshiro512starstar.orig.c => xoshiro512/xoshiro512.orig.c} (98%) rename numpy/random/src/{xoshiro512starstar/xoshiro512starstar.orig.h => xoshiro512/xoshiro512.orig.h} (100%) delete mode 100644 numpy/random/tests/data/pcg32-testset-1.csv delete mode 100644 numpy/random/tests/data/pcg32-testset-2.csv delete mode 100644 numpy/random/tests/data/pcg64-testset-1.csv delete mode 100644 numpy/random/tests/data/pcg64-testset-2.csv rename numpy/random/tests/data/{xoshiro256starstar-testset-1.csv => xoshiro256-testset-1.csv} (100%) rename numpy/random/tests/data/{xoshiro256starstar-testset-2.csv => xoshiro256-testset-2.csv} (100%) rename numpy/random/tests/data/{xoshiro512starstar-testset-1.csv => xoshiro512-testset-1.csv} (100%) rename numpy/random/tests/data/{xoshiro512starstar-testset-2.csv => xoshiro512-testset-2.csv} (100%) rename numpy/random/{xoshiro256starstar.pyx => xoshiro256.pyx} (52%) rename numpy/random/{xoshiro512starstar.pyx => xoshiro512.pyx} (51%) diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index 3589c65a387f..db63167d126e 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -4,7 +4,7 @@ import numpy as np -from numpy.random import RandomState, RandomGenerator +from numpy.random import RandomState, Generator class Random(Benchmark): params = ['normal', 'uniform', 'weibull 1', 'binomial 10 0.5', @@ -70,14 +70,14 @@ def time_randint_slow(self, name): class Permutation(Benchmark): def setup(self): self.n = 10000 - self.a_1d = np.random.random_sample(self.n) - self.a_2d = np.random.random_sample((self.n, 2)) - + self.a_1d = np.random.random(self.n) + self.a_2d = np.random.random((self.n, 2)) + def time_permutation_1d(self): np.random.permutation(self.a_1d) def time_permutation_2d(self): - np.random.permutation(self.a_2d) + np.random.permutation(self.a_2d) def time_permutation_int(self): np.random.permutation(self.n) @@ -86,33 +86,39 @@ def time_permutation_int(self): class RNG(Benchmark): param_names = ['rng'] - params = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', - 'Xorshift1024', 'Xoshiro256StarStar', 'Xoshiro512StarStar', + params = ['DSFMT', 'MT19937', 'Xoroshiro128', + 'Xorshift1024', 'Xoshiro256', 'Xoshiro512', 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] def setup(self, brng): if brng == 'numpy': self.rg = np.random.RandomState() else: - self.rg = RandomGenerator(getattr(np.random, brng)()) - self.rg.random_sample() + self.rg = Generator(getattr(np.random, brng)()) + self.rg.random() self.int32info = np.iinfo(np.int32) self.uint32info = np.iinfo(np.uint32) self.uint64info = np.iinfo(np.uint64) - + def time_raw(self, brng): if brng == 'numpy': self.rg.random_integers(self.int32info.max, size=nom_size) else: - self.rg.random_integers(self.int32info.max, size=nom_size) + self.rg.integers(self.int32info.max, size=nom_size, endpoint=True) def time_32bit(self, brng): min, max = self.uint32info.min, self.uint32info.max - self.rg.randint(min, max + 1, nom_size, dtype=np.uint32) + if brng == 'numpy': + self.rg.randint(min, max + 1, nom_size, dtype=np.uint32) + else: + self.rg.integers(min, max + 1, nom_size, dtype=np.uint32) def time_64bit(self, brng): min, max = self.uint64info.min, self.uint64info.max - self.rg.randint(min, max + 1, nom_size, dtype=np.uint64) + if brng == 'numpy': + self.rg.randint(min, max + 1, nom_size, dtype=np.uint64) + else: + self.rg.integers(min, max + 1, nom_size, dtype=np.uint64) def time_normal_zig(self, brng): self.rg.standard_normal(nom_size) @@ -122,34 +128,32 @@ class Bounded(Benchmark): u16 = np.uint16 u32 = np.uint32 u64 = np.uint64 - param_names = ['rng', 'dt_max_masked'] - params = [['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoroshiro128', - 'Xorshift1024', 'Xoshiro256StarStar', 'Xoshiro512StarStar', + param_names = ['rng', 'dt_max'] + params = [['DSFMT', 'MT19937', 'Xoroshiro128', + 'Xorshift1024', 'Xoshiro256', 'Xoshiro512', 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'], - [[u8, 95, True], - [u8, 64, False], # Worst case for legacy - [u8, 95, False], # Typ. avg. case for legacy - [u8, 127, False], # Best case for legacy - [u16, 95, True], - [u16, 1024, False], # Worst case for legacy - [u16, 1535, False], # Typ. avg. case for legacy - [u16, 2047, False], # Best case for legacy - [u32, 95, True], - [u32, 1024, False], # Worst case for legacy - [u32, 1535, False], # Typ. avg. case for legacy - [u32, 2047, False], # Best case for legacy - [u64, 95, True], - [u64, 1024, False], # Worst case for legacy - [u64, 1535, False], # Typ. avg. case for legacy - [u64, 2047, False], # Best case for legacy + [[u8, 95], + [u8, 64], # Worst case for legacy + [u8, 127], # Best case for legacy + [u16, 95], + [u16, 1024], # Worst case for legacy + [u16, 1535], # Typ. avg. case for legacy + [u16, 2047], # Best case for legacy + [u32, 1024], # Worst case for legacy + [u32, 1535], # Typ. avg. case for legacy + [u32, 2047], # Best case for legacy + [u64, 95], + [u64, 1024], # Worst case for legacy + [u64, 1535], # Typ. avg. case for legacy + [u64, 2047], # Best case for legacy ]] def setup(self, brng, args): if brng == 'numpy': self.rg = np.random.RandomState() else: - self.rg = RandomGenerator(getattr(np.random, brng)()) - self.rg.random_sample() + self.rg = Generator(getattr(np.random, brng)()) + self.rg.random() def time_bounded(self, brng, args): """ @@ -161,20 +165,9 @@ def time_bounded(self, brng, args): output dtype max : int Upper bound for range. Lower is always 0. Must be <= 2**bits. - use_masked: bool - If True, masking and rejection sampling is used to generate a random - number in an interval. If False, Lemire's algorithm is used if - available to generate a random number in an interval. - - Notes - ----- - Lemire's algorithm has improved performance when max+1 is not a - power of two. """ - dt, max, use_masked = args + dt, max = args if brng == 'numpy': self.rg.randint(0, max + 1, nom_size, dtype=dt) else: - self.rg.randint(0, max + 1, nom_size, dtype=dt, - use_masked=use_masked) - + self.rg.integers(0, max + 1, nom_size, dtype=dt) diff --git a/doc/neps/nep-0010-new-iterator-ufunc.rst b/doc/neps/nep-0010-new-iterator-ufunc.rst index 8601b4a4c7a9..fd7b3e52c44a 100644 --- a/doc/neps/nep-0010-new-iterator-ufunc.rst +++ b/doc/neps/nep-0010-new-iterator-ufunc.rst @@ -1877,8 +1877,8 @@ the new iterator. Here is one of the original functions, for reference, and some random image data.:: - In [5]: rand1 = np.random.random_sample(1080*1920*4).astype(np.float32) - In [6]: rand2 = np.random.random_sample(1080*1920*4).astype(np.float32) + In [5]: rand1 = np.random.random(1080*1920*4).astype(np.float32) + In [6]: rand2 = np.random.random(1080*1920*4).astype(np.float32) In [7]: image1 = rand1.reshape(1080,1920,4).swapaxes(0,1) In [8]: image2 = rand2.reshape(1080,1920,4).swapaxes(0,1) diff --git a/doc/neps/nep-0019-rng-policy.rst b/doc/neps/nep-0019-rng-policy.rst index f50897b0f1be..4887c8985aeb 100644 --- a/doc/neps/nep-0019-rng-policy.rst +++ b/doc/neps/nep-0019-rng-policy.rst @@ -91,12 +91,12 @@ those contributors simply walked away. Implementation -------------- -Work on a proposed new PRNG subsystem is already underway in the randomgen_ -project. The specifics of the new design are out of scope for this NEP and up -for much discussion, but we will discuss general policies that will guide the -evolution of whatever code is adopted. We will also outline just a few of the -requirements that such a new system must have to support the policy proposed in -this NEP. +Work on a proposed new pseudorandom number generator (PRNG) subsystem is +already underway in the randomgen_ project. The specifics of the new design +are out of scope for this NEP and up for much discussion, but we will discuss +general policies that will guide the evolution of whatever code is adopted. We +will also outline just a few of the requirements that such a new system must +have to support the policy proposed in this NEP. First, we will maintain API source compatibility just as we do with the rest of ``numpy``. If we *must* make a breaking change, we will only do so with an @@ -122,35 +122,35 @@ for a small performance improvement. Any new design for the RNG subsystem will provide a choice of different core uniform PRNG algorithms. A promising design choice is to make these core uniform PRNGs their own lightweight objects with a minimal set of methods -(randomgen_ calls them “basic RNGs”). The broader set of non-uniform -distributions will be its own class that holds a reference to one of these core -uniform PRNG objects and simply delegates to the core uniform PRNG object when -it needs uniform random numbers. To borrow an example from randomgen_, the -class ``MT19937`` is a basic RNG that implements the classic Mersenne Twister -algorithm. The class ``RandomGenerator`` wraps around the basic RNG to provide +(randomgen_ calls them “BitGenerators”). The broader set of non-uniform +distributions will be its own class "Generator" that holds a reference to one +of these BitGenerator objects and simply delegates to the BitGenerator object +when it needs uniform random numbers. To borrow an example from randomgen_, the +class ``MT19937`` is a BitGenerator that implements the classic Mersenne Twister +algorithm. The class ``Generator`` wraps around the BitGenerator to provide all of the non-uniform distribution methods:: # This is not the only way to instantiate this object. # This is just handy for demonstrating the delegation. >>> brng = MT19937(seed) - >>> rg = RandomGenerator(brng) + >>> rg = Generator(brng) >>> x = rg.standard_normal(10) -We will be more strict about a select subset of methods on these basic RNG +We will be more strict about a select subset of methods on these BitGenerator objects. They MUST guarantee stream-compatibility for a specified set of methods which are chosen to make it easier to compose them to build other distributions and which are needed to abstract over the implementation details -of the variety of core PRNG algorithms. Namely, +of the variety of BitGenerator algorithms. Namely, * ``.bytes()`` - * ``.random_uintegers()`` - * ``.random_sample()`` + * ``.integers()`` (which replaces ``randint`` and ``random_integers`` + * ``.random()`` (which replaces ``.random_sample()`` -The distributions class (``RandomGenerator``) SHOULD have all of the same +The distributions class (``Generator``) SHOULD have all of the same distribution methods as ``RandomState`` with close-enough function signatures such that almost all code that currently works with ``RandomState`` instances -will work with ``RandomGenerator`` instances (ignoring the precise stream -values). Some variance will be allowed for integer distributions: in order to +will work with ``Generator`` instances (ignoring the precise stream values). +Some variance will be allowed for integer distributions: in order to avoid some of the cross-platform problems described above, these SHOULD be rewritten to work with ``uint64`` numbers on all platforms. @@ -183,14 +183,14 @@ reproducible across numpy versions. This legacy distributions class MUST be accessible under the name ``numpy.random.RandomState`` for backwards compatibility. All current ways of instantiating ``numpy.random.RandomState`` with a given state should -instantiate the Mersenne Twister basic RNG with the same state. The legacy -distributions class MUST be capable of accepting other basic RNGs. The purpose -here is to ensure that one can write a program with a consistent basic RNG -state with a mixture of libraries that may or may not have upgraded from -``RandomState``. Instances of the legacy distributions class MUST respond -``True`` to ``isinstance(rg, numpy.random.RandomState)`` because there is -current utility code that relies on that check. Similarly, old pickles of -``numpy.random.RandomState`` instances MUST unpickle correctly. +instantiate the Mersenne Twister BitGenerator with the same state. The legacy +distributions class MUST be capable of accepting other BitGenerators. The +purpose here is to ensure that one can write a program with a consistent +BitGenerator state with a mixture of libraries that may or may not have +upgraded from ``RandomState``. Instances of the legacy distributions class +MUST respond ``True`` to ``isinstance(rg, numpy.random.RandomState)`` because +there is current utility code that relies on that check. Similarly, old +pickles of ``numpy.random.RandomState`` instances MUST unpickle correctly. ``numpy.random.*`` @@ -209,27 +209,26 @@ consistently and usefully, but a very common usage is in unit tests where many of the problems of global state are less likely. This NEP does not propose removing these functions or changing them to use the -less-stable ``RandomGenerator`` distribution implementations. Future NEPs -might. +less-stable ``Generator`` distribution implementations. Future NEPs might. Specifically, the initial release of the new PRNG subsystem SHALL leave these convenience functions as aliases to the methods on a global ``RandomState`` -that is initialized with a Mersenne Twister basic RNG object. A call to -``numpy.random.seed()`` will be forwarded to that basic RNG object. In +that is initialized with a Mersenne Twister BitGenerator object. A call to +``numpy.random.seed()`` will be forwarded to that BitGenerator object. In addition, the global ``RandomState`` instance MUST be accessible in this initial release by the name ``numpy.random.mtrand._rand``: Robert Kern long ago promised ``scikit-learn`` that this name would be stable. Whoops. -In order to allow certain workarounds, it MUST be possible to replace the basic -RNG underneath the global ``RandomState`` with any other basic RNG object (we -leave the precise API details up to the new subsystem). Calling +In order to allow certain workarounds, it MUST be possible to replace the +BitGenerator underneath the global ``RandomState`` with any other BitGenerator +object (we leave the precise API details up to the new subsystem). Calling ``numpy.random.seed()`` thereafter SHOULD just pass the given seed to the -current basic RNG object and not attempt to reset the basic RNG to the Mersenne -Twister. The set of ``numpy.random.*`` convenience functions SHALL remain the +current BitGenerator object and not attempt to reset the BitGenerator to the +Mersenne Twister. The set of ``numpy.random.*`` convenience functions SHALL remain the same as they currently are. They SHALL be aliases to the ``RandomState`` -methods and not the new less-stable distributions class (``RandomGenerator``, -in the examples above). Users who want to get the fastest, best distributions -can follow best practices and instantiate generator objects explicitly. +methods and not the new less-stable distributions class (``Generator``, in the +examples above). Users who want to get the fastest, best distributions can +follow best practices and instantiate Generator objects explicitly. This NEP does not propose that these requirements remain in perpetuity. After we have experience with the new PRNG subsystem, we can and should revisit these @@ -298,8 +297,8 @@ positive improvement to the downstream project, just avoiding being broken. Furthermore, under this old proposal, we would have had a quite lengthy deprecation period where ``RandomState`` existed alongside the new system of -basic RNGs and distribution classes. Leaving the implementation of -``RandomState`` fixed meant that it could not use the new basic RNG state +BitGenerator and Generator classes. Leaving the implementation of +``RandomState`` fixed meant that it could not use the new BitGenerator state objects. Developing programs that use a mixture of libraries that have and have not upgraded would require managing two sets of PRNG states. This would notionally have been time-limited, but we intended the deprecation to be very @@ -308,9 +307,9 @@ long. The current proposal solves all of these problems. All current usages of ``RandomState`` will continue to work in perpetuity, though some may be discouraged through documentation. Unit tests can continue to use the full -complement of ``RandomState`` methods. Mixed ``RandomState/RandomGenerator`` -code can safely share the common basic RNG state. Unmodified ``RandomState`` -code can make use of the new features of alternative basic RNGs like settable +complement of ``RandomState`` methods. Mixed ``RandomState/Generator`` +code can safely share the common BitGenerator state. Unmodified ``RandomState`` +code can make use of the new features of alternative BitGenerators like settable streams. diff --git a/doc/source/reference/random/brng/dsfmt.rst b/doc/source/reference/random/bit_generators/dsfmt.rst similarity index 81% rename from doc/source/reference/random/brng/dsfmt.rst rename to doc/source/reference/random/bit_generators/dsfmt.rst index a47586a50f5f..e7c6dbb31811 100644 --- a/doc/source/reference/random/brng/dsfmt.rst +++ b/doc/source/reference/random/bit_generators/dsfmt.rst @@ -23,14 +23,7 @@ Parallel generation .. autosummary:: :toctree: generated/ - ~DSFMT.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~DSFMT.generator + ~DSFMT.jumped Extending ========= diff --git a/doc/source/reference/random/brng/index.rst b/doc/source/reference/random/bit_generators/index.rst similarity index 62% rename from doc/source/reference/random/brng/index.rst rename to doc/source/reference/random/bit_generators/index.rst index a7e5ad8730ee..e3ca073c95c2 100644 --- a/doc/source/reference/random/brng/index.rst +++ b/doc/source/reference/random/bit_generators/index.rst @@ -1,12 +1,12 @@ -.. _brng: +.. _bit_generator: -Basic Random Number Generators ------------------------------- +Bit Generators +-------------- .. currentmodule:: numpy.random -The random values produced by :class:`~RandomGenerator` -are produced by a basic RNG. These basic RNGs do not directly provide +The random values produced by :class:`~Generator` +orignate in a BitGenerator. The BitGenerators do not directly provide random numbers and only contains methods used for seeding, getting or setting the state, jumping or advancing the state, and for accessing low-level wrappers for consumption by code that can efficiently @@ -20,23 +20,20 @@ Stable RNGs DSFMT MT19937 - PCG64 Philox ThreeFry XoroShiro128+ Xorshift1024*φ - Xoshiro256** - Xoshiro512** + Xoshiro256** + Xoshiro512** Experimental RNGs ================= -These RNGs are currently included for testing but are may not be -permanent. +These BitGenerators are currently included but are may not be permanent. .. toctree:: :maxdepth: 1 - PCG32 ThreeFry32 diff --git a/doc/source/reference/random/brng/mt19937.rst b/doc/source/reference/random/bit_generators/mt19937.rst similarity index 80% rename from doc/source/reference/random/brng/mt19937.rst rename to doc/source/reference/random/bit_generators/mt19937.rst index 1bd3597c8a0c..f5843ccf0e63 100644 --- a/doc/source/reference/random/brng/mt19937.rst +++ b/doc/source/reference/random/bit_generators/mt19937.rst @@ -22,14 +22,7 @@ Parallel generation .. autosummary:: :toctree: generated/ - ~MT19937.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~MT19937.generator + ~MT19937.jumped Extending ========= diff --git a/doc/source/reference/random/brng/philox.rst b/doc/source/reference/random/bit_generators/philox.rst similarity index 80% rename from doc/source/reference/random/brng/philox.rst rename to doc/source/reference/random/bit_generators/philox.rst index c1e047c5466d..7ef451d4bfec 100644 --- a/doc/source/reference/random/brng/philox.rst +++ b/doc/source/reference/random/bit_generators/philox.rst @@ -23,14 +23,7 @@ Parallel generation :toctree: generated/ ~Philox.advance - ~Philox.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~Philox.generator + ~Philox.jumped Extending ========= diff --git a/doc/source/reference/random/brng/threefry.rst b/doc/source/reference/random/bit_generators/threefry.rst similarity index 80% rename from doc/source/reference/random/brng/threefry.rst rename to doc/source/reference/random/bit_generators/threefry.rst index eefe16ea0937..951108d725fe 100644 --- a/doc/source/reference/random/brng/threefry.rst +++ b/doc/source/reference/random/bit_generators/threefry.rst @@ -23,14 +23,7 @@ Parallel generation :toctree: generated/ ~ThreeFry.advance - ~ThreeFry.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~ThreeFry.generator + ~ThreeFry.jumped Extending ========= diff --git a/doc/source/reference/random/brng/threefry32.rst b/doc/source/reference/random/bit_generators/threefry32.rst similarity index 80% rename from doc/source/reference/random/brng/threefry32.rst rename to doc/source/reference/random/bit_generators/threefry32.rst index f0d3dc281005..1af9491a6972 100644 --- a/doc/source/reference/random/brng/threefry32.rst +++ b/doc/source/reference/random/bit_generators/threefry32.rst @@ -23,14 +23,7 @@ Parallel generation :toctree: generated/ ~ThreeFry32.advance - ~ThreeFry32.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~ThreeFry32.generator + ~ThreeFry32.jumped Extending ========= diff --git a/doc/source/reference/random/brng/xoroshiro128.rst b/doc/source/reference/random/bit_generators/xoroshiro128.rst similarity index 79% rename from doc/source/reference/random/brng/xoroshiro128.rst rename to doc/source/reference/random/bit_generators/xoroshiro128.rst index 590552236c26..41f5238fcc68 100644 --- a/doc/source/reference/random/brng/xoroshiro128.rst +++ b/doc/source/reference/random/bit_generators/xoroshiro128.rst @@ -22,14 +22,7 @@ Parallel generation .. autosummary:: :toctree: generated/ - ~Xoroshiro128.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~Xoroshiro128.generator + ~Xoroshiro128.jumped Extending ========= diff --git a/doc/source/reference/random/brng/xorshift1024.rst b/doc/source/reference/random/bit_generators/xorshift1024.rst similarity index 79% rename from doc/source/reference/random/brng/xorshift1024.rst rename to doc/source/reference/random/bit_generators/xorshift1024.rst index 24ed3df04469..5d0c9048fe9f 100644 --- a/doc/source/reference/random/brng/xorshift1024.rst +++ b/doc/source/reference/random/bit_generators/xorshift1024.rst @@ -22,14 +22,7 @@ Parallel generation .. autosummary:: :toctree: generated/ - ~Xorshift1024.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~Xorshift1024.generator + ~Xorshift1024.jumped Extending ========= diff --git a/doc/source/reference/random/bit_generators/xoshiro256.rst b/doc/source/reference/random/bit_generators/xoshiro256.rst new file mode 100644 index 000000000000..fedc61b33323 --- /dev/null +++ b/doc/source/reference/random/bit_generators/xoshiro256.rst @@ -0,0 +1,35 @@ +Xoshiro256** +------------ + +.. module:: numpy.random.xoshiro256 + +.. currentmodule:: numpy.random.xoshiro256 + +.. autoclass:: Xoshiro256 + :exclude-members: + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256.seed + ~Xoshiro256.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256.jumped + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xoshiro256.cffi + ~Xoshiro256.ctypes + + diff --git a/doc/source/reference/random/bit_generators/xoshiro512.rst b/doc/source/reference/random/bit_generators/xoshiro512.rst new file mode 100644 index 000000000000..e39346cd633a --- /dev/null +++ b/doc/source/reference/random/bit_generators/xoshiro512.rst @@ -0,0 +1,35 @@ +Xoshiro512** +------------ + +.. module:: numpy.random.xoshiro512 + +.. currentmodule:: numpy.random.xoshiro512 + +.. autoclass:: Xoshiro512 + :exclude-members: + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512.seed + ~Xoshiro512.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512.jumped + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~Xoshiro512.cffi + ~Xoshiro512.ctypes + + diff --git a/doc/source/reference/random/brng/pcg32.rst b/doc/source/reference/random/brng/pcg32.rst deleted file mode 100644 index f079f5a8cb17..000000000000 --- a/doc/source/reference/random/brng/pcg32.rst +++ /dev/null @@ -1,43 +0,0 @@ -Parallel Congruent Generator (32-bit, PCG32) --------------------------------------------- - -.. module:: numpy.random.pcg32 - -.. currentmodule:: numpy.random.pcg32 - -.. autoclass:: PCG32 - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~PCG32.seed - ~PCG32.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~PCG32.advance - ~PCG32.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~PCG32.generator - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~PCG32.cffi - ~PCG32.ctypes - - diff --git a/doc/source/reference/random/brng/pcg64.rst b/doc/source/reference/random/brng/pcg64.rst deleted file mode 100644 index 93f026fcb4ed..000000000000 --- a/doc/source/reference/random/brng/pcg64.rst +++ /dev/null @@ -1,43 +0,0 @@ -Parallel Congruent Generator (64-bit, PCG64) --------------------------------------------- - -.. module:: numpy.random.pcg64 - -.. currentmodule:: numpy.random.pcg64 - -.. autoclass:: PCG64 - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~PCG64.seed - ~PCG64.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~PCG64.advance - ~PCG64.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~PCG64.generator - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~PCG64.cffi - ~PCG64.ctypes - - diff --git a/doc/source/reference/random/brng/xoshiro256starstar.rst b/doc/source/reference/random/brng/xoshiro256starstar.rst deleted file mode 100644 index 85c445666c29..000000000000 --- a/doc/source/reference/random/brng/xoshiro256starstar.rst +++ /dev/null @@ -1,42 +0,0 @@ -Xoshiro256** ------------- - -.. module:: numpy.random.xoshiro256starstar - -.. currentmodule:: numpy.random.xoshiro256starstar - -.. autoclass:: Xoshiro256StarStar - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~Xoshiro256StarStar.seed - ~Xoshiro256StarStar.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~Xoshiro256StarStar.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~Xoshiro256StarStar.generator - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~Xoshiro256StarStar.cffi - ~Xoshiro256StarStar.ctypes - - diff --git a/doc/source/reference/random/brng/xoshiro512starstar.rst b/doc/source/reference/random/brng/xoshiro512starstar.rst deleted file mode 100644 index 0c008d56eb44..000000000000 --- a/doc/source/reference/random/brng/xoshiro512starstar.rst +++ /dev/null @@ -1,42 +0,0 @@ -Xoshiro512** ------------- - -.. module:: numpy.random.xoshiro512starstar - -.. currentmodule:: numpy.random.xoshiro512starstar - -.. autoclass:: Xoshiro512StarStar - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~Xoshiro512StarStar.seed - ~Xoshiro512StarStar.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~Xoshiro512StarStar.jump - -Random Generator -================ -.. autosummary:: - :toctree: generated/ - - ~Xoshiro512StarStar.generator - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~Xoshiro512StarStar.cffi - ~Xoshiro512StarStar.ctypes - - diff --git a/doc/source/reference/random/change-log.rst b/doc/source/reference/random/change-log.rst deleted file mode 100644 index 1d9f2fefc179..000000000000 --- a/doc/source/reference/random/change-log.rst +++ /dev/null @@ -1,39 +0,0 @@ -Change Log for the original bashtage/randomgen repo ---------------------------------------------------- -v1.16.1 -======= -- Synchronized with upstream changes. -- Fixed a bug in gamma generation if the shape parameters is 0.0. - -v1.16.0 -======= -- Fixed a bug that affected ``randomgen.dsfmt.DSFMT`` when calling - ``~randomgen.dsfmt.DSFMT.jump`` or ``randomgen.dsfmt.DSFMT.seed`` - that failed to reset the buffer. This resulted in upto 381 values from the - previous state being used before the buffer was refilled at the new state. -- Fixed bugs in ``randomgen.xoshiro512starstar.Xoshiro512StarStar`` - and ``randomgen.xorshift1024.Xorshift1024`` where the fallback - entropy initialization used too few bytes. This bug is unlikely to be - encountered since this path is only encountered if the system random - number generator fails. -- Synchronized with upstream changes. - -v1.15.1 -======= -- Added Xoshiro256** and Xoshiro512**, the preferred generators of this class. -- Fixed bug in `jump` method of Random123 generators which did nto specify a default value. -- Added support for generating bounded uniform integers using Lemire's method. -- Synchronized with upstream changes, which requires moving the minimum supported NumPy to 1.13. - -v1.15 -===== -- Synced empty choice changes -- Synced upstream docstring changes -- Synced upstream changes in permutation -- Synced upstream doc fixes -- Added absolute_import to avoid import noise on Python 2.7 -- Add legacy generator mtrand which allows NumPy replication -- Improve type handling of integers -- Switch to array-fillers for 0 parameter distribution to improve performance -- Small changes to build on manylinux -- Build wheels using multibuild diff --git a/doc/source/reference/random/extending.rst b/doc/source/reference/random/extending.rst index f76e3984f851..f65d7708f806 100644 --- a/doc/source/reference/random/extending.rst +++ b/doc/source/reference/random/extending.rst @@ -2,16 +2,15 @@ Extending --------- -The basic RNGs have been designed to be extendable using standard tools for -high-performance Python -- numba and Cython. -The `~RandomGenerator` object can also be used with -user-provided basic RNGs as long as these export a small set of required -functions. +The BitGenerators have been designed to be extendable using standard tools for +high-performance Python -- numba and Cython. The `~Generator` object can also +be used with user-provided BitGenerators as long as these export a small set of +required functions. Numba ===== Numba can be used with either CTypes or CFFI. The current iteration of the -basic RNGs all export a small set of functions through both interfaces. +BitGenerators all export a small set of functions through both interfaces. This example shows how numba can be used to produce Box-Muller normals using a pure Python implementation which is then compiled. The random numbers are @@ -66,7 +65,7 @@ examples folder. Cython ====== -Cython can be used to unpack the ``PyCapsule`` provided by a basic RNG. +Cython can be used to unpack the ``PyCapsule`` provided by a BitGenerator. This example uses `~xoroshiro128.Xoroshiro128` and ``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an array. The usual caveats for writing high-performance code using Cython -- @@ -81,33 +80,29 @@ removing bounds checks and wrap around, providing array alignment information from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from numpy.random.common cimport * from numpy.random.distributions cimport random_gauss_zig - from numpy.random.xoroshiro128 import Xoroshiro128 + from numpy.random import Xoroshiro128 @cython.boundscheck(False) @cython.wraparound(False) def normals_zig(Py_ssize_t n): cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" + cdef bitgen_t *rng + cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values x = Xoroshiro128() capsule = x.capsule - # Optional check that the capsule if from a Basic RNG if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - # Cast the pointer - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) for i in range(n): - # Call the function random_values[i] = random_gauss_zig(rng) randoms = np.asarray(random_values) return randoms - -The basic RNG can also be directly accessed using the members of the basic +The BitGenerator can also be directly accessed using the members of the basic RNG structure. .. code-block:: cython @@ -116,8 +111,8 @@ RNG structure. @cython.wraparound(False) def uniforms(Py_ssize_t n): cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" + cdef bitgen_t *rng + cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values x = Xoroshiro128() @@ -126,7 +121,7 @@ RNG structure. if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") # Cast the pointer - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) for i in range(n): # Call the function @@ -139,29 +134,29 @@ examples folder. New Basic RNGs ============== -`~RandomGenerator` can be used with other -user-provided basic RNGs. The simplest way to write a new basic RNG is to -examine the pyx file of one of the existing basic RNGs. The key structure -that must be provided is the ``capsule`` which contains a ``PyCapsule`` to a -struct pointer of type ``brng_t``, +`~Generator` can be used with other user-provided BitGenerators. The simplest +way to write a new BitGenerator is to examine the pyx file of one of the +existing BitGenerators. The key structure that must be provided is the +``capsule`` which contains a ``PyCapsule`` to a struct pointer of type +``bitgen_t``, .. code-block:: c - typedef struct brng { + 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); - } brng_t; + } bitgen_t; which provides 5 pointers. The first is an opaque pointer to the data structure -used by the basic RNG. The next three are function pointers which return the -next 64- and 32-bit unsigned integers, the next random double and the next +used by the BitGenerators. The next three are function pointers which return +the next 64- and 32-bit unsigned integers, the next random double and the next raw value. This final function is used for testing and so can be set to the next 64-bit unsigned integer function if not needed. Functions inside -``RandomGenerator`` use this structure as in +``Generator`` use this structure as in .. code-block:: c - brng_state->next_uint64(brng_state->state) + bitgen_state->next_uint64(bitgen_state->state) diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst index 9d248732f5c9..ee70725e710a 100644 --- a/doc/source/reference/random/generator.rst +++ b/doc/source/reference/random/generator.rst @@ -2,84 +2,81 @@ Random Generator ---------------- -The `~RandomGenerator` provides access to +The `~Generator` provides access to a wide range of distributions, and served as a replacement for :class:`~numpy.random.RandomState`. The main difference between -the two is that ``RandomGenerator`` relies on an additional basic RNG to +the two is that ``Generator`` relies on an additional BitGenerator to manage state and generate the random bits, which are then transformed into -random values from useful distributions. The default basic RNG used by -``RandomGenerator`` is :class:`~xoroshiro128.Xoroshiro128`. The basic RNG can be -changed by passing an instantized basic RNG to ``RandomGenerator``. +random values from useful distributions. The default BitGenerator used by +``Generator`` is :class:`~xoroshiro128.Xoroshiro128`. The BitGenerator +can be changed by passing an instantized BitGenerator to ``Generator``. -.. autoclass:: RandomGenerator +.. autoclass:: Generator :exclude-members: -Accessing the RNG -================= +Accessing the BitGenerator +========================== .. autosummary:: :toctree: generated/ - ~RandomGenerator.brng + ~Generator.bit_generator Simple random data ================== .. autosummary:: :toctree: generated/ - ~RandomGenerator.rand - ~RandomGenerator.randn - ~RandomGenerator.randint - ~RandomGenerator.random_integers - ~RandomGenerator.random_sample - ~RandomGenerator.choice - ~RandomGenerator.bytes + ~Generator.integers + ~Generator.random + ~Generator.choice + ~Generator.bytes Permutations ============ .. autosummary:: :toctree: generated/ - ~RandomGenerator.shuffle - ~RandomGenerator.permutation + ~Generator.shuffle + ~Generator.permutation Distributions ============= .. autosummary:: :toctree: generated/ - ~RandomGenerator.beta - ~RandomGenerator.binomial - ~RandomGenerator.chisquare - ~RandomGenerator.dirichlet - ~RandomGenerator.exponential - ~RandomGenerator.f - ~RandomGenerator.gamma - ~RandomGenerator.geometric - ~RandomGenerator.gumbel - ~RandomGenerator.hypergeometric - ~RandomGenerator.laplace - ~RandomGenerator.logistic - ~RandomGenerator.lognormal - ~RandomGenerator.logseries - ~RandomGenerator.multinomial - ~RandomGenerator.multivariate_normal - ~RandomGenerator.negative_binomial - ~RandomGenerator.noncentral_chisquare - ~RandomGenerator.noncentral_f - ~RandomGenerator.normal - ~RandomGenerator.pareto - ~RandomGenerator.poisson - ~RandomGenerator.power - ~RandomGenerator.rayleigh - ~RandomGenerator.standard_cauchy - ~RandomGenerator.standard_exponential - ~RandomGenerator.standard_gamma - ~RandomGenerator.standard_normal - ~RandomGenerator.standard_t - ~RandomGenerator.triangular - ~RandomGenerator.uniform - ~RandomGenerator.vonmises - ~RandomGenerator.wald - ~RandomGenerator.weibull - ~RandomGenerator.zipf + ~Generator.beta + ~Generator.binomial + ~Generator.chisquare + ~Generator.dirichlet + ~Generator.exponential + ~Generator.f + ~Generator.gamma + ~Generator.geometric + ~Generator.gumbel + ~Generator.hypergeometric + ~Generator.laplace + ~Generator.logistic + ~Generator.lognormal + ~Generator.logseries + ~Generator.multinomial + ~Generator.multivariate_normal + ~Generator.negative_binomial + ~Generator.noncentral_chisquare + ~Generator.noncentral_f + ~Generator.normal + ~Generator.pareto + ~Generator.poisson + ~Generator.power + ~Generator.rayleigh + ~Generator.standard_cauchy + ~Generator.standard_exponential + ~Generator.standard_gamma + ~Generator.standard_normal + ~Generator.standard_t + ~Generator.triangular + ~Generator.uniform + ~Generator.vonmises + ~Generator.wald + ~Generator.weibull + ~Generator.zipf diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 9c8c99c38e97..032db8562a5c 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -39,28 +39,28 @@ which will be faster than the legacy methods in `RandomState` from numpy import random random.standard_normal() -`Generator` can be used as a direct replacement for `RandomState`, -although the random values are generated by `~xoroshiro128.Xoroshiro128`. The +`Generator` can be used as a direct replacement for `~RandomState`, although +the random values are generated by `~xoroshiro128.Xoroshiro128`. The `Generator` holds an instance of a BitGenerator. It is accessable as ``gen.bit_generator``. .. code-block:: python # As replacement for RandomState() - from numpy.random import RandomGenerator - rg = RandomGenerator() + from numpy.random import Generator + rg = Generator() rg.standard_normal() rg.bit_generator -Seeds can be passed to any of the basic RNGs. Here `mt19937.MT19937` is used -and the ``RandomGenerator`` is accessed via the attribute `mt19937.MT19937. -generator`. +Seeds can be passed to any of the BitGenerators. Here `mt19937.MT19937` is used +and is the wrapped with a `~.Generator`. + .. code-block:: python - from numpy.random import MT19937 - rg = MT19937(12345).generator + from numpy.random import Generator, MT19937 + rg = Generator(MT19937(12345)) rg.standard_normal() @@ -70,33 +70,32 @@ RandomGen takes a different approach to producing random numbers from the `RandomState` object. Random number generation is separated into two components, a bit generator and a random generator. -The basic RNG has a limited set of responsibilities. It manages the -underlying RNG state and provides functions to produce random doubles and -random unsigned 32- and 64-bit values. The basic random generator also handles -all seeding since this varies when using alternative basic RNGs. +The bit generator has a limited set of responsibilities. It manages state +and provides functions to produce random doubles and random unsigned 32- and +64-bit values. The bit generator also handles all seeding which varies with +different bit generators. The `random generator ` takes the bit generator-provided stream and transforms them into more useful distributions, e.g., simulated normal random values. This structure allows -alternative basic RNGs to be used without code duplication. +alternative bit generators to be used with little code duplication. The `Generator` is the user-facing object that is nearly identical to `RandomState`. The canonical method to initialize a generator passes a `~mt19937.MT19937` bit generator, the underlying bit generator in Python -- as -the sole argument. Note that the bit generator must be instantiated. - +the sole argument. Note that the BitGenerator must be instantiated. .. code-block:: python - rg = RandomGenerator(MT19937(12345)) - rg.random_sample() + from numpy.random import Generator, MT19937 + rg = Generator(MT19937()) + rg.random() -A shorthand method is also available which uses the `~mt19937.MT19937. -generator` property from a basic RNG to access an embedded random generator. +Seed information is directly passed to the bit generator. .. code-block:: python - rg = MT19937(12345).generator - rg.random_sample() + rg = Generator(MT19937(12345)) + rg.random() What's New or Different ~~~~~~~~~~~~~~~~~~~~~~~ @@ -136,7 +135,7 @@ What's New or Different is consistent with Python's `random.random`. See :ref:`new-or-different` for a complete list of improvements and -differences. +differences from the traditional ``Randomstate``. Parallel Generation ~~~~~~~~~~~~~~~~~~~ @@ -156,33 +155,32 @@ The included BitGenerators are: that returns a new generator with state as-if ``2**128`` draws have been made. * dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically the same, but with a different state and so it is not possible to produce a - sequence identical to MT19937. Supports ``jump`` and so can + sequence identical to MT19937. Supports ``jumped`` and so can be used in parallel applications. See the `dSFMT authors' page`_. * XoroShiro128+ - Improved version of XorShift128+ with better performance and statistical quality. Like the XorShift generators, it can be jumped to produce multiple streams in parallel applications. See - `~xoroshiro128.Xoroshiro128.jump` for details. - More information about this PRNG is available at the + `~xoroshiro128.Xoroshiro128.jumped` for details. + More information about this bit generator is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * XorShift1024*φ - Fast fast generator based on the XSadd - generator. Supports ``jump`` and so can be used in + generator. Supports ``jumped`` and so can be used in parallel applications. See the documentation for `~xorshift1024.Xorshift1024.jumped` for details. More information about these bit generators is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * Xorshiro256** and Xorshiro512** - The most recently introduced XOR, - shift, and rotate generator. Supports ``jump`` and so can be used in + shift, and rotate generator. Supports ``jumped`` and so can be used in parallel applications. See the documentation for `~xoshiro256.Xoshirt256.jumped` for details. More information about these bit generators is available at the `xorshift, xoroshiro and xoshiro authors' page`_. * ThreeFry and Philox - counter-based generators capable of being advanced an arbitrary number of steps or generating independent streams. See the - `Random123`_ page for more details about this class of PRNG. + `Random123`_ page for more details about this class of bit generators. .. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ .. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/ -.. _`PCG author's page`: http://www.pcg-random.org/ .. _`Random123`: https://www.deshawresearch.com/resources_random123.html Generator @@ -201,8 +199,8 @@ BitGenerators BitGenerators -New Features ------------- +Features +-------- .. toctree:: :maxdepth: 2 @@ -212,16 +210,9 @@ New Features Comparing Performance extending Reading System Entropy - references -Changes -~~~~~~~ +Original Source +~~~~~~~~~~~~~~~ This package was developed independently of NumPy and was integrated in version 1.17.0. The original repo is at https://github.com/bashtage/randomgen. - -.. toctree:: - :maxdepth: 2 - - Change Log - diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst index 3bf7569b0676..c5b92f1bb54a 100644 --- a/doc/source/reference/random/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -3,16 +3,18 @@ Legacy Random Generation ------------------------ The `~mtrand.RandomState` provides access to -legacy generators. These all depend on Box-Muller normals or -inverse CDF exponentials or gammas. This class should only be used +legacy generators. This generator is considered frozen and will have +no further improvements. It is guaranteed to produce the same values +as the final point release of NumPy v1.16. These all depend on Box-Muller +normals or inverse CDF exponentials or gammas. This class should only be used if it is essential to have randoms that are identical to what would have been produced by NumPy. `~mtrand.RandomState` adds additional information to the state which is required when using Box-Muller normals since these are produced in pairs. It is important to use -`~mtrand.RandomState.get_state` -when accessing the state so that these extra values are saved. +`~mtrand.RandomState.get_state`, and not the underlying bit generators +`state`, when accessing the state so that these extra values are saved. .. warning:: @@ -30,20 +32,19 @@ when accessing the state so that these extra values are saved. .. code-block:: python from numpy.random import MT19937 - from numpy.random._mtrand import RandomState as LegacyGenerator from numpy.random import RandomState - # Use same seed + + # Use same seed rs = RandomState(12345) mt19937 = MT19937(12345) - rg = RandomGenerator(mt19937) - lg = LegacyGenerator(mt19937) + lg = RandomState(mt19937) # Identical output rs.standard_normal() lg.standard_normal() - rs.random_sample() - rg.random_sample() + rs.random() + lg.random() rs.standard_exponential() lg.standard_exponential() diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst index d35cafe0620c..718fe05f1440 100644 --- a/doc/source/reference/random/multithreading.rst +++ b/doc/source/reference/random/multithreading.rst @@ -17,7 +17,7 @@ seed will produce the same outputs. .. code-block:: ipython - from numpy.random import Xorshift1024 + from numpy.random import Generator, Xorshift1024 import multiprocessing import concurrent.futures import numpy as np @@ -29,14 +29,13 @@ seed will produce the same outputs. threads = multiprocessing.cpu_count() self.threads = threads - self._random_generators = [] + self._random_generators = [rg] + last_rg = rg for _ in range(0, threads-1): - _rg = Xorshift1024() - _rg.state = rg.state - self._random_generators.append(_rg.generator) - rg.jump() - self._random_generators.append(rg.generator) - + new_rg = last_rg.jumped() + self._random_generators.append(new_rg) + last_rg = new_rg + self.n = n self.executor = concurrent.futures.ThreadPoolExecutor(threads) self.values = np.empty(n) @@ -90,7 +89,7 @@ The single threaded call directly uses the BitGenerator. .. code-block:: ipython In [5]: values = np.empty(10000000) - ...: rg = Xorshift1024().generator + ...: rg = Generator(Xorshift1024()) ...: %timeit rg.standard_normal(out=values) 99.6 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) @@ -101,7 +100,7 @@ that does not use an existing array due to array creation overhead. .. code-block:: ipython - In [6]: rg = Xorshift1024().generator + In [6]: rg = Generator(Xorshift1024()) ...: %timeit rg.standard_normal(10000000) 125 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst index 4922b6762c6d..906cceceb5fe 100644 --- a/doc/source/reference/random/new-or-different.rst +++ b/doc/source/reference/random/new-or-different.rst @@ -35,7 +35,11 @@ Feature Older Equivalent Notes Many other distributions are also supported. -=================== =================== ============= +------------------ -------------------- ------------- +``Generator().`` ``randint``, Use the ``endpoint`` kwarg to adjust +``integers()`` ``random_integers`` the inclusion or exclution of the + ``high`` interval endpoint +================== ==================== ============= And in more detail: @@ -43,26 +47,29 @@ And in more detail: source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). * Simulate from the complex normal distribution - (`~.RandomGenerator.complex_normal`) + (`~.Generator.complex_normal`) * The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy's default implementation in - `~.RandomGenerator.standard_normal`, - `~.RandomGenerator.standard_exponential` or - `~.RandomGenerator.standard_gamma`. + `~.Generator.standard_normal`, `~.Generator.standard_exponential` or + `~.Generator.standard_gamma`. +* `~.Generator.integers` is now the canonical way to generate integer + random numbers from a discrete uniform distribution. The ``rand`` and + ``randn`` methods are only availabe through the legacy `~.RandomState`. + This replaces both ``randint`` and the deprecated ``random_integers``. * The Box-Muller used to produce NumPy's normals is no longer available. -* All basic random generators functions to produce doubles, uint64s and +* All bit generators can produce doubles, uint64s and uint32s via CTypes (`~.xoroshiro128.Xoroshiro128. ctypes`) and CFFI (`~.xoroshiro128.Xoroshiro128.cffi`). - This allows these basic RNGs to be used in numba. -* The basic random number generators can be used in downstream projects via + This allows these bit generators to be used in numba. +* The bit generators can be used in downstream projects via Cython. .. ipython:: python - from numpy.random import Xoroshiro128 + from numpy.random import Generator, Xoroshiro128 import numpy.random - rg = Xoroshiro128().generator + rg = Generator(Xoroshiro128()) %timeit rg.standard_normal(100000) %timeit numpy.random.standard_normal(100000) @@ -80,27 +87,25 @@ And in more detail: to produce either single or double prevision uniform random variables for select distributions - * Uniforms (`~.RandomGenerator.random_sample` and - `~.RandomGenerator.rand`) - * Normals (`~.RandomGenerator.standard_normal` and - `~.RandomGenerator.randn`) - * Standard Gammas (`~.RandomGenerator.standard_gamma`) - * Standard Exponentials (`~.RandomGenerator.standard_exponential`) + * Uniforms (`~.Generator.random` and `~.Generator.integers`) + * Normals (`~.Generator.standard_normal`) + * Standard Gammas (`~.Generator.standard_gamma`) + * Standard Exponentials (`~.Generator.standard_exponential`) .. ipython:: python - rg.brng.seed(0) - rg.random_sample(3, dtype='d') - rg.brng.seed(0) - rg.random_sample(3, dtype='f') + rg.bit_generator.seed(0) + rg.random(3, dtype='d') + rg.bit_generator.seed(0) + rg.random(3, dtype='f') * Optional ``out`` argument that allows existing arrays to be filled for select distributions - * Uniforms (`~.RandomGenerator.random_sample`) - * Normals (`~.RandomGenerator.standard_normal`) - * Standard Gammas (`~.RandomGenerator.standard_gamma`) - * Standard Exponentials (`~.RandomGenerator.standard_exponential`) + * Uniforms (`~.Generator.random`) + * Normals (`~.Generator.standard_normal`) + * Standard Gammas (`~.Generator.standard_gamma`) + * Standard Exponentials (`~.Generator.standard_exponential`) This allows multithreading to fill large arrays in chunks using suitable BitGenerators in parallel. @@ -108,16 +113,6 @@ And in more detail: .. ipython:: python existing = np.zeros(4) - rg.random_sample(out=existing[:2]) + rg.random(out=existing[:2]) print(existing) -.. * For changes since the previous release, see the :ref:`change-log` - -* Support for Lemire’s method of generating uniform integers on an - arbitrary interval by setting ``use_masked=True`` in - (`~.RandomGenerator.randint`). - -.. ipython:: python - - %timeit rg.randint(0, 1535, use_masked=False) - %timeit numpy.random.randint(0, 1535) diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst index c831effa29d7..8bdc3f23fd39 100644 --- a/doc/source/reference/random/parallel.rst +++ b/doc/source/reference/random/parallel.rst @@ -12,20 +12,20 @@ or distributed). Independent Streams ------------------- -:class:`~pcg64.PCG64`, :class:`~threefry.ThreeFry` -and :class:`~philox.Philox` support independent streams. This -example shows how many streams can be created by passing in different index -values in the second input while using the same seed in the first. +:class:`~threefry.ThreeFry` and :class:`~philox.Philox` support independent +streams. This example shows how many streams can be created by passing in +different index values in the second input while using the same seed in the +first. .. code-block:: python from numpy.random.entropy import random_entropy - from numpy.random import PCG64 + from numpy.random import ThreeFry entropy = random_entropy(4) # 128-bit number as a seed seed = sum([int(entropy[i]) * 2 ** (32 * i) for i in range(4)]) - streams = [PCG64(seed, stream) for stream in range(10)] + streams = [ThreeFry(seed, stream) for stream in range(10)] :class:`~philox.Philox` and :class:`~threefry.ThreeFry` are @@ -49,8 +49,8 @@ to produce independent streams. Jump/Advance the BitGenerator state ----------------------------------- -Jump -**** +Jumped +****** ``jumped`` advances the state of the BitGenerator *as-if* a large number of random numbers have been drawn, and returns a new instance with this state. @@ -68,8 +68,6 @@ are listed below. +-----------------+-------------------------+-------------------------+-------------------------+ | MT19937 | :math:`2^{19937}` | :math:`2^{128}` | 32 | +-----------------+-------------------------+-------------------------+-------------------------+ -| PCG64 | :math:`2^{128}` | :math:`2^{64}` | 64 | -+-----------------+-------------------------+-------------------------+-------------------------+ | Philox | :math:`2^{256}` | :math:`2^{128}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ | ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 | @@ -78,6 +76,10 @@ are listed below. +-----------------+-------------------------+-------------------------+-------------------------+ | Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ +| Xoshiro256** | :math:`2^{256}` | :math:`2^{128}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ +| Xoshiro512** | :math:`2^{512}` | :math:`2^{256}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ ``jumped`` can be used to produce long blocks which should be long enough to not overlap. @@ -93,16 +95,14 @@ overlap. blocked_rng = [] rng = Xorshift1024(seed) for i in range(10): - blocked_rng.append(rng.jumped()) - + blocked_rng.append(rng.jumped(i)) Advance ******* ``advance`` can be used to jump the state an arbitrary number of steps, and so -is a more general approach than ``jump``. :class:`~pcg64.PCG64`, -:class:`~threefry.ThreeFry` and :class:`~philox.Philox` -support ``advance``, and since these also support independent -streams, it is not usually necessary to use ``advance``. +is a more general approach than ``jumped``. :class:`~threefry.ThreeFry` and +:class:`~philox.Philox` support ``advance``, and since these also support +independent streams, it is not usually necessary to use ``advance``. Advancing a BitGenerator updates the underlying state as-if a given number of calls to the BitGenerator have been made. In general there is not a @@ -120,23 +120,23 @@ This occurs for two reasons: Advancing the BitGenerator state resets any pre-computed random numbers. This is required to ensure exact reproducibility. -This example uses ``advance`` to advance a :class:`~pcg64.PCG64` +This example uses ``advance`` to advance a :class:`~threefry.ThreeFry` generator 2 ** 127 steps to set a sequence of random number generators. .. code-block:: python - from numpy.random import PCG64 - brng = PCG64() - brng_copy = PCG64() - brng_copy.state = brng.state + from numpy.random import ThreeFry + bit_generator = ThreeFry() + bit_generator_copy = ThreeFry() + bit_generator_copy.state = bit_generator.state advance = 2**127 - brngs = [brng] + bit_generators = [bit_generator] for _ in range(9): - brng_copy.advance(advance) - brng = PCG64() - brng.state = brng_copy.state - brngs.append(brng) + bit_generator_copy.advance(advance) + bit_generator = ThreeFry() + bit_generator.state = bit_generator_copy.state + bit_generators.append(bit_generator) .. end block diff --git a/doc/source/reference/random/performance.py b/doc/source/reference/random/performance.py index 12cbbc5d38f0..a29e09c41b5d 100644 --- a/doc/source/reference/random/performance.py +++ b/doc/source/reference/random/performance.py @@ -4,16 +4,15 @@ import numpy as np import pandas as pd -from randomgen import MT19937, DSFMT, ThreeFry, PCG64, Xoroshiro128, \ - Xorshift1024, Philox, Xoshiro256StarStar, Xoshiro512StarStar +from numpy.random import MT19937, DSFMT, ThreeFry, Xoroshiro128, \ + Xorshift1024, Philox, Xoshiro256, Xoshiro512 -PRNGS = [DSFMT, MT19937, Philox, PCG64, ThreeFry, Xoroshiro128, Xorshift1024, - Xoshiro256StarStar, Xoshiro512StarStar] +PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoroshiro128, Xorshift1024, + Xoshiro256, Xoshiro512] -funcs = {'32-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', - '64-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)', - 'Uniforms': 'random_sample(size=1000000)', - 'Complex Normals': 'complex_normal(size=1000000)', +funcs = {'32-bit Unsigned Ints': 'integers(0, 2**32,size=1000000, dtype="uint32")', + '64-bit Unsigned Ints': 'integers(0, 2**64,size=1000000, dtype="uint64")', + 'Uniforms': 'random(size=1000000)', 'Normals': 'standard_normal(size=1000000)', 'Exponentials': 'standard_exponential(size=1000000)', 'Gammas': 'standard_gamma(3.0,size=1000000)', @@ -22,8 +21,8 @@ 'Poissons': 'poisson(3.0, size=1000000)', } setup = """ -from randomgen import {prng} -rg = {prng}().generator +from numpy.random import {prng}, Generator +rg = Generator({prng}()) """ test = "rg.{func}" @@ -43,7 +42,6 @@ npfuncs.update(funcs) npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)' npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)' -del npfuncs['Complex Normals'] setup = """ from numpy.random import RandomState rg = RandomState() diff --git a/doc/source/reference/random/performance.rst b/doc/source/reference/random/performance.rst index 321d494547c7..61898ac89a8d 100644 --- a/doc/source/reference/random/performance.rst +++ b/doc/source/reference/random/performance.rst @@ -10,21 +10,19 @@ Recommendation The recommended generator for single use is :class:`~xoroshiro128.Xoroshiro128`. The recommended generator for use in large-scale parallel applications is -:class:`~xorshift1024.Xorshift1024` -where the `jump` method is used to advance the state. For very large scale +:class:`~.xoshiro256.Xoshiro256` +where the `jumped` method is used to advance the state. For very large scale applications -- requiring 1,000+ independent streams, -:class:`~pcg64.PCG64` or :class:`~threefry.ThreeFry` are -the best choices. +:class:`~.philox.Philox` is the best choice. Timings ******* -The timings below are the time in ms to produce 1,000,000 random values from a +The timings below are the time in ns to produce 1 random value from a specific distribution. :class:`~xoroshiro128.Xoroshiro128` is the -fastest, followed by :class:`~xorshift1024.Xorshift1024` and -:class:`~pcg64.PCG64`. The original :class:`~mt19937.MT19937` -generator is much slower since it requires 2 32-bit values to equal the output -of the faster generators. +fastest, followed by :class:`~xorshift1024.Xorshift1024`. The original +:class:`~mt19937.MT19937` generator is much slower since it requires 2 32-bit +values to equal the output of the faster generators. Integer performance has a similar ordering although `dSFMT` is slower since it generates 53-bit floating point values rather than integer values. On the @@ -37,40 +35,38 @@ performance gap for Exponentials is also large due to the cost of computing the log function to invert the CDF. .. csv-table:: - :header: ,Xoroshiro128,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy - :widths: 14,14,14,14,14,14,14,14,14 + :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry,NumPy + :widths: 14,14,14,14,14,14,14,14 - 32-bit Unsigned Ints,3.0,3.0,3.0,3.5,3.7,6.8,6.6,3.3 - 64-bit Unsigned Ints,2.6,3.0,3.1,3.4,3.8,6.9,6.6,8.8 - Uniforms,3.2,3.8,4.4,5.0,7.4,8.9,9.9,8.8 - Normals,11.0,13.9,13.7,15.8,16.9,17.8,18.8,63.0 - Exponentials,7.0,8.4,9.0,11.2,12.5,14.1,15.0,102.2 - Binomials,20.9,22.6,22.0,21.2,26.7,27.7,29.2,26.5 - Complex Normals,23.2,28.7,29.1,33.2,35.4,37.6,38.6, - Gammas,35.3,38.6,39.2,41.3,46.7,49.4,51.2,98.8 - Laplaces,97.8,99.9,99.8,96.2,104.1,104.6,104.8,104.1 - Poissons,104.8,113.2,113.3,107.6,129.7,135.6,138.1,131.9 + 64-bit Unsigned Ints,11.9,13.6,14.9,18.0,22.0,25.9,42.0 + Uniforms,16.3,15.6,16.0,19.1,23.5,25.5,44.1 + 32-bit Unsigned Ints,21.6,23.7,23.1,23.6,27.9,32.3,17.9 + Exponentials,21.2,22.4,23.8,26.7,30.8,33.0,115.3 + Normals,25.1,26.9,26.2,31.7,32.6,37.8,106.8 + Binomials,72.4,73.0,71.9,77.4,80.0,83.1,101.9 + Complex Normals,80.4,86.4,81.1,93.4,96.3,105.5, + Laplaces,97.0,97.4,99.6,109.8,102.3,105.1,125.3 + Gammas,91.3,91.2,94.8,101.7,108.7,113.8,187.9 + Poissons,136.7,137.6,139.7,161.9,171.0,181.0,265.1 The next table presents the performance relative to `xoroshiro128+` in percentage. The overall performance was computed using a geometric mean. .. csv-table:: - :header: ,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy - :widths: 14,14,14,14,14,14,14,14 + :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry + :widths: 14,14,14,14,14,14,14 - 32-bit Unsigned Ints,102,99,118,125,229,221,111 - 64-bit Unsigned Ints,114,116,129,143,262,248,331 - Uniforms,116,137,156,231,275,306,274 - Normals,126,124,143,153,161,170,572 - Exponentials,121,130,161,179,203,215,1467 - Binomials,108,105,101,128,133,140,127 - Complex Normals,124,125,143,153,162,166, - Gammas,109,111,117,132,140,145,280 - Laplaces,102,102,98,106,107,107,106 - Poissons,108,108,103,124,129,132,126 - Overall,113,115,125,144,172,177,251 - + 64-bit Unsigned Ints,353,309,283,233,191,162 + Uniforms,271,283,276,232,188,173 + 32-bit Unsigned Ints,83,76,78,76,64,56 + Exponentials,544,514,485,432,375,350 + Normals,425,397,407,337,328,283 + Binomials,141,140,142,132,127,123 + Laplaces,129,129,126,114,123,119 + Gammas,206,206,198,185,173,165 + Poissons,194,193,190,164,155,146 + Overall,223,215,210,186,170,156 .. note:: diff --git a/doc/source/reference/random/references.rst b/doc/source/reference/random/references.rst deleted file mode 100644 index 0dc99868f1e5..000000000000 --- a/doc/source/reference/random/references.rst +++ /dev/null @@ -1,5 +0,0 @@ -References ----------- - -.. [Lemire] Daniel Lemire., "Fast Random Integer Generation in an Interval", - CoRR, Aug. 13, 2018, http://arxiv.org/abs/1805.10941. diff --git a/numpy/random/LICENSE.md b/numpy/random/LICENSE.md index caa665373a6e..a6cf1b17e997 100644 --- a/numpy/random/LICENSE.md +++ b/numpy/random/LICENSE.md @@ -64,45 +64,8 @@ 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.** -# NumPy and Other Components - -Many parts of this module have been derived from NumPy. Other parts have been -derived from original sources, often the algorithm's designer. The NumPy license -is reproduced below. Component licenses are located with the component code. - -Copyright (c) 2005-2019, 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. - -## Components - -Many of the components have their own license terms which are stored -with the source for the component. +# 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 431d9701376e..7c30ada1547b 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -3,37 +3,41 @@ Random Number Generation ======================== -Instantiate a RandomNumberGenerator (RNG) and wrap it in a RandomGenerator -which will convert the uniform stream to a number of distributions. For -covenience, the module provides an instantiated instance of a RandomGenerator -available as ``gen``. +Instantiate a BitGenerator and wrap it in a Generator +which will convert the uniform stream to a number of distributions. The "bare" +functions are kept for legacy code, they should be called with the newer API +via ``np.random.Generator().function`` instead ==================== ========================================================= Utility functions -============================================================================== -random_sample Uniformly distributed floats over ``[0, 1)``. -random Alias for `random_sample`. +-------------------- --------------------------------------------------------- +random Uniformly distributed floats over ``[0, 1)`` +integers Uniformly distributed integers, replaces ``randint`` 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 ==================== ========================================================= ==================== ========================================================= -Univariate distributions -============================================================================== +Univariate +distributions +-------------------- --------------------------------------------------------- beta Beta distribution over ``[0, 1]``. binomial Binomial distribution. chisquare :math:`\\chi^2` distribution. @@ -63,17 +67,19 @@ 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. @@ -83,26 +89,24 @@ ==================== ========================================================= Internal functions -============================================================================== +-------------------- --------------------------------------------------------- get_state Get tuple representing internal state of generator. set_state Set state of generator. ==================== ========================================================= -==================== ========================================================= -Random Number Streams that work with RandomGenerator -============================================================================== +============================================= === +BitGenerator Streams that work with Generator +--------------------------------------------- --- MT19937 DSFMT -PCG32 -PCG64 Philox ThreeFry ThreeFry32 Xoroshiro128 Xoroshift1024 -Xoshiro256StarStar -Xoshiro512StarStar -==================== ========================================================= +Xoshiro256 +Xoshiro512 +============================================= === """ from __future__ import division, absolute_import, print_function @@ -160,24 +164,20 @@ from . import mtrand from .mtrand import * from .dsfmt import DSFMT -from .generator import RandomGenerator +from .generator import Generator from .mt19937 import MT19937 -from .pcg32 import PCG32 -from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry from .threefry32 import ThreeFry32 from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 -from .xoshiro256starstar import Xoshiro256StarStar -from .xoshiro512starstar import Xoshiro512StarStar +from .xoshiro256 import Xoshiro256 +from .xoshiro512 import Xoshiro512 from .mtrand import RandomState -gen = RandomGenerator(Xoshiro512StarStar()) - -__all__ += ['RandomGenerator', 'DSFMT', 'MT19937', 'PCG64', 'PCG32', 'Philox', +__all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox', 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256StarStar', 'Xoshiro512StarStar', 'RandomState', 'gen'] + 'Xoshiro256', 'Xoshiro512', 'RandomState'] # Some aliases: ranf = random = sample = random_sample diff --git a/numpy/random/_pickle.py b/numpy/random/_pickle.py index 1c365b0c7c8a..391c565a5300 100644 --- a/numpy/random/_pickle.py +++ b/numpy/random/_pickle.py @@ -1,103 +1,88 @@ -from .generator import RandomGenerator -from .dsfmt import DSFMT -from .mt19937 import MT19937 -from .pcg32 import PCG32 -from .pcg64 import PCG64 +from .mtrand import RandomState from .philox import Philox from .threefry import ThreeFry from .threefry32 import ThreeFry32 from .xoroshiro128 import Xoroshiro128 from .xorshift1024 import Xorshift1024 -from .xoshiro256starstar import Xoshiro256StarStar -from .xoshiro512starstar import Xoshiro512StarStar -from .mtrand import RandomState +from .xoshiro256 import Xoshiro256 +from .xoshiro512 import Xoshiro512 + +from .dsfmt import DSFMT +from .generator import Generator +from .mt19937 import MT19937 -BasicRNGS = {'MT19937': MT19937, +BitGenerators = {'MT19937': MT19937, 'DSFMT': DSFMT, - 'PCG32': PCG32, - 'PCG64': PCG64, 'Philox': Philox, 'ThreeFry': ThreeFry, 'ThreeFry32': ThreeFry32, 'Xorshift1024': Xorshift1024, 'Xoroshiro128': Xoroshiro128, - 'Xoshiro256StarStar': Xoshiro256StarStar, - 'Xoshiro512StarStar': Xoshiro512StarStar, + 'Xoshiro256': Xoshiro256, + 'Xoshiro512': Xoshiro512, } -def __generator_ctor(brng_name='mt19937'): +def __generator_ctor(bit_generator_name='mt19937'): """ - Pickling helper function that returns a RandomGenerator object + Pickling helper function that returns a Generator object Parameters ---------- - brng_name: str - String containing the core PRNG + bit_generator_name: str + String containing the core BitGenerator Returns ------- - rg: RandomGenerator - RandomGenerator using the named core PRNG + rg: Generator + Generator using the named core BitGenerator """ - try: - brng_name = brng_name.decode('ascii') - except AttributeError: - pass - if brng_name in PRNGS: - brng = PRNGS[brng_name] + if bit_generator_name in BitGenerators: + bit_generator = BitGenerators[bit_generator_name] else: - raise ValueError(str(brng_name) + ' is not a known PRNG module.') + raise ValueError(str(bit_generator_name) + ' is not a known BitGenerator module.') - return RandomGenerator(brng()) + return Generator(bit_generator()) -def __brng_ctor(brng_name='mt19937'): +def __bit_generator_ctor(bit_generator_name='mt19937'): """ - Pickling helper function that returns a basic RNG object + Pickling helper function that returns a bit generator object Parameters ---------- - brng_name: str - String containing the name of the Basic RNG + bit_generator_name: str + String containing the name of the BitGenerator Returns ------- - brng: BasicRNG - Basic RNG instance + bit_generator: BitGenerator + BitGenerator instance """ - try: - brng_name = brng_name.decode('ascii') - except AttributeError: - pass - if brng_name in PRNGS: - brng = PRNGS[brng_name] + if bit_generator_name in BitGenerators: + bit_generator = BitGenerators[bit_generator_name] else: - raise ValueError(str(brng_name) + ' is not a known PRNG module.') + raise ValueError(str(bit_generator_name) + ' is not a known BitGenerator module.') - return brng() + return bit_generator() -def __randomstate_ctor(brng_name='mt19937'): +def __randomstate_ctor(bit_generator_name='mt19937'): """ Pickling helper function that returns a legacy RandomState-like object Parameters ---------- - brng_name: str - String containing the core BasicRNG + bit_generator_name: str + String containing the core BitGenerator Returns ------- rs: RandomState - Legacy RandomState using the named core BasicRNG + Legacy RandomState using the named core BitGenerator """ - try: - brng_name = brng_name.decode('ascii') - except AttributeError: - pass - if brng_name in BasicRNGS: - brng = BasicRNGS[brng_name] + if bit_generator_name in BitGenerators: + bit_generator = BitGenerators[bit_generator_name] else: - raise ValueError(str(brng_name) + ' is not a known BasicRNG module.') + raise ValueError(str(bit_generator_name) + ' is not a known BitGenerator module.') - return RandomState(brng()) + return RandomState(bit_generator()) diff --git a/numpy/random/bounded_integers.pxd.in b/numpy/random/bounded_integers.pxd.in index ceb09c3c2d06..7a3f224dca16 100644 --- a/numpy/random/bounded_integers.pxd.in +++ b/numpy/random/bounded_integers.pxd.in @@ -4,7 +4,7 @@ import numpy as np cimport numpy as np ctypedef np.npy_bool bool_t -from .common cimport brng_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""" @@ -22,5 +22,5 @@ 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, brng_t *state, object lock) +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 index 5fbd10b4fdac..9f385f521527 100644 --- a/numpy/random/bounded_integers.pyx.in +++ b/numpy/random/bounded_integers.pyx.in @@ -8,7 +8,7 @@ from .distributions cimport * np.import_array() -_randint_types = {'bool': (0, 2), +_integers_types = {'bool': (0, 2), 'int8': (-2**7, 2**7), 'int16': (-2**15, 2**15), 'int32': (-2**31, 2**31), @@ -31,7 +31,7 @@ type_info = (('uint32', 'uint32', 'uint64', 'NPY_UINT64', 0, 0, 0, '0X100000000U {{ 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, - brng_t *state, object lock): + bitgen_t *state, object lock): """ Array path for smaller integer types @@ -107,7 +107,7 @@ big_type_info = (('uint64', 'uint64', 'NPY_UINT64', '0x0ULL', '0xFFFFFFFFFFFFFFF {{ py: otype = nptype}} cdef object _rand_{{nptype}}_broadcast(object low, object high, object size, bint use_masked, bint closed, - brng_t *state, object lock): + bitgen_t *state, object lock): """ Array path for 64-bit integer types @@ -210,7 +210,7 @@ type_info = (('uint64', 'uint64', '0x0ULL', '0xFFFFFFFFFFFFFFFFULL'), {{ py: otype = nptype + '_' if nptype == 'bool' else nptype }} cdef object _rand_{{nptype}}(object low, object high, object size, bint use_masked, bint closed, - brng_t *state, object lock): + bitgen_t *state, object lock): """ _rand_{{nptype}}(low, high, size, use_masked, *state, lock) @@ -238,8 +238,8 @@ cdef object _rand_{{nptype}}(object low, object high, object size, 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 : basic random state - State to use in the core random number generators + 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 diff --git a/numpy/random/common.pxd b/numpy/random/common.pxd index f6748e5aa27d..4f7c8c903ada 100644 --- a/numpy/random/common.pxd +++ b/numpy/random/common.pxd @@ -5,7 +5,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t) from libc.math cimport sqrt -from .distributions cimport brng_t +from .distributions cimport bitgen_t import numpy as np cimport numpy as np @@ -26,10 +26,10 @@ cdef enum ConstraintType: ctypedef ConstraintType constraint_type -cdef object benchmark(brng_t *brng, object lock, Py_ssize_t cnt, object method) -cdef object random_raw(brng_t *brng, object lock, object size, object output) -cdef object prepare_cffi(brng_t *brng) -cdef object prepare_ctypes(brng_t *brng) +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 @@ -39,14 +39,14 @@ cdef extern from "src/aligned_malloc/aligned_malloc.h": cdef void *PyArray_calloc_aligned(size_t n, size_t s) cdef void PyArray_free_aligned(void *p) -ctypedef double (*random_double_fill)(brng_t *state, np.npy_intp count, double* out) nogil +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)(brng_t *state) nogil -ctypedef float (*random_float_1)(brng_t *state, float a) 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 @@ -55,22 +55,22 @@ 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)(brng_t *state) nogil -ctypedef uint32_t (*random_uint_1_i_32)(brng_t *state, uint32_t a) 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)(brng_t *state, int32_t a, int32_t b) nogil -ctypedef int64_t (*random_int_2_i)(brng_t *state, int64_t a, int64_t b) 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, brng_t *state, object size, object lock, object out) +cdef object double_fill(void *func, bitgen_t *state, object size, object lock, object out) -cdef object float_fill(void *func, brng_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, brng_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 np.ndarray int_to_array(object value, object name, object bits, object uint_size) @@ -86,7 +86,7 @@ cdef object disc(void *func, void *state, object size, object lock, object b, object b_name, constraint_type b_constraint, object c, object c_name, constraint_type c_constraint) -cdef object cont_f(void *func, brng_t *state, object size, object lock, +cdef object cont_f(void *func, bitgen_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out) diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx index d5918c3a9ed8..2fa854807bae 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -11,25 +11,26 @@ from .common cimport * np.import_array() interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', - 'next_uint32', 'next_double', 'brng']) + 'next_uint32', 'next_double', + 'bit_generator']) -cdef object benchmark(brng_t *brng, object lock, Py_ssize_t cnt, object method): - """Benchmark command used by BasicRNG""" +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): - brng.next_uint64(brng.state) + bitgen.next_uint64(bitgen.state) elif method==u'double': with lock, nogil: for i in range(cnt): - brng.next_double(brng.state) + bitgen.next_double(bitgen.state) else: raise ValueError('Unknown method') -cdef object random_raw(brng_t *brng, object lock, object size, object output): +cdef object random_raw(bitgen_t *bitgen, object lock, object size, object output): """ random_raw(self, size=None) @@ -65,17 +66,17 @@ cdef object random_raw(brng_t *brng, object lock, object size, object output): if not output: if size is None: with lock: - brng.next_raw(brng.state) + bitgen.next_raw(bitgen.state) return None n = np.asarray(size).sum() with lock, nogil: for i in range(n): - brng.next_raw(brng.state) + bitgen.next_raw(bitgen.state) return None if size is None: with lock: - return brng.next_raw(brng.state) + return bitgen.next_raw(bitgen.state) randoms = np.empty(size, np.uint64) randoms_data = np.PyArray_DATA(randoms) @@ -83,29 +84,29 @@ cdef object random_raw(brng_t *brng, object lock, object size, object output): with lock, nogil: for i in range(n): - randoms_data[i] = brng.next_raw(brng.state) + randoms_data[i] = bitgen.next_raw(bitgen.state) return randoms -cdef object prepare_cffi(brng_t *brng): +cdef object prepare_cffi(bitgen_t *bitgen): """ - Bundles the interfaces to interact with a Basic RNG using cffi + Bundles the interfaces to interact with a BitGenerator using cffi Parameters ---------- - brng : pointer - A pointer to a Basic RNG instance + bitgen : pointer + A pointer to a BitGenerator instance Returns ------- interface : namedtuple - The functions required to interface with the Basic RNG using cffi + 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 - * brng - pointer to the Basic RNG struct + * bit_generator - pointer to the BitGenerator struct """ try: import cffi @@ -113,49 +114,49 @@ cdef object prepare_cffi(brng_t *brng): raise ImportError('cffi cannot be imported.') ffi = cffi.FFI() - _cffi = interface(brng.state, - ffi.cast('void *', brng.state), - ffi.cast('uint64_t (*)(void *)', brng.next_uint64), - ffi.cast('uint32_t (*)(void *)', brng.next_uint32), - ffi.cast('double (*)(void *)', brng.next_double), - ffi.cast('void *', brng)) + _cffi = interface(bitgen.state, + ffi.cast('void *', bitgen.state), + ffi.cast('uint64_t (*)(void *)', bitgen.next_uint64), + ffi.cast('uint32_t (*)(void *)', bitgen.next_uint32), + ffi.cast('double (*)(void *)', bitgen.next_double), + ffi.cast('void *', bitgen)) return _cffi -cdef object prepare_ctypes(brng_t *brng): +cdef object prepare_ctypes(bitgen_t *bitgen): """ - Bundles the interfaces to interact with a Basic RNG using ctypes + Bundles the interfaces to interact with a BitGenerator using ctypes Parameters ---------- - brng : pointer - A pointer to a Basic RNG instance + bitgen : pointer + A pointer to a BitGenerator instance Returns ------- interface : namedtuple - The functions required to interface with the Basic RNG using ctypes: + 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 - * brng - pointer to the Basic RNG struct + * bit_generator - pointer to the BitGenerator struct """ import ctypes - _ctypes = interface(brng.state, - ctypes.c_void_p(brng.state), - ctypes.cast(brng.next_uint64, + _ctypes = interface(bitgen.state, + ctypes.c_void_p(bitgen.state), + ctypes.cast(bitgen.next_uint64, ctypes.CFUNCTYPE(ctypes.c_uint64, ctypes.c_void_p)), - ctypes.cast(brng.next_uint32, + ctypes.cast(bitgen.next_uint32, ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_void_p)), - ctypes.cast(brng.next_double, + ctypes.cast(bitgen.next_double, ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_void_p)), - ctypes.c_void_p(brng)) + ctypes.c_void_p(bitgen)) return _ctypes cdef double kahan_sum(double *darr, np.npy_intp n): @@ -218,7 +219,7 @@ cdef check_output(object out, object dtype, object size): raise ValueError('size must match out.shape when used together') -cdef object double_fill(void *func, brng_t *state, object size, object lock, object out): +cdef object double_fill(void *func, bitgen_t *state, object size, object lock, object out): cdef random_double_fill random_func = (func) cdef double out_val cdef double *out_array_data @@ -242,7 +243,7 @@ cdef object double_fill(void *func, brng_t *state, object size, object lock, obj random_func(state, n, out_array_data) return out_array -cdef object float_fill(void *func, brng_t *state, object size, object lock, object out): +cdef object float_fill(void *func, bitgen_t *state, object size, object lock, object out): cdef random_float_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -265,7 +266,7 @@ cdef object float_fill(void *func, brng_t *state, object size, object lock, obje out_array_data[i] = random_func(state) return out_array -cdef object float_fill_from_double(void *func, brng_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 random_double_0 random_func = (func) cdef float *out_array_data cdef np.ndarray out_array @@ -871,7 +872,7 @@ cdef object disc(void *func, void *state, object size, object lock, return randoms -cdef object cont_broadcast_1_f(void *func, brng_t *state, object size, object lock, +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): @@ -907,7 +908,7 @@ cdef object cont_broadcast_1_f(void *func, brng_t *state, object size, object lo return randoms -cdef object cont_f(void *func, brng_t *state, object size, object lock, +cdef object cont_f(void *func, bitgen_t *state, object size, object lock, object a, object a_name, constraint_type a_constraint, object out): diff --git a/numpy/random/distributions.pxd b/numpy/random/distributions.pxd index 841fd32536fe..5d6f0841732f 100644 --- a/numpy/random/distributions.pxd +++ b/numpy/random/distributions.pxd @@ -5,7 +5,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t, import numpy as np cimport numpy as np -cdef extern from "distributions/distributions.h": +cdef extern from "src/distributions/distributions.h": struct s_binomial_t: int has_binomial @@ -28,122 +28,122 @@ cdef extern from "distributions/distributions.h": ctypedef s_binomial_t binomial_t - struct brng: + 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 brng brng_t - - double random_double(brng_t *brng_state) nogil - void random_double_fill(brng_t* brng_state, np.npy_intp cnt, double *out) nogil - double random_standard_exponential(brng_t *brng_state) nogil - void random_standard_exponential_fill(brng_t *brng_state, np.npy_intp cnt, double *out) nogil - double random_standard_exponential_zig(brng_t *brng_state) nogil - void random_standard_exponential_zig_fill(brng_t *brng_state, np.npy_intp cnt, double *out) nogil - double random_gauss_zig(brng_t* brng_state) nogil - void random_gauss_zig_fill(brng_t *brng_state, np.npy_intp count, double *out) nogil - double random_standard_gamma_zig(brng_t *brng_state, double shape) nogil - - float random_float(brng_t *brng_state) nogil - float random_standard_exponential_f(brng_t *brng_state) nogil - float random_standard_exponential_zig_f(brng_t *brng_state) nogil - float random_gauss_zig_f(brng_t* brng_state) nogil - float random_standard_gamma_f(brng_t *brng_state, float shape) nogil - float random_standard_gamma_zig_f(brng_t *brng_state, float shape) nogil - - int64_t random_positive_int64(brng_t *brng_state) nogil - int32_t random_positive_int32(brng_t *brng_state) nogil - int64_t random_positive_int(brng_t *brng_state) nogil - uint64_t random_uint(brng_t *brng_state) nogil - - double random_normal_zig(brng_t *brng_state, double loc, double scale) nogil - - double random_gamma(brng_t *brng_state, double shape, double scale) nogil - float random_gamma_float(brng_t *brng_state, float shape, float scale) nogil - - double random_exponential(brng_t *brng_state, double scale) nogil - double random_uniform(brng_t *brng_state, double lower, double range) nogil - double random_beta(brng_t *brng_state, double a, double b) nogil - double random_chisquare(brng_t *brng_state, double df) nogil - double random_f(brng_t *brng_state, double dfnum, double dfden) nogil - double random_standard_cauchy(brng_t *brng_state) nogil - double random_pareto(brng_t *brng_state, double a) nogil - double random_weibull(brng_t *brng_state, double a) nogil - double random_power(brng_t *brng_state, double a) nogil - double random_laplace(brng_t *brng_state, double loc, double scale) nogil - double random_gumbel(brng_t *brng_state, double loc, double scale) nogil - double random_logistic(brng_t *brng_state, double loc, double scale) nogil - double random_lognormal(brng_t *brng_state, double mean, double sigma) nogil - double random_rayleigh(brng_t *brng_state, double mode) nogil - double random_standard_t(brng_t *brng_state, double df) nogil - double random_noncentral_chisquare(brng_t *brng_state, double df, + ctypedef bitgen bitgen_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(brng_t *brng_state, double dfnum, + double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden, double nonc) nogil - double random_wald(brng_t *brng_state, double mean, double scale) nogil - double random_vonmises(brng_t *brng_state, double mu, double kappa) nogil - double random_triangular(brng_t *brng_state, double left, double mode, + 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(brng_t *brng_state, double lam) nogil - int64_t random_negative_binomial(brng_t *brng_state, double n, double p) nogil - int64_t random_binomial(brng_t *brng_state, double p, int64_t n, binomial_t *binomial) nogil - int64_t random_logseries(brng_t *brng_state, double p) nogil - int64_t random_geometric_search(brng_t *brng_state, double p) nogil - int64_t random_geometric_inversion(brng_t *brng_state, double p) nogil - int64_t random_geometric(brng_t *brng_state, double p) nogil - int64_t random_zipf(brng_t *brng_state, double a) nogil - int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, + 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(brng_t *brng_state, uint64_t max) 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, + 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(brng_t *brng_state, int64_t n, int64_t *mnix, + 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/dsfmt.pyx b/numpy/random/dsfmt.pyx index 709c2c8e8cf2..cd6d9215385f 100644 --- a/numpy/random/dsfmt.pyx +++ b/numpy/random/dsfmt.pyx @@ -1,6 +1,6 @@ import operator -from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New +from libc.string cimport memcpy try: from threading import Lock @@ -11,7 +11,7 @@ import numpy as np cimport numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy np.import_array() @@ -76,59 +76,61 @@ cdef class DSFMT: Parameters ---------- seed : {None, int, array_like}, optional - 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] or ``None`` (the default). If `seed` is ``None``, - then ``DSFMT`` will try to read entropy from ``/dev/urandom`` - (or the Windows analog) if available to produce a 32-bit - seed. If unavailable, a 32-bit hash of the time and process - ID is used. + 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 unsigned 32-bit integers, or ``None`` (the default). If + `seed` is ``None``, a 32-bit unsigned integer is read from + ``/dev/urandom`` (or the Windows analog) if available. If unavailable, + a 32-bit hash of the time and process ID is used. Notes ----- - ``DSFMT`` directly provides generators for doubles, and unsigned 32 and 64- - bit integers [1]_ . These are not directly available and must be consumed - via a ``RandomGenerator`` object. + ``DSFMT`` 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. - **Parallel Features** - - ``DSFMT`` can be used in parallel applications by calling the method - ``jump`` which advances the state as-if :math:`2^{128}` random numbers - have been generated [2]_. This allows the original sequence to be split - so that distinct segments can be used in each worker process. All - generators should be initialized with the same seed to ensure that the - segments come from the same sequence. - - >>> from numpy.random.entropy import random_entropy - >>> from numpy.random import RandomGenerator, DSFMT - >>> seed = random_entropy() - >>> rs = [RandomGenerator(DSFMT(seed)) for _ in range(10)] - # Advance each DSFMT instance by i jumps - >>> for i in range(10): - ... rs[i].brng.jump() - **State and Seeding** - The ``DSFMT`` state vector consists of a 384 element array of - 64-bit unsigned integers plus a single integer value between 0 and 382 - indicating the current position within the main array. The implementation + The ``DSFMT`` state vector consists of a 384 element array of 64-bit + unsigned integers plus a single integer value between 0 and 382 + indicating the current position within the main array. The implementation used here augments this with a 382 element array of doubles which are used to efficiently access the random numbers produced by the dSFMT generator. - ``DSFMT`` is seeded using either a single 32-bit unsigned integer - or a vector of 32-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for a hashing function, and the output of the + ``DSFMT`` is seeded using either a single 32-bit unsigned integer or a + vector of 32-bit unsigned integers. In either case, the input seed is used + as an input (or inputs) for a hashing function, and the output of the hashing function is used as the initial state. Using a single 32-bit value for the seed can only initialize a small range of the possible initial state values. + **Parallel Features** + + ``DSFMT`` can be used in parallel applications by calling the method + ``jumped`` which advances the state as-if :math:`2^{128}` random numbers + have been generated [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.entropy import random_entropy + >>> from numpy.random import Generator, DSFMT + >>> seed = random_entropy() + >>> bit_generator = DSFMT(seed) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() + **Compatibility Guarantee** - ``DSFMT`` does makes a guarantee that a fixed seed and will always - produce the same results. + ``DSFMT`` makes a guarantee that a fixed seed and will always produce + the same random integer stream. References ---------- @@ -139,34 +141,30 @@ cdef class DSFMT: Jump Ahead Algorithm for Linear Recurrences in a Polynomial Space", Sequences and Their Applications - SETA, 290--298, 2008. """ - cdef dsfmt_state *rng_state - cdef brng_t *_brng + cdef dsfmt_state rng_state + cdef bitgen_t _bitgen cdef public object capsule - cdef public object _cffi - cdef public object _ctypes - cdef public object _generator + cdef object _cffi + cdef object _ctypes cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(dsfmt_state)) self.rng_state.state = PyArray_malloc_aligned(sizeof(dsfmt_t)) self.rng_state.buffered_uniforms = PyArray_calloc_aligned(DSFMT_N64, sizeof(double)) self.rng_state.buffer_loc = DSFMT_N64 - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &dsfmt_uint64 - self._brng.next_uint32 = &dsfmt_uint32 - self._brng.next_double = &dsfmt_double - self._brng.next_raw = &dsfmt_raw - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &dsfmt_uint64 + self._bitgen.next_uint32 = &dsfmt_uint32 + self._bitgen.next_double = &dsfmt_double + self._bitgen.next_raw = &dsfmt_raw + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) self._cffi = None self._ctypes = None - self._generator = None # Pickling support: def __getstate__(self): @@ -176,18 +174,14 @@ cdef class DSFMT: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state def __dealloc__(self): - if self.rng_state: + if self.rng_state.state: PyArray_free_aligned(self.rng_state.state) + if self.rng_state.buffered_uniforms: PyArray_free_aligned(self.rng_state.buffered_uniforms) - free(self.rng_state) - if self._brng: - free(self._brng) cdef _reset_state_variables(self): self.rng_state.buffer_loc = DSFMT_N64 @@ -196,7 +190,7 @@ cdef class DSFMT: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -221,10 +215,10 @@ cdef class DSFMT: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -274,28 +268,49 @@ cdef class DSFMT: # Clear the buffer self._reset_state_variables() - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**128 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive - Number of times to jump the state of the brng. - - Returns - ------- - self : DSFMT - PRNG jumped iter times + Number of times to jump the state of the rng. """ cdef np.npy_intp i for i in range(iter): - dsfmt_jump(self.rng_state) + dsfmt_jump(&self.rng_state) # Clear the buffer self._reset_state_variables() - return self + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(128 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : DSFMT + New instance of generator jumped iter times + """ + cdef DSFMT bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -321,7 +336,7 @@ cdef class DSFMT: buffered_uniforms = np.empty(DSFMT_N64, dtype=np.double) for i in range(DSFMT_N64): buffered_uniforms[i] = self.rng_state.buffered_uniforms[i] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': {'state': np.asarray(state), 'idx': self.rng_state.state.idx}, 'buffer_loc': self.rng_state.buffer_loc, @@ -332,8 +347,8 @@ cdef class DSFMT: cdef Py_ssize_t i, j, loc = 0 if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + bitgen = value.get('bit_generator', '') + if bitgen != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) state = value['state']['state'] @@ -362,10 +377,10 @@ cdef class DSFMT: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -384,24 +399,9 @@ cdef class DSFMT: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator # ignore - Random generator used this instance as the basic RNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/entropy.pyx b/numpy/random/entropy.pyx index 0e429e9f2631..72b0a9851047 100644 --- a/numpy/random/entropy.pyx +++ b/numpy/random/entropy.pyx @@ -28,7 +28,7 @@ def seed_by_array(object seed, Py_ssize_t n): Parameters ---------- - seed: array, 1d, uint64 + seed: ndarray, 1d, uint64 Array to use. If seed is a scalar, promote to array. n : int Number of 64-bit unsigned integers required @@ -106,8 +106,9 @@ def random_entropy(size=None, source='system'): Returns ------- - entropy : scalar or ndarray - Entropy bits in 32-bit unsigned integers + entropy : scalar or array + Entropy bits in 32-bit unsigned integers. A scalar is returned if size + is `None`. Notes ----- @@ -117,7 +118,7 @@ def random_entropy(size=None, source='system'): This function reads from the system entropy pool and so samples are not reproducible. In particular, it does *NOT* make use of a - basic RNG, and so ``seed`` and setting ``state`` have no + BitGenerator, and so ``seed`` and setting ``state`` have no effect. Raises RuntimeError if the command fails. diff --git a/numpy/random/examples/cython/extending.pyx b/numpy/random/examples/cython/extending.pyx index b472312b41d8..858bf2f62494 100644 --- a/numpy/random/examples/cython/extending.pyx +++ b/numpy/random/examples/cython/extending.pyx @@ -1,4 +1,6 @@ +#!/usr/bin/env python #cython: language_level=3 + from libc.stdint cimport uint32_t from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer @@ -6,16 +8,16 @@ import numpy as np cimport numpy as np cimport cython -from numpy.random.randomgen.common cimport brng_t -from numpy.random.randomgen import Xoroshiro128 +from numpy.random.common cimport bitgen_t +from numpy.random import Xoroshiro128 np.import_array() def uniform_mean(Py_ssize_t N): cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" + cdef bitgen_t *rng + cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values cdef np.ndarray randoms @@ -23,7 +25,7 @@ def uniform_mean(Py_ssize_t N): capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(N) for i in range(N): random_values[i] = rng.next_double(rng.state) @@ -31,7 +33,7 @@ def uniform_mean(Py_ssize_t N): return randoms.mean() -cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, brng_t *rng): +cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, bitgen_t *rng): cdef uint32_t mask, delta, val mask = delta = ub - lb mask |= mask >> 1 @@ -51,9 +53,9 @@ cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, brng_t *rng): @cython.wraparound(False) def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): cdef Py_ssize_t i - cdef brng_t *rng + cdef bitgen_t *rng cdef uint32_t[::1] out - cdef const char *capsule_name = "BasicRNG" + cdef const char *capsule_name = "BitGenerator" x = Xoroshiro128() out = np.empty(n, dtype=np.uint32) @@ -61,7 +63,7 @@ def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) for i in range(n): out[i] = bounded_uint(lb, ub, rng) diff --git a/numpy/random/examples/cython/extending_distributions.pyx b/numpy/random/examples/cython/extending_distributions.pyx index 26d749b10c51..da584e941a71 100644 --- a/numpy/random/examples/cython/extending_distributions.pyx +++ b/numpy/random/examples/cython/extending_distributions.pyx @@ -1,26 +1,28 @@ +#!/usr/bin/env python #cython: language_level=3 + import numpy as np cimport numpy as np cimport cython from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer -from numpy.random.randomgen.common cimport * -from numpy.random.randomgen.distributions cimport random_gauss_zig -from numpy.random.randomgen import Xoroshiro128 +from numpy.random.common cimport * +from numpy.random.distributions cimport random_gauss_zig +from numpy.random import Xoroshiro128 @cython.boundscheck(False) @cython.wraparound(False) def normals_zig(Py_ssize_t n): cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" + cdef bitgen_t *rng + cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values x = Xoroshiro128() capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) for i in range(n): random_values[i] = random_gauss_zig(rng) @@ -32,17 +34,17 @@ def normals_zig(Py_ssize_t n): @cython.wraparound(False) def uniforms(Py_ssize_t n): cdef Py_ssize_t i - cdef brng_t *rng - cdef const char *capsule_name = "BasicRNG" + cdef bitgen_t *rng + cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values x = Xoroshiro128() capsule = x.capsule - # Optional check that the capsule if from a Basic RNG + # 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 = PyCapsule_GetPointer(capsule, capsule_name) + rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) for i in range(n): # Call the function diff --git a/numpy/random/examples/cython/setup.py b/numpy/random/examples/cython/setup.py index d7a04f75a6c6..69f057ed5c72 100644 --- a/numpy/random/examples/cython/setup.py +++ b/numpy/random/examples/cython/setup.py @@ -1,4 +1,10 @@ -# python setup.py build_ext -i +#!/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 @@ -10,7 +16,7 @@ include_dirs=[np.get_include()]) distributions = Extension("extending_distributions", sources=['extending_distributions.pyx', - join('..', '..', '..', 'randomgen', 'src', + join('..', '..', 'src', 'distributions', 'distributions.c')], include_dirs=[np.get_include()]) diff --git a/numpy/random/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py index 17ba2704c2e4..e1a57fa4f349 100644 --- a/numpy/random/examples/numba/extending_distributions.py +++ b/numpy/random/examples/numba/extending_distributions.py @@ -35,26 +35,26 @@ raise RuntimeError('Required DLL/so file was not found.') ffi.cdef(""" -double random_gauss_zig(void *brng_state); +double random_gauss_zig(void *bitgen_state); """) x = Xoroshiro128() xffi = x.cffi -brng = xffi.brng +bit_generator = xffi.bitgen random_gauss_zig = lib.random_gauss_zig -def normals(n, brng): +def normals(n, bit_generator): out = np.empty(n) for i in range(n): - out[i] = random_gauss_zig(brng) + 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.brng.value -brng_address = int(ffi.cast('uintptr_t', brng)) +# Can also get address from x.ctypes.bit_generator.value +bit_generator_address = int(ffi.cast('uintptr_t', bit_generator)) -norm = normalsj(1000, brng_address) +norm = normalsj(1000, bit_generator_address) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 6910a1e48364..6cba3c3c71c6 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -3,32 +3,34 @@ import operator import warnings +import numpy as np + +from .bounded_integers import _integers_types +from .xoroshiro128 import Xoroshiro128 + from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport (Py_INCREF, PyFloat_AsDouble) from libc cimport string -from libc.stdlib cimport malloc, free -cimport numpy as np -import numpy as np + cimport cython +cimport numpy as np from .bounded_integers cimport * -from .bounded_integers import _randint_types from .common cimport * from .distributions cimport * -from .xoroshiro128 import Xoroshiro128 np.import_array() -cdef class RandomGenerator: +cdef class Generator: """ - RandomGenerator(brng=None) + Generator(bit_generator=None) - Container for the Basic Random Number Generators. + Container for the BitGenerators. - ``RandomGenerator`` 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 + ``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, @@ -36,98 +38,106 @@ cdef class RandomGenerator: **No Compatibility Guarantee** - ``RandomGenerator`` is evolving and so it isn't possible to provide a - compatibility guarantee like NumPy does. In particular, better algorithms - have already been added. This will change once ``RandomGenerator`` - stabilizes. + ``Generator`` does not provide a version compatibility guarantee. In + particular, as better algorithms evolve the bit stream may change. Parameters ---------- - brng : Basic RNG, optional - Basic RNG to use as the core generator. If none is provided, uses + bit_generator : BitGenerator, optional + BitGenerator to use as the core generator. If none is provided, uses Xoroshiro128. Notes ----- The Python stdlib module `random` contains pseudo-random number generator with a number of methods that are similar to the ones available in - ``RandomGenerator``. It uses Mersenne Twister, and this basic RNG can be - accessed using ``MT19937``. ``RandomGenerator``, besides being + ``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 RandomGenerator - >>> rg = RandomGenerator() + >>> from numpy.random import Generator + >>> rg = Generator() >>> rg.standard_normal() -0.203 # random Using a specific generator >>> from numpy.random import MT19937 - >>> rg = RandomGenerator(MT19937()) - - The generator is also directly available from basic RNGs - - >>> rg = MT19937().generator - >>> rg.standard_normal() - -0.203 # random + >>> rg = Generator(MT19937()) """ - cdef public object brng - cdef brng_t *_brng - cdef binomial_t *_binomial + 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, brng=None): - if brng is None: - brng = Xoroshiro128() - self.brng = brng + def __init__(self, bit_generator=None): + if bit_generator is None: + bit_generator = Xoroshiro128() + self._bit_generator = bit_generator - capsule = brng.capsule - cdef const char *name = "BasicRNG" + capsule = bit_generator.capsule + cdef const char *name = "BitGenerator" if not PyCapsule_IsValid(capsule, name): - raise ValueError("Invalid brng. The brng must be instantized.") - self._brng = PyCapsule_GetPointer(capsule, name) - self._binomial = malloc(sizeof(binomial_t)) - self.lock = brng.lock - - def __dealloc__(self): - if self._binomial: - free(self._binomial) + raise ValueError("Invalid bit generator'. The bit generator must " + "be instantiated.") + self._bitgen = ( 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.brng.__class__.__name__ + ')' + _str += '(' + self.bit_generator.__class__.__name__ + ')' return _str # Pickling support: def __getstate__(self): - return self.brng.state + return self.bit_generator.state def __setstate__(self, state): - self.brng.state = state + self.bit_generator.state = state def __reduce__(self): from ._pickle import __generator_ctor - return __generator_ctor, (self.brng.state['brng'],), self.brng.state + return __generator_ctor, (self.bit_generator.state['bit_generator'],), self.bit_generator.state - def random_sample(self, size=None, dtype=np.float64, out=None): + @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 """ - random_sample(size=None, dtype='d', out=None) + return self._bit_generator + + def random_sample(self, *args, **kwargs): + """ + Deprecated, renamed to ``random`` + """ + warnings.warn("Renamed to random", RuntimeWarning) + self.random(*args, **kwargs) + + + 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_sample` by `(b-a)` and add `a`:: + the output of `random` by `(b-a)` and add `a`:: - (b - a) * random_sample() + a + (b - a) * random() + a Parameters ---------- @@ -152,16 +162,16 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.gen.random_sample() + >>> np.random.Generator().random() 0.47108547995356098 # random - >>> type(np.random.gen.random_sample()) + >>> type(np.random.Generator().random()) - >>> np.random.gen.random_sample((5,)) + >>> np.random.Generator().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 * np.random.gen.random_sample((3, 2)) - 5 + >>> 5 * np.random.Generator().random((3, 2)) - 5 array([[-3.99149989, -0.52338984], # random [-2.99091858, -0.79479508], [-1.23204345, -1.75224494]]) @@ -170,11 +180,11 @@ cdef class RandomGenerator: cdef double temp key = np.dtype(dtype).name if key == 'float64': - return double_fill(&random_double_fill, self._brng, size, self.lock, out) + return double_fill(&random_double_fill, &self._bitgen, size, self.lock, out) elif key == 'float32': - return float_fill(&random_float, self._brng, size, self.lock, out) + return float_fill(&random_float, &self._bitgen, size, self.lock, out) else: - raise TypeError('Unsupported dtype "%s" for random_sample' % key) + raise TypeError('Unsupported dtype "%s" for random' % key) def beta(self, a, b, size=None): """ @@ -214,7 +224,7 @@ cdef class RandomGenerator: Drawn samples from the parameterized beta distribution. """ - return cont(&random_beta, self._brng, size, self.lock, 2, + return cont(&random_beta, &self._bitgen, size, self.lock, 2, a, 'a', CONS_POSITIVE, b, 'b', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -265,7 +275,7 @@ cdef class RandomGenerator: https://en.wikipedia.org/wiki/Exponential_distribution """ - return cont(&random_exponential, self._brng, size, self.lock, 1, + return cont(&random_exponential, &self._bitgen, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -307,20 +317,20 @@ cdef class RandomGenerator: -------- Output a 3x8000 array: - >>> n = np.random.gen.standard_exponential((3, 8000)) + >>> n = np.random.Generator().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._brng, size, self.lock, out) + return double_fill(&random_standard_exponential_zig_fill, &self._bitgen, size, self.lock, out) else: - return double_fill(&random_standard_exponential_fill, self._brng, size, self.lock, out) + 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._brng, size, self.lock, out) + return float_fill(&random_standard_exponential_zig_f, &self._bitgen, size, self.lock, out) else: - return float_fill(&random_standard_exponential_f, self._brng, size, self.lock, out) + return float_fill(&random_standard_exponential_f, &self._bitgen, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) @@ -347,13 +357,11 @@ cdef class RandomGenerator: See Also -------- - randint : Uniform sampling over a given half-open interval of integers. - random_integers : Uniform sampling over a given closed interval of - integers. + integers : Uniform sampling over a given half-open interval of integers. Examples -------- - >>> rg = np.random.RandomGenerator() # need a RandomGenerator object + >>> rg = np.random.Generator() # need a Generator object >>> rg.tomaxint((2,2,2)) array([[[1170048599, 1600360186], # random [ 739731006, 1947757578]], @@ -366,28 +374,26 @@ cdef class RandomGenerator: [ True, True]]]) """ - return self.randint(0, np.iinfo(np.int).max + 1, dtype=np.int, size=size) + return self.integers(0, np.iinfo(np.int).max + 1, dtype=np.int, size=size) - def randint(self, low, high=None, size=None, dtype=np.int64, use_masked=True, - closed=False): + def integers(self, low, high=None, size=None, dtype=np.int64, endpoint=False): """ - randint(low, high=None, size=None, dtype='int64', use_masked=True, closed=False) + integers(low, high=None, size=None, dtype='int64', endpoint=False) Return random integers from `low` (inclusive) to `high` (exclusive), or - if closed=True, `low` (inclusive) to `high` (inclusive). + if endpoint=True, `low` (inclusive) to `high` (inclusive). Replaces + randint (with endpoint=False) and random_integers (with endpoint=True) Return random integers from the "discrete uniform" distribution of - the specified dtype in the "half-open" interval [`low`, `high`). If - `high` is None (the default), then results are from [0, `low`). If - `closed` is True, then samples from the closed interval [`low`, `high`] - or [0, `low`] if `high` is None. + 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 one above the - *highest* such integer). + ``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``). @@ -404,16 +410,10 @@ cdef class RandomGenerator: .. versionadded:: 1.11.0 - use_masked : bool - If True the generator uses rejection sampling with a bit mask to - reject random numbers that are out of bounds. If False the - generator will use Lemire's rejection sampling algorithm. - - .. versionadded:: 1.15.1 - - closed : bool + endpoint : bool, optional If true, sample from the interval [low, high] instead of the default [low, high) + Defaults to False Returns ------- @@ -427,38 +427,32 @@ cdef class RandomGenerator: 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]). - See Also - -------- - random_integers : similar to `randint`, only for the closed interval - [`low`, `high`], where 1 is the lowest value if - `high` is omitted. - Examples -------- - >>> np.random.gen.randint(2, size=10) + >>> np.random.Generator().integers(2, size=10) array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) # random - >>> np.random.gen.randint(1, size=10) + >>> np.random.Generator().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: - >>> np.random.gen.randint(5, size=(2, 4)) + >>> np.random.Generator().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 - >>> np.random.gen.randint(1, [3, 5, 10]) + >>> np.random.Generator().integers(1, [3, 5, 10]) array([2, 2, 9]) # random Generate a 1 by 3 array with 3 different lower bounds - >>> np.random.gen.randint([1, 5, 7], 10) + >>> np.random.Generator().integers([1, 5, 7], 10) array([9, 8, 7]) # random Generate a 2 by 4 array using broadcasting with dtype of uint8 - >>> np.random.gen.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) + >>> np.random.Generator().integers([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) array([[ 8, 6, 9, 7], [ 1, 16, 9, 12]], dtype=uint8) # random @@ -473,27 +467,32 @@ cdef class RandomGenerator: low = 0 key = np.dtype(dtype).name - if key not in _randint_types: - raise TypeError('Unsupported dtype "%s" for randint' % key) + if key not in _integers_types: + raise TypeError('Unsupported dtype "%s" for integers' % key) + + # Implementation detail: the old API used a masked method to generate + # bounded uniform integers. Lemire's method is preferrable since it is + # faster. randomgen allows a choice, we will always use the faster one. + cdef bint _masked = True if key == 'int32': - ret = _rand_int32(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_int32(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_int64(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_int16(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_int8(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_uint64(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_uint32(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_uint16(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, use_masked, closed, self._brng, self.lock) + ret = _rand_uint8(low, high, size, _masked, endpoint, &self._bitgen, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, use_masked, closed, self._brng, self.lock) + 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 == (): @@ -518,12 +517,20 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.gen.bytes(10) + >>> np.random.Generator().bytes(10) ' eh\\x85\\x022SZ\\xbf\\xa4' #random """ cdef Py_ssize_t n_uint32 = ((length - 1) // 4 + 1) - return self.randint(0, 4294967296, size=n_uint32, dtype=np.uint32).tobytes()[:length] + return self.integers(0, 4294967296, size=n_uint32, + dtype=np.uint32).tobytes()[:length] + + def randint(self, low, high=None, size=None, dtype=np.int64, endpoint=False): + """ + Deprecated, renamed to ``integers`` + """ + warnings.warn("Renamed to integers", RuntimeWarning) + self.integers(low, high, size, dtype, endpoint) @cython.wraparound(True) def choice(self, a, size=None, replace=True, p=None, axis=0): @@ -532,7 +539,7 @@ cdef class RandomGenerator: Generates a random sample from a given 1-D array - .. versionadded:: 1.7.0 + .. versionadded:: 1.7.0 Parameters ---------- @@ -541,8 +548,11 @@ cdef class RandomGenerator: 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. Default is None, in which case a - single value is returned. + ``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 @@ -569,39 +579,39 @@ cdef class RandomGenerator: See Also -------- - randint, shuffle, permutation + integers, shuffle, permutation Examples -------- Generate a uniform random sample from np.arange(5) of size 3: - >>> np.random.gen.choice(5, 3) + >>> np.random.Generator().choice(5, 3) array([0, 3, 4]) # random - >>> #This is equivalent to np.random.gen.randint(0,5,3) + >>> #This is equivalent to np.random.Generator().integers(0,5,3) Generate a non-uniform random sample from np.arange(5) of size 3: - >>> np.random.gen.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0]) + >>> np.random.Generator().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: - >>> np.random.gen.choice(5, 3, replace=False) + >>> np.random.Generator().choice(5, 3, replace=False) array([3,1,0]) # random - >>> #This is equivalent to np.random.gen.permutation(np.arange(5))[:3] + >>> #This is equivalent to np.random.Generator().permutation(np.arange(5))[:3] Generate a non-uniform random sample from np.arange(5) of size 3 without replacement: - >>> np.random.gen.choice(5, 3, replace=False, p=[0.1, 0, 0.3, 0.6, 0]) + >>> np.random.Generator().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'] - >>> np.random.gen.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) + >>> np.random.Generator().choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array(['pooh', 'pooh', 'pooh', 'Christopher', 'piglet'], # random dtype=' pop_size: raise ValueError("Cannot take a larger sample than " @@ -683,7 +693,7 @@ cdef class RandomGenerator: found = np.zeros(shape, dtype=np.int64) flat_found = found.ravel() while n_uniq < size: - x = self.rand(size - n_uniq) + x = self.random((size - n_uniq,)) if n_uniq > 0: p[flat_found[0:n_uniq]] = 0 cdf = np.cumsum(p) @@ -718,7 +728,7 @@ cdef class RandomGenerator: # Sample indices with one pass to avoid reacquiring the lock with self.lock: for j in range(pop_size_i - size_i, pop_size_i): - idx_data[loc] = random_interval(self._brng, j) + idx_data[loc] = random_interval(&self._bitgen, j) loc += 1 loc = 0 while len(idx_set) < size_i: @@ -786,14 +796,9 @@ cdef class RandomGenerator: See Also -------- - randint : Discrete uniform distribution, yielding integers. - random_integers : Discrete uniform distribution over the closed - interval ``[low, high]``. - random_sample : Floats uniformly distributed over ``[0, 1)``. - random : Alias for `random_sample`. - rand : Convenience function that accepts dimensions as input, e.g., - ``rand(2,2)`` would generate a 2-by-2 array of floats, - uniformly distributed over ``[0, 1)``. + integers : Discrete uniform distribution, yielding integers. + random : Floats uniformly distributed over ``[0, 1)``. + random : Alias for `random`. Notes ----- @@ -813,7 +818,7 @@ cdef class RandomGenerator: -------- Draw samples from the distribution: - >>> s = np.random.gen.uniform(-1,0,1000) + >>> s = np.random.Generator().uniform(-1,0,1000) All values are within the given interval: @@ -846,7 +851,7 @@ cdef class RandomGenerator: if not np.isfinite(range): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._brng, size, self.lock, 2, + return cont(&random_uniform, &self._bitgen, size, self.lock, 2, _low, '', CONS_NONE, range, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -860,218 +865,12 @@ cdef class RandomGenerator: arange = np.PyArray_EnsureArray(temp) if not np.all(np.isfinite(arange)): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._brng, size, self.lock, 2, + 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, dtype=np.float64): - """ - rand(d0, d1, ..., dn, dtype='d') - - Random values in a given shape. - - .. note:: - This is a convenience function for users porting code from Matlab, - and wraps `numpy.random.gen.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)``. - - Parameters - ---------- - d0, d1, ..., dn : int, optional - The dimensions of the returned array, must be non-negative. - If no argument is given a single Python float 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'. - - Returns - ------- - out : ndarray, shape ``(d0, d1, ..., dn)`` - Random values. - - See Also - -------- - random - - Examples - -------- - >>> np.random.gen.rand(3,2) - array([[ 0.14022471, 0.96360618], #random - [ 0.37601032, 0.25528411], #random - [ 0.49313049, 0.94909878]]) #random - - """ - if len(args) == 0: - return self.random_sample(dtype=dtype) - else: - return self.random_sample(size=args, dtype=dtype) - - def randn(self, *args, dtype=np.float64): - """ - randn(d0, d1, ..., dn, dtype='d') - - Return a sample (or samples) from the "standard normal" distribution. - - .. note:: - This is a convenience function for users porting code from Matlab, - and wraps `numpy.random.gen.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`. - - 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, must be non-negative. - If no argument is given a single Python float 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'. - - Returns - ------- - Z : ndarray or float - A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from - the standard normal distribution, or a single such float if - no parameters were supplied. - - See Also - -------- - standard_normal : Similar, but takes a tuple as its argument. - normal : Also accepts mu and sigma arguments. - - Notes - ----- - For random samples from :math:`N(\\mu, \\sigma^2)`, use: - - ``sigma * np.random.gen.randn(...) + mu`` - - Examples - -------- - >>> np.random.gen.randn() - 2.1923875335537315 # random - - Two-by-four array of samples from N(3, 6.25): - - >>> 3 + 2.5 * np.random.gen.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(dtype=dtype) - else: - return self.standard_normal(size=args, dtype=dtype) - - def random_integers(self, low, high=None, size=None): - """ - random_integers(low, high=None, size=None) - - Random integers of type np.int between `low` and `high`, inclusive. - - 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 integer type and its precision - is platform dependent. - - This function has been deprecated. Use randint instead. - - .. deprecated:: 1.11.0 - - Parameters - ---------- - low : int - Lowest (signed) integer to be drawn from the distribution (unless - ``high=None``, in which case this parameter is the *highest* such - integer). - high : int, optional - If provided, the largest (signed) integer to be drawn from the - distribution (see above for behavior if ``high=None``). - size : int or tuple of ints, optional - Output shape. 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 : 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. - - See Also - -------- - randint : Similar to `random_integers`, only for the half-open - interval [`low`, `high`), and 0 is the lowest value if `high` is - omitted. - - Notes - ----- - To sample from N evenly spaced floating-point numbers between a and b, - use:: - - a + (b - a) * (np.random.gen.random_integers(N) - 1) / (N - 1.) - - Examples - -------- - >>> np.random.gen.random_integers(5) - 4 # random - >>> type(np.random.gen.random_integers(5)) - - >>> np.random.gen.random_integers(5, size=(3,2)) - array([[5, 4], # random - [3, 3], - [4, 5]]) - - Choose five random numbers from the set of five evenly-spaced - numbers between 0 and 2.5, inclusive (*i.e.*, from the set - :math:`{0, 5/8, 10/8, 15/8, 20/8}`): - - >>> 2.5 * (np.random.gen.random_integers(5, size=(5,)) - 1) / 4. - array([ 0.625, 1.25 , 0.625, 0.625, 2.5 ]) # random - - Roll two six sided dice 1000 times and sum the results: - - >>> d1 = np.random.gen.random_integers(1, 6, 1000) - >>> d2 = np.random.gen.random_integers(1, 6, 1000) - >>> dsums = d1 + d2 - - Display results as a histogram: - - >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(dsums, 11, density=True) - >>> plt.show() - - """ - if high is None: - warnings.warn(("This function is deprecated. Please call " - "randint(1, {low} + 1) instead".format(low=low)), - DeprecationWarning) - high = low - low = 1 - - 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') - # Complicated, continuous distributions: def standard_normal(self, size=None, dtype=np.float64, out=None): """ @@ -1104,8 +903,8 @@ cdef class RandomGenerator: ----- For random samples from :math:`N(\\mu, \\sigma^2)`, use one of:: - mu + sigma * np.random.gen.standard_normal(size=...) - np.random.gen.normal(mu, sigma, size=...) + mu + sigma * np.random.Generator().standard_normal(size=...) + np.random.Generator().normal(mu, sigma, size=...) See Also -------- @@ -1115,31 +914,31 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.gen.standard_normal() + >>> np.random.Generator().standard_normal() 2.1923875335537315 #random - >>> s = np.random.gen.standard_normal(8000) + >>> s = np.random.Generator().standard_normal(8000) >>> s array([ 0.6888893 , 0.78096262, -0.89086505, ..., 0.49876311, # random -0.38672696, -0.4685006 ]) # random >>> s.shape (8000,) - >>> s = np.random.gen.standard_normal(size=(3, 4, 2)) + >>> s = np.random.Generator().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.gen.standard_normal(size=(2, 4)) + >>> 3 + 2.5 * np.random.Generator().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._brng, size, self.lock, out) + return double_fill(&random_gauss_zig_fill, &self._bitgen, size, self.lock, out) elif key == 'float32': - return float_fill(&random_gauss_zig_f, self._brng, size, self.lock, out) + return float_fill(&random_gauss_zig_f, &self._bitgen, size, self.lock, out) else: raise TypeError('Unsupported dtype "%s" for standard_normal' % key) @@ -1197,8 +996,8 @@ cdef class RandomGenerator: 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 - `numpy.random.gen.normal` is more likely to return samples lying close to - the mean, rather than those far away. + `numpy.random.Generator().normal` is more likely to return + samples lying close to the mean, rather than those far away. References ---------- @@ -1213,7 +1012,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 0, 0.1 # mean and standard deviation - >>> s = np.random.gen.normal(mu, sigma, 1000) + >>> s = np.random.Generator().normal(mu, sigma, 1000) Verify the mean and the variance: @@ -1235,12 +1034,12 @@ cdef class RandomGenerator: Two-by-four array of samples from N(3, 6.25): - >>> np.random.gen.normal(3, 2.5, size=(2, 4)) + >>> np.random.Generator().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._brng, size, self.lock, 2, + return cont(&random_normal_zig, &self._bitgen, size, self.lock, 2, loc, '', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, @@ -1309,7 +1108,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 1. # mean and width - >>> s = np.random.gen.standard_gamma(shape, 1000000) + >>> s = np.random.Generator().standard_gamma(shape, 1000000) Display the histogram of the samples, along with the probability density function: @@ -1326,13 +1125,13 @@ cdef class RandomGenerator: cdef void *func key = np.dtype(dtype).name if key == 'float64': - return cont(&random_standard_gamma_zig, self._brng, size, self.lock, 1, + 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._brng, size, self.lock, + return cont_f(&random_standard_gamma_zig_f, &self._bitgen, size, self.lock, shape, 'shape', CONS_NON_NEGATIVE, out) else: @@ -1397,7 +1196,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> shape, scale = 2., 2. # mean=4, std=2*sqrt(2) - >>> s = np.random.gen.gamma(shape, scale, 1000) + >>> s = np.random.Generator().gamma(shape, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -1411,7 +1210,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_gamma, self._brng, size, self.lock, 2, + 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) @@ -1487,7 +1286,7 @@ cdef class RandomGenerator: >>> dfnum = 1. # between group degrees of freedom >>> dfden = 48. # within groups degrees of freedom - >>> s = np.random.gen.f(dfnum, dfden, 1000) + >>> s = np.random.Generator().f(dfnum, dfden, 1000) The lower bound for the top 1% of the samples is : @@ -1499,7 +1298,7 @@ cdef class RandomGenerator: level. """ - return cont(&random_f, self._brng, size, self.lock, 2, + return cont(&random_f, &self._bitgen, size, self.lock, 2, dfnum, 'dfnum', CONS_POSITIVE, dfden, 'dfden', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -1566,9 +1365,9 @@ cdef class RandomGenerator: >>> dfnum = 3 # between group deg of freedom >>> dfden = 20 # within groups degrees of freedom >>> nonc = 3.0 - >>> nc_vals = np.random.gen.noncentral_f(dfnum, dfden, nonc, 1000000) + >>> nc_vals = np.random.Generator().noncentral_f(dfnum, dfden, nonc, 1000000) >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = np.random.gen.f(dfnum, dfden, 1000000) + >>> c_vals = np.random.Generator().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]) @@ -1576,7 +1375,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_noncentral_f, self._brng, size, self.lock, 3, + 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) @@ -1640,11 +1439,11 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.gen.chisquare(2,4) + >>> np.random.Generator().chisquare(2,4) array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ - return cont(&random_chisquare, self._brng, size, self.lock, 1, + return cont(&random_chisquare, &self._bitgen, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -1699,7 +1498,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> import matplotlib.pyplot as plt - >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.Generator().noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() @@ -1707,9 +1506,9 @@ cdef class RandomGenerator: and compare to a chisquare. >>> plt.figure() - >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, .0000001, 100000), + >>> values = plt.hist(np.random.Generator().noncentral_chisquare(3, .0000001, 100000), ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(np.random.gen.chisquare(3, 100000), + >>> values2 = plt.hist(np.random.Generator().chisquare(3, 100000), ... bins=np.arange(0., 25, .1), density=True) >>> plt.plot(values[1][0:-1], values[0]-values2[0], 'ob') >>> plt.show() @@ -1718,12 +1517,12 @@ cdef class RandomGenerator: distribution. >>> plt.figure() - >>> values = plt.hist(np.random.gen.noncentral_chisquare(3, 20, 100000), + >>> values = plt.hist(np.random.Generator().noncentral_chisquare(3, 20, 100000), ... bins=200, density=True) >>> plt.show() """ - return cont(&random_noncentral_chisquare, self._brng, size, self.lock, 2, + 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) @@ -1784,13 +1583,13 @@ cdef class RandomGenerator: Draw samples and plot the distribution: >>> import matplotlib.pyplot as plt - >>> s = np.random.gen.standard_cauchy(1000000) + >>> s = np.random.Generator().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._brng, size, self.lock, 0, + return cont(&random_standard_cauchy, &self._bitgen, size, self.lock, 0, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) def standard_t(self, df, size=None): @@ -1857,7 +1656,7 @@ cdef class RandomGenerator: We have 10 degrees of freedom, so is the sample mean within 95% of the recommended value? - >>> s = np.random.gen.standard_t(10, size=100000) + >>> s = np.random.Generator().standard_t(10, size=100000) >>> np.mean(intake) 6753.636363636364 >>> intake.std(ddof=1) @@ -1881,7 +1680,7 @@ cdef class RandomGenerator: probability of about 99% of being true. """ - return cont(&random_standard_t, self._brng, size, self.lock, 1, + return cont(&random_standard_t, &self._bitgen, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0, '', CONS_NONE, 0, '', CONS_NONE, @@ -1951,7 +1750,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, kappa = 0.0, 4.0 # mean and dispersion - >>> s = np.random.gen.vonmises(mu, kappa, 1000) + >>> s = np.random.Generator().vonmises(mu, kappa, 1000) Display the histogram of the samples, along with the probability density function: @@ -1965,7 +1764,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_vonmises, self._brng, size, self.lock, 2, + return cont(&random_vonmises, &self._bitgen, size, self.lock, 2, mu, 'mu', CONS_NONE, kappa, 'kappa', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2051,7 +1850,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a, m = 3., 2. # shape and mode - >>> s = (np.random.gen.pareto(a, 1000) + 1) * m + >>> s = (np.random.Generator().pareto(a, 1000) + 1) * m Display the histogram of the samples, along with the probability density function: @@ -2063,7 +1862,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_pareto, self._brng, size, self.lock, 1, + return cont(&random_pareto, &self._bitgen, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2144,7 +1943,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 5. # shape - >>> s = np.random.gen.weibull(a, 1000) + >>> s = np.random.Generator().weibull(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -2154,14 +1953,14 @@ cdef class RandomGenerator: >>> def weib(x,n,a): ... return (a / n) * (x / n)**(a - 1) * np.exp(-(x / n)**a) - >>> count, bins, ignored = plt.hist(np.random.gen.weibull(5.,1000)) + >>> count, bins, ignored = plt.hist(np.random.Generator().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._brng, size, self.lock, 1, + return cont(&random_weibull, &self._bitgen, size, self.lock, 1, a, 'a', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2224,7 +2023,7 @@ cdef class RandomGenerator: >>> a = 5. # shape >>> samples = 1000 - >>> s = np.random.gen.power(a, samples) + >>> s = np.random.Generator().power(a, samples) Display the histogram of the samples, along with the probability density function: @@ -2240,20 +2039,20 @@ cdef class RandomGenerator: Compare the power function distribution to the inverse of the Pareto. >>> from scipy import stats # doctest: +SKIP - >>> rvs = np.random.gen.power(5, 1000000) - >>> rvsp = np.random.gen.pareto(5, 1000000) + >>> rvs = np.random.Generator().power(5, 1000000) + >>> rvsp = np.random.Generator().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('np.random.gen.power(5)') + >>> plt.title('np.random.Generator().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 + np.random.gen.pareto(5)') + >>> plt.title('inverse of 1 + np.random.Generator().pareto(5)') >>> plt.figure() >>> plt.hist(1./(1.+rvsp), bins=50, density=True) @@ -2261,7 +2060,7 @@ cdef class RandomGenerator: >>> plt.title('inverse of stats.pareto(5)') """ - return cont(&random_power, self._brng, size, self.lock, 1, + return cont(&random_power, &self._bitgen, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2328,7 +2127,7 @@ cdef class RandomGenerator: Draw samples from the distribution >>> loc, scale = 0., 1. - >>> s = np.random.gen.laplace(loc, scale, 1000) + >>> s = np.random.Generator().laplace(loc, scale, 1000) Display the histogram of the samples, along with the probability density function: @@ -2346,7 +2145,7 @@ cdef class RandomGenerator: >>> plt.plot(x,g) """ - return cont(&random_laplace, self._brng, size, self.lock, 2, + return cont(&random_laplace, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2431,7 +2230,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, beta = 0, 0.1 # location and scale - >>> s = np.random.gen.gumbel(mu, beta, 1000) + >>> s = np.random.Generator().gumbel(mu, beta, 1000) Display the histogram of the samples, along with the probability density function: @@ -2449,7 +2248,7 @@ cdef class RandomGenerator: >>> means = [] >>> maxima = [] >>> for i in range(0,1000) : - ... a = np.random.gen.normal(mu, beta, 1000) + ... a = np.random.Generator().normal(mu, beta, 1000) ... means.append(a.mean()) ... maxima.append(a.max()) >>> count, bins, ignored = plt.hist(maxima, 30, density=True) @@ -2464,7 +2263,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_gumbel, self._brng, size, self.lock, 2, + return cont(&random_gumbel, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2531,7 +2330,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> loc, scale = 10, 1 - >>> s = np.random.gen.logistic(loc, scale, 10000) + >>> s = np.random.Generator().logistic(loc, scale, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s, bins=50) @@ -2544,7 +2343,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_logistic, self._brng, size, self.lock, 2, + return cont(&random_logistic, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2614,7 +2413,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = np.random.gen.lognormal(mu, sigma, 1000) + >>> s = np.random.Generator().lognormal(mu, sigma, 1000) Display the histogram of the samples, along with the probability density function: @@ -2638,7 +2437,7 @@ cdef class RandomGenerator: >>> # values, drawn from a normal distribution. >>> b = [] >>> for i in range(1000): - ... a = 10. + np.random.gen.standard_normal(100) + ... a = 10. + np.random.Generator().standard_normal(100) ... b.append(np.product(a)) >>> b = np.array(b) / np.min(b) # scale values to be positive @@ -2654,7 +2453,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return cont(&random_lognormal, self._brng, size, self.lock, 2, + return cont(&random_lognormal, &self._bitgen, size, self.lock, 2, mean, 'mean', CONS_NONE, sigma, 'sigma', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2706,7 +2505,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram >>> from matplotlib.pyplot import hist - >>> values = hist(np.random.gen.rayleigh(3, 100000), bins=200, density=True) + >>> values = hist(np.random.Generator().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 @@ -2714,7 +2513,7 @@ cdef class RandomGenerator: >>> meanvalue = 1 >>> modevalue = np.sqrt(2 / np.pi) * meanvalue - >>> s = np.random.gen.rayleigh(modevalue, 1000000) + >>> s = np.random.Generator().rayleigh(modevalue, 1000000) The percentage of waves larger than 3 meters is: @@ -2722,7 +2521,7 @@ cdef class RandomGenerator: 0.087300000000000003 # random """ - return cont(&random_rayleigh, self._brng, size, self.lock, 1, + return cont(&random_rayleigh, &self._bitgen, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2786,11 +2585,11 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.gen.wald(3, 2, 100000), bins=200, density=True) + >>> h = plt.hist(np.random.Generator().wald(3, 2, 100000), bins=200, density=True) >>> plt.show() """ - return cont(&random_wald, self._brng, size, self.lock, 2, + return cont(&random_wald, &self._bitgen, size, self.lock, 2, mean, 'mean', CONS_POSITIVE, scale, 'scale', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -2853,7 +2652,7 @@ cdef class RandomGenerator: Draw values from the distribution and plot the histogram: >>> import matplotlib.pyplot as plt - >>> h = plt.hist(np.random.gen.triangular(-3, 0, 8, 100000), bins=200, + >>> h = plt.hist(np.random.Generator().triangular(-3, 0, 8, 100000), bins=200, ... density=True) >>> plt.show() @@ -2877,7 +2676,7 @@ cdef class RandomGenerator: raise ValueError("mode > right") if fleft == fright: raise ValueError("left == right") - return cont(&random_triangular, self._brng, size, self.lock, 3, + return cont(&random_triangular, &self._bitgen, size, self.lock, 3, fleft, '', CONS_NONE, fmode, '', CONS_NONE, fright, '', CONS_NONE, None) @@ -2889,7 +2688,7 @@ cdef class RandomGenerator: if np.any(np.equal(oleft, oright)): raise ValueError("left == right") - return cont_broadcast_3(&random_triangular, self._brng, size, self.lock, + return cont_broadcast_3(&random_triangular, &self._bitgen, size, self.lock, oleft, '', CONS_NONE, omode, '', CONS_NONE, oright, '', CONS_NONE) @@ -2966,7 +2765,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = np.random.gen.binomial(n, p, 1000) + >>> s = np.random.Generator().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 @@ -2976,7 +2775,7 @@ cdef class RandomGenerator: Let's do 20,000 trials of the model, and count the number that generate zero positive results. - >>> sum(np.random.gen.binomial(9, 0.1, 20000) == 0)/20000. + >>> sum(np.random.Generator().binomial(9, 0.1, 20000) == 0)/20000. # answer = 0.38885, or 38%. """ @@ -3012,7 +2811,7 @@ cdef class RandomGenerator: for i in range(cnt): _dp = (np.PyArray_MultiIter_DATA(it, 1))[0] _in = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._brng, _dp, _in, self._binomial) + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(&self._bitgen, _dp, _in, &self._binomial) np.PyArray_MultiIter_NEXT(it) @@ -3025,7 +2824,7 @@ cdef class RandomGenerator: if size is None: with self.lock: - return random_binomial(self._brng, _dp, _in, self._binomial) + return random_binomial(&self._bitgen, _dp, _in, &self._binomial) randoms = np.empty(size, np.int64) cnt = np.PyArray_SIZE(randoms) @@ -3033,8 +2832,8 @@ cdef class RandomGenerator: with self.lock, nogil: for i in range(cnt): - randoms_data[i] = random_binomial(self._brng, _dp, _in, - self._binomial) + randoms_data[i] = random_binomial(&self._bitgen, _dp, _in, + &self._binomial) return randoms @@ -3103,13 +2902,13 @@ cdef class RandomGenerator: 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.gen.negative_binomial(1, 0.1, 100000) + >>> s = np.random.Generator().negative_binomial(1, 0.1, 100000) >>> for i in range(1, 11): # doctest: +SKIP ... probability = sum(s>> import numpy as np - >>> s = np.random.gen.poisson(5, 10000) + >>> s = np.random.Generator().poisson(5, 10000) Display histogram of the sample: @@ -3177,10 +2976,10 @@ cdef class RandomGenerator: Draw each 100 values for lambda 100 and 500: - >>> s = np.random.gen.poisson(lam=(100., 500.), size=(100, 2)) + >>> s = np.random.Generator().poisson(lam=(100., 500.), size=(100, 2)) """ - return disc(&random_poisson, self._brng, size, self.lock, 1, 0, + return disc(&random_poisson, &self._bitgen, size, self.lock, 1, 0, lam, 'lam', CONS_POISSON, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3242,7 +3041,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = 2. # parameter - >>> s = np.random.gen.zipf(a, 1000) + >>> s = np.random.Generator().zipf(a, 1000) Display the histogram of the samples, along with the probability density function: @@ -3260,7 +3059,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return disc(&random_zipf, self._brng, size, self.lock, 1, 0, + return disc(&random_zipf, &self._bitgen, size, self.lock, 1, 0, a, 'a', CONS_GT_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3303,7 +3102,7 @@ cdef class RandomGenerator: Draw ten thousand values from the geometric distribution, with the probability of an individual success equal to 0.35: - >>> z = np.random.gen.geometric(p=0.35, size=10000) + >>> z = np.random.Generator().geometric(p=0.35, size=10000) How many trials succeeded after a single run? @@ -3311,7 +3110,7 @@ cdef class RandomGenerator: 0.34889999999999999 #random """ - return disc(&random_geometric, self._brng, size, self.lock, 1, 0, + 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) @@ -3393,7 +3192,7 @@ cdef class RandomGenerator: >>> ngood, nbad, nsamp = 100, 2, 10 # number of good, number of bad, and number of samples - >>> s = np.random.gen.hypergeometric(ngood, nbad, nsamp, 1000) + >>> s = np.random.Generator().hypergeometric(ngood, nbad, nsamp, 1000) >>> from matplotlib.pyplot import hist >>> hist(s) # note that it is very unlikely to grab both bad items @@ -3402,7 +3201,7 @@ cdef class RandomGenerator: If you pull 15 marbles at random, how likely is it that 12 or more of them are one color? - >>> s = np.random.gen.hypergeometric(15, 15, 15, 100000) + >>> s = np.random.Generator().hypergeometric(15, 15, 15, 100000) >>> sum(s>=12)/100000. + sum(s<=3)/100000. # answer = 0.003 ... pretty unlikely! @@ -3423,14 +3222,14 @@ cdef class RandomGenerator: if lngood + lnbad < lnsample: raise ValueError("ngood + nbad < nsample") - return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, + 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(np.less(np.add(ongood, onbad), onsample)): raise ValueError("ngood + nbad < nsample") - return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, + 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) @@ -3497,7 +3296,7 @@ cdef class RandomGenerator: Draw samples from the distribution: >>> a = .6 - >>> s = np.random.gen.logseries(a, 10000) + >>> s = np.random.Generator().logseries(a, 10000) >>> import matplotlib.pyplot as plt >>> count, bins, ignored = plt.hist(s) @@ -3510,7 +3309,7 @@ cdef class RandomGenerator: >>> plt.show() """ - return disc(&random_logseries, self._brng, size, self.lock, 1, 0, + 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) @@ -3587,7 +3386,7 @@ cdef class RandomGenerator: Diagonal covariance means that points are oriented along x or y-axis: >>> import matplotlib.pyplot as plt - >>> x, y = np.random.gen.multivariate_normal(mean, cov, 5000).T + >>> x, y = np.random.Generator().multivariate_normal(mean, cov, 5000).T >>> plt.plot(x, y, 'x') >>> plt.axis('equal') >>> plt.show() @@ -3607,7 +3406,7 @@ cdef class RandomGenerator: -------- >>> mean = (1, 2) >>> cov = [[1, 0], [0, 1]] - >>> x = np.random.gen.multivariate_normal(mean, cov, (3, 3)) + >>> x = np.random.Generator().multivariate_normal(mean, cov, (3, 3)) >>> x.shape (3, 3, 2) @@ -3721,14 +3520,14 @@ cdef class RandomGenerator: -------- Throw a dice 20 times: - >>> np.random.gen.multinomial(20, [1/6.]*6, size=1) + >>> np.random.Generator().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: - >>> np.random.gen.multinomial(20, [1/6.]*6, size=2) + >>> np.random.Generator().multinomial(20, [1/6.]*6, size=2) array([[3, 4, 3, 3, 4, 3], [2, 4, 3, 4, 0, 7]]) # random @@ -3738,7 +3537,7 @@ cdef class RandomGenerator: Now, do one experiment throwing the dice 10 time, and 10 times again, and another throwing the dice 20 times, and 20 times again: - >>> np.random.gen.multinomial([[10], [20]], [1/6.]*6, size=2) + >>> np.random.Generator().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], @@ -3749,7 +3548,7 @@ cdef class RandomGenerator: A loaded die is more likely to land on number 6: - >>> np.random.gen.multinomial(100, [1/7.]*5 + [2/7.]) + >>> np.random.Generator().multinomial(100, [1/7.]*5 + [2/7.]) array([11, 16, 14, 17, 16, 26]) # random The probability inputs should be normalized. As an implementation @@ -3758,12 +3557,12 @@ cdef class RandomGenerator: A biased coin which has twice as much weight on one side as on the other should be sampled like so: - >>> np.random.gen.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT + >>> np.random.Generator().multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT array([38, 62]) # random not like: - >>> np.random.gen.multinomial(100, [1.0, 2.0]) # WRONG + >>> np.random.Generator().multinomial(100, [1.0, 2.0]) # WRONG Traceback (most recent call last): ValueError: pvals < 0, pvals > 1 or pvals contains NaNs @@ -3801,7 +3600,7 @@ cdef class RandomGenerator: with self.lock, nogil: for i in range(sz): ni = (np.PyArray_MultiIter_DATA(it, 0))[0] - random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial) offset += d np.PyArray_MultiIter_NEXT(it) return multin @@ -3823,7 +3622,7 @@ cdef class RandomGenerator: offset = 0 with self.lock, nogil: for i in range(sz // d): - random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial) offset += d return multin @@ -3896,7 +3695,7 @@ cdef class RandomGenerator: average length, but allowing some variation in the relative sizes of the pieces. - >>> s = np.random.gen.dirichlet((10, 5, 3), 20).transpose() + >>> s = np.random.Generator().dirichlet((10, 5, 3), 20).transpose() >>> import matplotlib.pyplot as plt >>> plt.barh(range(20), s[0]) @@ -3955,7 +3754,7 @@ cdef class RandomGenerator: while i < totsize: acc = 0.0 for j in range(k): - val_data[i+j] = random_standard_gamma_zig(self._brng, + val_data[i+j] = random_standard_gamma_zig(&self._bitgen, alpha_data[j]) acc = acc + val_data[i + j] invacc = 1/acc @@ -3988,14 +3787,14 @@ cdef class RandomGenerator: Examples -------- >>> arr = np.arange(10) - >>> np.random.gen.shuffle(arr) + >>> np.random.Generator().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)) - >>> np.random.gen.shuffle(arr) + >>> np.random.Generator().shuffle(arr) >>> arr array([[3, 4, 5], # random [6, 7, 8], @@ -4032,7 +3831,7 @@ cdef class RandomGenerator: buf = np.empty_like(x[0, ...]) with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._brng, i) + j = random_interval(&self._bitgen, i) if i == j: # i == j is not needed and memcpy is undefined. continue @@ -4043,7 +3842,7 @@ cdef class RandomGenerator: # Untyped path. with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._brng, i) + 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, @@ -4053,13 +3852,13 @@ cdef class RandomGenerator: Parameters ---------- n - Number of elements in data + Number of elements in data first - First observation to shuffle. Shuffles n-1, + First observation to shuffle. Shuffles n-1, n-2, ..., first, so that when first=1 the entire - array is shuffled + array is shuffled itemsize - Size in bytes of item + Size in bytes of item stride Array stride data @@ -4069,7 +3868,7 @@ cdef class RandomGenerator: """ cdef np.npy_intp i, j for i in reversed(range(first, n)): - j = random_interval(self._brng, i) + 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) @@ -4097,14 +3896,14 @@ cdef class RandomGenerator: Examples -------- - >>> np.random.gen.permutation(10) + >>> np.random.Generator().permutation(10) array([1, 7, 4, 3, 0, 9, 2, 5, 8, 6]) # random - >>> np.random.gen.permutation([1, 4, 9, 12, 15]) + >>> np.random.Generator().permutation([1, 4, 9, 12, 15]) array([15, 1, 9, 4, 12]) # random >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.gen.permutation(arr) + >>> np.random.Generator().permutation(arr) array([[6, 7, 8], # random [0, 1, 2], [3, 4, 5]]) @@ -4130,7 +3929,7 @@ cdef class RandomGenerator: self.shuffle(idx) return arr[idx] -_random_generator = RandomGenerator() +_random_generator = Generator() beta = _random_generator.beta binomial = _random_generator.binomial @@ -4144,6 +3943,7 @@ gamma = _random_generator.gamma geometric = _random_generator.geometric gumbel = _random_generator.gumbel hypergeometric = _random_generator.hypergeometric +integers = _random_generator.integers laplace = _random_generator.laplace logistic = _random_generator.logistic lognormal = _random_generator.lognormal @@ -4158,11 +3958,7 @@ pareto = _random_generator.pareto permutation = _random_generator.permutation poisson = _random_generator.poisson power = _random_generator.power -rand = _random_generator.rand -randint = _random_generator.randint -randn = _random_generator.randn -random_integers = _random_generator.random_integers -random_sample = _random_generator.random_sample +random = _random_generator.random rayleigh = _random_generator.rayleigh shuffle = _random_generator.shuffle standard_cauchy = _random_generator.standard_cauchy @@ -4177,3 +3973,4 @@ vonmises = _random_generator.vonmises wald = _random_generator.wald weibull = _random_generator.weibull zipf = _random_generator.zipf + diff --git a/numpy/random/legacy_distributions.pxd b/numpy/random/legacy_distributions.pxd index 69e5d69be8c1..7969cfb929ba 100644 --- a/numpy/random/legacy_distributions.pxd +++ b/numpy/random/legacy_distributions.pxd @@ -1,42 +1,42 @@ #cython: language_level=3 -from libc.stdint cimport uint64_t +from libc.stdint cimport int64_t import numpy as np cimport numpy as np -from .distributions cimport brng_t +from .distributions cimport bitgen_t cdef extern from "distributions-boxmuller.h": - struct aug_brng: - brng_t *basicrng + struct aug_bitgen: + bitgen_t *bit_generator int has_gauss double gauss - ctypedef aug_brng aug_brng_t - - double legacy_gauss(aug_brng_t *aug_state) nogil - double legacy_pareto(aug_brng_t *aug_state, double a) nogil - double legacy_weibull(aug_brng_t *aug_state, double a) nogil - double legacy_standard_gamma(aug_brng_t *aug_state, double shape) nogil - double legacy_normal(aug_brng_t *aug_state, double loc, double scale) nogil - double legacy_standard_t(aug_brng_t *aug_state, double df) nogil - - double legacy_standard_exponential(aug_brng_t *aug_state) nogil - double legacy_power(aug_brng_t *aug_state, double a) nogil - double legacy_gamma(aug_brng_t *aug_state, double shape, double scale) nogil - double legacy_power(aug_brng_t *aug_state, double a) nogil - double legacy_chisquare(aug_brng_t *aug_state, double df) nogil - double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, + 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_brng_t *aug_state, double dfnum, double dfden, + double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum, double dfden, double nonc) nogil - double legacy_wald(aug_brng_t *aug_state, double mean, double scale) nogil - double legacy_lognormal(aug_brng_t *aug_state, double mean, double sigma) nogil - uint64_t legacy_negative_binomial(aug_brng_t *aug_state, double n, double p) nogil - double legacy_standard_cauchy(aug_brng_t *state) nogil - double legacy_beta(aug_brng_t *aug_state, double a, double b) nogil - double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden) nogil - double legacy_exponential(aug_brng_t *aug_state, double scale) nogil - double legacy_power(aug_brng_t *state, double a) 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 + 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 index 8ed229984d8e..0579b3634349 100644 --- a/numpy/random/mt19937.pyx +++ b/numpy/random/mt19937.pyx @@ -1,6 +1,5 @@ import operator -from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New try: @@ -12,7 +11,7 @@ import numpy as np cimport numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy np.import_array() @@ -55,24 +54,26 @@ cdef class MT19937: 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 will attempt to read data from ``/dev/urandom`` - (or the Windows analog) if available or seed from the clock otherwise. + sequence) of unsigned 32-bit integers, or ``None`` (the default). If + `seed` is ``None``, a 32-bit unsigned integer is read from + ``/dev/urandom`` (or the Windows analog) if available. If unavailable, + a 32-bit hash of the time and process ID is used. Notes ----- - ``MT19937`` directly provides generators for doubles, and unsigned 32 and 64- - bit integers [1]_ . These are not directly available and must be consumed - via a ``RandomGenerator`` object. + ``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 768 element array of + The ``MT19937`` state vector consists of a 768-element array of 32-bit unsigned integers plus a single integer value between 0 and 768 - indicating the current position within the main array. + that indexes the current position within the main array. ``MT19937`` is seeded using either a single 32-bit unsigned integer or a vector of 32-bit unsigned integers. In either case, the input seed is @@ -81,30 +82,29 @@ cdef class MT19937: for the seed can only initialize a small range of the possible initial state values. - **Compatibility Guarantee** - - ``MT19937`` make a compatibility guarantee. A fixed seed and a fixed - series of calls to ``MT19937`` methods will always produce the same - results up to roundoff error except when the values were incorrect. - Incorrect values will be fixed and the version in which the fix was - made will be noted in the relevant docstring. - **Parallel Features** ``MT19937`` can be used in parallel applications by - calling the method ``jump`` 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 initialized with the same seed to ensure that the - segments come from the same sequence. + calling the method ``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.entropy import random_entropy - >>> from numpy.random import RandomGenerator, MT19937 + >>> from numpy.random import Generator, MT19937 >>> seed = random_entropy() - >>> rs = [RandomGenerator(MT19937(seed)) for _ in range(10)] - # Advance each MT19937 instance by i jumps - >>> for i in range(10): - ... rs[i].brng.jump(i) + >>> bit_generator = MT19937(seed) + >>> 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 ---------- @@ -117,38 +117,28 @@ cdef class MT19937: No. 3, Summer 2008, pp. 385-390. """ - cdef mt19937_state *rng_state - cdef brng_t *_brng + cdef mt19937_state rng_state + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(mt19937_state)) - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &mt19937_uint64 - self._brng.next_uint32 = &mt19937_uint32 - self._brng.next_double = &mt19937_double - self._brng.next_raw = &mt19937_raw + 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 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -158,16 +148,14 @@ cdef class MT19937: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state def random_raw(self, size=None, output=True): """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -192,10 +180,10 @@ cdef class MT19937: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -226,14 +214,14 @@ cdef class MT19937: seed = random_entropy(1) except RuntimeError: seed = random_entropy(1, 'fallback') - mt19937_seed(self.rng_state, seed[0]) + mt19937_seed(&self.rng_state, seed[0]) 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) + mt19937_seed(&self.rng_state, seed) except TypeError: obj = np.asarray(seed) if obj.size == 0: @@ -244,28 +232,50 @@ cdef class MT19937: 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, obj.data, np.PyArray_DIM(obj, 0)) + mt19937_init_by_array(&self.rng_state, obj.data, np.PyArray_DIM(obj, 0)) + + 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 jump(self, np.npy_intp iter=1): + + def jumped(self, np.npy_intp iter=1): """ - jump(iter=1) + jumped(iter=1) + + Returns a new bit generator with the state jumped - Jumps the state as-if 2**128 random numbers have been generated. + The state of the returned big generator is jumped as-if + 2**(128 * iter) random numbers have been generated. Parameters ---------- iter : integer, positive - Number of times to jump the state of the brng. + Number of times to jump the state of the bit generator returned Returns ------- - self : DSFMT - PRNG jumped iter times + bit_generator : Xoroshiro128 + New instance of generator jumped iter times """ - cdef np.npy_intp i - for i in range(iter): - mt19937_jump(self.rng_state) - return self + cdef MT19937 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -282,7 +292,7 @@ cdef class MT19937: for i in range(624): key[i] = self.rng_state.key[i] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': {'key': key, 'pos': self.rng_state.pos}} @state.setter @@ -290,13 +300,13 @@ cdef class MT19937: 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 ={'brng': 'MT19937', + value ={'bit_generator': 'MT19937', 'state': {'key': value[1], 'pos': value[2]}} if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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'] @@ -319,10 +329,10 @@ cdef class MT19937: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -341,24 +351,9 @@ cdef class MT19937: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index c67e398546af..299398c34cb4 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3,55 +3,59 @@ import operator import warnings +import numpy as np + +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 -from libc.stdlib cimport malloc, free -cimport numpy as np -import numpy as np + cimport cython +cimport numpy as np from .bounded_integers cimport * -from .bounded_integers import _randint_types from .common cimport * from .distributions cimport * from .legacy_distributions cimport * -from .mt19937 import MT19937 as _MT19937 np.import_array() cdef class RandomState: """ - RandomState(brng=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. + RandomState(bit_generator=None) + + 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 recieve updates that + are required by changes in the the internals of Numpy. More substantial + changes, including algorithmic improvements, are reserved for + `Generator`. Parameters ---------- - brng : {None, int, array_like, BasicRNG}, optional + bit_generator : {None, int, array_like, BitGenerator}, optional Random seed used to initialize the pseudo-random number generator or - an instantized BasicRNG. If an integer or array, used as a seed for - the MT19937 BasicRNG. Values can be any integer between 0 and + 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` - BasicRNG is initialized by reading data from ``/dev/urandom`` + BitGenerator is initialized by reading data from ``/dev/urandom`` (or the Windows analogue) if available or seed from the clock otherwise. @@ -63,44 +67,43 @@ 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 public object _basicrng - cdef brng_t *_brng - cdef aug_brng_t *_aug_state - cdef binomial_t *_binomial + cdef public object _bit_generator + cdef bitgen_t _bitgen + cdef aug_bitgen_t _aug_state + cdef binomial_t _binomial cdef object lock poisson_lam_max = POISSON_LAM_MAX - def __init__(self, brng=None): - if brng is None: - brng = _MT19937() - elif not hasattr(brng, 'capsule'): - brng = _MT19937(brng) + def __init__(self, bit_generator=None): + if bit_generator is None: + bit_generator = _MT19937() + elif not hasattr(bit_generator, 'capsule'): + bit_generator = _MT19937(bit_generator) - self._basicrng = brng - capsule = brng.capsule - cdef const char *name = "BasicRNG" + self._bit_generator = bit_generator + capsule = bit_generator.capsule + cdef const char *name = "BitGenerator" if not PyCapsule_IsValid(capsule, name): - raise ValueError("Invalid brng. The brng must be instantized.") - self._brng = PyCapsule_GetPointer(capsule, name) - self._aug_state = malloc(sizeof(aug_brng_t)) - self._aug_state.basicrng = self._brng - self._binomial = malloc(sizeof(binomial_t)) + raise ValueError("Invalid bit generator. The bit generator must " + "be instantized.") + self._bitgen = ( PyCapsule_GetPointer(capsule, name))[0] + self._aug_state.bit_generator = &self._bitgen self._reset_gauss() - self.lock = brng.lock - - def __dealloc__(self): - if self._binomial: - free(self._binomial) - if self._aug_state: - free(self._aug_state) + 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._basicrng.__class__.__name__ + ')' + _str += '(' + self._bit_generator.__class__.__name__ + ')' return _str # Pickling support: @@ -113,7 +116,7 @@ cdef class RandomState: def __reduce__(self): state = self.get_state(legacy=False) from ._pickle import __randomstate_ctor - return __randomstate_ctor, (state['brng'],), state + return __randomstate_ctor, (state['bit_generator'],), state cdef _reset_gauss(self): self._aug_state.has_gauss = 0 @@ -123,30 +126,28 @@ cdef class RandomState: """ seed(self, *args, **kwargs) - Reseed the basic RNG. - - Parameters depend on the basic RNG used. + Reseed the BitGenerator. Notes ----- - Arguments are directly passed to the basic RNG. This is a convenience + Arguments are directly passed to the BitGenerator. This is a convenience function. - The best method to access seed is to directly use a basic RNG instance. - This example demonstrates this best practice. + The best method to access seed is to directly use a BitGenerator + instance. This example demonstrates this best practice. >>> from numpy.random import MT19937 >>> from numpy.random import RandomState - >>> brng = MT19937(123456789) - >>> rs = RandomState(brng) - >>> brng.seed(987654321) + >>> bit_generator = MT19937(123456789) + >>> rs = RandomState(bit_generator) + >>> bit_generator.seed(987654321) These best practice examples are equivalent to >>> rs = RandomState(MT19937()) >>> rs.seed(987654321) """ - self._basicrng.seed(*args, **kwargs) + self._bit_generator.seed(*args, **kwargs) self._reset_gauss() def get_state(self, legacy=True): @@ -168,11 +169,11 @@ cdef class RandomState: 4. an integer ``has_gauss``. 5. a float ``cached_gaussian``. - If `legacy` is False, or the basic RNG is not NT19937, then + 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 basic RNG + Flag indicating the return a legacy tuple state when the BitGenerator is MT19937. See Also @@ -186,16 +187,16 @@ cdef class RandomState: the user should know exactly what he/she is doing. """ - st = self._basicrng.state - if st['brng'] != 'MT19937' and legacy: + 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 basic RNG. To silence this warning, ' + '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['brng'], st['state']['key'], st['state']['pos'], + return (st['bit_generator'], st['state']['key'], st['state']['pos'], st['has_gauss'], st['gauss']) return st @@ -205,9 +206,10 @@ 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 - Basic RNG used by the RandomState instance. By default, RandomState uses - 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 ---------- @@ -220,7 +222,7 @@ cdef class RandomState: 4. an integer ``has_gauss``. 5. a float ``cached_gaussian``. - If state is a dictionary, it is directly set using the BasicRNGs + If state is a dictionary, it is directly set using the BitGenerators `state` property. Returns @@ -251,7 +253,7 @@ cdef class RandomState: """ if isinstance(state, dict): - if 'brng' not in state or 'state' not in state: + if 'bit_generator' not in state or 'state' not in state: raise ValueError('state dictionary is not valid.') st = state else: @@ -260,7 +262,7 @@ cdef class RandomState: if state[0] != 'MT19937': raise ValueError('set_state can only be used with legacy MT19937' 'state instances.') - st = {'brng': state[0], + st = {'bit_generator': state[0], 'state': {'key': state[1], 'pos': state[2]}} if len(state) > 3: st['has_gauss'] = state[3] @@ -269,7 +271,7 @@ cdef class RandomState: self._aug_state.gauss = st.get('gauss', 0.0) self._aug_state.has_gauss = st.get('has_gauss', 0) - self._basicrng.state = st + self._bit_generator.state = st def random_sample(self, size=None): """ @@ -314,7 +316,16 @@ cdef class RandomState: """ cdef double temp - return double_fill(&random_double_fill, self._brng, size, self.lock, None) + 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): """ @@ -354,7 +365,7 @@ cdef class RandomState: Drawn samples from the parameterized beta distribution. """ - return cont(&legacy_beta, self._aug_state, size, self.lock, 2, + return cont(&legacy_beta, &self._aug_state, size, self.lock, 2, a, 'a', CONS_POSITIVE, b, 'b', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -405,7 +416,7 @@ cdef class RandomState: https://en.wikipedia.org/wiki/Exponential_distribution """ - return cont(&legacy_exponential, self._aug_state, size, self.lock, 1, + return cont(&legacy_exponential, &self._aug_state, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -439,7 +450,7 @@ cdef class RandomState: >>> n = np.random.standard_exponential((3, 8000)) """ - return cont(&legacy_standard_exponential, self._aug_state, size, self.lock, 0, + return cont(&legacy_standard_exponential, &self._aug_state, size, self.lock, 0, None, None, CONS_NONE, None, None, CONS_NONE, None, None, CONS_NONE, @@ -492,7 +503,7 @@ cdef class RandomState: if size is None: with self.lock: - return random_positive_int(self._brng) + return random_positive_int(&self._bitgen) randoms = np.empty(size, dtype=np.int64) randoms_data = np.PyArray_DATA(randoms) @@ -500,7 +511,7 @@ cdef class RandomState: for i in range(n): with self.lock, nogil: - randoms_data[i] = random_positive_int(self._brng) + randoms_data[i] = random_positive_int(&self._bitgen) return randoms def randint(self, low, high=None, size=None, dtype=int): @@ -577,34 +588,40 @@ cdef class RandomState: array([[ 8, 6, 9, 7], # random [ 1, 16, 9, 12]], dtype=uint8) """ - cdef bint use_masked=1 if high is None: high = low low = 0 key = np.dtype(dtype).name - if key not in _randint_types: + if key not in _integers_types: raise TypeError('Unsupported dtype "%s" for randint' % key) + # Implementation detail: the use a masked method to generate + # bounded uniform integers. Lemire's method is preferrable 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, use_masked, False, self._brng, self.lock) + ret = _rand_int32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'int64': - ret = _rand_int64(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_int64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'int16': - ret = _rand_int16(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_int16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'int8': - ret = _rand_int8(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_int8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'uint64': - ret = _rand_uint64(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_uint64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'uint32': - ret = _rand_uint32(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_uint32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'uint16': - ret = _rand_uint16(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_uint16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'uint8': - ret = _rand_uint8(low, high, size, use_masked, False, self._brng, self.lock) + ret = _rand_uint8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock) elif key == 'bool': - ret = _rand_bool(low, high, size, use_masked, False, self._brng, self.lock) + 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 == (): @@ -915,7 +932,7 @@ cdef class RandomState: if not np.isfinite(range): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._brng, size, self.lock, 2, + return cont(&random_uniform, &self._bitgen, size, self.lock, 2, _low, '', CONS_NONE, range, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -928,7 +945,7 @@ cdef class RandomState: arange = np.PyArray_EnsureArray(temp) if not np.all(np.isfinite(arange)): raise OverflowError('Range exceeds valid bounds') - return cont(&random_uniform, self._brng, size, self.lock, 2, + return cont(&random_uniform, &self._bitgen, size, self.lock, 2, alow, '', CONS_NONE, arange, '', CONS_NONE, 0.0, '', CONS_NONE, @@ -1187,7 +1204,7 @@ cdef class RandomState: [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random """ - return cont(&legacy_gauss, self._aug_state, size, self.lock, 0, + return cont(&legacy_gauss, &self._aug_state, size, self.lock, 0, None, None, CONS_NONE, None, None, CONS_NONE, None, None, CONS_NONE, @@ -1289,7 +1306,7 @@ cdef class RandomState: [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random """ - return cont(&legacy_normal, self._aug_state, size, self.lock, 2, + return cont(&legacy_normal, &self._aug_state, size, self.lock, 2, loc, '', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, @@ -1364,7 +1381,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_standard_gamma, self._aug_state, size, self.lock, 1, + 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, @@ -1443,7 +1460,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_gamma, self._aug_state, size, self.lock, 2, + 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) @@ -1531,7 +1548,7 @@ cdef class RandomState: level. """ - return cont(&legacy_f, self._aug_state, size, self.lock, 2, + return cont(&legacy_f, &self._aug_state, size, self.lock, 2, dfnum, 'dfnum', CONS_POSITIVE, dfden, 'dfden', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -1608,7 +1625,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_noncentral_f, self._aug_state, size, self.lock, 3, + 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) @@ -1676,7 +1693,7 @@ cdef class RandomState: array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random """ - return cont(&legacy_chisquare, self._aug_state, size, self.lock, 1, + return cont(&legacy_chisquare, &self._aug_state, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -1755,7 +1772,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_noncentral_chisquare, self._aug_state, size, self.lock, 2, + 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) @@ -1822,7 +1839,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_standard_cauchy, self._aug_state, size, self.lock, 0, + 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): @@ -1913,7 +1930,7 @@ cdef class RandomState: probability of about 99% of being true. """ - return cont(&legacy_standard_t, self._aug_state, size, self.lock, 1, + return cont(&legacy_standard_t, &self._aug_state, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0, '', CONS_NONE, 0, '', CONS_NONE, @@ -1997,7 +2014,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&random_vonmises, self._brng, size, self.lock, 2, + return cont(&random_vonmises, &self._bitgen, size, self.lock, 2, mu, 'mu', CONS_NONE, kappa, 'kappa', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2067,7 +2084,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 @@ -2095,7 +2111,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_pareto, self._aug_state, size, self.lock, 1, + return cont(&legacy_pareto, &self._aug_state, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2193,7 +2209,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_weibull, self._aug_state, size, self.lock, 1, + 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) @@ -2293,7 +2309,7 @@ cdef class RandomState: >>> plt.title('inverse of stats.pareto(5)') """ - return cont(&legacy_power, self._aug_state, size, self.lock, 1, + return cont(&legacy_power, &self._aug_state, size, self.lock, 1, a, 'a', CONS_POSITIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2378,7 +2394,7 @@ cdef class RandomState: >>> plt.plot(x,g) """ - return cont(&random_laplace, self._brng, size, self.lock, 2, + return cont(&random_laplace, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2496,7 +2512,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&random_gumbel, self._brng, size, self.lock, 2, + return cont(&random_gumbel, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2576,7 +2592,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&random_logistic, self._brng, size, self.lock, 2, + return cont(&random_logistic, &self._bitgen, size, self.lock, 2, loc, 'loc', CONS_NONE, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, None) @@ -2686,7 +2702,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_lognormal, self._aug_state, size, self.lock, 2, + 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) @@ -2754,7 +2770,7 @@ cdef class RandomState: 0.087300000000000003 # random """ - return cont(&random_rayleigh, self._brng, size, self.lock, 1, + return cont(&random_rayleigh, &self._bitgen, size, self.lock, 1, scale, 'scale', CONS_NON_NEGATIVE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) @@ -2822,7 +2838,7 @@ cdef class RandomState: >>> plt.show() """ - return cont(&legacy_wald, self._aug_state, size, self.lock, 2, + return cont(&legacy_wald, &self._aug_state, size, self.lock, 2, mean, 'mean', CONS_POSITIVE, scale, 'scale', CONS_POSITIVE, 0.0, '', CONS_NONE, None) @@ -2909,7 +2925,7 @@ cdef class RandomState: raise ValueError("mode > right") if fleft == fright: raise ValueError("left == right") - return cont(&random_triangular, self._brng, size, self.lock, 3, + return cont(&random_triangular, &self._bitgen, size, self.lock, 3, fleft, '', CONS_NONE, fmode, '', CONS_NONE, fright, '', CONS_NONE, None) @@ -2921,7 +2937,7 @@ cdef class RandomState: if np.any(np.equal(oleft, oright)): raise ValueError("left == right") - return cont_broadcast_3(&random_triangular, self._brng, size, self.lock, + return cont_broadcast_3(&random_triangular, &self._bitgen, size, self.lock, oleft, '', CONS_NONE, omode, '', CONS_NONE, oright, '', CONS_NONE) @@ -3044,7 +3060,7 @@ cdef class RandomState: for i in range(cnt): _dp = (np.PyArray_MultiIter_DATA(it, 1))[0] _in = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(self._brng, _dp, _in, self._binomial) + (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(&self._bitgen, _dp, _in, &self._binomial) np.PyArray_MultiIter_NEXT(it) @@ -3057,7 +3073,7 @@ cdef class RandomState: if size is None: with self.lock: - return random_binomial(self._brng, _dp, _in, self._binomial) + return random_binomial(&self._bitgen, _dp, _in, &self._binomial) randoms = np.empty(size, np.int64) cnt = np.PyArray_SIZE(randoms) @@ -3065,8 +3081,8 @@ cdef class RandomState: with self.lock, nogil: for i in range(cnt): - randoms_data[i] = random_binomial(self._brng, _dp, _in, - self._binomial) + randoms_data[i] = random_binomial(&self._bitgen, _dp, _in, + &self._binomial) return randoms @@ -3141,7 +3157,7 @@ cdef class RandomState: ... print(i, "wells drilled, probability of one success =", probability) """ - return disc(&legacy_negative_binomial, self._aug_state, size, self.lock, 2, 0, + return 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) @@ -3212,7 +3228,7 @@ cdef class RandomState: >>> s = np.random.poisson(lam=(100., 500.), size=(100, 2)) """ - return disc(&random_poisson, self._brng, size, self.lock, 1, 0, + return disc(&random_poisson, &self._bitgen, size, self.lock, 1, 0, lam, 'lam', CONS_POISSON, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3291,7 +3307,7 @@ cdef class RandomState: >>> plt.show() """ - return disc(&random_zipf, self._brng, size, self.lock, 1, 0, + return disc(&random_zipf, &self._bitgen, size, self.lock, 1, 0, a, 'a', CONS_GT_1, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) @@ -3342,7 +3358,7 @@ cdef class RandomState: 0.34889999999999999 #random """ - return disc(&random_geometric, self._brng, size, self.lock, 1, 0, + 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) @@ -3454,14 +3470,14 @@ cdef class RandomState: if lngood + lnbad < lnsample: raise ValueError("ngood + nbad < nsample") - return disc(&random_hypergeometric, self._brng, size, self.lock, 0, 3, + return disc(&random_hypergeometric, &self._bitgen, size, self.lock, 0, 3, lngood, 'ngood', CONS_NON_NEGATIVE, lnbad, 'nbad', CONS_NON_NEGATIVE, lnsample, 'nsample', CONS_GTE_1) if np.any(np.less(np.add(ongood, onbad), onsample)): raise ValueError("ngood + nbad < nsample") - return discrete_broadcast_iii(&random_hypergeometric, self._brng, size, self.lock, + return discrete_broadcast_iii(&random_hypergeometric, &self._bitgen, size, self.lock, ongood, 'ngood', CONS_NON_NEGATIVE, onbad, 'nbad', CONS_NON_NEGATIVE, onsample, 'nsample', CONS_GTE_1) @@ -3541,7 +3557,7 @@ cdef class RandomState: >>> plt.show() """ - return disc(&random_logseries, self._brng, size, self.lock, 1, 0, + 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) @@ -3819,7 +3835,7 @@ cdef class RandomState: offset = 0 with self.lock, nogil: for i in range(sz // d): - random_multinomial(self._brng, ni, &mnix[offset], pix, d, self._binomial) + random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial) offset += d return multin @@ -3951,7 +3967,7 @@ cdef class RandomState: while i < totsize: acc = 0.0 for j in range(k): - val_data[i+j] = legacy_standard_gamma(self._aug_state, + val_data[i+j] = legacy_standard_gamma(&self._aug_state, alpha_data[j]) acc = acc + val_data[i + j] invacc = 1/acc @@ -4028,7 +4044,7 @@ cdef class RandomState: buf = np.empty_like(x[0, ...]) with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._brng, i) + j = random_interval(&self._bitgen, i) if i == j: continue # i == j is not needed and memcpy is undefined. buf[...] = x[j] @@ -4038,14 +4054,14 @@ cdef class RandomState: # Untyped path. with self.lock: for i in reversed(range(1, n)): - j = random_interval(self._brng, i) + 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 itemsize, np.npy_intp stride, char* data, char* buf): cdef np.npy_intp i, j for i in reversed(range(1, n)): - j = random_interval(self._brng, i) + 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) @@ -4225,3 +4241,4 @@ __all__ = [ 'RandomState', ] + diff --git a/numpy/random/pcg32.pyx b/numpy/random/pcg32.pyx deleted file mode 100644 index 64e79dfe16f5..000000000000 --- a/numpy/random/pcg32.pyx +++ /dev/null @@ -1,387 +0,0 @@ -from libc.stdlib cimport malloc, free -from cpython.pycapsule cimport PyCapsule_New - -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -import numpy as np -cimport numpy as np - -from .common cimport * -from .distributions cimport brng_t -from .entropy import random_entropy - -np.import_array() - - -cdef extern from "src/pcg32/pcg32.h": - - cdef struct pcg_state_setseq_64: - uint64_t state - uint64_t inc - - ctypedef pcg_state_setseq_64 pcg32_random_t - - struct s_pcg32_state: - pcg32_random_t *pcg_state - - ctypedef s_pcg32_state pcg32_state - - uint64_t pcg32_next64(pcg32_state *state) nogil - uint32_t pcg32_next32(pcg32_state *state) nogil - double pcg32_next_double(pcg32_state *state) nogil - void pcg32_jump(pcg32_state *state) - void pcg32_advance_state(pcg32_state *state, uint64_t step) - void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) - -cdef uint64_t pcg32_uint64(void* st) nogil: - return pcg32_next64(st) - -cdef uint32_t pcg32_uint32(void *st) nogil: - return pcg32_next32( st) - -cdef double pcg32_double(void* st) nogil: - return pcg32_next_double(st) - -cdef uint64_t pcg32_raw(void* st) nogil: - return pcg32_next32( st) - - -cdef class PCG32: - u""" - PCG32(seed=None, inc=0) - - Container for the PCG-32 pseudo-random number generator. - - PCG-32 is a 64-bit implementation of O'Neill's permutation congruential - generator ([1]_, [2]_). PCG-32 has a period of :math:`2^{64}` and supports - advancing an arbitrary number of steps as well as :math:`2^{63}` streams. - - ``PCG32`` exposes no user-facing API except ``generator``,``state``, - ``cffi`` and ``ctypes``. Designed for use in a ``RandomGenerator`` object. - - **Compatibility Guarantee** - - ``PCG32`` makes a guarantee that a fixed seed will always produce the same - results. - - Parameters - ---------- - seed : {None, long}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64] or ``None`` (the default). - If `seed` is ``None``, then ``PCG32`` will try to read data - from ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. - inc : {None, int}, optional - Stream to return. - Can be an integer in [0, 2**64] or ``None`` (the default). If `inc` is - ``None``, then 0 is used. Can be used with the same seed to - produce multiple streams using other values of inc. - - Notes - ----- - Supports the method advance to advance the PRNG an arbitrary number of - steps. The state of the PCG-32 PRNG is represented by 2 128-bit unsigned - integers. - - See ``PCG32`` for a similar implementation with a smaller period. - - **Parallel Features** - - ``PCG32`` can be used in parallel applications in one of two ways. - The preferable method is to use sub-streams, which are generated by using the - same value of ``seed`` and incrementing the second value, ``inc``. - - >>> from numpy.random import RandomGenerator, PCG32 - >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] - - The alternative method is to call ``advance`` with a different value on - each instance to produce non-overlapping sequences. - - >>> rg = [RandomGenerator(PCG32(1234, i + 1)) for i in range(10)] - >>> for i in range(10): - ... rg[i].brng.advance(i * 2**32) - - **State and Seeding** - - The ``PCG32`` state vector consists of 2 unsigned 64-bit values/ - ``PCG32`` is seeded using a single 64-bit unsigned integer. In addition, - a second 64-bit unsigned integer is used to set the 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" - """ - cdef pcg32_state *rng_state - cdef brng_t *_brng - cdef public object capsule - cdef object _ctypes - cdef object _cffi - cdef object _generator - cdef public object lock - - def __init__(self, seed=None, inc=0): - self.rng_state = malloc(sizeof(pcg32_state)) - self.rng_state.pcg_state = malloc(sizeof(pcg32_random_t)) - self._brng = malloc(sizeof(brng_t)) - self.seed(seed, inc) - self.lock = Lock() - - self._brng.state = self.rng_state - self._brng.next_uint64 = &pcg32_uint64 - self._brng.next_uint32 = &pcg32_uint32 - self._brng.next_double = &pcg32_double - self._brng.next_raw = &pcg32_raw - - self._ctypes = None - self._cffi = None - self._generator = None - - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) - - # Pickling support: - def __getstate__(self): - return self.state - - def __setstate__(self, state): - self.state = state - - def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) - - def random_raw(self, size=None, output=True): - """ - random_raw(self, size=None) - - Return randoms as generated by the underlying BasicRNG - - 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._brng, self.lock, size, output) - - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) - - def seed(self, seed=None, inc=0): - """ - seed(seed=None, inc=0) - - Seed the generator. - - This method is called when ``PCG32`` is initialized. It can be - called again to re-seed the generator. For details, see - ``PCG32``. - - Parameters - ---------- - seed : int, optional - Seed for ``PCG32``. - inc : int, optional - Increment to use for PCG stream - - Raises - ------ - ValueError - If seed values are out of range for the PRNG. - """ - ub = 2 ** 64 - if seed is None: - try: - seed = random_entropy(2) - except RuntimeError: - seed = random_entropy(2, 'fallback') - seed = seed.view(np.uint64).squeeze() - else: - err_msg = 'seed must be a scalar integer between 0 and ' \ - '{ub}'.format(ub=ub) - if not np.isscalar(seed): - raise TypeError(err_msg) - if int(seed) != seed: - raise TypeError(err_msg) - if seed < 0 or seed > ub: - raise ValueError(err_msg) - - if not np.isscalar(inc): - raise TypeError('inc must be a scalar integer between 0 ' - 'and {ub}'.format(ub=ub)) - if inc < 0 or inc > ub or int(inc) != inc: - raise ValueError('inc must be a scalar integer between 0 ' - 'and {ub}'.format(ub=ub)) - - pcg32_set_seed(self.rng_state, seed, inc) - - @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 - """ - return {'brng': self.__class__.__name__, - 'state': {'state': self.rng_state.pcg_state.state, - 'inc': self.rng_state.pcg_state.inc}} - - @state.setter - def state(self, value): - if not isinstance(value, dict): - raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: - raise ValueError('state must be for a {0} ' - 'PRNG'.format(self.__class__.__name__)) - self.rng_state.pcg_state.state = value['state']['state'] - self.rng_state.pcg_state.inc = value['state']['inc'] - - 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 : PCG32 - 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. - """ - pcg32_advance_state(self.rng_state, delta) - return self - - def jump(self, np.npy_intp iter=1): - """ - jump(iter=1) - - Jumps the state as-if 2**32 random numbers have been generated - - Parameters - ---------- - iter : integer, positive - Number of times to jump the state of the rng. - - Returns - ------- - self : PCG32 - RNG jumped iter times - """ - return self.advance(iter * 2**32) - - @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 - * brng - pointer to the Basic RNG struct - """ - if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) - - 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 - * brng - pointer to the Basic RNG struct - """ - if self._cffi is not None: - return self._cffi - self._cffi = prepare_cffi(self._brng) - return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/pcg64.pyx b/numpy/random/pcg64.pyx deleted file mode 100644 index af98bbd84c30..000000000000 --- a/numpy/random/pcg64.pyx +++ /dev/null @@ -1,426 +0,0 @@ -from libc.stdlib cimport malloc, free -from cpython.pycapsule cimport PyCapsule_New - -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -import numpy as np -cimport numpy as np - -from .common cimport * -from .distributions cimport brng_t -from .entropy import random_entropy - -np.import_array() - -# IF PCG_EMULATED_MATH==1: -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(st) - -cdef uint32_t pcg64_uint32(void *st) nogil: - return pcg64_next32( st) - -cdef double pcg64_double(void* st) nogil: - return uint64_to_double(pcg64_next64(st)) - -cdef class PCG64: - u""" - PCG64(seed=None, inc=0) - - Container for the PCG-64 pseudo-random number generator. - - 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. - - ``PCG64`` exposes no user-facing API except ``generator``,``state``, - ``cffi`` and ``ctypes``. Designed for use in a ``RandomGenerator`` object. - - **Compatibility Guarantee** - - ``PCG64`` makes a guarantee that a fixed seed will always produce the same - results. - - Parameters - ---------- - seed : {None, long}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**128] or ``None`` (the default). - If `seed` is ``None``, then ``PCG64`` will try to read data - from ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. - inc : {None, int}, optional - Stream to return. - Can be an integer in [0, 2**128] or ``None`` (the default). If `inc` is - ``None``, then 0 is used. Can be used with the same seed to - produce multiple streams using other values of inc. - - Notes - ----- - Supports the method 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. - - See ``PCG32`` for a similar implementation with a smaller period. - - **Parallel Features** - - ``PCG64`` can be used in parallel applications in one of two ways. - The preferable method is to use sub-streams, which are generated by using the - same value of ``seed`` and incrementing the second value, ``inc``. - - >>> from numpy.random import RandomGenerator, PCG64 - >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] - - The alternative method is to call ``advance`` with a different value on - each instance to produce non-overlapping sequences. - - >>> rg = [RandomGenerator(PCG64(1234, i + 1)) for i in range(10)] - >>> for i in range(10): - ... rg[i].brng.advance(i * 2**64) - - **State and Seeding** - - The ``PCG64`` state vector consists of 2 unsigned 128-bit values, - which are represented externally as python longs (2.x) or ints (Python 3+). - ``PCG64`` is seeded using a single 128-bit unsigned integer - (Python long/int). In addition, a second 128-bit unsigned integer is used - to set the 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" - """ - cdef pcg64_state *rng_state - cdef brng_t *_brng - cdef public object capsule - cdef object _ctypes - cdef object _cffi - cdef object _generator - cdef public object lock - - def __init__(self, seed=None, inc=0): - self.rng_state = malloc(sizeof(pcg64_state)) - self.rng_state.pcg_state = malloc(sizeof(pcg64_random_t)) - self._brng = malloc(sizeof(brng_t)) - self.seed(seed, inc) - self.lock = Lock() - - self._brng.state = self.rng_state - self._brng.next_uint64 = &pcg64_uint64 - self._brng.next_uint32 = &pcg64_uint32 - self._brng.next_double = &pcg64_double - self._brng.next_raw = &pcg64_uint64 - - self._ctypes = None - self._cffi = None - self._generator = None - - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) - - # Pickling support: - def __getstate__(self): - return self.state - - def __setstate__(self, state): - self.state = state - - def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) - - cdef _reset_state_variables(self): - self.rng_state.has_uint32 = 0 - self.rng_state.uinteger = 0 - - def random_raw(self, size=None, output=True): - """ - random_raw(self, size=None) - - Return randoms as generated by the underlying BasicRNG - - 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._brng, self.lock, size, output) - - def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) - - def seed(self, seed=None, inc=0): - """ - seed(seed=None, inc=0) - - Seed the generator. - - This method is called when ``PCG64`` is initialized. It can be - called again to re-seed the generator. For details, see - ``PCG64``. - - Parameters - ---------- - seed : int, optional - Seed for ``PCG64``. - inc : int, optional - Increment to use for PCG stream - - Raises - ------ - ValueError - If seed values are out of range for the RNG. - - """ - cdef np.ndarray _seed, _inc - ub = 2 ** 128 - if seed is None: - try: - _seed = random_entropy(4) - except RuntimeError: - _seed = random_entropy(4, 'fallback') - _seed = _seed.view(np.uint64) - else: - err_msg = 'seed must be a scalar integer between 0 and ' \ - '{ub}'.format(ub=ub) - if not np.isscalar(seed): - raise TypeError(err_msg) - if int(seed) != seed: - raise TypeError(err_msg) - if seed < 0 or seed > ub: - raise ValueError(err_msg) - _seed = np.empty(2, np.uint64) - _seed[0] = int(seed) // 2**64 - _seed[1] = int(seed) % 2**64 - - if not np.isscalar(inc): - raise TypeError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) - if inc < 0 or inc > ub or int(inc) != inc: - raise ValueError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) - _inc = np.empty(2, np.uint64) - _inc[0] = int(inc) // 2**64 - _inc[1] = int(inc) % 2**64 - - pcg64_set_seed(self.rng_state, _seed.data, _inc.data) - self._reset_state_variables() - - @property - def state(self): - """ - Get or set the RNG state - - Returns - ------- - state : dict - Dictionary containing the information required to describe the - state of the RNG - """ - 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.empty(4, dtype=np.uint64) - pcg64_get_state(self.rng_state, state_vec.data, &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 {'brng': 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') - brng = value.get('brng', '') - if brng != self.__class__.__name__: - raise ValueError('state must be for a {0} ' - 'RNG'.format(self.__class__.__name__)) - state_vec = 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, state_vec.data, 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. - """ - 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, d.data) - self._reset_state_variables() - return self - - def jump(self, np.npy_intp iter=1): - """ - jump(iter=1) - - Jumps the state as-if 2**64 random numbers have been generated - - Parameters - ---------- - iter : integer, positive - Number of times to jump the state of the rng. - - Returns - ------- - self : PCG64 - RNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is required - to ensure exact reproducibility. - """ - return self.advance(iter * 2**64) - - @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 - * brng - pointer to the Basic RNG struct - """ - if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) - - 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 - * brng - pointer to the Basic RNG struct - """ - if self._cffi is not None: - return self._cffi - self._cffi = prepare_cffi(self._brng) - return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator using this instance as the core RNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/philox.pyx b/numpy/random/philox.pyx index 4ca38bb11968..19fd643998b2 100644 --- a/numpy/random/philox.pyx +++ b/numpy/random/philox.pyx @@ -1,4 +1,3 @@ -from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New try: @@ -9,10 +8,9 @@ except ImportError: import numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array - np.import_array() DEF PHILOX_BUFFER_SIZE=4 @@ -89,69 +87,59 @@ cdef class Philox: the sequence in increments of :math:`2^{128}`. These features allow multiple non-overlapping sequences to be generated. - ``Philox`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + ``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. - **Compatibility Guarantee** + See ``ThreeFry`` for a closely related PRNG. - ``Philox`` guarantees that a fixed seed will always produce the - same results. + **State and Seeding** - See ``Philox`` for a closely related PRNG implementation. + The ``Philox`` state vector consists of a 2 256-bit values encoded as + 4-element uint64 arrays. One 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. + + ``Philox`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the seed is + used as an input for a second random number generator, + SplitMix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. **Parallel Features** - ``Philox`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{128}` random numbers have been generated. Alternatively, - ``advance`` can be used to advance the counter for an abritrary number of - positive steps in [0, 2**256). When using ``jump``, all generators should - be initialized with the same seed to ensure that the segments come from - the same sequence. Alternatively, ``Philox`` can be used - in parallel applications by using a sequence of distinct keys where each - instance uses different key. + ``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 RandomGenerator, Philox - >>> rg = [RandomGenerator(Philox(1234)) for _ in range(10)] - # Advance each Philox instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) + >>> 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() - Using distinct keys produces independent streams + 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**32 + 2**65 + 2**33 + 2**17 + 2**9 - >>> rg = [RandomGenerator(Philox(key=key+i)) for i in range(10)] + >>> key = 2**96 + 2**33 + 2**17 + 2**9 + >>> rg = [Generator(Philox(key=key+i)) for i in range(10)] - **State and Seeding** + **Compatibility Guarantee** - The ``Philox`` state vector consists of a 256-bit counter encoded as a - 4-element uint64 array and a 128-bit key encoded as a 2-element uint64 - array. The counter is incremented by 1 for every 4 64-bit randoms - produced. The key determines the sequence produced. Using different - keys produces independent sequences. - - ``Philox`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for another simple random number generator, - Splitmix64, and the output of this PRNG function is used as the initial state. - Using a single 64-bit value for the seed can only initialize a small range of - the possible initial state values. When using an array, the SplitMix64 state - for producing the ith component of the initial state is XORd with the ith - value of the seed array until the seed array is exhausted. When using an array - the initial state for the SplitMix64 state is 0 so that using a single element - array and using the same value as a scalar will produce the same initial state. + ``Philox`` makes a guarantee that a fixed seed and will always produce + the same random integer stream. Examples -------- - >>> from numpy.random import RandomGenerator, Philox - >>> rg = RandomGenerator(Philox(1234)) - >>> rg.standard_normal() - 0.123 # random - - Identical method using only Philox - - >>> rg = Philox(1234).generator + >>> from numpy.random import Generator, Philox + >>> rg = Generator(Philox(1234)) >>> rg.standard_normal() 0.123 # random @@ -162,36 +150,32 @@ cdef class Philox: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef philox_state *rng_state - cdef brng_t *_brng + cdef philox_state rng_state + cdef philox4x64_key_t philox_key + cdef philox4x64_ctr_t philox_ctr + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None, counter=None, key=None): - self.rng_state = malloc(sizeof(philox_state)) - self.rng_state.ctr = malloc( - sizeof(philox4x64_ctr_t)) - self.rng_state.key = malloc( - sizeof(philox4x64_key_t)) - self._brng = malloc(sizeof(brng_t)) + self.rng_state.ctr = &self.philox_ctr + self.rng_state.key = &self.philox_key self.seed(seed, counter, key) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &philox_uint64 - self._brng.next_uint32 = &philox_uint32 - self._brng.next_double = &philox_double - self._brng.next_raw = &philox_uint64 + self._bitgen.state = &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 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = 'BasicRNG' - self.capsule = PyCapsule_New( self._brng, name, NULL) + cdef const char *name = 'BitGenerator' + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -201,18 +185,8 @@ cdef class Philox: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -225,7 +199,7 @@ cdef class Philox: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -250,10 +224,10 @@ cdef class Philox: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -333,7 +307,7 @@ cdef class Philox: buffer[i] = self.rng_state.buffer[i] state = {'counter': ctr, 'key': key} - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos, @@ -344,8 +318,8 @@ cdef class Philox: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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): @@ -359,28 +333,45 @@ cdef class Philox: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**128 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. + """ + self.advance(iter * 2 ** 128) + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(128 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned Returns ------- - self : Philox - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is - required to ensure exact reproducibility. + bit_generator : Xoroshiro128 + New instance of generator jumped iter times """ - return self.advance(iter * 2 ** 128) + cdef Philox bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator def advance(self, delta): """ @@ -420,7 +411,7 @@ cdef class Philox: """ cdef np.ndarray delta_a delta_a = int_to_array(delta, 'step', 256, 64) - philox_advance( delta_a.data, self.rng_state) + philox_advance( delta_a.data, &self.rng_state) self._reset_state_variables() return self @@ -439,10 +430,10 @@ cdef class Philox: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -461,24 +452,9 @@ cdef class Philox: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/setup.py b/numpy/random/setup.py index fc7c9a8863bf..5f3a48783b50 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -75,7 +75,6 @@ def generate_libraries(ext, build_dir): sys.argv.remove('--no-sse2') DEBUG = False - PCG_EMULATED_MATH = False EXTRA_LINK_ARGS = [] EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ @@ -88,18 +87,6 @@ def generate_libraries(ext, build_dir): if sys.version_info < (3, 0): EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] - PCG64_DEFS = [] - # TODO: remove the unconditional forced emulation, move code from pcg64.pyx - # to an #ifdef - if 1 or sys.maxsize < 2 ** 32 or os.name == 'nt': - # Force emulated mode here - PCG_EMULATED_MATH = True - PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] - - if struct.calcsize('P') < 8: - PCG_EMULATED_MATH = True - defs.append(('PCG_EMULATED_MATH', int(PCG_EMULATED_MATH))) - DSFMT_DEFS = [('DSFMT_MEXP', '19937')] if USE_SSE2: if os.name == 'nt': @@ -112,7 +99,6 @@ def generate_libraries(ext, build_dir): config.add_extension('entropy', sources=['entropy.c', 'src/entropy/entropy.c'], - include_dirs=[join('randomgen', 'src', 'entropy')], libraries=EXTRA_LIBRARIES, extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, @@ -148,15 +134,10 @@ def generate_libraries(ext, build_dir): define_macros=defs, ) for gen in ['philox', 'threefry', 'threefry32', - 'xoroshiro128', 'xorshift1024', 'xoshiro256starstar', - 'xoshiro512starstar', - 'pcg64', 'pcg32', + 'xoroshiro128', 'xorshift1024', 'xoshiro256', + 'xoshiro512', ]: # gen.pyx, src/gen/gen.c - if gen == 'pcg64': - _defs = defs + PCG64_DEFS - else: - _defs = defs config.add_extension(gen, sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], include_dirs=['.', 'src', join('src', gen)], @@ -164,7 +145,7 @@ def generate_libraries(ext, build_dir): extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, depends=['%s.pyx' % gen], - define_macros=_defs, + define_macros=defs, ) for gen in ['common']: # gen.pyx diff --git a/numpy/random/src/common/LICENSE.md b/numpy/random/src/common/LICENSE.md deleted file mode 100644 index 71bf8cf4624b..000000000000 --- a/numpy/random/src/common/LICENSE.md +++ /dev/null @@ -1,29 +0,0 @@ -ISO C9x compliant stdint.h for Microsoft Visual Studio -Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 - -Copyright (c) 2006-2013 Alexander Chemeris - -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 product 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 AUTHOR ``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 AUTHOR 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. \ No newline at end of file diff --git a/numpy/random/src/common/inttypes.h b/numpy/random/src/common/inttypes.h deleted file mode 100644 index 8f8b61108a21..000000000000 --- a/numpy/random/src/common/inttypes.h +++ /dev/null @@ -1,306 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2013 Alexander Chemeris -// -// 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 product 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 AUTHOR ``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 AUTHOR 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "stdint.h" - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -#endif // __STDC_FORMAT_MACROS ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - - -#endif // _MSC_INTTYPES_H_ ] \ No newline at end of file diff --git a/numpy/random/src/common/stdint.h b/numpy/random/src/common/stdint.h deleted file mode 100644 index 710de1570370..000000000000 --- a/numpy/random/src/common/stdint.h +++ /dev/null @@ -1,258 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2013 Alexander Chemeris -// -// 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 product 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 AUTHOR ``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 AUTHOR 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#if _MSC_VER >= 1600 // [ -#include -#else // ] _MSC_VER >= 1600 [ - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -#define _W64 __w64 -#else -#define _W64 -#endif -#endif - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -#else -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ -typedef signed __int64 intptr_t; -typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ -typedef _W64 signed int intptr_t; -typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || \ - defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and - // footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -#define PTRDIFF_MIN _I64_MIN -#define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -#define PTRDIFF_MIN _I32_MIN -#define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -#ifdef _WIN64 // [ -#define SIZE_MAX _UI64_MAX -#else // _WIN64 ][ -#define SIZE_MAX _UI32_MAX -#endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -#define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -#define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || \ - defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -// These #ifndef's are needed to prevent collisions with . -// Check out Issue 9 for the details. -#ifndef INTMAX_C // [ -#define INTMAX_C INT64_C -#endif // INTMAX_C ] -#ifndef UINTMAX_C // [ -#define UINTMAX_C UINT64_C -#endif // UINTMAX_C ] - -#endif // __STDC_CONSTANT_MACROS ] - -#endif // _MSC_VER >= 1600 ] - -#endif // _MSC_STDINT_H_ ] \ No newline at end of file diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 73396a50b317..789440f8bba6 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -7,110 +7,109 @@ #endif /* Random generators for external use */ -float random_float(brng_t *brng_state) { - return next_float(brng_state); -} +float random_float(bitgen_t *bitgen_state) { return next_float(bitgen_state); } -double random_double(brng_t *brng_state) { - return next_double(brng_state); +double random_double(bitgen_t *bitgen_state) { + return next_double(bitgen_state); } -static NPY_INLINE double next_standard_exponential(brng_t *brng_state) { - return -log(1.0 - next_double(brng_state)); +static NPY_INLINE double next_standard_exponential(bitgen_t *bitgen_state) { + return -log(1.0 - next_double(bitgen_state)); } -double random_standard_exponential(brng_t *brng_state) { - return next_standard_exponential(brng_state); +double random_standard_exponential(bitgen_t *bitgen_state) { + return next_standard_exponential(bitgen_state); } -void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, +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(brng_state); + out[i] = next_standard_exponential(bitgen_state); } } -float random_standard_exponential_f(brng_t *brng_state) { - return -logf(1.0f - next_float(brng_state)); +float random_standard_exponential_f(bitgen_t *bitgen_state) { + return -logf(1.0f - next_float(bitgen_state)); } -void random_double_fill(brng_t *brng_state, npy_intp cnt, double *out) { +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(brng_state); + out[i] = next_double(bitgen_state); } } #if 0 -double random_gauss(brng_t *brng_state) { - if (brng_state->has_gauss) { - const double temp = brng_state->gauss; - brng_state->has_gauss = false; - brng_state->gauss = 0.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(brng_state) - 1.0; - x2 = 2.0 * next_double(brng_state) - 1.0; + 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 */ - brng_state->gauss = f * x1; - brng_state->has_gauss = true; + bitgen_state->gauss = f * x1; + bitgen_state->has_gauss = true; return f * x2; } } -float random_gauss_f(brng_t *brng_state) { - if (brng_state->has_gauss_f) { - const float temp = brng_state->gauss_f; - brng_state->has_gauss_f = false; - brng_state->gauss_f = 0.0f; +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(brng_state) - 1.0f; - x2 = 2.0f * next_float(brng_state) - 1.0f; + 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 */ - brng_state->gauss_f = f * x1; - brng_state->has_gauss_f = true; + bitgen_state->gauss_f = f * x1; + bitgen_state->has_gauss_f = true; return f * x2; } } #endif -static NPY_INLINE double standard_exponential_zig(brng_t *brng_state); +static NPY_INLINE double standard_exponential_zig(bitgen_t *bitgen_state); -static double standard_exponential_zig_unlikely(brng_t *brng_state, uint8_t idx, - double x) { +static double standard_exponential_zig_unlikely(bitgen_t *bitgen_state, + uint8_t idx, double x) { if (idx == 0) { - return ziggurat_exp_r - log(next_double(brng_state)); - } else if ((fe_double[idx - 1] - fe_double[idx]) * next_double(brng_state) + + /* 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(brng_state); + return standard_exponential_zig(bitgen_state); } } -static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { +static NPY_INLINE double standard_exponential_zig(bitgen_t *bitgen_state) { uint64_t ri; uint8_t idx; double x; - ri = next_uint64(brng_state); + ri = next_uint64(bitgen_state); ri >>= 3; idx = ri & 0xFF; ri >>= 8; @@ -118,41 +117,42 @@ static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { if (ri < ke_double[idx]) { return x; /* 98.9% of the time we return here 1st try */ } - return standard_exponential_zig_unlikely(brng_state, idx, x); + return standard_exponential_zig_unlikely(bitgen_state, idx, x); } -double random_standard_exponential_zig(brng_t *brng_state) { - return standard_exponential_zig(brng_state); +double random_standard_exponential_zig(bitgen_t *bitgen_state) { + return standard_exponential_zig(bitgen_state); } -void random_standard_exponential_zig_fill(brng_t *brng_state, npy_intp cnt, +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(brng_state); + out[i] = standard_exponential_zig(bitgen_state); } } -static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state); +static NPY_INLINE float standard_exponential_zig_f(bitgen_t *bitgen_state); -static float standard_exponential_zig_unlikely_f(brng_t *brng_state, +static float standard_exponential_zig_unlikely_f(bitgen_t *bitgen_state, uint8_t idx, float x) { if (idx == 0) { - return ziggurat_exp_r_f - logf(next_float(brng_state)); - } else if ((fe_float[idx - 1] - fe_float[idx]) * next_float(brng_state) + + /* 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(brng_state); + return standard_exponential_zig_f(bitgen_state); } } -static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { +static NPY_INLINE float standard_exponential_zig_f(bitgen_t *bitgen_state) { uint32_t ri; uint8_t idx; float x; - ri = next_uint32(brng_state); + ri = next_uint32(bitgen_state); ri >>= 1; idx = ri & 0xFF; ri >>= 8; @@ -160,14 +160,14 @@ static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { if (ri < ke_float[idx]) { return x; /* 98.9% of the time we return here 1st try */ } - return standard_exponential_zig_unlikely_f(brng_state, idx, x); + return standard_exponential_zig_unlikely_f(bitgen_state, idx, x); } -float random_standard_exponential_zig_f(brng_t *brng_state) { - return standard_exponential_zig_f(brng_state); +float random_standard_exponential_zig_f(bitgen_t *bitgen_state) { + return standard_exponential_zig_f(bitgen_state); } -static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { +static NPY_INLINE double next_gauss_zig(bitgen_t *bitgen_state) { uint64_t r; int sign; int64_t rabs; @@ -175,7 +175,7 @@ static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { double x, xx, yy; for (;;) { /* r = e3n52sb8 */ - r = next_uint64(brng_state); + r = next_uint64(bitgen_state); idx = r & 0xff; r >>= 8; sign = r & 0x1; @@ -187,32 +187,33 @@ static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { return x; /* 99.3% of the time return here */ if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r * log(next_double(brng_state)); - yy = -log(next_double(brng_state)); + /* 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(brng_state) + + 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(brng_t *brng_state) { - return next_gauss_zig(brng_state); +double random_gauss_zig(bitgen_t *bitgen_state) { + return next_gauss_zig(bitgen_state); } -void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, double *out) { +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(brng_state); + out[i] = next_gauss_zig(bitgen_state); } } -float random_gauss_zig_f(brng_t *brng_state) { +float random_gauss_zig_f(bitgen_t *bitgen_state) { uint32_t r; int sign; int32_t rabs; @@ -220,7 +221,7 @@ float random_gauss_zig_f(brng_t *brng_state) { float x, xx, yy; for (;;) { /* r = n23sb8 */ - r = next_uint32(brng_state); + r = next_uint32(bitgen_state); idx = r & 0xff; sign = (r >> 8) & 0x1; rabs = (int32_t)((r >> 9) & 0x0007fffff); @@ -231,14 +232,15 @@ float random_gauss_zig_f(brng_t *brng_state) { return x; /* # 99.3% of the time return here */ if (idx == 0) { for (;;) { - xx = -ziggurat_nor_inv_r_f * logf(next_float(brng_state)); - yy = -logf(next_float(brng_state)); + /* 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(brng_state) + + if (((fi_float[idx - 1] - fi_float[idx]) * next_float(bitgen_state) + fi_float[idx]) < exp(-0.5 * x * x)) return x; } @@ -246,16 +248,16 @@ float random_gauss_zig_f(brng_t *brng_state) { } /* -static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { +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(brng_state); + return random_standard_exponential(bitgen_state); } else if (shape < 1.0) { for (;;) { - U = next_double(brng_state); - V = random_standard_exponential(brng_state); + U = next_double(bitgen_state); + V = random_standard_exponential(bitgen_state); if (U <= 1.0 - shape) { X = pow(U, 1. / shape); if (X <= V) { @@ -274,12 +276,12 @@ static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { c = 1. / sqrt(9 * b); for (;;) { do { - X = random_gauss(brng_state); + X = random_gauss(bitgen_state); V = 1.0 + c * X; } while (V <= 0.0); V = V * V * V; - U = next_double(brng_state); + 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))) @@ -288,16 +290,15 @@ static NPY_INLINE double standard_gamma(brng_t *brng_state, double shape) { } } -static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { - float b, c; - float U, V, X, Y; +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(brng_state); + return random_standard_exponential_f(bitgen_state); } else if (shape < 1.0f) { for (;;) { - U = next_float(brng_state); - V = random_standard_exponential_f(brng_state); + 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) { @@ -316,12 +317,12 @@ static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { c = 1.0f / sqrtf(9.0f * b); for (;;) { do { - X = random_gauss_f(brng_state); + X = random_gauss_f(bitgen_state); V = 1.0f + c * X; } while (V <= 0.0f); V = V * V * V; - U = next_float(brng_state); + 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))) @@ -331,27 +332,28 @@ static NPY_INLINE float standard_gamma_float(brng_t *brng_state, float shape) { } -double random_standard_gamma(brng_t *brng_state, double shape) { - return standard_gamma(brng_state, shape); +double random_standard_gamma(bitgen_t *bitgen_state, double shape) { + return standard_gamma(bitgen_state, shape); } -float random_standard_gamma_f(brng_t *brng_state, float shape) { - return standard_gamma_float(brng_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(brng_t *brng_state, double 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(brng_state); + return random_standard_exponential_zig(bitgen_state); } else if (shape == 0.0) { return 0.0; } else if (shape < 1.0) { for (;;) { - U = next_double(brng_state); - V = random_standard_exponential_zig(brng_state); + 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) { @@ -370,32 +372,34 @@ static NPY_INLINE double standard_gamma_zig(brng_t *brng_state, double shape) { c = 1. / sqrt(9 * b); for (;;) { do { - X = random_gauss_zig(brng_state); + X = random_gauss_zig(bitgen_state); V = 1.0 + c * X; } while (V <= 0.0); V = V * V * V; - U = next_double(brng_state); + 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(brng_t *brng_state, float shape) { +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(brng_state); + 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(brng_state); - V = random_standard_exponential_zig_f(brng_state); + 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) { @@ -414,49 +418,50 @@ static NPY_INLINE float standard_gamma_zig_f(brng_t *brng_state, float shape) { c = 1.0f / sqrtf(9.0f * b); for (;;) { do { - X = random_gauss_zig_f(brng_state); + X = random_gauss_zig_f(bitgen_state); V = 1.0f + c * X; } while (V <= 0.0f); V = V * V * V; - U = next_float(brng_state); + 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(brng_t *brng_state, double shape) { - return standard_gamma_zig(brng_state, shape); +double random_standard_gamma_zig(bitgen_t *bitgen_state, double shape) { + return standard_gamma_zig(bitgen_state, shape); } -float random_standard_gamma_zig_f(brng_t *brng_state, float shape) { - return standard_gamma_zig_f(brng_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(brng_t *brng_state) { - return next_uint64(brng_state) >> 1; +int64_t random_positive_int64(bitgen_t *bitgen_state) { + return next_uint64(bitgen_state) >> 1; } -int32_t random_positive_int32(brng_t *brng_state) { - return next_uint32(brng_state) >> 1; +int32_t random_positive_int32(bitgen_t *bitgen_state) { + return next_uint32(bitgen_state) >> 1; } -int64_t random_positive_int(brng_t *brng_state) { +int64_t random_positive_int(bitgen_t *bitgen_state) { #if ULONG_MAX <= 0xffffffffUL - return (int64_t)(next_uint32(brng_state) >> 1); + return (int64_t)(next_uint32(bitgen_state) >> 1); #else - return (int64_t)(next_uint64(brng_state) >> 1); + return (int64_t)(next_uint64(bitgen_state) >> 1); #endif } -uint64_t random_uint(brng_t *brng_state) { +uint64_t random_uint(bitgen_t *bitgen_state) { #if ULONG_MAX <= 0xffffffffUL - return next_uint32(brng_state); + return next_uint32(bitgen_state); #else - return next_uint64(brng_state); + return next_uint64(bitgen_state); #endif } @@ -500,47 +505,48 @@ static double loggam(double x) { } /* -double random_normal(brng_t *brng_state, double loc, double scale) { - return loc + scale * random_gauss(brng_state); +double random_normal(bitgen_t *bitgen_state, double loc, double scale) { + return loc + scale * random_gauss(bitgen_state); } */ -double random_normal_zig(brng_t *brng_state, double loc, double scale) { - return loc + scale * random_gauss_zig(brng_state); +double random_normal_zig(bitgen_t *bitgen_state, double loc, double scale) { + return loc + scale * random_gauss_zig(bitgen_state); } -double random_exponential(brng_t *brng_state, double scale) { - return scale * standard_exponential_zig(brng_state); +double random_exponential(bitgen_t *bitgen_state, double scale) { + return scale * standard_exponential_zig(bitgen_state); } -double random_uniform(brng_t *brng_state, double lower, double range) { - return lower + range * next_double(brng_state); +double random_uniform(bitgen_t *bitgen_state, double lower, double range) { + return lower + range * next_double(bitgen_state); } -double random_gamma(brng_t *brng_state, double shape, double scale) { - return scale * random_standard_gamma_zig(brng_state, shape); +double random_gamma(bitgen_t *bitgen_state, double shape, double scale) { + return scale * random_standard_gamma_zig(bitgen_state, shape); } -float random_gamma_float(brng_t *brng_state, float shape, float scale) { - return scale * random_standard_gamma_zig_f(brng_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(brng_t *brng_state, double a, double b) { +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; + double U, V, X, Y, XpY; /* Use Johnk's algorithm */ while (1) { - U = next_double(brng_state); - V = next_double(brng_state); + U = next_double(bitgen_state); + V = next_double(bitgen_state); X = pow(U, 1.0 / a); Y = pow(V, 1.0 / b); - - if ((X + Y) <= 1.0) { + 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 / (X + Y); + return X / XpY; } else { double logX = log(U) / a; double logY = log(V) / b; @@ -553,83 +559,94 @@ double random_beta(brng_t *brng_state, double a, double b) { } } } else { - Ga = random_standard_gamma_zig(brng_state, a); - Gb = random_standard_gamma_zig(brng_state, b); + Ga = random_standard_gamma_zig(bitgen_state, a); + Gb = random_standard_gamma_zig(bitgen_state, b); return Ga / (Ga + Gb); } } -double random_chisquare(brng_t *brng_state, double df) { - return 2.0 * random_standard_gamma_zig(brng_state, df / 2.0); +double random_chisquare(bitgen_t *bitgen_state, double df) { + return 2.0 * random_standard_gamma_zig(bitgen_state, df / 2.0); } -double random_f(brng_t *brng_state, double dfnum, double dfden) { - return ((random_chisquare(brng_state, dfnum) * dfden) / - (random_chisquare(brng_state, dfden) * dfnum)); +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(brng_t *brng_state) { - return random_gauss_zig(brng_state) / random_gauss_zig(brng_state); +double random_standard_cauchy(bitgen_t *bitgen_state) { + return random_gauss_zig(bitgen_state) / random_gauss_zig(bitgen_state); } -double random_pareto(brng_t *brng_state, double a) { - return exp(standard_exponential_zig(brng_state) / a) - 1; +double random_pareto(bitgen_t *bitgen_state, double a) { + return exp(standard_exponential_zig(bitgen_state) / a) - 1; } -double random_weibull(brng_t *brng_state, double a) { +double random_weibull(bitgen_t *bitgen_state, double a) { if (a == 0.0) { return 0.0; } - return pow(standard_exponential_zig(brng_state), 1. / a); + return pow(standard_exponential_zig(bitgen_state), 1. / a); } -double random_power(brng_t *brng_state, double a) { - return pow(1 - exp(-standard_exponential_zig(brng_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(brng_t *brng_state, double loc, double scale) { +double random_laplace(bitgen_t *bitgen_state, double loc, double scale) { double U; - U = next_double(brng_state); - if (U < 0.5) { + 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 { - U = loc - scale * log(2.0 - U - U); + /* Reject U == 0.0 and call again to get next value */ + U = random_laplace(bitgen_state, loc, scale); } return U; } -double random_gumbel(brng_t *brng_state, double loc, double scale) { +double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) { double U; - U = 1.0 - next_double(brng_state); - return loc - scale * log(-log(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(brng_t *brng_state, double loc, double scale) { +double random_logistic(bitgen_t *bitgen_state, double loc, double scale) { double U; - U = next_double(brng_state); - return loc + scale * log(U / (1.0 - 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(brng_t *brng_state, double mean, double sigma) { - return exp(random_normal_zig(brng_state, mean, sigma)); +double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) { + return exp(random_normal_zig(bitgen_state, mean, sigma)); } -double random_rayleigh(brng_t *brng_state, double mode) { - return mode * sqrt(-2.0 * log(1.0 - next_double(brng_state))); +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(brng_t *brng_state, double df) { +double random_standard_t(bitgen_t *bitgen_state, double df) { double num, denom; - num = random_gauss_zig(brng_state); - denom = random_standard_gamma_zig(brng_state, df / 2); + num = random_gauss_zig(bitgen_state); + denom = random_standard_gamma_zig(bitgen_state, df / 2); return sqrt(df / 2) * num / sqrt(denom); } -static int64_t random_poisson_mult(brng_t *brng_state, double lam) { +static int64_t random_poisson_mult(bitgen_t *bitgen_state, double lam) { int64_t X; double prod, U, enlam; @@ -637,7 +654,7 @@ static int64_t random_poisson_mult(brng_t *brng_state, double lam) { X = 0; prod = 1.0; while (1) { - U = next_double(brng_state); + U = next_double(bitgen_state); prod *= U; if (prod > enlam) { X += 1; @@ -654,7 +671,7 @@ static int64_t random_poisson_mult(brng_t *brng_state, double lam) { */ #define LS2PI 0.91893853320467267 #define TWELFTH 0.083333333333333333333333 -static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { +static int64_t random_poisson_ptrs(bitgen_t *bitgen_state, double lam) { int64_t k; double U, V, slam, loglam, a, b, invalpha, vr, us; @@ -666,8 +683,8 @@ static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { vr = 0.9277 - 3.6224 / (b - 2); while (1) { - U = next_double(brng_state) - 0.5; - V = next_double(brng_state); + U = next_double(bitgen_state) - 0.5; + V = next_double(bitgen_state); us = 0.5 - fabs(U); k = (int64_t)floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { @@ -676,6 +693,8 @@ static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { 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; @@ -683,22 +702,22 @@ static int64_t random_poisson_ptrs(brng_t *brng_state, double lam) { } } -int64_t random_poisson(brng_t *brng_state, double lam) { +int64_t random_poisson(bitgen_t *bitgen_state, double lam) { if (lam >= 10) { - return random_poisson_ptrs(brng_state, lam); + return random_poisson_ptrs(bitgen_state, lam); } else if (lam == 0) { return 0; } else { - return random_poisson_mult(brng_state, lam); + return random_poisson_mult(bitgen_state, lam); } } -int64_t random_negative_binomial(brng_t *brng_state, double n, double p) { - double Y = random_gamma(brng_state, n, (1 - p) / p); - return random_poisson(brng_state, Y); +int64_t 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); } -int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, +int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t 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; @@ -746,8 +765,8 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, /* sigh ... */ Step10: nrq = n * r * q; - u = next_double(brng_state) * p4; - v = next_double(brng_state); + u = next_double(bitgen_state) * p4; + v = next_double(bitgen_state); if (u > p1) goto Step20; y = (int64_t)floor(xm - p1 * v + u); @@ -767,14 +786,16 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, if (u > p3) goto Step40; y = (int64_t)floor(xl + log(v) / laml); - if (y < 0) + /* 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 = (int64_t)floor(xr - log(v) / lamr); - if (y > n) + /* Reject if v==0.0 since previous cast is undefined */ + if ((y > n) || (v == 0.0)) goto Step10; v = v * (u - p3) * lamr; @@ -803,6 +824,7 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, 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; @@ -838,7 +860,7 @@ int64_t random_binomial_btpe(brng_t *brng_state, int64_t n, double p, return y; } -int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, +int64_t random_binomial_inversion(bitgen_t *bitgen_state, int64_t n, double p, binomial_t *binomial) { double q, qn, np, px, U; int64_t X, bound; @@ -860,13 +882,13 @@ int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, } X = 0; px = qn; - U = next_double(brng_state); + U = next_double(bitgen_state); while (U > px) { X++; if (X > bound) { X = 0; px = qn; - U = next_double(brng_state); + U = next_double(bitgen_state); } else { U -= px; px = ((n - X + 1) * p * px) / (X * q); @@ -875,7 +897,7 @@ int64_t random_binomial_inversion(brng_t *brng_state, int64_t n, double p, return X; } -int64_t random_binomial(brng_t *brng_state, double p, int64_t n, +int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) { double q; @@ -884,52 +906,53 @@ int64_t random_binomial(brng_t *brng_state, double p, int64_t n, if (p <= 0.5) { if (p * n <= 30.0) { - return random_binomial_inversion(brng_state, n, p, binomial); + return random_binomial_inversion(bitgen_state, n, p, binomial); } else { - return random_binomial_btpe(brng_state, n, p, binomial); + return random_binomial_btpe(bitgen_state, n, p, binomial); } } else { q = 1.0 - p; if (q * n <= 30.0) { - return n - random_binomial_inversion(brng_state, n, q, binomial); + return n - random_binomial_inversion(bitgen_state, n, q, binomial); } else { - return n - random_binomial_btpe(brng_state, n, q, binomial); + return n - random_binomial_btpe(bitgen_state, n, q, binomial); } } } -double random_noncentral_chisquare(brng_t *brng_state, double df, double nonc) { - if (npy_isnan(nonc)){ +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(brng_state, df); + return random_chisquare(bitgen_state, df); } if (1 < df) { - const double Chi2 = random_chisquare(brng_state, df - 1); - const double n = random_gauss_zig(brng_state) + sqrt(nonc); + 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 int64_t i = random_poisson(brng_state, nonc / 2.0); - return random_chisquare(brng_state, df + 2 * i); + const int64_t i = random_poisson(bitgen_state, nonc / 2.0); + return random_chisquare(bitgen_state, df + 2 * i); } } -double random_noncentral_f(brng_t *brng_state, double dfnum, double dfden, +double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden, double nonc) { - double t = random_noncentral_chisquare(brng_state, dfnum, nonc) * dfden; - return t / (random_chisquare(brng_state, dfden) * dfnum); + double t = random_noncentral_chisquare(bitgen_state, dfnum, nonc) * dfden; + return t / (random_chisquare(bitgen_state, dfden) * dfnum); } -double random_wald(brng_t *brng_state, double mean, double scale) { +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(brng_state); + Y = random_gauss_zig(bitgen_state); Y = mean * Y * Y; X = mean + mu_2l * (Y - sqrt(4 * scale * Y + Y * Y)); - U = next_double(brng_state); + U = next_double(bitgen_state); if (U <= mean / (mean + X)) { return X; } else { @@ -937,16 +960,16 @@ double random_wald(brng_t *brng_state, double mean, double scale) { } } -double random_vonmises(brng_t *brng_state, double mu, double kappa) { +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)){ + if (npy_isnan(kappa)) { return NPY_NAN; } if (kappa < 1e-8) { - return M_PI * (2 * next_double(brng_state) - 1); + return M_PI * (2 * next_double(bitgen_state) - 1); } else { /* with double precision rho is zero until 1.4e-8 */ if (kappa < 1e-5) { @@ -962,17 +985,21 @@ double random_vonmises(brng_t *brng_state, double mu, double kappa) { } while (1) { - U = next_double(brng_state); + U = next_double(bitgen_state); Z = cos(M_PI * U); W = (1 + s * Z) / (s + Z); Y = kappa * (s - W); - V = next_double(brng_state); + 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(brng_state); + U = next_double(bitgen_state); result = acos(W); if (U < 0.5) { @@ -990,22 +1017,22 @@ double random_vonmises(brng_t *brng_state, double mu, double kappa) { } } -int64_t random_logseries(brng_t *brng_state, double p) { +int64_t random_logseries(bitgen_t *bitgen_state, double p) { double q, r, U, V; int64_t result; r = log(1.0 - p); while (1) { - V = next_double(brng_state); + V = next_double(bitgen_state); if (V >= p) { return 1; } - U = next_double(brng_state); + U = next_double(bitgen_state); q = 1.0 - exp(r * U); if (V <= q * q) { result = (int64_t)floor(1 + log(V) / log(q)); - if (result < 1) { + if ((result < 1) || (V == 0.0)) { continue; } else { return result; @@ -1018,7 +1045,7 @@ int64_t random_logseries(brng_t *brng_state, double p) { } } -int64_t random_geometric_search(brng_t *brng_state, double p) { +int64_t random_geometric_search(bitgen_t *bitgen_state, double p) { double U; int64_t X; double sum, prod, q; @@ -1026,7 +1053,7 @@ int64_t random_geometric_search(brng_t *brng_state, double p) { X = 1; sum = prod = p; q = 1.0 - p; - U = next_double(brng_state); + U = next_double(bitgen_state); while (U > sum) { prod *= q; sum += prod; @@ -1035,19 +1062,19 @@ int64_t random_geometric_search(brng_t *brng_state, double p) { return X; } -int64_t random_geometric_inversion(brng_t *brng_state, double p) { - return (int64_t)ceil(log(1.0 - next_double(brng_state)) / log(1.0 - p)); +int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) { + return (int64_t)ceil(log(1.0 - next_double(bitgen_state)) / log(1.0 - p)); } -int64_t random_geometric(brng_t *brng_state, double p) { +int64_t random_geometric(bitgen_t *bitgen_state, double p) { if (p >= 0.333333333333333333333333) { - return random_geometric_search(brng_state, p); + return random_geometric_search(bitgen_state, p); } else { - return random_geometric_inversion(brng_state, p); + return random_geometric_inversion(bitgen_state, p); } } -int64_t random_zipf(brng_t *brng_state, double a) { +int64_t random_zipf(bitgen_t *bitgen_state, double a) { double am1, b; am1 = a - 1.0; @@ -1055,8 +1082,8 @@ int64_t random_zipf(brng_t *brng_state, double a) { while (1) { double T, U, V, X; - U = 1.0 - random_double(brng_state); - V = random_double(brng_state); + 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 @@ -1075,7 +1102,7 @@ int64_t random_zipf(brng_t *brng_state, double a) { } } -double random_triangular(brng_t *brng_state, double left, double mode, +double random_triangular(bitgen_t *bitgen_state, double left, double mode, double right) { double base, leftbase, ratio, leftprod, rightprod; double U; @@ -1086,7 +1113,7 @@ double random_triangular(brng_t *brng_state, double left, double mode, leftprod = leftbase * base; rightprod = (right - mode) * base; - U = next_double(brng_state); + U = next_double(bitgen_state); if (U <= ratio) { return left + sqrt(U * leftprod); } else { @@ -1094,8 +1121,8 @@ double random_triangular(brng_t *brng_state, double left, double mode, } } -int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, - int64_t sample) { +int64_t random_hypergeometric_hyp(bitgen_t *bitgen_state, int64_t good, + int64_t bad, int64_t sample) { int64_t d1, k, z; double d2, u, y; @@ -1105,7 +1132,7 @@ int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, y = d2; k = sample; while (y > 0.0) { - u = next_double(brng_state); + u = next_double(bitgen_state); y -= (int64_t)floor(u + y / (d1 + k)); k--; if (k == 0) @@ -1121,7 +1148,7 @@ int64_t random_hypergeometric_hyp(brng_t *brng_state, int64_t good, int64_t bad, /* D2 = 3 - 2*sqrt(3/e) */ #define D1 1.7155277699214135 #define D2 0.8989161620588988 -int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, +int64_t random_hypergeometric_hrua(bitgen_t *bitgen_state, int64_t good, int64_t bad, int64_t sample) { int64_t mingoodbad, maxgoodbad, popsize, m, d9; double d4, d5, d6, d7, d8, d10, d11; @@ -1144,8 +1171,8 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, /* 16 for 16-decimal-digit precision in D1 and D2 */ while (1) { - X = next_double(brng_state); - Y = next_double(brng_state); + X = next_double(bitgen_state); + Y = next_double(bitgen_state); W = d6 + d8 * (Y - 0.5) / X; /* fast rejection: */ @@ -1163,7 +1190,7 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, /* 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 */ } @@ -1181,18 +1208,18 @@ int64_t random_hypergeometric_hrua(brng_t *brng_state, int64_t good, #undef D1 #undef D2 -int64_t random_hypergeometric(brng_t *brng_state, int64_t good, int64_t bad, +int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad, int64_t sample) { if (sample > 10) { - return random_hypergeometric_hrua(brng_state, good, bad, sample); + return random_hypergeometric_hrua(bitgen_state, good, bad, sample); } else if (sample > 0) { - return random_hypergeometric_hyp(brng_state, good, bad, sample); + return random_hypergeometric_hyp(bitgen_state, good, bad, sample); } else { - return 0; + return 0; } } -uint64_t random_interval(brng_t *brng_state, uint64_t max) { +uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) { uint64_t mask, value; if (max == 0) { return 0; @@ -1210,15 +1237,16 @@ uint64_t random_interval(brng_t *brng_state, uint64_t max) { /* Search a random value in [0..mask] <= max */ if (max <= 0xffffffffUL) { - while ((value = (next_uint32(brng_state) & mask)) > max) + while ((value = (next_uint32(bitgen_state) & mask)) > max) ; } else { - while ((value = (next_uint64(brng_state) & mask)) > max) + 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; @@ -1231,10 +1259,10 @@ static NPY_INLINE uint64_t gen_mask(uint64_t max) { } /* Generate 16 bit random numbers using a 32 bit buffer. */ -static NPY_INLINE uint16_t buffered_uint16(brng_t *brng_state, int *bcnt, +static NPY_INLINE uint16_t buffered_uint16(bitgen_t *bitgen_state, int *bcnt, uint32_t *buf) { if (!(bcnt[0])) { - buf[0] = next_uint32(brng_state); + buf[0] = next_uint32(bitgen_state); bcnt[0] = 1; } else { buf[0] >>= 16; @@ -1245,10 +1273,10 @@ static NPY_INLINE uint16_t buffered_uint16(brng_t *brng_state, int *bcnt, } /* Generate 8 bit random numbers using a 32 bit buffer. */ -static NPY_INLINE uint8_t buffered_uint8(brng_t *brng_state, int *bcnt, +static NPY_INLINE uint8_t buffered_uint8(bitgen_t *bitgen_state, int *bcnt, uint32_t *buf) { if (!(bcnt[0])) { - buf[0] = next_uint32(brng_state); + buf[0] = next_uint32(bitgen_state); bcnt[0] = 3; } else { buf[0] >>= 8; @@ -1259,11 +1287,11 @@ static NPY_INLINE uint8_t buffered_uint8(brng_t *brng_state, int *bcnt, } /* Static `masked rejection` function called by random_bounded_uint64(...) */ -static NPY_INLINE uint64_t bounded_masked_uint64(brng_t *brng_state, +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(brng_state) & mask)) > rng) + while ((val = (next_uint64(bitgen_state) & mask)) > rng) ; return val; @@ -1271,8 +1299,9 @@ static NPY_INLINE uint64_t bounded_masked_uint64(brng_t *brng_state, /* Static `masked rejection` function called by * random_buffered_bounded_uint32(...) */ -static NPY_INLINE uint32_t buffered_bounded_masked_uint32( - brng_t *brng_state, uint32_t rng, uint32_t mask, int *bcnt, uint32_t *buf) { +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 @@ -1281,7 +1310,7 @@ static NPY_INLINE uint32_t buffered_bounded_masked_uint32( uint32_t val; - while ((val = (next_uint32(brng_state) & mask)) > rng) + while ((val = (next_uint32(bitgen_state) & mask)) > rng) ; return val; @@ -1289,11 +1318,12 @@ static NPY_INLINE uint32_t buffered_bounded_masked_uint32( /* Static `masked rejection` function called by * random_buffered_bounded_uint16(...) */ -static NPY_INLINE uint16_t buffered_bounded_masked_uint16( - brng_t *brng_state, uint16_t rng, uint16_t mask, int *bcnt, uint32_t *buf) { +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(brng_state, bcnt, buf) & mask)) > rng) + while ((val = (buffered_uint16(bitgen_state, bcnt, buf) & mask)) > rng) ; return val; @@ -1301,20 +1331,36 @@ static NPY_INLINE uint16_t buffered_bounded_masked_uint16( /* Static `masked rejection` function called by * random_buffered_bounded_uint8(...) */ -static NPY_INLINE uint8_t buffered_bounded_masked_uint8(brng_t *brng_state, +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(brng_state, bcnt, buf) & mask)) > rng) + 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(brng_t *brng_state, +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 @@ -1331,7 +1377,7 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_state, uint64_t leftover; /* Generate a scaled random number. */ - m = ((__uint128_t)next_uint64(brng_state)) * rng_excl; + m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl; /* Rejection sampling to remove any bias. */ leftover = m & 0xFFFFFFFFFFFFFFFFULL; @@ -1344,7 +1390,7 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_state, * rng_excl; */ while (leftover < threshold) { - m = ((__uint128_t)next_uint64(brng_state)) * rng_excl; + m = ((__uint128_t)next_uint64(bitgen_state)) * rng_excl; leftover = m & 0xFFFFFFFFFFFFFFFFULL; } } @@ -1357,7 +1403,7 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_state, uint64_t x; uint64_t leftover; - x = next_uint64(brng_state); + x = next_uint64(bitgen_state); /* Rejection sampling to remove any bias. */ leftover = x * rng_excl; /* The lower 64-bits of the mult. */ @@ -1370,7 +1416,7 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_state, * rng_excl; */ while (leftover < threshold) { - x = next_uint64(brng_state); + x = next_uint64(bitgen_state); leftover = x * rng_excl; } } @@ -1403,10 +1449,8 @@ static NPY_INLINE uint64_t bounded_lemire_uint64(brng_t *brng_state, /* Static `Lemire rejection` function called by * random_buffered_bounded_uint32(...) */ -static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(brng_t *brng_state, - uint32_t rng, - int *bcnt, - uint32_t *buf) { +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 * @@ -1423,7 +1467,7 @@ static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(brng_t *brng_state, uint32_t leftover; /* Generate a scaled random number. */ - m = ((uint64_t)next_uint32(brng_state)) * rng_excl; + m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl; /* Rejection sampling to remove any bias */ leftover = m & 0xFFFFFFFFUL; @@ -1434,7 +1478,7 @@ static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(brng_t *brng_state, /* Same as: threshold=((uint64_t)(0x100000000ULL - rng_excl)) % rng_excl; */ while (leftover < threshold) { - m = ((uint64_t)next_uint32(brng_state)) * rng_excl; + m = ((uint64_t)next_uint32(bitgen_state)) * rng_excl; leftover = m & 0xFFFFFFFFUL; } } @@ -1444,10 +1488,8 @@ static NPY_INLINE uint32_t buffered_bounded_lemire_uint32(brng_t *brng_state, /* Static `Lemire rejection` function called by * random_buffered_bounded_uint16(...) */ -static NPY_INLINE uint16_t buffered_bounded_lemire_uint16(brng_t *brng_state, - uint16_t rng, - int *bcnt, - uint32_t *buf) { +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 * @@ -1460,7 +1502,7 @@ static NPY_INLINE uint16_t buffered_bounded_lemire_uint16(brng_t *brng_state, uint16_t leftover; /* Generate a scaled random number. */ - m = ((uint32_t)buffered_uint16(brng_state, bcnt, buf)) * rng_excl; + m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl; /* Rejection sampling to remove any bias */ leftover = m & 0xFFFFUL; @@ -1471,7 +1513,7 @@ static NPY_INLINE uint16_t buffered_bounded_lemire_uint16(brng_t *brng_state, /* Same as: threshold=((uint32_t)(0x10000ULL - rng_excl)) % rng_excl; */ while (leftover < threshold) { - m = ((uint32_t)buffered_uint16(brng_state, bcnt, buf)) * rng_excl; + m = ((uint32_t)buffered_uint16(bitgen_state, bcnt, buf)) * rng_excl; leftover = m & 0xFFFFUL; } } @@ -1481,7 +1523,7 @@ static NPY_INLINE uint16_t buffered_bounded_lemire_uint16(brng_t *brng_state, /* Static `Lemire rejection` function called by * random_buffered_bounded_uint8(...) */ -static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(brng_t *brng_state, +static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(bitgen_t *bitgen_state, uint8_t rng, int *bcnt, uint32_t *buf) { /* @@ -1496,7 +1538,7 @@ static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(brng_t *brng_state, uint8_t leftover; /* Generate a scaled random number. */ - m = ((uint16_t)buffered_uint8(brng_state, bcnt, buf)) * rng_excl; + m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl; /* Rejection sampling to remove any bias */ leftover = m & 0xFFUL; @@ -1507,7 +1549,7 @@ static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(brng_t *brng_state, /* Same as: threshold=((uint16_t)(0x100ULL - rng_excl)) % rng_excl; */ while (leftover < threshold) { - m = ((uint16_t)buffered_uint8(brng_state, bcnt, buf)) * rng_excl; + m = ((uint16_t)buffered_uint8(bitgen_state, bcnt, buf)) * rng_excl; leftover = m & 0xFFUL; } } @@ -1519,26 +1561,27 @@ static NPY_INLINE uint8_t buffered_bounded_lemire_uint8(brng_t *brng_state, * 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(brng_t *brng_state, uint64_t off, uint64_t rng, - uint64_t mask, bool use_masked) { +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(brng_state, rng, mask, NULL, NULL); + return off + buffered_bounded_masked_uint32(bitgen_state, rng, mask, NULL, + NULL); } else { - return off + buffered_bounded_lemire_uint32(brng_state, rng, NULL, NULL); + 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(brng_state); + return off + next_uint64(bitgen_state); } else { if (use_masked) { - return off + bounded_masked_uint64(brng_state, rng, mask); + return off + bounded_masked_uint64(bitgen_state, rng, mask); } else { - return off + bounded_lemire_uint64(brng_state, rng); + return off + bounded_lemire_uint64(bitgen_state, rng); } } } @@ -1547,7 +1590,7 @@ uint64_t random_bounded_uint64(brng_t *brng_state, uint64_t off, uint64_t 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(brng_t *brng_state, uint32_t off, +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) { @@ -1559,13 +1602,13 @@ uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, return off; } else if (rng == 0xFFFFFFFFUL) { /* Lemire32 doesn't support inclusive rng = 0xFFFFFFFF. */ - return off + next_uint32(brng_state); + return off + next_uint32(bitgen_state); } else { if (use_masked) { return off + - buffered_bounded_masked_uint32(brng_state, rng, mask, bcnt, buf); + buffered_bounded_masked_uint32(bitgen_state, rng, mask, bcnt, buf); } else { - return off + buffered_bounded_lemire_uint32(brng_state, rng, bcnt, buf); + return off + buffered_bounded_lemire_uint32(bitgen_state, rng, bcnt, buf); } } } @@ -1574,7 +1617,7 @@ uint32_t random_buffered_bounded_uint32(brng_t *brng_state, uint32_t off, * 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(brng_t *brng_state, uint16_t off, +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) { @@ -1582,13 +1625,13 @@ uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, return off; } else if (rng == 0xFFFFUL) { /* Lemire16 doesn't support inclusive rng = 0xFFFF. */ - return off + buffered_uint16(brng_state, bcnt, buf); + return off + buffered_uint16(bitgen_state, bcnt, buf); } else { if (use_masked) { return off + - buffered_bounded_masked_uint16(brng_state, rng, mask, bcnt, buf); + buffered_bounded_masked_uint16(bitgen_state, rng, mask, bcnt, buf); } else { - return off + buffered_bounded_lemire_uint16(brng_state, rng, bcnt, buf); + return off + buffered_bounded_lemire_uint16(bitgen_state, rng, bcnt, buf); } } } @@ -1597,7 +1640,7 @@ uint16_t random_buffered_bounded_uint16(brng_t *brng_state, uint16_t off, * 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(brng_t *brng_state, uint8_t off, +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) { @@ -1605,46 +1648,31 @@ uint8_t random_buffered_bounded_uint8(brng_t *brng_state, uint8_t off, return off; } else if (rng == 0xFFUL) { /* Lemire8 doesn't support inclusive rng = 0xFF. */ - return off + buffered_uint8(brng_state, bcnt, buf); + return off + buffered_uint8(bitgen_state, bcnt, buf); } else { if (use_masked) { return off + - buffered_bounded_masked_uint8(brng_state, rng, mask, bcnt, buf); + buffered_bounded_masked_uint8(bitgen_state, rng, mask, bcnt, buf); } else { - return off + buffered_bounded_lemire_uint8(brng_state, rng, bcnt, buf); + return off + buffered_bounded_lemire_uint8(bitgen_state, rng, bcnt, buf); } } } -static NPY_INLINE npy_bool buffered_bounded_bool(brng_t *brng_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(brng_state); - bcnt[0] = 31; - } else { - buf[0] >>= 1; - bcnt[0] -= 1; - } - return (buf[0] & 0x00000001UL) != 0; -} - -npy_bool random_buffered_bounded_bool(brng_t *brng_state, npy_bool off, +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(brng_state, off, rng, mask, bcnt, 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(brng_t *brng_state, uint64_t off, uint64_t rng, - npy_intp cnt, bool use_masked, uint64_t *out) { +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) { @@ -1661,19 +1689,19 @@ void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t rng, uint64_t mask = gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = off + buffered_bounded_masked_uint32(brng_state, rng, mask, + 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(brng_state, rng, &bcnt, &buf); + 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(brng_state); + out[i] = off + next_uint64(bitgen_state); } } else { if (use_masked) { @@ -1681,11 +1709,11 @@ void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t rng, uint64_t mask = gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = off + bounded_masked_uint64(brng_state, rng, mask); + out[i] = off + bounded_masked_uint64(bitgen_state, rng, mask); } } else { for (i = 0; i < cnt; i++) { - out[i] = off + bounded_lemire_uint64(brng_state, rng); + out[i] = off + bounded_lemire_uint64(bitgen_state, rng); } } } @@ -1695,8 +1723,9 @@ void random_bounded_uint64_fill(brng_t *brng_state, uint64_t off, uint64_t 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(brng_t *brng_state, uint32_t off, uint32_t rng, - npy_intp cnt, bool use_masked, uint32_t *out) { +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; @@ -1708,7 +1737,7 @@ void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, uint32_t rng, } else if (rng == 0xFFFFFFFFUL) { /* Lemire32 doesn't support rng = 0xFFFFFFFF. */ for (i = 0; i < cnt; i++) { - out[i] = off + next_uint32(brng_state); + out[i] = off + next_uint32(bitgen_state); } } else { if (use_masked) { @@ -1716,13 +1745,13 @@ void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, uint32_t rng, uint32_t mask = (uint32_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = off + buffered_bounded_masked_uint32(brng_state, rng, mask, + 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(brng_state, rng, &bcnt, &buf); + out[i] = off + + buffered_bounded_lemire_uint32(bitgen_state, rng, &bcnt, &buf); } } } @@ -1732,8 +1761,9 @@ void random_bounded_uint32_fill(brng_t *brng_state, uint32_t off, uint32_t rng, * 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(brng_t *brng_state, uint16_t off, uint16_t rng, - npy_intp cnt, bool use_masked, uint16_t *out) { +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; @@ -1745,7 +1775,7 @@ void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, } else if (rng == 0xFFFFUL) { /* Lemire16 doesn't support rng = 0xFFFF. */ for (i = 0; i < cnt; i++) { - out[i] = off + buffered_uint16(brng_state, &bcnt, &buf); + out[i] = off + buffered_uint16(bitgen_state, &bcnt, &buf); } } else { if (use_masked) { @@ -1753,13 +1783,13 @@ void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, uint16_t mask = (uint16_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = off + buffered_bounded_masked_uint16(brng_state, rng, mask, + 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(brng_state, rng, &bcnt, &buf); + out[i] = off + + buffered_bounded_lemire_uint16(bitgen_state, rng, &bcnt, &buf); } } } @@ -1769,7 +1799,7 @@ void random_bounded_uint16_fill(brng_t *brng_state, uint16_t off, uint16_t rng, * 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(brng_t *brng_state, uint8_t off, uint8_t rng, +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; @@ -1782,7 +1812,7 @@ void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, } else if (rng == 0xFFUL) { /* Lemire8 doesn't support rng = 0xFF. */ for (i = 0; i < cnt; i++) { - out[i] = off + buffered_uint8(brng_state, &bcnt, &buf); + out[i] = off + buffered_uint8(bitgen_state, &bcnt, &buf); } } else { if (use_masked) { @@ -1790,13 +1820,13 @@ void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, uint8_t mask = (uint8_t)gen_mask(rng); for (i = 0; i < cnt; i++) { - out[i] = off + buffered_bounded_masked_uint8(brng_state, rng, mask, + 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(brng_state, rng, &bcnt, &buf); + off + buffered_bounded_lemire_uint8(bitgen_state, rng, &bcnt, &buf); } } } @@ -1806,25 +1836,26 @@ void random_bounded_uint8_fill(brng_t *brng_state, uint8_t off, uint8_t rng, * Fills an array with cnt random npy_bool between off and off + rng * inclusive. */ -void random_bounded_bool_fill(brng_t *brng_state, npy_bool off, npy_bool rng, - npy_intp cnt, bool use_masked, npy_bool *out) { +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(brng_state, off, rng, mask, &bcnt, &buf); + out[i] = buffered_bounded_bool(bitgen_state, off, rng, mask, &bcnt, &buf); } } -void random_multinomial(brng_t *brng_state, int64_t n, int64_t *mnix, +void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix, double *pix, npy_intp d, binomial_t *binomial) { double remaining_p = 1.0; npy_intp j; int64_t dn = n; for (j = 0; j < (d - 1); j++) { - mnix[j] = random_binomial(brng_state, pix[j] / remaining_p, dn, binomial); + mnix[j] = random_binomial(bitgen_state, pix[j] / remaining_p, dn, binomial); dn = dn - mnix[j]; if (dn <= 0) { break; diff --git a/numpy/random/src/distributions/distributions.h b/numpy/random/src/distributions/distributions.h index 8ec4a83e8b3e..d1d439d78a63 100644 --- a/numpy/random/src/distributions/distributions.h +++ b/numpy/random/src/distributions/distributions.h @@ -3,20 +3,8 @@ #pragma once #include -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/stdint.h" -typedef int bool; -#define false 0 -#define true 1 -#else -#include -#include -#endif -#else #include #include -#endif #include "Python.h" #include "numpy/npy_common.h" @@ -72,152 +60,152 @@ typedef struct s_binomial_t { double p4; } binomial_t; -typedef struct brng { +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); -} brng_t; +} bitgen_t; /* Inline generators for internal use */ -static NPY_INLINE uint32_t next_uint32(brng_t *brng_state) { - return brng_state->next_uint32(brng_state->state); +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(brng_t *brng_state) { - return brng_state->next_uint64(brng_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(brng_t *brng_state) { - return (next_uint32(brng_state) >> 9) * (1.0f / 8388608.0f); +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(brng_t *brng_state) { - return brng_state->next_double(brng_state->state); +static NPY_INLINE double next_double(bitgen_t *bitgen_state) { + return bitgen_state->next_double(bitgen_state->state); } -DECLDIR float random_float(brng_t *brng_state); -DECLDIR double random_double(brng_t *brng_state); -DECLDIR void random_double_fill(brng_t *brng_state, npy_intp cnt, double *out); +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(brng_t *brng_state); -DECLDIR int32_t random_positive_int32(brng_t *brng_state); -DECLDIR int64_t random_positive_int(brng_t *brng_state); -DECLDIR uint64_t random_uint(brng_t *brng_state); +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(brng_t *brng_state); -DECLDIR void random_standard_exponential_fill(brng_t *brng_state, npy_intp cnt, +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(brng_t *brng_state); -DECLDIR double random_standard_exponential_zig(brng_t *brng_state); -DECLDIR void random_standard_exponential_zig_fill(brng_t *brng_state, +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(brng_t *brng_state); +DECLDIR float random_standard_exponential_zig_f(bitgen_t *bitgen_state); /* -DECLDIR double random_gauss(brng_t *brng_state); -DECLDIR float random_gauss_f(brng_t *brng_state); +DECLDIR double random_gauss(bitgen_t *bitgen_state); +DECLDIR float random_gauss_f(bitgen_t *bitgen_state); */ -DECLDIR double random_gauss_zig(brng_t *brng_state); -DECLDIR float random_gauss_zig_f(brng_t *brng_state); -DECLDIR void random_gauss_zig_fill(brng_t *brng_state, npy_intp cnt, +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(brng_t *brng_state, double shape); -DECLDIR float random_standard_gamma_f(brng_t *brng_state, float shape); +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(brng_t *brng_state, double shape); -DECLDIR float random_standard_gamma_zig_f(brng_t *brng_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(brng_t *brng_state, double loc, double scale); +DECLDIR double random_normal(bitgen_t *bitgen_state, double loc, double scale); */ -DECLDIR double random_normal_zig(brng_t *brng_state, double loc, double scale); - -DECLDIR double random_gamma(brng_t *brng_state, double shape, double scale); -DECLDIR float random_gamma_float(brng_t *brng_state, float shape, float scale); - -DECLDIR double random_exponential(brng_t *brng_state, double scale); -DECLDIR double random_uniform(brng_t *brng_state, double lower, double range); -DECLDIR double random_beta(brng_t *brng_state, double a, double b); -DECLDIR double random_chisquare(brng_t *brng_state, double df); -DECLDIR double random_f(brng_t *brng_state, double dfnum, double dfden); -DECLDIR double random_standard_cauchy(brng_t *brng_state); -DECLDIR double random_pareto(brng_t *brng_state, double a); -DECLDIR double random_weibull(brng_t *brng_state, double a); -DECLDIR double random_power(brng_t *brng_state, double a); -DECLDIR double random_laplace(brng_t *brng_state, double loc, double scale); -DECLDIR double random_gumbel(brng_t *brng_state, double loc, double scale); -DECLDIR double random_logistic(brng_t *brng_state, double loc, double scale); -DECLDIR double random_lognormal(brng_t *brng_state, double mean, double sigma); -DECLDIR double random_rayleigh(brng_t *brng_state, double mode); -DECLDIR double random_standard_t(brng_t *brng_state, double df); -DECLDIR double random_noncentral_chisquare(brng_t *brng_state, double df, +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(brng_t *brng_state, double dfnum, +DECLDIR double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden, double nonc); -DECLDIR double random_wald(brng_t *brng_state, double mean, double scale); -DECLDIR double random_vonmises(brng_t *brng_state, double mu, double kappa); -DECLDIR double random_triangular(brng_t *brng_state, double left, double mode, +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 int64_t random_poisson(brng_t *brng_state, double lam); -DECLDIR int64_t random_negative_binomial(brng_t *brng_state, double n, +DECLDIR int64_t random_poisson(bitgen_t *bitgen_state, double lam); +DECLDIR int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p); -DECLDIR int64_t random_binomial(brng_t *brng_state, double p, int64_t n, +DECLDIR int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial); -DECLDIR int64_t random_logseries(brng_t *brng_state, double p); -DECLDIR int64_t random_geometric_search(brng_t *brng_state, double p); -DECLDIR int64_t random_geometric_inversion(brng_t *brng_state, double p); -DECLDIR int64_t random_geometric(brng_t *brng_state, double p); -DECLDIR int64_t random_zipf(brng_t *brng_state, double a); -DECLDIR int64_t random_hypergeometric(brng_t *brng_state, int64_t good, +DECLDIR int64_t random_logseries(bitgen_t *bitgen_state, double p); +DECLDIR int64_t random_geometric_search(bitgen_t *bitgen_state, double p); +DECLDIR int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p); +DECLDIR int64_t random_geometric(bitgen_t *bitgen_state, double p); +DECLDIR int64_t 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(brng_t *brng_state, uint64_t max); +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(brng_t *brng_state, uint64_t off, +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(brng_t *brng_state, +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(brng_t *brng_state, +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(brng_t *brng_state, uint8_t off, +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(brng_t *brng_state, npy_bool off, +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(brng_t *brng_state, uint64_t off, +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(brng_t *brng_state, uint32_t off, +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(brng_t *brng_state, uint16_t off, +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(brng_t *brng_state, uint8_t off, +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(brng_t *brng_state, npy_bool off, +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(brng_t *brng_state, int64_t n, int64_t *mnix, +DECLDIR void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix, double *pix, npy_intp d, binomial_t *binomial); #endif diff --git a/numpy/random/src/entropy/LICENSE.md b/numpy/random/src/entropy/LICENSE.md deleted file mode 100644 index b7276aad786e..000000000000 --- a/numpy/random/src/entropy/LICENSE.md +++ /dev/null @@ -1,25 +0,0 @@ -# ENTROPY - -_Parts of this module were derived from PCG_ - - -PCG Random Number Generation for C. - -Copyright 2014 Melissa O'Neill - -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 diff --git a/numpy/random/src/entropy/entropy.c b/numpy/random/src/entropy/entropy.c index ead4bef835a3..eaca37a9ce5e 100644 --- a/numpy/random/src/entropy/entropy.c +++ b/numpy/random/src/entropy/entropy.c @@ -1,34 +1,3 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * 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 provides a mechanism for getting external randomness for - * seeding purposes. Usually, it's just a wrapper around reading - * /dev/random. - * - * Alas, because not every system provides /dev/random, we need a fallback. - * We also need to try to test whether or not to use the fallback. - */ - #include #include #include @@ -47,38 +16,12 @@ #include #include #include -#endif - -#ifndef IS_UNIX -#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \ - (defined(__APPLE__) && defined(__MACH__))) -#define IS_UNIX 1 -#else -#define IS_UNIX 0 -#endif -#endif - -// If HAVE_DEV_RANDOM is set, we use that value, otherwise we guess -#ifndef HAVE_DEV_RANDOM -#define HAVE_DEV_RANDOM IS_UNIX -#endif - -#if HAVE_DEV_RANDOM #include -#include #endif -#if HAVE_DEV_RANDOM -/* entropy_getbytes(dest, size): - * Use /dev/random to get some external entropy for seeding purposes. - * - * Note: - * If reading /dev/random fails (which ought to never happen), it returns - * false, otherwise it returns true. If it fails, you could instead call - * fallback_entropy_getbytes which always succeeds. - */ - bool entropy_getbytes(void *dest, size_t size) { +#ifndef _WIN32 + int fd = open("/dev/urandom", O_RDONLY); if (fd < 0) return false; @@ -86,11 +29,9 @@ bool entropy_getbytes(void *dest, size_t size) { if ((sz < 0) || ((size_t)sz < size)) return false; return close(fd) == 0; -} -#endif -#ifdef _WIN32 -bool entropy_getbytes(void *dest, size_t size) { +#else + HCRYPTPROV hCryptProv; BOOL done; @@ -106,8 +47,8 @@ bool entropy_getbytes(void *dest, size_t size) { } return true; -} #endif +} /* Thomas Wang 32/64 bits integer hash function */ uint32_t entropy_hash_32(uint32_t key) { @@ -155,7 +96,6 @@ uint32_t entropy_randombytes(void) { bool entropy_fallback_getbytes(void *dest, size_t size) { int hashes = (int)size; uint32_t *hash = malloc(hashes * sizeof(uint32_t)); - // uint32_t hash[hashes]; int i; for (i = 0; i < hashes; i++) { hash[i] = entropy_randombytes(); diff --git a/numpy/random/src/entropy/entropy.h b/numpy/random/src/entropy/entropy.h index 785603dd3d75..f00caf61d9d1 100644 --- a/numpy/random/src/entropy/entropy.h +++ b/numpy/random/src/entropy/entropy.h @@ -1,43 +1,9 @@ #ifndef _RANDOMDGEN__ENTROPY_H_ #define _RANDOMDGEN__ENTROPY_H_ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * 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 - */ #include -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/stdint.h" -typedef int bool; -#define false 0 -#define true 1 -#else #include #include -#endif -#else -#include -#include -#endif extern void entropy_fill(void *dest, size_t size); diff --git a/numpy/random/src/legacy/LICENSE.md b/numpy/random/src/legacy/LICENSE.md deleted file mode 100644 index 88b1791b200f..000000000000 --- a/numpy/random/src/legacy/LICENSE.md +++ /dev/null @@ -1,30 +0,0 @@ -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. diff --git a/numpy/random/src/legacy/distributions-boxmuller.c b/numpy/random/src/legacy/distributions-boxmuller.c index 5d3ba27f8218..2c715799f317 100644 --- a/numpy/random/src/legacy/distributions-boxmuller.c +++ b/numpy/random/src/legacy/distributions-boxmuller.c @@ -1,10 +1,10 @@ #include "distributions-boxmuller.h" -static NPY_INLINE double legacy_double(aug_brng_t *aug_state) { - return aug_state->basicrng->next_double(aug_state->basicrng->state); +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_brng_t *aug_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; @@ -28,12 +28,12 @@ double legacy_gauss(aug_brng_t *aug_state) { } } -double legacy_standard_exponential(aug_brng_t *aug_state) { +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_brng_t *aug_state, double shape) { +double legacy_standard_gamma(aug_bitgen_t *aug_state, double shape) { double b, c; double U, V, X, Y; @@ -78,30 +78,30 @@ double legacy_standard_gamma(aug_brng_t *aug_state, double shape) { } } -double legacy_gamma(aug_brng_t *aug_state, double shape, double scale) { +double legacy_gamma(aug_bitgen_t *aug_state, double shape, double scale) { return scale * legacy_standard_gamma(aug_state, shape); } -double legacy_pareto(aug_brng_t *aug_state, double a) { +double legacy_pareto(aug_bitgen_t *aug_state, double a) { return exp(legacy_standard_exponential(aug_state) / a) - 1; } -double legacy_weibull(aug_brng_t *aug_state, double a) { +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_brng_t *aug_state, double 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_brng_t *aug_state, double df) { +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_brng_t *aug_state, double df, +double legacy_noncentral_chisquare(aug_bitgen_t *aug_state, double df, double nonc) { double out; if (nonc == 0) { @@ -112,7 +112,7 @@ double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, const double n = legacy_gauss(aug_state) + sqrt(nonc); return Chi2 + n * n; } else { - const long i = random_poisson(aug_state->basicrng, nonc / 2.0); + 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)){ @@ -123,13 +123,13 @@ double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, } } -double legacy_noncentral_f(aug_brng_t *aug_state, double dfnum, double dfden, +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_brng_t *aug_state, double mean, double scale) { +double legacy_wald(aug_bitgen_t *aug_state, double mean, double scale) { double U, X, Y; double mu_2l; @@ -145,15 +145,15 @@ double legacy_wald(aug_brng_t *aug_state, double mean, double scale) { } } -double legacy_normal(aug_brng_t *aug_state, double loc, double scale) { +double legacy_normal(aug_bitgen_t *aug_state, double loc, double scale) { return loc + scale * legacy_gauss(aug_state); } -double legacy_lognormal(aug_brng_t *aug_state, double mean, double sigma) { +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_brng_t *aug_state, double df) { +double legacy_standard_t(aug_bitgen_t *aug_state, double df) { double num, denom; num = legacy_gauss(aug_state); @@ -161,16 +161,16 @@ double legacy_standard_t(aug_brng_t *aug_state, double df) { return sqrt(df / 2) * num / sqrt(denom); } -int64_t legacy_negative_binomial(aug_brng_t *aug_state, double n, double p) { +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 random_poisson(aug_state->basicrng, Y); + return random_poisson(aug_state->bit_generator, Y); } -double legacy_standard_cauchy(aug_brng_t *aug_state) { +double legacy_standard_cauchy(aug_bitgen_t *aug_state) { return legacy_gauss(aug_state) / legacy_gauss(aug_state); } -double legacy_beta(aug_brng_t *aug_state, double a, double b) { +double legacy_beta(aug_bitgen_t *aug_state, double a, double b) { double Ga, Gb; if ((a <= 1.0) && (b <= 1.0)) { @@ -204,11 +204,11 @@ double legacy_beta(aug_brng_t *aug_state, double a, double b) { } } -double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden) { +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_brng_t *aug_state, double scale) { +double legacy_exponential(aug_bitgen_t *aug_state, double scale) { return scale * legacy_standard_exponential(aug_state); } diff --git a/numpy/random/src/legacy/distributions-boxmuller.h b/numpy/random/src/legacy/distributions-boxmuller.h index 445686e6c85b..07e093b26c44 100644 --- a/numpy/random/src/legacy/distributions-boxmuller.h +++ b/numpy/random/src/legacy/distributions-boxmuller.h @@ -4,37 +4,37 @@ #include "../distributions/distributions.h" -typedef struct aug_brng { - brng_t *basicrng; +typedef struct aug_bitgen { + bitgen_t *bit_generator; int has_gauss; double gauss; -} aug_brng_t; +} aug_bitgen_t; -extern double legacy_gauss(aug_brng_t *aug_state); -extern double legacy_standard_exponential(aug_brng_t *aug_state); -extern double legacy_pareto(aug_brng_t *aug_state, double a); -extern double legacy_weibull(aug_brng_t *aug_state, double a); -extern double legacy_power(aug_brng_t *aug_state, double a); -extern double legacy_gamma(aug_brng_t *aug_state, double shape, double scale); -extern double legacy_pareto(aug_brng_t *aug_state, double a); -extern double legacy_weibull(aug_brng_t *aug_state, double a); -extern double legacy_chisquare(aug_brng_t *aug_state, double df); -extern double legacy_noncentral_chisquare(aug_brng_t *aug_state, double df, +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_brng_t *aug_state, double dfnum, +extern double legacy_noncentral_f(aug_bitgen_t *aug_state, double dfnum, double dfden, double nonc); -extern double legacy_wald(aug_brng_t *aug_state, double mean, double scale); -extern double legacy_lognormal(aug_brng_t *aug_state, double mean, +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_brng_t *aug_state, double df); -extern int64_t legacy_negative_binomial(aug_brng_t *aug_state, double n, +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_brng_t *state); -extern double legacy_beta(aug_brng_t *aug_state, double a, double b); -extern double legacy_f(aug_brng_t *aug_state, double dfnum, double dfden); -extern double legacy_normal(aug_brng_t *aug_state, double loc, double scale); -extern double legacy_standard_gamma(aug_brng_t *aug_state, double shape); -extern double legacy_exponential(aug_brng_t *aug_state, double scale); +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); #endif diff --git a/numpy/random/src/mt19937/mt19937.h b/numpy/random/src/mt19937/mt19937.h index 8105329ece6b..1b39e0b6434c 100644 --- a/numpy/random/src/mt19937/mt19937.h +++ b/numpy/random/src/mt19937/mt19937.h @@ -1,14 +1,6 @@ #pragma once #include -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/stdint.h" -#else -#include -#endif -#else #include -#endif #ifdef _WIN32 #define inline __forceinline diff --git a/numpy/random/src/pcg32/LICENSE.md b/numpy/random/src/pcg32/LICENSE.md deleted file mode 100644 index 3db2ac2e8e78..000000000000 --- a/numpy/random/src/pcg32/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -# PCG32 - -PCG Random Number Generation for C. - -Copyright 2014 Melissa O'Neill - -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 diff --git a/numpy/random/src/pcg32/pcg-advance-64.c b/numpy/random/src/pcg32/pcg-advance-64.c deleted file mode 100644 index 8210e75650eb..000000000000 --- a/numpy/random/src/pcg32/pcg-advance-64.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * 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. - * - * Repetative C code is derived using C preprocessor metaprogramming - * techniques. - */ - -#include "pcg_variants.h" - -/* 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". - */ - -uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, - uint64_t cur_plus) -{ - uint64_t acc_mult = 1u; - uint64_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; -} - diff --git a/numpy/random/src/pcg32/pcg32-test-data-gen.c b/numpy/random/src/pcg32/pcg32-test-data-gen.c deleted file mode 100644 index cccaf84b9948..000000000000 --- a/numpy/random/src/pcg32/pcg32-test-data-gen.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Generate testing csv files - * - * - * gcc pcg32-test-data-gen.c pcg32.orig.c ../splitmix64/splitmix64.c -o - * pgc64-test-data-gen - */ - -#include "pcg_variants.h" -#include -#include - -#define N 1000 - -int main() { - pcg32_random_t rng; - uint64_t inc, seed = 0xDEADBEAF; - inc = 0; - int i; - uint64_t store[N]; - pcg32_srandom_r(&rng, seed, inc); - for (i = 0; i < N; i++) { - store[i] = pcg32_random_r(&rng); - } - - FILE *fp; - fp = fopen("pcg32-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); - - seed = 0; - pcg32_srandom_r(&rng, seed, inc); - for (i = 0; i < N; i++) { - store[i] = pcg32_random_r(&rng); - } - fp = fopen("pcg32-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/pcg32/pcg32.c b/numpy/random/src/pcg32/pcg32.c deleted file mode 100644 index 5fbf6759f1a3..000000000000 --- a/numpy/random/src/pcg32/pcg32.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "pcg32.h" - -extern inline uint64_t pcg32_next64(pcg32_state *state); -extern inline uint32_t pcg32_next32(pcg32_state *state); -extern inline double pcg32_next_double(pcg32_state *state); - -uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, - uint64_t cur_plus) { - uint64_t acc_mult, acc_plus; - acc_mult = 1u; - 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; -} - -extern void pcg32_advance_state(pcg32_state *state, uint64_t step) { - pcg32_advance_r(state->pcg_state, step); -} - -extern void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) { - pcg32_srandom_r(state->pcg_state, seed, inc); -} diff --git a/numpy/random/src/pcg32/pcg32.h b/numpy/random/src/pcg32/pcg32.h deleted file mode 100644 index 557113d8f6af..000000000000 --- a/numpy/random/src/pcg32/pcg32.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef _RANDOMDGEN__PCG32_H_ -#define _RANDOMDGEN__PCG32_H_ - -#ifdef _WIN32 -#ifndef _INTTYPES -#include "../common/stdint.h" -#endif -#define inline __inline __forceinline -#else -#include -#endif - -#define PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL - -struct pcg_state_setseq_64 { - uint64_t state; - uint64_t inc; -}; - -static 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 -} - -static inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) { - rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc; -} - -static inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { - return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u); -} - -static inline uint32_t -pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) { - uint64_t oldstate; - oldstate = rng->state; - pcg_setseq_64_step_r(rng); - return pcg_output_xsh_rr_64_32(oldstate); -} - -static 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); -} - -extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, - uint64_t cur_mult, uint64_t cur_plus); - -static 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); -} - -typedef struct pcg_state_setseq_64 pcg32_random_t; -#define pcg32_random_r pcg_setseq_64_xsh_rr_32_random_r -#define pcg32_srandom_r pcg_setseq_64_srandom_r -#define pcg32_advance_r pcg_setseq_64_advance_r - -typedef struct s_pcg32_state { pcg32_random_t *pcg_state; } pcg32_state; - -static inline uint64_t pcg32_next64(pcg32_state *state) { - return (uint64_t)(pcg32_random_r(state->pcg_state)) << 32 | - pcg32_random_r(state->pcg_state); -} - -static inline uint32_t pcg32_next32(pcg32_state *state) { - return pcg32_random_r(state->pcg_state); -} - -static inline double pcg32_next_double(pcg32_state *state) { - int32_t a = pcg32_random_r(state->pcg_state) >> 5, - b = pcg32_random_r(state->pcg_state) >> 6; - return (a * 67108864.0 + b) / 9007199254740992.0; -} - -void pcg32_advance_state(pcg32_state *state, uint64_t step); -void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc); - -#endif diff --git a/numpy/random/src/pcg32/pcg_variants.h b/numpy/random/src/pcg32/pcg_variants.h deleted file mode 100644 index 32daac1ce4f5..000000000000 --- a/numpy/random/src/pcg32/pcg_variants.h +++ /dev/null @@ -1,2210 +0,0 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * 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 - -#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/pcg64/LICENSE.md b/numpy/random/src/pcg64/LICENSE.md deleted file mode 100644 index dd6a17ee8a86..000000000000 --- a/numpy/random/src/pcg64/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -# PCG64 - -PCG Random Number Generation for C. - -Copyright 2014 Melissa O'Neill - -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 diff --git a/numpy/random/src/pcg64/pcg64-benchmark.c b/numpy/random/src/pcg64/pcg64-benchmark.c deleted file mode 100644 index 76f3ec78c300..000000000000 --- a/numpy/random/src/pcg64/pcg64-benchmark.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 -#include -#include - -#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 deleted file mode 100644 index 0c2b079a3e15..000000000000 --- a/numpy/random/src/pcg64/pcg64-test-data-gen.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 -#include - -#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 deleted file mode 100644 index faec0c248b60..000000000000 --- a/numpy/random/src/pcg64/pcg64.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * PCG64 Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * Copyright 2015 Robert Kern - * - * 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 - */ - -#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; -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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; -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 - * - */ -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 - * - */ -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 deleted file mode 100644 index e42dc4d63e70..000000000000 --- a/numpy/random/src/pcg64/pcg64.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * PCG64 Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * Copyright 2015 Robert Kern - * - * 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 - */ - -#ifndef PCG64_H_INCLUDED -#define PCG64_H_INCLUDED 1 - -#ifdef _WIN32 -#ifndef _INTTYPES -#include "../common/stdint.h" -#endif -#define inline __inline __forceinline -#else -#include -#if _MSC_VER >= 1900 && _M_AMD64 -#include -#pragma intrinsic(_umul128) -#endif -#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 __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_128 \ - PCG_128BIT_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) -#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) { - return (value >> rot) | (value << ((-rot) & 63)); -} - -#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 & 0x800000000000ULL; - 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); -} - -#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 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_random_r(pcg_state_setseq_128 *rng) { - pcg_setseq_128_step_r(rng); - return pcg_output_xsl_rr_128_64(rng->state); -} - -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 deleted file mode 100644 index 07e97e4b6d97..000000000000 --- a/numpy/random/src/pcg64/pcg64.orig.c +++ /dev/null @@ -1,11 +0,0 @@ -#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 deleted file mode 100644 index 74be91f31a50..000000000000 --- a/numpy/random/src/pcg64/pcg64.orig.h +++ /dev/null @@ -1,2025 +0,0 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * 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 - -#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/philox.c b/numpy/random/src/philox/philox.c index 3382c60d6acf..6f2fad5a4384 100644 --- a/numpy/random/src/philox/philox.c +++ b/numpy/random/src/philox/philox.c @@ -1,8 +1,8 @@ #include "philox.h" -extern INLINE uint64_t philox_next64(philox_state *state); +extern NPY_INLINE uint64_t philox_next64(philox_state *state); -extern INLINE uint32_t philox_next32(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 */ diff --git a/numpy/random/src/philox/philox.h b/numpy/random/src/philox/philox.h index 411404b55787..ae6cf9308095 100644 --- a/numpy/random/src/philox/philox.h +++ b/numpy/random/src/philox/philox.h @@ -2,12 +2,7 @@ #define _RANDOMDGEN__PHILOX_H_ #include - -#ifdef _WIN32 -#define INLINE __inline __forceinline -#else -#define INLINE inline -#endif +#include "numpy/npy_common.h" #define PHILOX_BUFFER_SIZE 4L @@ -23,7 +18,7 @@ typedef struct r123array4x64 philox4x64_ctr_t; typedef struct r123array2x64 philox4x64_key_t; typedef struct r123array2x64 philox4x64_ukey_t; -static INLINE struct r123array2x64 +static NPY_INLINE struct r123array2x64 _philox4x64bumpkey(struct r123array2x64 key) { key.v[0] += (0x9E3779B97F4A7C15ULL); key.v[1] += (0xBB67AE8584CAA73BULL); @@ -37,7 +32,7 @@ _philox4x64bumpkey(struct r123array2x64 key) { #pragma intrinsic(_umul128) #else #pragma intrinsic(__emulu) -static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { +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; @@ -60,18 +55,18 @@ static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { return a_x_b_lo + ((a_x_b_mid + b_x_a_mid) << 32); } #endif -static INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { +static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } #else #if __SIZEOF_INT128__ -static INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { +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 -static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { +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; @@ -93,16 +88,16 @@ static INLINE uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { return a_x_b_lo + ((a_x_b_mid + b_x_a_mid) << 32); } -static INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { +static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } #endif #endif -static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, +static NPY_INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key); -static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, +static NPY_INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, struct r123array2x64 key) { uint64_t hi0; uint64_t hi1; @@ -113,14 +108,14 @@ static INLINE struct r123array4x64 _philox4x64round(struct r123array4x64 ctr, return out; } -static INLINE philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { +static NPY_INLINE philox4x64_key_t philox4x64keyinit(philox4x64_ukey_t uk) { return uk; } -static INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, +static NPY_INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, philox4x64_ctr_t ctr, philox4x64_key_t key); -static INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, +static NPY_INLINE philox4x64_ctr_t philox4x64_R(unsigned int R, philox4x64_ctr_t ctr, philox4x64_key_t key) { if (R > 0) { @@ -198,7 +193,7 @@ typedef struct s_philox_state { uint32_t uinteger; } philox_state; -static INLINE uint64_t philox_next(philox_state *state) { +static NPY_INLINE uint64_t philox_next(philox_state *state) { uint64_t out; int i; philox4x64_ctr_t ct; @@ -228,11 +223,11 @@ static INLINE uint64_t philox_next(philox_state *state) { return state->buffer[0]; } -static INLINE uint64_t philox_next64(philox_state *state) { +static NPY_INLINE uint64_t philox_next64(philox_state *state) { return philox_next(state); } -static INLINE uint32_t philox_next32(philox_state *state) { +static NPY_INLINE uint32_t philox_next32(philox_state *state) { uint64_t next; if (state->has_uint32) { diff --git a/numpy/random/src/splitmix64/splitmix64.h b/numpy/random/src/splitmix64/splitmix64.h index 880132970744..d5877905ea1a 100644 --- a/numpy/random/src/splitmix64/splitmix64.h +++ b/numpy/random/src/splitmix64/splitmix64.h @@ -1,13 +1,4 @@ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define inline __forceinline -#else #include -#endif -#else -#include -#endif typedef struct s_splitmix64_state { uint64_t state; diff --git a/numpy/random/src/threefry/threefry.c b/numpy/random/src/threefry/threefry.c index 19c37df1bf93..55d3c022a32d 100644 --- a/numpy/random/src/threefry/threefry.c +++ b/numpy/random/src/threefry/threefry.c @@ -1,8 +1,8 @@ #include "threefry.h" -extern INLINE uint64_t threefry_next64(threefry_state *state); +extern NPY_INLINE uint64_t threefry_next64(threefry_state *state); -extern INLINE uint32_t threefry_next32(threefry_state *state); +extern NPY_INLINE uint32_t threefry_next32(threefry_state *state); extern void threefry_jump(threefry_state *state) { /* Advances state as-if 2^128 draws were made */ diff --git a/numpy/random/src/threefry/threefry.h b/numpy/random/src/threefry/threefry.h index 297c1241a698..596b57e125ed 100644 --- a/numpy/random/src/threefry/threefry.h +++ b/numpy/random/src/threefry/threefry.h @@ -4,18 +4,8 @@ Adapted from random123's threefry.h #ifndef _RANDOMDGEN__THREEFRY_H_ #define _RANDOMDGEN__THREEFRY_H_ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else #include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif +#include "numpy/npy_common.h" #define THREEFRY_BUFFER_SIZE 4L @@ -47,15 +37,15 @@ struct r123array4x64 { typedef struct r123array4x64 threefry4x64_key_t; typedef struct r123array4x64 threefry4x64_ctr_t; -static INLINE uint64_t RotL_64(uint64_t x, unsigned int N); -static INLINE uint64_t RotL_64(uint64_t x, unsigned int N) { +static NPY_INLINE uint64_t RotL_64(uint64_t x, unsigned int N); +static NPY_INLINE uint64_t RotL_64(uint64_t x, unsigned int N) { return (x << (N & 63)) | (x >> ((64 - N) & 63)); } -static INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, +static NPY_INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k); -static INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, +static NPY_INLINE threefry4x64_ctr_t threefry4x64_R(unsigned int Nrounds, threefry4x64_ctr_t in, threefry4x64_key_t k) { threefry4x64_ctr_t X; @@ -288,7 +278,7 @@ typedef struct s_threefry_state { uint32_t uinteger; } threefry_state; -static INLINE uint64_t threefry_next(threefry_state *state) { +static NPY_INLINE uint64_t threefry_next(threefry_state *state) { int i; threefry4x64_ctr_t ct; uint64_t out; @@ -317,11 +307,11 @@ static INLINE uint64_t threefry_next(threefry_state *state) { return state->buffer[0]; } -static INLINE uint64_t threefry_next64(threefry_state *state) { +static NPY_INLINE uint64_t threefry_next64(threefry_state *state) { return threefry_next(state); } -static INLINE uint32_t threefry_next32(threefry_state *state) { +static NPY_INLINE uint32_t threefry_next32(threefry_state *state) { uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; diff --git a/numpy/random/src/threefry32/threefry32.c b/numpy/random/src/threefry32/threefry32.c index 500e9482d906..cc6890f2eeab 100644 --- a/numpy/random/src/threefry32/threefry32.c +++ b/numpy/random/src/threefry32/threefry32.c @@ -1,8 +1,8 @@ #include "threefry32.h" -extern INLINE uint64_t threefry32_next64(threefry32_state *state); +extern NPY_INLINE uint64_t threefry32_next64(threefry32_state *state); -extern INLINE uint32_t threefry32_next32(threefry32_state *state); +extern NPY_INLINE uint32_t threefry32_next32(threefry32_state *state); extern void threefry32_jump(threefry32_state *state) { /* Advances state as-if 2^64 draws were made */ diff --git a/numpy/random/src/threefry32/threefry32.h b/numpy/random/src/threefry32/threefry32.h index 74a85c42b453..ebedee8043a0 100644 --- a/numpy/random/src/threefry32/threefry32.h +++ b/numpy/random/src/threefry32/threefry32.h @@ -4,23 +4,13 @@ Adapted from random123's threefry.h #ifndef _RANDOMDGEN__THREEFRY32_H_ #define _RANDOMDGEN__THREEFRY32_H_ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else #include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif +#include "numpy/npy_common.h" #define THREEFRY_BUFFER_SIZE 4L -static INLINE uint32_t RotL_32(uint32_t x, unsigned int N); -static INLINE uint32_t RotL_32(uint32_t x, unsigned int N) { +static NPY_INLINE uint32_t RotL_32(uint32_t x, unsigned int N); +static NPY_INLINE uint32_t RotL_32(uint32_t x, unsigned int N) { return (x << (N & 31)) | (x >> ((32 - N) & 31)); } @@ -52,13 +42,13 @@ enum r123_enum_threefry32x4 { typedef struct r123array4x32 threefry4x32_ctr_t; typedef struct r123array4x32 threefry4x32_key_t; typedef struct r123array4x32 threefry4x32_ukey_t; -static INLINE threefry4x32_key_t threefry4x32keyinit(threefry4x32_ukey_t uk) { +static NPY_INLINE threefry4x32_key_t threefry4x32keyinit(threefry4x32_ukey_t uk) { return uk; }; -static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, +static NPY_INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in, threefry4x32_key_t k); -static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, +static NPY_INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, threefry4x32_ctr_t in, threefry4x32_key_t k) { threefry4x32_ctr_t X; @@ -779,9 +769,9 @@ static INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, return X; } enum r123_enum_threefry4x32 { threefry4x32_rounds = 20 }; -static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, +static NPY_INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, threefry4x32_key_t k); -static INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, +static NPY_INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, threefry4x32_key_t k) { return threefry4x32_R(threefry4x32_rounds, in, k); } @@ -793,7 +783,7 @@ typedef struct s_threefry32_state { uint32_t buffer[THREEFRY_BUFFER_SIZE]; } threefry32_state; -static INLINE uint32_t threefry32_next(threefry32_state *state) { +static NPY_INLINE uint32_t threefry32_next(threefry32_state *state) { int i; threefry4x32_ctr_t ct; uint32_t out; @@ -822,15 +812,15 @@ static INLINE uint32_t threefry32_next(threefry32_state *state) { return state->buffer[0]; } -static INLINE uint64_t threefry32_next64(threefry32_state *state) { +static NPY_INLINE uint64_t threefry32_next64(threefry32_state *state) { return ((uint64_t)threefry32_next(state) << 32) | threefry32_next(state); } -static INLINE uint32_t threefry32_next32(threefry32_state *state) { +static NPY_INLINE uint32_t threefry32_next32(threefry32_state *state) { return threefry32_next(state); } -static INLINE double threefry32_next_double(threefry32_state *state) { +static NPY_INLINE double threefry32_next_double(threefry32_state *state) { int32_t a = threefry32_next(state) >> 5, b = threefry32_next(state) >> 6; return (a * 67108864.0 + b) / 9007199254740992.0; } diff --git a/numpy/random/src/xoroshiro128/xoroshiro128.c b/numpy/random/src/xoroshiro128/xoroshiro128.c index 060eb8a518c1..baefcf3a8b19 100644 --- a/numpy/random/src/xoroshiro128/xoroshiro128.c +++ b/numpy/random/src/xoroshiro128/xoroshiro128.c @@ -31,9 +31,9 @@ See . */ #include "xoroshiro128.h" -extern INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); +extern NPY_INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); -extern INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); +extern NPY_INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); void xoroshiro128_jump(xoroshiro128_state *state) { diff --git a/numpy/random/src/xoroshiro128/xoroshiro128.h b/numpy/random/src/xoroshiro128/xoroshiro128.h index 0db82b173839..63682776bfd9 100644 --- a/numpy/random/src/xoroshiro128/xoroshiro128.h +++ b/numpy/random/src/xoroshiro128/xoroshiro128.h @@ -1,18 +1,8 @@ #ifndef _RANDOMDGEN__XOROSHIRO128_H_ #define _RANDOMDGEN__XOROSHIRO128_H_ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else #include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif +#include "numpy/npy_common.h" typedef struct s_xoroshiro128_state { @@ -21,12 +11,12 @@ typedef struct s_xoroshiro128_state uint32_t uinteger; } xoroshiro128_state; -static INLINE uint64_t rotl(const uint64_t x, int k) +static NPY_INLINE uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -static INLINE uint64_t xoroshiro128_next(uint64_t *s) +static NPY_INLINE uint64_t xoroshiro128_next(uint64_t *s) { const uint64_t s0 = s[0]; uint64_t s1 = s[1]; @@ -39,12 +29,12 @@ static INLINE uint64_t xoroshiro128_next(uint64_t *s) return result; } -static INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) +static NPY_INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) { return xoroshiro128_next(&state->s[0]); } -static INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) +static NPY_INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) { uint64_t next; if (state->has_uint32) diff --git a/numpy/random/src/xorshift1024/xorshift1024.c b/numpy/random/src/xorshift1024/xorshift1024.c index 8737b5a82ae4..d68ecc7d3a45 100644 --- a/numpy/random/src/xorshift1024/xorshift1024.c +++ b/numpy/random/src/xorshift1024/xorshift1024.c @@ -4,9 +4,9 @@ to 2^512 calls to next(); it can be used to generate 2^512 non-overlapping subsequences for parallel computations. */ -extern INLINE uint64_t xorshift1024_next(xorshift1024_state *state); -extern INLINE uint64_t xorshift1024_next64(xorshift1024_state *state); -extern INLINE uint32_t xorshift1024_next32(xorshift1024_state *state); +extern NPY_INLINE uint64_t xorshift1024_next(xorshift1024_state *state); +extern NPY_INLINE uint64_t xorshift1024_next64(xorshift1024_state *state); +extern NPY_INLINE uint32_t xorshift1024_next32(xorshift1024_state *state); void xorshift1024_jump(xorshift1024_state *state) { int i, j, b; diff --git a/numpy/random/src/xorshift1024/xorshift1024.h b/numpy/random/src/xorshift1024/xorshift1024.h index e0ef7782652f..38ec27430199 100644 --- a/numpy/random/src/xorshift1024/xorshift1024.h +++ b/numpy/random/src/xorshift1024/xorshift1024.h @@ -1,18 +1,8 @@ #ifndef _RANDOMDGEN__XORSHIFT1024_H_ #define _RANDOMDGEN__XORSHIFT1024_H_ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else #include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif +#include "numpy/npy_common.h" typedef struct s_xorshift1024_state { uint64_t s[16]; @@ -21,7 +11,7 @@ typedef struct s_xorshift1024_state { uint32_t uinteger; } xorshift1024_state; -static INLINE uint64_t xorshift1024_next(xorshift1024_state *state) { +static NPY_INLINE uint64_t xorshift1024_next(xorshift1024_state *state) { const uint64_t s0 = state->s[state->p]; uint64_t s1 = state->s[state->p = ((state->p) + 1) & 15]; s1 ^= s1 << 31; // a @@ -29,11 +19,11 @@ static INLINE uint64_t xorshift1024_next(xorshift1024_state *state) { return state->s[state->p] * 0x9e3779b97f4a7c13; } -static INLINE uint64_t xorshift1024_next64(xorshift1024_state *state) { +static NPY_INLINE uint64_t xorshift1024_next64(xorshift1024_state *state) { return xorshift1024_next(state); } -static INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { +static NPY_INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { uint64_t next; if (state->has_uint32) { state->has_uint32 = 0; diff --git a/numpy/random/src/xoshiro256starstar/LICENSE.md b/numpy/random/src/xoshiro256/LICENSE.md similarity index 100% rename from numpy/random/src/xoshiro256starstar/LICENSE.md rename to numpy/random/src/xoshiro256/LICENSE.md diff --git a/numpy/random/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c b/numpy/random/src/xoshiro256/xoshiro256-test-data-gen.c similarity index 74% rename from numpy/random/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c rename to numpy/random/src/xoshiro256/xoshiro256-test-data-gen.c index 8522229ddd89..94eeb734663d 100644 --- a/numpy/random/src/xoshiro256starstar/xoshiro256starstar-test-data-gen.c +++ b/numpy/random/src/xoshiro256/xoshiro256-test-data-gen.c @@ -1,13 +1,13 @@ /* * Generate testing csv files * - * cl xoshiro256starstar-test-data-gen.c xoshiro256starstar.orig.c / + * cl xoshiro256-test-data-gen.c xoshiro256.orig.c / * ../splitmix64/splitmix64.c /Ox - * xoshiro256starstar-test-data-gen.exe * + * xoshiro256-test-data-gen.exe * * - * gcc xoshiro256starstar-test-data-gen.c xoshiro256starstar.orig.c / - * ../splitmix64/splitmix64.c -o xoshiro256starstar-test-data-gen - * ./xoshiro256starstar-test-data-gen + * gcc xoshiro256-test-data-gen.c xoshiro256.orig.c / + * ../splitmix64/splitmix64.c -o xoshiro256-test-data-gen + * ./xoshiro256-test-data-gen * * Requres the Random123 directory containing header files to be located in the * same directory (not included). @@ -15,7 +15,7 @@ */ #include "../splitmix64/splitmix64.h" -#include "xoshiro256starstar.orig.h" +#include "xoshiro256.orig.h" #include #include @@ -35,7 +35,7 @@ int main() { } FILE *fp; - fp = fopen("xoshiro256starstar-testset-1.csv", "w"); + fp = fopen("xoshiro256-testset-1.csv", "w"); if (fp == NULL) { printf("Couldn't open file\n"); return -1; @@ -56,7 +56,7 @@ int main() { for (i = 0; i < N; i++) { store[i] = next(); } - fp = fopen("xoshiro256starstar-testset-2.csv", "w"); + fp = fopen("xoshiro256-testset-2.csv", "w"); if (fp == NULL) { printf("Couldn't open file\n"); return -1; diff --git a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.c b/numpy/random/src/xoshiro256/xoshiro256.c similarity index 83% rename from numpy/random/src/xoshiro256starstar/xoshiro256starstar.c rename to numpy/random/src/xoshiro256/xoshiro256.c index 30b6c7d85aef..f5cda27214d0 100644 --- a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.c +++ b/numpy/random/src/xoshiro256/xoshiro256.c @@ -6,7 +6,7 @@ worldwide. This software is distributed without any warranty. See . */ -#include "xoshiro256starstar.h" +#include "xoshiro256.h" /* This is xoshiro256** 1.0, our all-purpose, rock-solid generator. It has excellent (sub-ns) speed, a state (256 bits) that is large enough for @@ -18,15 +18,16 @@ See . */ a 64-bit seed, we suggest to seed a splitmix64 generator and use its output to fill s. */ -extern INLINE uint64_t xoshiro256starstar_next64(xoshiro256starstar_state *state); +extern NPY_INLINE uint64_t xoshiro256_next64(xoshiro256_state *state); + +extern NPY_INLINE uint32_t xoshiro256_next32(xoshiro256_state *state); -extern INLINE uint32_t xoshiro256starstar_next32(xoshiro256starstar_state *state); /* This is the jump function for the generator. It is equivalent to 2^128 calls to next(); it can be used to generate 2^128 non-overlapping subsequences for parallel computations. */ -void xoshiro256starstar_jump(xoshiro256starstar_state *state) +void xoshiro256_jump(xoshiro256_state *state) { int i, b; static const uint64_t JUMP[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c}; @@ -45,7 +46,7 @@ void xoshiro256starstar_jump(xoshiro256starstar_state *state) s2 ^= state->s[2]; s3 ^= state->s[3]; } - xoshiro256starstar_next(&state->s[0]); + xoshiro256_next(&state->s[0]); } state->s[0] = s0; diff --git a/numpy/random/src/xoshiro256/xoshiro256.h b/numpy/random/src/xoshiro256/xoshiro256.h new file mode 100644 index 000000000000..1908245a5df2 --- /dev/null +++ b/numpy/random/src/xoshiro256/xoshiro256.h @@ -0,0 +1,53 @@ +#ifndef _RANDOMDGEN__XOSHIRO256STARSTAR_H_ +#define _RANDOMDGEN__XOSHIRO256STARSTAR_H_ + +#include +#include "numpy/npy_common.h" + +typedef struct s_xoshiro256_state { + uint64_t s[4]; + int has_uint32; + uint32_t uinteger; +} xoshiro256_state; + +static NPY_INLINE uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +static NPY_INLINE uint64_t xoshiro256_next(uint64_t *s) { + const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; + const uint64_t t = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + + s[3] = rotl(s[3], 45); + + return result_starstar; +} + + +static NPY_INLINE uint64_t xoshiro256_next64(xoshiro256_state *state) { + return xoshiro256_next(&state->s[0]); +} + +static NPY_INLINE uint32_t xoshiro256_next32(xoshiro256_state *state) { + + uint64_t next; + if (state->has_uint32) { + state->has_uint32 = 0; + return state->uinteger; + } + next = xoshiro256_next(&state->s[0]); + state->has_uint32 = 1; + state->uinteger = (uint32_t)(next >> 32); + return (uint32_t)(next & 0xffffffff); +} + +void xoshiro256_jump(xoshiro256_state *state); + +#endif diff --git a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.c b/numpy/random/src/xoshiro256/xoshiro256.orig.c similarity index 100% rename from numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.c rename to numpy/random/src/xoshiro256/xoshiro256.orig.c diff --git a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.h b/numpy/random/src/xoshiro256/xoshiro256.orig.h similarity index 100% rename from numpy/random/src/xoshiro256starstar/xoshiro256starstar.orig.h rename to numpy/random/src/xoshiro256/xoshiro256.orig.h diff --git a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.h b/numpy/random/src/xoshiro256starstar/xoshiro256starstar.h deleted file mode 100644 index 1d7d8ea40485..000000000000 --- a/numpy/random/src/xoshiro256starstar/xoshiro256starstar.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _RANDOMDGEN__XOSHIRO256STARSTAR_H_ -#define _RANDOMDGEN__XOSHIRO256STARSTAR_H_ - -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else -#include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif - -typedef struct s_xoshiro256starstar_state { - uint64_t s[4]; - int has_uint32; - uint32_t uinteger; -} xoshiro256starstar_state; - -static INLINE uint64_t rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); -} - -static INLINE uint64_t xoshiro256starstar_next(uint64_t *s) { - const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; - const uint64_t t = s[1] << 17; - - s[2] ^= s[0]; - s[3] ^= s[1]; - s[1] ^= s[2]; - s[0] ^= s[3]; - - s[2] ^= t; - - s[3] = rotl(s[3], 45); - - return result_starstar; -} - -static INLINE uint64_t -xoshiro256starstar_next64(xoshiro256starstar_state *state) { - return xoshiro256starstar_next(&state->s[0]); -} - -static INLINE uint32_t -xoshiro256starstar_next32(xoshiro256starstar_state *state) { - uint64_t next; - if (state->has_uint32) { - state->has_uint32 = 0; - return state->uinteger; - } - next = xoshiro256starstar_next(&state->s[0]); - state->has_uint32 = 1; - state->uinteger = (uint32_t)(next >> 32); - return (uint32_t)(next & 0xffffffff); -} - -void xoshiro256starstar_jump(xoshiro256starstar_state *state); - -#endif diff --git a/numpy/random/src/xoshiro512starstar/LICENSE.md b/numpy/random/src/xoshiro512/LICENSE.md similarity index 100% rename from numpy/random/src/xoshiro512starstar/LICENSE.md rename to numpy/random/src/xoshiro512/LICENSE.md diff --git a/numpy/random/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c b/numpy/random/src/xoshiro512/xoshiro512-test-data-gen.c similarity index 74% rename from numpy/random/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c rename to numpy/random/src/xoshiro512/xoshiro512-test-data-gen.c index bcc3574e4a6c..83e164a51325 100644 --- a/numpy/random/src/xoshiro512starstar/xoshiro512starstar-test-data-gen.c +++ b/numpy/random/src/xoshiro512/xoshiro512-test-data-gen.c @@ -1,13 +1,13 @@ /* * Generate testing csv files * - * cl xoshiro512starstar-test-data-gen.c xoshiro512starstar.orig.c / + * cl xoshiro512-test-data-gen.c xoshiro512.orig.c / * ../splitmix64/splitmix64.c /Ox - * xoshiro512starstar-test-data-gen.exe * + * xoshiro512-test-data-gen.exe * * - * gcc xoshiro512starstar-test-data-gen.c xoshiro512starstar.orig.c / - * ../splitmix64/splitmix64.c -o xoshiro512starstar-test-data-gen - * ./xoshiro512starstar-test-data-gen + * gcc xoshiro512-test-data-gen.c xoshiro512.orig.c / + * ../splitmix64/splitmix64.c -o xoshiro512-test-data-gen + * ./xoshiro512-test-data-gen * * Requres the Random123 directory containing header files to be located in the * same directory (not included). @@ -15,7 +15,7 @@ */ #include "../splitmix64/splitmix64.h" -#include "xoshiro512starstar.orig.h" +#include "xoshiro512.orig.h" #include #include @@ -35,7 +35,7 @@ int main() { } FILE *fp; - fp = fopen("xoshiro512starstar-testset-1.csv", "w"); + fp = fopen("xoshiro512-testset-1.csv", "w"); if (fp == NULL) { printf("Couldn't open file\n"); return -1; @@ -56,7 +56,7 @@ int main() { for (i = 0; i < N; i++) { store[i] = next(); } - fp = fopen("xoshiro512starstar-testset-2.csv", "w"); + fp = fopen("xoshiro512-testset-2.csv", "w"); if (fp == NULL) { printf("Couldn't open file\n"); return -1; diff --git a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.c b/numpy/random/src/xoshiro512/xoshiro512.c similarity index 84% rename from numpy/random/src/xoshiro512starstar/xoshiro512starstar.c rename to numpy/random/src/xoshiro512/xoshiro512.c index a9f56699f51d..9fdbed125a34 100644 --- a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.c +++ b/numpy/random/src/xoshiro512/xoshiro512.c @@ -6,7 +6,7 @@ worldwide. This software is distributed without any warranty. See . */ -#include "xoshiro512starstar.h" +#include "xoshiro512.h" /* This is xoshiro512** 1.0, an all-purpose, rock-solid generator. It has excellent (about 1ns) speed, an increased state (512 bits) that is @@ -19,11 +19,10 @@ See . */ a 64-bit seed, we suggest to seed a splitmix64 generator and use its output to fill s. */ -extern INLINE uint64_t -xoshiro512starstar_next64(xoshiro512starstar_state *state); +extern NPY_INLINE uint64_t xoshiro512_next64(xoshiro512_state *state); + +extern NPY_INLINE uint32_t xoshiro512_next32(xoshiro512_state *state); -extern INLINE uint32_t -xoshiro512starstar_next32(xoshiro512starstar_state *state); /* This is the jump function for the generator. It is equivalent to 2^256 calls to next(); it can be used to generate 2^256 @@ -31,7 +30,7 @@ xoshiro512starstar_next32(xoshiro512starstar_state *state); static uint64_t s_placeholder[8]; -void xoshiro512starstar_jump(xoshiro512starstar_state *state) { +void xoshiro512_jump(xoshiro512_state *state) { int i, b, w; static const uint64_t JUMP[] = {0x33ed89b6e7a353f9, 0x760083d7955323be, @@ -46,7 +45,7 @@ void xoshiro512starstar_jump(xoshiro512starstar_state *state) { if (JUMP[i] & UINT64_C(1) << b) for (w = 0; w < sizeof s_placeholder / sizeof *s_placeholder; w++) t[w] ^= state->s[w]; - xoshiro512starstar_next(&state->s[0]); + xoshiro512_next(&state->s[0]); } memcpy(state->s, t, sizeof s_placeholder); diff --git a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.h b/numpy/random/src/xoshiro512/xoshiro512.h similarity index 50% rename from numpy/random/src/xoshiro512starstar/xoshiro512starstar.h rename to numpy/random/src/xoshiro512/xoshiro512.h index 0fa0ba3cda1a..6ce6c7db70d1 100644 --- a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.h +++ b/numpy/random/src/xoshiro512/xoshiro512.h @@ -1,33 +1,23 @@ #ifndef _RANDOMDGEN__XOSHIRO512STARSTAR_H_ #define _RANDOMDGEN__XOSHIRO512STARSTAR_H_ -#ifdef _WIN32 -#if _MSC_VER == 1500 -#include "../common/inttypes.h" -#define INLINE __forceinline -#else -#include -#define INLINE __inline __forceinline -#endif -#else -#include -#define INLINE inline -#endif #include +#include +#include "numpy/npy_common.h" -typedef struct s_xoshiro512starstar_state +typedef struct s_xoshiro512_state { uint64_t s[8]; int has_uint32; uint32_t uinteger; -} xoshiro512starstar_state; +} xoshiro512_state; -static INLINE uint64_t rotl(const uint64_t x, int k) +static NPY_INLINE uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -static INLINE uint64_t xoshiro512starstar_next(uint64_t *s) +static NPY_INLINE uint64_t xoshiro512_next(uint64_t *s) { const uint64_t result_starstar = rotl(s[1] * 5, 7) * 9; @@ -49,14 +39,13 @@ static INLINE uint64_t xoshiro512starstar_next(uint64_t *s) return result_starstar; } -static INLINE uint64_t -xoshiro512starstar_next64(xoshiro512starstar_state *state) + +static NPY_INLINE uint64_t xoshiro512_next64(xoshiro512_state *state) { - return xoshiro512starstar_next(&state->s[0]); + return xoshiro512_next(&state->s[0]); } -static INLINE uint32_t -xoshiro512starstar_next32(xoshiro512starstar_state *state) +static NPY_INLINE uint32_t xoshiro512_next32(xoshiro512_state *state) { uint64_t next; if (state->has_uint32) @@ -64,12 +53,12 @@ xoshiro512starstar_next32(xoshiro512starstar_state *state) state->has_uint32 = 0; return state->uinteger; } - next = xoshiro512starstar_next(&state->s[0]); + next = xoshiro512_next(&state->s[0]); state->has_uint32 = 1; state->uinteger = (uint32_t)(next >> 32); return (uint32_t)(next & 0xffffffff); } -void xoshiro512starstar_jump(xoshiro512starstar_state *state); +void xoshiro512_jump(xoshiro512_state *state); #endif diff --git a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.c b/numpy/random/src/xoshiro512/xoshiro512.orig.c similarity index 98% rename from numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.c rename to numpy/random/src/xoshiro512/xoshiro512.orig.c index 0cf884edb036..ecdf81fc1321 100644 --- a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.c +++ b/numpy/random/src/xoshiro512/xoshiro512.orig.c @@ -6,7 +6,7 @@ worldwide. This software is distributed without any warranty. See . */ -#include "xoshiro512starstar.orig.h" +#include "xoshiro512.orig.h" /* This is xoshiro512** 1.0, an all-purpose, rock-solid generator. It has excellent (about 1ns) speed, an increased state (512 bits) that is diff --git a/numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.h b/numpy/random/src/xoshiro512/xoshiro512.orig.h similarity index 100% rename from numpy/random/src/xoshiro512starstar/xoshiro512starstar.orig.h rename to numpy/random/src/xoshiro512/xoshiro512.orig.h diff --git a/numpy/random/tests/data/pcg32-testset-1.csv b/numpy/random/tests/data/pcg32-testset-1.csv deleted file mode 100644 index 6bddc8d5ccc2..000000000000 --- a/numpy/random/tests/data/pcg32-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0xbeb77374 -1, 0x75cad014 -2, 0xabc6773e -3, 0xe99a034e -4, 0x1e3f5c6d -5, 0x513d3c5b -6, 0x4a378bad -7, 0xba5b3488 -8, 0x21e96448 -9, 0x5197a3d3 -10, 0x84bbcc90 -11, 0x674fce76 -12, 0xd1dd9879 -13, 0x1625afd4 -14, 0x4bb5e330 -15, 0x3f4b8f74 -16, 0xf0a7c00b -17, 0xecdb92d0 -18, 0xf069232c -19, 0x56dbeaa2 -20, 0x70c62231 -21, 0x6c68e57e -22, 0x3829213c -23, 0x9b8bc5e6 -24, 0x45abd553 -25, 0xf5991ce7 -26, 0xb4aff20a -27, 0x677a5785 -28, 0x108f180d -29, 0x2b3f1001 -30, 0x838fdfcb -31, 0x8ad3c2a0 -32, 0x596268fa -33, 0xee6bcc56 -34, 0x46810af0 -35, 0x1648a587 -36, 0x7265a926 -37, 0xed0f3acc -38, 0x72a1ac0 -39, 0xb3f7109f -40, 0x6ddd75f2 -41, 0xa968127f -42, 0x40df20fd -43, 0xde835b80 -44, 0xe453cd68 -45, 0x26ad68eb -46, 0x23a052d2 -47, 0x17881c5c -48, 0x785d41b9 -49, 0x61b4530a -50, 0x5ee92c84 -51, 0x4cad7358 -52, 0x843db584 -53, 0x3576368b -54, 0x14db6b2b -55, 0xb6e8b042 -56, 0x6323e866 -57, 0x9a709e25 -58, 0xae594bdc -59, 0x4be9ec1b -60, 0x77b4fd05 -61, 0x4421667 -62, 0x24bf98f7 -63, 0xfb202aed -64, 0x2f01b05f -65, 0xac766e69 -66, 0xc1572ce2 -67, 0xb26354d6 -68, 0x4db5f193 -69, 0x41a4609b -70, 0x26bbb4cc -71, 0x676b7438 -72, 0x13b2be7d -73, 0x7df521c4 -74, 0x57f770f3 -75, 0x78a8a8 -76, 0x164d46c6 -77, 0xbb29da20 -78, 0x5c262bf9 -79, 0xfd305d0 -80, 0xb500d90b -81, 0xbb7b4e37 -82, 0x5ba2bbfd -83, 0xa9561043 -84, 0xe175c662 -85, 0x3a5c8eec -86, 0xac5e2184 -87, 0x1e1c7de7 -88, 0x46be092a -89, 0x8b82f5be -90, 0xb1c1b591 -91, 0x6f06d957 -92, 0x1d26dc5c -93, 0x158c57e3 -94, 0x6da1ebf8 -95, 0x74501e60 -96, 0x70587043 -97, 0xa19b90fe -98, 0x7d327dff -99, 0x22dc6b90 -100, 0xf48a9ae6 -101, 0x75eeb769 -102, 0x9cdc12cb -103, 0x7fe2cdc6 -104, 0x4fba8066 -105, 0x1a7a0667 -106, 0xd9289d22 -107, 0x3a045bce -108, 0x60e5f71f -109, 0xd81b35dc -110, 0xceae6194 -111, 0xa032a688 -112, 0x7157b327 -113, 0x61c74c80 -114, 0x2d519c39 -115, 0x5b1a352e -116, 0x5ad266da -117, 0x9118352b -118, 0xdd20b6e1 -119, 0xc0d154fa -120, 0x93bbb9c9 -121, 0x91170de2 -122, 0xa3af5e05 -123, 0x1b19ff2f -124, 0xf814c3bf -125, 0x8914a953 -126, 0x5278efb7 -127, 0x3c96d7bd -128, 0xb5422a7 -129, 0x2aee2619 -130, 0x60c6a90c -131, 0xfbec0e9c -132, 0xef794075 -133, 0xda93d22e -134, 0xb956d02a -135, 0xd97cc49b -136, 0x80737244 -137, 0x7c56a95 -138, 0xa5311355 -139, 0x7dcdd592 -140, 0x92add23e -141, 0xb1ba1317 -142, 0x507e5330 -143, 0x2644b95a -144, 0xa1afa519 -145, 0x596c65c0 -146, 0x6f47dd11 -147, 0xfd2fbada -148, 0x98675d7c -149, 0xb9e21413 -150, 0x8bae5eca -151, 0xe1f50018 -152, 0x7dd08715 -153, 0x36a888e1 -154, 0x7fcd6364 -155, 0xb84c093 -156, 0x18e2d58f -157, 0x19fd21ed -158, 0x3c25e3a3 -159, 0x7a0d833b -160, 0x47525b28 -161, 0xba88474 -162, 0xd108e7da -163, 0x32b06660 -164, 0xbce027b3 -165, 0x96b31787 -166, 0x916ab263 -167, 0xa5fa088 -168, 0x3cb9cd59 -169, 0x7a97051f -170, 0x104b6883 -171, 0x6e08c314 -172, 0x33a4c62c -173, 0x14eb854 -174, 0x873f730a -175, 0x8c3f7224 -176, 0x9a41beeb -177, 0xe4e2ab0a -178, 0xfa89ad0e -179, 0x4aa62ac3 -180, 0xb75dc1bf -181, 0x3f4c5131 -182, 0x3fef0f91 -183, 0xffa06655 -184, 0x417d7d38 -185, 0x1e7734df -186, 0x25685235 -187, 0x33fe5b68 -188, 0x68923f72 -189, 0x5da45ff -190, 0xb871df26 -191, 0xd3ffd8c6 -192, 0x1718d862 -193, 0xe127d844 -194, 0xadcdc48a -195, 0x79ee30cb -196, 0x931a6cba -197, 0x9463c42d -198, 0x9f8d2806 -199, 0xa3695a97 -200, 0xfc9587bc -201, 0xb3943573 -202, 0x50ed8901 -203, 0x6891f33 -204, 0xb7a12dfb -205, 0x1245cf5d -206, 0xbc0f73a7 -207, 0x26cbfeb2 -208, 0x774d8e83 -209, 0xa19e9c1 -210, 0xc147a437 -211, 0xe034f2a3 -212, 0xd288b664 -213, 0xdcd0356d -214, 0x2b695901 -215, 0x3bc31736 -216, 0x4a5b1998 -217, 0x18537410 -218, 0x11b40f35 -219, 0xf16f6f89 -220, 0xe844cffe -221, 0xce026166 -222, 0x3770aaba -223, 0xc62566ee -224, 0x6db2d1f8 -225, 0xe4720b6d -226, 0x68321a69 -227, 0x488539ac -228, 0x5e18ab61 -229, 0xb58e598e -230, 0x6f501a91 -231, 0xc4fd3e8d -232, 0x9faa3631 -233, 0x184366b0 -234, 0xecf74d6a -235, 0x3773d622 -236, 0x382ca536 -237, 0x93451381 -238, 0x9f148ed5 -239, 0x2b66f241 -240, 0xa6807c39 -241, 0xbb087446 -242, 0xa18ba432 -243, 0x8e7a6013 -244, 0xab30278e -245, 0xbf457c78 -246, 0xb24814b1 -247, 0x710f99d5 -248, 0xbcb84762 -249, 0x4913a7e7 -250, 0x90a31a0c -251, 0x6d4b1673 -252, 0x18873994 -253, 0x1efd517a -254, 0x99b499d1 -255, 0x2d488776 -256, 0x1cded201 -257, 0xa53b02e4 -258, 0xcb20d0fd -259, 0x72bfaae3 -260, 0x858c865b -261, 0x2e2d3e96 -262, 0x8bc5b0b9 -263, 0x8980346a -264, 0xa8e47fba -265, 0x2a39fe16 -266, 0x9f34eeeb -267, 0x7baebcc9 -268, 0xbc0b8d74 -269, 0x37373c8 -270, 0xe128cfc4 -271, 0x49cdb150 -272, 0x5965c726 -273, 0xfc326226 -274, 0x53a3e8e -275, 0xa99d89f7 -276, 0x33ac111c -277, 0x143fe678 -278, 0x96212281 -279, 0x6a83bffd -280, 0x529852f7 -281, 0x97fef4 -282, 0x303ce151 -283, 0x4f8c7b83 -284, 0xd5ef9c82 -285, 0xede9d572 -286, 0xc03e2c38 -287, 0x89d7f886 -288, 0x21e998b0 -289, 0x58d505cf -290, 0x5c42089 -291, 0x9a01dcab -292, 0x83d8cc17 -293, 0x7d6aacf -294, 0xa1cbdced -295, 0x47365e25 -296, 0xbb61e976 -297, 0xfeafd0a6 -298, 0x760d82b4 -299, 0x9ffb351d -300, 0x28e19ac0 -301, 0x891131c6 -302, 0xc1656522 -303, 0x4536d90 -304, 0x956b1b84 -305, 0xf9ff54f6 -306, 0xb0050d88 -307, 0x7d7fafa2 -308, 0x430e670b -309, 0x18ad450d -310, 0xd5a1d6b6 -311, 0x390a6da4 -312, 0xc70d557d -313, 0xd8fadb5e -314, 0xfb4b4cb6 -315, 0xce707f8b -316, 0x4c18d350 -317, 0x8dc0d200 -318, 0x228d9e85 -319, 0xd6485ba3 -320, 0x37c4a70a -321, 0x9d7cc5f5 -322, 0x889a9b9 -323, 0x41d2f942 -324, 0x4c13b3bd -325, 0x70e58147 -326, 0x4a0e1270 -327, 0x3cdc1b73 -328, 0x7a4e56f3 -329, 0xd8350406 -330, 0x46068108 -331, 0xfc4da48 -332, 0xf6111245 -333, 0x40a15167 -334, 0x38a591ac -335, 0x3e97e682 -336, 0x5c515d2d -337, 0x45023a37 -338, 0xacb0ed6a -339, 0x899f0ebb -340, 0x2054df01 -341, 0x6d629607 -342, 0x79ced597 -343, 0xba0a3a12 -344, 0xde63b611 -345, 0x228cb776 -346, 0x61f10dba -347, 0x9a1095d3 -348, 0xf08dcb3 -349, 0x88e58009 -350, 0x131880aa -351, 0xc55002ee -352, 0xcf556f47 -353, 0x17b6dd76 -354, 0x6110ba20 -355, 0x74a91935 -356, 0xe83cf9ed -357, 0x3138e936 -358, 0x103bfb72 -359, 0x2084abe4 -360, 0xf3a05dd9 -361, 0x9213f3a4 -362, 0xe7674dd7 -363, 0xcd09d629 -364, 0x260461f2 -365, 0x411c2428 -366, 0xbb5f6f2e -367, 0x6feb8c93 -368, 0x3cde3ece -369, 0x7a424d2c -370, 0x808a0948 -371, 0x653c3fdf -372, 0x26f88849 -373, 0xf540b6ae -374, 0x1f82e8ac -375, 0x300f7e39 -376, 0xb6e62e7b -377, 0x970441a1 -378, 0x91f2946c -379, 0xaad281f -380, 0x43be1dcf -381, 0x95a1b4c8 -382, 0x2d956dea -383, 0xc532ca29 -384, 0xc93f1fcf -385, 0x70762aab -386, 0x231a72ef -387, 0xe5bd1b75 -388, 0xfa31468 -389, 0x77e1b7b5 -390, 0x19d80215 -391, 0xd45704b7 -392, 0x33472a0d -393, 0x833a435e -394, 0x2354a326 -395, 0x8af39828 -396, 0x603a7960 -397, 0x288c2d54 -398, 0x75bd7c23 -399, 0xe2dd42e1 -400, 0x9a87b486 -401, 0x32e9bcd1 -402, 0x8630f74f -403, 0x160408ea -404, 0xd2127c63 -405, 0xaf327f8e -406, 0x8d879a61 -407, 0xc5c88f60 -408, 0x53a19fa1 -409, 0x706dacb4 -410, 0xd04ea0f -411, 0x94806c1a -412, 0x941cfe69 -413, 0x956a5562 -414, 0xee1f71c -415, 0xe6ba12d -416, 0x333e31f6 -417, 0x17aee12e -418, 0x20ccfedb -419, 0xd7bb7f92 -420, 0xba7d14f3 -421, 0xb935d4fb -422, 0xbdb8f5e1 -423, 0xb24e7adc -424, 0xc9abef71 -425, 0x3e3d8125 -426, 0x5fc0878b -427, 0x5ba172d9 -428, 0xe28f648c -429, 0x5137f3a7 -430, 0xb57273df -431, 0xe68df236 -432, 0xbc29802b -433, 0xb1419e66 -434, 0x69ecb739 -435, 0x490e8eb6 -436, 0x61e25a6c -437, 0xc1fa0de6 -438, 0x2bf2fbf1 -439, 0x9487e8da -440, 0xce5c5532 -441, 0x75859040 -442, 0x2606bdeb -443, 0x1b77c072 -444, 0xe5fbeed1 -445, 0xea9e1ab3 -446, 0x55cf96ae -447, 0x283ed27d -448, 0xc94067a1 -449, 0x8687b3e5 -450, 0x4031b307 -451, 0xc5790e82 -452, 0x4031ee7f -453, 0x952c4503 -454, 0x379ec606 -455, 0x7c35e19d -456, 0x2d333769 -457, 0xbca36d54 -458, 0xcdc70741 -459, 0xa3ab56fb -460, 0x187a2fd6 -461, 0xdd1f32f1 -462, 0xc007ac56 -463, 0x14c441c1 -464, 0xf290ed47 -465, 0xc833edac -466, 0x13f0a8fe -467, 0x63c10b6e -468, 0x6af1be34 -469, 0x5bd4930e -470, 0xfe56bfbb -471, 0x1b412c8e -472, 0xf0c7712a -473, 0xf3a96226 -474, 0xbd0aaad8 -475, 0xbd00355e -476, 0x8ba9eca1 -477, 0x81f136a0 -478, 0x7de3a327 -479, 0x7be298ea -480, 0xe60e320a -481, 0xaf4373b -482, 0x6eacbf3 -483, 0x1291760f -484, 0xd48ed89b -485, 0x596603d4 -486, 0x53abc8 -487, 0x82123b2f -488, 0x1276dc8 -489, 0xfeb474bb -490, 0x4013da51 -491, 0x111cb9d6 -492, 0x5726df82 -493, 0x45806861 -494, 0x2580801a -495, 0x1326049e -496, 0xb9474bf9 -497, 0x6c5d85ed -498, 0x9c4a9352 -499, 0x9eb915ed -500, 0x914505 -501, 0xd14c5b9a -502, 0x57ef8ffd -503, 0x480d8719 -504, 0xb18d7fce -505, 0xfd29e178 -506, 0x2679f6c9 -507, 0xd94a086e -508, 0x6e46f559 -509, 0xb7c3a2e3 -510, 0x793a4c3b -511, 0x4e5252f9 -512, 0x1bdb53a4 -513, 0xbed5794 -514, 0x31a3ebc7 -515, 0xa6eb54e1 -516, 0xc6ae5d92 -517, 0x392acfc8 -518, 0xb283fb8f -519, 0x80b15ffe -520, 0x763b49a8 -521, 0x3febc1d3 -522, 0x60f2b20 -523, 0xd93aeba9 -524, 0xeddf06bb -525, 0x13992ab3 -526, 0x4521bcf6 -527, 0x5ad82a14 -528, 0xf2bfc79c -529, 0xf664b9b -530, 0xeb9540a2 -531, 0x5641dc50 -532, 0x9282d9c4 -533, 0x5d2443a4 -534, 0x407b5011 -535, 0x84a415d7 -536, 0x5db90eae -537, 0xd2947d4c -538, 0x8bd8856d -539, 0xbc05a99b -540, 0x1c2e0f5 -541, 0xb94d03a2 -542, 0xb8ed5ac1 -543, 0x199943d9 -544, 0x12482e5c -545, 0x20aa7c9f -546, 0x8733e45c -547, 0x277b4f44 -548, 0x673d5a73 -549, 0xabc0aad9 -550, 0xbed6cd98 -551, 0x2943c24b -552, 0x5237d6f9 -553, 0x1cb1a392 -554, 0xc7b69454 -555, 0x4f792707 -556, 0xa32ef400 -557, 0x7a5b6b72 -558, 0xa8683acc -559, 0x418d0491 -560, 0x56e2470e -561, 0xbe385495 -562, 0xe7944341 -563, 0x438abaab -564, 0x82ad2c2 -565, 0x7afc306b -566, 0xfcb88957 -567, 0x530414bd -568, 0x2e3c7d41 -569, 0x633f7573 -570, 0xeffeefb2 -571, 0xf6de11f9 -572, 0x337710f2 -573, 0x88bf46dc -574, 0x6fdaf5dc -575, 0x34229d26 -576, 0x46b0aba0 -577, 0x78e40a29 -578, 0x7f9623cd -579, 0x6cfe8779 -580, 0x1d4af99 -581, 0x78f97244 -582, 0xa198d714 -583, 0x9124883e -584, 0x1cf88a12 -585, 0x69fe0966 -586, 0x78484a68 -587, 0xf9d8718b -588, 0xcbf3ba5b -589, 0xf67fb149 -590, 0xc95977c1 -591, 0x474f57f5 -592, 0x11bb9ec1 -593, 0xe28f21be -594, 0x8ca6e21b -595, 0x2609defc -596, 0x989b6f6b -597, 0x1c87383e -598, 0xacd78f57 -599, 0x8c46cfcb -600, 0xc37cce08 -601, 0x327d196a -602, 0xf63c3572 -603, 0xc56780b5 -604, 0x9ac37d16 -605, 0xe692a39c -606, 0x563938a3 -607, 0x1e80e32f -608, 0x745652af -609, 0xe425c9a8 -610, 0x11c71e82 -611, 0x9c721f6d -612, 0xef89b973 -613, 0x494c7e80 -614, 0xadc29895 -615, 0xc7ee35ad -616, 0x19beeb0c -617, 0x9c25ae3f -618, 0x27bf930f -619, 0x223970a0 -620, 0x7cdb17ca -621, 0xa49054f -622, 0xf8321dcb -623, 0x3f96a9eb -624, 0x4468072a -625, 0xfd7d727 -626, 0xee0af4f1 -627, 0xe6585512 -628, 0x56a6d8a1 -629, 0x40586642 -630, 0xb46bdaa0 -631, 0xe053a140 -632, 0x4de1953d -633, 0xb6cbc718 -634, 0x2ed92c19 -635, 0x9da2840 -636, 0x6ab418b1 -637, 0x179f64cf -638, 0x7c281c0 -639, 0x7015b62a -640, 0x8d31e38e -641, 0xa6de57ca -642, 0xe509c4e1 -643, 0xa010162c -644, 0xf71abd42 -645, 0x3d24ac8b -646, 0xc2deb72f -647, 0xd81570ba -648, 0x17fc7d15 -649, 0xf17997b6 -650, 0xfa2ec5b5 -651, 0xbf7e189b -652, 0xb3d9e761 -653, 0xe1194bd1 -654, 0x8d5280dd -655, 0xdea2d148 -656, 0x6d85e66c -657, 0x37f5fb07 -658, 0x65c1dd1 -659, 0xf52c04f8 -660, 0x4460d846 -661, 0x1729f55f -662, 0xe03a699d -663, 0x9f05ff9f -664, 0x31abe986 -665, 0x64899f61 -666, 0x52fba7 -667, 0x2833ce74 -668, 0xa34d0e57 -669, 0x7203d492 -670, 0x1a63d91e -671, 0x463781b7 -672, 0xf9842e7b -673, 0x809276ad -674, 0x88237b9d -675, 0xaa648b06 -676, 0x9cf916bd -677, 0x3b3068e4 -678, 0x20d6ae7d -679, 0x7855dafd -680, 0x9ebd14ed -681, 0xc5934a1c -682, 0xb3c421a1 -683, 0xa2b709a2 -684, 0x91fa8b34 -685, 0x9009a54 -686, 0xb2c4215f -687, 0x7b294eb1 -688, 0x1802911e -689, 0xa2067de5 -690, 0x5ebd85e9 -691, 0xc4f8e698 -692, 0xd143d368 -693, 0x2ca2b6fb -694, 0xb5d27ebc -695, 0x410146ca -696, 0x9d6948fe -697, 0xfafd0af5 -698, 0x290e9c5f -699, 0x2ff06292 -700, 0x417903d5 -701, 0xc51af07c -702, 0xd2bbaf6b -703, 0xfa3720f1 -704, 0x4a6eb52d -705, 0xed86ad3c -706, 0x72a8676e -707, 0xc3c2bbed -708, 0x62b6a951 -709, 0xe08f9534 -710, 0xe2686ea5 -711, 0x3dbbf99b -712, 0xfec5319f -713, 0xef9c67eb -714, 0x9d69d19b -715, 0xc732ed2 -716, 0xc6e829bd -717, 0xe712e882 -718, 0xd24594ca -719, 0x102b8426 -720, 0xa5145730 -721, 0x62fecd71 -722, 0xe6439ca2 -723, 0x58819419 -724, 0xef722791 -725, 0x5ef6ab17 -726, 0x85ce3714 -727, 0xd4e18303 -728, 0xf91eb9c2 -729, 0x86bae692 -730, 0x6d81c21c -731, 0xd9985982 -732, 0xfdd55f22 -733, 0x72ecd91a -734, 0x4b1cee6 -735, 0xefa672ec -736, 0x3f18114f -737, 0xacae5e62 -738, 0x68369afd -739, 0xff5e6612 -740, 0x3760af8c -741, 0xd8c878bf -742, 0x3945fe59 -743, 0x2cf7f99a -744, 0x2cc59bb4 -745, 0xbba95cd6 -746, 0x6511688d -747, 0xcf326178 -748, 0xf850cc68 -749, 0x4bd2540e -750, 0xa02cf5e5 -751, 0x5546fcb5 -752, 0xe2b289fd -753, 0x960c6ba -754, 0x3a2c9d74 -755, 0x2def7a8f -756, 0x54e57d43 -757, 0xf953c277 -758, 0xd9b414b1 -759, 0x19a25920 -760, 0xaf2691a1 -761, 0x81e88159 -762, 0x49a3eab -763, 0x276a797d -764, 0x98337885 -765, 0x37055fd0 -766, 0x6927effc -767, 0xb6de7fc0 -768, 0x9e920f9a -769, 0xd2dc9145 -770, 0xe2861109 -771, 0xe42e2c1e -772, 0x836fe968 -773, 0x23452a15 -774, 0xd49f0e2b -775, 0x2998f647 -776, 0x94f8c803 -777, 0xf8be479e -778, 0xfd44079f -779, 0x685ab9c1 -780, 0xea8eeab3 -781, 0x580ff5d8 -782, 0x88ad0666 -783, 0x19df5d86 -784, 0xe4862012 -785, 0x3ad25460 -786, 0x677449ce -787, 0x1c7e0b9a -788, 0x287a98d0 -789, 0xed39d094 -790, 0x40501707 -791, 0xb99073a4 -792, 0x31847bd4 -793, 0x91e5b7 -794, 0x46815e56 -795, 0xc823384c -796, 0xdb6fb24 -797, 0xabe50dd8 -798, 0x2a33797b -799, 0x4fb617ec -800, 0x811a36df -801, 0xb6b7a25f -802, 0x8962cd0a -803, 0xc40818fe -804, 0x5dbe4e57 -805, 0x591f6c61 -806, 0x22aa4809 -807, 0xc0e4a72 -808, 0xa8a0e2e7 -809, 0xf91d553a -810, 0x77674da7 -811, 0x196657d6 -812, 0x5ae38c0f -813, 0x8bcf1ed2 -814, 0x9e0a2c8f -815, 0xf94e5215 -816, 0x11299b2b -817, 0xc499eca3 -818, 0x25e58d1b -819, 0xdd722954 -820, 0x816f4c21 -821, 0x2504fd9b -822, 0x722a597a -823, 0x92f80aab -824, 0xe2d7e54d -825, 0xefb26dba -826, 0x9ebf8863 -827, 0xd297ec21 -828, 0xa0ebfbb5 -829, 0xec609873 -830, 0xd079b3d1 -831, 0x920f722d -832, 0xfd58146 -833, 0x5fbb5784 -834, 0x30187f5d -835, 0x887f4ec6 -836, 0x6839a2ed -837, 0x72bccd98 -838, 0x7565903e -839, 0x8d3afaef -840, 0xfb713a03 -841, 0x34216b35 -842, 0xbe0da7e9 -843, 0x4b11764e -844, 0x6666922a -845, 0x3f2dc90d -846, 0xeca8fb8d -847, 0x91579404 -848, 0x8d413df7 -849, 0x2a0f8307 -850, 0x39d5a495 -851, 0x79ba5e62 -852, 0xbb06fd0f -853, 0x47ba4208 -854, 0x4a2efb9c -855, 0xee3a07f0 -856, 0x291a73e0 -857, 0xe42a46c5 -858, 0x203455b2 -859, 0x40545253 -860, 0xa618bb0a -861, 0xd4792a15 -862, 0xd6e62559 -863, 0x8149e2f0 -864, 0x5f6499a9 -865, 0xa63fc585 -866, 0xe33e1c1f -867, 0x36ecb45b -868, 0x267883ca -869, 0x905d98fb -870, 0xfac3512c -871, 0x374d0a0e -872, 0x9920f3e0 -873, 0xfb961c9f -874, 0x70f2d752 -875, 0x69c44d12 -876, 0xcb6075d2 -877, 0xaf802ac8 -878, 0x2c4b792b -879, 0xa2203217 -880, 0xc2c15619 -881, 0xb13af213 -882, 0x759b165c -883, 0x411ecdf2 -884, 0x158e5fba -885, 0x70874450 -886, 0x226a484f -887, 0x87b95ecf -888, 0x45cef22f -889, 0xfaf186bd -890, 0x3544972a -891, 0xb4a2f73 -892, 0x5f5d10de -893, 0xf3d05e29 -894, 0x7616ba85 -895, 0x4d2e198 -896, 0x1f240293 -897, 0x317c2286 -898, 0x3bd97e7b -899, 0xd7e39d6f -900, 0x142ee43c -901, 0x688ada72 -902, 0xad8deac8 -903, 0xf7cc8d5e -904, 0xa84600f5 -905, 0xda6b1b3 -906, 0x5bad09de -907, 0x6f4276c7 -908, 0xa789933f -909, 0xede4329a -910, 0xa31f2df5 -911, 0x869c0c3c -912, 0x6658f5b -913, 0xdb451b7c -914, 0x16ec0b18 -915, 0x2e35872c -916, 0xf7bf3c44 -917, 0xda59c872 -918, 0x1ab63c0c -919, 0x9a361a82 -920, 0xd2e1afcc -921, 0x5c41ac55 -922, 0xd1d761db -923, 0x3639bb85 -924, 0x7a418cfb -925, 0xf0b06b8f -926, 0xa2ef4d47 -927, 0x4fac4d1b -928, 0x47e42283 -929, 0x6ee6a7df -930, 0xfe786975 -931, 0x4475b665 -932, 0xd881e311 -933, 0x6b02224 -934, 0xcba19b84 -935, 0x4efa35f6 -936, 0x3873a72d -937, 0x984d7964 -938, 0xe23cda62 -939, 0xea9949d2 -940, 0x243b83b1 -941, 0x48d1bcc4 -942, 0xe35b6a23 -943, 0x125288f1 -944, 0x72fdd401 -945, 0xa2af6873 -946, 0x7c211096 -947, 0xa00a13dd -948, 0x7b4ce5d6 -949, 0x1e4be120 -950, 0xc771cc00 -951, 0x343ae31 -952, 0xe8e0be50 -953, 0xd9095a3f -954, 0x616b7c17 -955, 0xa96e1580 -956, 0x60501426 -957, 0xeaac50b -958, 0x130c33b5 -959, 0xba30925b -960, 0xf942c440 -961, 0xc52e8e20 -962, 0x5f460318 -963, 0x94e1dadd -964, 0xdfa4f20e -965, 0xc9bbd26a -966, 0x75322ecb -967, 0x3dc3ff18 -968, 0xfa896826 -969, 0xe4ad213c -970, 0x7a0f97c3 -971, 0xd7b7b08f -972, 0x6ebcab4e -973, 0x1a37d816 -974, 0x16299fee -975, 0x89d94a3a -976, 0x11c2f073 -977, 0x4ef27a32 -978, 0xaaf42781 -979, 0x9862c844 -980, 0xaa672e94 -981, 0xba4f2690 -982, 0x1f767d21 -983, 0x157e1a5e -984, 0x5b6de343 -985, 0xc494501e -986, 0xe97b507b -987, 0x98cae4c8 -988, 0xc4a6b036 -989, 0x746f8686 -990, 0xe761c86 -991, 0xefdaaa15 -992, 0xb907b816 -993, 0xe9d05992 -994, 0xed2e1b0e -995, 0xe129d3ee -996, 0xb41bb95f -997, 0xaec36181 -998, 0xdcdcf5f0 -999, 0xf175572a diff --git a/numpy/random/tests/data/pcg32-testset-2.csv b/numpy/random/tests/data/pcg32-testset-2.csv deleted file mode 100644 index 2d4c8aed1312..000000000000 --- a/numpy/random/tests/data/pcg32-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0xe4c14788 -1, 0x379c6516 -2, 0x5c4ab3bb -3, 0x601d23e0 -4, 0x1c382b8c -5, 0xd1faab16 -6, 0x67680a2d -7, 0x92014a6e -8, 0x628ae389 -9, 0xa794034d -10, 0x5cc38cd9 -11, 0xfc913a3b -12, 0x81c851dc -13, 0x90c820e4 -14, 0x60dfa703 -15, 0xd613ae14 -16, 0x38ea1699 -17, 0x51f04d1b -18, 0xc4ef01a1 -19, 0x321eec02 -20, 0x4c37a737 -21, 0x6bfd1aa8 -22, 0x71a28325 -23, 0x4656d6e9 -24, 0x17509653 -25, 0x830bd521 -26, 0x6d35e3aa -27, 0x4ab85020 -28, 0x21c1da2c -29, 0x6a6057a2 -30, 0xf3a90dc1 -31, 0xa1cbdcd9 -32, 0xf70b61bf -33, 0x3b2b09a8 -34, 0xbc2ef54d -35, 0xce07f38f -36, 0xb51bc60b -37, 0x729efb83 -38, 0x7e4a5f66 -39, 0xdd824ead -40, 0x9be85945 -41, 0x57f8779c -42, 0xdb449e87 -43, 0xc0be253f -44, 0x18b4267e -45, 0xff78821 -46, 0xb53e3425 -47, 0x4550b21b -48, 0xefe89a4c -49, 0x74c130b9 -50, 0x1656a3a0 -51, 0x194da2a6 -52, 0x1a6cdb1d -53, 0x7c1fd58e -54, 0x3162d1e9 -55, 0x3e2f2c7d -56, 0xb0ab9b5c -57, 0x79156d4d -58, 0x97b85150 -59, 0x967a02ce -60, 0x1e64548d -61, 0x4196d24a -62, 0xd047eef5 -63, 0x8451cc3c -64, 0x7227eb94 -65, 0xb1191064 -66, 0x82e162d0 -67, 0xb473f07d -68, 0x92ea0426 -69, 0xbf2a25fa -70, 0x9935be52 -71, 0x28baec93 -72, 0xa29368b5 -73, 0xe3d6d97d -74, 0x85ecf1d4 -75, 0x482e4bc8 -76, 0xe4f22219 -77, 0x7531047 -78, 0x3c41ef1f -79, 0x19db5112 -80, 0xc1534caf -81, 0x6c45710a -82, 0xb323c369 -83, 0x2dac53c6 -84, 0xd5dc48b4 -85, 0x1dc6d7a1 -86, 0x3ae2bc10 -87, 0x6a7635e8 -88, 0xdeee7b7f -89, 0xcb705cd3 -90, 0xba11e537 -91, 0xb64a4936 -92, 0xff4b245e -93, 0x39cb1219 -94, 0x64833e10 -95, 0x76b0f975 -96, 0x333d7c7d -97, 0x88ccfb17 -98, 0xad78dace -99, 0xd82fb71 -100, 0x1595d411 -101, 0x47f9d57a -102, 0xd4dad6cb -103, 0x78bf16bd -104, 0x71b053d2 -105, 0xa4bb076e -106, 0xd7c57664 -107, 0x3fbcbf8f -108, 0xc816befc -109, 0x6df46890 -110, 0xd16f271f -111, 0xeeeb1571 -112, 0x58222e89 -113, 0xa55e81d3 -114, 0xafbe7622 -115, 0x938475a8 -116, 0xd8740af2 -117, 0xf937dbd7 -118, 0x7d3940fa -119, 0x694c55f2 -120, 0x2261fb68 -121, 0x6ce39e94 -122, 0xab43634 -123, 0xd92ff7c4 -124, 0xe8db22d -125, 0x52e250b1 -126, 0xaf0f7029 -127, 0xc23dd3a -128, 0xd66dc2b9 -129, 0xea7f01f3 -130, 0x4df54b3f -131, 0xf1eff09c -132, 0x2813663e -133, 0x21ae8115 -134, 0xb00d790d -135, 0x11e6adbb -136, 0x61005f4c -137, 0x3de17bf0 -138, 0x7b2050b9 -139, 0xe20dd275 -140, 0xafa0bdcc -141, 0x9c6d4c6c -142, 0xe938606 -143, 0x8eecdd8f -144, 0xea9a90a9 -145, 0x99cbb123 -146, 0x16fccad1 -147, 0x7e81fdd9 -148, 0x116e6abd -149, 0xdeb9ff4e -150, 0xc589f525 -151, 0x57d701a9 -152, 0xcf05e950 -153, 0x533a2839 -154, 0x12d592e7 -155, 0xae61f43f -156, 0x419ae221 -157, 0x81126e0a -158, 0xc3988c97 -159, 0xb3262eaa -160, 0x3baddf9e -161, 0xf19d8a16 -162, 0x2a8b130f -163, 0xe4c9ccea -164, 0xf5ae2ea -165, 0x75aaa98d -166, 0xdd45ce49 -167, 0x98e0d4f6 -168, 0xb1ec10a1 -169, 0xc9592952 -170, 0x23bb1f45 -171, 0xd0827b45 -172, 0x7a79b800 -173, 0x9d1b8348 -174, 0xe2958863 -175, 0x5143e17e -176, 0x44110af9 -177, 0x49d76858 -178, 0xdba4688e -179, 0x4e4d61dd -180, 0x729b81cc -181, 0xf3576e03 -182, 0x9b028e9d -183, 0x68d8d869 -184, 0xda15e018 -185, 0x5384abb2 -186, 0x1027ed5e -187, 0xaf5401f1 -188, 0x31411375 -189, 0xc75d87be -190, 0xad73f5fd -191, 0xadb3add7 -192, 0x4d5452ee -193, 0xdef42029 -194, 0x89d58a78 -195, 0x464d6b4a -196, 0xd01f533a -197, 0xb9533dd4 -198, 0x55c5d023 -199, 0x3dcf8fef -200, 0x198395ca -201, 0x7cdca51c -202, 0x6f4074f -203, 0xb9f79995 -204, 0xbbe3d9a5 -205, 0x520d417e -206, 0x9a8df0bd -207, 0xe390f486 -208, 0x5b578b3f -209, 0xb4cdf767 -210, 0x12d45034 -211, 0xe661e293 -212, 0x70cd3e91 -213, 0xdbc7f190 -214, 0x49829849 -215, 0x12017fbe -216, 0x1e35bf48 -217, 0x1effc3c7 -218, 0xe1f574cb -219, 0xf613ab7d -220, 0xd09d16fa -221, 0xa58bcf5a -222, 0xac39afdc -223, 0xd611d1ab -224, 0x36edd3b2 -225, 0xd9ea5d98 -226, 0xf6f2fce4 -227, 0x42cb31ce -228, 0xdd1f6530 -229, 0x3e43a7d0 -230, 0x175ec7fc -231, 0x8077af4b -232, 0x37cbcc22 -233, 0x26a89f -234, 0x998c930e -235, 0xb84e5f21 -236, 0x83817130 -237, 0x2ad05d66 -238, 0x48f3b861 -239, 0xd69f626 -240, 0x1d09f12 -241, 0xf207e7f0 -242, 0xcc709acc -243, 0x1b2881d7 -244, 0x7e18cc6c -245, 0xbfd9589c -246, 0xce0d301e -247, 0xc8668b4b -248, 0x584482bd -249, 0x722e14ae -250, 0xd79dfcff -251, 0xcc7e9c21 -252, 0xd081f540 -253, 0x3b49f7fa -254, 0xf23efb2a -255, 0xfd7fe8f8 -256, 0x9abcbf25 -257, 0x5b713674 -258, 0x1300e351 -259, 0xe884f0ad -260, 0x3c290461 -261, 0x4f64c1a1 -262, 0x17c55223 -263, 0xd5953a5f -264, 0xd85e042e -265, 0x75dfc597 -266, 0x379edfb -267, 0x75ebddc9 -268, 0xc19b98e1 -269, 0x1dd1b751 -270, 0xc5760a60 -271, 0x5f6e2f17 -272, 0x29e8610e -273, 0xb2edd7db -274, 0x9233eeca -275, 0xbc02b187 -276, 0xc997bb5b -277, 0x88ad3a98 -278, 0x3d1167ad -279, 0xcea54c9c -280, 0x7ea493eb -281, 0x586e3aa8 -282, 0xe2e027c7 -283, 0xae50ef9e -284, 0xd32e0c38 -285, 0xeba0edf6 -286, 0x980ad22a -287, 0x3b14e644 -288, 0xd7bfbff8 -289, 0xe0af1647 -290, 0x292d72dd -291, 0xb8c421bb -292, 0x114d690e -293, 0x85a86bd -294, 0x39f2b5e2 -295, 0x7c9c6b43 -296, 0xca387767 -297, 0x84f24ecf -298, 0x2aec5804 -299, 0x27d0f2 -300, 0xcd7bb6a9 -301, 0xe925969f -302, 0xc6454099 -303, 0xf7435a9d -304, 0xf7bc998f -305, 0xfa81f361 -306, 0xcba07d00 -307, 0x3e8a8a14 -308, 0xf0e7f785 -309, 0x25aecff -310, 0xe1a90226 -311, 0x4af1339d -312, 0x983f4fb9 -313, 0xbaec847f -314, 0x4e504dbb -315, 0xe7d0be86 -316, 0x73cb80ef -317, 0x336db698 -318, 0x8bf7de05 -319, 0x36e4e6ba -320, 0x47a8239b -321, 0x2a98e1d0 -322, 0x64a6c087 -323, 0x4a8591cb -324, 0x642d5d67 -325, 0x9f4b84b2 -326, 0x6bdf1176 -327, 0x7e2b1639 -328, 0xc90453f5 -329, 0xe72d0b96 -330, 0x5f0e1d0c -331, 0x156af798 -332, 0x6124d8e8 -333, 0xaa2f2ad7 -334, 0x145b30b7 -335, 0xd6582106 -336, 0x203abbad -337, 0x929d8d43 -338, 0x14d5b6dc -339, 0xef0f4eb2 -340, 0x8ff54463 -341, 0x588113a -342, 0x1bc43ba6 -343, 0x44f44097 -344, 0xb84cfdc6 -345, 0x3ee638af -346, 0xdd169321 -347, 0xaaac5f56 -348, 0xbb022bc2 -349, 0xf9ef8bde -350, 0x2829b2fb -351, 0x563368fa -352, 0x82ce66ae -353, 0x6d820e38 -354, 0xb87a080e -355, 0x756469af -356, 0x78086990 -357, 0xa220e762 -358, 0x14ba6bdb -359, 0xfa775c1b -360, 0x65fa7396 -361, 0xbae24370 -362, 0x8e42ddb8 -363, 0x1f46b8ac -364, 0x3c9236c5 -365, 0xd3a2184c -366, 0x308ba74 -367, 0x5638eb84 -368, 0x64076fe6 -369, 0x37fe334f -370, 0x8de24732 -371, 0xf0d0b02b -372, 0x18492b71 -373, 0x848f38ac -374, 0x9b46dc75 -375, 0xf5d3c06a -376, 0x203afe47 -377, 0x19857724 -378, 0x38033528 -379, 0xf7fa640c -380, 0xf1cb86e8 -381, 0x1fcd5b99 -382, 0xb07f1023 -383, 0x3bb9ab75 -384, 0x57f54e78 -385, 0xf5b51d4b -386, 0xe94eba44 -387, 0xa5a39292 -388, 0x50803af -389, 0x34ea9cc5 -390, 0xabf621ca -391, 0xb275f802 -392, 0xf46dffd6 -393, 0xd33e27d1 -394, 0xca9a56e -395, 0x6eda85a4 -396, 0x639b78ba -397, 0x799d1980 -398, 0xf3c09bf1 -399, 0x6d4cdbe -400, 0x112dae8d -401, 0xd97414b1 -402, 0x9499df3d -403, 0xa58ece6c -404, 0xe56bf91b -405, 0x3bdbfd9 -406, 0x91aae1fd -407, 0xec1fce54 -408, 0x60e0eced -409, 0x278d5b22 -410, 0xdee29da2 -411, 0xf1f55d27 -412, 0xd532ab83 -413, 0xb0fe9589 -414, 0x88fcc255 -415, 0xf524359b -416, 0x7270a00b -417, 0x42489eaf -418, 0xc020d6bb -419, 0xf9ed0f78 -420, 0x4bc5cdec -421, 0x55061393 -422, 0x6b84a5a4 -423, 0x826c0471 -424, 0x9e69e30d -425, 0x9dfd9b15 -426, 0xf4014c40 -427, 0xcd04ef4d -428, 0x7376c02c -429, 0xb15a9e3c -430, 0xf76c1fa9 -431, 0xcd51bdd8 -432, 0x99f2859e -433, 0xb62c6a4d -434, 0x52239d8b -435, 0x27fa2869 -436, 0x6dba918c -437, 0x9891e444 -438, 0x71e29f5 -439, 0xa9cd3ac9 -440, 0xf6ec3b80 -441, 0x8c8d3226 -442, 0x7c528725 -443, 0xd543932b -444, 0xf76b3e02 -445, 0xeccaf183 -446, 0x8f757854 -447, 0x785edb62 -448, 0x54397da0 -449, 0xe1fe0557 -450, 0x7a79d418 -451, 0xd2740507 -452, 0xc3561bc7 -453, 0xef7c3f18 -454, 0xecf8effe -455, 0xc7a073ad -456, 0xeb5ea9fd -457, 0x33dade18 -458, 0x89d0e41c -459, 0x7720d298 -460, 0xe912f029 -461, 0x7794462 -462, 0xa436dcf6 -463, 0x55cbb318 -464, 0x7b4a78e0 -465, 0xa8ce0afb -466, 0x7e18bb28 -467, 0x92c4f8f6 -468, 0x6828052c -469, 0xbf619f8 -470, 0x272d1d15 -471, 0xb34e2e52 -472, 0x52158f7f -473, 0x682fb062 -474, 0x52e80435 -475, 0x787e0fb3 -476, 0xe331da39 -477, 0xfad42e58 -478, 0x1bdb3f90 -479, 0xe313ab2 -480, 0xe61af9bb -481, 0x46f03903 -482, 0x926b3d33 -483, 0x2b23ce3b -484, 0xed04d4af -485, 0x34c49faf -486, 0x142f503c -487, 0x47cf6a21 -488, 0x5352250c -489, 0xf5942210 -490, 0xca5950ae -491, 0xc5302422 -492, 0x41a5e9b1 -493, 0x30076390 -494, 0x8951d0e4 -495, 0xebe74e22 -496, 0xfcb7dbf8 -497, 0xd55076e7 -498, 0x88a1165b -499, 0x1a89b5a3 -500, 0xda2c3e2e -501, 0xdc1d606d -502, 0xfda0315c -503, 0x5f5610dd -504, 0x3eba316c -505, 0x72cae07b -506, 0x5336095 -507, 0x6a110322 -508, 0x46cb153b -509, 0xa2b11116 -510, 0xe2543988 -511, 0x51f53bae -512, 0x3b10466d -513, 0x189ddd56 -514, 0x1fd355b6 -515, 0x1230e8d3 -516, 0x2050d313 -517, 0x2fbb5c16 -518, 0x64b03f4f -519, 0xbd6cdc1a -520, 0x9d423316 -521, 0xc71a702f -522, 0xf2254f39 -523, 0xd953728b -524, 0xef3c8bb5 -525, 0x685a2fab -526, 0xcea73dff -527, 0x4a7fa029 -528, 0xa27e8058 -529, 0x561a1413 -530, 0x570fc5bc -531, 0x917e93ee -532, 0x15fdbb15 -533, 0xabee295e -534, 0xc40f5307 -535, 0xba18b087 -536, 0x6ea6e339 -537, 0x7e282248 -538, 0x875062c2 -539, 0xd1520c30 -540, 0xb4cef1a5 -541, 0x55812dd1 -542, 0x9c67743c -543, 0x22fd5992 -544, 0x1dacbfa -545, 0x5b35eab1 -546, 0xfa8c9316 -547, 0x490bc71c -548, 0xe5129bfb -549, 0xe7acb79f -550, 0x87667765 -551, 0x945be067 -552, 0x8acf5c32 -553, 0x466e0ee -554, 0x8fa89be0 -555, 0x4eb4afcc -556, 0x3302055b -557, 0x8f2e3ab9 -558, 0xc5bc175e -559, 0x903a3e85 -560, 0x4055dd04 -561, 0x37873bac -562, 0x2965a951 -563, 0x2206c56a -564, 0xf34dc2db -565, 0x34e43ba2 -566, 0xb61caa44 -567, 0xfd3eb260 -568, 0x9dcdc817 -569, 0x7019df83 -570, 0x6fcd9bea -571, 0x270cba0a -572, 0xd6cc3241 -573, 0x6345c906 -574, 0xd213fb94 -575, 0x6195e5b5 -576, 0x804abab7 -577, 0xb4cace45 -578, 0xded19bbc -579, 0x617db00c -580, 0xafb933d6 -581, 0x8192cae8 -582, 0x45ffd8af -583, 0x13ae0868 -584, 0x840f4541 -585, 0x12cd1a05 -586, 0xbb5b7d6d -587, 0x3907ab3 -588, 0xd77a1582 -589, 0x4e741292 -590, 0x28c60865 -591, 0xbaad11e2 -592, 0xa9d3e364 -593, 0x88a197cb -594, 0xe90f021f -595, 0x2056017a -596, 0xeb0a2fd9 -597, 0x1d3435aa -598, 0xdaa0b802 -599, 0x8121bf09 -600, 0x95a88f55 -601, 0xa8b9c257 -602, 0xb0ab4914 -603, 0xf360b741 -604, 0x5563d4ab -605, 0xad33cf0e -606, 0x397d315a -607, 0x6893767f -608, 0x79dd5b31 -609, 0xa9ea6777 -610, 0xcf48c06 -611, 0xb4cceafc -612, 0xf53cab50 -613, 0x72426c8 -614, 0xd128aa5a -615, 0x511eec88 -616, 0x668ab20a -617, 0xb9b53dbe -618, 0x3b03a0fb -619, 0x8f416a98 -620, 0xaa15b7f6 -621, 0xc7767aba -622, 0xa64d3342 -623, 0x42cf1388 -624, 0xfc3ee7c0 -625, 0x892a2902 -626, 0xdb054bf6 -627, 0x4973223f -628, 0xb9f74682 -629, 0x72f2ece -630, 0xddf94382 -631, 0x67581d86 -632, 0x9cb9cd6f -633, 0xed74731a -634, 0xcca05451 -635, 0x3b21fdc0 -636, 0x9e18e52b -637, 0xa40bb287 -638, 0x8bb05e07 -639, 0xa33555fe -640, 0x4c819ed -641, 0x5373903e -642, 0x611403c2 -643, 0x133e25fb -644, 0x9c7a44e4 -645, 0x67197b8d -646, 0xfa910436 -647, 0xa86a825d -648, 0xfc9b24c1 -649, 0x464a718e -650, 0x7421bc26 -651, 0x3c3186b7 -652, 0xf7304619 -653, 0x7ac7be81 -654, 0xae6adcc4 -655, 0xca96bf8c -656, 0x49711d50 -657, 0x74c51f0 -658, 0x275804c0 -659, 0x228098c5 -660, 0x73a31b94 -661, 0x7f01db79 -662, 0xb36209c8 -663, 0x6ccf8677 -664, 0x70dbcce0 -665, 0xa533d8cd -666, 0xd0b0f097 -667, 0xd9a3b784 -668, 0x80a929fc -669, 0x9708f29a -670, 0x95e1e56f -671, 0xd07a0b45 -672, 0x566acdb6 -673, 0x92663054 -674, 0x3667dc9a -675, 0x80f850ff -676, 0x549dd640 -677, 0xc3ff18ca -678, 0x8c70d392 -679, 0xf5547e3b -680, 0x8dbee1d7 -681, 0x51fe33b8 -682, 0xb1ea480b -683, 0x6646f6d0 -684, 0x4a8e7de9 -685, 0xcb053e32 -686, 0x6311aee8 -687, 0xcc2a411b -688, 0x5330e60b -689, 0x4680e825 -690, 0x96bdd8a2 -691, 0x8cf4268a -692, 0x8445c833 -693, 0xc237eef1 -694, 0x459670e8 -695, 0xedf26624 -696, 0x5713340f -697, 0x5a3e87a3 -698, 0xa24a7c2d -699, 0xfa9fdceb -700, 0x746fd14e -701, 0xc6aef3e5 -702, 0x3d957e9b -703, 0xc1926f7a -704, 0xee717768 -705, 0x101fe323 -706, 0xec0d63ab -707, 0x8b8e6f42 -708, 0x8c3d2286 -709, 0xb573dd68 -710, 0x53b68ec0 -711, 0x696525cf -712, 0xdab65d8e -713, 0xd2c6ed42 -714, 0xa1fc10f6 -715, 0x1554666 -716, 0x6ed42947 -717, 0x87f7e62 -718, 0xaf34733b -719, 0xc55baa8b -720, 0xcbff66f -721, 0x2516c228 -722, 0xec6980fb -723, 0x4f53d66c -724, 0x1be17a32 -725, 0xdcfb31df -726, 0x4b17d04f -727, 0x81e1f54b -728, 0x749eae52 -729, 0x3811c4d5 -730, 0x5d11e6a1 -731, 0x535d5d6c -732, 0xbb74cd20 -733, 0xd1b18b71 -734, 0xfbf7221a -735, 0x817c4279 -736, 0xcef30b85 -737, 0x41dee06c -738, 0x9d340a3a -739, 0x691f0449 -740, 0x363a515d -741, 0x73a1af6c -742, 0x25718271 -743, 0xb4a52d50 -744, 0x1e392f40 -745, 0x3c811345 -746, 0xc9aa8565 -747, 0x357c24e0 -748, 0x19ad7230 -749, 0xed250e20 -750, 0x4acc4824 -751, 0x825d53a -752, 0xcf2f515f -753, 0xb7973ff4 -754, 0xb03ce53f -755, 0x1afad500 -756, 0x39f64ee8 -757, 0x60bea483 -758, 0xedf16817 -759, 0x88beff73 -760, 0x4909868 -761, 0x879a96da -762, 0x52d4ac6b -763, 0x46fabe65 -764, 0x88fa5751 -765, 0x71df4521 -766, 0xfc6eb286 -767, 0xf83e78ad -768, 0x885e5aca -769, 0x77e63e4a -770, 0x2bdf5c02 -771, 0x2528323c -772, 0x5b5d1ce9 -773, 0xf795be8c -774, 0x5e113b2b -775, 0xa993c7aa -776, 0xe5f8560a -777, 0x77e1e8d -778, 0x5e9db88a -779, 0xdac4e96b -780, 0x9126b945 -781, 0x15bf293a -782, 0x1dc9a8f4 -783, 0x909b48b1 -784, 0xb50ce29e -785, 0x21671c87 -786, 0xcda80dec -787, 0xf5aff1a9 -788, 0xd70cdb2e -789, 0xd293139a -790, 0xcbf4f51d -791, 0xb23c6d7a -792, 0x1a06aa33 -793, 0x21880210 -794, 0x92679678 -795, 0x8d5bb26b -796, 0x23304100 -797, 0x8f5d1df4 -798, 0x143b39ff -799, 0x29e97d16 -800, 0xbfad952f -801, 0x257ca1d8 -802, 0x32ad2f8f -803, 0x84d320c3 -804, 0xcc4c59a -805, 0xbb5ae046 -806, 0x3d5fcf1d -807, 0xa0130b0 -808, 0xad86e9de -809, 0x1e422521 -810, 0x6b56a617 -811, 0xbe64d9fc -812, 0xfff31ed0 -813, 0xd1ad616e -814, 0x13486a20 -815, 0x1754613b -816, 0x52c7b9da -817, 0xc05d75aa -818, 0xd719cd98 -819, 0x61890574 -820, 0xc4711a8b -821, 0x9afd5635 -822, 0x4dabed21 -823, 0x94f173 -824, 0xb8b6e708 -825, 0x1d590111 -826, 0x60315dfd -827, 0x7fb8ae79 -828, 0xc69f4f2b -829, 0xcaf1c898 -830, 0x861a0c8b -831, 0x6ed14eaa -832, 0xc77da58 -833, 0x8fd4f29a -834, 0xa38187fb -835, 0x6ed1ee88 -836, 0xf1a9f55a -837, 0x74368cc8 -838, 0xf327e944 -839, 0x97a578af -840, 0x8a5345e5 -841, 0x63ee0a30 -842, 0xa7e4919b -843, 0x51e26930 -844, 0x38dbe017 -845, 0xedace3a9 -846, 0x9cda2ad4 -847, 0x96b1119 -848, 0xff56282a -849, 0x71773edf -850, 0xe41fb69c -851, 0xe7bce539 -852, 0x221ffeed -853, 0x35d3f67f -854, 0x7e089168 -855, 0x6fd47823 -856, 0x43bfb28d -857, 0x9ce49e62 -858, 0xde32120 -859, 0x6eacfe4e -860, 0x116c6128 -861, 0x5f975284 -862, 0xc547361c -863, 0xf48e8251 -864, 0x2ac8a3bd -865, 0x9a0fce5b -866, 0x1764e3d9 -867, 0xa31e6954 -868, 0xb9dca055 -869, 0x1cd35c79 -870, 0x1b502882 -871, 0xf973ab10 -872, 0x8b585146 -873, 0x841fd3f8 -874, 0x4999200f -875, 0x7ad10c4b -876, 0xcf1695bd -877, 0x26c58bc3 -878, 0xdc1f8310 -879, 0x546e1e86 -880, 0x2e39fec8 -881, 0x8c65e2ed -882, 0x6469bac -883, 0xbc4af1ff -884, 0xa1669010 -885, 0x41dabd80 -886, 0x5797e218 -887, 0x9bed24c1 -888, 0xa7552347 -889, 0x4e214099 -890, 0x34d4f986 -891, 0x316cc527 -892, 0xde30c21c -893, 0x4f273c1e -894, 0xc3dd9324 -895, 0xe61fda1c -896, 0x1d0f8076 -897, 0x5570867e -898, 0x289d6062 -899, 0x465b8b26 -900, 0xb72307de -901, 0xe78c8647 -902, 0xfee9723e -903, 0xa1534c9b -904, 0x4d652645 -905, 0xe623b6c2 -906, 0x454cfc8 -907, 0xc5a7fcaf -908, 0x1de804d9 -909, 0xa2501de7 -910, 0xe036c091 -911, 0xa4a55d1d -912, 0x50409892 -913, 0x58fd2731 -914, 0xb6fd3618 -915, 0xa0180bd2 -916, 0xd9bb2fe8 -917, 0x7c8e7a2c -918, 0xd90906fc -919, 0xf8721260 -920, 0x451b372d -921, 0xeeb1c70 -922, 0xc1a18778 -923, 0xd466244a -924, 0x88e4b84a -925, 0x4fc3af63 -926, 0xcf4387e4 -927, 0xb8872734 -928, 0x276eadef -929, 0xd2c164a1 -930, 0xd3c812d9 -931, 0x5a94f176 -932, 0xfba6f632 -933, 0xf7aeba97 -934, 0x9207585f -935, 0x70a41d67 -936, 0xa0b70910 -937, 0xd579fc6b -938, 0xf06a8fca -939, 0x471fd406 -940, 0xb15a0491 -941, 0x2f340f7a -942, 0x3df02de3 -943, 0x6022f8d6 -944, 0xa15b11c2 -945, 0x45715dd6 -946, 0xf293d85e -947, 0x7a2100d -948, 0x7dff786e -949, 0x52c6a183 -950, 0x5fbce2db -951, 0xbc29ec65 -952, 0x3dd14b27 -953, 0x1bedecd1 -954, 0xbfcba31c -955, 0xb911a26d -956, 0x6b6de680 -957, 0x36e8769 -958, 0x908de4a0 -959, 0xe1abee1f -960, 0x83acd7f8 -961, 0x5008c1eb -962, 0xd8bc7a2b -963, 0x6f639c56 -964, 0xe1f2634b -965, 0x267222ec -966, 0x48fa416c -967, 0xfa01e3cb -968, 0x2d28a700 -969, 0x58dcdc97 -970, 0x685ac2e7 -971, 0x9318840b -972, 0x99247a55 -973, 0x8d749b83 -974, 0x403f8415 -975, 0x373eb9c6 -976, 0xb840b6a2 -977, 0x9bb7bfc4 -978, 0xd5800634 -979, 0x3ef4a02d -980, 0x2ffa791f -981, 0x8a671150 -982, 0x40fdfc5e -983, 0xfa4bd35e -984, 0xf4ca1642 -985, 0x17fb231a -986, 0x42a3e57c -987, 0x58cf119d -988, 0x32f19c67 -989, 0xf3e2e153 -990, 0x66fce6fb -991, 0x9d61059b -992, 0x1628eafb -993, 0x9a6cf683 -994, 0x5ff5df3a -995, 0x206fb3c9 -996, 0x1914913c -997, 0x58c002ad -998, 0xd099145f -999, 0x155aab4b diff --git a/numpy/random/tests/data/pcg64-testset-1.csv b/numpy/random/tests/data/pcg64-testset-1.csv deleted file mode 100644 index da6d77d40f19..000000000000 --- a/numpy/random/tests/data/pcg64-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0xb174ddf3fe597da6 -1, 0xfc217240c1e61e6f -2, 0x20279da26fec9cbf -3, 0xa5f4ee34651f4e1e -4, 0xb254d7901c68b9db -5, 0x6bf2a64e4052c36f -6, 0xbec4c7418c0f61b6 -7, 0xb03e595a4ef2b2bd -8, 0xc8e051957ccb74c6 -9, 0xf5082df7473c6f62 -10, 0xb72aa3dc22752a38 -11, 0x7a941561514bd680 -12, 0x90a95f42834f347b -13, 0x88e17b9d59def797 -14, 0x18f19c86bfe60368 -15, 0x667f89277be8d1d8 -16, 0x63305475e7aeff27 -17, 0xd7e4d5c09fb0fb4c -18, 0x7dd6deab03a8c26a -19, 0x42bbcb746e2d4b26 -20, 0xe91f2ac4fa90689c -21, 0x2f83458da0af3125 -22, 0x49a43537a00fae89 -23, 0xef02111d1ebc16eb -24, 0x32b3b3019875f3e7 -25, 0x89eb15c48cd02774 -26, 0xa9f1b37865752731 -27, 0xe0eff9dadc47fb3 -28, 0xae859b1c54cc90c2 -29, 0x7b7c5e04d5015dec -30, 0x38faeff5ce3266ff -31, 0xd2ddd0d19fbc24ee -32, 0xe0d4f692829a31a9 -33, 0x30a6aa3f408e71c2 -34, 0x298362be21de6d44 -35, 0xb7efab759e691149 -36, 0x2ae1f84bba093d4c -37, 0xf6ab55f78f8b9258 -38, 0x2275d0af583cec95 -39, 0x18cfe066b183ac3c -40, 0xcc0a546d54064cf5 -41, 0x5de027ea3c25c225 -42, 0xdaf31ef489fe71e1 -43, 0xa7a2b1a72a4360e7 -44, 0x678a55d7a0506791 -45, 0x36facd8799ad2b78 -46, 0x32fec94506dca70e -47, 0x34e890d8539871f8 -48, 0xec48b5362b0d7818 -49, 0xe2e58921cf8228d3 -50, 0xd163588ec22730a4 -51, 0x17e2322b6be47d25 -52, 0xe1544989a0c6d24f -53, 0xa3a10fb279cdc347 -54, 0xad4ee318a5853900 -55, 0xc96a185feef4a85d -56, 0x82ec5b3aed6636fb -57, 0x2aac2ef8f25426d7 -58, 0xa81e3114165e0d08 -59, 0xc1d8128f83969da5 -60, 0x157505508eaf50f1 -61, 0x77c175067c9c199c -62, 0x973052089bd7af0 -63, 0x3cd70041e32c1921 -64, 0x7783719f13a254a0 -65, 0x2216485ff502d9ff -66, 0x7dae695d2c7f3b79 -67, 0x809ce710156fea36 -68, 0xb90ac31262460e4e -69, 0xc1afe8019306e7d7 -70, 0x6c57638edba4ca0a -71, 0xbe6133f6ab1e9aeb -72, 0x8f5699ff0bcf341d -73, 0x69d0218df036bcbc -74, 0xf0976fd79735d47d -75, 0x82b36a795e5cc74b -76, 0x263c30766b985686 -77, 0xf7426f94511d5ba0 -78, 0x8b04f9573050ed9e -79, 0x7280d4ec202e8359 -80, 0xa8235fbd1324f172 -81, 0x6dbd5d500a809a8c -82, 0x26c53c69292bca1d -83, 0xe348f657b20305ec -84, 0x562f0e2fbb375421 -85, 0xdf2be07bebfbe447 -86, 0x4275044640683760 -87, 0xad5d68bfe4ab4858 -88, 0x3c0e57df5b3306f0 -89, 0xc9d87622ac847565 -90, 0x83d04fd9e102c311 -91, 0x71996b9c65aaf5c0 -92, 0xe3df32742d6fc446 -93, 0x58d3a6573a39d0cb -94, 0x74dfa090e96d289d -95, 0x7856f45e5416c1ea -96, 0x80a18e88b3e4dff8 -97, 0x60565bbcb04f56ac -98, 0x9f4cf5ec45fae3a6 -99, 0x885d2909fe34e3f0 -100, 0x7a1db9118f60dee0 -101, 0xc4c17dc810746c7e -102, 0x8b954b14effe83b1 -103, 0x4f89fb0940999c86 -104, 0xc62e634bceca1c97 -105, 0x7e06e87dffd1619f -106, 0xd1ccbce841371671 -107, 0xe7f99698c66df1b3 -108, 0x5302c2f0e4e1f4e0 -109, 0xa57d11d3d7ee652e -110, 0x8abe0ed0e5508407 -111, 0x6780588af9f6c2ff -112, 0x8603a9fc73b6a4cd -113, 0x169c13a0b7a166b9 -114, 0x868969fb53578598 -115, 0x6089e0eacbe69039 -116, 0xf82482d424397dc2 -117, 0x11475d20896fc890 -118, 0x7983933df29e2aa0 -119, 0x4889c4780cd8e9cc -120, 0x53ebb258f3ea266b -121, 0x121896059b256fd1 -122, 0x2f9934516b2f8090 -123, 0xbabb9fa1d1efa60c -124, 0xfb0b1370ea044797 -125, 0x782ab293b597bc8e -126, 0x297fc0b3977271f5 -127, 0xa573e4d0674d02fc -128, 0xc7e8ddb6efe8a2db -129, 0xaae8a024e62f6e32 -130, 0x3217a47698c9e439 -131, 0xd7015db847a3de0b -132, 0xbc0b4368776e10a7 -133, 0x69d9ef0178679bfb -134, 0x28fd8f0936b66fab -135, 0x45b1c4d4aa9b5aca -136, 0x28feade39cd3ac00 -137, 0xa7e6515c534520f1 -138, 0x735703b5f4bfd54e -139, 0x798271ae0c91b8d8 -140, 0xf858458f9efa8d2 -141, 0x6a41f5845422a9e -142, 0x7fb0bba5f097aab0 -143, 0xbfaea58fe090e745 -144, 0x84770504bfb15b35 -145, 0x67ae11aa368049b8 -146, 0x846c5e493ee15e4a -147, 0xbbcf3baf029f056c -148, 0xd30c23bde142a356 -149, 0x32cd403edb746a8d -150, 0x40161ab00c636730 -151, 0x3a882c3c60d3e19a -152, 0xca8faab24d826529 -153, 0x241a687288551d04 -154, 0xbbc607fb9b48ac00 -155, 0xa844329d0c2d475a -156, 0x8fa4aa1d7296b9e4 -157, 0x82c7dc1f588ce2fc -158, 0xcbdaa663041e078c -159, 0xec108d219b2b147a -160, 0xcab01864270b334 -161, 0x6d3d08545041621b -162, 0x2aae054b8e5648f -163, 0x1bf5a72fa70e7eab -164, 0x2dddb2050af45a3a -165, 0x2b910b7078021a75 -166, 0xf7160201ede45f4e -167, 0xfaf75ae996f079bb -168, 0x407984a9451e659c -169, 0xbdf9c0a9ea078ac0 -170, 0x1e7717b8345acbb6 -171, 0x25cc2df4c0c8dc4a -172, 0xfda1715b573850db -173, 0x50e5cedad99e2651 -174, 0x9a67673ed73cfc0 -175, 0x802ec4fc9e946805 -176, 0x677cd320e641999f -177, 0xbfeb1b6053fe4f78 -178, 0x220cfc90bd31541 -179, 0xe4fdfae10ae6c86f -180, 0x76c568fd869af80d -181, 0xd17dc57109200bb1 -182, 0xeb96ba01c95382be -183, 0x6a9c7ebea5b5f7ac -184, 0xc1680450532fb8cd -185, 0x26b0829f68888094 -186, 0x98335aa1612d7c70 -187, 0xad8662125bf32ae3 -188, 0x15f18a9025ae26e8 -189, 0x5d065dba0d17c9fc -190, 0xf68e1d59f10ff109 -191, 0xcfbd97901a79f8b0 -192, 0x3e72a9fd1d95f143 -193, 0xe7ee82c1bb740dfd -194, 0x3a0f4ae5db22527b -195, 0xf4d025080ed4ea92 -196, 0x6924a99549b4657 -197, 0xcb83b51552208e2f -198, 0x9f306634214b44e9 -199, 0x4fb3307b0e1a7535 -200, 0x73d202d4225c5394 -201, 0xd5a2fa42f8cc8c5c -202, 0x7b3b3e3f7b948d3c -203, 0xa2dbc4d30d8c148e -204, 0xd1bfc1f05a8f2c5d -205, 0x2b00a4efa2f19262 -206, 0x9d4a05bb18647f48 -207, 0xff21fbaf0b46d13f -208, 0x126f9c5f2132af20 -209, 0xd4b7629b0d9a6b89 -210, 0x2d61949fb3126ecc -211, 0x30d61648763db1ce -212, 0x9c5234d15120bf17 -213, 0x2eb0eccb6cc14c8a -214, 0xcf18eff5ca2af8a4 -215, 0xab5fe599ea68c377 -216, 0xe47a0bb8436af89 -217, 0xd3728a566187c400 -218, 0xb8b54592b62f633e -219, 0xe02b958f9c13a180 -220, 0x9e5f5cc85283f24a -221, 0xbd1ab869878744a -222, 0xb93fd6297a29c8dc -223, 0xf22f06ee61dc2413 -224, 0xc93fe440766cbd8e -225, 0x7459d9b19375a51c -226, 0xd4ec87c57baa4127 -227, 0x1514d0226dc0409e -228, 0xc6b0d7e1bd56b190 -229, 0xc0c61c73c9dbffee -230, 0x2f1154afb48a93e2 -231, 0xd2ca05901bae0117 -232, 0x6263f647273694a0 -233, 0x94a98bf80488205b -234, 0xcb0d63747735bead -235, 0x9cbd4e1659932c5b -236, 0x1807e01931b5ade0 -237, 0x1d9f7721d3067854 -238, 0xb25dbde4ec77e547 -239, 0x4b186592a39adcd6 -240, 0xe8ad5514de72a98f -241, 0x2deac1cb096a09b4 -242, 0x6952f4b82a2c87 -243, 0xaa1590223ed83ffe -244, 0x9baf13d08f572e12 -245, 0x83ec1bca1e724d88 -246, 0x5c61bf2222b4907 -247, 0xd950ff64ad7b956e -248, 0x36bf5e992bf1f211 -249, 0x75ad67249d7a6c35 -250, 0xeb12dcef5c2bfe7d -251, 0xc508da925157e39d -252, 0x91cbd7491ea7f70e -253, 0xf10c018ec0b0e55 -254, 0xeeffb21fef1e87f1 -255, 0xe31692b834d067dd -256, 0xd69bbafdeb5c0d15 -257, 0x41358dadb9260eb1 -258, 0x5fa3c67d353cd6b2 -259, 0xdbb743cac20b2eda -260, 0xe7877ba98b2bfe4 -261, 0xf14d679436fd2dcf -262, 0xa313e39059d62afe -263, 0x7eaa134c761a6183 -264, 0x7719af9ad1fecaec -265, 0x533f921a4702d433 -266, 0xe072f9665ec3a3c8 -267, 0xba89560ab4ba08fa -268, 0xe94f0aa266e56d53 -269, 0x774b84bcb152afc -270, 0x787c9517e589748d -271, 0x3831a5303adfd362 -272, 0x19cb20184a4264f8 -273, 0x9bc5e99e1773700e -274, 0xed323bf38642f651 -275, 0x860868c0eba789f2 -276, 0x8c1602ffd9a5621a -277, 0xe298d8fc74e146ce -278, 0x3181a2083c76037f -279, 0x27942fd6842079c0 -280, 0x38fe8c0406516df -281, 0xd211a4a42857bec3 -282, 0x56002508b351879d -283, 0x2472ed93614c7e99 -284, 0xbcafdaadc0f77b7c -285, 0x86becbd3e5303107 -286, 0x930251d84de72320 -287, 0xea79aa2964954052 -288, 0x6dbc5e63b50b1724 -289, 0xb098535ed4bc7372 -290, 0x6490d6d8541fb656 -291, 0xc738f6ccb4b7076b -292, 0xd69ee4fd6ce63026 -293, 0xfa98e9d78a628338 -294, 0x9c30b63a70d607b6 -295, 0x8d544b5d224a25d9 -296, 0xa051f7fe38445228 -297, 0xf6931861338a00f5 -298, 0xecd71cd64b0b5dcd -299, 0xdbc818e7126193b -300, 0x3aaaa032aad8199a -301, 0x6fd68a3818e0c439 -302, 0xc82a651ba9ede8c9 -303, 0xe6d958e267017187 -304, 0x73a9eab64de651ae -305, 0x5a6757f7f222bb3c -306, 0xe62e7cca6bd17a32 -307, 0xc4f6c31f528dd387 -308, 0xdecd8b663c995773 -309, 0x69a21dedcbfef9c7 -310, 0xb33f8ac00f17b6b2 -311, 0xe32b3c962d613ba3 -312, 0xa9c317d026600d41 -313, 0x901d971c49671213 -314, 0x46c3f3d35db8808b -315, 0x1336297232af9791 -316, 0xed88d9242e11edb3 -317, 0xc70c48843f54af0 -318, 0x611062a0461deedf -319, 0x7e3183514f127f20 -320, 0x7b549d10bace1c47 -321, 0x6db523d19d0a7af3 -322, 0xf6e677e5222a21a4 -323, 0x28e5188ba7055c32 -324, 0xbe7b41d2ce539c4f -325, 0x5c085a18c3b7bbe0 -326, 0x209cf345b3c3b06c -327, 0x79ca5407dd486857 -328, 0x8e07ac4c65338ccd -329, 0x56dd5372249cadad -330, 0x27e0b07863fa27ff -331, 0x78dec95d299a8699 -332, 0xbd5d71253b73d456 -333, 0xbf83b6cedd205e9 -334, 0xee2352ee69aa68e -335, 0x4b14f253d684cfbc -336, 0x12ffa5d5f8a34bec -337, 0x2e38346fbc793f67 -338, 0x2ab5862872b4850b -339, 0xcbc8aec1e2bb6760 -340, 0xd79ef783845cc329 -341, 0xdbdcde91e1685704 -342, 0x29880643aa1095e4 -343, 0xcd5ccc1fe9a616af -344, 0xc7b6cdc4a43c132c -345, 0x7b08597fdec7fc9c -346, 0xa01ab3827e120a16 -347, 0x89ce37de99ca7748 -348, 0xb4644823ea6b90d5 -349, 0xdbe189861c409209 -350, 0xbfeb614759981b60 -351, 0x48c2c3a6d2419755 -352, 0x1aa1df0e99b3417e -353, 0xb9f061bf98c0da28 -354, 0x8bce2755a0b5b8ae -355, 0xc9bb2ff33d60b3e7 -356, 0x6abcbb1ea0d3a575 -357, 0x983a3c16a0e5d6f8 -358, 0xa122e616797ccdbe -359, 0x751dfe60252a01d0 -360, 0x8d1bcbbde84f6a11 -361, 0xb6bc4f2942ba0e57 -362, 0xb298977a4bb20e12 -363, 0xcf658188dd931722 -364, 0x39735757b19c90a3 -365, 0xc2fcf1df99f1b7c4 -366, 0xd42c50f6a912aaea -367, 0x95d0cb8a953965c4 -368, 0x75c7d03289269f25 -369, 0xd8d96184031fb36b -370, 0xb3b34b5ba8bac75 -371, 0xcfbf16d241e46f8c -372, 0xec465e59019b6f6f -373, 0x4051ce0bc2562a63 -374, 0x859f05ce7b75da05 -375, 0xf2661ef2e3c733ef -376, 0x8067f432dd5af0c4 -377, 0x6e8542a346911713 -378, 0xfcda2ac6aa45ca20 -379, 0x571f23fdacb25fe2 -380, 0x2546f5badf7adb8b -381, 0x929ebe6fbd330e2b -382, 0x9d41d6ded9facbeb -383, 0x4cf9d9da6c125106 -384, 0x495d5708443faa36 -385, 0xb0023a41a6057e59 -386, 0x37fa1cd9ce66b20a -387, 0x96a376fca4aff5a8 -388, 0xc22469c4a3e1ea85 -389, 0x5ab79b721966249b -390, 0x2124be452f7d4ca4 -391, 0xe71bb882b954ca11 -392, 0x322bdcaf9c7b0efa -393, 0x4c99c8753878439f -394, 0x3ffd6caec9f9ac49 -395, 0xfba842dd40a3c72e -396, 0xfd93517d31681d77 -397, 0x44c139a74249a128 -398, 0x828a145610684c8 -399, 0xb53696f802522b6 -400, 0xa2da2199474d079a -401, 0x739e508fbbdeb714 -402, 0xe75c4734a7c95f94 -403, 0x5c22c226f2bd8487 -404, 0x7108fa6b99b0d72e -405, 0x3c60b40f6e4bebde -406, 0x395150555d56dd18 -407, 0x13246a6e4d795fe3 -408, 0x27dca990fb678027 -409, 0xc5a92c32724a7373 -410, 0x30fed89f4171a817 -411, 0xf7f7810edea2e7eb -412, 0x46e930eef5351212 -413, 0xe1331cd8a678dc66 -414, 0xd4cc0a5f96a72457 -415, 0x2559f8d286b1da16 -416, 0x73831b2f6e4a4ba -417, 0xd929ccf267504761 -418, 0x8a7a1b357f8bbc38 -419, 0xd5e0d3e200d0d633 -420, 0xc2cc05cc3ac5abb -421, 0x75b8f78a06ca465b -422, 0xeaf1d6aa9c0baef3 -423, 0xa6c9bc3dbe45e62e -424, 0xb1496074b4c338d7 -425, 0xc18ebb892108cec -426, 0xf6cbbf4cd0f8f9ba -427, 0xd73759407ecbdcf6 -428, 0x54dc0805c85a3b0c -429, 0x4ba3936d6be048f3 -430, 0xa3fbea19803cf35 -431, 0x78b1d3a837d4bed -432, 0x6ed09ac2c177453b -433, 0x16134c4e8b30f6ba -434, 0x94718ce4868f01a3 -435, 0x612fa336da82e66d -436, 0x5d8833c9483b235d -437, 0xf5c72d4883bed9a2 -438, 0x2a6e27d1ed337134 -439, 0xfba250d6b9cc0d2b -440, 0x432f8734b61e4366 -441, 0x45e8becd5ccb4f32 -442, 0xffc7d68cb343170a -443, 0x247cb9a6b29b1a35 -444, 0x89876df3681dc65 -445, 0xd1e646c49aac769b -446, 0x4c3cd721635602d0 -447, 0x5139344709c749fc -448, 0xc5130d981e1a6b14 -449, 0xff269bea082608cb -450, 0xf45a5d57a6d4c6a6 -451, 0xc4c9f3e5398db827 -452, 0x2b3a0eacd42665b4 -453, 0x94d847d848a8e65d -454, 0x1a8aff186e1d75d2 -455, 0x6ad986366c54a242 -456, 0xbd832c0607523e7e -457, 0x973064c20c31842d -458, 0x34d0513e6d602f80 -459, 0x91b3c812f83392ed -460, 0x4c49ba38b6a4cf90 -461, 0x82e3370e1c5ad5d4 -462, 0xa29a01fa53250a13 -463, 0xbe8ed1e615a1ee6a -464, 0x17fb15941a9fe6b4 -465, 0x84aea1c0138fb970 -466, 0xab065efb4558003d -467, 0x3345b340257a2551 -468, 0xfd2ebda1048c0dcd -469, 0x2aa72fce0cb23982 -470, 0x9952f9363830ff6d -471, 0xdb240e279cb7f901 -472, 0xb4a1e7b54206aca4 -473, 0xe13bdbb980623f25 -474, 0xd989f009368f8a9a -475, 0x7084b7695149660d -476, 0x55b92a3f139c7f1 -477, 0xdb43c75c633debd0 -478, 0x94e362574c70b9a8 -479, 0x218a1a06d9223f9b -480, 0x82f3c3808f86bb95 -481, 0x63e9de6cee4b77b2 -482, 0x3bc5effa36bb166 -483, 0x8369cbe5fa0ecab -484, 0x2a5808b4d7bc8572 -485, 0x6856e29700de99f5 -486, 0x107e86fcfd4a48d9 -487, 0x15c9ee6528c1c223 -488, 0xbf7318d4206c5e75 -489, 0x15d7a6aa9343c9e8 -490, 0x93419fe0ee3bd5df -491, 0x916c7f75ededdd53 -492, 0xe89d6230690f74f1 -493, 0xf92f96834e0eb27 -494, 0xed5adc06c305adc9 -495, 0xf656fe40e7ecb4d7 -496, 0x32a2d3eda46114b6 -497, 0xb3f17867d23c75e2 -498, 0x2a2cc838c4d89c33 -499, 0x413df7052f8866e7 -500, 0x373bd93e91bbed18 -501, 0x78c8e5aa1e1e2dda -502, 0x6bd362f6be6d572b -503, 0xba1926efd387aeb5 -504, 0x3b826b77ae3e53fd -505, 0x383cf5a66fb6723c -506, 0xf5a4e1dded64d931 -507, 0x76d9843a304729d3 -508, 0x205b8753b6d309f0 -509, 0xd2a68ef67d8e7758 -510, 0x60d517f325411c0c -511, 0x37a3bb4950cf08d5 -512, 0xea3d4f95542ffe2d -513, 0xa88708db07fb1d34 -514, 0xd96555e1194f7ee0 -515, 0xdd046e642b59fa51 -516, 0x18ff34e73582d46b -517, 0x7ed73af03535c5fe -518, 0x8ffd64801d2c5187 -519, 0x7134902903c9cfe2 -520, 0x74fa0b238ad1e1ec -521, 0xa220ff0032395fd5 -522, 0x4ed0a7a2d9c3a064 -523, 0xb02cb878b4c9a04d -524, 0x8437cebea5ae2bec -525, 0xabcc162a0027aefa -526, 0xc8e86ab8f5c09011 -527, 0xc28dfaf764ec07d4 -528, 0xb19127d64ae5db18 -529, 0x857cb1b00ac7fbc7 -530, 0x173a441c4b494aad -531, 0x255af1a4d50952c3 -532, 0x87ff01c7d0139add -533, 0x489b15e4c97cfcde -534, 0xd4abbccecfb67239 -535, 0xa1a2912ad34ac4fb -536, 0x94b7f12e10bf720 -537, 0xdb8840c295333634 -538, 0x5a29aab5b359f2c0 -539, 0x630352d282b695bd -540, 0x399f00854d3fbdf3 -541, 0x19e917e0eb8bf070 -542, 0xa464b4dc93d1fe7d -543, 0xf152d3cdecbd7647 -544, 0x517907b570a6b082 -545, 0xfeb06f4bd978e7bc -546, 0xa22859ad14c0f183 -547, 0x33c11e90be9721e3 -548, 0x8394f642b5a40d7d -549, 0x9525633e7e60ab73 -550, 0xf97401c9b4b96001 -551, 0x3d78ce1ecf900029 -552, 0xa85791d9754a2765 -553, 0x16e77aadd9a30946 -554, 0xc91d4defe72f39f2 -555, 0x2fb67bd91edc4b51 -556, 0x95d635e95b468fa7 -557, 0x28b81869d1739e29 -558, 0x5b098fa22cb1747f -559, 0x6544b8704bd2400a -560, 0x91a64f9ec6e93245 -561, 0x2b46ba92268db263 -562, 0xbb52d7758efd5416 -563, 0x7032adc08e6d39da -564, 0xe9d3bbefdb61feb6 -565, 0x2d603389c757996b -566, 0x5871ed32ce17d042 -567, 0x31d622a6b8438f70 -568, 0xc71af17db6bf7aed -569, 0xe419e3c6fbe86530 -570, 0x648471d670f18dcd -571, 0xd13f9e25078599ed -572, 0xdaf86e56826d07a3 -573, 0x3c9374e4420a8580 -574, 0xcd75b12ad6d8d9fe -575, 0x2d4530f6e2b93ca3 -576, 0x303bb663ad4ca963 -577, 0xf8caecede4436b61 -578, 0x315a8124669a907f -579, 0x1c18d130a4b93836 -580, 0x9e0b83663631562a -581, 0x400059c1ce071c7f -582, 0xb27f7f67e7cbd970 -583, 0x6b446e8c4866f3d0 -584, 0x4ab1755d2734121c -585, 0xb9fc8e017d89edf2 -586, 0x3a9aa7f50355c0c9 -587, 0x899fece06a169b2e -588, 0x19d7d7088db0b27d -589, 0xe4f8862ca8f6b87e -590, 0xceaf0d6ab4ba624d -591, 0x318965c56f79886d -592, 0xb1840d9bb60b720e -593, 0x387427e7549150ca -594, 0x9be3edb621a5d2ef -595, 0x9758993cca6a481 -596, 0x3733c5cd48a1590c -597, 0x9bbe26951c666fb1 -598, 0x74c7e89fefb4ba59 -599, 0x6aa490a23907053f -600, 0xa62febef1e8d7300 -601, 0xdbfb07bbba2fd4cd -602, 0x11ee9e4bbd4f358 -603, 0x6b40912657c7f02f -604, 0x8d56c1a9216714bb -605, 0x7fcd86985949c2f9 -606, 0x706bb172d5677f2c -607, 0xfb657efea1331957 -608, 0x6e3032f72a3fe367 -609, 0x509fb8c5b618a18e -610, 0x3599e957259222e7 -611, 0xaafc78bea53c9102 -612, 0x404addaf7ac55279 -613, 0x97db28b3b0a2dddc -614, 0xd3f5b151a9f5aefb -615, 0x1a6534a9be80a19a -616, 0x78f989eb80e055b7 -617, 0xe0200fe015112dce -618, 0xfbe67decef6204dd -619, 0x662fef92c8e00970 -620, 0x9a7838962250f5d7 -621, 0xac0eabb1621567b3 -622, 0x1874cf715cdc5daa -623, 0xd3281a25a82ceecc -624, 0xd8ac0e497b11156c -625, 0x3c8bf98f8210af89 -626, 0x971973ff9d428a3f -627, 0x1af47276bc157e63 -628, 0x671cd5e661ed0a05 -629, 0x71b8ffba9b976a0 -630, 0x8763f1fa85c5f5d5 -631, 0x61f3c56f3441aad4 -632, 0x86482f5e90362e3c -633, 0x8e9d9aceba401c48 -634, 0x51d916579d19d42b -635, 0x67bdfa28310ad3c7 -636, 0xb9ab819d6a00add8 -637, 0xaa12cb0ed2d507bf -638, 0xc636190dfc7f6d43 -639, 0xf3f1e6c104c5e782 -640, 0xaed0be2f07ad4313 -641, 0x1d782d74661278bf -642, 0x58e6501bc7e61fa2 -643, 0x8ca4ad0e02d7fb42 -644, 0x8afc9e9fe83d4b78 -645, 0x72cb69cf4abf0b1d -646, 0x7601a7b3500d474d -647, 0x97fee7da53b533b0 -648, 0xd6ab646f53c0e19a -649, 0x6480f60992f2fcc0 -650, 0x64ec7590c60a4c00 -651, 0x3ccab37f11acbe91 -652, 0x9ddd546f201299fd -653, 0x9a0dc59d0b545d96 -654, 0x8c5f366bd21664f5 -655, 0xc0af97b445bfc5ee -656, 0x29762536dc00c3fc -657, 0xfc30927fd8f1c257 -658, 0xac9aadfced7d59fb -659, 0x8d039f87658a29cd -660, 0x13a3d73580eacf6f -661, 0x80b80e0adcc11ac5 -662, 0x1e53c21e639f9d08 -663, 0x8a73352dc442bca7 -664, 0xec7cb2fe0e6b0100 -665, 0xfa5e63f403ac3f33 -666, 0x493d9a0018185f8c -667, 0x1b1d1f41c6cf5cb4 -668, 0x95b4caca3e2500a7 -669, 0x4e759e6f89f62f91 -670, 0xd0a76a3198d7c05f -671, 0x86eee6259cab63b5 -672, 0x1daab21067011b59 -673, 0xd02d9236ebc91b38 -674, 0x693e17ac2b70e1b7 -675, 0xceb5899aa14d0f86 -676, 0x59ffc317faf17ab2 -677, 0xce94f02892a0fa30 -678, 0xf7c9d6f9e753737c -679, 0x87258cf7ff6a29b5 -680, 0xb39fc8ea8aa52a0e -681, 0xadd4b4e73af1103f -682, 0x511f423730b25a4e -683, 0x7f673288e53502b2 -684, 0x9aa499e3b6295919 -685, 0x83841ad95e6a7a6 -686, 0x6e549a2457a850c -687, 0x4763220b923113c3 -688, 0x99737bb550aa5049 -689, 0x89eb31b3f707c4 -690, 0xdad5331dda8a58d3 -691, 0x5f1681518d5a21b8 -692, 0x258a0b9b24110918 -693, 0x8854bb025009fa21 -694, 0x7ac331fd885642af -695, 0xe520f0e9bedf0bf6 -696, 0xc9419e8801aa2afb -697, 0x356fdc0fc3702b37 -698, 0x6d6a25f39fbc9524 -699, 0x930f65c4dbf8ae94 -700, 0xa73d7bbf8c19c4b3 -701, 0xe473f700513139fa -702, 0xfef8f0e84c521bae -703, 0x88525351995576a7 -704, 0xa156b646ab95f272 -705, 0x1a46ff3b9ae7e723 -706, 0xf6d82b8bd9f2a80 -707, 0x837b8127d8f39ebf -708, 0x1f8e120ea11fc9bb -709, 0xbd0918421430f8c9 -710, 0x4ef121a688d130c7 -711, 0x3fef66f1cf180b77 -712, 0xa92070bdc6a0100 -713, 0x2444dcbb4853c174 -714, 0xe46b7d6234504df8 -715, 0xe5ac8fd968a5d1fd -716, 0x988828d885f04f30 -717, 0x9730c37b69f3d963 -718, 0xdb9a0d16bf0a2aab -719, 0xe75d00b3681941b9 -720, 0x518421d62db82da0 -721, 0x4da04c94268c1dae -722, 0xdcf2635a55b7da9e -723, 0xb679d8206c55a04c -724, 0x1fbf58865fec1e83 -725, 0x53ca7cc07c0e5785 -726, 0xd18eee3f5b57c813 -727, 0x9fc8d328e41d1299 -728, 0xb2231521e026e15 -729, 0x1a7e2a8df269acde -730, 0xe5f547b160b0a6de -731, 0xab01e7130bd70c14 -732, 0x82a051680f661a75 -733, 0x479da77dd9686ca2 -734, 0x1417cc197738b272 -735, 0xb65b5ced585a8186 -736, 0x40b5a74813e7a05b -737, 0x55481e0f404fc2c5 -738, 0xef1ca09a2640c44a -739, 0xa0f1d37ee2db47cf -740, 0xcabb0c8e551f0587 -741, 0x84227dd83ad941ef -742, 0x7b47691b6e8327d -743, 0x4fe615394f53d6d2 -744, 0x60bca7e568f65c80 -745, 0x8676b74f2d5600f4 -746, 0x70f256171f1eb9b1 -747, 0x6b1d25099f80e1fd -748, 0xd8e77e8a67ff3338 -749, 0x3ec375feb7727aca -750, 0x26b9ad4afd4be26b -751, 0x849e6f9bc5ec636 -752, 0xa34e3fad187c089f -753, 0xe369ba87f04ecc37 -754, 0x83c6e1c3985cab4e -755, 0x6ffc032379a15336 -756, 0x654645504b159afc -757, 0xabc97562087edfad -758, 0x4633765a9f068fe5 -759, 0xa226c586394d348b -760, 0x7034d9fd40133a22 -761, 0x89e1d142a1a20097 -762, 0x7a3e1387a5ecdf70 -763, 0xf0ae75084f0a1bc4 -764, 0xdcf97778ae782977 -765, 0x87996a44dbac128d -766, 0x94b102ac15479072 -767, 0x9d670a01e10c48a0 -768, 0x8f977a03176d0cb1 -769, 0x8522bdbed25653c -770, 0x8f2b64a9cd6b5483 -771, 0x86b2beaa71c92fbc -772, 0x40f896707639f820 -773, 0x40e7df1535fc03ad -774, 0x1d34c491e13debde -775, 0x862d5ad393292476 -776, 0xd33ee4efdd4b14d9 -777, 0x63ce5c7643b85ecd -778, 0xd28a7fe0700fd15 -779, 0x8c3536390f9b7b55 -780, 0xfaf87a9036dd0265 -781, 0x187e261c23b454a5 -782, 0x95362150f08e5f86 -783, 0x6588c21939d9521d -784, 0xc7cee242280b7526 -785, 0xc1b8f83462038485 -786, 0x68c2f342724de8d6 -787, 0x35c283dbca3c62fd -788, 0x556c441e9fdc5cee -789, 0x898ba42c4ad3f5ba -790, 0xc654a072fe9ce540 -791, 0xcc2da7cabdc658d4 -792, 0x518b6badf9c1ba7 -793, 0xd43b259427de48cd -794, 0xfe7e74d4415bea8a -795, 0xdee4cacb454d92c -796, 0xdfb09dde6d6c3000 -797, 0x5c0d4ce2c7a8d426 -798, 0x29ccf2d288f4de4a -799, 0x4106e7f40d2597ad -800, 0x3bc376950bccf69 -801, 0x65b74e149d1066e3 -802, 0x751d008e4f823e5e -803, 0x4a3b9a34d8ece205 -804, 0x372e79ed6d9461fc -805, 0x78e08cab6244f8d2 -806, 0x7d273315b6d9250b -807, 0x26c401cb05f556b2 -808, 0x3324d95fbc93408d -809, 0x14fb55fb83ab0a8a -810, 0x7ea7efcddd0a747f -811, 0x150a110bd5cb1b57 -812, 0x1122b31f5d20ad23 -813, 0xbd996a43507da1 -814, 0x6d11fad057e5a75a -815, 0x22a4d3223d77684b -816, 0x349973b5dda3d3e8 -817, 0xe4dab5aec267e32d -818, 0x371cbd61bbb7858c -819, 0x7e49182abfc0fc68 -820, 0x937722b126a7d173 -821, 0x29604490ccbe6611 -822, 0x6c8b230bdcc8dfaa -823, 0xb1c267c94d4550ee -824, 0x80d1fa6e33cde91f -825, 0xe205a132f35af0a7 -826, 0xe4e8e50899fea5c8 -827, 0x3a6517d09206dfef -828, 0xeff4e4f8efd0a4ba -829, 0xd8df88c992b3df74 -830, 0x5b0df3c40071c0ac -831, 0xd44a062781f833f0 -832, 0xef35653edcb68251 -833, 0x21f879df2bd3cfe0 -834, 0xdb5e837565891932 -835, 0x6da15316efae41e7 -836, 0xd33cdc0d05f8dd6d -837, 0x3c6588502a24be1c -838, 0x3d25da26bee94818 -839, 0x79979979960d383d -840, 0x8a20663424f816ec -841, 0x74c587d5824ee15 -842, 0x145f90c6b342c489 -843, 0xe2c2d15b8de95387 -844, 0xd9deaecc24e84ede -845, 0xce52add2f5c3ea3 -846, 0xd1da2db8cca0014d -847, 0xcbeed544f8791232 -848, 0xb55b421de003edf0 -849, 0xde102a5a87a9a5da -850, 0xd74fc9d34c964bd3 -851, 0xda7e1e271d197070 -852, 0x1167b33a6bad0d13 -853, 0xd35c886fd0e28798 -854, 0xfb3334085bbcef67 -855, 0x88f4957ddc912f99 -856, 0x7c1b0e356835cffa -857, 0x8c737bc009bf5a1c -858, 0x44edc242bfd88b0f -859, 0x391f8b5db15f8b01 -860, 0xd44794c8a4245701 -861, 0xefa90e38ba4a2f6e -862, 0x597f65c886e697b4 -863, 0x28972f6be3ca8677 -864, 0x18a487b5e89a9dbb -865, 0xffb15ebcb8a15fb1 -866, 0xa1f64108b7feeab0 -867, 0x36fc88b440612004 -868, 0x72a723294ba9af87 -869, 0x1a38da0ff8f187d7 -870, 0x529d7f6cd18f664a -871, 0x6a5941953b4732c7 -872, 0xe91243bd8fb27a03 -873, 0xb80c55de03262828 -874, 0xacb9183e5b28a8d0 -875, 0x4c4ca12eb3d5d2e5 -876, 0x758635a20eb18211 -877, 0x211e03e90d6bd001 -878, 0xe36e20fbf0f271b5 -879, 0x4daecb676fc64ebd -880, 0x8f1e82c4dd582eb7 -881, 0x6e3c35a21bca1b8f -882, 0xf3c2a69420f159e8 -883, 0x2cda4d630caba89f -884, 0x4c93f3f96360d308 -885, 0x4192046fb5e9d801 -886, 0x349f2b172f49599c -887, 0x7bbff8dd8b480e6c -888, 0x83b33fafc4388bf -889, 0x9a5440f806d9d1b -890, 0x8d6b62101dcfe51f -891, 0xbc7dd6987af227ca -892, 0x4338e67e0d6ba6a0 -893, 0x4a23deabbb5fc3ce -894, 0x9f8edc91e6356eb8 -895, 0xf6b723dd2dd5f80b -896, 0x35c558dd3443021d -897, 0xa559dd33c2cf594d -898, 0xa50ceeced7a82783 -899, 0x21107b581db4ee9f -900, 0x13e8dd9302e8c97d -901, 0xbd8491f437e57ad6 -902, 0x72f4c2a57c06f35f -903, 0x518fbb95071d8d7d -904, 0xcdbbe8d47f9b13e9 -905, 0xe8152b0f387251cd -906, 0x411070a4f345676 -907, 0xc589c285b962389 -908, 0x8b0eb9e285844319 -909, 0xe2b007f446a21b38 -910, 0x868ffafb958a6c40 -911, 0x19ccccd559408de0 -912, 0xa7666f366db0ae71 -913, 0xd78c5f137da6dbc2 -914, 0xeeecc913fdb9af03 -915, 0x7a5afb2f3d54a396 -916, 0x64fadf73d7ba200b -917, 0xaa1b82c6b4b346aa -918, 0x9a312d9482244a60 -919, 0xadb3c0a30f68d0f4 -920, 0x21eee75a717008c1 -921, 0xcda2779023f54837 -922, 0xea3c577c6d7783e2 -923, 0xdaae89efcd431a13 -924, 0x9a6102d2dafaded8 -925, 0xd29443448e01734e -926, 0x6b968e58c3d5bcd0 -927, 0x13949d0c5c0f9d19 -928, 0x7053eef909932489 -929, 0x49fb97e33c279171 -930, 0xc955e4854e254d03 -931, 0x3300cb752a7834fd -932, 0x8319585b09da0928 -933, 0xd35c64e4ce23a294 -934, 0x9a41d980ba1774dd -935, 0xff570729be1f3f02 -936, 0x3f68ae1c3e690a41 -937, 0x6f58a3e861159e42 -938, 0x111d9975e94f0004 -939, 0x276d3ea0ff1ca6c -940, 0x4209cb1f5ca1c594 -941, 0x71699dc4c58f1bcf -942, 0xe0288bffc5a27a2e -943, 0x6c0962c36163c4f5 -944, 0x3a8ad088b4fd204f -945, 0xb945dc7721092d36 -946, 0x315f4c1738bdf365 -947, 0xe07ddd7121cafb70 -948, 0x626fadaee66f331e -949, 0x6fe3f71dd5e7ebe1 -950, 0xe3cfb6b53bd8713c -951, 0x30f5b732f7070968 -952, 0xce2f941f93b957f2 -953, 0x116897bad7f55bca -954, 0xb9d2c4a98826c3ff -955, 0x9672c28485d1c95c -956, 0xd0656535c3df1e44 -957, 0x15294f18a999528d -958, 0x82a98977ad1e933a -959, 0xddd17b6eeced5f84 -960, 0x9901a04270fa2d5c -961, 0xcd2a8d3ab69a0c62 -962, 0x706bf86127a4597b -963, 0xe614aa96ed708afb -964, 0x7f6361ae8f59987 -965, 0x6a355657b59c4874 -966, 0x5211dca87f30cdd -967, 0xa21cbbc602f58ee4 -968, 0x68dff176c9b02a7b -969, 0x68f89bb7bca83c5a -970, 0x229cb884febc7e56 -971, 0xce4f300cf6b70884 -972, 0x6ad3f343c76c5e0c -973, 0xb059a099f121222e -974, 0x9e990641d81a63b8 -975, 0x5564e79afe160ecb -976, 0x2a9fa9c590511dcb -977, 0xca36751ba40931da -978, 0x23a332a9fe1104aa -979, 0xdfe116c321547662 -980, 0xf484bfbe18f2c1cf -981, 0xf8f2b4adf2d1ad4 -982, 0x4308800511929ba -983, 0xe2773c41e0082a51 -984, 0x6b74adc21bac6b3a -985, 0x1faa6a3704bd1b66 -986, 0x89e3e641298e87cd -987, 0xcb2f118548abcdc3 -988, 0x690e34dfb4153ab9 -989, 0x103d668edb5f7e88 -990, 0xb29d9f22b3b1d4a4 -991, 0xc4ce3be9022b314d -992, 0x1cb3d5af1306da15 -993, 0x8236da372d964cce -994, 0x79188ac299f06c2b -995, 0x953dfd978aad2545 -996, 0x6058e1066e7285cd -997, 0xf47307b50589e391 -998, 0x2923873ecd9c4d32 -999, 0x4c44d61328ac5e4a diff --git a/numpy/random/tests/data/pcg64-testset-2.csv b/numpy/random/tests/data/pcg64-testset-2.csv deleted file mode 100644 index 779761d0f8a7..000000000000 --- a/numpy/random/tests/data/pcg64-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0xd4feb4e5a4bcfe09 -1, 0xe85a7fe071b026e6 -2, 0x3a5b9037fe928c11 -3, 0x7b044380d100f216 -4, 0x1c7850a6b6d83e6a -5, 0x240b82fcc04f0926 -6, 0x7e43df85bf9fba26 -7, 0x43adf3380b1fe129 -8, 0x3f0fb307287219c -9, 0x781f4b84f42a2df -10, 0x36dac886f4232c6f -11, 0xa32006a96a8d46b -12, 0xa56e609a788ce098 -13, 0x75711678fa371144 -14, 0xbcdd4619fa063896 -15, 0x5cb5c9a1594f1a04 -16, 0x799e6cc7d09bf3fd -17, 0xda1a4b52f72a8c6f -18, 0x374b6f698c864e48 -19, 0x96a3e4d45b8d252d -20, 0x5fc89e7cbf7735e4 -21, 0xe0cfe37beef7efe6 -22, 0xc3467c95f4649808 -23, 0x95cbda6a3275f18a -24, 0x3a4dc1e59bdb4172 -25, 0x47f8755023ac78b5 -26, 0xef8e166bf07dfa95 -27, 0x40065cf0fa99882d -28, 0xbaa083ad70102eb6 -29, 0x7c88e9d1a72a8dc -30, 0x1484e44aa83e901e -31, 0xf0f8df78086fdeba -32, 0x5114e38e0cff505d -33, 0x7e04bb9a2828c944 -34, 0xb88c0de9e2af5658 -35, 0xecba992ca7e9178d -36, 0x8b40b65347cfeffb -37, 0xfce9281a9381a55f -38, 0xfde34f9f228fc03f -39, 0x8c46656aa79eba9d -40, 0x1ed0d3f416073189 -41, 0xd7adcc20a26d48d1 -42, 0x2429dcfa355eddba -43, 0xec100f2285aaad68 -44, 0x91a83984506e1ef4 -45, 0x4c10c0f973e3cba5 -46, 0x45d0d0ad9ab6890e -47, 0xa52b22d88ddb6090 -48, 0x63f7e7549bf80c43 -49, 0xfb03f87e5ea7137d -50, 0x822f96594246a4aa -51, 0x42242b1335cd3424 -52, 0xf78652fc51ec76ac -53, 0x24db7314bda69cc5 -54, 0xcce4cf66737c8427 -55, 0xffd70eeca33ed90f -56, 0xc154aff2caddd546 -57, 0x59d47a8ccd59e1bb -58, 0xabf793045ca561f8 -59, 0x3f1486708729b21d -60, 0x76ed98409f3f9abe -61, 0x3f0bb2cd7cedd012 -62, 0x448f78da1713ac85 -63, 0xddbae7151c1578b2 -64, 0xcf94237ec0973cd7 -65, 0x76a0657cedebac81 -66, 0x2b13b564bed7a3b3 -67, 0x47a6fc0f4604c781 -68, 0x22acf016523ae80f -69, 0xf728771b939c13a2 -70, 0xab4aee3986c80ec8 -71, 0x61d8c8c918b3fe52 -72, 0x7a40380c747f9044 -73, 0xfaf974af2e96a882 -74, 0xb8bd56d90c69d42c -75, 0x7cea307dda515497 -76, 0x56d0858a27ded2a3 -77, 0x8717ea17698706b7 -78, 0x6b34d0c0587e8867 -79, 0x387a8142ee80d29a -80, 0xbba414cee59e3194 -81, 0x6d2fe8bec0e51a8 -82, 0x11d5dc961ba15ec5 -83, 0x7af1ae07932b2fb8 -84, 0xb13ea6b28d63b57e -85, 0x7e89a6f060cf59c5 -86, 0xad1f662c4daa4764 -87, 0x929a054dec3e229f -88, 0xf7f41c2a34920f09 -89, 0xf0eac1b75822b72b -90, 0x24f311773d90d399 -91, 0x9c2147da3d098c17 -92, 0xa62963f5bb0f8b9e -93, 0x97f650195285e480 -94, 0x602433fd24fe4125 -95, 0x6f17d6e3b5fd704c -96, 0x3ad6f2cf0ffd6a04 -97, 0x73a6d93edf693e03 -98, 0x467d4e6fecdfdb20 -99, 0x6aadbba2b2f8a2f8 -100, 0xc865bae9d8713526 -101, 0xa94d7c6b462e5acc -102, 0xdcbb47fdacd4d865 -103, 0x80aa6a71fd60cb40 -104, 0xf27ad62910288223 -105, 0x88f93784d309825c -106, 0xf7f9a500b821c886 -107, 0x6cd6e37a5dca4830 -108, 0x57694853b9c75561 -109, 0x9c7ef1aa6b8f2c1 -110, 0x12046439309d6e40 -111, 0xee3d652c43bd35b9 -112, 0x3838110676b26d7a -113, 0x9efd697137fa24c9 -114, 0x1eeaa149a7edd5be -115, 0x17eb32cd212e374a -116, 0x73dd5b7d7fd3b280 -117, 0x788e514de9649f29 -118, 0x6e2fb96fbf87fe8b -119, 0xc736a34c7ea74137 -120, 0xa4d48bb7df0e3c51 -121, 0x25b66ee78063d37f -122, 0x9058e087b9696e7 -123, 0xa2e6397ebdd3d935 -124, 0x394a16ba856e6899 -125, 0xe4aad4f1bc61d046 -126, 0x5e4904686af5c43 -127, 0x4e58956c61a1880a -128, 0x7328c827d6236eff -129, 0x29463809b511cf73 -130, 0xceb2c403cef62247 -131, 0x9ccc00f358aa8346 -132, 0x6fdc1c42421ba33 -133, 0x1111d660460f5300 -134, 0x97a4f922e55a9226 -135, 0xbc2a217152bfbc63 -136, 0x3617700c68d104d9 -137, 0x8eecc63c4a929622 -138, 0xc69cf9d8f8b45df3 -139, 0xa2a8ca8262f8921b -140, 0x4339edf9e292f9e0 -141, 0xfe385e2e7f6e1a1a -142, 0x5f30d1b803abc1d9 -143, 0xf123207050238c3c -144, 0x79e3401200b54b1a -145, 0x858d7ce163d4de92 -146, 0x5803a44cd013b965 -147, 0x17c65b0b01800940 -148, 0xc50b38bb58dcb3c7 -149, 0xe476e9925898603 -150, 0x3972fb0fa748a3a5 -151, 0x93da971efb1036f7 -152, 0x658bab8ef6082bf2 -153, 0xf664abd0de92444f -154, 0xa2145e8039e61d87 -155, 0x28af5560cb0ee0ac -156, 0xc1e43e6a30cefef6 -157, 0x74f61d623cc6965e -158, 0x3ee0139a07b6c130 -159, 0x214992e8a6134c54 -160, 0xaa83b771c9421231 -161, 0x15487762c93cf5c6 -162, 0xa3d37b883fffdfe8 -163, 0xe398d2bd15c1c511 -164, 0x3154f894aedd5938 -165, 0xc7ed5190721ec2b5 -166, 0xca02cf8dcfef83b4 -167, 0xa22c6a2e5460e0f3 -168, 0x2d72e4d264875109 -169, 0xf282e30c8b945616 -170, 0xa1a286624feece2e -171, 0x6f773be8548d3fe -172, 0x8c6dc6f48c83c30f -173, 0x13dc5926122501a1 -174, 0x5537f3d25d126e0d -175, 0xdb654b8409365aa5 -176, 0x55d8f727e066e818 -177, 0x534841122140f9a3 -178, 0x4e4ecc7b2ce8efa0 -179, 0x3655d535028e4044 -180, 0x6c2ad71379f15365 -181, 0xd1f1238395ce193c -182, 0x4ecd9ccc56595a72 -183, 0x3304220c15b60f7a -184, 0x3726fecf394006bf -185, 0x4523e03e39a92ac1 -186, 0x191c97036c0e20a8 -187, 0xbfbcf849ecc37cd5 -188, 0x3c6090d256b1c780 -189, 0xf7e94dd0d3e02fd8 -190, 0x83034fb1c17bb99f -191, 0xa7be8e0eb37c9260 -192, 0x177d2c560b0b55af -193, 0x55da4c839514e82e -194, 0xc9b393b79b0e7617 -195, 0xe9658403d3a140 -196, 0xc86401b988be38e7 -197, 0xe82baf54ee5df9e1 -198, 0x3a562e6572a853a4 -199, 0xcb83facbed1cb364 -200, 0x4db406f08ea62242 -201, 0x9cc816f5376ab97a -202, 0xe65a32f96a78b09 -203, 0x59e7b42c496e2c2f -204, 0x7e3e59a4546b6b33 -205, 0xc51a371516d5adc4 -206, 0x19ba384285a523ca -207, 0x5b998f71002a0912 -208, 0x81ee2f95f53dbce1 -209, 0x966a0c0bbf15492e -210, 0x80f88202ff2d29c2 -211, 0xf827f45274e32733 -212, 0x66a2611b73547490 -213, 0x1b2c3c3ae80997d0 -214, 0x264a86e09c63e4c9 -215, 0x35d4bf9c9d0d89a2 -216, 0x6051e319babb305f -217, 0xdf0d08608262be49 -218, 0xbe7aa9a7697278c2 -219, 0xac531985f79fca17 -220, 0x7ce7de0d95ba34d -221, 0x9a03956d30de1ee0 -222, 0x8106a5873e7950b0 -223, 0x804c06b1fab989fc -224, 0x20d5fe19357e95dd -225, 0xf3e89c08d1841c79 -226, 0xfc93b079bdb323cb -227, 0x8f6eb1dea40eda88 -228, 0x6e7f6b657f6d971e -229, 0xf2b15bb03a49e9bf -230, 0xcf7fed1aff1786b -231, 0xe53366adc5bafe42 -232, 0x89b853ed67fc2387 -233, 0xd13dadf3828f1df7 -234, 0x2f884ffbb83075b9 -235, 0x8efd2baea4771d71 -236, 0x7872e80c946c6bce -237, 0xcc487bc4ea869070 -238, 0x820609347e4fdd75 -239, 0xe939e3c63701a997 -240, 0xf70ed361e42164e9 -241, 0xa9f29046fce9ba8d -242, 0x61edfa750175e868 -243, 0xb7d2424653bde389 -244, 0xdadd225205e74ef4 -245, 0xecfb9a633ee3c774 -246, 0xcbc69459f0634f30 -247, 0xdbcd82538e0785e2 -248, 0x2b272f59ad36e01c -249, 0x601a38897a57cc68 -250, 0xfa012b9e5722d8be -251, 0x5bce8d48277d7338 -252, 0xd1b6ca2b93483dc2 -253, 0x8b94eceb88f55be9 -254, 0x93403aea5df5da18 -255, 0x57b6fcaf351c16b8 -256, 0x70f5e54095404bd8 -257, 0x9124d47160362770 -258, 0x987ed72af8aa305d -259, 0x71e3a8d5156f82c7 -260, 0xf788e966e86f7004 -261, 0xcf0cd5911c4bb0e1 -262, 0x3340b119d3e2f28f -263, 0x9952106be6e3bf95 -264, 0x99a6213e19fe9d1a -265, 0x4f0d3811a8a5d481 -266, 0x62d732ee5f975dd2 -267, 0x3abc8340ab323ebd -268, 0x15da761a2518c843 -269, 0xb453de7d4d15b261 -270, 0x4adc2d7cc2cc0049 -271, 0xcc9b7fa135c7dba4 -272, 0xa14857a738db2b52 -273, 0xce036b49e28c19c7 -274, 0xaee7e9fde421bd4c -275, 0x15dd298915099a9e -276, 0xa3fa6550b639b66b -277, 0x5f27c59b035a6532 -278, 0x2eef2e6292288715 -279, 0xabd211c514e3699e -280, 0x6d7bf9b33f8b09e5 -281, 0x91ff83561361c170 -282, 0x8f8e309797a91e4f -283, 0x2b11ef1cedf1036b -284, 0x6fc36ed305d27972 -285, 0x7e294e03a91eb01f -286, 0xbe16009d8b2f38a4 -287, 0x2bf69c7b54e60cea -288, 0x860079a07fade829 -289, 0x8f0ce6ae4c90d38a -290, 0xab10e5f8ab4835fc -291, 0x49ed43ddd4ca0a76 -292, 0x201eaa53b6df058c -293, 0x2d9a4fdb16f6c1c -294, 0xd3406193e1dd0760 -295, 0xad38857b542ddb6a -296, 0x52ec1e450363aad8 -297, 0x6e65469594331886 -298, 0x4b027ce344dd6660 -299, 0xbc801654b4a1ccad -300, 0x155be4bc51328b2c -301, 0xa9a1965f9b2b5bdb -302, 0x386b8dc34de0889 -303, 0xd60ee4b1b9cbb057 -304, 0x6c1e60b6914c4876 -305, 0xd07bf84dc30bf653 -306, 0x362d5b19b3f4f7e9 -307, 0xd145b8fef9a6a3d2 -308, 0x5c401126b505dd09 -309, 0x8f5d1d4446f9cb4c -310, 0x725618359f1a3e38 -311, 0xaedad9cf455de2e5 -312, 0x7f7e4e549b4bde1b -313, 0x35002b8e995f815 -314, 0x9aecaf8f393cade0 -315, 0xf346a49595886d86 -316, 0x459d5a9e92e9c149 -317, 0x60885682c3d6ff0d -318, 0x90f5e985e08bfc3d -319, 0xbf413a432e1a1b81 -320, 0x789503524aa48aa9 -321, 0x7880e5bb484bd49e -322, 0x7426535c324b7176 -323, 0x190ad37f84acba3 -324, 0xbd52510631d4f5d7 -325, 0x98f794ad565c986d -326, 0xa0ea374e66c0bf56 -327, 0xd683fe7102145335 -328, 0x9b3dac61db2f2930 -329, 0x470d31e3096c2450 -330, 0x1f445f8292f6f3dd -331, 0x1687ff432def56a7 -332, 0x887d4e6617525278 -333, 0xcd81ce8cc70b13ff -334, 0xaadbc4c3525c18e1 -335, 0x96d81490c362b621 -336, 0x128b95092e36796c -337, 0xffeffbed0980cdb7 -338, 0x3bcef6c52b36d07a -339, 0x400879c888eeabe2 -340, 0x373c9978059787d -341, 0x35979fef9e20050a -342, 0xf4581367f3fc43b -343, 0xcec7b91352ed0186 -344, 0xa7b06e92b765203 -345, 0x6713f0b11fb9f296 -346, 0x95c53b86deafbd95 -347, 0x3694844a5eca42df -348, 0xd0f334ea2c650574 -349, 0x5ae6771044110ddf -350, 0x9f61d9087e7d36e5 -351, 0x28f04e48625e3e5e -352, 0x6164d6b5445cf130 -353, 0xa36b5c2de27084be -354, 0xa099a43d5c5f21bb -355, 0x706edfb05fbe8b9e -356, 0x7aacffffc81ebc3b -357, 0x6f49121baebd0e6a -358, 0x41fda7ba6df8f4cb -359, 0x1bea4b596dbac5ac -360, 0x71dd0261d65b02c6 -361, 0xad7f50624c15e9c9 -362, 0xf7c4eeb84d4866b6 -363, 0xa5e23dd382f48bdb -364, 0xe6ffdf875d534bfa -365, 0x40104d8444f75a7c -366, 0x8218a42f24a88364 -367, 0x9d3f9382759cae86 -368, 0x101d7adffbd9ebde -369, 0xf9fe3578d6b739dd -370, 0xd23c47039e882eb2 -371, 0x37fc4fff590191b3 -372, 0x2a672fc8cd3e0cf7 -373, 0x995b8faabb4332c7 -374, 0xabc6117aa665a743 -375, 0x3fc49d11869352ea -376, 0x4ccc3cfa9540797f -377, 0x111c57f059fa3ef4 -378, 0x44a737bac79496bd -379, 0x37924823edfe0774 -380, 0xa4d8ee07ab241d02 -381, 0xbb0bf46c50f349ac -382, 0x4db0a8506e22199c -383, 0x93239f377c85ba51 -384, 0x56f51e3970e409f5 -385, 0xe82d51ebc177609e -386, 0xec866d8b473eaeb -387, 0x42f8018bb955abed -388, 0xf58ba8a916b04fa1 -389, 0xf12d2f0cb0a41cff -390, 0x8102b5f91923cc2a -391, 0x91d95fcb9cb1346d -392, 0x819ccf0d122537ac -393, 0x34646b1c3f9a8527 -394, 0x4a3a7df812ff79cb -395, 0xc3d0b50ed434ad24 -396, 0x3e6cd372b453b5f0 -397, 0x39101f6226c43c8c -398, 0xff41e5b6b7ff540c -399, 0x1e8d77bc3f12e0f4 -400, 0x748d0860be568eee -401, 0x5baac1f743bfeff3 -402, 0x8bdbd895b2eed2d8 -403, 0x5d3a01fa82bd88d4 -404, 0x577271d2de3e06f4 -405, 0xd4fccaeb0db61acb -406, 0xa088377ed2b1d841 -407, 0x6f2e9e1566f37b5b -408, 0xb8d85eef688c049a -409, 0x6b7c06c55078761 -410, 0x223cd94cad1e0c32 -411, 0xbf27c193ae5881e3 -412, 0x5b784893a36d57dc -413, 0xdc9fa53968c262dd -414, 0xd7e820c76855fb61 -415, 0x72260eb94f096e2a -416, 0x49144b5732ca1b94 -417, 0xba8d85a47582d428 -418, 0x558abe242dc84de2 -419, 0xc27b1d54557b9de5 -420, 0x80c1f06559385330 -421, 0x4a5c1d4252675c73 -422, 0x225e3a9f7b2da067 -423, 0x9ac95bac9d2234a1 -424, 0x696e500589e0e490 -425, 0xd0fe548d81c82185 -426, 0x68d8b783037b4743 -427, 0xbe1664f1a8d814f -428, 0x2304308b691ca712 -429, 0x68e680af6b7189c5 -430, 0x13abe6c989949072 -431, 0x4c209f5029a59d0b -432, 0x63361139df6fea7a -433, 0xf07c52d8272cbdb -434, 0x665023146f27fa7 -435, 0x7cb535c55ad7ad0e -436, 0x76e366c7317eb1b0 -437, 0xa7d9b80b51585e9b -438, 0x85f0bd60122198b9 -439, 0x34bc89d7e7827fd5 -440, 0xdfa1167988c85807 -441, 0xe78f45588bfdba02 -442, 0x172a023eba7357b2 -443, 0x7bc4c79e06ea755b -444, 0x8aace6120b766b95 -445, 0x17b43a5a81b0db26 -446, 0xbc2b95819d959ff6 -447, 0x1b8841f2fe9c4622 -448, 0xc094a747ec30d67a -449, 0xf5b93ec01484b937 -450, 0x659bbe8bdfd43f01 -451, 0x9d96c22bcf9c64c9 -452, 0xcf7df324fba052ec -453, 0x5e4acd4f9e048e0b -454, 0xe3a0e7e9869c5dd2 -455, 0x4eb444727e1c346e -456, 0x7f6cda1ca7b3eb67 -457, 0x72fccac63ca649e9 -458, 0x711bfbf79a093651 -459, 0x5d48599fae7fd6a3 -460, 0xcc640119a296b34e -461, 0x39acfb198b2b439 -462, 0xde759b50e2db66f9 -463, 0xe83bf8363827e06 -464, 0x484d50365017de87 -465, 0x4c3b5dbacd68394b -466, 0xbbe47788c079218c -467, 0xd44099290c25fe62 -468, 0x3b7d1bd6f91f3857 -469, 0xe7366a677d2b7eb3 -470, 0xfaa770590b197910 -471, 0x610b7a2fe8c4e80e -472, 0x13451e1bf520a796 -473, 0x7e3d18c47e821077 -474, 0x8fd3a77c86eb9804 -475, 0xf24be740c87eadab -476, 0xd5a52e6d0b58345 -477, 0xae386b5ca037a8d -478, 0xb59fd16baf160f26 -479, 0xd4a05b473f6e0a8a -480, 0x47ede6678c2c6420 -481, 0x8851ed397da6f850 -482, 0x1de775cdb392d89b -483, 0x74e6c8ec9513ea38 -484, 0x30ae39e04187a984 -485, 0x614cfd09d043d601 -486, 0x3e0173138f562ee1 -487, 0x822d415a26bdba96 -488, 0x432f6dec77edd9a8 -489, 0x47a3a179627546b8 -490, 0x845dd7ffb1fe6d78 -491, 0x9778d5782de13a48 -492, 0x760198319b3cacce -493, 0x420ee262d07dd7c -494, 0x847c7424c365df20 -495, 0x56b3b590fb83ba16 -496, 0x7cd2410390a3e797 -497, 0xbb0c21b47aab8857 -498, 0x2743883e70a36a18 -499, 0xff8b29cdc75ebb7 -500, 0xe1e04a0f0379686f -501, 0xcfdf3083b792f281 -502, 0x27392ca026b55e88 -503, 0xeeb195994fd56abb -504, 0x7cf210041345882c -505, 0x3ddca2b8951fea4e -506, 0x21c89d88a3833996 -507, 0xe7128bccc4b25c9b -508, 0xe39b0fb96a4c05ae -509, 0xedf5326550594554 -510, 0x4aa45fe66b575558 -511, 0x2799fc8d3b06f777 -512, 0x2824863087187501 -513, 0xa15fa00818118906 -514, 0x559fc9e9344a310 -515, 0x1682745f8d571671 -516, 0x80b54f29f47a28d0 -517, 0x38e28103ffd9f771 -518, 0xedb5f440dab80945 -519, 0xdb0b8d04cece6091 -520, 0x1f60a7cae5ae8412 -521, 0x6719c0405e92b31d -522, 0x56752def7d642302 -523, 0xa5b0900f93c352dd -524, 0x5b82baf53be8983d -525, 0x7726202ccee5cbb6 -526, 0x1641c84c7f87a765 -527, 0x835ae1a82be4265e -528, 0x5f9ccee69c1d9da -529, 0x3e2a2228e21039b7 -530, 0xa45873582866d005 -531, 0x7fbeffc99401e59e -532, 0xcf66a6a974057890 -533, 0xd53704a96af96fd -534, 0x1a8b5e3460704b64 -535, 0x6939b27bb32ba451 -536, 0x3c39293e637a0115 -537, 0x335a6e6b779b8c4e -538, 0x75235d767dfd3d00 -539, 0xbdf0b36936b17c90 -540, 0x982dc5e4915a3a3a -541, 0x74657ac256407f55 -542, 0x603a724457b796b6 -543, 0xf178694f7a3f98bd -544, 0xe712de12db2aba47 -545, 0x1ca272d99a3355d8 -546, 0x93e7054d3e8dafc7 -547, 0xa29597810eff04c1 -548, 0xade242c0ae4bcea3 -549, 0xbcd226e2bd9d0e64 -550, 0x2e02e5736f889a -551, 0x3622dc09f5fdd576 -552, 0x6e66bd2a10d78705 -553, 0x71d8f19110d5b4d0 -554, 0xacae934ab3d759f0 -555, 0x68d670d5f9272132 -556, 0x571fb09d082e7da7 -557, 0x154540c51b7d8b33 -558, 0x1e2f3710c0b6890 -559, 0xaf26a826ef444b30 -560, 0x9fc9fdbd9342be72 -561, 0x9b33b306d22a35e0 -562, 0xb6d5895f56d4197b -563, 0x92fef06c1353b2e3 -564, 0x804e3eb42e65b938 -565, 0x73d5cd4bb7270902 -566, 0x274b8ac4925da8fd -567, 0xa9a57999f5df2e2f -568, 0xa6000be059e088b -569, 0x57de4fc48c9e9e84 -570, 0x16727392e94ee9bf -571, 0x53c9032f62848c4d -572, 0x8a8ddd8fcf0676dd -573, 0x1436de7c1735087 -574, 0xfa93b7d1425e8667 -575, 0xec34ca5f3f84bb2f -576, 0x489ed44d0880c4c8 -577, 0xb3b6051de7a6f740 -578, 0x2f303cb0f4040f11 -579, 0x302c42a6adbcbcb2 -580, 0x28ed7b87695cd600 -581, 0xee78d3b782a2fcd0 -582, 0xc47a2441a1082032 -583, 0xec9965704a044f33 -584, 0xcb1563e968460dc -585, 0xfecbb4fa2b544f93 -586, 0x3f3d7437a6d29a3d -587, 0xe4bfaccd729414ca -588, 0xb741ed954572d172 -589, 0xf34b49bf10ae47b6 -590, 0x1fbd1f068f1b796d -591, 0xc1d556e64345b226 -592, 0x85bbfa50a899c7be -593, 0x5310045dcf0fea8 -594, 0xbc6f6fb7f00e5960 -595, 0xf8bdf4074f2b5f5e -596, 0x2a5817aa122dc97f -597, 0x6d5ef86d6b8ad0ce -598, 0x96e7ccc235abb79e -599, 0x8d531c4cea492f66 -600, 0xfc124a123b4ce02a -601, 0xc6087ffd9130c2ca -602, 0x3a724c46f0f06175 -603, 0x59980713cfe4fe92 -604, 0xecde418e64a11bd -605, 0x5c9b333a0f0337cc -606, 0xcf014d508fc8e83a -607, 0x83998bb2aa4e16ba -608, 0xde8f5167ac0a40d9 -609, 0xe93b1846914c0dc7 -610, 0x668831ca8fd50c25 -611, 0xec764b87e402c28e -612, 0xd0e1303e56f6b268 -613, 0xa6b9f3c4872dbcd5 -614, 0x12a89c116ad924f0 -615, 0x23857c375ae928c8 -616, 0x29b117f63f2e8c1b -617, 0x64ff6cce272aa46d -618, 0xd40fb15b38d59f70 -619, 0x6e5a6257c4cc0c66 -620, 0x7b54845e6e119a4e -621, 0x9d88bf3dd9fa0f0e -622, 0xb6687fd4980a5d43 -623, 0x4f2e3fef88b640b8 -624, 0xf07ac2f7e2df40fa -625, 0x24059bd0ecb6c6a9 -626, 0x6204a47cbd57453d -627, 0x8477fd1a13ea9678 -628, 0x4555083f5eada49f -629, 0x352443e5d984691c -630, 0x3e904f796a9c5ffa -631, 0x11e182bc43754609 -632, 0x608cdbe03699a5d4 -633, 0x2619146efbf59f0 -634, 0x9b852370063940ee -635, 0xa1d8e7e91e42a52b -636, 0x19179affce38fa3c -637, 0xf68ff1ccce70380c -638, 0x12103cb41741ab38 -639, 0xdca7902fa6d960b2 -640, 0xad46a2fc70025445 -641, 0xac92f0b2d150d716 -642, 0x5de115babb43326e -643, 0xf335366fd69e4bcd -644, 0xe9aecd1f88889cd -645, 0xbce60087987b51d1 -646, 0xcfd395a167103939 -647, 0x2fdcb12826ac806c -648, 0xbd5129970869ccd6 -649, 0x5e922b68030c2698 -650, 0x7ada02a56d17779a -651, 0x7a1254c652b99ccc -652, 0x8be78733623db772 -653, 0xc22439789b68f0a8 -654, 0xee51ad4ab1a9a6ed -655, 0x44b15fa27694d9be -656, 0xc5b93e6c57805153 -657, 0xcf03df495c283a89 -658, 0x5c2a41954bb44bb -659, 0x9e651cb8c650dd -660, 0x73a20ee82570d4a8 -661, 0x5f805cab085e971f -662, 0x5354410872a8f587 -663, 0x1b50ef4e9519338d -664, 0xdeb873412301a1ce -665, 0x3a286bb2f5f8db39 -666, 0xad117a0d4dc7f82e -667, 0xdd880d581169d989 -668, 0x8356be106382a704 -669, 0x7c684ad93e996ff3 -670, 0x6b2d09e61ac02c11 -671, 0x99ad8c074fe046dc -672, 0x4a9b4f0e7c4ffa24 -673, 0x38afdcb5893b466 -674, 0x7ad58ef97c3d35c -675, 0xdd7c17c0d67ab69 -676, 0x61c77caf27938c86 -677, 0x978fc491080c0cee -678, 0x4c1750f8684c1ca4 -679, 0x86b4c683d5fe657e -680, 0x720e2bd8ec76cffc -681, 0x73ca52b4a7dd3b85 -682, 0xeb10a691e12ea3ca -683, 0x90355e369297b259 -684, 0x6c6bc16f639678ca -685, 0xd989f4c724f8fba7 -686, 0xbb1ba7e2ca1c4391 -687, 0x81e4194500a0d267 -688, 0xbb25489c1dcbf93f -689, 0x74d26b75e9f57fd -690, 0x59c085fa99b6493d -691, 0x3359805b0fc3fef9 -692, 0x60ef0f3a85e60650 -693, 0xf1a3692c8591e8d6 -694, 0xd7c8d2e7f3d3546e -695, 0xe8fc8518c11ca881 -696, 0x3380ef12114d1818 -697, 0x87203c98ff21fcaf -698, 0xbc37f8e034002ef8 -699, 0x891b7c3f55d02300 -700, 0x814eec8ff8956f0a -701, 0xa370639852acceae -702, 0x6c566310b6b00f15 -703, 0xd69fe78b9c8a05a6 -704, 0xb7b0df518738419e -705, 0x2a0c1185b29ed965 -706, 0x636c841214c0a8cf -707, 0xbf56297859e9bb72 -708, 0x2b5b9d432d6d008f -709, 0x1ea586cf0f86f542 -710, 0x23a2a1af76cbc988 -711, 0x6c72c799b6ed93f3 -712, 0x2266785315f3bb13 -713, 0xb68cd6e87b94065a -714, 0x5d395704514bb808 -715, 0x334bde59d526ee4 -716, 0xc5a6d87f96f055fa -717, 0xd47001378b4dcf08 -718, 0x7305818a39057557 -719, 0x8f72c128eac6d32 -720, 0x4957ed799339bbdc -721, 0xeb47d505f61dd5fa -722, 0x8ce8817cd6acc93a -723, 0x84ef66e511a52f35 -724, 0xbf5aa34bbaef7e1f -725, 0xadaa5ba2a5ee660e -726, 0x6eec8ac924058eea -727, 0x8af63be4d1a1b202 -728, 0x88eccf85fd9fce32 -729, 0xf19a1122f394af05 -730, 0x8dcd15d1c14f5077 -731, 0x6c0f2e6135e36545 -732, 0xe58f89bec4d929c8 -733, 0x4eea88221d983ef9 -734, 0x51ae3956d53e1a80 -735, 0x40d8a172bf713bb6 -736, 0x3e33536e43ad4fa2 -737, 0xeff9938a179138fa -738, 0x3e372bff1f51df8b -739, 0x59b86a407817c86c -740, 0x947164c2c57f9bd8 -741, 0xd8e67bb799d84475 -742, 0x4d9ed254d8189595 -743, 0xa021d8d181328996 -744, 0xc703e402f8e4688b -745, 0xd1eb104c970dd5fe -746, 0xd5bf4683b9337f8e -747, 0x98f405a2d998f06 -748, 0x59c734ddd208e85c -749, 0xbd167be2d43fde24 -750, 0x70602daab163fbe2 -751, 0xeb2f2b37cbfe13e7 -752, 0x28baa8f3fc4c4666 -753, 0xe212ffe352ea5ce6 -754, 0x538b93d2285eda3a -755, 0x3a9482ac69a39e1b -756, 0x3a98983ed4367767 -757, 0x1dc851c69e35d601 -758, 0xac7f83e4b02e9bb8 -759, 0xa939f99c5615ef7b -760, 0x439437f129076339 -761, 0x79a251bb1d50ce25 -762, 0xaa7b6ff8f13a7424 -763, 0x1b244bd86404327b -764, 0xc84d99185ab2a7d6 -765, 0xf6dcde975493c40b -766, 0xdee46f4346cf6af -767, 0x739b75df1fe18712 -768, 0x3d05cb298311f3e9 -769, 0x1fba9d9c10dc7780 -770, 0x31637fc416267053 -771, 0x46694e36246b8be2 -772, 0x8c67095ae6eaf1e4 -773, 0xebe2a68c27963dca -774, 0x532d344b14306cf2 -775, 0x6a847c8f3ae2ac92 -776, 0x8034bcb5a50cbd6a -777, 0x7544766784261059 -778, 0xe641799652df63ca -779, 0xd8cacad7099c07de -780, 0x429e62da116e4876 -781, 0x4442c8b57a5b7ef5 -782, 0xa7ea9c348cbeebaa -783, 0xce1a34f57bb2a7fa -784, 0xbb29ef457c9509cc -785, 0x1ba1030b19a32c1c -786, 0x412d1eb07cee79b8 -787, 0x3627dd37c6b36848 -788, 0x45432b319f26a2a9 -789, 0xb9a12e188cee2a29 -790, 0xeee69e0f1b1efd66 -791, 0xd4ccd61bc3fb8837 -792, 0x1b600476917cbf62 -793, 0x522950ddce26c142 -794, 0x956d8a5dbe9aa431 -795, 0x31cfba73bb524b7d -796, 0xc3b709a56885a6ac -797, 0x7341d4e32fffcdf8 -798, 0x5ed87c5315e4775 -799, 0x60fa512183e3dad5 -800, 0x4df6df14e9c2935f -801, 0xdec2dc983ab42a9 -802, 0x28265e213fd6de41 -803, 0x2f85d825454add06 -804, 0xf18119191ac41aa -805, 0xf870e36e83f4face -806, 0x2a4b213d973d83c8 -807, 0x2c7094cde18ba8ec -808, 0xb5998e0a1914446b -809, 0xefcb960ff010503a -810, 0xa8d928b99104aef5 -811, 0xe7a6893116e383a8 -812, 0x552dbe180a51b6c9 -813, 0x16b73f3832c9990c -814, 0xfefee9504783e187 -815, 0xc12d3aa0c1f8608b -816, 0xd5232106c7adea7e -817, 0xb207e82667fb71ed -818, 0xe93c50ef54a791cf -819, 0x3099900fdf7b1750 -820, 0xaa2a46c352132ad0 -821, 0xf2414daa174335e4 -822, 0x33080f98c42bbad2 -823, 0x9df24fe0b5b13394 -824, 0x840eedf2eec5fdb6 -825, 0x3715e262efbc907d -826, 0xa70a8cccfbe8a11f -827, 0x4a57a6f16ea4c9f3 -828, 0xe03dbe2f1493e9e1 -829, 0xbd92759a7becd4e4 -830, 0x21a3d87c3766887e -831, 0x6414f570caa74ef1 -832, 0x4e27490fc3fc0234 -833, 0xd4c40310c6ab2eba -834, 0xfbe8acd168ffd62d -835, 0x30b19992f1975ac8 -836, 0xaf93d22a8561f631 -837, 0x4574ebab81bed3b1 -838, 0x5390c6026e3940c7 -839, 0x7a5154d076a8b504 -840, 0x9676f2495f742943 -841, 0x8cfdb9e11bdb4502 -842, 0x36af5c8754d9ca17 -843, 0x61477e76367296ee -844, 0xd6f5f40f66acc700 -845, 0xe62c2462e96af1b8 -846, 0x18029746ac09ef3e -847, 0x871bbe15da7e0176 -848, 0x2443e806f54d179 -849, 0x9103af1634f9d0ac -850, 0xe6e5358eaa0efa2b -851, 0xdff4859198244a67 -852, 0x6e48c357be6042b -853, 0x6bb9e8aeb24d656a -854, 0x1b89fbb05f8438cb -855, 0xe0cea835b4db045d -856, 0x4eafe5c195e29d47 -857, 0xd2f0a452be9163f0 -858, 0xa7ae1d0eee928fe6 -859, 0x42c7a26c82a062c4 -860, 0xa8e93bcd89c5704e -861, 0x73784be379f09c34 -862, 0x91f8e599342d013f -863, 0x79c20bc462215ccc -864, 0x6ee77bc91b3753a6 -865, 0xd2c116d1eb2650d0 -866, 0x388f9767cfe30ebe -867, 0xdde5d5966815e7ae -868, 0x459b838c87ca1dec -869, 0xdf96cdb2bc916a60 -870, 0x215c4195b935d5ca -871, 0x56c9f516528598e5 -872, 0x1d8492a9923640f3 -873, 0x97830ac45234686f -874, 0x67f75117a7c952bb -875, 0xf1939dc69391e65d -876, 0xfc44bb1162cb2868 -877, 0x92b33d9df8fc6925 -878, 0x6c4496920de0d558 -879, 0xa4616bb101e924aa -880, 0xa0afc9701ad83cdb -881, 0x62d555323b0494d2 -882, 0xf18b31447a2dfdc3 -883, 0xb2ece318c128d4f3 -884, 0x29efea45a76b9b8f -885, 0xae05362b365d9cd2 -886, 0x5c4d374ce6aefb44 -887, 0xb9cdc65eec94136e -888, 0xf0212f42e3d4f5dc -889, 0xcde7c5085f95d8d8 -890, 0x9cc3799673a644e8 -891, 0xf878d89199bead01 -892, 0xab684fb9666abf61 -893, 0x3070d399b7a07d3d -894, 0x6d8c51673eeeef73 -895, 0x9bf4062ff5471832 -896, 0x92774cd03c511d00 -897, 0xc1aad7c6980df547 -898, 0x3291e3a234d50cc0 -899, 0x75645079bbe9d34a -900, 0x7f28bab9eba28fae -901, 0xa84415684ed6d765 -902, 0x56d9d67653cd172 -903, 0xa7bfed939db93e91 -904, 0x92940e5162d50470 -905, 0xcd6bf601e08f07a9 -906, 0x2ea9104d785e35cb -907, 0xd771ddd541649214 -908, 0x352554afbf9258d -909, 0x9d855486b77c5bc3 -910, 0xdb03cd71e906e1df -911, 0x7c2621690aabc265 -912, 0x1dd4ac7369a04640 -913, 0x57796cbc93d4d854 -914, 0x42a373d152eca785 -915, 0xbe7389edb8b144d3 -916, 0x8b6245bf01d2e4df -917, 0xacd1f9fcca317652 -918, 0x84545ac79a3eb960 -919, 0x2d2f28e6a8459db3 -920, 0x42b3a2e26ddeccdd -921, 0xe858272777abcef6 -922, 0xd9b5be7340dec08d -923, 0xe991af3579ac4fb6 -924, 0x7c30699b349fa6c1 -925, 0xbb842be14f7b5b9a -926, 0x1d31e1ca791a1cf0 -927, 0xf2bd448ebb878bc0 -928, 0x26a6adf6709863cb -929, 0xb11aa978539e3a34 -930, 0xce554a11bbbedd1d -931, 0x553d3c012682a47b -932, 0xb3c90ed36715903 -933, 0xda3c5c706e39e395 -934, 0x4e7f66006d583c2a -935, 0x6424190e9d28ca3a -936, 0x9916685e7384f3bf -937, 0x1285e17347eb806d -938, 0x877f10baf13e6659 -939, 0x222700ed5086438d -940, 0xd2473d08396634b8 -941, 0xb6b68f3bc883a77d -942, 0x168a489b0b7f5f63 -943, 0xee34dcf1f93ad3fa -944, 0xd25ef824f614f65a -945, 0xe30981905354f477 -946, 0x9463ef623c5eb3f8 -947, 0x46657408ea66980d -948, 0xa2e58d51d6e8e7f9 -949, 0xd80d7df3007e9845 -950, 0xd90fa96f4fc0f7aa -951, 0xd2a6059d171bbb33 -952, 0xb8bacb8f11c65c2d -953, 0x401de84b6a8b1ac -954, 0xf8b6eed644c802d9 -955, 0x30c927749fdd8e6 -956, 0x17c2f4f9c4524e16 -957, 0xa9c677daae4acc7e -958, 0x82c78d9c6b10446f -959, 0x5e544188277da629 -960, 0x7c6e1bd3b861dcd7 -961, 0xd4b00871a7f67d0d -962, 0x6b66ee142821e6d5 -963, 0x176d5e39f3b22474 -964, 0x58ea746f62acf933 -965, 0xc61fabd9961c3a51 -966, 0xb27ce0f87b416e3d -967, 0xd3c82b525b000e70 -968, 0x99578704fb3ff4e4 -969, 0x747da52468875493 -970, 0x5c5bfab7a474465b -971, 0xd82276bdb30e3dbd -972, 0x1d758772eebffe2 -973, 0xfed9d1e3ca887a6e -974, 0x23dd5f7b3ff9472b -975, 0xae2e842b51c9c598 -976, 0xe851bc45531123d7 -977, 0x1a18d2777151c29 -978, 0x9e82f3be14b12a48 -979, 0xdf9fdb3abc3e72cf -980, 0xdbea56e918ccb176 -981, 0x47abbd896eb0ca1a -982, 0xe850ee3cef9334dd -983, 0x3d69fe95275e7f2e -984, 0x4fcb936c048d8812 -985, 0xc98f0f6bb9865a99 -986, 0xc951cdb73514709 -987, 0x3ca839c27ca26de9 -988, 0x1478848a311f9cc5 -989, 0x35d2244064967478 -990, 0xe71df2d9732ffdc0 -991, 0xa12417d7b7b9e0ce -992, 0xa1bb6da3f284f77c -993, 0xf551e1c3171575eb -994, 0x16083ac8a062747d -995, 0x866d6c3a630fd4da -996, 0x8a972ff46b3c5c4c -997, 0x70af3b475e4a3d5d -998, 0x2c143fd5c01d9cf5 -999, 0x68089ffadc8ea2b9 diff --git a/numpy/random/tests/data/xoshiro256starstar-testset-1.csv b/numpy/random/tests/data/xoshiro256-testset-1.csv similarity index 100% rename from numpy/random/tests/data/xoshiro256starstar-testset-1.csv rename to numpy/random/tests/data/xoshiro256-testset-1.csv diff --git a/numpy/random/tests/data/xoshiro256starstar-testset-2.csv b/numpy/random/tests/data/xoshiro256-testset-2.csv similarity index 100% rename from numpy/random/tests/data/xoshiro256starstar-testset-2.csv rename to numpy/random/tests/data/xoshiro256-testset-2.csv diff --git a/numpy/random/tests/data/xoshiro512starstar-testset-1.csv b/numpy/random/tests/data/xoshiro512-testset-1.csv similarity index 100% rename from numpy/random/tests/data/xoshiro512starstar-testset-1.csv rename to numpy/random/tests/data/xoshiro512-testset-1.csv diff --git a/numpy/random/tests/data/xoshiro512starstar-testset-2.csv b/numpy/random/tests/data/xoshiro512-testset-2.csv similarity index 100% rename from numpy/random/tests/data/xoshiro512starstar-testset-2.csv rename to numpy/random/tests/data/xoshiro512-testset-2.csv diff --git a/numpy/random/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py index 3c83932e8bb8..a000e5db73f1 100644 --- a/numpy/random/tests/test_against_numpy.py +++ b/numpy/random/tests/test_against_numpy.py @@ -5,7 +5,7 @@ import pytest -from numpy.random import RandomGenerator, MT19937, generator +from numpy.random import Generator, MT19937, generator from numpy.random import RandomState @@ -93,17 +93,17 @@ class TestAgainstNumPy(object): @classmethod def setup_class(cls): cls.np = numpy.random - cls.brng = MT19937 + cls.bit_generator = MT19937 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.rs = RandomState(cls.brng(*cls.seed)) + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.rs = RandomState(cls.bit_generator(*cls.seed)) cls.nprs = cls.np.RandomState(*cls.seed) - cls.initial_state = cls.rg.brng.state + cls.initial_state = cls.rg.bit_generator.state cls._set_common_state() @classmethod def _set_common_state(cls): - state = cls.rg.brng.state + state = cls.rg.bit_generator.state st = [[]] * 5 st[0] = 'MT19937' st[1] = state['state']['key'] @@ -125,7 +125,7 @@ def _set_common_state_legacy(cls): def _is_state_common(self): state = self.nprs.get_state() - state2 = self.rg.brng.state + state2 = self.rg.bit_generator.state assert (state[1] == state2['state']['key']).all() assert (state[2] == state2['state']['pos']) @@ -138,10 +138,10 @@ def _is_state_common_legacy(self): assert_allclose(state[4], state2['gauss'], atol=1e-10) def test_common_seed(self): - self.rg.brng.seed(1234) + self.rg.bit_generator.seed(1234) self.nprs.seed(1234) self._is_state_common() - self.rg.brng.seed(23456) + self.rg.bit_generator.seed(23456) self.nprs.seed(23456) self._is_state_common() @@ -149,8 +149,8 @@ def test_numpy_state(self): nprs = np.random.RandomState() nprs.standard_normal(99) state = nprs.get_state() - self.rg.brng.state = state - state2 = self.rg.brng.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']) @@ -158,7 +158,7 @@ def test_random_sample(self): self._set_common_state() self._is_state_common() v1 = self.nprs.random_sample(10) - v2 = self.rg.random_sample(10) + v2 = self.rg.random(10) assert_array_equal(v1, v2) @@ -263,16 +263,6 @@ def test_vonmises(self): self.rg.vonmises) self._is_state_common() - def test_random_integers(self): - self._set_common_state() - self._is_state_common() - with suppress_warnings() as sup: - sup.record(DeprecationWarning) - compare_2_input(self.nprs.random_integers, - self.rg.random_integers, - is_scalar=True) - self._is_state_common() - def test_binomial(self): self._set_common_state() self._is_state_common() @@ -281,14 +271,6 @@ def test_binomial(self): is_np=True) self._is_state_common() - def test_rand(self): - self._set_common_state() - self._is_state_common() - f = self.rg.rand - g = self.nprs.rand - assert_allclose(f(10), g(10)) - assert_allclose(f(3, 4, 5), g(3, 4, 5)) - def test_poisson_lam_max(self): assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) @@ -367,40 +349,40 @@ def test_shuffle(self): def test_randint(self): self._set_common_state() self._is_state_common() - compare_2_input(self.rg.randint, + compare_2_input(self.rg.integers, self.nprs.randint, is_scalar=True) self._is_state_common() def test_scalar(self): - s = RandomGenerator(MT19937(0)) - assert_equal(s.randint(1000), 684) + s = Generator(MT19937(0)) + assert_equal(s.integers(1000), 684) s1 = np.random.RandomState(0) assert_equal(s1.randint(1000), 684) - assert_equal(s1.randint(1000), s.randint(1000)) + assert_equal(s1.randint(1000), s.integers(1000)) - s = RandomGenerator(MT19937(4294967295)) - assert_equal(s.randint(1000), 419) + s = Generator(MT19937(4294967295)) + assert_equal(s.integers(1000), 419) s1 = np.random.RandomState(4294967295) assert_equal(s1.randint(1000), 419) - assert_equal(s1.randint(1000), s.randint(1000)) + assert_equal(s1.randint(1000), s.integers(1000)) - self.rg.brng.seed(4294967295) + self.rg.bit_generator.seed(4294967295) self.nprs.seed(4294967295) self._is_state_common() def test_array(self): - s = RandomGenerator(MT19937(range(10))) - assert_equal(s.randint(1000), 468) + s = Generator(MT19937(range(10))) + assert_equal(s.integers(1000), 468) s = np.random.RandomState(range(10)) assert_equal(s.randint(1000), 468) - s = RandomGenerator(MT19937(np.arange(10))) - assert_equal(s.randint(1000), 468) - s = RandomGenerator(MT19937([0])) - assert_equal(s.randint(1000), 973) - s = RandomGenerator(MT19937([4294967295])) - assert_equal(s.randint(1000), 265) + s = Generator(MT19937(np.arange(10))) + assert_equal(s.integers(1000), 468) + s = Generator(MT19937([0])) + assert_equal(s.integers(1000), 973) + s = Generator(MT19937([4294967295])) + assert_equal(s.integers(1000), 265) # Tests using legacy generator def test_chisquare(self): diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index fd2d7eb9a565..4a95dfca6cd4 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -7,9 +7,9 @@ assert_raises import pytest -from numpy.random import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, \ - Xoshiro512StarStar, RandomState +from numpy.random import Generator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ + Philox, Xoroshiro128, Xorshift1024, Xoshiro256, \ + Xoshiro512, RandomState from numpy.random.common import interface try: @@ -129,7 +129,7 @@ class Base(object): @classmethod def setup_class(cls): - cls.brng = Xoroshiro128 + cls.bit_generator = Xoroshiro128 cls.bits = 64 cls.dtype = np.uint64 cls.seed_error_type = TypeError @@ -148,177 +148,173 @@ def _read_csv(cls, filename): return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)} def test_raw(self): - brng = self.brng(*self.data1['seed']) - uints = brng.random_raw(1000) + bit_generator = self.bit_generator(*self.data1['seed']) + uints = bit_generator.random_raw(1000) assert_equal(uints, self.data1['data']) - brng = self.brng(*self.data1['seed']) - uints = brng.random_raw() + bit_generator = self.bit_generator(*self.data1['seed']) + uints = bit_generator.random_raw() assert_equal(uints, self.data1['data'][0]) - brng = self.brng(*self.data2['seed']) - uints = brng.random_raw(1000) + 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): - brng = self.brng(*self.data1['seed']) - uints = brng.random_raw(output=False) + bit_generator = self.bit_generator(*self.data1['seed']) + uints = bit_generator.random_raw(output=False) assert uints is None - uints = brng.random_raw(1000, output=False) + uints = bit_generator.random_raw(1000, output=False) assert uints is None def test_gauss_inv(self): n = 25 - rs = RandomState(self.brng(*self.data1['seed'])) + 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.brng(*self.data2['seed'])) + 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 = RandomGenerator(self.brng(*self.data1['seed'])) + rs = Generator(self.bit_generator(*self.data1['seed'])) vals = uniform_from_uint(self.data1['data'], self.bits) - uniforms = rs.random_sample(len(vals)) + uniforms = rs.random(len(vals)) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float64) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = Generator(self.bit_generator(*self.data2['seed'])) vals = uniform_from_uint(self.data2['data'], self.bits) - uniforms = rs.random_sample(len(vals)) + uniforms = rs.random(len(vals)) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float64) def test_uniform_float(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) + rs = Generator(self.bit_generator(*self.data1['seed'])) vals = uniform32_from_uint(self.data1['data'], self.bits) - uniforms = rs.random_sample(len(vals), dtype=np.float32) + uniforms = rs.random(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = Generator(self.bit_generator(*self.data2['seed'])) vals = uniform32_from_uint(self.data2['data'], self.bits) - uniforms = rs.random_sample(len(vals), dtype=np.float32) + uniforms = rs.random(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.brng.seed, np.pi) - assert_raises(self.seed_error_type, rs.brng.seed, -np.pi) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, np.pi) + assert_raises(self.seed_error_type, rs.bit_generator.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([-np.pi])) - assert_raises(ValueError, rs.brng.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, rs.brng.seed, np.array([0, np.pi])) - assert_raises(TypeError, rs.brng.seed, [np.pi]) - assert_raises(TypeError, rs.brng.seed, [0, np.pi]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, np.array([np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, np.array([-np.pi])) + assert_raises(ValueError, rs.bit_generator.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, [np.pi]) + assert_raises(TypeError, rs.bit_generator.seed, [0, np.pi]) def test_seed_out_of_range(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.brng.seed, 2 ** (2 * self.bits + 1)) - assert_raises(ValueError, rs.brng.seed, -1) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(ValueError, rs.bit_generator.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.bit_generator.seed, -1) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) - assert_raises(ValueError, rs.brng.seed, [-1]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(ValueError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, [-1]) def test_repr(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert 'RandomGenerator' in repr(rs) + 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 = RandomGenerator(self.brng(*self.data1['seed'])) - assert 'RandomGenerator' in str(rs) - assert str(self.brng.__name__) in str(rs) + 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_generator(self): - brng = self.brng(*self.data1['seed']) - assert isinstance(brng.generator, RandomGenerator) - def test_pickle(self): import pickle - brng = self.brng(*self.data1['seed']) - state = brng.state - brng_pkl = pickle.dumps(brng) + bit_generator = self.bit_generator(*self.data1['seed']) + state = bit_generator.state + brng_pkl = pickle.dumps(bit_generator) reloaded = pickle.loads(brng_pkl) reloaded_state = reloaded.state - assert_array_equal(brng.generator.standard_normal(1000), - reloaded.generator.standard_normal(1000)) - assert brng is not reloaded + 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) def test_invalid_state_type(self): - brng = self.brng(*self.data1['seed']) + bit_generator = self.bit_generator(*self.data1['seed']) with pytest.raises(TypeError): - brng.state = {'1'} + bit_generator.state = {'1'} def test_invalid_state_value(self): - brng = self.brng(*self.data1['seed']) - state = brng.state - state['brng'] = 'otherBRNG' + bit_generator = self.bit_generator(*self.data1['seed']) + state = bit_generator.state + state['bit_generator'] = 'otherBRNG' with pytest.raises(ValueError): - brng.state = state + bit_generator.state = state def test_invalid_seed_type(self): - brng = self.brng(*self.data1['seed']) + bit_generator = self.bit_generator(*self.data1['seed']) for st in self.invalid_seed_types: with pytest.raises(TypeError): - brng.seed(*st) + bit_generator.seed(*st) def test_invalid_seed_values(self): - brng = self.brng(*self.data1['seed']) + bit_generator = self.bit_generator(*self.data1['seed']) for st in self.invalid_seed_values: with pytest.raises(ValueError): - brng.seed(*st) + bit_generator.seed(*st) def test_benchmark(self): - brng = self.brng(*self.data1['seed']) - brng._benchmark(1) - brng._benchmark(1, 'double') + bit_generator = self.bit_generator(*self.data1['seed']) + bit_generator._benchmark(1) + bit_generator._benchmark(1, 'double') with pytest.raises(ValueError): - brng._benchmark(1, 'int32') + bit_generator._benchmark(1, 'int32') @pytest.mark.skipif(MISSING_CFFI, reason='cffi not available') def test_cffi(self): - brng = self.brng(*self.data1['seed']) - cffi_interface = brng.cffi + bit_generator = self.bit_generator(*self.data1['seed']) + cffi_interface = bit_generator.cffi assert isinstance(cffi_interface, interface) - other_cffi_interface = brng.cffi + 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): - brng = self.brng(*self.data1['seed']) - ctypes_interface = brng.ctypes + bit_generator = self.bit_generator(*self.data1['seed']) + ctypes_interface = bit_generator.ctypes assert isinstance(ctypes_interface, interface) - other_ctypes_interface = brng.ctypes + other_ctypes_interface = bit_generator.ctypes assert other_ctypes_interface is ctypes_interface def test_getstate(self): - brng = self.brng(*self.data1['seed']) - state = brng.state - alt_state = brng.__getstate__() + bit_generator = self.bit_generator(*self.data1['seed']) + state = bit_generator.state + alt_state = bit_generator.__getstate__() assert_state_equal(state, alt_state) class TestXoroshiro128(Base): @classmethod def setup_class(cls): - cls.brng = Xoroshiro128 + cls.bit_generator = Xoroshiro128 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -330,31 +326,31 @@ def setup_class(cls): cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] -class TestXoshiro256StarStar(Base): +class TestXoshiro256(Base): @classmethod def setup_class(cls): - cls.brng = Xoshiro256StarStar + cls.bit_generator = Xoshiro256 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( - join(pwd, './data/xoshiro256starstar-testset-1.csv')) + join(pwd, './data/xoshiro256-testset-1.csv')) cls.data2 = cls._read_csv( - join(pwd, './data/xoshiro256starstar-testset-2.csv')) + join(pwd, './data/xoshiro256-testset-2.csv')) cls.seed_error_type = TypeError cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] -class TestXoshiro512StarStar(Base): +class TestXoshiro512(Base): @classmethod def setup_class(cls): - cls.brng = Xoshiro512StarStar + cls.bit_generator = Xoshiro512 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( - join(pwd, './data/xoshiro512starstar-testset-1.csv')) + join(pwd, './data/xoshiro512-testset-1.csv')) cls.data2 = cls._read_csv( - join(pwd, './data/xoshiro512starstar-testset-2.csv')) + join(pwd, './data/xoshiro512-testset-2.csv')) cls.seed_error_type = TypeError cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] @@ -363,7 +359,7 @@ def setup_class(cls): class TestXorshift1024(Base): @classmethod def setup_class(cls): - cls.brng = Xorshift1024 + cls.bit_generator = Xorshift1024 cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -378,7 +374,7 @@ def setup_class(cls): class TestThreeFry(Base): @classmethod def setup_class(cls): - cls.brng = ThreeFry + cls.bit_generator = ThreeFry cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -391,48 +387,17 @@ def setup_class(cls): (None, None, 2 ** 257 + 1)] def test_set_key(self): - brng = self.brng(*self.data1['seed']) - state = brng.state - keyed = self.brng(counter=state['state']['counter'], + 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(brng.state, keyed.state) - - -class TestPCG64(Base): - @classmethod - def setup_class(cls): - cls.brng = 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 = TypeError - cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), - (None, np.zeros(1))] - cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), - (None, 2 ** 129 + 1)] - - def test_seed_float_array(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([-np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, - np.array([np.pi, -np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, np.array([0, np.pi])) - assert_raises(self.seed_error_type, rs.brng.seed, [np.pi]) - assert_raises(self.seed_error_type, rs.brng.seed, [0, np.pi]) - - def test_seed_out_of_range_array(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.brng.seed, - [2 ** (2 * self.bits + 1)]) - assert_raises(self.seed_error_type, rs.brng.seed, [-1]) + assert_state_equal(bit_generator.state, keyed.state) class TestPhilox(Base): @classmethod def setup_class(cls): - cls.brng = Philox + cls.bit_generator = Philox cls.bits = 64 cls.dtype = np.uint64 cls.data1 = cls._read_csv( @@ -445,17 +410,17 @@ def setup_class(cls): (None, None, 2 ** 257 + 1)] def test_set_key(self): - brng = self.brng(*self.data1['seed']) - state = brng.state - keyed = self.brng(counter=state['state']['counter'], + 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(brng.state, keyed.state) + assert_state_equal(bit_generator.state, keyed.state) class TestMT19937(Base): @classmethod def setup_class(cls): - cls.brng = MT19937 + cls.bit_generator = MT19937 cls.bits = 32 cls.dtype = np.uint32 cls.data1 = cls._read_csv(join(pwd, './data/mt19937-testset-1.csv')) @@ -466,54 +431,54 @@ def setup_class(cls): def test_seed_out_of_range(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.brng.seed, 2 ** (self.bits + 1)) - assert_raises(ValueError, rs.brng.seed, -1) - assert_raises(ValueError, rs.brng.seed, 2 ** (2 * self.bits + 1)) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(ValueError, rs.bit_generator.seed, 2 ** (self.bits + 1)) + assert_raises(ValueError, rs.bit_generator.seed, -1) + assert_raises(ValueError, rs.bit_generator.seed, 2 ** (2 * self.bits + 1)) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.brng.seed, [2 ** (self.bits + 1)]) - assert_raises(ValueError, rs.brng.seed, [-1]) - assert_raises(TypeError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(ValueError, rs.bit_generator.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, [-1]) + assert_raises(TypeError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.brng.seed, np.pi) - assert_raises(TypeError, rs.brng.seed, -np.pi) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(TypeError, rs.bit_generator.seed, np.pi) + assert_raises(TypeError, rs.bit_generator.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - brng = rs.brng - assert_raises(TypeError, brng.seed, np.array([np.pi])) - assert_raises(TypeError, brng.seed, np.array([-np.pi])) - assert_raises(TypeError, brng.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, brng.seed, np.array([0, np.pi])) - assert_raises(TypeError, brng.seed, [np.pi]) - assert_raises(TypeError, brng.seed, [0, np.pi]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + bit_generator = rs.bit_generator + assert_raises(TypeError, bit_generator.seed, np.array([np.pi])) + assert_raises(TypeError, bit_generator.seed, np.array([-np.pi])) + assert_raises(TypeError, bit_generator.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, bit_generator.seed, np.array([0, np.pi])) + assert_raises(TypeError, bit_generator.seed, [np.pi]) + assert_raises(TypeError, bit_generator.seed, [0, np.pi]) def test_state_tuple(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - brng = rs.brng - state = brng.state - desired = rs.randint(2 ** 16) - tup = (state['brng'], state['state']['key'], state['state']['pos']) - brng.state = tup - actual = rs.randint(2 ** 16) + 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) - brng.state = tup - actual = rs.randint(2 ** 16) + bit_generator.state = tup + actual = rs.integers(2 ** 16) assert_equal(actual, desired) class TestDSFMT(Base): @classmethod def setup_class(cls): - cls.brng = DSFMT + cls.bit_generator = DSFMT cls.bits = 53 cls.dtype = np.uint64 cls.data1 = cls._read_csv(join(pwd, './data/dSFMT-testset-1.csv')) @@ -524,74 +489,74 @@ def setup_class(cls): (np.array([2 ** 33, 2 ** 33]),)] def test_uniform_double(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) + rs = Generator(self.bit_generator(*self.data1['seed'])) assert_array_equal(uniform_from_dsfmt(self.data1['data']), - rs.random_sample(1000)) + rs.random(1000)) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = Generator(self.bit_generator(*self.data2['seed'])) assert_equal(uniform_from_dsfmt(self.data2['data']), - rs.random_sample(1000)) + rs.random(1000)) def test_gauss_inv(self): n = 25 - rs = RandomState(self.brng(*self.data1['seed'])) + rs = RandomState(self.bit_generator(*self.data1['seed'])) gauss = rs.standard_normal(n) assert_allclose(gauss, gauss_from_uint(self.data1['data'], n, 'dsfmt')) - rs = RandomState(self.brng(*self.data2['seed'])) + rs = RandomState(self.bit_generator(*self.data2['seed'])) gauss = rs.standard_normal(25) assert_allclose(gauss, gauss_from_uint(self.data2['data'], n, 'dsfmt')) def test_seed_out_of_range_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(ValueError, rs.brng.seed, [2 ** (self.bits + 1)]) - assert_raises(ValueError, rs.brng.seed, [-1]) - assert_raises(TypeError, rs.brng.seed, [2 ** (2 * self.bits + 1)]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(ValueError, rs.bit_generator.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, [-1]) + assert_raises(TypeError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.brng.seed, np.pi) - assert_raises(TypeError, rs.brng.seed, -np.pi) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(TypeError, rs.bit_generator.seed, np.pi) + assert_raises(TypeError, rs.bit_generator.seed, -np.pi) def test_seed_float_array(self): # GH #82 - rs = RandomGenerator(self.brng(*self.data1['seed'])) - assert_raises(TypeError, rs.brng.seed, np.array([np.pi])) - assert_raises(TypeError, rs.brng.seed, np.array([-np.pi])) - assert_raises(TypeError, rs.brng.seed, np.array([np.pi, -np.pi])) - assert_raises(TypeError, rs.brng.seed, np.array([0, np.pi])) - assert_raises(TypeError, rs.brng.seed, [np.pi]) - assert_raises(TypeError, rs.brng.seed, [0, np.pi]) + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(TypeError, rs.bit_generator.seed, np.array([np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, np.array([-np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, np.array([0, np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, [np.pi]) + assert_raises(TypeError, rs.bit_generator.seed, [0, np.pi]) def test_uniform_float(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) + rs = Generator(self.bit_generator(*self.data1['seed'])) vals = uniform32_from_uint(self.data1['data'], self.bits) - uniforms = rs.random_sample(len(vals), dtype=np.float32) + uniforms = rs.random(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) - rs = RandomGenerator(self.brng(*self.data2['seed'])) + rs = Generator(self.bit_generator(*self.data2['seed'])) vals = uniform32_from_uint(self.data2['data'], self.bits) - uniforms = rs.random_sample(len(vals), dtype=np.float32) + uniforms = rs.random(len(vals), dtype=np.float32) assert_allclose(uniforms, vals) assert_equal(uniforms.dtype, np.float32) def test_buffer_reset(self): - rs = RandomGenerator(self.brng(*self.data1['seed'])) - rs.random_sample(1) - assert rs.brng.state['buffer_loc'] != 382 - rs.brng.seed(*self.data1['seed']) - assert rs.brng.state['buffer_loc'] == 382 + rs = Generator(self.bit_generator(*self.data1['seed'])) + rs.random(1) + assert rs.bit_generator.state['buffer_loc'] != 382 + rs.bit_generator.seed(*self.data1['seed']) + assert rs.bit_generator.state['buffer_loc'] == 382 class TestThreeFry32(Base): @classmethod def setup_class(cls): - cls.brng = ThreeFry32 + cls.bit_generator = ThreeFry32 cls.bits = 32 cls.dtype = np.uint32 cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) @@ -602,23 +567,8 @@ def setup_class(cls): (None, None, 2 ** 129 + 1)] def test_set_key(self): - brng = self.brng(*self.data1['seed']) - state = brng.state - keyed = self.brng(counter=state['state']['counter'], + 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(brng.state, keyed.state) - - -class TestPCG32(TestPCG64): - @classmethod - def setup_class(cls): - cls.brng = PCG32 - cls.bits = 32 - cls.dtype = np.uint32 - cls.data1 = cls._read_csv(join(pwd, './data/pcg32-testset-1.csv')) - cls.data2 = cls._read_csv(join(pwd, './data/pcg32-testset-2.csv')) - cls.seed_error_type = TypeError - cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), - (None, np.zeros(1))] - cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), - (None, 2 ** 129 + 1)] + assert_state_equal(bit_generator.state, keyed.state) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index ace5c230c677..3bb3bd791c46 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -9,32 +9,32 @@ assert_warns, assert_no_warnings, assert_array_equal, assert_array_almost_equal, suppress_warnings) -from numpy.random import RandomGenerator, MT19937 +from numpy.random import Generator, MT19937 -random = RandomGenerator(MT19937()) +random = Generator(MT19937()) @pytest.fixture(scope='module', params=[True, False]) -def closed(request): +def endpoint(request): return request.param class TestSeed(object): def test_scalar(self): - s = RandomGenerator(MT19937(0)) - assert_equal(s.randint(1000), 684) - s = RandomGenerator(MT19937(4294967295)) - assert_equal(s.randint(1000), 419) + s = Generator(MT19937(0)) + assert_equal(s.integers(1000), 684) + s = Generator(MT19937(4294967295)) + assert_equal(s.integers(1000), 419) def test_array(self): - s = RandomGenerator(MT19937(range(10))) - assert_equal(s.randint(1000), 468) - s = RandomGenerator(MT19937(np.arange(10))) - assert_equal(s.randint(1000), 468) - s = RandomGenerator(MT19937([0])) - assert_equal(s.randint(1000), 973) - s = RandomGenerator(MT19937([4294967295])) - assert_equal(s.randint(1000), 265) + s = Generator(MT19937(range(10))) + assert_equal(s.integers(1000), 468) + s = Generator(MT19937(np.arange(10))) + assert_equal(s.integers(1000), 468) + s = Generator(MT19937([0])) + assert_equal(s.integers(1000), 973) + s = Generator(MT19937([4294967295])) + assert_equal(s.integers(1000), 265) def test_invalid_scalar(self): # seed must be an unsigned 32 bit integer @@ -49,8 +49,8 @@ def test_invalid_array(self): assert_raises(ValueError, MT19937, [1, 2, 4294967296]) assert_raises(ValueError, MT19937, [1, -2, 4294967296]) - def test_noninstantized_brng(self): - assert_raises(ValueError, RandomGenerator, MT19937) + def test_noninstantized_bitgen(self): + assert_raises(ValueError, Generator, MT19937) class TestBinomial(object): @@ -76,8 +76,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_(-5 <= random.integers(-5, -1) < -1) + x = random.integers(-5, -1, 5) assert_(np.all(-5 <= x)) assert_(np.all(x < -1)) @@ -107,23 +107,23 @@ def test_invalid_n(self): class TestSetState(object): def setup(self): self.seed = 1234567890 - self.rg = RandomGenerator(MT19937(self.seed)) - self.brng = self.rg.brng - self.state = self.brng.state - self.legacy_state = (self.state['brng'], + 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_basic(self): old = self.rg.tomaxint(16) - self.brng.state = self.state + self.bit_generator.state = self.state new = self.rg.tomaxint(16) assert_(np.all(old == new)) def test_gaussian_reset(self): # Make sure the cached every-other-Gaussian is reset. old = self.rg.standard_normal(size=3) - self.brng.state = self.state + self.bit_generator.state = self.state new = self.rg.standard_normal(size=3) assert_(np.all(old == new)) @@ -132,9 +132,9 @@ def test_gaussian_reset_in_media_res(self): # cached Gaussian is restored. self.rg.standard_normal() - state = self.brng.state + state = self.bit_generator.state old = self.rg.standard_normal(size=3) - self.brng.state = state + self.bit_generator.state = state new = self.rg.standard_normal(size=3) assert_(np.all(old == new)) @@ -144,84 +144,84 @@ def test_negative_binomial(self): self.rg.negative_binomial(0.5, 0.5) -class TestRandint(object): - rfunc = random.randint +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, closed): - assert_raises(TypeError, self.rfunc, 1, closed=closed, dtype=float) + def test_unsupported_type(self, endpoint): + assert_raises(TypeError, self.rfunc, 1, endpoint=endpoint, dtype=float) - def test_bounds_checking(self, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd assert_raises(ValueError, self.rfunc, lbnd - 1, ubnd, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, lbnd, ubnd + 1, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, ubnd, lbnd, - closed=closed, dtype=dt) - assert_raises(ValueError, self.rfunc, 1, 0, closed=closed, + endpoint=endpoint, dtype=dt) + assert_raises(ValueError, self.rfunc, 1, 0, endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, [lbnd - 1], ubnd, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, [lbnd], [ubnd + 1], - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, [ubnd], [lbnd], - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, 1, [0], - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) - def test_bounds_checking_array(self, closed): + 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 closed) + ubnd = 2 if dt is bool else np.iinfo(dt).max + (not endpoint) assert_raises(ValueError, self.rfunc, [ - lbnd - 1] * 2, [ubnd] * 2, closed=closed, dtype=dt) + lbnd - 1] * 2, [ubnd] * 2, endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, [ - lbnd] * 2, [ubnd + 1] * 2, closed=closed, dtype=dt) + lbnd] * 2, [ubnd + 1] * 2, endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, ubnd, [lbnd] * 2, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) assert_raises(ValueError, self.rfunc, [1] * 2, 0, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) - def test_rng_zero_and_extremes(self, closed): + 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 closed else ubnd - is_open = not closed + ubnd = ubnd - 1 if endpoint else ubnd + is_open = not endpoint tgt = ubnd - 1 assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, - closed=closed, dtype=dt), tgt) + endpoint=endpoint, dtype=dt), tgt) assert_equal(self.rfunc([tgt], tgt + is_open, size=1000, - closed=closed, dtype=dt), tgt) + endpoint=endpoint, dtype=dt), tgt) tgt = lbnd assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, - closed=closed, dtype=dt), tgt) + endpoint=endpoint, dtype=dt), tgt) assert_equal(self.rfunc(tgt, [tgt + is_open], size=1000, - closed=closed, dtype=dt), tgt) + endpoint=endpoint, dtype=dt), tgt) tgt = (lbnd + ubnd) // 2 assert_equal(self.rfunc(tgt, tgt + is_open, size=1000, - closed=closed, dtype=dt), tgt) + endpoint=endpoint, dtype=dt), tgt) assert_equal(self.rfunc([tgt], [tgt + is_open], - size=1000, closed=closed, dtype=dt), tgt) + size=1000, endpoint=endpoint, dtype=dt), tgt) - def test_rng_zero_and_extremes_array(self, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd tgt = ubnd - 1 assert_equal(self.rfunc([tgt], [tgt + 1], @@ -247,73 +247,73 @@ def test_rng_zero_and_extremes_array(self, closed): assert_equal(self.rfunc( [tgt] * size, [tgt + 1] * size, size=size, dtype=dt), tgt) - def test_full_range(self, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd try: - self.rfunc(lbnd, ubnd, closed=closed, dtype=dt) + 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, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd try: - self.rfunc([lbnd] * 2, [ubnd], closed=closed, dtype=dt) + 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, closed): + def test_in_bounds_fuzz(self, endpoint): # Don't use fixed seed - random.brng.seed() + random.bit_generator.seed() for dt in self.itype[1:]: for ubnd in [4, 8, 16]: - vals = self.rfunc(2, ubnd - closed, size=2 ** 16, - closed=closed, dtype=dt) + 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 - closed, size=2 ** 16, closed=closed, + 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, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd size = 1000 - random.brng.seed(1234) - scalar = self.rfunc(lbnd, ubnd, size=size, closed=closed, dtype=dt) + random.bit_generator.seed(1234) + scalar = self.rfunc(lbnd, ubnd, size=size, endpoint=endpoint, dtype=dt) - random.brng.seed(1234) + random.bit_generator.seed(1234) scalar_array = self.rfunc([lbnd], [ubnd], size=size, - closed=closed, dtype=dt) + endpoint=endpoint, dtype=dt) - random.brng.seed(1234) + random.bit_generator.seed(1234) array = self.rfunc([lbnd] * size, [ubnd] * - size, size=size, closed=closed, dtype=dt) + size, size=size, endpoint=endpoint, dtype=dt) assert_array_equal(scalar, scalar_array) assert_array_equal(scalar, array) - def test_repeatability(self, closed): + 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 @@ -329,77 +329,77 @@ def test_repeatability(self, closed): 'uint8': '27dd30c4e08a797063dffac2490b0be6'} for dt in self.itype[1:]: - random.brng.seed(1234) + random.bit_generator.seed(1234) # view as little endian for hash if sys.byteorder == 'little': - val = self.rfunc(0, 6 - closed, size=1000, closed=closed, + val = self.rfunc(0, 6 - endpoint, size=1000, endpoint=endpoint, dtype=dt) else: - val = self.rfunc(0, 6 - closed, size=1000, closed=closed, + val = self.rfunc(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.brng.seed(1234) - val = self.rfunc(0, 2 - closed, size=1000, closed=closed, + random.bit_generator.seed(1234) + val = self.rfunc(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, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd # view as little endian for hash - random.brng.seed(1234) - val = self.rfunc(lbnd, ubnd, size=1000, closed=closed, dtype=dt) + random.bit_generator.seed(1234) + val = self.rfunc(lbnd, ubnd, size=1000, endpoint=endpoint, dtype=dt) - random.brng.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, ubnd, closed=closed, dtype=dt) + random.bit_generator.seed(1234) + val_bc = self.rfunc([lbnd] * 1000, ubnd, endpoint=endpoint, dtype=dt) assert_array_equal(val, val_bc) - random.brng.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, closed=closed, + random.bit_generator.seed(1234) + val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, endpoint=endpoint, dtype=dt) assert_array_equal(val, val_bc) - def test_int64_uint64_broadcast_exceptions(self, closed): + 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 - closed + high = high - endpoint low_a = np.array([[low]*10]) high_a = np.array([high] * 10) - assert_raises(ValueError, random.randint, low, high, - closed=closed, dtype=dtype) - assert_raises(ValueError, random.randint, low_a, high, - closed=closed, dtype=dtype) - assert_raises(ValueError, random.randint, low, high_a, - closed=closed, dtype=dtype) - assert_raises(ValueError, random.randint, low_a, high_a, - closed=closed, dtype=dtype) + 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.randint, low_o, high, - closed=closed, dtype=dtype) - assert_raises(ValueError, random.randint, low, high_o, - closed=closed, dtype=dtype) - assert_raises(ValueError, random.randint, low_o, high_o, - closed=closed, dtype=dtype) - - def test_int64_uint64_corner_case(self, closed): + 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 @@ -415,58 +415,58 @@ def test_int64_uint64_corner_case(self, closed): 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 - closed) + ubnd = np.uint64(np.iinfo(np.int64).max + 1 - endpoint) # None of these function calls should # generate a ValueError now. - actual = random.randint(lbnd, ubnd, closed=closed, dtype=dt) + actual = random.integers(lbnd, ubnd, endpoint=endpoint, dtype=dt) assert_equal(actual, tgt) - def test_respect_dtype_singleton(self, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd dt = np.bool_ if dt is bool else dt - sample = self.rfunc(lbnd, ubnd, closed=closed, dtype=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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd # gh-7284: Ensure that we get Python data types - sample = self.rfunc(lbnd, ubnd, closed=closed, dtype=dt) + 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, closed): + 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 closed else ubnd + ubnd = ubnd - 1 if endpoint else ubnd dt = np.bool_ if dt is bool else dt - sample = self.rfunc([lbnd], [ubnd], closed=closed, dtype=dt) + sample = self.rfunc([lbnd], [ubnd], endpoint=endpoint, dtype=dt) assert_equal(sample.dtype, dt) - sample = self.rfunc([lbnd] * 2, [ubnd] * 2, closed=closed, + sample = self.rfunc([lbnd] * 2, [ubnd] * 2, endpoint=endpoint, dtype=dt) assert_equal(sample.dtype, dt) - def test_zero_size(self, closed): + def test_zero_size(self, endpoint): # See gh-7203 for dt in self.itype: - sample = self.rfunc(0, 0, (3, 0, 4), closed=closed, dtype=dt) + 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, closed=closed, dtype=dt).shape == (0,) - 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 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,)) class TestRandomDist(object): @@ -476,178 +476,111 @@ class TestRandomDist(object): def setup(self): self.seed = 1234567890 - def test_rand(self): - random.brng.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.brng.seed(self.seed) - actual = random.rand() - desired = 0.61879477158567997 - assert_array_almost_equal(actual, desired, decimal=15) - - def test_randn(self): - random.brng.seed(self.seed) - actual = random.randn(3, 2) - desired = np.array([[-3.472754000610961, -0.108938564229143], - [-0.245965753396411, -0.704101550261701], - [0.360102487116356, 0.127832101772367]]) - assert_array_almost_equal(actual, desired, decimal=15) - - random.brng.seed(self.seed) - actual = random.randn() - assert_array_almost_equal(actual, desired[0, 0], decimal=15) - - def test_randint(self): - random.brng.seed(self.seed) - actual = random.randint(-99, 99, size=(3, 2)) + def test_integers(self): + random.bit_generator.seed(self.seed) + actual = random.integers(-99, 99, size=(3, 2)) desired = np.array([[31, 3], [-52, 41], [-48, -66]]) assert_array_equal(actual, desired) - def test_randint_masked(self): + def test_integers_masked(self): # Test masked rejection sampling algorithm to generate array of # uint32 in an interval. - random.brng.seed(self.seed) - actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, - use_masked=True) + random.bit_generator.seed(self.seed) + actual = random.integers(0, 99, size=(3, 2), dtype=np.uint32) desired = np.array([[2, 47], [12, 51], [33, 43]], dtype=np.uint32) assert_array_equal(actual, desired) - def test_randint_lemire_32(self): - # Test lemire algorithm to generate array of uint32 in an interval. - random.brng.seed(self.seed) - actual = random.randint(0, 99, size=(3, 2), dtype=np.uint32, - use_masked=False) - desired = np.array([[61, 33], - [58, 14], - [87, 23]], dtype=np.uint32) - assert_array_equal(actual, desired) - - def test_randint_lemire_64(self): - # Test lemire algorithm to generate array of uint64 in an interval. - random.brng.seed(self.seed) - actual = random.randint(0, 99 + 0xFFFFFFFFF, size=(3, 2), - dtype=np.uint64, use_masked=False) - desired = np.array([[42523252834, 40656066204], - [61069871386, 61274051182], - [31443797706, 53476677934]], dtype=np.uint64) - assert_array_equal(actual, desired) - - def test_random_integers(self): - random.brng.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) + def test_integers_closed(self): + random.bit_generator.seed(self.seed) + actual = random.integers(-99, 99, size=(3, 2), endpoint=True) desired = np.array([[31, 3], [-52, 41], [-48, -66]]) assert_array_equal(actual, desired) - def test_random_integers_max_int(self): - # Tests whether random_integers can generate the + 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. - 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) + 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_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.brng.seed(self.seed) - actual = random.random_sample((3, 2)) + def test_random(self): + random.bit_generator.seed(self.seed) + actual = random.random((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.brng.seed(self.seed) - actual = random.random_sample() + random.bit_generator.seed(self.seed) + actual = random.random() assert_array_almost_equal(actual, desired[0, 0], decimal=15) - def test_random_sample_float(self): - random.brng.seed(self.seed) - actual = random.random_sample((3, 2)) + def test_random_float(self): + random.bit_generator.seed(self.seed) + actual = random.random((3, 2)) desired = np.array([[0.6187948, 0.5916236], [0.8886836, 0.8916548], [0.4575675, 0.7781881]]) assert_array_almost_equal(actual, desired, decimal=7) - def test_random_sample_float_scalar(self): - random.brng.seed(self.seed) - actual = random.random_sample(dtype=np.float32) + def test_random_float_scalar(self): + random.bit_generator.seed(self.seed) + actual = random.random(dtype=np.float32) desired = 0.6187948 assert_array_almost_equal(actual, desired, decimal=7) - def test_random_sample_unsupported_type(self): - assert_raises(TypeError, random.random_sample, dtype='int32') + def test_random_unsupported_type(self): + assert_raises(TypeError, random.random, dtype='int32') def test_choice_uniform_replace(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.choice(4, 4) desired = np.array([2, 3, 2, 3], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_nonuniform_replace(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.choice(4, 4, p=[0.4, 0.4, 0.1, 0.1]) desired = np.array([1, 1, 2, 2], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_uniform_noreplace(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.choice(4, 3, replace=False) desired = np.array([0, 2, 3], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_nonuniform_noreplace(self): - random.brng.seed(self.seed) + random.bit_generator.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], dtype=np.int64) assert_array_equal(actual, desired) def test_choice_noninteger(self): - random.brng.seed(self.seed) + random.bit_generator.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_multidimensional_default_axis(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.choice([[0, 1], [2, 3], [4, 5], [6, 7]], 3) desired = np.array([[4, 5], [6, 7], [4, 5]]) assert_array_equal(actual, desired) def test_choice_multidimensional_custom_axis(self): - random.brng.seed(self.seed) + random.bit_generator.seed(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) @@ -707,9 +640,9 @@ def test_choice_return_shape(self): 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.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, @@ -737,7 +670,7 @@ def test_choice_large_sample(self): import hashlib choice_hash = '6395868be877d27518c832213c17977c' - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.choice(10000, 5000, replace=False) if sys.byteorder != 'little': actual = actual.byteswap() @@ -745,7 +678,7 @@ def test_choice_large_sample(self): assert_(choice_hash == res) def test_bytes(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.bytes(10) desired = b'\x82Ui\x9e\xff\x97+Wf\xa5' assert_equal(actual, desired) @@ -770,7 +703,7 @@ def test_shuffle(self): lambda x: np.asarray([(i, i) for i in x], [("a", object, 1), ("b", np.int32, 1)])]: - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) random.shuffle(alist) actual = alist @@ -792,19 +725,19 @@ def test_shuffle_masked(self): sorted(b.data[~b.mask]), sorted(b_orig.data[~b_orig.mask])) def test_permutation(self): - random.brng.seed(self.seed) + random.bit_generator.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.brng.seed(self.seed) + random.bit_generator.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.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.beta(.1, .9, size=(3, 2)) desired = np.array( [[1.45341850513746058e-02, 5.31297615662868145e-04], @@ -813,20 +746,20 @@ def test_beta(self): assert_array_almost_equal(actual, desired, decimal=15) def test_binomial(self): - random.brng.seed(self.seed) + random.bit_generator.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.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.binomial(100.123, .456) desired = 37 assert_array_equal(actual, desired) def test_chisquare(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.chisquare(50, size=(3, 2)) desired = np.array([[22.2534560369812, 46.9302393710074], [52.9974164611614, 85.3559029505718], @@ -834,7 +767,7 @@ def test_chisquare(self): assert_array_almost_equal(actual, desired, decimal=13) def test_dirichlet(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) actual = random.dirichlet(alpha, size=(3, 2)) desired = np.array([[[0.444382290764855, 0.555617709235145], @@ -847,7 +780,7 @@ def test_dirichlet(self): bad_alpha = np.array([5.4e-01, -1.0e-16]) assert_raises(ValueError, random.dirichlet, bad_alpha) - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) alpha = np.array([51.72840233779265162, 39.74494232180943953]) actual = random.dirichlet(alpha) assert_array_almost_equal(actual, desired[0, 0], decimal=15) @@ -870,7 +803,7 @@ def test_dirichlet_bad_alpha(self): assert_raises(ValueError, random.dirichlet, alpha) def test_exponential(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.exponential(1.1234, size=(3, 2)) desired = np.array([[5.350682337747634, 1.152307441755771], [3.867015473358779, 1.538765912839396], @@ -882,7 +815,7 @@ def test_exponential_0(self): assert_raises(ValueError, random.exponential, scale=-0.) def test_f(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.f(12, 77, size=(3, 2)) desired = np.array([[0.809498839488467, 2.867222762455471], [0.588036831639353, 1.012185639664636], @@ -890,7 +823,7 @@ def test_f(self): assert_array_almost_equal(actual, desired, decimal=15) def test_gamma(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.gamma(5, 3, size=(3, 2)) desired = np.array([[12.46569350177219, 16.46580642087044], [43.65744473309084, 11.98722785682592], @@ -902,7 +835,7 @@ def test_gamma_0(self): assert_raises(ValueError, random.gamma, shape=-0., scale=-0.) def test_geometric(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.geometric(.123456789, size=(3, 2)) desired = np.array([[8, 7], [17, 17], @@ -919,7 +852,7 @@ def test_geometric_exceptions(self): assert_raises(ValueError, random.geometric, [np.nan] * 10) def test_gumbel(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -931,7 +864,7 @@ def test_gumbel_0(self): assert_raises(ValueError, random.gumbel, scale=-0.) def test_hypergeometric(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.hypergeometric(10.1, 5.5, 14, size=(3, 2)) desired = np.array([[10, 10], [10, 10], @@ -957,7 +890,7 @@ def test_hypergeometric(self): assert_array_equal(actual, desired) def test_laplace(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -969,7 +902,7 @@ def test_laplace_0(self): assert_raises(ValueError, random.laplace, scale=-0.) def test_logistic(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -977,7 +910,7 @@ def test_logistic(self): assert_array_almost_equal(actual, desired, decimal=15) def test_lognormal(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2)) desired = np.array([[1.0894838661036e-03, 9.0990021488311e-01], [6.9178869932225e-01, 2.7672077560016e-01], @@ -989,7 +922,7 @@ def test_lognormal_0(self): assert_raises(ValueError, random.lognormal, sigma=-0.) def test_logseries(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.logseries(p=.923456789, size=(3, 2)) desired = np.array([[2, 2], [6, 17], @@ -1002,7 +935,7 @@ def test_logseries_exceptions(self): assert_raises(ValueError, random.logseries, [np.nan] * 10) def test_multinomial(self): - random.brng.seed(self.seed) + random.bit_generator.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]], @@ -1013,7 +946,7 @@ def test_multinomial(self): assert_array_equal(actual, desired) def test_multivariate_normal(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) mean = (.123456789, 10) cov = [[1, 0], [0, 1]] size = (3, 2) @@ -1064,7 +997,7 @@ def test_multivariate_normal(self): mu, np.eye(3)) def test_negative_binomial(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.negative_binomial(n=100, p=.12345, size=(3, 2)) desired = np.array([[521, 736], [665, 690], @@ -1078,7 +1011,7 @@ def test_negative_binomial_exceptions(self): [np.nan] * 10) def test_noncentral_chisquare(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2)) desired = np.array([[9.47783251920357, 10.02066178260461], [3.15869984192364, 10.5581565031544], @@ -1091,7 +1024,7 @@ def test_noncentral_chisquare(self): [1.41985055641800, 0.15451287602753]]) assert_array_almost_equal(actual, desired, decimal=14) - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.noncentral_chisquare(df=5, nonc=0, size=(3, 2)) desired = np.array([[3.64881368071039, 5.48224544747803], [20.41999842025404, 3.44075915187367], @@ -1099,7 +1032,7 @@ def test_noncentral_chisquare(self): assert_array_almost_equal(actual, desired, decimal=14) def test_noncentral_f(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.noncentral_f(dfnum=5, dfden=2, nonc=1, size=(3, 2)) desired = np.array([[1.22680230963236, 2.56457837623956], @@ -1108,12 +1041,12 @@ def test_noncentral_f(self): assert_array_almost_equal(actual, desired, decimal=14) def test_noncentral_f_nan(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.noncentral_f(dfnum=5, dfden=2, nonc=np.nan) assert np.isnan(actual) def test_normal(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.normal(loc=.123456789, scale=2.0, size=(3, 2)) desired = np.array([[-6.822051212221923, -0.094420339458285], [-0.368474717792823, -1.284746311523402], @@ -1125,7 +1058,7 @@ def test_normal_0(self): assert_raises(ValueError, random.normal, scale=-0.) def test_pareto(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.pareto(a=.123456789, size=(3, 2)) desired = np.array([[5.6883528121891552e+16, 4.0569373841667057e+03], [1.2854967019379475e+12, 6.5833156486851483e+04], @@ -1139,7 +1072,7 @@ def test_pareto(self): np.testing.assert_array_almost_equal_nulp(actual, desired, nulp=30) def test_poisson(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.poisson(lam=.123456789, size=(3, 2)) desired = np.array([[0, 0], [1, 0], @@ -1158,7 +1091,7 @@ def test_poisson_exceptions(self): assert_raises(ValueError, random.poisson, [np.nan] * 10) def test_power(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.power(a=.123456789, size=(3, 2)) desired = np.array([[9.328833342693975e-01, 2.742250409261003e-02], [7.684513237993961e-01, 9.297548209160028e-02], @@ -1166,7 +1099,7 @@ def test_power(self): assert_array_almost_equal(actual, desired, decimal=15) def test_rayleigh(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.rayleigh(scale=10, size=(3, 2)) desired = np.array([[13.8882496494248393, 13.383318339044731], [20.95413364294492098, 21.08285015800712614], @@ -1178,7 +1111,7 @@ def test_rayleigh_0(self): assert_raises(ValueError, random.rayleigh, scale=-0.) def test_standard_cauchy(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_cauchy(size=(3, 2)) desired = np.array([[31.87809592667601, 0.349332782046838], [2.816995747731641, 10.552372563459114], @@ -1186,7 +1119,7 @@ def test_standard_cauchy(self): assert_array_almost_equal(actual, desired, decimal=15) def test_standard_exponential(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_exponential(size=(3, 2), method='inv') desired = np.array([[0.96441739162374596, 0.89556604882105506], [2.1953785836319808, 2.22243285392490542], @@ -1197,7 +1130,7 @@ def test_standard_expoential_type_error(self): assert_raises(TypeError, random.standard_exponential, dtype=np.int32) def test_standard_gamma(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_gamma(shape=3, size=(3, 2)) desired = np.array([[2.28483515569645, 3.29899524967824], [11.12492298902645, 2.16784417297277], @@ -1205,13 +1138,13 @@ def test_standard_gamma(self): assert_array_almost_equal(actual, desired, decimal=14) def test_standard_gammma_scalar_float(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_gamma(3, dtype=np.float32) desired = 1.3877466 assert_array_almost_equal(actual, desired, decimal=6) def test_standard_gamma_float(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_gamma(shape=3, size=(3, 2)) desired = np.array([[2.2848352, 3.2989952], [11.124923, 2.1678442], @@ -1220,14 +1153,14 @@ def test_standard_gamma_float(self): def test_standard_gammma_float_out(self): actual = np.zeros((3, 2), dtype=np.float32) - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) random.standard_gamma(10.0, out=actual, dtype=np.float32) desired = np.array([[6.9824033, 7.3731737], [14.860578, 7.5327270], [11.767487, 6.2320185]], dtype=np.float32) assert_array_almost_equal(actual, desired, decimal=5) - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) random.standard_gamma(10.0, out=actual, size=(3, 2), dtype=np.float32) assert_array_almost_equal(actual, desired, decimal=5) @@ -1247,7 +1180,7 @@ def test_standard_gamma_0(self): assert_raises(ValueError, random.standard_gamma, shape=-0.) def test_standard_normal(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_normal(size=(3, 2)) desired = np.array([[-3.472754000610961, -0.108938564229143], [-0.245965753396411, -0.704101550261701], @@ -1258,7 +1191,7 @@ def test_standard_normal_unsupported_type(self): assert_raises(TypeError, random.standard_normal, dtype=np.int32) def test_standard_t(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.standard_t(df=10, size=(3, 2)) desired = np.array([[-3.68722108185508, -0.672031186266171], [2.900224996448669, -0.199656996187739], @@ -1266,7 +1199,7 @@ def test_standard_t(self): assert_array_almost_equal(actual, desired, decimal=15) def test_triangular(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -1275,7 +1208,7 @@ def test_triangular(self): assert_array_almost_equal(actual, desired, decimal=14) def test_uniform(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -1321,7 +1254,7 @@ def __int__(self): assert_raises(TypeError, random.hypergeometric, throwing_int, 1, 1) def test_vonmises(self): - random.brng.seed(self.seed) + random.bit_generator.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], @@ -1330,17 +1263,17 @@ def test_vonmises(self): def test_vonmises_small(self): # check infinite loop, gh-4720 - random.brng.seed(self.seed) + random.bit_generator.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.brng.seed(self.seed) + random.bit_generator.seed(self.seed) r = random.vonmises(mu=0., kappa=np.nan) assert_(np.isnan(r)) def test_wald(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.wald(mean=1.23, scale=1.54, size=(3, 2)) desired = np.array([[0.10653278160339, 0.98771068102461], [0.89276055317879, 0.13640126419923], @@ -1348,7 +1281,7 @@ def test_wald(self): assert_array_almost_equal(actual, desired, decimal=14) def test_weibull(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.weibull(a=1.23, size=(3, 2)) desired = np.array([[3.557276979846361, 1.020870580998542], [2.731847777612348, 1.29148068905082], @@ -1356,12 +1289,12 @@ def test_weibull(self): assert_array_almost_equal(actual, desired, decimal=15) def test_weibull_0(self): - random.brng.seed(self.seed) + random.bit_generator.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.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.zipf(a=1.23, size=(3, 2)) desired = np.array([[66, 29], [1, 1], @@ -1376,7 +1309,7 @@ def setup(self): self.seed = 123456789 def set_seed(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) def test_uniform(self): low = [0] @@ -1956,7 +1889,7 @@ def test_logseries(self): assert_raises(ValueError, logseries, bad_p_two * 3) def test_multinomial(self): - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.multinomial([5, 20], [1 / 6.] * 6, size=(3, 2)) desired = np.array([[[1, 1, 1, 1, 0, 1], [4, 5, 1, 4, 3, 3]], @@ -1966,7 +1899,7 @@ def test_multinomial(self): [3, 2, 3, 4, 2, 6]]], dtype=np.int64) assert_array_equal(actual, desired) - random.brng.seed(self.seed) + random.bit_generator.seed(self.seed) actual = random.multinomial([5, 20], [1 / 6.] * 6) desired = np.array([[1, 1, 1, 1, 0, 1], [4, 5, 1, 4, 3, 3]], dtype=np.int64) @@ -1985,14 +1918,14 @@ def check_function(self, function, sz): out2 = np.empty((len(self.seeds),) + sz) # threaded generation - t = [Thread(target=function, args=(RandomGenerator(MT19937(s)), o)) + 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(RandomGenerator(MT19937(s)), o) + function(Generator(MT19937(s)), o) # these platforms change x87 fpu precision mode in threads if np.intp().dtype.itemsize == 4 and sys.platform == "win32": @@ -2073,21 +2006,21 @@ def test_two_arg_funcs(self): out = func(self.argOne, argTwo[0]) assert_equal(out.shape, self.tgtShape) - def test_randint(self, closed): + 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.randint + func = random.integers high = np.array([1]) low = np.array([0]) for dt in itype: - out = func(low, high, closed=closed, dtype=dt) + out = func(low, high, endpoint=endpoint, dtype=dt) assert_equal(out.shape, self.tgtShape) - out = func(low[0], high, closed=closed, dtype=dt) + out = func(low[0], high, endpoint=endpoint, dtype=dt) assert_equal(out.shape, self.tgtShape) - out = func(low, high[0], closed=closed, dtype=dt) + out = func(low, high[0], endpoint=endpoint, dtype=dt) assert_equal(out.shape, self.tgtShape) def test_three_arg_funcs(self): diff --git a/numpy/random/tests/test_generator_mt19937_regressions.py b/numpy/random/tests/test_generator_mt19937_regressions.py index f9478ccf6455..cd4e08d6fc90 100644 --- a/numpy/random/tests/test_generator_mt19937_regressions.py +++ b/numpy/random/tests/test_generator_mt19937_regressions.py @@ -3,9 +3,9 @@ from numpy.compat import long import numpy as np import pytest -from numpy.random import RandomGenerator, MT19937 +from numpy.random import Generator, MT19937 -mt19937 = RandomGenerator(MT19937()) +mt19937 = Generator(MT19937()) class TestRegression(object): @@ -36,7 +36,7 @@ def test_hypergeometric_range(self): def test_logseries_convergence(self): # Test for ticket #923 N = 1000 - mt19937.brng.seed(0) + mt19937.bit_generator.seed(0) rvsn = mt19937.logseries(0.8, size=N) # these two frequency counts should be close to theoretical # numbers with this large sample @@ -50,9 +50,9 @@ def test_logseries_convergence(self): assert_(freq < 0.23, msg) def test_permutation_longs(self): - mt19937.brng.seed(1234) + mt19937.bit_generator.seed(1234) a = mt19937.permutation(12) - mt19937.brng.seed(1234) + mt19937.bit_generator.seed(1234) b = mt19937.permutation(long(12)) assert_array_equal(a, b) @@ -62,18 +62,18 @@ def test_shuffle_mixed_dimension(self): [(1, 1), (2, 2), (3, 3), None], [1, (2, 2), (3, 3), None], [(1, 1), 2, 3, None]]: - mt19937.brng.seed(12345) + mt19937.bit_generator.seed(12345) shuffled = list(t) mt19937.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 = RandomGenerator(MT19937()) # mt19937.RandomState() + m = Generator(MT19937()) # mt19937.RandomState() res = np.array([0, 8, 7, 2, 1, 9, 4, 7, 0, 3]) for i in range(3): - mt19937.brng.seed(i) - m.brng.seed(4321) + mt19937.bit_generator.seed(i) + m.bit_generator.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) @@ -88,7 +88,7 @@ def test_multivariate_normal_size_types(self): 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.brng.seed(1234567890) + mt19937.bit_generator.seed(1234567890) x = mt19937.beta(0.0001, 0.0001, size=100) assert_(not np.any(np.isnan(x)), 'Nans in mt19937.beta') @@ -96,7 +96,7 @@ 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.brng.seed(1234) + mt19937.bit_generator.seed(1234) a = [1, 2, 3] counts = [4, 4, 2] for dt in np.float16, np.float32, np.float64: @@ -110,7 +110,7 @@ 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.brng.seed(1234) + mt19937.bit_generator.seed(1234) a = np.array(['a', 'a' * 1000]) @@ -125,7 +125,7 @@ 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.brng.seed(1234) + mt19937.bit_generator.seed(1234) a = np.array([np.arange(1), np.arange(4)]) for _ in range(1000): @@ -139,7 +139,7 @@ def test_permutation_subclass(self): class N(np.ndarray): pass - mt19937.brng.seed(1) + mt19937.bit_generator.seed(1) orig = np.arange(3).view(N) perm = mt19937.permutation(orig) assert_array_equal(perm, np.array([0, 2, 1])) @@ -151,7 +151,7 @@ class M(object): def __array__(self): return self.a - mt19937.brng.seed(1) + mt19937.bit_generator.seed(1) m = M() perm = mt19937.permutation(m) assert_array_equal(perm, np.array([2, 1, 4, 0, 3])) diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index 711270072bc0..b367599cd8e4 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -349,9 +349,9 @@ def test_random_integers_deprecated(self): 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]]) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index c5fb5c9b42cf..0c57b9aaff47 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -9,11 +9,11 @@ suppress_warnings ) -from numpy.random import MT19937, Xoshiro256StarStar, mtrand as random +from numpy.random import MT19937, Xoshiro256, mtrand as random def assert_mt19937_state_equal(a, b): - assert_equal(a['brng'], b['brng']) + 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']) @@ -166,13 +166,13 @@ def test_negative_binomial(self): self.random_state.negative_binomial(0.5, 0.5) def test_get_state_warning(self): - rs = random.RandomState(Xoshiro256StarStar()) + rs = random.RandomState(Xoshiro256()) with suppress_warnings() as sup: w = sup.record(RuntimeWarning) state = rs.get_state() assert_(len(w) == 1) assert isinstance(state, dict) - assert state['brng'] == 'Xoshiro256StarStar' + assert state['bit_generator'] == 'Xoshiro256' def test_invalid_legacy_state_setting(self): state = self.random_state.get_state() @@ -181,7 +181,7 @@ def test_invalid_legacy_state_setting(self): 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['brng'] + del state['bit_generator'] assert_raises(ValueError, self.random_state.set_state, state) def test_pickle(self): diff --git a/numpy/random/tests/test_smoke.py b/numpy/random/tests/test_smoke.py index fa7a0b567ad1..4bfa0ae6e975 100644 --- a/numpy/random/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -8,9 +8,9 @@ import pytest from numpy.testing import (assert_almost_equal, assert_equal, assert_, assert_array_equal, suppress_warnings) -from numpy.random import (RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, - PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024, Xoshiro256StarStar, - Xoshiro512StarStar, entropy) +from numpy.random import (Generator, MT19937, DSFMT, ThreeFry32, ThreeFry, + Philox, Xoroshiro128, Xorshift1024, Xoshiro256, + Xoshiro512, entropy) @pytest.fixture(scope='module', @@ -90,23 +90,23 @@ def warmup(rg, n=None): rg.standard_normal(n) rg.standard_normal(n, dtype=np.float32) rg.standard_normal(n, dtype=np.float32) - rg.randint(0, 2 ** 24, n, dtype=np.uint64) - rg.randint(0, 2 ** 48, n, dtype=np.uint64) + 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_sample(n, dtype=np.float64) - rg.random_sample(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.brng = Xoshiro256StarStar + cls.bit_generator = Xoshiro256 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -118,39 +118,41 @@ def _extra_setup(cls): cls.seed_error = TypeError def _reset_state(self): - self.rg.brng.state = self.initial_state + self.rg.bit_generator.state = self.initial_state def test_init(self): - rg = RandomGenerator(self.brng()) - state = rg.brng.state + rg = Generator(self.bit_generator()) + state = rg.bit_generator.state rg.standard_normal(1) rg.standard_normal(1) - rg.brng.state = state - new_state = rg.brng.state + rg.bit_generator.state = state + new_state = rg.bit_generator.state assert_(comp_state(state, new_state)) def test_advance(self): - state = self.rg.brng.state - if hasattr(self.rg.brng, 'advance'): - self.rg.brng.advance(self.advance) - assert_(not comp_state(state, self.rg.brng.state)) + 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: - brng_name = self.rg.brng.__class__.__name__ + brng_name = self.rg.bit_generator.__class__.__name__ pytest.skip('Advance is not supported by {0}'.format(brng_name)) def test_jump(self): - state = self.rg.brng.state - if hasattr(self.rg.brng, 'jump'): - self.rg.brng.jump() - jumped_state = self.rg.brng.state + 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_sample(2 * 3 * 5 * 7 * 11 * 13 * 17) - self.rg.brng.state = state - self.rg.brng.jump() - rejumped_state = self.rg.brng.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: - brng_name = self.rg.brng.__class__.__name__ + brng_name = self.rg.bit_generator.__class__.__name__ + if name not in ('',): + raise AttributeError('no "jumped" in %s' % brng_name) pytest.skip('Jump is not supported by {0}'.format(brng_name)) def test_uniform(self): @@ -174,9 +176,9 @@ def test_uniform_array(self): assert_((r > -1).all()) assert_((r <= 0).all()) - def test_random_sample(self): - assert_(len(self.rg.random_sample(10)) == 10) - params_0(self.rg.random_sample) + 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) @@ -221,52 +223,52 @@ def test_binomial(self): assert_(self.rg.binomial(1000, .5) >= 0) def test_reset_state(self): - state = self.rg.brng.state - int_1 = self.rg.randint(2**31) - self.rg.brng.state = state - int_2 = self.rg.randint(2**31) + 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 = RandomGenerator(self.brng()) - rg2 = RandomGenerator(self.brng()) - assert_(not comp_state(rg.brng.state, rg2.brng.state)) + 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 = RandomGenerator(self.brng(*self.seed)) - rg2 = RandomGenerator(self.brng(*self.seed)) - rg.random_sample() - rg2.random_sample() - assert_(comp_state(rg.brng.state, rg2.brng.state)) + 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 = RandomGenerator(self.brng(*self.seed)) + rg = Generator(self.bit_generator(*self.seed)) rg.standard_normal() - state = rg.brng.state + state = rg.bit_generator.state n1 = rg.standard_normal(size=10) - rg2 = RandomGenerator(self.brng()) - rg2.brng.state = state + 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 = RandomGenerator(self.brng(*self.seed)) - rg.randint(0, 2 ** 24, 120, dtype=np.uint32) - state = rg.brng.state - n1 = rg.randint(0, 2 ** 24, 10, dtype=np.uint32) - rg2 = RandomGenerator(self.brng()) - rg2.brng.state = state - n2 = rg2.randint(0, 2 ** 24, 10, dtype=np.uint32) + 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 = RandomGenerator(self.brng(*self.seed)) - rg.random_sample(dtype='float32') - state = rg.brng.state - n1 = rg.random_sample(size=10, dtype='float32') - rg2 = RandomGenerator(self.brng()) - rg2.brng.state = state - n2 = rg2.random_sample(size=10, dtype='float32') + 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): @@ -353,33 +355,6 @@ def test_negative_binomial(self): vals = self.rg.negative_binomial(10, 0.2, 10) assert_(len(vals) == 10) - def test_rand(self): - state = self.rg.brng.state - vals = self.rg.rand(10, 10, 10) - self.rg.brng.state = state - assert_((vals == self.rg.random_sample((10, 10, 10))).all()) - assert_(vals.shape == (10, 10, 10)) - vals = self.rg.rand(10, 10, 10, dtype=np.float32) - assert_(vals.shape == (10, 10, 10)) - - def test_randn(self): - state = self.rg.brng.state - vals = self.rg.randn(10, 10, 10) - self.rg.brng.state = state - assert_equal(vals, self.rg.standard_normal((10, 10, 10))) - assert_equal(vals.shape, (10, 10, 10)) - - state = self.rg.brng.state - vals = self.rg.randn(10, 10, 10) - self.rg.brng.state = state - assert_equal(vals, self.rg.standard_normal((10, 10, 10))) - - state = self.rg.brng.state - self.rg.randn(10, 10, 10) - self.rg.brng.state = state - vals = self.rg.randn(10, 10, 10, dtype=np.float32) - assert_(vals.shape == (10, 10, 10)) - def test_noncentral_chisquare(self): vals = self.rg.noncentral_chisquare(10, 2, 10) assert_(len(vals) == 10) @@ -413,14 +388,8 @@ def test_power(self): vals = self.rg.power(0.2, 10) assert_(len(vals) == 10) - def test_randint(self): - vals = self.rg.randint(10, 20, 10) - assert_(len(vals) == 10) - - def test_random_integers(self): - with suppress_warnings() as sup: - sup.record(DeprecationWarning) - vals = self.rg.random_integers(10, 20, 10) + def test_integers(self): + vals = self.rg.integers(10, 20, 10) assert_(len(vals) == 10) def test_rayleigh(self): @@ -487,16 +456,16 @@ def test_pickle(self): pick = pickle.dumps(self.rg) unpick = pickle.loads(pick) assert_((type(self.rg) == type(unpick))) - assert_(comp_state(self.rg.brng.state, unpick.brng.state)) + 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.brng.state, unpick.brng.state)) + assert_(comp_state(self.rg.bit_generator.state, unpick.bit_generator.state)) def test_seed_array(self): if self.seed_vector_bits is None: - brng_name = self.brng.__name__ + brng_name = self.bit_generator.__name__ pytest.skip('Vector seeding is not supported by ' '{0}'.format(brng_name)) @@ -505,32 +474,32 @@ def test_seed_array(self): else: dtype = np.uint64 seed = np.array([1], dtype=dtype) - self.rg.brng.seed(seed) - state1 = self.rg.brng.state - self.rg.brng.seed(1) - state2 = self.rg.brng.state + self.rg.bit_generator.seed(seed) + state1 = self.rg.bit_generator.state + self.rg.bit_generator.seed(1) + state2 = self.rg.bit_generator.state assert_(comp_state(state1, state2)) seed = np.arange(4, dtype=dtype) - self.rg.brng.seed(seed) - state1 = self.rg.brng.state - self.rg.brng.seed(seed[0]) - state2 = self.rg.brng.state + self.rg.bit_generator.seed(seed) + state1 = self.rg.bit_generator.state + self.rg.bit_generator.seed(seed[0]) + state2 = self.rg.bit_generator.state assert_(not comp_state(state1, state2)) seed = np.arange(1500, dtype=dtype) - self.rg.brng.seed(seed) - state1 = self.rg.brng.state - self.rg.brng.seed(seed[0]) - state2 = self.rg.brng.state + self.rg.bit_generator.seed(seed) + state1 = self.rg.bit_generator.state + self.rg.bit_generator.seed(seed[0]) + state2 = self.rg.bit_generator.state assert_(not comp_state(state1, state2)) seed = 2 ** np.mod(np.arange(1500, dtype=dtype), self.seed_vector_bits - 1) + 1 - self.rg.brng.seed(seed) - state1 = self.rg.brng.state - self.rg.brng.seed(seed[0]) - state2 = self.rg.brng.state + self.rg.bit_generator.seed(seed) + state1 = self.rg.bit_generator.state + self.rg.bit_generator.seed(seed[0]) + state2 = self.rg.bit_generator.state assert_(not comp_state(state1, state2)) def test_seed_array_error(self): @@ -541,164 +510,164 @@ def test_seed_array_error(self): seed = -1 with pytest.raises(ValueError): - self.rg.brng.seed(seed) + self.rg.bit_generator.seed(seed) seed = np.array([-1], dtype=np.int32) with pytest.raises(ValueError): - self.rg.brng.seed(seed) + self.rg.bit_generator.seed(seed) seed = np.array([1, 2, 3, -5], dtype=np.int32) with pytest.raises(ValueError): - self.rg.brng.seed(seed) + self.rg.bit_generator.seed(seed) seed = np.array([1, 2, 3, out_of_bounds]) with pytest.raises(ValueError): - self.rg.brng.seed(seed) + self.rg.bit_generator.seed(seed) def test_uniform_float(self): - rg = RandomGenerator(self.brng(12345)) + rg = Generator(self.bit_generator(12345)) warmup(rg) - state = rg.brng.state - r1 = rg.random_sample(11, dtype=np.float32) - rg2 = RandomGenerator(self.brng()) + state = rg.bit_generator.state + r1 = rg.random(11, dtype=np.float32) + rg2 = Generator(self.bit_generator()) warmup(rg2) - rg2.brng.state = state - r2 = rg2.random_sample(11, dtype=np.float32) + 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.brng.state, rg2.brng.state)) + assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state)) def test_gamma_floats(self): - rg = RandomGenerator(self.brng()) + rg = Generator(self.bit_generator()) warmup(rg) - state = rg.brng.state + state = rg.bit_generator.state r1 = rg.standard_gamma(4.0, 11, dtype=np.float32) - rg2 = RandomGenerator(self.brng()) + rg2 = Generator(self.bit_generator()) warmup(rg2) - rg2.brng.state = state + 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.brng.state, rg2.brng.state)) + assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state)) def test_normal_floats(self): - rg = RandomGenerator(self.brng()) + rg = Generator(self.bit_generator()) warmup(rg) - state = rg.brng.state + state = rg.bit_generator.state r1 = rg.standard_normal(11, dtype=np.float32) - rg2 = RandomGenerator(self.brng()) + rg2 = Generator(self.bit_generator()) warmup(rg2) - rg2.brng.state = state + 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.brng.state, rg2.brng.state)) + assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state)) def test_normal_zig_floats(self): - rg = RandomGenerator(self.brng()) + rg = Generator(self.bit_generator()) warmup(rg) - state = rg.brng.state + state = rg.bit_generator.state r1 = rg.standard_normal(11, dtype=np.float32) - rg2 = RandomGenerator(self.brng()) + rg2 = Generator(self.bit_generator()) warmup(rg2) - rg2.brng.state = state + 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.brng.state, rg2.brng.state)) + assert_(comp_state(rg.bit_generator.state, rg2.bit_generator.state)) def test_output_fill(self): rg = self.rg - state = rg.brng.state + state = rg.bit_generator.state size = (31, 7, 97) existing = np.empty(size) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_normal(out=existing) - rg.brng.state = state + rg.bit_generator.state = state direct = rg.standard_normal(size=size) assert_equal(direct, existing) sized = np.empty(size) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_normal(out=sized, size=sized.shape) existing = np.empty(size, dtype=np.float32) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_normal(out=existing, dtype=np.float32) - rg.brng.state = state + 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.brng.state + state = rg.bit_generator.state size = (31, 7, 97) existing = np.empty(size) - rg.brng.state = state - rg.random_sample(out=existing) - rg.brng.state = state - direct = rg.random_sample(size=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.brng.state = state - rg.random_sample(out=existing, dtype=np.float32) - rg.brng.state = state - direct = rg.random_sample(size=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.brng.state + state = rg.bit_generator.state size = (31, 7, 97) existing = np.empty(size) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_exponential(out=existing) - rg.brng.state = state + rg.bit_generator.state = state direct = rg.standard_exponential(size=size) assert_equal(direct, existing) existing = np.empty(size, dtype=np.float32) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_exponential(out=existing, dtype=np.float32) - rg.brng.state = state + 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.brng.state + state = rg.bit_generator.state size = (31, 7, 97) existing = np.zeros(size) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_gamma(1.0, out=existing) - rg.brng.state = state + 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.brng.state = state + rg.bit_generator.state = state rg.standard_gamma(1.0, out=existing, dtype=np.float32) - rg.brng.state = state + 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.brng.state + state = rg.bit_generator.state size = (31, 7, 97) mu = np.arange(97.0) + 1.0 existing = np.zeros(size) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_gamma(mu, out=existing) - rg.brng.state = state + rg.bit_generator.state = state direct = rg.standard_gamma(mu, size=size) assert_equal(direct, existing) existing = np.zeros(size, dtype=np.float32) - rg.brng.state = state + rg.bit_generator.state = state rg.standard_gamma(mu, out=existing, dtype=np.float32) - rg.brng.state = state + rg.bit_generator.state = state direct = rg.standard_gamma(mu, size=size, dtype=np.float32) assert_equal(direct, existing) @@ -725,7 +694,7 @@ def test_output_fill_error(self): with pytest.raises(ValueError): rg.standard_gamma(1.0, out=existing[::3]) - def test_randint_broadcast(self, dtype): + def test_integers_broadcast(self, dtype): if dtype == np.bool: upper = 2 lower = 0 @@ -734,44 +703,44 @@ def test_randint_broadcast(self, dtype): upper = int(info.max) + 1 lower = info.min self._reset_state() - a = self.rg.randint(lower, [upper] * 10, dtype=dtype) + a = self.rg.integers(lower, [upper] * 10, dtype=dtype) self._reset_state() - b = self.rg.randint([lower] * 10, upper, dtype=dtype) + b = self.rg.integers([lower] * 10, upper, dtype=dtype) assert_equal(a, b) self._reset_state() - c = self.rg.randint(lower, upper, size=10, dtype=dtype) + c = self.rg.integers(lower, upper, size=10, dtype=dtype) assert_equal(a, c) self._reset_state() - d = self.rg.randint(np.array( + 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.randint( + 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.randint(0, upper, size=10, dtype=dtype) + a = self.rg.integers(0, upper, size=10, dtype=dtype) self._reset_state() - b = self.rg.randint([upper] * 10, dtype=dtype) + b = self.rg.integers([upper] * 10, dtype=dtype) assert_equal(a, b) - def test_randint_numpy(self, dtype): + def test_integers_numpy(self, dtype): high = np.array([1]) low = np.array([0]) - out = self.rg.randint(low, high, dtype=dtype) + out = self.rg.integers(low, high, dtype=dtype) assert out.shape == (1,) - out = self.rg.randint(low[0], high, dtype=dtype) + out = self.rg.integers(low[0], high, dtype=dtype) assert out.shape == (1,) - out = self.rg.randint(low, high[0], dtype=dtype) + out = self.rg.integers(low, high[0], dtype=dtype) assert out.shape == (1,) - def test_randint_broadcast_errors(self, dtype): + def test_integers_broadcast_errors(self, dtype): if dtype == np.bool: upper = 2 lower = 0 @@ -780,23 +749,23 @@ def test_randint_broadcast_errors(self, dtype): upper = int(info.max) + 1 lower = info.min with pytest.raises(ValueError): - self.rg.randint(lower, [upper + 1] * 10, dtype=dtype) + self.rg.integers(lower, [upper + 1] * 10, dtype=dtype) with pytest.raises(ValueError): - self.rg.randint(lower - 1, [upper] * 10, dtype=dtype) + self.rg.integers(lower - 1, [upper] * 10, dtype=dtype) with pytest.raises(ValueError): - self.rg.randint([lower - 1], [upper] * 10, dtype=dtype) + self.rg.integers([lower - 1], [upper] * 10, dtype=dtype) with pytest.raises(ValueError): - self.rg.randint([0], [0], dtype=dtype) + self.rg.integers([0], [0], dtype=dtype) class TestMT19937(RNG): @classmethod def setup_class(cls): - cls.brng = MT19937 + cls.bit_generator = MT19937 cls.advance = None cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + 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 @@ -805,57 +774,20 @@ def test_numpy_state(self): nprg = np.random.RandomState() nprg.standard_normal(99) state = nprg.get_state() - self.rg.brng.state = state - state2 = self.rg.brng.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 TestPCG64(RNG): - @classmethod - def setup_class(cls): - cls.brng = PCG64 - cls.advance = 2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 - cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, - 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state - cls.seed_vector_bits = None - cls._extra_setup() - - def test_seed_array_error(self): - # GH #82 for error type changes - if self.seed_vector_bits == 32: - out_of_bounds = 2 ** 32 - else: - out_of_bounds = 2 ** 64 - - seed = -1 - with pytest.raises(ValueError): - self.rg.brng.seed(seed) - - error_type = ValueError if self.seed_vector_bits else TypeError - seed = np.array([-1], dtype=np.int32) - with pytest.raises(error_type): - self.rg.brng.seed(seed) - - seed = np.array([1, 2, 3, -5], dtype=np.int32) - with pytest.raises(error_type): - self.rg.brng.seed(seed) - - seed = np.array([1, 2, 3, out_of_bounds]) - with pytest.raises(error_type): - self.rg.brng.seed(seed) - - class TestPhilox(RNG): @classmethod def setup_class(cls): - cls.brng = Philox + cls.bit_generator = Philox cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -863,11 +795,11 @@ def setup_class(cls): class TestThreeFry(RNG): @classmethod def setup_class(cls): - cls.brng = ThreeFry + cls.bit_generator = ThreeFry cls.advance = 2 ** 63 + 2 ** 31 + 2 ** 15 + 1 cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -875,35 +807,35 @@ def setup_class(cls): class TestXoroshiro128(RNG): @classmethod def setup_class(cls): - cls.brng = Xoroshiro128 + cls.bit_generator = Xoroshiro128 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + 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 TestXoshiro256StarStar(RNG): +class TestXoshiro256(RNG): @classmethod def setup_class(cls): - cls.brng = Xoshiro256StarStar + cls.bit_generator = Xoshiro256 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + 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 TestXoshiro512StarStar(RNG): +class TestXoshiro512(RNG): @classmethod def setup_class(cls): - cls.brng = Xoshiro512StarStar + cls.bit_generator = Xoshiro512 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -911,11 +843,11 @@ def setup_class(cls): class TestXorshift1024(RNG): @classmethod def setup_class(cls): - cls.brng = Xorshift1024 + cls.bit_generator = Xorshift1024 cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() @@ -923,11 +855,11 @@ def setup_class(cls): class TestDSFMT(RNG): @classmethod def setup_class(cls): - cls.brng = DSFMT + cls.bit_generator = DSFMT cls.advance = None cls.seed = [12345] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls._extra_setup() cls.seed_vector_bits = 32 @@ -935,11 +867,11 @@ def setup_class(cls): class TestThreeFry32(RNG): @classmethod def setup_class(cls): - cls.brng = ThreeFry32 + cls.bit_generator = ThreeFry32 cls.advance = 2**63 + 2**31 + 2**15 + 1 cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state + cls.rg = Generator(cls.bit_generator(*cls.seed)) + cls.initial_state = cls.rg.bit_generator.state cls.seed_vector_bits = 64 cls._extra_setup() cls.seed_error = ValueError @@ -962,16 +894,3 @@ def test_fallback(self): time.sleep(0.1) e2 = entropy.random_entropy(source='fallback') assert_((e1 != e2)) - - -class TestPCG32(TestPCG64): - @classmethod - def setup_class(cls): - cls.brng = PCG32 - cls.advance = 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 - cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, - 2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = RandomGenerator(cls.brng(*cls.seed)) - cls.initial_state = cls.rg.brng.state - cls.seed_vector_bits = None - cls._extra_setup() diff --git a/numpy/random/threefry.pyx b/numpy/random/threefry.pyx index a8878c6bc4a1..d008cd828338 100644 --- a/numpy/random/threefry.pyx +++ b/numpy/random/threefry.pyx @@ -1,4 +1,3 @@ -from libc.stdlib cimport malloc, free from cpython.pycapsule cimport PyCapsule_New try: @@ -9,7 +8,7 @@ except ImportError: import numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() @@ -67,56 +66,29 @@ cdef class ThreeFry: used. counter : {None, int, array_like}, optional Counter to use in the ThreeFry state. Can be either - a Python int (long in 2.x) in [0, 2**256) or a 4-element uint64 array. + a Python int 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 ThreeFry state. Unlike seed, which is run through another RNG before use, the value in key is directly set. Can be either - a Python int (long in 2.x) in [0, 2**256) or a 4-element uint64 array. + a Python int in [0, 2**256) or a 4-element uint64 array. key and seed cannot both be used. Notes ----- - ThreeFry 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. ThreeFry 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 + ThreeFry 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. ``ThreeFry`` + 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. - ``ThreeFry`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + ``ThreeFry`` 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. - **Compatibility Guarantee** - - ``ThreeFry`` guarantees that a fixed seed will always produce the - same results. - - See ``Philox`` for a closely related PRNG implementation. - - **Parallel Features** - - ``ThreeFry`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{128}` random numbers have been generated. Alternatively, - ``advance`` can be used to advance the counter for an any - positive step in [0, 2**256). When using ``jump``, all generators should - be initialized with the same seed to ensure that the segments come from - the same sequence. Alternatively, ``ThreeFry`` can be used - in parallel applications by using a sequence of distinct keys where each - instance uses different key. - - >>> from numpy.random import RandomGenerator, ThreeFry - >>> rg = [RandomGenerator(ThreeFry(1234)) for _ in range(10)] - # Advance each ThreeFry instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) - - Using distinct keys produces independent streams - - >>> key = 2**196 + 2**132 + 2**65 + 2**33 + 2**17 + 2**9 - >>> rg = [RandomGenerator(ThreeFry(key=key+i)) for i in range(10)] + See ``Philox`` for a closely related PRNG. **State and Seeding** @@ -127,26 +99,44 @@ cdef class ThreeFry: sequences. ``ThreeFry`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for another simple random number generator, - Splitmix64, and the output of this PRNG function is used as the initial state. + or a vector of 64-bit unsigned integers. In either case, the seed is + used as an input for a second random number generator, + SplitMix64, and the output of this PRNG function is used as the initial state. Using a single 64-bit value for the seed can only initialize a small range of - the possible initial state values. When using an array, the SplitMix64 state - for producing the ith component of the initial state is XORd with the ith - value of the seed array until the seed array is exhausted. When using an array - the initial state for the SplitMix64 state is 0 so that using a single element - array and using the same value as a scalar will produce the same initial state. + the possible initial state values. - Examples - -------- - >>> from numpy.random import RandomGenerator, ThreeFry - >>> rg = RandomGenerator(ThreeFry(1234)) - >>> rg.standard_normal() - 0.123 # random + **Parallel Features** - Identical method using only ThreeFry + ``ThreeFry`` 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. - >>> rg = ThreeFry(1234).generator + >>> from numpy.random import Generator, ThreeFry + >>> bit_generator = ThreeFry(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() + + Alternatively, ``ThreeFry`` can be used in parallel applications by using + a sequence of distinct keys where each instance uses different key. + + >>> key = 2**196 + 2**132 + 2**65 + 2**33 + 2**17 + 2**9 + >>> rg = [Generator(ThreeFry(key=key+i)) for i in range(10)] + + **Compatibility Guarantee** + + ``ThreeFry`` makes a guarantee that a fixed seed and will always produce + the same random integer stream. + + Examples + -------- + >>> from numpy.random import Generator, ThreeFry + >>> rg = Generator(ThreeFry(1234)) >>> rg.standard_normal() 0.123 # random @@ -157,34 +147,32 @@ cdef class ThreeFry: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef threefry_state *rng_state - cdef brng_t *_brng + cdef threefry_state rng_state + cdef threefry4x64_ctr_t threefry_ctr + cdef threefry4x64_key_t threefry_key + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None, counter=None, key=None): - self.rng_state = malloc(sizeof(threefry_state)) - self.rng_state.ctr = malloc(sizeof(threefry4x64_ctr_t)) - self.rng_state.key = malloc(sizeof(threefry4x64_key_t)) - self._brng = malloc(sizeof(brng_t)) + self.rng_state.ctr = &self.threefry_ctr + self.rng_state.key = &self.threefry_key self.seed(seed, counter, key) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &threefry_uint64 - self._brng.next_uint32 = &threefry_uint32 - self._brng.next_double = &threefry_double - self._brng.next_raw = &threefry_uint64 + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &threefry_uint64 + self._bitgen.next_uint32 = &threefry_uint32 + self._bitgen.next_double = &threefry_double + self._bitgen.next_raw = &threefry_uint64 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = 'BasicRNG' - self.capsule = PyCapsule_New(self._brng, name, NULL) + cdef const char *name = 'BitGenerator' + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -194,18 +182,8 @@ cdef class ThreeFry: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -218,7 +196,7 @@ cdef class ThreeFry: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -243,10 +221,10 @@ cdef class ThreeFry: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -325,7 +303,7 @@ cdef class ThreeFry: for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] state = {'counter': ctr, 'key': key} - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos, @@ -336,8 +314,8 @@ cdef class ThreeFry: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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): @@ -349,28 +327,45 @@ cdef class ThreeFry: self.rng_state.uinteger = value['uinteger'] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**128 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. + """ + self.advance(iter * 2 ** 128) + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(128 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned Returns ------- - self : ThreeFry - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is - required to ensure exact reproducibility. + bit_generator : Xoroshiro128 + New instance of generator jumped iter times """ - return self.advance(iter * 2**128) + cdef ThreeFry bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator def advance(self, delta): """ @@ -410,8 +405,7 @@ cdef class ThreeFry: """ cdef np.ndarray delta_a delta_a = int_to_array(delta, 'step', 256, 64) - loc = 0 - threefry_advance(delta_a.data, self.rng_state) + threefry_advance(delta_a.data, &self.rng_state) self._reset_state_variables() return self @@ -430,10 +424,10 @@ cdef class ThreeFry: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -452,24 +446,9 @@ cdef class ThreeFry: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/threefry32.pyx b/numpy/random/threefry32.pyx index b1b4d4c5197e..2e2b32bfede6 100644 --- a/numpy/random/threefry32.pyx +++ b/numpy/random/threefry32.pyx @@ -8,7 +8,7 @@ from cpython.pycapsule cimport PyCapsule_New from libc.stdlib cimport malloc, free from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() @@ -51,7 +51,6 @@ cdef double threefry32_double(void* st) nogil: cdef uint64_t threefry32_raw(void *st) nogil: return threefry32_next32( st) - cdef class ThreeFry32: """ ThreeFry32(seed=None, counter=None, key=None) @@ -69,57 +68,30 @@ cdef class ThreeFry32: used. counter : {None, int, array_like}, optional Counter to use in the ThreeFry32 state. Can be either - a Python int (long in 2.x) in [0, 2**128) or a 4-element uint32 array. + a Python int in [0, 2**128) or a 4-element uint32 array. If not provided, the RNG is initialized at 0. key : {None, int, array_like}, optional Key to use in the ThreeFry32 state. Unlike seed, which is run through another RNG before use, the value in key is directly set. Can be either - a Python int (long in 2.x) in [0, 2**128) or a 4-element uint32 array. + a Python int in [0, 2**128) or a 4-element uint32 array. key and seed cannot both be used. Notes ----- ThreeFry32 is a 32-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. ThreeFry32 + using different values of the key produce independent sequences. ``ThreeFry32`` has a period of :math:`2^{128} - 1` and supports arbitrary advancing and jumping the sequence in increments of :math:`2^{64}`. These features allow multiple non-overlapping sequences to be generated. - ``ThreeFry32`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. - - **Compatibility Guarantee** - - ``ThreeFry32`` guarantees that a fixed seed will always produce the - same results. + ``ThreeFry32`` 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. See ``TheeFry`` and ``Philox`` closely related PRNG implementations. - **Parallel Features** - - ``ThreeFry32`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{64}` random numbers have been generated. Alternatively, - ``advance`` can be used to advance the counter for an arbitrary number of - positive steps in [0, 2**128). When using ``jump``, all generators should - be initialized with the same seed to ensure that the segments come from - the same sequence. Alternatively, ``ThreeFry32`` can be used - in parallel applications by using a sequence of distinct keys where each - instance uses different key. - - >>> from numpy.random import RandomGenerator, ThreeFry32 - >>> rg = [RandomGenerator(ThreeFry32(1234)) for _ in range(10)] - # Advance each ThreeFry32 instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) - - Using distinct keys produces independent streams - - >>> key = 2**65 + 2**33 + 2**17 + 2**9 - >>> rg = [RandomGenerator(ThreeFry32(key=key+i)) for i in range(10)] - **State and Seeding** The ``ThreeFry32`` state vector consists of a 2 128-bit values encoded as @@ -130,8 +102,8 @@ cdef class ThreeFry32: ``ThreeFry32`` is seeded using either a single 64-bit unsigned integer or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for another simple random number generator, - Splitmix64, and the output of this PRNG function is used as the initial + used as an input (or inputs) for a second random number generator, + SplitMix64, and the output of this PRNG function is used as the initial state. Using a single 64-bit value for the seed can only initialize a small range of the possible initial state values. When using an array, the SplitMix64 state for producing the ith component of the initial state is @@ -140,16 +112,38 @@ cdef class ThreeFry32: is 0 so that using a single element array and using the same value as a scalar will produce the same initial state. - Examples - -------- - >>> from numpy.random import RandomGenerator, ThreeFry32 - >>> rg = RandomGenerator(ThreeFry32(1234)) - >>> rg.standard_normal() - 0.123 # random + **Parallel Features** + + ``ThreeFry32`` can be used in parallel applications by calling the + ``jumped`` method to advances the state as-if :math:`2^{64}` random + numbers have been generated. Alternatively, ``advance`` can be used to + advance the counter for any positive step in [0, 2**128). When using + ``jumped``, all generators should be chained to ensure that the segments + come from the same sequence. + + >>> from numpy.random import Generator, ThreeFry32 + >>> bit_generator = ThreeFry32(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() - Identical method using only ThreeFry32 + Alternatively, ``ThreeFry32`` can be used in parallel applications by using + a sequence of distinct keys where each instance uses different key. - >>> rg = ThreeFry32(1234).generator + >>> key = 2**65 + 2**33 + 2**17 + 2**9 + >>> rg = [Generator(ThreeFry32(key=key+i)) for i in range(10)] + + **Compatibility Guarantee** + + ``ThreeFry32`` makes a guarantee that a fixed seed and will always produce + the same random integer stream. + + Examples + -------- + >>> from numpy.random import Generator, ThreeFry32 + >>> rg = Generator(ThreeFry32(1234)) >>> rg.standard_normal() 0.123 # random @@ -160,34 +154,32 @@ cdef class ThreeFry32: the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11), New York, NY: ACM, 2011. """ - cdef threefry32_state *rng_state - cdef brng_t *_brng + cdef threefry32_state rng_state + cdef threefry4x32_ctr_t threefry_ctr + cdef threefry4x32_key_t threefry_key + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None, counter=None, key=None): - self.rng_state = malloc(sizeof(threefry32_state)) - self.rng_state.ctr = malloc(sizeof(threefry4x32_ctr_t)) - self.rng_state.key = malloc(sizeof(threefry4x32_key_t)) - self._brng = malloc(sizeof(brng_t)) + self.rng_state.ctr = &self.threefry_ctr + self.rng_state.key = &self.threefry_key self.seed(seed, counter, key) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &threefry32_uint64 - self._brng.next_uint32 = &threefry32_uint32 - self._brng.next_double = &threefry32_double - self._brng.next_raw = &threefry32_raw + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &threefry32_uint64 + self._bitgen.next_uint32 = &threefry32_uint32 + self._bitgen.next_double = &threefry32_double + self._bitgen.next_raw = &threefry32_raw self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = 'BasicRNG' - self.capsule = PyCapsule_New( self._brng, name, NULL) + cdef const char *name = 'BitGenerator' + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -197,18 +189,8 @@ cdef class ThreeFry32: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state.ctr) - free(self.rng_state.key) - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE @@ -219,7 +201,7 @@ cdef class ThreeFry32: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -244,10 +226,10 @@ cdef class ThreeFry32: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None, counter=None, key=None): """ @@ -325,7 +307,7 @@ cdef class ThreeFry32: for i in range(THREEFRY_BUFFER_SIZE): buffer[i] = self.rng_state.buffer[i] state = {'counter': ctr, 'key': key} - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': state, 'buffer': buffer, 'buffer_pos': self.rng_state.buffer_pos} @@ -334,8 +316,8 @@ cdef class ThreeFry32: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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): @@ -345,28 +327,45 @@ cdef class ThreeFry32: self.rng_state.buffer[i] = value['buffer'][i] self.rng_state.buffer_pos = value['buffer_pos'] - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**64 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. + """ + self.advance(iter * 2 ** 64) + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(64 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned Returns ------- - self : ThreeFry32 - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is - required to ensure exact reproducibility. + bit_generator : Xoroshiro128 + New instance of generator jumped iter times """ - return self.advance(iter * 2 ** 64) + cdef ThreeFry32 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator def advance(self, delta): """ @@ -406,8 +405,7 @@ cdef class ThreeFry32: """ cdef np.ndarray delta_a delta_a = int_to_array(delta, 'step', 128, 32) - loc = 0 - threefry32_advance( delta_a.data, self.rng_state) + threefry32_advance( delta_a.data, &self.rng_state) self._reset_state_variables() return self @@ -426,10 +424,10 @@ cdef class ThreeFry32: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -448,24 +446,9 @@ cdef class ThreeFry32: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the BitGenerator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/xoroshiro128.pyx b/numpy/random/xoroshiro128.pyx index 5c4642513b9b..5d4fda90a988 100644 --- a/numpy/random/xoroshiro128.pyx +++ b/numpy/random/xoroshiro128.pyx @@ -3,14 +3,14 @@ try: except ImportError: from dummy_threading import Lock -from libc.stdlib cimport malloc, free +from libc.string cimport memcpy from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() @@ -47,75 +47,67 @@ cdef class Xoroshiro128: ---------- seed : {None, int, array_like}, optional Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in - [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``Xoroshiro128`` will try to read data from - ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. + Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] + or ``None`` (the default). If `seed` is ``None``, then data is read + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a hash of the time and process ID is used. Notes ----- - xoroshiro128+ is the successor to xorshift128+ written by David Blackman and - Sebastiano Vigna. It is a 64-bit PRNG that uses a carefully handcrafted - shift/rotate-based linear transformation. This change both improves speed and - statistical quality of the PRNG [1]_. xoroshiro128+ has a period of - :math:`2^{128} - 1` and supports jumping the sequence in increments of - :math:`2^{64}`, which allows multiple non-overlapping sequences to be - generated. - - ``Xoroshiro128`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + xoroshiro128+ is the successor to xorshift128+ written by David Blackman + and Sebastiano Vigna. It is a 64-bit PRNG that uses a carefully + handcrafted shift/rotate-based linear transformation. This change both + improves speed and statistical quality of the PRNG [1]_. xoroshiro128+ has + a period of :math:`2^{128} - 1` and supports jumping the sequence in + increments of :math:`2^{64}`, which allows multiple non-overlapping + sequences to be generated. + + ``Xoroshiro128`` 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. + + See ``Xorshift1024`` for a related PRNG with a larger + period (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). - **Compatibility Guarantee** + **State and Seeding** - ``Xoroshiro128`` guarantees that a fixed seed will always produce the - same results. + The ``Xoroshiro128`` state vector consists of a 2-element array of 64-bit + unsigned integers. - See ``Xorshift1024`` for an related PRNG implementation with a larger - period (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + ``Xoroshiro128`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the seed is + used as an input for another simple random number generator, + SplitMix64, and the output of this PRNG function is used as the initial state. + Using a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. **Parallel Features** - ``Xoroshiro128`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{64}` random numbers have been generated. This - allow the original sequence to be split so that distinct segments can be used - in each worker process. All generators should be initialized with the same - seed to ensure that the segments come from the same sequence. - - >>> from numpy.random import RandomGenerator, Xoroshiro128 - >>> rg = [RandomGenerator(Xoroshiro128(1234)) for _ in range(10)] - # Advance each Xoroshiro128 instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) + ``Xoroshiro128`` can be used in parallel applications by calling the method + ``jumped`` which advances the state as-if :math:`2^{64}` random numbers + have been generated. 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, Xoroshiro128 + >>> bit_generator = Xoroshiro128(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() - **State and Seeding** + **Compatibility Guarantee** - The ``Xoroshiro128`` state vector consists of a 2 element array - of 64-bit unsigned integers. - - ``Xoroshiro128`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for another simple random number generator, - Splitmix64, and the output of this PRNG function is used as the initial state. - Using a single 64-bit value for the seed can only initialize a small range of - the possible initial state values. When using an array, the SplitMix64 state - for producing the ith component of the initial state is XORd with the ith - value of the seed array until the seed array is exhausted. When using an array - the initial state for the SplitMix64 state is 0 so that using a single element - array and using the same value as a scalar will produce the same initial state. + ``Xoroshiro128`` makes a guarantee that a fixed seed will always + produce the same random integer stream. Examples -------- - >>> from numpy.random import RandomGenerator, Xoroshiro128 - >>> rg = RandomGenerator(Xoroshiro128(1234)) - >>> rg.standard_normal() - 0.123 # random - - Identical method using only Xoroshiro128 - - >>> rg = Xoroshiro128(1234).generator + >>> from numpy.random import Generator, Xoroshiro128 + >>> rg = Generator(Xoroshiro128(1234)) >>> rg.standard_normal() 0.123 # random @@ -124,32 +116,28 @@ cdef class Xoroshiro128: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoroshiro128_state *rng_state - cdef brng_t *_brng + cdef xoroshiro128_state rng_state + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(xoroshiro128_state)) - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &xoroshiro128_uint64 - self._brng.next_uint32 = &xoroshiro128_uint32 - self._brng.next_double = &xoroshiro128_double - self._brng.next_raw = &xoroshiro128_uint64 + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &xoroshiro128_uint64 + self._bitgen.next_uint32 = &xoroshiro128_uint32 + self._bitgen.next_double = &xoroshiro128_double + self._bitgen.next_raw = &xoroshiro128_uint64 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -159,16 +147,8 @@ cdef class Xoroshiro128: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -178,7 +158,7 @@ cdef class Xoroshiro128: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -203,10 +183,10 @@ cdef class Xoroshiro128: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -241,32 +221,48 @@ cdef class Xoroshiro128: self.rng_state.s[1] = int(state[1]) self._reset_state_variables() - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**64 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. - - Returns - ------- - self : Xoroshiro128 - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is required - to ensure exact reproducibility. """ cdef np.npy_intp i for i in range(iter): - xoroshiro128_jump(self.rng_state) + xoroshiro128_jump(&self.rng_state) self._reset_state_variables() - return self + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(64 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : Xoroshiro128 + New instance of generator jumped iter times + """ + cdef Xoroshiro128 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -282,7 +278,7 @@ cdef class Xoroshiro128: state = np.empty(2, dtype=np.uint64) state[0] = self.rng_state.s[0] state[1] = self.rng_state.s[1] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 's': state, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -291,8 +287,8 @@ cdef class Xoroshiro128: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + bitgen = value.get('bit_generator', '') + if bitgen != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) self.rng_state.s[0] = value['s'][0] @@ -315,11 +311,11 @@ cdef class Xoroshiro128: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -338,24 +334,9 @@ cdef class Xoroshiro128: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the basic RNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/xorshift1024.pyx b/numpy/random/xorshift1024.pyx index 04fb542c142a..ad7debe308c5 100644 --- a/numpy/random/xorshift1024.pyx +++ b/numpy/random/xorshift1024.pyx @@ -3,14 +3,14 @@ try: except ImportError: from dummy_threading import Lock -from libc.stdlib cimport malloc, free +from libc.string cimport memcpy from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() @@ -44,77 +44,68 @@ cdef class Xorshift1024: Container for the xorshift1024*φ pseudo-random number generator. + Parameters + ---------- + seed : {None, int, array_like}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] + or ``None`` (the default). If `seed` is ``None``, then data is read + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a hash of the time and process ID is used. + + Notes + ----- xorshift1024*φ is a 64-bit implementation of Saito and Matsumoto's XSadd generator [1]_ (see also [2]_, [3]_, [4]_). xorshift1024*φ has a period of :math:`2^{1024} - 1` and supports jumping the sequence in increments of :math:`2^{512}`, which allows multiple non-overlapping sequences to be generated. - ``Xorshift1024`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + ``Xorshift1024`` 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. - **Compatibility Guarantee** + See ``Xoroshiro128`` for a faster bit generator that has a smaller period. - ``Xorshift1024`` guarantees that a fixed seed will always produce the - same results. + **State and Seeding** - Parameters - ---------- - seed : {None, int, array_like}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in - [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``Xorshift1024`` will try to read data from - ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. + The ``Xoroshiro128`` state vector consists of a 16-element array of 64-bit + unsigned integers. - Notes - ----- - See ``Xoroshiro128`` for a faster implementation that has a smaller - period. + ``Xoroshiro1024`` is seeded using either a single 64-bit unsigned integer + or a vector of 64-bit unsigned integers. In either case, the seed is + used as an input for another simple random number generator, + SplitMix64, and the output of this PRNG function is used as the initial + state. Using a single 64-bit value for the seed can only initialize a + small range of the possible initial state values. **Parallel Features** - ``Xorshift1024`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{512}` random numbers have been generated. This - allows the original sequence to be split so that distinct segments can be used - in each worker process. All generators should be initialized with the same - seed to ensure that the segments come from the same sequence. + ``Xoroshiro1024`` can be used in parallel applications by calling the + method ``jumped`` which advances the state as-if :math:`2^{512}` random + numbers have been generated. 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, Xorshift1024 + >>> bit_generator = Xorshift1024(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() - >>> from numpy.random import RandomGenerator, Xorshift1024 - >>> rg = [RandomGenerator(Xorshift1024(1234)) for _ in range(10)] - # Advance each Xorshift1024 instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) - - **State and Seeding** - - The ``Xorshift1024`` state vector consists of a 16 element array - of 64-bit unsigned integers. + **Compatibility Guarantee** - ``Xorshift1024`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for another simple random number generator, - Splitmix64, and the output of this PRNG function is used as the initial state. - Using a single 64-bit value for the seed can only initialize a small range of - the possible initial state values. When using an array, the SplitMix64 state - for producing the ith component of the initial state is XORd with the ith - value of the seed array until the seed array is exhausted. When using an array - the initial state for the SplitMix64 state is 0 so that using a single element - array and using the same value as a scalar will produce the same initial state. + ``Xorshift1024`` makes a guarantee that a fixed seed will always + produce the same random integer stream. Examples -------- - >>> from numpy.random import RandomGenerator, Xorshift1024 - >>> rg = RandomGenerator(Xorshift1024(1234)) - >>> rg.standard_normal() - 0.123 # random - - Identical method using only Xoroshiro128 - - >>> rg = Xorshift1024(1234).generator + >>> from numpy.random import Generator, Xorshift1024 + >>> rg = Generator(Xorshift1024(1234)) >>> rg.standard_normal() 0.123 # random @@ -130,32 +121,28 @@ cdef class Xorshift1024: generators." CoRR, abs/1403.0930, 2014. """ - cdef xorshift1024_state *rng_state - cdef brng_t *_brng + cdef xorshift1024_state rng_state + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(xorshift1024_state)) - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &xorshift1024_uint64 - self._brng.next_uint32 = &xorshift1024_uint32 - self._brng.next_double = &xorshift1024_double - self._brng.next_raw = &xorshift1024_uint64 + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &xorshift1024_uint64 + self._bitgen.next_uint32 = &xorshift1024_uint32 + self._bitgen.next_double = &xorshift1024_double + self._bitgen.next_raw = &xorshift1024_uint64 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -165,16 +152,8 @@ cdef class Xorshift1024: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -184,7 +163,7 @@ cdef class Xorshift1024: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -209,10 +188,10 @@ cdef class Xorshift1024: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -249,32 +228,48 @@ cdef class Xorshift1024: self.rng_state.p = 0 self._reset_state_variables() - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**512 random numbers have been generated + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. - - Returns - ------- - self : Xorshift1024 - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is required - to ensure exact reproducibility. """ cdef np.npy_intp i for i in range(iter): - xorshift1024_jump(self.rng_state) + xorshift1024_jump(&self.rng_state) self._reset_state_variables() - return self + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(512 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : Xoroshiro128 + New instance of generator jumped iter times + """ + cdef Xorshift1024 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -290,7 +285,7 @@ cdef class Xorshift1024: s = np.empty(16, dtype=np.uint64) for i in range(16): s[i] = self.rng_state.s[i] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 'state': {'s': s, 'p': self.rng_state.p}, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -299,8 +294,8 @@ cdef class Xorshift1024: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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(16): @@ -324,10 +319,10 @@ cdef class Xorshift1024: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -346,24 +341,9 @@ cdef class Xorshift1024: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the core PRNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/xoshiro256starstar.pyx b/numpy/random/xoshiro256.pyx similarity index 52% rename from numpy/random/xoshiro256starstar.pyx rename to numpy/random/xoshiro256.pyx index 278356b05db1..7258ea3fb883 100644 --- a/numpy/random/xoshiro256starstar.pyx +++ b/numpy/random/xoshiro256.pyx @@ -1,45 +1,45 @@ -from libc.stdlib cimport malloc, free -from cpython.pycapsule cimport PyCapsule_New - -import numpy as np -cimport numpy as np - try: from threading import Lock except ImportError: from dummy_threading import Lock +from libc.string cimport memcpy +from cpython.pycapsule cimport PyCapsule_New + +import numpy as np +cimport numpy as np + from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() -cdef extern from "src/xoshiro256starstar/xoshiro256starstar.h": +cdef extern from "src/xoshiro256/xoshiro256.h": - struct s_xoshiro256starstar_state: + struct s_xoshiro256_state: uint64_t s[4] int has_uint32 uint32_t uinteger - ctypedef s_xoshiro256starstar_state xoshiro256starstar_state + ctypedef s_xoshiro256_state xoshiro256_state - uint64_t xoshiro256starstar_next64(xoshiro256starstar_state *state) nogil - uint32_t xoshiro256starstar_next32(xoshiro256starstar_state *state) nogil - void xoshiro256starstar_jump(xoshiro256starstar_state *state) + uint64_t xoshiro256_next64(xoshiro256_state *state) nogil + uint32_t xoshiro256_next32(xoshiro256_state *state) nogil + void xoshiro256_jump(xoshiro256_state *state) -cdef uint64_t xoshiro256starstar_uint64(void* st) nogil: - return xoshiro256starstar_next64(st) +cdef uint64_t xoshiro256_uint64(void* st) nogil: + return xoshiro256_next64(st) -cdef uint32_t xoshiro256starstar_uint32(void *st) nogil: - return xoshiro256starstar_next32( st) +cdef uint32_t xoshiro256_uint32(void *st) nogil: + return xoshiro256_next32( st) -cdef double xoshiro256starstar_double(void* st) nogil: - return uint64_to_double(xoshiro256starstar_next64(st)) +cdef double xoshiro256_double(void* st) nogil: + return uint64_to_double(xoshiro256_next64(st)) -cdef class Xoshiro256StarStar: +cdef class Xoshiro256: """ - Xoshiro256StarStar(seed=None) + Xoshiro256(seed=None) Container for the xoshiro256** pseudo-random number generator. @@ -47,75 +47,65 @@ cdef class Xoshiro256StarStar: ---------- seed : {None, int, array_like}, optional Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in - [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``Xoshiro256StarStar`` will try to read data from - ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. + Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] + or ``None`` (the default). If `seed` is ``None``, then data is read + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a hash of the time and process ID is used. Notes ----- xoshiro256** is written by David Blackman and Sebastiano Vigna. - It is a 64-bit PRNG that uses a carefully linear transformation. + It is a 64-bit PRNG that uses a carefully constructed linear transformation. This produces a fast PRNG with excellent statistical quality [1]_. xoshiro256** has a period of :math:`2^{256} - 1` and supports jumping the sequence in increments of :math:`2^{128}`, - which allows multiple non-overlapping sequences to be generated. + which allows multiple non-overlapping subsequences to be generated. - ``Xoshiro256StarStar`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + ``Xoshiro256`` 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. - **Compatibility Guarantee** + See ``Xorshift1024`` for a related PRNG with a different period + (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). - ``Xoshiro256StarStar`` guarantees that a fixed seed will always produce the - same results. + **State and Seeding** - See ``Xorshift1024`` for a related PRNG with different periods - (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + The ``Xoshiro256`` state vector consists of a 4-element array + of 64-bit unsigned integers. - **Parallel Features** + ``Xoshiro256`` is seeded using either a single 64-bit unsigned + integer or a vector of 64-bit unsigned integers. In either case, the seed + is used as an input for another simple random number generator, SplitMix64, + and the output of this PRNG function is used as the initial state. Using + a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. - ``Xoshiro256StarStar`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{128}` random numbers have been generated. This - allow the original sequence to be split so that distinct segments can be used - in each worker process. All generators should be initialized with the same - seed to ensure that the segments come from the same sequence. + **Parallel Features** - >>> from numpy.random import RandomGenerator, Xoshiro256StarStar - >>> rg = [RandomGenerator(Xoshiro256StarStar(1234)) for _ in range(10)] - # Advance each Xoshiro256StarStar instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) + ``Xoshiro256`` can be used in parallel applications by calling the + method ``jumped`` which advances the state as-if :math:`2^{128}` random + numbers have been generated. 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. - **State and Seeding** + >>> from numpy.random import Generator, Xoshiro256 + >>> bit_generator = Xoshiro256(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... bit_generator = bit_generator.jumped() - The ``Xoshiro256StarStar`` state vector consists of a 4 element array - of 64-bit unsigned integers. + **Compatibility Guarantee** - ``Xoshiro256StarStar`` is seeded using either a single 64-bit unsigned - integer or a vector of 64-bit unsigned integers. In either case, the - input seed is used as an input (or inputs) for another simple random - number generator, Splitmix64, and the output of this PRNG function is - used as the initial state. Using a single 64-bit value for the seed can - only initialize a small range of the possible initial state values. When - using an array, the SplitMix64 state for producing the ith component of - the initial state is XORd with the ith value of the seed array until the - seed array is exhausted. When using an array the initial state for the - SplitMix64 state is 0 so that using a single element array and using the - same value as a scalar will produce the same initial state. + ``Xoshiro256`` makes a guarantee that a fixed seed will always + produce the same random integer stream. Examples -------- - >>> from numpy.random import RandomGenerator, Xoshiro256StarStar - >>> rg = RandomGenerator(Xoshiro256StarStar(1234)) - >>> rg.standard_normal() - 0.123 # random - - Identical method using only Xoshiro256StarStar - - >>> rg = Xoshiro256StarStar(1234).generator + >>> from numpy.random import Generator, Xoshiro256 + >>> rg = Generator(Xoshiro256(1234)) >>> rg.standard_normal() 0.123 # random @@ -124,32 +114,28 @@ cdef class Xoshiro256StarStar: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoshiro256starstar_state *rng_state - cdef brng_t *_brng + cdef xoshiro256_state rng_state + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(xoshiro256starstar_state)) - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &xoshiro256starstar_uint64 - self._brng.next_uint32 = &xoshiro256starstar_uint32 - self._brng.next_double = &xoshiro256starstar_double - self._brng.next_raw = &xoshiro256starstar_uint64 + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &xoshiro256_uint64 + self._bitgen.next_uint32 = &xoshiro256_uint32 + self._bitgen.next_double = &xoshiro256_double + self._bitgen.next_raw = &xoshiro256_uint64 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -159,16 +145,8 @@ cdef class Xoshiro256StarStar: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -178,7 +156,7 @@ cdef class Xoshiro256StarStar: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -203,10 +181,10 @@ cdef class Xoshiro256StarStar: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -243,32 +221,48 @@ cdef class Xoshiro256StarStar: self.rng_state.s[3] = int(state[3]) self._reset_state_variables() - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**128 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. - - Returns - ------- - self : Xoshiro256StarStar - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is required - to ensure exact reproducibility. """ cdef np.npy_intp i for i in range(iter): - xoshiro256starstar_jump(self.rng_state) + xoshiro256_jump(&self.rng_state) self._reset_state_variables() - return self + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(128 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : Xoroshiro128 + New instance of generator jumped iter times + """ + cdef Xoshiro256 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -286,7 +280,7 @@ cdef class Xoshiro256StarStar: state[1] = self.rng_state.s[1] state[2] = self.rng_state.s[2] state[3] = self.rng_state.s[3] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 's': state, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -295,8 +289,8 @@ cdef class Xoshiro256StarStar: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + bitgen = value.get('bit_generator', '') + if bitgen != self.__class__.__name__: raise ValueError('state must be for a {0} ' 'PRNG'.format(self.__class__.__name__)) self.rng_state.s[0] = value['s'][0] @@ -321,10 +315,10 @@ cdef class Xoshiro256StarStar: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -343,24 +337,9 @@ cdef class Xoshiro256StarStar: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the basic RNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator diff --git a/numpy/random/xoshiro512starstar.pyx b/numpy/random/xoshiro512.pyx similarity index 51% rename from numpy/random/xoshiro512starstar.pyx rename to numpy/random/xoshiro512.pyx index 65d4c7c3e298..a2c0a48965b4 100644 --- a/numpy/random/xoshiro512starstar.pyx +++ b/numpy/random/xoshiro512.pyx @@ -3,43 +3,43 @@ try: except ImportError: from dummy_threading import Lock -from libc.stdlib cimport malloc, free +from libc.string cimport memcpy from cpython.pycapsule cimport PyCapsule_New import numpy as np cimport numpy as np from .common cimport * -from .distributions cimport brng_t +from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array np.import_array() -cdef extern from "src/xoshiro512starstar/xoshiro512starstar.h": +cdef extern from "src/xoshiro512/xoshiro512.h": - struct s_xoshiro512starstar_state: + struct s_xoshiro512_state: uint64_t s[8] int has_uint32 uint32_t uinteger - ctypedef s_xoshiro512starstar_state xoshiro512starstar_state + ctypedef s_xoshiro512_state xoshiro512_state - uint64_t xoshiro512starstar_next64(xoshiro512starstar_state *state) nogil - uint32_t xoshiro512starstar_next32(xoshiro512starstar_state *state) nogil - void xoshiro512starstar_jump(xoshiro512starstar_state *state) + uint64_t xoshiro512_next64(xoshiro512_state *state) nogil + uint32_t xoshiro512_next32(xoshiro512_state *state) nogil + void xoshiro512_jump(xoshiro512_state *state) -cdef uint64_t xoshiro512starstar_uint64(void* st) nogil: - return xoshiro512starstar_next64(st) +cdef uint64_t xoshiro512_uint64(void* st) nogil: + return xoshiro512_next64(st) -cdef uint32_t xoshiro512starstar_uint32(void *st) nogil: - return xoshiro512starstar_next32( st) +cdef uint32_t xoshiro512_uint32(void *st) nogil: + return xoshiro512_next32( st) -cdef double xoshiro512starstar_double(void* st) nogil: - return uint64_to_double(xoshiro512starstar_next64(st)) +cdef double xoshiro512_double(void* st) nogil: + return uint64_to_double(xoshiro512_next64(st)) -cdef class Xoshiro512StarStar: +cdef class Xoshiro512: """ - Xoshiro512StarStar(seed=None) + Xoshiro512(seed=None) Container for the xoshiro512** pseudo-random number generator. @@ -47,75 +47,66 @@ cdef class Xoshiro512StarStar: ---------- seed : {None, int, array_like}, optional Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in - [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - then ``Xoshiro512StarStar`` will try to read data from - ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a 64-bit hash of the time and process ID is used. + Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] + or ``None`` (the default). If `seed` is ``None``, then data is read + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a hash of the time and process ID is used. Notes ----- xoshiro512** is written by David Blackman and Sebastiano Vigna. - It is a 64-bit PRNG that uses a carefully linear transformation. + It is a 64-bit PRNG that uses a carefully constructed linear transformation. This produces a fast PRNG with excellent statistical quality [1]_. xoshiro512** has a period of :math:`2^{512} - 1` and supports jumping the sequence in increments of :math:`2^{256}`, - which allows multiple non-overlapping sequences to be generated. + which allows multiple non-overlapping subsequences to be generated. - ``Xoshiro512StarStar`` exposes no user-facing API except ``generator``, - ``state``, ``cffi`` and ``ctypes``. Designed for use in a - ``RandomGenerator`` object. + ``Xoshiro512`` 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. - **Compatibility Guarantee** + See ``Xorshift1024`` for a related PRNG with a different period + (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). + + **State and Seeding** - ``Xoshiro512StarStar`` guarantees that a fixed seed will always produce the - same results. + The ``Xoshiro512`` state vector consists of a 4 element array + of 64-bit unsigned integers. - See ``Xorshift1024`` for a related PRNG with different periods - (:math:`2^{1024} - 1`) and jump size (:math:`2^{512} - 1`). + ``Xoshiro512`` is seeded using either a single 64-bit unsigned + integer or a vector of 64-bit unsigned integers. In either case, the seed + is used as an input for another simple random number generator, SplitMix64, + and the output of this PRNG function is used as the initial state. Using + a single 64-bit value for the seed can only initialize a small range of + the possible initial state values. **Parallel Features** - ``Xoshiro512StarStar`` can be used in parallel applications by - calling the method ``jump`` which advances the state as-if - :math:`2^{128}` random numbers have been generated. This - allow the original sequence to be split so that distinct segments can be used - in each worker process. All generators should be initialized with the same - seed to ensure that the segments come from the same sequence. - - >>> from numpy.random import RandomGenerator, Xoshiro512StarStar - >>> rg = [RandomGenerator(Xoshiro512StarStar(1234)) for _ in range(10)] - # Advance each Xoshiro512StarStar instance by i jumps - >>> for i in range(10): - ... rg[i].brng.jump(i) + ``Xoshiro512`` can be used in parallel applications by calling the + method ``jumped`` which advances the state as-if :math:`2^{128}` random + numbers have been generated. 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, Xoshiro512 + >>> bit_generator = Xoshiro512(1234) + >>> rg = [] + >>> for _ in range(10): + ... rg.append(Generator(bit_generator)) + ... # Chain the BitGenerators + ... bit_generator = bit_generator.jumped() - **State and Seeding** - - The ``Xoshiro512StarStar`` state vector consists of a 4 element array - of 64-bit unsigned integers. + **Compatibility Guarantee** - ``Xoshiro512StarStar`` is seeded using either a single 64-bit unsigned - integer or a vector of 64-bit unsigned integers. In either case, the - input seed is used as an input (or inputs) for another simple random - number generator, Splitmix64, and the output of this PRNG function is - used as the initial state. Using a single 64-bit value for the seed can - only initialize a small range of the possible initial state values. When - using an array, the SplitMix64 state for producing the ith component of - the initial state is XORd with the ith value of the seed array until the - seed array is exhausted. When using an array the initial state for the - SplitMix64 state is 0 so that using a single element array and using the - same value as a scalar will produce the same initial state. + ``Xoshiro512`` makes a guarantee that a fixed seed will always + produce the same random integer stream. Examples -------- - >>> from numpy.random import RandomGenerator, Xoshiro512StarStar - >>> rg = RandomGenerator(Xoshiro512StarStar(1234)) - >>> rg.standard_normal() - 0.123 # random - - Identical method using only Xoshiro512StarStar - - >>> rg = Xoshiro512StarStar(1234).generator + >>> from numpy.random import Generator, Xoshiro512 + >>> rg = Generator(Xoshiro512(1234)) >>> rg.standard_normal() 0.123 # random @@ -124,32 +115,28 @@ cdef class Xoshiro512StarStar: .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", http://xorshift.di.unimi.it/ """ - cdef xoshiro512starstar_state *rng_state - cdef brng_t *_brng + cdef xoshiro512_state rng_state + cdef bitgen_t _bitgen cdef public object capsule cdef object _ctypes cdef object _cffi - cdef object _generator cdef public object lock def __init__(self, seed=None): - self.rng_state = malloc(sizeof(xoshiro512starstar_state)) - self._brng = malloc(sizeof(brng_t)) self.seed(seed) self.lock = Lock() - self._brng.state = self.rng_state - self._brng.next_uint64 = &xoshiro512starstar_uint64 - self._brng.next_uint32 = &xoshiro512starstar_uint32 - self._brng.next_double = &xoshiro512starstar_double - self._brng.next_raw = &xoshiro512starstar_uint64 + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &xoshiro512_uint64 + self._bitgen.next_uint32 = &xoshiro512_uint32 + self._bitgen.next_double = &xoshiro512_double + self._bitgen.next_raw = &xoshiro512_uint64 self._ctypes = None self._cffi = None - self._generator = None - cdef const char *name = "BasicRNG" - self.capsule = PyCapsule_New(self._brng, name, NULL) + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) # Pickling support: def __getstate__(self): @@ -159,16 +146,8 @@ cdef class Xoshiro512StarStar: self.state = state def __reduce__(self): - from ._pickle import __brng_ctor - return (__brng_ctor, - (self.state['brng'],), - self.state) - - def __dealloc__(self): - if self.rng_state: - free(self.rng_state) - if self._brng: - free(self._brng) + from ._pickle import __bit_generator_ctor + return __bit_generator_ctor, (self.state['bit_generator'],), self.state cdef _reset_state_variables(self): self.rng_state.has_uint32 = 0 @@ -178,7 +157,7 @@ cdef class Xoshiro512StarStar: """ random_raw(self, size=None) - Return randoms as generated by the underlying BasicRNG + Return randoms as generated by the underlying BitGenerator Parameters ---------- @@ -203,10 +182,10 @@ cdef class Xoshiro512StarStar: See the class docstring for the number of bits returned. """ - return random_raw(self._brng, self.lock, size, output) + return random_raw(&self._bitgen, self.lock, size, output) def _benchmark(self, Py_ssize_t cnt, method=u'uint64'): - return benchmark(self._brng, self.lock, cnt, method) + return benchmark(&self._bitgen, self.lock, cnt, method) def seed(self, seed=None): """ @@ -241,32 +220,48 @@ cdef class Xoshiro512StarStar: self.rng_state.s[i] = int(state[i]) self._reset_state_variables() - def jump(self, np.npy_intp iter=1): + cdef jump_inplace(self, np.npy_intp iter): """ - jump(iter=1) + Jump state in-place - Jumps the state as-if 2**256 random numbers have been generated. + Not part of public API Parameters ---------- iter : integer, positive Number of times to jump the state of the rng. - - Returns - ------- - self : Xoshiro512StarStar - PRNG jumped iter times - - Notes - ----- - Jumping the rng state resets any pre-computed random numbers. This is required - to ensure exact reproducibility. """ cdef np.npy_intp i for i in range(iter): - xoshiro512starstar_jump(self.rng_state) + xoshiro512_jump(&self.rng_state) self._reset_state_variables() - return self + + def jumped(self, np.npy_intp iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(256 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : Xoroshiro128 + New instance of generator jumped iter times + """ + cdef Xoshiro512 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + return bit_generator @property def state(self): @@ -282,7 +277,7 @@ cdef class Xoshiro512StarStar: state = np.empty(8, dtype=np.uint64) for i in range(8): state[i] = self.rng_state.s[i] - return {'brng': self.__class__.__name__, + return {'bit_generator': self.__class__.__name__, 's': state, 'has_uint32': self.rng_state.has_uint32, 'uinteger': self.rng_state.uinteger} @@ -291,8 +286,8 @@ cdef class Xoshiro512StarStar: def state(self, value): if not isinstance(value, dict): raise TypeError('state must be a dict') - brng = value.get('brng', '') - if brng != self.__class__.__name__: + 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(8): @@ -315,10 +310,10 @@ cdef class Xoshiro512StarStar: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._ctypes is None: - self._ctypes = prepare_ctypes(self._brng) + self._ctypes = prepare_ctypes(&self._bitgen) return self._ctypes @@ -337,24 +332,9 @@ cdef class Xoshiro512StarStar: * 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 - * brng - pointer to the Basic RNG struct + * bitgen - pointer to the bit generator struct """ if self._cffi is not None: return self._cffi - self._cffi = prepare_cffi(self._brng) + self._cffi = prepare_cffi(&self._bitgen) return self._cffi - - @property - def generator(self): - """ - Return a RandomGenerator object - - Returns - ------- - gen : numpy.random.RandomGenerator - Random generator used this instance as the basic RNG - """ - if self._generator is None: - from .generator import RandomGenerator - self._generator = RandomGenerator(self) - return self._generator From b42a5ca0a076b40c612014dc540ca5f9bcf10f41 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 18 May 2019 23:47:51 +0100 Subject: [PATCH 122/138] BUG: Ensure integer-type stream on 32bit Ensure integer type is stream compatible on 32 bit Fix incorrect clause end Add integer-generator tests that check long streams --- numpy/random/common.pxd | 6 +- numpy/random/common.pyx | 6 +- numpy/random/legacy_distributions.pxd | 8 +- numpy/random/mtrand.pyx | 126 +++++++++++------- numpy/random/setup.py | 5 +- .../random/src/distributions/distributions.c | 112 +++++++++------- .../random/src/distributions/distributions.h | 47 ++++--- .../src/legacy/distributions-boxmuller.c | 39 +++++- .../src/legacy/distributions-boxmuller.h | 12 ++ numpy/random/tests/test_generator_mt19937.py | 10 +- numpy/random/tests/test_randomstate.py | 61 ++++++++- 11 files changed, 293 insertions(+), 139 deletions(-) diff --git a/numpy/random/common.pxd b/numpy/random/common.pxd index 4f7c8c903ada..1223b2706d65 100644 --- a/numpy/random/common.pxd +++ b/numpy/random/common.pxd @@ -96,6 +96,6 @@ cdef object cont_broadcast_3(void *func, void *state, object size, object lock, 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) + 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 index 2fa854807bae..e195195a4af1 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -666,9 +666,9 @@ cdef object discrete_broadcast_di(void *func, void *state, object size, object l 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): + 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 diff --git a/numpy/random/legacy_distributions.pxd b/numpy/random/legacy_distributions.pxd index 7969cfb929ba..e5d7a22a4f09 100644 --- a/numpy/random/legacy_distributions.pxd +++ b/numpy/random/legacy_distributions.pxd @@ -5,7 +5,7 @@ from libc.stdint cimport int64_t import numpy as np cimport numpy as np -from .distributions cimport bitgen_t +from .distributions cimport bitgen_t, binomial_t cdef extern from "distributions-boxmuller.h": @@ -35,6 +35,12 @@ cdef extern from "distributions-boxmuller.h": 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 diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 299398c34cb4..74d1f519d97a 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -21,6 +21,19 @@ 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 x64 + return x.astype('l', casting='unsafe') + + cdef class RandomState: """ RandomState(bit_generator=None) @@ -3031,43 +3044,43 @@ cdef class RandomState: # Uses a custom implementation since self._binomial is required cdef double _dp = 0 - cdef int64_t _in = 0 + cdef long _in = 0 cdef bint is_scalar = True cdef np.npy_intp i, cnt cdef np.ndarray randoms - cdef np.int64_t *randoms_data + cdef long *randoms_data cdef np.broadcast it p_arr = 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.PyArray_FROM_OTF(n, np.NPY_INT64, np.NPY_ALIGNED) + n_arr = 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.empty(size, np.int64) + randoms = np.empty(size, int) else: it = np.PyArray_MultiIterNew2(p_arr, n_arr) - randoms = np.empty(it.shape, np.int64) + randoms = np.empty(it.shape, int) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = 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 = (np.PyArray_MultiIter_DATA(it, 1))[0] - _in = (np.PyArray_MultiIter_DATA(it, 2))[0] - (np.PyArray_MultiIter_DATA(it, 0))[0] = random_binomial(&self._bitgen, _dp, _in, &self._binomial) + _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + (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 = n + _in = n check_constraint(_dp, 'p', CONS_BOUNDED_0_1) check_constraint(_in, 'n', CONS_NON_NEGATIVE) @@ -3075,9 +3088,9 @@ cdef class RandomState: with self.lock: return random_binomial(&self._bitgen, _dp, _in, &self._binomial) - randoms = np.empty(size, np.int64) + randoms = np.empty(size, int) cnt = np.PyArray_SIZE(randoms) - randoms_data = np.PyArray_DATA(randoms) + randoms_data = np.PyArray_DATA(randoms) with self.lock, nogil: for i in range(cnt): @@ -3157,10 +3170,12 @@ cdef class RandomState: ... print(i, "wells drilled, probability of one success =", probability) """ - return 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) + 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): """ @@ -3228,10 +3243,12 @@ cdef class RandomState: >>> s = np.random.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) + out = disc(&legacy_random_poisson, &self._bitgen, size, self.lock, 1, 0, + lam, 'lam', 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): """ @@ -3307,10 +3324,12 @@ cdef class RandomState: >>> 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) + 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): """ @@ -3358,10 +3377,12 @@ cdef class RandomState: 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) + 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): """ @@ -3458,9 +3479,10 @@ cdef class RandomState: cdef np.ndarray ongood, onbad, onsample cdef int64_t lngood, lnbad, lnsample - ongood = np.PyArray_FROM_OTF(ngood, np.NPY_INT64, np.NPY_ALIGNED) - onbad = np.PyArray_FROM_OTF(nbad, np.NPY_INT64, np.NPY_ALIGNED) - onsample = np.PyArray_FROM_OTF(nsample, np.NPY_INT64, np.NPY_ALIGNED) + # This cast to long is required to ensure that the values are inbounds + ongood = np.PyArray_FROM_OTF(ngood, np.NPY_LONG, np.NPY_ALIGNED) + onbad = np.PyArray_FROM_OTF(nbad, np.NPY_LONG, np.NPY_ALIGNED) + onsample = 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: @@ -3470,17 +3492,25 @@ cdef class RandomState: 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_GTE_1) + 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 discrete_broadcast_iii(&random_hypergeometric, &self._bitgen, size, self.lock, - ongood, 'ngood', CONS_NON_NEGATIVE, - onbad, 'nbad', CONS_NON_NEGATIVE, - onsample, 'nsample', CONS_GTE_1) + # 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): """ @@ -3557,10 +3587,12 @@ cdef class RandomState: >>> 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) + 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', @@ -3808,8 +3840,8 @@ cdef class RandomState: cdef np.npy_intp d, i, sz, offset cdef np.ndarray parr, mnarr cdef double *pix - cdef int64_t *mnix - cdef int64_t ni + cdef long *mnix + cdef long ni d = len(pvals) parr = np.PyArray_FROM_OTF(pvals, np.NPY_DOUBLE, np.NPY_ALIGNED) @@ -3826,16 +3858,16 @@ cdef class RandomState: except: shape = tuple(size) + (d,) - multin = np.zeros(shape, dtype=np.int64) + multin = np.zeros(shape, dtype=int) mnarr = multin - mnix = np.PyArray_DATA(mnarr) + mnix = 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) + legacy_random_multinomial(&self._bitgen, ni, &mnix[offset], pix, d, &self._binomial) offset += d return multin diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 5f3a48783b50..3c9b3289fa42 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -84,9 +84,8 @@ def generate_libraries(ext, build_dir): if DEBUG: EXTRA_LINK_ARGS += ['-debug'] EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] - if sys.version_info < (3, 0): - EXTRA_INCLUDE_DIRS += [join(MOD_DIR, 'src', 'common')] + LEGACY_DEFS = [('NP_RANDOM_LEGACY', '1')] DSFMT_DEFS = [('DSFMT_MEXP', '19937')] if USE_SSE2: if os.name == 'nt': @@ -180,7 +179,7 @@ def generate_libraries(ext, build_dir): extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, depends=['mtrand.pyx'], - define_macros=defs + DSFMT_DEFS, + define_macros=defs + DSFMT_DEFS + LEGACY_DEFS, ) return config diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 789440f8bba6..d8362a39a58c 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -646,8 +646,8 @@ double random_standard_t(bitgen_t *bitgen_state, double df) { return sqrt(df / 2) * num / sqrt(denom); } -static int64_t random_poisson_mult(bitgen_t *bitgen_state, double lam) { - int64_t X; +static RAND_INT_TYPE random_poisson_mult(bitgen_t *bitgen_state, double lam) { + RAND_INT_TYPE X; double prod, U, enlam; enlam = exp(-lam); @@ -671,8 +671,8 @@ static int64_t random_poisson_mult(bitgen_t *bitgen_state, double lam) { */ #define LS2PI 0.91893853320467267 #define TWELFTH 0.083333333333333333333333 -static int64_t random_poisson_ptrs(bitgen_t *bitgen_state, double lam) { - int64_t k; +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); @@ -686,7 +686,7 @@ static int64_t random_poisson_ptrs(bitgen_t *bitgen_state, double lam) { U = next_double(bitgen_state) - 0.5; V = next_double(bitgen_state); us = 0.5 - fabs(U); - k = (int64_t)floor((2 * a / us + b) * U + lam + 0.43); + k = (RAND_INT_TYPE)floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { return k; } @@ -702,7 +702,7 @@ static int64_t random_poisson_ptrs(bitgen_t *bitgen_state, double lam) { } } -int64_t random_poisson(bitgen_t *bitgen_state, double lam) { +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) { @@ -712,16 +712,17 @@ int64_t random_poisson(bitgen_t *bitgen_state, double lam) { } } -int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) { +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); } -int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, - binomial_t *binomial) { +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; - int64_t m, y, k, i; + RAND_INT_TYPE m, y, k, i; if (!(binomial->has_binomial) || (binomial->nsave != n) || (binomial->psave != p)) { @@ -732,7 +733,7 @@ int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, binomial->r = r = MIN(p, 1.0 - p); binomial->q = q = 1.0 - r; binomial->fm = fm = n * r + r; - binomial->m = m = (int64_t)floor(binomial->fm); + 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; @@ -769,7 +770,7 @@ int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, v = next_double(bitgen_state); if (u > p1) goto Step20; - y = (int64_t)floor(xm - p1 * v + u); + y = (RAND_INT_TYPE)floor(xm - p1 * v + u); goto Step60; Step20: @@ -779,13 +780,13 @@ int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, v = v * c + 1.0 - fabs(m - x + 0.5) / p1; if (v > 1.0) goto Step10; - y = (int64_t)floor(x); + y = (RAND_INT_TYPE)floor(x); goto Step50; Step30: if (u > p3) goto Step40; - y = (int64_t)floor(xl + log(v) / laml); + 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; @@ -793,7 +794,7 @@ int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, goto Step50; Step40: - y = (int64_t)floor(xr - log(v) / lamr); + 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; @@ -860,10 +861,10 @@ int64_t random_binomial_btpe(bitgen_t *bitgen_state, int64_t n, double p, return y; } -int64_t random_binomial_inversion(bitgen_t *bitgen_state, int64_t n, double p, - binomial_t *binomial) { +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; - int64_t X, bound; + RAND_INT_TYPE X, bound; if (!(binomial->has_binomial) || (binomial->nsave != n) || (binomial->psave != p)) { @@ -873,7 +874,7 @@ int64_t random_binomial_inversion(bitgen_t *bitgen_state, int64_t n, double p, binomial->q = q = 1.0 - p; binomial->r = qn = exp(n * log(q)); binomial->c = np = n * p; - binomial->m = bound = (int64_t)MIN(n, np + 10.0 * sqrt(np * q + 1)); + binomial->m = bound = (RAND_INT_TYPE)MIN(n, np + 10.0 * sqrt(np * q + 1)); } else { q = binomial->q; qn = binomial->r; @@ -897,8 +898,8 @@ int64_t random_binomial_inversion(bitgen_t *bitgen_state, int64_t n, double p, return X; } -int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, - binomial_t *binomial) { +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)) @@ -933,7 +934,7 @@ double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, const double n = random_gauss_zig(bitgen_state) + sqrt(nonc); return Chi2 + n * n; } else { - const int64_t i = random_poisson(bitgen_state, nonc / 2.0); + const RAND_INT_TYPE i = random_poisson(bitgen_state, nonc / 2.0); return random_chisquare(bitgen_state, df + 2 * i); } } @@ -1017,9 +1018,15 @@ double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) { } } -int64_t random_logseries(bitgen_t *bitgen_state, double p) { +/* + * 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; - int64_t result; + RAND_INT_TYPE result; r = log(1.0 - p); @@ -1031,7 +1038,7 @@ int64_t random_logseries(bitgen_t *bitgen_state, double p) { U = next_double(bitgen_state); q = 1.0 - exp(r * U); if (V <= q * q) { - result = (int64_t)floor(1 + log(V) / log(q)); + result = (RAND_INT_TYPE)floor(1 + log(V) / log(q)); if ((result < 1) || (V == 0.0)) { continue; } else { @@ -1045,9 +1052,9 @@ int64_t random_logseries(bitgen_t *bitgen_state, double p) { } } -int64_t random_geometric_search(bitgen_t *bitgen_state, double p) { +RAND_INT_TYPE random_geometric_search(bitgen_t *bitgen_state, double p) { double U; - int64_t X; + RAND_INT_TYPE X; double sum, prod, q; X = 1; @@ -1062,11 +1069,11 @@ int64_t random_geometric_search(bitgen_t *bitgen_state, double p) { return X; } -int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) { - return (int64_t)ceil(log(1.0 - next_double(bitgen_state)) / log(1.0 - p)); +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)); } -int64_t random_geometric(bitgen_t *bitgen_state, double p) { +RAND_INT_TYPE random_geometric(bitgen_t *bitgen_state, double p) { if (p >= 0.333333333333333333333333) { return random_geometric_search(bitgen_state, p); } else { @@ -1074,7 +1081,7 @@ int64_t random_geometric(bitgen_t *bitgen_state, double p) { } } -int64_t random_zipf(bitgen_t *bitgen_state, double a) { +RAND_INT_TYPE random_zipf(bitgen_t *bitgen_state, double a) { double am1, b; am1 = a - 1.0; @@ -1091,13 +1098,13 @@ int64_t random_zipf(bitgen_t *bitgen_state, double a) { * just reject this value. This function then models a Zipf * distribution truncated to sys.maxint. */ - if (X > LONG_MAX || X < 1.0) { + 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 (int64_t)X; + return (RAND_INT_TYPE)X; } } } @@ -1121,9 +1128,10 @@ double random_triangular(bitgen_t *bitgen_state, double left, double mode, } } -int64_t random_hypergeometric_hyp(bitgen_t *bitgen_state, int64_t good, - int64_t bad, int64_t sample) { - int64_t d1, k, z; +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; @@ -1133,12 +1141,12 @@ int64_t random_hypergeometric_hyp(bitgen_t *bitgen_state, int64_t good, k = sample; while (y > 0.0) { u = next_double(bitgen_state); - y -= (int64_t)floor(u + y / (d1 + k)); + y -= (RAND_INT_TYPE)floor(u + y / (d1 + k)); k--; if (k == 0) break; } - z = (int64_t)(d2 - y); + z = (RAND_INT_TYPE)(d2 - y); if (good > bad) z = sample - z; return z; @@ -1148,11 +1156,12 @@ int64_t random_hypergeometric_hyp(bitgen_t *bitgen_state, int64_t good, /* D2 = 3 - 2*sqrt(3/e) */ #define D1 1.7155277699214135 #define D2 0.8989161620588988 -int64_t random_hypergeometric_hrua(bitgen_t *bitgen_state, int64_t good, - int64_t bad, int64_t sample) { - int64_t mingoodbad, maxgoodbad, popsize, m, d9; +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; - int64_t Z; + RAND_INT_TYPE Z; double T, W, X, Y; mingoodbad = MIN(good, bad); @@ -1164,7 +1173,7 @@ int64_t random_hypergeometric_hrua(bitgen_t *bitgen_state, int64_t good, d6 = m * d4 + 0.5; d7 = sqrt((double)(popsize - m) * sample * d4 * d5 / (popsize - 1) + 0.5); d8 = D1 * d7 + D2; - d9 = (int64_t)floor((double)(m + 1) * (mingoodbad + 1) / (popsize + 2)); + 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)); @@ -1179,7 +1188,7 @@ int64_t random_hypergeometric_hrua(bitgen_t *bitgen_state, int64_t good, if ((W < 0.0) || (W >= d11)) continue; - Z = (int64_t)floor(W); + Z = (RAND_INT_TYPE)floor(W); T = d10 - (loggam(Z + 1) + loggam(mingoodbad - Z + 1) + loggam(m - Z + 1) + loggam(maxgoodbad - m + Z + 1)); @@ -1208,8 +1217,8 @@ int64_t random_hypergeometric_hrua(bitgen_t *bitgen_state, int64_t good, #undef D1 #undef D2 -int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad, - int64_t sample) { +RAND_INT_TYPE random_hypergeometric(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) { @@ -1849,11 +1858,12 @@ void random_bounded_bool_fill(bitgen_t *bitgen_state, npy_bool off, } } -void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix, - double *pix, npy_intp d, binomial_t *binomial) { +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; - int64_t dn = n; + 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]; @@ -1861,8 +1871,8 @@ void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix, break; } remaining_p -= pix[j]; - if (dn > 0) { + } + if (dn > 0) { mnix[d - 1] = dn; - } } } diff --git a/numpy/random/src/distributions/distributions.h b/numpy/random/src/distributions/distributions.h index d1d439d78a63..e43a5279c1af 100644 --- a/numpy/random/src/distributions/distributions.h +++ b/numpy/random/src/distributions/distributions.h @@ -10,19 +10,18 @@ #include "numpy/npy_common.h" #include "numpy/npy_math.h" -#ifdef _WIN32 -#if _MSC_VER == 1500 - -static NPY_INLINE int64_t llabs(int64_t x) { - int64_t o; - if (x < 0) { - o = -x; - } else { - o = x; - } - return o; -} -#endif +/* + * 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 @@ -151,18 +150,18 @@ 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 int64_t random_poisson(bitgen_t *bitgen_state, double lam); -DECLDIR int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, +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 int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, +DECLDIR RAND_INT_TYPE random_binomial(bitgen_t *bitgen_state, double p, RAND_INT_TYPE n, binomial_t *binomial); -DECLDIR int64_t random_logseries(bitgen_t *bitgen_state, double p); -DECLDIR int64_t random_geometric_search(bitgen_t *bitgen_state, double p); -DECLDIR int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p); -DECLDIR int64_t random_geometric(bitgen_t *bitgen_state, double p); -DECLDIR int64_t 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 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 RAND_INT_TYPE random_hypergeometric(bitgen_t *bitgen_state, RAND_INT_TYPE good, + RAND_INT_TYPE bad, RAND_INT_TYPE sample); DECLDIR uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max); @@ -205,7 +204,7 @@ 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, int64_t n, int64_t *mnix, +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/legacy/distributions-boxmuller.c b/numpy/random/src/legacy/distributions-boxmuller.c index 2c715799f317..e7b3bdde7321 100644 --- a/numpy/random/src/legacy/distributions-boxmuller.c +++ b/numpy/random/src/legacy/distributions-boxmuller.c @@ -163,7 +163,7 @@ double legacy_standard_t(aug_bitgen_t *aug_state, double df) { 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 random_poisson(aug_state->bit_generator, Y); + return (int64_t)random_poisson(aug_state->bit_generator, Y); } double legacy_standard_cauchy(aug_bitgen_t *aug_state) { @@ -212,3 +212,40 @@ double legacy_f(aug_bitgen_t *aug_state, double dfnum, double dfden) { double legacy_exponential(aug_bitgen_t *aug_state, double scale) { return scale * legacy_standard_exponential(aug_state); } + +/* + * 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(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/distributions-boxmuller.h b/numpy/random/src/legacy/distributions-boxmuller.h index 07e093b26c44..005c4e5d24bb 100644 --- a/numpy/random/src/legacy/distributions-boxmuller.h +++ b/numpy/random/src/legacy/distributions-boxmuller.h @@ -36,5 +36,17 @@ 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/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 3bb3bd791c46..770c32a3907b 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -182,10 +182,10 @@ def test_bounds_checking_array(self, endpoint): 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, [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, @@ -1895,7 +1895,7 @@ def test_multinomial(self): [4, 5, 1, 4, 3, 3]], [[1, 1, 1, 0, 0, 2], [2, 0, 4, 3, 7, 4]], - [[1, 2, 0, 0, 2, 2], + [[1, 2, 0, 0, 2, 0], [3, 2, 3, 4, 2, 6]]], dtype=np.int64) assert_array_equal(actual, desired) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 0c57b9aaff47..75c35ef62453 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -1,8 +1,10 @@ +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, @@ -11,6 +13,44 @@ from numpy.random import MT19937, Xoshiro256, 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']) @@ -269,7 +309,6 @@ def test_in_bounds_fuzz(self): assert_(vals.min() >= 0) def test_repeatability(self): - 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. @@ -1862,3 +1901,23 @@ def test_three_arg_funcs(self): out = func(self.argOne, self.argTwo[0], self.argThree) assert_equal(out.shape, self.tgtShape) + + +# Ensure returned array dtype is corect 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) From 720a0a9a6baa3cb0ded826933807b2be061bfe2c Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 19 May 2019 23:32:38 +0100 Subject: [PATCH 123/138] BLD: Use numpy detection of SSE Let numpy detect SSE2 --- numpy/random/setup.py | 27 +++++++++------------------ numpy/random/src/dsfmt/dSFMT.h | 6 ++++++ 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 3c9b3289fa42..30dfcdb0f1e5 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -65,15 +65,6 @@ def generate_libraries(ext, build_dir): ############################## # Make a guess as to whether SSE2 is present for now, TODO: Improve - USE_SSE2 = False - for k in platform.uname(): - for val in ('x86', 'i686', 'i386', 'amd64'): - USE_SSE2 = USE_SSE2 or val in k.lower() - print('Building with SSE?: {0}'.format(USE_SSE2)) - if '--no-sse2' in sys.argv: - USE_SSE2 = False - sys.argv.remove('--no-sse2') - DEBUG = False EXTRA_LINK_ARGS = [] EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] @@ -86,15 +77,15 @@ def generate_libraries(ext, build_dir): EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] LEGACY_DEFS = [('NP_RANDOM_LEGACY', '1')] - DSFMT_DEFS = [('DSFMT_MEXP', '19937')] - if USE_SSE2: - if os.name == 'nt': - EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] - if struct.calcsize('P') < 8: - EXTRA_COMPILE_ARGS += ['/arch:SSE2'] - else: - EXTRA_COMPILE_ARGS += ['-msse2'] - DSFMT_DEFS += [('HAVE_SSE2', '1')] + DSFMT_DEFS = [('DSFMT_MEXP', '19937'), ("HAVE_NPY_CONFIG_H", "1")] + INTEL_LIKE = any([val in k.lower() for k in platform.uname() + for val in ('x86', 'i686', 'i386', 'amd64')]) + if os.name == 'nt': + EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] + if struct.calcsize('P') < 8: + EXTRA_COMPILE_ARGS += ['/arch:SSE2'] + elif INTEL_LIKE: + EXTRA_COMPILE_ARGS += ['-msse2'] config.add_extension('entropy', sources=['entropy.c', 'src/entropy/entropy.c'], diff --git a/numpy/random/src/dsfmt/dSFMT.h b/numpy/random/src/dsfmt/dSFMT.h index 224d0108fbf3..75ef5746fbf9 100644 --- a/numpy/random/src/dsfmt/dSFMT.h +++ b/numpy/random/src/dsfmt/dSFMT.h @@ -41,6 +41,12 @@ extern "C" { #include #include +/* Use NumPy config to determine if SSE2 is present */ +#include "numpy/npy_common.h" +#if defined NPY_HAVE_SSE2_INTRINSICS +#define HAVE_SSE2 1 +#endif + #if !defined(DSFMT_MEXP) #ifdef __GNUC__ #warning "DSFMT_MEXP is not defined. I assume DSFMT_MEXP is 19937." From e058ae46f534f675bb39e521eacc5874c0149c11 Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 20 May 2019 16:54:55 +0300 Subject: [PATCH 124/138] MAINT: remove unused file --- MANIFEST.in | 1 - numpy/random/_mtrand/generate_mtrand_c.py | 42 ----------------------- 2 files changed, 43 deletions(-) delete mode 100644 numpy/random/_mtrand/generate_mtrand_c.py diff --git a/MANIFEST.in b/MANIFEST.in index e27b843a9e97..7c8f3b6ef936 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,7 +9,6 @@ include pytest.ini include *.txt include README.md include site.cfg.example -include numpy/random/_mtrand/generate_mtrand_c.py recursive-include numpy/random *.pyx *.pxd *.pyx.in *.pxd.in # Add build support that should go in sdist, but not go in bdist/be installed # Note that sub-directories that don't have __init__ are apparently not diff --git a/numpy/random/_mtrand/generate_mtrand_c.py b/numpy/random/_mtrand/generate_mtrand_c.py deleted file mode 100644 index ec935e6ddf09..000000000000 --- 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') From 3d19ae92ac3dc4fad7018112a3e293a5e4b283b1 Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 20 May 2019 23:06:48 +0300 Subject: [PATCH 125/138] MAINT: remove threefry32, xoroshiro128, xorshift1024 BitGenerators --- benchmarks/benchmarks/bench_random.py | 10 +- .../reference/random/bit_generators/index.rst | 12 - .../random/bit_generators/threefry32.rst | 36 - .../random/bit_generators/xoroshiro128.rst | 35 - .../random/bit_generators/xorshift1024.rst | 35 - doc/source/reference/random/index.rst | 20 +- .../reference/random/new-or-different.rst | 8 +- numpy/random/__init__.py | 9 +- numpy/random/_pickle.py | 6 - numpy/random/generator.pyx | 6 +- numpy/random/setup.py | 5 +- numpy/random/src/threefry32/LICENSE.md | 31 - .../src/threefry32/threefry32-test-data-gen.c | 88 -- numpy/random/src/threefry32/threefry32.c | 29 - numpy/random/src/threefry32/threefry32.h | 832 ------------------ numpy/random/tests/test_direct.py | 60 +- numpy/random/tests/test_smoke.py | 42 +- numpy/random/threefry32.pyx | 454 ---------- numpy/random/xoroshiro128.pyx | 342 ------- numpy/random/xorshift1024.pyx | 349 -------- 20 files changed, 23 insertions(+), 2386 deletions(-) delete mode 100644 doc/source/reference/random/bit_generators/threefry32.rst delete mode 100644 doc/source/reference/random/bit_generators/xoroshiro128.rst delete mode 100644 doc/source/reference/random/bit_generators/xorshift1024.rst delete mode 100644 numpy/random/src/threefry32/LICENSE.md delete mode 100644 numpy/random/src/threefry32/threefry32-test-data-gen.c delete mode 100644 numpy/random/src/threefry32/threefry32.c delete mode 100644 numpy/random/src/threefry32/threefry32.h delete mode 100644 numpy/random/threefry32.pyx delete mode 100644 numpy/random/xoroshiro128.pyx delete mode 100644 numpy/random/xorshift1024.pyx diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index db63167d126e..c0bf42e2ef50 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -86,9 +86,8 @@ def time_permutation_int(self): class RNG(Benchmark): param_names = ['rng'] - params = ['DSFMT', 'MT19937', 'Xoroshiro128', - 'Xorshift1024', 'Xoshiro256', 'Xoshiro512', - 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'] + params = ['DSFMT', 'MT19937', 'Xoshiro256', 'Xoshiro512', + 'Philox', 'ThreeFry', 'numpy'] def setup(self, brng): if brng == 'numpy': @@ -129,9 +128,8 @@ class Bounded(Benchmark): u32 = np.uint32 u64 = np.uint64 param_names = ['rng', 'dt_max'] - params = [['DSFMT', 'MT19937', 'Xoroshiro128', - 'Xorshift1024', 'Xoshiro256', 'Xoshiro512', - 'Philox', 'ThreeFry', 'ThreeFry32', 'numpy'], + params = [['DSFMT', 'MT19937','Xoshiro256', 'Xoshiro512', + 'Philox', 'ThreeFry', 'numpy'], [[u8, 95], [u8, 64], # Worst case for legacy [u8, 127], # Best case for legacy diff --git a/doc/source/reference/random/bit_generators/index.rst b/doc/source/reference/random/bit_generators/index.rst index e3ca073c95c2..5fcb6ce37307 100644 --- a/doc/source/reference/random/bit_generators/index.rst +++ b/doc/source/reference/random/bit_generators/index.rst @@ -22,18 +22,6 @@ Stable RNGs MT19937 Philox ThreeFry - XoroShiro128+ - Xorshift1024*φ Xoshiro256** Xoshiro512** - -Experimental RNGs -================= - -These BitGenerators are currently included but are may not be permanent. - -.. toctree:: - :maxdepth: 1 - - ThreeFry32 diff --git a/doc/source/reference/random/bit_generators/threefry32.rst b/doc/source/reference/random/bit_generators/threefry32.rst deleted file mode 100644 index 1af9491a6972..000000000000 --- a/doc/source/reference/random/bit_generators/threefry32.rst +++ /dev/null @@ -1,36 +0,0 @@ -ThreeFry32 Counter-based RNG ----------------------------- - -.. module:: numpy.random.threefry32 - -.. currentmodule:: numpy.random.threefry32 - -.. autoclass:: ThreeFry32 - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~ThreeFry32.seed - ~ThreeFry32.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~ThreeFry32.advance - ~ThreeFry32.jumped - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~ThreeFry32.cffi - ~ThreeFry32.ctypes - - diff --git a/doc/source/reference/random/bit_generators/xoroshiro128.rst b/doc/source/reference/random/bit_generators/xoroshiro128.rst deleted file mode 100644 index 41f5238fcc68..000000000000 --- a/doc/source/reference/random/bit_generators/xoroshiro128.rst +++ /dev/null @@ -1,35 +0,0 @@ -Xoroshiro128+ -------------- - -.. module:: numpy.random.xoroshiro128 - -.. currentmodule:: numpy.random.xoroshiro128 - -.. autoclass:: Xoroshiro128 - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~Xoroshiro128.seed - ~Xoroshiro128.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~Xoroshiro128.jumped - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~Xoroshiro128.cffi - ~Xoroshiro128.ctypes - - diff --git a/doc/source/reference/random/bit_generators/xorshift1024.rst b/doc/source/reference/random/bit_generators/xorshift1024.rst deleted file mode 100644 index 5d0c9048fe9f..000000000000 --- a/doc/source/reference/random/bit_generators/xorshift1024.rst +++ /dev/null @@ -1,35 +0,0 @@ -Xorshift1024*φ --------------- - -.. module:: numpy.random.xorshift1024 - -.. currentmodule:: numpy.random.xorshift1024 - -.. autoclass:: Xorshift1024 - :exclude-members: - -Seeding and State -================= - -.. autosummary:: - :toctree: generated/ - - ~Xorshift1024.seed - ~Xorshift1024.state - -Parallel generation -=================== -.. autosummary:: - :toctree: generated/ - - ~Xorshift1024.jumped - -Extending -========= -.. autosummary:: - :toctree: generated/ - - ~Xorshift1024.cffi - ~Xorshift1024.ctypes - - diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 032db8562a5c..45b5ed2c00f6 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -30,7 +30,7 @@ instance's methods are imported into the numpy.random namespace, see Quick Start ----------- -By default, `Generator` uses normals provided by `xoroshiro128.Xoroshiro128` +By default, `Generator` uses normals provided by `xoshiro256.Xoshiro256` which will be faster than the legacy methods in `RandomState` .. code-block:: python @@ -40,7 +40,7 @@ which will be faster than the legacy methods in `RandomState` random.standard_normal() `Generator` can be used as a direct replacement for `~RandomState`, although -the random values are generated by `~xoroshiro128.Xoroshiro128`. The +the random values are generated by `~xoshiro256.Xoshiro256`. The `Generator` holds an instance of a BitGenerator. It is accessable as ``gen.bit_generator``. @@ -120,8 +120,8 @@ What's New or Different source of randomness that is used in cryptographic applications (e.g., ``/dev/urandom`` on Unix). * All BitGenerators can produce doubles, uint64s and uint32s via CTypes - (`~xoroshiro128.Xoroshiro128.ctypes`) and CFFI - (:meth:`~xoroshiro128.Xoroshiro128.cffi`). This allows the bit generators to + (`~xoshiro256.Xoshiro256.ctypes`) and CFFI + (:meth:`~xoshiro256.Xoshiro256.cffi`). This allows the bit generators to be used in numba. * The bit generators can be used in downstream projects via :ref:`Cython `. @@ -157,18 +157,6 @@ The included BitGenerators are: the same, but with a different state and so it is not possible to produce a sequence identical to MT19937. Supports ``jumped`` and so can be used in parallel applications. See the `dSFMT authors' page`_. -* XoroShiro128+ - Improved version of XorShift128+ with better performance - and statistical quality. Like the XorShift generators, it can be jumped - to produce multiple streams in parallel applications. See - `~xoroshiro128.Xoroshiro128.jumped` for details. - More information about this bit generator is available at the - `xorshift, xoroshiro and xoshiro authors' page`_. -* XorShift1024*φ - Fast fast generator based on the XSadd - generator. Supports ``jumped`` and so can be used in - parallel applications. See the documentation for - `~xorshift1024.Xorshift1024.jumped` for details. More - information about these bit generators is available at the - `xorshift, xoroshiro and xoshiro authors' page`_. * Xorshiro256** and Xorshiro512** - The most recently introduced XOR, shift, and rotate generator. Supports ``jumped`` and so can be used in parallel applications. See the documentation for diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst index 906cceceb5fe..969a9372da39 100644 --- a/doc/source/reference/random/new-or-different.rst +++ b/doc/source/reference/random/new-or-different.rst @@ -58,8 +58,8 @@ And in more detail: This replaces both ``randint`` and the deprecated ``random_integers``. * The Box-Muller used to produce NumPy's normals is no longer available. * All bit generators can produce doubles, uint64s and - uint32s via CTypes (`~.xoroshiro128.Xoroshiro128. - ctypes`) and CFFI (`~.xoroshiro128.Xoroshiro128.cffi`). + uint32s via CTypes (`~.xoshiro256.Xoshiro256. + ctypes`) and CFFI (`~.xoshiro256.Xoshiro256.cffi`). This allows these bit generators to be used in numba. * The bit generators can be used in downstream projects via Cython. @@ -67,9 +67,9 @@ And in more detail: .. ipython:: python - from numpy.random import Generator, Xoroshiro128 + from numpy.random import Generator, Xoshiro256 import numpy.random - rg = Generator(Xoroshiro128()) + rg = Generator(Xoshiro256()) %timeit rg.standard_normal(100000) %timeit numpy.random.standard_normal(100000) diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 7c30ada1547b..51a2952f1cea 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -101,9 +101,6 @@ DSFMT Philox ThreeFry -ThreeFry32 -Xoroshiro128 -Xoroshift1024 Xoshiro256 Xoshiro512 ============================================= === @@ -168,16 +165,12 @@ from .mt19937 import MT19937 from .philox import Philox from .threefry import ThreeFry -from .threefry32 import ThreeFry32 -from .xoroshiro128 import Xoroshiro128 -from .xorshift1024 import Xorshift1024 from .xoshiro256 import Xoshiro256 from .xoshiro512 import Xoshiro512 from .mtrand import RandomState __all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox', - 'ThreeFry', 'ThreeFry32', 'Xoroshiro128', 'Xorshift1024', - 'Xoshiro256', 'Xoshiro512', 'RandomState'] + 'ThreeFry', 'Xoshiro256', 'Xoshiro512', 'RandomState'] # Some aliases: ranf = random = sample = random_sample diff --git a/numpy/random/_pickle.py b/numpy/random/_pickle.py index 391c565a5300..71a6d8bdd11a 100644 --- a/numpy/random/_pickle.py +++ b/numpy/random/_pickle.py @@ -1,9 +1,6 @@ from .mtrand import RandomState from .philox import Philox from .threefry import ThreeFry -from .threefry32 import ThreeFry32 -from .xoroshiro128 import Xoroshiro128 -from .xorshift1024 import Xorshift1024 from .xoshiro256 import Xoshiro256 from .xoshiro512 import Xoshiro512 @@ -15,9 +12,6 @@ 'DSFMT': DSFMT, 'Philox': Philox, 'ThreeFry': ThreeFry, - 'ThreeFry32': ThreeFry32, - 'Xorshift1024': Xorshift1024, - 'Xoroshiro128': Xoroshiro128, 'Xoshiro256': Xoshiro256, 'Xoshiro512': Xoshiro512, } diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 6cba3c3c71c6..331d634d62ee 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -6,7 +6,7 @@ import warnings import numpy as np from .bounded_integers import _integers_types -from .xoroshiro128 import Xoroshiro128 +from .xoshiro256 import Xoshiro256 from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer from cpython cimport (Py_INCREF, PyFloat_AsDouble) @@ -45,7 +45,7 @@ cdef class Generator: ---------- bit_generator : BitGenerator, optional BitGenerator to use as the core generator. If none is provided, uses - Xoroshiro128. + Xoshiro256. Notes ----- @@ -77,7 +77,7 @@ cdef class Generator: def __init__(self, bit_generator=None): if bit_generator is None: - bit_generator = Xoroshiro128() + bit_generator = Xoshiro256() self._bit_generator = bit_generator capsule = bit_generator.capsule diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 30dfcdb0f1e5..31feddb29617 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -123,10 +123,7 @@ def generate_libraries(ext, build_dir): depends=['%s.pyx' % gen], define_macros=defs, ) - for gen in ['philox', 'threefry', 'threefry32', - 'xoroshiro128', 'xorshift1024', 'xoshiro256', - 'xoshiro512', - ]: + for gen in ['philox', 'threefry', 'xoshiro256', 'xoshiro512']: # gen.pyx, src/gen/gen.c config.add_extension(gen, sources=['{0}.c'.format(gen), 'src/{0}/{0}.c'.format(gen)], diff --git a/numpy/random/src/threefry32/LICENSE.md b/numpy/random/src/threefry32/LICENSE.md deleted file mode 100644 index 591cd75f4e79..000000000000 --- a/numpy/random/src/threefry32/LICENSE.md +++ /dev/null @@ -1,31 +0,0 @@ -# THREEFRY32 - -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/threefry32/threefry32-test-data-gen.c b/numpy/random/src/threefry32/threefry32-test-data-gen.c deleted file mode 100644 index 0e62299957b1..000000000000 --- a/numpy/random/src/threefry32/threefry32-test-data-gen.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Generate testing csv files - * - * cl threefry32-test-data-gen.c /Ox ../splitmix64/splitmix64.c /Ox - * threefry32-test-data-gen.exe - * - * gcc threefry32-test-data-gen.c ../splitmix64/splitmix64.c /Ox -o - * threefry32-test-data-gen - * ./threefry32-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/threefry.h" -#include -#include - -#define N 1000 - -int main() { - threefry4x32_key_t ctr = {{0, 0, 0, 0}}; - uint64_t state, seed = 0xDEADBEAF; - state = seed; - threefry4x32_ctr_t key = {{0}}; - threefry4x32_ctr_t out; - uint64_t store[N]; - uint64_t seed_val; - int i, j; - for (i = 0; i < 4; i++) { - seed_val = splitmix64_next(&state); - key.v[2*i] = (uint32_t)seed_val; - key.v[2*i+1] = (uint32_t)(seed_val >> 32); - } - for (i = 0; i < N / 4UL; i++) { - ctr.v[0]++; - out = threefry4x32_R(threefry4x32_rounds, ctr, key); - for (j = 0; j < 4; j++) { - store[i * 4 + j] = out.v[j]; - } - } - - FILE *fp; - fp = fopen("threefry32-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 < 4; i++) { - seed_val = splitmix64_next(&state); - key.v[2*i] = (uint32_t)seed_val; - key.v[2*i+1] = (uint32_t)(seed_val >> 32); - } - for (i = 0; i < N / 4; i++) { - ctr.v[0]++; - out = threefry4x32_R(threefry4x32_rounds, ctr, key); - for (j = 0; j < 4; j++) { - store[i * 4 + j] = out.v[j]; - } - } - - fp = fopen("threefry32-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/threefry32/threefry32.c b/numpy/random/src/threefry32/threefry32.c deleted file mode 100644 index cc6890f2eeab..000000000000 --- a/numpy/random/src/threefry32/threefry32.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "threefry32.h" - -extern NPY_INLINE uint64_t threefry32_next64(threefry32_state *state); - -extern NPY_INLINE uint32_t threefry32_next32(threefry32_state *state); - -extern void threefry32_jump(threefry32_state *state) { - /* Advances state as-if 2^64 draws were made */ - state->ctr->v[2]++; - if (state->ctr->v[2] == 0) { - state->ctr->v[3]++; - } -} - -extern void threefry32_advance(uint32_t *step, threefry32_state *state) { - int i, carry = 0; - uint32_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/threefry32/threefry32.h b/numpy/random/src/threefry32/threefry32.h deleted file mode 100644 index ebedee8043a0..000000000000 --- a/numpy/random/src/threefry32/threefry32.h +++ /dev/null @@ -1,832 +0,0 @@ -/* -Adapted from random123's threefry.h -*/ -#ifndef _RANDOMDGEN__THREEFRY32_H_ -#define _RANDOMDGEN__THREEFRY32_H_ - -#include -#include "numpy/npy_common.h" - -#define THREEFRY_BUFFER_SIZE 4L - -static NPY_INLINE uint32_t RotL_32(uint32_t x, unsigned int N); -static NPY_INLINE uint32_t RotL_32(uint32_t x, unsigned int N) { - return (x << (N & 31)) | (x >> ((32 - N) & 31)); -} - -struct r123array4x32 { - uint32_t v[4]; -}; - -enum r123_enum_threefry32x4 { - - R_32x4_0_0 = 10, - R_32x4_0_1 = 26, - R_32x4_1_0 = 11, - R_32x4_1_1 = 21, - R_32x4_2_0 = 13, - R_32x4_2_1 = 27, - R_32x4_3_0 = 23, - R_32x4_3_1 = 5, - R_32x4_4_0 = 6, - R_32x4_4_1 = 20, - R_32x4_5_0 = 17, - R_32x4_5_1 = 11, - R_32x4_6_0 = 25, - R_32x4_6_1 = 10, - R_32x4_7_0 = 18, - R_32x4_7_1 = 20 - -}; - -typedef struct r123array4x32 threefry4x32_ctr_t; -typedef struct r123array4x32 threefry4x32_key_t; -typedef struct r123array4x32 threefry4x32_ukey_t; -static NPY_INLINE threefry4x32_key_t threefry4x32keyinit(threefry4x32_ukey_t uk) { - return uk; -}; -static NPY_INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, - threefry4x32_ctr_t in, - threefry4x32_key_t k); -static NPY_INLINE threefry4x32_ctr_t threefry4x32_R(unsigned int Nrounds, - threefry4x32_ctr_t in, - threefry4x32_key_t k) { - threefry4x32_ctr_t X; - uint32_t ks[4 + 1]; - int i; - ks[4] = 0x1BD11BDA; - for (i = 0; i < 4; i++) { - ks[i] = k.v[i]; - X.v[i] = in.v[i]; - ks[4] ^= k.v[i]; - } - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - if (Nrounds > 0) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 1) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 2) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 3) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 3) { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 1; - } - if (Nrounds > 4) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 5) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 6) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 7) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 7) { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 2; - } - if (Nrounds > 8) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 9) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 10) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 11) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 11) { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 3; - } - if (Nrounds > 12) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 13) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 14) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 15) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 15) { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 4; - } - if (Nrounds > 16) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 17) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 18) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 19) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 19) { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 5; - } - if (Nrounds > 20) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 21) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 22) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 23) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 23) { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 6; - } - if (Nrounds > 24) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 25) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 26) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 27) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 27) { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 7; - } - if (Nrounds > 28) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 29) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 30) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 31) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 31) { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 8; - } - if (Nrounds > 32) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 33) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 34) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 35) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 35) { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 9; - } - if (Nrounds > 36) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 37) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 38) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 39) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 39) { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 10; - } - if (Nrounds > 40) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 41) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 42) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 43) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 43) { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 11; - } - if (Nrounds > 44) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 45) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 46) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 47) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 47) { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 12; - } - if (Nrounds > 48) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 49) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 50) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 51) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 51) { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 13; - } - if (Nrounds > 52) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 53) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 54) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 55) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 55) { - X.v[0] += ks[4]; - X.v[1] += ks[0]; - X.v[2] += ks[1]; - X.v[3] += ks[2]; - X.v[4 - 1] += 14; - } - if (Nrounds > 56) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 57) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 58) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 59) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 59) { - X.v[0] += ks[0]; - X.v[1] += ks[1]; - X.v[2] += ks[2]; - X.v[3] += ks[3]; - X.v[4 - 1] += 15; - } - if (Nrounds > 60) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 61) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 62) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 63) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 63) { - X.v[0] += ks[1]; - X.v[1] += ks[2]; - X.v[2] += ks[3]; - X.v[3] += ks[4]; - X.v[4 - 1] += 16; - } - if (Nrounds > 64) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_0_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_0_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 65) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_1_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_1_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 66) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_2_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_2_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 67) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_3_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_3_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 67) { - X.v[0] += ks[2]; - X.v[1] += ks[3]; - X.v[2] += ks[4]; - X.v[3] += ks[0]; - X.v[4 - 1] += 17; - } - if (Nrounds > 68) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_4_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_4_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 69) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_5_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_5_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 70) { - X.v[0] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_6_0); - X.v[1] ^= X.v[0]; - X.v[2] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_6_1); - X.v[3] ^= X.v[2]; - } - if (Nrounds > 71) { - X.v[0] += X.v[3]; - X.v[3] = RotL_32(X.v[3], R_32x4_7_0); - X.v[3] ^= X.v[0]; - X.v[2] += X.v[1]; - X.v[1] = RotL_32(X.v[1], R_32x4_7_1); - X.v[1] ^= X.v[2]; - } - if (Nrounds > 71) { - X.v[0] += ks[3]; - X.v[1] += ks[4]; - X.v[2] += ks[0]; - X.v[3] += ks[1]; - X.v[4 - 1] += 18; - } - return X; -} -enum r123_enum_threefry4x32 { threefry4x32_rounds = 20 }; -static NPY_INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, - threefry4x32_key_t k); -static NPY_INLINE threefry4x32_ctr_t threefry4x32(threefry4x32_ctr_t in, - threefry4x32_key_t k) { - return threefry4x32_R(threefry4x32_rounds, in, k); -} - -typedef struct s_threefry32_state { - threefry4x32_key_t *ctr; - threefry4x32_ctr_t *key; - int buffer_pos; - uint32_t buffer[THREEFRY_BUFFER_SIZE]; -} threefry32_state; - -static NPY_INLINE uint32_t threefry32_next(threefry32_state *state) { - int i; - threefry4x32_ctr_t ct; - uint32_t out; - if (state->buffer_pos < THREEFRY_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 = threefry4x32_R(threefry4x32_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 threefry32_next64(threefry32_state *state) { - return ((uint64_t)threefry32_next(state) << 32) | threefry32_next(state); -} - -static NPY_INLINE uint32_t threefry32_next32(threefry32_state *state) { - return threefry32_next(state); -} - -static NPY_INLINE double threefry32_next_double(threefry32_state *state) { - int32_t a = threefry32_next(state) >> 5, b = threefry32_next(state) >> 6; - return (a * 67108864.0 + b) / 9007199254740992.0; -} - -extern void threefry32_jump(threefry32_state *state); - -extern void threefry32_advance(uint32_t *step, threefry32_state *state); - -#endif diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 4a95dfca6cd4..ca6dbb58dd2a 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -3,13 +3,12 @@ from os.path import join import numpy as np -from numpy.testing import assert_equal, assert_allclose, assert_array_equal, \ - assert_raises +from numpy.testing import (assert_equal, assert_allclose, assert_array_equal, + assert_raises) import pytest -from numpy.random import Generator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ - Philox, Xoroshiro128, Xorshift1024, Xoshiro256, \ - Xoshiro512, RandomState +from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, + Philox, Xoshiro256, Xoshiro512, RandomState) from numpy.random.common import interface try: @@ -311,21 +310,6 @@ def test_getstate(self): assert_state_equal(state, alt_state) -class TestXoroshiro128(Base): - @classmethod - def setup_class(cls): - cls.bit_generator = Xoroshiro128 - cls.bits = 64 - cls.dtype = np.uint64 - cls.data1 = cls._read_csv( - join(pwd, './data/xoroshiro128-testset-1.csv')) - cls.data2 = cls._read_csv( - join(pwd, './data/xoroshiro128-testset-2.csv')) - cls.seed_error_type = TypeError - cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] - cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] - - class TestXoshiro256(Base): @classmethod def setup_class(cls): @@ -356,21 +340,6 @@ def setup_class(cls): cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] -class TestXorshift1024(Base): - @classmethod - def setup_class(cls): - cls.bit_generator = Xorshift1024 - cls.bits = 64 - cls.dtype = np.uint64 - cls.data1 = cls._read_csv( - join(pwd, './data/xorshift1024-testset-1.csv')) - cls.data2 = cls._read_csv( - join(pwd, './data/xorshift1024-testset-2.csv')) - cls.seed_error_type = TypeError - cls.invalid_seed_types = [('apple',), (2 + 3j,), (3.1,)] - cls.invalid_seed_values = [(-2,), (np.empty((2, 2), dtype=np.int64),)] - - class TestThreeFry(Base): @classmethod def setup_class(cls): @@ -551,24 +520,3 @@ def test_buffer_reset(self): assert rs.bit_generator.state['buffer_loc'] != 382 rs.bit_generator.seed(*self.data1['seed']) assert rs.bit_generator.state['buffer_loc'] == 382 - - -class TestThreeFry32(Base): - @classmethod - def setup_class(cls): - cls.bit_generator = ThreeFry32 - cls.bits = 32 - cls.dtype = np.uint32 - cls.data1 = cls._read_csv(join(pwd, './data/threefry32-testset-1.csv')) - cls.data2 = cls._read_csv(join(pwd, './data/threefry32-testset-2.csv')) - cls.seed_error_type = TypeError - cls.invalid_seed_types = [] - cls.invalid_seed_values = [(1, None, 1), (-1,), (2 ** 257 + 1,), - (None, None, 2 ** 129 + 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) diff --git a/numpy/random/tests/test_smoke.py b/numpy/random/tests/test_smoke.py index 4bfa0ae6e975..ca5fde500de8 100644 --- a/numpy/random/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -8,9 +8,8 @@ import pytest from numpy.testing import (assert_almost_equal, assert_equal, assert_, assert_array_equal, suppress_warnings) -from numpy.random import (Generator, MT19937, DSFMT, ThreeFry32, ThreeFry, - Philox, Xoroshiro128, Xorshift1024, Xoshiro256, - Xoshiro512, entropy) +from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, + Philox, Xoshiro256, Xoshiro512, entropy) @pytest.fixture(scope='module', @@ -804,18 +803,6 @@ def setup_class(cls): cls._extra_setup() -class TestXoroshiro128(RNG): - @classmethod - def setup_class(cls): - cls.bit_generator = Xoroshiro128 - 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() - - class TestXoshiro256(RNG): @classmethod def setup_class(cls): @@ -840,18 +827,6 @@ def setup_class(cls): cls._extra_setup() -class TestXorshift1024(RNG): - @classmethod - def setup_class(cls): - cls.bit_generator = Xorshift1024 - 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() - - class TestDSFMT(RNG): @classmethod def setup_class(cls): @@ -864,19 +839,6 @@ def setup_class(cls): cls.seed_vector_bits = 32 -class TestThreeFry32(RNG): - @classmethod - def setup_class(cls): - cls.bit_generator = ThreeFry32 - cls.advance = 2**63 + 2**31 + 2**15 + 1 - 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 = 64 - cls._extra_setup() - cls.seed_error = ValueError - - class TestEntropy(object): def test_entropy(self): e1 = entropy.random_entropy() diff --git a/numpy/random/threefry32.pyx b/numpy/random/threefry32.pyx deleted file mode 100644 index 2e2b32bfede6..000000000000 --- a/numpy/random/threefry32.pyx +++ /dev/null @@ -1,454 +0,0 @@ -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -import numpy as np -from cpython.pycapsule cimport PyCapsule_New -from libc.stdlib cimport malloc, free - -from .common cimport * -from .distributions cimport bitgen_t -from .entropy import random_entropy, seed_by_array - -np.import_array() - -DEF THREEFRY_BUFFER_SIZE=4 - -cdef extern from 'src/threefry32/threefry32.h': - struct s_r123array4x32: - uint32_t v[4] - - ctypedef s_r123array4x32 r123array4x32 - - ctypedef r123array4x32 threefry4x32_key_t - ctypedef r123array4x32 threefry4x32_ctr_t - - struct s_threefry32_state: - threefry4x32_ctr_t *ctr - threefry4x32_key_t *key - int buffer_pos - uint32_t buffer[THREEFRY_BUFFER_SIZE] - - ctypedef s_threefry32_state threefry32_state - - uint64_t threefry32_next64(threefry32_state *state) nogil - uint32_t threefry32_next32(threefry32_state *state) nogil - double threefry32_next_double(threefry32_state *state) nogil - void threefry32_jump(threefry32_state *state) - void threefry32_advance(uint32_t *step, threefry32_state *state) - - -cdef uint64_t threefry32_uint64(void* st) nogil: - return threefry32_next64(st) - -cdef uint32_t threefry32_uint32(void *st) nogil: - return threefry32_next32( st) - -cdef double threefry32_double(void* st) nogil: - return threefry32_next_double(st) - -cdef uint64_t threefry32_raw(void *st) nogil: - return threefry32_next32( st) - -cdef class ThreeFry32: - """ - ThreeFry32(seed=None, counter=None, key=None) - - Container for the ThreeFry (4x32) pseudo-random number generator. - - Parameters - ---------- - seed : {None, int, array_like}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in - [0, 2**64-1] or ``None`` (the default). If `seed` is ``None``, - data will be read from ``/dev/urandom`` (or the Windows analog) - if available. If unavailable, a hash of the time and process ID is - used. - counter : {None, int, array_like}, optional - Counter to use in the ThreeFry32 state. Can be either - a Python int in [0, 2**128) or a 4-element uint32 array. - If not provided, the RNG is initialized at 0. - key : {None, int, array_like}, optional - Key to use in the ThreeFry32 state. Unlike seed, which is run through - another RNG before use, the value in key is directly set. Can be either - a Python int in [0, 2**128) or a 4-element uint32 array. - key and seed cannot both be used. - - Notes - ----- - ThreeFry32 is a 32-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. ``ThreeFry32`` - has a period of :math:`2^{128} - 1` and supports arbitrary advancing and - jumping the sequence in increments of :math:`2^{64}`. These features allow - multiple non-overlapping sequences to be generated. - - ``ThreeFry32`` 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. - - See ``TheeFry`` and ``Philox`` closely related PRNG implementations. - - **State and Seeding** - - The ``ThreeFry32`` state vector consists of a 2 128-bit values encoded as - 4-element uint32 arrays. One is a counter which is incremented by 1 for - every 4 32-bit randoms produced. The second is a key which determined - the sequence produced. Using different keys produces independent - sequences. - - ``ThreeFry32`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the input seed is - used as an input (or inputs) for a second random number generator, - SplitMix64, and the output of this PRNG function is used as the initial - state. Using a single 64-bit value for the seed can only initialize a small - range of the possible initial state values. When using an array, the - SplitMix64 state for producing the ith component of the initial state is - XORd with the ith value of the seed array until the seed array is - exhausted. When using an array the initial state for the SplitMix64 state - is 0 so that using a single element array and using the same value as a - scalar will produce the same initial state. - - **Parallel Features** - - ``ThreeFry32`` can be used in parallel applications by calling the - ``jumped`` method to advances the state as-if :math:`2^{64}` random - numbers have been generated. Alternatively, ``advance`` can be used to - advance the counter for any positive step in [0, 2**128). When using - ``jumped``, all generators should be chained to ensure that the segments - come from the same sequence. - - >>> from numpy.random import Generator, ThreeFry32 - >>> bit_generator = ThreeFry32(1234) - >>> rg = [] - >>> for _ in range(10): - ... rg.append(Generator(bit_generator)) - ... # Chain the BitGenerators - ... bit_generator = bit_generator.jumped() - - Alternatively, ``ThreeFry32`` can be used in parallel applications by using - a sequence of distinct keys where each instance uses different key. - - >>> key = 2**65 + 2**33 + 2**17 + 2**9 - >>> rg = [Generator(ThreeFry32(key=key+i)) for i in range(10)] - - **Compatibility Guarantee** - - ``ThreeFry32`` makes a guarantee that a fixed seed and will always produce - the same random integer stream. - - Examples - -------- - >>> from numpy.random import Generator, ThreeFry32 - >>> rg = Generator(ThreeFry32(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 threefry32_state rng_state - cdef threefry4x32_ctr_t threefry_ctr - cdef threefry4x32_key_t threefry_key - cdef bitgen_t _bitgen - cdef public object capsule - cdef object _ctypes - cdef object _cffi - cdef public object lock - - def __init__(self, seed=None, counter=None, key=None): - self.rng_state.ctr = &self.threefry_ctr - self.rng_state.key = &self.threefry_key - self.seed(seed, counter, key) - self.lock = Lock() - - self._bitgen.state = &self.rng_state - self._bitgen.next_uint64 = &threefry32_uint64 - self._bitgen.next_uint32 = &threefry32_uint32 - self._bitgen.next_double = &threefry32_double - self._bitgen.next_raw = &threefry32_raw - - self._ctypes = None - self._cffi = None - - cdef const char *name = 'BitGenerator' - self.capsule = PyCapsule_New(&self._bitgen, name, NULL) - - # 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 - - cdef _reset_state_variables(self): - self.rng_state.buffer_pos = THREEFRY_BUFFER_SIZE - for i in range(THREEFRY_BUFFER_SIZE): - self.rng_state.buffer[i] = 0 - - 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'): - return benchmark(&self._bitgen, self.lock, cnt, method) - - def seed(self, seed=None, counter=None, key=None): - """ - seed(seed=None, counter=None, key=None) - - Seed the generator. - - This method is called when ``ThreeFry32`` is initialized. It can be - called again to re-seed the generator. For details, see - ``ThreeFry32``. - - Parameters - ---------- - seed : int, optional - Seed for ``ThreeFry32``. - counter : {int array}, optional - Positive integer less than 2**128 containing the counter position - or a 4 element array of uint32 containing the counter - key : {int, array}, options - Positive integer less than 2**128 containing the key - or a 4 element array of uint32 containing the key - - Raises - ------ - ValueError - If values are out of range for the PRNG. - - Notes - ----- - The two representation of the counter and key are related through - array[i] = (value // 2**(32*i)) % 2**32. - """ - if seed is not None and key is not None: - raise ValueError('seed and key cannot be both used') - if key is None: - if seed is None: - try: - state = random_entropy(4) - except RuntimeError: - state = random_entropy(4, 'fallback') - else: - state = seed_by_array(seed, 2) - state = state.view(np.uint32) - for i in range(4): - self.rng_state.key.v[i] = state[i] - else: - key = int_to_array(key, 'key', 128, 32) - for i in range(4): - self.rng_state.key.v[i] = key[i] - - counter = 0 if counter is None else counter - counter = int_to_array(counter, 'counter', 128, 32) - for i in range(4): - self.rng_state.ctr.v[i] = counter[i] - - self._reset_state_variables() - - @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.uint32) - key = np.empty(4, dtype=np.uint32) - buffer = np.empty(THREEFRY_BUFFER_SIZE, dtype=np.uint32) - for i in range(4): - ctr[i] = self.rng_state.ctr.v[i] - key[i] = self.rng_state.key.v[i] - for i in range(THREEFRY_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} - - @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] = value['state']['counter'][i] - self.rng_state.key.v[i] = value['state']['key'][i] - for i in range(THREEFRY_BUFFER_SIZE): - self.rng_state.buffer[i] = value['buffer'][i] - self.rng_state.buffer_pos = value['buffer_pos'] - - cdef jump_inplace(self, np.npy_intp 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 * 2 ** 64) - - def jumped(self, np.npy_intp iter=1): - """ - jumped(iter=1) - - Returns a new bit generator with the state jumped - - The state of the returned big generator is jumped as-if - 2**(64 * iter) random numbers have been generated. - - Parameters - ---------- - iter : integer, positive - Number of times to jump the state of the bit generator returned - - Returns - ------- - bit_generator : Xoroshiro128 - New instance of generator jumped iter times - """ - cdef ThreeFry32 bit_generator - - bit_generator = self.__class__() - bit_generator.state = self.state - bit_generator.jump_inplace(iter) - - 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 : ThreeFry32 - 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. - """ - cdef np.ndarray delta_a - delta_a = int_to_array(delta, 'step', 128, 32) - threefry32_advance( delta_a.data, &self.rng_state) - self._reset_state_variables() - return self - - @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 BitGenerator 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 BitGenerator struct - """ - if self._cffi is not None: - return self._cffi - self._cffi = prepare_cffi(&self._bitgen) - return self._cffi diff --git a/numpy/random/xoroshiro128.pyx b/numpy/random/xoroshiro128.pyx deleted file mode 100644 index 5d4fda90a988..000000000000 --- a/numpy/random/xoroshiro128.pyx +++ /dev/null @@ -1,342 +0,0 @@ -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -from libc.string cimport memcpy -from cpython.pycapsule cimport PyCapsule_New - -import numpy as np -cimport numpy as np - -from .common cimport * -from .distributions cimport bitgen_t -from .entropy import random_entropy, seed_by_array - -np.import_array() - -cdef extern from "src/xoroshiro128/xoroshiro128.h": - - struct s_xoroshiro128_state: - uint64_t s[2] - int has_uint32 - uint32_t uinteger - - ctypedef s_xoroshiro128_state xoroshiro128_state - - uint64_t xoroshiro128_next64(xoroshiro128_state *state) nogil - uint32_t xoroshiro128_next32(xoroshiro128_state *state) nogil - void xoroshiro128_jump(xoroshiro128_state *state) - -cdef uint64_t xoroshiro128_uint64(void* st) nogil: - return xoroshiro128_next64(st) - -cdef uint32_t xoroshiro128_uint32(void *st) nogil: - return xoroshiro128_next32( st) - -cdef double xoroshiro128_double(void* st) nogil: - return uint64_to_double(xoroshiro128_next64(st)) - -cdef class Xoroshiro128: - """ - Xoroshiro128(seed=None) - - Container for the xoroshiro128+ pseudo-random number generator. - - Parameters - ---------- - seed : {None, int, array_like}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] - or ``None`` (the default). If `seed` is ``None``, then data is read - from ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a hash of the time and process ID is used. - - Notes - ----- - xoroshiro128+ is the successor to xorshift128+ written by David Blackman - and Sebastiano Vigna. It is a 64-bit PRNG that uses a carefully - handcrafted shift/rotate-based linear transformation. This change both - improves speed and statistical quality of the PRNG [1]_. xoroshiro128+ has - a period of :math:`2^{128} - 1` and supports jumping the sequence in - increments of :math:`2^{64}`, which allows multiple non-overlapping - sequences to be generated. - - ``Xoroshiro128`` 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. - - See ``Xorshift1024`` for a related PRNG with a larger - period (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). - - **State and Seeding** - - The ``Xoroshiro128`` state vector consists of a 2-element array of 64-bit - unsigned integers. - - ``Xoroshiro128`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the seed is - used as an input for another simple random number generator, - SplitMix64, and the output of this PRNG function is used as the initial state. - Using a single 64-bit value for the seed can only initialize a small range of - the possible initial state values. - - **Parallel Features** - - ``Xoroshiro128`` can be used in parallel applications by calling the method - ``jumped`` which advances the state as-if :math:`2^{64}` random numbers - have been generated. 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, Xoroshiro128 - >>> bit_generator = Xoroshiro128(1234) - >>> rg = [] - >>> for _ in range(10): - ... rg.append(Generator(bit_generator)) - ... # Chain the BitGenerators - ... bit_generator = bit_generator.jumped() - - **Compatibility Guarantee** - - ``Xoroshiro128`` makes a guarantee that a fixed seed will always - produce the same random integer stream. - - Examples - -------- - >>> from numpy.random import Generator, Xoroshiro128 - >>> rg = Generator(Xoroshiro128(1234)) - >>> rg.standard_normal() - 0.123 # random - - References - ---------- - .. [1] "xoroshiro+ / xorshift* / xorshift+ generators and the PRNG shootout", - http://xorshift.di.unimi.it/ - """ - cdef xoroshiro128_state rng_state - cdef bitgen_t _bitgen - cdef public object capsule - cdef object _ctypes - cdef object _cffi - cdef public object lock - - def __init__(self, seed=None): - self.seed(seed) - self.lock = Lock() - - self._bitgen.state = &self.rng_state - self._bitgen.next_uint64 = &xoroshiro128_uint64 - self._bitgen.next_uint32 = &xoroshiro128_uint32 - self._bitgen.next_double = &xoroshiro128_double - self._bitgen.next_raw = &xoroshiro128_uint64 - - self._ctypes = None - self._cffi = None - - cdef const char *name = "BitGenerator" - self.capsule = PyCapsule_New(&self._bitgen, name, NULL) - - # 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 - - cdef _reset_state_variables(self): - self.rng_state.has_uint32 = 0 - self.rng_state.uinteger = 0 - - 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'): - return benchmark(&self._bitgen, self.lock, cnt, method) - - def seed(self, seed=None): - """ - seed(seed=None) - - Seed the generator. - - This method is called at initialized. It can be - called again to re-seed the generator. - - Parameters - ---------- - seed : {int, ndarray}, optional - Seed for PRNG. Can be a single 64 biy unsigned integer or an array - of 64 bit unsigned integers. - - Raises - ------ - ValueError - If seed values are out of range for the PRNG. - """ - ub = 2 ** 64 - if seed is None: - try: - state = random_entropy(4) - except RuntimeError: - state = random_entropy(4, 'fallback') - state = state.view(np.uint64) - else: - state = seed_by_array(seed, 2) - self.rng_state.s[0] = int(state[0]) - self.rng_state.s[1] = int(state[1]) - self._reset_state_variables() - - cdef jump_inplace(self, np.npy_intp 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): - xoroshiro128_jump(&self.rng_state) - self._reset_state_variables() - - def jumped(self, np.npy_intp iter=1): - """ - jumped(iter=1) - - Returns a new bit generator with the state jumped - - The state of the returned big generator is jumped as-if - 2**(64 * iter) random numbers have been generated. - - Parameters - ---------- - iter : integer, positive - Number of times to jump the state of the bit generator returned - - Returns - ------- - bit_generator : Xoroshiro128 - New instance of generator jumped iter times - """ - cdef Xoroshiro128 bit_generator - - bit_generator = self.__class__() - bit_generator.state = self.state - bit_generator.jump_inplace(iter) - - 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 - """ - state = np.empty(2, dtype=np.uint64) - state[0] = self.rng_state.s[0] - state[1] = self.rng_state.s[1] - return {'bit_generator': self.__class__.__name__, - 's': state, - '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__)) - self.rng_state.s[0] = value['s'][0] - self.rng_state.s[1] = value['s'][1] - self.rng_state.has_uint32 = value['has_uint32'] - self.rng_state.uinteger = value['uinteger'] - - @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 not None: - return self._cffi - self._cffi = prepare_cffi(&self._bitgen) - return self._cffi diff --git a/numpy/random/xorshift1024.pyx b/numpy/random/xorshift1024.pyx deleted file mode 100644 index ad7debe308c5..000000000000 --- a/numpy/random/xorshift1024.pyx +++ /dev/null @@ -1,349 +0,0 @@ -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock - -from libc.string cimport memcpy -from cpython.pycapsule cimport PyCapsule_New - -import numpy as np -cimport numpy as np - -from .common cimport * -from .distributions cimport bitgen_t -from .entropy import random_entropy, seed_by_array - -np.import_array() - -cdef extern from "src/xorshift1024/xorshift1024.h": - - struct s_xorshift1024_state: - uint64_t s[16] - int p - int has_uint32 - uint32_t uinteger - - ctypedef s_xorshift1024_state xorshift1024_state - - uint64_t xorshift1024_next64(xorshift1024_state *state) nogil - uint32_t xorshift1024_next32(xorshift1024_state *state) nogil - void xorshift1024_jump(xorshift1024_state *state) - -cdef uint64_t xorshift1024_uint64(void* st) nogil: - return xorshift1024_next64(st) - -cdef uint32_t xorshift1024_uint32(void *st) nogil: - return xorshift1024_next32( st) - -cdef double xorshift1024_double(void* st) nogil: - return uint64_to_double(xorshift1024_next64(st)) - -cdef class Xorshift1024: - u""" - Xorshift1024(seed=None) - - Container for the xorshift1024*φ pseudo-random number generator. - - Parameters - ---------- - seed : {None, int, array_like}, optional - Random seed initializing the pseudo-random number generator. - Can be an integer in [0, 2**64-1], array of integers in [0, 2**64-1] - or ``None`` (the default). If `seed` is ``None``, then data is read - from ``/dev/urandom`` (or the Windows analog) if available. If - unavailable, a hash of the time and process ID is used. - - Notes - ----- - xorshift1024*φ is a 64-bit implementation of Saito and Matsumoto's XSadd - generator [1]_ (see also [2]_, [3]_, [4]_). xorshift1024*φ has a period of - :math:`2^{1024} - 1` and supports jumping the sequence in increments of - :math:`2^{512}`, which allows multiple non-overlapping sequences to be - generated. - - ``Xorshift1024`` 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. - - See ``Xoroshiro128`` for a faster bit generator that has a smaller period. - - **State and Seeding** - - The ``Xoroshiro128`` state vector consists of a 16-element array of 64-bit - unsigned integers. - - ``Xoroshiro1024`` is seeded using either a single 64-bit unsigned integer - or a vector of 64-bit unsigned integers. In either case, the seed is - used as an input for another simple random number generator, - SplitMix64, and the output of this PRNG function is used as the initial - state. Using a single 64-bit value for the seed can only initialize a - small range of the possible initial state values. - - **Parallel Features** - - ``Xoroshiro1024`` can be used in parallel applications by calling the - method ``jumped`` which advances the state as-if :math:`2^{512}` random - numbers have been generated. 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, Xorshift1024 - >>> bit_generator = Xorshift1024(1234) - >>> rg = [] - >>> for _ in range(10): - ... rg.append(Generator(bit_generator)) - ... # Chain the BitGenerators - ... bit_generator = bit_generator.jumped() - - **Compatibility Guarantee** - - ``Xorshift1024`` makes a guarantee that a fixed seed will always - produce the same random integer stream. - - Examples - -------- - >>> from numpy.random import Generator, Xorshift1024 - >>> rg = Generator(Xorshift1024(1234)) - >>> rg.standard_normal() - 0.123 # random - - References - ---------- - .. [1] "xorshift*/xorshift+ generators and the PRNG shootout", - http://xorshift.di.unimi.it/ - .. [2] Marsaglia, George. "Xorshift RNGs." Journal of Statistical Software - [Online], 8.14, pp. 1 - 6, .2003. - .. [3] Sebastiano Vigna. "An experimental exploration of Marsaglia's xorshift - generators, scrambled." CoRR, abs/1402.6246, 2014. - .. [4] Sebastiano Vigna. "Further scramblings of Marsaglia's xorshift - generators." CoRR, abs/1403.0930, 2014. - """ - - cdef xorshift1024_state rng_state - cdef bitgen_t _bitgen - cdef public object capsule - cdef object _ctypes - cdef object _cffi - cdef public object lock - - def __init__(self, seed=None): - self.seed(seed) - self.lock = Lock() - - self._bitgen.state = &self.rng_state - self._bitgen.next_uint64 = &xorshift1024_uint64 - self._bitgen.next_uint32 = &xorshift1024_uint32 - self._bitgen.next_double = &xorshift1024_double - self._bitgen.next_raw = &xorshift1024_uint64 - - self._ctypes = None - self._cffi = None - - cdef const char *name = "BitGenerator" - self.capsule = PyCapsule_New(&self._bitgen, name, NULL) - - # 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 - - cdef _reset_state_variables(self): - self.rng_state.has_uint32 = 0 - self.rng_state.uinteger = 0 - - 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'): - return benchmark(&self._bitgen, self.lock, cnt, method) - - def seed(self, seed=None): - """ - seed(seed=None, stream=None) - - Seed the generator. - - This method is called when ``Xorshift1024`` is initialized. It can be - called again to re-seed the generator. For details, see - ``Xorshift1024``. - - Parameters - ---------- - seed : int, optional - Seed for ``Xorshift1024``. - - Raises - ------ - ValueError - If seed values are out of range for the PRNG. - - """ - ub = 2 ** 64 - if seed is None: - try: - state = random_entropy(32) - except RuntimeError: - state = random_entropy(32, 'fallback') - state = state.view(np.uint64) - else: - state = seed_by_array(seed, 16) - for i in range(16): - self.rng_state.s[i] = int(state[i]) - self.rng_state.p = 0 - self._reset_state_variables() - - cdef jump_inplace(self, np.npy_intp 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): - xorshift1024_jump(&self.rng_state) - self._reset_state_variables() - - def jumped(self, np.npy_intp iter=1): - """ - jumped(iter=1) - - Returns a new bit generator with the state jumped - - The state of the returned big generator is jumped as-if - 2**(512 * iter) random numbers have been generated. - - Parameters - ---------- - iter : integer, positive - Number of times to jump the state of the bit generator returned - - Returns - ------- - bit_generator : Xoroshiro128 - New instance of generator jumped iter times - """ - cdef Xorshift1024 bit_generator - - bit_generator = self.__class__() - bit_generator.state = self.state - bit_generator.jump_inplace(iter) - - 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 - """ - s = np.empty(16, dtype=np.uint64) - for i in range(16): - s[i] = self.rng_state.s[i] - return {'bit_generator': self.__class__.__name__, - 'state': {'s': s, 'p': self.rng_state.p}, - '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(16): - self.rng_state.s[i] = value['state']['s'][i] - self.rng_state.p = value['state']['p'] - self.rng_state.has_uint32 = value['has_uint32'] - self.rng_state.uinteger = value['uinteger'] - - @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 not None: - return self._cffi - self._cffi = prepare_cffi(&self._bitgen) - return self._cffi From 4e6a812732b4c09b20354a47d488fbe384124827 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 23 May 2019 07:54:47 +0300 Subject: [PATCH 126/138] MAINT: remove pre-randomgen _mtrand --- numpy/random/_mtrand/Python.pxi | 43 - numpy/random/_mtrand/_mtrand.pyx | 5036 ------------------- numpy/random/_mtrand/distributions.c | 946 ---- numpy/random/_mtrand/distributions.h | 185 - numpy/random/_mtrand/initarray.c | 151 - numpy/random/_mtrand/initarray.h | 8 - numpy/random/_mtrand/mtrand_py_helper.h | 23 - numpy/random/_mtrand/numpy.pxd | 163 - numpy/random/_mtrand/randint_helpers.pxi.in | 77 - numpy/random/_mtrand/randomkit.c | 626 --- numpy/random/_mtrand/randomkit.h | 226 - numpy/random/setup.py | 13 - setup.py | 2 +- 13 files changed, 1 insertion(+), 7498 deletions(-) delete mode 100644 numpy/random/_mtrand/Python.pxi delete mode 100644 numpy/random/_mtrand/_mtrand.pyx delete mode 100644 numpy/random/_mtrand/distributions.c delete mode 100644 numpy/random/_mtrand/distributions.h delete mode 100644 numpy/random/_mtrand/initarray.c delete mode 100644 numpy/random/_mtrand/initarray.h delete mode 100644 numpy/random/_mtrand/mtrand_py_helper.h delete mode 100644 numpy/random/_mtrand/numpy.pxd delete mode 100644 numpy/random/_mtrand/randint_helpers.pxi.in delete mode 100644 numpy/random/_mtrand/randomkit.c delete mode 100644 numpy/random/_mtrand/randomkit.h diff --git a/numpy/random/_mtrand/Python.pxi b/numpy/random/_mtrand/Python.pxi deleted file mode 100644 index 08aadbaa1160..000000000000 --- 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/_mtrand.pyx b/numpy/random/_mtrand/_mtrand.pyx deleted file mode 100644 index 42e40e87e394..000000000000 --- a/numpy/random/_mtrand/_mtrand.pyx +++ /dev/null @@ -1,5036 +0,0 @@ -# cython: language_level=3 - -# 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" - -from libc cimport string - -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() - -cimport cython -import numpy as np -import operator -import warnings - -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 = np.empty(size, np.float64) - length = PyArray_SIZE(array) - array_data = 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 = np.empty(size, np.float64) - length = PyArray_SIZE(array) - array_data = 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 = PyArray_SimpleNew(PyArray_NDIM(oa), - PyArray_DIMS(oa) , NPY_DOUBLE) - length = PyArray_SIZE(array) - array_data = PyArray_DATA(array) - itera = PyArray_IterNew(oa) - with lock, nogil: - for i from 0 <= i < length: - array_data[i] = func(state, (PyArray_ITER_DATA(itera))[0]) - PyArray_ITER_NEXT(itera) - else: - array = np.empty(size, np.float64) - array_data = PyArray_DATA(array) - multi = PyArray_MultiIterNew(2, array, - 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 = 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 = np.empty(size, np.float64) - length = PyArray_SIZE(array) - array_data = 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 = np.broadcast(oa, ob) - array = np.empty(multi.shape, dtype=np.float64) - else: - array = np.empty(size, dtype=np.float64) - multi = np.broadcast(oa, ob, array) - if multi.shape != array.shape: - raise ValueError("size is not compatible with inputs") - - array_data = PyArray_DATA(array) - - with lock, nogil: - for i in range(multi.size): - oa_data = PyArray_MultiIter_DATA(multi, 0) - ob_data = 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 = np.empty(size, np.float64) - length = PyArray_SIZE(array) - array_data = 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 = np.broadcast(oa, ob, oc) - array = np.empty(multi.shape, dtype=np.float64) - else: - array = np.empty(size, dtype=np.float64) - multi = np.broadcast(oa, ob, oc, array) - if multi.shape != array.shape: - raise ValueError("size is not compatible with inputs") - - array_data = PyArray_DATA(array) - - with lock, nogil: - for i in range(multi.size): - oa_data = PyArray_MultiIter_DATA(multi, 0) - ob_data = PyArray_MultiIter_DATA(multi, 1) - oc_data = 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 = np.empty(size, int) - length = PyArray_SIZE(array) - array_data = 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 = np.empty(size, int) - length = PyArray_SIZE(array) - array_data = 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 = np.broadcast(on, op) - array = np.empty(multi.shape, dtype=int) - else: - array = np.empty(size, dtype=int) - multi = np.broadcast(on, op, array) - if multi.shape != array.shape: - raise ValueError("size is not compatible with inputs") - - array_data = PyArray_DATA(array) - - with lock, nogil: - for i in range(multi.size): - on_data = PyArray_MultiIter_DATA(multi, 0) - op_data = 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 = np.empty(size, int) - length = PyArray_SIZE(array) - array_data = 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 = np.broadcast(on, op) - array = np.empty(multi.shape, dtype=int) - else: - array = np.empty(size, dtype=int) - multi = np.broadcast(on, op, array) - if multi.shape != array.shape: - raise ValueError("size is not compatible with inputs") - - array_data = PyArray_DATA(array) - - with lock, nogil: - for i in range(multi.size): - on_data = PyArray_MultiIter_DATA(multi, 0) - op_data = 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 = np.empty(size, int) - length = PyArray_SIZE(array) - array_data = 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 = np.broadcast(on, om, oN) - array = np.empty(multi.shape, dtype=int) - else: - array = np.empty(size, dtype=int) - multi = np.broadcast(on, om, oN, array) - if multi.shape != array.shape: - raise ValueError("size is not compatible with inputs") - - array_data = PyArray_DATA(array) - - with lock, nogil: - for i in range(multi.size): - on_data = PyArray_MultiIter_DATA(multi, 0) - om_data = PyArray_MultiIter_DATA(multi, 1) - oN_data = 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 = np.empty(size, int) - length = PyArray_SIZE(array) - array_data = 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 = PyArray_SimpleNew(PyArray_NDIM(oa), - PyArray_DIMS(oa), NPY_LONG) - length = PyArray_SIZE(array) - array_data = PyArray_DATA(array) - itera = PyArray_IterNew(oa) - with lock, nogil: - for i from 0 <= i < length: - array_data[i] = func(state, (PyArray_ITER_DATA(itera))[0]) - PyArray_ITER_NEXT(itera) - else: - array = np.empty(size, int) - array_data = PyArray_DATA(array) - multi = PyArray_MultiIterNew(2, array, 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 = 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) -} - - -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. - - 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. - - Notes - ----- - The Python stdlib module "random" also contains a Mersenne Twister - pseudo-random number generator with a number of methods that are similar - to the ones available in `RandomState`. `RandomState`, besides being - NumPy-aware, has the advantage that it provides a much larger number - of probability distributions to choose from. - - """ - cdef rk_state *internal_state - cdef object lock - cdef object state_address - poisson_lam_max = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10 - - def __init__(self, seed=None): - self.internal_state = PyMem_Malloc(sizeof(rk_state)) - self.state_address = PyCapsule_New(self.internal_state, NULL, NULL) - self.lock = Lock() - self.seed(seed) - - def __dealloc__(self): - if self.internal_state != NULL: - PyMem_Free(self.internal_state) - self.internal_state = NULL - - def seed(self, seed=None): - """ - seed(seed=None) - - Seed the generator. - - 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. - - See Also - -------- - RandomState - - """ - 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, PyArray_DATA(obj), - PyArray_DIM(obj, 0)) - - def get_state(self): - """ - get_state() - - Return a tuple representing the internal state of the generator. - - For more details, see `set_state`. - - Returns - ------- - out : tuple(str, ndarray of 624 uints, int, int, float) - The returned tuple has the following items: - - 1. the string 'MT19937'. - 2. a 1-D array of 624 unsigned integer keys. - 3. an integer ``pos``. - 4. an integer ``has_gauss``. - 5. a float ``cached_gaussian``. - - See Also - -------- - set_state - - Notes - ----- - `set_state` and `get_state` are not needed to work with any of the - random distributions in NumPy. If the internal state is manually altered, - the user should know exactly what he/she is doing. - - """ - cdef ndarray state "arrayObject_state" - state = np.empty(624, np.uint) - with self.lock: - memcpy(PyArray_DATA(state), (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 = np.asarray(state, np.uint32) - return ('MT19937', state, pos, has_gauss, gauss) - - def set_state(self, state): - """ - set_state(state) - - 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. - - Parameters - ---------- - state : tuple(str, ndarray of 624 uints, int, int, float) - The `state` tuple has the following items: - - 1. the string 'MT19937', specifying the Mersenne Twister algorithm. - 2. a 1-D array of 624 unsigned integers ``keys``. - 3. an integer ``pos``. - 4. an integer ``has_gauss``. - 5. a float ``cached_gaussian``. - - Returns - ------- - out : None - Returns 'None' on success. - - See Also - -------- - get_state - - Notes - ----- - `set_state` and `get_state` are not needed to work with any of the - random distributions in NumPy. If the internal state is manually altered, - the user should know exactly what he/she is doing. - - For backwards compatibility, the form (str, array of 624 uints, int) is - also accepted although it is missing some information about the cached - Gaussian value: ``state = ('MT19937', keys, pos)``. - - References - ---------- - .. [1] M. Matsumoto and T. Nishimura, "Mersenne Twister: A - 623-dimensionally equidistributed uniform pseudorandom number - generator," *ACM Trans. on Modeling and Computer Simulation*, - 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 - else: - has_gauss, cached_gaussian = state[3:5] - try: - obj = PyArray_ContiguousFromObject(key, NPY_ULONG, 1, 1) - except TypeError: - # compatibility -- could be an older pickle - obj = PyArray_ContiguousFromObject(key, NPY_LONG, 1, 1) - if PyArray_DIM(obj, 0) != 624: - raise ValueError("state must be 624 longs") - with self.lock: - memcpy((self.internal_state.key), 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) - - def __reduce__(self): - return (np.random.__RandomState_ctor, (), self.get_state()) - - # Basic distributions: - def random_sample(self, size=None): - """ - random_sample(size=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_sample` by `(b-a)` and add `a`:: - - (b - a) * random_sample() + 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. - - 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 - -------- - >>> np.random.random_sample() - 0.47108547995356098 # random - >>> type(np.random.random_sample()) - - >>> np.random.random_sample((5,)) - 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], # random - [-2.99091858, -0.79479508], - [-1.23204345, -1.75224494]]) - - """ - return cont0_array(self.internal_state, rk_double, size, self.lock) - - def tomaxint(self, size=None): - """ - tomaxint(size=None) - - Return a sample of uniformly distributed random integers in the interval - [0, ``np.iinfo(np.int).max``]. The np.int type translates to the C long - integer type and its precision is platform dependent. - - 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 : ndarray - Drawn samples, with shape `size`. - - See Also - -------- - randint : Uniform sampling over a given half-open interval of integers. - random_integers : Uniform sampling over a given closed interval of - integers. - - Examples - -------- - >>> rs = np.random.RandomState() # need a RandomState object - >>> rs.tomaxint((2,2,2)) - array([[[1170048599, 1600360186], # random - [ 739731006, 1947757578]], - [[1871712945, 752307660], - [1601631370, 1479324245]]]) - >>> np.iinfo(np.int).max - 2147483647 - >>> 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) - - def randint(self, low, high=None, size=None, dtype=int): - """ - randint(low, high=None, size=None, dtype='l') - - Return random integers from `low` (inclusive) to `high` (exclusive). - - Return random integers from the "discrete uniform" distribution of - the specified dtype in the "half-open" interval [`low`, `high`). If - `high` is None (the default), then results are from [0, `low`). - - Parameters - ---------- - low : int - Lowest (signed) integer to be drawn from the distribution (unless - ``high=None``, in which case this parameter is one above the - *highest* such integer). - high : int, optional - If provided, one above the largest (signed) integer to be drawn - from the distribution (see above for behavior if ``high=None``). - size : int or tuple of ints, optional - Output shape. 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. 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'. - - .. versionadded:: 1.11.0 - - 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. - - See Also - -------- - 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. - - Examples - -------- - >>> np.random.randint(2, size=10) - 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], # random - [3, 2, 2, 0]]) - - """ - 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) - - return ret - - def bytes(self, 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.bytes(10) - ' 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 - - - def choice(self, a, size=None, replace=True, p=None): - """ - choice(a, size=None, replace=True, p=None) - - Generates a random sample from a given 1-D array - - .. 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) - 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. - 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. - - 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 - probabilities, if a and p have different lengths, or if - replace=False and the sample size is greater than the population - 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]) # 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]) # 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]) # 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]) # 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'], # random - dtype='PyArray_ContiguousFromObject(p, NPY_DOUBLE, 1, 1) - pix = 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_sample(shape) - idx = cdf.searchsorted(uniform_samples, side='right') - idx = np.array(idx, copy=False) # searchsorted returns a scalar - 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: - 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.int) - flat_found = found.ravel() - while n_uniq < size: - x = self.rand(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: - idx = self.permutation(pop_size)[:size] - 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 - - return a[idx] - - - 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 or equal to 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 - -------- - randint : Discrete uniform distribution, yielding integers. - random_integers : Discrete uniform distribution over the closed - interval ``[low, high]``. - random_sample : Floats uniformly distributed over ``[0, 1)``. - random : Alias for `random_sample`. - rand : Convenience function that accepts dimensions as input, e.g., - ``rand(2,2)`` would generate a 2-by-2 array of floats, - uniformly distributed over ``[0, 1)``. - - 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. The ``high`` limit may be included in the - returned array of floats due to floating-point rounding in the - equation ``low + (high-low) * random_sample()``. For example: - - >>> x = np.float32(5*0.99999999) - >>> x - 5.0 - - - Examples - -------- - Draw samples from the distribution: - - >>> s = np.random.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 ndarray olow, ohigh, odiff - cdef double flow, fhigh, fscale - cdef object temp - - olow = PyArray_FROM_OTF(low, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - ohigh = PyArray_FROM_OTF(high, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - - if olow.shape == ohigh.shape == (): - flow = PyFloat_AsDouble(low) - fhigh = PyFloat_AsDouble(high) - fscale = fhigh - flow - - if not npy_isfinite(fscale): - 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 = PyArray_EnsureArray(temp) - - if not np.all(np.isfinite(odiff)): - raise OverflowError('Range exceeds valid bounds') - - return cont2_array(self.internal_state, rk_uniform, size, olow, odiff, - self.lock) - - def rand(self, *args): - """ - rand(d0, d1, ..., dn) - - 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)``. - - Parameters - ---------- - d0, d1, ..., dn : int, optional - The dimensions of the returned array, should all be positive. - If no argument is given a single Python float is returned. - - Returns - ------- - out : ndarray, shape ``(d0, d1, ..., dn)`` - Random values. - - See Also - -------- - random - - Examples - -------- - >>> np.random.rand(3,2) - array([[ 0.14022471, 0.96360618], #random - [ 0.37601032, 0.25528411], #random - [ 0.49313049, 0.94909878]]) #random - - """ - if len(args) == 0: - return self.random_sample() - else: - return self.random_sample(size=args) - - def randn(self, *args): - """ - randn(d0, d1, ..., dn) - - Return a sample (or samples) from the "standard normal" distribution. - - .. 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`. - - 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. - If no argument is given a single Python float is returned. - - Returns - ------- - Z : ndarray or float - A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from - the standard normal distribution, or a single such float if - no parameters were supplied. - - See Also - -------- - standard_normal : Similar, but takes a tuple as its argument. - normal : Also accepts mu and sigma arguments. - - Notes - ----- - For random samples from :math:`N(\\mu, \\sigma^2)`, use: - - ``sigma * np.random.randn(...) + mu`` - - Examples - -------- - >>> np.random.randn() - 2.1923875335537315 # random - - Two-by-four array of samples from N(3, 6.25): - - >>> 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) - - def random_integers(self, low, high=None, size=None): - """ - random_integers(low, high=None, size=None) - - Random integers of type np.int between `low` and `high`, inclusive. - - 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 integer type and its precision - is platform dependent. - - This function has been deprecated. Use randint instead. - - .. deprecated:: 1.11.0 - - Parameters - ---------- - low : int - Lowest (signed) integer to be drawn from the distribution (unless - ``high=None``, in which case this parameter is the *highest* such - integer). - high : int, optional - If provided, the largest (signed) integer to be drawn from the - distribution (see above for behavior if ``high=None``). - size : int or tuple of ints, optional - Output shape. 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 : 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. - - See Also - -------- - randint : Similar to `random_integers`, only for the half-open - interval [`low`, `high`), and 0 is the lowest value if `high` is - omitted. - - Notes - ----- - To sample from N evenly spaced floating-point numbers between a and b, - use:: - - a + (b - a) * (np.random.random_integers(N) - 1) / (N - 1.) - - Examples - -------- - >>> np.random.random_integers(5) - 4 # random - >>> type(np.random.random_integers(5)) - - >>> np.random.random_integers(5, size=(3,2)) - array([[5, 4], # random - [3, 3], - [4, 5]]) - - Choose five random numbers from the set of five evenly-spaced - numbers between 0 and 2.5, inclusive (*i.e.*, from the set - :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 ]) # random - - Roll two six sided dice 1000 times and sum the results: - - >>> d1 = np.random.random_integers(1, 6, 1000) - >>> d2 = np.random.random_integers(1, 6, 1000) - >>> dsums = d1 + d2 - - Display results as a histogram: - - >>> import matplotlib.pyplot as plt - >>> count, bins, ignored = plt.hist(dsums, 11, density=True) - >>> plt.show() - - """ - if high is None: - warnings.warn(("This function is deprecated. Please call " - "randint(1, {low} + 1) instead".format(low=low)), - DeprecationWarning) - high = low - low = 1 - - 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') - - - - # Complicated, continuous distributions: - def standard_normal(self, size=None): - """ - standard_normal(size=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. - - 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 * 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 - >>> 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) - - 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 - `numpy.random.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.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.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 - - """ - 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_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 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. - - """ - cdef ndarray oa, ob - cdef double fa, fb - - oa = PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - ob = 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`. 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 - - """ - cdef ndarray oscale - cdef double fscale - - oscale = 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: - - >>> n = np.random.standard_exponential((3, 8000)) - - """ - return cont0_array(self.internal_state, rk_standard_exponential, size, - self.lock) - - def standard_gamma(self, shape, size=None): - """ - standard_gamma(shape, size=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. - - 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.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') - >>> plt.show() - - """ - cdef ndarray oshape - cdef double fshape - - oshape = 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) - - 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.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 - >>> count, bins, ignored = plt.hist(s, 50, density=True) - >>> y = bins**(shape-1)*(np.exp(-bins/scale) / - ... (sps.gamma(shape)*scale**shape)) - >>> plt.plot(bins, y, linewidth=2, color='r') - >>> plt.show() - - """ - cdef ndarray oshape, oscale - cdef double fshape, fscale - - oshape = PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - oscale = 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) - - 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 should 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, should be > 0. - dfden : float or array_like of float - Degrees of freedom in denominator, should 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.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. - - """ - cdef ndarray odfnum, odfden - cdef double fdfnum, fdfden - - odfnum = PyArray_FROM_OTF(dfnum, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - odfden = 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) - - 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, should 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. - nonc : float or array_like of floats - Non-centrality parameter, the sum of the squares of the numerator - means, should 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. - - >>> dfnum = 3 # between group deg of freedom - >>> dfden = 20 # within groups degrees of freedom - >>> nonc = 3.0 - >>> nc_vals = np.random.noncentral_f(dfnum, dfden, nonc, 1000000) - >>> NF = np.histogram(nc_vals, bins=50, density=True) - >>> c_vals = np.random.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() - - """ - cdef ndarray odfnum, odfden, ononc - cdef double fdfnum, fdfden, fnonc - - odfnum = PyArray_FROM_OTF(dfnum, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - odfden = PyArray_FROM_OTF(dfden, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - ononc = 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) - - 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, should 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.chisquare(2,4) - array([ 1.89920014, 9.00867716, 3.13710533, 5.62318272]) # random - - """ - cdef ndarray odf - cdef double fdf - - odf = 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) - - 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, should 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. - 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 - - >>> import matplotlib.pyplot as plt - >>> values = plt.hist(np.random.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(np.random.noncentral_chisquare(3, .0000001, 100000), - ... bins=np.arange(0., 25, .1), density=True) - >>> values2 = plt.hist(np.random.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(np.random.noncentral_chisquare(3, 20, 100000), - ... bins=200, density=True) - >>> plt.show() - - """ - cdef ndarray odf, ononc - cdef double fdf, fnonc - - odf = PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - ononc = 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) - - 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.standard_cauchy(1000000) - >>> s = s[(s>-25) & (s<25)] # truncate distribution so it plots well - >>> plt.hist(s, bins=100) - >>> plt.show() - - """ - return cont0_array(self.internal_state, rk_standard_cauchy, size, - self.lock) - - 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, should 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.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 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) - - 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.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 - >>> 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') - >>> plt.show() - - """ - cdef ndarray omu, okappa - cdef double fmu, fkappa - - omu = PyArray_FROM_OTF(mu, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - okappa = 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) - - 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 all 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.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() - - """ - cdef ndarray oa - cdef double fa - - oa = 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) - - 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: - - >>> a = 5. # shape - >>> s = np.random.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(np.random.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() - - """ - cdef ndarray oa - cdef double fa - - oa = 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) - - 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: - - >>> a = 5. # shape - >>> samples = 1000 - >>> s = np.random.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 - >>> rvs = np.random.power(5, 1000000) - >>> rvsp = np.random.pareto(5, 1000000) - >>> xx = np.linspace(0,1,100) - >>> powpdf = stats.powerlaw.pdf(xx,5) - - >>> plt.figure() - >>> plt.hist(rvs, bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> plt.title('np.random.power(5)') - - >>> plt.figure() - >>> plt.hist(1./(1.+rvsp), bins=50, density=True) - >>> plt.plot(xx,powpdf,'r-') - >>> 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.title('inverse of stats.pareto(5)') - - """ - cdef ndarray oa - cdef double fa - - oa = 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) - - 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.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) - - """ - 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) - - 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: - - >>> mu, beta = 0, 0.1 # location and scale - >>> s = np.random.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 = np.random.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() - - """ - 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) - - 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.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) - >>> plt.plot(bins, logist(bins, loc, scale)*count.max()/\\ - ... logist(bins, loc, scale).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) - - 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: - - >>> mu, sigma = 3., 1. # mean and standard deviation - >>> s = np.random.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. - >>> b = [] - >>> for i in range(1000): - ... a = 10. + np.random.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() - - """ - 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) - - 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 - >>> values = hist(np.random.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 = np.random.rayleigh(modevalue, 1000000) - - The percentage of waves larger than 3 meters is: - - >>> 100.*sum(s>3)/1000000. - 0.087300000000000003 # random - - """ - cdef ndarray oscale - cdef double fscale - - oscale = 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) - - 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.wald(3, 2, 100000), bins=200, density=True) - >>> 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) - - 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 should fulfill the condition ``left <= mode <= right``. - right : float or array_like of floats - Upper limit, should 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.triangular(-3, 0, 8, 100000), bins=200, - ... density=True) - >>> plt.show() - - """ - cdef ndarray oleft, omode, oright - cdef double fleft, fmode, fright - - oleft = PyArray_FROM_OTF(left, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - omode = PyArray_FROM_OTF(mode, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - oright = PyArray_FROM_OTF(right, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - - if oleft.shape == omode.shape == oright.shape == (): - 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 cont3_array_sc(self.internal_state, rk_triangular, size, - fleft, fmode, fright, self.lock) - - 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 cont3_array(self.internal_state, rk_triangular, size, oleft, - omode, oright, self.lock) - - # 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%. Since - 0.27*15 = 4, 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: - - >>> n, p = 10, .5 # number of trials, probability of each trial - >>> s = np.random.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(np.random.binomial(9, 0.1, 20000) == 0)/20000. - # answer = 0.38885, or 38%. - - """ - cdef ndarray on, op - cdef long ln - cdef double fp - - on = PyArray_FROM_OTF(n, NPY_LONG, NPY_ARRAY_ALIGNED) - op = 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) - - 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.negative_binomial(1, 0.1, 100000) - >>> for i in range(1, 11): # doctest: +SKIP - ... probability = sum(sPyArray_FROM_OTF(n, NPY_DOUBLE, NPY_ARRAY_ALIGNED) - op = 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) - - 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, should be >= 0. A sequence of expectation - intervals must be broadcastable over the requested size. - size : int or tuple of ints, optional - Output shape. If the given shape is, e.g., ``(m, n, k)``, then - ``m * n * k`` samples are drawn. 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 long 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 - >>> s = np.random.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 = np.random.poisson(lam=(100., 500.), size=(100, 2)) - - """ - cdef ndarray olam - cdef double flam - - olam = 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) - - 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.zipf(a, 1000) - - Display the histogram of the samples, along with - the probability density function: - - >>> import matplotlib.pyplot as plt - >>> from scipy import special - - 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') - >>> plt.show() - - """ - cdef ndarray oa - cdef double fa - - oa = 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) - - 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.geometric(p=0.35, size=10000) - - How many trials succeeded after a single run? - - >>> (z == 1).sum() / 10000. - 0.34889999999999999 #random - - """ - cdef ndarray op - cdef double fp - - op = 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) - - 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. - nbad : int or array_like of ints - Number of ways to make a bad selection. Must be nonnegative. - nsample : int or array_like of ints - Number of items sampled. Must be at least 1 and at most - ``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. - - 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 - - Examples - -------- - Draw samples from the distribution: - - >>> ngood, nbad, nsamp = 100, 2, 10 - # number of good, number of bad, and number of samples - >>> s = np.random.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 = np.random.hypergeometric(15, 15, 15, 100000) - >>> sum(s>=12)/100000. + sum(s<=3)/100000. - # answer = 0.003 ... pretty unlikely! - - """ - cdef ndarray ongood, onbad, onsample - cdef long lngood, lnbad, lnsample - - ongood = PyArray_FROM_OTF(ngood, NPY_LONG, NPY_ARRAY_ALIGNED) - onbad = PyArray_FROM_OTF(nbad, NPY_LONG, NPY_ARRAY_ALIGNED) - onsample = 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") - 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)): - raise ValueError("ngood + nbad < nsample") - return discnmN_array(self.internal_state, rk_hypergeometric, size, - ongood, onbad, onsample, self.lock) - - 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 density 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.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() - - """ - cdef ndarray op - cdef double fp - - op = 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) - - # 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.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.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 symmetric 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. - - # 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 symmetric positive-semidefinite.", - RuntimeWarning) - else: - raise ValueError( - "covariance is not symmetric 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): - """ - 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 - 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 - 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: - - >>> np.random.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: - - >>> np.random.multinomial(20, [1/6.]*6, size=2) - 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, - we threw 2 times 1, 4 times 2, etc. - - 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]) # 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: - - >>> np.random.multinomial(100, [1.0 / 3, 2.0 / 3]) # RIGHT - array([38, 62]) # random - - not like: - - >>> np.random.multinomial(100, [1.0, 2.0]) # WRONG - array([100, 0]) - - """ - cdef npy_intp d - cdef ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr" - cdef double *pix - cdef long *mnix - cdef npy_intp i, j, dn, sz - cdef double Sum - - d = len(pvals) - parr = PyArray_ContiguousFromObject(pvals, NPY_DOUBLE, 1, 1) - pix = PyArray_DATA(parr) - - 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 = multin - mnix = 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 - - 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.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 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 = PyArray_ContiguousFromObject(alpha, NPY_DOUBLE, 1, 1) - if np.any(np.less_equal(alpha_arr, 0)): - raise ValueError('alpha <= 0') - alpha_data = PyArray_DATA(alpha_arr) - - shape = _shape_from_size(size, k) - - diric = np.zeros(shape, np.float64) - val_arr = diric - val_data= PyArray_DATA(val_arr) - - i = 0 - totsize = 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 - 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 - -------- - >>> arr = np.arange(10) - >>> np.random.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)) - >>> np.random.shuffle(arr) - >>> arr - array([[3, 4, 5], # random - [6, 7, 8], - [0, 1, 2]]) - - """ - cdef: - 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 = 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 = 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) - 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,...]) - with self.lock: - for i in reversed(range(1, n)): - j = rk_interval(i, self.internal_state) - buf[...] = x[j] - x[j] = x[i] - x[i] = buf - else: - # Untyped path. - with self.lock: - for i in reversed(range(1, n)): - j = rk_interval(i, self.internal_state) - 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 - 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. - string.memcpy(buf, data + j * stride, itemsize) - string.memcpy(data + j * stride, data + i * stride, itemsize) - string.memcpy(data + i * stride, buf, itemsize) - - 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 - -------- - >>> np.random.permutation(10) - 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]) # random - - >>> arr = np.arange(9).reshape((3, 3)) - >>> np.random.permutation(arr) - array([[6, 7, 8], # random - [0, 1, 2], - [3, 4, 5]]) - - """ - if isinstance(x, (int, long, 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] - - -_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 -bytes = _rand.bytes -uniform = _rand.uniform -rand = _rand.rand -randn = _rand.randn -random_integers = _rand.random_integers -standard_normal = _rand.standard_normal -normal = _rand.normal -beta = _rand.beta -exponential = _rand.exponential -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_t = _rand.standard_t -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 -zipf = _rand.zipf -geometric = _rand.geometric -hypergeometric = _rand.hypergeometric -logseries = _rand.logseries - -multivariate_normal = _rand.multivariate_normal -multinomial = _rand.multinomial -dirichlet = _rand.dirichlet - -shuffle = _rand.shuffle -permutation = _rand.permutation diff --git a/numpy/random/_mtrand/distributions.c b/numpy/random/_mtrand/distributions.c deleted file mode 100644 index 1b410db57444..000000000000 --- a/numpy/random/_mtrand/distributions.c +++ /dev/null @@ -1,946 +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 -#include -#include -#include - -#ifndef min -#define min(x,y) ((xy)?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 ((n == 0LL) || (p == 0.0f)) { - return 0; - } - - 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 0b42bc79442a..000000000000 --- 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/initarray.c b/numpy/random/_mtrand/initarray.c deleted file mode 100644 index beff7851002a..000000000000 --- a/numpy/random/_mtrand/initarray.c +++ /dev/null @@ -1,151 +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 - */ - -#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 f5e5e5332d22..000000000000 --- 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 266847cbe9fc..000000000000 --- 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 - -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 e146054b117d..000000000000 --- a/numpy/random/_mtrand/numpy.pxd +++ /dev/null @@ -1,163 +0,0 @@ -# cython: language_level=3 - -# :Author: Travis Oliphant -from cpython.exc cimport PyErr_Print - -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 894a25167f5f..000000000000 --- 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 = PyCapsule_GetPointer(rngstate, NULL) - - off = (low) - rng = (high) - (low) - - if size is None: - rk_random_{{npy_udt}}(off, rng, 1, &buf, state) - return np.{{np_dt}}(buf) - else: - array = np.empty(size, np.{{np_dt}}) - cnt = PyArray_SIZE(array) - array_data = 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 6371ebe3368c..000000000000 --- 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 -#include - -/* - * 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 -#include -#define _FTIME(x) _ftime((x)) -#endif - -#ifndef RK_NO_WINCRYPT -/* Windows crypto */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif -#include -#include -#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 -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#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/_mtrand/randomkit.h deleted file mode 100644 index a24dabebfed7..000000000000 --- a/numpy/random/_mtrand/randomkit.h +++ /dev/null @@ -1,226 +0,0 @@ -/* Random kit 1.3 */ - -/* - * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.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. - */ - -/* @(#) $Jeannot: randomkit.h,v 1.24 2005/07/21 22:14:09 js Exp $ */ - -/* - * Typical use: - * - * { - * rk_state state; - * unsigned long seed = 1, random_value; - * - * rk_seed(seed, &state); // Initialize the RNG - * ... - * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] - * } - * - * Instead of rk_seed, you can use rk_randomseed which will get a random seed - * from /dev/urandom (or the clock, if /dev/urandom is unavailable): - * - * { - * rk_state state; - * unsigned long random_value; - * - * rk_randomseed(&state); // Initialize the RNG with a random seed - * ... - * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] - * } - */ - -/* - * Useful macro: - * RK_DEV_RANDOM: the device used for random seeding. - * defaults to "/dev/urandom" - */ - -#ifndef _RANDOMKIT_ -#define _RANDOMKIT_ - -#include -#include - - -#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 enum { - RK_NOERR = 0, /* no error */ - RK_ENODEV = 1, /* no RK_DEV_RANDOM device */ - RK_ERR_MAX = 2 -} rk_error; - -/* error strings */ -extern char *rk_strerror[RK_ERR_MAX]; - -/* Maximum generated random value */ -#define RK_MAX 0xFFFFFFFFUL - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Initialize the RNG state using the given seed. - */ -extern void rk_seed(unsigned long seed, rk_state *state); - -/* - * Initialize the RNG state using a random seed. - * Uses /dev/random or, when unavailable, the clock (see randomkit.c). - * Returns RK_NOERR when no errors occurs. - * Returns RK_ENODEV when the use of RK_DEV_RANDOM failed (for example because - * there is no such device). In this case, the RNG was initialized using the - * clock. - */ -extern rk_error rk_randomseed(rk_state *state); - -/* - * Returns a random unsigned long between 0 and RK_MAX inclusive - */ -extern unsigned long rk_random(rk_state *state); - -/* - * Returns a random long between 0 and LONG_MAX inclusive - */ -extern long rk_long(rk_state *state); - -/* - * Returns a random unsigned long between 0 and ULONG_MAX inclusive - */ -extern unsigned long rk_ulong(rk_state *state); - -/* - * Returns a random unsigned long between 0 and max inclusive. - */ -extern unsigned long rk_interval(unsigned long max, rk_state *state); - -/* - * Fills an array with cnt random npy_uint64 between off and off + rng - * inclusive. The numbers wrap if rng is sufficiently large. - */ -extern void rk_random_uint64(npy_uint64 off, npy_uint64 rng, npy_intp cnt, - npy_uint64 *out, rk_state *state); - -/* - * Fills an array with cnt random npy_uint32 between off and off + rng - * inclusive. The numbers wrap if rng is sufficiently large. - */ -extern void rk_random_uint32(npy_uint32 off, npy_uint32 rng, npy_intp cnt, - npy_uint32 *out, rk_state *state); - -/* - * Fills an array with cnt random npy_uint16 between off and off + rng - * inclusive. The numbers wrap if rng is sufficiently large. - */ -extern void rk_random_uint16(npy_uint16 off, npy_uint16 rng, npy_intp cnt, - npy_uint16 *out, rk_state *state); - -/* - * Fills an array with cnt random npy_uint8 between off and off + rng - * inclusive. The numbers wrap if rng is sufficiently large. - */ -extern void rk_random_uint8(npy_uint8 off, npy_uint8 rng, npy_intp cnt, - npy_uint8 *out, rk_state *state); - -/* - * Fills an array with cnt random npy_bool between off and off + rng - * inclusive. It is assumed tha npy_bool as the same size as npy_uint8. - */ -extern void rk_random_bool(npy_bool off, npy_bool rng, npy_intp cnt, - npy_bool *out, rk_state *state); - -/* - * Returns a random double between 0.0 and 1.0, 1.0 excluded. - */ -extern double rk_double(rk_state *state); - -/* - * fill the buffer with size random bytes - */ -extern void rk_fill(void *buffer, size_t size, rk_state *state); - -/* - * fill the buffer with randombytes from the random device - * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is - * On Unix, if strong is defined, RK_DEV_RANDOM is used. If not, RK_DEV_URANDOM - * is used instead. This parameter has no effect on Windows. - * Warning: on most unixes RK_DEV_RANDOM will wait for enough entropy to answer - * which can take a very long time on quiet systems. - */ -extern rk_error rk_devfill(void *buffer, size_t size, int strong); - -/* - * fill the buffer using rk_devfill if the random device is available and using - * rk_fill if it is not - * parameters have the same meaning as rk_fill and rk_devfill - * 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); - -/* - * return a random gaussian deviate with variance unity and zero mean. - */ -extern double rk_gauss(rk_state *state); - -#ifdef __cplusplus -} -#endif - -#endif /* _RANDOMKIT_ */ diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 31feddb29617..48a729179184 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -45,19 +45,6 @@ def generate_libraries(ext, build_dir): libs = [] defs.append(('NPY_NO_DEPRECATED_API', 0)) - # 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'))) config.add_data_dir('tests') ############################## diff --git a/setup.py b/setup.py index 6680e3b6a0bc..7dd87da8a072 100755 --- a/setup.py +++ b/setup.py @@ -225,7 +225,7 @@ def run(self): def generate_cython(): cwd = os.path.abspath(os.path.dirname(__file__)) print("Cythonizing sources") - for d in ('random/_mtrand', 'random'): + for d in ('random',): p = subprocess.call([sys.executable, os.path.join(cwd, 'tools', 'cythonize.py'), 'numpy/{0}'.format(d)], From 19b48e2c655c966ff96070c14e9b51c38b35f708 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 23 May 2019 07:58:47 +0300 Subject: [PATCH 127/138] BUG: test, fix missing return to deprecated function --- numpy/random/generator.pyx | 2 +- numpy/random/tests/test_direct.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 331d634d62ee..4b3d0166576e 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -124,7 +124,7 @@ cdef class Generator: Deprecated, renamed to ``random`` """ warnings.warn("Renamed to random", RuntimeWarning) - self.random(*args, **kwargs) + return self.random(*args, **kwargs) def random(self, size=None, dtype=np.float64, out=None): diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index ca6dbb58dd2a..5ae71ade73d8 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -4,7 +4,7 @@ import numpy as np from numpy.testing import (assert_equal, assert_allclose, assert_array_equal, - assert_raises) + assert_raises, assert_warns) import pytest from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, @@ -191,6 +191,13 @@ def test_uniform_double(self): 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) + with assert_warns(RuntimeWarning): + uniforms = rs.random_sample(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) From cdb2b0febd5e287c56b021bb1f55b21d62d618f4 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 23 May 2019 10:24:05 +0300 Subject: [PATCH 128/138] MAINT: remove tomaxint, random_sample from generator --- numpy/random/generator.pyx | 50 -------------------- numpy/random/tests/test_direct.py | 7 --- numpy/random/tests/test_generator_mt19937.py | 6 --- numpy/random/tests/test_smoke.py | 15 ------ 4 files changed, 78 deletions(-) diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 4b3d0166576e..e61696226593 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -119,14 +119,6 @@ cdef class Generator: """ return self._bit_generator - def random_sample(self, *args, **kwargs): - """ - Deprecated, renamed to ``random`` - """ - warnings.warn("Renamed to random", RuntimeWarning) - return self.random(*args, **kwargs) - - def random(self, size=None, dtype=np.float64, out=None): """ random(size=None, dtype='d', out=None) @@ -335,47 +327,6 @@ cdef class Generator: raise TypeError('Unsupported dtype "%s" for standard_exponential' % key) - def tomaxint(self, size=None): - """ - tomaxint(size=None) - - Return a sample of uniformly distributed random integers in the interval - [0, ``np.iinfo(np.int).max``]. The np.int type translates to the C long - integer type and its precision is platform dependent. - - 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 : ndarray - Drawn samples, with shape `size`. - - See Also - -------- - integers : Uniform sampling over a given half-open interval of integers. - - Examples - -------- - >>> rg = np.random.Generator() # need a Generator object - >>> rg.tomaxint((2,2,2)) - array([[[1170048599, 1600360186], # random - [ 739731006, 1947757578]], - [[1871712945, 752307660], - [1601631370, 1479324245]]]) - >>> rg.tomaxint((2,2,2)) < np.iinfo(np.int).max - array([[[ True, True], - [ True, True]], - [[ True, True], - [ True, True]]]) - - """ - return self.integers(0, np.iinfo(np.int).max + 1, dtype=np.int, size=size) - def integers(self, low, high=None, size=None, dtype=np.int64, endpoint=False): """ integers(low, high=None, size=None, dtype='int64', endpoint=False) @@ -3966,7 +3917,6 @@ standard_exponential = _random_generator.standard_exponential standard_gamma = _random_generator.standard_gamma standard_normal = _random_generator.standard_normal standard_t = _random_generator.standard_t -tomaxint = _random_generator.tomaxint triangular = _random_generator.triangular uniform = _random_generator.uniform vonmises = _random_generator.vonmises diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 5ae71ade73d8..4700bb0cea99 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -191,13 +191,6 @@ def test_uniform_double(self): 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) - with assert_warns(RuntimeWarning): - uniforms = rs.random_sample(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) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 770c32a3907b..c20fc5b74f39 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -114,12 +114,6 @@ def setup(self): self.state['state']['key'], self.state['state']['pos']) - def test_basic(self): - old = self.rg.tomaxint(16) - self.bit_generator.state = self.state - new = self.rg.tomaxint(16) - assert_(np.all(old == new)) - def test_gaussian_reset(self): # Make sure the cached every-other-Gaussian is reset. old = self.rg.standard_normal(size=3) diff --git a/numpy/random/tests/test_smoke.py b/numpy/random/tests/test_smoke.py index ca5fde500de8..d5a0c38a50ba 100644 --- a/numpy/random/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -280,21 +280,6 @@ def test_permutation(self): permuted = self.rg.permutation(original) assert_((original != permuted).any()) - def test_tomaxint(self): - vals = self.rg.tomaxint(size=100000) - maxsize = 0 - if os.name == 'nt': - maxsize = 2 ** 31 - 1 - else: - try: - maxsize = sys.maxint - except AttributeError: - maxsize = sys.maxsize - if maxsize < 2 ** 32: - assert_((vals < sys.maxsize).all()) - else: - assert_((vals >= 2 ** 32).any()) - def test_beta(self): vals = self.rg.beta(2.0, 2.0, 10) assert_(len(vals) == 10) From 2c14e47834262de85673c0b71e94494a5f642268 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 23 May 2019 09:07:15 +0100 Subject: [PATCH 129/138] ENH: Split poisson_lam_max Use type-dependent poisson lam max Make private Fix backward compat issue in loggam --- numpy/random/common.pxd | 2 ++ numpy/random/common.pyx | 19 +++++++++++++++---- numpy/random/generator.pyx | 2 +- numpy/random/mtrand.pyx | 4 ++-- .../random/src/distributions/distributions.c | 4 ++-- numpy/random/tests/test_against_numpy.py | 1 + numpy/random/tests/test_generator_mt19937.py | 4 ++-- numpy/random/tests/test_randomstate.py | 2 +- 8 files changed, 26 insertions(+), 12 deletions(-) diff --git a/numpy/random/common.pxd b/numpy/random/common.pxd index 1223b2706d65..4636fd2f0daa 100644 --- a/numpy/random/common.pxd +++ b/numpy/random/common.pxd @@ -10,6 +10,7 @@ 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: @@ -23,6 +24,7 @@ cdef enum ConstraintType: CONS_GT_1 CONS_GTE_1 CONS_POISSON + LEGACY_CONS_POISSON ctypedef ConstraintType constraint_type diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx index e195195a4af1..fdf930900a07 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -14,6 +14,11 @@ interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', 'next_uint32', 'next_double', 'bit_generator']) +cdef double LEGACY_POISSON_LAM_MAX = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10 +cdef double POISSON_LAM_MAX = np.iinfo('int64').max - np.sqrt(np.iinfo('int64').max)*10 + +cdef uint64_t MAXSIZE = sys.maxsize + cdef object benchmark(bitgen_t *bitgen, object lock, Py_ssize_t cnt, object method): """Benchmark command used by BitGenerator""" @@ -290,10 +295,6 @@ cdef object float_fill_from_double(void *func, bitgen_t *state, object size, obj return out_array -cdef double POISSON_LAM_MAX = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10 - -cdef uint64_t MAXSIZE = sys.maxsize - 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))): @@ -321,6 +322,11 @@ cdef int check_array_constraint(np.ndarray val, object name, constraint_type con 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 @@ -352,6 +358,11 @@ cdef int check_constraint(double val, object name, constraint_type cons) except 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 diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index e61696226593..9389e85ee3f7 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -73,7 +73,7 @@ cdef class Generator: cdef bitgen_t _bitgen cdef binomial_t _binomial cdef object lock - poisson_lam_max = POISSON_LAM_MAX + _poisson_lam_max = POISSON_LAM_MAX def __init__(self, bit_generator=None): if bit_generator is None: diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 74d1f519d97a..ecbd8401ac5a 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -92,7 +92,7 @@ cdef class RandomState: cdef aug_bitgen_t _aug_state cdef binomial_t _binomial cdef object lock - poisson_lam_max = POISSON_LAM_MAX + _poisson_lam_max = POISSON_LAM_MAX def __init__(self, bit_generator=None): if bit_generator is None: @@ -3244,7 +3244,7 @@ cdef class RandomState: """ out = disc(&legacy_random_poisson, &self._bitgen, size, self.lock, 1, 0, - lam, 'lam', CONS_POISSON, + lam, 'lam', LEGACY_CONS_POISSON, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE) # Match historical output type diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index d8362a39a58c..1272a37e320a 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -472,7 +472,7 @@ uint64_t random_uint(bitgen_t *bitgen_state) { */ static double loggam(double x) { double x0, x2, xp, gl, gl0; - int64_t k, n; + RAND_INT_TYPE k, n; static double a[10] = {8.333333333333333e-02, -2.777777777777778e-03, 7.936507936507937e-04, -5.952380952380952e-04, @@ -484,7 +484,7 @@ static double loggam(double x) { if ((x == 1.0) || (x == 2.0)) { return 0.0; } else if (x <= 7.0) { - n = (int64_t)(7 - x); + n = (RAND_INT_TYPE)(7 - x); x0 = x + n; } x2 = 1.0 / (x0 * x0); diff --git a/numpy/random/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py index a000e5db73f1..52e67214df1d 100644 --- a/numpy/random/tests/test_against_numpy.py +++ b/numpy/random/tests/test_against_numpy.py @@ -271,6 +271,7 @@ def test_binomial(self): is_np=True) self._is_state_common() + @pytest.mark.xfail(reason='Definition of poisson_lam_max changed') def test_poisson_lam_max(self): assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index c20fc5b74f39..207ec1a2bba1 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -1074,7 +1074,7 @@ def test_poisson(self): assert_array_equal(actual, desired) def test_poisson_exceptions(self): - lambig = np.iinfo('l').max + lambig = np.iinfo('int64').max lamneg = -1 assert_raises(ValueError, random.poisson, lamneg) assert_raises(ValueError, random.poisson, [lamneg] * 10) @@ -1788,7 +1788,7 @@ def test_negative_binomial(self): assert_raises(ValueError, neg_binom, n, bad_p_two * 3) def test_poisson(self): - max_lam = random.poisson_lam_max + max_lam = random._poisson_lam_max lam = [1] bad_lam_one = [-1] diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 75c35ef62453..066e4d661a68 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -1693,7 +1693,7 @@ def test_negative_binomial(self): assert_raises(ValueError, neg_binom, n, bad_p_two * 3) def test_poisson(self): - max_lam = random.RandomState().poisson_lam_max + max_lam = random.RandomState()._poisson_lam_max lam = [1] bad_lam_one = [-1] From 457c6c5f3a9c08a724965be7205178b24696ad4b Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 23 May 2019 09:08:04 +0100 Subject: [PATCH 130/138] MAINT: Remove test_against_numpy Remove test file that is circular when randomgen is in numpy --- numpy/random/tests/test_against_numpy.py | 557 ----------------------- 1 file changed, 557 deletions(-) delete mode 100644 numpy/random/tests/test_against_numpy.py diff --git a/numpy/random/tests/test_against_numpy.py b/numpy/random/tests/test_against_numpy.py deleted file mode 100644 index 52e67214df1d..000000000000 --- a/numpy/random/tests/test_against_numpy.py +++ /dev/null @@ -1,557 +0,0 @@ -import numpy as np -import numpy.random -from numpy.testing import (assert_allclose, assert_array_equal, assert_equal, - suppress_warnings) - -import pytest - -from numpy.random import Generator, MT19937, generator -from numpy.random import RandomState - - -def compare_0_input(f1, f2): - inputs = [(tuple([]), {}), - (tuple([]), {'size': 10}), - (tuple([]), {'size': (20, 31)}), - (tuple([]), {'size': (20, 31, 5)})] - - for i in inputs: - v1 = f1(*i[0], **i[1]) - v2 = f2(*i[0], **i[1]) - assert_allclose(v1, v2) - - -def compare_1_input(f1, f2, is_small=False): - a = 0.3 if is_small else 10 - inputs = [((a,), {}), - ((a,), {'size': 10}), - ((np.array([a] * 10),), {}), - ((np.array([a] * 10),), {'size': 10}), - ((np.array([a] * 10),), {'size': (100, 10)})] - for i in inputs: - v1 = f1(*i[0], **i[1]) - v2 = f2(*i[0], **i[1]) - assert_allclose(v1, v2) - - -def compare_2_input(f1, f2, is_np=False, is_scalar=False): - if is_np: - a, b = 10, 0.3 - dtype = np.int - else: - a, b = 2, 3 - dtype = np.double - inputs = [((a, b), {}), - ((a, b), {'size': 10}), - ((a, b), {'size': (23, 7)}), - ((np.array([a] * 10), b), {}), - ((a, np.array([b] * 10)), {}), - ((a, np.array([b] * 10)), {'size': 10}), - ((np.reshape(np.array([[a] * 100]), (100, 1)), - np.array([b] * 10)), {'size': (100, 10)}), - ((np.ones((7, 31), dtype=dtype) * a, - np.array([b] * 31)), {'size': (7, 31)}), - ((np.ones((7, 31), dtype=dtype) * a, np.array([b] * 31)), - {'size': (10, 7, 31)})] - - if is_scalar: - inputs = inputs[:3] - - for i in inputs: - v1 = f1(*i[0], **i[1]) - v2 = f2(*i[0], **i[1]) - assert_allclose(v1, v2) - - -def compare_3_input(f1, f2, is_np=False): - a, b, c = 10, 20, 25 - inputs = [((a, b, c), {}), - ((a, b, c), {'size': 10}), - ((a, b, c), {'size': (23, 7)}), - ((np.array([a] * 10), b, c), {}), - ((a, np.array([b] * 10), c), {}), - ((a, b, np.array([c] * 10)), {}), - ((a, np.array([b] * 10), np.array([c] * 10)), {}), - ((a, np.array([b] * 10), c), {'size': 10}), - ((np.ones((1, 37), dtype=np.int) * a, - np.ones((23, 1), dtype=np.int) * [b], - c * np.ones((7, 1, 1), dtype=np.int)), - {}), - ((np.ones((1, 37), dtype=np.int) * a, - np.ones((23, 1), dtype=np.int) * [b], - c * np.ones((7, 1, 1), dtype=np.int)), - {'size': (7, 23, 37)}) - ] - - for i in inputs: - v1 = f1(*i[0], **i[1]) - v2 = f2(*i[0], **i[1]) - assert_allclose(v1, v2) - - -class TestAgainstNumPy(object): - @classmethod - def setup_class(cls): - cls.np = numpy.random - cls.bit_generator = MT19937 - cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1] - cls.rg = Generator(cls.bit_generator(*cls.seed)) - cls.rs = RandomState(cls.bit_generator(*cls.seed)) - cls.nprs = cls.np.RandomState(*cls.seed) - cls.initial_state = cls.rg.bit_generator.state - cls._set_common_state() - - @classmethod - def _set_common_state(cls): - state = cls.rg.bit_generator.state - st = [[]] * 5 - st[0] = 'MT19937' - st[1] = state['state']['key'] - st[2] = state['state']['pos'] - st[3] = 0 - st[4] = 0.0 - cls.nprs.set_state(st) - - @classmethod - def _set_common_state_legacy(cls): - state = cls.rs.get_state(legacy=False) - st = [[]] * 5 - st[0] = 'MT19937' - st[1] = state['state']['key'] - st[2] = state['state']['pos'] - st[3] = state['has_gauss'] - st[4] = state['gauss'] - cls.nprs.set_state(st) - - def _is_state_common(self): - state = self.nprs.get_state() - state2 = self.rg.bit_generator.state - assert (state[1] == state2['state']['key']).all() - assert (state[2] == state2['state']['pos']) - - def _is_state_common_legacy(self): - state = self.nprs.get_state() - state2 = self.rs.get_state(legacy=False) - assert (state[1] == state2['state']['key']).all() - assert (state[2] == state2['state']['pos']) - assert (state[3] == state2['has_gauss']) - assert_allclose(state[4], state2['gauss'], atol=1e-10) - - def test_common_seed(self): - self.rg.bit_generator.seed(1234) - self.nprs.seed(1234) - self._is_state_common() - self.rg.bit_generator.seed(23456) - self.nprs.seed(23456) - self._is_state_common() - - def test_numpy_state(self): - nprs = np.random.RandomState() - nprs.standard_normal(99) - state = nprs.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']) - - def test_random_sample(self): - self._set_common_state() - self._is_state_common() - v1 = self.nprs.random_sample(10) - v2 = self.rg.random(10) - - assert_array_equal(v1, v2) - - def test_standard_normal(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_0_input(self.nprs.standard_normal, - self.rs.standard_normal) - self._is_state_common_legacy() - - def test_standard_cauchy(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_0_input(self.nprs.standard_cauchy, - self.rs.standard_cauchy) - self._is_state_common_legacy() - - def test_standard_exponential(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_0_input(self.nprs.standard_exponential, - self.rs.standard_exponential) - self._is_state_common_legacy() - - @pytest.mark.xfail(reason='Stream broken for simplicity') - def test_tomaxint(self): - self._set_common_state() - self._is_state_common() - compare_0_input(self.nprs.tomaxint, - self.rg.tomaxint) - self._is_state_common() - - def test_poisson(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.poisson, - self.rg.poisson) - self._is_state_common() - - def test_rayleigh(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.rayleigh, - self.rg.rayleigh) - self._is_state_common() - - def test_zipf(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.zipf, - self.rg.zipf) - self._is_state_common() - - def test_logseries(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.logseries, - self.rg.logseries, - is_small=True) - self._is_state_common() - - def test_geometric(self): - self._set_common_state() - self._is_state_common() - compare_1_input(self.nprs.geometric, - self.rg.geometric, - is_small=True) - self._is_state_common() - - def test_logistic(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.logistic, - self.rg.logistic) - self._is_state_common() - - def test_gumbel(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.gumbel, - self.rg.gumbel) - self._is_state_common() - - def test_laplace(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.laplace, - self.rg.laplace) - self._is_state_common() - - def test_uniform(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.uniform, - self.rg.uniform) - self._is_state_common() - - def test_vonmises(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.vonmises, - self.rg.vonmises) - self._is_state_common() - - def test_binomial(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.nprs.binomial, - self.rg.binomial, - is_np=True) - self._is_state_common() - - @pytest.mark.xfail(reason='Definition of poisson_lam_max changed') - def test_poisson_lam_max(self): - assert_allclose(self.rg.poisson_lam_max, self.nprs.poisson_lam_max) - - def test_triangular(self): - self._set_common_state() - self._is_state_common() - compare_3_input(self.nprs.triangular, - self.rg.triangular) - self._is_state_common() - - def test_hypergeometric(self): - self._set_common_state() - self._is_state_common() - compare_3_input(self.nprs.hypergeometric, - self.rg.hypergeometric) - self._is_state_common() - - def test_bytes(self): - self._set_common_state() - self._is_state_common() - assert_equal(self.rg.bytes(8), self.nprs.bytes(8)) - self._is_state_common() - assert_equal(self.rg.bytes(103), self.nprs.bytes(103)) - self._is_state_common() - assert_equal(self.rg.bytes(8), self.nprs.bytes(8)) - self._is_state_common() - - def test_multinomial(self): - self._set_common_state() - self._is_state_common() - f = self.rg.multinomial - g = self.nprs.multinomial - p = [.1, .3, .4, .2] - assert_equal(f(100, p), g(100, p)) - assert_equal(f(100, np.array(p)), g(100, np.array(p))) - assert_equal(f(100, np.array(p), size=(7, 23)), - g(100, np.array(p), size=(7, 23))) - self._is_state_common() - - @pytest.mark.xfail(reason='Stream broken for performance') - def test_choice(self): - self._set_common_state() - self._is_state_common() - f = self.rg.choice - g = self.nprs.choice - a = np.arange(100) - size = 25 - for replace in (True, False): - assert_equal(f(a, size, replace), g(a, size, replace)) - assert_equal(f(100, size, replace), g(100, size, replace)) - self._is_state_common() - - def test_permutation(self): - self._set_common_state() - self._is_state_common() - f = self.rg.permutation - g = self.nprs.permutation - a = np.arange(100) - assert_equal(f(a), g(a)) - assert_equal(f(23), g(23)) - self._is_state_common() - - def test_shuffle(self): - self._set_common_state() - self._is_state_common() - f = self.rg.shuffle - g = self.nprs.shuffle - a = np.arange(100) - fa = a.copy() - ga = a.copy() - g(ga) - f(fa) - assert_equal(fa, ga) - self._is_state_common() - - def test_randint(self): - self._set_common_state() - self._is_state_common() - compare_2_input(self.rg.integers, - self.nprs.randint, - is_scalar=True) - self._is_state_common() - - def test_scalar(self): - s = Generator(MT19937(0)) - assert_equal(s.integers(1000), 684) - s1 = np.random.RandomState(0) - assert_equal(s1.randint(1000), 684) - assert_equal(s1.randint(1000), s.integers(1000)) - - s = Generator(MT19937(4294967295)) - assert_equal(s.integers(1000), 419) - s1 = np.random.RandomState(4294967295) - assert_equal(s1.randint(1000), 419) - assert_equal(s1.randint(1000), s.integers(1000)) - - self.rg.bit_generator.seed(4294967295) - self.nprs.seed(4294967295) - self._is_state_common() - - def test_array(self): - s = Generator(MT19937(range(10))) - assert_equal(s.integers(1000), 468) - s = np.random.RandomState(range(10)) - assert_equal(s.randint(1000), 468) - - s = Generator(MT19937(np.arange(10))) - assert_equal(s.integers(1000), 468) - s = Generator(MT19937([0])) - assert_equal(s.integers(1000), 973) - s = Generator(MT19937([4294967295])) - assert_equal(s.integers(1000), 265) - - # Tests using legacy generator - def test_chisquare(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.chisquare, - self.rs.chisquare) - self._is_state_common_legacy() - - def test_standard_gamma(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.standard_gamma, - self.rs.standard_gamma) - self._is_state_common_legacy() - - def test_standard_t(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.standard_t, - self.rs.standard_t) - self._is_state_common_legacy() - - def test_pareto(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.pareto, - self.rs.pareto) - self._is_state_common_legacy() - - def test_power(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.power, - self.rs.power) - self._is_state_common_legacy() - - def test_weibull(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.weibull, - self.rs.weibull) - self._is_state_common_legacy() - - def test_beta(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.beta, - self.rs.beta) - self._is_state_common_legacy() - - def test_exponential(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_1_input(self.nprs.exponential, - self.rs.exponential) - self._is_state_common_legacy() - - def test_f(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.f, - self.rs.f) - self._is_state_common_legacy() - - def test_gamma(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.gamma, - self.rs.gamma) - self._is_state_common_legacy() - - def test_lognormal(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.lognormal, - self.rs.lognormal) - self._is_state_common_legacy() - - def test_noncentral_chisquare(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.noncentral_chisquare, - self.rs.noncentral_chisquare) - self._is_state_common_legacy() - - def test_normal(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.normal, - self.rs.normal) - self._is_state_common_legacy() - - def test_wald(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.wald, - self.rs.wald) - self._is_state_common_legacy() - - def test_negative_binomial(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_2_input(self.nprs.negative_binomial, - self.rs.negative_binomial, - is_np=True) - self._is_state_common_legacy() - - def test_randn(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - f = self.rs.randn - g = self.nprs.randn - assert_allclose(f(10), g(10)) - assert_allclose(f(3, 4, 5), g(3, 4, 5)) - self._is_state_common_legacy() - - def test_dirichlet(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - f = self.rs.dirichlet - g = self.nprs.dirichlet - a = [3, 4, 5, 6, 7, 10] - assert_allclose(f(a), g(a)) - assert_allclose(f(np.array(a), 10), g(np.array(a), 10)) - assert_allclose(f(np.array(a), (3, 37)), g(np.array(a), (3, 37))) - self._is_state_common_legacy() - - def test_noncentral_f(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - compare_3_input(self.nprs.noncentral_f, - self.rs.noncentral_f) - self._is_state_common_legacy() - - def test_multivariate_normal(self): - self._set_common_state_legacy() - self._is_state_common_legacy() - mu = [1, 2, 3] - cov = [[1, .2, .3], [.2, 4, 1], [.3, 1, 10]] - f = self.rs.multivariate_normal - g = self.nprs.multivariate_normal - assert_allclose(f(mu, cov), g(mu, cov)) - assert_allclose(f(np.array(mu), cov), g(np.array(mu), cov)) - assert_allclose(f(np.array(mu), np.array(cov)), - g(np.array(mu), np.array(cov))) - assert_allclose(f(np.array(mu), np.array(cov), size=(7, 31)), - g(np.array(mu), np.array(cov), size=(7, 31))) - self._is_state_common_legacy() - - -funcs = [generator.zipf, - generator.logseries, - generator.poisson] -ids = [f.__name__ for f in funcs] - - -@pytest.mark.filterwarnings('ignore:invalid value encountered:RuntimeWarning') -@pytest.mark.parametrize('func', funcs, ids=ids) -def test_nan_guard(func): - with pytest.raises(ValueError): - func([np.nan]) - with pytest.raises(ValueError): - func(np.nan) - - -def test_cons_gte1_nan_guard(): - with pytest.raises(ValueError): - generator.hypergeometric(10, 10, [np.nan]) - with pytest.raises(ValueError): - generator.hypergeometric(10, 10, np.nan) From 9e5ae6156855e5a2e2edccaf0112362ecb6d31fc Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 23 May 2019 09:30:19 +0100 Subject: [PATCH 131/138] BUG: Change renamed attribute Change renamed attribute --- numpy/random/tests/test_random.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index b367599cd8e4..22e37151c694 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -1447,7 +1447,7 @@ def test_negative_binomial(self): 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] From 7c52c2810e20a9e483e564751b8e2342c97f56c2 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 23 May 2019 11:11:59 +0100 Subject: [PATCH 132/138] DOC: Add __all__ and document lock Add docstring for lock Use __all__ to discuorage unless attributes from appearing --- numpy/random/bounded_integers.pyx.in | 2 ++ numpy/random/common.pyx | 3 ++- numpy/random/dsfmt.pyx | 10 ++++++++++ numpy/random/entropy.pyx | 2 ++ numpy/random/generator.pyx | 12 ++++++++++++ numpy/random/mt19937.pyx | 10 ++++++++++ numpy/random/philox.pyx | 10 ++++++++++ numpy/random/threefry.pyx | 10 ++++++++++ numpy/random/xoshiro256.pyx | 10 ++++++++++ numpy/random/xoshiro512.pyx | 10 ++++++++++ 10 files changed, 78 insertions(+), 1 deletion(-) diff --git a/numpy/random/bounded_integers.pyx.in b/numpy/random/bounded_integers.pyx.in index 9f385f521527..93277652d5ce 100644 --- a/numpy/random/bounded_integers.pyx.in +++ b/numpy/random/bounded_integers.pyx.in @@ -6,6 +6,8 @@ cimport numpy as np from .distributions cimport * +__all__ = [] + np.import_array() _integers_types = {'bool': (0, 2), diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx index fdf930900a07..994de434536f 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -8,6 +8,8 @@ cimport numpy as np from .common cimport * +__all__ = ['interface'] + np.import_array() interface = namedtuple('interface', ['state_address', 'state', 'next_uint64', @@ -929,7 +931,6 @@ cdef object cont_f(void *func, bitgen_t *state, object size, object lock, cdef int requirements = np.NPY_ALIGNED | np.NPY_FORCECAST check_output(out, np.float32, size) a_arr = np.PyArray_FROMANY(a, np.NPY_FLOAT32, 0, 0, requirements) - # a_arr = np.PyArray_FROM_OTF(a, np.NPY_FLOAT32, np.NPY_ALIGNED) is_scalar = np.PyArray_NDIM(a_arr) == 0 if not is_scalar: diff --git a/numpy/random/dsfmt.pyx b/numpy/random/dsfmt.pyx index cd6d9215385f..ea77b7821d1e 100644 --- a/numpy/random/dsfmt.pyx +++ b/numpy/random/dsfmt.pyx @@ -14,6 +14,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy +__all__ = ['DSFMT'] + np.import_array() DEF DSFMT_MEXP = 19937 @@ -83,6 +85,14 @@ cdef class DSFMT: ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a 32-bit hash of the time and process ID is 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 ----- ``DSFMT`` provides a capsule containing function pointers that produce diff --git a/numpy/random/entropy.pyx b/numpy/random/entropy.pyx index 72b0a9851047..ecbacd9c8bfd 100644 --- a/numpy/random/entropy.pyx +++ b/numpy/random/entropy.pyx @@ -3,6 +3,8 @@ 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": diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index 9389e85ee3f7..ae920fc9fd35 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -19,6 +19,18 @@ 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() diff --git a/numpy/random/mt19937.pyx b/numpy/random/mt19937.pyx index 0579b3634349..8b3ca38255cf 100644 --- a/numpy/random/mt19937.pyx +++ b/numpy/random/mt19937.pyx @@ -14,6 +14,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy +__all__ = ['MT19937'] + np.import_array() cdef extern from "src/mt19937/mt19937.h": @@ -59,6 +61,14 @@ cdef class MT19937: ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a 32-bit hash of the time and process ID is 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 ----- ``MT19937`` provides a capsule containing function pointers that produce diff --git a/numpy/random/philox.pyx b/numpy/random/philox.pyx index 19fd643998b2..b36d65d6963b 100644 --- a/numpy/random/philox.pyx +++ b/numpy/random/philox.pyx @@ -11,6 +11,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array +__all__ = ['Philox'] + np.import_array() DEF PHILOX_BUFFER_SIZE=4 @@ -78,6 +80,14 @@ cdef class Philox: a Python int (long in 2.x) 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 diff --git a/numpy/random/threefry.pyx b/numpy/random/threefry.pyx index d008cd828338..02911528b190 100644 --- a/numpy/random/threefry.pyx +++ b/numpy/random/threefry.pyx @@ -11,6 +11,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array +__all__ = ['ThreeFry'] + np.import_array() DEF THREEFRY_BUFFER_SIZE=4 @@ -74,6 +76,14 @@ cdef class ThreeFry: a Python int in [0, 2**256) or a 4-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 ----- ThreeFry is a 64-bit PRNG that uses a counter-based design based on diff --git a/numpy/random/xoshiro256.pyx b/numpy/random/xoshiro256.pyx index 7258ea3fb883..362139cfa147 100644 --- a/numpy/random/xoshiro256.pyx +++ b/numpy/random/xoshiro256.pyx @@ -13,6 +13,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array +__all__ = ['Xoshiro256'] + np.import_array() cdef extern from "src/xoshiro256/xoshiro256.h": @@ -52,6 +54,14 @@ cdef class Xoshiro256: from ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a hash of the time and process ID is 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 ----- xoshiro256** is written by David Blackman and Sebastiano Vigna. diff --git a/numpy/random/xoshiro512.pyx b/numpy/random/xoshiro512.pyx index a2c0a48965b4..0505af207691 100644 --- a/numpy/random/xoshiro512.pyx +++ b/numpy/random/xoshiro512.pyx @@ -13,6 +13,8 @@ from .common cimport * from .distributions cimport bitgen_t from .entropy import random_entropy, seed_by_array +__all__ = ['Xoshiro512'] + np.import_array() cdef extern from "src/xoshiro512/xoshiro512.h": @@ -52,6 +54,14 @@ cdef class Xoshiro512: from ``/dev/urandom`` (or the Windows analog) if available. If unavailable, a hash of the time and process ID is 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 ----- xoshiro512** is written by David Blackman and Sebastiano Vigna. From dabf42be29208a59bbacffd40d9d8dca6e200f49 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 23 May 2019 15:28:22 +0100 Subject: [PATCH 133/138] MAINT: Remove remnants of bit generators Remove traces of the three removed bit generators Add lock to Cython examples --- doc/source/reference/random/extending.rst | 95 +- doc/source/reference/random/generator.rst | 2 +- .../reference/random/multithreading.rst | 12 +- doc/source/reference/random/parallel.rst | 8 +- doc/source/reference/random/performance.py | 7 +- doc/source/reference/random/performance.rst | 67 +- numpy/random/examples/cython/extending.pyx | 28 +- .../cython/extending_distributions.pyx | 24 +- numpy/random/examples/numba/extending.py | 6 +- .../examples/numba/extending_distributions.py | 10 +- numpy/random/mt19937.pyx | 2 +- numpy/random/philox.pyx | 2 +- numpy/random/src/xoroshiro128/LICENSE.md | 9 - .../src/xoroshiro128/xoroshiro128-benchmark.c | 35 - .../xoroshiro128/xoroshiro128-test-data-gen.c | 83 -- numpy/random/src/xoroshiro128/xoroshiro128.c | 60 - numpy/random/src/xoroshiro128/xoroshiro128.h | 53 - .../src/xoroshiro128/xoroshiro128plus.orig.c | 102 -- .../src/xoroshiro128/xoroshiro128plus.orig.h | 5 - numpy/random/src/xorshift1024/LICENSE.md | 9 - .../src/xorshift1024/xorshift1024-benchmark.c | 35 - .../xorshift1024/xorshift1024-test-data-gen.c | 74 -- numpy/random/src/xorshift1024/xorshift1024.c | 32 - numpy/random/src/xorshift1024/xorshift1024.h | 40 - .../src/xorshift1024/xorshift1024.orig.c | 68 -- .../src/xorshift1024/xorshift1024.orig.h | 7 - .../tests/data/threefry32-testset-1.csv | 1001 ----------------- .../tests/data/threefry32-testset-2.csv | 1001 ----------------- .../tests/data/xoroshiro128-testset-1.csv | 1001 ----------------- .../tests/data/xoroshiro128-testset-2.csv | 1001 ----------------- .../tests/data/xorshift1024-testset-1.csv | 1001 ----------------- .../tests/data/xorshift1024-testset-2.csv | 1001 ----------------- numpy/random/tests/test_direct.py | 2 +- numpy/random/threefry.pyx | 2 +- numpy/random/xoshiro256.pyx | 4 +- numpy/random/xoshiro512.pyx | 6 +- 36 files changed, 143 insertions(+), 6752 deletions(-) delete mode 100644 numpy/random/src/xoroshiro128/LICENSE.md delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128-test-data-gen.c delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128.c delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128.h delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c delete mode 100644 numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h delete mode 100644 numpy/random/src/xorshift1024/LICENSE.md delete mode 100644 numpy/random/src/xorshift1024/xorshift1024-benchmark.c delete mode 100644 numpy/random/src/xorshift1024/xorshift1024-test-data-gen.c delete mode 100644 numpy/random/src/xorshift1024/xorshift1024.c delete mode 100644 numpy/random/src/xorshift1024/xorshift1024.h delete mode 100644 numpy/random/src/xorshift1024/xorshift1024.orig.c delete mode 100644 numpy/random/src/xorshift1024/xorshift1024.orig.h delete mode 100644 numpy/random/tests/data/threefry32-testset-1.csv delete mode 100644 numpy/random/tests/data/threefry32-testset-2.csv delete mode 100644 numpy/random/tests/data/xoroshiro128-testset-1.csv delete mode 100644 numpy/random/tests/data/xoroshiro128-testset-2.csv delete mode 100644 numpy/random/tests/data/xorshift1024-testset-1.csv delete mode 100644 numpy/random/tests/data/xorshift1024-testset-2.csv diff --git a/doc/source/reference/random/extending.rst b/doc/source/reference/random/extending.rst index f65d7708f806..28db4021c30e 100644 --- a/doc/source/reference/random/extending.rst +++ b/doc/source/reference/random/extending.rst @@ -18,11 +18,11 @@ provided by ``ctypes.next_double``. .. code-block:: python - from numpy.random import Xoroshiro128 + from numpy.random import Xoshiro256 import numpy as np import numba as nb - x = Xoroshiro128() + x = Xoshiro256() f = x.ctypes.next_double s = x.ctypes.state state_addr = x.ctypes.state_address @@ -50,7 +50,7 @@ provided by ``ctypes.next_double``. # Must use state address not state with numba normalsj(1, state_addr) %timeit normalsj(1000000, state_addr) - print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms') + print('1,000,000 Box-Muller (numba/Xoshiro256) randoms') %timeit np.random.standard_normal(1000000) print('1,000,000 Box-Muller (NumPy) randoms') @@ -66,7 +66,7 @@ Cython ====== Cython can be used to unpack the ``PyCapsule`` provided by a BitGenerator. -This example uses `~xoroshiro128.Xoroshiro128` and +This example uses `~xoshiro256.Xoshiro256` and ``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an array. The usual caveats for writing high-performance code using Cython -- removing bounds checks and wrap around, providing array alignment information @@ -80,54 +80,57 @@ removing bounds checks and wrap around, providing array alignment information 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 Xoroshiro128 - - - @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 = Xoroshiro128() - capsule = x.capsule - if not PyCapsule_IsValid(capsule, capsule_name): - raise ValueError("Invalid pointer to anon_func_state") - rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(n) - for i in range(n): - random_values[i] = random_gauss_zig(rng) - randoms = np.asarray(random_values) - return randoms + from numpy.random import Xoshiro256 + + + @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 = Xoshiro256() + capsule = x.capsule + if not PyCapsule_IsValid(capsule, capsule_name): + raise ValueError("Invalid pointer to anon_func_state") + rng = 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 The BitGenerator can also be directly accessed using the members of the basic RNG structure. .. code-block:: cython - @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 = Xoroshiro128() - capsule = x.capsule - # Optional check that the capsule if from a Basic RNG - if not PyCapsule_IsValid(capsule, capsule_name): - raise ValueError("Invalid pointer to anon_func_state") - # Cast the pointer - rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(n) - for i in range(n): - # Call the function - random_values[i] = rng.next_double(rng.state) - 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 = Xoshiro256() + 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 = 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 These functions along with a minimal setup file are included in the examples folder. diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst index ee70725e710a..8b086e901d8b 100644 --- a/doc/source/reference/random/generator.rst +++ b/doc/source/reference/random/generator.rst @@ -8,7 +8,7 @@ a wide range of distributions, and served as a replacement for the two is that ``Generator`` relies on an additional BitGenerator to manage state and generate the random bits, which are then transformed into random values from useful distributions. The default BitGenerator used by -``Generator`` is :class:`~xoroshiro128.Xoroshiro128`. The BitGenerator +``Generator`` is :class:`~xoshiro256.Xoshiro256`. The BitGenerator can be changed by passing an instantized BitGenerator to ``Generator``. diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst index 718fe05f1440..871425e6d129 100644 --- a/doc/source/reference/random/multithreading.rst +++ b/doc/source/reference/random/multithreading.rst @@ -10,21 +10,21 @@ these requirements. This example makes use of Python 3 :mod:`concurrent.futures` to fill an array using multiple threads. Threads are long-lived so that repeated calls do not require any additional overheads from thread creation. The underlying -BitGenerator is `Xorshift1024` which is fast, has a long period and supports -using `Xorshift1024.jumped` to return a new generator while advancing the +BitGenerator is `Xoshiro256` which is fast, has a long period and supports +using `Xoshiro256.jumped` to return a new generator while advancing the state. The random numbers generated are reproducible in the sense that the same seed will produce the same outputs. .. code-block:: ipython - from numpy.random import Generator, Xorshift1024 + from numpy.random import Generator, Xoshiro256 import multiprocessing import concurrent.futures import numpy as np class MultithreadedRNG(object): def __init__(self, n, seed=None, threads=None): - rg = Xorshift1024(seed) + rg = Xoshiro256(seed) if threads is None: threads = multiprocessing.cpu_count() self.threads = threads @@ -89,7 +89,7 @@ The single threaded call directly uses the BitGenerator. .. code-block:: ipython In [5]: values = np.empty(10000000) - ...: rg = Generator(Xorshift1024()) + ...: rg = Generator(Xoshiro256()) ...: %timeit rg.standard_normal(out=values) 99.6 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) @@ -100,7 +100,7 @@ that does not use an existing array due to array creation overhead. .. code-block:: ipython - In [6]: rg = Generator(Xorshift1024()) + In [6]: rg = Generator(Xoshiro256()) ...: %timeit rg.standard_normal(10000000) 125 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst index 8bdc3f23fd39..40f0bce63819 100644 --- a/doc/source/reference/random/parallel.rst +++ b/doc/source/reference/random/parallel.rst @@ -72,10 +72,6 @@ are listed below. +-----------------+-------------------------+-------------------------+-------------------------+ | ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ -| Xoroshiro128 | :math:`2^{128}` | :math:`2^{64}` | 64 | -+-----------------+-------------------------+-------------------------+-------------------------+ -| Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 | -+-----------------+-------------------------+-------------------------+-------------------------+ | Xoshiro256** | :math:`2^{256}` | :math:`2^{128}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ | Xoshiro512** | :math:`2^{512}` | :math:`2^{256}` | 64 | @@ -87,13 +83,13 @@ overlap. .. code-block:: python from numpy.random.entropy import random_entropy - from numpy.random import Xorshift1024 + from numpy.random import Xoshiro256 entropy = random_entropy(2).astype(np.uint64) # 64-bit number as a seed seed = entropy[0] * 2**32 + entropy[1] blocked_rng = [] - rng = Xorshift1024(seed) + rng = Xoshiro256(seed) for i in range(10): blocked_rng.append(rng.jumped(i)) diff --git a/doc/source/reference/random/performance.py b/doc/source/reference/random/performance.py index a29e09c41b5d..bbf17b1d0aef 100644 --- a/doc/source/reference/random/performance.py +++ b/doc/source/reference/random/performance.py @@ -4,11 +4,10 @@ import numpy as np import pandas as pd -from numpy.random import MT19937, DSFMT, ThreeFry, Xoroshiro128, \ - Xorshift1024, Philox, Xoshiro256, Xoshiro512 +from numpy.random import MT19937, DSFMT, ThreeFry, Philox, Xoshiro256, \ + Xoshiro512 -PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoroshiro128, Xorshift1024, - Xoshiro256, Xoshiro512] +PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoshiro256, Xoshiro512] funcs = {'32-bit Unsigned Ints': 'integers(0, 2**32,size=1000000, dtype="uint32")', '64-bit Unsigned Ints': 'integers(0, 2**64,size=1000000, dtype="uint64")', diff --git a/doc/source/reference/random/performance.rst b/doc/source/reference/random/performance.rst index 61898ac89a8d..395744eb8afd 100644 --- a/doc/source/reference/random/performance.rst +++ b/doc/source/reference/random/performance.rst @@ -8,25 +8,22 @@ Performance Recommendation ************** The recommended generator for single use is -:class:`~xoroshiro128.Xoroshiro128`. The recommended generator +:class:`~.xoshiro256.Xoshiro256`. The recommended generator for use in large-scale parallel applications is -:class:`~.xoshiro256.Xoshiro256` -where the `jumped` method is used to advance the state. For very large scale -applications -- requiring 1,000+ independent streams, -:class:`~.philox.Philox` is the best choice. +:class:`~.xoshiro512.Xoshiro512` where the `jumped` method is used to advance +the state. For very large scale applications -- requiring 1,000+ independent +streams -- :class:`~.philox.Philox` is the best choice. Timings ******* The timings below are the time in ns to produce 1 random value from a -specific distribution. :class:`~xoroshiro128.Xoroshiro128` is the -fastest, followed by :class:`~xorshift1024.Xorshift1024`. The original -:class:`~mt19937.MT19937` generator is much slower since it requires 2 32-bit -values to equal the output of the faster generators. +specific distribution. The original :class:`~mt19937.MT19937` generator is +much slower since it requires 2 32-bit values to equal the output of the +faster generators. Integer performance has a similar ordering although `dSFMT` is slower since -it generates 53-bit floating point values rather than integer values. On the -other hand, it is very fast for uniforms, although slower than `xoroshiro128+`. +it generates 53-bit floating point values rather than integer values. The pattern is similar for other, more complex generators. The normal performance of NumPy's MT19937 is much lower than the other since it @@ -35,38 +32,38 @@ performance gap for Exponentials is also large due to the cost of computing the log function to invert the CDF. .. csv-table:: - :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry,NumPy + :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,NumPy,ThreeFry :widths: 14,14,14,14,14,14,14,14 - 64-bit Unsigned Ints,11.9,13.6,14.9,18.0,22.0,25.9,42.0 - Uniforms,16.3,15.6,16.0,19.1,23.5,25.5,44.1 - 32-bit Unsigned Ints,21.6,23.7,23.1,23.6,27.9,32.3,17.9 - Exponentials,21.2,22.4,23.8,26.7,30.8,33.0,115.3 - Normals,25.1,26.9,26.2,31.7,32.6,37.8,106.8 - Binomials,72.4,73.0,71.9,77.4,80.0,83.1,101.9 - Complex Normals,80.4,86.4,81.1,93.4,96.3,105.5, - Laplaces,97.0,97.4,99.6,109.8,102.3,105.1,125.3 - Gammas,91.3,91.2,94.8,101.7,108.7,113.8,187.9 - Poissons,136.7,137.6,139.7,161.9,171.0,181.0,265.1 + 32-bit Unsigned Ints,2.6,2.9,3.4,3.2,5.0,3.3,7.6 + 64-bit Unsigned Ints,3.1,4.0,5.6,5.7,6.6,8.1,13.4 + Uniforms,3.7,4.2,3.2,7.4,9.1,8.9,13.5 + Exponentials,4.3,5.3,7.3,8.2,9.7,42.4,14.9 + Normals,8.2,8.9,11.7,13.4,15.0,37.3,18.6 + Binomials,20.0,20.8,19.8,26.4,28.2,26.6,31.0 + Gammas,26.4,28.7,30.4,37.1,38.8,62.9,49.0 + Laplaces,40.2,40.0,39.4,48.7,51.2,47.4,51.4 + Poissons,48.8,51.6,47.8,73.6,82.3,74.0,90.6 -The next table presents the performance relative to `xoroshiro128+` in -percentage. The overall performance was computed using a geometric mean. +The next table presents the performance in percentage relative to values +generated by the legagy generator, `RandomState(MT19937())`. The overall +performance was computed using a geometric mean. .. csv-table:: - :header: ,Xoroshiro128,Xoshiro256**,Xorshift1024,MT19937,Philox,ThreeFry + :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,ThreeFry :widths: 14,14,14,14,14,14,14 - 64-bit Unsigned Ints,353,309,283,233,191,162 - Uniforms,271,283,276,232,188,173 - 32-bit Unsigned Ints,83,76,78,76,64,56 - Exponentials,544,514,485,432,375,350 - Normals,425,397,407,337,328,283 - Binomials,141,140,142,132,127,123 - Laplaces,129,129,126,114,123,119 - Gammas,206,206,198,185,173,165 - Poissons,194,193,190,164,155,146 - Overall,223,215,210,186,170,156 + 32-bit Unsigned Ints,129,113,98,103,66,44 + 64-bit Unsigned Ints,258,202,145,142,122,61 + Uniforms,244,214,283,121,98,66 + Exponentials,981,796,580,518,436,285 + Normals,453,417,319,278,249,200 + Binomials,133,128,134,101,94,86 + Gammas,238,219,207,170,162,129 + Laplaces,118,118,120,97,93,92 + Poissons,152,144,155,101,90,82 + Overall,233,209,194,152,130,98 .. note:: diff --git a/numpy/random/examples/cython/extending.pyx b/numpy/random/examples/cython/extending.pyx index 858bf2f62494..b2418e93c349 100644 --- a/numpy/random/examples/cython/extending.pyx +++ b/numpy/random/examples/cython/extending.pyx @@ -9,31 +9,38 @@ cimport numpy as np cimport cython from numpy.random.common cimport bitgen_t -from numpy.random import Xoroshiro128 +from numpy.random import Xoshiro256 np.import_array() -def uniform_mean(Py_ssize_t N): +@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 = Xoroshiro128() + x = Xoshiro256() capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") rng = PyCapsule_GetPointer(capsule, capsule_name) - random_values = np.empty(N) - for i in range(N): - random_values[i] = rng.next_double(rng.state) + 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() -cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, bitgen_t *rng): +# 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 @@ -57,7 +64,7 @@ def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): cdef uint32_t[::1] out cdef const char *capsule_name = "BitGenerator" - x = Xoroshiro128() + x = Xoshiro256() out = np.empty(n, dtype=np.uint32) capsule = x.capsule @@ -65,6 +72,7 @@ def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n): raise ValueError("Invalid pointer to anon_func_state") rng = PyCapsule_GetPointer(capsule, capsule_name) - for i in range(n): - out[i] = bounded_uint(lb, ub, rng) + 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 index da584e941a71..89477eb6d14e 100644 --- a/numpy/random/examples/cython/extending_distributions.pyx +++ b/numpy/random/examples/cython/extending_distributions.pyx @@ -1,13 +1,16 @@ #!/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 Xoroshiro128 +from numpy.random import Xoshiro256 @cython.boundscheck(False) @@ -18,14 +21,16 @@ def normals_zig(Py_ssize_t n): cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values - x = Xoroshiro128() + x = Xoshiro256() capsule = x.capsule if not PyCapsule_IsValid(capsule, capsule_name): raise ValueError("Invalid pointer to anon_func_state") rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) - for i in range(n): - random_values[i] = random_gauss_zig(rng) + # 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 @@ -38,7 +43,7 @@ def uniforms(Py_ssize_t n): cdef const char *capsule_name = "BitGenerator" cdef double[::1] random_values - x = Xoroshiro128() + x = Xoshiro256() capsule = x.capsule # Optional check that the capsule if from a BitGenerator if not PyCapsule_IsValid(capsule, capsule_name): @@ -46,8 +51,9 @@ def uniforms(Py_ssize_t n): # Cast the pointer rng = PyCapsule_GetPointer(capsule, capsule_name) random_values = np.empty(n) - for i in range(n): - # Call the function - random_values[i] = rng.next_double(rng.state) + 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/numba/extending.py b/numpy/random/examples/numba/extending.py index 72e903b1f19a..a1a2b3d1253d 100644 --- a/numpy/random/examples/numba/extending.py +++ b/numpy/random/examples/numba/extending.py @@ -3,9 +3,9 @@ import numpy as np import numba as nb -from randomgen import Xoroshiro128 +from numpy.random import Xoshiro256 -x = Xoroshiro128() +x = Xoshiro256() f = x.ctypes.next_uint32 s = x.ctypes.state @@ -68,7 +68,7 @@ def normals(n, state): start = dt.datetime.now() normalsj(1000000, state_addr) ms = 1000 * (dt.datetime.now() - start).total_seconds() -print('1,000,000 Polar-transform (numba/Xoroshiro128) randoms in ' +print('1,000,000 Polar-transform (numba/Xoshiro256) randoms in ' '{ms:0.1f}ms'.format(ms=ms)) start = dt.datetime.now() diff --git a/numpy/random/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py index e1a57fa4f349..f1f9003a9942 100644 --- a/numpy/random/examples/numba/extending_distributions.py +++ b/numpy/random/examples/numba/extending_distributions.py @@ -5,8 +5,7 @@ ${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} +gcc -shared -o libdistributions.so -fPIC distributions.c -I${NUMPY_INCLUDE} -I${PYTHON_INCLUDE} mv libdistributions.so ../../examples/numba/ On Windows @@ -24,7 +23,7 @@ import numpy as np from cffi import FFI -from randomgen import Xoroshiro128 +from numpy.random import Xoshiro256 ffi = FFI() if os.path.exists('./distributions.dll'): @@ -37,9 +36,9 @@ ffi.cdef(""" double random_gauss_zig(void *bitgen_state); """) -x = Xoroshiro128() +x = Xoshiro256() xffi = x.cffi -bit_generator = xffi.bitgen +bit_generator = xffi.bit_generator random_gauss_zig = lib.random_gauss_zig @@ -58,3 +57,4 @@ def normals(n, bit_generator): bit_generator_address = int(ffi.cast('uintptr_t', bit_generator)) norm = normalsj(1000, bit_generator_address) +print(norm[:12]) diff --git a/numpy/random/mt19937.pyx b/numpy/random/mt19937.pyx index 8b3ca38255cf..56e425ab7cf8 100644 --- a/numpy/random/mt19937.pyx +++ b/numpy/random/mt19937.pyx @@ -276,7 +276,7 @@ cdef class MT19937: Returns ------- - bit_generator : Xoroshiro128 + bit_generator : MT19937 New instance of generator jumped iter times """ cdef MT19937 bit_generator diff --git a/numpy/random/philox.pyx b/numpy/random/philox.pyx index b36d65d6963b..45b4087aca5c 100644 --- a/numpy/random/philox.pyx +++ b/numpy/random/philox.pyx @@ -372,7 +372,7 @@ cdef class Philox: Returns ------- - bit_generator : Xoroshiro128 + bit_generator : Philox New instance of generator jumped iter times """ cdef Philox bit_generator diff --git a/numpy/random/src/xoroshiro128/LICENSE.md b/numpy/random/src/xoroshiro128/LICENSE.md deleted file mode 100644 index 969430149615..000000000000 --- a/numpy/random/src/xoroshiro128/LICENSE.md +++ /dev/null @@ -1,9 +0,0 @@ -# XOROSHIRO128 - -Written in 2016 by David Blackman and 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 . \ No newline at end of file diff --git a/numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c b/numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c deleted file mode 100644 index 9a7b52bfbf29..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128-benchmark.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * cl xoroshiro128-benchmark.c xoroshiro128plus.orig.c \ - * ../splitmix64/splitmix64.c /Ox - * - * gcc -O3 xoroshiro128-benchmark.c xoroshiro128plus.orig.c \ - * ../splitmix64/splitmix64.c -o xoroshiro128-benchmark - * - */ -#include "../splitmix64/splitmix64.h" -#include "xoroshiro128plus.orig.h" -#include -#include -#include - -#define N 1000000000 - -int main() -{ - uint64_t count = 0, sum = 0; - uint64_t seed = 0xDEADBEAF; - s[0] = splitmix64_next(&seed); - s[1] = splitmix64_next(&seed); - int i; - clock_t begin = clock(); - for (i = 0; i < N; i++) - { - sum += next(); - 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/xoroshiro128/xoroshiro128-test-data-gen.c b/numpy/random/src/xoroshiro128/xoroshiro128-test-data-gen.c deleted file mode 100644 index d50e63f5e6da..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128-test-data-gen.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Generate testing csv files - * - * cl xoroshiro128-test-data-gen.c xoroshiro128plus.orig.c / - * ../splitmix64/splitmix64.c /Ox - * xoroshiro128-test-data-gen.exe * - * - * gcc xoroshiro128-test-data-gen.c xoroshiro128plus.orig.c / - * ../splitmix64/splitmix64.c -o xoroshiro128-test-data-gen - * ./xoroshiro128-test-data-gen - * - * Requres the Random123 directory containing header files to be located in the - * same directory (not included). - * - */ - -#include "../splitmix64/splitmix64.h" -#include "xoroshiro128plus.orig.h" -#include -#include - -#define N 1000 - -int main() -{ - uint64_t sum = 0; - uint64_t state, seed = 0xDEADBEAF; - state = seed; - int i; - for (i = 0; i < 2; i++) - { - s[i] = splitmix64_next(&state); - } - uint64_t store[N]; - for (i = 0; i < N; i++) - { - store[i] = next(); - } - - FILE *fp; - fp = fopen("xoroshiro128-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); - - seed = state = 0; - for (i = 0; i < 2; i++) - { - s[i] = splitmix64_next(&state); - } - for (i = 0; i < N; i++) - { - store[i] = next(); - } - fp = fopen("xoroshiro128-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/xoroshiro128/xoroshiro128.c b/numpy/random/src/xoroshiro128/xoroshiro128.c deleted file mode 100644 index baefcf3a8b19..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Written in 2016-2018 by David Blackman and 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 . */ - -/* This is xoroshiro128+ 1.0, our best and fastest small-state generator - for floating-point numbers. We suggest to use its upper bits for - floating-point generation, as it is slightly faster than - xoroshiro128**. It passes all tests we are aware of except for the four - lower bits, which might fail linearity tests (and just those), so if - low linear complexity is not considered an issue (as it is usually the - case) it can be used to generate 64-bit outputs, too; moreover, this - generator has a very mild Hamming-weight dependency making our test - (http://prng.di.unimi.it/hwd.php) fail after 5 TB of output; we believe - this slight bias cannot affect any application. If you are concerned, - use xoroshiro128** or xoshiro256+. - - We suggest to use a sign test to extract a random Boolean value, and - right shifts to extract subsets of bits. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s. - - NOTE: the parameters (a=24, b=16, b=37) of this version give slightly - better results in our test than the 2016 version (a=55, b=14, c=36). -*/ - -#include "xoroshiro128.h" - -extern NPY_INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state); - -extern NPY_INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state); - -void xoroshiro128_jump(xoroshiro128_state *state) -{ - int i, b; - uint64_t s0; - uint64_t s1; - static const uint64_t JUMP[] = {0xdf900294d8f554a5, 0x170865df4b3201fc}; - - s0 = 0; - s1 = 0; - for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (b = 0; b < 64; b++) - { - if (JUMP[i] & UINT64_C(1) << b) - { - s0 ^= state->s[0]; - s1 ^= state->s[1]; - } - xoroshiro128_next(&state->s[0]); - } - - state->s[0] = s0; - state->s[1] = s1; -} diff --git a/numpy/random/src/xoroshiro128/xoroshiro128.h b/numpy/random/src/xoroshiro128/xoroshiro128.h deleted file mode 100644 index 63682776bfd9..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _RANDOMDGEN__XOROSHIRO128_H_ -#define _RANDOMDGEN__XOROSHIRO128_H_ - -#include -#include "numpy/npy_common.h" - -typedef struct s_xoroshiro128_state -{ - uint64_t s[2]; - int has_uint32; - uint32_t uinteger; -} xoroshiro128_state; - -static NPY_INLINE uint64_t rotl(const uint64_t x, int k) -{ - return (x << k) | (x >> (64 - k)); -} - -static NPY_INLINE uint64_t xoroshiro128_next(uint64_t *s) -{ - const uint64_t s0 = s[0]; - uint64_t s1 = s[1]; - const uint64_t result = s0 + s1; - - s1 ^= s0; - s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b - s[1] = rotl(s1, 37); // c - - return result; -} - -static NPY_INLINE uint64_t xoroshiro128_next64(xoroshiro128_state *state) -{ - return xoroshiro128_next(&state->s[0]); -} - -static NPY_INLINE uint32_t xoroshiro128_next32(xoroshiro128_state *state) -{ - uint64_t next; - if (state->has_uint32) - { - state->has_uint32 = 0; - return state->uinteger; - } - next = xoroshiro128_next(&state->s[0]); - state->has_uint32 = 1; - state->uinteger = (uint32_t)(next >> 32); - return (uint32_t)(next & 0xffffffff); -} - -void xoroshiro128_jump(xoroshiro128_state *state); - -#endif diff --git a/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c b/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c deleted file mode 100644 index 1b5f46e4bdb5..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Written in 2016-2018 by David Blackman and 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 . */ - -#include - -/* This is xoroshiro128+ 1.0, our best and fastest small-state generator - for floating-point numbers. We suggest to use its upper bits for - floating-point generation, as it is slightly faster than - xoroshiro128**. It passes all tests we are aware of except for the four - lower bits, which might fail linearity tests (and just those), so if - low linear complexity is not considered an issue (as it is usually the - case) it can be used to generate 64-bit outputs, too; moreover, this - generator has a very mild Hamming-weight dependency making our test - (http://prng.di.unimi.it/hwd.php) fail after 5 TB of output; we believe - this slight bias cannot affect any application. If you are concerned, - use xoroshiro128** or xoshiro256+. - - We suggest to use a sign test to extract a random Boolean value, and - right shifts to extract subsets of bits. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s. - - NOTE: the parameters (a=24, b=16, b=37) of this version give slightly - better results in our test than the 2016 version (a=55, b=14, c=36). -*/ - -uint64_t s[2]; - -static inline uint64_t rotl(const uint64_t x, int k) -{ - return (x << k) | (x >> (64 - k)); -} - -uint64_t next(void) -{ - const uint64_t s0 = s[0]; - uint64_t s1 = s[1]; - const uint64_t result = s0 + s1; - - s1 ^= s0; - s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b - s[1] = rotl(s1, 37); // c - - return result; -} - -/* This is the jump function for the generator. It is equivalent - to 2^64 calls to next(); it can be used to generate 2^64 - non-overlapping subsequences for parallel computations. */ - -void jump(void) -{ - static const uint64_t JUMP[] = {0xdf900294d8f554a5, 0x170865df4b3201fc}; - - uint64_t s0 = 0; - uint64_t s1 = 0; - for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (int b = 0; b < 64; b++) - { - if (JUMP[i] & UINT64_C(1) << b) - { - s0 ^= s[0]; - s1 ^= s[1]; - } - next(); - } - s[0] = s0; - s[1] = s1; -} - -/* This is the long-jump function for the generator. It is equivalent to - 2^96 calls to next(); it can be used to generate 2^32 starting points, - from each of which jump() will generate 2^32 non-overlapping - subsequences for parallel distributed computations. */ - -void long_jump(void) -{ - static const uint64_t LONG_JUMP[] = {0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1}; - - uint64_t s0 = 0; - uint64_t s1 = 0; - for (int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) - for (int b = 0; b < 64; b++) - { - if (LONG_JUMP[i] & UINT64_C(1) << b) - { - s0 ^= s[0]; - s1 ^= s[1]; - } - next(); - } - - s[0] = s0; - s[1] = s1; -} diff --git a/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h b/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h deleted file mode 100644 index 20c96fe04dec..000000000000 --- a/numpy/random/src/xoroshiro128/xoroshiro128plus.orig.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -uint64_t s[2]; -uint64_t next(void); -void jump(void); diff --git a/numpy/random/src/xorshift1024/LICENSE.md b/numpy/random/src/xorshift1024/LICENSE.md deleted file mode 100644 index 3ca8ed4b9898..000000000000 --- a/numpy/random/src/xorshift1024/LICENSE.md +++ /dev/null @@ -1,9 +0,0 @@ -# XORSHIFT1024 - -Written in 2017 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 . \ No newline at end of file diff --git a/numpy/random/src/xorshift1024/xorshift1024-benchmark.c b/numpy/random/src/xorshift1024/xorshift1024-benchmark.c deleted file mode 100644 index 0eef33537090..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024-benchmark.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * cl xorshift1024-benchmark.c xorshift2014.orig.c - * ../splitmix64/splitmix64.c /Ox - * - * gcc -O3 xorshift1024-benchmark.c xorshift2014.orig.c / - * ../splitmix64/splitmix64.c -o xorshift1024-benchmark - * - */ -#include "../splitmix64/splitmix64.h" -#include "xorshift1024.orig.h" -#include -#include -#include - -#define N 1000000000 - -int main() { - uint64_t count = 0, sum = 0; - uint64_t seed = 0xDEADBEAF; - int i; - for (i = 0; i < 16; i++) { - s[i] = splitmix64_next(&seed); - } - p = 0; - clock_t begin = clock(); - for (i = 0; i < N; i++) { - sum += next(); - 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/xorshift1024/xorshift1024-test-data-gen.c b/numpy/random/src/xorshift1024/xorshift1024-test-data-gen.c deleted file mode 100644 index a2ae08df4f6b..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024-test-data-gen.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Generate testing csv files - * - * cl xorshift1024-test-data-gen.c xorshift1024.orig.c / - * ../splitmix64/splitmix64.c /Ox - * xorshift1024-test-data-gen.exe * - * - * gcc xorshift1024-test-data-gen.c xorshift1024.orig.c / - * ../splitmix64/splitmix64.c -o xorshift1024-test-data-gen - * ./xorshift1024-test-data-gen - * - * Requres the Random123 directory containing header files to be located in the - * same directory (not included). - * - */ - -#include "../splitmix64/splitmix64.h" -#include "xorshift1024.orig.h" -#include -#include - -#define N 1000 - -int main() { - uint64_t sum = 0; - uint64_t state, seed = 0xDEADBEAF; - state = seed; - int i; - for (i = 0; i < 16; i++) { - s[i] = splitmix64_next(&state); - } - p = 0; - uint64_t store[N]; - for (i = 0; i < N; i++) { - store[i] = next(); - } - - FILE *fp; - fp = fopen("xorshift1024-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); - - seed = state = 0; - for (i = 0; i < 16; i++) { - s[i] = splitmix64_next(&state); - } - p = 0; - for (i = 0; i < N; i++) { - store[i] = next(); - } - fp = fopen("xorshift1024-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/xorshift1024/xorshift1024.c b/numpy/random/src/xorshift1024/xorshift1024.c deleted file mode 100644 index d68ecc7d3a45..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "xorshift1024.h" - -/* This is the jump function for the generator. It is equivalent - to 2^512 calls to next(); it can be used to generate 2^512 - non-overlapping subsequences for parallel computations. */ - -extern NPY_INLINE uint64_t xorshift1024_next(xorshift1024_state *state); -extern NPY_INLINE uint64_t xorshift1024_next64(xorshift1024_state *state); -extern NPY_INLINE uint32_t xorshift1024_next32(xorshift1024_state *state); - -void xorshift1024_jump(xorshift1024_state *state) { - int i, j, b; - static const uint64_t JUMP[] = { - 0x84242f96eca9c41d, 0xa3c65b8776f96855, 0x5b34a39f070b5837, - 0x4489affce4f31a1e, 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, - 0x3659132bb12fea70, 0xaac17d8efa43cab8, 0xc4cb815590989b13, - 0x5ee975283d71c93b, 0x691548c86c1bd540, 0x7910c41d10a1e6a5, - 0x0b5fc64563b3e2a8, 0x047f7684e9fc949d, 0xb99181f2d8f685ca, - 0x284600e3f30e38c3}; - - uint64_t t[16] = {0}; - for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) - for (j = 0; j < 16; j++) - t[j] ^= state->s[(j + state->p) & 15]; - xorshift1024_next(state); - } - - for (j = 0; j < 16; j++) - state->s[(j + state->p) & 15] = t[j]; -} diff --git a/numpy/random/src/xorshift1024/xorshift1024.h b/numpy/random/src/xorshift1024/xorshift1024.h deleted file mode 100644 index 38ec27430199..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _RANDOMDGEN__XORSHIFT1024_H_ -#define _RANDOMDGEN__XORSHIFT1024_H_ - -#include -#include "numpy/npy_common.h" - -typedef struct s_xorshift1024_state { - uint64_t s[16]; - int p; - int has_uint32; - uint32_t uinteger; -} xorshift1024_state; - -static NPY_INLINE uint64_t xorshift1024_next(xorshift1024_state *state) { - const uint64_t s0 = state->s[state->p]; - uint64_t s1 = state->s[state->p = ((state->p) + 1) & 15]; - s1 ^= s1 << 31; // a - state->s[state->p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c - return state->s[state->p] * 0x9e3779b97f4a7c13; -} - -static NPY_INLINE uint64_t xorshift1024_next64(xorshift1024_state *state) { - return xorshift1024_next(state); -} - -static NPY_INLINE uint32_t xorshift1024_next32(xorshift1024_state *state) { - uint64_t next; - if (state->has_uint32) { - state->has_uint32 = 0; - return state->uinteger; - } - next = xorshift1024_next(state); - state->has_uint32 = 1; - state->uinteger = (uint32_t)(next >> 32); - return (uint32_t)(next & 0xffffffff); -} - -void xorshift1024_jump(xorshift1024_state *state); - -#endif diff --git a/numpy/random/src/xorshift1024/xorshift1024.orig.c b/numpy/random/src/xorshift1024/xorshift1024.orig.c deleted file mode 100644 index 03c1c17fe800..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024.orig.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Written in 2017 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 . */ - -#include -#include - -/* NOTE: as of 2017-10-08, this generator has a different multiplier (a - fixed-point representation of the golden ratio), which eliminates - linear dependencies from one of the lowest bits. The previous - multiplier was 1181783497276652981 (M_8 in the paper). If you need to - tell apart the two generators, you can refer to this generator as - xorshift1024φ and to the previous one as xorshift1024*M_8. - - This is a fast, high-quality generator. If 1024 bits of state are too - much, try a xoroshiro128+ generator. - - Note that the two lowest bits of this generator are LFSRs of degree - 1024, and thus will fail binary rank tests. The other bits needs a much - higher degree to be represented as LFSRs. - - We suggest to use a sign test to extract a random Boolean value, and - right shifts to extract subsets of bits. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s. */ - -uint64_t s[16]; -int p; - -uint64_t next(void) { - const uint64_t s0 = s[p]; - uint64_t s1 = s[p = (p + 1) & 15]; - s1 ^= s1 << 31; // a - s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c - return s[p] * 0x9e3779b97f4a7c13; -} - -/* This is the jump function for the generator. It is equivalent - to 2^512 calls to next(); it can be used to generate 2^512 - non-overlapping subsequences for parallel computations. */ - -void jump(void) { - static const uint64_t JUMP[] = { - 0x84242f96eca9c41d, 0xa3c65b8776f96855, 0x5b34a39f070b5837, - 0x4489affce4f31a1e, 0x2ffeeb0a48316f40, 0xdc2d9891fe68c022, - 0x3659132bb12fea70, 0xaac17d8efa43cab8, 0xc4cb815590989b13, - 0x5ee975283d71c93b, 0x691548c86c1bd540, 0x7910c41d10a1e6a5, - 0x0b5fc64563b3e2a8, 0x047f7684e9fc949d, 0xb99181f2d8f685ca, - 0x284600e3f30e38c3}; - - uint64_t t[16] = {0}; - for (int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) - for (int b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) - for (int j = 0; j < 16; j++) - t[j] ^= s[(j + p) & 15]; - next(); - } - - for (int j = 0; j < 16; j++) - s[(j + p) & 15] = t[j]; -} diff --git a/numpy/random/src/xorshift1024/xorshift1024.orig.h b/numpy/random/src/xorshift1024/xorshift1024.orig.h deleted file mode 100644 index 9b7597967677..000000000000 --- a/numpy/random/src/xorshift1024/xorshift1024.orig.h +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -uint64_t s[16]; -int p; -uint64_t next(void); -void jump(void); diff --git a/numpy/random/tests/data/threefry32-testset-1.csv b/numpy/random/tests/data/threefry32-testset-1.csv deleted file mode 100644 index 3aec7304df34..000000000000 --- a/numpy/random/tests/data/threefry32-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0x6cffcc99 -1, 0x2b7c051c -2, 0x4ab0b74a -3, 0xee73ea3c -4, 0x5b43def8 -5, 0x7e166501 -6, 0xead67c35 -7, 0xa8bd9381 -8, 0x67d79512 -9, 0x18a341e4 -10, 0xd6672c17 -11, 0x40a13b1e -12, 0xcd31ce04 -13, 0x12fdb46d -14, 0xf2fd0ffa -15, 0x4e4fc443 -16, 0x61a53917 -17, 0xff60cc00 -18, 0x51671412 -19, 0xf3a08627 -20, 0x5ba59f45 -21, 0x1a9f5793 -22, 0x3e2a31fe -23, 0xa2242742 -24, 0xcafae297 -25, 0x5eb5a116 -26, 0x23ef9e16 -27, 0x54f01377 -28, 0x47114dcb -29, 0x4ce52425 -30, 0xc898c3a8 -31, 0xf34d52b -32, 0xf05e3aea -33, 0x8e122dd -34, 0x57ed51e5 -35, 0xa949f8c1 -36, 0x6b0c6ca2 -37, 0xeaff706a -38, 0x7ff23d83 -39, 0xb29857d5 -40, 0xbc79b2d3 -41, 0x350e2f98 -42, 0x3deae452 -43, 0x75c70896 -44, 0x8743a85c -45, 0x8c05ccda -46, 0xbb547a23 -47, 0x53f341ee -48, 0xfdf5fe22 -49, 0x6bea4979 -50, 0x1dc06326 -51, 0x58f1fc83 -52, 0x1130e7e5 -53, 0xc434fc00 -54, 0x13acc9b6 -55, 0x198a6356 -56, 0xe59278f7 -57, 0x720ce91c -58, 0xa4587617 -59, 0xa68be124 -60, 0xd54392ab -61, 0x19eeb16a -62, 0x5abac829 -63, 0x2303dcdd -64, 0xaffc0c4c -65, 0xd3757435 -66, 0x8fd204f -67, 0x7f48f1d -68, 0x94512051 -69, 0x4d5d385b -70, 0xd4877f13 -71, 0x834af295 -72, 0xf97fca51 -73, 0x31b766b5 -74, 0xa25a5371 -75, 0x21ae0ebb -76, 0xe5e1066a -77, 0x1633cf01 -78, 0xab411bb9 -79, 0xb2982b5c -80, 0x67cc822b -81, 0x2eabd825 -82, 0x21e0dc17 -83, 0xb9170084 -84, 0x53c52c00 -85, 0x3acc5cec -86, 0x985ce088 -87, 0xf6e2d9b1 -88, 0x37cc5a23 -89, 0x34222cf3 -90, 0xc8f6823a -91, 0x581173b2 -92, 0x300416ea -93, 0x2357d4ad -94, 0x1bfceca9 -95, 0x48e6cdc5 -96, 0xcbf8d214 -97, 0x25c47e6a -98, 0x8a99c824 -99, 0x367c07b6 -100, 0x38643cfb -101, 0x7899c225 -102, 0xefd1c7f9 -103, 0xdfd3d507 -104, 0x7a868d74 -105, 0xac8cfcfa -106, 0x901aac22 -107, 0x52d4f1e5 -108, 0xb8d0b9a3 -109, 0x4d1ac438 -110, 0x1b6995e3 -111, 0xf2b49c8c -112, 0xa4ee5aa9 -113, 0x63f48457 -114, 0x1f092683 -115, 0xe1ffa0c1 -116, 0x64c14ec9 -117, 0x7c86caae -118, 0x96810301 -119, 0xfdeb5934 -120, 0x70636d11 -121, 0x857cc412 -122, 0x83244693 -123, 0xa46e5de7 -124, 0x47406f19 -125, 0x34a31ade -126, 0xb5168ae6 -127, 0xca6e0cc1 -128, 0xb7f612e6 -129, 0x296f0512 -130, 0xe7230082 -131, 0xde6f547f -132, 0xf12bd1cc -133, 0xf51dd599 -134, 0x8a5ab59e -135, 0xd8b1cd87 -136, 0xe81304df -137, 0x3c0ddff1 -138, 0xc6d3a649 -139, 0x2d950bdb -140, 0xafecc338 -141, 0x5b20a006 -142, 0x6d813023 -143, 0xcb698f0f -144, 0xdb7ba980 -145, 0x78942bed -146, 0xb12a3df5 -147, 0xde84510e -148, 0xe99351ee -149, 0xbe5ff58e -150, 0xe0fd9ef -151, 0x1e4b9d22 -152, 0x8bca03a1 -153, 0x7c6377a0 -154, 0x37fbd0a3 -155, 0xe8bef1ba -156, 0xb14651cb -157, 0x3e69d08a -158, 0x56cc688a -159, 0xf86ddf5a -160, 0xd5818aff -161, 0xfe1b8f29 -162, 0x2b505d54 -163, 0xd85caf4 -164, 0x7d360464 -165, 0x276c469 -166, 0xb949fc4a -167, 0xc2bef2ac -168, 0xd07c9118 -169, 0xb0ac2494 -170, 0xbda3bc0f -171, 0xc3fe015d -172, 0x741b443 -173, 0xafd4a887 -174, 0xc3ee9b82 -175, 0x12a16e1b -176, 0x7c3a37f9 -177, 0xee996915 -178, 0x52e7f5a0 -179, 0x1f3880de -180, 0x8735c769 -181, 0x7e51e99b -182, 0xf3c35d4c -183, 0x49f56f0 -184, 0x18c5a61f -185, 0x76a3685f -186, 0xabe0061f -187, 0x9393af8b -188, 0x97fc918b -189, 0xf512e881 -190, 0x2ddd9768 -191, 0x1b7c2e28 -192, 0x5f6a6f1f -193, 0x7960eb61 -194, 0x7805d6c2 -195, 0x20165f7a -196, 0x77490b1c -197, 0xb2cdd255 -198, 0xe6d1bcb5 -199, 0x9687e506 -200, 0x55a213f7 -201, 0xedf9c17d -202, 0xdeec02a8 -203, 0x9d182919 -204, 0x61a1d691 -205, 0xedfa20aa -206, 0x843a4793 -207, 0x56d799cd -208, 0x8535f679 -209, 0x37dbf765 -210, 0x92353041 -211, 0x82532156 -212, 0xa118dd43 -213, 0x198bda1e -214, 0x5d8d60f4 -215, 0xcef238f2 -216, 0x8474c6e0 -217, 0x169a9ab1 -218, 0x50cc819 -219, 0x9b3bda9a -220, 0xd813c3ec -221, 0x8dafb7c4 -222, 0xf3d9ace2 -223, 0x8b9cf3da -224, 0xe9d8fd48 -225, 0xaa7f1866 -226, 0xe8186b07 -227, 0xd6ff13a4 -228, 0xc4a41308 -229, 0xefa359f6 -230, 0x4b257335 -231, 0xffda6c5e -232, 0xc3f7362 -233, 0xe3b123cf -234, 0xe774fc0c -235, 0x4d470897 -236, 0x8930aaf5 -237, 0xa801bc -238, 0x638348ec -239, 0x1002026f -240, 0x196fbcaf -241, 0x422838fa -242, 0xf101e6a1 -243, 0x823e3a7e -244, 0x89efe85c -245, 0x710d363d -246, 0xa96fe815 -247, 0x4b6921c6 -248, 0xe744e488 -249, 0xa0b744a2 -250, 0xac95b93e -251, 0xf820586d -252, 0x9b54d2bc -253, 0x78f663a4 -254, 0xdab3fe37 -255, 0x9212053c -256, 0xa23d60ea -257, 0x82c99bd3 -258, 0x90a9a2d3 -259, 0x80fee31c -260, 0xf14ecf6e -261, 0xde7ce14 -262, 0x9d3cd17c -263, 0x4f07180e -264, 0xa1f53dd2 -265, 0xf7b8f170 -266, 0x4947ceb5 -267, 0x9cc97da3 -268, 0x11e679a7 -269, 0x707ac9f2 -270, 0xa02c05c8 -271, 0xefcd3b07 -272, 0xba998379 -273, 0xf4d1d5b -274, 0xec4d44c0 -275, 0xf9775389 -276, 0xbee26a88 -277, 0x604a69da -278, 0x69dd0436 -279, 0x64ace3c4 -280, 0x74a7effd -281, 0x93a88a8 -282, 0x9d86abd9 -283, 0x2d7c8fd7 -284, 0x2e34bfd1 -285, 0xda5d15ec -286, 0x666c44ea -287, 0x1e97fd34 -288, 0x64fffc5e -289, 0x7d909a49 -290, 0xe5b8a071 -291, 0xc71ecf14 -292, 0x32bc254e -293, 0xe6ffc12e -294, 0x76488aaa -295, 0xfaa24b5d -296, 0x2546a15f -297, 0xd61ec5e -298, 0x5b28529f -299, 0xe9d32272 -300, 0x9937f54e -301, 0x83fcf3cb -302, 0xf57e30df -303, 0x6ed40238 -304, 0x455afea -305, 0x39c1421b -306, 0x97056915 -307, 0xa7fb7b80 -308, 0xe12d4aeb -309, 0xd701e899 -310, 0x191d6f8e -311, 0xb276c998 -312, 0xd5640ed -313, 0xc8607d38 -314, 0xd1f75765 -315, 0x4046f224 -316, 0xf9fa0881 -317, 0x9f835301 -318, 0x70282b9a -319, 0x261420a1 -320, 0x1bace8af -321, 0x6506d84e -322, 0x990ad5b7 -323, 0x63ef0eb7 -324, 0x2dafd32d -325, 0xe119e891 -326, 0x1e163f6f -327, 0x2eb990b2 -328, 0xd9768cf8 -329, 0x93424291 -330, 0xd531428e -331, 0x6d130cb -332, 0xdce0f084 -333, 0x8e7932dd -334, 0xe83a0030 -335, 0xbe046ef8 -336, 0x47d195c2 -337, 0xe2987a93 -338, 0x9c17514e -339, 0xa771c561 -340, 0xcd6ebf92 -341, 0x500e7961 -342, 0x14c5473e -343, 0x45a306b7 -344, 0x21255baa -345, 0xb691678f -346, 0x4131c107 -347, 0x3432699c -348, 0xf5ac1ff3 -349, 0x1e1f80b7 -350, 0xab6004e3 -351, 0xbd693e1f -352, 0x2758f73e -353, 0x7b263738 -354, 0xfed2a560 -355, 0xf7f167d6 -356, 0x34103c7b -357, 0xcf976532 -358, 0xb8b12c25 -359, 0x9d5d119f -360, 0xc9e759fe -361, 0x86d83a5e -362, 0x1552d7c0 -363, 0x797787fe -364, 0xcd07ca28 -365, 0xca65456f -366, 0x534771 -367, 0x47690072 -368, 0x5b9dac8b -369, 0x4cca6876 -370, 0x1568b652 -371, 0x6e5013fd -372, 0xfd62e488 -373, 0xd548844a -374, 0xfa88dff -375, 0xa95def7e -376, 0x34c6113e -377, 0x77d17485 -378, 0xe3177854 -379, 0xef3cf974 -380, 0x4f503249 -381, 0x6cac12b8 -382, 0x93b1b00d -383, 0xe12d8b14 -384, 0x8b7761f6 -385, 0xae579607 -386, 0x12698508 -387, 0xb7cc10cb -388, 0xe3dea112 -389, 0xa0c8aaa3 -390, 0xdff5d91a -391, 0x2b9d97fa -392, 0x666986e4 -393, 0x78362d27 -394, 0x19d29dde -395, 0x204c0a1 -396, 0xf47d5694 -397, 0xab6869c5 -398, 0x48b31962 -399, 0x44d25176 -400, 0xaf7fcc00 -401, 0xa36ce44b -402, 0x2407cd84 -403, 0xd026a2a6 -404, 0x90b84a3d -405, 0x9d603df5 -406, 0x4d967930 -407, 0x5502e782 -408, 0x882554ed -409, 0xcfe11605 -410, 0xbeb03084 -411, 0x603ee8b8 -412, 0xbcac4498 -413, 0x2363e45b -414, 0x7c21d019 -415, 0x4e61e47b -416, 0x67bd2c08 -417, 0xba375f5d -418, 0xa696833e -419, 0xcb34c947 -420, 0xf15f7f3d -421, 0x1a4c69f3 -422, 0x7e4a1b40 -423, 0x9dee5fdd -424, 0x5c147767 -425, 0xe7e03c3f -426, 0x794164c3 -427, 0x5f898b58 -428, 0x88040da8 -429, 0x5e1a8b3 -430, 0x5cb9efed -431, 0xfb1101dd -432, 0xaf9efd69 -433, 0x8290ea8a -434, 0x64f8f010 -435, 0x49807233 -436, 0xeb88e614 -437, 0xba226f1d -438, 0x61210a53 -439, 0x531c4f30 -440, 0x74e22c1a -441, 0x9cae65a6 -442, 0x6e8e3937 -443, 0x96a2bd8c -444, 0xafae3c8f -445, 0xbaf80a8e -446, 0x449afe78 -447, 0x40383d30 -448, 0x3e66c60a -449, 0x2a31d63b -450, 0x48b3969a -451, 0x5775f739 -452, 0xe026f067 -453, 0xbc709fbd -454, 0xde443d0 -455, 0xe6894de7 -456, 0xf52c6863 -457, 0x62467a12 -458, 0xe3e04ed5 -459, 0x20465164 -460, 0xaa776694 -461, 0x6eb049cc -462, 0x9e12645d -463, 0xf2d9811c -464, 0x250cfb6d -465, 0xf0c558a5 -466, 0x1ba68ddc -467, 0xeb613fca -468, 0xf7b3ea83 -469, 0x285856db -470, 0xee7eec5 -471, 0xb29a8957 -472, 0xd53ae176 -473, 0xf6bc1b72 -474, 0x84fcd042 -475, 0xd69b4de -476, 0x64f75919 -477, 0x975dbac4 -478, 0x468516c6 -479, 0x5fc2b6a8 -480, 0x843a7733 -481, 0x8617a7d3 -482, 0x1ae51e88 -483, 0x504cfd60 -484, 0x66370c96 -485, 0xabf2b071 -486, 0x8352d0db -487, 0xa08736a7 -488, 0x1e7aeeed -489, 0xe8c0c560 -490, 0x980f18d8 -491, 0x197e42e3 -492, 0x6e54de4c -493, 0x61ff23b0 -494, 0x73a7e155 -495, 0x6ebf82ca -496, 0xea6877b4 -497, 0xbef6f25d -498, 0x6f184109 -499, 0x60ea6b22 -500, 0xd19f311f -501, 0x936a60d0 -502, 0x6dc64c -503, 0xaa004e58 -504, 0x347ffbb3 -505, 0xb778b487 -506, 0x3c59f9e9 -507, 0xbfef5c8f -508, 0x140797f0 -509, 0x83751722 -510, 0x99ea8dac -511, 0x265e85e7 -512, 0x9888771e -513, 0x55df56b1 -514, 0xb7a38fc0 -515, 0x87b0367d -516, 0xb178bf83 -517, 0xc9cecbae -518, 0xd51a44f8 -519, 0x14ed0be5 -520, 0xcc59258d -521, 0x81d6fb8a -522, 0xb8cf3c7b -523, 0x5181ed39 -524, 0xc600f024 -525, 0xd0cc403a -526, 0x8d30f27e -527, 0x2c2a2d50 -528, 0x253ed4f3 -529, 0x9c60942e -530, 0xe6981fc2 -531, 0xa56bc4c7 -532, 0x982b8be0 -533, 0x7f6bd77c -534, 0x7125b484 -535, 0x583b1e69 -536, 0xd37ffc24 -537, 0x576d6403 -538, 0xd74af7ae -539, 0xe16d3263 -540, 0x317e011c -541, 0x3ce41efe -542, 0x83d23f63 -543, 0x9d2cf991 -544, 0xa4e2a0fa -545, 0xbf4eee6e -546, 0x2569d1ed -547, 0xcc5ad808 -548, 0xb220c85f -549, 0x89f80cc6 -550, 0xe548df1c -551, 0x41ac99ea -552, 0x4e87664a -553, 0xb68e1066 -554, 0xcbeeecf -555, 0xfb1e10a0 -556, 0xebedff9d -557, 0x50228e53 -558, 0xee98ed95 -559, 0xc0f85f66 -560, 0x93cd2127 -561, 0xdbde4239 -562, 0x39ecb5ac -563, 0x8eb7231e -564, 0x887c5d5f -565, 0x2c60e46c -566, 0xbc1ee8e9 -567, 0x58879130 -568, 0x5a96d152 -569, 0x5606b37d -570, 0x34c032dc -571, 0x9c14c594 -572, 0x9906cc61 -573, 0x96af599b -574, 0x1157986c -575, 0xae56ee8d -576, 0x5cfb4b8a -577, 0x1f4cc06 -578, 0x736b8866 -579, 0x9746edbf -580, 0xfec1033e -581, 0xc7c4674a -582, 0xac4d187d -583, 0xfe1a82c -584, 0x5a128715 -585, 0x5ad9dd00 -586, 0xab377c1d -587, 0xf03eccd7 -588, 0xab5f33d0 -589, 0xf45a33ad -590, 0x1d9bbedd -591, 0x9eb804f6 -592, 0x35bd73ca -593, 0xe5d1fbd8 -594, 0x49831b90 -595, 0x15db3cba -596, 0x8f0ead01 -597, 0x6411208 -598, 0x23519624 -599, 0x2b8a7684 -600, 0x150a66df -601, 0x1e795760 -602, 0xabf9d64e -603, 0xcccae49c -604, 0x5f3f8b4f -605, 0x603e684c -606, 0x3845d5d8 -607, 0x7391be20 -608, 0xbeaccb8c -609, 0x2d13a52e -610, 0x84f2af52 -611, 0xa2bbde3d -612, 0x4ce5614f -613, 0x7ae9b8da -614, 0xf6106be4 -615, 0xe7e1285 -616, 0xba30e483 -617, 0x83d280ed -618, 0x21f2c5d2 -619, 0x55e9ba2f -620, 0x207e76e2 -621, 0x5ebc56cf -622, 0xd729163f -623, 0xcc23cc38 -624, 0x670da835 -625, 0xbc773681 -626, 0x898775db -627, 0x82a10cd0 -628, 0x427f744 -629, 0xe6cea8b4 -630, 0x204e288e -631, 0x1cbe370e -632, 0x3b5dedc1 -633, 0x6bb98282 -634, 0x1a91857b -635, 0xaa19bacd -636, 0xfc6f1648 -637, 0x635f80 -638, 0x4fd9e77f -639, 0x44fec088 -640, 0x99c56a90 -641, 0xb2ea52cc -642, 0xc470432b -643, 0x530429ac -644, 0xdca36aad -645, 0x49a809ef -646, 0xb482c9 -647, 0x23d6b0ae -648, 0xa04bb8db -649, 0xe152bead -650, 0x712cd313 -651, 0xdd8884 -652, 0x878d5dd8 -653, 0xc07b6349 -654, 0x1756faf7 -655, 0xad018b -656, 0xdc43b58b -657, 0xf85bdb52 -658, 0xc122a040 -659, 0x82fe93e0 -660, 0x1d96963 -661, 0x10c3c58e -662, 0xfb2cbb70 -663, 0x4b791df8 -664, 0x809955ab -665, 0x9c953fbc -666, 0xa5cccc3c -667, 0x64da4f2f -668, 0xac3e0846 -669, 0x80a4e88b -670, 0xc8294a38 -671, 0x9edbd52d -672, 0xf1c197f1 -673, 0xd94a32d8 -674, 0x221a2152 -675, 0x7fd4186 -676, 0x1f571e9b -677, 0x3af1d0c -678, 0x2c43e1b -679, 0x45e08358 -680, 0xe5b95a08 -681, 0x65c7ff38 -682, 0xb7e9408d -683, 0x35be615c -684, 0xd3a51e78 -685, 0xa043073e -686, 0x1dac1ad8 -687, 0xcd20bbf4 -688, 0x3ab08692 -689, 0x3d31363b -690, 0x5617339c -691, 0x2f329775 -692, 0x63ba0912 -693, 0xd09e248c -694, 0x3bc83bb7 -695, 0xc9348e84 -696, 0x488f5f0d -697, 0xb3458148 -698, 0x98e67262 -699, 0xb36e3560 -700, 0x929127c7 -701, 0x91e3d3f1 -702, 0xc6116448 -703, 0xd6422c05 -704, 0xbd483f8b -705, 0x10063cee -706, 0x2807588f -707, 0xa69116b4 -708, 0xd7ca402c -709, 0x246046be -710, 0xeb6d6a28 -711, 0x8f6a3400 -712, 0xd6bf311d -713, 0x6c351a62 -714, 0xedcdcdcf -715, 0x59c4a3bf -716, 0xcd30992 -717, 0x7fc3aa6f -718, 0xe0d1366 -719, 0xa7c21e2c -720, 0xbf08babf -721, 0xfe06a4d5 -722, 0xd6928489 -723, 0xb05a6b77 -724, 0xe24da592 -725, 0x670f8cab -726, 0xf9f7bc1b -727, 0xd947c6a1 -728, 0x5ecb738a -729, 0x7205a778 -730, 0xd3ec7582 -731, 0x3a4193b4 -732, 0xe886eae -733, 0xdfe36b6b -734, 0x3c60bd41 -735, 0x2df8d216 -736, 0xd6cd52dc -737, 0x62349c08 -738, 0xedc081d7 -739, 0x64b8b994 -740, 0x1dce9981 -741, 0x3a79907 -742, 0xb32a0cf0 -743, 0xc03eef19 -744, 0x8bb7c178 -745, 0xcd1b5db -746, 0x7321faf0 -747, 0x19e68294 -748, 0x839c6c14 -749, 0xdd5a50b -750, 0xe2d86a23 -751, 0xa569857a -752, 0xd65ae947 -753, 0x46b31b8d -754, 0x48972e1c -755, 0x78fadb27 -756, 0x628cd86e -757, 0x6deaa2fb -758, 0x27f03380 -759, 0xbe85ea45 -760, 0x3c756834 -761, 0x4c23f1b1 -762, 0x2fe19c7d -763, 0x440f4bce -764, 0x476f20a -765, 0x36ddd49 -766, 0x8045684e -767, 0x86f4929c -768, 0xb59d7fb5 -769, 0xa27493e6 -770, 0x6f138746 -771, 0x65f4c3e7 -772, 0xea8b35ca -773, 0xfedf7607 -774, 0x370a4ea6 -775, 0xa169c840 -776, 0xa5027aee -777, 0x4eb8e8bb -778, 0xeaf37f83 -779, 0xea132a33 -780, 0x69cb7c2f -781, 0xde8bf9d5 -782, 0x5130d59a -783, 0x35b0ea82 -784, 0xaa6caf17 -785, 0x6b32b3ac -786, 0x2e93d09f -787, 0x8caa797e -788, 0x2ac7a457 -789, 0xd14ef094 -790, 0xecd60b04 -791, 0x7ff2f29f -792, 0x2573aeec -793, 0x7dabab04 -794, 0x198ec9c5 -795, 0x4a06b4d1 -796, 0xdbffff88 -797, 0xa2590396 -798, 0x31f42c16 -799, 0xe17aa6a -800, 0x354d8dcf -801, 0xc85f2d16 -802, 0x73784c21 -803, 0x56f1fbd7 -804, 0x1e3bf2a8 -805, 0x6f05ca05 -806, 0xa3710020 -807, 0xc0b0f694 -808, 0x30e9a497 -809, 0x3ff37729 -810, 0xe3f1b68f -811, 0xce718921 -812, 0xa9074ee2 -813, 0xdeb2b4a2 -814, 0x26eb212b -815, 0x5e87a111 -816, 0xc41c4197 -817, 0xbc48ed4e -818, 0x1de24c29 -819, 0x59dc549a -820, 0x6b4399d5 -821, 0xb9860ac5 -822, 0xdf2fc014 -823, 0x260aaa8d -824, 0xdabad253 -825, 0x12e71787 -826, 0x5664c1db -827, 0x6d495c83 -828, 0x79e0b310 -829, 0x368f29e -830, 0x3acdb5bb -831, 0xcbf13e70 -832, 0x6278dc5c -833, 0xd1e6cb57 -834, 0x706e951c -835, 0xa7cfc951 -836, 0x8704efc3 -837, 0xf7800daf -838, 0x5fb19c1b -839, 0x78112b3b -840, 0xdac745fd -841, 0x47df196b -842, 0x4f88a4a2 -843, 0x7e6baeff -844, 0xac2ea7f2 -845, 0x25c3b636 -846, 0xc4d965ee -847, 0x7b69c478 -848, 0xedd5c411 -849, 0x3657cccd -850, 0xbc9445 -851, 0x543d022e -852, 0xd730178b -853, 0x77ab0476 -854, 0xaad88906 -855, 0x30e20b4f -856, 0x6b22eac5 -857, 0x546b82d0 -858, 0xf929bc3a -859, 0xd0b0b99f -860, 0x514df63a -861, 0xfbc7e698 -862, 0xee55f095 -863, 0xda24f02a -864, 0x5ff2707c -865, 0x89827981 -866, 0xb9cc9888 -867, 0x650869c8 -868, 0x4fd63ace -869, 0xd39d2f37 -870, 0xa679e9d8 -871, 0x41704f94 -872, 0xd805ec68 -873, 0xa8c5b428 -874, 0x8da67e50 -875, 0xfd9a0b2d -876, 0x4dad37db -877, 0x5e96adc2 -878, 0xb6def746 -879, 0xc0f62686 -880, 0x48b3cfbc -881, 0xb37fc4b9 -882, 0xa7cf842 -883, 0x6507dc6d -884, 0x6196b146 -885, 0x43c5d8aa -886, 0x60f33402 -887, 0x4414f4ba -888, 0x10e28315 -889, 0xe186ea71 -890, 0xf8b720f6 -891, 0xc91596da -892, 0xcb08553a -893, 0x70089537 -894, 0x8b04e96b -895, 0x3916b464 -896, 0xc6dc1c6 -897, 0x14a76f2f -898, 0xdb04c528 -899, 0xbea612a5 -900, 0xe3676fe5 -901, 0x8a375532 -902, 0x79b1094a -903, 0x82d1bb88 -904, 0xaff5eefd -905, 0x1cb16caf -906, 0x86e420d7 -907, 0x6a84d295 -908, 0xbb861954 -909, 0x8a07d8c4 -910, 0x123ee917 -911, 0x754c2657 -912, 0x740340d9 -913, 0xd59bad68 -914, 0xd64f4821 -915, 0x6f462234 -916, 0x6897df5 -917, 0xc96399fa -918, 0x2d4b464a -919, 0x54b49a -920, 0x3b1ba328 -921, 0x37a28fb3 -922, 0xb870be13 -923, 0xb6f2eca -924, 0x75b05373 -925, 0x7c6ebdde -926, 0x7b6fc55a -927, 0xe386aee -928, 0xbcd168a7 -929, 0x51f8affa -930, 0x284a497b -931, 0xa0b5e79c -932, 0x1f6ae589 -933, 0xb16f5bba -934, 0x98d750d6 -935, 0xe2ecc0fd -936, 0xa73276c4 -937, 0x6a25d164 -938, 0x4f074d9a -939, 0x8daed6a0 -940, 0x505cbbde -941, 0x2abf25b7 -942, 0x6aea0f39 -943, 0x142efd1f -944, 0x8f668dd4 -945, 0xda98e857 -946, 0xb74b0c57 -947, 0x843da941 -948, 0x80c9c03e -949, 0x9dcc37a7 -950, 0xc09b0037 -951, 0x32d52326 -952, 0xe4c9f6bf -953, 0xde872120 -954, 0x2e7b2957 -955, 0xe17b7baa -956, 0x6d32aad0 -957, 0xdfe6c604 -958, 0xc4e497c9 -959, 0xb6208fef -960, 0x88d8f15d -961, 0x9b8b48d5 -962, 0x591c1666 -963, 0xb974dfd4 -964, 0xb880e0dd -965, 0x4a2774ef -966, 0x3a735723 -967, 0x5b580f75 -968, 0x9a988e56 -969, 0x2ea12bfc -970, 0x11995890 -971, 0x48525745 -972, 0xe9d12a00 -973, 0x7dc73054 -974, 0xa2701b3e -975, 0xcc9b116b -976, 0xc438f3ec -977, 0xfe61e77d -978, 0xed2afc8c -979, 0x9468ca59 -980, 0x8d9c84fb -981, 0x4fe77716 -982, 0x39bb1634 -983, 0x4b1e04bb -984, 0xf0dcc50b -985, 0x109f398d -986, 0xd9f23761 -987, 0x348cb388 -988, 0x2c9b1a0f -989, 0x911041ad -990, 0x282e5df9 -991, 0x575a1995 -992, 0x7204304e -993, 0x797d6d3 -994, 0xae7d37c -995, 0x5521a6cf -996, 0x712c3e19 -997, 0x8fb8dbd5 -998, 0x7ded12a7 -999, 0x50a92df2 diff --git a/numpy/random/tests/data/threefry32-testset-2.csv b/numpy/random/tests/data/threefry32-testset-2.csv deleted file mode 100644 index b7753638fd04..000000000000 --- a/numpy/random/tests/data/threefry32-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0x96bf21c6 -1, 0xa0fe05c7 -2, 0xe1fe280e -3, 0xf35055dc -4, 0x4ec871e3 -5, 0x3bc86276 -6, 0x17a5b958 -7, 0xf49e5388 -8, 0xf7374019 -9, 0x917691a0 -10, 0x448e864 -11, 0x6d3821bc -12, 0x4db62dea -13, 0x4ea93fd4 -14, 0x8a2981e0 -15, 0x6db52782 -16, 0x1391de47 -17, 0x8cbe2e34 -18, 0x6001fa10 -19, 0xa38115ee -20, 0x14199363 -21, 0x934fcba -22, 0xb240df72 -23, 0x6ab87661 -24, 0x60b9d9f5 -25, 0xdbd34621 -26, 0x526af21d -27, 0x1a6b4bf5 -28, 0xd7173663 -29, 0xdce2b053 -30, 0x62080540 -31, 0xe1c3dd3e -32, 0x33ae037a -33, 0xe602063e -34, 0x5ea0ec41 -35, 0xf0313701 -36, 0xa41e72c -37, 0x291889ad -38, 0x6eb6b020 -39, 0x4d623617 -40, 0x5a1574d7 -41, 0x78d45c73 -42, 0xeb9e4d3c -43, 0xe4775f83 -44, 0x89f67a5 -45, 0xcaa0ac99 -46, 0x6caee87b -47, 0x5cafd04e -48, 0x9717a3a0 -49, 0xd6be9166 -50, 0x1288e672 -51, 0x6dfe4ec3 -52, 0x3bb56a74 -53, 0x58582a09 -54, 0x44c7519a -55, 0x17500801 -56, 0xdddc251 -57, 0xc32bf7a8 -58, 0x6f79b324 -59, 0x8a6f971d -60, 0x246d519e -61, 0xda4d3a03 -62, 0x9bed7502 -63, 0xe3dc760a -64, 0x35eb67da -65, 0x717b6e2c -66, 0xe540553b -67, 0xa8ffd00e -68, 0xc7f801c2 -69, 0x2b762e33 -70, 0x420e2c94 -71, 0x8c339dfa -72, 0x99f694f8 -73, 0x217f423a -74, 0x1fd8e09f -75, 0xb3f76cd2 -76, 0x1cee1308 -77, 0xc83f9c45 -78, 0xd48e24a1 -79, 0xb779cf03 -80, 0x1e042002 -81, 0x8f18d559 -82, 0x9d5e185d -83, 0xe2ca5f65 -84, 0x13f56ff3 -85, 0x20fd0f05 -86, 0x201f99ab -87, 0x331c3df5 -88, 0xbaba8549 -89, 0xc6f7306 -90, 0x2b360412 -91, 0x31043048 -92, 0x959c617f -93, 0xadf28e64 -94, 0xfc5b23e6 -95, 0x70e6b601 -96, 0x6bb34693 -97, 0x1fddbf26 -98, 0x7cd372db -99, 0x695ed6f3 -100, 0xc5a37f9a -101, 0x575aba37 -102, 0x74ae0700 -103, 0x8443b8e9 -104, 0x4157dfc0 -105, 0x150dc093 -106, 0x3f7d86 -107, 0x5a11d745 -108, 0x26e3530b -109, 0x2700974b -110, 0x3f395b3c -111, 0x32dc070 -112, 0x7816fd58 -113, 0xf11f39b0 -114, 0xb1bdb3ae -115, 0x933c37a -116, 0x9621e2b -117, 0x6aa61ac8 -118, 0xea05ee84 -119, 0x9e481f10 -120, 0xbc5f31b4 -121, 0x4c29115c -122, 0xcc492bf4 -123, 0xe8f67fb -124, 0xcf9ef4d6 -125, 0xde0d0e81 -126, 0x7b673c75 -127, 0xad3fe9ed -128, 0xbee239e9 -129, 0x1e087877 -130, 0x912eee8a -131, 0x2f55f5ee -132, 0xd0fa0da0 -133, 0xa14fb442 -134, 0xd86b0234 -135, 0x7b1d72db -136, 0x919aa862 -137, 0xfa0196ec -138, 0x30e35f2d -139, 0xa907b642 -140, 0x537204fa -141, 0x8ef7f10d -142, 0x3625e260 -143, 0x5b4d7d73 -144, 0x436729fd -145, 0x8c52723 -146, 0xcde668bd -147, 0xe1d74aa2 -148, 0x73e380e2 -149, 0x19d2f3b4 -150, 0x693d2c4d -151, 0xf1ee106 -152, 0x110b4a39 -153, 0x367df2b2 -154, 0x603b9495 -155, 0xf1fe7afb -156, 0xe77de62d -157, 0xfb68fae5 -158, 0x235b3ef5 -159, 0xc4bdad24 -160, 0xb57f08f3 -161, 0x195a8e95 -162, 0x29f1a9de -163, 0x8d4c905f -164, 0x1419c72e -165, 0x8944437d -166, 0x13587ab7 -167, 0x8c2c89f0 -168, 0xc5446300 -169, 0x7d4dbbd1 -170, 0xb4ce733 -171, 0x2e106d -172, 0x1aecbeb2 -173, 0xd6e885e3 -174, 0x8a0969e0 -175, 0x402a5a80 -176, 0x963d7b5f -177, 0x366051e9 -178, 0x9221f52e -179, 0x3922be06 -180, 0x3f3ea09c -181, 0xb4c67478 -182, 0xa582bfad -183, 0xd8190211 -184, 0x1a5bdcca -185, 0x438d1ac -186, 0x91e68cc7 -187, 0xb584a426 -188, 0x248e2953 -189, 0xff061284 -190, 0x14204e87 -191, 0x41be6ee6 -192, 0xd28c68e9 -193, 0x7c1a6cb2 -194, 0x3dfb5acc -195, 0x9350bf13 -196, 0x633a5ea -197, 0x4e2d241b -198, 0x5a4878f1 -199, 0x775a7a87 -200, 0x7d1538fa -201, 0x43f49533 -202, 0xafc96ab9 -203, 0xe08e3b31 -204, 0xe5f234ff -205, 0x91953358 -206, 0x45cf4358 -207, 0x8070f40f -208, 0x61140fa4 -209, 0xb56542bc -210, 0x3def3833 -211, 0x3afcb202 -212, 0x9ddad97e -213, 0x364f535a -214, 0x722d4445 -215, 0x292e4364 -216, 0x708a1fda -217, 0x9ddb0c16 -218, 0xf3a27c5e -219, 0x18acae39 -220, 0x93e92f61 -221, 0x3e2fa33 -222, 0x878d11f3 -223, 0x61a220a9 -224, 0x4a649d1f -225, 0x394c9f4b -226, 0x9e7c84ad -227, 0xf7fd62c4 -228, 0xcbb4ba39 -229, 0x5eadd8c1 -230, 0x720fa83c -231, 0x64c36bf9 -232, 0x574d17c3 -233, 0x8cdf6eec -234, 0x7638f112 -235, 0xa9c131ce -236, 0x4466a7e0 -237, 0x5e932445 -238, 0xe504370f -239, 0xed84b1c -240, 0x216bd3f5 -241, 0xe8068a58 -242, 0xa15bcde9 -243, 0xee5dbcce -244, 0x413e0b5e -245, 0xfe3255f6 -246, 0x5d9816d0 -247, 0xbcd5a8a0 -248, 0x49ef0ff6 -249, 0x872570c1 -250, 0x3ca3bb8b -251, 0xc4b4d57d -252, 0x25d109b5 -253, 0x5c750b00 -254, 0xc46b7428 -255, 0x2484eda -256, 0xd4c33354 -257, 0x38bb7d44 -258, 0x113da842 -259, 0xb86e73d7 -260, 0x134b9007 -261, 0x672857a -262, 0x7e1f4f33 -263, 0x6c562447 -264, 0x8e592c4b -265, 0x32d2c0b9 -266, 0x5c734488 -267, 0x52acf2d5 -268, 0xfcb64a7f -269, 0xe2ab9d6a -270, 0x18dde6a7 -271, 0xa518ca9c -272, 0x12c92fce -273, 0x9bed83a6 -274, 0x8a78b026 -275, 0x946d9163 -276, 0xddddd15e -277, 0x4d80628c -278, 0x4c6feb7f -279, 0x8f775fbc -280, 0xb1a8e3b -281, 0x3809bc2d -282, 0xd2c72be8 -283, 0x4b481760 -284, 0xc2e72e75 -285, 0x8f37c5ea -286, 0x7307ed25 -287, 0xdc14b350 -288, 0xb2c286f2 -289, 0xa050d102 -290, 0x2f114a3a -291, 0xc27c7a7b -292, 0xdea01eb -293, 0x932cf59d -294, 0xcf4d5b30 -295, 0x86b6bbbf -296, 0x2b290705 -297, 0xabebd181 -298, 0x702ddf78 -299, 0xf4ca859d -300, 0x2020e833 -301, 0x217f3e4 -302, 0x7f0e8cbd -303, 0x7904900 -304, 0x77cb8b6 -305, 0x5daffd7 -306, 0xb6f1a28c -307, 0xfc3a016f -308, 0x61c54f36 -309, 0x27061341 -310, 0xcff54873 -311, 0x4e9690f9 -312, 0x4836fd91 -313, 0x17166086 -314, 0x5bee87b9 -315, 0x1824513f -316, 0x2e121297 -317, 0xeb6700d -318, 0x131ba5ed -319, 0xadef4e19 -320, 0x6b4f51ad -321, 0x35361ab8 -322, 0x5663d841 -323, 0xb2f164a2 -324, 0x402d76f -325, 0xafbd20c0 -326, 0xf8876253 -327, 0x2bf3b986 -328, 0x9f91ddf8 -329, 0xf2b9da4c -330, 0xaa14c7e4 -331, 0xe15cf29b -332, 0x357f2012 -333, 0x4561ab12 -334, 0x1bc5dff3 -335, 0xf07dad88 -336, 0xdd3cc715 -337, 0xe560ac91 -338, 0x8b9475e3 -339, 0xd181c80f -340, 0x55d1cd2c -341, 0x11d425f6 -342, 0x2ca6b58f -343, 0x21b3ad57 -344, 0x1754cd75 -345, 0x90a8050e -346, 0x72e84c22 -347, 0x96dd5f3d -348, 0x6044db23 -349, 0x63434074 -350, 0x6bd5b611 -351, 0xd72ae77c -352, 0xc82da625 -353, 0x7e98cda9 -354, 0x276e09ff -355, 0x24a72915 -356, 0xac1f8749 -357, 0x8c5d96fc -358, 0x322933ef -359, 0x6e8fd47 -360, 0x931acda0 -361, 0x6a714821 -362, 0xfa5ee5c -363, 0x48e64ef0 -364, 0xd8e3e670 -365, 0x4b30496f -366, 0x56959138 -367, 0x121fa62a -368, 0x927f7b6e -369, 0xdee500 -370, 0x38fb7e0c -371, 0x17708fb1 -372, 0xd55c07be -373, 0x2e18a475 -374, 0x431d85a7 -375, 0xa405d3f8 -376, 0x5de38b47 -377, 0x96f6b788 -378, 0xd0f84145 -379, 0xd2392752 -380, 0x44a6566c -381, 0xb3d46be3 -382, 0xc8c9dc5f -383, 0xa952122d -384, 0x197d11c9 -385, 0xa135e6e2 -386, 0xd9d91bbb -387, 0xf4b56186 -388, 0x3cb621ba -389, 0xb572252f -390, 0x8668224e -391, 0x44cb5619 -392, 0xa68bb5c8 -393, 0x224639d9 -394, 0xde35e870 -395, 0x3df1148 -396, 0x21fe35fa -397, 0xccfaffb5 -398, 0x18add490 -399, 0x8126b15e -400, 0xbfd69b4e -401, 0x216fd33a -402, 0x932589c0 -403, 0xabbdd53 -404, 0x1ded816b -405, 0xad0c1ff0 -406, 0x6a5f7a8d -407, 0xcb3e1d5e -408, 0xa8559680 -409, 0xfad440ef -410, 0xdc3e4a27 -411, 0xd1606be4 -412, 0x9e8b03ea -413, 0xf3a38fb8 -414, 0x9cab22b -415, 0x4d25b615 -416, 0xc46114c6 -417, 0xa2726196 -418, 0x65ecb782 -419, 0x79439d3c -420, 0x69ab8d82 -421, 0x216184d2 -422, 0xab262a47 -423, 0xecee9422 -424, 0xa3c1674e -425, 0x357992aa -426, 0x44278f94 -427, 0x4c12fab -428, 0x7740f7fc -429, 0x944222fd -430, 0xc251348 -431, 0x83b629f8 -432, 0x4b594fa0 -433, 0x51d6a9ab -434, 0x830bef86 -435, 0xe250fac1 -436, 0xfde9e381 -437, 0x9e22470a -438, 0x8653c37 -439, 0xd7ec4710 -440, 0xa698bf59 -441, 0x4bf8a5fe -442, 0xbb9fd26 -443, 0xd3cc40d -444, 0xcc1d24da -445, 0x8100b99c -446, 0x199a71bd -447, 0x77464e71 -448, 0x65556a05 -449, 0x1c713ff -450, 0x99c9edc3 -451, 0xa1a0a60d -452, 0x4cf77f1e -453, 0x407ffa53 -454, 0xcebf9b42 -455, 0x2228074e -456, 0x29332ee0 -457, 0x66b2c926 -458, 0x8c7b4df3 -459, 0xd1968179 -460, 0xde7124c9 -461, 0x6d8abf4e -462, 0x25d0af4c -463, 0x65e6fbf4 -464, 0xf8c9d76a -465, 0x5b39bce9 -466, 0x1e9dda4f -467, 0x99dfa42 -468, 0x11531373 -469, 0x5e387ef -470, 0xb474e29a -471, 0xff1d322d -472, 0x3de7e402 -473, 0xb3e2a619 -474, 0xac6f3b84 -475, 0x32650d1d -476, 0x854d9bd7 -477, 0x177d6cf2 -478, 0x64cbb5f7 -479, 0x9a86778 -480, 0x6e1277ef -481, 0xfb4c2f35 -482, 0x1e1931a8 -483, 0x8c66d53 -484, 0xb60870e0 -485, 0xb27759f3 -486, 0x525bfba8 -487, 0xea4b4ac0 -488, 0xb8d944a3 -489, 0xee27be58 -490, 0x506d723f -491, 0x5ceb9607 -492, 0x91efc140 -493, 0x799cb2c5 -494, 0x30c9a8a0 -495, 0x5f03f36 -496, 0xed6ade24 -497, 0xfaaa5117 -498, 0x9174a363 -499, 0x4eef8150 -500, 0x1eec4b8e -501, 0x39901de7 -502, 0xf92f40a3 -503, 0xaa1d14 -504, 0xb9313106 -505, 0xb68676ea -506, 0x6f11d728 -507, 0x66c59d63 -508, 0xb09e79f9 -509, 0x68d29514 -510, 0x9deedf1d -511, 0xfd972780 -512, 0x9bf1cbbd -513, 0x18c1f79 -514, 0x5fed1afe -515, 0xd7a51fc6 -516, 0x2eae8dbb -517, 0xf293e112 -518, 0x1e437bbb -519, 0x5e3d390e -520, 0xbcced217 -521, 0x55d23765 -522, 0xa02aa678 -523, 0xec96a24a -524, 0x29e500a8 -525, 0x98b8a4d2 -526, 0x8c2d9136 -527, 0xe65dec90 -528, 0x3eba15de -529, 0x3c25ef33 -530, 0xdbca90a6 -531, 0x4f09311d -532, 0x990e05c6 -533, 0x54679cf9 -534, 0x8d0ae2b3 -535, 0xa33b8506 -536, 0xf5437070 -537, 0x887fe2ad -538, 0x906a30e0 -539, 0xb2b464f4 -540, 0x415c3577 -541, 0x6057c5c0 -542, 0x70cc0f44 -543, 0x9b2fb077 -544, 0x7336a7f3 -545, 0x9068d9ec -546, 0xc5057d25 -547, 0x705d52e7 -548, 0x6a4aca4c -549, 0x2dadbe60 -550, 0x9c59fba4 -551, 0x791bd0ac -552, 0x11299194 -553, 0xb21a9f2d -554, 0x30aa87c3 -555, 0xede7a398 -556, 0xeece9bb0 -557, 0x38f46a57 -558, 0xb69cd5a8 -559, 0xa04d6d8e -560, 0x42db338f -561, 0x933948d9 -562, 0xb8c1b512 -563, 0x9915f7a2 -564, 0xf0467ab7 -565, 0xc43a5426 -566, 0x53e1470c -567, 0x60c764c7 -568, 0x676c6da5 -569, 0xace51d51 -570, 0x240628e7 -571, 0x3f0c776 -572, 0x7185d397 -573, 0x4209e930 -574, 0xcd75c0db -575, 0x3917fb29 -576, 0x3c95c879 -577, 0x10e9bb04 -578, 0x63a072ce -579, 0x39401a04 -580, 0x6ea9edc1 -581, 0xe4008fe0 -582, 0xebf2bf0d -583, 0x760c3233 -584, 0x7b8edd5f -585, 0xfd632b63 -586, 0x863a8155 -587, 0x9e5dcf41 -588, 0x374dc183 -589, 0xe6279dcf -590, 0x3a802f -591, 0xa17e7cb5 -592, 0x773a8161 -593, 0xda344f6a -594, 0x86a50b9 -595, 0x2defa7cb -596, 0x87b49d8 -597, 0x2169b33c -598, 0x2e1f1748 -599, 0x7d10a959 -600, 0x86fe64a6 -601, 0x9fd5b948 -602, 0xaad08122 -603, 0x1a2a52a3 -604, 0xeede4a8f -605, 0x17117e8 -606, 0xa4650709 -607, 0x2ce293d1 -608, 0x5d1cf4ee -609, 0x94b23094 -610, 0x150f50ff -611, 0x7beeeefa -612, 0xa0baf1db -613, 0x363a69f2 -614, 0x5a67965 -615, 0x9e014734 -616, 0xb7313d3e -617, 0x6e070b62 -618, 0x4fc9b70f -619, 0x455a5d8b -620, 0x21c94a8a -621, 0x203853dc -622, 0x79e0dde1 -623, 0x68b11257 -624, 0x888bb806 -625, 0xa7e9178e -626, 0x8022be3 -627, 0xc550db7b -628, 0xa8f3f180 -629, 0xd28c1484 -630, 0x955445a5 -631, 0xc84c1609 -632, 0x71463ea6 -633, 0x20962712 -634, 0xf9a074 -635, 0xae59fb67 -636, 0x5bf0a427 -637, 0x165146c2 -638, 0xb08ec935 -639, 0x20cfa297 -640, 0x8492faa8 -641, 0xa1f3cf65 -642, 0x646479a9 -643, 0xb035174e -644, 0xb3b039f8 -645, 0x7780d61b -646, 0x63754f94 -647, 0x286565d0 -648, 0x10e13878 -649, 0x145f546f -650, 0xd857539 -651, 0xd8db00e8 -652, 0xc092dc9e -653, 0xb835b8bf -654, 0xe207b116 -655, 0x7961075d -656, 0x5e50116b -657, 0x355bf5c1 -658, 0x897dde54 -659, 0xc505a279 -660, 0x729aaf7c -661, 0xdfb9f60c -662, 0xdb75db2e -663, 0x520f947d -664, 0x6847c154 -665, 0x69a24a1a -666, 0xecf825c7 -667, 0x8b4da35b -668, 0x71e73004 -669, 0xaa594a1c -670, 0x70f6260e -671, 0x73b565a -672, 0xf050bb33 -673, 0xd9409845 -674, 0x32354d60 -675, 0xabed3745 -676, 0x1995883 -677, 0x6418b501 -678, 0x6a96c78c -679, 0xece6bffc -680, 0xc3892389 -681, 0xf1fa0e62 -682, 0x59a93622 -683, 0xac1d1798 -684, 0x8b1984b4 -685, 0x2603f602 -686, 0x4fdd2d48 -687, 0xaa57c8af -688, 0x49735a97 -689, 0x73075464 -690, 0x75647208 -691, 0xe88930a0 -692, 0x4c51d399 -693, 0x86904118 -694, 0x62af2995 -695, 0x4c62090e -696, 0x7319e53 -697, 0xb11c255c -698, 0xa9fb903f -699, 0xc602439b -700, 0x447eb0a4 -701, 0x9b602006 -702, 0xa6583b9a -703, 0xc33d5e64 -704, 0xf945c9be -705, 0x1199ecfc -706, 0x58ca9756 -707, 0xc0f98006 -708, 0x7694cb6e -709, 0x537b5f33 -710, 0x5ad022df -711, 0xc23ae783 -712, 0xf27d584c -713, 0x3410e1d4 -714, 0xc69867f2 -715, 0x239cb4fc -716, 0xedeffd68 -717, 0x9cc9e0be -718, 0xb44585c7 -719, 0xf811df78 -720, 0x32e3779c -721, 0x495830a7 -722, 0xb5c7ecb2 -723, 0x8583521a -724, 0x26cd0f3f -725, 0x7f79bf6e -726, 0xf63c2afa -727, 0xabbf2df3 -728, 0x90cead53 -729, 0xdac401a -730, 0x76d10bb8 -731, 0xa7a6a87e -732, 0x3f7783c1 -733, 0x2cdf71e0 -734, 0xb7e5ebfb -735, 0xa5eb1c64 -736, 0xfa462a94 -737, 0x92e33c33 -738, 0xb1f5f201 -739, 0xb58b1587 -740, 0x212b9bbf -741, 0x63938326 -742, 0xd7562019 -743, 0x9e1974ea -744, 0x670c615b -745, 0x62460641 -746, 0x9be46c7e -747, 0x34421fab -748, 0xe722475c -749, 0x8e6170aa -750, 0xfa68a479 -751, 0xb77324b0 -752, 0xa64c0f97 -753, 0x5183720b -754, 0xf3160e77 -755, 0x23a3b269 -756, 0x9d7b11d1 -757, 0x3cfbefd4 -758, 0x1fe0e235 -759, 0x910ebbce -760, 0x84eae93d -761, 0xe390b082 -762, 0xce29298f -763, 0xe7e718c7 -764, 0x7adc4e73 -765, 0xc3c5dae4 -766, 0x685c0b9b -767, 0xa5ed9a8 -768, 0x5a2ccb4a -769, 0x3c94fa33 -770, 0xdc8726ef -771, 0x92121728 -772, 0xe2c57ec6 -773, 0x522712e1 -774, 0xec5e6145 -775, 0xe486d06c -776, 0x1ef7fa3a -777, 0xd3e8ac09 -778, 0xca770944 -779, 0xd490c429 -780, 0x5b626100 -781, 0x973f8555 -782, 0x5b690d01 -783, 0x3ba958c1 -784, 0xa4b3f08c -785, 0x6760f219 -786, 0x59bac764 -787, 0xb1c54d52 -788, 0xcb4aa641 -789, 0x2d6c9a4e -790, 0xebd48ef -791, 0xee3109d4 -792, 0xd286c88e -793, 0xfd26fd0f -794, 0x450825c5 -795, 0xaa1a4313 -796, 0xb07511ed -797, 0xb2836487 -798, 0x900cd63b -799, 0x2345cfa0 -800, 0xc6de4d20 -801, 0xf57de173 -802, 0x24890b60 -803, 0x522ce8c2 -804, 0xb70a8eb2 -805, 0x358ee7a -806, 0x6a29365c -807, 0x402f9666 -808, 0x6889332c -809, 0x21e55b7e -810, 0x8c886218 -811, 0x943ce0c2 -812, 0x637f3dcc -813, 0x336ceaef -814, 0x65d94c0d -815, 0x2e07516c -816, 0x7b03d97a -817, 0x5d0dd1ce -818, 0x98e27a9f -819, 0x329e3e00 -820, 0xa758619e -821, 0xf2401413 -822, 0xc73c21d2 -823, 0xa7f97da5 -824, 0x397c2e9c -825, 0x9511ed82 -826, 0x824760e6 -827, 0x2391d3c2 -828, 0x7ca7092c -829, 0xbb63f94 -830, 0xa7370c1d -831, 0x61a44ce8 -832, 0xfdf08bf1 -833, 0x5dba1ae3 -834, 0x72a21633 -835, 0x2239c7fe -836, 0xfbcc7e2 -837, 0xe2f724d7 -838, 0x69223ca3 -839, 0xd7759240 -840, 0xbdeda501 -841, 0x413c2cf0 -842, 0xbc7e5c63 -843, 0x339f3ef9 -844, 0x95749faf -845, 0xb1ac835 -846, 0x866fb03a -847, 0x90873b55 -848, 0x59c09bd6 -849, 0x180f8d78 -850, 0x729bf2a0 -851, 0x13a32fe6 -852, 0x62dd49a5 -853, 0x9eecb212 -854, 0x258d30e8 -855, 0x2153d968 -856, 0xaba5083a -857, 0x726aaf8e -858, 0x512c3192 -859, 0x62414d -860, 0x48fa16b8 -861, 0xf761e7e4 -862, 0xf6012be7 -863, 0x77dff028 -864, 0xd21abf72 -865, 0xed2f995f -866, 0x69cee22 -867, 0x54200535 -868, 0xd883594c -869, 0x28b475e6 -870, 0xe0a2038c -871, 0x1b56c6e1 -872, 0x7220704 -873, 0xf842418 -874, 0x90aa400 -875, 0x941b5975 -876, 0x576d964d -877, 0x93ef2176 -878, 0xd9562201 -879, 0xf7433ac -880, 0x23ede5c7 -881, 0xfadf3362 -882, 0x769830d1 -883, 0x21ee4b1e -884, 0x6c60a5f8 -885, 0xf42ec278 -886, 0x5ac46157 -887, 0xc527c639 -888, 0xdbbbb7bc -889, 0xcbf79715 -890, 0x26384600 -891, 0x9cdfad11 -892, 0x60815d7a -893, 0x20bcf98a -894, 0x4652d4ba -895, 0x7ea46112 -896, 0x7c560e8d -897, 0xbeb3e89d -898, 0xb861dd4 -899, 0xe1d4189c -900, 0xe83ea3e5 -901, 0x92393c2b -902, 0xdd6bbf3d -903, 0x620a691a -904, 0xdb64b940 -905, 0x5fbadf2d -906, 0x1ce81d5f -907, 0x4b20d0d7 -908, 0x53ea3105 -909, 0xf350f9fc -910, 0xd04736d8 -911, 0x358e8630 -912, 0x18fb3a7d -913, 0x8633154e -914, 0xf48a9fec -915, 0x98c40cb2 -916, 0x98596dac -917, 0xb5e16a27 -918, 0x1834670b -919, 0x3e8cf415 -920, 0x6e6ba2b8 -921, 0xfa5cddae -922, 0x77032bac -923, 0x97b9e6c -924, 0x3ffc2aa1 -925, 0x879b53a -926, 0xbbf693b5 -927, 0x971efbd3 -928, 0x9ab6ad89 -929, 0x160d498a -930, 0x66cebdce -931, 0x4fb855c0 -932, 0x68558584 -933, 0xa695f564 -934, 0xebea0104 -935, 0xb349d0b1 -936, 0xb27c5871 -937, 0xd4965433 -938, 0x3b48325d -939, 0x816851ad -940, 0xa7328098 -941, 0x307cdf7c -942, 0xfacb2352 -943, 0xac2ded57 -944, 0xd01efb86 -945, 0x9e039163 -946, 0xb9e02f -947, 0xd18c1916 -948, 0xef4380f0 -949, 0x1c578bcf -950, 0x737f6c89 -951, 0x47dd10af -952, 0x459bbd41 -953, 0xf0c0a4ff -954, 0xc2166f81 -955, 0x4ffabd22 -956, 0x89731a04 -957, 0x989a031a -958, 0x941ed188 -959, 0xa77ec4d9 -960, 0x3e6ca8e5 -961, 0x238e5fe7 -962, 0x2ac9b71b -963, 0x95a0d1be -964, 0xfc56dbaf -965, 0xbb5a4378 -966, 0x4cc6e834 -967, 0x36175364 -968, 0xb097fbe3 -969, 0xea1466d4 -970, 0x317733fc -971, 0xeb88ef75 -972, 0xb82570c6 -973, 0x2b8adfa2 -974, 0xd7a86699 -975, 0x6d13d28f -976, 0x6dd2c41b -977, 0x92d733e6 -978, 0x928f31a5 -979, 0xfe7c01bd -980, 0x62a1bc47 -981, 0x47d9b6e1 -982, 0xae6f97a4 -983, 0xbdaed100 -984, 0xbb24138 -985, 0xa6f1819 -986, 0xdc5f99a -987, 0xc5b5b978 -988, 0xdfb7fc81 -989, 0xc82744ca -990, 0xbdd30239 -991, 0x6c11d175 -992, 0x3910ed7a -993, 0x6b9efa62 -994, 0x29a9dd01 -995, 0x492afa85 -996, 0x151b62e8 -997, 0x2546c48d -998, 0x3cb52c7c -999, 0x8fc96435 diff --git a/numpy/random/tests/data/xoroshiro128-testset-1.csv b/numpy/random/tests/data/xoroshiro128-testset-1.csv deleted file mode 100644 index 4ef7172e1735..000000000000 --- a/numpy/random/tests/data/xoroshiro128-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0x86f9f4feeebed928 -1, 0xb3617382bfd2bb33 -2, 0x4314c03ca1908f7a -3, 0xfdbe2ea0213dab80 -4, 0x6076f6f829c64721 -5, 0x6587411cc85fa712 -6, 0x4778e74dc7f92125 -7, 0x6ada4530f4cf01c8 -8, 0xe0ddb30ce61b5172 -9, 0x2998c6e98e79ae50 -10, 0xfb8cb09917a0e99a -11, 0x7df546933cbeabcc -12, 0x972407f8132f16c2 -13, 0x6dcfab42a6d97aaa -14, 0xcbd39869fb69f683 -15, 0xaa789636ea4daf4c -16, 0xe364dbbff8064dbd -17, 0xf639489e242feaca -18, 0xa3454eb3b12942b7 -19, 0xbaa569d8f934bc14 -20, 0xbfe4a0166c493f06 -21, 0x96dec770408b339d -22, 0xc75a3b26b2702eec -23, 0x4752a021254c0915 -24, 0x35edf588263b9bbc -25, 0xa97342f217e541c2 -26, 0xea9bc6a01b4b7d83 -27, 0x93cec444361979b5 -28, 0x8ed5719f5ba9a424 -29, 0x8e1dead734d410b1 -30, 0x1f63a442ce77d4db -31, 0x3c36e0a05da986de -32, 0xc6c10658893be094 -33, 0x196ed853b1167184 -34, 0x8b06218d6a34950a -35, 0xac51e33319f103a4 -36, 0xdf47e4b0ef46c70 -37, 0xf34775455325aea0 -38, 0xf341953786525c76 -39, 0xe9b85d99c1115696 -40, 0x4432daff0305cfed -41, 0x34cc1bfed7b9676f -42, 0x87d19c7db528ca12 -43, 0xaa767030e19682b1 -44, 0xac39890dafd308ef -45, 0x92a6d833ca6a68c2 -46, 0x6626523fdceed4ba -47, 0xa609844feb22593c -48, 0x3d68f39a561a7c78 -49, 0xee2b74bafbe9a80e -50, 0x7f23ba8a58a0226a -51, 0x8900ca1c9d5550b6 -52, 0x781ff936e2d8abfc -53, 0x960fa9c6da5eeab3 -54, 0xdc316a7a5161cd -55, 0x61f6096510d22bdd -56, 0x1c1fc069b6643ce7 -57, 0x3105b8feea7651bb -58, 0x4ea8c76afedfa6e5 -59, 0x55cce3ba46b2ff82 -60, 0x32ce23a4e59a9ddb -61, 0x5d8b33b817a1e1c2 -62, 0x6861f95a5dbc833d -63, 0x1af405acc0346f1e -64, 0x4bea8e5e87e6b3cd -65, 0x6a79d9021478eb80 -66, 0xbd1512cd44c0d03e -67, 0x870719b2e322e44 -68, 0x10eaf80ea8e95a14 -69, 0xad85fdbe2e6d99ec -70, 0x47e9f8f63db20254 -71, 0x69ca77aa6a12ff2d -72, 0x385ec684f96ed9aa -73, 0x573a97f8103f9ea8 -74, 0x57a94ba1ca505197 -75, 0xcb4bbe5444b0b4ae -76, 0xcbe456413a8d1566 -77, 0x67a21dc37357827e -78, 0x992ea6028ade725c -79, 0x89cc89e9570792f2 -80, 0x2b4873ae2a6260c6 -81, 0xec8e07e9204eac1a -82, 0x6bc898204729c23c -83, 0x7d086557a49d391d -84, 0xfa16b7ede631dfd9 -85, 0xf2710cc7516fd414 -86, 0x9aef67d70498456d -87, 0x518f9fc570ea091e -88, 0xe765ca35b2293f35 -89, 0xb06015f656a5ce97 -90, 0xc0154acff67d930 -91, 0x1cb3b41de66b3964 -92, 0x41a024e712b0d577 -93, 0x921572c63007b7a7 -94, 0xb2864274d855fbb9 -95, 0xe555774f7bbf0590 -96, 0x2d15198702e750fc -97, 0x3fb422e738e347c8 -98, 0x8562515206baf50 -99, 0x13dcd174d6640321 -100, 0x2c2d1d739e2243c4 -101, 0xc41b5f458215c274 -102, 0xa6d7e86d348f1f4b -103, 0x9d78f189583149c7 -104, 0x685ac4ec5ac7c326 -105, 0xfb998afb22666cfe -106, 0x5b9df8c77816280b -107, 0x2ebad315b4a6de5e -108, 0xb70f296a67a1ee71 -109, 0x3b714a6ba151c3c0 -110, 0xa0b64d501736310f -111, 0x17f827804629ad52 -112, 0x46ed287bdea3217b -113, 0xb26d12305a6fb5eb -114, 0x184247bba474368b -115, 0x542b93986dd5ea3 -116, 0xb8a0cc8fbd9a193b -117, 0x7a89dcac9c85a621 -118, 0x48d466d072a44c78 -119, 0xada1f7e65a517caa -120, 0xf6febf549d553ec3 -121, 0x19cf94cb14dadd59 -122, 0x9087aeca4e923157 -123, 0x1afb1bb6e2fc9f3e -124, 0x6192b1b315392ddc -125, 0xedcd055d2840341f -126, 0x396cfce39b432fa7 -127, 0x183319afd1d0cf9 -128, 0x917409d968c3620a -129, 0x5868095709377c1b -130, 0x84e1f92faddbb86a -131, 0x45c5ecb0c1bf2a92 -132, 0xc5a7f84f16b52592 -133, 0xb389866b9cca1c35 -134, 0x7924255948cb4bb8 -135, 0x6b4a33d0810f1d99 -136, 0x749800294244b46 -137, 0x4ce2e9d74a34c543 -138, 0x3bf47c412961da25 -139, 0x35ecd46092b0d494 -140, 0x360703f0b4c8fd18 -141, 0xef4f039e6428f8bd -142, 0xfc63479c9833ab9f -143, 0xc660fc00994c3490 -144, 0x57a055abc0afd99c -145, 0xe83bee603058ba87 -146, 0xa6c06409fab71942 -147, 0x8ee4675a90f2eded -148, 0xef7240fbaaa4454e -149, 0x73d0378b4855e043 -150, 0x4039e6cd0da81154 -151, 0x3e4261378314b8ef -152, 0x5f891423c2a77d05 -153, 0xd57c43570ff9cc37 -154, 0x3c69a08bb46e066c -155, 0xe265cba3cabb6fd8 -156, 0xd9bed8fe0179a58a -157, 0x882255210140b153 -158, 0x7d212a20e03003a2 -159, 0x5821c48f435aa8db -160, 0x3ff2fc230e4fc421 -161, 0x7617ac677d8703e2 -162, 0x306c8cf9c6be23ef -163, 0xd7728cfebc614ab4 -164, 0xeddb425f79076eee -165, 0x76e61bc49c5b61e7 -166, 0x803610661e501d33 -167, 0x52c2968fd8b30ba9 -168, 0x56c3d2813aabf019 -169, 0x895c1923a0f7f8b8 -170, 0x2bb50b203d52d465 -171, 0x6987baec87355c0c -172, 0x1186c9e7e524b89a -173, 0xd72695cdee9d1e41 -174, 0x1aed250f3b25eb65 -175, 0x7a98d55cc9b790cf -176, 0xe3f84b1f0a3436a2 -177, 0x929f43e01cdb529b -178, 0xee439860101d371f -179, 0xc30f8f543ea1391 -180, 0x51470330a3a9555c -181, 0x13cbcd8728edb72b -182, 0xc2ff37a63d496acc -183, 0x38a775bab54c9e5 -184, 0xd3b9a106f7cae82e -185, 0x409dbb706362645f -186, 0x6756c88f065e228d -187, 0xfca59c508b33a615 -188, 0x4f1a85c2cf7f70b -189, 0xde05e1f080183683 -190, 0x58cc04c78668d30e -191, 0x29a6cdaabc128bd4 -192, 0x7fd48a7175d7080b -193, 0xf62615d9f1a4c0e0 -194, 0xc0bcdabf943a9882 -195, 0x2e17eaa18c30cbe9 -196, 0x23b0a7bf11059cdf -197, 0x980faafc56997e96 -198, 0x5df31ba1971bc9b -199, 0xf2918ccd892a579b -200, 0x863c265ba908fbd0 -201, 0x6c4d8604d73771f -202, 0x8231891e28337ca1 -203, 0xcf1bca7019e17620 -204, 0xc2914444386dd7b2 -205, 0xb2940f2f54af1342 -206, 0x5f94a7742182144 -207, 0xdd84510e416c55a9 -208, 0xed6cabbc034639b6 -209, 0x8ec7d280a1dc818e -210, 0xff9c27aafcdf6ad8 -211, 0xe4eb67cd34584e9e -212, 0xde9094e8bd9372fc -213, 0xf72c5d7a9f648bff -214, 0xab84eec6625de3ab -215, 0x31401a873557b3f0 -216, 0x3a92ea998fbe33e0 -217, 0x938f51440df1e372 -218, 0x1b8adb3266aa2b20 -219, 0x52614e3f539aa97e -220, 0x8c3910405c2b6db5 -221, 0x5678fa580938f1d0 -222, 0xaecec4c57c393677 -223, 0x25387b15ce263e99 -224, 0xa2064849456b89fc -225, 0xf3d6abe7c5ccbf89 -226, 0x71306e8ce5f15360 -227, 0x9100205404028ff -228, 0x473f2c3ee60b5ff8 -229, 0xa98cccbcb30fd354 -230, 0x150886f18c2a8abe -231, 0x73a10ec9d0a3e5b -232, 0xa04d37f64652298d -233, 0xc47af08c27df64bd -234, 0x127ec96954fef972 -235, 0xd8ce70375554f482 -236, 0xdb2e3388772bb0b3 -237, 0x843d9952b8e93044 -238, 0xb4c50aa1b3ff8dc0 -239, 0x41d43b3662be19e4 -240, 0x5de18309d9cb944c -241, 0xbfcbc63f45cf4998 -242, 0xc58ce67bd9f221ba -243, 0xeb3c7f7349d6876b -244, 0xbd38b8331d766037 -245, 0x5c0de7cf313bef77 -246, 0xe8984144d81c9ab8 -247, 0x42ba3a205f55572 -248, 0x316372b92fd6df46 -249, 0xe7c4b5535873e7fc -250, 0xec4b062406fad890 -251, 0xcb9254c0853f3bc6 -252, 0x6fbb40d1758c5a4c -253, 0xa17b63cb93c12094 -254, 0x3e00a27f4b51696a -255, 0x7dcec0f01bead947 -256, 0x1a8b827e9d0658c4 -257, 0x75929c838a9fc9eb -258, 0x165b162560d5bcc -259, 0x2320fd4ab2fbe43 -260, 0xf0ca89e97c60154b -261, 0x90a3b09348c0caf8 -262, 0xac1516105437f9d0 -263, 0x8f11e6454bea6007 -264, 0x19b8a0c5805ebeec -265, 0x3105e78b4e2f11b0 -266, 0x8c365bc66d26d165 -267, 0xdccf55c3bf85167a -268, 0x926c88470d3a703a -269, 0xe5421ab183b63c89 -270, 0x9fbcfd19c800e684 -271, 0x618b70d50ad85d44 -272, 0xcdc7b4b5f83386e1 -273, 0xb03b91dccaff6125 -274, 0xf470624fdbde22b7 -275, 0xac2f659be06a08ea -276, 0xa49f1af1a29abb77 -277, 0x5c2e94fe6a5d7978 -278, 0xf12b8c7cfa17f5f4 -279, 0xa8c4c5c917203a0e -280, 0xd1ea9aa8c49fa551 -281, 0x7363288bd7b40258 -282, 0xb3668a32f1b36dfe -283, 0xeebdb9e4377e3fc2 -284, 0xa07bf94365ce0a90 -285, 0x49a75731b3efe51b -286, 0x29af2e86886df8db -287, 0x84cab4d861631a0b -288, 0xec45e2345d9c1114 -289, 0x9e0aca51ba3aef2b -290, 0xef6db51f7d2239c0 -291, 0x6bd53260a01e4992 -292, 0x5ff887fc83732499 -293, 0xef39c88e15608f39 -294, 0x166883224e645f35 -295, 0xb296e3561ccc419c -296, 0x342081199780e04b -297, 0xdf24e8c78a472e -298, 0xa64a89e743ae2617 -299, 0x6cc623876bd66b3d -300, 0x45066f03a3fae72d -301, 0x99030d380d113008 -302, 0x891b6637052d6ed2 -303, 0x8ac4de1d3bacdd5c -304, 0x6bd4540970e747b5 -305, 0xb48125e69019055f -306, 0xefc03dc62eee31b8 -307, 0xbb61f62afc671564 -308, 0xf941c67dc61e4f9 -309, 0x58dfbb0f8cdf6857 -310, 0xfdd423db3734d952 -311, 0xddbef0ea939712bc -312, 0x64cb6c97a176d099 -313, 0x57d73985fa34a17e -314, 0xa5241bd90d5a351c -315, 0xc2669439928e2f29 -316, 0x4a00c61ffe77951b -317, 0x562532cdc210a37 -318, 0xe2fb88acfe451d04 -319, 0x8b4053716affaa4a -320, 0x208616d3e2ef242b -321, 0xf830a95da5ba3676 -322, 0xbf01348d4133f007 -323, 0xd44cd6d38e4b2c1a -324, 0xa577c236744b677e -325, 0x1a08ee02ccfaf7d4 -326, 0x94b364baa2e88b22 -327, 0x1278a7e8f3886173 -328, 0x5e5c595c284d8555 -329, 0xe81240395bfc355f -330, 0x5c72a5e76ba9777f -331, 0x30c5587516d5dd3b -332, 0x3a01ab159c61cc3 -333, 0x921a5153ca306f87 -334, 0x499d0410a755a3c3 -335, 0xe35523f8c25a0e36 -336, 0x923135834356ca2e -337, 0xf0d3cfbca4b9c1f6 -338, 0x523ba92f35c890b5 -339, 0x32791ee78e661d2d -340, 0xb8def8bec5d4833f -341, 0x8ddf479407495133 -342, 0x32af2693e93bea72 -343, 0xfe7c577a150a526b -344, 0x29f322d80b5d31e7 -345, 0x770f1c2f276aac75 -346, 0x710d900fa16454bc -347, 0xad35a054b19a6419 -348, 0xf8543705d2221c4d -349, 0x1a208f09dcd992e6 -350, 0xc6fe24f4478fae54 -351, 0x15af9b23589efa5c -352, 0x77c3cdaf72c7974a -353, 0x8b9ee62898b42805 -354, 0x24d86bd194b32df2 -355, 0x8947894a6f9e06bf -356, 0x8f74894e2ebc9e42 -357, 0x30a460a64ac97b89 -358, 0x985f3b650b19bfd1 -359, 0x6b68d65a7decd3b8 -360, 0x33ca1f7082b77691 -361, 0xe16c9da462bcc4c2 -362, 0x85512fb1e448efc1 -363, 0xd23729cdc1fbf8af -364, 0xb4c48c3dd40c6431 -365, 0xc408b5198e25d53d -366, 0x9c3ede789980eac6 -367, 0xea44b85282535bfc -368, 0x8a4ef27cc51a1368 -369, 0x92b1c10cd267b53c -370, 0xe262b216c571e216 -371, 0x9ab945ad23c45d33 -372, 0xf8a6ee8859691e81 -373, 0xb4387e4124b6ede6 -374, 0x67057ebcb0458cba -375, 0xcfea5995ea0d9036 -376, 0xf60e552368e88671 -377, 0x97a744db9ea2a465 -378, 0xf9bdfa8f7765704d -379, 0x4a092a7483623007 -380, 0xd1ec15e72770f23d -381, 0x9f4bddf29a1ec891 -382, 0x7574533dbfd85aef -383, 0xf336b164aa32c8c1 -384, 0xaecebdd3bb1f6273 -385, 0xcdee4c8c59b621f3 -386, 0x4e62a96f422f045e -387, 0x7954b5c0c33402d9 -388, 0x44284a788c4bd72b -389, 0x3f7f331379400e90 -390, 0xbe47722adce724fa -391, 0x202ec17f30c6dfd3 -392, 0x20e6bd8b12ae33ca -393, 0x56ba93c9a6aa537d -394, 0x2ffaed6a56011829 -395, 0x59bf8fb6387acb10 -396, 0x1d092715f75b4731 -397, 0x4f73c9b5945ea6c5 -398, 0x4f9965a9cef20ef1 -399, 0xcce9d598a9ee3128 -400, 0xad6bf86f41263232 -401, 0xb768dbb67c5e35c0 -402, 0xb5c06fa5f590c5c0 -403, 0x2849f01daca38cdb -404, 0xe31daf6540d3c5a2 -405, 0xa462464c813059e0 -406, 0x98cd0da9a864a13c -407, 0xa0bf6269bcb1c79b -408, 0x354467e29dd2415b -409, 0x8760ca9ca2ed96c1 -410, 0xdcbc0296a9d243e8 -411, 0x940f0679c02babd0 -412, 0x4f389795e70c9b32 -413, 0xcad57ca19c578c20 -414, 0x346870e71ed575ad -415, 0x4dc47ca3f25bc1bf -416, 0x636afe20b8e9f185 -417, 0xb47b4b4dbf6ec559 -418, 0x8634686a6ec85170 -419, 0xc176c9709a40fdc0 -420, 0xaf830009e390dfb0 -421, 0x65cb55acd3653031 -422, 0x52d53d142c15219b -423, 0xffe9258ae4b63350 -424, 0xa118cfbbb64e3f6e -425, 0xf0aa49900685c7bd -426, 0xf4a63180c7a493e0 -427, 0xb219297f315c3905 -428, 0xedbe04b3e65cee75 -429, 0x17578b66c9422dcb -430, 0x93341d13d6f3f307 -431, 0x4cb05e69da41bb0a -432, 0x1f1dad0ac8c3b625 -433, 0x4cc0d69392282fe4 -434, 0xa415bcab7a9e9030 -435, 0x49c4bce139b17cd7 -436, 0x70921ec48102ba98 -437, 0xcce784ad8ecc8ef1 -438, 0x1394434e6983851 -439, 0xdceea9694050de81 -440, 0xdd34ce31271e0733 -441, 0xaa722f329463f189 -442, 0xca65b550f35dd0c9 -443, 0x1477d0711156ff76 -444, 0xeff9d7e1e525c056 -445, 0xf425a4a41487a26c -446, 0xd7a62c18f2ce9451 -447, 0x178ad1414c520698 -448, 0xd5fb19755b8a9cd3 -449, 0xf9b662ac336df748 -450, 0x3ab374b95c09392 -451, 0xb1017e23e64343a2 -452, 0x4e38eaa252f0eda8 -453, 0xe50e9e51d4b9abce -454, 0xaa5d9bfb8193c02c -455, 0x823a22b374b70757 -456, 0x31cebbf89930801b -457, 0xd7c29187bcea4c72 -458, 0xe9118fc76c45cbf1 -459, 0x9c71d746e81ad2de -460, 0x61546ce34ed37e5 -461, 0x93cf2b2f08a9dd70 -462, 0xaa8a0e918d246f1a -463, 0xbd35895f4913143c -464, 0xdfe98084bcf724b5 -465, 0x3711d1a09d3b438c -466, 0xef7a4589307c37f9 -467, 0x174de3c95aad64d -468, 0xa66127748de17435 -469, 0xaa7789614da98e6d -470, 0xa01a9a6570b63f02 -471, 0x52e4422529cdf289 -472, 0x5fa480a033fa2eaf -473, 0x8d950f2a0362d44d -474, 0x264fa25f7b50b19e -475, 0x4f2ed2872e35635e -476, 0x1173eaed49ff03d -477, 0x7cbde5b17f7541b1 -478, 0x80913ce7ba0fd00f -479, 0xae85c98e607af8ab -480, 0xd4349f0a1a724b17 -481, 0x436510b9fdbb00b5 -482, 0x345d25f181b23831 -483, 0x360875f99d1dbc3f -484, 0x77657a493413286e -485, 0xdb45294b3f8dab13 -486, 0x25e84d1be5f5c6d6 -487, 0xbb44ba55be3f453 -488, 0x7d7b2c5077ddb248 -489, 0x4c7e02c08f79a63f -490, 0xea589769295ebac7 -491, 0xcf1159ed1fbbabb2 -492, 0x5f0c199a69956db4 -493, 0xb2c190830b28ba75 -494, 0xfef7b55986f49a19 -495, 0x961eb7b425de477b -496, 0xdb31045f05af950c -497, 0x13bc7a5600b306b9 -498, 0xe4834efcc7d8515c -499, 0x6d3ebda0630a9e64 -500, 0xcf453a9b686cbc0 -501, 0xe1048db43e9dc5ec -502, 0x95b3b95608ff12fe -503, 0xdaa8457f1d3bca37 -504, 0x3913e8473f5593ba -505, 0x3afceee33004c5dc -506, 0xd117393f5e9d11f6 -507, 0x7f462da9314f76e -508, 0xa4fc522c19f1f8d6 -509, 0x7429b79b76acdcfd -510, 0x5a570cb8d216a730 -511, 0x705c4c4af10c7ac7 -512, 0x4abf3a808087344e -513, 0xe6313ab9845d433c -514, 0xb038e24fbbfc7716 -515, 0x80a25d4531599d7c -516, 0xb2b75e488f81693b -517, 0x43b8d27a4dbba2a9 -518, 0xa611ff50d23f05e2 -519, 0x872da217d6fa41a6 -520, 0xb153855cda09b36f -521, 0x3c6f5d7d21da31a7 -522, 0x59a63c7ad79be63f -523, 0x27a4679e83422368 -524, 0x4e8bc4d771b0feaa -525, 0x6719469e9cf2c3d9 -526, 0xb56b708a9a915da5 -527, 0x2594e558e515d19 -528, 0xd6df1e4a0bf1b153 -529, 0x4f7f25d38191e1fe -530, 0xaaaf850ad5e538b0 -531, 0x6355175a813e200c -532, 0xbe7544f56eef5ae9 -533, 0x5c516d87bbf779cb -534, 0x23c180f962a3d2a5 -535, 0x5cb1ac1c4261b281 -536, 0x4717bb3567432de1 -537, 0xeb1285580fa935a0 -538, 0xc50894350d82d33a -539, 0xcd0e2cfea37c3245 -540, 0x298bc40ad881a2b5 -541, 0x466df434870604fc -542, 0xbc1eb2d8ebbd351f -543, 0x357534396e12e369 -544, 0x305a159545ad695a -545, 0x63775f2479bae51a -546, 0x44e266968147590e -547, 0xd733336da0cfd6b9 -548, 0x7b1668635266025e -549, 0xe25f2c506843c3de -550, 0xf9635d39029105fe -551, 0x4098dbd2e7b717fe -552, 0xd58848e50b96b32d -553, 0xdf776a82ade5f937 -554, 0xb86fe57c82d76cf3 -555, 0x8cb4f08fb1f46b4e -556, 0x5df5b1c00ab261ac -557, 0x6726d97935f08d31 -558, 0x4cbc02697842c6ac -559, 0x6c0440408a22bcae -560, 0x2327f06b5ef97cf8 -561, 0xabf95d4d77e37c76 -562, 0xc53b4d7aa97f77d6 -563, 0x6964842fd4206b42 -564, 0xee45d852faa5932a -565, 0x607e303bc41e73e8 -566, 0xe604d0952299ff3a -567, 0xd762802eed4cb935 -568, 0x4cf13e77ae1782aa -569, 0x6780f1ac226eb1e7 -570, 0xc102e38a0e8e8199 -571, 0xb97f0632dec2edb1 -572, 0x43b1a8890a987c2a -573, 0x5603f8d9115551a -574, 0xdd523847a2d2346a -575, 0xd9a6c2e9be51ec7e -576, 0x5c87bb42ff344def -577, 0x1c08b83d807a9322 -578, 0x6c79b279737cd049 -579, 0xc75ee98ecd59cd3c -580, 0x318284b03e77d76e -581, 0x6737a1e79456ce1a -582, 0xefe096a77d952f55 -583, 0x37f780c27a9fdd68 -584, 0xfefed1b3b932191e -585, 0xdf552be0dfc09adf -586, 0x4d210f71c1ccfe6a -587, 0xf524993a9f48c96e -588, 0x6fb8c3c46cb1e951 -589, 0x2ac8c28e67eb7b03 -590, 0xefcb311d060d2897 -591, 0x675c6ca4aba62734 -592, 0x1f5f1df09191b5ed -593, 0x177d32b3b4fe46da -594, 0x58f48456e4a88cf2 -595, 0xec0233251bedcbae -596, 0x11046407a9ce0c19 -597, 0x50eccedfa2531ef9 -598, 0x5769c9369f18c53a -599, 0x879442d615c8f67b -600, 0xc7aee966f982a0a7 -601, 0xaadf9a353e6dffd -602, 0x216d2fcfe81b00f7 -603, 0x8b17b3b2a61765b8 -604, 0x7cc969d82c53763e -605, 0x1b1a5d88afda0c8e -606, 0x21ea1e785061959c -607, 0xbbbf45849572539e -608, 0xf84972b569d342a6 -609, 0x85952fc81713400 -610, 0xf6bccc50b5741a48 -611, 0x35106a9ef28f5be -612, 0x785370b833caca28 -613, 0xc6c5c3d1bbe5b4ef -614, 0xda7658fec38bbb8c -615, 0xd3d1e9de94c6f41e -616, 0x73ad91859892dd7a -617, 0x35621a8da5e3fd19 -618, 0x5530b00cd5c63fb2 -619, 0xfa36112a09c088cd -620, 0x302b7f4fc815cd73 -621, 0x1fa4adb717689692 -622, 0x3a15fd5eb37c731a -623, 0xcc854934e21d4cd7 -624, 0x1d11465a34be290e -625, 0x213b3e59f10b1d60 -626, 0xf923efefe3fd28b8 -627, 0x81b56a961626ed7d -628, 0xe4f41f8c283c8fba -629, 0x374ade85b0260e4e -630, 0x4cf71f967d36fcca -631, 0x705b52b4a9d5d174 -632, 0xdc6f883cf909c428 -633, 0x44dd73ed064e8a3a -634, 0xdcff5a374c2641c1 -635, 0xe3177de93b2197ad -636, 0x71f40cde55876808 -637, 0x4c12e600bd6a1b3 -638, 0xc3940e86b962699c -639, 0x133569f533cf1540 -640, 0xcba6db36e8054239 -641, 0xc7c92f14ee34a962 -642, 0x133c8d42f4690453 -643, 0x2a62456f39aa3030 -644, 0x35354ef813ee1dec -645, 0x35e10f4c2f2fb795 -646, 0xf105e888f10c8397 -647, 0xaa22e206ac7652dd -648, 0x65121135905afd4c -649, 0xe2c49866de9626ca -650, 0xeb6ae66e1a605d02 -651, 0x7379ba1f2f16b81e -652, 0x4a3a91e2f22d4d19 -653, 0x30e4af3cd5e5a24 -654, 0xac59e67a483fa52 -655, 0xc4f027dd48c1e37d -656, 0x91263160b58e9e0d -657, 0xc7672b7fbd4ef6b2 -658, 0xf3262da8a7645caa -659, 0x7a5f4990cab96f40 -660, 0xcec55da0937d86a4 -661, 0xd25017295c98b613 -662, 0xc2c9ad08c34fd189 -663, 0xfb6ca6018b1e019f -664, 0x480ee3cc62324c8e -665, 0xab37c56a10ab0519 -666, 0x13fff4e20b1eb15f -667, 0xab25dc0f003e940e -668, 0xdbadd5f2b73aec35 -669, 0xa7b4d6770d19f43 -670, 0xd28144880c1c5434 -671, 0xa435c41dce914dc5 -672, 0x9883a2e3cddd7ad -673, 0xddb29b179c922b28 -674, 0xed3f6669842e0c39 -675, 0xb663238d46b213a7 -676, 0x6346ef1606873452 -677, 0xe7923ae257befe28 -678, 0x848ce090039c77 -679, 0xb77a6da428f4da49 -680, 0x6d9acffa8252ae03 -681, 0xd90d55fd8f8abf1c -682, 0x28718a78a031f802 -683, 0x8305f9005a1b1d6d -684, 0xd065b82167b53418 -685, 0xec65275154e9da5c -686, 0x292c7a783bc2dc04 -687, 0x71aa213998c2c31a -688, 0x114032c57e9fc4a0 -689, 0x67c3675a88faa9d3 -690, 0x7813f653eef4d4fc -691, 0x50004f43e4f4c43c -692, 0x43d3ac5d63714a93 -693, 0x4142e7030323e77a -694, 0x5da693da8e656d6f -695, 0xac696f7b0818c8b -696, 0x910b5df8803af3fb -697, 0x8d89168d50ded4d6 -698, 0x37c31ab0b2635495 -699, 0x66d97616af36f929 -700, 0x2ada02a3c0389bda -701, 0x62eea272c6334ef -702, 0xc8afae44f45ccc49 -703, 0x4978910fb289af22 -704, 0x64590f6a489183f9 -705, 0x594837052d1ee56f -706, 0x8553a88dd84e460c -707, 0x5c11e1d61832edfe -708, 0x7d5b6fde3c05ef8d -709, 0xfaf96bbdea0d6f11 -710, 0x2112b6f8f25fc3b7 -711, 0x6ce347dc5bd8d9f6 -712, 0xb072e2c4076aa185 -713, 0xf4162f4ab453ead3 -714, 0x369789462fc197c7 -715, 0xe732c5b207c55f3c -716, 0x4689ce674194c32c -717, 0x6bcf28130ebd7bbe -718, 0x4d7a25def10edb97 -719, 0xc4a2283e380f5239 -720, 0xab31536a95f7e336 -721, 0x50c1ecd9e4dec3e4 -722, 0x1bbea15462cfde71 -723, 0x1e7c73d56d6e939d -724, 0x7c46fb35982735db -725, 0x83c23f93c4221593 -726, 0xddc566e8005e0e6e -727, 0xd0551a666c088325 -728, 0x2c57b590ab686557 -729, 0xf2e9351a14724fe1 -730, 0x45d25cf2ebb2ee0d -731, 0xbe23d2a8fc7aea1 -732, 0xc721cb7b65d8dd7b -733, 0xe6642683775efcac -734, 0x6c29ca0adc0a83e0 -735, 0xd0de3128954b2eef -736, 0x7abea9b318f9a544 -737, 0x3a63475d59d64b22 -738, 0xb804c9cd589c817 -739, 0xfc4f880ac9dbc246 -740, 0x414d492c8870732f -741, 0x3ee15c71660a8129 -742, 0x57f4ab3a25da00eb -743, 0x5a1d89d6f9eaa29f -744, 0x60139567a3d66313 -745, 0x5759ec448bbaba05 -746, 0x44d3088d8cf1cc1 -747, 0x77d8019fadba610e -748, 0xcdc729417b13904e -749, 0xdc77421f8b2bfb0e -750, 0x47ae0c4222bc1d4a -751, 0x22768d4b89156cbb -752, 0xa60d3ef97eae8ddb -753, 0x7aa22493dbfceff3 -754, 0x2ee0ee06bf9a5fb -755, 0xd54b7701d7afc96f -756, 0x1aa49ed985a53efb -757, 0x97d6fad17caacdd3 -758, 0x1b2f6dcd1d10fe -759, 0x46347f5bcca0f422 -760, 0xb9dc35c224242d3c -761, 0xb5dd657190fa8a03 -762, 0x50ff9434c7862fae -763, 0x7a05cd5c25bc1209 -764, 0xd5aa141a498560a1 -765, 0x73c62b8d0206e8b1 -766, 0x740f369af4ac9f51 -767, 0xe7479d9a0716b94e -768, 0x8b3d0375452d633 -769, 0x6ed58c4d905dfe37 -770, 0xbefb7f1e9c79f6ed -771, 0xe2cd7ee311d7a8c7 -772, 0x932cfb8178492b88 -773, 0x8e39205fbe47711c -774, 0x149ea35973cc055e -775, 0x96b73b6cfad8ad7c -776, 0x572898ff1f967eef -777, 0x795e8172b62cbf69 -778, 0x4e3d34c5bb921c28 -779, 0x7a4c623c7295f4c3 -780, 0x15b7ca7ef7179a7 -781, 0x48340589636b223f -782, 0xfcd61c186913a7aa -783, 0xf4f7f0cb49d78f5c -784, 0xb9591798ca218218 -785, 0xe304bc438ae109a6 -786, 0xe65890c4bed537f4 -787, 0x54719032d537f085 -788, 0x927bbdd2931be349 -789, 0xfd4a852025d02c14 -790, 0x915a7c2bc713221c -791, 0x4adac4a960ecdf9b -792, 0x58133bde7f0edb25 -793, 0x73d00fa5f091794f -794, 0xcb2fe411bfb56cf3 -795, 0x54a4f66f2c5f6220 -796, 0x125bce09ee493ea -797, 0x766ba624e5f3b266 -798, 0x884478527221bba1 -799, 0x8a1920c18ba6676a -800, 0xb0c08f7fbca3cdbb -801, 0xd3b570c49c774405 -802, 0xae4a55264d8e012f -803, 0x91a25b7c5e5872a9 -804, 0xeb65375cda8296ef -805, 0x149f98de1b29f459 -806, 0xe00a81c67b8ba093 -807, 0xbd7da1f6c6be49f3 -808, 0x4ad7c327a630b482 -809, 0x7efc93c60449206a -810, 0xff182d272189a04c -811, 0x4e7892e8adc82e19 -812, 0x1327926bc36b7f99 -813, 0x9b6a8085d12fca4d -814, 0x34a29cb661d313b9 -815, 0x7b3398923572c6a4 -816, 0x8b3ff461c821a464 -817, 0x8e5581286f82448e -818, 0x82a8d223a7b6937a -819, 0x1a0c750d6029237a -820, 0xf19a0a7f578497a5 -821, 0x2e6a85391da4f651 -822, 0x98676879af572d0e -823, 0x50110f1f738507a0 -824, 0xbe88faea0d4f8cf4 -825, 0x183bdc54555acc08 -826, 0x1d4dd72e0c7a82f1 -827, 0xef500f1dd19059f1 -828, 0xad98db5c386d33a8 -829, 0xa17bbcaea00a9361 -830, 0x8b8967126839c74d -831, 0xcc9d0e484a9b1dfc -832, 0x4216966d5af86872 -833, 0xdc3f8b825876e2ef -834, 0x3ef820c11b63f9f9 -835, 0x78da1c113cdca011 -836, 0x7f74559d9177c87 -837, 0xfde51ee31804305a -838, 0xc491d970fa5ce907 -839, 0x89b0ff390723a6ff -840, 0x7452028822f2d7bd -841, 0x3e55cee332d78047 -842, 0x5dabead1e04596ed -843, 0xc4e878a6ba18aec7 -844, 0xa785fac229f7f353 -845, 0xd95155479c867ad0 -846, 0x678fdb174e3774e3 -847, 0x54106e733d27b887 -848, 0x60bdc0fa294764ec -849, 0x55f1d4270179bd54 -850, 0x80165190a3df59ba -851, 0x81b128a7508d2174 -852, 0x831d78b199fe132f -853, 0x80ee7eba239ed866 -854, 0x359f1906550f62bc -855, 0xe293dd490df5f745 -856, 0xf3362af4b0de9c01 -857, 0x9cdc46fbc7f9bee8 -858, 0xe577a13809850692 -859, 0x1490ed2b4ed8ce8c -860, 0x63b861e371a125f4 -861, 0x49916e67be281c2e -862, 0x1a3a8999e60fe603 -863, 0xa373c8ff642e222b -864, 0x8112bea03196843c -865, 0x29c507a4ee61f7c2 -866, 0x4eedd845cd786583 -867, 0x1d9bdbe51c1aa7c7 -868, 0x3e5d043d5ab768ad -869, 0x8a3c0e9801e39bee -870, 0xc49cd378bfb3c516 -871, 0x1b9ebe1f63af91d4 -872, 0xe44afa8dcf0f28f5 -873, 0xf5a7ab4f9a8d8cc5 -874, 0x8ba7cba3af03234 -875, 0xe79397a55e04d4b2 -876, 0xc49014ba09442ad4 -877, 0xe58a5dd949723f3b -878, 0xd67c781ca27169dc -879, 0x409f1435da244c9a -880, 0x7ec9df0b04c17696 -881, 0x8a34c51bafd6e390 -882, 0x2f60cc0ebb4a781d -883, 0x161283264abcb573 -884, 0x9c9db4bf55a46c8a -885, 0x381e6106ff6053cd -886, 0x6e8fd5a7b8ed1c18 -887, 0x89d0da00aecbae85 -888, 0x1baffa4542d298f9 -889, 0xbf53f2e1dc44d359 -890, 0x4c31d9bd148120a8 -891, 0xc36be4d6404a748b -892, 0x400584c614a63b32 -893, 0x6622b75443cfa5dc -894, 0xbbfcae44c8eec3d -895, 0x28dbf6790e9ad12b -896, 0x7779f5d56f2613c3 -897, 0xd221ad0b4c565a5f -898, 0x4949752332a98b9 -899, 0x5bd9931a164b2717 -900, 0xb5108565cbec069b -901, 0x2e8491298f41ecd8 -902, 0xc94483fba700a620 -903, 0x7c1299ec45d1e22 -904, 0xf37c3a7e7e020358 -905, 0x3635565fc484cbf6 -906, 0xa93b65e210af2a2b -907, 0xcf18d773960a3667 -908, 0xa7529ce40290e679 -909, 0xd539e8afab9ff21f -910, 0x44fa456fc4e2908a -911, 0x138e0dfef16de572 -912, 0xb55ac8aa42abe21f -913, 0xc8a7a9ed90a4920a -914, 0xcc0f0dff8f4f1fc0 -915, 0x78c99cc82195feac -916, 0xa7669ab9998bdb89 -917, 0x2bf510028d6ea80a -918, 0x8995287d2a60326c -919, 0xb3c5676e9772daa7 -920, 0xf210121d1f5cf3cf -921, 0x3ec0fa808fe50e83 -922, 0x42f5269fd9717a58 -923, 0x7603ca20951ebe1a -924, 0x7f75e4c3afca107 -925, 0xa08af524629c434d -926, 0x1d144241418f216e -927, 0x7cabc46fab0dfa3b -928, 0x317172e8fe407c21 -929, 0x2694bf3be80d8b3c -930, 0xdf18b4db02b875c5 -931, 0x5df0cb415bc5a2fd -932, 0x954386c3df63e124 -933, 0xf0ad49aa400ee528 -934, 0x2a941df25bb38eb8 -935, 0x3b43af03f2d3eefe -936, 0x7a58932cec64555d -937, 0xabb56ea03deeaec1 -938, 0x33673826e58f9a52 -939, 0x8cb6fb8e42cd9f80 -940, 0xda88c439fe3b9dbe -941, 0x31cb50c4a69d5883 -942, 0xe2164f69f02e57e4 -943, 0xb6ea04dd0ba2811f -944, 0xb3458306841de334 -945, 0xbc6cd1a3cf526a19 -946, 0x9424b50438e687e2 -947, 0xa668fa546aecdd82 -948, 0xb8783bd3623d86f5 -949, 0x6d4341f1dd170d5c -950, 0x1202c1b457913af9 -951, 0xf2b532602b908de1 -952, 0xb15f6354e6482108 -953, 0x4a542e16c973ef2f -954, 0xcef0b8ef4bcbbf64 -955, 0xdd7090f21726ab28 -956, 0xd53de858192a0094 -957, 0x58e723302bf4d675 -958, 0xc3ffb98f745409ec -959, 0x5489e4fa52210035 -960, 0x3a6a10b142c74d43 -961, 0x69436c7b12a2c4c7 -962, 0xccecdcc046f76f03 -963, 0xa6b9793a0660fc0f -964, 0xf114cd63b38756a5 -965, 0xa44ac409c2246f07 -966, 0x65dd5dde54b6aa26 -967, 0x5df21b90d999494a -968, 0xafc3d89336a6d356 -969, 0x1acc23065a7ba8bd -970, 0x87ff903278b23e2f -971, 0x58e4a44f7e4c012f -972, 0xb2eb460bab7744a1 -973, 0x9b1aa5a17ba581c2 -974, 0x90c87a15edc021b4 -975, 0x43369d9b481b28a5 -976, 0xd05dc8b00763dc1 -977, 0x40f058f20d77b5e6 -978, 0x2502c9829f78bdb4 -979, 0xa5ef6729f601b2d7 -980, 0xab49116e5d404023 -981, 0x6b77c686cd653da8 -982, 0xd99e324ce1468143 -983, 0xb338c64071fd5469 -984, 0x94f67b1e04fb4267 -985, 0x16f34d11e280c73f -986, 0x9a6c4cd947bed4e0 -987, 0xd1bf20f05cd068f0 -988, 0x2ced63b15eaa27e4 -989, 0x95989123251dec6a -990, 0x38906e5a3cb4fb01 -991, 0x4b02f03a01180ba3 -992, 0x67d5842c2b13960a -993, 0x45dc1d0f5981374e -994, 0xe6dbf0961817185a -995, 0xf5717f537c683578 -996, 0xf7a689617ffe5002 -997, 0xdbd1595a8ec1ac24 -998, 0x545db9592b492be4 -999, 0x9e1085dc2c3335ed diff --git a/numpy/random/tests/data/xoroshiro128-testset-2.csv b/numpy/random/tests/data/xoroshiro128-testset-2.csv deleted file mode 100644 index 2de341ecda94..000000000000 --- a/numpy/random/tests/data/xoroshiro128-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0x509946a41cd733a3 -1, 0xd805fcac6824536e -2, 0xdadc02f3e3cf7be3 -3, 0x622e4dd99d2720e5 -4, 0xaacfd52d630b52bd -5, 0xa94fc32eb4128023 -6, 0x9ee359839e68f625 -7, 0xd9f180e03b686e4f -8, 0xd6825e7d8fc65068 -9, 0x887f15071c20b9d -10, 0x6dc39f8336eeaa66 -11, 0x13d17509661b69b -12, 0xdbe703ea4e61caec -13, 0x1a4deda7c51c5b7b -14, 0xe2f2259fb30bafcc -15, 0x7eb5a4d5f053fcbf -16, 0x4704d55257921919 -17, 0xcfeb1c70eacd6734 -18, 0xed98c92a0d6b8b3e -19, 0x4efb928a052188b7 -20, 0x15617edcea5e98ab -21, 0x8ac022e71a4d1a40 -22, 0xe0ae2cdf81cc05bf -23, 0x11ae6d329bc72f19 -24, 0x5369885a834c1073 -25, 0x7a865692c8495a12 -26, 0xaf752d7df50f6968 -27, 0x4b81c799c968e005 -28, 0x4104e06972751b34 -29, 0x8600214cf598d6f6 -30, 0x444545884a4b0a80 -31, 0x2d13243847e43cfe -32, 0x6064921c3b70601c -33, 0x1b2c2f204185130e -34, 0xac1e21160f7e90f4 -35, 0xa718d564118e2bca -36, 0x25fb8750f330bdc1 -37, 0xcdd8329cb365e06 -38, 0xfdcfbff05c3470e3 -39, 0xcbce143aec5155a5 -40, 0x1d17b5b1e2c3c21 -41, 0x68fe2fbabc30aa23 -42, 0x19086e8dbd448c02 -43, 0xdb7d8126e6f3d1c6 -44, 0x1865e34fb131a69f -45, 0xce3be151debb3e9a -46, 0xdf573313ce569b70 -47, 0x3a7fcf8ef4fd495a -48, 0xe26450c5ec487bcc -49, 0xe99eaeeb35354e -50, 0x959e7e6cb8bf55d4 -51, 0x3ba4778a79b1b758 -52, 0x30e4f35a940c2e04 -53, 0x67717bb8a50f2c22 -54, 0xa9b3e9db4934cd8e -55, 0xe22bc184e5d2ad8d -56, 0x7390583f39dfbb76 -57, 0x19e7ba95b2482b72 -58, 0x549b0c65abc1615f -59, 0x43989e0d7268118a -60, 0x1376e3b4f7319b9c -61, 0x41bc4dd69e4a3eca -62, 0xdb5b777a0a90e830 -63, 0x4885cae86597a2fd -64, 0xe472ab9f66c240b5 -65, 0x387e53bf7d31a3c0 -66, 0xd8826e1be0364bef -67, 0x2a334c6d6f748f84 -68, 0x10c7d9da8f7ba2ce -69, 0x7b23655caa5a3872 -70, 0x4e52d38a6128c877 -71, 0x581cf9ba515b9abc -72, 0x464df6946cf89b19 -73, 0xaf0f20053d807827 -74, 0xddeb1fe3d90b8aa2 -75, 0xccb863176382287e -76, 0x831e79b8d6d91e8b -77, 0x88ed0822fceb3abc -78, 0x66adaa8387e19785 -79, 0x23a5005fb1c9c598 -80, 0x4ab28f3b1585657b -81, 0xd620ca461099e06f -82, 0xf056f4fdf816bab5 -83, 0xeaef5b9b3cdb015c -84, 0xee4f14793695313b -85, 0xaa406259c23ccb33 -86, 0x9ec3e4585b6d933f -87, 0xb5806dfe257e6c7c -88, 0x7bee992cfb5fd41 -89, 0x91a70b316b42bd18 -90, 0x874df34eea24edb5 -91, 0x379a0a3ad79d7db2 -92, 0xeaea9f7eb0292235 -93, 0xf4742d169fbb5198 -94, 0x57a84e20592727d -95, 0x5d8ec89195373de3 -96, 0x22eaeb51baa32533 -97, 0xc3cad6ca8be847bb -98, 0xf316a8b9b6172611 -99, 0xb687d7988a8a2ee5 -100, 0x8635d3f011c6253a -101, 0x2280ec837c98731b -102, 0x2f815c82713ebd61 -103, 0xb2b4c124ac4ea1a9 -104, 0x5db6c0a6a90a1866 -105, 0x3cc317501c96e9f8 -106, 0xd38b689a10819dac -107, 0x1b8a114bbc51341e -108, 0xa276c85761cf5978 -109, 0xe6b3d7d5b3b6dc0c -110, 0x14963fae33e6c2fa -111, 0x88f83f53a67231d7 -112, 0x77aec607b4aacad8 -113, 0x33cddae181b93178 -114, 0xf1bfcef2a7493c7d -115, 0xc4177359c975f669 -116, 0x9d603ef0b6bee8a2 -117, 0xc16ee77a4391d9b1 -118, 0xe93f0736cbd3f398 -119, 0x327500ca9afb0730 -120, 0xd8cba3672638e75d -121, 0xd87f00175eea9770 -122, 0x6680cfd0f0651f47 -123, 0x13287cbd1981e44d -124, 0x9da5fb61bd633e98 -125, 0x2d704f64c4ad5444 -126, 0x4c28b98c2f7349e -127, 0x42d156862c609af0 -128, 0xcbd49a9595d2964e -129, 0x8d54cf464a529131 -130, 0xd6b74f26dd0e313d -131, 0x4ef8b45baf3ec3a7 -132, 0xfc8be973c860481c -133, 0x6112312f08028018 -134, 0x78d492d0049b30bf -135, 0x3160db98b853a1a5 -136, 0x81eb3fabead6d97a -137, 0xfb54ee3224945380 -138, 0x3c62663cd2aa07dd -139, 0xeaa2eff9e2752bb4 -140, 0xbdecb6e8041eccf9 -141, 0x9a135a78514e92a2 -142, 0xacdbb7139969ae66 -143, 0xf71fc98126f511ba -144, 0x1bd6dc2853a20898 -145, 0x6fb80e8eff8b26a3 -146, 0xfff9ba38f9c3664f -147, 0xa4224ddddbe3a700 -148, 0xd76b8f1bc09e35ad -149, 0x1b6c5bdad062aae9 -150, 0xabc5a61088f2a3f4 -151, 0x5160b68fd92f30c -152, 0xb2cd4c619e1cb446 -153, 0xceffe90f16c69c0a -154, 0xd7845f2eb8b1bf67 -155, 0xb6ddd2d76e99be45 -156, 0xf6212b33d0bc1019 -157, 0xdebc75b6e2d6db50 -158, 0x7a6d61de4c4c3a9e -159, 0x473933055a8727a8 -160, 0x83ca458dff43a0aa -161, 0xde2b9e38b321aa3 -162, 0x78ba83864952e9de -163, 0xdb4c6db1049e8406 -164, 0x9c3a30ffdcfac7ee -165, 0xeab6e9a0cf1ecd0a -166, 0x3617b147dd5ce2ca -167, 0xe5c000907864b48e -168, 0x7dcb724b2767b90e -169, 0x4ecd7ad20e75e566 -170, 0xe03be67c421d2942 -171, 0x7e7a68988cd564d3 -172, 0xa8c25e5165919c51 -173, 0xa1d550ed4a39e690 -174, 0x6e7abdcf98453f72 -175, 0xe57eb7d34da3c5b -176, 0x8da6eebbab5ef00a -177, 0x7574363208ed2700 -178, 0xff06b2a934a953b9 -179, 0xf3c8951de92dcabf -180, 0x78b817c0dee711db -181, 0x358522c82c15f627 -182, 0x81d54c2d5ef396b8 -183, 0x1f98c21036a70b27 -184, 0x4d3692ad8d5e5112 -185, 0xb63674f55b06bd46 -186, 0xbf30a7aada9b1cc2 -187, 0x57f75205e81f6b47 -188, 0x37e9ab7e796bd0c9 -189, 0x34aad24654a70694 -190, 0x5602376e46ea14ea -191, 0x3761258bc9e79732 -192, 0xffe7d79561680d75 -193, 0x35b82f78a688b86e -194, 0x42d23cba46456a80 -195, 0xd64f0c226c84d855 -196, 0x6ef5d71859f03982 -197, 0xdb7dabdf5282c818 -198, 0x94ec7253c617acfe -199, 0xcc118236ff2009fd -200, 0x9f91eaee04579472 -201, 0xbf79aadb5a3a4a1e -202, 0xf6ac29ee74fae107 -203, 0xc82643f14e42e045 -204, 0xb08f864a06e4db72 -205, 0x7a2a402f1a000aaf -206, 0x2c2e03247fad91fd -207, 0xe70bb051040fd7bf -208, 0x8d42d479e23862ed -209, 0x3b2b368d659b45f8 -210, 0x96c8d7c31b396bc5 -211, 0x41664c476575aeea -212, 0x303ba0289cd281fa -213, 0x2936193bbe462f68 -214, 0x4a63581937611f45 -215, 0x10f69bed29c2a652 -216, 0xcda3073cb7dd2082 -217, 0x374da8d58157bbdb -218, 0xf3c040dd9a135d51 -219, 0x5ae628cef3e753da -220, 0xafdfa06ac9ed9eda -221, 0x94582756d1cc948b -222, 0xce387a039a43baa5 -223, 0xd9aab74b36032cb4 -224, 0x720e30cbfc81765f -225, 0xba42d487e461d31 -226, 0x445fa16350da585b -227, 0x43a3b57501104e19 -228, 0x55571957e6267eb3 -229, 0x8c1f8cc37a83b2cc -230, 0xdd433be6a0188876 -231, 0xdd0c1053757845fd -232, 0x47d17129bdec523 -233, 0x5fdc39aa7f38cf97 -234, 0x92ab54d8c66e4417 -235, 0xf46a39cdbdee494a -236, 0x6a226e83cc244891 -237, 0xdd2dde8767318719 -238, 0x794e882325646a7 -239, 0xf1d269b9fa82e09b -240, 0x5871ab313f97bbde -241, 0x30a0f742fe7a1746 -242, 0x8f3b8c2ef199341a -243, 0xf280d28fd6ab1ade -244, 0x8b5e8a112798cd0e -245, 0x80cc043e4ace43b -246, 0x1dcd69d6d8f6c527 -247, 0x467dc81c1f462ff8 -248, 0x47e98dba34af7440 -249, 0xae4599c86b11c6d5 -250, 0x4cc5574019676ca9 -251, 0x79b0a34fc332cfbb -252, 0xc5c778c13974e8 -253, 0xa1773cddcb7f3bd -254, 0xae20dcad57acc7e1 -255, 0x11e6e98c02b4ee9f -256, 0xfedb58925c42929 -257, 0x2ab56b3fccf3c5b6 -258, 0x5740e0a90920bbdb -259, 0xe02ea72778a4cc5c -260, 0x7fa9448e7563e3e -261, 0x907603f2ccd28776 -262, 0xc655d1fbe3fbf1e0 -263, 0x40bcc587212acc1b -264, 0x1af8bcb6c4902043 -265, 0xd47a71193454c4ba -266, 0x9e9cb523c3c9dfe9 -267, 0x4b9e107b36ba9f0b -268, 0xc89d86427a63c956 -269, 0x2353f37179b7147 -270, 0x7c6d3c3d67f1f245 -271, 0xf008463da2875270 -272, 0x4494eb9f1d83aca9 -273, 0x84dc57b61ca36077 -274, 0x461480c6f708fec3 -275, 0x6256b05de4b8233c -276, 0x2b02af1084a4dfd5 -277, 0xd4f3bb079fb41a61 -278, 0x83ee412671f4ef78 -279, 0x6c46e97c8f197f8c -280, 0x4d949413ea0d1e9d -281, 0xd7eef89a4d084d17 -282, 0x18f03d6a52592eec -283, 0xaf6fc843c53e63fd -284, 0x551f420f53de9097 -285, 0x4fa8dd599dd1365d -286, 0x399727713519d072 -287, 0xbdf7dbcc18541feb -288, 0x3f2336894ebad1fd -289, 0x903a74b979250389 -290, 0x733313e457a65fe -291, 0xd189b01b9258d1c5 -292, 0xb2d9533680f9a70b -293, 0x2a0929d54aaae5c6 -294, 0x9c6b844de0367b34 -295, 0x341d37b0d1e75bac -296, 0x5cd370014b87cc94 -297, 0x4bdb409173abcb35 -298, 0xafd38d4c9d91240f -299, 0x76d7d551533f344 -300, 0x3779e62cbdef738d -301, 0x211052148f86c129 -302, 0xf2f325e09a17da4e -303, 0x1e874c70b2d62dec -304, 0x412fb842edc1c3f0 -305, 0x23d9f5e6c9d83d27 -306, 0x8e58937e012d3c76 -307, 0xb0ab1175918a765 -308, 0xfc7991f83e0e06fd -309, 0x1066d7c10f16cf5e -310, 0x29a14ec418defe81 -311, 0x20f98e60c158d08f -312, 0x463c0497605efae6 -313, 0xdd02ac91db3f0cb9 -314, 0x434cbbb353edfa66 -315, 0x892ea5a463774836 -316, 0x8e00064e77225923 -317, 0xca7ec8ebe244a404 -318, 0xa9146f68a99e0a77 -319, 0xc85ab0fd6c4c8a99 -320, 0x4a1104cb1287380 -321, 0x25a570b6e2b45828 -322, 0x3e3f5935137b0d61 -323, 0x499d6aa0407317b9 -324, 0x4ab08263445a3fee -325, 0x2dcd45f060d8f5cf -326, 0xa73225adf6418dd1 -327, 0x738ff6caaffb838c -328, 0xa93e4a4d2330026e -329, 0x47421b8206cf7ba8 -330, 0x5d9ad2876b1a4e84 -331, 0x6557edadf965aad3 -332, 0xaeffe33ca45ac0bc -333, 0x2196b20f7074c7d2 -334, 0x351a0c784e1056b4 -335, 0xfefaa1eca46cba97 -336, 0xf58741e34d53876e -337, 0x5942f6de49d5cade -338, 0xe1b0d6514455ac99 -339, 0x456dc6a18b651d36 -340, 0xa8d240033f5c9074 -341, 0x7d758bc84ec678bf -342, 0x21ce28f61ecde645 -343, 0x83b8f058c1b36557 -344, 0xeaf452c4467ea627 -345, 0x60bb8582e53d2f9f -346, 0x9649572eaa40c725 -347, 0x59533356c226c99a -348, 0xc06b7f790fd4fda1 -349, 0xdb7d827921aa5962 -350, 0xd9be204c05438878 -351, 0x67f903bed4fb0450 -352, 0xf8e583b98827118c -353, 0x72c8508fca1e207a -354, 0xcab1df54ae1542dc -355, 0xaaa774d0c8833857 -356, 0x710c4b86e747bbcb -357, 0x8ffc4dd34d5f12db -358, 0x3b1d4fbe64743023 -359, 0x3ca88da03e8d8da2 -360, 0x970b522fdad62c7d -361, 0x7596d74c3e598a71 -362, 0x1e9c86f3b5d93e5b -363, 0x378a3fe78b730c3c -364, 0xfbc82d6ace6346 -365, 0x1eddf6aca48b7ff8 -366, 0xed12c2c2e137a0c6 -367, 0xd2001d92384c365d -368, 0x69a1bad8bc8742eb -369, 0xe1b460d2e65e9a74 -370, 0xeff030a0954e3832 -371, 0x23ac5413d4b3e60 -372, 0x802fffd55c4d2279 -373, 0x1776b952e25fcacb -374, 0x595f3f386b0f524 -375, 0x3f2d5e55b839c40e -376, 0x145202db5650c14d -377, 0xc28858131b702442 -378, 0xa1381d43a4f59fcc -379, 0xb3088835a18600fc -380, 0xca7830bf9187f705 -381, 0xa189dbff019ca64d -382, 0x82ad4b1f88491340 -383, 0x27262f1b70bcc1c7 -384, 0xaa52ad0b4cdc95b9 -385, 0x6898a6e5a791cca8 -386, 0x4c892bd369fb7c7c -387, 0x2c5040316ad789e4 -388, 0x25aceb42f6d853d4 -389, 0x8f3e09dd6e6fcacb -390, 0x35f4e10c7b4e29cf -391, 0x6156e9fcc26a6e83 -392, 0x8a8389e8a9c70fda -393, 0x81219b723a3dd912 -394, 0x631f0c99c62650e -395, 0x9cec1c4f650d6c4c -396, 0x1d3b402d466479aa -397, 0x6d2fc0877f6f8e46 -398, 0x2000b7178225c4c -399, 0xb01c45dca932ffb2 -400, 0x61f25ea549d3b3ef -401, 0xfc0733a134f7bb8c -402, 0xea3ab2a0cc6a366d -403, 0xe26bf2b8fe0db591 -404, 0x3186c9cdd8757ee3 -405, 0x9cb472c0c526cf7b -406, 0xdafe18916dbd33d2 -407, 0xe0b15a3aed330dec -408, 0x7079ae5641dd16cc -409, 0x49b6b9756c347b90 -410, 0xdda875fe11e94d34 -411, 0x8c77fb380278f362 -412, 0x602904b0cd3bc464 -413, 0xd2dc40f56fc531be -414, 0x753175bcc1a93ba0 -415, 0x333a71f4d2d756ea -416, 0x7b862ff73b46e03b -417, 0x9df539d017e9017e -418, 0x4113e5be11f63f2c -419, 0x422942050abc4fd6 -420, 0x737b754e2add8d6a -421, 0x313e6c1ecefdca96 -422, 0x5436d70ed2ee4cdd -423, 0x1db894fde99e34f6 -424, 0xd86bc0b79db9a96f -425, 0x9d904f0aca534217 -426, 0xfb14afbeabfc04df -427, 0x9c4ccba431333edb -428, 0xc7de0af1a5760939 -429, 0x735669225566ce71 -430, 0xf5815dabb0665733 -431, 0xf0a6b7c00d4d569 -432, 0x1448e6fe1432b7af -433, 0x2e0586f6c9e6e7b1 -434, 0x7b75aa00eb44d795 -435, 0x7ba5cfa018a44c87 -436, 0x5854a5f78e636c5e -437, 0xdcbe856037d0228e -438, 0xe8882d90f7259452 -439, 0xcb6ff056c4171c82 -440, 0x4a7bd2245f0e0e32 -441, 0x3e2a40308897a793 -442, 0xe404dfa4d3284167 -443, 0xab022bce6ad8cbc -444, 0xbb5a145064db9976 -445, 0xedd82ddea103ab7e -446, 0xcc906d55fb10a8cc -447, 0x63ba976a36e0cf56 -448, 0xb3ef5ad3129eedba -449, 0x409b01e4107e9dc4 -450, 0x41059d8141efd96e -451, 0x10bc4a29ac5cd941 -452, 0xe2fd0fb5c7787046 -453, 0xba24bd0f8d018cb3 -454, 0xc9cf71f73e6979f5 -455, 0xd79a917354d39e89 -456, 0x44fac8764c14e096 -457, 0x29c2cdcce0ce515c -458, 0x41c6704b232934ac -459, 0x2ace8d883c6ed401 -460, 0x76d37e5aa3c57f87 -461, 0xc7b7ae6275c47624 -462, 0x33e426b3e22bc96d -463, 0x77818a58fdc8b640 -464, 0x49c3b6b021037e35 -465, 0x8a941f067ca1c772 -466, 0x8dac8803caad398f -467, 0x2478a7f23abb4332 -468, 0x98ef79938ccc8b65 -469, 0xdddd5e6776f61726 -470, 0x8d9412cdc85ab90d -471, 0x901946d2c1a63b26 -472, 0xc93fbcced6bacc00 -473, 0xabc3dfbdcc9b8fc -474, 0x6b4ba01186620ec0 -475, 0xbb32573515ef782b -476, 0x174d712e47dc77ee -477, 0xd0528205819fe3ee -478, 0xab1f77e5dc7b0e95 -479, 0x7f86317fcf8bc84a -480, 0xa7806c55ff0b4f49 -481, 0xe8cdce88ac77263 -482, 0x2e497636f939d7c1 -483, 0x9ff5e2c32edc3ee -484, 0x71579e5276731bbf -485, 0x565c679f3f2eb61c -486, 0xc2a747df0c436c -487, 0xfc30f2f9d9489081 -488, 0x74548f1d9581fed5 -489, 0xb5819230ffd9afeb -490, 0x228ff1227ebe13cc -491, 0x38ac137ff54ff158 -492, 0x41ed776d549ca7da -493, 0xb4cfe4cc90297ff -494, 0x17988d6ed8190a5d -495, 0xe27817eb69723f90 -496, 0xbe1cee1533890e29 -497, 0x8ee48e99d9a74f22 -498, 0xa31a5dceb1db5438 -499, 0xeecbbf998e1c0d43 -500, 0x6f8e0b0b2b361b9b -501, 0x2a102fca177728ae -502, 0x55a27f350de42380 -503, 0xc45ace761d5cf37b -504, 0xe14d0182a002d8a6 -505, 0xc05841ad2de5d64 -506, 0xca6b7b7131476892 -507, 0xe4a92da10eada512 -508, 0xf7a33c11f8927959 -509, 0x7b47639e2bcd8c44 -510, 0xaed8ec8dc551d755 -511, 0xba4b5ffd28ad78b7 -512, 0xc30ddd4d1df6ce2b -513, 0xe1b9bd0020b56548 -514, 0x8f73edbced893634 -515, 0x738098d32669cab4 -516, 0x28c03717c5adc3c0 -517, 0xbc044ebe07a8f4f3 -518, 0xc3083814802950fb -519, 0x8639da9ccdd4068 -520, 0x2ac89cfb975e2c41 -521, 0x8e163ccdbc863461 -522, 0x4a60169f9a3648fe -523, 0x6694ab36d7d02548 -524, 0x6b4e5764db952413 -525, 0xbf842329b9a13bfa -526, 0x1c8639cae82e7d92 -527, 0xd5669e818fb34170 -528, 0x1f4df6bc59f9f6aa -529, 0x8b192245d457c5a0 -530, 0xdff62af9d9eb696d -531, 0x53dcf9276ae1ab0f -532, 0xc1c4052d4c9d3c16 -533, 0x5c5f7b33e6aa6e0e -534, 0x482c8e4be2a5d704 -535, 0xc5d1632e532ddf97 -536, 0x92a41d90396b49c6 -537, 0xf895429c172ec71c -538, 0xab3ed20fad9ae896 -539, 0xbecd1ee462ba9dee -540, 0x29e020d2bf854671 -541, 0x4a31b52b2b48d795 -542, 0x14b2c4bf2ff453a2 -543, 0xbd49a5992f3deac2 -544, 0xfe19fe4becf1b1c8 -545, 0xa90ede0ced2811cb -546, 0x409de5d1234b16fb -547, 0x4eb18dd87fdd6cd7 -548, 0x52387faf2214a168 -549, 0x18678b302a911d42 -550, 0x484ccf18cb491bbe -551, 0x8610462c7e48b54d -552, 0xb2b2712e35cc4282 -553, 0x754abdb493e3ce4f -554, 0x352745881ade5eea -555, 0x37d4c7cc6c238692 -556, 0xe7a8061b7c0259d2 -557, 0x187e5ee097b24be1 -558, 0x41af64f7cecc63e0 -559, 0x33612ca0ca35a2bf -560, 0xc8b652dc6cdd0829 -561, 0xd050306acf3314b4 -562, 0x7bb7c4114d5d2347 -563, 0xd583132ce17b2f9c -564, 0x1473fcb33448ece2 -565, 0x5f9d56e869d06300 -566, 0x45c27eae73dd6391 -567, 0x15164b3b33d2c145 -568, 0x32991907d6370c8 -569, 0x9445ff1373a9635b -570, 0xf33ffa711ebc9d97 -571, 0x38dc80e03d8badcf -572, 0xf346f6f42e3c396e -573, 0x47bae2fa3827f514 -574, 0xde0e4fc698e6a6d1 -575, 0xd26d4b4097367afd -576, 0x16dea3bef70fe858 -577, 0x226decb65f433fa0 -578, 0x2e4b7f4915de64c7 -579, 0x4f31a10935fcd415 -580, 0x5e3e420e134d2191 -581, 0x52bf5207327dfe09 -582, 0xd8c4ab9ec015b93a -583, 0x55154818bf1ca7c9 -584, 0xc121666af28dcc9a -585, 0x9904729e1a01bd3c -586, 0x6e9cae3d292339bc -587, 0xf6fb78d385e10840 -588, 0x8fb67f5e56ee1e0b -589, 0xba17083a33230c28 -590, 0x9994a47b97c3dc9f -591, 0x53391314bd23bebb -592, 0x9ad473ee0eacee3b -593, 0xaec807e5cb1f0f18 -594, 0x5d5838c5e16e82ba -595, 0x7c810095640d10df -596, 0x898b9da105d90061 -597, 0x9296de76fe275a73 -598, 0xb118361c5dad2c6d -599, 0x4b9051df7724b504 -600, 0xd91789023183a552 -601, 0xc35ca6285eea0aaf -602, 0xb6fb918229e8bb05 -603, 0x4f3f41b3fe26df66 -604, 0xb63885de73089f64 -605, 0xc55aad297e8db9cc -606, 0x7a5ebc6cbb977bf9 -607, 0x122478e8d6b4b5fa -608, 0x52f69dc782aba318 -609, 0xce068981160e9756 -610, 0x303897ea358b700b -611, 0x9963ff7db9effb75 -612, 0xa3e4224b2372dc4a -613, 0x68d78fde1f0b1e -614, 0xb895f75785c0ec92 -615, 0x3df2981af65f3be6 -616, 0x88b17d18c7584a58 -617, 0x560834beafb27138 -618, 0xfa1d9ee07edbf359 -619, 0xc27c98d528ba33f8 -620, 0x58873114fbc61614 -621, 0x3f8112bff34dd5fc -622, 0xbe7fbc694b26e7a1 -623, 0x323d8907780f85fb -624, 0x7e77f48feec1f69a -625, 0xf6d8ac3573ac4ba4 -626, 0xf013633aaba2cd2c -627, 0x5c3153cd6f9f2fd8 -628, 0x4c3ae3906dc4e92a -629, 0xd2f375cec67af24d -630, 0x31943d0c1139dced -631, 0x95ee9d16c2320163 -632, 0x1c0f03c058441f3b -633, 0xa4dd49a2abbb39a5 -634, 0xcf6c4c9c695783ec -635, 0xbb0ea4c9a55af9ac -636, 0xb6a7a4c82fb232d5 -637, 0xd090cc06191a5d2f -638, 0x653c0a506097397e -639, 0x5a5af47067bba201 -640, 0x23df206d3d6f105 -641, 0x8501560fac79fa17 -642, 0x2b95d59621a424c8 -643, 0xb20ca1d29061c6cd -644, 0x9824922790be5c12 -645, 0xdee7448af6c82ce -646, 0xb57c8ab1b2b0ddb1 -647, 0x9241c7effe12d339 -648, 0xf69967036e960af9 -649, 0xe2e14558fcf89166 -650, 0x23a16c73c276d451 -651, 0x9fdd05ed8828875b -652, 0xc3466fd3814d3253 -653, 0xdfc9c839dc99a11d -654, 0x16693a83f78664fe -655, 0x65da2039561d5402 -656, 0x20b0d78000a063fa -657, 0x6b1346e833500ca1 -658, 0x7aa4a72cf75d077b -659, 0x378c2101d36355d8 -660, 0x95910003849a5839 -661, 0x4ad588ff7fe780cc -662, 0xd64d44efcf333e82 -663, 0x2f16c1742dcd9e7 -664, 0xd52ee978f72d63c2 -665, 0xaebda4339041c968 -666, 0x909d2433eedf9e81 -667, 0x670d7dbb7420f9da -668, 0x2880a01109e20500 -669, 0x7b48c2a4e918f6a1 -670, 0xf38fac2caf78d1c -671, 0x426944a0a0fcca7f -672, 0x24331c63647d4d36 -673, 0xc8e11bd52e232844 -674, 0xe7fb6b0ccc6a867a -675, 0x5c797fb7a7603019 -676, 0x2f6b2971284d996a -677, 0x96a89cf3747fd01f -678, 0x9aaedf8572e12afe -679, 0xdf9e5a2214174223 -680, 0x163ed5bedfd06b59 -681, 0x6c45e87d73677bae -682, 0x97b415906449e5ce -683, 0x53f30cd13d0bca1c -684, 0x86b204c8a1775e1d -685, 0x7ab03915913dbaa3 -686, 0x30767dc8d5a8e96 -687, 0x4b4fd100a4d86d59 -688, 0x65a5dfabb1a06ea1 -689, 0x59632b7fec7ad10e -690, 0x2d436b149509d8 -691, 0x37a45927a3898861 -692, 0x396db74b149f86d4 -693, 0xa1fdf757db1de83 -694, 0x3a08d99d4a60dae3 -695, 0x9df8a778bfd97996 -696, 0xc7196b2c8db56799 -697, 0x9378d20ec50eeffb -698, 0xb9ecc104b558e25c -699, 0x2929a6ddc011e01d -700, 0x5c8e297d48eaa335 -701, 0x9e000149b1821081 -702, 0xa8d080481a874776 -703, 0xedb2e0fcc8695de1 -704, 0x31c38628250d2d1f -705, 0xd92b4c99893c21a0 -706, 0xa56a77e01dffa3e6 -707, 0xa607e4ebc9c39fb5 -708, 0x6c8f5f7df2cddeaa -709, 0x1180c33d565487aa -710, 0xf4c66f402b7c1a21 -711, 0x4bd81bbcbe186a4d -712, 0x623e742bf4cfc10c -713, 0x84074e36e58825dc -714, 0xaa70f6dfdd617ae3 -715, 0xe305ea5aaf5aea74 -716, 0xc4726917aa5914ec -717, 0x317bbc6430cf6442 -718, 0x5b8af46f34f146a2 -719, 0xe4552970afbf97bd -720, 0x20d7a393f8176838 -721, 0x5e4a65ab657c7d2b -722, 0x1e430b0ad9e6fe49 -723, 0xa51866b0155c88d4 -724, 0xf1e2cdf07c51638f -725, 0x50f57c27c4e00a44 -726, 0x23bd9255fbb896d0 -727, 0xa91748820079892f -728, 0xb4d156ae147d6fab -729, 0xb3a474a3480c38a9 -730, 0x45dbbb715f1e3085 -731, 0x585986863049a87c -732, 0x436045cd7d1a9172 -733, 0x236972e814d5a4d -734, 0x2249b5f676f29b8a -735, 0x67fdcd55de80a8a9 -736, 0xd4fe890341189ee6 -737, 0x70e1eac3eb0a498d -738, 0xce1c2beb72f7cff3 -739, 0x50d28189d52b5785 -740, 0x93c740175c287808 -741, 0xf29621c38e8a1044 -742, 0x32d50b2824a59d70 -743, 0x8d595966ab119908 -744, 0xa5750cc7ceb0823 -745, 0xbcdefc996aed9ceb -746, 0xc1d70bb5480e2778 -747, 0x942b3f26a50fec6d -748, 0xa7d4851f6990be3d -749, 0x4086348def6e7c11 -750, 0x18aa95009f903221 -751, 0x3010f2c49ca532ad -752, 0xe9e9b21cd5552b31 -753, 0xd90541d86fbd9566 -754, 0x9240f2d8ffffd945 -755, 0xc7815330b2fd5f62 -756, 0x89040a5ec01115f3 -757, 0x4da5e5bb136d77ec -758, 0xc6a489d50839194b -759, 0x37839dcfaa606c7f -760, 0x8177b7be1443adb8 -761, 0xf588b929a63b0790 -762, 0x900a6482fa22b6de -763, 0x845502c244d08f04 -764, 0xc0a8f114df2a3608 -765, 0x5e201627c73573b9 -766, 0xa371ef9c7fc8ac6c -767, 0xca8a07e82c615463 -768, 0xba00e6e8d1c033db -769, 0xcd76dbe8a10cf399 -770, 0x959fe93180800aec -771, 0x8e77fa85404e4cce -772, 0x7b34e8983b9be1b4 -773, 0x81c0125be3d132bf -774, 0xfdbc9bb181a67f5c -775, 0xf2d7962c98584eaa -776, 0x8922b4291b6d0d41 -777, 0xb8235b21de4093bf -778, 0xc94518b4e632edb7 -779, 0x757f43c099ff5783 -780, 0xc063132013dafb63 -781, 0xfd579036a7030019 -782, 0xa5f0638c9ead0004 -783, 0x7494b34172659deb -784, 0x481772ff25eadcfe -785, 0x72e37428f1e21d99 -786, 0x5cf98e5c40aa77e1 -787, 0xb3ce6c54df0aedf1 -788, 0xf00af8c613bcd8f8 -789, 0xd1237f23a07b0e3a -790, 0xa8fe00d99f32f731 -791, 0x8b85f312af567228 -792, 0xdc2515684772c84d -793, 0x7d11b82c9e31766f -794, 0xf09c8697b3ff95c4 -795, 0xd35ebc77a86212eb -796, 0xadb5a1e95afb5f6d -797, 0x6ed845ef3fcadff1 -798, 0xaeb029f4caacb130 -799, 0x7cce6f1bf0ed8e7c -800, 0x23b6201003d49e50 -801, 0x6dfbf0e3c21a03de -802, 0x4729d4f0e6a9240c -803, 0x40af60788c357e6 -804, 0xcd17f1e93dca508b -805, 0x24a823f6424d2821 -806, 0x35194e11b535d3ef -807, 0x948f055d9436932b -808, 0x4e733969108a5551 -809, 0x3c0816162700c63e -810, 0x7370a331ce8096a2 -811, 0xfcf5caf742e23baf -812, 0xe960bb3fe0308e95 -813, 0x8ef061808248efc7 -814, 0x16c6c5da0fcf1296 -815, 0x14a05c065cffe433 -816, 0x568dd4ba989a423 -817, 0xd20a156a56768914 -818, 0x9872a06bbf694ad8 -819, 0x8ac764e367433878 -820, 0x2453eb53416ca0c4 -821, 0xa59ef657a7de7140 -822, 0x43cb5c3119ddabac -823, 0x645ebee1c5d62133 -824, 0xacf017344a2a6031 -825, 0xc22ebb7b220dba01 -826, 0x9048e327d43fc69c -827, 0xca2319dcd6c49370 -828, 0x63844574971006d8 -829, 0x7ce248cd860d2997 -830, 0x4d5780b45f802359 -831, 0x99798ec46c6536c5 -832, 0x4a42d4a45bdc0a1c -833, 0x75f126405fa990ba -834, 0xa1cf7cf0ee32ac82 -835, 0x12b722bce6d8b9a6 -836, 0x85ace663a1f92677 -837, 0x5f0514135be46137 -838, 0xb86863169f76d2f4 -839, 0x1dfc6f087c8721df -840, 0xde984a38824ac47b -841, 0x249504789c3f7704 -842, 0xaab5d4d12f9df445 -843, 0x863caa50cd8764c9 -844, 0x24cf6ca7a6a8e5ab -845, 0xf293f7488a738c5d -846, 0x2936a321fe93cce5 -847, 0xf5b2504862ce0521 -848, 0x9d6f9350f3a2b4f3 -849, 0x5093102345eb9ef0 -850, 0x20aaace8135cecbb -851, 0x252a8e893ad79698 -852, 0x2c68c7a18c5bb936 -853, 0xf973af891f51cfc0 -854, 0xe5c661b55596bcfd -855, 0x98b08b4904602dbd -856, 0x9fcde37c43372b73 -857, 0xa5d05483d489e6ce -858, 0x8b359f723ae63264 -859, 0xadaa0de5bdbd2d33 -860, 0xa4976d2755a6096 -861, 0x7174d708c2537633 -862, 0x24d86478fd44e33e -863, 0x8a0abcdb74f29fcb -864, 0x1fbf39da74328bcd -865, 0x2c5973fdfcbbf09f -866, 0xe23b300ec45a7b8b -867, 0x69019e93b3633c1d -868, 0x749053f7f30d6029 -869, 0x84aa9ded82b4a5c1 -870, 0xb6bb6cb827d5bcb8 -871, 0x503002036e031d34 -872, 0xba06a59f171023a1 -873, 0x733ccfc01e97abba -874, 0xa34cc599a30202ea -875, 0x7581c12df8a4174 -876, 0x8ee2efea87ff8766 -877, 0x2cd79614de9ff639 -878, 0xb190669d3052a8f0 -879, 0x9f3d98c2c3fc3266 -880, 0x48555e89c5b6184e -881, 0x4b9c73be9c8e8ec2 -882, 0xeee8586bdb309974 -883, 0x823a9e3bb2741bbd -884, 0x94a1a50e42fed547 -885, 0x2d7fcb9382eb1ba1 -886, 0xece0e31c5bb89719 -887, 0x440c75600472ddb2 -888, 0x28990d7882d9563c -889, 0x4e9b55cfdbe05ae9 -890, 0x4dba7e062bc24994 -891, 0x71faedf4414cbab1 -892, 0xb12901b28a65ce11 -893, 0xc0834509da822274 -894, 0x7daf95e13d676f29 -895, 0x6bc8df584cd07431 -896, 0xc614bbb95c749cd6 -897, 0x11d888ab3d6e9f38 -898, 0x8f4b7c7b0bda401b -899, 0x5eae46c2079e6f7d -900, 0x9c6f616b61328d61 -901, 0x9415dd3fea046eeb -902, 0x2b04d5dc9a25c2b2 -903, 0x402fd8a16781cf56 -904, 0xdc0be7170faaf41e -905, 0x23d4fe72e8f2fa1d -906, 0x18909afc53a4bce1 -907, 0xc8cfb6a2c1f230bb -908, 0x8268ee65c393a138 -909, 0x9c6b4210f409a598 -910, 0xe3122eb7e28e1c8a -911, 0xe3f0903f892e2aee -912, 0xc51ead0ad0dd1fb8 -913, 0xb2e7343037d7e6f0 -914, 0x89376733a7d3d9b7 -915, 0x13e1f3b9da7cc130 -916, 0xe1911b0a3fa4089b -917, 0xfdc131f18d761b91 -918, 0x782dbb406f0453f9 -919, 0xa61c1d244fdbea55 -920, 0xa4d2ed4dfd8bf85a -921, 0x3459f746e0a71313 -922, 0xa4f67e188e38d8c9 -923, 0x271dd484aee01e22 -924, 0x1907c912ddab4c06 -925, 0xed295346066663cc -926, 0xbebf878973ec93bb -927, 0x464b6c605cf80b2f -928, 0x924f8c5d8af46c76 -929, 0x8a705a5045a54c51 -930, 0xbe630deef4598083 -931, 0x63a782885bf2ef56 -932, 0x5c408ad85ab683f8 -933, 0x5a35bf59ca6db7f0 -934, 0x995b786bc77fcae8 -935, 0x93ac6c1d806cfe6a -936, 0xdc8ad969faae9220 -937, 0x67eda7e6d2b41375 -938, 0x21d2eeb2f58da10e -939, 0x4209dff5fec899a2 -940, 0x1b30fe5b2d96eddd -941, 0x3959011cb1541a05 -942, 0xfd0400e18394ce3e -943, 0xfff052e033e0ce86 -944, 0x569bb5da57a3cf2e -945, 0x45e0ef9753a2731e -946, 0xf6c64d69371ef3ea -947, 0xff6e5d50e2b29841 -948, 0x57334a6acad31efd -949, 0x3f39b0989b465114 -950, 0x9bf7bda3bc70b5dd -951, 0x44adb420df4b19ae -952, 0xa32ca7df58be9881 -953, 0x1af3b91f5078f255 -954, 0x9b1c0f815dba0781 -955, 0x29a5f5869108b99f -956, 0x890ebd600b286b45 -957, 0x4fdbfbba80a094ba -958, 0xbb42ae41c9679296 -959, 0xf51a153b2e4ea0d2 -960, 0xcb01bcb495a01869 -961, 0x1005c4deb506d28e -962, 0x3e1213bfd6496f47 -963, 0x388f29b4151fb7aa -964, 0xe75b0d72872db802 -965, 0xc764bfae67627d2f -966, 0xb86fd279622fb937 -967, 0x3fc887ebd2afa4e6 -968, 0x850b7ec2436195dc -969, 0x11495c0c0e4d1d34 -970, 0xc98421a7c82ced -971, 0x8337132f8c2eea5a -972, 0x77eb95949a98f2f3 -973, 0xcb325cf4d527f0e3 -974, 0x483192546ec89241 -975, 0x957fba4dd4238c59 -976, 0x6b12c9edf75d9ac6 -977, 0x9e959f3749b97cc4 -978, 0x1d77ee83f6b337c1 -979, 0xf6cf70e9db6bee2a -980, 0x87155a5e5746a82b -981, 0x552b032dc590447e -982, 0xbb939df7cb2dc42d -983, 0x1db106ff15b953c7 -984, 0xcee301b609e43399 -985, 0xe9babbea0fc4b81c -986, 0x8ea4ec5562e67027 -987, 0x422d3637cfb0c29 -988, 0x534c6604cd9cc6c -989, 0x301f4f55a0fdac48 -990, 0xf6c4cc1ea05c27a5 -991, 0xa1f4a4d5b999fbb1 -992, 0x343425e806758ccd -993, 0x9641ccb506ca4b0f -994, 0xa94166fa9641d3f5 -995, 0xf344ca329bff56e1 -996, 0xbc49cac1233860fb -997, 0x9087c97dba7f230 -998, 0xf2acda7714a3d1f6 -999, 0x4d076fb8ea7d9b9a diff --git a/numpy/random/tests/data/xorshift1024-testset-1.csv b/numpy/random/tests/data/xorshift1024-testset-1.csv deleted file mode 100644 index 661b157b155a..000000000000 --- a/numpy/random/tests/data/xorshift1024-testset-1.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0xdeadbeaf -0, 0x2968fec4616d9509 -1, 0xe82b10da7bd80ac4 -2, 0xa876e84316e70643 -3, 0x888c2d982b27d7ea -4, 0xd47d3d65778ed02f -5, 0x25af25e8c1c544c9 -6, 0x8e6f9814c92f661b -7, 0x3e71ea4e4046b05d -8, 0x9e1b58fa0207d9c0 -9, 0xc0393d91a0decbd -10, 0xd47df476d2f67dd6 -11, 0xf8a1b120acb29876 -12, 0x54d2351fff4b408d -13, 0x9321d56bc4bef94a -14, 0x12cb604007aac05f -15, 0xdabe30bab4e9a876 -16, 0x31962560988e567 -17, 0x53c8c00896fb249a -18, 0x9168b213fa8b49d2 -19, 0xe826ed57af7757c6 -20, 0x44084ca88c61d0e1 -21, 0x8a447ca13984034f -22, 0xea56bca7496a1192 -23, 0x38e40233ed1cbbdf -24, 0x826a5efdb65df22 -25, 0xe08ec869c2a206ad -26, 0x20bf847ba6e1475c -27, 0x268e99dc93ac3518 -28, 0x214e2263efcc56f8 -29, 0x4e62968a99e00539 -30, 0x2a12a52c634607b4 -31, 0xb0341a4f4a44ee46 -32, 0xaef66935a23e89bd -33, 0xe73d009165d10070 -34, 0x9d29bca8937c1712 -35, 0xac3450f789a44382 -36, 0x443eaafc99628e70 -37, 0x48609ba2fdc6814a -38, 0x6e01d53af8a01099 -39, 0x1b725df253d832a0 -40, 0x68ead3c52c36b98e -41, 0x36ba072b471d0dc8 -42, 0xac1fb808b1d93c3c -43, 0x2c36d9080979be7d -44, 0xcb9b374317b668c9 -45, 0x3c960912b44d56e -46, 0x657454550f8d9c1d -47, 0xbf072badce6c2737 -48, 0x6ee018e5c5cdd2ae -49, 0x609301623d936f60 -50, 0x35b40c58a518a941 -51, 0xf7d24a9c7d57564c -52, 0x7e4845b8f0374310 -53, 0x2a8223e03ac4cc2e -54, 0x1dc81758070ebd3d -55, 0x1320cd7c3abce6ca -56, 0xe95f5f03abd4731e -57, 0x90b6a7ee72f350f3 -58, 0x55e452037c949ad5 -59, 0x78d987c7609b326f -60, 0x9bff2e52746449e8 -61, 0x72cbc26a9b57c406 -62, 0xb8959ab6826ac35a -63, 0x59fe539c62ff9483 -64, 0x8c4cde1d65563241 -65, 0xe95ac9f2113f1be8 -66, 0x2846aa0dff366b9a -67, 0x39c3e61f5dc795cf -68, 0xf2b9b55af6b6b5b0 -69, 0x733951a107450c51 -70, 0x936dd0f66530a3a5 -71, 0xd55b63e0b5b6ae46 -72, 0xaa1035d6d371b80c -73, 0xf4f3719e466df564 -74, 0xece7d9e23f0a45bf -75, 0x95934ea577a81777 -76, 0x976a1776f73c1dac -77, 0x18029546eafd78b5 -78, 0xbb3ab35668fd6e65 -79, 0xb6915972b96a5b95 -80, 0x850ad09ba84b49c0 -81, 0xdb4a551245fcd15f -82, 0xbc2d21640007eacf -83, 0xba298f635a1645c2 -84, 0xa4aa6afabb88bb5d -85, 0xebcfc388cf8b1367 -86, 0xef6be3c48d331077 -87, 0x19132af4445e429d -88, 0x2f76a37bc0e45ced -89, 0x13f96ad00878df48 -90, 0xb8fdad62c4f0c365 -91, 0xf95de6a5528ec985 -92, 0x481aa24b342ffcfa -93, 0x132ccc5c3747112c -94, 0xb196b0efd2d09259 -95, 0xcf62746a3bcdec2c -96, 0x996325bf949590b5 -97, 0x305700d04fa07df1 -98, 0xaeab52bb4902e669 -99, 0x80068435ef98181f -100, 0xf3246828280d675d -101, 0xf59f61b26f5caffe -102, 0x15b7df7abf1d8759 -103, 0x3ff43423d8680a02 -104, 0xafbaaadfeb8ec37e -105, 0xf8be84cb4cbfedbd -106, 0x9e797d3b952a645e -107, 0xb9ff208124efc7a -108, 0x2e2ea03051b1d3f4 -109, 0xf059946cd8062ef5 -110, 0x5dfaa02e1c1c33a7 -111, 0xb938008377468bc2 -112, 0x29bd7ba26ddb5cfd -113, 0x8599e95956955b5b -114, 0x9674aa92fdbbaf2b -115, 0x6927290eba39179b -116, 0x48a4b594b063fc01 -117, 0x12cb99682cc95ca8 -118, 0xd0198db4fe06e935 -119, 0xe2efc92564cd6d78 -120, 0xf29e3401fe800978 -121, 0x3a45b04622a1918d -122, 0xc7d986f6cee748a -123, 0x18fe46fe75a1d8b7 -124, 0x94b0e9c83192d269 -125, 0x381890e6c4a10efd -126, 0x42305bef9a1eb0e7 -127, 0xd2e8f910b5a96bd3 -128, 0xa7343b2938ef16a9 -129, 0xe432fca6a883a22c -130, 0xd923cd3bb0c77a46 -131, 0x771440156f17d440 -132, 0x3a103372ad5c822b -133, 0xd65317c76a70e0b6 -134, 0x6bf5a7df9ddcbbea -135, 0x8a62bfb4bd7ee1cc -136, 0x14c564aeddaa9842 -137, 0x111d23185c329a25 -138, 0x80066727b94859b0 -139, 0xe76f847614409d35 -140, 0x61330b492b389f64 -141, 0xde2a98a5a181fb20 -142, 0x50ffc4f594291ec0 -143, 0xe766de7529bff4a -144, 0x440629959a350415 -145, 0x6e6f7cc6e501d547 -146, 0xb31b8eb4db5cd9e5 -147, 0x32e8e659bbfa3651 -148, 0xa3bcfee564006c60 -149, 0x71563f2f89f0da28 -150, 0x83dee9a700a53a62 -151, 0x4f3cf79d558883cf -152, 0x6a3f3d752b3ef555 -153, 0x92582ef4c19a74da -154, 0x6dd33c13eb4103a2 -155, 0x63e7310213e9f7fa -156, 0x9ce3c17c6b9a076c -157, 0x5e3f2d4d07b42014 -158, 0x109589489e174134 -159, 0xaf51d807c1140a71 -160, 0xd5223c84c2425bec -161, 0x6ba4d7869f4259b3 -162, 0x597067c2bfcf3489 -163, 0xf9c59e81f49883a9 -164, 0x5e4a60775ded4b74 -165, 0xba6535ab12b07bf4 -166, 0x9922d0b7a853d36d -167, 0x9059571a67c9bd7a -168, 0x55c0b45bc5687a44 -169, 0x22b726e1a977463f -170, 0xd3467ec3e6888b9e -171, 0x420d1f2b5a3db74f -172, 0x87ac3bbf7ead0f24 -173, 0x6eefc0436f3199b2 -174, 0xe862c445add78a8f -175, 0xe2408382341cc1ef -176, 0x759152fe96db65ae -177, 0x58a46b8ee63f95f5 -178, 0xc2b639beacfb790c -179, 0x50f35b69ec430636 -180, 0xb565cc1acac8a8dd -181, 0xe2a379d5edc2ff2f -182, 0xd0abfb8ff3c76c0f -183, 0xaacb26508bf52c62 -184, 0xece254ff3e0fdb97 -185, 0xc41bf846cdd6b3a1 -186, 0xef03f2c371e3a12b -187, 0x1ce74e57ba14f001 -188, 0x9b5dc37c48907b32 -189, 0x6312b7a3c0e0d71 -190, 0xde51fea867eac892 -191, 0xa09af6cd2a5e2703 -192, 0x173416b34c78e921 -193, 0x892a28ab1909ba26 -194, 0xc77a69b6885a8f89 -195, 0x3d508e62c2feee2f -196, 0x5119ad966235eea2 -197, 0x67f0222ecb886bea -198, 0xa9c1bdae30c4e60a -199, 0x2d518b070541cb10 -200, 0xadc88b8fb3d0345b -201, 0xaa8e0549c3d8081a -202, 0xf6922301b0234292 -203, 0x57c61f02f871f052 -204, 0xb68b57425ec40f26 -205, 0x64e6bc6cdeb78a38 -206, 0x1dc5e9141a3e0118 -207, 0xdb5c616c4b112874 -208, 0xccaa45b96144a599 -209, 0x3c2570670361fba5 -210, 0xab63b1345fee697a -211, 0x2cbcf6518ca555f5 -212, 0x4b84780b234494f3 -213, 0x934519ac136d696a -214, 0xdf19065ede5d9033 -215, 0xc4f240f01a18c940 -216, 0x51799f4eb478267e -217, 0x22bdaa06e7ced71f -218, 0xc42a003cdaa32e09 -219, 0xa3746906fac5abc8 -220, 0x6ff7b8a74c61d8cc -221, 0x48fa29ab00d2e849 -222, 0x1409a2bdc81c923 -223, 0x50d00ad328c1fe85 -224, 0xab79bc5db01d9a6e -225, 0x3fbcfd2cebabc23e -226, 0x1814a2065f9efbcc -227, 0xbeaa8ece82351ba7 -228, 0x391ad79ff0512dfa -229, 0xad5babcb6318a0a5 -230, 0x2cf1ae641d54b7c5 -231, 0xca32becbaabf2e9c -232, 0x8ba3d47914242362 -233, 0xf1a764b81ffcf79c -234, 0x91f20f4ba933dbbf -235, 0x88ac060061f0363f -236, 0xda21e847fc8e1aab -237, 0xdc7f4d3e6cf0baa6 -238, 0xd85c1d81dc96ee90 -239, 0xba23e43a6b5051ea -240, 0x90a0939eea412d8b -241, 0x12ce33d77b029fec -242, 0x5fbfb6a87d6357d2 -243, 0xa7597dd027f65afb -244, 0x8ebb6b8b8b185239 -245, 0x45e89426a0d04436 -246, 0x4a5383818bb40ec8 -247, 0x919b5b80a43bda4e -248, 0xf9b8d22461280026 -249, 0xe13ad8f7ab5ee8f3 -250, 0x39c8d72628967129 -251, 0x6de22f7a2fbf9e40 -252, 0xc6c5744d174deb7b -253, 0x626e5f3a50df3c90 -254, 0x62f8e30ba24dd13 -255, 0xd72dc4febe774cf4 -256, 0xd200b1afb0a73c25 -257, 0x65c7563901c2fc64 -258, 0x30e9818e85515f7c -259, 0x8643ffb0bb71293a -260, 0x3abe1c4ea7de258c -261, 0x45084bb1f370c75e -262, 0xed89ee41dc8c95a0 -263, 0x99bb56fb1279d194 -264, 0x217d6c46d7d50ea4 -265, 0x42dae06f1ca3c2be -266, 0x3103af8d85ea50a8 -267, 0x7cbd22f30fc047c -268, 0x9b981290c7de08b4 -269, 0xb0d2dbe062abbbfa -270, 0x2de6fdb8df120a87 -271, 0xffd5f46e69d4f755 -272, 0xee735a0f05dc71fd -273, 0xe079ecc2224d9a64 -274, 0xbf400cdc00cd920d -275, 0xa2757efb078c65dc -276, 0x3a0d632515afc842 -277, 0x164dfab63dafc317 -278, 0xcb7a3131d97eaa24 -279, 0x3ce938f6a615ad07 -280, 0x8e23c8155a33858 -281, 0x26ffdf8d6b4312a5 -282, 0xa73c99c8f5a2efff -283, 0xb622fba6a1cca389 -284, 0x933a270fee14587c -285, 0x97684114e2320ae4 -286, 0x585ba967f0b16324 -287, 0xb0b3306cd44abac0 -288, 0x6ca0f5ef7c106cde -289, 0x995d51989aa1c417 -290, 0xc9f2c923fe4455a5 -291, 0x643815429f7eb3b2 -292, 0x62ea9ec7264da11c -293, 0x447d0b45dd80f0c6 -294, 0x28f4cfd3070a7954 -295, 0xe489352888499c52 -296, 0x8052cbc99a85e051 -297, 0xb8f3cb6026cc90ad -298, 0x912584210563a88d -299, 0x6d4d13a07f86a423 -300, 0xfa4d51b338c3b5ae -301, 0xa03ef23eb024427e -302, 0x6f7f11baaa5687bd -303, 0x408d5fb68881b088 -304, 0x29e51d59129fc75c -305, 0xcdec3ff5975e02f7 -306, 0x6008150d8694fb00 -307, 0x1716a8dc698523b0 -308, 0x5630cb8b8291ffa -309, 0x5fd5da716e1a78da -310, 0xb1a6db0fce436d0 -311, 0x57e1d30fd93a3c37 -312, 0x72757a0a3321ea6d -313, 0xcc76c5afc421e56d -314, 0x16190b05f0b40caf -315, 0xf78a3f994c913ad -316, 0x7e1a1b1c5d24c00b -317, 0xa1e2fb1ff0b9d6db -318, 0xfc498b8039b54f0f -319, 0xe53a07e1d2eaea28 -320, 0x78fb2fe5aead5931 -321, 0xc88e3c02e3dc1785 -322, 0x1316793c718709cc -323, 0x87ee50ee2442393d -324, 0xfaed744d0586ef7f -325, 0xb421ca20f3f36511 -326, 0x167a97dae8220873 -327, 0xd1923f827aaa2686 -328, 0xdabb838e2156893c -329, 0xef5035dbb60a0e43 -330, 0x4eb59086d683c897 -331, 0xf53508888be59fda -332, 0x6c901a026863b64f -333, 0x533e9b2905812820 -334, 0x5995efd0f86f0247 -335, 0x85407d7c71a8519c -336, 0x4ec365075d3107de -337, 0x2ef189e758ccac93 -338, 0x94965c831e00c74a -339, 0xc703660168ee5f1e -340, 0xb299ff5db8adc89 -341, 0xf016bd3198c82f20 -342, 0xb547315812240a6a -343, 0x2615627e3eba8870 -344, 0xb78e0f43405b7898 -345, 0xa9d14916e9b7efb8 -346, 0x112d9ae68e8904d9 -347, 0x3dd1e5d8d87a2a00 -348, 0xe72d6f0971f538dc -349, 0xa39e9d3bb475c18b -350, 0xe8e4c1e4d8c6a8d8 -351, 0xbd79ba7f0ad62765 -352, 0xc385792825aa00a8 -353, 0xb6d7f610d9c4d243 -354, 0x4335b0eb532176f1 -355, 0xc0a2e5238b8e0677 -356, 0x16c65023c679608b -357, 0x4d994626744b8f46 -358, 0xcb0b2741af2df9ca -359, 0xe4a7e3fe75a1aaab -360, 0xe32a45741e898d8d -361, 0xe67a3f4fd4b2b6d2 -362, 0xa0ea8adc980fb9df -363, 0x22677c7e716dff46 -364, 0x61a419a44db57308 -365, 0x2450dd931ff2ec3f -366, 0xce84c6e8acfad7fc -367, 0x760e778b2e193a05 -368, 0x8eae9f11a89be32 -369, 0xa4e9d719935d50f6 -370, 0xd5b566b0369a52a2 -371, 0x42fc4fca6052ff0e -372, 0x54bdc983732078bd -373, 0x2a34b26ece1a4a1f -374, 0x4a6c02709bf62226 -375, 0xe764d4869ca86a88 -376, 0x3b55160e0eccab3d -377, 0x6298740e7a75206b -378, 0xf5dfabfaf966966a -379, 0xb69af13f6a58df15 -380, 0x40d98d1218870fd0 -381, 0xd31db917ad090d36 -382, 0xa0f51d92105470eb -383, 0xd49a359996308801 -384, 0x9c0a51cf0afe4987 -385, 0x3c5139c9bde54e2f -386, 0x3d8764a94f3910f0 -387, 0x72c022834f060c6e -388, 0xfc1bdf8001e68e68 -389, 0x99fe3ed21088ad60 -390, 0x53d270e055960efa -391, 0xace8c828bb806861 -392, 0x281e3aeb0a9c4834 -393, 0x449b247a025d9c17 -394, 0x9d348001ba4afbbf -395, 0x287d8e15971d6c94 -396, 0x95f6b9856848aa36 -397, 0x7ad4738f43ec445c -398, 0xf5dc701c62cb0707 -399, 0xf85fba15e2f3af47 -400, 0x339c4e96a86d310a -401, 0x8ce140d016eff7fa -402, 0x65edfc5c5c98dbd9 -403, 0x1d0a87d9af90f167 -404, 0x203dc34e1e9ee146 -405, 0x1660fbddaca7a089 -406, 0xa4595cfc69627ae6 -407, 0xf5c6c28fdf65db44 -408, 0x73cc91643c51bf0e -409, 0x56d5ec5f4df77ef1 -410, 0x238903979a24cf65 -411, 0x96268de7413313b8 -412, 0x28a3c908362a9bad -413, 0x728d68bc8b6496d0 -414, 0xbfb6a39f37f22189 -415, 0x9c1e845d3b060423 -416, 0x11962b88cf841c42 -417, 0x5d91b9809053bfcb -418, 0x854693772fd6c780 -419, 0xba2a80b61299b067 -420, 0xc167859290090b3a -421, 0xd8ebc6acc7fdc96 -422, 0x5840dddbfb862b08 -423, 0x5202ea8acba4faa8 -424, 0x49d3bbda86413c0e -425, 0x32be126f76f93277 -426, 0x89663ff83ea2de5b -427, 0x80f40ad26cb40dd2 -428, 0xf766a092380d8ebd -429, 0xa4487b65fe0744ca -430, 0x322eb186046a4a94 -431, 0xc02a504c09a45a1c -432, 0xdb7ee621ffff440e -433, 0xfc0dfc9f26c858eb -434, 0x69c4fe6af18bcd7c -435, 0xefe02edb24d56ea4 -436, 0xa50a14ad0e9eef00 -437, 0xe423d1c202ef28a6 -438, 0x7afd0f5d320da389 -439, 0xdc08b10bf5eb2150 -440, 0x2725a6e6b0d16c3c -441, 0x4ebc9a86ad70a406 -442, 0xe5b234e726949788 -443, 0x61895444577fa683 -444, 0x579bb863c9c0f4d4 -445, 0xf57472f1c2186e40 -446, 0xe20f9e4dd18b7a86 -447, 0xdd874db6f18ad18d -448, 0xd33a6863b26e7e0f -449, 0xfbb06768ee299508 -450, 0xa698449c04c6dac7 -451, 0xef8956f00b0b93b6 -452, 0x50187c36dcbb27b5 -453, 0xe183c93b50fc5db2 -454, 0xeff4e91a9f691af5 -455, 0xfeb0c53b5f79d85f -456, 0xcdf64cb7aa9e77b8 -457, 0x92c7e1c5d0cf8545 -458, 0x2364334169a8777c -459, 0xbb59d00220215aa6 -460, 0xf0e84db1ba5e485c -461, 0x32eadec20b527e69 -462, 0x40a8c172ae43ffe9 -463, 0xef1bede2c2ded35a -464, 0x92db9273d1c956a3 -465, 0x6c9cb922edb2d4b -466, 0x5a679c0c94b3f39f -467, 0xe6a5221838453419 -468, 0x66de19b420c14ee1 -469, 0x8c2bd98ad9467af1 -470, 0xa147d5f399568982 -471, 0x9e8aae9d332472be -472, 0xdefb07cadadfbd88 -473, 0x444a202d1b2edd27 -474, 0x319c8773f6a754fc -475, 0x36606ba635cfced5 -476, 0x31504a5b044d1808 -477, 0x806e09994bdacb17 -478, 0x9427e77e577af871 -479, 0xb59d548f5aff715b -480, 0xf52251410861803d -481, 0x38e43e9d0e116362 -482, 0x4193f31faf42df63 -483, 0x220bc4765445a54c -484, 0xa70017472927b966 -485, 0x7df2a19540ba70f7 -486, 0x312517443864a8a6 -487, 0x5b3050b6e7369529 -488, 0x7d78902a459de6bc -489, 0xb55cc03b010496e2 -490, 0x4b5e70c18d90afe8 -491, 0xa25c9282539ffa39 -492, 0xb3634844d85ca854 -493, 0xd70f1ba5cb23f155 -494, 0xa7164bd3ba66fd13 -495, 0xe8fa24efc28e0b35 -496, 0x53cffa8448fa39a3 -497, 0xda1963ccf029a46d -498, 0xab159eb294b3b2ed -499, 0xa3a837503c32174a -500, 0x83b5e56c63ca910d -501, 0x77174c7925c01bc4 -502, 0xd9723ab7a9b06742 -503, 0x407fc7b87e1b3301 -504, 0x3067a710c13076ae -505, 0xf490b50ae1c760c0 -506, 0x3984834f76388042 -507, 0x8f61a75763eebcc6 -508, 0x5526d22e2c18bfca -509, 0xbd1f2ed9006893e5 -510, 0x751810cfad06bf24 -511, 0xf21af6042e4b3618 -512, 0xc159c3b878206376 -513, 0x1f40d0561588b836 -514, 0x84e387cbeefc8370 -515, 0xef8378b1b551cf8b -516, 0x501934cdd42db314 -517, 0x2671bd3b0b8edb35 -518, 0xe08db954f218bf8b -519, 0x6e2daf982de67f0d -520, 0xa07c0f0c4958d787 -521, 0xd7fe2217582a0977 -522, 0x8c4b91a83a7dd84e -523, 0xb0f97b4621d12984 -524, 0xccb5ea2b6fc4d012 -525, 0x65fd9271c2cdf119 -526, 0xedad88bbdb81bc5d -527, 0x3d744a2bba50afd -528, 0xf30a4cc4a9a02eae -529, 0x1ec08d6b2a3aae18 -530, 0x93fc3ba3fda6076d -531, 0x1a51f49322a2a528 -532, 0xa9f55a607051835e -533, 0xce3bccb15f94a155 -534, 0xc7e0428cc4a6cd37 -535, 0x24707a92b8e71cd8 -536, 0x443fe1ef6689de4d -537, 0xe5610bdfa3bc3809 -538, 0x1c684dfabc1a719f -539, 0x3e41dff1948ab65a -540, 0xa58cb5d77eed149f -541, 0xc589c050bea7760 -542, 0xe4b8316d7455d38d -543, 0x3ad6140f84f0c0dd -544, 0xdf7deca619fedeb9 -545, 0x5fcb5d0ea1b1e47a -546, 0xc602267112df1d8f -547, 0x91f44054fac54920 -548, 0xd740c0213fdac4a0 -549, 0x677a64717564c678 -550, 0x733009a5e9360091 -551, 0xa50ee09f5b7f8854 -552, 0x2b7a9cb61c3de26d -553, 0x23349b2382903734 -554, 0xb498a233184e1c0e -555, 0xb44201ef4443deae -556, 0x6daca8c5a6647612 -557, 0x36f4b7e94bfd7b50 -558, 0x8ca5d0a0098bea0e -559, 0x5bfa417533e65be3 -560, 0xb2b7ca005d530c22 -561, 0x780136e2cf6fc471 -562, 0x874a13ef938027a5 -563, 0x1e855317eaf4937d -564, 0xe9e122ade32fc335 -565, 0xf24661d4287b8f5f -566, 0x6113a640f6a23e6a -567, 0xa5d681ea6fd4538d -568, 0x2f5afe3fa42ac6f8 -569, 0x924ace74f2200a67 -570, 0x2860af7bdc0a1328 -571, 0xc18d7e42dbe8defa -572, 0xd565ccbc02300ca1 -573, 0xe2c425203673bc87 -574, 0xe7cc4d62fcb1b7a5 -575, 0x4736a2fc73e0408 -576, 0x8b63d58d06bf6f4f -577, 0x2fe82ed95c103404 -578, 0x9d6458914f301d00 -579, 0xe6dbde6799cb0c2d -580, 0x437153bd57359448 -581, 0x91cca254d0b51be1 -582, 0x4b5618013971476 -583, 0xf7a30620ebd70ebd -584, 0x3170e9eba79c8fea -585, 0x8983fb74dc098ba3 -586, 0xe597a911134d02ee -587, 0xc1bf7730780802cd -588, 0x1ac341a0343abe36 -589, 0x877addb61c4f6d53 -590, 0xaa6326c5c9f7dfc3 -591, 0x2176da3fa9450570 -592, 0xb9086e2124d7db1a -593, 0x75b150a1ad48736 -594, 0x72361f3255bb1c6c -595, 0xe77633cc35d21649 -596, 0x7fe0c14523deda1e -597, 0xbed948a006ab7ae -598, 0x5deecc48e391cc9e -599, 0x1c60216cb5b769be -600, 0xeb3158cd91cefbfe -601, 0x8ff0059d384b3482 -602, 0xc270fdcdf1b27054 -603, 0xcbda49df540f7bee -604, 0x9569dad154192b1 -605, 0x626b1d9dc5af9355 -606, 0x1f2e390fb9f72c34 -607, 0xb5da34db64cb3c12 -608, 0x91bc689a0a76f72a -609, 0x722e70eb16c2883f -610, 0x4e3e4ffd2dbc23eb -611, 0x530b6cc8da38189d -612, 0xcc1e8a97bc9f7f3 -613, 0x8606896c6384df29 -614, 0xf12057ea9246c3a6 -615, 0xa36176adf40ed649 -616, 0xbd41dd899b1e7e1e -617, 0xee6b4a30cfc1705a -618, 0xecaf8b48645b1a1d -619, 0x45b9d22e4b67d526 -620, 0xf4633b7932f7b231 -621, 0x3d110c58b9d3af76 -622, 0x5476134f5a62c65c -623, 0x8b8c459aebedbcfd -624, 0x85438a06efcf7244 -625, 0x4093cff6b13d0235 -626, 0x3441e41c4240a04a -627, 0x7d2ddfcef9e1502a -628, 0xb103bf1629052a4e -629, 0xc7b6242cd4b0ac6 -630, 0xca90bbd3896e5cef -631, 0x475a4f194b2efc95 -632, 0x40b7befb56e87d9c -633, 0x6cad487ce5b9fab7 -634, 0xfea988ecd11b1e48 -635, 0xeae1a787969dd6a -636, 0xca61203919f24b59 -637, 0x4fbb1b7da2ed1eae -638, 0x2293875acfb13bce -639, 0x83bdb0d855f80904 -640, 0xc6cb9af3dc51663c -641, 0x3670a82bf259af61 -642, 0xad19636327ae2f9 -643, 0x1e3c9eda8aa86f0e -644, 0x9bf0294f709db9c8 -645, 0x82634a2a6f68d88b -646, 0xd28459865ee6ba06 -647, 0xdca0589a37b686bc -648, 0x6d599e666b676946 -649, 0x532da8f80b2ab6fe -650, 0xd04c13960c6ada57 -651, 0x6b6be861eaa20840 -652, 0x7bee96f844d8af14 -653, 0x5262b1b291404b11 -654, 0x7c2e76df26ec97a5 -655, 0x200a74e9d28af98f -656, 0x4c524db7ac5bdae0 -657, 0x7220e9ce3b2bd645 -658, 0x253c92bd314da1e1 -659, 0x61c99004de5ee6ad -660, 0x1a8b45e7a2b8a09b -661, 0x8210afa2eb0147e6 -662, 0x275f3a56f6ec8ba8 -663, 0x882e054db980aee2 -664, 0xa2a4f61060588c1d -665, 0x7c4cfbadd5d38529 -666, 0xee8a9c0ae89de452 -667, 0x3a1e9d46843f2574 -668, 0xd076b0d7f2e7dd81 -669, 0x16c1e3acf3b45fbe -670, 0x182de2922f0e2a0c -671, 0x9ae8e92260ea419a -672, 0xe07af4e2b7b48d7d -673, 0x600e3ec66ee20ec2 -674, 0xf7036d1caeacf4b8 -675, 0xc147ed61fcd4f647 -676, 0x7f9e195665802bba -677, 0xfed9db42c4ab22eb -678, 0xaef24cde91dbcab4 -679, 0xf84b896fabe3218a -680, 0xc99a2b2725700ca1 -681, 0x8e9e3242ed539a42 -682, 0xd68f96459b7d4eda -683, 0x3519bfc85e559ae1 -684, 0x6837e68bef1bac4a -685, 0xa09f0e34eb061e55 -686, 0xbf9ad807ad35e4e9 -687, 0x5a5d949c5bc4a894 -688, 0xc5c44dae5464903a -689, 0xca5b2b8c8ea7b8a8 -690, 0xa55ff2894f125040 -691, 0x9f6ff13eae26b16f -692, 0x584babe068e32d0b -693, 0x675701bb344f15d8 -694, 0xc7cf1a1ae4965137 -695, 0xcbd397007200464 -696, 0x441dbbbc178e9f1f -697, 0x68de3be524e615d0 -698, 0xeeefd0ae2953fde1 -699, 0xf3f25710aac6e8dc -700, 0xa6e739afd86491f8 -701, 0x788b33d85140da94 -702, 0x93e31f17b30996bf -703, 0xe339877de36dc99b -704, 0xab8d1922e63a81a7 -705, 0x2fdec0bc47274e3b -706, 0x46fac763279a6456 -707, 0xcf43d49178b7e2c8 -708, 0x6c97160d52f7541 -709, 0x338082733f40fe0f -710, 0xaaa7adedc68075fc -711, 0xf6be5a0983c7e38e -712, 0x23704a0305bb6e4f -713, 0x863b4177c8b4b645 -714, 0x49d46155cd596ed4 -715, 0x9c3aff0f8f51e7aa -716, 0x818d564029593dd6 -717, 0xf86d183be4f9bc67 -718, 0x2913f9929b732227 -719, 0x70170b1cd3a3ac54 -720, 0xb8a80aa5e5a049ab -721, 0xc11837b6e5d05914 -722, 0xac4e428e8179ffd0 -723, 0x365ae1ad260341a2 -724, 0xdeb434fa400c659a -725, 0x301e5022964913a7 -726, 0x9b5353184587e65c -727, 0xe87952dcff2bb94b -728, 0x38018ea9168498f -729, 0x5329faa0a9b31518 -730, 0x4e9826e7a5309cc6 -731, 0x8c8b3902b3fb31cb -732, 0x51fa6eb8243361a7 -733, 0xf83033cee6066488 -734, 0xb5bfa21e11d0084a -735, 0x5dea1df773d5472c -736, 0x8df2cd3cf75596ea -737, 0x927d1c793c8cea03 -738, 0xf1c36260836e102d -739, 0x1359f6c8df89970d -740, 0xa6d259498334bc -741, 0xa6e07155f17c845f -742, 0x10deac98d78f615e -743, 0x82dd4e3ebd26fe73 -744, 0xa38711f23c38a1af -745, 0x2fdcd69782301538 -746, 0x216d402e19d85877 -747, 0xac673ce673285122 -748, 0x7875f10741c5d847 -749, 0x68c40a47711addc5 -750, 0x2993772e15b714ab -751, 0x7e98b5fb52c5fa95 -752, 0x4bbf5c436cc0ae -753, 0x18b9dd31c535817f -754, 0xb461f16678918bed -755, 0x3c036fc204d6af40 -756, 0x97a7f1ee6acbac2d -757, 0xe14fd6e30c86a58d -758, 0x88573c172e1f841b -759, 0xc34525268445a76a -760, 0xd87d260c104a3640 -761, 0xe4e89f8d92a8d78a -762, 0xa8ddfdacfdb10b31 -763, 0xa4afe400345727fe -764, 0xc86d9a624d1c58ec -765, 0xf343ee93309d8a86 -766, 0x3e2e1a0436b09535 -767, 0x6d43bc645ed9ac6c -768, 0x851c37fabf29f39b -769, 0xc3426e0cb4dd3941 -770, 0x497fc67d26f9c0eb -771, 0x763f57a1e7b7c7f2 -772, 0x6d17c1946432276a -773, 0x8eb40863a03a9f6 -774, 0xb4d2efaf434f99e -775, 0x3b7362a21b09a974 -776, 0x8346f15db661117d -777, 0x935d7f4718c0b76b -778, 0xebecf09e8cd66494 -779, 0x6488514887be6d6e -780, 0x8967e6482106a9b1 -781, 0x1027a9c65d640f4b -782, 0x616ac0c09e0c0424 -783, 0x370fd6f501ee434e -784, 0x64656b86647db284 -785, 0x1e75f13e5710fe36 -786, 0x6f707be9595741f3 -787, 0x36005270b95cedb2 -788, 0xef4d96d7855c072e -789, 0xe00dd4df241aa017 -790, 0xb7636a7a39dbec9d -791, 0x55f0089bed163558 -792, 0xbc2629bb08892645 -793, 0x7972323d3b65070a -794, 0x6d034ae888e1dde3 -795, 0xe3746defc543a1fc -796, 0xe21f07f7946046e5 -797, 0xb4a1beab89060010 -798, 0x7599da8e80780a1f -799, 0x2c9a6831a67fac80 -800, 0xd96d4d3e81ba74d5 -801, 0xb9945639961e680a -802, 0xd8a540ebd9244a95 -803, 0xa083f2ced29445e6 -804, 0x8be65673106fa2dc -805, 0x9896bf42455914ee -806, 0x12143e7988bb5799 -807, 0x53c754030fa4a756 -808, 0x1737b69502b0aa59 -809, 0x2ddf23fe48a62247 -810, 0x3841e493ee590199 -811, 0x912f09f5d33d43b8 -812, 0x19229c58ff93efb4 -813, 0xf1779404e2983aaa -814, 0xe83633e2c248d359 -815, 0xc717450be4d4874 -816, 0x96c7e09c87a882d3 -817, 0xf7de965536666dea -818, 0x8500552659716f4e -819, 0xa325745ddbd5991d -820, 0x646a7720bf41f124 -821, 0xfcb2de34a2319f8c -822, 0xa5cb25a06e56c96e -823, 0xc2098ced3a1d7f16 -824, 0x4e0c42ddc545e1ec -825, 0x1a81a4072bc8c70d -826, 0x33c8c26ee5f2a8a8 -827, 0xfa73293671dcdea2 -828, 0xdfcef95a123b6e75 -829, 0x1be31c104c2f8884 -830, 0xa3a38df49047b410 -831, 0x927d2d9fcfd5e906 -832, 0xacd1b5febc723579 -833, 0xdb3ae10ff6179edc -834, 0x83034561e2390270 -835, 0xbd9316c92698ccde -836, 0xaa17f5dc651ba328 -837, 0x21fda6d3c574a13 -838, 0x5510e62023ec3b60 -839, 0x8d939254ae548157 -840, 0x10f3d1f467526a1 -841, 0xb86c845b5fc5248a -842, 0x8545fc74955c82d1 -843, 0x394de00459610bf5 -844, 0xb98e7648d039f546 -845, 0xec2c9942f392b082 -846, 0x63fb45dc65abb87c -847, 0xa293317b6f87fbe7 -848, 0xeec10eee4880bdab -849, 0x7e0a96d7a639db96 -850, 0xeafa162cdb08dcb3 -851, 0x816e68da04ed4bf6 -852, 0xa4700cf2444147a6 -853, 0x5538ff41c87380bf -854, 0xe7e18e47273372ad -855, 0x6b9344f90332664a -856, 0x38f37af3a5ecf737 -857, 0x51e7197547bae5f2 -858, 0x417b49ddbd5c8ac1 -859, 0x7aefd1477efa2b53 -860, 0x3760d5701bf49440 -861, 0x710be29a267e823e -862, 0xf4c6d8607df3e45e -863, 0x452230b3ed570aa8 -864, 0x6f99237e35b6950b -865, 0x6abf4caea61cecdf -866, 0xd43740daec5c5a5f -867, 0xa7f576b3fd5d5d05 -868, 0xb076d89b96a33c88 -869, 0xa39c1bcd83b190b2 -870, 0x7618d27a72b13ce1 -871, 0xaf93ae79c6dac995 -872, 0xc837ce1ec14feacd -873, 0x1606184f9270d69b -874, 0x98a0d302ec1868fb -875, 0x8e4010b8c6ba8b85 -876, 0x91fabe97c826be7c -877, 0x69bd7d8486501178 -878, 0x15008364e9a58f51 -879, 0xa51ab44e26267b7 -880, 0x85ee973bc9e19ee9 -881, 0xfb39b02ce57899 -882, 0xc0f80d8e1f5c890e -883, 0x3f229a821ba4bff2 -884, 0xe9d4c6ff69970580 -885, 0x83e9ccaa3d5ff548 -886, 0xc6554c73cb94447c -887, 0x56d094f66000a7ba -888, 0x2180ce39c7ba63a2 -889, 0x70b47bf5afc29d65 -890, 0x976a3290e523061a -891, 0x3950058fb90fe132 -892, 0x76da108a69799048 -893, 0x42699b4c4f7d1866 -894, 0xf281a11c6bb173ef -895, 0x700b4d769e2f5ef -896, 0xf0e0ce96a60102f9 -897, 0x77b92c4fee413da6 -898, 0xe5dbad4fd50d56fd -899, 0xa240bb500fda3852 -900, 0xa2ace5d55a2f4da0 -901, 0xca519e0c48a53c8c -902, 0x5451834c28b0ed25 -903, 0xf8b83e1f7de31f36 -904, 0x9c8c416b9a1091b0 -905, 0x25884ab7529ae96 -906, 0x6097e452343a4525 -907, 0xff30584230d3f39e -908, 0x56d383168357ba28 -909, 0xca95d287a8895aa6 -910, 0x1820536c986a151f -911, 0x8bb62b7c25dfdf4b -912, 0x46ea14775124a4d9 -913, 0x2424a64e4d04bb9c -914, 0x17738043edc89d31 -915, 0xdba93bd6dc35fba9 -916, 0xf4d84f1396123324 -917, 0xd3afb0d529380864 -918, 0xfa9b0888c037d6f1 -919, 0x5978537bec8f972a -920, 0x8fa9926a080affd4 -921, 0xd5d0b7419c2c0a6b -922, 0x5218c0d0da166bf8 -923, 0x113766ed52074b0a -924, 0xcb3cb49751a8ed51 -925, 0x76f4964c1369cfb8 -926, 0x248ef6f6a0b7987c -927, 0x124962f6cd30d2a4 -928, 0x3ac9098b45d56fcd -929, 0x9db9dc39098adf0b -930, 0x281d775a9aabe3e1 -931, 0xade94768d752f284 -932, 0x2916418b2780283c -933, 0xf6842d520f056828 -934, 0x644f905ae21dee4c -935, 0xb33624d20348f897 -936, 0xe10430135a63b21d -937, 0xe4f73ae0a126d8f6 -938, 0xbe6ba34486dbfea9 -939, 0xd4ee40812332dd9 -940, 0x4ee8a69b86449ad5 -941, 0xb1a298727256af05 -942, 0xa3e558c4f12d9f59 -943, 0x645703828b4d5fbe -944, 0xdf4223058118c420 -945, 0x251dcdba6d3ded09 -946, 0xb2d84c99dcbf9318 -947, 0x8dc95fe1c9863322 -948, 0xfdc6ad87458a50e4 -949, 0x4cf57028f4f133cd -950, 0x5a13d134a30830f9 -951, 0xa550bddcdb0804a -952, 0x8f50b20e973d1ad9 -953, 0x5d8fd8547fbb25a2 -954, 0x57fb0001fd795ae7 -955, 0x80a847e957440201 -956, 0x12e25c663b26ed6e -957, 0x8a3793d5204fdc1a -958, 0xa7e782709f666612 -959, 0xf08d5b5e3e6fe48c -960, 0x226c01d4c843035b -961, 0xde70ce6a314b4a5b -962, 0x2b3f4c7488c346ca -963, 0xda121178e4f987ea -964, 0x9c39f51596ab15d4 -965, 0x56b363742c0401e9 -966, 0x791873978c61e53d -967, 0x703acd4c93373bc1 -968, 0xfa9d1ce6b783d3f5 -969, 0x1dc0a81be853fe40 -970, 0x95a2eff6de671578 -971, 0x49bffaacb5073f9a -972, 0x4f5875882fc088a1 -973, 0xb2cb0e0a7684f052 -974, 0xc8a96b8e988aee2f -975, 0x906c865a40447872 -976, 0x9713e82964a3e5eb -977, 0xa0d4766ce887c073 -978, 0x7375bbdc687fd720 -979, 0x4edbab65f44b6dd7 -980, 0x77d3db5253bac0ca -981, 0x8fd1b3db8997a7df -982, 0x7977905089848b28 -983, 0x60d769441eaa0ceb -984, 0x17eef7b60f4f9f5 -985, 0xdffd2e0b4deff6e0 -986, 0x6c07d6c0eab9583d -987, 0xb6d0c41c540524e8 -988, 0xa5f74648efa213b0 -989, 0xccf793ee870c7483 -990, 0xcb057091573dd7d5 -991, 0x572507949b0a9d22 -992, 0x51bfc469fa3bbb0c -993, 0xc0e35708c36e3969 -994, 0xee22a97b146d408 -995, 0x5b4049f83503ef66 -996, 0xf0bcba04dba7bc72 -997, 0xd27a0dff278d071f -998, 0x9b7eaff14d464db6 -999, 0xfe5f490518b254cf diff --git a/numpy/random/tests/data/xorshift1024-testset-2.csv b/numpy/random/tests/data/xorshift1024-testset-2.csv deleted file mode 100644 index ef10e6872219..000000000000 --- a/numpy/random/tests/data/xorshift1024-testset-2.csv +++ /dev/null @@ -1,1001 +0,0 @@ -seed, 0x0 -0, 0x3f76833568b96fd6 -1, 0x49701b0dcd023e7e -2, 0x5f266f1686d3bb85 -3, 0x4df1723af9a5a67d -4, 0x2fb393fa5be2f6bd -5, 0xf7212425ebb2ea96 -6, 0x3f02cec25804b60e -7, 0x7f3a0fa3228a48a1 -8, 0x79d9baad4538be8b -9, 0x4ae9b98e9c834b48 -10, 0x39b5728e47ba6016 -11, 0x9f1d986c6dced8f -12, 0x90e883bb0ca1a839 -13, 0x98995f729732f4ec -14, 0x26b741189221c8e3 -15, 0x293ae8b010a6b556 -16, 0x30180d5248809a52 -17, 0x3edc6105a838a0a1 -18, 0x315e9f489399aa35 -19, 0xd2c7f9142fc59292 -20, 0xe9f6c92674f1e75b -21, 0x785fdf1bf2633d4e -22, 0xbffdf9ac080cf1f7 -23, 0x29c63dce8aca1786 -24, 0x1e16e12f382e3f58 -25, 0x1509b2db378308f8 -26, 0x2f82c24732d9ab17 -27, 0x94feeee6b53644bb -28, 0xea274cb2e3a714ee -29, 0xbe0a718ad2dcb289 -30, 0x3c8ab9a7bb57e51e -31, 0x7eca590bacfdcca4 -32, 0xfcf259b0ee0f33a1 -33, 0x6323e00217e9bb03 -34, 0xbeba78e81e3e1e11 -35, 0xdc83427163d46eae -36, 0xc93193975a686b2e -37, 0x8984b33e2993452d -38, 0x98f329f05f37585d -39, 0x76ce85b5532f566 -40, 0x87bda8155b05a2f1 -41, 0xd949bf037a42d942 -42, 0x9f4021daa72f983c -43, 0x184bff5390deca78 -44, 0x4588bd90c642a4ab -45, 0x907886ff47abc57c -46, 0x7d5edf3810ac69a1 -47, 0xa22a609f3af5f287 -48, 0x6b40ffc40ebcc7b7 -49, 0xebdc35de8c34aef6 -50, 0x27f55c4ed36bd7b3 -51, 0xcb5680ca28b93c4 -52, 0xde59d0be040aeafe -53, 0xcb98df139b6ffb67 -54, 0xe5f29ae79bc3fbd2 -55, 0xf594a05f7d5c2cf4 -56, 0xbf9c12fce3be883b -57, 0xab1ae13d69b39529 -58, 0x421d72f4cc8f996b -59, 0x1e11487c7c5c80e5 -60, 0x3735d17439eec8c8 -61, 0x4b45af31c2a90a7f -62, 0x30a2cb0b8f4effc5 -63, 0x1d9c11ce9ed98912 -64, 0x459938610b8c056e -65, 0xcf8dc26a419b01cb -66, 0x6811a148c58a4b2e -67, 0xb524fbb0a1f9364e -68, 0xba973b1bafcafc8e -69, 0xa5ddb20be4f0ffdb -70, 0xc454734347f3ebc -71, 0x4712b34f7bc603ca -72, 0xcfd5fc37f5f96d64 -73, 0xd9376e1384a016dc -74, 0xd3e2e66d7522c11 -75, 0x143e2e7ceb65246b -76, 0xec0c92eb1c04628 -77, 0x45748e2648e1cf23 -78, 0xe0a78e265aed478d -79, 0x1ade12b47bff7af9 -80, 0x7df63a29c36980b1 -81, 0x1244bbc2c3b55d5b -82, 0x71dafa1fcd09e981 -83, 0x6da5bfe009eb025b -84, 0x446e999577098c05 -85, 0x4e740791bd030e0c -86, 0xeb81a0c4b7411481 -87, 0x78fb5228d162578a -88, 0x22e0adc5d0865c85 -89, 0x161f0870dc2730c8 -90, 0x55cd2b4204fc7021 -91, 0xa3f7032a1b14b9ca -92, 0x854f738869897eec -93, 0x6034a7deeec8a32e -94, 0xa65fdd6da09fcb69 -95, 0xad33713fcb48206e -96, 0xd3dbaad174c43ae9 -97, 0x96dd91e508c447f -98, 0x1a3340c5f67ac6c7 -99, 0xea0c47871d675b88 -100, 0x54bacdff7e665368 -101, 0x9bcc294b0224dc44 -102, 0x61ab987c7f6f44e0 -103, 0xa889ce8426a089e9 -104, 0xb3fbf7d9d2693b82 -105, 0xa034bba7212e9bcd -106, 0xf5b9ceb0347e27ec -107, 0x21a294cdc75fe066 -108, 0xdefd61a8423cc66b -109, 0x8bb34afc4238ac28 -110, 0x123125a26fec35fb -111, 0x12264435308f2e02 -112, 0x3040dc41d9d44a7f -113, 0xc0afa8f0419dd5c9 -114, 0xb104cc03806dbcc1 -115, 0xfee1222b5504c5e4 -116, 0xbd030f4ee7c7bb42 -117, 0xd9ae404361851df3 -118, 0xa152dc8b4829587f -119, 0xbe098e4fc3244521 -120, 0x962610a22b49f5f8 -121, 0x332846cf38524603 -122, 0x50df3207fc830c79 -123, 0xf3f3f1e7e4dc35e6 -124, 0x84a45b323586ee98 -125, 0xd081c30746cd1271 -126, 0x2f8a32f0bab99b4 -127, 0x10b35b4eaaa85d37 -128, 0x544e543d7301f095 -129, 0x7d4eb1f6620b0e8b -130, 0x8fc9da866e9f7d9d -131, 0xad4fc278afffcefe -132, 0x6ec8f6e385d52ba3 -133, 0xe373d4e2c67e1eac -134, 0xb66c7a0aafeb8bdf -135, 0x9c2861000abb6a04 -136, 0xd7ac7033ba369609 -137, 0xa89efcd43ddff9e1 -138, 0x8691faea965fab39 -139, 0x4706b127c3c60cb0 -140, 0x1f2bb20c07eee57 -141, 0x75de540960f2d73c -142, 0xa7d357a7588a06e2 -143, 0xc2fb0569e2deefcf -144, 0x2daa6fdc86ed6b5e -145, 0x8d22e7f3ddb473d2 -146, 0x4bfb1c145aa187ff -147, 0x4072049cc0ac3535 -148, 0x33aff50fd4fbd9a6 -149, 0x3b6b44b730ccbf99 -150, 0x6c642c48d77b70d9 -151, 0x5d906e071f55e4cd -152, 0xd2339209bf1902f6 -153, 0xe83a2462b66f9630 -154, 0x99b0e7998ef43ae3 -155, 0x10f9fed156fa7a40 -156, 0x916d7fe56fac3286 -157, 0x3300c38652e68e29 -158, 0x567d9b4b64e1b06c -159, 0x84760e41f897468d -160, 0xe20a22b206efe5ae -161, 0xcf62d03b167564a8 -162, 0x84154af6fd23be10 -163, 0xe598e0d0794d9418 -164, 0xf8aae24ab57b3e2c -165, 0xd32964005491aef8 -166, 0x227d2b64377a4129 -167, 0xa72ddc508c67727a -168, 0x2e2d60c022c700ec -169, 0x69fa3d4d34fbe852 -170, 0x756111547c3d3310 -171, 0xd462579cae5de843 -172, 0xe6cffa31860e71d8 -173, 0x3b63062bbcf07c93 -174, 0x25a83fddb4d2a4c0 -175, 0xe6b93ed6ee5b01a8 -176, 0x4ce86cf8224d215c -177, 0xe700f73f958137d5 -178, 0xeedce56e96870b8b -179, 0x3a03a241098f72b1 -180, 0xe066b4e17c9e7591 -181, 0x73b18bbd4b75ee0d -182, 0xe2b966c36c34d2c5 -183, 0x11f5a749521edf76 -184, 0x8f865c02ebed5bc7 -185, 0xcb93fe0bce57f9f7 -186, 0xe380b5ddf23dda17 -187, 0x98b03716d02f2dd9 -188, 0x9594e9b56cd3a8de -189, 0x6aa30fb660591e99 -190, 0x1e35c2dd1fcf24be -191, 0x1af2e84dbaae951a -192, 0x7fa337d7cd70b8d7 -193, 0xd0a270c39990acae -194, 0xcabf237235574a17 -195, 0xdf8219166c76b423 -196, 0x7ee41851de09d1c3 -197, 0xd444c75128a3aead -198, 0x595291e15ace95b1 -199, 0x3f96f0a33493d662 -200, 0x524c9f003c2d74aa -201, 0x30e4b6855164d763 -202, 0xd2cc4597098a4500 -203, 0x9a11cf7e7d856ddd -204, 0x6f71b7f4da0728ab -205, 0xa4f4b90919184391 -206, 0xc420d20c06ddc291 -207, 0x40bd7102c1406163 -208, 0x3e0ffda5947e78b2 -209, 0x2b283f6394d08786 -210, 0xea1381e7f22269e2 -211, 0xd9af6fb63feb67ab -212, 0xe65d7ada4c0ed57d -213, 0x29390a105449ba95 -214, 0xb714f9a216f85022 -215, 0x99761fbf534d3253 -216, 0x8bee9140cc17f8ad -217, 0x119bf94d69993284 -218, 0xca34608a9dad7608 -219, 0x6f85cf613b771566 -220, 0xa5d41c9378efd4e2 -221, 0x1189d8ac0d41087d -222, 0x9cc77851a3d6256a -223, 0x363a1ed11a7bceab -224, 0x3e20c00dde9ac9b4 -225, 0xbf1033cb123038ac -226, 0x748824fc5d57ae8d -227, 0x29c6f3b0f34acaca -228, 0x89336ff6ffb38204 -229, 0x367634fdf6f5e062 -230, 0x17dada74ad118131 -231, 0x77fa722a7b7758c4 -232, 0x8ab624aa783988dd -233, 0xbb1a2d574226dd4b -234, 0x1367c3ee11cc302c -235, 0xe303b78053ea7d45 -236, 0x57692f8f470748db -237, 0x88117a25910baa9c -238, 0x67945be555ef710b -239, 0xf78d697319517706 -240, 0xc624069abacab039 -241, 0x406c99876ee0014b -242, 0xc268f98bb4187961 -243, 0x34c1fe6d9a249a66 -244, 0x7b229f23ed186b48 -245, 0x813447c8c6b3a02f -246, 0x7dd08df945ce95fa -247, 0xe8439c737db475cf -248, 0xa060ed8d264bb4e9 -249, 0xfec7390334233d46 -250, 0xc786d08ab50aa0b5 -251, 0x8f8f5f96fc6d877e -252, 0x2ef7ccf97c1c4568 -253, 0x27a14053814966b -254, 0x2ea6f6167c4ce2e5 -255, 0xe45bdc101c584e71 -256, 0x7927f5ac670f2125 -257, 0x51d140214f8fb611 -258, 0x96eba70b12dc9642 -259, 0x30c35af279a715c2 -260, 0x5e6f1fef8babd762 -261, 0x3d84a3c7012aa1ed -262, 0xfaa23aae7c57a141 -263, 0x4f91d0308ab5ccd -264, 0x9ba4c6fb766b1d71 -265, 0xc3bb36fe1a75b832 -266, 0x9c41667dc9637d7c -267, 0x18e7228d28293b69 -268, 0x1d6b71e7e87d5950 -269, 0xbfc7e99d1eea3c7c -270, 0xda9afc08f8b7bbea -271, 0x3ff5761b30c8bb43 -272, 0x81df41076e62f613 -273, 0x7e0a93b2112863a -274, 0x2aded22e3c3505d3 -275, 0xac8708ce5ef15377 -276, 0x273889f29f88382a -277, 0x5f74810e09927568 -278, 0x6e10e51a892a9da8 -279, 0xe6eefe4463d9038d -280, 0xfe194822bf0b3419 -281, 0xcf98d3b3f7701024 -282, 0x3b68bfc20c696612 -283, 0xef06d708e6327398 -284, 0x115d9132577f4566 -285, 0xb0247d0045c6524 -286, 0x1ffb63669817b448 -287, 0x10954c02bb530f75 -288, 0x3e7c1076a5e89acc -289, 0x239b3401cd7e8056 -290, 0x9f8df322b64c4962 -291, 0xbe9539d72df565d7 -292, 0x7ebdf0839712cee9 -293, 0x72f59054c80879ab -294, 0x78cf26fdca1e23bf -295, 0x7f53ea01601034e2 -296, 0xac0e9524b4043f55 -297, 0x1bb323be19e1b898 -298, 0x381e9a0b43ba368b -299, 0xbcbc8ff4b598c9ab -300, 0xa453f6680a2eb4d7 -301, 0x91ffe27309f97963 -302, 0x91c516cace3203be -303, 0x3224f64f8714d361 -304, 0x4f6d6f775c7a2b32 -305, 0x7b84b4d40a2177ce -306, 0x81bbcc7123cbc6e1 -307, 0x97a72d7f8b0d2dd4 -308, 0x21bd4232adf86e98 -309, 0xec4ab4065e523a75 -310, 0x420dfc4bc490cc07 -311, 0xb8bfb45dce69f9c5 -312, 0x6d0459f3cfc48a26 -313, 0xad9c1dea5e333a1a -314, 0x256625ac14326b06 -315, 0x396ea8de20ed603e -316, 0x7419c2884aa94922 -317, 0xd9eeb9a53cb471ae -318, 0xa0aac8233b2d27f3 -319, 0xdecb4cc4c1fd518d -320, 0x5ddd5eb974b7183b -321, 0xdcaf4600c6f236b2 -322, 0x6a7fa0a9ab5dfe2c -323, 0x91608b5fb33fd9e4 -324, 0x934bc1e6635f93f1 -325, 0xcda9674329048f55 -326, 0x7db603137ab31c62 -327, 0x788842593a8a36ed -328, 0xc1144ce4e0cfc1b6 -329, 0xca0da06301356dee -330, 0x2e609e408dc6d488 -331, 0x2c910b390a076ccb -332, 0xcdad30b1f4c3aa7 -333, 0xe5f2803b739851ac -334, 0x9f8ea3daa1c36e56 -335, 0x47ed39920178a5a -336, 0x4cef4092c54e9c51 -337, 0x12ebdfeb4847b6bf -338, 0xebc3f046a004670 -339, 0xce66c4aab5ea2aa2 -340, 0x27088642c863fd4 -341, 0xd7729cf6e92fd77f -342, 0x5a736a0216708ed6 -343, 0xfb49b5fd93f2c041 -344, 0x3e72423a05badd91 -345, 0x7c71eb29547e7bc8 -346, 0xcb40d0049872cf15 -347, 0xa284b7e30ca1145 -348, 0x592d91e0d87f9123 -349, 0xfa4db97733a8d46a -350, 0x33e0188f9b5d5a15 -351, 0xcef2c9a938c4b632 -352, 0x7b0e7bb55e2de88a -353, 0x154509b3c6ccf5e7 -354, 0xd9f168c6562843cb -355, 0x5774a6c2f1870f6c -356, 0xcf61f03f990d2fa8 -357, 0xeebff250f37ba8a2 -358, 0x6e5cda9f932e1052 -359, 0x4d305d91b590a85f -360, 0x26d083f26c6f0962 -361, 0x193d7cf4666a62d6 -362, 0x16d5f99e8a5b06a8 -363, 0x7b0b84b314572d8f -364, 0xc2b5d8f73da78be2 -365, 0x997e699bbdc0e646 -366, 0x720e559e24126bcd -367, 0x46b281355d2f486e -368, 0x6fe30651b885494c -369, 0x5736ed3979ae2d1e -370, 0x3298bf38f1185e64 -371, 0x33c4cf1fd1c9f0e1 -372, 0x84c8acaa32f4972 -373, 0x203d97007f3eff1d -374, 0x6b0b1b27d8fd7c84 -375, 0xc791ed0eed40ddbe -376, 0x13863752048fe702 -377, 0xc5ad8abd0b55c285 -378, 0x1ff361677761ec1d -379, 0x50630e4db5d26a0f -380, 0x1d874f4f175bfaaf -381, 0xf9a772934d22937a -382, 0x33e35f9ec8f608e3 -383, 0xc0953e273301c556 -384, 0x722fa1dbd45e5ae7 -385, 0x937eff91f242e7a5 -386, 0xa1a9e58a6c492813 -387, 0x5a72e88472ea3927 -388, 0xb5267cbdb4e014fc -389, 0xcdaa66f2de7c5ec4 -390, 0x64435583f46235cd -391, 0x95d31d5b002ce32e -392, 0xbfb014b274a6c503 -393, 0x74e839390843cd16 -394, 0xac6949cbf5d364ef -395, 0x1479db78d333bb8e -396, 0x2c7c11dda1f4905a -397, 0xb96f093c2e1b7e20 -398, 0x975acd07a18de87e -399, 0x812358a90bc79d95 -400, 0x76cdee04f004fb29 -401, 0x5e3b3481faf2bb49 -402, 0x890a8a9d41bae44 -403, 0xb7be0ca619af0890 -404, 0x4acb36efb0d6b770 -405, 0x71f80306003ade01 -406, 0x6fecdbb899af55d0 -407, 0x8314c0048baaddca -408, 0x534b12b2f7f0cc76 -409, 0xd9355306b6cb3f52 -410, 0xb0f97ca0e0ab1d93 -411, 0x89d153e37f98ea2b -412, 0x12e68f2795d4f051 -413, 0x906e397219a1ace -414, 0xd4727951a949b01c -415, 0xd33e3ff226ae285e -416, 0xfca4fa59e21a1dd1 -417, 0xec3fe6b91647b696 -418, 0x63d7aa385795076c -419, 0x55ebe0e2765d55af -420, 0xed70c55156b6944b -421, 0x2e65098d479e0006 -422, 0x5311ac9e79d145c8 -423, 0xaca7a78c96a8901a -424, 0xcb38f5f6a6992d08 -425, 0x9c144477c018fb03 -426, 0x216b3b13e04a6495 -427, 0x8e4d521ab71f367 -428, 0xa17063caaccda60 -429, 0x23900aaa25cf3bc8 -430, 0x1889209510603108 -431, 0xc8f99af9d0de76a7 -432, 0xc6fad82edb65f52c -433, 0x9f382a97ae383143 -434, 0xbb4596f5e389ede6 -435, 0xdfbb3da5441e6923 -436, 0x35bf9ee561580153 -437, 0x3c401b162f4a4479 -438, 0xbba8e9feab108d71 -439, 0x78c15ec1926e3d40 -440, 0x24c54d5604a9fb4d -441, 0x3d65e97ac30dd152 -442, 0x3ff106c26e925fa1 -443, 0x994d0fc4273e547f -444, 0x9348554463808d14 -445, 0x16a8f20bbdd24edb -446, 0xcb20c09774c4ce20 -447, 0x83f1b14f2bab7fe1 -448, 0x5b03859915c40093 -449, 0xc578aeb49ce9ecf9 -450, 0xb51d25e52cfa85f1 -451, 0x58781d91ce35247 -452, 0xcd4222374d4e7eb8 -453, 0xbe7bc2cd6690b2e9 -454, 0x2f56338457305032 -455, 0xa5e696a2c3010178 -456, 0x249bb58b22f4bfb0 -457, 0xf439f41bd99cf89a -458, 0xff4987ee68c91e95 -459, 0x496a634e8032a27d -460, 0x8571dd7ba26413d5 -461, 0xec112e9e23f14e63 -462, 0xcff790437f3c20ed -463, 0xa67b9fa0db0aa231 -464, 0x765cc90556d15624 -465, 0x8683c3dd207422ab -466, 0xff2d139be6499b33 -467, 0x72d02be5b40ad6aa -468, 0x8f6d1c4265a58b12 -469, 0x9f0cb4e8a53cb479 -470, 0x85d4cd253510301b -471, 0x3ef6422a20e34ec9 -472, 0x2b510e1f5ec6f97e -473, 0x46a2e5b35fb78706 -474, 0x506a027d4e2205f5 -475, 0x36de7c336f2c9a05 -476, 0x86fbe1c3ea00a2de -477, 0xeec25bddc61238c9 -478, 0xf02b9c043c956a05 -479, 0x6b13b95622a9807b -480, 0x2a9e68f100ee409 -481, 0x41d3ad00d81683f1 -482, 0x8a4b386910e89455 -483, 0x7ab9f9fa2285614b -484, 0x359c0b462d735de9 -485, 0x3b4cc9b3c45ff686 -486, 0x36efe94862f105a1 -487, 0x8b425f27f3996c8c -488, 0x396750b5141990c0 -489, 0x95e8016fd8be3b03 -490, 0x76fc07ca93fa58d9 -491, 0x846bb14c645b0c75 -492, 0xa605cfb398297aac -493, 0x19e42af61faaefcd -494, 0x8fbc9c5be2370b9 -495, 0xfabb6a708b774c92 -496, 0x24e23045a7ccb7e6 -497, 0x84caca37453c53a7 -498, 0x9fbe0deda0ab217a -499, 0xf41cce8970ac144b -500, 0x8e8a33acaab17e59 -501, 0x846608d05c9b73fe -502, 0xb32c80a1c82fcc1b -503, 0x89c4d0ea85766f75 -504, 0x99405647ddcb348c -505, 0x1e831b51204b7a63 -506, 0xfd8bf1b743791185 -507, 0xde489c75cda83196 -508, 0xd579f8a2c70628f1 -509, 0x60e4bb07af5ace5d -510, 0x262843c44883481d -511, 0x992a22735ab308c9 -512, 0x74de79ece0a914b0 -513, 0xd4a3ff83127baf97 -514, 0x23dc69bcc5fe770d -515, 0x58f3497d5a9ad653 -516, 0x58ed53ecb7a64cb0 -517, 0x6ee92d9763d37f9e -518, 0x7f6f9fbf877b0164 -519, 0x7139eeb4b3c482bd -520, 0x197316b659bf8834 -521, 0xc28a627d979022f6 -522, 0x85ae4049d8ad47fb -523, 0x11c9516d4ae13e22 -524, 0xaccdffbd16f33d28 -525, 0x68882afaea90ca13 -526, 0x7e6c6fe98874f58 -527, 0xa2aac5489c8ab7cc -528, 0x3978eabb2543d737 -529, 0xa17c62e45a3fe296 -530, 0x6eb109d81c9224d8 -531, 0x49e550d7a5f68291 -532, 0x550c48610a266785 -533, 0x717df8f6f8c4c714 -534, 0x6c9171ae4c97ebc5 -535, 0x9248555f2e938277 -536, 0xeee197be9a685e21 -537, 0x23b10d152729c79e -538, 0xd99a0e35e22c02c5 -539, 0xb2a229086a71360a -540, 0xb53ad493eca7e4d8 -541, 0xdce4c80cc7b59a25 -542, 0x1d0f7a0a78f628bd -543, 0xebf4133a6b4da324 -544, 0x1c6a43aaa8a28e82 -545, 0x417512b9c8c332fe -546, 0xb82c515788d7474e -547, 0x58d8b6d62366b9a9 -548, 0x417383f667b82e5d -549, 0x5065df19d5156876 -550, 0x45f7a177dce0ae19 -551, 0x51bb2b6e4b99b7d0 -552, 0x607a99fb8d715e92 -553, 0x5f8ae53d33601b03 -554, 0x555a8aa2cf4dbe8c -555, 0x5fe3af983f2dd205 -556, 0x340b495f8d7f771d -557, 0x5b1efc807762ee26 -558, 0xbe0f72f3f2b2529c -559, 0xec1b0691d58149a7 -560, 0x97e7874c9af94cf1 -561, 0x7da8f0dca84401eb -562, 0xc4c0f0da6a25bdfa -563, 0x1d1b16f1a51b9535 -564, 0x805482e682b26d71 -565, 0x2b6f9a35fee36ca1 -566, 0x57ef4cb20da96729 -567, 0x261932d0691874e6 -568, 0x314883c0836ac0e3 -569, 0x1f831417a3c49289 -570, 0xaded4280fb377fa3 -571, 0x43bc2d0eb4fe43c7 -572, 0xc1d71eefdfe9cea4 -573, 0xa876eba383515868 -574, 0x994d9fcf3142f08 -575, 0x8f10d482bda9d35c -576, 0xd4a386334c346cc3 -577, 0x410ea73faef00896 -578, 0x2b19d1288b764b7c -579, 0x73d80efec82579b6 -580, 0x79fe50849dd6db16 -581, 0x99d073390884e5b5 -582, 0xb656c4f5b7d8c251 -583, 0x265f1a55f456463 -584, 0x3ca410702fe4f733 -585, 0x838c4431205583ff -586, 0x1223f9eca84c7513 -587, 0x68ab8b0bde2f7e5c -588, 0x6ea394530b224537 -589, 0x9ef5afd2667e6cf0 -590, 0x3f6ea8a19a50ba0c -591, 0x5f279dd237a1e3a9 -592, 0x7c4cee031b6361c6 -593, 0x9646a6547ac7b2b9 -594, 0x3ff18f84973f81aa -595, 0x9ddf4b58616f4374 -596, 0xd484e12a4d9c6c08 -597, 0xf6df9d6cbbfacdfb -598, 0xa55f08713250cbbe -599, 0xdcbc45f59afd73e3 -600, 0xa6c1b651ac0b5b8 -601, 0xdb57ae1da9226710 -602, 0x2a825af2f9016875 -603, 0x5634e077906a70f5 -604, 0xcfe76fb8a918b9af -605, 0x96a65ede52b0f259 -606, 0x3b1ea564eaf66326 -607, 0x42ecb562ebd36e80 -608, 0xeefe615d1df23980 -609, 0xd6c79be5c011e807 -610, 0x22e39b0698f93131 -611, 0xa5d5cafff6e1dc41 -612, 0x8f2b02fe6f4a3c06 -613, 0x207edba6a1336b20 -614, 0x363262b62a0d36c7 -615, 0x295ec0d93e112449 -616, 0x83c1f7c6b1b985e5 -617, 0xc02a5c40cdb4d615 -618, 0x23a73f3c52eb8f32 -619, 0x62cc20f4d6e11dd8 -620, 0x766166e1da546d7c -621, 0x9d16d9030c9cfb84 -622, 0xaefc85375fa75d91 -623, 0xba77a56d0ea4ba13 -624, 0x39a31a730e0687d7 -625, 0xe3a57f64109f562d -626, 0x1d74491bd9d29388 -627, 0xa6c5f561a185dfb -628, 0x633992b1c0d3fe44 -629, 0xee814a1280651a2c -630, 0xe2f2b54ae6a45ded -631, 0xf391217301365d25 -632, 0xbb76dda0270a6006 -633, 0x3b48ecebee5b9bce -634, 0x6d06438edf209241 -635, 0x357ba920e8b1997d -636, 0x6041cf82c985d9e1 -637, 0x26e199481a8f8370 -638, 0x402bef99c898c7ad -639, 0xaf537688258ece78 -640, 0x8bd65a5e42349fc1 -641, 0x966d6db227125e56 -642, 0x1c2bf537dbdf6a18 -643, 0xf882d51b88effda7 -644, 0x7934750e1ff84314 -645, 0x5d3a2ef7b201a299 -646, 0x43a1c0074fc7f3b2 -647, 0xe4ac4fa8e80ea889 -648, 0x7edcb91435ab94e4 -649, 0xbfc1dd08ddf7a0f -650, 0x14952561bbe706d6 -651, 0x76ff2246de9054bb -652, 0x164e716d44262e2 -653, 0xa2f0f0863f249aaa -654, 0x306df43087c5eab3 -655, 0x9e082542ffd2eac6 -656, 0x15371e1c1c88ef39 -657, 0x88380af1bbcb80bb -658, 0x6970f2d4e27e8997 -659, 0x7852aa8ba9e1d9bd -660, 0x353e12a671e73337 -661, 0xad43311c6ad719de -662, 0xb650a6d41913f4b0 -663, 0x1970174855d8058d -664, 0x8bb04033e9ae7065 -665, 0xac845cd23eeaf4ae -666, 0x75a264443291a7d4 -667, 0xab2b59c9ff6a40ca -668, 0x55733ca31b6413f6 -669, 0x6646ece8a89f9a74 -670, 0x318b0f83763269b1 -671, 0x285718955e9e5eda -672, 0xbe635b7f41321ba5 -673, 0x5208b1776231474b -674, 0x77f3df408394f208 -675, 0xd65a9dd028a3be77 -676, 0xb870f9a5a396b5de -677, 0x171038f25bc6ac14 -678, 0x99080d183e6246a5 -679, 0xe6260240b3509008 -680, 0xa0d3d2b8e1e5c4ff -681, 0x361a2692ef38fc0d -682, 0x907f5f272f8cc40a -683, 0x69fe3e0760201193 -684, 0x376118679943bc68 -685, 0xb137d0ab55d55d9d -686, 0x93f13b625502297 -687, 0xa49ed908d712453f -688, 0xbc215abe4adbf771 -689, 0x6a8e285265915d23 -690, 0xb838f15249c88f2d -691, 0xfd0fe93ee175e160 -692, 0xa86c8a70a0f1efb -693, 0xe2385851319e2d35 -694, 0xa0109f10353a584d -695, 0x63d54fde29ca316f -696, 0x6101dbcb043a06f9 -697, 0xceaa0b0a69440ce5 -698, 0x33e883a6b04e5103 -699, 0xee1b5ff43e231092 -700, 0xb427baf113599501 -701, 0x12b2317e71c6f9e8 -702, 0x1e3b122a92d24b36 -703, 0xc48ac99bd429a525 -704, 0xb07d638ce8aa1535 -705, 0x84c65dcac2b974ca -706, 0xdb4c47b0ec83241c -707, 0xed92b08dcb8c8bdb -708, 0xc9ea8ecb281d5a28 -709, 0xfa0b3e63ea37fd67 -710, 0x228ff7b873098379 -711, 0x77d6f7cf9c6e7bda -712, 0x8fe3f2b9ace02ffd -713, 0x2384ac4a406dcbe2 -714, 0x1fdce3138708f093 -715, 0xd34e85210c534b21 -716, 0xf8916e32dbfabbda -717, 0xb86418c0e2a753f2 -718, 0x98aaf36286e26ede -719, 0x66167e59c5d5a36b -720, 0x4c4d4c520ab6ae3a -721, 0xe83dcbe740d700cf -722, 0xafdbf579b9bfd667 -723, 0x2ae659b5e10ed7c4 -724, 0x7aa4d22f99423301 -725, 0x62c315f474195042 -726, 0x7c9212e3389c5959 -727, 0xa1f58e637d2c5a05 -728, 0xa0bb57dfd563a2ea -729, 0xb1ba41472dc9907a -730, 0x4355e0abae1b4e2b -731, 0x7831551c86ba472c -732, 0x6377246eb9c563c1 -733, 0xc33cca358031cd73 -734, 0x1a3df433adc587b9 -735, 0x959e58590ac04430 -736, 0x551713647091eb40 -737, 0xf15b81000b87a230 -738, 0x3c73394683730b04 -739, 0xc5ecf4d9c0d365a6 -740, 0x3cf3bb6f48141888 -741, 0xebd1e9e53e18117a -742, 0xa61d9146dcf3de9 -743, 0x9f64cf0611d26ff5 -744, 0xbea8440eee55a206 -745, 0x77426a4854f7dc77 -746, 0x415be11a6b4b34f8 -747, 0xbea05b3645aaf507 -748, 0x57d73bee3328d944 -749, 0x96c76260dae635b7 -750, 0xbbac81463c836e7a -751, 0x687822e5d4be6aed -752, 0xe3a0256c9e82d869 -753, 0x87efe94616042e3b -754, 0x127ecd55502079e0 -755, 0xdeed29e6ad9d3e5e -756, 0xd0f2b4d2fff9819f -757, 0x2c8ae834d48257d0 -758, 0x1f3aa79b5cd2cf52 -759, 0x693344b041cd0a74 -760, 0xe274c86488294f4 -761, 0x6a72fe61886a1d90 -762, 0xf7ec995387d51db -763, 0xc8f89ee89a223b6f -764, 0xc18a8258219c435b -765, 0xd2b83efbe2cb4fb3 -766, 0xf641b18d7ac141bc -767, 0x749d69c6371218c3 -768, 0x9435604b36073ca2 -769, 0x108bef88ea3a207 -770, 0x755776561f260626 -771, 0x4427e10b7c01c9da -772, 0xe503a94f8c3736bb -773, 0x4af8b8388166989e -774, 0xded90567abb2ee96 -775, 0x2337907e762a4f7 -776, 0x281fbe8330c24237 -777, 0x9d05969f770ba3b6 -778, 0x5b14db87a3978c1f -779, 0x1aca424488742d16 -780, 0xea3d971ce98124af -781, 0x5a45029209753fc5 -782, 0x551db2424e7892d -783, 0x55c5e85b29fa995b -784, 0x6f9b5885dae0bb3b -785, 0x40c269f378668751 -786, 0x31db833ffc89d7b4 -787, 0x54360752ef548928 -788, 0xde47ece2daf0f4c4 -789, 0x705c2f3be27845a9 -790, 0xdddd3a82ef299df0 -791, 0x24f914ca137e58c1 -792, 0xf737cd929f8a0b74 -793, 0x61642bf1f0f67553 -794, 0xf8876f5d9aaef9e2 -795, 0x766d2cb707ad74f2 -796, 0xf44c1e3d1083a1 -797, 0x996635c0d00e9fe0 -798, 0xefebf35270fa64c5 -799, 0x7db96619def7e9c0 -800, 0xf331b2e18b743845 -801, 0x62a2f25ec518575e -802, 0x31c3681a727de50f -803, 0xf98c015a5a1c54fb -804, 0x743bd3b5fbec0062 -805, 0xf3dc863a7f8b7ab6 -806, 0x839b8142fa0abd9f -807, 0xa641d1b43d37b18a -808, 0xb71faae321765fd -809, 0x2ec5a90aa7b571f0 -810, 0x89764721520044c0 -811, 0xf231a2e03edf49ba -812, 0xa1579465ebb9cdd -813, 0xfcb73c83c8438163 -814, 0x1aecf871e3e78339 -815, 0xe4466ba1de623b9a -816, 0xfab6458b9a8b7425 -817, 0xd08a56b73b9c289e -818, 0x821d2fcc13b84a8f -819, 0xbfb8842df2e876f1 -820, 0x94682890433e1e78 -821, 0x6a06072528ac8590 -822, 0xc408544d50b3b450 -823, 0x808753793fb29a6e -824, 0xabf989d4fa6b4087 -825, 0x796eacee17b0dc9b -826, 0xf6a77ae26e88dbac -827, 0x2fa97a02950c054f -828, 0xc711f4f82d4a6bb5 -829, 0x9caf50bbb28c3998 -830, 0x3bb92e640c99b657 -831, 0xbd888a8215f757f7 -832, 0xb75989e611a773b2 -833, 0x566399962d08ee5 -834, 0xf71d630e51443477 -835, 0xa0e3179e50dca26a -836, 0xebaf61a44eacc2c -837, 0xd5a358ff51aba185 -838, 0x3ea9c5e748d7ef7d -839, 0x897d6f8d03cd8cfe -840, 0xbedff90968cc3d94 -841, 0x87c5d60ba0e32b94 -842, 0x77898f21c70aa1a5 -843, 0xf02536e75c4381a4 -844, 0x4846df09787df4b0 -845, 0x4228b5bbc1e7137b -846, 0x87591acaee0d2b2a -847, 0x1094db803d6a2294 -848, 0x351bd6517744343d -849, 0xc6b66f7b4ab87e27 -850, 0xa138357faf31fffa -851, 0x3412ebb334d67bf9 -852, 0x831e1dbb632ff45d -853, 0xb008f6fa331ac5c4 -854, 0x9e22b7aef7223f2c -855, 0xc460a6aa5002f154 -856, 0xf353a66ff09b0a26 -857, 0xd5254e93c6a14abe -858, 0x4f72ff6246201214 -859, 0x10c1343f8a78f3e9 -860, 0x33b25deced647ff3 -861, 0x1a1f8abfd8907972 -862, 0x5a6278a9f7ed8433 -863, 0x7a40269035528530 -864, 0x7ef16d32772d58ce -865, 0x8252729ff8c33aed -866, 0x436c4d77c6bf0e2e -867, 0x5fd97535df293b19 -868, 0x8fde6dc6be9469b2 -869, 0xfaba1ba4fdb254d2 -870, 0x1d517806e45f2257 -871, 0xa040c894d9b0d308 -872, 0x48f32da1e1f879fb -873, 0xba444bb3081a8225 -874, 0x51e174f14631ce31 -875, 0x4b0eade95134975c -876, 0x5189f935656f29ab -877, 0x30c58e655faafb4f -878, 0x371996d1e3ac1806 -879, 0x953ae118b4e7385a -880, 0x7169becb6a7701a7 -881, 0x65c138388881dd6a -882, 0x9facc10f2cde5ac8 -883, 0xd80e3d6e2a953134 -884, 0xd410f904163c2a4a -885, 0x73a836e050f95de8 -886, 0x1a03a8183edcd8cd -887, 0x46ae001eec388186 -888, 0xeea3aa51afca2103 -889, 0x7af3b7ac380c934e -890, 0x7ca100978bbea8a8 -891, 0x8231c46ea318f711 -892, 0xe848e769f59373d4 -893, 0xae4823022d3452a7 -894, 0xc8bd326d8092a1a6 -895, 0x9e0ae695cae65d4b -896, 0x95e760a060655036 -897, 0x6fb7c9035c3ad544 -898, 0xcade3a08dea3432f -899, 0xad47f39e3fdb2ece -900, 0x41cdb1fb154826f6 -901, 0xb55de258f6727990 -902, 0x1c547ad05236f8da -903, 0xb6d373042359f1d -904, 0xdb9aad9d0f6549e2 -905, 0x6f09843e435c9d18 -906, 0x4b15fdd5f152bbc0 -907, 0xe9423d09f9d91535 -908, 0x8eb6dd3e2e87aebc -909, 0x7a8583a8124b1741 -910, 0xe6d5ce1819791a58 -911, 0x5d362b7f66fccbec -912, 0xc737676690fa26ea -913, 0x832aa877e040d398 -914, 0xe1aab8a68d879f2b -915, 0x8939c5616a219730 -916, 0x7e2ebccbd4019680 -917, 0xd86f3e4cb2a2f76 -918, 0xd82d4bb2eb375edc -919, 0x737d7bdf10e00e90 -920, 0x3764d163ed0a417f -921, 0xe06f90beaefb963a -922, 0xa74d750318857241 -923, 0xf804ecbcb5c25c8 -924, 0xbf9b027357f99374 -925, 0x2e5b2d58d1144a08 -926, 0xfa7ce04633c5cac2 -927, 0x4eb7775c4e9ee4e5 -928, 0x65457f52533039f0 -929, 0x5182d68bf085853c -930, 0xdcf362534f2b4616 -931, 0xee7ccedf18c95a68 -932, 0x691f8ff9750b925 -933, 0x3d82b8e8d8fc31fb -934, 0x85c0bb0f4b4a112f -935, 0xe95df77752e5e173 -936, 0x3605e7d61fb76af5 -937, 0x60335d8c6cbf6988 -938, 0x2b5a314000327ed5 -939, 0xca0cffe76d1778e6 -940, 0xd6033f0b2e789355 -941, 0x8f90a41a4fdfcc53 -942, 0xcb2b7cfc32976d3f -943, 0xce14afa2b8fb65b2 -944, 0x94a561aba9fe7cf -945, 0xf1c0bc3b71900acf -946, 0x47d384605f859409 -947, 0xb2becb4cb5ebb62f -948, 0x6080faf5ce884092 -949, 0x870ba05eb5ae8340 -950, 0x32116515ddc7e7cd -951, 0xc40857c60e3dba4a -952, 0x4e1e70e385c9c86e -953, 0xa8a36df8f9ec77b8 -954, 0x7ae475e0af4c4883 -955, 0xf60a62a9b8e92e66 -956, 0x9b4fb6700726b37f -957, 0xf30871c82b621163 -958, 0x87fa839419a1b038 -959, 0x7c70f09e12e5c9c6 -960, 0x2a55a6b0700f191e -961, 0xc5319239b1cb6247 -962, 0x5b3d7daa4da4d79d -963, 0xc845b957a849bf3e -964, 0x8ab82092c3b8ea4e -965, 0xe4d3330f64e85823 -966, 0x8b4359b012bf4ec7 -967, 0x94f2ae8fc8a645c2 -968, 0xe1c16a64d7ccb7d5 -969, 0xf7ab947c49dd9053 -970, 0x3ffe0e57136f4933 -971, 0x8378e36e4fdda387 -972, 0xbb3e9622b0527aa2 -973, 0x754dfcf2de3400df -974, 0x73b47f3626ed9d1b -975, 0xe056dc83a126f693 -976, 0xf9c646b99afe77f -977, 0x20d89f4d3b7ea72a -978, 0x82d8b24230c46c2a -979, 0x9ba818f53341aad3 -980, 0x4a0e781a1646ea64 -981, 0xc7d87a350ff43d7a -982, 0xc396afe3eab47776 -983, 0x6a61f73b628e8892 -984, 0x60e383f172e15eeb -985, 0x9722fdbd2a03b13e -986, 0xfd634049374a2628 -987, 0xf9863806fbc39457 -988, 0xc83f2fc42eca9f -989, 0x16d1bfdf49fc98f0 -990, 0xa28f80d5c410cd30 -991, 0xe94f58e03cbdf4ee -992, 0xe5ad5ccde4a99bb3 -993, 0x482c3dfa3bc71d3b -994, 0x75fee65a654d5c0a -995, 0x6aa16a97c454a20d -996, 0xfbe5549c65d74c76 -997, 0xa2292c465994cb9b -998, 0x5d1d10d51694d4d1 -999, 0x40e57b3aa1059716 diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 4700bb0cea99..7c60912542e1 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -128,7 +128,7 @@ class Base(object): @classmethod def setup_class(cls): - cls.bit_generator = Xoroshiro128 + cls.bit_generator = Xoshiro256 cls.bits = 64 cls.dtype = np.uint64 cls.seed_error_type = TypeError diff --git a/numpy/random/threefry.pyx b/numpy/random/threefry.pyx index 02911528b190..5e5b9cf7aabd 100644 --- a/numpy/random/threefry.pyx +++ b/numpy/random/threefry.pyx @@ -366,7 +366,7 @@ cdef class ThreeFry: Returns ------- - bit_generator : Xoroshiro128 + bit_generator : ThreeFry New instance of generator jumped iter times """ cdef ThreeFry bit_generator diff --git a/numpy/random/xoshiro256.pyx b/numpy/random/xoshiro256.pyx index 362139cfa147..380d04af745a 100644 --- a/numpy/random/xoshiro256.pyx +++ b/numpy/random/xoshiro256.pyx @@ -76,7 +76,7 @@ cdef class Xoshiro256: directly consumable in Python and must be consumed by a ``Generator`` or similar object that supports low-level access. - See ``Xorshift1024`` for a related PRNG with a different period + See ``Xoshiro512`` for a related PRNG with a different period (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). **State and Seeding** @@ -263,7 +263,7 @@ cdef class Xoshiro256: Returns ------- - bit_generator : Xoroshiro128 + bit_generator : Xoshiro256 New instance of generator jumped iter times """ cdef Xoshiro256 bit_generator diff --git a/numpy/random/xoshiro512.pyx b/numpy/random/xoshiro512.pyx index 0505af207691..91b0ce51b0ce 100644 --- a/numpy/random/xoshiro512.pyx +++ b/numpy/random/xoshiro512.pyx @@ -76,8 +76,8 @@ cdef class Xoshiro512: directly consumable in Python and must be consumed by a ``Generator`` or similar object that supports low-level access. - See ``Xorshift1024`` for a related PRNG with a different period - (:math:`2^{1024} - 1`) and jumped size (:math:`2^{512} - 1`). + See ``Xorshift256`` for a related PRNG with a different period + (:math:`2^{256} - 1`) and jumped size (:math:`2^{128} - 1`). **State and Seeding** @@ -262,7 +262,7 @@ cdef class Xoshiro512: Returns ------- - bit_generator : Xoroshiro128 + bit_generator : Xoshiro512 New instance of generator jumped iter times """ cdef Xoshiro512 bit_generator From 3db5a7736cf26db59817eb8939b042ae18c482fa Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 24 May 2019 00:37:22 +0100 Subject: [PATCH 134/138] BLD: Improve setup Attempt to avoid defining variables that are incorrect for some platforms --- numpy/random/setup.py | 204 ++++++++++++++++++++---------------------- 1 file changed, 97 insertions(+), 107 deletions(-) diff --git a/numpy/random/setup.py b/numpy/random/setup.py index 48a729179184..b8b190b09590 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -1,26 +1,17 @@ from __future__ import division, print_function -from os.path import join -import sys import os import platform -import struct -from distutils.dep_util import newer -from distutils.msvccompiler import get_build_version as get_msvc_build_version +import sys +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) @@ -28,7 +19,7 @@ def generate_libraries(ext, build_dir): 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 @@ -40,124 +31,123 @@ def generate_libraries(ext, build_dir): 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 = [] defs.append(('NPY_NO_DEPRECATED_API', 0)) config.add_data_dir('tests') - ############################## - # randomgen - ############################## - - # Make a guess as to whether SSE2 is present for now, TODO: Improve - DEBUG = False EXTRA_LINK_ARGS = [] + # Math lib EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else [] - EXTRA_COMPILE_ARGS = [] if os.name == 'nt' else [ - '-std=c99', '-U__GNUC_GNU_INLINE__'] - if os.name == 'nt': - EXTRA_LINK_ARGS = ['/LTCG', '/OPT:REF', 'Advapi32.lib', 'Kernel32.lib'] - if DEBUG: - EXTRA_LINK_ARGS += ['-debug'] - EXTRA_COMPILE_ARGS += ["-Zi", "/Od"] + # 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')] + # Required defined for DSFMT size and to allow it to detect SSE2 using + # config file information DSFMT_DEFS = [('DSFMT_MEXP', '19937'), ("HAVE_NPY_CONFIG_H", "1")] - INTEL_LIKE = any([val in k.lower() for k in platform.uname() - for val in ('x86', 'i686', 'i386', 'amd64')]) - if os.name == 'nt': - EXTRA_COMPILE_ARGS += ['/wd4146', '/GL'] - if struct.calcsize('P') < 8: - EXTRA_COMPILE_ARGS += ['/arch:SSE2'] - elif INTEL_LIKE: - EXTRA_COMPILE_ARGS += ['-msse2'] config.add_extension('entropy', - sources=['entropy.c', 'src/entropy/entropy.c'], - 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, - ) + 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, + ) config.add_extension('dsfmt', - sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', - 'src/dsfmt/dSFMT-jump.c', - 'src/aligned_malloc/aligned_malloc.c'], - include_dirs=['.', 'src', join('src', 'dsfmt')], - libraries=EXTRA_LIBRARIES, - extra_compile_args=EXTRA_COMPILE_ARGS, - extra_link_args=EXTRA_LINK_ARGS, - depends=[join('src', 'dsfmt', 'dsfmt.h'), - 'dsfmt.pyx', - ], - define_macros=defs + DSFMT_DEFS, - ) + sources=['dsfmt.c', 'src/dsfmt/dSFMT.c', + 'src/dsfmt/dSFMT-jump.c', + 'src/aligned_malloc/aligned_malloc.c'], + include_dirs=['.', 'src', join('src', 'dsfmt')], + libraries=EXTRA_LIBRARIES, + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, + depends=[join('src', 'dsfmt', 'dsfmt.h'), + 'dsfmt.pyx', + ], + define_macros=defs + DSFMT_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, - ) + 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', 'threefry', 'xoshiro256', 'xoshiro512']: # gen.pyx, src/gen/gen.c 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], - define_macros=defs, - ) + 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], + define_macros=defs, + ) for gen in ['common']: # 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], - define_macros=defs, - ) + 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], + define_macros=defs, + ) for gen in ['generator', 'bounded_integers']: # gen.pyx, src/distributions/distributions.c config.add_extension(gen, - sources=['{0}.c'.format(gen), - join('src', 'distributions', - 'distributions.c')], - 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, - ) + sources=['{0}.c'.format(gen), + join('src', 'distributions', + 'distributions.c')], + 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', - sources=['mtrand.c', - 'src/legacy/distributions-boxmuller.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 + DSFMT_DEFS + LEGACY_DEFS, - ) + sources=['mtrand.c', + 'src/legacy/distributions-boxmuller.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 + DSFMT_DEFS + LEGACY_DEFS, + ) return config + if __name__ == '__main__': from numpy.distutils.core import setup + setup(configuration=configuration) From 58c0e72854c3f79d3d165d74f2dc721815a38b57 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 24 May 2019 10:41:58 +0100 Subject: [PATCH 135/138] Revert "MAINT: Implement API changes for randomgen-derived code" This reverts commit 17e0070df93f4262908f884dca4b08cb7d0bba7f. --- benchmarks/benchmarks/bench_random.py | 8 +- .../reference/random/bit_generators/index.rst | 8 +- .../reference/random/bit_generators/pcg32.rst | 34 + .../reference/random/bit_generators/pcg64.rst | 34 + doc/source/reference/random/index.rst | 1 + doc/source/reference/random/legacy.rst | 4 +- .../reference/random/multithreading.rst | 18 +- doc/source/reference/random/parallel.rst | 29 +- doc/source/reference/random/performance.py | 38 +- doc/source/reference/random/performance.rst | 68 +- numpy/random/__init__.py | 6 +- numpy/random/_pickle.py | 16 +- numpy/random/pcg32.pyx | 392 +++ numpy/random/pcg64.pyx | 431 ++++ numpy/random/setup.py | 10 +- numpy/random/src/pcg32/LICENSE.md | 22 + numpy/random/src/pcg32/pcg-advance-64.c | 62 + numpy/random/src/pcg32/pcg32-test-data-gen.c | 59 + numpy/random/src/pcg32/pcg32.c | 30 + numpy/random/src/pcg32/pcg32.h | 86 + numpy/random/src/pcg32/pcg_variants.h | 2210 +++++++++++++++++ numpy/random/src/pcg64/LICENSE.md | 22 + numpy/random/src/pcg64/pcg64-benchmark.c | 42 + numpy/random/src/pcg64/pcg64-test-data-gen.c | 73 + numpy/random/src/pcg64/pcg64.c | 185 ++ numpy/random/src/pcg64/pcg64.h | 262 ++ numpy/random/src/pcg64/pcg64.orig.c | 11 + numpy/random/src/pcg64/pcg64.orig.h | 2025 +++++++++++++++ numpy/random/tests/data/pcg32-testset-1.csv | 1001 ++++++++ numpy/random/tests/data/pcg32-testset-2.csv | 1001 ++++++++ numpy/random/tests/data/pcg64-testset-1.csv | 1001 ++++++++ numpy/random/tests/data/pcg64-testset-2.csv | 1001 ++++++++ numpy/random/tests/test_direct.py | 52 +- numpy/random/tests/test_smoke.py | 52 +- numpy/random/xoshiro256.pyx | 3 +- numpy/random/xoshiro512.pyx | 2 +- 36 files changed, 10205 insertions(+), 94 deletions(-) create mode 100644 doc/source/reference/random/bit_generators/pcg32.rst create mode 100644 doc/source/reference/random/bit_generators/pcg64.rst create mode 100644 numpy/random/pcg32.pyx create mode 100644 numpy/random/pcg64.pyx create mode 100644 numpy/random/src/pcg32/LICENSE.md create mode 100644 numpy/random/src/pcg32/pcg-advance-64.c create mode 100644 numpy/random/src/pcg32/pcg32-test-data-gen.c create mode 100644 numpy/random/src/pcg32/pcg32.c create mode 100644 numpy/random/src/pcg32/pcg32.h create mode 100644 numpy/random/src/pcg32/pcg_variants.h create mode 100644 numpy/random/src/pcg64/LICENSE.md create mode 100644 numpy/random/src/pcg64/pcg64-benchmark.c create mode 100644 numpy/random/src/pcg64/pcg64-test-data-gen.c create mode 100644 numpy/random/src/pcg64/pcg64.c create mode 100644 numpy/random/src/pcg64/pcg64.h create mode 100644 numpy/random/src/pcg64/pcg64.orig.c create mode 100644 numpy/random/src/pcg64/pcg64.orig.h create mode 100644 numpy/random/tests/data/pcg32-testset-1.csv create mode 100644 numpy/random/tests/data/pcg32-testset-2.csv create mode 100644 numpy/random/tests/data/pcg64-testset-1.csv create mode 100644 numpy/random/tests/data/pcg64-testset-2.csv diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index c0bf42e2ef50..044986029080 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -86,8 +86,8 @@ def time_permutation_int(self): class RNG(Benchmark): param_names = ['rng'] - params = ['DSFMT', 'MT19937', 'Xoshiro256', 'Xoshiro512', - 'Philox', 'ThreeFry', 'numpy'] + params = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoshiro256', + 'Xoshiro512', 'Philox', 'ThreeFry', 'numpy'] def setup(self, brng): if brng == 'numpy': @@ -128,8 +128,8 @@ class Bounded(Benchmark): u32 = np.uint32 u64 = np.uint64 param_names = ['rng', 'dt_max'] - params = [['DSFMT', 'MT19937','Xoshiro256', 'Xoshiro512', - 'Philox', 'ThreeFry', 'numpy'], + params = [['DSFMT', 'PCG64', 'PCG32', 'MT19937','Xoshiro256', + 'Xoshiro512', 'Philox', 'ThreeFry', 'numpy'], [[u8, 95], [u8, 64], # Worst case for legacy [u8, 127], # Best case for legacy diff --git a/doc/source/reference/random/bit_generators/index.rst b/doc/source/reference/random/bit_generators/index.rst index 5fcb6ce37307..3a9294bfb782 100644 --- a/doc/source/reference/random/bit_generators/index.rst +++ b/doc/source/reference/random/bit_generators/index.rst @@ -5,11 +5,11 @@ Bit Generators .. currentmodule:: numpy.random -The random values produced by :class:`~Generator` +The random values produced by :class:`~Generator` orignate in a BitGenerator. The BitGenerators do not directly provide random numbers and only contains methods used for seeding, getting or -setting the state, jumping or advancing the state, and for accessing -low-level wrappers for consumption by code that can efficiently +setting the state, jumping or advancing the state, and for accessing +low-level wrappers for consumption by code that can efficiently access the functions provided, e.g., `numba `_. Stable RNGs @@ -20,6 +20,8 @@ Stable RNGs DSFMT MT19937 + PCG32 + PCG64 Philox ThreeFry Xoshiro256** diff --git a/doc/source/reference/random/bit_generators/pcg32.rst b/doc/source/reference/random/bit_generators/pcg32.rst new file mode 100644 index 000000000000..faaccaf9bb91 --- /dev/null +++ b/doc/source/reference/random/bit_generators/pcg32.rst @@ -0,0 +1,34 @@ +Parallel Congruent Generator (32-bit, PCG32) +-------------------------------------------- + +.. module:: numpy.random.pcg32 + +.. currentmodule:: numpy.random.pcg32 + +.. autoclass:: PCG32 + :exclude-members: + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~PCG32.seed + ~PCG32.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~PCG32.advance + ~PCG32.jumped + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~PCG32.cffi + ~PCG32.ctypes diff --git a/doc/source/reference/random/bit_generators/pcg64.rst b/doc/source/reference/random/bit_generators/pcg64.rst new file mode 100644 index 000000000000..fa719cea4890 --- /dev/null +++ b/doc/source/reference/random/bit_generators/pcg64.rst @@ -0,0 +1,34 @@ +Parallel Congruent Generator (64-bit, PCG64) +-------------------------------------------- + +.. module:: numpy.random.pcg64 + +.. currentmodule:: numpy.random.pcg64 + +.. autoclass:: PCG64 + :exclude-members: + +Seeding and State +================= + +.. autosummary:: + :toctree: generated/ + + ~PCG64.seed + ~PCG64.state + +Parallel generation +=================== +.. autosummary:: + :toctree: generated/ + + ~PCG64.advance + ~PCG64.jumped + +Extending +========= +.. autosummary:: + :toctree: generated/ + + ~PCG64.cffi + ~PCG64.ctypes diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst index 45b5ed2c00f6..0b81457355e7 100644 --- a/doc/source/reference/random/index.rst +++ b/doc/source/reference/random/index.rst @@ -168,6 +168,7 @@ The included BitGenerators are: `Random123`_ page for more details about this class of bit generators. .. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ +.. _`PCG author's page`: http://www.pcg-random.org/ .. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/ .. _`Random123`: https://www.deshawresearch.com/resources_random123.html diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst index c5b92f1bb54a..d9391e9e2bf1 100644 --- a/doc/source/reference/random/legacy.rst +++ b/doc/source/reference/random/legacy.rst @@ -19,8 +19,8 @@ are produced in pairs. It is important to use .. warning:: :class:`~randomgen.legacy.LegacyGenerator` only contains functions - that have changed. Since it does not contain other functions, it - is not direclty possible to replace :class:`~numpy.random.RandomState`. + that have changed. Since it does not contain other functions, it + is not directly possible to replace :class:`~numpy.random.RandomState`. In order to full replace :class:`~numpy.random.RandomState`, it is necessary to use both :class:`~randomgen.legacy.LegacyGenerator` and :class:`~randomgen.generator.RandomGenerator` both driven diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst index 871425e6d129..7ce90af99fca 100644 --- a/doc/source/reference/random/multithreading.rst +++ b/doc/source/reference/random/multithreading.rst @@ -21,14 +21,14 @@ seed will produce the same outputs. import multiprocessing import concurrent.futures import numpy as np - + class MultithreadedRNG(object): def __init__(self, n, seed=None, threads=None): rg = Xoshiro256(seed) if threads is None: threads = multiprocessing.cpu_count() self.threads = threads - + self._random_generators = [rg] last_rg = rg for _ in range(0, threads-1): @@ -40,21 +40,21 @@ seed will produce the same outputs. self.executor = concurrent.futures.ThreadPoolExecutor(threads) self.values = np.empty(n) self.step = np.ceil(n / threads).astype(np.int) - + def fill(self): def _fill(random_state, out, first, last): random_state.standard_normal(out=out[first:last]) - + futures = {} for i in range(self.threads): - args = (_fill, + args = (_fill, self._random_generators[i], - self.values, - i * self.step, + self.values, + i * self.step, (i + 1) * self.step) futures[self.executor.submit(*args)] = i concurrent.futures.wait(futures) - + def __del__(self): self.executor.shutdown(False) @@ -80,7 +80,7 @@ the time required to generate using a single thread. In [4]: print(mrng.threads) ...: %timeit mrng.fill() - + 4 32.8 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst index 40f0bce63819..ffbaea62b51b 100644 --- a/doc/source/reference/random/parallel.rst +++ b/doc/source/reference/random/parallel.rst @@ -12,20 +12,20 @@ or distributed). Independent Streams ------------------- -:class:`~threefry.ThreeFry` and :class:`~philox.Philox` support independent -streams. This example shows how many streams can be created by passing in -different index values in the second input while using the same seed in the -first. +:class:`~pcg64.PCG64`, :class:`~threefry.ThreeFry` +and :class:`~philox.Philox` support independent streams. This +example shows how many streams can be created by passing in different index +values in the second input while using the same seed in the first. .. code-block:: python from numpy.random.entropy import random_entropy - from numpy.random import ThreeFry + from numpy.random import PCG64 entropy = random_entropy(4) # 128-bit number as a seed seed = sum([int(entropy[i]) * 2 ** (32 * i) for i in range(4)]) - streams = [ThreeFry(seed, stream) for stream in range(10)] + streams = [PCG64(seed, stream) for stream in range(10)] :class:`~philox.Philox` and :class:`~threefry.ThreeFry` are @@ -68,6 +68,8 @@ are listed below. +-----------------+-------------------------+-------------------------+-------------------------+ | MT19937 | :math:`2^{19937}` | :math:`2^{128}` | 32 | +-----------------+-------------------------+-------------------------+-------------------------+ +| PCG64 | :math:`2^{128}` | :math:`2^{64}` | 64 | ++-----------------+-------------------------+-------------------------+-------------------------+ | Philox | :math:`2^{256}` | :math:`2^{128}` | 64 | +-----------------+-------------------------+-------------------------+-------------------------+ | ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 | @@ -96,8 +98,9 @@ overlap. Advance ******* ``advance`` can be used to jump the state an arbitrary number of steps, and so -is a more general approach than ``jumped``. :class:`~threefry.ThreeFry` and -:class:`~philox.Philox` support ``advance``, and since these also support +is a more general approach than ``jumped``. :class:`~pcg64.PCG64`, +:class:`~threefry.ThreeFry` and :class:`~philox.Philox` +support ``advance``, and since these also support independent streams, it is not usually necessary to use ``advance``. Advancing a BitGenerator updates the underlying state as-if a given number of @@ -116,21 +119,21 @@ This occurs for two reasons: Advancing the BitGenerator state resets any pre-computed random numbers. This is required to ensure exact reproducibility. -This example uses ``advance`` to advance a :class:`~threefry.ThreeFry` +This example uses ``advance`` to advance a :class:`~pcg64.PCG64` generator 2 ** 127 steps to set a sequence of random number generators. .. code-block:: python - from numpy.random import ThreeFry - bit_generator = ThreeFry() - bit_generator_copy = ThreeFry() + from numpy.random import PCG64 + bit_generator = PCG64() + bit_generator_copy = PCG64() bit_generator_copy.state = bit_generator.state advance = 2**127 bit_generators = [bit_generator] for _ in range(9): bit_generator_copy.advance(advance) - bit_generator = ThreeFry() + bit_generator = PCG64() bit_generator.state = bit_generator_copy.state bit_generators.append(bit_generator) diff --git a/doc/source/reference/random/performance.py b/doc/source/reference/random/performance.py index bbf17b1d0aef..54165226eb36 100644 --- a/doc/source/reference/random/performance.py +++ b/doc/source/reference/random/performance.py @@ -1,23 +1,25 @@ from collections import OrderedDict from timeit import repeat -import numpy as np import pandas as pd -from numpy.random import MT19937, DSFMT, ThreeFry, Philox, Xoshiro256, \ - Xoshiro512 +import numpy as np +from numpy.random import MT19937, DSFMT, ThreeFry, PCG64, Philox, \ + Xoshiro256, Xoshiro512 -PRNGS = [DSFMT, MT19937, Philox, ThreeFry, Xoshiro256, Xoshiro512] +PRNGS = [DSFMT, MT19937, PCG64, Philox, ThreeFry, Xoshiro256, Xoshiro512] -funcs = {'32-bit Unsigned Ints': 'integers(0, 2**32,size=1000000, dtype="uint32")', - '64-bit Unsigned Ints': 'integers(0, 2**64,size=1000000, dtype="uint64")', - 'Uniforms': 'random(size=1000000)', - 'Normals': 'standard_normal(size=1000000)', - 'Exponentials': 'standard_exponential(size=1000000)', - 'Gammas': 'standard_gamma(3.0,size=1000000)', - 'Binomials': 'binomial(9, .1, size=1000000)', - 'Laplaces': 'laplace(size=1000000)', - 'Poissons': 'poisson(3.0, size=1000000)', } +funcs = OrderedDict() +integers = 'integers(0, 2**{bits},size=1000000, dtype="uint{bits}")' +funcs['32-bit Unsigned Ints'] = integers.format(bits=32) +funcs['64-bit Unsigned Ints'] = integers.format(bits=64) +funcs['Uniforms'] = 'random(size=1000000)' +funcs['Normals'] = 'standard_normal(size=1000000)' +funcs['Exponentials'] = 'standard_exponential(size=1000000)' +funcs['Gammas'] = 'standard_gamma(3.0,size=1000000)' +funcs['Binomials'] = 'binomial(9, .1, size=1000000)' +funcs['Laplaces'] = 'laplace(size=1000000)' +funcs['Poissons'] = 'poisson(3.0, size=1000000)' setup = """ from numpy.random import {prng}, Generator @@ -40,7 +42,7 @@ npfuncs = OrderedDict() npfuncs.update(funcs) npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)' -npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)' +npfuncs['64-bit Unsigned Ints'] = 'randint(2**64,dtype="uint64",size=1000000)' setup = """ from numpy.random import RandomState rg = RandomState() @@ -51,7 +53,7 @@ setup.format(prng=prng().__class__.__name__), number=1, repeat=3) col[key] = 1000 * min(t) -table['NumPy'] = pd.Series(col) +table['RandomState'] = pd.Series(col) table = pd.DataFrame(table) table = table.reindex(table.mean(1).sort_values().index) @@ -59,10 +61,12 @@ table = table.T table = table.reindex(order) table = table.T +table = table.reindex([k for k in funcs], axis=0) print(table.to_csv(float_format='%0.1f')) -rel = table.loc[:, ['NumPy']].values @ np.ones((1, table.shape[1])) / table -rel.pop(rel.columns[0]) +rel = table.loc[:, ['RandomState']].values @ np.ones( + (1, table.shape[1])) / table +rel.pop('RandomState') rel = rel.T rel['Overall'] = np.exp(np.log(rel).mean(1)) rel *= 100 diff --git a/doc/source/reference/random/performance.rst b/doc/source/reference/random/performance.rst index 395744eb8afd..82efdab60a78 100644 --- a/doc/source/reference/random/performance.rst +++ b/doc/source/reference/random/performance.rst @@ -7,12 +7,13 @@ Performance Recommendation ************** -The recommended generator for single use is -:class:`~.xoshiro256.Xoshiro256`. The recommended generator -for use in large-scale parallel applications is +The recommended generator for single use is :class:`~.xoshiro256.Xoshiro256`. +The recommended generator for use in large-scale parallel applications is :class:`~.xoshiro512.Xoshiro512` where the `jumped` method is used to advance the state. For very large scale applications -- requiring 1,000+ independent -streams -- :class:`~.philox.Philox` is the best choice. +streams -- is the best choice. For very large scale applications -- requiring +1,000+ independent streams, :class:`~pcg64.PCG64` or :class:`~.philox.Philox` +are the best choices. Timings ******* @@ -26,24 +27,27 @@ Integer performance has a similar ordering although `dSFMT` is slower since it generates 53-bit floating point values rather than integer values. The pattern is similar for other, more complex generators. The normal -performance of NumPy's MT19937 is much lower than the other since it -uses the Box-Muller transformation rather than the Ziggurat generator. The -performance gap for Exponentials is also large due to the cost of computing -the log function to invert the CDF. +performance of the legacy :class:`~mtrand.RandomState` generator is much +lower than the other since it uses the Box-Muller transformation rather +than the Ziggurat generator. The performance gap for Exponentials is also +large due to the cost of computing the log function to invert the CDF. +The column labeled MT19973 is used the same 32-bit generator as +:class:`~mtrand.RandomState` but produces random values using +:class:`~generator.Generator`. .. csv-table:: - :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,NumPy,ThreeFry - :widths: 14,14,14,14,14,14,14,14 + :header: ,Xoshiro256**,Xoshiro512**,DSFMT,PCG64,MT19937,Philox,RandomState,ThreeFry + :widths: 14,14,14,14,14,14,14,14,14 - 32-bit Unsigned Ints,2.6,2.9,3.4,3.2,5.0,3.3,7.6 - 64-bit Unsigned Ints,3.1,4.0,5.6,5.7,6.6,8.1,13.4 - Uniforms,3.7,4.2,3.2,7.4,9.1,8.9,13.5 - Exponentials,4.3,5.3,7.3,8.2,9.7,42.4,14.9 - Normals,8.2,8.9,11.7,13.4,15.0,37.3,18.6 - Binomials,20.0,20.8,19.8,26.4,28.2,26.6,31.0 - Gammas,26.4,28.7,30.4,37.1,38.8,62.9,49.0 - Laplaces,40.2,40.0,39.4,48.7,51.2,47.4,51.4 - Poissons,48.8,51.6,47.8,73.6,82.3,74.0,90.6 + 32-bit Unsigned Ints,2.6,2.9,3.5,3.2,3.3,4.8,3.2,7.6 + 64-bit Unsigned Ints,3.3,4.3,5.7,4.8,5.7,6.9,5.7,12.8 + Uniforms,3.4,4.0,3.2,5.0,7.3,8.0,7.3,12.8 + Normals,7.9,9.0,11.8,11.3,13.0,13.7,34.4,18.1 + Exponentials,4.7,5.2,7.4,6.7,7.9,8.6,40.3,14.7 + Gammas,29.1,27.5,28.5,30.6,34.2,35.1,58.1,47.6 + Binomials,22.7,23.1,21.1,25.7,27.7,28.4,25.9,32.1 + Laplaces,38.5,38.1,36.9,41.1,44.5,45.4,46.9,50.2 + Poissons,46.9,50.9,46.4,58.1,68.4,70.2,86.0,88.2 The next table presents the performance in percentage relative to values @@ -51,19 +55,19 @@ generated by the legagy generator, `RandomState(MT19937())`. The overall performance was computed using a geometric mean. .. csv-table:: - :header: ,Xoshiro256**,Xoshiro512**,DSFMT,MT19937,Philox,ThreeFry - :widths: 14,14,14,14,14,14,14 - - 32-bit Unsigned Ints,129,113,98,103,66,44 - 64-bit Unsigned Ints,258,202,145,142,122,61 - Uniforms,244,214,283,121,98,66 - Exponentials,981,796,580,518,436,285 - Normals,453,417,319,278,249,200 - Binomials,133,128,134,101,94,86 - Gammas,238,219,207,170,162,129 - Laplaces,118,118,120,97,93,92 - Poissons,152,144,155,101,90,82 - Overall,233,209,194,152,130,98 + :header: ,Xoshiro256**,Xoshiro256**,DSFMT,PCG64,MT19937,Philox,ThreeFry + :widths: 14,14,14,14,14,14,14,14 + + 32-bit Unsigned Ints,124,113,93,100,99,67,43 + 64-bit Unsigned Ints,174,133,100,118,100,83,44 + Uniforms,212,181,229,147,100,91,57 + Normals,438,382,291,304,264,252,190 + Exponentials,851,770,547,601,512,467,275 + Gammas,200,212,204,190,170,166,122 + Binomials,114,112,123,101,93,91,81 + Laplaces,122,123,127,114,105,103,93 + Poissons,183,169,185,148,126,123,98 + Overall,212,194,180,167,145,131,93 .. note:: diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 51a2952f1cea..ade91283992c 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -99,6 +99,8 @@ --------------------------------------------- --- MT19937 DSFMT +PCG32 +PCG64 Philox ThreeFry Xoshiro256 @@ -163,13 +165,15 @@ from .dsfmt import DSFMT from .generator import Generator from .mt19937 import MT19937 +from .pcg32 import PCG32 +from .pcg64 import PCG64 from .philox import Philox from .threefry import ThreeFry from .xoshiro256 import Xoshiro256 from .xoshiro512 import Xoshiro512 from .mtrand import RandomState -__all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox', +__all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox','PCG64', 'PCG32', 'ThreeFry', 'Xoshiro256', 'Xoshiro512', 'RandomState'] # Some aliases: diff --git a/numpy/random/_pickle.py b/numpy/random/_pickle.py index 71a6d8bdd11a..cc624a1e818e 100644 --- a/numpy/random/_pickle.py +++ b/numpy/random/_pickle.py @@ -1,6 +1,8 @@ from .mtrand import RandomState from .philox import Philox from .threefry import ThreeFry +from .pcg32 import PCG32 +from .pcg64 import PCG64 from .xoshiro256 import Xoshiro256 from .xoshiro512 import Xoshiro512 @@ -9,12 +11,14 @@ from .mt19937 import MT19937 BitGenerators = {'MT19937': MT19937, - 'DSFMT': DSFMT, - 'Philox': Philox, - 'ThreeFry': ThreeFry, - 'Xoshiro256': Xoshiro256, - 'Xoshiro512': Xoshiro512, - } + 'DSFMT': DSFMT, + 'PCG32': PCG32, + 'PCG64': PCG64, + 'Philox': Philox, + 'ThreeFry': ThreeFry, + 'Xoshiro256': Xoshiro256, + 'Xoshiro512': Xoshiro512 + } def __generator_ctor(bit_generator_name='mt19937'): diff --git a/numpy/random/pcg32.pyx b/numpy/random/pcg32.pyx new file mode 100644 index 000000000000..b57f8e04e805 --- /dev/null +++ b/numpy/random/pcg32.pyx @@ -0,0 +1,392 @@ +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 .common cimport * +from .distributions cimport bitgen_t +from .entropy import random_entropy + +__all__ = ['PCG32'] + +np.import_array() + +cdef extern from "src/pcg32/pcg32.h": + + cdef struct pcg_state_setseq_64: + uint64_t state + uint64_t inc + + ctypedef pcg_state_setseq_64 pcg32_random_t + + struct s_pcg32_state: + pcg32_random_t *pcg_state + + ctypedef s_pcg32_state pcg32_state + + uint64_t pcg32_next64(pcg32_state *state) nogil + uint32_t pcg32_next32(pcg32_state *state) nogil + double pcg32_next_double(pcg32_state *state) nogil + void pcg32_jump(pcg32_state *state) + void pcg32_advance_state(pcg32_state *state, uint64_t step) + void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) + +cdef uint64_t pcg32_uint64(void* st) nogil: + return pcg32_next64(st) + +cdef uint32_t pcg32_uint32(void *st) nogil: + return pcg32_next32( st) + +cdef double pcg32_double(void* st) nogil: + return pcg32_next_double(st) + +cdef uint64_t pcg32_raw(void* st) nogil: + return pcg32_next32( st) + + +cdef class PCG32: + u""" + PCG32(seed=None, inc=0) + + Container for the PCG-32 pseudo-random number generator. + + Parameters + ---------- + seed : {None, long}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**64] or ``None`` (the default). + If `seed` is ``None``, then ``PCG32`` will try to read data + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + inc : {None, int}, optional + Stream to return. + Can be an integer in [0, 2**64] or ``None`` (the default). If `inc` is + ``None``, then 0 is used. Can be used with the same seed to + produce multiple streams using other values of inc. + + 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 + ----- + PCG-32 is a 64-bit implementation of O'Neill's permutation congruential + generator ([1]_, [2]_). PCG-32 has a period of :math:`2^{64}` and supports + advancing an arbitrary number of steps as well as :math:`2^{63}` streams. + + ``PCG32`` 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 advance to advance the RNG an arbitrary number of + steps. The state of the PCG-32 PRNG is represented by 2 64-bit unsigned + integers. + + See ``PCG64`` for a similar implementation with a smaller period. + + **State and Seeding** + + The ``PCG32`` state vector consists of 2 unsigned 64-bit values. + ``PCG32`` is seeded using a single 64-bit unsigned integer. + In addition, a second 64-bit unsigned integer is used to set the stream. + + **Parallel Features** + + ``PCG32`` can be used in parallel applications in one of two ways. + The preferable method is to use sub-streams, which are generated by using the + same value of ``seed`` and incrementing the second value, ``inc``. + + >>> from numpy.random import Generator, PCG32 + >>> rg = [Generator(PCG32(1234, i + 1)) for i in range(10)] + + The alternative method is to call ``advance`` with a different value on + each instance to produce non-overlapping sequences. + + >>> rg = [Generator(PCG32(1234, i + 1)) for i in range(10)] + >>> for i in range(10): + ... rg[i].bit_generator.advance(i * 2**32) + + **Compatibility Guarantee** + + ``PCG32`` 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" + """ + cdef pcg32_state rng_state + cdef pcg32_random_t pcg32_random_state + cdef bitgen_t _bitgen + cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef public object lock + + def __init__(self, seed=None, inc=0): + self.rng_state.pcg_state = &self.pcg32_random_state + self.seed(seed, inc) + self.lock = Lock() + + self._bitgen.state = &self.rng_state + self._bitgen.next_uint64 = &pcg32_uint64 + self._bitgen.next_uint32 = &pcg32_uint32 + self._bitgen.next_double = &pcg32_double + self._bitgen.next_raw = &pcg32_raw + + self._ctypes = None + self._cffi = None + + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) + + # 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 + + 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'): + return benchmark(&self._bitgen, self.lock, cnt, method) + + def seed(self, seed=None, inc=0): + """ + seed(seed=None, inc=0) + + Seed the generator. + + This method is called at initialization. It can be called again to + re-seed the generator. + + Parameters + ---------- + seed : int, optional + Seed for ``PCG64``. Integer between 0 and 2**64-1. + inc : int, optional + Increment to use for PCG stream. Integer between 0 and 2**64-1. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + ub = 2 ** 64 + if seed is None: + try: + seed = random_entropy(2) + except RuntimeError: + seed = random_entropy(2, 'fallback') + seed = seed.view(np.uint64).squeeze() + else: + err_msg = 'seed must be a scalar integer between 0 and ' \ + '{ub}'.format(ub=ub) + if not np.isscalar(seed): + raise TypeError(err_msg) + if int(seed) != seed: + raise TypeError(err_msg) + if seed < 0 or seed > ub: + raise ValueError(err_msg) + + if not np.isscalar(inc): + raise TypeError('inc must be a scalar integer between 0 ' + 'and {ub}'.format(ub=ub)) + if inc < 0 or inc > ub or int(inc) != inc: + raise ValueError('inc must be a scalar integer between 0 ' + 'and {ub}'.format(ub=ub)) + + pcg32_set_seed(&self.rng_state, seed, inc) + + 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 * 2**32) + + def jumped(self, iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(32 * iter) random numbers have been generated. + + Parameters + ---------- + iter : integer, positive + Number of times to jump the state of the bit generator returned + + Returns + ------- + bit_generator : PCG32 + New instance of generator jumped iter times + """ + cdef PCG32 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + 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 + """ + return {'bit_generator': self.__class__.__name__, + 'state': {'state': self.rng_state.pcg_state.state, + 'inc': self.rng_state.pcg_state.inc}} + + @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__)) + self.rng_state.pcg_state.state = value['state']['state'] + self.rng_state.pcg_state.inc = value['state']['inc'] + + 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 : PCG32 + 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. + """ + pcg32_advance_state(&self.rng_state, delta) + return self + + @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 not None: + return self._cffi + self._cffi = prepare_cffi(&self._bitgen) + return self._cffi diff --git a/numpy/random/pcg64.pyx b/numpy/random/pcg64.pyx new file mode 100644 index 000000000000..7610fb203a73 --- /dev/null +++ b/numpy/random/pcg64.pyx @@ -0,0 +1,431 @@ +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 .common cimport * +from .distributions cimport bitgen_t +from .entropy import random_entropy + +__all__ = ['PCG64'] + +np.import_array() + +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(st) + +cdef uint32_t pcg64_uint32(void *st) nogil: + return pcg64_next32( st) + +cdef double pcg64_double(void* st) nogil: + return uint64_to_double(pcg64_next64(st)) + + +cdef class PCG64: + u""" + PCG64(seed=None, inc=0) + + Container for the PCG-64 pseudo-random number generator. + + Parameters + ---------- + seed : {None, long}, optional + Random seed initializing the pseudo-random number generator. + Can be an integer in [0, 2**128] or ``None`` (the default). + If `seed` is ``None``, then ``PCG64`` will try to read data + from ``/dev/urandom`` (or the Windows analog) if available. If + unavailable, a 64-bit hash of the time and process ID is used. + inc : {None, int}, optional + Stream to return. + Can be an integer in [0, 2**128] or ``None`` (the default). If `inc` is + ``None``, then 0 is used. Can be used with the same seed to + produce multiple streams using other values of inc. + + 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 + ----- + 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. + + ``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 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. + + See ``PCG32`` for a similar implementation with a smaller period. + + **State and Seeding** + + The ``PCG64`` state vector consists of 2 unsigned 128-bit values, + which are represented externally as Python ints. + ``PCG64`` is seeded using a single 128-bit unsigned integer. + In addition, a second 128-bit unsigned integer is used to set the stream. + + **Parallel Features** + + ``PCG64`` can be used in parallel applications in one of two ways. + The preferable method is to use sub-streams, which are generated by using the + same value of ``seed`` and incrementing the second value, ``inc``. + + >>> from numpy.random import Generator, PCG64 + >>> rg = [Generator(PCG64(1234, i + 1)) for i in range(10)] + + The alternative method is to call ``advance`` with a different value on + each instance to produce non-overlapping sequences. + + >>> rg = [Generator(PCG64(1234, i + 1)) for i in range(10)] + >>> for i in range(10): + ... rg[i].bit_generator.advance(i * 2**64) + + **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" + """ + cdef pcg64_state rng_state + cdef pcg64_random_t pcg64_random_state + cdef bitgen_t _bitgen + cdef public object capsule + cdef object _ctypes + cdef object _cffi + cdef public object lock + + def __init__(self, seed=None, inc=0): + self.rng_state.pcg_state = &self.pcg64_random_state + self.seed(seed, inc) + self.lock = Lock() + + self._bitgen.state = &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 + + self._ctypes = None + self._cffi = None + + cdef const char *name = "BitGenerator" + self.capsule = PyCapsule_New(&self._bitgen, name, NULL) + + # 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 + + cdef _reset_state_variables(self): + self.rng_state.has_uint32 = 0 + self.rng_state.uinteger = 0 + + 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'): + return benchmark(&self._bitgen, self.lock, cnt, method) + + def seed(self, seed=None, inc=0): + """ + seed(seed=None, inc=0) + + Seed the generator. + + This method is called at initialization. It can be called again to + re-seed the generator. + + Parameters + ---------- + seed : int, optional + Seed for ``PCG64``. Integer between 0 and 2**128-1. + inc : int, optional + Increment to use for PCG stream. Integer between 0 and 2**128-1. + + Raises + ------ + ValueError + If seed values are out of range for the PRNG. + """ + cdef np.ndarray _seed, _inc + ub = 2 ** 128 + if seed is None: + try: + _seed = random_entropy(4) + except RuntimeError: + _seed = random_entropy(4, 'fallback') + _seed = _seed.view(np.uint64) + else: + err_msg = 'seed must be a scalar integer between 0 and ' \ + '{ub}'.format(ub=ub) + if not np.isscalar(seed): + raise TypeError(err_msg) + if int(seed) != seed: + raise TypeError(err_msg) + if seed < 0 or seed > ub: + raise ValueError(err_msg) + _seed = np.empty(2, np.uint64) + _seed[0] = int(seed) // 2**64 + _seed[1] = int(seed) % 2**64 + + if not np.isscalar(inc): + raise TypeError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + if inc < 0 or inc > ub or int(inc) != inc: + raise ValueError('inc must be a scalar integer between 0 and {ub}'.format(ub=ub)) + _inc = np.empty(2, np.uint64) + _inc[0] = int(inc) // 2**64 + _inc[1] = int(inc) % 2**64 + + pcg64_set_seed(&self.rng_state, + np.PyArray_DATA(_seed), + np.PyArray_DATA(_inc)) + self._reset_state_variables() + + 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 * 2**64) + + def jumped(self, iter=1): + """ + jumped(iter=1) + + Returns a new bit generator with the state jumped + + The state of the returned big generator is jumped as-if + 2**(64 * iter) random numbers have been generated. + + Parameters + ---------- + iter : 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 + """ + cdef PCG64 bit_generator + + bit_generator = self.__class__() + bit_generator.state = self.state + bit_generator.jump_inplace(iter) + + 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.empty(4, dtype=np.uint64) + pcg64_get_state(&self.rng_state, + 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.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, + 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. + """ + 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, np.PyArray_DATA(d)) + self._reset_state_variables() + return self + + @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 not None: + return self._cffi + self._cffi = prepare_cffi(&self._bitgen) + return self._cffi diff --git a/numpy/random/setup.py b/numpy/random/setup.py index b8b190b09590..b634b5eb0668 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -58,6 +58,10 @@ def generate_libraries(ext, build_dir): # Required defined for DSFMT size and to allow it to detect SSE2 using # config file information DSFMT_DEFS = [('DSFMT_MEXP', '19937'), ("HAVE_NPY_CONFIG_H", "1")] + PCG64_DEFS = [] + if 1 or sys.maxsize < 2 ** 32 or os.name == 'nt': + # Force emulated mode here + PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')] config.add_extension('entropy', sources=['entropy.c', 'src/entropy/entropy.c'] + @@ -97,8 +101,10 @@ def generate_libraries(ext, build_dir): depends=['%s.pyx' % gen], define_macros=defs, ) - for gen in ['philox', 'threefry', 'xoshiro256', 'xoshiro512']: + for gen in ['philox', 'threefry', 'xoshiro256', 'xoshiro512', + 'pcg64', 'pcg32']: # 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)], @@ -107,7 +113,7 @@ def generate_libraries(ext, build_dir): extra_compile_args=EXTRA_COMPILE_ARGS, extra_link_args=EXTRA_LINK_ARGS, depends=['%s.pyx' % gen], - define_macros=defs, + define_macros=_defs, ) for gen in ['common']: # gen.pyx diff --git a/numpy/random/src/pcg32/LICENSE.md b/numpy/random/src/pcg32/LICENSE.md new file mode 100644 index 000000000000..e28ef1a8bb06 --- /dev/null +++ b/numpy/random/src/pcg32/LICENSE.md @@ -0,0 +1,22 @@ +# PCG32 + +## The MIT License + +PCG Random Number Generation for C. + +Copyright 2014 Melissa 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/pcg32/pcg-advance-64.c b/numpy/random/src/pcg32/pcg-advance-64.c new file mode 100644 index 000000000000..8210e75650eb --- /dev/null +++ b/numpy/random/src/pcg32/pcg-advance-64.c @@ -0,0 +1,62 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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. + * + * Repetative C code is derived using C preprocessor metaprogramming + * techniques. + */ + +#include "pcg_variants.h" + +/* 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". + */ + +uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, + uint64_t cur_plus) +{ + uint64_t acc_mult = 1u; + uint64_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; +} + diff --git a/numpy/random/src/pcg32/pcg32-test-data-gen.c b/numpy/random/src/pcg32/pcg32-test-data-gen.c new file mode 100644 index 000000000000..cccaf84b9948 --- /dev/null +++ b/numpy/random/src/pcg32/pcg32-test-data-gen.c @@ -0,0 +1,59 @@ +/* + * Generate testing csv files + * + * + * gcc pcg32-test-data-gen.c pcg32.orig.c ../splitmix64/splitmix64.c -o + * pgc64-test-data-gen + */ + +#include "pcg_variants.h" +#include +#include + +#define N 1000 + +int main() { + pcg32_random_t rng; + uint64_t inc, seed = 0xDEADBEAF; + inc = 0; + int i; + uint64_t store[N]; + pcg32_srandom_r(&rng, seed, inc); + for (i = 0; i < N; i++) { + store[i] = pcg32_random_r(&rng); + } + + FILE *fp; + fp = fopen("pcg32-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); + + seed = 0; + pcg32_srandom_r(&rng, seed, inc); + for (i = 0; i < N; i++) { + store[i] = pcg32_random_r(&rng); + } + fp = fopen("pcg32-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/pcg32/pcg32.c b/numpy/random/src/pcg32/pcg32.c new file mode 100644 index 000000000000..5fbf6759f1a3 --- /dev/null +++ b/numpy/random/src/pcg32/pcg32.c @@ -0,0 +1,30 @@ +#include "pcg32.h" + +extern inline uint64_t pcg32_next64(pcg32_state *state); +extern inline uint32_t pcg32_next32(pcg32_state *state); +extern inline double pcg32_next_double(pcg32_state *state); + +uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, uint64_t cur_mult, + uint64_t cur_plus) { + uint64_t acc_mult, acc_plus; + acc_mult = 1u; + 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; +} + +extern void pcg32_advance_state(pcg32_state *state, uint64_t step) { + pcg32_advance_r(state->pcg_state, step); +} + +extern void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc) { + pcg32_srandom_r(state->pcg_state, seed, inc); +} diff --git a/numpy/random/src/pcg32/pcg32.h b/numpy/random/src/pcg32/pcg32.h new file mode 100644 index 000000000000..32c6b693dd86 --- /dev/null +++ b/numpy/random/src/pcg32/pcg32.h @@ -0,0 +1,86 @@ +#ifndef _RANDOMDGEN__PCG32_H_ +#define _RANDOMDGEN__PCG32_H_ + +#include + +#ifdef _WIN32 +#define inline __forceinline +#endif + +#define PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL + +struct pcg_state_setseq_64 { + uint64_t state; + uint64_t inc; +}; + +static 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 +} + +static inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64 *rng) { + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc; +} + +static inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { + return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u); +} + +static inline uint32_t +pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64 *rng) { + uint64_t oldstate; + oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +static 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); +} + +extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, + uint64_t cur_mult, uint64_t cur_plus); + +static 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); +} + +typedef struct pcg_state_setseq_64 pcg32_random_t; +#define pcg32_random_r pcg_setseq_64_xsh_rr_32_random_r +#define pcg32_srandom_r pcg_setseq_64_srandom_r +#define pcg32_advance_r pcg_setseq_64_advance_r + +typedef struct s_pcg32_state { pcg32_random_t *pcg_state; } pcg32_state; + +static inline uint64_t pcg32_next64(pcg32_state *state) { + return (uint64_t)(pcg32_random_r(state->pcg_state)) << 32 | + pcg32_random_r(state->pcg_state); +} + +static inline uint32_t pcg32_next32(pcg32_state *state) { + return pcg32_random_r(state->pcg_state); +} + +static inline double pcg32_next_double(pcg32_state *state) { + int32_t a = pcg32_random_r(state->pcg_state) >> 5, + b = pcg32_random_r(state->pcg_state) >> 6; + return (a * 67108864.0 + b) / 9007199254740992.0; +} + +void pcg32_advance_state(pcg32_state *state, uint64_t step); +void pcg32_set_seed(pcg32_state *state, uint64_t seed, uint64_t inc); + +#endif diff --git a/numpy/random/src/pcg32/pcg_variants.h b/numpy/random/src/pcg32/pcg_variants.h new file mode 100644 index 000000000000..32daac1ce4f5 --- /dev/null +++ b/numpy/random/src/pcg32/pcg_variants.h @@ -0,0 +1,2210 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * + * 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 + +#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/pcg64/LICENSE.md b/numpy/random/src/pcg64/LICENSE.md new file mode 100644 index 000000000000..7aac7a51c96a --- /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 + +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 000000000000..76f3ec78c300 --- /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 +#include +#include + +#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 000000000000..0c2b079a3e15 --- /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 +#include + +#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 000000000000..c894540290c4 --- /dev/null +++ b/numpy/random/src/pcg64/pcg64.c @@ -0,0 +1,185 @@ +/* + * PCG64 Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * Copyright 2015 Robert Kern + * + * 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 + * + * 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; +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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; +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 + * + */ +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 + * + */ +#if __SIZEOF_INT128__ && !defined(PCG_FORCE_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 000000000000..d4c96ff5ffc0 --- /dev/null +++ b/numpy/random/src/pcg64/pcg64.h @@ -0,0 +1,262 @@ +/* + * PCG64 Random Number Generation for C. + * + * Copyright 2014 Melissa O'Neill + * Copyright 2015 Robert Kern + * + * 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 + * + * 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 + +#ifdef _WIN32 +#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 __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_128 \ + PCG_128BIT_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) +#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) { + return (value >> rot) | (value << ((-rot) & 63)); +} + +#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 & 0x800000000000ULL; + 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); +} + +#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 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_random_r(pcg_state_setseq_128 *rng) { + pcg_setseq_128_step_r(rng); + return pcg_output_xsl_rr_128_64(rng->state); +} + +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 000000000000..07e97e4b6d97 --- /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 000000000000..74be91f31a50 --- /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 + * + * 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 + +#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/tests/data/pcg32-testset-1.csv b/numpy/random/tests/data/pcg32-testset-1.csv new file mode 100644 index 000000000000..6bddc8d5ccc2 --- /dev/null +++ b/numpy/random/tests/data/pcg32-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xbeb77374 +1, 0x75cad014 +2, 0xabc6773e +3, 0xe99a034e +4, 0x1e3f5c6d +5, 0x513d3c5b +6, 0x4a378bad +7, 0xba5b3488 +8, 0x21e96448 +9, 0x5197a3d3 +10, 0x84bbcc90 +11, 0x674fce76 +12, 0xd1dd9879 +13, 0x1625afd4 +14, 0x4bb5e330 +15, 0x3f4b8f74 +16, 0xf0a7c00b +17, 0xecdb92d0 +18, 0xf069232c +19, 0x56dbeaa2 +20, 0x70c62231 +21, 0x6c68e57e +22, 0x3829213c +23, 0x9b8bc5e6 +24, 0x45abd553 +25, 0xf5991ce7 +26, 0xb4aff20a +27, 0x677a5785 +28, 0x108f180d +29, 0x2b3f1001 +30, 0x838fdfcb +31, 0x8ad3c2a0 +32, 0x596268fa +33, 0xee6bcc56 +34, 0x46810af0 +35, 0x1648a587 +36, 0x7265a926 +37, 0xed0f3acc +38, 0x72a1ac0 +39, 0xb3f7109f +40, 0x6ddd75f2 +41, 0xa968127f +42, 0x40df20fd +43, 0xde835b80 +44, 0xe453cd68 +45, 0x26ad68eb +46, 0x23a052d2 +47, 0x17881c5c +48, 0x785d41b9 +49, 0x61b4530a +50, 0x5ee92c84 +51, 0x4cad7358 +52, 0x843db584 +53, 0x3576368b +54, 0x14db6b2b +55, 0xb6e8b042 +56, 0x6323e866 +57, 0x9a709e25 +58, 0xae594bdc +59, 0x4be9ec1b +60, 0x77b4fd05 +61, 0x4421667 +62, 0x24bf98f7 +63, 0xfb202aed +64, 0x2f01b05f +65, 0xac766e69 +66, 0xc1572ce2 +67, 0xb26354d6 +68, 0x4db5f193 +69, 0x41a4609b +70, 0x26bbb4cc +71, 0x676b7438 +72, 0x13b2be7d +73, 0x7df521c4 +74, 0x57f770f3 +75, 0x78a8a8 +76, 0x164d46c6 +77, 0xbb29da20 +78, 0x5c262bf9 +79, 0xfd305d0 +80, 0xb500d90b +81, 0xbb7b4e37 +82, 0x5ba2bbfd +83, 0xa9561043 +84, 0xe175c662 +85, 0x3a5c8eec +86, 0xac5e2184 +87, 0x1e1c7de7 +88, 0x46be092a +89, 0x8b82f5be +90, 0xb1c1b591 +91, 0x6f06d957 +92, 0x1d26dc5c +93, 0x158c57e3 +94, 0x6da1ebf8 +95, 0x74501e60 +96, 0x70587043 +97, 0xa19b90fe +98, 0x7d327dff +99, 0x22dc6b90 +100, 0xf48a9ae6 +101, 0x75eeb769 +102, 0x9cdc12cb +103, 0x7fe2cdc6 +104, 0x4fba8066 +105, 0x1a7a0667 +106, 0xd9289d22 +107, 0x3a045bce +108, 0x60e5f71f +109, 0xd81b35dc +110, 0xceae6194 +111, 0xa032a688 +112, 0x7157b327 +113, 0x61c74c80 +114, 0x2d519c39 +115, 0x5b1a352e +116, 0x5ad266da +117, 0x9118352b +118, 0xdd20b6e1 +119, 0xc0d154fa +120, 0x93bbb9c9 +121, 0x91170de2 +122, 0xa3af5e05 +123, 0x1b19ff2f +124, 0xf814c3bf +125, 0x8914a953 +126, 0x5278efb7 +127, 0x3c96d7bd +128, 0xb5422a7 +129, 0x2aee2619 +130, 0x60c6a90c +131, 0xfbec0e9c +132, 0xef794075 +133, 0xda93d22e +134, 0xb956d02a +135, 0xd97cc49b +136, 0x80737244 +137, 0x7c56a95 +138, 0xa5311355 +139, 0x7dcdd592 +140, 0x92add23e +141, 0xb1ba1317 +142, 0x507e5330 +143, 0x2644b95a +144, 0xa1afa519 +145, 0x596c65c0 +146, 0x6f47dd11 +147, 0xfd2fbada +148, 0x98675d7c +149, 0xb9e21413 +150, 0x8bae5eca +151, 0xe1f50018 +152, 0x7dd08715 +153, 0x36a888e1 +154, 0x7fcd6364 +155, 0xb84c093 +156, 0x18e2d58f +157, 0x19fd21ed +158, 0x3c25e3a3 +159, 0x7a0d833b +160, 0x47525b28 +161, 0xba88474 +162, 0xd108e7da +163, 0x32b06660 +164, 0xbce027b3 +165, 0x96b31787 +166, 0x916ab263 +167, 0xa5fa088 +168, 0x3cb9cd59 +169, 0x7a97051f +170, 0x104b6883 +171, 0x6e08c314 +172, 0x33a4c62c +173, 0x14eb854 +174, 0x873f730a +175, 0x8c3f7224 +176, 0x9a41beeb +177, 0xe4e2ab0a +178, 0xfa89ad0e +179, 0x4aa62ac3 +180, 0xb75dc1bf +181, 0x3f4c5131 +182, 0x3fef0f91 +183, 0xffa06655 +184, 0x417d7d38 +185, 0x1e7734df +186, 0x25685235 +187, 0x33fe5b68 +188, 0x68923f72 +189, 0x5da45ff +190, 0xb871df26 +191, 0xd3ffd8c6 +192, 0x1718d862 +193, 0xe127d844 +194, 0xadcdc48a +195, 0x79ee30cb +196, 0x931a6cba +197, 0x9463c42d +198, 0x9f8d2806 +199, 0xa3695a97 +200, 0xfc9587bc +201, 0xb3943573 +202, 0x50ed8901 +203, 0x6891f33 +204, 0xb7a12dfb +205, 0x1245cf5d +206, 0xbc0f73a7 +207, 0x26cbfeb2 +208, 0x774d8e83 +209, 0xa19e9c1 +210, 0xc147a437 +211, 0xe034f2a3 +212, 0xd288b664 +213, 0xdcd0356d +214, 0x2b695901 +215, 0x3bc31736 +216, 0x4a5b1998 +217, 0x18537410 +218, 0x11b40f35 +219, 0xf16f6f89 +220, 0xe844cffe +221, 0xce026166 +222, 0x3770aaba +223, 0xc62566ee +224, 0x6db2d1f8 +225, 0xe4720b6d +226, 0x68321a69 +227, 0x488539ac +228, 0x5e18ab61 +229, 0xb58e598e +230, 0x6f501a91 +231, 0xc4fd3e8d +232, 0x9faa3631 +233, 0x184366b0 +234, 0xecf74d6a +235, 0x3773d622 +236, 0x382ca536 +237, 0x93451381 +238, 0x9f148ed5 +239, 0x2b66f241 +240, 0xa6807c39 +241, 0xbb087446 +242, 0xa18ba432 +243, 0x8e7a6013 +244, 0xab30278e +245, 0xbf457c78 +246, 0xb24814b1 +247, 0x710f99d5 +248, 0xbcb84762 +249, 0x4913a7e7 +250, 0x90a31a0c +251, 0x6d4b1673 +252, 0x18873994 +253, 0x1efd517a +254, 0x99b499d1 +255, 0x2d488776 +256, 0x1cded201 +257, 0xa53b02e4 +258, 0xcb20d0fd +259, 0x72bfaae3 +260, 0x858c865b +261, 0x2e2d3e96 +262, 0x8bc5b0b9 +263, 0x8980346a +264, 0xa8e47fba +265, 0x2a39fe16 +266, 0x9f34eeeb +267, 0x7baebcc9 +268, 0xbc0b8d74 +269, 0x37373c8 +270, 0xe128cfc4 +271, 0x49cdb150 +272, 0x5965c726 +273, 0xfc326226 +274, 0x53a3e8e +275, 0xa99d89f7 +276, 0x33ac111c +277, 0x143fe678 +278, 0x96212281 +279, 0x6a83bffd +280, 0x529852f7 +281, 0x97fef4 +282, 0x303ce151 +283, 0x4f8c7b83 +284, 0xd5ef9c82 +285, 0xede9d572 +286, 0xc03e2c38 +287, 0x89d7f886 +288, 0x21e998b0 +289, 0x58d505cf +290, 0x5c42089 +291, 0x9a01dcab +292, 0x83d8cc17 +293, 0x7d6aacf +294, 0xa1cbdced +295, 0x47365e25 +296, 0xbb61e976 +297, 0xfeafd0a6 +298, 0x760d82b4 +299, 0x9ffb351d +300, 0x28e19ac0 +301, 0x891131c6 +302, 0xc1656522 +303, 0x4536d90 +304, 0x956b1b84 +305, 0xf9ff54f6 +306, 0xb0050d88 +307, 0x7d7fafa2 +308, 0x430e670b +309, 0x18ad450d +310, 0xd5a1d6b6 +311, 0x390a6da4 +312, 0xc70d557d +313, 0xd8fadb5e +314, 0xfb4b4cb6 +315, 0xce707f8b +316, 0x4c18d350 +317, 0x8dc0d200 +318, 0x228d9e85 +319, 0xd6485ba3 +320, 0x37c4a70a +321, 0x9d7cc5f5 +322, 0x889a9b9 +323, 0x41d2f942 +324, 0x4c13b3bd +325, 0x70e58147 +326, 0x4a0e1270 +327, 0x3cdc1b73 +328, 0x7a4e56f3 +329, 0xd8350406 +330, 0x46068108 +331, 0xfc4da48 +332, 0xf6111245 +333, 0x40a15167 +334, 0x38a591ac +335, 0x3e97e682 +336, 0x5c515d2d +337, 0x45023a37 +338, 0xacb0ed6a +339, 0x899f0ebb +340, 0x2054df01 +341, 0x6d629607 +342, 0x79ced597 +343, 0xba0a3a12 +344, 0xde63b611 +345, 0x228cb776 +346, 0x61f10dba +347, 0x9a1095d3 +348, 0xf08dcb3 +349, 0x88e58009 +350, 0x131880aa +351, 0xc55002ee +352, 0xcf556f47 +353, 0x17b6dd76 +354, 0x6110ba20 +355, 0x74a91935 +356, 0xe83cf9ed +357, 0x3138e936 +358, 0x103bfb72 +359, 0x2084abe4 +360, 0xf3a05dd9 +361, 0x9213f3a4 +362, 0xe7674dd7 +363, 0xcd09d629 +364, 0x260461f2 +365, 0x411c2428 +366, 0xbb5f6f2e +367, 0x6feb8c93 +368, 0x3cde3ece +369, 0x7a424d2c +370, 0x808a0948 +371, 0x653c3fdf +372, 0x26f88849 +373, 0xf540b6ae +374, 0x1f82e8ac +375, 0x300f7e39 +376, 0xb6e62e7b +377, 0x970441a1 +378, 0x91f2946c +379, 0xaad281f +380, 0x43be1dcf +381, 0x95a1b4c8 +382, 0x2d956dea +383, 0xc532ca29 +384, 0xc93f1fcf +385, 0x70762aab +386, 0x231a72ef +387, 0xe5bd1b75 +388, 0xfa31468 +389, 0x77e1b7b5 +390, 0x19d80215 +391, 0xd45704b7 +392, 0x33472a0d +393, 0x833a435e +394, 0x2354a326 +395, 0x8af39828 +396, 0x603a7960 +397, 0x288c2d54 +398, 0x75bd7c23 +399, 0xe2dd42e1 +400, 0x9a87b486 +401, 0x32e9bcd1 +402, 0x8630f74f +403, 0x160408ea +404, 0xd2127c63 +405, 0xaf327f8e +406, 0x8d879a61 +407, 0xc5c88f60 +408, 0x53a19fa1 +409, 0x706dacb4 +410, 0xd04ea0f +411, 0x94806c1a +412, 0x941cfe69 +413, 0x956a5562 +414, 0xee1f71c +415, 0xe6ba12d +416, 0x333e31f6 +417, 0x17aee12e +418, 0x20ccfedb +419, 0xd7bb7f92 +420, 0xba7d14f3 +421, 0xb935d4fb +422, 0xbdb8f5e1 +423, 0xb24e7adc +424, 0xc9abef71 +425, 0x3e3d8125 +426, 0x5fc0878b +427, 0x5ba172d9 +428, 0xe28f648c +429, 0x5137f3a7 +430, 0xb57273df +431, 0xe68df236 +432, 0xbc29802b +433, 0xb1419e66 +434, 0x69ecb739 +435, 0x490e8eb6 +436, 0x61e25a6c +437, 0xc1fa0de6 +438, 0x2bf2fbf1 +439, 0x9487e8da +440, 0xce5c5532 +441, 0x75859040 +442, 0x2606bdeb +443, 0x1b77c072 +444, 0xe5fbeed1 +445, 0xea9e1ab3 +446, 0x55cf96ae +447, 0x283ed27d +448, 0xc94067a1 +449, 0x8687b3e5 +450, 0x4031b307 +451, 0xc5790e82 +452, 0x4031ee7f +453, 0x952c4503 +454, 0x379ec606 +455, 0x7c35e19d +456, 0x2d333769 +457, 0xbca36d54 +458, 0xcdc70741 +459, 0xa3ab56fb +460, 0x187a2fd6 +461, 0xdd1f32f1 +462, 0xc007ac56 +463, 0x14c441c1 +464, 0xf290ed47 +465, 0xc833edac +466, 0x13f0a8fe +467, 0x63c10b6e +468, 0x6af1be34 +469, 0x5bd4930e +470, 0xfe56bfbb +471, 0x1b412c8e +472, 0xf0c7712a +473, 0xf3a96226 +474, 0xbd0aaad8 +475, 0xbd00355e +476, 0x8ba9eca1 +477, 0x81f136a0 +478, 0x7de3a327 +479, 0x7be298ea +480, 0xe60e320a +481, 0xaf4373b +482, 0x6eacbf3 +483, 0x1291760f +484, 0xd48ed89b +485, 0x596603d4 +486, 0x53abc8 +487, 0x82123b2f +488, 0x1276dc8 +489, 0xfeb474bb +490, 0x4013da51 +491, 0x111cb9d6 +492, 0x5726df82 +493, 0x45806861 +494, 0x2580801a +495, 0x1326049e +496, 0xb9474bf9 +497, 0x6c5d85ed +498, 0x9c4a9352 +499, 0x9eb915ed +500, 0x914505 +501, 0xd14c5b9a +502, 0x57ef8ffd +503, 0x480d8719 +504, 0xb18d7fce +505, 0xfd29e178 +506, 0x2679f6c9 +507, 0xd94a086e +508, 0x6e46f559 +509, 0xb7c3a2e3 +510, 0x793a4c3b +511, 0x4e5252f9 +512, 0x1bdb53a4 +513, 0xbed5794 +514, 0x31a3ebc7 +515, 0xa6eb54e1 +516, 0xc6ae5d92 +517, 0x392acfc8 +518, 0xb283fb8f +519, 0x80b15ffe +520, 0x763b49a8 +521, 0x3febc1d3 +522, 0x60f2b20 +523, 0xd93aeba9 +524, 0xeddf06bb +525, 0x13992ab3 +526, 0x4521bcf6 +527, 0x5ad82a14 +528, 0xf2bfc79c +529, 0xf664b9b +530, 0xeb9540a2 +531, 0x5641dc50 +532, 0x9282d9c4 +533, 0x5d2443a4 +534, 0x407b5011 +535, 0x84a415d7 +536, 0x5db90eae +537, 0xd2947d4c +538, 0x8bd8856d +539, 0xbc05a99b +540, 0x1c2e0f5 +541, 0xb94d03a2 +542, 0xb8ed5ac1 +543, 0x199943d9 +544, 0x12482e5c +545, 0x20aa7c9f +546, 0x8733e45c +547, 0x277b4f44 +548, 0x673d5a73 +549, 0xabc0aad9 +550, 0xbed6cd98 +551, 0x2943c24b +552, 0x5237d6f9 +553, 0x1cb1a392 +554, 0xc7b69454 +555, 0x4f792707 +556, 0xa32ef400 +557, 0x7a5b6b72 +558, 0xa8683acc +559, 0x418d0491 +560, 0x56e2470e +561, 0xbe385495 +562, 0xe7944341 +563, 0x438abaab +564, 0x82ad2c2 +565, 0x7afc306b +566, 0xfcb88957 +567, 0x530414bd +568, 0x2e3c7d41 +569, 0x633f7573 +570, 0xeffeefb2 +571, 0xf6de11f9 +572, 0x337710f2 +573, 0x88bf46dc +574, 0x6fdaf5dc +575, 0x34229d26 +576, 0x46b0aba0 +577, 0x78e40a29 +578, 0x7f9623cd +579, 0x6cfe8779 +580, 0x1d4af99 +581, 0x78f97244 +582, 0xa198d714 +583, 0x9124883e +584, 0x1cf88a12 +585, 0x69fe0966 +586, 0x78484a68 +587, 0xf9d8718b +588, 0xcbf3ba5b +589, 0xf67fb149 +590, 0xc95977c1 +591, 0x474f57f5 +592, 0x11bb9ec1 +593, 0xe28f21be +594, 0x8ca6e21b +595, 0x2609defc +596, 0x989b6f6b +597, 0x1c87383e +598, 0xacd78f57 +599, 0x8c46cfcb +600, 0xc37cce08 +601, 0x327d196a +602, 0xf63c3572 +603, 0xc56780b5 +604, 0x9ac37d16 +605, 0xe692a39c +606, 0x563938a3 +607, 0x1e80e32f +608, 0x745652af +609, 0xe425c9a8 +610, 0x11c71e82 +611, 0x9c721f6d +612, 0xef89b973 +613, 0x494c7e80 +614, 0xadc29895 +615, 0xc7ee35ad +616, 0x19beeb0c +617, 0x9c25ae3f +618, 0x27bf930f +619, 0x223970a0 +620, 0x7cdb17ca +621, 0xa49054f +622, 0xf8321dcb +623, 0x3f96a9eb +624, 0x4468072a +625, 0xfd7d727 +626, 0xee0af4f1 +627, 0xe6585512 +628, 0x56a6d8a1 +629, 0x40586642 +630, 0xb46bdaa0 +631, 0xe053a140 +632, 0x4de1953d +633, 0xb6cbc718 +634, 0x2ed92c19 +635, 0x9da2840 +636, 0x6ab418b1 +637, 0x179f64cf +638, 0x7c281c0 +639, 0x7015b62a +640, 0x8d31e38e +641, 0xa6de57ca +642, 0xe509c4e1 +643, 0xa010162c +644, 0xf71abd42 +645, 0x3d24ac8b +646, 0xc2deb72f +647, 0xd81570ba +648, 0x17fc7d15 +649, 0xf17997b6 +650, 0xfa2ec5b5 +651, 0xbf7e189b +652, 0xb3d9e761 +653, 0xe1194bd1 +654, 0x8d5280dd +655, 0xdea2d148 +656, 0x6d85e66c +657, 0x37f5fb07 +658, 0x65c1dd1 +659, 0xf52c04f8 +660, 0x4460d846 +661, 0x1729f55f +662, 0xe03a699d +663, 0x9f05ff9f +664, 0x31abe986 +665, 0x64899f61 +666, 0x52fba7 +667, 0x2833ce74 +668, 0xa34d0e57 +669, 0x7203d492 +670, 0x1a63d91e +671, 0x463781b7 +672, 0xf9842e7b +673, 0x809276ad +674, 0x88237b9d +675, 0xaa648b06 +676, 0x9cf916bd +677, 0x3b3068e4 +678, 0x20d6ae7d +679, 0x7855dafd +680, 0x9ebd14ed +681, 0xc5934a1c +682, 0xb3c421a1 +683, 0xa2b709a2 +684, 0x91fa8b34 +685, 0x9009a54 +686, 0xb2c4215f +687, 0x7b294eb1 +688, 0x1802911e +689, 0xa2067de5 +690, 0x5ebd85e9 +691, 0xc4f8e698 +692, 0xd143d368 +693, 0x2ca2b6fb +694, 0xb5d27ebc +695, 0x410146ca +696, 0x9d6948fe +697, 0xfafd0af5 +698, 0x290e9c5f +699, 0x2ff06292 +700, 0x417903d5 +701, 0xc51af07c +702, 0xd2bbaf6b +703, 0xfa3720f1 +704, 0x4a6eb52d +705, 0xed86ad3c +706, 0x72a8676e +707, 0xc3c2bbed +708, 0x62b6a951 +709, 0xe08f9534 +710, 0xe2686ea5 +711, 0x3dbbf99b +712, 0xfec5319f +713, 0xef9c67eb +714, 0x9d69d19b +715, 0xc732ed2 +716, 0xc6e829bd +717, 0xe712e882 +718, 0xd24594ca +719, 0x102b8426 +720, 0xa5145730 +721, 0x62fecd71 +722, 0xe6439ca2 +723, 0x58819419 +724, 0xef722791 +725, 0x5ef6ab17 +726, 0x85ce3714 +727, 0xd4e18303 +728, 0xf91eb9c2 +729, 0x86bae692 +730, 0x6d81c21c +731, 0xd9985982 +732, 0xfdd55f22 +733, 0x72ecd91a +734, 0x4b1cee6 +735, 0xefa672ec +736, 0x3f18114f +737, 0xacae5e62 +738, 0x68369afd +739, 0xff5e6612 +740, 0x3760af8c +741, 0xd8c878bf +742, 0x3945fe59 +743, 0x2cf7f99a +744, 0x2cc59bb4 +745, 0xbba95cd6 +746, 0x6511688d +747, 0xcf326178 +748, 0xf850cc68 +749, 0x4bd2540e +750, 0xa02cf5e5 +751, 0x5546fcb5 +752, 0xe2b289fd +753, 0x960c6ba +754, 0x3a2c9d74 +755, 0x2def7a8f +756, 0x54e57d43 +757, 0xf953c277 +758, 0xd9b414b1 +759, 0x19a25920 +760, 0xaf2691a1 +761, 0x81e88159 +762, 0x49a3eab +763, 0x276a797d +764, 0x98337885 +765, 0x37055fd0 +766, 0x6927effc +767, 0xb6de7fc0 +768, 0x9e920f9a +769, 0xd2dc9145 +770, 0xe2861109 +771, 0xe42e2c1e +772, 0x836fe968 +773, 0x23452a15 +774, 0xd49f0e2b +775, 0x2998f647 +776, 0x94f8c803 +777, 0xf8be479e +778, 0xfd44079f +779, 0x685ab9c1 +780, 0xea8eeab3 +781, 0x580ff5d8 +782, 0x88ad0666 +783, 0x19df5d86 +784, 0xe4862012 +785, 0x3ad25460 +786, 0x677449ce +787, 0x1c7e0b9a +788, 0x287a98d0 +789, 0xed39d094 +790, 0x40501707 +791, 0xb99073a4 +792, 0x31847bd4 +793, 0x91e5b7 +794, 0x46815e56 +795, 0xc823384c +796, 0xdb6fb24 +797, 0xabe50dd8 +798, 0x2a33797b +799, 0x4fb617ec +800, 0x811a36df +801, 0xb6b7a25f +802, 0x8962cd0a +803, 0xc40818fe +804, 0x5dbe4e57 +805, 0x591f6c61 +806, 0x22aa4809 +807, 0xc0e4a72 +808, 0xa8a0e2e7 +809, 0xf91d553a +810, 0x77674da7 +811, 0x196657d6 +812, 0x5ae38c0f +813, 0x8bcf1ed2 +814, 0x9e0a2c8f +815, 0xf94e5215 +816, 0x11299b2b +817, 0xc499eca3 +818, 0x25e58d1b +819, 0xdd722954 +820, 0x816f4c21 +821, 0x2504fd9b +822, 0x722a597a +823, 0x92f80aab +824, 0xe2d7e54d +825, 0xefb26dba +826, 0x9ebf8863 +827, 0xd297ec21 +828, 0xa0ebfbb5 +829, 0xec609873 +830, 0xd079b3d1 +831, 0x920f722d +832, 0xfd58146 +833, 0x5fbb5784 +834, 0x30187f5d +835, 0x887f4ec6 +836, 0x6839a2ed +837, 0x72bccd98 +838, 0x7565903e +839, 0x8d3afaef +840, 0xfb713a03 +841, 0x34216b35 +842, 0xbe0da7e9 +843, 0x4b11764e +844, 0x6666922a +845, 0x3f2dc90d +846, 0xeca8fb8d +847, 0x91579404 +848, 0x8d413df7 +849, 0x2a0f8307 +850, 0x39d5a495 +851, 0x79ba5e62 +852, 0xbb06fd0f +853, 0x47ba4208 +854, 0x4a2efb9c +855, 0xee3a07f0 +856, 0x291a73e0 +857, 0xe42a46c5 +858, 0x203455b2 +859, 0x40545253 +860, 0xa618bb0a +861, 0xd4792a15 +862, 0xd6e62559 +863, 0x8149e2f0 +864, 0x5f6499a9 +865, 0xa63fc585 +866, 0xe33e1c1f +867, 0x36ecb45b +868, 0x267883ca +869, 0x905d98fb +870, 0xfac3512c +871, 0x374d0a0e +872, 0x9920f3e0 +873, 0xfb961c9f +874, 0x70f2d752 +875, 0x69c44d12 +876, 0xcb6075d2 +877, 0xaf802ac8 +878, 0x2c4b792b +879, 0xa2203217 +880, 0xc2c15619 +881, 0xb13af213 +882, 0x759b165c +883, 0x411ecdf2 +884, 0x158e5fba +885, 0x70874450 +886, 0x226a484f +887, 0x87b95ecf +888, 0x45cef22f +889, 0xfaf186bd +890, 0x3544972a +891, 0xb4a2f73 +892, 0x5f5d10de +893, 0xf3d05e29 +894, 0x7616ba85 +895, 0x4d2e198 +896, 0x1f240293 +897, 0x317c2286 +898, 0x3bd97e7b +899, 0xd7e39d6f +900, 0x142ee43c +901, 0x688ada72 +902, 0xad8deac8 +903, 0xf7cc8d5e +904, 0xa84600f5 +905, 0xda6b1b3 +906, 0x5bad09de +907, 0x6f4276c7 +908, 0xa789933f +909, 0xede4329a +910, 0xa31f2df5 +911, 0x869c0c3c +912, 0x6658f5b +913, 0xdb451b7c +914, 0x16ec0b18 +915, 0x2e35872c +916, 0xf7bf3c44 +917, 0xda59c872 +918, 0x1ab63c0c +919, 0x9a361a82 +920, 0xd2e1afcc +921, 0x5c41ac55 +922, 0xd1d761db +923, 0x3639bb85 +924, 0x7a418cfb +925, 0xf0b06b8f +926, 0xa2ef4d47 +927, 0x4fac4d1b +928, 0x47e42283 +929, 0x6ee6a7df +930, 0xfe786975 +931, 0x4475b665 +932, 0xd881e311 +933, 0x6b02224 +934, 0xcba19b84 +935, 0x4efa35f6 +936, 0x3873a72d +937, 0x984d7964 +938, 0xe23cda62 +939, 0xea9949d2 +940, 0x243b83b1 +941, 0x48d1bcc4 +942, 0xe35b6a23 +943, 0x125288f1 +944, 0x72fdd401 +945, 0xa2af6873 +946, 0x7c211096 +947, 0xa00a13dd +948, 0x7b4ce5d6 +949, 0x1e4be120 +950, 0xc771cc00 +951, 0x343ae31 +952, 0xe8e0be50 +953, 0xd9095a3f +954, 0x616b7c17 +955, 0xa96e1580 +956, 0x60501426 +957, 0xeaac50b +958, 0x130c33b5 +959, 0xba30925b +960, 0xf942c440 +961, 0xc52e8e20 +962, 0x5f460318 +963, 0x94e1dadd +964, 0xdfa4f20e +965, 0xc9bbd26a +966, 0x75322ecb +967, 0x3dc3ff18 +968, 0xfa896826 +969, 0xe4ad213c +970, 0x7a0f97c3 +971, 0xd7b7b08f +972, 0x6ebcab4e +973, 0x1a37d816 +974, 0x16299fee +975, 0x89d94a3a +976, 0x11c2f073 +977, 0x4ef27a32 +978, 0xaaf42781 +979, 0x9862c844 +980, 0xaa672e94 +981, 0xba4f2690 +982, 0x1f767d21 +983, 0x157e1a5e +984, 0x5b6de343 +985, 0xc494501e +986, 0xe97b507b +987, 0x98cae4c8 +988, 0xc4a6b036 +989, 0x746f8686 +990, 0xe761c86 +991, 0xefdaaa15 +992, 0xb907b816 +993, 0xe9d05992 +994, 0xed2e1b0e +995, 0xe129d3ee +996, 0xb41bb95f +997, 0xaec36181 +998, 0xdcdcf5f0 +999, 0xf175572a diff --git a/numpy/random/tests/data/pcg32-testset-2.csv b/numpy/random/tests/data/pcg32-testset-2.csv new file mode 100644 index 000000000000..2d4c8aed1312 --- /dev/null +++ b/numpy/random/tests/data/pcg32-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0xe4c14788 +1, 0x379c6516 +2, 0x5c4ab3bb +3, 0x601d23e0 +4, 0x1c382b8c +5, 0xd1faab16 +6, 0x67680a2d +7, 0x92014a6e +8, 0x628ae389 +9, 0xa794034d +10, 0x5cc38cd9 +11, 0xfc913a3b +12, 0x81c851dc +13, 0x90c820e4 +14, 0x60dfa703 +15, 0xd613ae14 +16, 0x38ea1699 +17, 0x51f04d1b +18, 0xc4ef01a1 +19, 0x321eec02 +20, 0x4c37a737 +21, 0x6bfd1aa8 +22, 0x71a28325 +23, 0x4656d6e9 +24, 0x17509653 +25, 0x830bd521 +26, 0x6d35e3aa +27, 0x4ab85020 +28, 0x21c1da2c +29, 0x6a6057a2 +30, 0xf3a90dc1 +31, 0xa1cbdcd9 +32, 0xf70b61bf +33, 0x3b2b09a8 +34, 0xbc2ef54d +35, 0xce07f38f +36, 0xb51bc60b +37, 0x729efb83 +38, 0x7e4a5f66 +39, 0xdd824ead +40, 0x9be85945 +41, 0x57f8779c +42, 0xdb449e87 +43, 0xc0be253f +44, 0x18b4267e +45, 0xff78821 +46, 0xb53e3425 +47, 0x4550b21b +48, 0xefe89a4c +49, 0x74c130b9 +50, 0x1656a3a0 +51, 0x194da2a6 +52, 0x1a6cdb1d +53, 0x7c1fd58e +54, 0x3162d1e9 +55, 0x3e2f2c7d +56, 0xb0ab9b5c +57, 0x79156d4d +58, 0x97b85150 +59, 0x967a02ce +60, 0x1e64548d +61, 0x4196d24a +62, 0xd047eef5 +63, 0x8451cc3c +64, 0x7227eb94 +65, 0xb1191064 +66, 0x82e162d0 +67, 0xb473f07d +68, 0x92ea0426 +69, 0xbf2a25fa +70, 0x9935be52 +71, 0x28baec93 +72, 0xa29368b5 +73, 0xe3d6d97d +74, 0x85ecf1d4 +75, 0x482e4bc8 +76, 0xe4f22219 +77, 0x7531047 +78, 0x3c41ef1f +79, 0x19db5112 +80, 0xc1534caf +81, 0x6c45710a +82, 0xb323c369 +83, 0x2dac53c6 +84, 0xd5dc48b4 +85, 0x1dc6d7a1 +86, 0x3ae2bc10 +87, 0x6a7635e8 +88, 0xdeee7b7f +89, 0xcb705cd3 +90, 0xba11e537 +91, 0xb64a4936 +92, 0xff4b245e +93, 0x39cb1219 +94, 0x64833e10 +95, 0x76b0f975 +96, 0x333d7c7d +97, 0x88ccfb17 +98, 0xad78dace +99, 0xd82fb71 +100, 0x1595d411 +101, 0x47f9d57a +102, 0xd4dad6cb +103, 0x78bf16bd +104, 0x71b053d2 +105, 0xa4bb076e +106, 0xd7c57664 +107, 0x3fbcbf8f +108, 0xc816befc +109, 0x6df46890 +110, 0xd16f271f +111, 0xeeeb1571 +112, 0x58222e89 +113, 0xa55e81d3 +114, 0xafbe7622 +115, 0x938475a8 +116, 0xd8740af2 +117, 0xf937dbd7 +118, 0x7d3940fa +119, 0x694c55f2 +120, 0x2261fb68 +121, 0x6ce39e94 +122, 0xab43634 +123, 0xd92ff7c4 +124, 0xe8db22d +125, 0x52e250b1 +126, 0xaf0f7029 +127, 0xc23dd3a +128, 0xd66dc2b9 +129, 0xea7f01f3 +130, 0x4df54b3f +131, 0xf1eff09c +132, 0x2813663e +133, 0x21ae8115 +134, 0xb00d790d +135, 0x11e6adbb +136, 0x61005f4c +137, 0x3de17bf0 +138, 0x7b2050b9 +139, 0xe20dd275 +140, 0xafa0bdcc +141, 0x9c6d4c6c +142, 0xe938606 +143, 0x8eecdd8f +144, 0xea9a90a9 +145, 0x99cbb123 +146, 0x16fccad1 +147, 0x7e81fdd9 +148, 0x116e6abd +149, 0xdeb9ff4e +150, 0xc589f525 +151, 0x57d701a9 +152, 0xcf05e950 +153, 0x533a2839 +154, 0x12d592e7 +155, 0xae61f43f +156, 0x419ae221 +157, 0x81126e0a +158, 0xc3988c97 +159, 0xb3262eaa +160, 0x3baddf9e +161, 0xf19d8a16 +162, 0x2a8b130f +163, 0xe4c9ccea +164, 0xf5ae2ea +165, 0x75aaa98d +166, 0xdd45ce49 +167, 0x98e0d4f6 +168, 0xb1ec10a1 +169, 0xc9592952 +170, 0x23bb1f45 +171, 0xd0827b45 +172, 0x7a79b800 +173, 0x9d1b8348 +174, 0xe2958863 +175, 0x5143e17e +176, 0x44110af9 +177, 0x49d76858 +178, 0xdba4688e +179, 0x4e4d61dd +180, 0x729b81cc +181, 0xf3576e03 +182, 0x9b028e9d +183, 0x68d8d869 +184, 0xda15e018 +185, 0x5384abb2 +186, 0x1027ed5e +187, 0xaf5401f1 +188, 0x31411375 +189, 0xc75d87be +190, 0xad73f5fd +191, 0xadb3add7 +192, 0x4d5452ee +193, 0xdef42029 +194, 0x89d58a78 +195, 0x464d6b4a +196, 0xd01f533a +197, 0xb9533dd4 +198, 0x55c5d023 +199, 0x3dcf8fef +200, 0x198395ca +201, 0x7cdca51c +202, 0x6f4074f +203, 0xb9f79995 +204, 0xbbe3d9a5 +205, 0x520d417e +206, 0x9a8df0bd +207, 0xe390f486 +208, 0x5b578b3f +209, 0xb4cdf767 +210, 0x12d45034 +211, 0xe661e293 +212, 0x70cd3e91 +213, 0xdbc7f190 +214, 0x49829849 +215, 0x12017fbe +216, 0x1e35bf48 +217, 0x1effc3c7 +218, 0xe1f574cb +219, 0xf613ab7d +220, 0xd09d16fa +221, 0xa58bcf5a +222, 0xac39afdc +223, 0xd611d1ab +224, 0x36edd3b2 +225, 0xd9ea5d98 +226, 0xf6f2fce4 +227, 0x42cb31ce +228, 0xdd1f6530 +229, 0x3e43a7d0 +230, 0x175ec7fc +231, 0x8077af4b +232, 0x37cbcc22 +233, 0x26a89f +234, 0x998c930e +235, 0xb84e5f21 +236, 0x83817130 +237, 0x2ad05d66 +238, 0x48f3b861 +239, 0xd69f626 +240, 0x1d09f12 +241, 0xf207e7f0 +242, 0xcc709acc +243, 0x1b2881d7 +244, 0x7e18cc6c +245, 0xbfd9589c +246, 0xce0d301e +247, 0xc8668b4b +248, 0x584482bd +249, 0x722e14ae +250, 0xd79dfcff +251, 0xcc7e9c21 +252, 0xd081f540 +253, 0x3b49f7fa +254, 0xf23efb2a +255, 0xfd7fe8f8 +256, 0x9abcbf25 +257, 0x5b713674 +258, 0x1300e351 +259, 0xe884f0ad +260, 0x3c290461 +261, 0x4f64c1a1 +262, 0x17c55223 +263, 0xd5953a5f +264, 0xd85e042e +265, 0x75dfc597 +266, 0x379edfb +267, 0x75ebddc9 +268, 0xc19b98e1 +269, 0x1dd1b751 +270, 0xc5760a60 +271, 0x5f6e2f17 +272, 0x29e8610e +273, 0xb2edd7db +274, 0x9233eeca +275, 0xbc02b187 +276, 0xc997bb5b +277, 0x88ad3a98 +278, 0x3d1167ad +279, 0xcea54c9c +280, 0x7ea493eb +281, 0x586e3aa8 +282, 0xe2e027c7 +283, 0xae50ef9e +284, 0xd32e0c38 +285, 0xeba0edf6 +286, 0x980ad22a +287, 0x3b14e644 +288, 0xd7bfbff8 +289, 0xe0af1647 +290, 0x292d72dd +291, 0xb8c421bb +292, 0x114d690e +293, 0x85a86bd +294, 0x39f2b5e2 +295, 0x7c9c6b43 +296, 0xca387767 +297, 0x84f24ecf +298, 0x2aec5804 +299, 0x27d0f2 +300, 0xcd7bb6a9 +301, 0xe925969f +302, 0xc6454099 +303, 0xf7435a9d +304, 0xf7bc998f +305, 0xfa81f361 +306, 0xcba07d00 +307, 0x3e8a8a14 +308, 0xf0e7f785 +309, 0x25aecff +310, 0xe1a90226 +311, 0x4af1339d +312, 0x983f4fb9 +313, 0xbaec847f +314, 0x4e504dbb +315, 0xe7d0be86 +316, 0x73cb80ef +317, 0x336db698 +318, 0x8bf7de05 +319, 0x36e4e6ba +320, 0x47a8239b +321, 0x2a98e1d0 +322, 0x64a6c087 +323, 0x4a8591cb +324, 0x642d5d67 +325, 0x9f4b84b2 +326, 0x6bdf1176 +327, 0x7e2b1639 +328, 0xc90453f5 +329, 0xe72d0b96 +330, 0x5f0e1d0c +331, 0x156af798 +332, 0x6124d8e8 +333, 0xaa2f2ad7 +334, 0x145b30b7 +335, 0xd6582106 +336, 0x203abbad +337, 0x929d8d43 +338, 0x14d5b6dc +339, 0xef0f4eb2 +340, 0x8ff54463 +341, 0x588113a +342, 0x1bc43ba6 +343, 0x44f44097 +344, 0xb84cfdc6 +345, 0x3ee638af +346, 0xdd169321 +347, 0xaaac5f56 +348, 0xbb022bc2 +349, 0xf9ef8bde +350, 0x2829b2fb +351, 0x563368fa +352, 0x82ce66ae +353, 0x6d820e38 +354, 0xb87a080e +355, 0x756469af +356, 0x78086990 +357, 0xa220e762 +358, 0x14ba6bdb +359, 0xfa775c1b +360, 0x65fa7396 +361, 0xbae24370 +362, 0x8e42ddb8 +363, 0x1f46b8ac +364, 0x3c9236c5 +365, 0xd3a2184c +366, 0x308ba74 +367, 0x5638eb84 +368, 0x64076fe6 +369, 0x37fe334f +370, 0x8de24732 +371, 0xf0d0b02b +372, 0x18492b71 +373, 0x848f38ac +374, 0x9b46dc75 +375, 0xf5d3c06a +376, 0x203afe47 +377, 0x19857724 +378, 0x38033528 +379, 0xf7fa640c +380, 0xf1cb86e8 +381, 0x1fcd5b99 +382, 0xb07f1023 +383, 0x3bb9ab75 +384, 0x57f54e78 +385, 0xf5b51d4b +386, 0xe94eba44 +387, 0xa5a39292 +388, 0x50803af +389, 0x34ea9cc5 +390, 0xabf621ca +391, 0xb275f802 +392, 0xf46dffd6 +393, 0xd33e27d1 +394, 0xca9a56e +395, 0x6eda85a4 +396, 0x639b78ba +397, 0x799d1980 +398, 0xf3c09bf1 +399, 0x6d4cdbe +400, 0x112dae8d +401, 0xd97414b1 +402, 0x9499df3d +403, 0xa58ece6c +404, 0xe56bf91b +405, 0x3bdbfd9 +406, 0x91aae1fd +407, 0xec1fce54 +408, 0x60e0eced +409, 0x278d5b22 +410, 0xdee29da2 +411, 0xf1f55d27 +412, 0xd532ab83 +413, 0xb0fe9589 +414, 0x88fcc255 +415, 0xf524359b +416, 0x7270a00b +417, 0x42489eaf +418, 0xc020d6bb +419, 0xf9ed0f78 +420, 0x4bc5cdec +421, 0x55061393 +422, 0x6b84a5a4 +423, 0x826c0471 +424, 0x9e69e30d +425, 0x9dfd9b15 +426, 0xf4014c40 +427, 0xcd04ef4d +428, 0x7376c02c +429, 0xb15a9e3c +430, 0xf76c1fa9 +431, 0xcd51bdd8 +432, 0x99f2859e +433, 0xb62c6a4d +434, 0x52239d8b +435, 0x27fa2869 +436, 0x6dba918c +437, 0x9891e444 +438, 0x71e29f5 +439, 0xa9cd3ac9 +440, 0xf6ec3b80 +441, 0x8c8d3226 +442, 0x7c528725 +443, 0xd543932b +444, 0xf76b3e02 +445, 0xeccaf183 +446, 0x8f757854 +447, 0x785edb62 +448, 0x54397da0 +449, 0xe1fe0557 +450, 0x7a79d418 +451, 0xd2740507 +452, 0xc3561bc7 +453, 0xef7c3f18 +454, 0xecf8effe +455, 0xc7a073ad +456, 0xeb5ea9fd +457, 0x33dade18 +458, 0x89d0e41c +459, 0x7720d298 +460, 0xe912f029 +461, 0x7794462 +462, 0xa436dcf6 +463, 0x55cbb318 +464, 0x7b4a78e0 +465, 0xa8ce0afb +466, 0x7e18bb28 +467, 0x92c4f8f6 +468, 0x6828052c +469, 0xbf619f8 +470, 0x272d1d15 +471, 0xb34e2e52 +472, 0x52158f7f +473, 0x682fb062 +474, 0x52e80435 +475, 0x787e0fb3 +476, 0xe331da39 +477, 0xfad42e58 +478, 0x1bdb3f90 +479, 0xe313ab2 +480, 0xe61af9bb +481, 0x46f03903 +482, 0x926b3d33 +483, 0x2b23ce3b +484, 0xed04d4af +485, 0x34c49faf +486, 0x142f503c +487, 0x47cf6a21 +488, 0x5352250c +489, 0xf5942210 +490, 0xca5950ae +491, 0xc5302422 +492, 0x41a5e9b1 +493, 0x30076390 +494, 0x8951d0e4 +495, 0xebe74e22 +496, 0xfcb7dbf8 +497, 0xd55076e7 +498, 0x88a1165b +499, 0x1a89b5a3 +500, 0xda2c3e2e +501, 0xdc1d606d +502, 0xfda0315c +503, 0x5f5610dd +504, 0x3eba316c +505, 0x72cae07b +506, 0x5336095 +507, 0x6a110322 +508, 0x46cb153b +509, 0xa2b11116 +510, 0xe2543988 +511, 0x51f53bae +512, 0x3b10466d +513, 0x189ddd56 +514, 0x1fd355b6 +515, 0x1230e8d3 +516, 0x2050d313 +517, 0x2fbb5c16 +518, 0x64b03f4f +519, 0xbd6cdc1a +520, 0x9d423316 +521, 0xc71a702f +522, 0xf2254f39 +523, 0xd953728b +524, 0xef3c8bb5 +525, 0x685a2fab +526, 0xcea73dff +527, 0x4a7fa029 +528, 0xa27e8058 +529, 0x561a1413 +530, 0x570fc5bc +531, 0x917e93ee +532, 0x15fdbb15 +533, 0xabee295e +534, 0xc40f5307 +535, 0xba18b087 +536, 0x6ea6e339 +537, 0x7e282248 +538, 0x875062c2 +539, 0xd1520c30 +540, 0xb4cef1a5 +541, 0x55812dd1 +542, 0x9c67743c +543, 0x22fd5992 +544, 0x1dacbfa +545, 0x5b35eab1 +546, 0xfa8c9316 +547, 0x490bc71c +548, 0xe5129bfb +549, 0xe7acb79f +550, 0x87667765 +551, 0x945be067 +552, 0x8acf5c32 +553, 0x466e0ee +554, 0x8fa89be0 +555, 0x4eb4afcc +556, 0x3302055b +557, 0x8f2e3ab9 +558, 0xc5bc175e +559, 0x903a3e85 +560, 0x4055dd04 +561, 0x37873bac +562, 0x2965a951 +563, 0x2206c56a +564, 0xf34dc2db +565, 0x34e43ba2 +566, 0xb61caa44 +567, 0xfd3eb260 +568, 0x9dcdc817 +569, 0x7019df83 +570, 0x6fcd9bea +571, 0x270cba0a +572, 0xd6cc3241 +573, 0x6345c906 +574, 0xd213fb94 +575, 0x6195e5b5 +576, 0x804abab7 +577, 0xb4cace45 +578, 0xded19bbc +579, 0x617db00c +580, 0xafb933d6 +581, 0x8192cae8 +582, 0x45ffd8af +583, 0x13ae0868 +584, 0x840f4541 +585, 0x12cd1a05 +586, 0xbb5b7d6d +587, 0x3907ab3 +588, 0xd77a1582 +589, 0x4e741292 +590, 0x28c60865 +591, 0xbaad11e2 +592, 0xa9d3e364 +593, 0x88a197cb +594, 0xe90f021f +595, 0x2056017a +596, 0xeb0a2fd9 +597, 0x1d3435aa +598, 0xdaa0b802 +599, 0x8121bf09 +600, 0x95a88f55 +601, 0xa8b9c257 +602, 0xb0ab4914 +603, 0xf360b741 +604, 0x5563d4ab +605, 0xad33cf0e +606, 0x397d315a +607, 0x6893767f +608, 0x79dd5b31 +609, 0xa9ea6777 +610, 0xcf48c06 +611, 0xb4cceafc +612, 0xf53cab50 +613, 0x72426c8 +614, 0xd128aa5a +615, 0x511eec88 +616, 0x668ab20a +617, 0xb9b53dbe +618, 0x3b03a0fb +619, 0x8f416a98 +620, 0xaa15b7f6 +621, 0xc7767aba +622, 0xa64d3342 +623, 0x42cf1388 +624, 0xfc3ee7c0 +625, 0x892a2902 +626, 0xdb054bf6 +627, 0x4973223f +628, 0xb9f74682 +629, 0x72f2ece +630, 0xddf94382 +631, 0x67581d86 +632, 0x9cb9cd6f +633, 0xed74731a +634, 0xcca05451 +635, 0x3b21fdc0 +636, 0x9e18e52b +637, 0xa40bb287 +638, 0x8bb05e07 +639, 0xa33555fe +640, 0x4c819ed +641, 0x5373903e +642, 0x611403c2 +643, 0x133e25fb +644, 0x9c7a44e4 +645, 0x67197b8d +646, 0xfa910436 +647, 0xa86a825d +648, 0xfc9b24c1 +649, 0x464a718e +650, 0x7421bc26 +651, 0x3c3186b7 +652, 0xf7304619 +653, 0x7ac7be81 +654, 0xae6adcc4 +655, 0xca96bf8c +656, 0x49711d50 +657, 0x74c51f0 +658, 0x275804c0 +659, 0x228098c5 +660, 0x73a31b94 +661, 0x7f01db79 +662, 0xb36209c8 +663, 0x6ccf8677 +664, 0x70dbcce0 +665, 0xa533d8cd +666, 0xd0b0f097 +667, 0xd9a3b784 +668, 0x80a929fc +669, 0x9708f29a +670, 0x95e1e56f +671, 0xd07a0b45 +672, 0x566acdb6 +673, 0x92663054 +674, 0x3667dc9a +675, 0x80f850ff +676, 0x549dd640 +677, 0xc3ff18ca +678, 0x8c70d392 +679, 0xf5547e3b +680, 0x8dbee1d7 +681, 0x51fe33b8 +682, 0xb1ea480b +683, 0x6646f6d0 +684, 0x4a8e7de9 +685, 0xcb053e32 +686, 0x6311aee8 +687, 0xcc2a411b +688, 0x5330e60b +689, 0x4680e825 +690, 0x96bdd8a2 +691, 0x8cf4268a +692, 0x8445c833 +693, 0xc237eef1 +694, 0x459670e8 +695, 0xedf26624 +696, 0x5713340f +697, 0x5a3e87a3 +698, 0xa24a7c2d +699, 0xfa9fdceb +700, 0x746fd14e +701, 0xc6aef3e5 +702, 0x3d957e9b +703, 0xc1926f7a +704, 0xee717768 +705, 0x101fe323 +706, 0xec0d63ab +707, 0x8b8e6f42 +708, 0x8c3d2286 +709, 0xb573dd68 +710, 0x53b68ec0 +711, 0x696525cf +712, 0xdab65d8e +713, 0xd2c6ed42 +714, 0xa1fc10f6 +715, 0x1554666 +716, 0x6ed42947 +717, 0x87f7e62 +718, 0xaf34733b +719, 0xc55baa8b +720, 0xcbff66f +721, 0x2516c228 +722, 0xec6980fb +723, 0x4f53d66c +724, 0x1be17a32 +725, 0xdcfb31df +726, 0x4b17d04f +727, 0x81e1f54b +728, 0x749eae52 +729, 0x3811c4d5 +730, 0x5d11e6a1 +731, 0x535d5d6c +732, 0xbb74cd20 +733, 0xd1b18b71 +734, 0xfbf7221a +735, 0x817c4279 +736, 0xcef30b85 +737, 0x41dee06c +738, 0x9d340a3a +739, 0x691f0449 +740, 0x363a515d +741, 0x73a1af6c +742, 0x25718271 +743, 0xb4a52d50 +744, 0x1e392f40 +745, 0x3c811345 +746, 0xc9aa8565 +747, 0x357c24e0 +748, 0x19ad7230 +749, 0xed250e20 +750, 0x4acc4824 +751, 0x825d53a +752, 0xcf2f515f +753, 0xb7973ff4 +754, 0xb03ce53f +755, 0x1afad500 +756, 0x39f64ee8 +757, 0x60bea483 +758, 0xedf16817 +759, 0x88beff73 +760, 0x4909868 +761, 0x879a96da +762, 0x52d4ac6b +763, 0x46fabe65 +764, 0x88fa5751 +765, 0x71df4521 +766, 0xfc6eb286 +767, 0xf83e78ad +768, 0x885e5aca +769, 0x77e63e4a +770, 0x2bdf5c02 +771, 0x2528323c +772, 0x5b5d1ce9 +773, 0xf795be8c +774, 0x5e113b2b +775, 0xa993c7aa +776, 0xe5f8560a +777, 0x77e1e8d +778, 0x5e9db88a +779, 0xdac4e96b +780, 0x9126b945 +781, 0x15bf293a +782, 0x1dc9a8f4 +783, 0x909b48b1 +784, 0xb50ce29e +785, 0x21671c87 +786, 0xcda80dec +787, 0xf5aff1a9 +788, 0xd70cdb2e +789, 0xd293139a +790, 0xcbf4f51d +791, 0xb23c6d7a +792, 0x1a06aa33 +793, 0x21880210 +794, 0x92679678 +795, 0x8d5bb26b +796, 0x23304100 +797, 0x8f5d1df4 +798, 0x143b39ff +799, 0x29e97d16 +800, 0xbfad952f +801, 0x257ca1d8 +802, 0x32ad2f8f +803, 0x84d320c3 +804, 0xcc4c59a +805, 0xbb5ae046 +806, 0x3d5fcf1d +807, 0xa0130b0 +808, 0xad86e9de +809, 0x1e422521 +810, 0x6b56a617 +811, 0xbe64d9fc +812, 0xfff31ed0 +813, 0xd1ad616e +814, 0x13486a20 +815, 0x1754613b +816, 0x52c7b9da +817, 0xc05d75aa +818, 0xd719cd98 +819, 0x61890574 +820, 0xc4711a8b +821, 0x9afd5635 +822, 0x4dabed21 +823, 0x94f173 +824, 0xb8b6e708 +825, 0x1d590111 +826, 0x60315dfd +827, 0x7fb8ae79 +828, 0xc69f4f2b +829, 0xcaf1c898 +830, 0x861a0c8b +831, 0x6ed14eaa +832, 0xc77da58 +833, 0x8fd4f29a +834, 0xa38187fb +835, 0x6ed1ee88 +836, 0xf1a9f55a +837, 0x74368cc8 +838, 0xf327e944 +839, 0x97a578af +840, 0x8a5345e5 +841, 0x63ee0a30 +842, 0xa7e4919b +843, 0x51e26930 +844, 0x38dbe017 +845, 0xedace3a9 +846, 0x9cda2ad4 +847, 0x96b1119 +848, 0xff56282a +849, 0x71773edf +850, 0xe41fb69c +851, 0xe7bce539 +852, 0x221ffeed +853, 0x35d3f67f +854, 0x7e089168 +855, 0x6fd47823 +856, 0x43bfb28d +857, 0x9ce49e62 +858, 0xde32120 +859, 0x6eacfe4e +860, 0x116c6128 +861, 0x5f975284 +862, 0xc547361c +863, 0xf48e8251 +864, 0x2ac8a3bd +865, 0x9a0fce5b +866, 0x1764e3d9 +867, 0xa31e6954 +868, 0xb9dca055 +869, 0x1cd35c79 +870, 0x1b502882 +871, 0xf973ab10 +872, 0x8b585146 +873, 0x841fd3f8 +874, 0x4999200f +875, 0x7ad10c4b +876, 0xcf1695bd +877, 0x26c58bc3 +878, 0xdc1f8310 +879, 0x546e1e86 +880, 0x2e39fec8 +881, 0x8c65e2ed +882, 0x6469bac +883, 0xbc4af1ff +884, 0xa1669010 +885, 0x41dabd80 +886, 0x5797e218 +887, 0x9bed24c1 +888, 0xa7552347 +889, 0x4e214099 +890, 0x34d4f986 +891, 0x316cc527 +892, 0xde30c21c +893, 0x4f273c1e +894, 0xc3dd9324 +895, 0xe61fda1c +896, 0x1d0f8076 +897, 0x5570867e +898, 0x289d6062 +899, 0x465b8b26 +900, 0xb72307de +901, 0xe78c8647 +902, 0xfee9723e +903, 0xa1534c9b +904, 0x4d652645 +905, 0xe623b6c2 +906, 0x454cfc8 +907, 0xc5a7fcaf +908, 0x1de804d9 +909, 0xa2501de7 +910, 0xe036c091 +911, 0xa4a55d1d +912, 0x50409892 +913, 0x58fd2731 +914, 0xb6fd3618 +915, 0xa0180bd2 +916, 0xd9bb2fe8 +917, 0x7c8e7a2c +918, 0xd90906fc +919, 0xf8721260 +920, 0x451b372d +921, 0xeeb1c70 +922, 0xc1a18778 +923, 0xd466244a +924, 0x88e4b84a +925, 0x4fc3af63 +926, 0xcf4387e4 +927, 0xb8872734 +928, 0x276eadef +929, 0xd2c164a1 +930, 0xd3c812d9 +931, 0x5a94f176 +932, 0xfba6f632 +933, 0xf7aeba97 +934, 0x9207585f +935, 0x70a41d67 +936, 0xa0b70910 +937, 0xd579fc6b +938, 0xf06a8fca +939, 0x471fd406 +940, 0xb15a0491 +941, 0x2f340f7a +942, 0x3df02de3 +943, 0x6022f8d6 +944, 0xa15b11c2 +945, 0x45715dd6 +946, 0xf293d85e +947, 0x7a2100d +948, 0x7dff786e +949, 0x52c6a183 +950, 0x5fbce2db +951, 0xbc29ec65 +952, 0x3dd14b27 +953, 0x1bedecd1 +954, 0xbfcba31c +955, 0xb911a26d +956, 0x6b6de680 +957, 0x36e8769 +958, 0x908de4a0 +959, 0xe1abee1f +960, 0x83acd7f8 +961, 0x5008c1eb +962, 0xd8bc7a2b +963, 0x6f639c56 +964, 0xe1f2634b +965, 0x267222ec +966, 0x48fa416c +967, 0xfa01e3cb +968, 0x2d28a700 +969, 0x58dcdc97 +970, 0x685ac2e7 +971, 0x9318840b +972, 0x99247a55 +973, 0x8d749b83 +974, 0x403f8415 +975, 0x373eb9c6 +976, 0xb840b6a2 +977, 0x9bb7bfc4 +978, 0xd5800634 +979, 0x3ef4a02d +980, 0x2ffa791f +981, 0x8a671150 +982, 0x40fdfc5e +983, 0xfa4bd35e +984, 0xf4ca1642 +985, 0x17fb231a +986, 0x42a3e57c +987, 0x58cf119d +988, 0x32f19c67 +989, 0xf3e2e153 +990, 0x66fce6fb +991, 0x9d61059b +992, 0x1628eafb +993, 0x9a6cf683 +994, 0x5ff5df3a +995, 0x206fb3c9 +996, 0x1914913c +997, 0x58c002ad +998, 0xd099145f +999, 0x155aab4b 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 000000000000..da6d77d40f19 --- /dev/null +++ b/numpy/random/tests/data/pcg64-testset-1.csv @@ -0,0 +1,1001 @@ +seed, 0xdeadbeaf +0, 0xb174ddf3fe597da6 +1, 0xfc217240c1e61e6f +2, 0x20279da26fec9cbf +3, 0xa5f4ee34651f4e1e +4, 0xb254d7901c68b9db +5, 0x6bf2a64e4052c36f +6, 0xbec4c7418c0f61b6 +7, 0xb03e595a4ef2b2bd +8, 0xc8e051957ccb74c6 +9, 0xf5082df7473c6f62 +10, 0xb72aa3dc22752a38 +11, 0x7a941561514bd680 +12, 0x90a95f42834f347b +13, 0x88e17b9d59def797 +14, 0x18f19c86bfe60368 +15, 0x667f89277be8d1d8 +16, 0x63305475e7aeff27 +17, 0xd7e4d5c09fb0fb4c +18, 0x7dd6deab03a8c26a +19, 0x42bbcb746e2d4b26 +20, 0xe91f2ac4fa90689c +21, 0x2f83458da0af3125 +22, 0x49a43537a00fae89 +23, 0xef02111d1ebc16eb +24, 0x32b3b3019875f3e7 +25, 0x89eb15c48cd02774 +26, 0xa9f1b37865752731 +27, 0xe0eff9dadc47fb3 +28, 0xae859b1c54cc90c2 +29, 0x7b7c5e04d5015dec +30, 0x38faeff5ce3266ff +31, 0xd2ddd0d19fbc24ee +32, 0xe0d4f692829a31a9 +33, 0x30a6aa3f408e71c2 +34, 0x298362be21de6d44 +35, 0xb7efab759e691149 +36, 0x2ae1f84bba093d4c +37, 0xf6ab55f78f8b9258 +38, 0x2275d0af583cec95 +39, 0x18cfe066b183ac3c +40, 0xcc0a546d54064cf5 +41, 0x5de027ea3c25c225 +42, 0xdaf31ef489fe71e1 +43, 0xa7a2b1a72a4360e7 +44, 0x678a55d7a0506791 +45, 0x36facd8799ad2b78 +46, 0x32fec94506dca70e +47, 0x34e890d8539871f8 +48, 0xec48b5362b0d7818 +49, 0xe2e58921cf8228d3 +50, 0xd163588ec22730a4 +51, 0x17e2322b6be47d25 +52, 0xe1544989a0c6d24f +53, 0xa3a10fb279cdc347 +54, 0xad4ee318a5853900 +55, 0xc96a185feef4a85d +56, 0x82ec5b3aed6636fb +57, 0x2aac2ef8f25426d7 +58, 0xa81e3114165e0d08 +59, 0xc1d8128f83969da5 +60, 0x157505508eaf50f1 +61, 0x77c175067c9c199c +62, 0x973052089bd7af0 +63, 0x3cd70041e32c1921 +64, 0x7783719f13a254a0 +65, 0x2216485ff502d9ff +66, 0x7dae695d2c7f3b79 +67, 0x809ce710156fea36 +68, 0xb90ac31262460e4e +69, 0xc1afe8019306e7d7 +70, 0x6c57638edba4ca0a +71, 0xbe6133f6ab1e9aeb +72, 0x8f5699ff0bcf341d +73, 0x69d0218df036bcbc +74, 0xf0976fd79735d47d +75, 0x82b36a795e5cc74b +76, 0x263c30766b985686 +77, 0xf7426f94511d5ba0 +78, 0x8b04f9573050ed9e +79, 0x7280d4ec202e8359 +80, 0xa8235fbd1324f172 +81, 0x6dbd5d500a809a8c +82, 0x26c53c69292bca1d +83, 0xe348f657b20305ec +84, 0x562f0e2fbb375421 +85, 0xdf2be07bebfbe447 +86, 0x4275044640683760 +87, 0xad5d68bfe4ab4858 +88, 0x3c0e57df5b3306f0 +89, 0xc9d87622ac847565 +90, 0x83d04fd9e102c311 +91, 0x71996b9c65aaf5c0 +92, 0xe3df32742d6fc446 +93, 0x58d3a6573a39d0cb +94, 0x74dfa090e96d289d +95, 0x7856f45e5416c1ea +96, 0x80a18e88b3e4dff8 +97, 0x60565bbcb04f56ac +98, 0x9f4cf5ec45fae3a6 +99, 0x885d2909fe34e3f0 +100, 0x7a1db9118f60dee0 +101, 0xc4c17dc810746c7e +102, 0x8b954b14effe83b1 +103, 0x4f89fb0940999c86 +104, 0xc62e634bceca1c97 +105, 0x7e06e87dffd1619f +106, 0xd1ccbce841371671 +107, 0xe7f99698c66df1b3 +108, 0x5302c2f0e4e1f4e0 +109, 0xa57d11d3d7ee652e +110, 0x8abe0ed0e5508407 +111, 0x6780588af9f6c2ff +112, 0x8603a9fc73b6a4cd +113, 0x169c13a0b7a166b9 +114, 0x868969fb53578598 +115, 0x6089e0eacbe69039 +116, 0xf82482d424397dc2 +117, 0x11475d20896fc890 +118, 0x7983933df29e2aa0 +119, 0x4889c4780cd8e9cc +120, 0x53ebb258f3ea266b +121, 0x121896059b256fd1 +122, 0x2f9934516b2f8090 +123, 0xbabb9fa1d1efa60c +124, 0xfb0b1370ea044797 +125, 0x782ab293b597bc8e +126, 0x297fc0b3977271f5 +127, 0xa573e4d0674d02fc +128, 0xc7e8ddb6efe8a2db +129, 0xaae8a024e62f6e32 +130, 0x3217a47698c9e439 +131, 0xd7015db847a3de0b +132, 0xbc0b4368776e10a7 +133, 0x69d9ef0178679bfb +134, 0x28fd8f0936b66fab +135, 0x45b1c4d4aa9b5aca +136, 0x28feade39cd3ac00 +137, 0xa7e6515c534520f1 +138, 0x735703b5f4bfd54e +139, 0x798271ae0c91b8d8 +140, 0xf858458f9efa8d2 +141, 0x6a41f5845422a9e +142, 0x7fb0bba5f097aab0 +143, 0xbfaea58fe090e745 +144, 0x84770504bfb15b35 +145, 0x67ae11aa368049b8 +146, 0x846c5e493ee15e4a +147, 0xbbcf3baf029f056c +148, 0xd30c23bde142a356 +149, 0x32cd403edb746a8d +150, 0x40161ab00c636730 +151, 0x3a882c3c60d3e19a +152, 0xca8faab24d826529 +153, 0x241a687288551d04 +154, 0xbbc607fb9b48ac00 +155, 0xa844329d0c2d475a +156, 0x8fa4aa1d7296b9e4 +157, 0x82c7dc1f588ce2fc +158, 0xcbdaa663041e078c +159, 0xec108d219b2b147a +160, 0xcab01864270b334 +161, 0x6d3d08545041621b +162, 0x2aae054b8e5648f +163, 0x1bf5a72fa70e7eab +164, 0x2dddb2050af45a3a +165, 0x2b910b7078021a75 +166, 0xf7160201ede45f4e +167, 0xfaf75ae996f079bb +168, 0x407984a9451e659c +169, 0xbdf9c0a9ea078ac0 +170, 0x1e7717b8345acbb6 +171, 0x25cc2df4c0c8dc4a +172, 0xfda1715b573850db +173, 0x50e5cedad99e2651 +174, 0x9a67673ed73cfc0 +175, 0x802ec4fc9e946805 +176, 0x677cd320e641999f +177, 0xbfeb1b6053fe4f78 +178, 0x220cfc90bd31541 +179, 0xe4fdfae10ae6c86f +180, 0x76c568fd869af80d +181, 0xd17dc57109200bb1 +182, 0xeb96ba01c95382be +183, 0x6a9c7ebea5b5f7ac +184, 0xc1680450532fb8cd +185, 0x26b0829f68888094 +186, 0x98335aa1612d7c70 +187, 0xad8662125bf32ae3 +188, 0x15f18a9025ae26e8 +189, 0x5d065dba0d17c9fc +190, 0xf68e1d59f10ff109 +191, 0xcfbd97901a79f8b0 +192, 0x3e72a9fd1d95f143 +193, 0xe7ee82c1bb740dfd +194, 0x3a0f4ae5db22527b +195, 0xf4d025080ed4ea92 +196, 0x6924a99549b4657 +197, 0xcb83b51552208e2f +198, 0x9f306634214b44e9 +199, 0x4fb3307b0e1a7535 +200, 0x73d202d4225c5394 +201, 0xd5a2fa42f8cc8c5c +202, 0x7b3b3e3f7b948d3c +203, 0xa2dbc4d30d8c148e +204, 0xd1bfc1f05a8f2c5d +205, 0x2b00a4efa2f19262 +206, 0x9d4a05bb18647f48 +207, 0xff21fbaf0b46d13f +208, 0x126f9c5f2132af20 +209, 0xd4b7629b0d9a6b89 +210, 0x2d61949fb3126ecc +211, 0x30d61648763db1ce +212, 0x9c5234d15120bf17 +213, 0x2eb0eccb6cc14c8a +214, 0xcf18eff5ca2af8a4 +215, 0xab5fe599ea68c377 +216, 0xe47a0bb8436af89 +217, 0xd3728a566187c400 +218, 0xb8b54592b62f633e +219, 0xe02b958f9c13a180 +220, 0x9e5f5cc85283f24a +221, 0xbd1ab869878744a +222, 0xb93fd6297a29c8dc +223, 0xf22f06ee61dc2413 +224, 0xc93fe440766cbd8e +225, 0x7459d9b19375a51c +226, 0xd4ec87c57baa4127 +227, 0x1514d0226dc0409e +228, 0xc6b0d7e1bd56b190 +229, 0xc0c61c73c9dbffee +230, 0x2f1154afb48a93e2 +231, 0xd2ca05901bae0117 +232, 0x6263f647273694a0 +233, 0x94a98bf80488205b +234, 0xcb0d63747735bead +235, 0x9cbd4e1659932c5b +236, 0x1807e01931b5ade0 +237, 0x1d9f7721d3067854 +238, 0xb25dbde4ec77e547 +239, 0x4b186592a39adcd6 +240, 0xe8ad5514de72a98f +241, 0x2deac1cb096a09b4 +242, 0x6952f4b82a2c87 +243, 0xaa1590223ed83ffe +244, 0x9baf13d08f572e12 +245, 0x83ec1bca1e724d88 +246, 0x5c61bf2222b4907 +247, 0xd950ff64ad7b956e +248, 0x36bf5e992bf1f211 +249, 0x75ad67249d7a6c35 +250, 0xeb12dcef5c2bfe7d +251, 0xc508da925157e39d +252, 0x91cbd7491ea7f70e +253, 0xf10c018ec0b0e55 +254, 0xeeffb21fef1e87f1 +255, 0xe31692b834d067dd +256, 0xd69bbafdeb5c0d15 +257, 0x41358dadb9260eb1 +258, 0x5fa3c67d353cd6b2 +259, 0xdbb743cac20b2eda +260, 0xe7877ba98b2bfe4 +261, 0xf14d679436fd2dcf +262, 0xa313e39059d62afe +263, 0x7eaa134c761a6183 +264, 0x7719af9ad1fecaec +265, 0x533f921a4702d433 +266, 0xe072f9665ec3a3c8 +267, 0xba89560ab4ba08fa +268, 0xe94f0aa266e56d53 +269, 0x774b84bcb152afc +270, 0x787c9517e589748d +271, 0x3831a5303adfd362 +272, 0x19cb20184a4264f8 +273, 0x9bc5e99e1773700e +274, 0xed323bf38642f651 +275, 0x860868c0eba789f2 +276, 0x8c1602ffd9a5621a +277, 0xe298d8fc74e146ce +278, 0x3181a2083c76037f +279, 0x27942fd6842079c0 +280, 0x38fe8c0406516df +281, 0xd211a4a42857bec3 +282, 0x56002508b351879d +283, 0x2472ed93614c7e99 +284, 0xbcafdaadc0f77b7c +285, 0x86becbd3e5303107 +286, 0x930251d84de72320 +287, 0xea79aa2964954052 +288, 0x6dbc5e63b50b1724 +289, 0xb098535ed4bc7372 +290, 0x6490d6d8541fb656 +291, 0xc738f6ccb4b7076b +292, 0xd69ee4fd6ce63026 +293, 0xfa98e9d78a628338 +294, 0x9c30b63a70d607b6 +295, 0x8d544b5d224a25d9 +296, 0xa051f7fe38445228 +297, 0xf6931861338a00f5 +298, 0xecd71cd64b0b5dcd +299, 0xdbc818e7126193b +300, 0x3aaaa032aad8199a +301, 0x6fd68a3818e0c439 +302, 0xc82a651ba9ede8c9 +303, 0xe6d958e267017187 +304, 0x73a9eab64de651ae +305, 0x5a6757f7f222bb3c +306, 0xe62e7cca6bd17a32 +307, 0xc4f6c31f528dd387 +308, 0xdecd8b663c995773 +309, 0x69a21dedcbfef9c7 +310, 0xb33f8ac00f17b6b2 +311, 0xe32b3c962d613ba3 +312, 0xa9c317d026600d41 +313, 0x901d971c49671213 +314, 0x46c3f3d35db8808b +315, 0x1336297232af9791 +316, 0xed88d9242e11edb3 +317, 0xc70c48843f54af0 +318, 0x611062a0461deedf +319, 0x7e3183514f127f20 +320, 0x7b549d10bace1c47 +321, 0x6db523d19d0a7af3 +322, 0xf6e677e5222a21a4 +323, 0x28e5188ba7055c32 +324, 0xbe7b41d2ce539c4f +325, 0x5c085a18c3b7bbe0 +326, 0x209cf345b3c3b06c +327, 0x79ca5407dd486857 +328, 0x8e07ac4c65338ccd +329, 0x56dd5372249cadad +330, 0x27e0b07863fa27ff +331, 0x78dec95d299a8699 +332, 0xbd5d71253b73d456 +333, 0xbf83b6cedd205e9 +334, 0xee2352ee69aa68e +335, 0x4b14f253d684cfbc +336, 0x12ffa5d5f8a34bec +337, 0x2e38346fbc793f67 +338, 0x2ab5862872b4850b +339, 0xcbc8aec1e2bb6760 +340, 0xd79ef783845cc329 +341, 0xdbdcde91e1685704 +342, 0x29880643aa1095e4 +343, 0xcd5ccc1fe9a616af +344, 0xc7b6cdc4a43c132c +345, 0x7b08597fdec7fc9c +346, 0xa01ab3827e120a16 +347, 0x89ce37de99ca7748 +348, 0xb4644823ea6b90d5 +349, 0xdbe189861c409209 +350, 0xbfeb614759981b60 +351, 0x48c2c3a6d2419755 +352, 0x1aa1df0e99b3417e +353, 0xb9f061bf98c0da28 +354, 0x8bce2755a0b5b8ae +355, 0xc9bb2ff33d60b3e7 +356, 0x6abcbb1ea0d3a575 +357, 0x983a3c16a0e5d6f8 +358, 0xa122e616797ccdbe +359, 0x751dfe60252a01d0 +360, 0x8d1bcbbde84f6a11 +361, 0xb6bc4f2942ba0e57 +362, 0xb298977a4bb20e12 +363, 0xcf658188dd931722 +364, 0x39735757b19c90a3 +365, 0xc2fcf1df99f1b7c4 +366, 0xd42c50f6a912aaea +367, 0x95d0cb8a953965c4 +368, 0x75c7d03289269f25 +369, 0xd8d96184031fb36b +370, 0xb3b34b5ba8bac75 +371, 0xcfbf16d241e46f8c +372, 0xec465e59019b6f6f +373, 0x4051ce0bc2562a63 +374, 0x859f05ce7b75da05 +375, 0xf2661ef2e3c733ef +376, 0x8067f432dd5af0c4 +377, 0x6e8542a346911713 +378, 0xfcda2ac6aa45ca20 +379, 0x571f23fdacb25fe2 +380, 0x2546f5badf7adb8b +381, 0x929ebe6fbd330e2b +382, 0x9d41d6ded9facbeb +383, 0x4cf9d9da6c125106 +384, 0x495d5708443faa36 +385, 0xb0023a41a6057e59 +386, 0x37fa1cd9ce66b20a +387, 0x96a376fca4aff5a8 +388, 0xc22469c4a3e1ea85 +389, 0x5ab79b721966249b +390, 0x2124be452f7d4ca4 +391, 0xe71bb882b954ca11 +392, 0x322bdcaf9c7b0efa +393, 0x4c99c8753878439f +394, 0x3ffd6caec9f9ac49 +395, 0xfba842dd40a3c72e +396, 0xfd93517d31681d77 +397, 0x44c139a74249a128 +398, 0x828a145610684c8 +399, 0xb53696f802522b6 +400, 0xa2da2199474d079a +401, 0x739e508fbbdeb714 +402, 0xe75c4734a7c95f94 +403, 0x5c22c226f2bd8487 +404, 0x7108fa6b99b0d72e +405, 0x3c60b40f6e4bebde +406, 0x395150555d56dd18 +407, 0x13246a6e4d795fe3 +408, 0x27dca990fb678027 +409, 0xc5a92c32724a7373 +410, 0x30fed89f4171a817 +411, 0xf7f7810edea2e7eb +412, 0x46e930eef5351212 +413, 0xe1331cd8a678dc66 +414, 0xd4cc0a5f96a72457 +415, 0x2559f8d286b1da16 +416, 0x73831b2f6e4a4ba +417, 0xd929ccf267504761 +418, 0x8a7a1b357f8bbc38 +419, 0xd5e0d3e200d0d633 +420, 0xc2cc05cc3ac5abb +421, 0x75b8f78a06ca465b +422, 0xeaf1d6aa9c0baef3 +423, 0xa6c9bc3dbe45e62e +424, 0xb1496074b4c338d7 +425, 0xc18ebb892108cec +426, 0xf6cbbf4cd0f8f9ba +427, 0xd73759407ecbdcf6 +428, 0x54dc0805c85a3b0c +429, 0x4ba3936d6be048f3 +430, 0xa3fbea19803cf35 +431, 0x78b1d3a837d4bed +432, 0x6ed09ac2c177453b +433, 0x16134c4e8b30f6ba +434, 0x94718ce4868f01a3 +435, 0x612fa336da82e66d +436, 0x5d8833c9483b235d +437, 0xf5c72d4883bed9a2 +438, 0x2a6e27d1ed337134 +439, 0xfba250d6b9cc0d2b +440, 0x432f8734b61e4366 +441, 0x45e8becd5ccb4f32 +442, 0xffc7d68cb343170a +443, 0x247cb9a6b29b1a35 +444, 0x89876df3681dc65 +445, 0xd1e646c49aac769b +446, 0x4c3cd721635602d0 +447, 0x5139344709c749fc +448, 0xc5130d981e1a6b14 +449, 0xff269bea082608cb +450, 0xf45a5d57a6d4c6a6 +451, 0xc4c9f3e5398db827 +452, 0x2b3a0eacd42665b4 +453, 0x94d847d848a8e65d +454, 0x1a8aff186e1d75d2 +455, 0x6ad986366c54a242 +456, 0xbd832c0607523e7e +457, 0x973064c20c31842d +458, 0x34d0513e6d602f80 +459, 0x91b3c812f83392ed +460, 0x4c49ba38b6a4cf90 +461, 0x82e3370e1c5ad5d4 +462, 0xa29a01fa53250a13 +463, 0xbe8ed1e615a1ee6a +464, 0x17fb15941a9fe6b4 +465, 0x84aea1c0138fb970 +466, 0xab065efb4558003d +467, 0x3345b340257a2551 +468, 0xfd2ebda1048c0dcd +469, 0x2aa72fce0cb23982 +470, 0x9952f9363830ff6d +471, 0xdb240e279cb7f901 +472, 0xb4a1e7b54206aca4 +473, 0xe13bdbb980623f25 +474, 0xd989f009368f8a9a +475, 0x7084b7695149660d +476, 0x55b92a3f139c7f1 +477, 0xdb43c75c633debd0 +478, 0x94e362574c70b9a8 +479, 0x218a1a06d9223f9b +480, 0x82f3c3808f86bb95 +481, 0x63e9de6cee4b77b2 +482, 0x3bc5effa36bb166 +483, 0x8369cbe5fa0ecab +484, 0x2a5808b4d7bc8572 +485, 0x6856e29700de99f5 +486, 0x107e86fcfd4a48d9 +487, 0x15c9ee6528c1c223 +488, 0xbf7318d4206c5e75 +489, 0x15d7a6aa9343c9e8 +490, 0x93419fe0ee3bd5df +491, 0x916c7f75ededdd53 +492, 0xe89d6230690f74f1 +493, 0xf92f96834e0eb27 +494, 0xed5adc06c305adc9 +495, 0xf656fe40e7ecb4d7 +496, 0x32a2d3eda46114b6 +497, 0xb3f17867d23c75e2 +498, 0x2a2cc838c4d89c33 +499, 0x413df7052f8866e7 +500, 0x373bd93e91bbed18 +501, 0x78c8e5aa1e1e2dda +502, 0x6bd362f6be6d572b +503, 0xba1926efd387aeb5 +504, 0x3b826b77ae3e53fd +505, 0x383cf5a66fb6723c +506, 0xf5a4e1dded64d931 +507, 0x76d9843a304729d3 +508, 0x205b8753b6d309f0 +509, 0xd2a68ef67d8e7758 +510, 0x60d517f325411c0c +511, 0x37a3bb4950cf08d5 +512, 0xea3d4f95542ffe2d +513, 0xa88708db07fb1d34 +514, 0xd96555e1194f7ee0 +515, 0xdd046e642b59fa51 +516, 0x18ff34e73582d46b +517, 0x7ed73af03535c5fe +518, 0x8ffd64801d2c5187 +519, 0x7134902903c9cfe2 +520, 0x74fa0b238ad1e1ec +521, 0xa220ff0032395fd5 +522, 0x4ed0a7a2d9c3a064 +523, 0xb02cb878b4c9a04d +524, 0x8437cebea5ae2bec +525, 0xabcc162a0027aefa +526, 0xc8e86ab8f5c09011 +527, 0xc28dfaf764ec07d4 +528, 0xb19127d64ae5db18 +529, 0x857cb1b00ac7fbc7 +530, 0x173a441c4b494aad +531, 0x255af1a4d50952c3 +532, 0x87ff01c7d0139add +533, 0x489b15e4c97cfcde +534, 0xd4abbccecfb67239 +535, 0xa1a2912ad34ac4fb +536, 0x94b7f12e10bf720 +537, 0xdb8840c295333634 +538, 0x5a29aab5b359f2c0 +539, 0x630352d282b695bd +540, 0x399f00854d3fbdf3 +541, 0x19e917e0eb8bf070 +542, 0xa464b4dc93d1fe7d +543, 0xf152d3cdecbd7647 +544, 0x517907b570a6b082 +545, 0xfeb06f4bd978e7bc +546, 0xa22859ad14c0f183 +547, 0x33c11e90be9721e3 +548, 0x8394f642b5a40d7d +549, 0x9525633e7e60ab73 +550, 0xf97401c9b4b96001 +551, 0x3d78ce1ecf900029 +552, 0xa85791d9754a2765 +553, 0x16e77aadd9a30946 +554, 0xc91d4defe72f39f2 +555, 0x2fb67bd91edc4b51 +556, 0x95d635e95b468fa7 +557, 0x28b81869d1739e29 +558, 0x5b098fa22cb1747f +559, 0x6544b8704bd2400a +560, 0x91a64f9ec6e93245 +561, 0x2b46ba92268db263 +562, 0xbb52d7758efd5416 +563, 0x7032adc08e6d39da +564, 0xe9d3bbefdb61feb6 +565, 0x2d603389c757996b +566, 0x5871ed32ce17d042 +567, 0x31d622a6b8438f70 +568, 0xc71af17db6bf7aed +569, 0xe419e3c6fbe86530 +570, 0x648471d670f18dcd +571, 0xd13f9e25078599ed +572, 0xdaf86e56826d07a3 +573, 0x3c9374e4420a8580 +574, 0xcd75b12ad6d8d9fe +575, 0x2d4530f6e2b93ca3 +576, 0x303bb663ad4ca963 +577, 0xf8caecede4436b61 +578, 0x315a8124669a907f +579, 0x1c18d130a4b93836 +580, 0x9e0b83663631562a +581, 0x400059c1ce071c7f +582, 0xb27f7f67e7cbd970 +583, 0x6b446e8c4866f3d0 +584, 0x4ab1755d2734121c +585, 0xb9fc8e017d89edf2 +586, 0x3a9aa7f50355c0c9 +587, 0x899fece06a169b2e +588, 0x19d7d7088db0b27d +589, 0xe4f8862ca8f6b87e +590, 0xceaf0d6ab4ba624d +591, 0x318965c56f79886d +592, 0xb1840d9bb60b720e +593, 0x387427e7549150ca +594, 0x9be3edb621a5d2ef +595, 0x9758993cca6a481 +596, 0x3733c5cd48a1590c +597, 0x9bbe26951c666fb1 +598, 0x74c7e89fefb4ba59 +599, 0x6aa490a23907053f +600, 0xa62febef1e8d7300 +601, 0xdbfb07bbba2fd4cd +602, 0x11ee9e4bbd4f358 +603, 0x6b40912657c7f02f +604, 0x8d56c1a9216714bb +605, 0x7fcd86985949c2f9 +606, 0x706bb172d5677f2c +607, 0xfb657efea1331957 +608, 0x6e3032f72a3fe367 +609, 0x509fb8c5b618a18e +610, 0x3599e957259222e7 +611, 0xaafc78bea53c9102 +612, 0x404addaf7ac55279 +613, 0x97db28b3b0a2dddc +614, 0xd3f5b151a9f5aefb +615, 0x1a6534a9be80a19a +616, 0x78f989eb80e055b7 +617, 0xe0200fe015112dce +618, 0xfbe67decef6204dd +619, 0x662fef92c8e00970 +620, 0x9a7838962250f5d7 +621, 0xac0eabb1621567b3 +622, 0x1874cf715cdc5daa +623, 0xd3281a25a82ceecc +624, 0xd8ac0e497b11156c +625, 0x3c8bf98f8210af89 +626, 0x971973ff9d428a3f +627, 0x1af47276bc157e63 +628, 0x671cd5e661ed0a05 +629, 0x71b8ffba9b976a0 +630, 0x8763f1fa85c5f5d5 +631, 0x61f3c56f3441aad4 +632, 0x86482f5e90362e3c +633, 0x8e9d9aceba401c48 +634, 0x51d916579d19d42b +635, 0x67bdfa28310ad3c7 +636, 0xb9ab819d6a00add8 +637, 0xaa12cb0ed2d507bf +638, 0xc636190dfc7f6d43 +639, 0xf3f1e6c104c5e782 +640, 0xaed0be2f07ad4313 +641, 0x1d782d74661278bf +642, 0x58e6501bc7e61fa2 +643, 0x8ca4ad0e02d7fb42 +644, 0x8afc9e9fe83d4b78 +645, 0x72cb69cf4abf0b1d +646, 0x7601a7b3500d474d +647, 0x97fee7da53b533b0 +648, 0xd6ab646f53c0e19a +649, 0x6480f60992f2fcc0 +650, 0x64ec7590c60a4c00 +651, 0x3ccab37f11acbe91 +652, 0x9ddd546f201299fd +653, 0x9a0dc59d0b545d96 +654, 0x8c5f366bd21664f5 +655, 0xc0af97b445bfc5ee +656, 0x29762536dc00c3fc +657, 0xfc30927fd8f1c257 +658, 0xac9aadfced7d59fb +659, 0x8d039f87658a29cd +660, 0x13a3d73580eacf6f +661, 0x80b80e0adcc11ac5 +662, 0x1e53c21e639f9d08 +663, 0x8a73352dc442bca7 +664, 0xec7cb2fe0e6b0100 +665, 0xfa5e63f403ac3f33 +666, 0x493d9a0018185f8c +667, 0x1b1d1f41c6cf5cb4 +668, 0x95b4caca3e2500a7 +669, 0x4e759e6f89f62f91 +670, 0xd0a76a3198d7c05f +671, 0x86eee6259cab63b5 +672, 0x1daab21067011b59 +673, 0xd02d9236ebc91b38 +674, 0x693e17ac2b70e1b7 +675, 0xceb5899aa14d0f86 +676, 0x59ffc317faf17ab2 +677, 0xce94f02892a0fa30 +678, 0xf7c9d6f9e753737c +679, 0x87258cf7ff6a29b5 +680, 0xb39fc8ea8aa52a0e +681, 0xadd4b4e73af1103f +682, 0x511f423730b25a4e +683, 0x7f673288e53502b2 +684, 0x9aa499e3b6295919 +685, 0x83841ad95e6a7a6 +686, 0x6e549a2457a850c +687, 0x4763220b923113c3 +688, 0x99737bb550aa5049 +689, 0x89eb31b3f707c4 +690, 0xdad5331dda8a58d3 +691, 0x5f1681518d5a21b8 +692, 0x258a0b9b24110918 +693, 0x8854bb025009fa21 +694, 0x7ac331fd885642af +695, 0xe520f0e9bedf0bf6 +696, 0xc9419e8801aa2afb +697, 0x356fdc0fc3702b37 +698, 0x6d6a25f39fbc9524 +699, 0x930f65c4dbf8ae94 +700, 0xa73d7bbf8c19c4b3 +701, 0xe473f700513139fa +702, 0xfef8f0e84c521bae +703, 0x88525351995576a7 +704, 0xa156b646ab95f272 +705, 0x1a46ff3b9ae7e723 +706, 0xf6d82b8bd9f2a80 +707, 0x837b8127d8f39ebf +708, 0x1f8e120ea11fc9bb +709, 0xbd0918421430f8c9 +710, 0x4ef121a688d130c7 +711, 0x3fef66f1cf180b77 +712, 0xa92070bdc6a0100 +713, 0x2444dcbb4853c174 +714, 0xe46b7d6234504df8 +715, 0xe5ac8fd968a5d1fd +716, 0x988828d885f04f30 +717, 0x9730c37b69f3d963 +718, 0xdb9a0d16bf0a2aab +719, 0xe75d00b3681941b9 +720, 0x518421d62db82da0 +721, 0x4da04c94268c1dae +722, 0xdcf2635a55b7da9e +723, 0xb679d8206c55a04c +724, 0x1fbf58865fec1e83 +725, 0x53ca7cc07c0e5785 +726, 0xd18eee3f5b57c813 +727, 0x9fc8d328e41d1299 +728, 0xb2231521e026e15 +729, 0x1a7e2a8df269acde +730, 0xe5f547b160b0a6de +731, 0xab01e7130bd70c14 +732, 0x82a051680f661a75 +733, 0x479da77dd9686ca2 +734, 0x1417cc197738b272 +735, 0xb65b5ced585a8186 +736, 0x40b5a74813e7a05b +737, 0x55481e0f404fc2c5 +738, 0xef1ca09a2640c44a +739, 0xa0f1d37ee2db47cf +740, 0xcabb0c8e551f0587 +741, 0x84227dd83ad941ef +742, 0x7b47691b6e8327d +743, 0x4fe615394f53d6d2 +744, 0x60bca7e568f65c80 +745, 0x8676b74f2d5600f4 +746, 0x70f256171f1eb9b1 +747, 0x6b1d25099f80e1fd +748, 0xd8e77e8a67ff3338 +749, 0x3ec375feb7727aca +750, 0x26b9ad4afd4be26b +751, 0x849e6f9bc5ec636 +752, 0xa34e3fad187c089f +753, 0xe369ba87f04ecc37 +754, 0x83c6e1c3985cab4e +755, 0x6ffc032379a15336 +756, 0x654645504b159afc +757, 0xabc97562087edfad +758, 0x4633765a9f068fe5 +759, 0xa226c586394d348b +760, 0x7034d9fd40133a22 +761, 0x89e1d142a1a20097 +762, 0x7a3e1387a5ecdf70 +763, 0xf0ae75084f0a1bc4 +764, 0xdcf97778ae782977 +765, 0x87996a44dbac128d +766, 0x94b102ac15479072 +767, 0x9d670a01e10c48a0 +768, 0x8f977a03176d0cb1 +769, 0x8522bdbed25653c +770, 0x8f2b64a9cd6b5483 +771, 0x86b2beaa71c92fbc +772, 0x40f896707639f820 +773, 0x40e7df1535fc03ad +774, 0x1d34c491e13debde +775, 0x862d5ad393292476 +776, 0xd33ee4efdd4b14d9 +777, 0x63ce5c7643b85ecd +778, 0xd28a7fe0700fd15 +779, 0x8c3536390f9b7b55 +780, 0xfaf87a9036dd0265 +781, 0x187e261c23b454a5 +782, 0x95362150f08e5f86 +783, 0x6588c21939d9521d +784, 0xc7cee242280b7526 +785, 0xc1b8f83462038485 +786, 0x68c2f342724de8d6 +787, 0x35c283dbca3c62fd +788, 0x556c441e9fdc5cee +789, 0x898ba42c4ad3f5ba +790, 0xc654a072fe9ce540 +791, 0xcc2da7cabdc658d4 +792, 0x518b6badf9c1ba7 +793, 0xd43b259427de48cd +794, 0xfe7e74d4415bea8a +795, 0xdee4cacb454d92c +796, 0xdfb09dde6d6c3000 +797, 0x5c0d4ce2c7a8d426 +798, 0x29ccf2d288f4de4a +799, 0x4106e7f40d2597ad +800, 0x3bc376950bccf69 +801, 0x65b74e149d1066e3 +802, 0x751d008e4f823e5e +803, 0x4a3b9a34d8ece205 +804, 0x372e79ed6d9461fc +805, 0x78e08cab6244f8d2 +806, 0x7d273315b6d9250b +807, 0x26c401cb05f556b2 +808, 0x3324d95fbc93408d +809, 0x14fb55fb83ab0a8a +810, 0x7ea7efcddd0a747f +811, 0x150a110bd5cb1b57 +812, 0x1122b31f5d20ad23 +813, 0xbd996a43507da1 +814, 0x6d11fad057e5a75a +815, 0x22a4d3223d77684b +816, 0x349973b5dda3d3e8 +817, 0xe4dab5aec267e32d +818, 0x371cbd61bbb7858c +819, 0x7e49182abfc0fc68 +820, 0x937722b126a7d173 +821, 0x29604490ccbe6611 +822, 0x6c8b230bdcc8dfaa +823, 0xb1c267c94d4550ee +824, 0x80d1fa6e33cde91f +825, 0xe205a132f35af0a7 +826, 0xe4e8e50899fea5c8 +827, 0x3a6517d09206dfef +828, 0xeff4e4f8efd0a4ba +829, 0xd8df88c992b3df74 +830, 0x5b0df3c40071c0ac +831, 0xd44a062781f833f0 +832, 0xef35653edcb68251 +833, 0x21f879df2bd3cfe0 +834, 0xdb5e837565891932 +835, 0x6da15316efae41e7 +836, 0xd33cdc0d05f8dd6d +837, 0x3c6588502a24be1c +838, 0x3d25da26bee94818 +839, 0x79979979960d383d +840, 0x8a20663424f816ec +841, 0x74c587d5824ee15 +842, 0x145f90c6b342c489 +843, 0xe2c2d15b8de95387 +844, 0xd9deaecc24e84ede +845, 0xce52add2f5c3ea3 +846, 0xd1da2db8cca0014d +847, 0xcbeed544f8791232 +848, 0xb55b421de003edf0 +849, 0xde102a5a87a9a5da +850, 0xd74fc9d34c964bd3 +851, 0xda7e1e271d197070 +852, 0x1167b33a6bad0d13 +853, 0xd35c886fd0e28798 +854, 0xfb3334085bbcef67 +855, 0x88f4957ddc912f99 +856, 0x7c1b0e356835cffa +857, 0x8c737bc009bf5a1c +858, 0x44edc242bfd88b0f +859, 0x391f8b5db15f8b01 +860, 0xd44794c8a4245701 +861, 0xefa90e38ba4a2f6e +862, 0x597f65c886e697b4 +863, 0x28972f6be3ca8677 +864, 0x18a487b5e89a9dbb +865, 0xffb15ebcb8a15fb1 +866, 0xa1f64108b7feeab0 +867, 0x36fc88b440612004 +868, 0x72a723294ba9af87 +869, 0x1a38da0ff8f187d7 +870, 0x529d7f6cd18f664a +871, 0x6a5941953b4732c7 +872, 0xe91243bd8fb27a03 +873, 0xb80c55de03262828 +874, 0xacb9183e5b28a8d0 +875, 0x4c4ca12eb3d5d2e5 +876, 0x758635a20eb18211 +877, 0x211e03e90d6bd001 +878, 0xe36e20fbf0f271b5 +879, 0x4daecb676fc64ebd +880, 0x8f1e82c4dd582eb7 +881, 0x6e3c35a21bca1b8f +882, 0xf3c2a69420f159e8 +883, 0x2cda4d630caba89f +884, 0x4c93f3f96360d308 +885, 0x4192046fb5e9d801 +886, 0x349f2b172f49599c +887, 0x7bbff8dd8b480e6c +888, 0x83b33fafc4388bf +889, 0x9a5440f806d9d1b +890, 0x8d6b62101dcfe51f +891, 0xbc7dd6987af227ca +892, 0x4338e67e0d6ba6a0 +893, 0x4a23deabbb5fc3ce +894, 0x9f8edc91e6356eb8 +895, 0xf6b723dd2dd5f80b +896, 0x35c558dd3443021d +897, 0xa559dd33c2cf594d +898, 0xa50ceeced7a82783 +899, 0x21107b581db4ee9f +900, 0x13e8dd9302e8c97d +901, 0xbd8491f437e57ad6 +902, 0x72f4c2a57c06f35f +903, 0x518fbb95071d8d7d +904, 0xcdbbe8d47f9b13e9 +905, 0xe8152b0f387251cd +906, 0x411070a4f345676 +907, 0xc589c285b962389 +908, 0x8b0eb9e285844319 +909, 0xe2b007f446a21b38 +910, 0x868ffafb958a6c40 +911, 0x19ccccd559408de0 +912, 0xa7666f366db0ae71 +913, 0xd78c5f137da6dbc2 +914, 0xeeecc913fdb9af03 +915, 0x7a5afb2f3d54a396 +916, 0x64fadf73d7ba200b +917, 0xaa1b82c6b4b346aa +918, 0x9a312d9482244a60 +919, 0xadb3c0a30f68d0f4 +920, 0x21eee75a717008c1 +921, 0xcda2779023f54837 +922, 0xea3c577c6d7783e2 +923, 0xdaae89efcd431a13 +924, 0x9a6102d2dafaded8 +925, 0xd29443448e01734e +926, 0x6b968e58c3d5bcd0 +927, 0x13949d0c5c0f9d19 +928, 0x7053eef909932489 +929, 0x49fb97e33c279171 +930, 0xc955e4854e254d03 +931, 0x3300cb752a7834fd +932, 0x8319585b09da0928 +933, 0xd35c64e4ce23a294 +934, 0x9a41d980ba1774dd +935, 0xff570729be1f3f02 +936, 0x3f68ae1c3e690a41 +937, 0x6f58a3e861159e42 +938, 0x111d9975e94f0004 +939, 0x276d3ea0ff1ca6c +940, 0x4209cb1f5ca1c594 +941, 0x71699dc4c58f1bcf +942, 0xe0288bffc5a27a2e +943, 0x6c0962c36163c4f5 +944, 0x3a8ad088b4fd204f +945, 0xb945dc7721092d36 +946, 0x315f4c1738bdf365 +947, 0xe07ddd7121cafb70 +948, 0x626fadaee66f331e +949, 0x6fe3f71dd5e7ebe1 +950, 0xe3cfb6b53bd8713c +951, 0x30f5b732f7070968 +952, 0xce2f941f93b957f2 +953, 0x116897bad7f55bca +954, 0xb9d2c4a98826c3ff +955, 0x9672c28485d1c95c +956, 0xd0656535c3df1e44 +957, 0x15294f18a999528d +958, 0x82a98977ad1e933a +959, 0xddd17b6eeced5f84 +960, 0x9901a04270fa2d5c +961, 0xcd2a8d3ab69a0c62 +962, 0x706bf86127a4597b +963, 0xe614aa96ed708afb +964, 0x7f6361ae8f59987 +965, 0x6a355657b59c4874 +966, 0x5211dca87f30cdd +967, 0xa21cbbc602f58ee4 +968, 0x68dff176c9b02a7b +969, 0x68f89bb7bca83c5a +970, 0x229cb884febc7e56 +971, 0xce4f300cf6b70884 +972, 0x6ad3f343c76c5e0c +973, 0xb059a099f121222e +974, 0x9e990641d81a63b8 +975, 0x5564e79afe160ecb +976, 0x2a9fa9c590511dcb +977, 0xca36751ba40931da +978, 0x23a332a9fe1104aa +979, 0xdfe116c321547662 +980, 0xf484bfbe18f2c1cf +981, 0xf8f2b4adf2d1ad4 +982, 0x4308800511929ba +983, 0xe2773c41e0082a51 +984, 0x6b74adc21bac6b3a +985, 0x1faa6a3704bd1b66 +986, 0x89e3e641298e87cd +987, 0xcb2f118548abcdc3 +988, 0x690e34dfb4153ab9 +989, 0x103d668edb5f7e88 +990, 0xb29d9f22b3b1d4a4 +991, 0xc4ce3be9022b314d +992, 0x1cb3d5af1306da15 +993, 0x8236da372d964cce +994, 0x79188ac299f06c2b +995, 0x953dfd978aad2545 +996, 0x6058e1066e7285cd +997, 0xf47307b50589e391 +998, 0x2923873ecd9c4d32 +999, 0x4c44d61328ac5e4a 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 000000000000..779761d0f8a7 --- /dev/null +++ b/numpy/random/tests/data/pcg64-testset-2.csv @@ -0,0 +1,1001 @@ +seed, 0x0 +0, 0xd4feb4e5a4bcfe09 +1, 0xe85a7fe071b026e6 +2, 0x3a5b9037fe928c11 +3, 0x7b044380d100f216 +4, 0x1c7850a6b6d83e6a +5, 0x240b82fcc04f0926 +6, 0x7e43df85bf9fba26 +7, 0x43adf3380b1fe129 +8, 0x3f0fb307287219c +9, 0x781f4b84f42a2df +10, 0x36dac886f4232c6f +11, 0xa32006a96a8d46b +12, 0xa56e609a788ce098 +13, 0x75711678fa371144 +14, 0xbcdd4619fa063896 +15, 0x5cb5c9a1594f1a04 +16, 0x799e6cc7d09bf3fd +17, 0xda1a4b52f72a8c6f +18, 0x374b6f698c864e48 +19, 0x96a3e4d45b8d252d +20, 0x5fc89e7cbf7735e4 +21, 0xe0cfe37beef7efe6 +22, 0xc3467c95f4649808 +23, 0x95cbda6a3275f18a +24, 0x3a4dc1e59bdb4172 +25, 0x47f8755023ac78b5 +26, 0xef8e166bf07dfa95 +27, 0x40065cf0fa99882d +28, 0xbaa083ad70102eb6 +29, 0x7c88e9d1a72a8dc +30, 0x1484e44aa83e901e +31, 0xf0f8df78086fdeba +32, 0x5114e38e0cff505d +33, 0x7e04bb9a2828c944 +34, 0xb88c0de9e2af5658 +35, 0xecba992ca7e9178d +36, 0x8b40b65347cfeffb +37, 0xfce9281a9381a55f +38, 0xfde34f9f228fc03f +39, 0x8c46656aa79eba9d +40, 0x1ed0d3f416073189 +41, 0xd7adcc20a26d48d1 +42, 0x2429dcfa355eddba +43, 0xec100f2285aaad68 +44, 0x91a83984506e1ef4 +45, 0x4c10c0f973e3cba5 +46, 0x45d0d0ad9ab6890e +47, 0xa52b22d88ddb6090 +48, 0x63f7e7549bf80c43 +49, 0xfb03f87e5ea7137d +50, 0x822f96594246a4aa +51, 0x42242b1335cd3424 +52, 0xf78652fc51ec76ac +53, 0x24db7314bda69cc5 +54, 0xcce4cf66737c8427 +55, 0xffd70eeca33ed90f +56, 0xc154aff2caddd546 +57, 0x59d47a8ccd59e1bb +58, 0xabf793045ca561f8 +59, 0x3f1486708729b21d +60, 0x76ed98409f3f9abe +61, 0x3f0bb2cd7cedd012 +62, 0x448f78da1713ac85 +63, 0xddbae7151c1578b2 +64, 0xcf94237ec0973cd7 +65, 0x76a0657cedebac81 +66, 0x2b13b564bed7a3b3 +67, 0x47a6fc0f4604c781 +68, 0x22acf016523ae80f +69, 0xf728771b939c13a2 +70, 0xab4aee3986c80ec8 +71, 0x61d8c8c918b3fe52 +72, 0x7a40380c747f9044 +73, 0xfaf974af2e96a882 +74, 0xb8bd56d90c69d42c +75, 0x7cea307dda515497 +76, 0x56d0858a27ded2a3 +77, 0x8717ea17698706b7 +78, 0x6b34d0c0587e8867 +79, 0x387a8142ee80d29a +80, 0xbba414cee59e3194 +81, 0x6d2fe8bec0e51a8 +82, 0x11d5dc961ba15ec5 +83, 0x7af1ae07932b2fb8 +84, 0xb13ea6b28d63b57e +85, 0x7e89a6f060cf59c5 +86, 0xad1f662c4daa4764 +87, 0x929a054dec3e229f +88, 0xf7f41c2a34920f09 +89, 0xf0eac1b75822b72b +90, 0x24f311773d90d399 +91, 0x9c2147da3d098c17 +92, 0xa62963f5bb0f8b9e +93, 0x97f650195285e480 +94, 0x602433fd24fe4125 +95, 0x6f17d6e3b5fd704c +96, 0x3ad6f2cf0ffd6a04 +97, 0x73a6d93edf693e03 +98, 0x467d4e6fecdfdb20 +99, 0x6aadbba2b2f8a2f8 +100, 0xc865bae9d8713526 +101, 0xa94d7c6b462e5acc +102, 0xdcbb47fdacd4d865 +103, 0x80aa6a71fd60cb40 +104, 0xf27ad62910288223 +105, 0x88f93784d309825c +106, 0xf7f9a500b821c886 +107, 0x6cd6e37a5dca4830 +108, 0x57694853b9c75561 +109, 0x9c7ef1aa6b8f2c1 +110, 0x12046439309d6e40 +111, 0xee3d652c43bd35b9 +112, 0x3838110676b26d7a +113, 0x9efd697137fa24c9 +114, 0x1eeaa149a7edd5be +115, 0x17eb32cd212e374a +116, 0x73dd5b7d7fd3b280 +117, 0x788e514de9649f29 +118, 0x6e2fb96fbf87fe8b +119, 0xc736a34c7ea74137 +120, 0xa4d48bb7df0e3c51 +121, 0x25b66ee78063d37f +122, 0x9058e087b9696e7 +123, 0xa2e6397ebdd3d935 +124, 0x394a16ba856e6899 +125, 0xe4aad4f1bc61d046 +126, 0x5e4904686af5c43 +127, 0x4e58956c61a1880a +128, 0x7328c827d6236eff +129, 0x29463809b511cf73 +130, 0xceb2c403cef62247 +131, 0x9ccc00f358aa8346 +132, 0x6fdc1c42421ba33 +133, 0x1111d660460f5300 +134, 0x97a4f922e55a9226 +135, 0xbc2a217152bfbc63 +136, 0x3617700c68d104d9 +137, 0x8eecc63c4a929622 +138, 0xc69cf9d8f8b45df3 +139, 0xa2a8ca8262f8921b +140, 0x4339edf9e292f9e0 +141, 0xfe385e2e7f6e1a1a +142, 0x5f30d1b803abc1d9 +143, 0xf123207050238c3c +144, 0x79e3401200b54b1a +145, 0x858d7ce163d4de92 +146, 0x5803a44cd013b965 +147, 0x17c65b0b01800940 +148, 0xc50b38bb58dcb3c7 +149, 0xe476e9925898603 +150, 0x3972fb0fa748a3a5 +151, 0x93da971efb1036f7 +152, 0x658bab8ef6082bf2 +153, 0xf664abd0de92444f +154, 0xa2145e8039e61d87 +155, 0x28af5560cb0ee0ac +156, 0xc1e43e6a30cefef6 +157, 0x74f61d623cc6965e +158, 0x3ee0139a07b6c130 +159, 0x214992e8a6134c54 +160, 0xaa83b771c9421231 +161, 0x15487762c93cf5c6 +162, 0xa3d37b883fffdfe8 +163, 0xe398d2bd15c1c511 +164, 0x3154f894aedd5938 +165, 0xc7ed5190721ec2b5 +166, 0xca02cf8dcfef83b4 +167, 0xa22c6a2e5460e0f3 +168, 0x2d72e4d264875109 +169, 0xf282e30c8b945616 +170, 0xa1a286624feece2e +171, 0x6f773be8548d3fe +172, 0x8c6dc6f48c83c30f +173, 0x13dc5926122501a1 +174, 0x5537f3d25d126e0d +175, 0xdb654b8409365aa5 +176, 0x55d8f727e066e818 +177, 0x534841122140f9a3 +178, 0x4e4ecc7b2ce8efa0 +179, 0x3655d535028e4044 +180, 0x6c2ad71379f15365 +181, 0xd1f1238395ce193c +182, 0x4ecd9ccc56595a72 +183, 0x3304220c15b60f7a +184, 0x3726fecf394006bf +185, 0x4523e03e39a92ac1 +186, 0x191c97036c0e20a8 +187, 0xbfbcf849ecc37cd5 +188, 0x3c6090d256b1c780 +189, 0xf7e94dd0d3e02fd8 +190, 0x83034fb1c17bb99f +191, 0xa7be8e0eb37c9260 +192, 0x177d2c560b0b55af +193, 0x55da4c839514e82e +194, 0xc9b393b79b0e7617 +195, 0xe9658403d3a140 +196, 0xc86401b988be38e7 +197, 0xe82baf54ee5df9e1 +198, 0x3a562e6572a853a4 +199, 0xcb83facbed1cb364 +200, 0x4db406f08ea62242 +201, 0x9cc816f5376ab97a +202, 0xe65a32f96a78b09 +203, 0x59e7b42c496e2c2f +204, 0x7e3e59a4546b6b33 +205, 0xc51a371516d5adc4 +206, 0x19ba384285a523ca +207, 0x5b998f71002a0912 +208, 0x81ee2f95f53dbce1 +209, 0x966a0c0bbf15492e +210, 0x80f88202ff2d29c2 +211, 0xf827f45274e32733 +212, 0x66a2611b73547490 +213, 0x1b2c3c3ae80997d0 +214, 0x264a86e09c63e4c9 +215, 0x35d4bf9c9d0d89a2 +216, 0x6051e319babb305f +217, 0xdf0d08608262be49 +218, 0xbe7aa9a7697278c2 +219, 0xac531985f79fca17 +220, 0x7ce7de0d95ba34d +221, 0x9a03956d30de1ee0 +222, 0x8106a5873e7950b0 +223, 0x804c06b1fab989fc +224, 0x20d5fe19357e95dd +225, 0xf3e89c08d1841c79 +226, 0xfc93b079bdb323cb +227, 0x8f6eb1dea40eda88 +228, 0x6e7f6b657f6d971e +229, 0xf2b15bb03a49e9bf +230, 0xcf7fed1aff1786b +231, 0xe53366adc5bafe42 +232, 0x89b853ed67fc2387 +233, 0xd13dadf3828f1df7 +234, 0x2f884ffbb83075b9 +235, 0x8efd2baea4771d71 +236, 0x7872e80c946c6bce +237, 0xcc487bc4ea869070 +238, 0x820609347e4fdd75 +239, 0xe939e3c63701a997 +240, 0xf70ed361e42164e9 +241, 0xa9f29046fce9ba8d +242, 0x61edfa750175e868 +243, 0xb7d2424653bde389 +244, 0xdadd225205e74ef4 +245, 0xecfb9a633ee3c774 +246, 0xcbc69459f0634f30 +247, 0xdbcd82538e0785e2 +248, 0x2b272f59ad36e01c +249, 0x601a38897a57cc68 +250, 0xfa012b9e5722d8be +251, 0x5bce8d48277d7338 +252, 0xd1b6ca2b93483dc2 +253, 0x8b94eceb88f55be9 +254, 0x93403aea5df5da18 +255, 0x57b6fcaf351c16b8 +256, 0x70f5e54095404bd8 +257, 0x9124d47160362770 +258, 0x987ed72af8aa305d +259, 0x71e3a8d5156f82c7 +260, 0xf788e966e86f7004 +261, 0xcf0cd5911c4bb0e1 +262, 0x3340b119d3e2f28f +263, 0x9952106be6e3bf95 +264, 0x99a6213e19fe9d1a +265, 0x4f0d3811a8a5d481 +266, 0x62d732ee5f975dd2 +267, 0x3abc8340ab323ebd +268, 0x15da761a2518c843 +269, 0xb453de7d4d15b261 +270, 0x4adc2d7cc2cc0049 +271, 0xcc9b7fa135c7dba4 +272, 0xa14857a738db2b52 +273, 0xce036b49e28c19c7 +274, 0xaee7e9fde421bd4c +275, 0x15dd298915099a9e +276, 0xa3fa6550b639b66b +277, 0x5f27c59b035a6532 +278, 0x2eef2e6292288715 +279, 0xabd211c514e3699e +280, 0x6d7bf9b33f8b09e5 +281, 0x91ff83561361c170 +282, 0x8f8e309797a91e4f +283, 0x2b11ef1cedf1036b +284, 0x6fc36ed305d27972 +285, 0x7e294e03a91eb01f +286, 0xbe16009d8b2f38a4 +287, 0x2bf69c7b54e60cea +288, 0x860079a07fade829 +289, 0x8f0ce6ae4c90d38a +290, 0xab10e5f8ab4835fc +291, 0x49ed43ddd4ca0a76 +292, 0x201eaa53b6df058c +293, 0x2d9a4fdb16f6c1c +294, 0xd3406193e1dd0760 +295, 0xad38857b542ddb6a +296, 0x52ec1e450363aad8 +297, 0x6e65469594331886 +298, 0x4b027ce344dd6660 +299, 0xbc801654b4a1ccad +300, 0x155be4bc51328b2c +301, 0xa9a1965f9b2b5bdb +302, 0x386b8dc34de0889 +303, 0xd60ee4b1b9cbb057 +304, 0x6c1e60b6914c4876 +305, 0xd07bf84dc30bf653 +306, 0x362d5b19b3f4f7e9 +307, 0xd145b8fef9a6a3d2 +308, 0x5c401126b505dd09 +309, 0x8f5d1d4446f9cb4c +310, 0x725618359f1a3e38 +311, 0xaedad9cf455de2e5 +312, 0x7f7e4e549b4bde1b +313, 0x35002b8e995f815 +314, 0x9aecaf8f393cade0 +315, 0xf346a49595886d86 +316, 0x459d5a9e92e9c149 +317, 0x60885682c3d6ff0d +318, 0x90f5e985e08bfc3d +319, 0xbf413a432e1a1b81 +320, 0x789503524aa48aa9 +321, 0x7880e5bb484bd49e +322, 0x7426535c324b7176 +323, 0x190ad37f84acba3 +324, 0xbd52510631d4f5d7 +325, 0x98f794ad565c986d +326, 0xa0ea374e66c0bf56 +327, 0xd683fe7102145335 +328, 0x9b3dac61db2f2930 +329, 0x470d31e3096c2450 +330, 0x1f445f8292f6f3dd +331, 0x1687ff432def56a7 +332, 0x887d4e6617525278 +333, 0xcd81ce8cc70b13ff +334, 0xaadbc4c3525c18e1 +335, 0x96d81490c362b621 +336, 0x128b95092e36796c +337, 0xffeffbed0980cdb7 +338, 0x3bcef6c52b36d07a +339, 0x400879c888eeabe2 +340, 0x373c9978059787d +341, 0x35979fef9e20050a +342, 0xf4581367f3fc43b +343, 0xcec7b91352ed0186 +344, 0xa7b06e92b765203 +345, 0x6713f0b11fb9f296 +346, 0x95c53b86deafbd95 +347, 0x3694844a5eca42df +348, 0xd0f334ea2c650574 +349, 0x5ae6771044110ddf +350, 0x9f61d9087e7d36e5 +351, 0x28f04e48625e3e5e +352, 0x6164d6b5445cf130 +353, 0xa36b5c2de27084be +354, 0xa099a43d5c5f21bb +355, 0x706edfb05fbe8b9e +356, 0x7aacffffc81ebc3b +357, 0x6f49121baebd0e6a +358, 0x41fda7ba6df8f4cb +359, 0x1bea4b596dbac5ac +360, 0x71dd0261d65b02c6 +361, 0xad7f50624c15e9c9 +362, 0xf7c4eeb84d4866b6 +363, 0xa5e23dd382f48bdb +364, 0xe6ffdf875d534bfa +365, 0x40104d8444f75a7c +366, 0x8218a42f24a88364 +367, 0x9d3f9382759cae86 +368, 0x101d7adffbd9ebde +369, 0xf9fe3578d6b739dd +370, 0xd23c47039e882eb2 +371, 0x37fc4fff590191b3 +372, 0x2a672fc8cd3e0cf7 +373, 0x995b8faabb4332c7 +374, 0xabc6117aa665a743 +375, 0x3fc49d11869352ea +376, 0x4ccc3cfa9540797f +377, 0x111c57f059fa3ef4 +378, 0x44a737bac79496bd +379, 0x37924823edfe0774 +380, 0xa4d8ee07ab241d02 +381, 0xbb0bf46c50f349ac +382, 0x4db0a8506e22199c +383, 0x93239f377c85ba51 +384, 0x56f51e3970e409f5 +385, 0xe82d51ebc177609e +386, 0xec866d8b473eaeb +387, 0x42f8018bb955abed +388, 0xf58ba8a916b04fa1 +389, 0xf12d2f0cb0a41cff +390, 0x8102b5f91923cc2a +391, 0x91d95fcb9cb1346d +392, 0x819ccf0d122537ac +393, 0x34646b1c3f9a8527 +394, 0x4a3a7df812ff79cb +395, 0xc3d0b50ed434ad24 +396, 0x3e6cd372b453b5f0 +397, 0x39101f6226c43c8c +398, 0xff41e5b6b7ff540c +399, 0x1e8d77bc3f12e0f4 +400, 0x748d0860be568eee +401, 0x5baac1f743bfeff3 +402, 0x8bdbd895b2eed2d8 +403, 0x5d3a01fa82bd88d4 +404, 0x577271d2de3e06f4 +405, 0xd4fccaeb0db61acb +406, 0xa088377ed2b1d841 +407, 0x6f2e9e1566f37b5b +408, 0xb8d85eef688c049a +409, 0x6b7c06c55078761 +410, 0x223cd94cad1e0c32 +411, 0xbf27c193ae5881e3 +412, 0x5b784893a36d57dc +413, 0xdc9fa53968c262dd +414, 0xd7e820c76855fb61 +415, 0x72260eb94f096e2a +416, 0x49144b5732ca1b94 +417, 0xba8d85a47582d428 +418, 0x558abe242dc84de2 +419, 0xc27b1d54557b9de5 +420, 0x80c1f06559385330 +421, 0x4a5c1d4252675c73 +422, 0x225e3a9f7b2da067 +423, 0x9ac95bac9d2234a1 +424, 0x696e500589e0e490 +425, 0xd0fe548d81c82185 +426, 0x68d8b783037b4743 +427, 0xbe1664f1a8d814f +428, 0x2304308b691ca712 +429, 0x68e680af6b7189c5 +430, 0x13abe6c989949072 +431, 0x4c209f5029a59d0b +432, 0x63361139df6fea7a +433, 0xf07c52d8272cbdb +434, 0x665023146f27fa7 +435, 0x7cb535c55ad7ad0e +436, 0x76e366c7317eb1b0 +437, 0xa7d9b80b51585e9b +438, 0x85f0bd60122198b9 +439, 0x34bc89d7e7827fd5 +440, 0xdfa1167988c85807 +441, 0xe78f45588bfdba02 +442, 0x172a023eba7357b2 +443, 0x7bc4c79e06ea755b +444, 0x8aace6120b766b95 +445, 0x17b43a5a81b0db26 +446, 0xbc2b95819d959ff6 +447, 0x1b8841f2fe9c4622 +448, 0xc094a747ec30d67a +449, 0xf5b93ec01484b937 +450, 0x659bbe8bdfd43f01 +451, 0x9d96c22bcf9c64c9 +452, 0xcf7df324fba052ec +453, 0x5e4acd4f9e048e0b +454, 0xe3a0e7e9869c5dd2 +455, 0x4eb444727e1c346e +456, 0x7f6cda1ca7b3eb67 +457, 0x72fccac63ca649e9 +458, 0x711bfbf79a093651 +459, 0x5d48599fae7fd6a3 +460, 0xcc640119a296b34e +461, 0x39acfb198b2b439 +462, 0xde759b50e2db66f9 +463, 0xe83bf8363827e06 +464, 0x484d50365017de87 +465, 0x4c3b5dbacd68394b +466, 0xbbe47788c079218c +467, 0xd44099290c25fe62 +468, 0x3b7d1bd6f91f3857 +469, 0xe7366a677d2b7eb3 +470, 0xfaa770590b197910 +471, 0x610b7a2fe8c4e80e +472, 0x13451e1bf520a796 +473, 0x7e3d18c47e821077 +474, 0x8fd3a77c86eb9804 +475, 0xf24be740c87eadab +476, 0xd5a52e6d0b58345 +477, 0xae386b5ca037a8d +478, 0xb59fd16baf160f26 +479, 0xd4a05b473f6e0a8a +480, 0x47ede6678c2c6420 +481, 0x8851ed397da6f850 +482, 0x1de775cdb392d89b +483, 0x74e6c8ec9513ea38 +484, 0x30ae39e04187a984 +485, 0x614cfd09d043d601 +486, 0x3e0173138f562ee1 +487, 0x822d415a26bdba96 +488, 0x432f6dec77edd9a8 +489, 0x47a3a179627546b8 +490, 0x845dd7ffb1fe6d78 +491, 0x9778d5782de13a48 +492, 0x760198319b3cacce +493, 0x420ee262d07dd7c +494, 0x847c7424c365df20 +495, 0x56b3b590fb83ba16 +496, 0x7cd2410390a3e797 +497, 0xbb0c21b47aab8857 +498, 0x2743883e70a36a18 +499, 0xff8b29cdc75ebb7 +500, 0xe1e04a0f0379686f +501, 0xcfdf3083b792f281 +502, 0x27392ca026b55e88 +503, 0xeeb195994fd56abb +504, 0x7cf210041345882c +505, 0x3ddca2b8951fea4e +506, 0x21c89d88a3833996 +507, 0xe7128bccc4b25c9b +508, 0xe39b0fb96a4c05ae +509, 0xedf5326550594554 +510, 0x4aa45fe66b575558 +511, 0x2799fc8d3b06f777 +512, 0x2824863087187501 +513, 0xa15fa00818118906 +514, 0x559fc9e9344a310 +515, 0x1682745f8d571671 +516, 0x80b54f29f47a28d0 +517, 0x38e28103ffd9f771 +518, 0xedb5f440dab80945 +519, 0xdb0b8d04cece6091 +520, 0x1f60a7cae5ae8412 +521, 0x6719c0405e92b31d +522, 0x56752def7d642302 +523, 0xa5b0900f93c352dd +524, 0x5b82baf53be8983d +525, 0x7726202ccee5cbb6 +526, 0x1641c84c7f87a765 +527, 0x835ae1a82be4265e +528, 0x5f9ccee69c1d9da +529, 0x3e2a2228e21039b7 +530, 0xa45873582866d005 +531, 0x7fbeffc99401e59e +532, 0xcf66a6a974057890 +533, 0xd53704a96af96fd +534, 0x1a8b5e3460704b64 +535, 0x6939b27bb32ba451 +536, 0x3c39293e637a0115 +537, 0x335a6e6b779b8c4e +538, 0x75235d767dfd3d00 +539, 0xbdf0b36936b17c90 +540, 0x982dc5e4915a3a3a +541, 0x74657ac256407f55 +542, 0x603a724457b796b6 +543, 0xf178694f7a3f98bd +544, 0xe712de12db2aba47 +545, 0x1ca272d99a3355d8 +546, 0x93e7054d3e8dafc7 +547, 0xa29597810eff04c1 +548, 0xade242c0ae4bcea3 +549, 0xbcd226e2bd9d0e64 +550, 0x2e02e5736f889a +551, 0x3622dc09f5fdd576 +552, 0x6e66bd2a10d78705 +553, 0x71d8f19110d5b4d0 +554, 0xacae934ab3d759f0 +555, 0x68d670d5f9272132 +556, 0x571fb09d082e7da7 +557, 0x154540c51b7d8b33 +558, 0x1e2f3710c0b6890 +559, 0xaf26a826ef444b30 +560, 0x9fc9fdbd9342be72 +561, 0x9b33b306d22a35e0 +562, 0xb6d5895f56d4197b +563, 0x92fef06c1353b2e3 +564, 0x804e3eb42e65b938 +565, 0x73d5cd4bb7270902 +566, 0x274b8ac4925da8fd +567, 0xa9a57999f5df2e2f +568, 0xa6000be059e088b +569, 0x57de4fc48c9e9e84 +570, 0x16727392e94ee9bf +571, 0x53c9032f62848c4d +572, 0x8a8ddd8fcf0676dd +573, 0x1436de7c1735087 +574, 0xfa93b7d1425e8667 +575, 0xec34ca5f3f84bb2f +576, 0x489ed44d0880c4c8 +577, 0xb3b6051de7a6f740 +578, 0x2f303cb0f4040f11 +579, 0x302c42a6adbcbcb2 +580, 0x28ed7b87695cd600 +581, 0xee78d3b782a2fcd0 +582, 0xc47a2441a1082032 +583, 0xec9965704a044f33 +584, 0xcb1563e968460dc +585, 0xfecbb4fa2b544f93 +586, 0x3f3d7437a6d29a3d +587, 0xe4bfaccd729414ca +588, 0xb741ed954572d172 +589, 0xf34b49bf10ae47b6 +590, 0x1fbd1f068f1b796d +591, 0xc1d556e64345b226 +592, 0x85bbfa50a899c7be +593, 0x5310045dcf0fea8 +594, 0xbc6f6fb7f00e5960 +595, 0xf8bdf4074f2b5f5e +596, 0x2a5817aa122dc97f +597, 0x6d5ef86d6b8ad0ce +598, 0x96e7ccc235abb79e +599, 0x8d531c4cea492f66 +600, 0xfc124a123b4ce02a +601, 0xc6087ffd9130c2ca +602, 0x3a724c46f0f06175 +603, 0x59980713cfe4fe92 +604, 0xecde418e64a11bd +605, 0x5c9b333a0f0337cc +606, 0xcf014d508fc8e83a +607, 0x83998bb2aa4e16ba +608, 0xde8f5167ac0a40d9 +609, 0xe93b1846914c0dc7 +610, 0x668831ca8fd50c25 +611, 0xec764b87e402c28e +612, 0xd0e1303e56f6b268 +613, 0xa6b9f3c4872dbcd5 +614, 0x12a89c116ad924f0 +615, 0x23857c375ae928c8 +616, 0x29b117f63f2e8c1b +617, 0x64ff6cce272aa46d +618, 0xd40fb15b38d59f70 +619, 0x6e5a6257c4cc0c66 +620, 0x7b54845e6e119a4e +621, 0x9d88bf3dd9fa0f0e +622, 0xb6687fd4980a5d43 +623, 0x4f2e3fef88b640b8 +624, 0xf07ac2f7e2df40fa +625, 0x24059bd0ecb6c6a9 +626, 0x6204a47cbd57453d +627, 0x8477fd1a13ea9678 +628, 0x4555083f5eada49f +629, 0x352443e5d984691c +630, 0x3e904f796a9c5ffa +631, 0x11e182bc43754609 +632, 0x608cdbe03699a5d4 +633, 0x2619146efbf59f0 +634, 0x9b852370063940ee +635, 0xa1d8e7e91e42a52b +636, 0x19179affce38fa3c +637, 0xf68ff1ccce70380c +638, 0x12103cb41741ab38 +639, 0xdca7902fa6d960b2 +640, 0xad46a2fc70025445 +641, 0xac92f0b2d150d716 +642, 0x5de115babb43326e +643, 0xf335366fd69e4bcd +644, 0xe9aecd1f88889cd +645, 0xbce60087987b51d1 +646, 0xcfd395a167103939 +647, 0x2fdcb12826ac806c +648, 0xbd5129970869ccd6 +649, 0x5e922b68030c2698 +650, 0x7ada02a56d17779a +651, 0x7a1254c652b99ccc +652, 0x8be78733623db772 +653, 0xc22439789b68f0a8 +654, 0xee51ad4ab1a9a6ed +655, 0x44b15fa27694d9be +656, 0xc5b93e6c57805153 +657, 0xcf03df495c283a89 +658, 0x5c2a41954bb44bb +659, 0x9e651cb8c650dd +660, 0x73a20ee82570d4a8 +661, 0x5f805cab085e971f +662, 0x5354410872a8f587 +663, 0x1b50ef4e9519338d +664, 0xdeb873412301a1ce +665, 0x3a286bb2f5f8db39 +666, 0xad117a0d4dc7f82e +667, 0xdd880d581169d989 +668, 0x8356be106382a704 +669, 0x7c684ad93e996ff3 +670, 0x6b2d09e61ac02c11 +671, 0x99ad8c074fe046dc +672, 0x4a9b4f0e7c4ffa24 +673, 0x38afdcb5893b466 +674, 0x7ad58ef97c3d35c +675, 0xdd7c17c0d67ab69 +676, 0x61c77caf27938c86 +677, 0x978fc491080c0cee +678, 0x4c1750f8684c1ca4 +679, 0x86b4c683d5fe657e +680, 0x720e2bd8ec76cffc +681, 0x73ca52b4a7dd3b85 +682, 0xeb10a691e12ea3ca +683, 0x90355e369297b259 +684, 0x6c6bc16f639678ca +685, 0xd989f4c724f8fba7 +686, 0xbb1ba7e2ca1c4391 +687, 0x81e4194500a0d267 +688, 0xbb25489c1dcbf93f +689, 0x74d26b75e9f57fd +690, 0x59c085fa99b6493d +691, 0x3359805b0fc3fef9 +692, 0x60ef0f3a85e60650 +693, 0xf1a3692c8591e8d6 +694, 0xd7c8d2e7f3d3546e +695, 0xe8fc8518c11ca881 +696, 0x3380ef12114d1818 +697, 0x87203c98ff21fcaf +698, 0xbc37f8e034002ef8 +699, 0x891b7c3f55d02300 +700, 0x814eec8ff8956f0a +701, 0xa370639852acceae +702, 0x6c566310b6b00f15 +703, 0xd69fe78b9c8a05a6 +704, 0xb7b0df518738419e +705, 0x2a0c1185b29ed965 +706, 0x636c841214c0a8cf +707, 0xbf56297859e9bb72 +708, 0x2b5b9d432d6d008f +709, 0x1ea586cf0f86f542 +710, 0x23a2a1af76cbc988 +711, 0x6c72c799b6ed93f3 +712, 0x2266785315f3bb13 +713, 0xb68cd6e87b94065a +714, 0x5d395704514bb808 +715, 0x334bde59d526ee4 +716, 0xc5a6d87f96f055fa +717, 0xd47001378b4dcf08 +718, 0x7305818a39057557 +719, 0x8f72c128eac6d32 +720, 0x4957ed799339bbdc +721, 0xeb47d505f61dd5fa +722, 0x8ce8817cd6acc93a +723, 0x84ef66e511a52f35 +724, 0xbf5aa34bbaef7e1f +725, 0xadaa5ba2a5ee660e +726, 0x6eec8ac924058eea +727, 0x8af63be4d1a1b202 +728, 0x88eccf85fd9fce32 +729, 0xf19a1122f394af05 +730, 0x8dcd15d1c14f5077 +731, 0x6c0f2e6135e36545 +732, 0xe58f89bec4d929c8 +733, 0x4eea88221d983ef9 +734, 0x51ae3956d53e1a80 +735, 0x40d8a172bf713bb6 +736, 0x3e33536e43ad4fa2 +737, 0xeff9938a179138fa +738, 0x3e372bff1f51df8b +739, 0x59b86a407817c86c +740, 0x947164c2c57f9bd8 +741, 0xd8e67bb799d84475 +742, 0x4d9ed254d8189595 +743, 0xa021d8d181328996 +744, 0xc703e402f8e4688b +745, 0xd1eb104c970dd5fe +746, 0xd5bf4683b9337f8e +747, 0x98f405a2d998f06 +748, 0x59c734ddd208e85c +749, 0xbd167be2d43fde24 +750, 0x70602daab163fbe2 +751, 0xeb2f2b37cbfe13e7 +752, 0x28baa8f3fc4c4666 +753, 0xe212ffe352ea5ce6 +754, 0x538b93d2285eda3a +755, 0x3a9482ac69a39e1b +756, 0x3a98983ed4367767 +757, 0x1dc851c69e35d601 +758, 0xac7f83e4b02e9bb8 +759, 0xa939f99c5615ef7b +760, 0x439437f129076339 +761, 0x79a251bb1d50ce25 +762, 0xaa7b6ff8f13a7424 +763, 0x1b244bd86404327b +764, 0xc84d99185ab2a7d6 +765, 0xf6dcde975493c40b +766, 0xdee46f4346cf6af +767, 0x739b75df1fe18712 +768, 0x3d05cb298311f3e9 +769, 0x1fba9d9c10dc7780 +770, 0x31637fc416267053 +771, 0x46694e36246b8be2 +772, 0x8c67095ae6eaf1e4 +773, 0xebe2a68c27963dca +774, 0x532d344b14306cf2 +775, 0x6a847c8f3ae2ac92 +776, 0x8034bcb5a50cbd6a +777, 0x7544766784261059 +778, 0xe641799652df63ca +779, 0xd8cacad7099c07de +780, 0x429e62da116e4876 +781, 0x4442c8b57a5b7ef5 +782, 0xa7ea9c348cbeebaa +783, 0xce1a34f57bb2a7fa +784, 0xbb29ef457c9509cc +785, 0x1ba1030b19a32c1c +786, 0x412d1eb07cee79b8 +787, 0x3627dd37c6b36848 +788, 0x45432b319f26a2a9 +789, 0xb9a12e188cee2a29 +790, 0xeee69e0f1b1efd66 +791, 0xd4ccd61bc3fb8837 +792, 0x1b600476917cbf62 +793, 0x522950ddce26c142 +794, 0x956d8a5dbe9aa431 +795, 0x31cfba73bb524b7d +796, 0xc3b709a56885a6ac +797, 0x7341d4e32fffcdf8 +798, 0x5ed87c5315e4775 +799, 0x60fa512183e3dad5 +800, 0x4df6df14e9c2935f +801, 0xdec2dc983ab42a9 +802, 0x28265e213fd6de41 +803, 0x2f85d825454add06 +804, 0xf18119191ac41aa +805, 0xf870e36e83f4face +806, 0x2a4b213d973d83c8 +807, 0x2c7094cde18ba8ec +808, 0xb5998e0a1914446b +809, 0xefcb960ff010503a +810, 0xa8d928b99104aef5 +811, 0xe7a6893116e383a8 +812, 0x552dbe180a51b6c9 +813, 0x16b73f3832c9990c +814, 0xfefee9504783e187 +815, 0xc12d3aa0c1f8608b +816, 0xd5232106c7adea7e +817, 0xb207e82667fb71ed +818, 0xe93c50ef54a791cf +819, 0x3099900fdf7b1750 +820, 0xaa2a46c352132ad0 +821, 0xf2414daa174335e4 +822, 0x33080f98c42bbad2 +823, 0x9df24fe0b5b13394 +824, 0x840eedf2eec5fdb6 +825, 0x3715e262efbc907d +826, 0xa70a8cccfbe8a11f +827, 0x4a57a6f16ea4c9f3 +828, 0xe03dbe2f1493e9e1 +829, 0xbd92759a7becd4e4 +830, 0x21a3d87c3766887e +831, 0x6414f570caa74ef1 +832, 0x4e27490fc3fc0234 +833, 0xd4c40310c6ab2eba +834, 0xfbe8acd168ffd62d +835, 0x30b19992f1975ac8 +836, 0xaf93d22a8561f631 +837, 0x4574ebab81bed3b1 +838, 0x5390c6026e3940c7 +839, 0x7a5154d076a8b504 +840, 0x9676f2495f742943 +841, 0x8cfdb9e11bdb4502 +842, 0x36af5c8754d9ca17 +843, 0x61477e76367296ee +844, 0xd6f5f40f66acc700 +845, 0xe62c2462e96af1b8 +846, 0x18029746ac09ef3e +847, 0x871bbe15da7e0176 +848, 0x2443e806f54d179 +849, 0x9103af1634f9d0ac +850, 0xe6e5358eaa0efa2b +851, 0xdff4859198244a67 +852, 0x6e48c357be6042b +853, 0x6bb9e8aeb24d656a +854, 0x1b89fbb05f8438cb +855, 0xe0cea835b4db045d +856, 0x4eafe5c195e29d47 +857, 0xd2f0a452be9163f0 +858, 0xa7ae1d0eee928fe6 +859, 0x42c7a26c82a062c4 +860, 0xa8e93bcd89c5704e +861, 0x73784be379f09c34 +862, 0x91f8e599342d013f +863, 0x79c20bc462215ccc +864, 0x6ee77bc91b3753a6 +865, 0xd2c116d1eb2650d0 +866, 0x388f9767cfe30ebe +867, 0xdde5d5966815e7ae +868, 0x459b838c87ca1dec +869, 0xdf96cdb2bc916a60 +870, 0x215c4195b935d5ca +871, 0x56c9f516528598e5 +872, 0x1d8492a9923640f3 +873, 0x97830ac45234686f +874, 0x67f75117a7c952bb +875, 0xf1939dc69391e65d +876, 0xfc44bb1162cb2868 +877, 0x92b33d9df8fc6925 +878, 0x6c4496920de0d558 +879, 0xa4616bb101e924aa +880, 0xa0afc9701ad83cdb +881, 0x62d555323b0494d2 +882, 0xf18b31447a2dfdc3 +883, 0xb2ece318c128d4f3 +884, 0x29efea45a76b9b8f +885, 0xae05362b365d9cd2 +886, 0x5c4d374ce6aefb44 +887, 0xb9cdc65eec94136e +888, 0xf0212f42e3d4f5dc +889, 0xcde7c5085f95d8d8 +890, 0x9cc3799673a644e8 +891, 0xf878d89199bead01 +892, 0xab684fb9666abf61 +893, 0x3070d399b7a07d3d +894, 0x6d8c51673eeeef73 +895, 0x9bf4062ff5471832 +896, 0x92774cd03c511d00 +897, 0xc1aad7c6980df547 +898, 0x3291e3a234d50cc0 +899, 0x75645079bbe9d34a +900, 0x7f28bab9eba28fae +901, 0xa84415684ed6d765 +902, 0x56d9d67653cd172 +903, 0xa7bfed939db93e91 +904, 0x92940e5162d50470 +905, 0xcd6bf601e08f07a9 +906, 0x2ea9104d785e35cb +907, 0xd771ddd541649214 +908, 0x352554afbf9258d +909, 0x9d855486b77c5bc3 +910, 0xdb03cd71e906e1df +911, 0x7c2621690aabc265 +912, 0x1dd4ac7369a04640 +913, 0x57796cbc93d4d854 +914, 0x42a373d152eca785 +915, 0xbe7389edb8b144d3 +916, 0x8b6245bf01d2e4df +917, 0xacd1f9fcca317652 +918, 0x84545ac79a3eb960 +919, 0x2d2f28e6a8459db3 +920, 0x42b3a2e26ddeccdd +921, 0xe858272777abcef6 +922, 0xd9b5be7340dec08d +923, 0xe991af3579ac4fb6 +924, 0x7c30699b349fa6c1 +925, 0xbb842be14f7b5b9a +926, 0x1d31e1ca791a1cf0 +927, 0xf2bd448ebb878bc0 +928, 0x26a6adf6709863cb +929, 0xb11aa978539e3a34 +930, 0xce554a11bbbedd1d +931, 0x553d3c012682a47b +932, 0xb3c90ed36715903 +933, 0xda3c5c706e39e395 +934, 0x4e7f66006d583c2a +935, 0x6424190e9d28ca3a +936, 0x9916685e7384f3bf +937, 0x1285e17347eb806d +938, 0x877f10baf13e6659 +939, 0x222700ed5086438d +940, 0xd2473d08396634b8 +941, 0xb6b68f3bc883a77d +942, 0x168a489b0b7f5f63 +943, 0xee34dcf1f93ad3fa +944, 0xd25ef824f614f65a +945, 0xe30981905354f477 +946, 0x9463ef623c5eb3f8 +947, 0x46657408ea66980d +948, 0xa2e58d51d6e8e7f9 +949, 0xd80d7df3007e9845 +950, 0xd90fa96f4fc0f7aa +951, 0xd2a6059d171bbb33 +952, 0xb8bacb8f11c65c2d +953, 0x401de84b6a8b1ac +954, 0xf8b6eed644c802d9 +955, 0x30c927749fdd8e6 +956, 0x17c2f4f9c4524e16 +957, 0xa9c677daae4acc7e +958, 0x82c78d9c6b10446f +959, 0x5e544188277da629 +960, 0x7c6e1bd3b861dcd7 +961, 0xd4b00871a7f67d0d +962, 0x6b66ee142821e6d5 +963, 0x176d5e39f3b22474 +964, 0x58ea746f62acf933 +965, 0xc61fabd9961c3a51 +966, 0xb27ce0f87b416e3d +967, 0xd3c82b525b000e70 +968, 0x99578704fb3ff4e4 +969, 0x747da52468875493 +970, 0x5c5bfab7a474465b +971, 0xd82276bdb30e3dbd +972, 0x1d758772eebffe2 +973, 0xfed9d1e3ca887a6e +974, 0x23dd5f7b3ff9472b +975, 0xae2e842b51c9c598 +976, 0xe851bc45531123d7 +977, 0x1a18d2777151c29 +978, 0x9e82f3be14b12a48 +979, 0xdf9fdb3abc3e72cf +980, 0xdbea56e918ccb176 +981, 0x47abbd896eb0ca1a +982, 0xe850ee3cef9334dd +983, 0x3d69fe95275e7f2e +984, 0x4fcb936c048d8812 +985, 0xc98f0f6bb9865a99 +986, 0xc951cdb73514709 +987, 0x3ca839c27ca26de9 +988, 0x1478848a311f9cc5 +989, 0x35d2244064967478 +990, 0xe71df2d9732ffdc0 +991, 0xa12417d7b7b9e0ce +992, 0xa1bb6da3f284f77c +993, 0xf551e1c3171575eb +994, 0x16083ac8a062747d +995, 0x866d6c3a630fd4da +996, 0x8a972ff46b3c5c4c +997, 0x70af3b475e4a3d5d +998, 0x2c143fd5c01d9cf5 +999, 0x68089ffadc8ea2b9 diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 7c60912542e1..794a895b89da 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -8,7 +8,7 @@ import pytest from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, - Philox, Xoshiro256, Xoshiro512, RandomState) + PCG32, PCG64, Philox, Xoshiro256, Xoshiro512, RandomState) from numpy.random.common import interface try: @@ -386,6 +386,56 @@ def test_set_key(self): 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 = TypeError + cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), + (None, np.zeros(1))] + cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), + (None, 2 ** 129 + 1)] + + def test_seed_float_array(self): + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([-np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([np.pi, -np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([0, np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, [np.pi]) + assert_raises(self.seed_error_type, rs.bit_generator.seed, [0, np.pi]) + + def test_seed_out_of_range_array(self): + rs = Generator(self.bit_generator(*self.data1['seed'])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + [2 ** (2 * self.bits + 1)]) + assert_raises(self.seed_error_type, rs.bit_generator.seed, [-1]) + + +class TestPCG32(TestPCG64): + @classmethod + def setup_class(cls): + cls.bit_generator = PCG32 + cls.bits = 32 + cls.dtype = np.uint32 + cls.data1 = cls._read_csv(join(pwd, './data/pcg32-testset-1.csv')) + cls.data2 = cls._read_csv(join(pwd, './data/pcg32-testset-2.csv')) + cls.seed_error_type = TypeError + cls.invalid_seed_types = [(np.array([1, 2]),), (3.2,), + (None, np.zeros(1))] + cls.invalid_seed_values = [(-1,), (2 ** 129 + 1,), (None, -1), + (None, 2 ** 129 + 1)] + + class TestMT19937(Base): @classmethod def setup_class(cls): diff --git a/numpy/random/tests/test_smoke.py b/numpy/random/tests/test_smoke.py index d5a0c38a50ba..a5395619398c 100644 --- a/numpy/random/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -9,7 +9,7 @@ from numpy.testing import (assert_almost_equal, assert_equal, assert_, assert_array_equal, suppress_warnings) from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, - Philox, Xoshiro256, Xoshiro512, entropy) + PCG32, PCG64, Philox, Xoshiro256, Xoshiro512, entropy) @pytest.fixture(scope='module', @@ -841,3 +841,53 @@ def test_fallback(self): time.sleep(0.1) e2 = entropy.random_entropy(source='fallback') assert_((e1 != e2)) + + +class TestPCG64(RNG): + @classmethod + def setup_class(cls): + cls.bit_generator = PCG64 + cls.advance = 2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 + cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, + 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 = None + cls._extra_setup() + + def test_seed_array_error(self): + # GH #82 for error type changes + if self.seed_vector_bits == 32: + out_of_bounds = 2 ** 32 + else: + out_of_bounds = 2 ** 64 + + seed = -1 + with pytest.raises(ValueError): + self.rg.bit_generator.seed(seed) + + error_type = ValueError if self.seed_vector_bits else TypeError + seed = np.array([-1], dtype=np.int32) + with pytest.raises(error_type): + self.rg.bit_generator.seed(seed) + + seed = np.array([1, 2, 3, -5], dtype=np.int32) + with pytest.raises(error_type): + self.rg.bit_generator.seed(seed) + + seed = np.array([1, 2, 3, out_of_bounds]) + with pytest.raises(error_type): + self.rg.bit_generator.seed(seed) + + +class TestPCG32(TestPCG64): + @classmethod + def setup_class(cls): + cls.bit_generator = PCG32 + cls.advance = 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1 + cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, + 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 = None + cls._extra_setup() diff --git a/numpy/random/xoshiro256.pyx b/numpy/random/xoshiro256.pyx index 380d04af745a..9c44328ff75c 100644 --- a/numpy/random/xoshiro256.pyx +++ b/numpy/random/xoshiro256.pyx @@ -3,7 +3,6 @@ try: except ImportError: from dummy_threading import Lock -from libc.string cimport memcpy from cpython.pycapsule cimport PyCapsule_New import numpy as np @@ -202,7 +201,7 @@ cdef class Xoshiro256: Seed the generator. - This method is called at initialized. It can be called again to + This method is called at initialization. It can be called again to re-seed the generator. Parameters diff --git a/numpy/random/xoshiro512.pyx b/numpy/random/xoshiro512.pyx index 91b0ce51b0ce..27c26486a438 100644 --- a/numpy/random/xoshiro512.pyx +++ b/numpy/random/xoshiro512.pyx @@ -203,7 +203,7 @@ cdef class Xoshiro512: Seed the generator. - This method is called at initialized. It can be called again to + This method is called at initialization. It can be called again to re-seed the generator. Parameters From 23853d65e5c31f182a405427f580123f214e386e Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Fri, 24 May 2019 21:19:11 +0100 Subject: [PATCH 136/138] STY: Clean up code Pep8 fixes Remove unused imports Fix name error --- benchmarks/benchmarks/bench_random.py | 30 ++++----- numpy/random/__init__.py | 6 +- numpy/random/_pickle.py | 10 ++- numpy/random/common.pyx | 4 ++ numpy/random/distributions.pxd | 2 +- numpy/random/dsfmt.pyx | 1 - .../examples/numba/extending_distributions.py | 3 +- numpy/random/generator.pyx | 2 +- numpy/random/mtrand.pyx | 4 +- numpy/random/tests/test_direct.py | 63 ++++++++++--------- numpy/random/tests/test_generator_mt19937.py | 27 ++++---- numpy/random/tests/test_random.py | 24 ++++--- numpy/random/tests/test_regression.py | 3 +- numpy/random/tests/test_smoke.py | 39 ++++++------ numpy/random/xoshiro512.pyx | 1 - 15 files changed, 125 insertions(+), 94 deletions(-) diff --git a/benchmarks/benchmarks/bench_random.py b/benchmarks/benchmarks/bench_random.py index 044986029080..c9c7baf7c335 100644 --- a/benchmarks/benchmarks/bench_random.py +++ b/benchmarks/benchmarks/bench_random.py @@ -89,37 +89,37 @@ class RNG(Benchmark): params = ['DSFMT', 'PCG64', 'PCG32', 'MT19937', 'Xoshiro256', 'Xoshiro512', 'Philox', 'ThreeFry', 'numpy'] - def setup(self, brng): - if brng == 'numpy': + def setup(self, bitgen): + if bitgen == 'numpy': self.rg = np.random.RandomState() else: - self.rg = Generator(getattr(np.random, brng)()) + self.rg = Generator(getattr(np.random, bitgen)()) self.rg.random() self.int32info = np.iinfo(np.int32) self.uint32info = np.iinfo(np.uint32) self.uint64info = np.iinfo(np.uint64) - def time_raw(self, brng): - if brng == 'numpy': + def time_raw(self, bitgen): + if bitgen == 'numpy': self.rg.random_integers(self.int32info.max, size=nom_size) else: self.rg.integers(self.int32info.max, size=nom_size, endpoint=True) - def time_32bit(self, brng): + def time_32bit(self, bitgen): min, max = self.uint32info.min, self.uint32info.max - if brng == 'numpy': + if bitgen == 'numpy': self.rg.randint(min, max + 1, nom_size, dtype=np.uint32) else: self.rg.integers(min, max + 1, nom_size, dtype=np.uint32) - def time_64bit(self, brng): + def time_64bit(self, bitgen): min, max = self.uint64info.min, self.uint64info.max - if brng == 'numpy': + if bitgen == 'numpy': self.rg.randint(min, max + 1, nom_size, dtype=np.uint64) else: self.rg.integers(min, max + 1, nom_size, dtype=np.uint64) - def time_normal_zig(self, brng): + def time_normal_zig(self, bitgen): self.rg.standard_normal(nom_size) class Bounded(Benchmark): @@ -146,14 +146,14 @@ class Bounded(Benchmark): [u64, 2047], # Best case for legacy ]] - def setup(self, brng, args): - if brng == 'numpy': + def setup(self, bitgen, args): + if bitgen == 'numpy': self.rg = np.random.RandomState() else: - self.rg = Generator(getattr(np.random, brng)()) + self.rg = Generator(getattr(np.random, bitgen)()) self.rg.random() - def time_bounded(self, brng, args): + def time_bounded(self, bitgen, args): """ Timer for 8-bit bounded values. @@ -165,7 +165,7 @@ def time_bounded(self, brng, args): Upper bound for range. Lower is always 0. Must be <= 2**bits. """ dt, max = args - if brng == 'numpy': + if bitgen == 'numpy': self.rg.randint(0, max + 1, nom_size, dtype=dt) else: self.rg.integers(0, max + 1, nom_size, dtype=dt) diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index ade91283992c..2e83e419d672 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -173,13 +173,14 @@ from .xoshiro512 import Xoshiro512 from .mtrand import RandomState -__all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox','PCG64', 'PCG32', - 'ThreeFry', 'Xoshiro256', 'Xoshiro512', 'RandomState'] +__all__ += ['Generator', 'DSFMT', 'MT19937', 'Philox', 'PCG64', 'PCG32', + 'ThreeFry', 'Xoshiro256', 'Xoshiro512', 'RandomState'] # Some aliases: ranf = random = sample = random_sample __all__.extend(['ranf', 'random', 'sample']) + def __RandomState_ctor(): """Return a RandomState instance. @@ -195,6 +196,7 @@ def __RandomState_ctor(): """ 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 index cc624a1e818e..307ffe61e457 100644 --- a/numpy/random/_pickle.py +++ b/numpy/random/_pickle.py @@ -38,7 +38,8 @@ def __generator_ctor(bit_generator_name='mt19937'): 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.') + raise ValueError(str(bit_generator_name) + ' is not a known ' + 'BitGenerator module.') return Generator(bit_generator()) @@ -60,10 +61,12 @@ def __bit_generator_ctor(bit_generator_name='mt19937'): 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.') + 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 @@ -81,6 +84,7 @@ def __randomstate_ctor(bit_generator_name='mt19937'): 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.') + raise ValueError(str(bit_generator_name) + ' is not a known ' + 'BitGenerator module.') return RandomState(bit_generator()) diff --git a/numpy/random/common.pyx b/numpy/random/common.pyx index 994de434536f..0fd2d154a358 100644 --- a/numpy/random/common.pyx +++ b/numpy/random/common.pyx @@ -45,6 +45,10 @@ cdef object random_raw(bitgen_t *bitgen, object lock, object size, object output 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 diff --git a/numpy/random/distributions.pxd b/numpy/random/distributions.pxd index 5d6f0841732f..2f336a17d232 100644 --- a/numpy/random/distributions.pxd +++ b/numpy/random/distributions.pxd @@ -1,7 +1,7 @@ #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) + int32_t, int64_t) import numpy as np cimport numpy as np diff --git a/numpy/random/dsfmt.pyx b/numpy/random/dsfmt.pyx index ea77b7821d1e..65475e30d664 100644 --- a/numpy/random/dsfmt.pyx +++ b/numpy/random/dsfmt.pyx @@ -1,6 +1,5 @@ import operator from cpython.pycapsule cimport PyCapsule_New -from libc.string cimport memcpy try: from threading import Lock diff --git a/numpy/random/examples/numba/extending_distributions.py b/numpy/random/examples/numba/extending_distributions.py index f1f9003a9942..1172e51decd5 100644 --- a/numpy/random/examples/numba/extending_distributions.py +++ b/numpy/random/examples/numba/extending_distributions.py @@ -5,7 +5,8 @@ ${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} +gcc -shared -o libdistributions.so -fPIC distributions.c \ + -I${NUMPY_INCLUDE} -I${PYTHON_INCLUDE} mv libdistributions.so ../../examples/numba/ On Windows diff --git a/numpy/random/generator.pyx b/numpy/random/generator.pyx index ae920fc9fd35..ca5d4293cc13 100644 --- a/numpy/random/generator.pyx +++ b/numpy/random/generator.pyx @@ -3872,7 +3872,7 @@ cdef class Generator: [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 diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index ecbd8401ac5a..f1d45668ed26 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3704,7 +3704,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 @@ -4134,7 +4134,7 @@ cdef class RandomState: [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 diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 794a895b89da..4ab521d1b798 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -1,14 +1,13 @@ import os -import sys from os.path import join import numpy as np from numpy.testing import (assert_equal, assert_allclose, assert_array_equal, - assert_raises, assert_warns) + assert_raises) import pytest -from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, - PCG32, PCG64, Philox, Xoshiro256, Xoshiro512, RandomState) +from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, PCG32, PCG64, + Philox, Xoshiro256, Xoshiro512, RandomState) from numpy.random.common import interface try: @@ -25,9 +24,6 @@ except ImportError: MISSING_CTYPES = False -if (sys.version_info > (3, 0)): - long = int - pwd = os.path.dirname(os.path.abspath(__file__)) @@ -102,7 +98,7 @@ def gauss_from_uint(x, n, bits): doubles = uniform_from_uint64(x) elif bits == 32: doubles = uniform_from_uint32(x) - elif bits == 'dsfmt': + else: # bits == 'dsfmt' doubles = uniform_from_dsfmt(x) gauss = [] loc = 0 @@ -140,10 +136,10 @@ def _read_csv(cls, filename): with open(filename) as csv: seed = csv.readline() seed = seed.split(',') - seed = [long(s.strip(), 0) for s in seed[1:]] + seed = [int(s.strip(), 0) for s in seed[1:]] data = [] for line in csv: - data.append(long(line.split(',')[-1].strip(), 0)) + data.append(int(line.split(',')[-1].strip(), 0)) return {'seed': seed, 'data': np.array(data, dtype=cls.dtype)} def test_raw(self): @@ -213,9 +209,12 @@ def test_seed_float(self): def test_seed_float_array(self): # GH #82 rs = Generator(self.bit_generator(*self.data1['seed'])) - assert_raises(self.seed_error_type, rs.bit_generator.seed, np.array([np.pi])) - assert_raises(self.seed_error_type, rs.bit_generator.seed, np.array([-np.pi])) - assert_raises(ValueError, rs.bit_generator.seed, np.array([np.pi, -np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([np.pi])) + assert_raises(self.seed_error_type, rs.bit_generator.seed, + np.array([-np.pi])) + assert_raises(ValueError, rs.bit_generator.seed, + np.array([np.pi, -np.pi])) assert_raises(TypeError, rs.bit_generator.seed, np.array([0, np.pi])) assert_raises(TypeError, rs.bit_generator.seed, [np.pi]) assert_raises(TypeError, rs.bit_generator.seed, [0, np.pi]) @@ -223,13 +222,15 @@ def test_seed_float_array(self): def test_seed_out_of_range(self): # GH #82 rs = Generator(self.bit_generator(*self.data1['seed'])) - assert_raises(ValueError, rs.bit_generator.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.bit_generator.seed, + 2 ** (2 * self.bits + 1)) assert_raises(ValueError, rs.bit_generator.seed, -1) def test_seed_out_of_range_array(self): # GH #82 rs = Generator(self.bit_generator(*self.data1['seed'])) - assert_raises(ValueError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, + [2 ** (2 * self.bits + 1)]) assert_raises(ValueError, rs.bit_generator.seed, [-1]) def test_repr(self): @@ -248,8 +249,8 @@ def test_pickle(self): bit_generator = self.bit_generator(*self.data1['seed']) state = bit_generator.state - brng_pkl = pickle.dumps(bit_generator) - reloaded = pickle.loads(brng_pkl) + 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)) @@ -264,7 +265,7 @@ def test_invalid_state_type(self): def test_invalid_state_value(self): bit_generator = self.bit_generator(*self.data1['seed']) state = bit_generator.state - state['bit_generator'] = 'otherBRNG' + state['bit_generator'] = 'otherBitGenerator' with pytest.raises(ValueError): bit_generator.state = state @@ -359,7 +360,7 @@ 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']) + key=state['state']['key']) assert_state_equal(bit_generator.state, keyed.state) @@ -382,11 +383,10 @@ 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']) + key=state['state']['key']) assert_state_equal(bit_generator.state, keyed.state) - class TestPCG64(Base): @classmethod def setup_class(cls): @@ -453,14 +453,17 @@ def test_seed_out_of_range(self): rs = Generator(self.bit_generator(*self.data1['seed'])) assert_raises(ValueError, rs.bit_generator.seed, 2 ** (self.bits + 1)) assert_raises(ValueError, rs.bit_generator.seed, -1) - assert_raises(ValueError, rs.bit_generator.seed, 2 ** (2 * self.bits + 1)) + assert_raises(ValueError, rs.bit_generator.seed, + 2 ** (2 * self.bits + 1)) def test_seed_out_of_range_array(self): # GH #82 rs = Generator(self.bit_generator(*self.data1['seed'])) - assert_raises(ValueError, rs.bit_generator.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, + [2 ** (self.bits + 1)]) assert_raises(ValueError, rs.bit_generator.seed, [-1]) - assert_raises(TypeError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(TypeError, rs.bit_generator.seed, + [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 @@ -484,7 +487,8 @@ def test_state_tuple(self): bit_generator = rs.bit_generator state = bit_generator.state desired = rs.integers(2 ** 16) - tup = (state['bit_generator'], state['state']['key'], state['state']['pos']) + tup = (state['bit_generator'], state['state']['key'], + state['state']['pos']) bit_generator.state = tup actual = rs.integers(2 ** 16) assert_equal(actual, desired) @@ -531,9 +535,11 @@ def test_gauss_inv(self): def test_seed_out_of_range_array(self): # GH #82 rs = Generator(self.bit_generator(*self.data1['seed'])) - assert_raises(ValueError, rs.bit_generator.seed, [2 ** (self.bits + 1)]) + assert_raises(ValueError, rs.bit_generator.seed, + [2 ** (self.bits + 1)]) assert_raises(ValueError, rs.bit_generator.seed, [-1]) - assert_raises(TypeError, rs.bit_generator.seed, [2 ** (2 * self.bits + 1)]) + assert_raises(TypeError, rs.bit_generator.seed, + [2 ** (2 * self.bits + 1)]) def test_seed_float(self): # GH #82 @@ -546,7 +552,8 @@ def test_seed_float_array(self): rs = Generator(self.bit_generator(*self.data1['seed'])) assert_raises(TypeError, rs.bit_generator.seed, np.array([np.pi])) assert_raises(TypeError, rs.bit_generator.seed, np.array([-np.pi])) - assert_raises(TypeError, rs.bit_generator.seed, np.array([np.pi, -np.pi])) + assert_raises(TypeError, rs.bit_generator.seed, + np.array([np.pi, -np.pi])) assert_raises(TypeError, rs.bit_generator.seed, np.array([0, np.pi])) assert_raises(TypeError, rs.bit_generator.seed, [np.pi]) assert_raises(TypeError, rs.bit_generator.seed, [0, np.pi]) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 207ec1a2bba1..c51164c55fb2 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -1,5 +1,4 @@ import sys -import warnings import pytest @@ -208,7 +207,8 @@ def test_rng_zero_and_extremes(self, endpoint): 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) + size=1000, endpoint=endpoint, dtype=dt), + tgt) def test_rng_zero_and_extremes_array(self, endpoint): size = 1000 @@ -295,7 +295,8 @@ def test_scalar_array_equiv(self, endpoint): size = 1000 random.bit_generator.seed(1234) - scalar = self.rfunc(lbnd, ubnd, size=size, endpoint=endpoint, dtype=dt) + scalar = self.rfunc(lbnd, ubnd, size=size, endpoint=endpoint, + dtype=dt) random.bit_generator.seed(1234) scalar_array = self.rfunc([lbnd], [ubnd], size=size, @@ -352,16 +353,18 @@ def test_repeatability_broadcasting(self, endpoint): # view as little endian for hash random.bit_generator.seed(1234) - val = self.rfunc(lbnd, ubnd, size=1000, endpoint=endpoint, dtype=dt) + val = self.rfunc(lbnd, ubnd, size=1000, endpoint=endpoint, + dtype=dt) random.bit_generator.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, ubnd, endpoint=endpoint, dtype=dt) + val_bc = self.rfunc([lbnd] * 1000, ubnd, endpoint=endpoint, + dtype=dt) assert_array_equal(val, val_bc) random.bit_generator.seed(1234) - val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, endpoint=endpoint, - dtype=dt) + val_bc = self.rfunc([lbnd] * 1000, [ubnd] * 1000, + endpoint=endpoint, dtype=dt) assert_array_equal(val, val_bc) @@ -457,8 +460,10 @@ def test_zero_size(self, endpoint): 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 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,)) @@ -502,8 +507,8 @@ def test_integers_max_int(self): # 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) + actual = random.integers(np.iinfo('l').max, np.iinfo('l').max, + endpoint=True) desired = np.iinfo('l').max assert_equal(actual, desired) diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index 22e37151c694..f192a914123c 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -43,7 +43,8 @@ def test_invalid_array(self): 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]]) @@ -449,7 +450,8 @@ def test_choice_return_shape(self): 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): @@ -693,7 +695,7 @@ def test_multivariate_normal(self): 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 +723,7 @@ def test_multivariate_normal(self): 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,7 +919,8 @@ def __float__(self): 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): @@ -1384,21 +1387,24 @@ def test_triangular(self): 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] @@ -1536,6 +1542,7 @@ def test_logseries(self): 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): @@ -1578,6 +1585,7 @@ 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): diff --git a/numpy/random/tests/test_regression.py b/numpy/random/tests/test_regression.py index ca9bbbc719db..509e2d57ff28 100644 --- a/numpy/random/tests/test_regression.py +++ b/numpy/random/tests/test_regression.py @@ -29,7 +29,8 @@ def test_hypergeometric_range(self): ] 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_smoke.py b/numpy/random/tests/test_smoke.py index a5395619398c..c94e1a285664 100644 --- a/numpy/random/tests/test_smoke.py +++ b/numpy/random/tests/test_smoke.py @@ -1,15 +1,13 @@ -import os import pickle -import sys import time from functools import partial import numpy as np import pytest -from numpy.testing import (assert_almost_equal, assert_equal, assert_, - assert_array_equal, suppress_warnings) +from numpy.testing import assert_equal, assert_, assert_array_equal from numpy.random import (Generator, MT19937, DSFMT, ThreeFry, - PCG32, PCG64, Philox, Xoshiro256, Xoshiro512, entropy) + PCG32, PCG64, Philox, Xoshiro256, Xoshiro512, + entropy) @pytest.fixture(scope='module', @@ -35,10 +33,10 @@ def params_0(f): 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) + 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) + g = np.arange(2.0, 12.0).reshape((1, 10, 1)) if bounded: a = 0.5 b = b / (1.5 * b.max()) @@ -134,8 +132,8 @@ def test_advance(self): self.rg.bit_generator.advance(self.advance) assert_(not comp_state(state, self.rg.bit_generator.state)) else: - brng_name = self.rg.bit_generator.__class__.__name__ - pytest.skip('Advance is not supported by {0}'.format(brng_name)) + 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 @@ -149,10 +147,10 @@ def test_jump(self): rejumped_state = bit_gen3.state assert_(comp_state(jumped_state, rejumped_state)) else: - brng_name = self.rg.bit_generator.__class__.__name__ - if name not in ('',): - raise AttributeError('no "jumped" in %s' % brng_name) - pytest.skip('Jump is not supported by {0}'.format(brng_name)) + bitgen_name = self.rg.bit_generator.__class__.__name__ + if bitgen_name not in ('',): + 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) @@ -231,7 +229,8 @@ def test_reset_state(self): 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)) + assert_(not comp_state(rg.bit_generator.state, + rg2.bit_generator.state)) def test_seed(self): rg = Generator(self.bit_generator(*self.seed)) @@ -440,18 +439,20 @@ 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)) + 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)) + assert_(comp_state(self.rg.bit_generator.state, + unpick.bit_generator.state)) def test_seed_array(self): if self.seed_vector_bits is None: - brng_name = self.bit_generator.__name__ + bitgen_name = self.bit_generator.__name__ pytest.skip('Vector seeding is not supported by ' - '{0}'.format(brng_name)) + '{0}'.format(bitgen_name)) if self.seed_vector_bits == 32: dtype = np.uint32 diff --git a/numpy/random/xoshiro512.pyx b/numpy/random/xoshiro512.pyx index 27c26486a438..4a6db3b23777 100644 --- a/numpy/random/xoshiro512.pyx +++ b/numpy/random/xoshiro512.pyx @@ -3,7 +3,6 @@ try: except ImportError: from dummy_threading import Lock -from libc.string cimport memcpy from cpython.pycapsule cimport PyCapsule_New import numpy as np From 9c261e6d617fcb3d58708f10b52dd3ea1eb6e301 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Mon, 27 May 2019 11:11:57 +0100 Subject: [PATCH 137/138] PERF: Reorder header for philox (#34) * PERF: Reorder header for philox Reorder header so that support uint128 is always used if avilable, irrespective of platform --- numpy/random/src/pcg64/pcg64.h | 2 +- numpy/random/src/philox/philox.h | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/numpy/random/src/pcg64/pcg64.h b/numpy/random/src/pcg64/pcg64.h index d4c96ff5ffc0..a28c8eaa6d3f 100644 --- a/numpy/random/src/pcg64/pcg64.h +++ b/numpy/random/src/pcg64/pcg64.h @@ -62,7 +62,7 @@ extern "C" { #endif -#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH) +#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 diff --git a/numpy/random/src/philox/philox.h b/numpy/random/src/philox/philox.h index ae6cf9308095..309d89eae7e5 100644 --- a/numpy/random/src/philox/philox.h +++ b/numpy/random/src/philox/philox.h @@ -25,10 +25,17 @@ _philox4x64bumpkey(struct r123array2x64 key) { 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 -/* TODO: This isn't correct for many platforms */ -#ifdef _WIN64 +#if defined(_WIN64) && defined(_M_AMD64) #pragma intrinsic(_umul128) #else #pragma intrinsic(__emulu) @@ -59,13 +66,6 @@ static NPY_INLINE uint64_t mulhilo64(uint64_t a, uint64_t b, uint64_t *hip) { return _umul128(a, b, hip); } #else -#if __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 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, From 70d6293bf8ae48e68844d34def56e9fb59027433 Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 27 May 2019 23:55:49 +0300 Subject: [PATCH 138/138] MAINT: fix for dtype specification --- numpy/random/tests/test_generator_mt19937.py | 4 ++-- numpy/random/tests/test_randomstate.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index c51164c55fb2..192dcce08225 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -700,8 +700,8 @@ def test_shuffle(self): .view(np.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], - [("a", object, 1), - ("b", np.int32, 1)])]: + [("a", object, (1,)), + ("b", np.int32, (1,))])]: random.bit_generator.seed(self.seed) alist = conv([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) random.shuffle(alist) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 066e4d661a68..5e2b93f5282b 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -633,8 +633,8 @@ def test_shuffle(self): .view(np.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], - [("a", object, 1), - ("b", np.int32, 1)])]: + [("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)