removed QWQNG, added stdin

This commit is contained in:
randogoth 2024-03-02 17:58:28 +02:00
commit 0fe369bc5a
39 changed files with 3095 additions and 0 deletions

106
RandTest/ACBinomialChi2.cpp Executable file
View file

@ -0,0 +1,106 @@
//#include "StdAfx.h"
#include "ACBinomialChi2.h"
#include "math.h"
CACBinomialChi2::CACBinomialChi2(void)
{
InitPTable();
}
CACBinomialChi2::~CACBinomialChi2(void)
{
}
// Bins incomming values for future Chi2 test
void CACBinomialChi2::BinIt(double BinVal)
{
int BinIndex = -1;
if (BinVal <= 16090)
BinIndex = 0;
else if (BinVal >= 16679)
BinIndex = 50;
else {
BinIndex = (int)BinVal - 16091;
BinIndex /= 12;
BinIndex += 1;
}
pBin[BinIndex] += 1.0;
// update Total count
Total += 1.0;
}
// Calculate cumulative chi^2
double CACBinomialChi2::Calc()
{
double Sum = 0;
for (int i=0; i<51; i++)
Sum += (pBin[i] * pBin[i])/(Total * pTable[i]);
return Sum-Total;
}
// Resets the cumulative test completely
void CACBinomialChi2::ResetAll(void)
{
ZeroMemory(pBin, 51*sizeof(double));
Total = 0;
}
// Initializes pTable
void CACBinomialChi2::InitPTable(void)
{
pTable[0] = 0.0199136;
pTable[1] = 0.00443703;
pTable[2] = 0.00523732;
pTable[3] = 0.00613872;
pTable[4] = 0.00714366;
pTable[5] = 0.00825334;
pTable[6] = 0.00946896;
pTable[7] = 0.0107857;
pTable[8] = 0.0121988;
pTable[9] = 0.0136985;
pTable[10] = 0.0152738;
pTable[11] = 0.0169106;
pTable[12] = 0.0185897;
pTable[13] = 0.0202911;
pTable[14] = 0.021992;
pTable[15] = 0.0236668;
pTable[16] = 0.0252903;
pTable[17] = 0.0268349;
pTable[18] = 0.0282722;
pTable[19] = 0.0295779;
pTable[20] = 0.0307263;
pTable[21] = 0.0316944;
pTable[22] = 0.0324642;
pTable[23] = 0.0330194;
pTable[24] = 0.0333472;
pTable[25] = 0.0334425;
pTable[26] = 0.0333044;
pTable[27] = 0.0329349;
pTable[28] = 0.0323407;
pTable[29] = 0.031536;
pTable[30] = 0.0305358;
pTable[31] = 0.0293616;
pTable[32] = 0.0280353;
pTable[33] = 0.026582;
pTable[34] = 0.0250301;
pTable[35] = 0.0234031;
pTable[36] = 0.0217306;
pTable[37] = 0.020037;
pTable[38] = 0.018347;
pTable[39] = 0.0166828;
pTable[40] = 0.0150652;
pTable[41] = 0.0135096;
pTable[42] = 0.0120311;
pTable[43] = 0.0106397;
pTable[44] = 0.0093446;
pTable[45] = 0.00814988;
pTable[46] = 0.00705929;
pTable[47] = 0.00607215;
pTable[48] = 0.00518732;
pTable[49] = 0.00440057;
pTable[50] = 0.0200105;
}

21
RandTest/ACBinomialChi2.h Executable file
View file

@ -0,0 +1,21 @@
#pragma once
#include "BinomialChi2.h"
class CACBinomialChi2 :
public CBinomialChi2
{
public:
CACBinomialChi2(void);
~CACBinomialChi2(void);
// Overridden to initialze pTable for auto-correlation
virtual void InitPTable(void);
// Oberridden to calc index for ac binning
virtual void BinIt(double BinVal);
virtual double Calc();
virtual void ResetAll();
private:
double pBin[54];
double pTable[54];
};

74
RandTest/ACBinomialChi2.old.cpp Executable file
View file

@ -0,0 +1,74 @@
#include "StdAfx.h"
#include "acbinomialchi2.h"
#include "math.h"
CACBinomialChi2::CACBinomialChi2(void)
{
InitPTable();
}
CACBinomialChi2::~CACBinomialChi2(void)
{
}
// Overridden to initialze pTable for auto-correlation
VOID CACBinomialChi2::InitPTable(void)
{
// 2^16 auto-correlation
pTable[0] = 0.0436123510244955321;
pTable[1] = 0.0494945236349887629;
pTable[2] = 0.0483966799920995590;
pTable[3] = 0.0465904838376547746;
pTable[4] = 0.0441572550221125783;
pTable[5] = 0.0412031166704026490;
pTable[6] = 0.0378513315493016954;
pTable[7] = 0.0342338133652554904;
pTable[8] = 0.0304826229422669920;
pTable[9] = 0.0267222012692252800;
pTable[10] = 0.0230629500401081457;
pTable[11] = 0.0195965713435074457;
pTable[12] = 0.0163933532864769463;
pTable[13] = 0.0135013695454263963;
pTable[14] = 0.0109473753452615719;
pTable[15] = 0.0087390490108419405;
pTable[16] = 0.0068681557366127721;
pTable[17] = 0.0053141974233424296;
pTable[18] = 0.0040481501288843967;
pTable[19] = 0.0030359644605488801;
pTable[20] = 0.0022415976474860848;
pTable[21] = 0.0016294434474942837;
pTable[22] = 0.0011661147954655219;
pTable[23] = 0.0008216056587517001;
pTable[24] = 0.0016958983342359457;
}
// Oberridden to calc index for ac binning
VOID CACBinomialChi2::BinIt(double BinVal)
{
// center bin (7 slots for ac)
int BinIndex = 0;
int Side = 1; // middle bin and right side
// calc for autocorrelation
if ((BinVal<-3.) || (BinVal>3.))
BinIndex = 1 + (abs((int)BinVal)-4)/8; // 8 slots per bin
if (BinVal<-3.)
Side = -1; // left side
// tails of distribution fall in one bin
if (BinIndex>24)
BinIndex = 24;
if (Side>0)
{ // fill in positive side
pBinPositive[BinIndex]+=1.;
}
else
{ // fill in negative side
pBinNegative[BinIndex]+=1.;
}
// update Total count
Total += 1.;
}

125
RandTest/AutoCorrelation.cpp Executable file
View file

@ -0,0 +1,125 @@
//#include "StdAfx.h"
#include "AutoCorrelation.h"
#include "math.h"
CAutoCorrelation::CAutoCorrelation(void)
: maxOrder(32)
, bitStream(0)
{
CreateChi2Tests();
// ZeroMemory(cumulativeACZScore, 32*sizeof(double));
memset(cumulativeACZScore, 0, 32*sizeof(double));
for (int i=0; i<32; i++)
P_Chi2[i] = .5;
ResetTest();
// Initializing app must call ResetAll()!!!
}
CAutoCorrelation::~CAutoCorrelation(void)
{
for (int i=0; i<32; i++)
delete MetaChi2[i];
}
// Inserts a 32 bit word into the unit test
// Must insert word into Bias test first, AC is completely dependent upon Bias
void CAutoCorrelation::InsertWord32(uint32_t InWord32)
{
bitStream >>= 32;
bitStream |= (uint64_t)InWord32 << 32;
int Order;
for (Order=1; Order<=maxOrder; Order++)
{
totalAndCount[Order-1] += BitCount.GetCount32((uint32_t)bitStream & (uint32_t)(bitStream>>Order));
blockXorCount[Order-1] += BitCount.GetCount32((uint32_t)bitStream ^ (uint32_t)(bitStream>>Order));
}
// Every 2048 32 bit words do a unit and cumulative calculation
if ((++blockWordCount)>=2048)
{
for (Order=1; Order<=maxOrder; Order++)
{
totalXorCount[Order-1] += blockXorCount[Order-1];
double NN = (65536.*(totalBlockCount+1));
// double XX = totalXorCount[Order-1];
// cumulativeACZScore[Order-1] = -(2*XX-NN) / sqrt(NN);
// fractional ANDs
double fAnd = totalAndCount[Order-1] / NN;
// fractional bias
double fBias = *pTotalBiasCount / NN;
// full AC calculation (a-b^2) / ((1-b) * b)
if ((fBias*fBias)<=0 || fBias>=1)
cumulativeACZScore[Order-1] = 0;
else
cumulativeACZScore[Order-1] = sqrt(NN) * (fAnd - fBias*fBias)/(fBias - fBias*fBias);
MetaChi2[Order-1]->Insert(blockXorCount[Order-1]);
P_Chi2[Order-1] = MetaChi2[Order-1]->GetPvalue();//Gamma.Gamma(50, ACChi2[Order-1].Calc());
}
ResetTest();
totalBlockCount++;
}
}
// Resets current unit testing
void CAutoCorrelation::ResetTest(void)
{
blockWordCount = 0;
for (int i=0; i<32; i++)
blockXorCount[i] = 0;
}
// Resets cumulative scores
void CAutoCorrelation::ResetAll(double* pTotalBiasCount, double* pBlockBiasCount)
{
this->pBlockBiasCount = pBlockBiasCount;
this->pTotalBiasCount = pTotalBiasCount;
totalBlockCount = 0;
// ZeroMemory(totalAndCount, 32*sizeof(double));
memset(totalAndCount, 0, 32*sizeof(double));
// ZeroMemory(totalXorCount, 32*sizeof(double));
memset(totalXorCount, 0, 32*sizeof(double));
for (int i=0; i<32; i++)
P_Chi2[i] = .5;
for (int i=0; i<32; i++)
{
MetaChi2[i]->Reset();
// ACChi2[i].ResetAll();
cumulativeACZScore[i] = 0.;
prevCumulativeACZScore[i] = 0.;
P_Chi2[i] = .5;
}
bitStream = 0;
ResetTest();
}
void CAutoCorrelation::CreateChi2Tests(void) {
double pTable[] = {
0.0016751591157826984, 0.0008125704223141780, 0.0011538175281394167, 0.0016130041110183372, 0.0022200160266961827,
0.0030081473713346360, 0.0040129572987985991, 0.0052705078207208266, 0.0068149541705240074, 0.0086755302334023398,
0.0108730598645528967, 0.0134162222471676280, 0.0162978932289932796, 0.0194919592594017396, 0.0229510396552503468,
0.0266055419211793493, 0.0303644043131267252, 0.0341177483099464753, 0.0377414795440626524, 0.0411036575708872835,
0.0440722296391575050, 0.0465235232774633227, 0.0483507488411394182, 0.0494717022548410683, 0.0467242519481981447,
0.0494717022548410683, 0.0483507488411394182, 0.0465235232774633227, 0.0440722296391575050, 0.0411036575708872835,
0.0377414795440626524, 0.0341177483099464753, 0.0303644043131267252, 0.0266055419211793493, 0.0229510396552503468,
0.0194919592594017396, 0.0162978932289932796, 0.0134162222471676280, 0.0108730598645528967, 0.0086755302334023398,
0.0068149541705240074, 0.0052705078207208266, 0.0040129572987985991, 0.0030081473713346360, 0.0022200160266961827,
0.0016130041110183372, 0.0011538175281394167, 0.0008125704223141780, 0.0016751591157826984
};
double boundryTable[] = {
32392, 32408, 32424, 32440, 32456, 32472, 32488, 32504, 32520,
32536, 32552, 32568, 32584, 32600, 32616, 32632, 32648, 32664, 32680,
32696, 32712, 32728, 32744, 32760, 32775, 32791, 32807, 32823, 32839,
32855, 32871, 32887, 32903, 32919, 32935, 32951, 32967, 32983, 32999,
33015, 33031, 33047, 33063, 33079, 33095, 33111, 33127, 33143, 1e100
};
for (int i=0; i<32; i++)
MetaChi2[i] = new Chi2(49, pTable, false, boundryTable, false);
}

