rng/randomness_tests/runs_ones.cpp
2025-07-06 17:13:58 +01:00

78 lines
2.4 KiB
C++

#include "../rng.h"
#include "./rngtest.h"
#include "../math/incomplete_gamma.cpp"
#define vecdebug(list) for(auto vecdebugitem : list){ std::cout << vecdebugitem <<","; }std::cout << "\n";
namespace splat {
class runs_ones_test : public RNGTEST {
public:
runs_ones_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
testPValue = runTest(data);
testPassed = testPValue > 0.01;
}
std::string getName() override {
return "Runs of 1s";
}
double runTest(std::vector<std::bitset<32>> &data) override {
long long totalSize = data.size() * 32;
if(totalSize < 750000){
std::cout << "Error, runs of ones test requires more than 750K bits of input\n";
return 0;
}
// we do it with M=10^4 here
std::vector<double> counts(7,0);
double chunks = totalSize / 10000;
for(int chunkIndex=0; chunkIndex<chunks; chunkIndex++){
int longestRun = 0;
int ones = 0;
for(int i=0; i<10000; i++){
long long index = chunkIndex*10000 + i;
int dataIndex = (index / 32);
int bitIndex = (index % 32);
if(data[dataIndex][bitIndex]){
ones++;
}else{
if(ones>longestRun) longestRun = ones;
ones = 0;
}
}
if(longestRun <=10){
counts[0]++;
}else if(longestRun>=16){
counts[6]++;
}else{
counts[longestRun-10]++;
}
}
double x2 = 0;
std::vector<double> probabilities = {
0.0882,
0.2092,
0.2483,
0.1933,
0.1208,
0.0675,
0.0727
};
for(int i=0; i<7; i++){
x2 += std::pow((counts[i] - (chunks * probabilities[i])),2.0) /(chunks * probabilities[i]);
}
return igamc(3, x2/2.0);
}
};
}