libcruft-util/test/rand/buckets.cpp

72 lines
2.3 KiB
C++

#include "rand/xorshift.hpp"
#include "rand/lcg.hpp"
#include "rand/mwc64x.hpp"
#include "rand/pcg.hpp"
#include "tap.hpp"
#include "maths.hpp"
#include "types/string.hpp"
///////////////////////////////////////////////////////////////////////////////
template <>
std::string
type_to_string<cruft::rand::xorshift<uint32_t>> (void) { return "xorshift<uint32_t>"; }
template <>
std::string
type_to_string<cruft::rand::xorshift<uint64_t>> (void) { return "xorshift<uint64_t>"; }
template <> std::string type_to_string<cruft::rand::lcg_t> (void) { return "lcg_t"; }
template <> std::string type_to_string<cruft::rand::mwc64x> (void) { return "mwc64x"; }
template <> std::string type_to_string<cruft::rand::pcg_xsh_rr<u64,u32>> (void) { return "pcg_xsh_rr<64,32>"; }
///////////////////////////////////////////////////////////////////////////////
/// check random outputs are roughly divisible between a number of fixed width
/// buckets.
///
/// this is not anything close to a strict statistical test. it is more aimed
/// at link testing and basic functionality verification within a small
/// resource footprint (ie, fast unit testing).
template <typename G, typename ...Args>
void
test_buckets (cruft::TAP::logger &tap, Args&& ...args)
{
constexpr unsigned BUCKET_BITS = 8u;
constexpr size_t BUCKET_COUNT = 1u << BUCKET_BITS;
constexpr unsigned EXPECTED = 1024u;
constexpr unsigned ITERATIONS = BUCKET_COUNT * EXPECTED;
G gen (std::forward<Args> (args)...);
std::uniform_int_distribution<int> dist (0, BUCKET_COUNT - 1);
unsigned buckets[BUCKET_COUNT] = {};
for (unsigned i = 0; i < ITERATIONS; ++i)
++buckets[dist (gen)];
tap.expect (
std::find_if (std::cbegin (buckets),
std::cend (buckets),
[] (auto v) { return v < EXPECTED * 7 / 8; }) == std::cend (buckets),
"bucket counts for %s", type_to_string<G> ());
}
///////////////////////////////////////////////////////////////////////////////
int
main (int,char**)
{
cruft::TAP::logger tap;
test_buckets<cruft::rand::xorshift<uint32_t>> (tap, 0x1234u);
test_buckets<cruft::rand::xorshift<uint64_t>> (tap, 0x1234u);
test_buckets<cruft::rand::lcg_t> (tap, 0x1234u);
test_buckets<cruft::rand::mwc64x> (tap, 0x1234u);
test_buckets<cruft::rand::pcg_xsh_rr<>> (tap, 0x1234u);
return tap.status ();
}