69
RandTest/AutoCorrelation.h Executable file
View file

@ -0,0 +1,69 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "BitCount.h"
#include "ACBinomialChi2.h"
#include "Gamma.h"
#include "Chi2.hpp"
class CAutoCorrelation
{
public:
CAutoCorrelation(void);
~CAutoCorrelation(void);
// Inserts a 32 bit word into the unit test
void InsertWord32(uint32_t InWord32);
// Resets current unit testing
void ResetTest(void);
// Resets cumulative scores
void ResetAll(double* pTotalBiasCount, double* pBlockBiasCount);
// Cumulative z-score
double cumulativeACZScore[32];
double prevCumulativeACZScore[32];
// Keeps track of all blocks in cumulative testing
double totalBlockCount;
// P-values of cumulative chi^2 tests
double P_Chi2[32];
// Highest order to be tested
int maxOrder;
protected:
// History bit stream of last 32 plus current 32 bits (=64bits)
uint64_t bitStream;
// First word in block to calc bias difference
// uint32_t firstBlockWord32;
// Counts up "ands" for a block = multiply in cross correlation
// int blockAndCount[32];
double blockXorCount[32];
// Counts up cumulative "ands" for each AC order
double totalXorCount[32];
double totalAndCount[32];
// Chi^2 test cumulative for each order
void CreateChi2Tests();
Chi2* MetaChi2[32];
// Incomplete Gamma function
CGamma Gamma;
// Counts 32 bits words in current block test
int blockWordCount;
// To quickly count bits within 32 bit word
CBitCount BitCount;
// Pointer to the just calculated block bias one count
double* pBlockBiasCount;
// Pointer to the cumulative (including current block) one count
double* pTotalBiasCount;
};

85
RandTest/Bias.cpp Executable file
View file

@ -0,0 +1,85 @@
//#include "StdAfx.h"
#include "Bias.h"
#include "math.h"
CBias::CBias(void)
: cumulativeBiasZScore(0)
, P_Chi2(.5)
{
CreateChi2Test();
ResetAll();
}
CBias::~CBias(void)
{
delete MetaChi2;
}
// Tests a 32 bit word
void CBias::InsertWord32(uint32_t InWord32)
{
blockBiasCount += BitCount.GetCount32(InWord32);
// Every 2^16 bits calc cumulative bias and chi^2
if ( (++blockWordCount)>=2048 )
{
// calculate unit bias
double BlockZScore = (2.*blockBiasCount-(32*blockWordCount))/(sqrt(32.0*blockWordCount));
// Chi^2 for bias using binomial chi^2 test Chi2Binomial
MetaChi2->Insert(blockBiasCount);
P_Chi2 = MetaChi2->GetPvalue();
totalBiasCount += blockBiasCount;
formerBlockBiasCount = blockBiasCount;
totalBlockCount++;
cumulativeBiasZScore = ((2.*totalBiasCount) - (65536.*totalBlockCount)) / sqrt(65536.*totalBlockCount);
ResetTest();
}
}
// Resets current test
void CBias::ResetTest()
{
blockWordCount = 0;
blockBiasCount = 0;
}
// Resets all
void CBias::ResetAll()
{
P_Chi2 = .5;
cumulativeBiasZScore = 0.;
totalBiasCount = 0;
totalBlockCount = 0;
// BiasChi2.ResetAll();
MetaChi2->Reset();
ResetTest();
}
void CBias::CreateChi2Test(void) {
double pTable[] = {
0.0016751591157826984, 0.0008125704223141780, 0.0011538175281394167, 0.0016130041110183372, 0.0022200160266961827,
0.0030081473713346360, 0.0040129572987985991, 0.0052705078207208266, 0.0068149541705240074, 0.0086755302334023398,
0.0108730598645528967, 0.0134162222471676280, 0.0162978932289932796, 0.0194919592594017396, 0.0229510396552503468,
0.0266055419211793493, 0.0303644043131267252, 0.0341177483099464753, 0.0377414795440626524, 0.0411036575708872835,
0.0440722296391575050, 0.0465235232774633227, 0.0483507488411394182, 0.0494717022548410683, 0.0467242519481981447,
0.0494717022548410683, 0.0483507488411394182, 0.0465235232774633227, 0.0440722296391575050, 0.0411036575708872835,
0.0377414795440626524, 0.0341177483099464753, 0.0303644043131267252, 0.0266055419211793493, 0.0229510396552503468,
0.0194919592594017396, 0.0162978932289932796, 0.0134162222471676280, 0.0108730598645528967, 0.0086755302334023398,
0.0068149541705240074, 0.0052705078207208266, 0.0040129572987985991, 0.0030081473713346360, 0.0022200160266961827,
0.0016130041110183372, 0.0011538175281394167, 0.0008125704223141780, 0.0016751591157826984
};
double boundryTable[] = {
32392, 32408, 32424, 32440, 32456, 32472, 32488, 32504, 32520,
32536, 32552, 32568, 32584, 32600, 32616, 32632, 32648, 32664, 32680,
32696, 32712, 32728, 32744, 32760, 32775, 32791, 32807, 32823, 32839,
32855, 32871, 32887, 32903, 32919, 32935, 32951, 32967, 32983, 32999,
33015, 33031, 33047, 33063, 33079, 33095, 33111, 33127, 33143, 1e100
};
MetaChi2 = new Chi2(49, pTable, false, boundryTable, false);
}

57
RandTest/Bias.h Executable file
View file

@ -0,0 +1,57 @@
// 1/0 Balance - expected value is p(0) = p(1) = 0.5
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "BitCount.h"
#include "Chi2.hpp"
#include "Gamma.h"
class CBias
{
friend class CBiasAndAC;
public:
CBias(void);
~CBias(void);
// Tests a 32 bit word
void InsertWord32(uint32_t InWord32);
// Resets all
void ResetAll();
// Cumulative z score
double cumulativeBiasZScore;
// Cumulative chi^2 results
double P_Chi2;
// Keeps track of all blocks in cumulative testing
double totalBlockCount;
protected:
// Counts 1-bits per block
double blockBiasCount;
// Cumulative bias 1-bit count
double totalBiasCount;
double formerBlockBiasCount;
// Resets current test
void ResetTest();
// Quick 32 bit word bit count table lookup
CBitCount BitCount;
// Keeps track of words tested in block
int blockWordCount;
// Calculates the chi^2
void CreateChi2Test();
Chi2* MetaChi2;
// Incomplete Gamma function
CGamma Gamma;
};

25
RandTest/BiasAndAC.cpp Executable file
View file

@ -0,0 +1,25 @@
//#include "StdAfx.h"
#include "BiasAndAC.h"
CBiasAndAC::CBiasAndAC(void)
{
ResetAll();
}
CBiasAndAC::~CBiasAndAC(void)
{
}
// Inserts a 32 bit word into both Bias an AC tests
void CBiasAndAC::InsertWord32(uint32_t InWord32)
{
Bias.InsertWord32(InWord32);
AC.InsertWord32(InWord32);
}
// Resets all in Bias and AutoCorrelation
void CBiasAndAC::ResetAll(void)
{
Bias.ResetAll();
AC.ResetAll(&Bias.totalBiasCount, &Bias.formerBlockBiasCount);
}

