@@ -39,9 +39,9 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
39
39
BOOST_CHECK_EQUAL (7 , ctx.rand_uniform_delay (time_point, 9s).time_since_epoch ().count ());
40
40
BOOST_CHECK_EQUAL (-6 , ctx.rand_uniform_delay (time_point, -9s).time_since_epoch ().count ());
41
41
BOOST_CHECK_EQUAL (1 , ctx.rand_uniform_delay (time_point, 0s).time_since_epoch ().count ());
42
- BOOST_CHECK_EQUAL (1467825113502396065 , ctx.rand_uniform_delay (time_point, 9223372036854775807s).time_since_epoch ().count ());
43
- BOOST_CHECK_EQUAL (-970181367944767837 , ctx.rand_uniform_delay (time_point, -9223372036854775807s).time_since_epoch ().count ());
44
- BOOST_CHECK_EQUAL (24761 , ctx.rand_uniform_delay (time_point, 9h).time_since_epoch ().count ());
42
+ BOOST_CHECK_EQUAL (4652286523065884857 , ctx.rand_uniform_delay (time_point, 9223372036854775807s).time_since_epoch ().count ());
43
+ BOOST_CHECK_EQUAL (-8813961240025683129 , ctx.rand_uniform_delay (time_point, -9223372036854775807s).time_since_epoch ().count ());
44
+ BOOST_CHECK_EQUAL (26443 , ctx.rand_uniform_delay (time_point, 9h).time_since_epoch ().count ());
45
45
}
46
46
BOOST_CHECK_EQUAL (ctx1.rand32 (), ctx2.rand32 ());
47
47
BOOST_CHECK_EQUAL (ctx1.rand32 (), ctx2.rand32 ());
@@ -103,6 +103,52 @@ BOOST_AUTO_TEST_CASE(fastrandom_randbits)
103
103
}
104
104
}
105
105
106
+ /* * Verify that RandomMixin::randbits returns 0 and 1 for every requested bit. */
107
+ BOOST_AUTO_TEST_CASE (randbits_test)
108
+ {
109
+ FastRandomContext ctx_lens; // !< RNG for producing the lengths requested from ctx_test.
110
+ FastRandomContext ctx_test; // !< The RNG being tested.
111
+ int ctx_test_bitsleft{0 }; // !< (Assumed value of) ctx_test::bitbuf_len
112
+
113
+ // Run the entire test 5 times.
114
+ for (int i = 0 ; i < 5 ; ++i) {
115
+ // count (first) how often it has occurred, and (second) how often it was true:
116
+ // - for every bit position, in every requested bits count (0 + 1 + 2 + ... + 64 = 2080)
117
+ // - for every value of ctx_test_bitsleft (0..63 = 64)
118
+ std::vector<std::pair<uint64_t , uint64_t >> seen (2080 * 64 );
119
+ while (true ) {
120
+ // Loop 1000 times, just to not continuously check std::all_of.
121
+ for (int j = 0 ; j < 1000 ; ++j) {
122
+ // Decide on a number of bits to request (0 through 64, inclusive; don't use randbits/randrange).
123
+ int bits = ctx_lens.rand64 () % 65 ;
124
+ // Generate that many bits.
125
+ uint64_t gen = ctx_test.randbits (bits);
126
+ // Make sure the result is in range.
127
+ if (bits < 64 ) BOOST_CHECK_EQUAL (gen >> bits, 0 );
128
+ // Mark all the seen bits in the output.
129
+ for (int bit = 0 ; bit < bits; ++bit) {
130
+ int idx = bit + (bits * (bits - 1 )) / 2 + 2080 * ctx_test_bitsleft;
131
+ seen[idx].first += 1 ;
132
+ seen[idx].second += (gen >> bit) & 1 ;
133
+ }
134
+ // Update ctx_test_bitself.
135
+ if (bits > ctx_test_bitsleft) {
136
+ ctx_test_bitsleft = ctx_test_bitsleft + 64 - bits;
137
+ } else {
138
+ ctx_test_bitsleft -= bits;
139
+ }
140
+ }
141
+ // Loop until every bit position/combination is seen 242 times.
142
+ if (std::all_of (seen.begin (), seen.end (), [](const auto & x) { return x.first >= 242 ; })) break ;
143
+ }
144
+ // Check that each bit appears within 7.78 standard deviations of 50%
145
+ // (each will fail with P < 1/(2080 * 64 * 10^9)).
146
+ for (const auto & val : seen) {
147
+ assert (fabs (val.first * 0.5 - val.second ) < sqrt (val.first * 0.25 ) * 7.78 );
148
+ }
149
+ }
150
+ }
151
+
106
152
/* * Does-it-compile test for compatibility with standard library RNG interface. */
107
153
BOOST_AUTO_TEST_CASE (stdrandom_test)
108
154
{
0 commit comments