diff options
Diffstat (limited to 'contrib/bc/src/rand.c')
-rw-r--r-- | contrib/bc/src/rand.c | 201 |
1 files changed, 128 insertions, 73 deletions
diff --git a/contrib/bc/src/rand.c b/contrib/bc/src/rand.c index a3b8942a6042..560e494214ad 100644 --- a/contrib/bc/src/rand.c +++ b/contrib/bc/src/rand.c @@ -13,7 +13,7 @@ * This code is under the following license: * * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2023 Gavin D. Howard and contributors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,8 +66,9 @@ * @param b The second operand. * @return The sum, including overflow. */ -static BcRandState bc_rand_addition(uint_fast64_t a, uint_fast64_t b) { - +static BcRandState +bc_rand_addition(uint_fast64_t a, uint_fast64_t b) +{ BcRandState res; res.lo = a + b; @@ -82,8 +83,9 @@ static BcRandState bc_rand_addition(uint_fast64_t a, uint_fast64_t b) { * @param b The second operand. * @return The sum, without overflow. */ -static BcRandState bc_rand_addition2(BcRandState a, BcRandState b) { - +static BcRandState +bc_rand_addition2(BcRandState a, BcRandState b) +{ BcRandState temp, res; res = bc_rand_addition(a.lo, b.lo); @@ -99,8 +101,9 @@ static BcRandState bc_rand_addition2(BcRandState a, BcRandState b) { * @param b The second operand. * @return The product, including overflow. */ -static BcRandState bc_rand_multiply(uint_fast64_t a, uint_fast64_t b) { - +static BcRandState +bc_rand_multiply(uint_fast64_t a, uint_fast64_t b) +{ uint_fast64_t al, ah, bl, bh, c0, c1, c2, c3; BcRandState carry, res; @@ -128,8 +131,9 @@ static BcRandState bc_rand_multiply(uint_fast64_t a, uint_fast64_t b) { * @param b The second operand. * @return The product, without overflow. */ -static BcRandState bc_rand_multiply2(BcRandState a, BcRandState b) { - +static BcRandState +bc_rand_multiply2(BcRandState a, BcRandState b) +{ BcRandState c0, c1, c2, carry; c0 = bc_rand_multiply(a.lo, b.lo); @@ -150,8 +154,9 @@ static BcRandState bc_rand_multiply2(BcRandState a, BcRandState b) { * stack of PRNG's. * @param r The PRNG to mark as modified. */ -static void bc_rand_setModified(BcRNGData *r) { - +static void +bc_rand_setModified(BcRNGData* r) +{ #if BC_RAND_BUILTIN r->inc |= (BcRandState) 1UL; #else // BC_RAND_BUILTIN @@ -164,8 +169,9 @@ static void bc_rand_setModified(BcRNGData *r) { * stack of PRNG's. * @param r The PRNG to mark as not modified. */ -static void bc_rand_clearModified(BcRNGData *r) { - +static void +bc_rand_clearModified(BcRNGData* r) +{ #if BC_RAND_BUILTIN r->inc &= ~((BcRandState) 1UL); #else // BC_RAND_BUILTIN @@ -179,9 +185,14 @@ static void bc_rand_clearModified(BcRNGData *r) { * @param d The destination PRNG. * @param s The source PRNG. */ -static void bc_rand_copy(BcRNGData *d, BcRNGData *s) { +static void +bc_rand_copy(BcRNGData* d, BcRNGData* s) +{ bool unmod = BC_RAND_NOTMODIFIED(d); + + // NOLINTNEXTLINE memcpy(d, s, sizeof(BcRNGData)); + if (!unmod) bc_rand_setModified(d); else if (!BC_RAND_NOTMODIFIED(s)) bc_rand_clearModified(d); } @@ -193,21 +204,22 @@ static void bc_rand_copy(BcRNGData *d, BcRNGData *s) { * @param ptr A pointer to the file, as a void pointer. * @return The random data as an unsigned long. */ -static ulong bc_rand_frand(void* ptr) { - +static ulong +bc_rand_frand(void* ptr) +{ ulong buf[1]; int fd; ssize_t nread; assert(ptr != NULL); - fd = *((int*)ptr); + fd = *((int*) ptr); nread = read(fd, buf, sizeof(ulong)); if (BC_ERR(nread != sizeof(ulong))) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR); - return *((ulong*)buf); + return *((ulong*) buf); } #else // _WIN32 @@ -216,8 +228,9 @@ static ulong bc_rand_frand(void* ptr) { * @param ptr An unused parameter. * @return The random data as an unsigned long. */ -static ulong bc_rand_winrand(void *ptr) { - +static ulong +bc_rand_winrand(void* ptr) +{ ulong buf[1]; NTSTATUS s; @@ -242,8 +255,9 @@ static ulong bc_rand_winrand(void *ptr) { * @param ptr An unused parameter. * @return The random data as an unsigned long. */ -static ulong bc_rand_rand(void *ptr) { - +static ulong +bc_rand_rand(void* ptr) +{ size_t i; ulong res = 0; @@ -251,7 +265,9 @@ static ulong bc_rand_rand(void *ptr) { // Fill up the unsigned long byte-by-byte. for (i = 0; i < sizeof(ulong); ++i) + { res |= ((ulong) (rand() & BC_RAND_SRAND_BITS)) << (i * CHAR_BIT); + } return res; } @@ -262,8 +278,9 @@ static ulong bc_rand_rand(void *ptr) { * @param r The PRNG. * @return The increment of the PRNG, including the last odd bit. */ -static BcRandState bc_rand_inc(BcRNGData *r) { - +static BcRandState +bc_rand_inc(BcRNGData* r) +{ BcRandState inc; #if BC_RAND_BUILTIN @@ -280,8 +297,9 @@ static BcRandState bc_rand_inc(BcRNGData *r) { * Sets up the increment for the PRNG. * @param r The PRNG whose increment will be set up. */ -static void bc_rand_setupInc(BcRNGData *r) { - +static void +bc_rand_setupInc(BcRNGData* r) +{ #if BC_RAND_BUILTIN r->inc <<= 1UL; #else // BC_RAND_BUILTIN @@ -297,8 +315,9 @@ static void bc_rand_setupInc(BcRNGData *r) { * @param val1 The lower half of the state. * @param val2 The upper half of the state. */ -static void bc_rand_seedState(BcRandState *state, ulong val1, ulong val2) { - +static void +bc_rand_seedState(BcRandState* state, ulong val1, ulong val2) +{ #if BC_RAND_BUILTIN *state = ((BcRandState) val1) | ((BcRandState) val2) << (BC_LONG_BIT); #else // BC_RAND_BUILTIN @@ -315,8 +334,9 @@ static void bc_rand_seedState(BcRandState *state, ulong val1, ulong val2) { * @param inc1 The lower half of the increment. * @param inc2 The upper half of the increment. */ -static void bc_rand_seedRNG(BcRNGData *r, ulong state1, ulong state2, - ulong inc1, ulong inc2) +static void +bc_rand_seedRNG(BcRNGData* r, ulong state1, ulong state2, ulong inc1, + ulong inc2) { bc_rand_seedState(&r->state, state1, state2); bc_rand_seedState(&r->inc, inc1, inc2); @@ -329,8 +349,9 @@ static void bc_rand_seedRNG(BcRNGData *r, ulong state1, ulong state2, * @param fulong The function to fill an unsigned long. * @param ptr The parameter to pass to @a fulong. */ -static void bc_rand_fill(BcRNGData *r, BcRandUlong fulong, void *ptr) { - +static void +bc_rand_fill(BcRNGData* r, BcRandUlong fulong, void* ptr) +{ ulong state1, state2, inc1, inc2; state1 = fulong(ptr); @@ -346,7 +367,9 @@ static void bc_rand_fill(BcRNGData *r, BcRandUlong fulong, void *ptr) { * Executes the "step" portion of a PCG udpate. * @param r The PRNG. */ -static void bc_rand_step(BcRNGData *r) { +static void +bc_rand_step(BcRNGData* r) +{ BcRandState temp = bc_rand_mul2(r->state, bc_rand_multiplier); r->state = bc_rand_add2(temp, bc_rand_inc(r)); } @@ -356,7 +379,9 @@ static void bc_rand_step(BcRNGData *r) { * @param r The PRNG. * @return The new output from the PRNG. */ -static BcRand bc_rand_output(BcRNGData *r) { +static BcRand +bc_rand_output(BcRNGData* r) +{ return BC_RAND_ROT(BC_RAND_FOLD(r->state), BC_RAND_ROTAMT(r->state)); } @@ -366,9 +391,10 @@ static BcRand bc_rand_output(BcRNGData *r) { * @param r The PRNG stack. * @param rng The PRNG on the top of the stack. Must have been seeded. */ -static void bc_rand_seedZeroes(BcRNG *r, BcRNGData *rng, size_t idx) { - - BcRNGData *rng2; +static void +bc_rand_seedZeroes(BcRNG* r, BcRNGData* rng, size_t idx) +{ + BcRNGData* rng2; // Just return if there are none to do. if (r->v.len <= idx) return; @@ -377,18 +403,21 @@ static void bc_rand_seedZeroes(BcRNG *r, BcRNGData *rng, size_t idx) { rng2 = bc_vec_item_rev(&r->v, idx); // Does it need seeding? Then it, and maybe more, do. - if (BC_RAND_ZERO(rng2)) { - + if (BC_RAND_ZERO(rng2)) + { size_t i; // Seed the ones that need seeding. for (i = 1; i < r->v.len; ++i) + { bc_rand_copy(bc_vec_item_rev(&r->v, i), rng); + } } } -void bc_rand_srand(BcRNGData *rng) { - +void +bc_rand_srand(BcRNGData* rng) +{ int fd = 0; BC_SIG_LOCK; @@ -398,16 +427,18 @@ void bc_rand_srand(BcRNGData *rng) { // Try /dev/urandom first. fd = open("/dev/urandom", O_RDONLY); - if (BC_NO_ERR(fd >= 0)) { + if (BC_NO_ERR(fd >= 0)) + { bc_rand_fill(rng, bc_rand_frand, &fd); close(fd); } - else { - + else + { // Try /dev/random second. fd = open("/dev/random", O_RDONLY); - if (BC_NO_ERR(fd >= 0)) { + if (BC_NO_ERR(fd >= 0)) + { bc_rand_fill(rng, bc_rand_frand, &fd); close(fd); } @@ -418,7 +449,10 @@ void bc_rand_srand(BcRNGData *rng) { #endif // _WIN32 // Fallback to rand() until the thing is seeded. - while (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_fill(rng, bc_rand_rand, NULL); + while (BC_ERR(BC_RAND_ZERO(rng))) + { + bc_rand_fill(rng, bc_rand_rand, NULL); + } BC_SIG_UNLOCK; } @@ -429,21 +463,22 @@ void bc_rand_srand(BcRNGData *rng) { * @param r The PRNG stack. * @param rng The PRNG that will be used to seed the others. */ -static void bc_rand_propagate(BcRNG *r, BcRNGData *rng) { - +static void +bc_rand_propagate(BcRNG* r, BcRNGData* rng) +{ // Just return if there are none to do. if (r->v.len <= 1) return; // If the PRNG has not been modified... - if (BC_RAND_NOTMODIFIED(rng)) { - + if (BC_RAND_NOTMODIFIED(rng)) + { size_t i; bool go = true; // Find the first PRNG that is modified and seed the others. - for (i = 1; go && i < r->v.len; ++i) { - - BcRNGData *rng2 = bc_vec_item_rev(&r->v, i); + for (i = 1; go && i < r->v.len; ++i) + { + BcRNGData* rng2 = bc_vec_item_rev(&r->v, i); go = BC_RAND_NOTMODIFIED(rng2); @@ -457,10 +492,11 @@ static void bc_rand_propagate(BcRNG *r, BcRNGData *rng) { else bc_rand_seedZeroes(r, rng, 1); } -BcRand bc_rand_int(BcRNG *r) { - +BcRand +bc_rand_int(BcRNG* r) +{ // Get the actual PRNG. - BcRNGData *rng = bc_vec_top(&r->v); + BcRNGData* rng = bc_vec_top(&r->v); BcRand res; // Make sure the PRNG is seeded. @@ -478,22 +514,29 @@ BcRand bc_rand_int(BcRNG *r) { return res; } -BcRand bc_rand_bounded(BcRNG *r, BcRand bound) { +BcRand +bc_rand_bounded(BcRNG* r, BcRand bound) +{ + BcRand rand; + BcRand threshold; // Calculate the threshold below which we have to try again. - BcRand rand, threshold = (0 - bound) % bound; + threshold = (0 - bound) % bound; - do { + do + { rand = bc_rand_int(r); - } while (rand < threshold); + } + while (rand < threshold); return rand % bound; } -void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2) +void +bc_rand_seed(BcRNG* r, ulong state1, ulong state2, ulong inc1, ulong inc2) { // Get the actual PRNG. - BcRNGData *rng = bc_vec_top(&r->v); + BcRNGData* rng = bc_vec_top(&r->v); // Seed and set up the PRNG's increment. bc_rand_seedState(&rng->inc, inc1, inc2); @@ -502,7 +545,9 @@ void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2) // If the state is 0, use the increment as the state. Otherwise, seed it // with the state. - if (!state1 && !state2) { + if (!state1 && !state2) + { + // NOLINTNEXTLINE memcpy(&rng->state, &rng->inc, sizeof(BcRandState)); bc_rand_step(rng); } @@ -519,8 +564,9 @@ void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2) * @return The increment without the odd bit and with being shifted one bit * down. */ -static BcRandState bc_rand_getInc(BcRNGData *r) { - +static BcRandState +bc_rand_getInc(BcRNGData* r) +{ BcRandState res; #if BC_RAND_BUILTIN @@ -535,10 +581,11 @@ static BcRandState bc_rand_getInc(BcRNGData *r) { return res; } -void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2) +void +bc_rand_getRands(BcRNG* r, BcRand* s1, BcRand* s2, BcRand* i1, BcRand* i2) { BcRandState inc; - BcRNGData *rng = bc_vec_top(&r->v); + BcRNGData* rng = bc_vec_top(&r->v); if (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_srand(rng); @@ -554,30 +601,38 @@ void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2) *i2 = BC_RAND_CHOP(inc); } -void bc_rand_push(BcRNG *r) { - - BcRNGData *rng = bc_vec_pushEmpty(&r->v); +void +bc_rand_push(BcRNG* r) +{ + BcRNGData* rng = bc_vec_pushEmpty(&r->v); // Make sure the PRNG is properly zeroed because that marks it as needing to // be seeded. + // NOLINTNEXTLINE memset(rng, 0, sizeof(BcRNGData)); // If there is another item, copy it too. if (r->v.len > 1) bc_rand_copy(rng, bc_vec_item_rev(&r->v, 1)); } -void bc_rand_pop(BcRNG *r, bool reset) { +void +bc_rand_pop(BcRNG* r, bool reset) +{ bc_vec_npop(&r->v, reset ? r->v.len - 1 : 1); } -void bc_rand_init(BcRNG *r) { +void +bc_rand_init(BcRNG* r) +{ BC_SIG_ASSERT_LOCKED; bc_vec_init(&r->v, sizeof(BcRNGData), BC_DTOR_NONE); bc_rand_push(r); } #if BC_RAND_USE_FREE -void bc_rand_free(BcRNG *r) { +void +bc_rand_free(BcRNG* r) +{ BC_SIG_ASSERT_LOCKED; bc_vec_free(&r->v); } |