diff options
Diffstat (limited to 'nist/packtest.c')
-rw-r--r-- | nist/packtest.c | 2250 |
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 |