using System;
using System.Linq;
class Program {
static uint lfsr(uint s, int n, int[] t) {
uint b = 0;
foreach (int p in t) if (p != n) b ^= (s >> (p - 1)) & 1;
return (s >> 1) | (b << (n - 1));
}
static bool g(bool a, bool b, bool c) => (a & b) ^ (a & c) ^ (b & c);
static void Main() {
var r1 = 1U; var r2 = 1U; var r3 = 0xAAAAAAAAU;
int n = 1000000;
bool[] s = new bool[n];
for (int i = 0; i < n; i++) {
r1 = lfsr(r1, 16, new[]{16,5,3,2,0});
r2 = lfsr(r2, 8, new[]{8,4,3,2,0});
r3 = lfsr(r3, 32, new[]{32,7,6,2,0});
s[i] = g((r1 & 1)==1, (r2 & 1)==1, (r3 & 1)==1);
}
// Тест 1: частотный
int n0 = s.Count(x => !x), n1 = n - n0;
double x1 = (n0 - n1) * (n0 - n1) / (double)n;
Console.WriteLine("1: " + (x1 <= 3.8415 ? "OK" : "FAIL") + " X1=" + x1);
// Тест 2: серии
int n00=0,n01=0,n10=0,n11=0;
for (int i=0;i<n-1;i++) {
if (!s[i]&&!s[i+1]) n00++; else if(!s[i]&&s[i+1]) n01++;
else if(s[i]&&!s[i+1]) n10++; else if(s[i]&&s[i+1]) n11++;
}
double x2 = 4.0/(n-1)*(n00*n00+n01*n01+n10*n10+n11*n11) - 2.0/n*(n0*n0+n1*n1) + 1;
Console.WriteLine("2: " + (x2 <= 5.9915 ? "OK" : "FAIL") + " X2=" + x2);
// Тест 3: обобщенный (m=3)
int m=3, k=n/m; int[] c=new int[8];
for(int i=0;i<k;i++){ int idx=0; for(int j=0;j<m;j++) idx=(idx<<1)|(s[i*m+j]?1:0); c[idx]++; }
double x3 = 8.0/k * c.Sum(x=>x*x) - k;
Console.WriteLine("3: " + (x3 <= 14.0671 ? "OK" : "FAIL") + " X3=" + x3);
// Тест 4: последовательности
double x4=0; int K=4;
for(int i=1;i<=K;i++){ double e=(n-i+3)/Math.Pow(2,i+2); int b=0,g=0,l=0;
for(int j=0;j<n;j++){ if(s[j]) l++; else { if(l==i) b++; l=0; } } if(l==i) b++;
l=0; for(int j=0;j<n;j++){ if(!s[j]) l++; else { if(l==i) g++; l=0; } } if(l==i) g++;
x4 += (b-e)*(b-e)/e + (g-e)*(g-e)/e;
}
Console.WriteLine("4: " + (x4 <= 9.4877 ? "OK" : "FAIL") + " X4=" + x4);
// Тест 5: автокорреляция
int d=n/4, A=0; for(int i=0;i<n-d;i++) if(s[i]!=s[i+d]) A++;
double x5 = 2*(A - (n-d)/2.0)/Math.Sqrt(n-d);
Console.WriteLine("5: " + (Math.Abs(x5) <= 1.96 ? "OK" : "FAIL") + " X5=" + x5);
}
}