/// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            //calculate all psi_squares
            double psim0 = this.psi2(this.m, this.n);
            double psim1 = this.psi2(this.m - 1, this.n);
            double psim2 = this.psi2(this.m - 2, this.n);
            double del1  = psim0 - psim1;
            double del2  = psim0 - 2.0 * psim1 + psim2;

            //calculate p_values
            double p_value1 = Cephes.igamc(Math.Pow(2, this.m - 1) / 2, del1 / 2.0);
            double p_value2 = Cephes.igamc(Math.Pow(2, this.m - 2) / 2, del2 / 2.0);

            if (printResults)
            {
                Report report = new Report("11: Serial Test");
                report.Write("\t\t\t       SERIAL TEST");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\t COMPUTATIONAL INFORMATION:		  ");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\t(a) Block length    (m) = " + this.m);
                report.Write("\t\t(b) Sequence length (n) = " + this.n);
                report.Write("\t\t(c) Psi_m               = " + psim0);
                report.Write("\t\t(d) Psi_m-1             = " + psim1);
                report.Write("\t\t(e) Psi_m-2             = " + psim2);
                report.Write("\t\t(f) Del_1               = " + del1);
                report.Write("\t\t(g) Del_2               = " + del2);
                report.Write("\t\t---------------------------------------------\n");
                report.Write(p_value1 < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value1 = " + p_value1);
                report.Write(p_value2 < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value2 = " + p_value2);
                this.model.reports.Add(report.title, report);
            }

            return(new double[] { p_value1, p_value2 });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            int N = n / M;      //number of blocks that can be made from the binary string

            //for each block calculate the proportion of ones
            double sum = 0.0;

            for (int i = 0; i < N; i++)
            {
                double pi = (double)model.epsilon.GetRange(i * M, M).Sum() / (double)M;   //sum of bits in block / length of the block
                sum += Math.Pow((pi - 0.5), 2);
            }

            //calculate p_value
            double chi_squared = 4.0 * M * sum;
            double p_value     = Cephes.igamc(N / 2.0, chi_squared / 2.0);

            if (printResults)
            {
                Report report = new Report("2: Frequency Test within a Block");
                report.Write("\t\t\tBLOCK FREQUENCY TEST");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\t(a) Chi^2           = " + chi_squared);
                report.Write("\t\t(b) # of substrings = " + N);
                report.Write("\t\t(c) block length    = " + M);
                report.Write("\t\t(d) Note: " + n % M + " bits were discarded.");
                report.Write("\t\t---------------------------------------------");
                report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value);
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
Example #3
0
        private double[] run(int[] B, bool printResults)
        {
            if (n > model.epsilon.Count || n <= 0)
            {
                throw new ArgumentException("The value of n must be smaller than the size of the input data, and be greater than 0", "Frequency n");
            }

            int[] Wj = new int[N];

            for (int i = 0; i < N; i++)                    //for each start position
            {
                for (int j = 0; j < M - B.Length + 1; j++) //is there a match for the template
                {
                    bool match = true;
                    for (int k = 0; k < B.Length; k++)
                    {
                        if ((int)B[k] != (int)model.epsilon[i * M + j + k])
                        {
                            match = false;
                            break;
                        }
                    }
                    if (match)
                    {
                        Wj[i]++;    //if there was a match, record it
                    }
                }
            }

            //calculate p_value
            double chi2 = 0.0;

            for (int i = 0; i < N; i++)
            {
                chi2 += Math.Pow(((double)Wj[i] - mu) / Math.Pow(sigma, 0.5), 2);
            }
            double p_value = Cephes.igamc(N / 2.0, chi2 / 2.0);

            if (printResults)
            {
                Report report = new Report("7: Non-overlapping Template Matching Test");
                report.Write("chi^2   = " + chi2);
                report.Write("p_value = " + p_value);
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
Example #4
0
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            double[] pi     = new double[6];
            double   lambda = (double)(M - this.B.Length + 1) / Math.Pow(2, this.B.Length);
            double   eta    = lambda / 2.0;
            double   total  = 0.0;

            for (int i = 0; i < K; i++)
            { //compute prior probabilities
                pi[i]  = this.probability(i, eta);
                total += pi[i];
            }
            pi[K] = 1 - total;

            int[] v = new int[K + 1];
            for (int i = 0; i < N; i++)
            {   //search for a match of the template in each block
                int count = 0;
                for (int j = 0; j < M - this.B.Length + 1; j++)
                {
                    bool match = true;
                    for (int k = 0; k < this.B.Length; k++)
                    {
                        if (this.B[k] != this.model.epsilon[i * M + j + k])
                        {
                            match = false;
                        }
                    }
                    if (match)
                    {
                        count++;
                    }
                }
                if (count < K)
                {   //record the matches found
                    v[count]++;
                }
                else
                {
                    v[K]++;
                }
            }

            //compute p_value
            double sum        = 0.0;
            double chiSquared = 0.0;

            for (int i = 0; i < K + 1; i++)
            {
                chiSquared += Math.Pow((double)v[i] - (double)N * pi[i], 2) / ((double)N * pi[i]);
                sum        += v[i];
            }

            double p_value = Cephes.igamc(5.0 / 2.0, chiSquared / 2.0);

            if (printResults)
            {
                Report report = new Report("8: Overlapping Template Matching Test");
                report.Write("\t\t    OVERLAPPING TEMPLATE OF ALL ONES TEST");
                report.Write("\t\t-----------------------------------------------");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:");
                report.Write("\t\t-----------------------------------------------");
                report.Write("\t\t(a) n (sequence_length)      = " + this.n);
                report.Write("\t\t(b) m (block length of 1s)   = " + this.B.Length);
                report.Write("\t\t(c) M (length of substring)  = " + M);
                report.Write("\t\t(d) N (number of substrings) = " + N);
                report.Write("\t\t(e) lambda [(M-m+1)/2^m]     = " + lambda);
                report.Write("\t\t(f) eta                      = " + eta);
                report.Write("\t\t(g) Chi^2                    = " + chiSquared);
                report.Write("\t\t(h) P-value                  = " + p_value);
                report.Write("\t\t-----------------------------------------------");
                report.Write("\t\t   F R E Q U E N C Y");
                report.Write("\t\t", false);
                for (int i = 0; i < K; i++)
                {
                    report.Write("   " + i + " ");
                }
                report.Write("  >=" + K);
                report.Write("\t\t-----------------------------------------------");
                report.Write("\t\t", false);
                for (int i = 0; i < K + 1; i++)
                {
                    report.Write(" " + v[i] + " ");
                }
                if (p_value < 0 || p_value > 1)
                {
                    report.Write("WARNING:  P_VALUE IS OUT OF RANGE.");
                }
                report.Write(p_value + " " + (p_value < ALPHA ? "FAILURE" : "SUCCESS"));
                this.model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            double[] Pm      = new double[3];
            int      r       = Math.Min(M, Q);  //compute predicted probabilities
            double   product = 1;

            for (int i = 0; i <= r - 1; i++)
            {
                product *= ((1.0 - Math.Pow(2, i - Q)) * (1.0 - Math.Pow(2, i - M))) / (1.0 - Math.Pow(2, i - r));
            }
            Pm[0] = Math.Pow(2, r * (M + Q - r) - M * Q) * product;
            r--;
            product = 1;
            for (int i = 0; i <= r - 1; i++)
            {
                product *= ((1.0 - Math.Pow(2, i - Q)) * (1.0 - Math.Pow(2, i - M))) / (1.0 - Math.Pow(2, i - r));
            }
            Pm[1] = Math.Pow(2, r * (M + Q - r) - M * Q) * product;
            Pm[2] = 1 - (Pm[0] + Pm[1]);

            int N = n / (M * Q); //number of blocks

            int[] Fm = new int[3];
            for (int k = 0; k < N; k++)
            {
                //construct the matrix of MxQ in size
                int[,] matrix = new int[M, Q];
                for (int i = 0; i < M; i++)
                {
                    for (int j = 0; j < Q; j++)
                    {
                        matrix[i, j] = model.epsilon[k * (M * Q) + j + i * M];
                    }
                }

                int R = computeRank(M, Q, matrix); //get the rank of the matrix

                if (R == M)
                {
                    Fm[0]++;    //full rank
                }
                else if (R == M - 1)
                {
                    Fm[1]++;    //full rank - 1
                }
            }
            Fm[2] = N - (Fm[0] + Fm[1]); //full rank - 2

            //compute p_value
            double chi_squared = (Math.Pow(Fm[0] - N * Pm[0], 2) / (double)(N * Pm[0]) +
                                  Math.Pow(Fm[1] - N * Pm[1], 2) / (double)(N * Pm[1]) +
                                  Math.Pow(Fm[2] - N * Pm[2], 2) / (double)(N * Pm[2]));
            double p_value = Cephes.igamc(1, chi_squared / 2.0);

            if (printResults)
            {
                Report report = new Report("2.5 Binary Matrix Rank Test");
                report.Write("\t\t\t\tRANK TEST");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:");
                report.Write("\t\t---------------------------------------------");
                report.Write("\t\t(a) Probability P_" + M + " = " + Pm[0]);
                report.Write("\t\t(b)             P_" + (M - 1) + " = " + Pm[1]);
                report.Write("\t\t(c)             P_" + (M - 2) + " = " + Pm[2]);
                report.Write("\t\t(d) Frequency   F_" + M + " = " + Fm[0]);
                report.Write("\t\t(e)             F_" + (M - 1) + " = " + Fm[1]);
                report.Write("\t\t(f)             F_" + (M - 2) + " = " + Fm[2]);
                report.Write("\t\t(g) # of matrices    = " + N);
                report.Write("\t\t(h) Chi^2            = " + chi_squared);
                report.Write("\t\t(i) NOTE: " + n % (M * Q) + " BITS WERE DISCARDED.");
                report.Write("\t\t---------------------------------------------");
                report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value);
                if (p_value < 0 || p_value > 1)
                {
                    report.Write("WARNING:  P_VALUE IS OUT OF RANGE.");
                }
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            double[] pi;
            int      K, M, V0;

            init(out K, out M, out V0, out pi);  //initialize variables to sensible values

            int[] V = new int[pi.Length];
            int   N = n / M;  //number of blocks that can be made from the binary string

            for (int i = 0; i < N; i++)
            {
                //count the longest run of ones in each block
                int longestRun = 0;
                int currentRun = 0;
                for (int j = 0; j < M; j++)
                {
                    if (model.epsilon[i * M + j] == 1)
                    {
                        longestRun = Math.Max(longestRun, ++currentRun);
                    }
                    else
                    {
                        currentRun = 0;
                    }
                }
                //record the longest run of ones found in the correct counter
                if (longestRun < V0)
                {
                    V[0]++;
                }
                else if (longestRun > V0 + K)
                {
                    V[K]++;
                }
                else
                {
                    V[longestRun - V0]++;
                }
            }

            //calculate p_value
            double chi_squared = 0.0;

            for (int i = 0; i <= K; i++)
            {
                chi_squared += ((V[i] - N * pi[i]) * (V[i] - N * pi[i])) / (N * pi[i]);
            }
            double p_value = Cephes.igamc((double)(K / 2.0), chi_squared / 2.0);

            if (printResults)
            {
                Report report = new Report("4: Test for the Longest Run of Ones in a Block");
                report.Write("\t\t\t  LONGEST RUNS OF ONES TEST\n");
                report.Write("\t\t---------------------------------------------\n");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:\n");
                report.Write("\t\t---------------------------------------------\n");
                report.Write("\t\t(a) N (# of substrings)  = " + N);
                report.Write("\t\t(b) M (Substring Length) = " + M);
                report.Write("\t\t(c) Chi^2                = " + chi_squared);
                report.Write("\t\t---------------------------------------------\n");
                report.Write("\t\t      F R E Q U E N C Y\n");
                report.Write("\t\t---------------------------------------------\n");
                if (K == 3)
                {
                    report.Write("\t\t  <=1     2     3    >=4   P-value  Assignment");
                    report.Write("\t\t " + V[0] + " " + V[1] + " " + V[2] + " " + V[3]);
                }
                else if (K == 5)
                {
                    report.Write("\t\t<=4  5  6  7  8  >=9 P-value  Assignment");
                    report.Write("\t\t " + V[0] + " " + V[1] + " " + V[2] + " " + V[3] + " " + V[4] + " " + V[5]);
                }
                else
                {
                    report.Write("\t\t<=10  11  12  13  14  15 >=16 P-value  Assignment");
                    report.Write("\t\t " + V[0] + " " + V[1] + " " + V[2] + " " + V[3] + " " + V[4] + " " + V[5] + " " + V[6]);
                }
                if (p_value < 0 || p_value > 1)
                {
                    report.Write("WARNING:  P_VALUE IS OUT OF RANGE.\n");
                }
                report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "{0}\t\tp_value = " + p_value);
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            double[] pi = { 0.01047, 0.03125, 0.12500, 0.50000, 0.25000, 0.06250, 0.020833 };

            int N = n / M;    //number of blocks

            double mu = M / 2.0 + (9.0 + Math.Pow(-1, M + 1)) / 36.0 - 1.0 / Math.Pow(2, M) * (M / 3.0 + 2.0 / 9.0);

            double[] v = new double[K + 1];

            for (int i = 0; i < N; i++)
            {
                int[] T = new int[M];   //initialize the work arrays
                int[] P = new int[M];
                int[] C = new int[M];
                int[] B = new int[M];

                int L = 0;
                int m = -1;
                int d = 0;
                C[0] = 1;
                B[0] = 1;

                //calculate the linear complexity of the block
                int blockPos = 0;
                while (blockPos < M)
                {
                    d = (int)model.epsilon[i * M + blockPos];
                    for (int j = 1; j <= L; j++)
                    {
                        d += C[j] * model.epsilon[i * M + blockPos - j];
                    }
                    d = d % 2;
                    if (d == 1)
                    {
                        for (int j = 0; j < M; j++)
                        {
                            T[j] = C[j];
                            P[j] = 0;
                        }
                        for (int j = 0; j < M; j++)
                        {
                            if (B[j] == 1)
                            {
                                P[j + blockPos - m] = 1;
                            }
                        }
                        for (int j = 0; j < M; j++)
                        {
                            C[j] = (C[j] + P[j]) % 2;
                        }
                        if (L <= blockPos / 2)
                        {
                            L = blockPos + 1 - L;
                            m = blockPos;
                            for (int j = 0; j < M; j++)
                            {
                                B[j] = T[j];
                            }
                        }
                    }
                    blockPos++;
                }

                double Ti = Math.Pow(-1, M) * (L - mu) + 2.0 / 9.0;

                //record result of complexity test
                if (Ti <= -2.5)
                {
                    v[0]++;
                }
                else if (Ti > -2.5 && Ti <= -1.5)
                {
                    v[1]++;
                }
                else if (Ti > -1.5 && Ti <= -0.5)
                {
                    v[2]++;
                }
                else if (Ti > -0.5 && Ti <= 0.5)
                {
                    v[3]++;
                }
                else if (Ti > 0.5 && Ti <= 1.5)
                {
                    v[4]++;
                }
                else if (Ti > 1.5 && Ti <= 2.5)
                {
                    v[5]++;
                }
                else
                {
                    v[6]++;
                }
            }

            //calculate p_value
            double chi_squared = 0;

            for (int i = 0; i < K + 1; i++)
            {
                chi_squared += Math.Pow(v[i] - N * pi[i], 2) / (N * pi[i]);
            }
            double p_value = Cephes.igamc(K / 2.0, chi_squared / 2.0);

            if (printResults)
            {
                Report report = new Report("10: Linear Complexity Test");
                report.Write("-----------------------------------------------------");
                report.Write("\tL I N E A R  C O M P L E X I T Y");
                report.Write("-----------------------------------------------------");
                report.Write("\tM (substring length)     = {0}" + M);
                report.Write("\tN (number of substrings) = {0}" + N);
                report.Write("-----------------------------------------------------");
                report.Write("        F R E Q U E N C Y                            ");
                report.Write("-----------------------------------------------------");
                report.Write("  C0   C1   C2   C3   C4   C5   C6    CHI2    P-value");
                report.Write("-----------------------------------------------------");
                report.Write("\tNote: " + n % M + " bits were discarded!");
                for (int i = 0; i < K + 1; i++)
                {
                    report.Write(((int)v[i]).ToString(), false);
                }
                report.Write("");
                report.Write(p_value < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tp_value = " + p_value);
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            int r = 0;

            double[] apEn = new double[2];
            for (int blockSize = m; blockSize <= m + 1; blockSize++)
            {
                if (blockSize == 0)
                {
                    apEn[0] = 0;
                    r++;
                }
                else
                {
                    int[] P = new int[(int)Math.Pow(2, blockSize + 1) - 1];

                    for (int i = 1; i < Math.Pow(2, blockSize + 1) - 1; i++)
                    {
                        P[i] = 0;
                    }
                    //calculate frequency of n overlapping blocks
                    for (int i = 0; i < n; i++)
                    {
                        int k = 1;
                        for (int j = 0; j < blockSize; j++)
                        {
                            k *= 2;
                            if ((int)model.epsilon[(i + j) % n] == 1)
                            {
                                k++;
                            }
                        }
                        P[k - 1]++;
                    }
                    //calculate approximate entropy entry from frequency
                    double sum   = 0;
                    int    index = (int)Math.Pow(2, blockSize) - 1;
                    for (int i = 0; i < (int)Math.Pow(2, blockSize); i++)
                    {
                        if (P[index] > 0)
                        {
                            sum += P[index] * Math.Log(P[index] / (double)n);
                        }
                        index++;
                    }
                    apEn[r] = sum / n;
                    r++;
                }
            }
            double approximateEntropy = apEn[0] - apEn[1];

            //calculate p_value
            double chi_squared = 2.0 * n * (Math.Log(2) - approximateEntropy);
            double p_value     = Cephes.igamc(Math.Pow(2, m - 1), chi_squared / 2.0);

            if (printResults)
            {
                Report report = new Report("12: Approximate Entropy Test");
                report.Write("\t\t\tAPPROXIMATE ENTROPY TEST");
                report.Write("\t\t--------------------------------------------");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:");
                report.Write("\t\t--------------------------------------------");
                report.Write("\t\t(a) m (block length)    = " + m);
                report.Write("\t\t(b) n (sequence length) = " + n);
                report.Write("\t\t(c) Chi^2               = " + chi_squared);
                report.Write("\t\t(d) Phi(m)	          = "+ apEn[0]);
                report.Write("\t\t(e) Phi(m+1)	          = "+ apEn[1]);
                report.Write("\t\t(f) ApEn                = " + approximateEntropy);
                report.Write("\t\t--------------------------------------------");
                if (m > (int)(Math.Log(n) / Math.Log(2) - 5))
                {
                    report.Write("\t\tNote: The blockSize = " + m + " exceeds recommended value of " +
                                 Math.Max(1, (int)(Math.Log(n) / Math.Log(2) - 5)));
                    report.Write("\t\tResults are inaccurate!");
                    report.Write("\t\t--------------------------------------------");
                }
                report.Write((p_value < ALPHA ? "FAILURE" : "SUCCESS") + "\t\tp_value = " + p_value);
                model.reports.Add(report.title, report);
            }

            return(new double[] { p_value });
        }
        /// <summary>
        /// Runs the test
        /// </summary>
        /// <param name="printResults">If true text output will be added to a log, otherwise not</param>
        /// <returns>The p_value(s) of the test based upon the input data</returns>
        public override double[] run(bool printResults)
        {
            int[] stateX = { -4, -3, -2, -1, 1, 2, 3, 4 };

            double[,] pi = { { 0.0000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.00000000000, 0.0000000000 },
                             { 0.5000000000, 0.25000000000, 0.12500000000, 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 } };

            Report report = new Report("14: Random Excursions Test");

            //determine cycles
            int J = 0;

            int[] S_k = new int[n];
            S_k[0] = 2 * (int)model.epsilon[0] - 1;
            int[] cycle = new int[Math.Max(1000, n / 100)];
            for (int i = 1; i < n; i++)
            {
                S_k[i] = S_k[i - 1] + 2 * model.epsilon[i] - 1;
                if (S_k[i] == 0)
                {
                    J++;
                    if (J > Math.Max(1000, n / 100))
                    {
                        if (printResults)
                        {
                            report.Write("ERROR IN FUNCTION randomExcursions:  EXCEEDING THE MAX NUMBER OF CYCLES EXPECTED.");
                        }
                        return(null);
                    }
                    cycle[J] = i;
                }
            }
            if (S_k[n - 1] != 0)
            {
                J++;
            }
            cycle[J] = n;

            if (printResults)
            {
                report.Write("\t\t\t  RANDOM EXCURSIONS TEST");
                report.Write("\t\t--------------------------------------------");
                report.Write("\t\tCOMPUTATIONAL INFORMATION:");
                report.Write("\t\t--------------------------------------------");
                report.Write("\t\t(a) Number Of Cycles (J) = " + J);
                report.Write("\t\t(b) Sequence Length (n)  = " + n);
            }

            double constraint = Math.Max(0.005 * Math.Pow(n, 0.5), 500);

            double[] p_values = new double[8];
            if (J < constraint)
            {
                if (printResults)
                {
                    report.Write("\t\t---------------------------------------------");
                    report.Write("\t\tWARNING:  TEST NOT APPLICABLE.  THERE ARE AN");
                    report.Write("\t\t\t  INSUFFICIENT NUMBER OF CYCLES.");
                    report.Write("\t\t---------------------------------------------");
                    for (int i = 0; i < 8; i++)
                    {
                        report.Write(0.0.ToString());
                    }
                }
            }
            else
            {
                if (printResults)
                {
                    report.Write("\t\t(c) Rejection Constraint = " + constraint);
                    report.Write("\t\t-------------------------------------------");
                }

                double[,] v = new double[6, 8];
                int cycleStart = 0;
                int cycleStop  = cycle[1];
                for (int k = 0; k < 6; k++)
                {
                    for (int i = 0; i < 8; i++)
                    {
                        v[k, i] = 0.0;
                    }
                }
                int[] counter = new int[8];
                //for each cycle compute frequency of x
                for (int j = 1; j <= J; j++)
                {
                    for (int i = 0; i < 8; i++)
                    {
                        counter[i] = 0;
                    }
                    for (int i = cycleStart; i < cycleStop; i++)
                    {
                        if ((S_k[i] >= 1 && S_k[i] <= 4) || (S_k[i] >= -4 && S_k[i] <= -1))
                        {
                            int b = S_k[i] < 0 ? 4 : 3;
                            counter[S_k[i] + b]++;
                        }
                    }
                    cycleStart = cycle[j] + 1;
                    if (j < J)
                    {
                        cycleStop = cycle[j + 1];
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        if ((counter[i] >= 0) && (counter[i] <= 4))
                        {
                            v[counter[i], i]++;
                        }
                        else if (counter[i] >= 5)
                        {
                            v[5, i]++;
                        }
                    }
                }

                //calculate p_values
                for (int i = 0; i < 8; i++)
                {
                    int    x   = stateX[i];
                    double sum = 0;
                    for (int k = 0; k < 6; k++)
                    {
                        sum += Math.Pow(v[k, i] - J * pi[(int)Math.Abs(x), k], 2) / (J * pi[(int)Math.Abs(x), k]);
                    }
                    p_values[i] = Cephes.igamc(2.5, sum / 2.0);

                    if (printResults)
                    {
                        if (p_values[i] < 0 || p_values[i] > 1)
                        {
                            report.Write("WARNING:  P_VALUE IS OUT OF RANGE.");
                        }

                        report.Write(p_values[i] < ALPHA ? "FAILURE" : "SUCCESS" + "\t\tx = " + x + " chi^2 = " + sum + " p_value = " + p_values[i]);
                    }
                }
            }
            if (printResults)
            {
                model.reports.Add(report.title, report);
            }
            return(p_values);
        }