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 * 1310328f8bSStefan 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 1610328f8bSStefan 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 53*44d4804dSStefan Eßer #if BC_ENABLE_LIBRARY 54*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (1) 55*44d4804dSStefan Eßer #else // BC_ENABLE_LIBRARY 56*44d4804dSStefan Eßer #ifndef NDEBUG 57*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (1) 58*44d4804dSStefan Eßer #else // NDEBUG 59*44d4804dSStefan Eßer #define BC_RAND_USE_FREE (0) 60*44d4804dSStefan Eßer #endif // NDEBUG 61*44d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY 623aa99676SStefan Eßer 63*44d4804dSStefan Eßer /** 64*44d4804dSStefan Eßer * A function to return a random unsigned long. 65*44d4804dSStefan Eßer * @param ptr A void ptr to some data that will help generate the random ulong. 66*44d4804dSStefan Eßer * @return The random ulong. 67*44d4804dSStefan Eßer */ 68*44d4804dSStefan Eßer typedef ulong (*BcRandUlong)(void *ptr); 69252884aeSStefan Eßer 70252884aeSStefan Eßer #if BC_LONG_BIT >= 64 71252884aeSStefan Eßer 72*44d4804dSStefan Eßer // If longs are 64 bits, we have the option of 128-bit integers on some 73*44d4804dSStefan Eßer // compilers. These two sections test that. 74252884aeSStefan Eßer #ifdef BC_RAND_BUILTIN 75252884aeSStefan Eßer #if BC_RAND_BUILTIN 76252884aeSStefan Eßer #ifndef __SIZEOF_INT128__ 77252884aeSStefan Eßer #undef BC_RAND_BUILTIN 78252884aeSStefan Eßer #define BC_RAND_BUILTIN (0) 79252884aeSStefan Eßer #endif // __SIZEOF_INT128__ 80252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 81252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 82252884aeSStefan Eßer 83252884aeSStefan Eßer #ifndef BC_RAND_BUILTIN 84252884aeSStefan Eßer #ifdef __SIZEOF_INT128__ 85252884aeSStefan Eßer #define BC_RAND_BUILTIN (1) 86252884aeSStefan Eßer #else // __SIZEOF_INT128__ 87252884aeSStefan Eßer #define BC_RAND_BUILTIN (0) 88252884aeSStefan Eßer #endif // __SIZEOF_INT128__ 89252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 90252884aeSStefan Eßer 91*44d4804dSStefan Eßer /// The type for random integers. 92252884aeSStefan Eßer typedef uint64_t BcRand; 93252884aeSStefan Eßer 94*44d4804dSStefan Eßer /// A constant defined by PCG. 95252884aeSStefan Eßer #define BC_RAND_ROTC (63) 96252884aeSStefan Eßer 97252884aeSStefan Eßer #if BC_RAND_BUILTIN 98252884aeSStefan Eßer 99*44d4804dSStefan Eßer /// A typedef for the PCG state. 100252884aeSStefan Eßer typedef __uint128_t BcRandState; 101252884aeSStefan Eßer 102*44d4804dSStefan Eßer /** 103*44d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 104*44d4804dSStefan Eßer * @param a The first integer. 105*44d4804dSStefan Eßer * @param b The second integer. 106*44d4804dSStefan Eßer * @return The product of the PCG states. 107*44d4804dSStefan Eßer */ 108252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 109*44d4804dSStefan Eßer 110*44d4804dSStefan Eßer /** 111*44d4804dSStefan Eßer * Add two integers, worrying about overflow. 112*44d4804dSStefan Eßer * @param a The first integer. 113*44d4804dSStefan Eßer * @param b The second integer. 114*44d4804dSStefan Eßer * @return The sum of the PCG states. 115*44d4804dSStefan Eßer */ 116252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 117252884aeSStefan Eßer 118*44d4804dSStefan Eßer /** 119*44d4804dSStefan Eßer * Multiply two PCG states. 120*44d4804dSStefan Eßer * @param a The first PCG state. 121*44d4804dSStefan Eßer * @param b The second PCG state. 122*44d4804dSStefan Eßer * @return The product of the PCG states. 123*44d4804dSStefan Eßer */ 124252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 125*44d4804dSStefan Eßer 126*44d4804dSStefan Eßer /** 127*44d4804dSStefan Eßer * Add two PCG states. 128*44d4804dSStefan Eßer * @param a The first PCG state. 129*44d4804dSStefan Eßer * @param b The second PCG state. 130*44d4804dSStefan Eßer * @return The sum of the PCG states. 131*44d4804dSStefan Eßer */ 132252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 133252884aeSStefan Eßer 134*44d4804dSStefan Eßer /** 135*44d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 136*44d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 137*44d4804dSStefan Eßer * @param r The PRNG. 138*44d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 139*44d4804dSStefan Eßer */ 140252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 141*44d4804dSStefan Eßer 142*44d4804dSStefan Eßer /** 143*44d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 144*44d4804dSStefan Eßer * @param r The PRNG. 145*44d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 146*44d4804dSStefan Eßer */ 147252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 148252884aeSStefan Eßer 149*44d4804dSStefan Eßer /** 150*44d4804dSStefan Eßer * Returns a constant built from @a h and @a l. 151*44d4804dSStefan Eßer * @param h The high 64 bits. 152*44d4804dSStefan Eßer * @param l The low 64 bits. 153*44d4804dSStefan Eßer * @return The constant built from @a h and @a l. 154*44d4804dSStefan Eßer */ 155252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l)) 156252884aeSStefan Eßer 157*44d4804dSStefan Eßer /** 158*44d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 159*44d4804dSStefan Eßer * @param s The state to truncate. 160*44d4804dSStefan Eßer * @return The truncated state. 161*44d4804dSStefan Eßer */ 162252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint64_t) (s)) 163*44d4804dSStefan Eßer 164*44d4804dSStefan Eßer /** 165*44d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 166*44d4804dSStefan Eßer * @param s The state to chop. 167*44d4804dSStefan Eßer * @return The chopped state's top bits. 168*44d4804dSStefan Eßer */ 169252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL)) 170*44d4804dSStefan Eßer 171*44d4804dSStefan Eßer /** 172*44d4804dSStefan Eßer * Rotates a PCG state. 173*44d4804dSStefan Eßer * @param s The state to rotate. 174*44d4804dSStefan Eßer * @return The rotated state. 175*44d4804dSStefan Eßer */ 176252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL)) 177252884aeSStefan Eßer 178252884aeSStefan Eßer #else // BC_RAND_BUILTIN 179252884aeSStefan Eßer 180*44d4804dSStefan Eßer /// A typedef for the PCG state. 181252884aeSStefan Eßer typedef struct BcRandState { 182252884aeSStefan Eßer 183*44d4804dSStefan Eßer /// The low bits. 184252884aeSStefan Eßer uint_fast64_t lo; 185*44d4804dSStefan Eßer 186*44d4804dSStefan Eßer /// The high bits. 187252884aeSStefan Eßer uint_fast64_t hi; 188252884aeSStefan Eßer 189252884aeSStefan Eßer } BcRandState; 190252884aeSStefan Eßer 191*44d4804dSStefan Eßer /** 192*44d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 193*44d4804dSStefan Eßer * @param a The first integer. 194*44d4804dSStefan Eßer * @param b The second integer. 195*44d4804dSStefan Eßer * @return The product of the PCG states. 196*44d4804dSStefan Eßer */ 197252884aeSStefan Eßer #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b))) 198*44d4804dSStefan Eßer 199*44d4804dSStefan Eßer /** 200*44d4804dSStefan Eßer * Add two integers, worrying about overflow. 201*44d4804dSStefan Eßer * @param a The first integer. 202*44d4804dSStefan Eßer * @param b The second integer. 203*44d4804dSStefan Eßer * @return The sum of the PCG states. 204*44d4804dSStefan Eßer */ 205252884aeSStefan Eßer #define bc_rand_add(a, b) (bc_rand_addition((a), (b))) 206252884aeSStefan Eßer 207*44d4804dSStefan Eßer /** 208*44d4804dSStefan Eßer * Multiply two PCG states. 209*44d4804dSStefan Eßer * @param a The first PCG state. 210*44d4804dSStefan Eßer * @param b The second PCG state. 211*44d4804dSStefan Eßer * @return The product of the PCG states. 212*44d4804dSStefan Eßer */ 213252884aeSStefan Eßer #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b))) 214*44d4804dSStefan Eßer 215*44d4804dSStefan Eßer /** 216*44d4804dSStefan Eßer * Add two PCG states. 217*44d4804dSStefan Eßer * @param a The first PCG state. 218*44d4804dSStefan Eßer * @param b The second PCG state. 219*44d4804dSStefan Eßer * @return The sum of the PCG states. 220*44d4804dSStefan Eßer */ 221252884aeSStefan Eßer #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b))) 222252884aeSStefan Eßer 223*44d4804dSStefan Eßer /** 224*44d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 225*44d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 226*44d4804dSStefan Eßer * @param r The PRNG. 227*44d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 228*44d4804dSStefan Eßer */ 229252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0) 230*44d4804dSStefan Eßer 231*44d4804dSStefan Eßer /** 232*44d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 233*44d4804dSStefan Eßer * @param r The PRNG. 234*44d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 235*44d4804dSStefan Eßer */ 236252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi) 237252884aeSStefan Eßer 238*44d4804dSStefan Eßer /** 239*44d4804dSStefan Eßer * Returns a constant built from @a h and @a l. 240*44d4804dSStefan Eßer * @param h The high 64 bits. 241*44d4804dSStefan Eßer * @param l The low 64 bits. 242*44d4804dSStefan Eßer * @return The constant built from @a h and @a l. 243*44d4804dSStefan Eßer */ 244252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) } 245252884aeSStefan Eßer 246*44d4804dSStefan Eßer /** 247*44d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 248*44d4804dSStefan Eßer * @param s The state to truncate. 249*44d4804dSStefan Eßer * @return The truncated state. 250*44d4804dSStefan Eßer */ 251252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((s).lo) 252*44d4804dSStefan Eßer 253*44d4804dSStefan Eßer /** 254*44d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 255*44d4804dSStefan Eßer * @param s The state to chop. 256*44d4804dSStefan Eßer * @return The chopped state's top bits. 257*44d4804dSStefan Eßer */ 258252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((s).hi) 259*44d4804dSStefan Eßer 260*44d4804dSStefan Eßer /** 261*44d4804dSStefan Eßer * Returns the rotate amount for a PCG state. 262*44d4804dSStefan Eßer * @param s The state to rotate. 263*44d4804dSStefan Eßer * @return The semi-rotated state. 264*44d4804dSStefan Eßer */ 265252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL)) 266252884aeSStefan Eßer 267*44d4804dSStefan Eßer /// A 64-bit integer with the bottom 32 bits set. 268252884aeSStefan Eßer #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL)) 269*44d4804dSStefan Eßer 270*44d4804dSStefan Eßer /** 271*44d4804dSStefan Eßer * Returns the 32-bit truncated value of @a n. 272*44d4804dSStefan Eßer * @param n The integer to truncate. 273*44d4804dSStefan Eßer * @return The bottom 32 bits of @a n. 274*44d4804dSStefan Eßer */ 275252884aeSStefan Eßer #define BC_RAND_TRUNC32(n) ((n) & BC_RAND_BOTTOM32) 276*44d4804dSStefan Eßer 277*44d4804dSStefan Eßer /** 278*44d4804dSStefan Eßer * Returns the second 32 bits of @a n. 279*44d4804dSStefan Eßer * @param n The integer to truncate. 280*44d4804dSStefan Eßer * @return The second 32 bits of @a n. 281*44d4804dSStefan Eßer */ 282252884aeSStefan Eßer #define BC_RAND_CHOP32(n) ((n) >> 32) 283252884aeSStefan Eßer 284252884aeSStefan Eßer #endif // BC_RAND_BUILTIN 285252884aeSStefan Eßer 286*44d4804dSStefan Eßer /// A constant defined by PCG. 287252884aeSStefan Eßer #define BC_RAND_MULTIPLIER \ 288252884aeSStefan Eßer BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) 289252884aeSStefan Eßer 290*44d4804dSStefan Eßer /** 291*44d4804dSStefan Eßer * Returns the result of a PCG fold. 292*44d4804dSStefan Eßer * @param s The state to fold. 293*44d4804dSStefan Eßer * @return The folded state. 294*44d4804dSStefan Eßer */ 295252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s))) 296252884aeSStefan Eßer 297252884aeSStefan Eßer #else // BC_LONG_BIT >= 64 298252884aeSStefan Eßer 299*44d4804dSStefan Eßer // If we are using 32-bit longs, we need to set these so. 300252884aeSStefan Eßer #undef BC_RAND_BUILTIN 301252884aeSStefan Eßer #define BC_RAND_BUILTIN (1) 302252884aeSStefan Eßer 303*44d4804dSStefan Eßer /// The type for random integers. 304252884aeSStefan Eßer typedef uint32_t BcRand; 305252884aeSStefan Eßer 306*44d4804dSStefan Eßer /// A constant defined by PCG. 307252884aeSStefan Eßer #define BC_RAND_ROTC (31) 308252884aeSStefan Eßer 309*44d4804dSStefan Eßer /// A typedef for the PCG state. 310252884aeSStefan Eßer typedef uint_fast64_t BcRandState; 311252884aeSStefan Eßer 312*44d4804dSStefan Eßer /** 313*44d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 314*44d4804dSStefan Eßer * @param a The first integer. 315*44d4804dSStefan Eßer * @param b The second integer. 316*44d4804dSStefan Eßer * @return The product of the PCG states. 317*44d4804dSStefan Eßer */ 318252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 319*44d4804dSStefan Eßer 320*44d4804dSStefan Eßer /** 321*44d4804dSStefan Eßer * Add two integers, worrying about overflow. 322*44d4804dSStefan Eßer * @param a The first integer. 323*44d4804dSStefan Eßer * @param b The second integer. 324*44d4804dSStefan Eßer * @return The sum of the PCG states. 325*44d4804dSStefan Eßer */ 326252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 327252884aeSStefan Eßer 328*44d4804dSStefan Eßer /** 329*44d4804dSStefan Eßer * Multiply two PCG states. 330*44d4804dSStefan Eßer * @param a The first PCG state. 331*44d4804dSStefan Eßer * @param b The second PCG state. 332*44d4804dSStefan Eßer * @return The product of the PCG states. 333*44d4804dSStefan Eßer */ 334252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 335*44d4804dSStefan Eßer 336*44d4804dSStefan Eßer /** 337*44d4804dSStefan Eßer * Add two PCG states. 338*44d4804dSStefan Eßer * @param a The first PCG state. 339*44d4804dSStefan Eßer * @param b The second PCG state. 340*44d4804dSStefan Eßer * @return The sum of the PCG states. 341*44d4804dSStefan Eßer */ 342252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 343252884aeSStefan Eßer 344*44d4804dSStefan Eßer /** 345*44d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 346*44d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 347*44d4804dSStefan Eßer * @param r The PRNG. 348*44d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 349*44d4804dSStefan Eßer */ 350252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 351*44d4804dSStefan Eßer 352*44d4804dSStefan Eßer /** 353*44d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 354*44d4804dSStefan Eßer * @param r The PRNG. 355*44d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 356*44d4804dSStefan Eßer */ 357252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 358252884aeSStefan Eßer 359*44d4804dSStefan Eßer /** 360*44d4804dSStefan Eßer * Returns a constant built from a number. 361*44d4804dSStefan Eßer * @param n The number. 362*44d4804dSStefan Eßer * @return The constant built from @a n. 363*44d4804dSStefan Eßer */ 364*44d4804dSStefan Eßer #define BC_RAND_CONSTANT(n) UINT64_C(n) 365*44d4804dSStefan Eßer 366*44d4804dSStefan Eßer /// A constant defined by PCG. 367252884aeSStefan Eßer #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005) 368252884aeSStefan Eßer 369*44d4804dSStefan Eßer /** 370*44d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 371*44d4804dSStefan Eßer * @param s The state to truncate. 372*44d4804dSStefan Eßer * @return The truncated state. 373*44d4804dSStefan Eßer */ 374252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint32_t) (s)) 375*44d4804dSStefan Eßer 376*44d4804dSStefan Eßer /** 377*44d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 378*44d4804dSStefan Eßer * @param s The state to chop. 379*44d4804dSStefan Eßer * @return The chopped state's top bits. 380*44d4804dSStefan Eßer */ 381252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL)) 382*44d4804dSStefan Eßer 383*44d4804dSStefan Eßer /** 384*44d4804dSStefan Eßer * Returns the rotate amount for a PCG state. 385*44d4804dSStefan Eßer * @param s The state to rotate. 386*44d4804dSStefan Eßer * @return The semi-rotated state. 387*44d4804dSStefan Eßer */ 388252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL)) 389252884aeSStefan Eßer 390*44d4804dSStefan Eßer /** 391*44d4804dSStefan Eßer * Returns the result of a PCG fold. 392*44d4804dSStefan Eßer * @param s The state to fold. 393*44d4804dSStefan Eßer * @return The folded state. 394*44d4804dSStefan Eßer */ 395252884aeSStefan Eßer #define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U)) 396252884aeSStefan Eßer 397252884aeSStefan Eßer #endif // BC_LONG_BIT >= 64 398252884aeSStefan Eßer 399*44d4804dSStefan Eßer /** 400*44d4804dSStefan Eßer * Rotates @a v by @a r bits. 401*44d4804dSStefan Eßer * @param v The value to rotate. 402*44d4804dSStefan Eßer * @param r The amount to rotate by. 403*44d4804dSStefan Eßer * @return The rotated value. 404*44d4804dSStefan Eßer */ 405252884aeSStefan Eßer #define BC_RAND_ROT(v, r) \ 406252884aeSStefan Eßer ((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC)))) 407252884aeSStefan Eßer 408*44d4804dSStefan Eßer /// The number of bits in a random integer. 409252884aeSStefan Eßer #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT) 410*44d4804dSStefan Eßer 411*44d4804dSStefan Eßer /// The number of bits in a PCG state. 412252884aeSStefan Eßer #define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT) 413252884aeSStefan Eßer 414*44d4804dSStefan Eßer /// The size of a BcNum with the max random integer. This isn't exact; it's 415*44d4804dSStefan Eßer /// actually rather crude. But it's always enough. 416252884aeSStefan Eßer #define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2) 417252884aeSStefan Eßer 418*44d4804dSStefan Eßer /// The mask for how many bits bc_rand_srand() can set per iteration. 419252884aeSStefan Eßer #define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1) 420252884aeSStefan Eßer 421*44d4804dSStefan Eßer /// The actual RNG data. These are the actual PRNG's. 422252884aeSStefan Eßer typedef struct BcRNGData { 423252884aeSStefan Eßer 424*44d4804dSStefan Eßer /// The state. 425252884aeSStefan Eßer BcRandState state; 426*44d4804dSStefan Eßer 427*44d4804dSStefan Eßer /// The increment and the modified bit. 428252884aeSStefan Eßer BcRandState inc; 429252884aeSStefan Eßer 430252884aeSStefan Eßer } BcRNGData; 431252884aeSStefan Eßer 432*44d4804dSStefan Eßer /// The public PRNG. This is just a stack of PRNG's to maintain the globals 433*44d4804dSStefan Eßer /// stack illusion. 434252884aeSStefan Eßer typedef struct BcRNG { 435252884aeSStefan Eßer 436*44d4804dSStefan Eßer /// The stack of PRNG's. 437252884aeSStefan Eßer BcVec v; 438252884aeSStefan Eßer 439252884aeSStefan Eßer } BcRNG; 440252884aeSStefan Eßer 441*44d4804dSStefan Eßer /** 442*44d4804dSStefan Eßer * Initializes a BcRNG. 443*44d4804dSStefan Eßer * @param r The BcRNG to initialize. 444*44d4804dSStefan Eßer */ 445252884aeSStefan Eßer void bc_rand_init(BcRNG *r); 446252884aeSStefan Eßer 447*44d4804dSStefan Eßer #if BC_RAND_USE_FREE 448*44d4804dSStefan Eßer 449*44d4804dSStefan Eßer /** 450*44d4804dSStefan Eßer * Frees a BcRNG. This is only in debug builds because it would only be freed on 451*44d4804dSStefan Eßer * exit. 452*44d4804dSStefan Eßer * @param r The BcRNG to free. 453*44d4804dSStefan Eßer */ 454*44d4804dSStefan Eßer void bc_rand_free(BcRNG *r); 455*44d4804dSStefan Eßer 456*44d4804dSStefan Eßer #endif // BC_RAND_USE_FREE 457*44d4804dSStefan Eßer 458*44d4804dSStefan Eßer /** 459*44d4804dSStefan Eßer * Returns a random integer from the PRNG. 460*44d4804dSStefan Eßer * @param r The PRNG. 461*44d4804dSStefan Eßer * @return A random integer. 462*44d4804dSStefan Eßer */ 463252884aeSStefan Eßer BcRand bc_rand_int(BcRNG *r); 464*44d4804dSStefan Eßer 465*44d4804dSStefan Eßer /** 466*44d4804dSStefan Eßer * Returns a random integer from the PRNG bounded by @a bound. Bias is 467*44d4804dSStefan Eßer * eliminated. 468*44d4804dSStefan Eßer * @param r The PRNG. 469*44d4804dSStefan Eßer * @param bound The bound for the random integer. 470*44d4804dSStefan Eßer * @return A bounded random integer. 471*44d4804dSStefan Eßer */ 472252884aeSStefan Eßer BcRand bc_rand_bounded(BcRNG *r, BcRand bound); 473*44d4804dSStefan Eßer 474*44d4804dSStefan Eßer /** 475*44d4804dSStefan Eßer * Seed the PRNG with the state in two parts and the increment in two parts. 476*44d4804dSStefan Eßer * @param r The PRNG. 477*44d4804dSStefan Eßer * @param state1 The first part of the state. 478*44d4804dSStefan Eßer * @param state2 The second part of the state. 479*44d4804dSStefan Eßer * @param inc1 The first part of the increment. 480*44d4804dSStefan Eßer * @param inc2 The second part of the increment. 481*44d4804dSStefan Eßer */ 482252884aeSStefan Eßer void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2); 483*44d4804dSStefan Eßer 484*44d4804dSStefan Eßer /** 485*44d4804dSStefan Eßer * Pushes a new PRNG onto the PRNG stack. 486*44d4804dSStefan Eßer * @param r The PRNG. 487*44d4804dSStefan Eßer */ 488252884aeSStefan Eßer void bc_rand_push(BcRNG *r); 489*44d4804dSStefan Eßer 490*44d4804dSStefan Eßer /** 491*44d4804dSStefan Eßer * Pops one or all but one items off of the PRNG stack. 492*44d4804dSStefan Eßer * @param r The PRNG. 493*44d4804dSStefan Eßer * @param reset True if all but one PRNG should be popped off the stack, false 494*44d4804dSStefan Eßer * if only one should be popped. 495*44d4804dSStefan Eßer */ 496252884aeSStefan Eßer void bc_rand_pop(BcRNG *r, bool reset); 497*44d4804dSStefan Eßer 498*44d4804dSStefan Eßer /** 499*44d4804dSStefan Eßer * Returns, via pointers, the state of the PRNG in pieces. 500*44d4804dSStefan Eßer * @param r The PRNG. 501*44d4804dSStefan Eßer * @param s1 The return value for the first part of the state. 502*44d4804dSStefan Eßer * @param s2 The return value for the second part of the state. 503*44d4804dSStefan Eßer * @param i1 The return value for the first part of the increment. 504*44d4804dSStefan Eßer * @param i2 The return value for the second part of the increment. 505*44d4804dSStefan Eßer */ 506252884aeSStefan Eßer void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2); 507*44d4804dSStefan Eßer 508*44d4804dSStefan Eßer /** 509*44d4804dSStefan Eßer * Seed the PRNG with random data. 510*44d4804dSStefan Eßer * @param rng The PRNG. 511*44d4804dSStefan Eßer */ 51250696a6eSStefan Eßer void bc_rand_srand(BcRNGData *rng); 513252884aeSStefan Eßer 514*44d4804dSStefan Eßer /// A reference to a constant multiplier. 515252884aeSStefan Eßer extern const BcRandState bc_rand_multiplier; 516252884aeSStefan Eßer 517252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 518252884aeSStefan Eßer 519252884aeSStefan Eßer #endif // BC_RAND_H 520