24
RandTest/BiasAndAC.h Executable file
View file

@ -0,0 +1,24 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "Bias.h"
#include "AutoCorrelation.h"
class CBiasAndAC
{
public:
CBiasAndAC(void);
~CBiasAndAC(void);
// Inserts a 32 bit word into both Bias an AC tests
void InsertWord32(uint32_t InWord32);
// Bias test
CBias Bias;
// Auto-correlation test
CAutoCorrelation AC;
// Resets all in Bias and AutoCorrelation
void ResetAll(void);
};

97
RandTest/BinomialChi2.cpp Executable file
View file

@ -0,0 +1,97 @@
#include "StdAfx.h"
#include "binomialchi2.h"
#include "math.h"
CBinomialChi2::CBinomialChi2(void)
{
InitPTable();
}
CBinomialChi2::~CBinomialChi2(void)
{
}
// Bins incomming values for future Chi2 test
void CBinomialChi2::BinIt(double BinVal)
{
// center bin (15 slots for 1/0)
int BinIndex = 0;
int Side = 1; // middle bin and right side
// calc Index for 1/0 balance
if ((BinVal>32775.) || (BinVal<32761.))
BinIndex = 1 + (abs((int)BinVal-32768)-8)/16; // 16 slots per bin
if (BinVal<32761)
Side = -1; // left side
// tails of distribution fall in one bin
if (BinIndex>24)
BinIndex = 24;
if (Side>0)
{ // fill in positive side
pBinPositive[BinIndex]+=1.;
}
else
{ // fill in negative side
pBinNegative[BinIndex]+=1.;
}
// update Total count
Total += 1.;
}
// Calculate cumulative chi^2
double CBinomialChi2::Calc()
{
double Sum = (pBinPositive[0] * pBinPositive[0])/(Total * pTable[0]);
for (int i=1; i<25; i++)
{
Sum += (pBinPositive[i] * pBinPositive[i])/(Total * pTable[i]);
Sum += (pBinNegative[i] * pBinNegative[i])/(Total * pTable[i]);
}
return Sum-Total;
}
// Resets the cumulative test completely
void CBinomialChi2::ResetAll(void)
{
ZeroMemory(pBinPositive, 30*sizeof(double));
ZeroMemory(pBinNegative, 30*sizeof(double));
Total = 0;
}
// Initializes pTable
void CBinomialChi2::InitPTable(void)
{
// 2^16 1/0 bias distribution table
pTable[0] = 0.0467242519481981447;
pTable[1] = 0.0494717022548410683;
pTable[2] = 0.0483507488411394182;
pTable[3] = 0.0465235232774633227;
pTable[4] = 0.0440722296391575050;
pTable[5] = 0.0411036575708872835;
pTable[6] = 0.0377414795440626524;
pTable[7] = 0.0341177483099464753;
pTable[8] = 0.0303644043131267252;
pTable[9] = 0.0266055419211793493;
pTable[10] = 0.0229510396552503468;
pTable[11] = 0.0194919592594017396;
pTable[12] = 0.0162978932289932796;
pTable[13] = 0.0134162222471676280;
pTable[14] = 0.0108730598645528967;
pTable[15] = 0.0086755302334023398;
pTable[16] = 0.0068149541705240074;
pTable[17] = 0.0052705078207208266;
pTable[18] = 0.0040129572987985991;
pTable[19] = 0.0030081473713346360;
pTable[20] = 0.0022200160266961827;
pTable[21] = 0.0016130041110183372;
pTable[22] = 0.0011538175281394167;
pTable[23] = 0.0008125704223141780;
pTable[24] = 0.0016751591157826984;
}

29
RandTest/BinomialChi2.h Executable file
View file

@ -0,0 +1,29 @@
#pragma once
class CBinomialChi2
{
public:
CBinomialChi2(void);
~CBinomialChi2(void);
// Bins incomming values for future Chi2 test
virtual void BinIt(double BinVal);
// Calculate cumulative chi^2
double Calc(void);
// Resets the cumulative test completely
void ResetAll(void);
protected:
// Positive side bins
double pBinPositive[30];
// Negative side bins
double pBinNegative[30];
// Total values binned
double Total;
// Table with bin probabilities
double pTable[25];
// Initializes pTable
virtual void InitPTable(void);
};

29
RandTest/BitCount.cpp Executable file
View file

@ -0,0 +1,29 @@
//#include "StdAfx.h"
#include "BitCount.h"
uint8_t CBitCount::Table16[65536];
bool CBitCount::IsInitialized = false;
CBitCount::CBitCount(void)
{
// Initialize, if not already done so
if (!IsInitialized)
{
for (int i=0; i<=65535; i++)
{
// Fill up table
uint8_t BitCount = 0;
for (int b=0; b<16; b++)
BitCount += ((i>>b)&0x1);
Table16[i] = BitCount;
}
IsInitialized = true;
}
}
CBitCount::~CBitCount(void)
{
}

24
RandTest/BitCount.h Executable file
View file

@ -0,0 +1,24 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
class CBitCount
{
public:
CBitCount(void);
~CBitCount(void);
// Get bitcount for this 32 bit word
// __forceinline uint8_t GetCount32(uint32_t InWord32) {
uint8_t GetCount32(uint32_t InWord32) {
// PUSHORT pWordDiv16 = (PUSHORT)&InWord32;
return (Table16[(uint16_t)InWord32] + Table16[(uint16_t)(InWord32>>16)]);
}
private:
// Table to keep bit counts of 16 bit values
static uint8_t Table16[65536];
static bool IsInitialized;
};

39
RandTest/Chi2.cpp Executable file
View file

@ -0,0 +1,39 @@
#include "StdAfx.h"
#include "chi2.h"
CChi2::CChi2(void)
{
Init();
}
CChi2::~CChi2(void)
{
}
// Clear Chi2 test and set number of bins to use
void CChi2::Init(double nBins)
{
nCount = 0; // nCount
this->nBins = nBins; // nBins
pBin = 1./nBins; // pBin = 1/nBins
SumBinsSquared = 0; // SumBinsSquared
memset( Bin, 0, 65536*4 ); // Zero all Bins
}
// Inserts a probability and calculates new chi^2
double CChi2::CalcChi2(double pValue)
{
double np;
double BinAdd;
UINT BinIndex;
nCount++;
np = nCount*pBin;
BinIndex = (UINT)(nBins * pValue);
BinAdd = 2 * Bin[BinIndex] + 1;
Bin[BinIndex]++;
SumBinsSquared += BinAdd;
return (SumBinsSquared/np - nCount);
}

20
RandTest/Chi2.h Executable file
View file

@ -0,0 +1,20 @@
#pragma once
class CChi2
{
public:
CChi2(void);
~CChi2(void);
// Clear Chi2 test and set number of bins to use
void Init(double nBins=32.);
// Inserts a probability and calculates new chi^2
double CalcChi2(double pValue);
protected:
double Bin[65536];
double SumBinsSquared;
double pBin; // Probability of falling into any given bin
double nBins; // Total number of bins
double nCount; // Number of pValues binned
};

104
RandTest/Chi2.hpp Executable file
View file

@ -0,0 +1,104 @@
#pragma once
#include <memory.h>
#include "Gamma.h"
class Chi2 {
public:
Chi2(int binCount=10, double* pTable=0, bool pTableCumulative=false, double* boundryTable=0, bool reverseBoundrySense=false) {
this->binCount = binCount;
this->binned = new double[binCount];
this->boundryTable = new double[binCount];
this->reverseBoundrySense = reverseBoundrySense;
this->pTable = new double[binCount];
if (pTable == 0) {
for (int i=0; i<binCount; i++) {
this->pTable[i] = 1.0 / binCount;
this->boundryTable[i] = (1.0+i) / binCount;
}
}
else {
memcpy(this->pTable, pTable, sizeof(double)*binCount);
memcpy(this->boundryTable, boundryTable, sizeof(double)*binCount);
}
if (pTableCumulative == true) {
for (int i=(binCount-1); i>=1; i--) {
this->pTable[i] = pTable[i] - pTable[i-1];
}
}
Reset();
}
~Chi2() {
delete[] pTable;
delete[] boundryTable;
delete[] binned;
}
void Reset() {
doRecalc = true;
for (int i=0; i<binCount; i++)
binned[i] = 0;
}
void Insert(double inValue) {
int i = 0;
if (reverseBoundrySense == false) {
while (inValue > boundryTable[i])
i++;
}
else {
while (inValue < boundryTable[i])
i++;
}
binned[i]++;
doRecalc = true;
}
double GetChi2() {
if (doRecalc == true)
Recalc();
return chi2;
}
double GetPvalue() {
if (doRecalc == true)
Recalc();
return (Gamma.Gamma(binCount-1, chi2));
}
private:
void Recalc() {
double sum = 0;
double total = 0;
for (int i=0; i<binCount; i++) {
sum += (binned[i]*binned[i]) / pTable[i] ;
total += binned[i];
}
sum /= total;
chi2 = sum - total;
}
double chi2;
double pValue;
bool doRecalc;
int binCount;
double* boundryTable;
bool reverseBoundrySense;
double* pTable;
CGamma Gamma;
public:
double* binned;
};

174
RandTest/Entropy.cpp Executable file
View file

