diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f740bf..a16efe9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,6 @@ +cmake_minimum_required(VERSION 3.10) +project(qngmeter CXX) + option(QNGMETER "Build qngMeter program" ON) if (QNGMETER) diff --git a/QNGmeter.cpp b/QNGmeter.cpp index 7feae1e..7348698 100755 --- a/QNGmeter.cpp +++ b/QNGmeter.cpp @@ -148,7 +148,10 @@ int main() if (!newBuffer->empty()) { #pragma omp critical - dataQueue.push(newBuffer); + { + dataQueue.push(newBuffer); + bitsThroughputCount += 32.0 * newBuffer->size(); + } } } doExit = true; // Exit if stdin closes or reaches EOF @@ -158,34 +161,8 @@ int main() #pragma omp section { // This section processes the enqueued data - while (!doExit || !dataQueue.empty()) { - shared_ptr> testBuffer = nullptr; - #pragma omp critical - { - if (!dataQueue.empty()) { - testBuffer = dataQueue.front(); - dataQueue.pop(); - } - } - - if (testBuffer != nullptr) { - // Parallel processing of the testBuffer - #pragma omp parallel sections num_threads(4) - { - #pragma omp section - { for (uint32_t value : *testBuffer) biasAndAc.InsertWord32(value); } - #pragma omp section - { for (uint32_t value : *testBuffer) oqso.InsertWord32(value); } - #pragma omp section - { for (uint32_t value : *testBuffer) serial.InsertWord32(value); } - #pragma omp section - { for (uint32_t value : *testBuffer) entropy.InsertWord32(value); } - } - - // Display results - time(&timeNow); - if (difftime(timeNow, timePrev) >= 10) - { + // Computes the meta tests and meter, then prints the results table. + auto report = [&]() { // calc rates #ifdef _WIN32 QueryPerformanceCounter(&nowCount); @@ -293,7 +270,7 @@ int main() cout << " | | 1/0 Balance " << setiosflags(ios::fixed) << setprecision(3) << showpos << biasAndAc.Bias.cumulativeBiasZScore << " " << setprecision(4) << noshowpos << CStat::ZtoP(biasAndAc.Bias.cumulativeBiasZScore) << " " << biasAndAc.Bias.P_Chi2 << " |" << endl; cout << " | | Serial Test " << setiosflags(ios::fixed) << setprecision(3) << showpos << serialZ << " " << setprecision(4) << noshowpos << serialP << " " << serial.P_Chi2 << " |" << endl; cout << " | | OQSO Test " << setiosflags(ios::fixed) << setprecision(3) << showpos << oqso.cumulativeZScore << " " << setprecision(4) << noshowpos << CStat::ZtoP(oqso.cumulativeZScore) << " " << oqso.P_Chi2 << " |" << endl; - cout << " | | Entropy Test " << setiosflags(ios::fixed) << setprecision(3) << showpos << entropy.cumulativeZScore << " " << setprecision(4) << noshowpos << CStat::ZtoP(entropy.cumulativeZScore) << " " << serial.P_Chi2 << " |" << endl; + cout << " | | Entropy Test " << setiosflags(ios::fixed) << setprecision(3) << showpos << entropy.cumulativeZScore << " " << setprecision(4) << noshowpos << CStat::ZtoP(entropy.cumulativeZScore) << " " << entropy.P_Chi2 << " |" << endl; cout << " | | H: " << setiosflags(ios::fixed) << setprecision(9) << entropy.E << " |" << endl; cout << " | | |" << endl; @@ -347,7 +324,8 @@ int main() default: cout << " | |"; } - cout << " " << setw(2) << i << "st AutoCorr " << setiosflags(ios::fixed) << setprecision(3) << showpos << biasAndAc.AC.cumulativeACZScore[i-1] << " " << setprecision(4) << noshowpos << CStat::ZtoP(biasAndAc.AC.cumulativeACZScore[i-1]) << " " << biasAndAc.AC.P_Chi2[i-1] << " |" << endl; + const char *suffix = (i % 10 == 1 && i != 11) ? "st" : (i % 10 == 2 && i != 12) ? "nd" : (i % 10 == 3 && i != 13) ? "rd" : "th"; + cout << " " << setw(2) << i << suffix << " AutoCorr " << setiosflags(ios::fixed) << setprecision(3) << showpos << biasAndAc.AC.cumulativeACZScore[i-1] << " " << setprecision(4) << noshowpos << CStat::ZtoP(biasAndAc.AC.cumulativeACZScore[i-1]) << " " << biasAndAc.AC.P_Chi2[i-1] << " |" << endl; } cout << " +---------------------------+------------------------------------------------+" << endl; @@ -365,8 +343,39 @@ int main() timePrev = timeNow; cout.flush(); + }; + + while (!doExit || !dataQueue.empty()) { + shared_ptr> testBuffer = nullptr; + #pragma omp critical + { + if (!dataQueue.empty()) { + testBuffer = dataQueue.front(); + dataQueue.pop(); + } + } + + if (testBuffer != nullptr) { + // Parallel processing of the testBuffer + #pragma omp parallel sections num_threads(4) + { + #pragma omp section + { for (uint32_t value : *testBuffer) biasAndAc.InsertWord32(value); } + #pragma omp section + { for (uint32_t value : *testBuffer) oqso.InsertWord32(value); } + #pragma omp section + { for (uint32_t value : *testBuffer) serial.InsertWord32(value); } + #pragma omp section + { for (uint32_t value : *testBuffer) entropy.InsertWord32(value); } } + bitsTestedCount += 32.0 * testBuffer->size(); + + // Display results every 10 seconds + time(&timeNow); + if (difftime(timeNow, timePrev) >= 10) + report(); + // End on an 'x' keypress #ifdef _WIN32 if (kbhit()) @@ -390,6 +399,10 @@ int main() usleep(1000); } } + + // Final results when the input ends (or on CTRL-C) + time(&timeNow); + report(); } } } diff --git a/RandTest/Entropy.cpp b/RandTest/Entropy.cpp index 7ce75d9..587793b 100755 --- a/RandTest/Entropy.cpp +++ b/RandTest/Entropy.cpp @@ -34,7 +34,7 @@ double CEntropy::CalcStandardDeviation(uint32_t K, uint32_t m) data[8][1] = 3.4075860; data[8][2] = 0.3901408; data[8][3] = 0.3606982; data[9][1] = 3.4149476; data[9][2] = 0.3909846; data[9][3] = 0.3600222; data[10][1] = 3.4189794; data[10][2] = 0.3914671; data[10][3] = 0.3596484; - data[11][1] = 3.4211711; data[11][2] = 0.3917390; data[11][1] = 0.3594433; + data[11][1] = 3.4211711; data[11][2] = 0.3917390; data[11][3] = 0.3594433; data[12][1] = 3.4223549; data[12][2] = 0.3918905; data[12][3] = 0.3593316; data[13][1] = 3.4229908; data[13][2] = 0.3919740; data[13][3] = 0.3592712; data[14][1] = 3.4233308; data[14][2] = 0.3920198; data[14][3] = 0.3592384; diff --git a/readme.md b/readme.md index b00e43f..d63ea98 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,8 @@ $ dd if=/dev/urandom of=random_data.bin bs=4096 count=4096 $ cat random_data.bin | ./qngmeter ``` +The results table is printed every 10 seconds while data arrives and once more when the input ends (or on CTRL-C). Bytes are read as little-endian 32-bit words, least significant bit first, so within each byte the bits are tested in reverse order; this only matters for the autocorrelation lags of non-random data. + ## Output ```sh