Skip to content

Commit 7cb3bf9

Browse files
authored
Merge pull request #202 from mmore500/getuint64
Write and test uint64_t generator
2 parents 4002225 + 9914349 commit 7cb3bf9

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

source/tools/Random.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ namespace emp {
202202
+ static_cast<uint32_t>(GetDouble() * 65536.0);
203203
}
204204

205+
/**
206+
* Generate a random 64-bit block of bits.
207+
*
208+
* @return The pseudo random number.
209+
**/
210+
inline uint64_t GetUInt64() {
211+
return ( static_cast<uint64_t>(GetUInt()) << 32)
212+
+ static_cast<uint64_t>(GetUInt());
213+
}
214+
205215
/**
206216
* Generate an uint64_t.
207217
*
@@ -371,10 +381,10 @@ namespace emp {
371381

372382
/**
373383
* By default GetRandBinomial calls the full (non-approximation) version.
374-
*
384+
*
375385
* Note that if approximations are okay, they can create a big speedup
376386
* for n > 1000.
377-
*
387+
*
378388
* @see Random::GetFullRandBinomial
379389
* @see Random::GetApproxRandBinomial
380390
* @see emp::Binomial in source/tools/Binomial.h

tests/test_tools.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <string>
1616
#include <deque>
1717
#include <algorithm>
18+
#include <limits>
19+
#include <numeric>
1820
#include <climits>
1921
#include <unordered_set>
2022

@@ -1160,6 +1162,57 @@ TEST_CASE("Test random", "[tools]")
11601162
REQUIRE(mean_value < max_threshold);
11611163
}
11621164

1165+
// Test GetUInt()
1166+
emp::vector<uint32_t> uint32_draws;
1167+
total = 0.0;
1168+
for (size_t i = 0; i < num_tests; i++) {
1169+
const uint32_t cur_value = rng.GetUInt();
1170+
total += cur_value;
1171+
uint32_draws.push_back(cur_value);
1172+
}
1173+
1174+
{
1175+
const double expected_mean = ((double)std::numeric_limits<uint32_t>::max())/2.0;
1176+
const double min_threshold = (expected_mean*0.995);
1177+
const double max_threshold = (expected_mean*1.005);
1178+
double mean_value = total/(double) num_tests;
1179+
1180+
REQUIRE(mean_value > min_threshold);
1181+
REQUIRE(mean_value < max_threshold);
1182+
// ensure that all bits are set at least once and unset at least once
1183+
REQUIRE(std::numeric_limits<uint32_t>::max() == std::accumulate(uint32_draws.begin(),uint32_draws.end(),(uint32_t)0,
1184+
[](uint32_t accumulator, uint32_t val){ return accumulator | val; })
1185+
);
1186+
REQUIRE(std::numeric_limits<uint32_t>::max() == std::accumulate(uint32_draws.begin(),uint32_draws.end(),(uint32_t)0,
1187+
[](uint32_t accumulator, uint32_t val){ return accumulator | (~val); })
1188+
);
1189+
}
1190+
// Test GetUInt64
1191+
emp::vector<uint64_t> uint64_draws;
1192+
total = 0.0;
1193+
for (size_t i = 0; i < num_tests; i++) {
1194+
const uint64_t cur_value = rng.GetUInt64();
1195+
total += cur_value/(double)num_tests;
1196+
uint64_draws.push_back(cur_value);
1197+
}
1198+
1199+
{
1200+
const double expected_mean = ((double)std::numeric_limits<uint64_t>::max())/2.0;
1201+
const double min_threshold = (expected_mean*0.995);
1202+
const double max_threshold = (expected_mean*1.005);
1203+
double mean_value = total; // values were divided by num_tests when added
1204+
1205+
REQUIRE(mean_value > min_threshold);
1206+
REQUIRE(mean_value < max_threshold);
1207+
// ensure that all bits are set at least once and unset at least once
1208+
REQUIRE(std::numeric_limits<uint64_t>::max() == std::accumulate(uint64_draws.begin(),uint64_draws.end(),(uint64_t)0,
1209+
[](uint64_t accumulator, uint64_t val){ return accumulator | val; })
1210+
);
1211+
REQUIRE(std::numeric_limits<uint64_t>::max() == std::accumulate(uint64_draws.begin(),uint64_draws.end(),(uint64_t)0,
1212+
[](uint64_t accumulator, uint64_t val){ return accumulator | (~val); })
1213+
);
1214+
}
1215+
11631216
// Test P
11641217
double flip_prob = 0.56789;
11651218
int hit_count = 0;

0 commit comments

Comments
 (0)