@ -0,0 +1,174 @@
//#include "StdAfx.h"
#include "Entropy.h"
#include "math.h"
CEntropy::CEntropy()
: E(1.0)
{
CreateChi2Test();
pow2_32 = pow( 2.0, 32 );
ResetAll();
}
CEntropy::~CEntropy()
{
delete MetaChi2;
}
double CEntropy::CalcStandardDeviation(uint32_t K, uint32_t m)
{
double sd; // standard deviation
double clk; // intermediate calc variable
double data[15][4]; // data needed for sd calculation
// initialize data matrix
data[1][1] = 2.5769918; data[1][2] = 0.3313257; data[1][3] = 0.4381809;
data[2][1] = 2.9191004; data[2][2] = 0.3516506; data[2][3] = 0.4050170;
data[3][1] = 3.1291382; data[3][2] = 0.3660832; data[3][3] = 0.3856668;
data[4][1] = 3.2547450; data[4][2] = 0.3758725; data[4][3] = 0.3743782;
data[5][1] = 3.3282150; data[5][2] = 0.3822459; data[5][3] = 0.3678269;
data[6][1] = 3.3704039; data[6][2] = 0.3862500; data[6][3] = 0.3640569;
data[7][1] = 3.3942629; data[7][2] = 0.3886906; data[7][3] = 0.3619091;
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[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;
clk = sqrt( data[m-2][2] + (data[m-2][3]*pow( 2.0, (double)m )/K) );
sd = clk * sqrt( data[m-2][1] / K );
return sd;
}
void CEntropy::Initialize(uint32_t BitCount, uint32_t qFactor )
{
this->BitCount = BitCount;
// get initialization blocks used
Q = qFactor * 256; // 20*256 = 5120
// get total number of m-bit blocks
nb = (unsigned long)floor( BitCount / 8.0 ); // 524288
// get number of calculation blocks used
K = nb - Q; // 519168
// calc sd
sd = CalcStandardDeviation( K, 8 );
// zero out tab
memset( tab, 0, 256*4 );
blockWordCount = 0;
Sum = 0;
}
void CEntropy::InsertWord32(uint32_t InWord32)
{
int i;
uint8_t RndByte;
for ( i=0; i<=3; i++ )
{
RndByte = (uint8_t)(InWord32>>(8*i));
blockWordCount++;
if ( blockWordCount<=Q )
{
tab[RndByte] = blockWordCount;
}
else
{
Sum += fcoef( blockWordCount - tab[RndByte] );
tab[RndByte] = blockWordCount;
}
}
if ( (blockWordCount*8)>=BitCount )
{
H = Sum/((double)K);
ETotal += H/8.;
totalBlockCount++;
E = ETotal / (totalBlockCount);
double BlockZScore = ( (H-8.)/sd );
ZScoreTotal += BlockZScore;
MetaChi2->Insert(Sum);
P_Chi2 = MetaChi2->GetPvalue();
if (totalBlockCount!=0)
cumulativeZScore = ZScoreTotal / sqrt(totalBlockCount);
Initialize( 4194304, 20 );
}
}
double CEntropy::fcoef(uint32_t i)
{
// set constants
const double l2 = log(2.0);
const double c = -0.8327462;
const int limit = 23;
double retval; // return value
unsigned long kk; // universal index
int j; // intermediate calc value
retval = 0;
if ( i<limit )
{
for ( kk=1; kk<i; kk++ )
{
retval += 1/(double)kk;
}
retval /= l2;
}
else
{
j = i - 1;
retval = ( log((double)j)/l2 ) - c + ( ((1./(2.*j)) - (1./(12.*j*j)))/l2 );
}
return retval;
}
// Reset cumulative test
void CEntropy::ResetAll(void)
{
E = 1.0;
P_Chi2 = .5;
cumulativeZScore = 0.;
ZScoreTotal = 0;
ETotal = 0;
totalBlockCount = 0.;
MetaChi2->Reset();
// Chi2.Init();
Initialize( 4194304, 20 );
}
void CEntropy::CreateChi2Test(void) {
double pTable[] = {0.02012108166,0.04008956584,0.06018692852,0.08018501372,0.1001359343,0.120192745,0.1401963459,0.16005801,0.1802017087,0.200031418,0.2200301029,0.2399762859,0.2599755987,0.2800970982,0.3000327584,0.3202120847,0.340234622,0.360070732,0.3800778627,0.3998619416,0.4199041271,0.4398490175,0.4601300439,0.4798811487,0.5000167861,0.5201045044,0.5399738275,0.5600664317,0.5798227432,0.5998761946,0.619978835,0.6402984742,0.6599255874,0.6799283734,0.7001158234,0.7199709181,0.7401361424,0.7599607824,0.7802489806,0.8001210836,0.8200605293,0.8400672073,0.8601944042,0.880037642,0.900350094,0.9203249058,0.9401774272,0.9600776027,0.9807874005,1.0};
double boundryTable[] = {
4151655.83724745500, 4151904.48938296180, 4152066.26934954900, 4152189.24478157190, 4152290.52925698830,
4152378.39198942950, 4152456.23714622110, 4152526.37086037970, 4152591.89903046660, 4152652.04845737200,
4152709.17705694870, 4152763.25623371170, 4152815.06782631900, 4152865.15788602550, 4152913.08992392620,
4152960.15932061100, 4153005.64889538610, 4153049.71294774950, 4153093.31400005010, 4153135.74272596740,
4153178.16347156510, 4153219.94024266860, 4153262.09135455310, 4153302.92978435200, 4153344.45511117900,
4153385.87801960110, 4153426.95058751110, 4153468.69217352150, 4153510.04595550760, 4153552.45207967800,
4153595.52232766520, 4153639.76729502670, 4153683.32874056320, 4153728.72452108000, 4153775.75883651480,
4153823.43728935770, 4153873.56984770070, 4153924.85234509460, 4153979.78749536580, 4154036.49777039420,
4154096.92328405190, 4154161.94629989700, 4154232.98319796660, 4154310.19911737930, 4154399.23572011480,
4154500.86437934400, 4154623.25103316270, 4154783.62485346620, 4155045.02386120380, 1e100
};
MetaChi2 = new Chi2(50, pTable, true, boundryTable, false);
}

45
RandTest/Entropy.h Executable file
View file

@ -0,0 +1,45 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "Gamma.h"
#include "Chi2.hpp"
#include "Stat.h"
class CEntropy
{
public:
double P_Chi2;
inline double fcoef(uint32_t i);
double sd;
double E;
double H;
double cumulativeZScore;
double totalBlockCount;
uint32_t blockWordCount;
void InsertWord32(uint32_t InWord32);
void Initialize(uint32_t BitCount, uint32_t qFactor);
CEntropy();
virtual ~CEntropy();
protected:
CStat Stat;
double pow2_32;
CGamma Gamma;
double ETotal;
double ZScoreTotal;
double Sum;
uint32_t K;
uint32_t nb;
uint32_t Q;
uint32_t BitCount;
uint32_t tab[256];
double CalcStandardDeviation(uint32_t K, uint32_t m);
Chi2* MetaChi2;
void CreateChi2Test(void);
public:
// Reset cumulative test
void ResetAll(void);
};

218
RandTest/Gamma.cpp Executable file
View file

@ -0,0 +1,218 @@
//#include "StdAfx.h"
#include "Gamma.h"
#include "math.h"
#include <stdlib.h>
CGamma::CGamma()
{
}
CGamma::~CGamma()
{
}
double CGamma::gammln(double xx)
{
double RetVal;
double y;
double x;
double tmp;
double ser;
int j;
double cof[6];
cof[0] = 76.18009172947146; cof[1] = -86.50532032941677; cof[2] = 24.01409824083091;
cof[3] = -1.231739572450155; cof[4] = 1.208650973866179e-3; cof[5] = -5.395239384953e-6;
y = x = xx;
tmp = (x+5.5) - (x+0.5)*(log(x+5.5));
ser = 1.000000000190015;
for ( j=0; j<=5; j++ )
{
y += 1.0;
ser += cof[j]/y;
}
RetVal = log( 2.506628274631*ser/x ) - tmp;
return RetVal;
}
double CGamma::gamser(double a, double x)
{
double RetVal;
double gln;
double ap;
double del;
double sm;
int ITMAX;
int m;
if ( x!=0 )
{
ITMAX = 31;
gln = gammln( a );
ap = a;
del = sm = 1.0/a;
for( m=1; m<=ITMAX; m++ )
{
ap += 1;
del *= x/ap;
sm += del;
}
RetVal = sm * exp( a*log(x) - x - gln );
}
else
RetVal = 0;
return RetVal;
}
double CGamma::gcf(double a, double x)
{
double RetVal;
double gln;
double b;
double c;
double d;
double h;
double an;
double del;
double FPMIN;
int ITMAX;
int i;
gln = gammln( a );
b = x + 1.0 - a;
FPMIN = pow( 10., -30 );
c = 1.0 / FPMIN;
d = 1.0 / b;
h = d;
ITMAX = 30;
for ( i=1; i<=ITMAX; i++ )
{
an = (-i) * (i-a);
b += 2.0;
d = an*d + b;
if ( abs((int)d) < FPMIN ) d = FPMIN;
c = b + an/c;
if ( abs((int)c) < FPMIN ) c = FPMIN;
d = 1.0/d;
del = d * c;
h *= del;
}
RetVal = 1.0 - (exp( a*log(x) - x - gln ) * h);
return RetVal;
}
double CGamma::Gamma(double a, double chi2)
{
double RetVal;
double x;
a = a / 2;
x = chi2 / 2;
if ( x<=a )
RetVal = gamser( a, x );
else
RetVal = gcf( a, x );
return 1-RetVal;
}
double CGamma::Beta(double z, double a, double b)
{
double bt;
if (z < 0.0)
z = 0.0;
if (z > 1.0)
z = 1.0;
if (z == 0.0 || z == 1.0)
bt=0.0;
else
// Factors in front of the continued fraction.
bt = exp( gammln(a+b) - gammln(a) - gammln(b) + a*log(z) + b*log(1.0-z) );
if (z < (a+1.0)/(a+b+2.0)) // Use continued fraction directly.
return bt*betacf(a, b, z)/a;
else // Use continued fraction after making the symmetry transformation.
return 1.0-bt*betacf(b, a, 1.0-z)/b;
}
double CGamma::betacf(double a, double b, double x)
{
int m,m2;
double aa,c,d,del,h,qab,qam,qap;
double MAXIT = 100;
double EPS = 3.0e-7;
double FPMIN = 1.0e-30;
qab = a+b;
qap = a+1.0;
qam = a-1.0;
c = 1.0; // First step of Lentz's method.
d = 1.0 - qab*x/qap;
if (fabs(d) < FPMIN)
d = FPMIN;
d = 1.0/d;
h = d;
for (m=1; m<=MAXIT; m++)
// while (true)
{
m2 = 2*m;
aa = m*(b-m)*x / ((qam+m2)*(a+m2));
d = 1.0 + aa*d; // One step (the even one) of the recurrence.
if (fabs(d) < FPMIN)
d=FPMIN;
c = 1.0 + aa/c;
if (fabs(c) < FPMIN)
c = FPMIN;
d = 1.0/d;
h *= d*c;
aa = -(a+m)*(qab+m)*x / ((a+m2)*(qap+m2));
d = 1.0 + aa*d; // Next step of the recurrence (the odd one).
if (fabs(d) < FPMIN)
d = FPMIN;
c = 1.0 + aa/c;
if (fabs(c) < FPMIN)
c = FPMIN;
d = 1.0/d;
del = d*c;
h *= del;
if (fabs(del-1.0) < EPS) // Are we done?
break;
}
return h;
}

15
RandTest/Gamma.h Executable file
View file

@ -0,0 +1,15 @@
#pragma once
class CGamma
{
public:
double betacf(double a, double b, double x);
double Beta(double z, double a, double b);
double Gamma( double a, double chi2 );
CGamma();
virtual ~CGamma();
protected:
double gcf( double a, double x );
double gamser( double a, double x );
double gammln( double xx );
};

249
RandTest/KolmogorovSmirnov.cpp Executable file
View file

@ -0,0 +1,249 @@
//#include "StdAfx.h"
#include "KolmogorovSmirnov.h"
#include "memory.h"
#include "stdlib.h"
#include "math.h"
#include <float.h>
CKolmogorovSmirnov::CKolmogorovSmirnov()
{
}
///////////////////////////////////////////////////////////////////////////////
// double CKolmogorovSmirnov::ZtoP
//
// Returns: cumulative normal distribution value based on input z-score
// Accuracy better than 1% for zscore<=±7.5; better than 0.05% for zscore=±4
double CKolmogorovSmirnov::ZtoP( double zscore )
{
double retval;
// calculation variables
double w;
double y;
double t;
double num;
double denom;
// calculation constants
double c[8];
c[1] = 2.506628275; c[2] = 0.31938153; c[3] = -0.356563782; c[4] = 1.781477937;
c[5] = -1.821255978; c[6] = 1.330274429; c[7] = 0.2316419;
w = (zscore>=0)? 1 : -1;
y = 1./( 1. + (c[7]*w*zscore) );
t = 1. + (c[7]*w*zscore);
num = w * ( 0.5 - c[2] + ((c[6] + (c[5]*t) + (c[4]*t*t) + (c[3]*t*t*t))/(t*t*t*t)) );
denom = c[1] * pow( 10, pow(0.5*zscore, 2) );
retval = 0.5 + (num/denom);
return retval;
}
///////////////////////////////////////////////////////////////////////////////
// double CKolmogorovSmirnov::PtoZ
//
// Returns: z-score based on input cumulative normal distribution value
// Accuracy better than 0.1% for zscore<=±7.5; 6 digits for zscore=±6
double CKolmogorovSmirnov::PtoZ( double p )
{
double retval = -8.2;
if (p <= DBL_EPSILON)
return retval;
// calculation variables
double pp;
double y;
double num;
double denom;
// calculation constants
double P[5];
P[0] = -0.322232431088; P[1] = -1.0; P[2] = -0.342242088547;
P[3] = -0.0204231210245; P[4] = -0.453642210148e-4;
double q[5];
q[0] = 0.099348462606; q[1] = 0.588581570495; q[2] = 0.531103462366;
q[3] = 0.10353775285; q[4] = 0.38560700634e-2;
pp = (p<0.5)? p : (1.-p);
y = sqrt( log(1./(pp*pp)) );
num = y*(y*(y*(y*P[4]+P[3]) + P[2]) + P[1]) + P[0];
denom = y*(y*(y*(y*q[4]+q[3]) + q[2]) + q[1]) + q[0];
retval = y + (num/denom);
retval = (p<0.5)? -retval : retval;
return retval;
}
void CKolmogorovSmirnov::KSUP( double* pKn_pos, double* pKn_neg, double* U, unsigned long n )
{
unsigned long i; // universal index
double val; // calc value
double* Us = new double[n];
double Kn_pos;
double Kn_neg;
double* cump1 = new double[n+2];
double* cump2 = new double[n+2];
double* kn = new double[n+2];
double max;
double min;
memcpy( (void*)Us, (void*)U, n * sizeof(double) );
qsort( Us, n, sizeof(double), KSUPcompare );
cump1[1] = Us[0];
cump2[1] = 0.;
for ( i=1; i<=n; i++ )
{
cump1[i+1] = Us[i-1];
val = (double)i/n;
cump2[i+1] = val;
}
min = cump2[2] - cump1[2];
max = min;
for ( i=2; i<=(n+1); i++ )
{
kn[i-1] = cump2[i] - cump1[i];
if ( kn[i-1] > max )
{
max = kn[i-1];
}
if ( kn[i-1] < min )
{
min = kn[i-1];
}
}
Kn_pos = sqrt((double)n) * (double)max;
Kn_neg = (-sqrt((double)n)) * ((double)min - (1/(double)n));
*pKn_pos = KSProb( n, Kn_pos );
*pKn_neg = KSProb( n, Kn_neg );
if (Us!=NULL)
{
delete Us;
Us = NULL;
}
if (kn!=NULL)
{
delete kn;
kn = NULL;
}
if (cump1!=NULL)
{
delete cump1;
cump1 = NULL;
}
if (cump2!=NULL)
{
delete cump2;
cump2 = NULL;
}
}
double CKolmogorovSmirnov::KSProb( unsigned long n, double Kn )
{
double retval;
double e;
double las;
unsigned long j;
double cof[7];
cof[1] = 76.18009172947146; cof[2] = -86.50532032941677; cof[3] = 24.01409824083091;
cof[4] = -1.231739572450155; cof[5] = 1.208650973866179e-3; cof[6] = -5.395239384953e-6;
if ( Kn<=0 )
{
retval = 0;
}
else if ( Kn>=sqrt((double)n) )
{
retval = 1;
}
else
{
e = Kn / sqrt((double)n);
las = floor( (double)n - ((double)n*e) );
retval = 0;
for ( j=0; j<=las; j++ )
{
double ee = exp(lnbin(n, j));
double p1 = pow((e+(double)j/(double)n),((double)j-1.));
double p2 = pow((1.0-e-(double)j/(double)n),(double)(n-j));
retval += ee * p1 * p2;
}
retval = 1.-e*retval;
}
return retval;
}
double CKolmogorovSmirnov::lnbin( double n, double k )
{
double retval = 0;
if (k==0)
retval = 0;
else
{
retval = lnf(n) - lnf(k) - lnf(n-k);
}
return retval;
}
double CKolmogorovSmirnov::lnf( double xx )
{
double retval = 0;
double x1 = xx + 1.;
double cof[7];
cof[1] = 76.18009172947146; cof[2] = -86.50532032941677; cof[3] = 24.01409824083091;
cof[4] = -1.231739572450155; cof[5] = 1.208650973866179e-3; cof[6] = -5.395239384953e-6;
if (x1<=1.)
retval = 0;
else
{
double x = x1;
double y = x1;
double tmp = x + 5.5 - (x+.5)*log(x+5.5);
double ser = 1.000000000190015;
for (int j=0; j<=5; j++)
{
y = y+1.;
ser += cof[j+1]/y;
}
retval = log(2.506628274631 * ser/x) - tmp;
}
return retval;
}
int CKolmogorovSmirnov::KSUPcompare( const void* elem1, const void* elem2 )
{
if ((*(double*)elem1)==(*(double*)elem2))
return 0;
if ((*(double*)elem1)>(*(double*)elem2))
return 1;
else
return -1;
}

20
RandTest/KolmogorovSmirnov.h Executable file
View file

@ -0,0 +1,20 @@
#pragma once
#include <math.h>
class CKolmogorovSmirnov
{
public:
CKolmogorovSmirnov();
public:
double ZtoP( double zscore );
double PtoZ( double p );
void KSUP( double* pKn_pos, double* pKn_neg, double* U, unsigned long n );
double lnf( double xx );
double lnbin( double n, double k );
double KSProb( unsigned long n, double Kn );
private:
static int KSUPcompare( const void* elem1, const void* elem2 );
};

73
RandTest/MT19937.cpp Executable file
View file

@ -0,0 +1,73 @@
#include "StdAfx.h"
#include "mt19937.h"
CMT19937::CMT19937()
{
mti = N+1;
mag01[0] = 0;
/* mag01[x] = x * MATRIX_A for x=0,1 */
mag01[1] = MATRIX_A;
}
CMT19937::~CMT19937()
{
}
void CMT19937::SGenRand(uint32_t seed)
{
/* setting initial seeds to mt[N] using */
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
/* Vol. 2 (2nd Ed.), pp102] */
// mt[0]= seed & 0xffffffff;
// for (mti=1; mti<N; mti++)
// mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
mt[0]= seed & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] =
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
uint32_t CMT19937::GenRand()
{
uint32_t y;
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if sgenrand() has not been called, */
SGenRand(5489UL); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
return y;
}

64
RandTest/MT19937.h Executable file
View file

@ -0,0 +1,64 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
class CMT19937
{
public:
uint32_t GenRand();
CMT19937();
virtual ~CMT19937();
void SGenRand(uint32_t seed);
private:
uint32_t mag01[2];
int mti;
uint32_t mt[N];
};
// C++ encapsulated modified from:
//
/* A C-program for MT19937: Integer version */
/* genrand() generates one pseudorandom unsigned integer (32bit) */
/* which is uniformly distributed among 0 to 2^32-1 for each */
/* call. sgenrand(seed) set initial values to the working area */
/* of 624 words. Before genrand(), sgenrand(seed) must be */
/* called once. (seed is any 32-bit integer except for 0). */
/* Coded by Takuji Nishimura, considering the suggestions by */
/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Library General Public */
/* License as published by the Free Software Foundation; either */
/* version 2 of the License, or (at your option) any later */
/* version. */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
/* See the GNU Library General Public License for more details. */
/* You should have received a copy of the GNU Library General */
/* Public License along with this library; if not, write to the */
/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
/* 02111-1307 USA */
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
/* Any feedback is very welcome. For any question, comments, */
/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
/* matumoto@math.keio.ac.jp */

102
RandTest/Monkey.cpp Executable file
View file

@ -0,0 +1,102 @@
//#include "StdAfx.h"
#include "Monkey.h"
#include "math.h"
CMonkey::CMonkey(void)
{
CreateChi2Test();
pow2_32 = pow( 2.0, 32 );
ResetAll();
}
CMonkey::~CMonkey(void)
{
delete MetaChi2;
}
// Submits a 32 bit word for OQSO testing
void CMonkey::InsertWord32(uint32_t InWord32)
{
WordStream >>= 32;
WordStream |= (uint64_t)InWord32 << 32;
// Submit as many overlapped words as possible from wordstream
while ( LetterPointer >= 0 )
{
// Word is 20 bits long, overlapped every 5 bits
CurrentWord = (uint32_t)(WordStream>>LetterPointer);
CurrentWord &= 0x000fffff;
if ( !(MonkeyBitmap.CheckWord( CurrentWord )) )
MissingWords--;
// Test 2097152 words (or 10485775 bits)
WordCount++;
if ( WordCount>=2097152 )
{
// Calc current and cumulative z-scores
totalBlockCount++;
//double UnitZScore = -((double)MissingWords-141909.1945)/294.656;
MetaChi2->Insert(MissingWords);
//ZScoreTotal += UnitZScore;
MissingWordsTotal += (uint64_t)MissingWords;
P_Chi2 = MetaChi2->GetPvalue();
if (totalBlockCount!=0) {
//cumulativeZScore = ZScoreTotal / sqrt(totalBlockCount);
cumulativeZScore = -((double)MissingWordsTotal - (totalBlockCount * 141909.104)) / (sqrt(totalBlockCount) * 294.656);
}
ResetTest();
}
LetterPointer -= 5;
}
LetterPointer += 32;
}
// Resets cumulative and current test
void CMonkey::ResetAll(void)
{
cumulativeZScore = 0;
WordStream = 0;
ZScoreTotal = 0;
MissingWordsTotal = 0;
totalBlockCount = 0.;
LetterPointer = 12;
P_Chi2 = .5;
MetaChi2->Reset();
ResetTest();
}
// Resets current test
void CMonkey::ResetTest(void)
{
MissingWords = 1048576;
MonkeyBitmap.Clearmap();
WordCount = 0;
}
void CMonkey::CreateChi2Test(void) {
double pTable[] = {
0.020035263116770285, 0.04007592896841139, 0.059900259673160094, 0.07990555454845777, 0.09973585094717441, 0.12019013336507156, 0.14037340713890295, 0.16024040737242062, 0.18006661762415743, 0.20040959652731188, 0.22005106263679536, 0.2407529898402695, 0.26025548231499596, 0.2805415527829255, 0.300377215413428, 0.3208231113598671, 0.3405774462690355, 0.36077911411228614, 0.38137696414272143, 0.4009988146079183, 0.4208736799354211, 0.4409523283066323, 0.4611839548890032, 0.4815165669138008, 0.5018973841149283, 0.522273249393845, 0.5425910443898824, 0.5614554567534166, 0.5815124046447061, 0.6026740748901427, 0.6222435463400903, 0.6427760999481655, 0.6616581917860309, 0.6825745983586168, 0.7017433191528237, 0.722654551841068, 0.7428220165027213, 0.7621991815446298, 0.7817526213870567, 0.8022460422705294, 0.8224190682008065, 0.8420653268505389, 0.8617367254552067, 0.8817041720232961, 0.9019201354926609, 0.9214978872400847, 0.9412230272875216, 0.9610265302820049, 0.981060464990248, 1.0
};
double boundaryTable[] = {
141306, 141395, 141452, 141496, 141532, 141564, 141592, 141617, 141640, 141662,
141682, 141702, 141720, 141738, 141755, 141772, 141788, 141804, 141820, 141835,
141850, 141865, 141880, 141895, 141910, 141925, 141940, 141954, 141969, 141985,
142000, 142016, 142031, 142048, 142064, 142082, 142100, 142118, 142137, 142158,
142180, 142203, 142228, 142256, 142288, 142324, 142368, 142426, 142518, 1e100
};
MetaChi2 = new Chi2(50, pTable, true, boundaryTable, false);
}

70
RandTest/Monkey.h Executable file
View file

@ -0,0 +1,70 @@
// OQSO - Overlapping-Quadruples-Sparse-Occupancy test
// Expected values are mean = 141909.47 and standard deviation = 295
// (G. Marsaglia and A. Zaman, Computers Math. Applic.,
// Vol. 26, No. 9, pp 1-10, 1993)
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "MonkeyBitmap.h"
#include "Chi2.hpp"
#include "Gamma.h"
#include "Stat.h"
class CMonkey
{
public:
CMonkey(void);
~CMonkey(void);
// Cumulative z-score
double cumulativeZScore;
// Total number of unit z-scores
double totalBlockCount;
// Cumulative chi^2 results
double P_Chi2;
// Submits a 32 bit word for OQSO testing
void InsertWord32(uint32_t InWord32);
// Resets cumulative and current test
void ResetAll(void);
protected:
// Resets current test
void ResetTest(void);
void CreateChi2Test();
// Keeps track of missing words
CMonkeyBitmap MonkeyBitmap;
// Incomplete Gamma function
CGamma Gamma;
// Chi2 Test
Chi2* MetaChi2;
// Adds ZtoP transformation
CStat Stat;
// Missing word count
uint32_t MissingWords;
// Words (20 bit overlapped) tested
uint32_t WordCount;
// Actual wordstream
uint64_t WordStream;
// Wordstream 5-bit letter pointer
int LetterPointer;
// Current 20-bit word under investigation
uint32_t CurrentWord;
// Sum of unit z-scores
double ZScoreTotal;
uint64_t MissingWordsTotal;
// Stored value of 2^32
double pow2_32;
};

40
RandTest/MonkeyBitmap.cpp Executable file
View file

@ -0,0 +1,40 @@
//#include "StdAfx.h"
#include "MonkeyBitmap.h"
#include <memory.h>
CMonkeyBitmap::CMonkeyBitmap(void)
{
Clearmap();
}
CMonkeyBitmap::~CMonkeyBitmap(void)
{
}
// Sets the entire bit memory map to 0's
void CMonkeyBitmap::Clearmap(void)
{
memset( Word, 0, 131072 );
}
// Check in Bitmap if this word has already been tested, true if tested previously, false otherwise;
bool CMonkeyBitmap::CheckWord(uint32_t Word20Bit)
{
bool bRet = false;
uint32_t Index;
uint32_t BitMask;
// Find the index in an array of 32 bit words
Index = Word20Bit / 32;
// Now find the slot of the remainder
BitMask = 1<<(Word20Bit%32);
// Check if bit-slot already filled
if ( BitMask & Word[Index] )
bRet = true;
// Fill bit-slot for future
Word[Index] |= BitMask;
return bRet;
}

21
RandTest/MonkeyBitmap.h Executable file
View file

@ -0,0 +1,21 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
class CMonkeyBitmap
{
public:
CMonkeyBitmap(void);
~CMonkeyBitmap(void);
// Sets the entire bit memory map to 0's
void Clearmap(void);
// Check in Bitmap if this word has already been used, true if tested previously, false otherwise;
bool CheckWord(uint32_t Word20Bit);
protected:
// Bitmap
uint32_t Word[32768];
};

49
RandTest/QuickLfsrCorrector.hpp Executable file
View file

@ -0,0 +1,49 @@
#pragma once
template <class T>
class QuickLfsrCorrector {
public:
QuickLfsrCorrector() {
T initVal = -1;
T deltaVal = initVal / 11;
for (int i=0; i<15; i++) {
lfsr[i] = initVal;
initVal -= deltaVal;
}
inPointer = 0;
tab3 = initVal;
initVal -= deltaVal;
tab5 = initVal;
initVal -= deltaVal;
tab7 = initVal;
}
T Correct(T inVal) {
inVal ^= tab3 ^ tab5 ^ tab7;
inPointer--;
if (inPointer<0)
inPointer = 14;
lfsr[inPointer] = inVal;
int tabPointer = inPointer + 3;
tabPointer %= 15;
tab3 ^= lfsr[tabPointer];
tabPointer += 5;
tabPointer %= 15;
tab5 ^= lfsr[tabPointer];
tabPointer += 7;
tabPointer %= 15;
tab7 ^= lfsr[tabPointer];
return inVal;
}
private:
T lfsr[15];
T tab3;
T tab5;
T tab7;
int inPointer;
};

21
RandTest/RandTest.h Executable file
View file

@ -0,0 +1,21 @@
#include "Windows.h"
#include "Bias.h"
#include "AutoCorrelation.h"
#include "BiasAndAC.h"
#include "BitCount.h"
#include "Monkey.h"
#include "MonkeyBitMap.h"
#include "Entropy.h"
#include "Serial.h"
#include "Chi2.h"
#include "BinomialChi2.h"
#include "ACBinomialChi2.h"
#include "Stat.h"
#include "Gamma.h"

258
RandTest/Serial.cpp Executable file
View file

@ -0,0 +1,258 @@
//#include "StdAfx.h"
#include "Serial.h"
#include "math.h"
//CRITICAL_SECTION cs;
//FILE* pFile;
//char filename[200];
CSerial::CSerial(void)
{
/*InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
unsigned short num = GetTickCount();
sprintf(filename, "STable_%i.txt", num);
LeaveCriticalSection(&cs);*/
for (int i=0; i<50; i++)
CreateChi2Test();
ResetAll();
P_Chi2 = 0.5;
cumulativeSerialChi2 = 127.3339;
}
CSerial::~CSerial(void)
{
delete MetaChi2;
}
// Inserts a 32 bit word into the serial test
void CSerial::InsertWord32(uint32_t InWord32)
{
wordStream >>= 32;
wordStream |= (uint64_t)InWord32 << 32;
// Shift through each bit to create a sub-word
while ( bitPointer >= 1 )
{
// Take an overlapping 8 and 7 bit word from stream
uint32_t Bit8Word = ((uint32_t)(wordStream>>bitPointer)) & 0x000000ff;
uint32_t Bit7Word = Bit8Word>>1;
// Stuff these words into independent bins for this test block
Bin8[Bit8Word]++;
Bin7[Bit7Word]++;
// Every 8192 words binned do a block and cumulative calc
if ( (++blockWordCount)>=(16*262144) )
{
// Calc chi^2 value for this block
double BlockSerialChi2 = BlockSumBinsSquared8() - BlockSumBinsSquared7();
MetaChi2->Insert(BlockSerialChi2);
// Insert into meta chi^2 test
P_Chi2 = MetaChi2->GetPvalue();
// Calc cumulative chi^2 test
totalBlockCount++;
cumulativeSerialChi2 = QuickCompare8() - QuickCompare7();
ResetTest();
}
bitPointer --;
}
bitPointer = 32;
}
// Resets cumulative testing
void CSerial::ResetAll(void)
{
wordStream = 0;
bitPointer = 24;
cumulativeSerialChi2 = 127.3339;
P_Chi2 = 0.5;
totalBlockCount = 0;
// ZeroMemory(CumulativeBin8, 256*sizeof(double));
memset(CumulativeBin8, 0, 256*sizeof(double));
// ZeroMemory(CumulativeBin7, 128*sizeof(double));
memset(CumulativeBin7, 0, 128*sizeof(double));
MetaChi2->Reset();
ResetTest();
}
// Resets current block test
void CSerial::ResetTest(void)
{
// ZeroMemory(Bin8, 256*sizeof(double));
memset(Bin8, 0, 256*sizeof(double));
// ZeroMemory(Bin7, 128*sizeof(double));
memset(Bin7, 0, 128*sizeof(double));
blockWordCount = 0;
}
// Returns sum of the bis squared for the block of 8bit words
double CSerial::BlockSumBinsSquared8(void)
{
double Sum = 0;
double val;
for (int i=0; i<256; i++)
{
val = Bin8[i] - ((blockWordCount/256.));
Sum += val*val;
}
Sum /= ((blockWordCount/256.));
return Sum;
}
// Returns sum of the bis squared for the block of 7bit words
double CSerial::BlockSumBinsSquared7(void)
{
double Sum = 0;
double val;
for (int i=0; i<128; i++)
{
val = Bin7[i] - ((blockWordCount/128.));
Sum += val*val;
}
Sum /= ((blockWordCount/128.));
return Sum;
}
// Adds new block to cumulative Squared 8bit words
double CSerial::CumulativeBins8(void)
{
double MSBS8 = 0.;
for (int i=0; i<256; i++)
{
CumulativeBin8[i] += Bin8[i];
MSBS8 += CumulativeBin8[i]*CumulativeBin8[i];
}
return MSBS8;
}
// Adds new block to cumulative Squared 7bit words
double CSerial::CumulativeBins7(void)
{
double MSBS7 = 0.;
for (int i=0; i<128; i++)
{
CumulativeBin7[i] += Bin7[i];
MSBS7 += CumulativeBin7[i]*CumulativeBin7[i];
}
return MSBS7;
}
double CSerial::QuickCompare8(void)
{
double Sum = 0;
double val;
for (int i=0; i<256; i++)
{
CumulativeBin8[i] += Bin8[i];
val = (CumulativeBin8[i] / (totalBlockCount * (blockWordCount/256.))) - 2.;
Sum += val * CumulativeBin8[i];
}
Sum += (blockWordCount*totalBlockCount);
Sum = 0;
for (int i=0; i<256; i++)
{
val = CumulativeBin8[i] - ((blockWordCount/256.)*totalBlockCount);
Sum += val*val;
}
Sum /= ((blockWordCount/256.)*totalBlockCount);
return Sum;
}
double CSerial::QuickCompare7(void)
{
double Sum = 0;
double val;
for (int i=0; i<128; i++)
{
CumulativeBin7[i] += Bin7[i];
val = (CumulativeBin7[i] / (totalBlockCount * (blockWordCount/128.))) - 2.;
Sum += val * CumulativeBin7[i];
}
Sum += (blockWordCount*totalBlockCount);
Sum = 0;
for (int i=0; i<128; i++)
{
val = CumulativeBin7[i] - ((blockWordCount/128.)*totalBlockCount);
Sum += val*val;
}
Sum /= ((blockWordCount/128.)*totalBlockCount);
return Sum;
}
double CSerial::QuickCompare88(void)
{
double Sum = 0;
double val;
for (int i=0; i<256; i++)
{
val = (CumulativeBin8[i] / (totalBlockCount * (blockWordCount/256.))) - 2.;
Sum += val * CumulativeBin8[i];
}
Sum += (blockWordCount*totalBlockCount);
return Sum;
}
double CSerial::QuickCompare77(void)
{
double Sum = 0;
double val;
for (int i=0; i<128; i++)
{
val = (CumulativeBin7[i] / (totalBlockCount * (blockWordCount/128.))) - 2.;
Sum += val * CumulativeBin7[i];
}
Sum += (blockWordCount*totalBlockCount);
return Sum;
}
void CSerial::CreateChi2Test(void) {
double pTable[] = {0.019993076,0.019996996,0.020004305,0.020003831,0.019996602,0.020006223,0.020008612,0.019993278,0.020002222,0.020011793,0.019995081,0.020002287,0.019998775,0.020004405,0.019999817,0.020010438,0.019994155,0.020003369,0.020008374,0.019995879,0.020008228,0.019993876,0.020004749,0.020003208,0.019893452,0.020001708,0.020002342,0.020000863,0.020008678,0.020005665,0.020001275,0.02000936,0.020000663,0.019986486,0.020003196,0.020004123,0.020002657,0.020016139,0.019989378,0.020004423,0.019999113,0.019998812,0.020002742,0.020004996,0.020003909,0.019997932,0.020000403,0.020004695,0.019999863,0.020017545};
double boundryTable[] = {
162.960449218750, 157.338134765625, 153.770507812500, 151.080566406250, 148.885253906250,
147.007324218750, 145.352050781250, 143.862548828125, 142.498779296875, 141.234375000000,
140.051757812500, 138.935058593750, 137.873779296875, 136.858642578125, 135.883056640625,
134.940429687500, 134.027099609375, 133.137695312500, 132.268798828125, 131.417968750000,
130.581298828125, 129.757324218750, 128.942626953125, 128.135498046875, 127.337646484375,
126.538574218750, 125.740966796875, 124.942871093750, 124.141845703125, 123.336181640625,
122.523681640625, 121.701416015625, 120.867431640625, 120.019042968750, 119.151611328125,
118.261962890625, 117.345703125000, 116.396728515625, 115.410400390625, 114.376464843750,
113.285400390625, 112.123046875000, 110.870117187500, 109.499511718750, 107.970458984375,
106.216796875000, 104.117187500000, 101.411621093750, 97.322021484375, 0.0
};
MetaChi2 = new Chi2(50, pTable, false, boundryTable, true);
}

73
RandTest/Serial.h Executable file
View file

@ -0,0 +1,73 @@
#pragma once
#pragma warning( disable : 4005 )
#include <stdint.h>
#pragma warning( default : 4005 )
#include "Gamma.h"
#include "Chi2.hpp"
#include "stdio.h"
class CSerial
{
public:
CSerial(void);
~CSerial(void);
// Inserts a 32 bit word into the serial test
void InsertWord32(uint32_t InWord32);
// Resets cumulative testing
void ResetAll(void);
// Resets current block test
void ResetTest(void);
// Serial test cumulative result;
double cumulativeSerialChi2;
// Keeps track of all block in cumulative results
double totalBlockCount;
// Cumulative chi^2 results
double P_Chi2;
protected:
// Wordstream
uint64_t wordStream;
// Pointer to current bit in wordStream
int bitPointer;
// Counts the number of 8/7 bit words binned in this block
uint32_t blockWordCount;
// Binning for 8-bit words
double Bin8[256];
// Binning for 7-bit words
double Bin7[128];
// Cumulative binning for 8-bit words
double CumulativeBin8[256];
// Cumulative binning for 7-bit words
double CumulativeBin7[128];
// Returns sum of the bis squared for the block 8bit words
double BlockSumBinsSquared8(void);
// Returns sum of the bis squared for the block 7bit words
double BlockSumBinsSquared7(void);
// Meta chi^2 test
Chi2* MetaChi2;
void CreateChi2Test();
// Incomplete gamma function
CGamma Gamma;
// Adds new block to cumulative bins 8 bit words
double CumulativeBins8(void);
// Adds new block to cumulative bins 7 bit words
double CumulativeBins7(void);
double QuickCompare8(void);
double QuickCompare7(void);
double QuickCompare88(void);
double QuickCompare77(void);
};

53
RandTest/Stat.cpp Executable file
View file

@ -0,0 +1,53 @@
//#include "StdAfx.h"
#include "Stat.h"
#include "math.h"
CStat::CStat(void)
{
}
CStat::~CStat(void)
{
}
// Input z-score, returns cumulative normal distribution value
// Accuracy better than 1% to z=+/-7.5; .05% to z=+/-4.
double CStat::ZtoP( double zScore )
{
double retval;
// calculation variables
double w;
double y;
double t;
double num;
double denom;
// check
if ( zScore > 8. )
{
zScore = 8.;
}
else
{
if ( zScore < -8. )
zScore = -8.;
}
// calculation constants
double c[8];
c[1] = 2.506628275; c[2] = 0.31938153; c[3] = -0.356563782; c[4] = 1.781477937;
c[5] = -1.821255978; c[6] = 1.330274429; c[7] = 0.2316419;
w = (zScore>=0)? 1 : -1;
t = 1. + (c[7]*w*zScore);
y = 1./t;
num = c[2] + (c[6] + (c[5]*t) + (c[4]*t*t) + (c[3]*t*t*t)) / (t*t*t*t) ;
denom = c[1] * exp( .5*zScore*zScore ) * t;
retval = 0.5 + w * ( .5 - (num/denom) );
return retval;
}

11
RandTest/Stat.h Executable file
View file

@ -0,0 +1,11 @@
#pragma once
class CStat
{
public:
CStat(void);
~CStat(void);
// Calculate a p-value from a z-score
static double ZtoP(double zScore);
};

168
RandTest/Well44497.h Executable file
View file

@ -0,0 +1,168 @@
/* ***************************************************************************** */
/* Copyright: Francois Panneton and Pierre L'Ecuyer, University of Montreal */
/* Makoto Matsumoto, Hiroshima University */
/* Notice: This code can be used freely for personal, academic, */
/* or non-commercial purposes. For commercial purposes, */
/* please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca */
/* A modified "maximally equidistributed" implementations */
/* by Shin Harase, Hiroshima University. */
/* ***************************************************************************** */
#define W 32
#define R 1391
#define DISCARD 15
#define MASKU (0xffffffffU>>(W-DISCARD))
#define MASKL (~MASKU)
#define M1 23
#define M2 481
#define M3 229
#define MAT0POS(t,v) (v^(v>>t))
#define MAT0NEG(t,v) (v^(v<<(-(t))))
#define MAT1(v) v
#define MAT2(a,v) ((v & 1U)?((v>>1)^a):(v>>1))
#define MAT3POS(t,v) (v>>t)
#define MAT3NEG(t,v) (v<<(-(t)))
#define MAT4POS(t,b,v) (v ^ ((v>> t ) & b))
#define MAT4NEG(t,b,v) (v ^ ((v<<(-(t))) & b))
#define MAT5(r,a,ds,dt,v) ((v & dt)?((((v<<r)^(v>>(W-r)))&ds)^a):(((v<<r)^(v>>(W-r)))&ds))
#define MAT7(v) 0
#define V0 STATE[state_i]
#define VM1Over STATE[state_i+M1-R]
#define VM1 STATE[state_i+M1]
#define VM2Over STATE[state_i+M2-R]
#define VM2 STATE[state_i+M2]
#define VM3Over STATE[state_i+M3-R]
#define VM3 STATE[state_i+M3]
#define Vrm1 STATE[state_i-1]
#define Vrm1Under STATE[state_i+R-1]
#define Vrm2 STATE[state_i-2]
#define Vrm2Under STATE[state_i+R-2]
#define newV0 STATE[state_i-1]
#define newV0Under STATE[state_i-1+R]
#define newV1 STATE[state_i]
#define newVRm1 STATE[state_i-2]
#define newVRm1Under STATE[state_i-2+R]
/*output transformation parameter*/
#define newVM2Over STATE[state_i+M2-R+1]
#define newVM2 STATE[state_i+M2+1]
#define BITMASK 0x48000000
static unsigned int STATE[R];
static unsigned int z0,z1,z2;
static int state_i=0;
static unsigned int case_1(void);
static unsigned int case_2(void);
static unsigned int case_3(void);
static unsigned int case_4(void);
static unsigned int case_5(void);
static unsigned int case_6(void);
unsigned int (*WELLRNG44497)(void);
void SeedWELL(unsigned int seed) {
state_i=0;
WELLRNG44497 = case_1;
if (seed == 0U)
seed = 5489U;
STATE[0] = seed & 0xffffffffUL;
// Same generator used to seed Mersenne twister
for (int i=1; i<R; i++)
STATE[i] = (1812433253U * (STATE[i-1] ^ (STATE[i-1] >> 30)) + i);
// mix it up to avoid bias
for (int i=0; i<10000*R; i++)
WELLRNG44497();
}
void InitWELLRNG44497(unsigned int *init ){
int j;
state_i=0;
WELLRNG44497 = case_1;
for(j=0;j<R;j++)
STATE[j]=init[j];
}
unsigned int case_1(void){
// state_i == 0
z0 = (Vrm1Under & MASKL) | (Vrm2Under & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1);
z2 = MAT0NEG(-10,VM2) ^ MAT3NEG(-26,VM3);
newV1 = z1 ^ z2;
newV0Under = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i = R-1;
WELLRNG44497 = case_3;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_2(void){
// state_i == 1
z0 = (Vrm1 & MASKL) | (Vrm2Under & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1);
z2 = MAT0NEG(-10,VM2) ^ MAT3NEG(-26,VM3);
newV1 = z1 ^ z2;
newV0 = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i=0;
WELLRNG44497 = case_1;
return (STATE[state_i] ^ (newVM2 & BITMASK));
}
static unsigned int case_3(void){
// state_i+M1 >= R
z0 = (Vrm1 & MASKL) | (Vrm2 & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1Over);
z2 = MAT0NEG(-10,VM2Over) ^ MAT3NEG(-26,VM3Over);
newV1 = z1 ^ z2;
newV0 = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i--;
if(state_i+M1<R)
WELLRNG44497 = case_4;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_4(void){
// state_i+M3 >= R
z0 = (Vrm1 & MASKL) | (Vrm2 & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1);
z2 = MAT0NEG(-10,VM2Over) ^ MAT3NEG(-26,VM3Over);
newV1 = z1 ^ z2;
newV0 = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i--;
if (state_i+M3 < R)
WELLRNG44497 = case_5;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_5(void){
//state_i+M2 >= R
z0 = (Vrm1 & MASKL) | (Vrm2 & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1);
z2 = MAT0NEG(-10,VM2Over) ^ MAT3NEG(-26,VM3);
newV1 = z1 ^ z2;
newV0 = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i--;
if(state_i+M2 < R)
WELLRNG44497 = case_6;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_6(void){
// 2 <= state_i <= R-M2-1
z0 = (Vrm1 & MASKL) | (Vrm2 & MASKU);
z1 = MAT0NEG(-24,V0) ^ MAT0POS(30,VM1);
z2 = MAT0NEG(-10,VM2) ^ MAT3NEG(-26,VM3);
newV1 = z1 ^ z2;
newV0 = MAT1(z0) ^ MAT0POS(20,z1) ^ MAT5(9,0xb729fcecU,0xfbffffffU,0x00020000U,z2) ^ MAT1(newV1);
state_i--;
if(state_i == 1 )
WELLRNG44497 = case_2;
return (STATE[state_i] ^ (newVM2 & BITMASK));
}

8
RandTest/stdafx.cpp Executable file
View file

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// RandTest.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

11
RandTest/stdafx.h Executable file
View file

@ -0,0 +1,11 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// TODO: reference additional headers your program requires here
#include "RandTest.h"