/* chi-square checker for sampled byte streams + k64 bias counter */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
int main(int argc,char**argv){
    FILE*f=fopen(argv[1],"rb"); if(!f){perror("open");return 1;}
    static unsigned long long freq[256];
    static unsigned long long dig[65536];
    uint8_t buf[1<<20]; unsigned prev=0; unsigned long long n=0;
    size_t r;
    if (argc>2 && !strcmp(argv[2],"k64")) {
        uint64_t w[8192]; unsigned long long top=0,b3=0,cnt=0;
        while((r=fread(w,8,sizeof(w),f))>0){
            for(size_t i=0;i<r;i++){
                if(((w[i]>>32)&0xffffffffULL)==0xffffffffULL) top++;
                if(((w[i]>>24)&0xff)>=0x80) b3++;
                cnt++;
            }
        }
        printf("k64 words=%llu top32==0xffffffff: %llu (%.6f) byte3>=0x80: %llu (%.6f)\n",
            cnt,top,(double)top/cnt,b3,(double)b3/cnt);
        return 0;
    }
    while((r=fread(buf,1,sizeof(buf),f))>0){
        for(size_t i=0;i<r;i++){freq[buf[i]]++;dig[(prev<<8)|buf[i]]++;prev=buf[i];n++;}
    }
    double e=(double)n/256.0,x2=0;
    for(int i=0;i<256;i++){double d=(double)freq[i]-e;x2+=d*d/e;}
    printf("n=%llu chi2_byte=%.1f (df=255 z=%+.2f)\n",n,x2,(x2-255)/sqrt(2*255));
    e=(double)(n-1)/65536.0;x2=0;
    for(int i=0;i<65536;i++){double d=(double)dig[i]-e;x2+=d*d/e;}
    printf("chi2_digraph=%.1f (df=65535 z=%+.2f)\n",x2,(x2-65535)/sqrt(2*65535));
    return 0;
}
