/*1* *****************************************************************************2*3* Parts of this code are adapted from the following:4*5* PCG, A Family of Better Random Number Generators.6*7* You can find the original source code at:8* https://github.com/imneme/pcg-c9*10* -----------------------------------------------------------------------------11*12* This code is under the following license:13*14* Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors15* Copyright (c) 2018-2025 Gavin D. Howard and contributors.16*17* Permission is hereby granted, free of charge, to any person obtaining a copy18* of this software and associated documentation files (the "Software"), to deal19* in the Software without restriction, including without limitation the rights20* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell21* copies of the Software, and to permit persons to whom the Software is22* furnished to do so, subject to the following conditions:23*24* The above copyright notice and this permission notice shall be included in25* all copies or substantial portions of the Software.26*27* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR28* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,29* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE30* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER31* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,32* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE33* SOFTWARE.34*35* *****************************************************************************36*37* Definitions for the RNG.38*39*/4041#ifndef BC_RAND_H42#define BC_RAND_H4344#include <stdint.h>45#include <inttypes.h>4647#include <vector.h>48#include <num.h>4950#if BC_ENABLE_EXTRA_MATH5152#if BC_ENABLE_LIBRARY53#define BC_RAND_USE_FREE (1)54#else // BC_ENABLE_LIBRARY55#if BC_DEBUG56#define BC_RAND_USE_FREE (1)57#else // BC_DEBUG58#define BC_RAND_USE_FREE (0)59#endif // BC_DEBUG60#endif // BC_ENABLE_LIBRARY6162/**63* A function to return a random unsigned long.64* @param ptr A void ptr to some data that will help generate the random ulong.65* @return The random ulong.66*/67typedef ulong (*BcRandUlong)(void* ptr);6869#if BC_LONG_BIT >= 647071// If longs are 64 bits, we have the option of 128-bit integers on some72// compilers. These two sections test that.73#ifdef BC_RAND_BUILTIN74#if BC_RAND_BUILTIN75#ifndef __SIZEOF_INT128__76#undef BC_RAND_BUILTIN77#define BC_RAND_BUILTIN (0)78#endif // __SIZEOF_INT128__79#endif // BC_RAND_BUILTIN80#endif // BC_RAND_BUILTIN8182#ifndef BC_RAND_BUILTIN83#ifdef __SIZEOF_INT128__84#define BC_RAND_BUILTIN (1)85#else // __SIZEOF_INT128__86#define BC_RAND_BUILTIN (0)87#endif // __SIZEOF_INT128__88#endif // BC_RAND_BUILTIN8990/// The type for random integers.91typedef uint64_t BcRand;9293/// A constant defined by PCG.94#define BC_RAND_ROTC (63)9596#if BC_RAND_BUILTIN9798/// A typedef for the PCG state.99typedef __uint128_t BcRandState;100101/**102* Multiply two integers, worrying about overflow.103* @param a The first integer.104* @param b The second integer.105* @return The product of the PCG states.106*/107#define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))108109/**110* Add two integers, worrying about overflow.111* @param a The first integer.112* @param b The second integer.113* @return The sum of the PCG states.114*/115#define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))116117/**118* Multiply two PCG states.119* @param a The first PCG state.120* @param b The second PCG state.121* @return The product of the PCG states.122*/123#define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))124125/**126* Add two PCG states.127* @param a The first PCG state.128* @param b The second PCG state.129* @return The sum of the PCG states.130*/131#define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))132133/**134* Figure out if the PRNG has been modified. Since the increment of the PRNG has135* to be odd, we use the extra bit to store whether it has been modified or not.136* @param r The PRNG.137* @return True if the PRNG has *not* been modified, false otherwise.138*/139#define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0)140141/**142* Return true if the PRNG has not been seeded yet.143* @param r The PRNG.144* @return True if the PRNG has not been seeded yet, false otherwise.145*/146#define BC_RAND_ZERO(r) (!(r)->state)147148/**149* Returns a constant built from @a h and @a l.150* @param h The high 64 bits.151* @param l The low 64 bits.152* @return The constant built from @a h and @a l.153*/154#define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l))155156/**157* Truncates a PCG state to the number of bits in a random integer.158* @param s The state to truncate.159* @return The truncated state.160*/161#define BC_RAND_TRUNC(s) ((uint64_t) (s))162163/**164* Chops a PCG state in half and returns the top bits.165* @param s The state to chop.166* @return The chopped state's top bits.167*/168#define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL))169170/**171* Rotates a PCG state.172* @param s The state to rotate.173* @return The rotated state.174*/175#define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL))176177#else // BC_RAND_BUILTIN178179/// A typedef for the PCG state.180typedef struct BcRandState181{182/// The low bits.183uint_fast64_t lo;184185/// The high bits.186uint_fast64_t hi;187188} BcRandState;189190/**191* Multiply two integers, worrying about overflow.192* @param a The first integer.193* @param b The second integer.194* @return The product of the PCG states.195*/196#define bc_rand_mul(a, b) (bc_rand_multiply((a), (b)))197198/**199* Add two integers, worrying about overflow.200* @param a The first integer.201* @param b The second integer.202* @return The sum of the PCG states.203*/204#define bc_rand_add(a, b) (bc_rand_addition((a), (b)))205206/**207* Multiply two PCG states.208* @param a The first PCG state.209* @param b The second PCG state.210* @return The product of the PCG states.211*/212#define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b)))213214/**215* Add two PCG states.216* @param a The first PCG state.217* @param b The second PCG state.218* @return The sum of the PCG states.219*/220#define bc_rand_add2(a, b) (bc_rand_addition2((a), (b)))221222/**223* Figure out if the PRNG has been modified. Since the increment of the PRNG has224* to be odd, we use the extra bit to store whether it has been modified or not.225* @param r The PRNG.226* @return True if the PRNG has *not* been modified, false otherwise.227*/228#define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0)229230/**231* Return true if the PRNG has not been seeded yet.232* @param r The PRNG.233* @return True if the PRNG has not been seeded yet, false otherwise.234*/235#define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi)236237/**238* Returns a constant built from @a h and @a l.239* @param h The high 64 bits.240* @param l The low 64 bits.241* @return The constant built from @a h and @a l.242*/243#define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) }244245/**246* Truncates a PCG state to the number of bits in a random integer.247* @param s The state to truncate.248* @return The truncated state.249*/250#define BC_RAND_TRUNC(s) ((s).lo)251252/**253* Chops a PCG state in half and returns the top bits.254* @param s The state to chop.255* @return The chopped state's top bits.256*/257#define BC_RAND_CHOP(s) ((s).hi)258259/**260* Returns the rotate amount for a PCG state.261* @param s The state to rotate.262* @return The semi-rotated state.263*/264#define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL))265266/// A 64-bit integer with the bottom 32 bits set.267#define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL))268269/**270* Returns the 32-bit truncated value of @a n.271* @param n The integer to truncate.272* @return The bottom 32 bits of @a n.273*/274#define BC_RAND_TRUNC32(n) ((n) & (BC_RAND_BOTTOM32))275276/**277* Returns the second 32 bits of @a n.278* @param n The integer to truncate.279* @return The second 32 bits of @a n.280*/281#define BC_RAND_CHOP32(n) ((n) >> 32)282283#endif // BC_RAND_BUILTIN284285/// A constant defined by PCG.286#define BC_RAND_MULTIPLIER \287BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL)288289/**290* Returns the result of a PCG fold.291* @param s The state to fold.292* @return The folded state.293*/294#define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s)))295296#else // BC_LONG_BIT >= 64297298// If we are using 32-bit longs, we need to set these so.299#undef BC_RAND_BUILTIN300#define BC_RAND_BUILTIN (1)301302/// The type for random integers.303typedef uint32_t BcRand;304305/// A constant defined by PCG.306#define BC_RAND_ROTC (31)307308/// A typedef for the PCG state.309typedef uint_fast64_t BcRandState;310311/**312* Multiply two integers, worrying about overflow.313* @param a The first integer.314* @param b The second integer.315* @return The product of the PCG states.316*/317#define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))318319/**320* Add two integers, worrying about overflow.321* @param a The first integer.322* @param b The second integer.323* @return The sum of the PCG states.324*/325#define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))326327/**328* Multiply two PCG states.329* @param a The first PCG state.330* @param b The second PCG state.331* @return The product of the PCG states.332*/333#define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b)))334335/**336* Add two PCG states.337* @param a The first PCG state.338* @param b The second PCG state.339* @return The sum of the PCG states.340*/341#define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b)))342343/**344* Figure out if the PRNG has been modified. Since the increment of the PRNG has345* to be odd, we use the extra bit to store whether it has been modified or not.346* @param r The PRNG.347* @return True if the PRNG has *not* been modified, false otherwise.348*/349#define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0)350351/**352* Return true if the PRNG has not been seeded yet.353* @param r The PRNG.354* @return True if the PRNG has not been seeded yet, false otherwise.355*/356#define BC_RAND_ZERO(r) (!(r)->state)357358/**359* Returns a constant built from a number.360* @param n The number.361* @return The constant built from @a n.362*/363#define BC_RAND_CONSTANT(n) UINT64_C(n)364365/// A constant defined by PCG.366#define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005)367368/**369* Truncates a PCG state to the number of bits in a random integer.370* @param s The state to truncate.371* @return The truncated state.372*/373#define BC_RAND_TRUNC(s) ((uint32_t) (s))374375/**376* Chops a PCG state in half and returns the top bits.377* @param s The state to chop.378* @return The chopped state's top bits.379*/380#define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL))381382/**383* Returns the rotate amount for a PCG state.384* @param s The state to rotate.385* @return The semi-rotated state.386*/387#define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL))388389/**390* Returns the result of a PCG fold.391* @param s The state to fold.392* @return The folded state.393*/394#define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U))395396#endif // BC_LONG_BIT >= 64397398/**399* Rotates @a v by @a r bits.400* @param v The value to rotate.401* @param r The amount to rotate by.402* @return The rotated value.403*/404#define BC_RAND_ROT(v, r) \405((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC))))406407/// The number of bits in a random integer.408#define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT)409410/// The number of bits in a PCG state.411#define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT)412413/// The size of a BcNum with the max random integer. This isn't exact; it's414/// actually rather crude. But it's always enough.415#define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2)416417/// The mask for how many bits bc_rand_srand() can set per iteration.418#define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1)419420/// The actual RNG data. These are the actual PRNG's.421typedef struct BcRNGData422{423/// The state.424BcRandState state;425426/// The increment and the modified bit.427BcRandState inc;428429} BcRNGData;430431/// The public PRNG. This is just a stack of PRNG's to maintain the globals432/// stack illusion.433typedef struct BcRNG434{435/// The stack of PRNG's.436BcVec v;437438} BcRNG;439440/**441* Initializes a BcRNG.442* @param r The BcRNG to initialize.443*/444void445bc_rand_init(BcRNG* r);446447#if BC_RAND_USE_FREE448449/**450* Frees a BcRNG. This is only in debug builds because it would only be freed on451* exit.452* @param r The BcRNG to free.453*/454void455bc_rand_free(BcRNG* r);456457#endif // BC_RAND_USE_FREE458459/**460* Returns a random integer from the PRNG.461* @param r The PRNG.462* @return A random integer.463*/464BcRand465bc_rand_int(BcRNG* r);466467/**468* Returns a random integer from the PRNG bounded by @a bound. Bias is469* eliminated.470* @param r The PRNG.471* @param bound The bound for the random integer.472* @return A bounded random integer.473*/474BcRand475bc_rand_bounded(BcRNG* r, BcRand bound);476477/**478* Seed the PRNG with the state in two parts and the increment in two parts.479* @param r The PRNG.480* @param state1 The first part of the state.481* @param state2 The second part of the state.482* @param inc1 The first part of the increment.483* @param inc2 The second part of the increment.484*/485void486bc_rand_seed(BcRNG* r, ulong state1, ulong state2, ulong inc1, ulong inc2);487488/**489* Pushes a new PRNG onto the PRNG stack.490* @param r The PRNG.491*/492void493bc_rand_push(BcRNG* r);494495/**496* Pops one or all but one items off of the PRNG stack.497* @param r The PRNG.498* @param reset True if all but one PRNG should be popped off the stack, false499* if only one should be popped.500*/501void502bc_rand_pop(BcRNG* r, bool reset);503504/**505* Returns, via pointers, the state of the PRNG in pieces.506* @param r The PRNG.507* @param s1 The return value for the first part of the state.508* @param s2 The return value for the second part of the state.509* @param i1 The return value for the first part of the increment.510* @param i2 The return value for the second part of the increment.511*/512void513bc_rand_getRands(BcRNG* r, BcRand* s1, BcRand* s2, BcRand* i1, BcRand* i2);514515/**516* Seed the PRNG with random data.517* @param rng The PRNG.518*/519void520bc_rand_srand(BcRNGData* rng);521522/// A reference to a constant multiplier.523extern const BcRandState bc_rand_multiplier;524525#endif // BC_ENABLE_EXTRA_MATH526527#endif // BC_RAND_H528529530