1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 4252884aeSStefan Eßer * Parts of this code are adapted from the following: 5252884aeSStefan Eßer * 6252884aeSStefan Eßer * PCG, A Family of Better Random Number Generators. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * You can find the original source code at: 9252884aeSStefan Eßer * https://github.com/imneme/pcg-c 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * ----------------------------------------------------------------------------- 12252884aeSStefan Eßer * 13*10328f8bSStefan Eßer * This code is under the following license: 14252884aeSStefan Eßer * 15252884aeSStefan Eßer * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors 16*10328f8bSStefan Eßer * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * Permission is hereby granted, free of charge, to any person obtaining a copy 19252884aeSStefan Eßer * of this software and associated documentation files (the "Software"), to deal 20252884aeSStefan Eßer * in the Software without restriction, including without limitation the rights 21252884aeSStefan Eßer * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22252884aeSStefan Eßer * copies of the Software, and to permit persons to whom the Software is 23252884aeSStefan Eßer * furnished to do so, subject to the following conditions: 24252884aeSStefan Eßer * 25252884aeSStefan Eßer * The above copyright notice and this permission notice shall be included in 26252884aeSStefan Eßer * all copies or substantial portions of the Software. 27252884aeSStefan Eßer * 28252884aeSStefan Eßer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29252884aeSStefan Eßer * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30252884aeSStefan Eßer * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31252884aeSStefan Eßer * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32252884aeSStefan Eßer * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33252884aeSStefan Eßer * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34252884aeSStefan Eßer * SOFTWARE. 35252884aeSStefan Eßer * 36252884aeSStefan Eßer * ***************************************************************************** 37252884aeSStefan Eßer * 38252884aeSStefan Eßer * Definitions for the RNG. 39252884aeSStefan Eßer * 40252884aeSStefan Eßer */ 41252884aeSStefan Eßer 42252884aeSStefan Eßer #ifndef BC_RAND_H 43252884aeSStefan Eßer #define BC_RAND_H 44252884aeSStefan Eßer 45252884aeSStefan Eßer #include <stdint.h> 46252884aeSStefan Eßer #include <inttypes.h> 47252884aeSStefan Eßer 48252884aeSStefan Eßer #include <vector.h> 49252884aeSStefan Eßer #include <num.h> 50252884aeSStefan Eßer 513aa99676SStefan Eßer #if BC_ENABLE_EXTRA_MATH 523aa99676SStefan Eßer 533aa99676SStefan Eßer #if BC_ENABLE_RAND 543aa99676SStefan Eßer 55252884aeSStefan Eßer typedef ulong (*BcRandUlong)(void*); 56252884aeSStefan Eßer 57252884aeSStefan Eßer #if BC_LONG_BIT >= 64 58252884aeSStefan Eßer 59252884aeSStefan Eßer #ifdef BC_RAND_BUILTIN 60252884aeSStefan Eßer #if BC_RAND_BUILTIN 61252884aeSStefan Eßer #ifndef __SIZEOF_INT128__ 62252884aeSStefan Eßer #undef BC_RAND_BUILTIN 63252884aeSStefan Eßer #define BC_RAND_BUILTIN (0) 64252884aeSStefan Eßer #endif // __SIZEOF_INT128__ 65252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 66252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 67252884aeSStefan Eßer 68252884aeSStefan Eßer #ifndef BC_RAND_BUILTIN 69252884aeSStefan Eßer #ifdef __SIZEOF_INT128__ 70252884aeSStefan Eßer #define BC_RAND_BUILTIN (1) 71252884aeSStefan Eßer #else // __SIZEOF_INT128__ 72252884aeSStefan Eßer #define BC_RAND_BUILTIN (0) 73252884aeSStefan Eßer #endif // __SIZEOF_INT128__ 74252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 75252884aeSStefan Eßer 76252884aeSStefan Eßer typedef uint64_t BcRand; 77252884aeSStefan Eßer 78252884aeSStefan Eßer #define BC_RAND_ROTC (63) 79252884aeSStefan Eßer 80252884aeSStefan Eßer #if BC_RAND_BUILTIN 81252884aeSStefan Eßer 82252884aeSStefan Eßer typedef __uint128_t BcRandState; 83252884aeSStefan Eßer 84252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 85252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 86252884aeSStefan Eßer 87252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 88252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 89252884aeSStefan Eßer 90252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 91252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 92252884aeSStefan Eßer 93252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l)) 94252884aeSStefan Eßer 95252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint64_t) (s)) 96252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL)) 97252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL)) 98252884aeSStefan Eßer 99252884aeSStefan Eßer #else // BC_RAND_BUILTIN 100252884aeSStefan Eßer 101252884aeSStefan Eßer typedef struct BcRandState { 102252884aeSStefan Eßer 103252884aeSStefan Eßer uint_fast64_t lo; 104252884aeSStefan Eßer uint_fast64_t hi; 105252884aeSStefan Eßer 106252884aeSStefan Eßer } BcRandState; 107252884aeSStefan Eßer 108252884aeSStefan Eßer #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b))) 109252884aeSStefan Eßer #define bc_rand_add(a, b) (bc_rand_addition((a), (b))) 110252884aeSStefan Eßer 111252884aeSStefan Eßer #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b))) 112252884aeSStefan Eßer #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b))) 113252884aeSStefan Eßer 114252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0) 115252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi) 116252884aeSStefan Eßer 117252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) } 118252884aeSStefan Eßer 119252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((s).lo) 120252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((s).hi) 121252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL)) 122252884aeSStefan Eßer 123252884aeSStefan Eßer #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL)) 124252884aeSStefan Eßer #define BC_RAND_TRUNC32(n) ((n) & BC_RAND_BOTTOM32) 125252884aeSStefan Eßer #define BC_RAND_CHOP32(n) ((n) >> 32) 126252884aeSStefan Eßer 127252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 128252884aeSStefan Eßer 129252884aeSStefan Eßer #define BC_RAND_MULTIPLIER \ 130252884aeSStefan Eßer BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) 131252884aeSStefan Eßer 132252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s))) 133252884aeSStefan Eßer 134252884aeSStefan Eßer #else // BC_LONG_BIT >= 64 135252884aeSStefan Eßer 136252884aeSStefan Eßer #undef BC_RAND_BUILTIN 137252884aeSStefan Eßer #define BC_RAND_BUILTIN (1) 138252884aeSStefan Eßer 139252884aeSStefan Eßer typedef uint32_t BcRand; 140252884aeSStefan Eßer 141252884aeSStefan Eßer #define BC_RAND_ROTC (31) 142252884aeSStefan Eßer 143252884aeSStefan Eßer typedef uint_fast64_t BcRandState; 144252884aeSStefan Eßer 145252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 146252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 147252884aeSStefan Eßer 148252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 149252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 150252884aeSStefan Eßer 151252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 152252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 153252884aeSStefan Eßer 154252884aeSStefan Eßer #define BC_RAND_CONSTANT UINT64_C 155252884aeSStefan Eßer #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005) 156252884aeSStefan Eßer 157252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint32_t) (s)) 158252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL)) 159252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL)) 160252884aeSStefan Eßer 161252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U)) 162252884aeSStefan Eßer 163252884aeSStefan Eßer #endif // BC_LONG_BIT >= 64 164252884aeSStefan Eßer 165252884aeSStefan Eßer #define BC_RAND_ROT(v, r) \ 166252884aeSStefan Eßer ((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC)))) 167252884aeSStefan Eßer 168252884aeSStefan Eßer #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT) 169252884aeSStefan Eßer #define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT) 170252884aeSStefan Eßer 171252884aeSStefan Eßer #define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2) 172252884aeSStefan Eßer 173252884aeSStefan Eßer #define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1) 174252884aeSStefan Eßer 175252884aeSStefan Eßer typedef struct BcRNGData { 176252884aeSStefan Eßer 177252884aeSStefan Eßer BcRandState state; 178252884aeSStefan Eßer BcRandState inc; 179252884aeSStefan Eßer 180252884aeSStefan Eßer } BcRNGData; 181252884aeSStefan Eßer 182252884aeSStefan Eßer typedef struct BcRNG { 183252884aeSStefan Eßer 184252884aeSStefan Eßer BcVec v; 185252884aeSStefan Eßer 186252884aeSStefan Eßer } BcRNG; 187252884aeSStefan Eßer 188252884aeSStefan Eßer void bc_rand_init(BcRNG *r); 189252884aeSStefan Eßer #ifndef NDEBUG 190252884aeSStefan Eßer void bc_rand_free(BcRNG *r); 191252884aeSStefan Eßer #endif // NDEBUG 192252884aeSStefan Eßer 193252884aeSStefan Eßer BcRand bc_rand_int(BcRNG *r); 194252884aeSStefan Eßer BcRand bc_rand_bounded(BcRNG *r, BcRand bound); 195252884aeSStefan Eßer void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2); 196252884aeSStefan Eßer void bc_rand_push(BcRNG *r); 197252884aeSStefan Eßer void bc_rand_pop(BcRNG *r, bool reset); 198252884aeSStefan Eßer void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2); 19950696a6eSStefan Eßer void bc_rand_srand(BcRNGData *rng); 200252884aeSStefan Eßer 201252884aeSStefan Eßer extern const BcRandState bc_rand_multiplier; 202252884aeSStefan Eßer 2033aa99676SStefan Eßer #endif // BC_ENABLE_RAND 2043aa99676SStefan Eßer 205252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 206252884aeSStefan Eßer 207252884aeSStefan Eßer #endif // BC_RAND_H 208