/// <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 the sum of all bits in the string after mapping (0->-1, 1->1) double S_n = model.epsilon.GetRange(0, n).Sum(delegate(int i) { return(2 * i - 1); }); //calculate p_value double S_obs = Math.Abs(S_n) / Math.Sqrt(n); double p_value = Cephes.erfc(S_obs / Math.Sqrt(2)); if (printResults) { Report report = new Report("1: Frequency (Monobit) Test"); report.Write("\t\t\t FREQUENCY TEST"); report.Write("\t\t---------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t---------------------------------------------"); report.Write("\t\t(a) The nth partial sum = " + (int)S_n); report.Write("\t\t(b) S_n/n = " + S_n / n); 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) { double pi = (double)model.epsilon.GetRange(0, n).Sum() / (double)n; //number of ones in the binary string / length //prerequisite for test, if not passed test is not applicable if (Math.Abs(pi - 0.5) > (2.0 / Math.Sqrt(n))) { if (printResults) { Report report = new Report("3: Runs Test"); report.Write("\t\t\t\tRUNS TEST"); report.Write("\t\t------------------------------------------"); report.Write("\t\tPI ESTIMATOR CRITERIA NOT MET! PI = " + pi); model.reports.Add(report.title, report); } return(new double[] { 0.0 }); } else { //count number of runs in the binary string (where e(i) = e(i+1) is considered to be a run) int V_obs = 1; for (int i = 1; i < n; i++) { if (model.epsilon[i] != model.epsilon[i - 1]) { V_obs++; } } //calculate p_value double p_value = Cephes.erfc(Math.Abs(V_obs - 2.0 * n * pi * (1 - pi)) / (2.0 * pi * (1 - pi) * Math.Sqrt(2 * n))); if (printResults) { Report report = new Report("3: Runs Test"); report.Write("\t\t\t\tRUNS TEST"); report.Write("\t\t------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t------------------------------------------"); report.Write("\t\t(a) Pi = " + pi); report.Write("\t\t(b) V_n_obs (Total # of runs) = " + (int)V_obs); report.Write("\t\t(c) V_n_obs - 2 n pi (1-pi)", false); report.Write("\t\t 2 sqrt(2n) pi (1-pi)"); report.Write("\t\t------------------------------------------"); if (p_value < 0 || p_value > 1) { report.Write("WARNING: P_VALUE IS OUT OF RANGE."); } 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) { double[] expected_value = { 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 = { 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 K = (int)(n / L - (double)Q); //number of test blocks int p = (int)Math.Pow(2, L); long[] T = new long[p]; //initialization segment for (int i = 1; i <= Q; i++) { long decValue = 0; for (int j = 0; j < L; j++) { decValue += model.epsilon[(i - 1) * L + j] * (long)Math.Pow(2, L - 1 - j); //calculate decimal value of segment } T[decValue] = i; } //test segment double sum = 0; for (int i = Q + 1; i <= Q + K; i++) { long decValue = 0; for (int j = 0; j < L; j++) { decValue += model.epsilon[(i - 1) * L + j] * (long)Math.Pow(2, L - 1 - j); //calculate decimal value of segment } sum += Math.Log(i - T[decValue]) / Math.Log(2); T[decValue] = i; } double phi = (double)(sum / (double)K); //forumla from 2.9.4(5) double c = 0.7 - 0.8 / (double)L + (4 + 32 / (double)L) * Math.Pow(K, -3 / (double)L) / 15; double sigma = c * Math.Sqrt(variance[L] / (double)K); //calculate p_value double arg = Math.Abs(phi - expected_value[L]) / (Math.Sqrt(2) * sigma); double p_value = Cephes.erfc(arg); if (printResults) { Report report = new Report("9: Maurer’s “Universal Statistical” Test"); report.Write("\t\tUNIVERSAL STATISTICAL TEST"); report.Write("\t\t--------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t--------------------------------------------"); report.Write("\t\t(a) L = " + L); report.Write("\t\t(b) Q = " + Q); report.Write("\t\t(c) K = " + K); report.Write("\t\t(d) sum = " + sum); report.Write("\t\t(f) variance = " + variance[L]); report.Write("\t\t(g) exp_value = " + expected_value[L]); report.Write("\t\t(h) phi = " + phi); report.Write("\t\t(i) WARNING: " + (n - (Q + K) * L) + " bits were discarded."); report.Write("\t\t-----------------------------------------"); if (p_value < 0 || p_value > 1) { report.Write("\t\tWARNING: P_VALUE IS OUT OF RANGE"); } 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 unsafe override double[] run(bool printResults) { double[] X = new double[n]; for (int i = 0; i < n; i++) { X[i] = 2 * (int)model.epsilon[i] - 1; //map all bits in binary string (0->-1,1->1) } double[] m = new double[n / 2 + 1]; //generate DFT of the binary string, using the unsafe functions implemented in C fixed(double *wsavePtr = &(new double[2 * n])[0]) { fixed(int *ifacPtr = &(new int[15])[0]) { fixed(double *mPtr = &m[0]) { fixed(double *XPtr = &X[0]) { FFT.__ogg_fdrffti(n, wsavePtr, ifacPtr); //init stage for work arrays FFT.__ogg_fdrfftf(n, XPtr, wsavePtr, ifacPtr); //apply FFT on data } } } } //get magnitude of the DFT produced (to convert complex domain to real domain) m[0] = Math.Sqrt(X[0] * X[0]); for (int i = 0; i < n / 2; i++) { if (2 * i + 2 >= X.Length) { m[i + 1] = Math.Sqrt(Math.Pow(X[2 * i + 1], 2)); } else { m[i + 1] = Math.Sqrt(Math.Pow(X[2 * i + 1], 2) + Math.Pow(X[2 * i + 2], 2)); } } int N_l = 0; double T = Math.Sqrt(2.995732274 * n); //calculate upper bound (T) (the 95% peak height threshold) for (int i = 0; i < n / 2; i++) { if (m[i] < T) { N_l++; //count observed number of peaks in |DFT| greater than T } } double N_0 = 0.95 * n / 2.0; //expected number of peaks double d = (N_l - N_0) / Math.Sqrt(n / 4.0 * 0.95 * 0.05); //calculate p_value double p_value = Cephes.erfc(Math.Abs(d) / Math.Sqrt(2.0)); if (printResults) { Report report = new Report("6: Discrete Fourier Transform (Sprectral) Test"); report.Write("\t\t\t\tFFT TEST"); report.Write("\t\t-------------------------------------------"); report.Write("\t\tCOMPUTATIONAL INFORMATION:"); report.Write("\t\t-------------------------------------------"); report.Write("\t\t(-) Upper Bound= " + T); report.Write("\t\t(b) N_l = " + N_l); report.Write("\t\t(c) N_o = " + N_0); report.Write("\t\t(d) d = " + d); 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 = { -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int J = 0; int[] S = new int[this.n]; //compute partial sums S[0] = 2 * (int)this.model.epsilon[0] - 1; for (int i = 1; i < this.n; i++) { S[i] = S[i - 1] + 2 * this.model.epsilon[i] - 1; if (S[i] == 0) { J++; } } if (S[this.n - 1] != 0) { J++; } Report report = new Report("15: Random Excursions Variant Test"); if (printResults) { report.Write("\t\t\tRANDOM EXCURSIONS VARIANT 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) = " + this.n); } double[] p_values = new double[18]; int constraint = (int)Math.Max(0.005 * Math.Pow(this.n, 0.5), 500); if (J < constraint) { if (printResults) { 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 < 18; i++) { report.Write(0.0.ToString()); } } else { for (int p = 0; p < 18; p++) { int x = stateX[p]; int count = 0; //count occurences of state x for (int i = 0; i < this.n; i++) { if (S[i] == x) { count++; } } //compute p_value p_values[p] = Cephes.erfc(Math.Abs(count - J) / (Math.Sqrt(2.0 * J * (4.0 * Math.Abs(x) - 2)))); if (printResults) { if (p_values[p] < 0 || p_values[p] > 1) { report.Write("\t\t(b) WARNING: P_VALUE IS OUT OF RANGE."); } report.Write(p_values[p] < ALPHA ? "FAILURE" : "SUCCESS" + "\t\t"); report.Write("(x = " + x + ") Total visits = " + count + "; p-value = " + p_values[p]); report.Write(p_values[p].ToString()); } } } if (printResults) { this.model.reports.Add(report.title, report); } return(p_values); }