mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-07-05 05:02:06 +02:00
Faster secp256k1_rand_int implementation
This commit is contained in:
@ -45,19 +45,40 @@ static uint32_t secp256k1_rand_bits(int bits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t secp256k1_rand_int(uint32_t range) {
|
static uint32_t secp256k1_rand_int(uint32_t range) {
|
||||||
|
/* We want a uniform integer between 0 and range-1, inclusive.
|
||||||
|
* B is the smallest number such that range <= 2**B.
|
||||||
|
* two mechanisms implemented here:
|
||||||
|
* - generate B bits numbers until one below range is found, and return it
|
||||||
|
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
|
||||||
|
* bits numbers until one below M is found, and return it modulo range
|
||||||
|
* The second mechanism consumes A more bits of entropy in every iteration,
|
||||||
|
* but may need fewer iterations due to M being closer to 2**(B+A) then
|
||||||
|
* range is to 2**B. The array below (indexed by B) contains a 0 when the
|
||||||
|
* first mechanism is to be used, and the number A otherwise.
|
||||||
|
*/
|
||||||
|
static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
|
||||||
|
uint32_t trange, mult;
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
uint32_t ret = range - 1;
|
|
||||||
if (range <= 1) {
|
if (range <= 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (ret > 0) {
|
trange = range - 1;
|
||||||
ret >>= 1;
|
while (trange > 0) {
|
||||||
|
trange >>= 1;
|
||||||
bits++;
|
bits++;
|
||||||
}
|
}
|
||||||
while (1) {
|
if (addbits[bits]) {
|
||||||
ret = secp256k1_rand_bits(bits);
|
bits = bits + addbits[bits];
|
||||||
if (ret < range) {
|
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
|
||||||
return ret;
|
trange = range * mult;
|
||||||
|
} else {
|
||||||
|
trange = range;
|
||||||
|
mult = 1;
|
||||||
|
}
|
||||||
|
while(1) {
|
||||||
|
uint32_t x = secp256k1_rand_bits(bits);
|
||||||
|
if (x < trange) {
|
||||||
|
return (mult == 1) ? x : (x % range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user