Skip to content

Commit 6ec3731

Browse files
committed
Simplify test PRNG implementation
1 parent fb5bfa4 commit 6ec3731

File tree

1 file changed

+17
-48
lines changed

1 file changed

+17
-48
lines changed

src/testrand_impl.h

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include "util.h"
1717

1818
static uint64_t secp256k1_test_state[4];
19-
static uint64_t secp256k1_test_rng_integer;
20-
static int secp256k1_test_rng_integer_bits_left = 0;
2119

2220
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
2321
static const unsigned char PREFIX[19] = "secp256k1 test init";
@@ -36,7 +34,6 @@ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16
3634
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
3735
secp256k1_test_state[i] = s;
3836
}
39-
secp256k1_test_rng_integer_bits_left = 0;
4037
}
4138

4239
SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
@@ -57,58 +54,30 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
5754
}
5855

5956
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
60-
uint64_t ret;
61-
if (secp256k1_test_rng_integer_bits_left < bits) {
62-
secp256k1_test_rng_integer = secp256k1_testrand64();
63-
secp256k1_test_rng_integer_bits_left = 64;
64-
}
65-
ret = secp256k1_test_rng_integer;
66-
secp256k1_test_rng_integer >>= bits;
67-
secp256k1_test_rng_integer_bits_left -= bits;
68-
ret &= ((~((uint64_t)0)) >> (64 - bits));
69-
return ret;
57+
if (bits == 0) return 0;
58+
return secp256k1_testrand64() >> (64 - bits);
7059
}
7160

7261
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
73-
return secp256k1_testrand_bits(32);
62+
return secp256k1_testrand64() >> 32;
7463
}
7564

7665
static uint32_t secp256k1_testrand_int(uint32_t range) {
77-
/* We want a uniform integer between 0 and range-1, inclusive.
78-
* B is the smallest number such that range <= 2**B.
79-
* two mechanisms implemented here:
80-
* - generate B bits numbers until one below range is found, and return it
81-
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
82-
* bits numbers until one below M is found, and return it modulo range
83-
* The second mechanism consumes A more bits of entropy in every iteration,
84-
* but may need fewer iterations due to M being closer to 2**(B+A) then
85-
* range is to 2**B. The array below (indexed by B) contains a 0 when the
86-
* first mechanism is to be used, and the number A otherwise.
87-
*/
88-
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};
89-
uint32_t trange, mult;
90-
int bits = 0;
91-
if (range <= 1) {
92-
return 0;
93-
}
94-
trange = range - 1;
95-
while (trange > 0) {
96-
trange >>= 1;
97-
bits++;
66+
uint32_t mask = 0;
67+
uint32_t range_copy;
68+
/* Reduce range by 1, changing its meaning to "maximum value". */
69+
VERIFY_CHECK(range != 0);
70+
range -= 1;
71+
/* Count the number of bits in range. */
72+
range_copy = range;
73+
while (range_copy) {
74+
mask = (mask << 1) | 1U;
75+
range_copy >>= 1;
9876
}
99-
if (addbits[bits]) {
100-
bits = bits + addbits[bits];
101-
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
102-
trange = range * mult;
103-
} else {
104-
trange = range;
105-
mult = 1;
106-
}
107-
while(1) {
108-
uint32_t x = secp256k1_testrand_bits(bits);
109-
if (x < trange) {
110-
return (mult == 1) ? x : (x % range);
111-
}
77+
/* Generation loop. */
78+
while (1) {
79+
uint32_t val = secp256k1_testrand64() & mask;
80+
if (val <= range) return val;
11281
}
11382
}
11483

0 commit comments

Comments
 (0)