Skip to content

Instantly share code, notes, and snippets.

@imneme
Last active June 24, 2019 01:06
Show Gist options
  • Save imneme/13c96540bbc656f432b59f6ae4264d41 to your computer and use it in GitHub Desktop.
Save imneme/13c96540bbc656f432b59f6ae4264d41 to your computer and use it in GitHub Desktop.
Seeding Bias Test
/*
* Seeding Bias Test
*
* - Runs through all possible seeds and examines the output for
* bias. Doing so is only practical for 32-bit (or less) seeds
* and 32-bit (or less) output.
*
* Compilation note:
*
* - You need to define the following preprocessor symbols to compile this
* code:
*
* INCLUDE_FILE (e.g., <random>, "pcg_random.hpp", etc.)
* RNG_TYPE (e.g., std:mt19937, pcg32_once_insecure, etc.)
* SEED_TYPE (e.g., uint32_t, should be the type of the argument
* to the RNG_TYPE constructor).
*
* Note: You can't test pcg32 with this code, since it has a 64-bit seed
* argument.
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Melissa E. O'Neill
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <vector>
#include <iostream>
#include <random>
#include <type_traits>
#include <cstdint>
#ifndef SEED_TYPE
#define SEED_TYPE RNG_TYPE::result_type
#endif
#ifdef INCLUDE_FILE
#include INCLUDE_FILE
#endif
#define STRINGIFY_HELPER(...) #__VA_ARGS__
#define STRINGIFY(...) STRINGIFY_HELPER(__VA_ARGS__)
int main(int argc, char* argv[]) {
constexpr size_t SEEDS = size_t(~(SEED_TYPE(0))) + 1;
constexpr size_t OUTPUTS = size_t(RNG_TYPE::max()) + 1;
size_t DEPTH = argc > 1 ? atoi(argv[1]) : 1;
std::cout << "Bias test of " STRINGIFY(RNG_TYPE) ":\n"
<< "- Will enumerate through all " << SEEDS
<< " seeds, reading " << DEPTH
<< " outputs from each one.\n";
using count_type = std::conditional_t<OUTPUTS >= SEEDS, uint8_t, uint32_t>;
std::vector<count_type> counts(OUTPUTS);
std::cout << "- Enumerating: " << std::flush;
for (size_t seed=0; seed < SEEDS; ++seed) {
RNG_TYPE rng(seed);
for (size_t i = 0; i < DEPTH; ++i) {
auto r = rng();
++counts[r];
}
if ((seed & (SEEDS/64-1)) == (SEEDS/64-1))
std::cout << "." << std::flush;
}
size_t shown = 0;
std::cout << "\n\nNever occurring: ";
for (size_t i = 0; i < OUTPUTS; ++i) {
if (counts[i] == 0) {
std::cout << i << ", ";
if (++shown >= 20) {
std::cout << "...";
break;
}
}
}
if (shown == 0)
std::cout << "(none)";
std::cout << "\nMost overrepresented: ";
size_t highrep_count = 0;
size_t highrep_n = 0;
for (size_t i = 0; i < OUTPUTS; ++i) {
if (counts[i] > highrep_count) {
highrep_n = i;
highrep_count = counts[i];
}
}
if (highrep_n == 0 && highrep_count == DEPTH*SEEDS/OUTPUTS)
std::cout << "(nothing overrepresented)\n";
else
std::cout << highrep_n << " -- repeated "
<< highrep_count << " times\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment