### Faster secp256k1_rand_int implementation

master Pieter Wuille 7 years ago
parent
commit
f684d7d987
1 changed files with 28 additions and 7 deletions
1. 35
src/testrand_impl.h

#### 35 src/testrand_impl.h Unescape Escape View File

 `@ -45,19 +45,40 @@ static uint32_t secp256k1_rand_bits(int bits) {` @@ -45,19 +45,40 @@ static uint32_t secp256k1_rand_bits(int bits) { `}` ``` ``` `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;` ` uint32_t ret = range - 1;` ` if (range <= 1) {` ` return 0;` ` }` ` while (ret > 0) {` ` ret >>= 1;` ` trange = range - 1;` ` while (trange > 0) {` ` trange >>= 1;` ` bits++;` ` }` ` while (1) {` ` ret = secp256k1_rand_bits(bits);` ` if (ret < range) {` ` return ret;` ` if (addbits[bits]) {` ` bits = bits + addbits[bits];` ` mult = ((~((uint32_t)0)) >> (32 - bits)) / range;` ` 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);` ` }` ` }` `}`