summaryrefslogtreecommitdiffstats
path: root/nist/packtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'nist/packtest.c')
-rw-r--r--nist/packtest.c2250
1 files changed, 2250 insertions, 0 deletions
diff --git a/nist/packtest.c b/nist/packtest.c
new file mode 100644
index 0000000..9439607
--- /dev/null
+++ b/nist/packtest.c
@@ -0,0 +1,2250 @@
+/* --------------------------------------------------------------------------
+ Title : The NIST Statistical Test Suite
+
+ Date : December 1999
+
+ Programmer : Juan Soto
+
+ Summary : For use in the evaluation of the randomness of bitstreams
+ produced by cryptographic random number generators.
+
+ Package : Version 1.0
+
+ Copyright : (c) 1999 by the National Institute Of Standards & Technology
+
+ History : Version 1.0 by J. Soto, October 1999
+ Revised by J. Soto, November 1999
+
+ Keywords : Pseudorandom Number Generator (PRNG), Randomness, Statistical
+ Tests, Complementary Error functions, Incomplete Gamma
+ Function, Random Walks, Rank, Fast Fourier Transform,
+ Template, Cryptographically Secure PRNG (CSPRNG),
+ Approximate Entropy (ApEn), Secure Hash Algorithm (SHA-1),
+ Blum-Blum-Shub (BBS) CSPRNG, Micali-Schnorr (MS) CSPRNG,
+
+ Source : David Banks, Elaine Barker, James Dray, Allen Heckert,
+ Stefan Leigh, Mark Levenson, James Nechvatal, Andrew Rukhin,
+ Miles Smid, Juan Soto, Mark Vangel, and San Vo.
+
+ Technical
+ Assistance : Lawrence Bassham, Ron Boisvert, James Filliben, Sharon Keller,
+ Daniel Lozier, and Bert Rust.
+
+ Warning : Portability Issues.
+
+ Limitation : Amount of memory allocated for workspace.
+
+ Restrictions: Permission to use, copy, and modify this software without
+ fee is hereby granted, provided that this entire notice is
+ included in all copies of any software which is or includes
+ a copy or modification of this software and in all copies
+ of the supporting documentation for such software.
+ -------------------------------------------------------------------------- */
+
+/* --------------------------------------------------------------------------
+ * Derived by Andre Seznec (IRISA/INRIA - www.irisa.fr/caps) to overcome the
+ * limitations on the sequences size. It should now work on sequences larger
+ * than 1MB and smaller than 256MB.
+ *
+ * Modified on March 2002, last update on June 2002
+ *
+ * Modified Aug 2008 for clean compilation under gcc 4.4
+ * --------------------------------------------------------------------------
+ */
+#ifndef NOIO
+#define IO
+#endif
+#define LinuxorUnix
+#ifdef WIN
+#ifndef CYGWIN
+#undef LinuxorUnix
+/* same libraries are available*/
+#endif
+#endif
+
+#ifdef LinuxorUnix
+
+#define MAX(x,y) ((x) < (y) ? (y) : (x))
+#define MOD(x,y) (((x) % (y)) < 0 ? ((x) % (y)) + (y) : ((x) % (y)))
+
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include "special-functions.h"
+#include "mconf.h"
+#include "matrix.h"
+#include "nist.h"
+
+#define THRESHOLDFAIL 0.001
+static int TotalTEST = 0;
+
+/*
+ * on Windows systems, we encountered difficulties with the memory allocation
+ * libraries, therefor we used our own allocation technique in a big array
+ */
+
+#define BIGSIZE 32768*1024
+char BigArray[BIGSIZE];
+int PtBigArray = 0;
+char *
+MYCALLOC (int n, int S)
+{
+ int i, OldPt;
+ OldPt = PtBigArray;
+ PtBigArray += ((n * S + 16) & 0xfffffff0);
+ if (PtBigArray >= BIGSIZE)
+ {
+ printf ("Pb memory allocation in PackTest\n");
+ exit (1);
+ }
+ for (i = OldPt; i < PtBigArray; i++)
+ BigArray[i] = 0;
+
+ return (&BigArray[OldPt]);
+}
+
+void
+MYFREE (char *X)
+{
+ PtBigArray = (int) (X - BigArray);
+}
+
+BitField **create_matrix (int M, int Q);
+
+FILE *fileout;
+
+int
+PackTestF (int *ARRAY, int ArraySize, char *C)
+{
+ int i;
+ int TEST = 0;
+ int failure = 0;
+
+#ifdef IO
+ fileout = fopen (C, "w");
+#endif
+ if (ArraySize >= (1 << 26))
+ {
+ fprintf (fileout,
+ "This test does not work for an array larger than 256Mbytes\n");
+ return (failure);
+ }
+#ifdef IO
+ {
+ printf
+ ("16 NIST tests to be executed: results will be written in file %s\n\n",
+ C);
+ printf
+ ("To maintain response time in a reasonable range,\nsome of the tests are executed on only subsequences\n\n");
+
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t Frequency test \n\n");
+ fprintf (fileout, " \n\n Frequency test \n\n");
+ }
+#endif
+ for (i = 4; i < ArraySize; i = (i << 1))
+ {
+ int inter;
+ inter = MOD (ARRAY[ArraySize - i], ArraySize - i);
+ if (failure >= 8)
+ {
+#ifdef IO
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+
+ failure += Frequency (i, &ARRAY[inter]);
+ }
+
+ if (failure >= 8)
+ {
+#ifdef IO
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += Frequency (ArraySize, ARRAY);
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t Block Frequency test \n\n");
+ fprintf (fileout, " \n\n Block Frequency test \n\n");
+ }
+#endif
+ for (i = 4; i < ArraySize; i = (i << 1))
+ {
+ int inter;
+ inter = MOD (ARRAY[ArraySize - i], ArraySize - i);
+ failure += BlockFrequency (i, (32 * i / 99), &ARRAY[inter]);
+ }
+
+ if (failure >= 8)
+ {
+#ifdef IO
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += BlockFrequency (ArraySize, (32 * ArraySize / 99), ARRAY);
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t Runs test \n\n");
+ fprintf (fileout, " \n\n Runs test \n\n");
+ }
+#endif
+ for (i = 4; i < ArraySize; i = (i << 1))
+ {
+ int inter;
+ inter = MOD (ARRAY[ArraySize - i], ArraySize - i);
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += Runs (i, &ARRAY[inter]);
+ }
+ Runs (ArraySize, ARRAY);
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t LongestRunOfOnes \n\n");
+ fprintf (fileout, " \n\n LongestRunOfOnes \n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ failure += LongestRunOfOnes (((750000) >> 5) + 1, &ARRAY[index]);
+if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+ }
+
+fclose(fileout);
+return(failure);
+}
+int
+PackTestL (int *ARRAY, int ArraySize, char *C)
+{
+ int i;
+ int TEST = 4;
+ int DATA, pt, PT;
+ int failure = 0;
+
+#ifdef IO
+ fileout = fopen (C, "a");
+#endif
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr,
+ "\t Binary Matrix Rank test on 8 random 38,912 bit slices \n\n");
+ fprintf (fileout,
+ " \n\n Binary Matrix Rank test on 8 random 38,912 bit slices \n\n");
+ }
+#endif
+ if (ArraySize >= (1 << 26))
+ {
+ fprintf (fileout,
+ "This test does not work for an array larger than 256Mbytes\n");
+ return (failure);
+ }
+
+
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ failure += Rank (38192 >> 5, &ARRAY[index]);
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t Discrete Fourier test by slice of 1 Mbits\n\n");
+ fprintf (fileout, " \n\n Discrete Fourier test by slice of 1 Mbits\n\n");
+ fprintf (fileout, " \n\n 8 random slices are picked \n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += DiscreteFourierTransform (32768, &ARRAY[index]);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t NON OVERLAPPING TEMPLATE MATCHING TEST \n");
+ fprintf (fileout, "\n\n\t NON OVERLAPPING TEMPLATE MATCHING TEST \n");
+ fprintf (fileout, "\t 1 random 1Mbit slices \n\n");
+ }
+#endif
+ for (i = 0; i < 1; i++)
+ {
+ int index;
+ index = (ArraySize) * i;
+ if (ArraySize > 262144)
+ index = index + MOD (ARRAY[index], ((ArraySize) - 32768));
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure +=
+ NonOverlappingTemplateMatchings (9, 1024 * 1024, &ARRAY[index]);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t OVERLAPPING TEMPLATE MATCHING TEST \n");
+ fprintf (fileout, "\n\n\t OVERLAPPING TEMPLATE MATCHING TEST \n");
+ fprintf (fileout, "\t 8 random 1000000 bits slices \n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+
+ failure +=
+ OverlappingTemplateMatchings (9, 1000000 >> 5, &ARRAY[index]);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t Maurer's Universal test\n");
+ fprintf (fileout, "\n\n Maurer's Universal test\n");
+ fprintf
+ (fileout,
+ "\n For each of the L parameters, we test the beginning of the sequence\n\n");
+ }
+#endif
+
+ if (failure >= 8)
+ {
+#ifdef IO
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+
+ failure += Universal (ArraySize, ARRAY);
+
+ TEST++;
+#ifdef IO
+ {
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr,
+ "\t LEMPEL-ZIV COMPRESSION TEST: 8 random slices of 1000000 bits\n\n");
+ fprintf (fileout,
+ "\n\n\t LEMPEL-ZIV COMPRESSION TEST: 8 random slices of 1000000 bits\n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ DATA = ARRAY[index];
+ pt = 0;
+ PT = 0;
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure +=
+ LempelZivCompression (1000000, &ARRAY[index], &DATA, &pt, &PT);
+ }
+ if (failure >= 8)
+ {
+/* in order to enable fast detection of strong failure for random sequences*/
+#ifdef IO
+ fprintf (fileout,
+ "%d failed individual tests with THRESHOLD %f on %d individual tests before LINEAR COMPLEXITY TEST\ndon't waste your CPU time\n",
+ failure, THRESHOLDFAIL, TotalTEST);
+ fprintf (stderr,
+ "%d failed individual tests with THRESHOLD %f on %d individual tests before LINEAR COMPLEXITY TEST\ndon't waste your CPU time\n",
+ failure, THRESHOLDFAIL, TotalTEST);
+
+#endif
+ fclose (fileout);
+ return (failure);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr,
+ "\t LINEAR COMPLEXITY TEST: 1 SLICE OF 4731 * 371 bits\n\n");
+ fprintf (fileout,
+ "\n\n\t LINEAR COMPLEXITY TEST: 1 SLICE OF 4731 * 371 bits\n\n");
+ }
+#endif
+
+/* these parameters were chosen arbitraly, NIST recommendation are 500<=M<=5000, N>=200, NM >=1000000*/
+ for (i = 5; i <= 5; i++)
+ {
+ int index, inter;
+ inter = (371 * 4731 + 32) >> 5;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+ if (index + inter > ArraySize)
+ index = ArraySize - inter;
+
+
+ failure += LinearComplexity (4731, 371, &ARRAY[index], 0);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t SERIAL TEST BY SLICE OF 1000000 bits\n\n");
+ fprintf (fileout, "\n\n\t SERIAL TEST BY SLICE OF 1000000 bits\n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += Serial (14, 1000000, &ARRAY[index], 0);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t APPROXIMATE ENTROPY TEST\n\n");
+ fprintf (fileout, "\n\n\t APPROXIMATE ENTROPY TEST\n\n");
+ }
+#endif
+ failure += ApproximateEntropy (3, 17, 32 * ArraySize, ARRAY);
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr, "\t CUSUM TEST\n\n");
+ fprintf (fileout, "\n\n\t CUSUM TEST\n\n");
+ }
+#endif
+ for (i = 4; i < ArraySize; i = (i << 1))
+ {
+ int inter;
+ inter = MOD (ARRAY[ArraySize - i], ArraySize - i);
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += CumulativeSums (32 * i, &ARRAY[inter]);
+ }
+
+ if (failure >= 8)
+ {
+#ifdef IO
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += CumulativeSums (32 * ArraySize, ARRAY);
+
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr,
+ "\t RANDOM EXCURSION TEST: 8 SLICE OF 1000000 bits\n\n");
+ fprintf (fileout,
+ "\n\n\t RANDOM EXCURSION TEST: 8 SLICE OF 1000000 bits\n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += RandomExcursions (1000000, &ARRAY[index >> 5]);
+ }
+#ifdef IO
+ {
+ TEST++;
+ fprintf (stderr, "Test %d, ", TEST);
+ fprintf (stderr,
+ "\t RANDOM EXCURSION TEST VARIANT: 8 SLICES OF 1000000 bits\n\n");
+ fprintf (fileout,
+ "\n\n\t RANDOM EXCURSION TEST VARIANT: 8 SLICES OF 1000000 bits\n\n");
+ }
+#endif
+ for (i = 0; i < 8; i++)
+ {
+ int index;
+ index = (ArraySize / 8) * i;
+ if (ArraySize > 262144)
+ index = index + (MOD (ARRAY[index], (ArraySize / 8) - 32768));
+
+ if (failure >= 8)
+ {
+#ifdef IO
+
+
+ fprintf (stderr,
+ "%d failures at %f threshold,\nsequence should be considered as not random\n",
+ failure, THRESHOLDFAIL);
+
+#endif
+ return (failure);
+ }
+
+ failure += RandomExcursionsVariant (1000000, &ARRAY[index >> 5]);
+ }
+
+
+#ifdef IO
+ {
+ fprintf (stderr,
+ "%d failed individual tests with THRESHOLD %f on %d individual tests\n",
+ failure, THRESHOLDFAIL, TotalTEST);
+ fprintf (fileout,
+ "%d failed individual tests with THRESHOLD %f on %d individual tests\n",
+ failure, THRESHOLDFAIL, TotalTEST);
+ }
+#endif
+ fclose (fileout);
+ return (failure);
+}
+
+#define MAXNUMOFTEMPLATES 148
+int TEMPLATE[MAXNUMOFTEMPLATES];
+int Skip[MAXNUMOFTEMPLATES];
+int nu[6][MAXNUMOFTEMPLATES];
+int Wj[8][MAXNUMOFTEMPLATES];
+int W_obs[MAXNUMOFTEMPLATES];
+/* was adapted to m =9 by A. Seznec 03/04/2002*/
+int
+NonOverlappingTemplateMatchings (int m, int n, int *ARRAY)
+{
+ FILE *fp;
+ double sum, chi2, p_value, lambda;
+ int i, j, k;
+ char directory[FILENAME_MAX];
+ int M, N, K = 5;
+ int fail = 0;
+ double pi[6], varWj;
+ int DATA, PT, pt;
+ N = 8;
+ M = floor (n / N);
+
+
+ lambda = (M - m + 1) / pow (2, m);
+ varWj = M * (1. / pow (2., m) - (2. * m - 1.) / pow (2., 2. * m));
+ sprintf (directory, "%stemplate%d", GetBaseDir(), m);
+ if ((fp = fopen (directory, "r")) == NULL)
+ {
+#ifdef IO
+ {
+ fprintf (fileout, "\tTemplate file %s not existing\n", directory);
+ fprintf (stderr, "\tTemplate file %s not existing\n", directory);
+ }
+#endif
+ exit (1);
+
+ }
+ else
+ {
+
+ sum = 0.0;
+ for (i = 0; i < 2; i++)
+ { /* Compute Probabilities */
+ pi[i] = exp (-lambda + i * log (lambda) - lgam (i + 1));
+ sum += pi[i];
+ }
+ pi[0] = sum;
+ for (i = 2; i <= K; i++)
+ { /* Compute Probabilities */
+ pi[i - 1] = exp (-lambda + i * log (lambda) - lgam (i + 1));
+ sum += pi[i - 1];
+ }
+ pi[K] = 1 - sum;
+ for (i = 0; i < MAXNUMOFTEMPLATES; i++)
+ {
+ int inter;
+ TEMPLATE[i] = 0;
+ for (j = 0; j < m; j++)
+ {
+ if (fscanf (fp, "%d", &inter)<1) inter=0;
+ TEMPLATE[i] += (inter << j);
+ }
+ }
+ DATA = ARRAY[0] & ((1 << m) - 1);
+ pt = 0;
+ PT = m;
+
+ for (i = 0; i < MAXNUMOFTEMPLATES; i++)
+ for (k = 0; k <= K; k++)
+ nu[k][i] = 0;
+
+ for (i = 0; i < N; i++)
+ {
+ for (k = 0; k < MAXNUMOFTEMPLATES; k++)
+ W_obs[k] = 0;
+ for (j = 0; j < M - m + 1; j++)
+ {
+ for (k = 0; k < MAXNUMOFTEMPLATES; k++)
+ {
+ if (Skip[k] == 0)
+ {
+ if (DATA == TEMPLATE[k])
+ {
+ W_obs[k]++;
+ Skip[k] = m - 1;
+ }
+ }
+ else
+ {
+ Skip[k]--;
+ }
+ }
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ }
+ DATA = ((DATA << 1) + ((ARRAY[pt] >> PT) & 1)) & ((1 << m) - 1);
+ }
+/* skipping the final values in the slice*/
+ for (j = M - m + 1; j < M; j++)
+ {
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ }
+ DATA = ((DATA << 1) + ((ARRAY[pt] >> PT) & 1)) & ((1 << m) - 1);
+ }
+
+ for (k = 0; k < MAXNUMOFTEMPLATES; k++)
+ {
+ Wj[i][k] = W_obs[k];
+ }
+ }
+ }
+ for (k = 0; k < MAXNUMOFTEMPLATES; k++)
+ {
+ sum = 0;
+ chi2 = 0.0; /* Compute Chi Square */
+ for (i = 0; i < N; i++)
+ {
+ chi2 += pow (((double) Wj[i][k] - lambda) / pow (varWj, 0.5), 2);
+ }
+ p_value = igamc (N / 2.0, chi2 / 2.0);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+ }
+ fclose (fp);
+ return (fail);
+}
+
+int
+OverlappingTemplateMatchings (int m, int n, int *ARRAY)
+{
+/* A. Seznec 03/03/2002:
+I got some troubles with porting the function from the NIST package:
+computation of array pi did not work satisfactory.
+For m=9, I picked back values from page 34 in NIST report.
+I do not have the values for m=10.
+
+*/
+
+ int i;
+ double sum, chi2;
+ int W_obs;
+ double p_value;
+ int DATA;
+ int M, N, j, K = 5;
+ unsigned int nu[6] = { 0, 0, 0, 0, 0, 0 };
+ int fail = 0;
+ double pi[6] =
+ { 0.367879, 0.183940, 0.137955, 0.099634, 0.069935, 0.140657 };
+
+/* double pi[6] =
+ { 0.143783, 0.139430, 0.137319, 0.124314, 0.106209, 0.348945 };*/
+
+
+ int PT, pt;
+ pt = 0;
+ PT = 0;
+
+ M = 1032;
+/* N = (int) floor (n / M);*/
+ N = 968;
+
+
+/*
+ lambda = (double) (M - m + 1) / pow (2, m);
+ eta = lambda / 2.0;
+ sum = 0.0;
+ for (i = 0; i < K; i++)
+ {
+
+ pi[i] = Pr (i, eta);
+ sum += pi[i];
+ }
+ pi[K] = 1 - sum;*/
+ DATA = ARRAY[0] & ((1 << m) - 1);
+ pt = 0;
+ PT = m;
+ for (i = 0; i < N; i++)
+ {
+ W_obs = 0;
+ for (j = 0; j < M - m + 1; j++)
+ {
+ if (DATA == ((1 << m) - 1))
+ W_obs++;
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ }
+ DATA = ((DATA << 1) + ((ARRAY[pt] >> PT) & 1)) & ((1 << m) - 1);
+ }
+/* skipping the final values in the slice*/
+ for (j = M - m + 1; j < M; j++)
+ {
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ }
+ DATA = ((DATA << 1) + ((ARRAY[pt] >> PT) & 1)) & ((1 << m) - 1);
+ }
+
+ if (W_obs <= 4)
+ nu[W_obs]++;
+ else
+ nu[K]++;
+ }
+
+ sum = 0;
+ chi2 = 0.0; /* Compute Chi Square */
+ for (i = 0; i < K + 1; i++)
+ {
+ chi2 +=
+ pow ((double) nu[i] - ((double) N * pi[i]), 2) / ((double) N * pi[i]);
+ sum += nu[i];
+
+ }
+ p_value = igamc (K / 2., chi2 / 2.);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "m= %d, p_value= %f\n", m, p_value);
+ }
+#endif
+ return (fail);
+}
+
+int
+RandomExcursionsVariant (int n, int *ARRAY)
+{
+ int i, p, J, x, constraint;
+ double p_value;
+ int stateX[18] =
+ { -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ int count;
+ int fail = 0;
+ int *S_k;
+ int pt, PT;
+ if ((S_k = (int *) MYCALLOC (n, sizeof (int))) == NULL)
+ {
+
+ }
+ else
+ {
+ J = 0;
+ S_k[0] = 2 * (ARRAY[0] & 1) - 1;
+ pt = 0;
+ PT = 1;
+ for (i = 1; i < n; i++)
+ {
+ S_k[i] = S_k[i - 1] + 2 * ((ARRAY[pt] >> PT) & 1) - 1;
+ PT++;
+ if (PT == 32)
+ {
+ pt++;
+ PT = 0;
+ }
+ if (S_k[i] == 0)
+ J++;
+ }
+ if (S_k[n - 1] != 0)
+ J++;
+
+ constraint = MAX (0.005 * pow (n, 0.5), 500);
+ if (J < constraint)
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout,
+ "\n\t\tWARNING: TEST NOT APPLICABLE. THERE ARE ");
+ fprintf (fileout, "AN\n\t INSUFFICIENT NUMBER OF CYCLES.\n");
+ fprintf (fileout,
+ "\t\t---------------------------------------------");
+ fprintf (fileout, "\n");
+ }
+#endif
+ }
+
+ else
+ {
+ for (p = 0; p <= 17; p++)
+ {
+ x = stateX[p];
+ count = 0;
+ for (i = 0; i < n; i++)
+ if (S_k[i] == x)
+ count++;
+ p_value =
+ erfc (fabs (count - J) /
+ (sqrt (2. * J * (4. * fabs (x) - 2))));
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f \n", p_value);
+ }
+#endif
+
+ }
+ }
+ }
+#ifdef IO
+ {
+ fprintf (fileout, "\n");
+ }
+#endif
+ MYFREE ((char*)S_k);
+ return (fail);
+}
+
+int
+RandomExcursions (int n, int *ARRAY)
+{
+ int b, i, j, k, J, x;
+ int cycleStart, cycleStop, *cycle, *S_k;
+ int stateX[8] = { -4, -3, -2, -1, 1, 2, 3, 4 };
+ int counter[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int PT, pt;
+ int fail = 0;
+ double p_value, sum, constraint, nu[6][8];
+ double pi[5][6] = {
+ {0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000},
+ {0.5000000000, 0.2500000000, 0.1250000000, 0.06250000000, 0.03125000000, 0.0312500000},
+ {0.7500000000, 0.06250000000, 0.04687500000, 0.03515625000, 0.02636718750, 0.0791015625},
+ {0.8333333333, 0.02777777778, 0.02314814815, 0.01929012346, 0.01607510288, 0.0803755143},
+ {0.8750000000, 0.01562500000, 0.01367187500, 0.01196289063, 0.01046752930, 0.0732727051}
+ };
+
+
+ S_k = (int *) MYCALLOC (n, sizeof (int));
+ cycle = (int *) MYCALLOC (MAX (1000, n / 200), sizeof (int));
+ {
+ J = 0; /* DETERMINE CYCLES */
+
+ S_k[0] = 2 * (ARRAY[0] & 1) - 1;
+ pt = 0;
+ PT = 1;
+ for (i = 1; i < n; i++)
+ {
+ S_k[i] = S_k[i - 1] + 2 * ((ARRAY[pt] >> PT) & 1) - 1;
+ PT++;
+ if (PT == 32)
+ {
+ pt++;
+ PT = 0;
+ }
+ if (S_k[i] == 0)
+ {
+ J++;
+ if (J > MAX (1000, n / 128))
+ {
+#ifdef IO
+ {
+ fprintf
+ (fileout,
+ "ERROR IN FUNCTION randomExcursions: EXCEEDING THE MAX");
+ fprintf (fileout, " NUMBER OF CYCLES EXPECTED\n.");
+ }
+#endif
+ MYFREE ((char*)cycle);
+ MYFREE ((char*)S_k);
+
+ return (fail);
+ }
+ cycle[J] = i;
+ }
+ }
+ if (S_k[n - 1] != 0)
+ {
+ J++;
+
+ }
+
+
+ constraint = MAX (0.005 * pow (n, 0.5), 500);
+ if (J < constraint)
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout,
+ "\t\t---------------------------------------------");
+ fprintf (fileout,
+ "\n\t\tWARNING: TEST NOT APPLICABLE. THERE ARE ");
+ fprintf (fileout, "AN\n\t INSUFFICIENT NUMBER OF CYCLES.\n");
+ fprintf (fileout,
+ "\t\t---------------------------------------------");
+ fprintf (fileout, "\n");
+ }
+#endif
+
+ }
+ else
+ {
+ cycleStart = 0;
+ cycleStop = cycle[1];
+ for (k = 0; k < 6; k++)
+ for (i = 0; i < 8; i++)
+ nu[k][i] = 0.;
+ for (j = 1; j <= J; j++)
+ { /* FOR EACH CYCLE */
+ for (i = 0; i < 8; i++)
+ counter[i] = 0;
+ for (i = cycleStart; i < cycleStop; i++)
+ {
+ if ((S_k[i] >= 1 && S_k[i] <= 4)
+ || (S_k[i] >= -4 && S_k[i] <= -1))
+ {
+ if (S_k[i] < 0)
+ b = 4;
+ else
+ b = 3;
+ counter[S_k[i] + b]++;
+ }
+ }
+ cycleStart = cycle[j] + 1;
+ if (j < J)
+ cycleStop = cycle[j + 1];
+ else
+ cycleStop = n;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (counter[i] >= 0 && counter[i] <= 4)
+ nu[counter[i]][i]++;
+ else if (counter[i] >= 5)
+ nu[5][i]++;
+ }
+ }
+ for (i = 0; i < 8; i++)
+ {
+ x = stateX[i];
+ sum = 0.;
+ for (k = 0; k < 6; k++)
+ {
+ sum += pow (nu[k][i] - J * pi[(int) fabs (x)][k], 2) /
+ (J * pi[(int) fabs (x)][k]);
+ }
+ p_value = igamc (2.5, sum / 2.);
+
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+
+
+
+ }
+ }
+
+#ifdef IO
+ {
+ fprintf (fileout, "\n");
+ }
+#endif
+
+ MYFREE ((char*)cycle);
+ MYFREE ((char*)S_k);
+ }
+ return (fail);
+}
+
+int
+CumulativeSums (int n, int *ARRAY)
+{
+ int i, k, start, finish, mode;
+ double p_value, cusum, sum, sum1, sum2;
+ int z;
+ int pt, PT;
+ int fail = 0;
+ for (mode = 0; mode < 2; mode++)
+ { /* mode = {0,1} => {forward,reverse} */
+ sum = 0.0;
+ cusum = 1.0;
+ if (mode == 0)
+ {
+ pt = 0;
+ PT = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ sum += (double) (2 * ((ARRAY[pt] >> PT) & 1) - 1);
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ }
+ cusum = MAX (cusum, fabs (sum));
+ }
+ }
+ else if (mode == 1)
+ {
+ pt = (n >> 5);
+ PT = 31;
+ for (i = n - 1; i >= 0; i--)
+ {
+ sum += (double) (2 * ((ARRAY[pt] >> PT) & 1) - 1);
+ PT--;
+ if (PT == -1)
+ {
+ PT = 31;
+ pt--;
+ }
+ cusum = MAX (cusum, fabs (sum));
+ }
+ }
+ z = (int) cusum;
+
+ sum1 = 0.0;
+ start = (-n / z + 1) / 4;
+ finish = (n / z - 1) / 4;
+ for (k = start; k <= finish; k++)
+ sum1 +=
+ (normal ((4 * k + 1) * z / sqrt (n)) -
+ normal ((4 * k - 1) * z / sqrt (n)));
+
+ sum2 = 0.0;
+ start = (-n / z - 3) / 4;
+ finish = (n / z - 1) / 4;
+ for (k = start; k <= finish; k++)
+ sum2 +=
+ (normal ((double) ((4 * k + 3) * z) / sqrt ((double) n)) -
+ normal ((double) ((4 * k + 1) * z) / sqrt (n)));
+ p_value = 1.0 - sum1 + sum2;
+ if (mode == 1)
+{ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+
+#ifdef IO
+ {
+ fprintf (fileout, "%d bits sequence, reverse p_value= %f \n", n,
+ p_value);
+ }
+#endif
+ }
+ if (mode == 0){
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+
+#ifdef IO
+ {
+ fprintf (fileout, "%d bits sequence, forward p_value= %f \n", n,
+ p_value);
+ }
+#endif
+}
+ }
+ return (fail);
+
+}
+
+
+
+int
+ApproximateEntropy (int mmin, int mmax, int n, int *ARRAY)
+{
+ int i, blockSize, seqLength;
+ int powLen;
+ double sum, numOfBlocks, ApEn[25], apen, chi_squared, p_value;
+ unsigned int *P[25];
+ int pt, PT, DATA;
+ int fail = 0;
+ int MaskEnt[25] =
+ { 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff,
+ 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
+ 0x1fffff,
+ 0x3fffff, 0x7fffff, 0xffffff
+ };
+
+ seqLength = n - (mmax);
+ numOfBlocks = (double) seqLength;
+ for (blockSize = mmin; blockSize <= mmax; blockSize++)
+ {
+ powLen = (int) pow (2, blockSize + 1);
+ if ((P[blockSize] =
+ (unsigned int *) MYCALLOC (powLen, sizeof (unsigned int))) == NULL)
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout, "ApEn: Insufficient memory available.\n");
+ }
+#endif
+ exit (1);
+ return (fail);
+ }
+ for (i = 0; i < powLen; i++)
+ P[blockSize][i] = 0;
+ }
+
+ for (blockSize = mmin; blockSize <= mmax; blockSize++)
+ {
+ DATA = ARRAY[0];
+ pt = 0;
+ PT = mmax;
+ for (i = 0; i < seqLength; i++)
+ { /* COMPUTE FREQUENCY */
+
+ (P[blockSize][DATA & MaskEnt[blockSize]])++;
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ };
+ DATA = (DATA << 1) + ((ARRAY[pt] >> PT) & 1);
+ }
+ }
+
+ for (blockSize = mmin; blockSize <= mmax; blockSize++)
+ {
+ sum = 0.0;
+
+ for (i = 0; i < (int) pow (2, blockSize); i++)
+ {
+ if (P[blockSize][i] > 0)
+ sum +=
+ (((double) P[blockSize][i]) / (numOfBlocks)) *
+ log ((double) P[blockSize][i] / numOfBlocks);
+ }
+
+ ApEn[blockSize] = sum;
+ }
+ for (blockSize = mmax; blockSize >= mmin; blockSize--)
+ MYFREE ((char*)P[blockSize]);
+
+ for (i = mmin; i < mmax; i++)
+ {
+ apen = ApEn[i] - ApEn[i + 1];
+ chi_squared = 2.0 * ((double) seqLength) * (log (2) - apen);
+ p_value = igamc (pow (2, i - 1), chi_squared / 2.);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "m= %d,\t p_value= %f, Entropy per %d bits %f \n",
+ i, p_value, i, -ApEn[i] / log (2));
+ }
+#endif
+ }
+
+ return (fail);
+}
+
+int
+Serial (int m, int n, int *ARRAY, int PT)
+{
+ double p_value1, p_value2, psim0, psim1, psim2, del1, del2;
+ int fail = 0;
+ psim0 = psi2 (m, n, &ARRAY[PT >> 5], (PT & 31));
+ psim1 = psi2 (m - 1, n, &ARRAY[PT >> 5], (PT & 31));
+ psim2 = psi2 (m - 2, n, &ARRAY[PT >> 5], (PT & 31));
+ del1 = psim0 - psim1;
+ del2 = psim0 - 2.0 * psim1 + psim2;
+ p_value1 = igamc (pow (2, m - 1) / 2, del1 / 2.0);
+ p_value2 = igamc (pow (2, m - 2) / 2, del2 / 2.0);
+
+ if (p_value1 < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value1= %f\n", p_value1);
+ }
+#endif
+ if (p_value1 < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value2= %f\n", p_value2);
+ }
+#endif
+ return (fail);
+}
+
+
+double
+psi2 (int m, int n, int *ARRAY, int PT)
+{
+ int i, j, k;
+ double sum, numOfBlocks;
+ unsigned int *P;
+
+ if ((m == 0) || (m == -1))
+ return 0.0;
+ numOfBlocks = n;
+
+ P = (unsigned int*) MYCALLOC (65536, sizeof (unsigned int));
+ for (i = 0; i < numOfBlocks; i++)
+ { /* COMPUTE FREQUENCY */
+ k = 1;
+ for (j = 0; j < m; j++)
+ {
+
+ if (((ARRAY[(MOD (PT + i + j, n) >> 5)] >>
+ (MOD (PT + i + j, n) & 31)) & 1) == 0)
+ k *= 2;
+ else
+ k = 2 * k + 1;
+ }
+ P[k - 1]++;
+ }
+ sum = 0.0;
+ for (i = (int) pow (2, m) - 1; i < (int) pow (2, m + 1) - 1; i++)
+ sum += pow (P[i], 2);
+ sum = (sum * pow (2, m) / (double) n) - (double) n;
+ MYFREE ((char*)P);
+ return sum;
+}
+
+
+int
+LinearComplexity (int M, int N, int *ARRAY, int PT)
+{
+ int i, ii, j, d;
+ int L, m, N_, parity, sign;
+ double p_value, T_, mean;
+ int fail = 0;
+ int K = 6;
+ double pi[7] =
+ { 0.01047, 0.03125, 0.12500, 0.50000, 0.25000, 0.06250, 0.020833 };
+ double nu[7], chi2;
+ int *T, *P, *B_, *C;
+
+ B_ = (int *) MYCALLOC (M, sizeof (int));
+ C = (int *) MYCALLOC (M, sizeof (int));
+ P = (int *) MYCALLOC (M, sizeof (int));
+ T = (int *) MYCALLOC (M, sizeof (int));
+
+ for (i = 0; i < K + 1; i++)
+ nu[i] = 0.00;
+ for (ii = 0; ii < N; ii++)
+ {
+ for (i = 0; i < M; i++)
+ {
+ B_[i] = 0;
+ C[i] = 0;
+ T[i] = 0;
+ P[i] = 0;
+ }
+ L = 0;
+ m = -1;
+ d = 0;
+ C[0] = 1;
+ B_[0] = 1;
+ /* DETERMINE LINEAR COMPLEXITY */
+ N_ = 0;
+
+ while (N_ < M)
+ {
+ d =
+ ((ARRAY[(ii * M + N_ + PT) >> 5]) >>
+ ((ii * M + N_ + PT) & 31)) & 1;
+
+ for (i = 1; i <= L; i++)
+
+ d +=
+ (C[i] &
+ (((ARRAY[(ii * M + N_ - i + PT) >> 5]) >>
+ ((ii * M + N_ - i + PT) & 31)) & 1));
+ d = d & 1;
+ if (d == 1)
+ {
+ for (i = 0; i < M; i++)
+ {
+ T[i] = C[i];
+ P[i] = 0;
+ }
+ for (j = 0; j < M; j++)
+ if (B_[j] == 1)
+ P[j + N_ - m] = 1;
+ for (i = 0; i < M; i++)
+ C[i] = (C[i] + P[i]) & 1;
+ if (L <= N_ / 2)
+ {
+ L = N_ + 1 - L;
+ m = N_;
+ for (i = 0; i < M; i++)
+ B_[i] = T[i];
+ }
+ }
+ N_++;
+ }
+ if ((parity = (M + 1) % 2) == 0)
+ sign = -1;
+ else
+ sign = 1;
+ mean =
+ M / 2. + (9. + sign) / 36. - 1. / pow (2, M) * (M / 3. + 2. / 9.);
+ if ((parity = M % 2) == 0)
+ sign = 1;
+ else
+ sign = -1;
+ T_ = sign * (L - mean) + 2. / 9.;
+
+ if (T_ <= -2.5)
+ nu[0]++;
+ else if (T_ > -2.5 && T_ <= -1.5)
+ nu[1]++;
+ else if (T_ > -1.5 && T_ <= -0.5)
+ nu[2]++;
+ else if (T_ > -0.5 && T_ <= 0.5)
+ nu[3]++;
+ else if (T_ > 0.5 && T_ <= 1.5)
+ nu[4]++;
+ else if (T_ > 1.5 && T_ <= 2.5)
+ nu[5]++;
+ else
+ nu[6]++;
+
+
+ }
+ chi2 = 0.00;
+ for (i = 0; i < K + 1; i++)
+ chi2 += pow (nu[i] - N * pi[i], 2) / (N * pi[i]);
+ p_value = igamc (K / 2.0, chi2 / 2.0);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+
+ MYFREE ((char*)B_);
+ return (fail);
+}
+
+
+int
+LempelZivCompression (int n, int *ARRAY, int *DATA, int *pt, int *PT)
+{
+ int W; /* Number of words */
+ int i, j, k, prev_I, powLen, max_len;
+ int done = 0;
+ double p_value, mean=0.0, variance=0.0;
+ BitField *P;
+ int fail = 0;
+ W = 0;
+ k = (int) log (n) / log (2) + 6;
+ powLen = pow (2, k);
+
+ if ((P = (BitField *) MYCALLOC (powLen, sizeof (BitField))) == NULL)
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout, "\t\tLempel-Ziv Compression has been aborted,\n");
+ fprintf (fileout, "\t\tdue to insufficient workspace!\n");
+ }
+#endif
+ }
+ else
+ {
+ for (i = 0; i < powLen; i++)
+ P[i].b = 0;
+ i = 0;
+ max_len = 0;
+ while (i <= n - 1)
+ {
+ done = 0;
+ j = 1;
+ prev_I = i;
+ while (!done)
+ {
+ if (2 * j + 1 <= powLen)
+ {
+ if ((*DATA & 1) == 0)
+ {
+ if (P[2 * j].b == 1)
+ {
+ j *= 2;
+ }
+ else
+ {
+ P[2 * j].b = 1;
+ done = 1;
+ }
+ }
+ else
+ {
+ if (P[2 * j + 1].b == 1)
+ {
+ j = 2 * j + 1;
+ }
+ else
+ {
+ P[2 * j + 1].b = 1;
+ done = 1;
+ }
+ }
+ (*PT)++;
+ if (*PT == 32)
+ {
+ (*pt)++;
+ *DATA = ARRAY[*pt];
+ *PT = 0;
+ }
+ else
+ *DATA = *DATA >> 1;
+ i++;
+ if (i > n - 1)
+ {
+ done = 1;
+ }
+ if (done)
+ {
+ W++;
+ max_len = MAX (max_len, i - prev_I);
+ }
+ }
+ else
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout,
+ "\t\tWARNING: Segmentation Violation Imminent.");
+ fprintf (fileout,
+ "\n\t Lempel-Ziv Compression Terminated.\n");
+ fprintf (fileout,
+ "\t\t-----------------------------------------\n");
+ fflush (fileout);
+ }
+#endif
+ done = 1;
+ i = n;
+ }
+ }
+ }
+ }
+ switch (n)
+ {
+ case 100000:
+ mean = 8782.500000;
+ variance = 11.589744;
+ break;
+ case 200000:
+ mean = 16292.1000;
+ variance = 21.4632;
+ break;
+ case 400000:
+ mean = 30361.9500;
+ variance = 58.7868;
+ break;
+ case 600000:
+ mean = 43787.5000;
+ variance = 70.1579;
+ break;
+ case 800000:
+ mean = 56821.9500;
+ variance = 67.4184;
+ break;
+ case 1000000: /* Updated Mean and Variance 10/26/99 */
+ mean = 69588.20190000;
+ variance = 73.23726011;
+ /* Previous Mean and Variance
+ mean = 69586.250000;
+ variance = 70.448718;
+ */
+ break;
+ default:
+ break;
+ }
+ p_value = 0.5 * erfc ((mean - W) / pow (2.0 * variance, 0.5));
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+ MYFREE ((char*)P);
+ return (fail);
+}
+
+
+int
+DiscreteFourierTransform (int N, int *ARRAY)
+{
+ double p_value, upperBound, *m, *X;
+ int i, count;
+ double N_l, N_o, d;
+ double *wsave;
+ int n, j, J, *ifac;
+ int fail = 0;
+ n = 32 * N;
+ X = (double *) MYCALLOC (n, sizeof (double));
+ wsave = (double *) MYCALLOC (2 * n + 15, sizeof (double));
+ ifac = (int *) MYCALLOC (15, sizeof (double));
+ m = (double *) MYCALLOC (n / 2 + 1, sizeof (double));
+ {
+ J = 0;
+ for (i = 0; i < N; i++)
+ for (j = 0; j < 32; j++)
+ {
+ X[J] = (2 * ((ARRAY[i] >> j) & 1)) - 1;
+ J++;
+ }
+ __ogg_fdrffti (n, wsave, ifac); /* INITIALIZE WORK ARRAYS */
+ __ogg_fdrfftf (n, X, wsave, ifac); /* APPLY FORWARD FFT */
+
+ m[0] = sqrt (X[0] * X[0]); /* COMPUTE MAGNITUDE */
+
+
+ for (i = 0; i < n / 2; i++)
+ { /* DISPLAY FOURIER POINTS */
+ m[i + 1] = sqrt (pow (X[2 * i + 1], 2) + pow (X[2 * i + 2], 2));
+ }
+ count = 0; /* CONFIDENCE INTERVAL */
+ upperBound = sqrt (3 * n);
+ for (i = 0; i < n / 2; i++)
+ if (m[i] < upperBound)
+ count++;
+ N_l = (double) count; /* number of peaks less than h = sqrt(3*n) */
+ N_o = (double) 0.95 *n / 2.;
+ d = (N_l - N_o) / sqrt (n / 2. * 0.95 * 0.05);
+ p_value = erfc (fabs (d) / sqrt (2.));
+
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+ }
+ MYFREE ((char*)m);
+ MYFREE ((char*)ifac);
+ MYFREE ((char*)wsave);
+ MYFREE ((char*)X);
+ return (fail);
+}
+
+int
+LongestRunOfOnes (int n, int *ARRAY)
+{
+ double p_value, sum, chi2;
+ int N, i, j;
+ int run, v_n_obs;
+ int fail = 0;
+/* since we are not interested in short sequences we used only 10000*/
+
+
+ double pi[7] = { 0.0882, 0.2092, 0.2483, 0.1933, 0.1208, 0.0675, 0.0727 };
+ double K = 6;
+ unsigned int nu[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ int M = 10000;
+ int PT;
+ int pt;
+ int DATA;
+ pt = 0;
+ PT = 0;
+ DATA = ARRAY[0];
+ N = (int) floor ((32 * n) / M);
+ for (i = 0; i < N; i++)
+ {
+ v_n_obs = 0;
+ run = 0;
+ for (j = i * M; j < (i + 1) * M; j++)
+ {
+ if (DATA & 1)
+ {
+ run++;
+ v_n_obs = MAX (v_n_obs, run);
+ }
+ else
+ run = 0;
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ DATA = ARRAY[pt];
+ }
+ else
+ DATA = DATA >> 1;
+ }
+ if (v_n_obs <= 10)
+ nu[0]++;
+ else if (v_n_obs == 11)
+ nu[1]++;
+ else if (v_n_obs == 12)
+ nu[2]++;
+ else if (v_n_obs == 13)
+ nu[3]++;
+ else if (v_n_obs == 14)
+ nu[4]++;
+ else if (v_n_obs == 15)
+ nu[5]++;
+ else if (v_n_obs >= 16)
+ nu[6]++;
+ }
+ chi2 = 0.0; /* Compute Chi Square */
+ sum = 0;
+ for (i = 0; i < ((int) K) + 1; i++)
+ {
+ chi2 +=
+ pow ((double) nu[i] - ((double) N * pi[i]), 2) / ((double) N * pi[i]);
+ sum += nu[i];
+ }
+ p_value = igamc (K / 2., chi2 / 2.);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+ return (fail);
+}
+
+int
+Runs (int n, int *ARRAY)
+{
+ int i, j;
+ double argument, pi, V_n_obs, tau;
+ double p_value, product;
+ int SUM;
+ double N;
+ int fail = 0;
+ int V_N_obs;
+ N = (double) (32 * (n - 1) + 1);
+
+ SUM = 0;
+ for (i = 0; i < n - 1; i++)
+ for (j = 0; j < 32; j++)
+ {
+ SUM += (ARRAY[i] >> j) & 1;
+ }
+ SUM += (ARRAY[n] & 1);
+
+ pi = ((double) SUM) / N;
+ tau = 2.0 / sqrt (N);
+
+ if (fabs (pi - 0.5) < tau)
+ {
+ V_N_obs = 0;
+ for (i = 0; i < n - 1; i++)
+ {
+ for (j = 0; j < 31; j++)
+ V_N_obs += (((ARRAY[i] >> j) ^ (ARRAY[i] >> (j + 1))) & 1);
+ V_N_obs += ((ARRAY[i] >> 31) ^ (ARRAY[i + 1])) & 1;
+ }
+
+ V_N_obs++;
+ V_n_obs = (double) V_N_obs;
+ product = pi * (1.e0 - pi);
+ argument =
+ fabs (V_n_obs -
+ 2.e0 * N * product) / (2.e0 * sqrt (2.e0 * N) * product);
+ p_value = erfc (argument);
+ }
+ else
+ {
+ p_value = 0.0;
+ }
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value=%f\n", p_value);
+ }
+#endif
+ return (fail);
+}
+
+int
+Frequency (int n, int *ARRAY)
+{
+ int i, j;
+ double f, s_obs, p_value;
+ double sqrt2 = 1.41421356237309504880;
+ int SUM;
+ int fail = 0;
+ SUM = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ for (j = 0; j < 32; j++)
+ SUM += (2 * ((ARRAY[i] >> j) & 1)) - 1;
+ }
+ s_obs = fabs ((double) SUM) / sqrt (32.0 * ((double) n));
+ f = s_obs / sqrt2;
+ p_value = erfc (f);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "%d bits sequence, p_value= %f\n", 32 * n, p_value);
+ }
+#endif
+ return (fail);
+}
+
+int
+BlockFrequency (int ArraySize, int m, int *ARRAY)
+{
+ int i, j, N, n;
+ double arg1, arg2, p_value;
+ double sum, pi, v, chi_squared;
+ int BlockSum;
+ int PT;
+ int pt;
+ int DATA;
+ int fail = 0;
+ n = ArraySize * 32;
+ pt = 0;
+ PT = 0;
+ DATA = ARRAY[0];
+ N = (int) floor ((double) n / (double) m);
+ sum = 0.0;
+ for (i = 0; i < N; i++)
+ {
+ pi = 0.0;
+ BlockSum = 0;
+ for (j = 0; j < m; j++)
+ {
+ BlockSum += (DATA & 1);
+ PT++;
+ if (PT == 32)
+ {
+ PT = 0;
+ pt++;
+ DATA = ARRAY[pt];
+ }
+ else
+ DATA = DATA >> 1;
+ }
+
+ pi = (double) BlockSum / (double) m;
+ v = pi - 0.5;
+ sum += v * v;
+ }
+ chi_squared = 4.0 * m * sum;
+ arg1 = (double) N / 2.e0;
+ arg2 = chi_squared / 2.e0;
+ p_value = igamc (arg1, arg2);
+
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, " %d bits sequence, p_value= %f\n", n, p_value);
+ }
+#endif
+ return (fail);
+}
+
+
+
+
+
+
+int SizeMin[18] =
+ { 0, 0, 0, 0, 0, 0, 387840, 904960, 2068480, 4654080, 10342400, 22753280,
+ 49643520, 107560960, 231669760, 496435200, 1059061760, 0x7fffffff
+};
+
+
+int
+Universal (int n, int *ARRAY)
+{
+ int I, param;
+ int fail = 0;
+ if (32 * n < SizeMin[6])
+ {
+
+#ifdef IO
+ {
+ fprintf (fileout, "Too small\n");
+ }
+#endif
+ return (fail);
+ }
+ I = 6;
+ while ((32 * n >= SizeMin[I]) & (I < 17))
+ {
+ if (32 * n >= SizeMin[I + 1])
+ param = SizeMin[I + 1] - 1;
+ else
+ param = 32 * n;
+ fail += UNIVERSAL (param, ARRAY);
+ I++;
+ }
+ return (fail);
+}
+
+
+
+
+int
+UNIVERSAL (int n, int *ARRAY)
+{
+ int i, j, p, K, L, Q;
+ double arg, sqrt2, sigma, phi, sum, p_value, c;
+ long *T, decRep;
+ double expected_value[17] = {
+ 0, 0, 0, 0, 0, 0, 5.2177052, 6.1962507, 7.1836656,
+ 8.1764248, 9.1723243, 10.170032, 11.168765,
+ 12.168070, 13.167693, 14.167488, 15.167379
+ };
+ double variance[17] = {
+ 0, 0, 0, 0, 0, 0, 2.954, 3.125, 3.238, 3.311, 3.356, 3.384,
+ 3.401, 3.410, 3.416, 3.419, 3.421
+ };
+ int PT, DATA, pt;
+ int fail = 0;
+ double Pow[20];
+ double POW;
+ if (n >= 387840)
+ L = 6;
+ if (n >= 904960)
+ L = 7;
+ if (n >= 2068480)
+ L = 8;
+ if (n >= 4654080)
+ L = 9;
+ if (n >= 10342400)
+ L = 10;
+ if (n >= 22753280)
+ L = 11;
+ if (n >= 49643520)
+ L = 12;
+ if (n >= 107560960)
+ L = 13;
+ if (n >= 231669760)
+ L = 14;
+ if (n >= 496435200)
+ L = 15;
+ if (n >= 1059061760)
+ L = 16;
+ PT = 0;
+ pt = 0;
+ DATA = ARRAY[pt];
+ POW = pow (2, L);
+ for (i = 0; i <= L; i++)
+ Pow[i] = pow (2, i);
+ Q = (int) 10 *POW;
+ K = (int) (floor (n / L) - (double) Q);
+ c =
+ 0.7 - 0.8 / (double) L + (4 + 32 / (double) L) * pow (K,
+ -3 /
+ (double) L) / 15;
+ sigma = c * sqrt (variance[L] / (double) K);
+ sqrt2 = sqrt (2);
+ sum = 0.0;
+ p = (int) pow (2, L);
+ T = (long *) MYCALLOC (p, sizeof (long));
+ for (i = 0; i < p; i++)
+ T[i] = 0;
+ for (i = 1; i <= Q; i++)
+ {
+ decRep = 0;
+ for (j = 0; j < L; j++)
+ {
+ decRep += (DATA & 1) * Pow[L - 1 - j];
+ PT++;
+ if (PT == 32)
+ {
+ pt++;
+ DATA = ARRAY[pt];
+ PT = 0;
+ }
+ else
+ DATA = DATA >> 1;
+ }
+ T[decRep] = i;
+ }
+ for (i = Q + 1; i <= Q + K; i++)
+ {
+ decRep = 0;
+ for (j = 0; j < L; j++)
+ {
+ decRep += (DATA & 1) * Pow[L - 1 - j];
+ PT++;
+ if (PT == 32)
+ {
+ pt++;
+ DATA = ARRAY[pt];
+ PT = 0;
+ }
+ else
+ DATA = DATA >> 1;
+ }
+ sum += log (i - T[decRep]) / log (2);
+ T[decRep] = i;
+ }
+ phi = (double) (sum / (double) K);
+ arg = fabs (phi - expected_value[L]) / (sqrt2 * sigma);
+ p_value = erfc (arg);
+ MYFREE ((char*)T);
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "L= %d\tp_value %f\texp_value= %f\tphi = %f\n", L,
+ p_value, expected_value[L], phi);
+ }
+#endif
+ return (fail);
+}
+
+
+BitField **
+create_matrix (int M, int Q)
+{
+ int i;
+ BitField **matrix;
+
+ if ((matrix = (BitField **) MYCALLOC (M, sizeof (BitField *))) == NULL)
+ {
+ printf
+ ("ERROR IN FUNCTION create_matrix: Insufficient memory available.");
+ printf ("\n");
+ fprintf (stderr,
+ "CREATE_MATRIX: Insufficient memory for %dx%d matrix.\n", M,
+ M);
+ return matrix;
+ }
+ else
+ {
+ for (i = 0; i < M; i++)
+ {
+ if ((matrix[i] = (BitField *)MYCALLOC (Q, sizeof (BitField))) == NULL)
+ {
+ fprintf (stderr,
+ "CREATE_MATRIX: Insufficient memory for %dx%d ", M,
+ M);
+ fprintf (stderr, "matrix.\n");
+ printf
+ ("ERROR IN FUNCTION create_matrix: Insufficient memory for ");
+ printf ("%dx%d matrix.\n", M, M);
+ return NULL;
+ }
+ }
+ return matrix;
+ }
+}
+
+
+int
+Rank (int n, int *ARRAY)
+{
+ int N = (int) floor (n / (32)); /* NUMBER OF MATRICES */
+ int r;
+ double p_value, product;
+ int i, k;
+ double chi_squared, arg1;
+ double p_32, p_31, p_30; /* PROBABILITIES */
+ double R; /* RANK */
+ double F_32, F_31, F_30; /* FREQUENCIES */
+ BitField **matrix = create_matrix (32, 32);
+ int pt, PT, DATA;
+ int fail = 0;
+ pt = 0;
+ PT = 0;
+ DATA = ARRAY[0];
+ r = 32; /* COMPUTE PROBABILITIES */
+ product = 1;
+ for (i = 0; i <= r - 1; i++)
+ product *=
+ ((1.e0 - pow (2, i - 32)) * (1.e0 - pow (2, i - 32))) / (1.e0 -
+ pow (2,
+ i - r));
+ p_32 = pow (2, r * (32 + 32 - r) - 32 * 32) * product;
+
+ r = 31;
+ product = 1;
+ for (i = 0; i <= r - 1; i++)
+ product *=
+ ((1.e0 - pow (2, i - 32)) * (1.e0 - pow (2, i - 32))) / (1.e0 -
+ pow (2,
+ i - r));
+ p_31 = pow (2, r * (32 + 32 - r) - 32 * 32) * product;
+
+ p_30 = 1 - (p_32 + p_31);
+
+ F_32 = 0;
+ F_31 = 0;
+ for (k = 0; k < N; k++)
+ { /* FOR EACH 32x32 MATRIX */
+ def_matrix (32, 32, matrix, k, &pt, &PT, &DATA, ARRAY);
+ R = computeRank (32, 32, matrix);
+ if (R == 32)
+ F_32++; /* DETERMINE FREQUENCIES */
+ if (R == 31)
+ F_31++;
+ }
+ F_30 = (double) N - (F_32 + F_31);
+
+ chi_squared = (pow (F_32 - N * p_32, 2) / (double) (N * p_32) +
+ pow (F_31 - N * p_31, 2) / (double) (N * p_31) +
+ pow (F_30 - N * p_30, 2) / (double) (N * p_30));
+
+ arg1 = -chi_squared / 2.e0;
+
+ p_value = exp (arg1);
+
+ MYFREE ((char*)matrix);
+
+ if (p_value < THRESHOLDFAIL)
+ fail++;
+ else
+ TotalTEST++;
+#ifdef IO
+ {
+ fprintf (fileout, "p_value= %f\n", p_value);
+ }
+#endif
+ return (fail);
+}
+#else
+#include <stdio.h>
+int
+PackTestF (int *ARRAY, int ArraySize, char *C)
+{
+ fprintf (stderr,
+ "Sorry, on-line analysis is implemented using the CygWin math libraries,\nyou must recompile the application under the CygWin environment to allow online analysis\n");
+}
+int
+PackTestL (int *ARRAY, int ArraySize, char *C)
+{
+ fprintf (stderr,
+ "Sorry, on-line analysis is implemented using the CygWin math libraries,\nyou must recompile the application under the CygWin environment to allow online analysis\n");
+}
+#endif