#include "rand/xorshift.hpp" #include "rand/lcg.hpp" #include "rand/mwc64x.hpp" #include "rand/pcg.hpp" #include "rand/rdrand.hpp" #include "rand/system.hpp" #include "rand/xoshiro.hpp" #include "rand/splitmix64.hpp" #include "tap.hpp" #include "maths.hpp" #include "types/string.hpp" #include "introspection/name.hpp" /// ////////////////////////////////////////////////////////////////////////////// /// Check that outputs from a UniformRandomBitGenerator 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 GeneratorT, typename ...Args> static 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; GeneratorT 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}", cruft::introspection::name::full<GeneratorT> () ); } /////////////////////////////////////////////////////////////////////////////// int main (int,char**) { cruft::TAP::logger tap; test_buckets<cruft::rand::splitmix64> (tap, 0x1234u); test_buckets<cruft::rand::xoshiro256plusplus> (tap, 0x1234u); 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); test_buckets<cruft::rand::system> (tap); test_buckets<cruft::rand::rdrand> (tap); return tap.status (); }