using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class GAMAFUNCTION //Creating 1st. class
{
public BitArray MakeBitArray(string bitString)
{
int size = 0;
for (int i = 0; i < bitString.Length; ++i)
if (bitString[i] != ' ') ++size;
BitArray result = new BitArray(size);
int k = 0; // ptr into result
for (int i = 0; i < bitString.Length; ++i)
{
if (bitString[i] == ' ') continue;
if (bitString[i] == '1') result[k] = true;
else result[k] = false;
++k;
}
return result;
}
public void ShowBitArray(BitArray bitArray, int blockSize,
int lineSize)
{
for (int i = 0; i < bitArray.Length; ++i)
{
if (i > 0 && i % blockSize == 0) Console.Write(" ");
if (i > 0 && i % lineSize == 0) Console.WriteLine("");
if (bitArray[i] == false) Console.Write("0");
else Console.Write("1");
}
Console.WriteLine("");
}
public double BlockTest(BitArray bitArray, int blockLength)
{
int numBlocks = bitArray.Length / blockLength; // 'N'
double[] proportions = new double[numBlocks];
int k = 0; // ptr into bitArray
for (int block = 0; block < numBlocks; ++block)
{
int countOnes = 0;
for (int i = 0; i < blockLength; ++i)
{
if (bitArray[k++] == true)
++countOnes;
}
proportions[block] = (countOnes * 1.0) / blockLength;
}
double summ = 0.0;
for (int block = 0; block < numBlocks; ++block)
summ = summ + (proportions[block] - 0.5) *
(proportions[block] - 0.5);
double chiSquared = 4 * blockLength * summ; // magic
double a = numBlocks / 2.0;
double x = chiSquared / 2.0;
//gammatest gm = new gammatest();
double pValue = GammaUpper(a, x);
return pValue;
}
public static double GammaUpper(double a, double x)
{
// Incomplete Gamma 'Q' (upper)
if (x < 0.0 || a <= 0.0)
throw new Exception("Bad args in GammaUpper");
if (x < a + 1)
return 1.0 - GammaLowerSer(a, x); // Indirect is faster
else
return GammaUpperCont(a, x);
}
public static double GammaLowerSer(double a, double x)
{
// Incomplete GammaLower (computed by series expansion)
if (x < 0.0)
throw new Exception("x param less than 0.0 in GammaLowerSer");
double gln = LogGamma(a);
double ap = a;
double del = 1.0 / a;
double sum = del;
for (int n = 1; n <= 100; ++n)
{
++ap;
del *= x / ap;
sum += del;
if (Math.Abs(del) < Math.Abs(sum) * 3.0E-7) // Close enough?
return sum * Math.Exp(-x + a * Math.Log(x) - gln);
}
throw new Exception("Unable to compute GammaLowerSer " +
"to desired accuracy");
}
public static double GammaUpperCont(double a, double x)
{
// Incomplete GammaUpper computed by continuing fraction
if (x < 0.0)
throw new Exception("x param less than 0.0 in GammaUpperCont");
double gln = LogGamma(a);
double b = x + 1.0 - a;
double c = 1.0 / 1.0E-30; // Div by close to double.MinValue
double d = 1.0 / b;
double h = d;
for (int i = 1; i <= 100; ++i)
{
double an = -i * (i - a);
b += 2.0;
d = an * d + b;
if (Math.Abs(d) < 1.0E-30) d = 1.0E-30; // Got too small?
c = b + an / c;
if (Math.Abs(c) < 1.0E-30) c = 1.0E-30;
d = 1.0 / d;
double del = d * c;
h *= del;
if (Math.Abs(del - 1.0) < 3.0E-7)
return Math.Exp(-x + a * Math.Log(x) - gln) * h; // Close enough?
}
throw new Exception("Unable to compute GammaUpperCont " +
"to desired accuracy");
}
public static double LogGamma(double x)
{
double[] coef = new double[6] { 76.18009172947146, -86.50532032941677,
24.01409824083091, -1.231739572450155,
0.1208650973866179E-2, -0.5395239384953E-5 };
double LogSqrtTwoPi = 0.91893853320467274178;
double denom = x + 1;
double y = x + 5.5;
double series = 1.000000000190015;
for (int i = 0; i < 6; ++i)
{
series += coef[i] / denom;
denom += 1.0;
}
return (LogSqrtTwoPi + (x + 0.5) * Math.Log(y) -
y + Math.Log(series / x));
}
public double LongestRunOfOnes(int n, BitArray epsilon)
{
double pval, chi2;
//pi[7];
double[] pi = new double[7];
int run, v_n_obs, N, i, j, K, M;
int[] V = new int[7];
int[] nu = new int[7] { 0, 0, 0, 0, 0,0,0 };
if (n < 128)
{
Console.WriteLine("n value is too short\n");
/*fprintf(stats[TEST_LONGEST_RUN], "\t\t\t LONGEST RUNS OF ONES TEST\n");
fprintf(stats[TEST_LONGEST_RUN], "\t\t---------------------------------------------\n");
fprintf(stats[TEST_LONGEST_RUN], "\t\t n=%d is too short\n", n);*/
return 1.6;//take care of this value
}
if (n < 6272)
{
K = 3;
M = 8;
V[0] = 1; V[1] = 2; V[2] = 3; V[3] = 4;
pi[0] = 0.21484375;
pi[1] = 0.3671875;
pi[2] = 0.23046875;
pi[3] = 0.1875;
}
else if (n < 750000)
{
K = 5;
M = 128;
V[0] = 4; V[1] = 5; V[2] = 6; V[3] = 7; V[4] = 8; V[5] = 9;
pi[0] = 0.1174035788;
pi[1] = 0.242955959;
pi[2] = 0.249363483;
pi[3] = 0.17517706;
pi[4] = 0.102701071;
pi[5] = 0.112398847;
}
else
{
K = 6;
M = 10000;
V[0] = 10; V[1] = 11; V[2] = 12; V[3] = 13; V[4] = 14; V[5] = 15; V[6] = 16;
pi[0] = 0.0882;
pi[1] = 0.2092;
pi[2] = 0.2483;
pi[3] = 0.1933;
pi[4] = 0.1208;
pi[5] = 0.0675;
pi[6] = 0.0727;
}
N = n / M;
for (i = 0; i < N; i++)
{
v_n_obs = 0;
run = 0;
for (j = 0; j < M; j++)
{
if (epsilon[i * M + j] == true)
{
run++;
if (run > v_n_obs)
v_n_obs = run;
}
else
run = 0;
}
if (v_n_obs < V[0])
nu[0]++;
for (j = 0; j <= K; j++)
{
if (v_n_obs == V[j])
nu[j]++;
}
if (v_n_obs > V[K])
nu[K]++;
}
chi2 = 0.0;
for (i = 0; i <= K; i++)
chi2 += ((nu[i] - N * pi[i]) * (nu[i] - N * pi[i])) / (N * pi[i]);
pval = GammaUpper((double)(K / 2.0), chi2 / 2.0);
return pval;
}
}
public class Test
{
public static void Main()
{
// your code goes here
GAMAFUNCTION g = new GAMAFUNCTION();
Console.WriteLine("Begin NIST tests of randomness using C# demo\n");
string bitString = "11001100000101010110110001001100111000000000001001 00110101010001000100111101011010000000110101111100 1100111001101101100010110010";
BitArray bitArray = g.MakeBitArray(bitString);
Console.WriteLine("Input sequence to test for randomness: \n");
g.ShowBitArray(bitArray, 4, 52);
Console.WriteLine("Sequence passes NIST frequency test for randomness");
int blockLength = 3;
Console.WriteLine("2. Testing input blocks (block length = " +
blockLength + ")");
double pBlock = g.BlockTest(bitArray, blockLength);
Console.WriteLine("pValue for Block test = " + pBlock.ToString("F4"));
if (pBlock < 0.01)
Console.WriteLine("There is evidence that sequence is NOT random");
else
Console.WriteLine("Sequence passes NIST block test for randomness");
Console.WriteLine("\n Testing for longest run of ones\n");
double pLongest = g.LongestRunOfOnes(128,bitArray);
Console.WriteLine("p vvalue for longest run of one si =" + pLongest);
Console.ReadKey();
}
}
}