1 /* 2 * ***************************************************************************** 3 * 4 * Parts of this code are adapted from the following: 5 * 6 * PCG, A Family of Better Random Number Generators. 7 * 8 * You can find the original source code at: 9 * https://github.com/imneme/pcg-c 10 * 11 * ----------------------------------------------------------------------------- 12 * 13 * This code is under the following license: 14 * 15 * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors 16 * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 17 * 18 * Permission is hereby granted, free of charge, to any person obtaining a copy 19 * of this software and associated documentation files (the "Software"), to deal 20 * in the Software without restriction, including without limitation the rights 21 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 * copies of the Software, and to permit persons to whom the Software is 23 * furnished to do so, subject to the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be included in 26 * all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 * SOFTWARE. 35 * 36 * ***************************************************************************** 37 * 38 * Definitions for the RNG. 39 * 40 */ 41 42 #ifndef BC_RAND_H 43 #define BC_RAND_H 44 45 #include <stdint.h> 46 #include <inttypes.h> 47 48 #include <vector.h> 49 #include <num.h> 50 51 #if BC_ENABLE_EXTRA_MATH 52 53 #if BC_ENABLE_RAND 54 55 typedef ulong (*BcRandUlong)(void*); 56 57 #if BC_LONG_BIT >= 64 58 59 #ifdef BC_RAND_BUILTIN 60 #if BC_RAND_BUILTIN 61 #ifndef __SIZEOF_INT128__ 62 #undef BC_RAND_BUILTIN 63 #define BC_RAND_BUILTIN (0) 64 #endif // __SIZEOF_INT128__ 65 #endif // BC_RAND_BUILTIN 66 #endif // BC_RAND_BUILTIN 67 68 #ifndef BC_RAND_BUILTIN 69 #ifdef __SIZEOF_INT128__ 70 #define BC_RAND_BUILTIN (1) 71 #else // __SIZEOF_INT128__ 72 #define BC_RAND_BUILTIN (0) 73 #endif // __SIZEOF_INT128__ 74 #endif // BC_RAND_BUILTIN 75 76 typedef uint64_t BcRand; 77 78 #define BC_RAND_ROTC (63) 79 80 #if BC_RAND_BUILTIN 81 82 typedef __uint128_t BcRandState; 83 84 #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 85 #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 86 87 #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 88 #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 89 90 #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 91 #define BC_RAND_ZERO(r) (!(r)->state) 92 93 #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l)) 94 95 #define BC_RAND_TRUNC(s) ((uint64_t) (s)) 96 #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL)) 97 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL)) 98 99 #else // BC_RAND_BUILTIN 100 101 typedef struct BcRandState { 102 103 uint_fast64_t lo; 104 uint_fast64_t hi; 105 106 } BcRandState; 107 108 #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b))) 109 #define bc_rand_add(a, b) (bc_rand_addition((a), (b))) 110 111 #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b))) 112 #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b))) 113 114 #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0) 115 #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi) 116 117 #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) } 118 119 #define BC_RAND_TRUNC(s) ((s).lo) 120 #define BC_RAND_CHOP(s) ((s).hi) 121 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL)) 122 123 #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL)) 124 #define BC_RAND_TRUNC32(n) ((n) & BC_RAND_BOTTOM32) 125 #define BC_RAND_CHOP32(n) ((n) >> 32) 126 127 #endif // BC_RAND_BUILTIN 128 129 #define BC_RAND_MULTIPLIER \ 130 BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) 131 132 #define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s))) 133 134 #else // BC_LONG_BIT >= 64 135 136 #undef BC_RAND_BUILTIN 137 #define BC_RAND_BUILTIN (1) 138 139 typedef uint32_t BcRand; 140 141 #define BC_RAND_ROTC (31) 142 143 typedef uint_fast64_t BcRandState; 144 145 #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 146 #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 147 148 #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 149 #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 150 151 #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 152 #define BC_RAND_ZERO(r) (!(r)->state) 153 154 #define BC_RAND_CONSTANT UINT64_C 155 #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005) 156 157 #define BC_RAND_TRUNC(s) ((uint32_t) (s)) 158 #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL)) 159 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL)) 160 161 #define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U)) 162 163 #endif // BC_LONG_BIT >= 64 164 165 #define BC_RAND_ROT(v, r) \ 166 ((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC)))) 167 168 #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT) 169 #define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT) 170 171 #define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2) 172 173 #define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1) 174 175 typedef struct BcRNGData { 176 177 BcRandState state; 178 BcRandState inc; 179 180 } BcRNGData; 181 182 typedef struct BcRNG { 183 184 BcVec v; 185 186 } BcRNG; 187 188 void bc_rand_init(BcRNG *r); 189 #ifndef NDEBUG 190 void bc_rand_free(BcRNG *r); 191 #endif // NDEBUG 192 193 BcRand bc_rand_int(BcRNG *r); 194 BcRand bc_rand_bounded(BcRNG *r, BcRand bound); 195 void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2); 196 void bc_rand_push(BcRNG *r); 197 void bc_rand_pop(BcRNG *r, bool reset); 198 void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2); 199 void bc_rand_srand(BcRNGData *rng); 200 201 extern const BcRandState bc_rand_multiplier; 202 203 #endif // BC_ENABLE_RAND 204 205 #endif // BC_ENABLE_EXTRA_MATH 206 207 #endif // BC_RAND_H 208