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 16*a970610aSStefan Eßer * Copyright (c) 2018-2024 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 5344d4804dSStefan Eßer #if BC_ENABLE_LIBRARY 5444d4804dSStefan Eßer #define BC_RAND_USE_FREE (1) 5544d4804dSStefan Eßer #else // BC_ENABLE_LIBRARY 56103d7cdfSStefan Eßer #if BC_DEBUG 5744d4804dSStefan Eßer #define BC_RAND_USE_FREE (1) 58103d7cdfSStefan Eßer #else // BC_DEBUG 5944d4804dSStefan Eßer #define BC_RAND_USE_FREE (0) 60103d7cdfSStefan Eßer #endif // BC_DEBUG 6144d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY 623aa99676SStefan Eßer 6344d4804dSStefan Eßer /** 6444d4804dSStefan Eßer * A function to return a random unsigned long. 6544d4804dSStefan Eßer * @param ptr A void ptr to some data that will help generate the random ulong. 6644d4804dSStefan Eßer * @return The random ulong. 6744d4804dSStefan Eßer */ 6844d4804dSStefan Eßer typedef ulong (*BcRandUlong)(void* ptr); 69252884aeSStefan Eßer 70252884aeSStefan Eßer #if BC_LONG_BIT >= 64 71252884aeSStefan Eßer 7244d4804dSStefan Eßer // If longs are 64 bits, we have the option of 128-bit integers on some 7344d4804dSStefan 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 9144d4804dSStefan Eßer /// The type for random integers. 92252884aeSStefan Eßer typedef uint64_t BcRand; 93252884aeSStefan Eßer 9444d4804dSStefan 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 9944d4804dSStefan Eßer /// A typedef for the PCG state. 100252884aeSStefan Eßer typedef __uint128_t BcRandState; 101252884aeSStefan Eßer 10244d4804dSStefan Eßer /** 10344d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 10444d4804dSStefan Eßer * @param a The first integer. 10544d4804dSStefan Eßer * @param b The second integer. 10644d4804dSStefan Eßer * @return The product of the PCG states. 10744d4804dSStefan Eßer */ 108252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 10944d4804dSStefan Eßer 11044d4804dSStefan Eßer /** 11144d4804dSStefan Eßer * Add two integers, worrying about overflow. 11244d4804dSStefan Eßer * @param a The first integer. 11344d4804dSStefan Eßer * @param b The second integer. 11444d4804dSStefan Eßer * @return The sum of the PCG states. 11544d4804dSStefan Eßer */ 116252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 117252884aeSStefan Eßer 11844d4804dSStefan Eßer /** 11944d4804dSStefan Eßer * Multiply two PCG states. 12044d4804dSStefan Eßer * @param a The first PCG state. 12144d4804dSStefan Eßer * @param b The second PCG state. 12244d4804dSStefan Eßer * @return The product of the PCG states. 12344d4804dSStefan Eßer */ 124252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 12544d4804dSStefan Eßer 12644d4804dSStefan Eßer /** 12744d4804dSStefan Eßer * Add two PCG states. 12844d4804dSStefan Eßer * @param a The first PCG state. 12944d4804dSStefan Eßer * @param b The second PCG state. 13044d4804dSStefan Eßer * @return The sum of the PCG states. 13144d4804dSStefan Eßer */ 132252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 133252884aeSStefan Eßer 13444d4804dSStefan Eßer /** 13544d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 13644d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 13744d4804dSStefan Eßer * @param r The PRNG. 13844d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 13944d4804dSStefan Eßer */ 140252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 14144d4804dSStefan Eßer 14244d4804dSStefan Eßer /** 14344d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 14444d4804dSStefan Eßer * @param r The PRNG. 14544d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 14644d4804dSStefan Eßer */ 147252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 148252884aeSStefan Eßer 14944d4804dSStefan Eßer /** 15044d4804dSStefan Eßer * Returns a constant built from @a h and @a l. 15144d4804dSStefan Eßer * @param h The high 64 bits. 15244d4804dSStefan Eßer * @param l The low 64 bits. 15344d4804dSStefan Eßer * @return The constant built from @a h and @a l. 15444d4804dSStefan Eßer */ 155252884aeSStefan Eßer #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l)) 156252884aeSStefan Eßer 15744d4804dSStefan Eßer /** 15844d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 15944d4804dSStefan Eßer * @param s The state to truncate. 16044d4804dSStefan Eßer * @return The truncated state. 16144d4804dSStefan Eßer */ 162252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint64_t) (s)) 16344d4804dSStefan Eßer 16444d4804dSStefan Eßer /** 16544d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 16644d4804dSStefan Eßer * @param s The state to chop. 16744d4804dSStefan Eßer * @return The chopped state's top bits. 16844d4804dSStefan Eßer */ 169252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL)) 17044d4804dSStefan Eßer 17144d4804dSStefan Eßer /** 17244d4804dSStefan Eßer * Rotates a PCG state. 17344d4804dSStefan Eßer * @param s The state to rotate. 17444d4804dSStefan Eßer * @return The rotated state. 17544d4804dSStefan 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 18044d4804dSStefan Eßer /// A typedef for the PCG state. 18178bc019dSStefan Eßer typedef struct BcRandState 18278bc019dSStefan Eßer { 18344d4804dSStefan Eßer /// The low bits. 184252884aeSStefan Eßer uint_fast64_t lo; 18544d4804dSStefan Eßer 18644d4804dSStefan Eßer /// The high bits. 187252884aeSStefan Eßer uint_fast64_t hi; 188252884aeSStefan Eßer 189252884aeSStefan Eßer } BcRandState; 190252884aeSStefan Eßer 19144d4804dSStefan Eßer /** 19244d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 19344d4804dSStefan Eßer * @param a The first integer. 19444d4804dSStefan Eßer * @param b The second integer. 19544d4804dSStefan Eßer * @return The product of the PCG states. 19644d4804dSStefan Eßer */ 197252884aeSStefan Eßer #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b))) 19844d4804dSStefan Eßer 19944d4804dSStefan Eßer /** 20044d4804dSStefan Eßer * Add two integers, worrying about overflow. 20144d4804dSStefan Eßer * @param a The first integer. 20244d4804dSStefan Eßer * @param b The second integer. 20344d4804dSStefan Eßer * @return The sum of the PCG states. 20444d4804dSStefan Eßer */ 205252884aeSStefan Eßer #define bc_rand_add(a, b) (bc_rand_addition((a), (b))) 206252884aeSStefan Eßer 20744d4804dSStefan Eßer /** 20844d4804dSStefan Eßer * Multiply two PCG states. 20944d4804dSStefan Eßer * @param a The first PCG state. 21044d4804dSStefan Eßer * @param b The second PCG state. 21144d4804dSStefan Eßer * @return The product of the PCG states. 21244d4804dSStefan Eßer */ 213252884aeSStefan Eßer #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b))) 21444d4804dSStefan Eßer 21544d4804dSStefan Eßer /** 21644d4804dSStefan Eßer * Add two PCG states. 21744d4804dSStefan Eßer * @param a The first PCG state. 21844d4804dSStefan Eßer * @param b The second PCG state. 21944d4804dSStefan Eßer * @return The sum of the PCG states. 22044d4804dSStefan Eßer */ 221252884aeSStefan Eßer #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b))) 222252884aeSStefan Eßer 22344d4804dSStefan Eßer /** 22444d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 22544d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 22644d4804dSStefan Eßer * @param r The PRNG. 22744d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 22844d4804dSStefan Eßer */ 229252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0) 23044d4804dSStefan Eßer 23144d4804dSStefan Eßer /** 23244d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 23344d4804dSStefan Eßer * @param r The PRNG. 23444d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 23544d4804dSStefan Eßer */ 236252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi) 237252884aeSStefan Eßer 23844d4804dSStefan Eßer /** 23944d4804dSStefan Eßer * Returns a constant built from @a h and @a l. 24044d4804dSStefan Eßer * @param h The high 64 bits. 24144d4804dSStefan Eßer * @param l The low 64 bits. 24244d4804dSStefan Eßer * @return The constant built from @a h and @a l. 24344d4804dSStefan Eßer */ 244*a970610aSStefan Eßer #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) } 245252884aeSStefan Eßer 24644d4804dSStefan Eßer /** 24744d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 24844d4804dSStefan Eßer * @param s The state to truncate. 24944d4804dSStefan Eßer * @return The truncated state. 25044d4804dSStefan Eßer */ 251252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((s).lo) 25244d4804dSStefan Eßer 25344d4804dSStefan Eßer /** 25444d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 25544d4804dSStefan Eßer * @param s The state to chop. 25644d4804dSStefan Eßer * @return The chopped state's top bits. 25744d4804dSStefan Eßer */ 258252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((s).hi) 25944d4804dSStefan Eßer 26044d4804dSStefan Eßer /** 26144d4804dSStefan Eßer * Returns the rotate amount for a PCG state. 26244d4804dSStefan Eßer * @param s The state to rotate. 26344d4804dSStefan Eßer * @return The semi-rotated state. 26444d4804dSStefan Eßer */ 265252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL)) 266252884aeSStefan Eßer 26744d4804dSStefan Eßer /// A 64-bit integer with the bottom 32 bits set. 268252884aeSStefan Eßer #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL)) 26944d4804dSStefan Eßer 27044d4804dSStefan Eßer /** 27144d4804dSStefan Eßer * Returns the 32-bit truncated value of @a n. 27244d4804dSStefan Eßer * @param n The integer to truncate. 27344d4804dSStefan Eßer * @return The bottom 32 bits of @a n. 27444d4804dSStefan Eßer */ 27578bc019dSStefan Eßer #define BC_RAND_TRUNC32(n) ((n) & (BC_RAND_BOTTOM32)) 27644d4804dSStefan Eßer 27744d4804dSStefan Eßer /** 27844d4804dSStefan Eßer * Returns the second 32 bits of @a n. 27944d4804dSStefan Eßer * @param n The integer to truncate. 28044d4804dSStefan Eßer * @return The second 32 bits of @a n. 28144d4804dSStefan 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 28644d4804dSStefan 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 29044d4804dSStefan Eßer /** 29144d4804dSStefan Eßer * Returns the result of a PCG fold. 29244d4804dSStefan Eßer * @param s The state to fold. 29344d4804dSStefan Eßer * @return The folded state. 29444d4804dSStefan 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 29944d4804dSStefan 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 30344d4804dSStefan Eßer /// The type for random integers. 304252884aeSStefan Eßer typedef uint32_t BcRand; 305252884aeSStefan Eßer 30644d4804dSStefan Eßer /// A constant defined by PCG. 307252884aeSStefan Eßer #define BC_RAND_ROTC (31) 308252884aeSStefan Eßer 30944d4804dSStefan Eßer /// A typedef for the PCG state. 310252884aeSStefan Eßer typedef uint_fast64_t BcRandState; 311252884aeSStefan Eßer 31244d4804dSStefan Eßer /** 31344d4804dSStefan Eßer * Multiply two integers, worrying about overflow. 31444d4804dSStefan Eßer * @param a The first integer. 31544d4804dSStefan Eßer * @param b The second integer. 31644d4804dSStefan Eßer * @return The product of the PCG states. 31744d4804dSStefan Eßer */ 318252884aeSStefan Eßer #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 31944d4804dSStefan Eßer 32044d4804dSStefan Eßer /** 32144d4804dSStefan Eßer * Add two integers, worrying about overflow. 32244d4804dSStefan Eßer * @param a The first integer. 32344d4804dSStefan Eßer * @param b The second integer. 32444d4804dSStefan Eßer * @return The sum of the PCG states. 32544d4804dSStefan Eßer */ 326252884aeSStefan Eßer #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 327252884aeSStefan Eßer 32844d4804dSStefan Eßer /** 32944d4804dSStefan Eßer * Multiply two PCG states. 33044d4804dSStefan Eßer * @param a The first PCG state. 33144d4804dSStefan Eßer * @param b The second PCG state. 33244d4804dSStefan Eßer * @return The product of the PCG states. 33344d4804dSStefan Eßer */ 334252884aeSStefan Eßer #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 33544d4804dSStefan Eßer 33644d4804dSStefan Eßer /** 33744d4804dSStefan Eßer * Add two PCG states. 33844d4804dSStefan Eßer * @param a The first PCG state. 33944d4804dSStefan Eßer * @param b The second PCG state. 34044d4804dSStefan Eßer * @return The sum of the PCG states. 34144d4804dSStefan Eßer */ 342252884aeSStefan Eßer #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 343252884aeSStefan Eßer 34444d4804dSStefan Eßer /** 34544d4804dSStefan Eßer * Figure out if the PRNG has been modified. Since the increment of the PRNG has 34644d4804dSStefan Eßer * to be odd, we use the extra bit to store whether it has been modified or not. 34744d4804dSStefan Eßer * @param r The PRNG. 34844d4804dSStefan Eßer * @return True if the PRNG has *not* been modified, false otherwise. 34944d4804dSStefan Eßer */ 350252884aeSStefan Eßer #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 35144d4804dSStefan Eßer 35244d4804dSStefan Eßer /** 35344d4804dSStefan Eßer * Return true if the PRNG has not been seeded yet. 35444d4804dSStefan Eßer * @param r The PRNG. 35544d4804dSStefan Eßer * @return True if the PRNG has not been seeded yet, false otherwise. 35644d4804dSStefan Eßer */ 357252884aeSStefan Eßer #define BC_RAND_ZERO(r) (!(r)->state) 358252884aeSStefan Eßer 35944d4804dSStefan Eßer /** 36044d4804dSStefan Eßer * Returns a constant built from a number. 36144d4804dSStefan Eßer * @param n The number. 36244d4804dSStefan Eßer * @return The constant built from @a n. 36344d4804dSStefan Eßer */ 36444d4804dSStefan Eßer #define BC_RAND_CONSTANT(n) UINT64_C(n) 36544d4804dSStefan Eßer 36644d4804dSStefan Eßer /// A constant defined by PCG. 367252884aeSStefan Eßer #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005) 368252884aeSStefan Eßer 36944d4804dSStefan Eßer /** 37044d4804dSStefan Eßer * Truncates a PCG state to the number of bits in a random integer. 37144d4804dSStefan Eßer * @param s The state to truncate. 37244d4804dSStefan Eßer * @return The truncated state. 37344d4804dSStefan Eßer */ 374252884aeSStefan Eßer #define BC_RAND_TRUNC(s) ((uint32_t) (s)) 37544d4804dSStefan Eßer 37644d4804dSStefan Eßer /** 37744d4804dSStefan Eßer * Chops a PCG state in half and returns the top bits. 37844d4804dSStefan Eßer * @param s The state to chop. 37944d4804dSStefan Eßer * @return The chopped state's top bits. 38044d4804dSStefan Eßer */ 381252884aeSStefan Eßer #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL)) 38244d4804dSStefan Eßer 38344d4804dSStefan Eßer /** 38444d4804dSStefan Eßer * Returns the rotate amount for a PCG state. 38544d4804dSStefan Eßer * @param s The state to rotate. 38644d4804dSStefan Eßer * @return The semi-rotated state. 38744d4804dSStefan Eßer */ 388252884aeSStefan Eßer #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL)) 389252884aeSStefan Eßer 39044d4804dSStefan Eßer /** 39144d4804dSStefan Eßer * Returns the result of a PCG fold. 39244d4804dSStefan Eßer * @param s The state to fold. 39344d4804dSStefan Eßer * @return The folded state. 39444d4804dSStefan 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 39944d4804dSStefan Eßer /** 40044d4804dSStefan Eßer * Rotates @a v by @a r bits. 40144d4804dSStefan Eßer * @param v The value to rotate. 40244d4804dSStefan Eßer * @param r The amount to rotate by. 40344d4804dSStefan Eßer * @return The rotated value. 40444d4804dSStefan 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 40844d4804dSStefan Eßer /// The number of bits in a random integer. 409252884aeSStefan Eßer #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT) 41044d4804dSStefan Eßer 41144d4804dSStefan 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 41444d4804dSStefan Eßer /// The size of a BcNum with the max random integer. This isn't exact; it's 41544d4804dSStefan 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 41844d4804dSStefan 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 42144d4804dSStefan Eßer /// The actual RNG data. These are the actual PRNG's. 42278bc019dSStefan Eßer typedef struct BcRNGData 42378bc019dSStefan Eßer { 42444d4804dSStefan Eßer /// The state. 425252884aeSStefan Eßer BcRandState state; 42644d4804dSStefan Eßer 42744d4804dSStefan Eßer /// The increment and the modified bit. 428252884aeSStefan Eßer BcRandState inc; 429252884aeSStefan Eßer 430252884aeSStefan Eßer } BcRNGData; 431252884aeSStefan Eßer 43244d4804dSStefan Eßer /// The public PRNG. This is just a stack of PRNG's to maintain the globals 43344d4804dSStefan Eßer /// stack illusion. 43478bc019dSStefan Eßer typedef struct BcRNG 43578bc019dSStefan Eßer { 43644d4804dSStefan Eßer /// The stack of PRNG's. 437252884aeSStefan Eßer BcVec v; 438252884aeSStefan Eßer 439252884aeSStefan Eßer } BcRNG; 440252884aeSStefan Eßer 44144d4804dSStefan Eßer /** 44244d4804dSStefan Eßer * Initializes a BcRNG. 44344d4804dSStefan Eßer * @param r The BcRNG to initialize. 44444d4804dSStefan Eßer */ 44578bc019dSStefan Eßer void 44678bc019dSStefan Eßer bc_rand_init(BcRNG* r); 447252884aeSStefan Eßer 44844d4804dSStefan Eßer #if BC_RAND_USE_FREE 44944d4804dSStefan Eßer 45044d4804dSStefan Eßer /** 45144d4804dSStefan Eßer * Frees a BcRNG. This is only in debug builds because it would only be freed on 45244d4804dSStefan Eßer * exit. 45344d4804dSStefan Eßer * @param r The BcRNG to free. 45444d4804dSStefan Eßer */ 45578bc019dSStefan Eßer void 45678bc019dSStefan Eßer bc_rand_free(BcRNG* r); 45744d4804dSStefan Eßer 45844d4804dSStefan Eßer #endif // BC_RAND_USE_FREE 45944d4804dSStefan Eßer 46044d4804dSStefan Eßer /** 46144d4804dSStefan Eßer * Returns a random integer from the PRNG. 46244d4804dSStefan Eßer * @param r The PRNG. 46344d4804dSStefan Eßer * @return A random integer. 46444d4804dSStefan Eßer */ 46578bc019dSStefan Eßer BcRand 46678bc019dSStefan Eßer bc_rand_int(BcRNG* r); 46744d4804dSStefan Eßer 46844d4804dSStefan Eßer /** 46944d4804dSStefan Eßer * Returns a random integer from the PRNG bounded by @a bound. Bias is 47044d4804dSStefan Eßer * eliminated. 47144d4804dSStefan Eßer * @param r The PRNG. 47244d4804dSStefan Eßer * @param bound The bound for the random integer. 47344d4804dSStefan Eßer * @return A bounded random integer. 47444d4804dSStefan Eßer */ 47578bc019dSStefan Eßer BcRand 47678bc019dSStefan Eßer bc_rand_bounded(BcRNG* r, BcRand bound); 47744d4804dSStefan Eßer 47844d4804dSStefan Eßer /** 47944d4804dSStefan Eßer * Seed the PRNG with the state in two parts and the increment in two parts. 48044d4804dSStefan Eßer * @param r The PRNG. 48144d4804dSStefan Eßer * @param state1 The first part of the state. 48244d4804dSStefan Eßer * @param state2 The second part of the state. 48344d4804dSStefan Eßer * @param inc1 The first part of the increment. 48444d4804dSStefan Eßer * @param inc2 The second part of the increment. 48544d4804dSStefan Eßer */ 48678bc019dSStefan Eßer void 48778bc019dSStefan Eßer bc_rand_seed(BcRNG* r, ulong state1, ulong state2, ulong inc1, ulong inc2); 48844d4804dSStefan Eßer 48944d4804dSStefan Eßer /** 49044d4804dSStefan Eßer * Pushes a new PRNG onto the PRNG stack. 49144d4804dSStefan Eßer * @param r The PRNG. 49244d4804dSStefan Eßer */ 49378bc019dSStefan Eßer void 49478bc019dSStefan Eßer bc_rand_push(BcRNG* r); 49544d4804dSStefan Eßer 49644d4804dSStefan Eßer /** 49744d4804dSStefan Eßer * Pops one or all but one items off of the PRNG stack. 49844d4804dSStefan Eßer * @param r The PRNG. 49944d4804dSStefan Eßer * @param reset True if all but one PRNG should be popped off the stack, false 50044d4804dSStefan Eßer * if only one should be popped. 50144d4804dSStefan Eßer */ 50278bc019dSStefan Eßer void 50378bc019dSStefan Eßer bc_rand_pop(BcRNG* r, bool reset); 50444d4804dSStefan Eßer 50544d4804dSStefan Eßer /** 50644d4804dSStefan Eßer * Returns, via pointers, the state of the PRNG in pieces. 50744d4804dSStefan Eßer * @param r The PRNG. 50844d4804dSStefan Eßer * @param s1 The return value for the first part of the state. 50944d4804dSStefan Eßer * @param s2 The return value for the second part of the state. 51044d4804dSStefan Eßer * @param i1 The return value for the first part of the increment. 51144d4804dSStefan Eßer * @param i2 The return value for the second part of the increment. 51244d4804dSStefan Eßer */ 51378bc019dSStefan Eßer void 51478bc019dSStefan Eßer bc_rand_getRands(BcRNG* r, BcRand* s1, BcRand* s2, BcRand* i1, BcRand* i2); 51544d4804dSStefan Eßer 51644d4804dSStefan Eßer /** 51744d4804dSStefan Eßer * Seed the PRNG with random data. 51844d4804dSStefan Eßer * @param rng The PRNG. 51944d4804dSStefan Eßer */ 52078bc019dSStefan Eßer void 52178bc019dSStefan Eßer bc_rand_srand(BcRNGData* rng); 522252884aeSStefan Eßer 52344d4804dSStefan Eßer /// A reference to a constant multiplier. 524252884aeSStefan Eßer extern const BcRandState bc_rand_multiplier; 525252884aeSStefan Eßer 526252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 527252884aeSStefan Eßer 528252884aeSStefan Eßer #endif // BC_RAND_H 529