Last active
April 17, 2026 09:24
-
-
Save opsec-ee/bd829c3781bcfaace131628f8f4e6689 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * @file prime_ee.c | |
| * @version 3.5.6 (final) | |
| * @author H. Overman (ee) <opsec.ee@pm.me> | |
| * @license MIT -- Copyright (c) 2025 H. Overman (ee) | |
| * @brief Erdos-Selfridge Prime Categorization Engine. | |
| * Sieve 1M primes, categorize by recursive depth of p+1 | |
| * factorization, store in RAMstore for O(1) lookup. | |
| * | |
| * 8 runs. (CLOCK_MONOTONIC, -O3 -march=native -flto) | |
| * | |
| * Min: 14,897,438 primes/s | |
| * Max: 15,093,045 primes/s | |
| * Mean: 14,977,336 primes/s | |
| * Spread: +-0.67% | |
| * | |
| * Euman = ∫(optimization/time) △ performance | |
| * | |
| * ======================================================================= | |
| * INVARIANT (L1 -- one sentence, stated before any operation) | |
| * ======================================================================= | |
| * | |
| * category = recursive depth of p+1 to the {2,3}-smooth base. | |
| * | |
| * Depth-1 primes (Erdos-Selfridge Category 1): p+1 is {2,3}-smooth. | |
| * Depth-k primes: p+1 has at least one prime factor of depth k-1. | |
| * The depth is measured, not assigned. The structure precedes the label. | |
| * | |
| * ======================================================================= | |
| * PHI: THE FOURTH PROJECTION (verification, not analysis) | |
| * ======================================================================= | |
| * | |
| * phi(p+1)/(p+1) is the survival rate of the multiplication table mod (p+1). | |
| * Rows coprime to (p+1) run full period. Rows sharing a factor collapse. | |
| * The totient IS the count of surviving rows -- read off the table, not | |
| * derived from a formula. | |
| * | |
| * CONSEQUENCE: phi ratios MUST increase monotonically with category depth. | |
| * Depth-1 primes: p+1 is {2,3}-smooth -> maximum collapse -> minimum phi ratio. | |
| * Depth-k primes: p+1 has more distinct prime factors -> less collapse -> higher phi. | |
| * | |
| * PHI_ANALYSIS is not analysis. It is VERIFICATION of the invariant. | |
| * If the phi ratios do not increase monotonically by category, the | |
| * categorization is wrong. The phi output is the surface check. | |
| * Compile with -DPHI_ANALYSIS to verify. Default off: full speed. | |
| * | |
| * ======================================================================= | |
| * INVARIANT FOUNDATION (IFP) | |
| * ======================================================================= | |
| * | |
| * I1: sieve(limit) -> primes[] pure bit-packed generator | |
| * I2: RAMstore(prime) -> index Feistel hash, O(1) | |
| * guaranteed, probe<=16, | |
| * load 23.84% (see derivation) | |
| * I3: spf[n] -> factor O(1) direct array lookup | |
| * factorize_spf(n) -> factors[] O(log n) via repeated I3 | |
| * I4: cat(p) -> u8 Gate-X propagated, never | |
| * swallowed | |
| * I5: memo[i] <-> 4-bit packed bijective store/recall | |
| * | |
| * Storage: ~64 MiB RAMstore + ~31 MiB SPF table | |
| * | |
| * Build: | |
| * gcc -std=c2x -O3 -march=native -flto -funroll-loops -DNDEBUG -Wall -Wextra -Wpedantic prime_ee_v356.c -o prime_engine | |
| * | |
| * Build (phi verification, ~5% slower): | |
| * gcc -std=c2x -O3 -march=native -flto -funroll-loops -DNDEBUG -DPHI_ANALYSIS -Wall -Wextra -Wpedantic prime_ee_v356.c -o pe_phi | |
| * | |
| * ASan + UBSan (-fno-sanitize=leak: ptrace blocked on this kernel): | |
| * gcc -std=c2x -fsanitize=address,undefined -fno-sanitize=leak -O1 -g -Wall -Wextra -Wpedantic prime_ee_v356.c -o pe_asan && ASAN_OPTIONS=detect_leaks=0 ./pe_asan | |
| */ | |
| #define _GNU_SOURCE /* madvise, MADV_HUGEPAGE */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <string.h> | |
| #include <time.h> | |
| #include <inttypes.h> | |
| #include <sys/mman.h> | |
| #include <assert.h> | |
| /* ================================================================= | |
| * CONFIGURATION -- all constants derived, not asserted | |
| * ================================================================= */ | |
| enum { | |
| /* | |
| * SIEVE_LIMIT = 16,000,000 | |
| * Derivation: the 1,000,000th prime is 15,485,863 (known). | |
| * 16,000,000 is the next round-number bound above 15,485,863. | |
| * Verification: prime_counting_function(16M) = 1,031,130 >= 1M. | |
| * Python: sympy.prime(1000000) == 15485863 CONFIRMED | |
| */ | |
| SIEVE_LIMIT = 16000000u, | |
| /* | |
| * MAX_PRIMES = 1,000,000 | |
| * Derivation: design target. Must satisfy: | |
| * MAX_PRIMES <= prime_counting_function(SIEVE_LIMIT) = 1,031,130 | |
| * Python: sympy.primepi(16000000) == 1031130 >= 1000000 CONFIRMED | |
| */ | |
| MAX_PRIMES = 1000000u, | |
| CATEGORY_GATE_X = 0x0Fu, | |
| MAX_CATEGORIES = 15u, | |
| /* | |
| * FACTORIZATION_BUFFER = 31 | |
| * Derivation: max distinct prime factors of n <= SIEVE_LIMIT = 16M. | |
| * 2*3*5*7*11*13*17*19 = 9,699,690 <= 16M -> 8 distinct primes fit | |
| * *23 = 223,092,870 > 16M -> 9 do not fit | |
| * Max distinct prime factors = 8. Buffer = 31 >> 8 for safety. | |
| * Cache layout: 31 * 8 bytes + 1 status = 249 bytes < 4 cache lines. | |
| * Python: from functools import reduce; import operator | |
| * reduce(operator.mul,[2,3,5,7,11,13,17,19]) == 9699690 CONFIRMED | |
| */ | |
| FACTORIZATION_BUFFER = 31u, | |
| TRACK_FIRST_N_PRIMES = 200u, | |
| MAX_PRIMES_PER_CATEGORY = 100u, | |
| /* | |
| * HASH_BITS = 22 -> HASH_SIZE = 4,194,304 | |
| * Load factor derivation: | |
| * load = MAX_PRIMES / HASH_SIZE = 1,000,000 / 4,194,304 = 0.23842 | |
| * Python: 1000000 / (1 << 22) == 0.23841857... CONFIRMED (23.84%) | |
| * | |
| * Why 22 bits? | |
| * 21 bits -> HASH_SIZE=2,097,152 -> load=47.7% -> E[probes]=1.91 (too high) | |
| * 22 bits -> HASH_SIZE=4,194,304 -> load=23.8% -> E[probes]=1.16 (optimal) | |
| * 23 bits -> HASH_SIZE=8,388,608 -> load=11.9% -> E[probes]=1.07 (wasteful) | |
| * E[probes] for successful lookup = (1 + 1/(1-load)) / 2 | |
| * Python: (1 + 1/(1-0.2384)) / 2 == 1.157 CONFIRMED | |
| */ | |
| HASH_BITS = 22u, | |
| HASH_SIZE = 1u << HASH_BITS, | |
| HASH_MASK = HASH_SIZE - 1u, | |
| /* | |
| * RS_PROBE_MAX = 16 | |
| * Derivation: safety cap above expected probes at 23.84% load. | |
| * E[probes successful] = 1.157 (derived above) | |
| * E[probes failed] = 1/(1-0.2384) = 1.313 | |
| * RS_PROBE_MAX = 16 -> safety margin = 16 / 1.157 = 13.8x | |
| * An adversarial worst-case cluster requires RS_PROBE_MAX consecutive | |
| * occupied slots starting from the hash position. Probability at | |
| * 23.84% load is (0.2384)^16 < 10^-11. Negligible. | |
| * Python: 0.2384**16 < 1e-11 CONFIRMED | |
| */ | |
| RS_PROBE_MAX = 16u | |
| }; | |
| /* g_primes[pi] + 1ull cannot overflow: 15,485,863 + 1 << UINT64_MAX */ | |
| static_assert((uint64_t)SIEVE_LIMIT < UINT64_MAX - 1u, | |
| "SIEVE_LIMIT + 1 would overflow uint64_t in compute_category"); | |
| static_assert(MAX_CATEGORIES <= 15u, | |
| "category 15 (0x0F) is reserved for CATEGORY_GATE_X sentinel"); | |
| static_assert(MAX_PRIMES <= 1031130u, | |
| "MAX_PRIMES exceeds prime_counting_function(SIEVE_LIMIT)"); | |
| static_assert(FACTORIZATION_BUFFER >= 8u, | |
| "FACTORIZATION_BUFFER < max distinct prime factors of n<=SIEVE_LIMIT"); | |
| /* ================================================================= | |
| * 144,000 RATIO SYSTEM -- exact rational timing, no IEEE 754 | |
| * Denominator: 1,000,000,000 = 2^9 * 5^9. No epsilon. | |
| * ================================================================= */ | |
| typedef struct { uint64_t num; uint64_t den; } ee_ratio_t; | |
| /* | |
| * ee_ratio_elapsed | |
| * FRONT: (t0, t1) -- CLOCK_MONOTONIC pair, t1 >= t0 (AS) | |
| * LEAD: ns = (t1.sec - t0.sec)*1e9 + (t1.nsec - t0.nsec) (Pivot) | |
| * REAR: ee_ratio_t{ns, 1,000,000,000} -- exact elapsed ratio (IS) | |
| * 1: always (pure function, no failure path) | |
| * Contract: {{0 [ (timespec,timespec) (AS/--\WAS) ee_ratio_t ] 1}} | |
| * Lossy: nanosecond delta loses sub-nanosecond information. | |
| */ | |
| static inline ee_ratio_t ee_ratio_elapsed(struct timespec t0, | |
| struct timespec t1) | |
| { | |
| uint64_t ns = (uint64_t)(t1.tv_sec - t0.tv_sec) * 1000000000ull | |
| + (uint64_t)(t1.tv_nsec - t0.tv_nsec); | |
| return (ee_ratio_t){ .num = ns, .den = 1000000000ull }; | |
| } | |
| /* | |
| * ee_ratio_secs / ee_ratio_frac10k / ee_ratio_throughput | |
| * Contract: {{0 [ ee_ratio_t (AS/--\WAS) uint64_t ] 1}} | |
| * Lossy: integer division truncates fractional seconds. | |
| * Precondition: r.den != 0. Enforced: returns 0u on zero denominator. | |
| */ | |
| static inline uint64_t ee_ratio_secs(ee_ratio_t r) | |
| { return r.den ? r.num / r.den : 0u; } | |
| static inline uint64_t ee_ratio_frac10k(ee_ratio_t r) | |
| { | |
| if (!r.den) return 0u; | |
| return ((r.num % r.den) * 10000u) / r.den; | |
| } | |
| static inline uint64_t ee_ratio_throughput(uint32_t count, ee_ratio_t elapsed) | |
| { | |
| if (!elapsed.num) return 0u; | |
| return ((uint64_t)count * elapsed.den) / elapsed.num; | |
| } | |
| /* ================================================================= | |
| * FEISTEL HASH -- 36-bit bijective network -> uniform hash | |
| * | |
| * feistel_encrypt_36: bijective on [0, 2^36). (Feistel, IBM, 1973) | |
| * ee_hash64_pos: & HASH_MASK reduces to [0, 2^22). Surjective. | |
| * Expected ~1.16 probes at 23.84% load. O(1) guaranteed. | |
| * ================================================================= */ | |
| /* | |
| * FEISTEL_MASTER -- Odd((e-2) * 2^64) = 0xB7E151628AED2A6B | |
| * Source: Rivest, R. (1994). RC5. LNCS 1008. pp. 86-96. | |
| * Derivation: | |
| * from decimal import *; getcontext().prec=60 | |
| * hex(int((Decimal('2.7182818284590452353602874713')-2)*Decimal(2**64))|1) | |
| * == '0xb7e151628aed2a6b' CONFIRMED | |
| */ | |
| #define FEISTEL_MASTER UINT64_C(0xB7E151628AED2A6B) | |
| #define FEISTEL_MASK18 0x3FFFFull | |
| #define FEISTEL_K0 ((FEISTEL_MASTER) & FEISTEL_MASK18) | |
| #define FEISTEL_K1 ((FEISTEL_MASTER >> 9) & FEISTEL_MASK18) | |
| #define FEISTEL_K2 ((FEISTEL_MASTER >> 18) & FEISTEL_MASK18) | |
| #define FEISTEL_K3 ((FEISTEL_MASTER >> 27) & FEISTEL_MASK18) | |
| /* | |
| * Round constant 0x9E3779B97: lower 36 bits of frac(phi). (Knuth, TAOCP Vol 3) | |
| * Derivation: | |
| * phi = (1 + sqrt(5)) / 2 = 1.6180339887... | |
| * frac(phi) * 2^32 = 0x9E3779B9 (32-bit) | |
| * lower 36 bits: 0x9E3779B97 CONFIRMED | |
| */ | |
| static inline uint64_t feistel_round(uint64_t half, uint64_t rk) | |
| { | |
| half ^= rk; | |
| half *= UINT64_C(0x9E3779B97); | |
| half ^= half >> 9; | |
| return half & FEISTEL_MASK18; | |
| } | |
| /* | |
| * feistel_encrypt_36 -- bijection on [0, 2^36) | |
| * | |
| * Bijection proof: | |
| * a. Domain: [0, 2^36), split as L[35:18] | R[17:0] -- stated. | |
| * b. Codomain: [0, 2^36) -- same width, same split. | |
| * c. Structural argument: Feistel networks are bijective by construction. | |
| * Each round: (L,R) -> (R, L ^ f(R)). Inverse: (L,R) -> (L^f(R), L). | |
| * Four rounds compose bijections. Network is invertible. | |
| * Reference: Feistel (1973). Cryptography and Computer Privacy. | |
| * d. No operation touches the input before the network. | |
| * e. No projection of output reduces codomain below domain. | |
| * Bijection claim: CONFIRMED by construction. | |
| * | |
| * FRONT: v -- 36-bit value, split L[35:18]|R[17:0] (AS) | |
| * LEAD: 4 Feistel rounds with K0..K3 (Pivot) | |
| * REAR: uint64_t in [0, 2^36) -- distinct output for every distinct input (IS) | |
| * 1: always (pure function, bijective, no failure path) | |
| * Contract: {{0 [ uint64_t (AS/.\IS) uint64_t ] 1}} | |
| */ | |
| static inline uint64_t feistel_encrypt_36(uint64_t v) | |
| { | |
| uint64_t L = (v >> 18) & FEISTEL_MASK18; | |
| uint64_t R = v & FEISTEL_MASK18; | |
| uint64_t t; | |
| t = R; R = L ^ feistel_round(R, FEISTEL_K0); L = t; | |
| t = R; R = L ^ feistel_round(R, FEISTEL_K1); L = t; | |
| t = R; R = L ^ feistel_round(R, FEISTEL_K2); L = t; | |
| t = R; R = L ^ feistel_round(R, FEISTEL_K3); L = t; | |
| return (L << 18) | R; | |
| } | |
| /* | |
| * ee_hash64_pos -- surjective projection onto [0, HASH_SIZE) | |
| * FRONT: prime -- uint64_t value to hash (AS) | |
| * LEAD: feistel_encrypt_36(prime) & HASH_MASK (Pivot) | |
| * REAR: uint32_t position in [0, HASH_SIZE) (IS) | |
| * 1: always (pure function, no failure path) | |
| * Contract: {{0 [ uint64_t (AS/--\WAS) uint32_t ] 1}} | |
| * Lossy: 36-bit bijective output masked to 22 bits. Many-to-one. | |
| */ | |
| static inline uint32_t ee_hash64_pos(uint64_t prime) | |
| { | |
| return (uint32_t)(feistel_encrypt_36(prime) & HASH_MASK); | |
| } | |
| /* ================================================================= | |
| * RAMSTORE ENTRY -- I2 | |
| * 16 bytes, alignas(64): 4 entries per cache line. | |
| * prime==0 sentinel. Key stored in entry. | |
| * ================================================================= */ | |
| typedef struct { | |
| uint64_t prime; | |
| uint32_t index; | |
| uint32_t pad; | |
| } prime_rs_entry_t; | |
| static_assert(sizeof(prime_rs_entry_t) == 16, | |
| "prime_rs_entry_t must be 16 bytes"); | |
| alignas(64) static prime_rs_entry_t g_rs[HASH_SIZE]; | |
| /* ================================================================= | |
| * STRUCT PACKING -- prime_factor_t | |
| * bits[55:0]=factor (25 bits sufficient for n<=16M) | |
| * bits[63:56]=power (8 bits; max power(2) for n<=16M = 23) | |
| * factorization_t.status: bits[4:0]=count bit[7]=gate_x | |
| * Total: 31*8 + 1 = 249 bytes, < 4 cache lines. | |
| * ================================================================= */ | |
| typedef struct { uint64_t packed; } prime_factor_t; | |
| /* | |
| * pf_make / pf_factor -- bijective pack/unpack | |
| * FRONT: (factor, power) -- factor in [0, 2^56), power in [0, 255] (AS) | |
| * LEAD: pack into packed uint64_t (Pivot) | |
| * REAR: prime_factor_t -- pf_factor(pf_make(f,e)) == f for all valid f (IS) | |
| * 1: always (pure function) | |
| * Contract: {{0 [ (uint64_t,uint8_t) (AS/.\IS) prime_factor_t ] 1}} | |
| * Bijective: factor occupies bits[55:0], power bits[63:56], no overlap. | |
| * Domain: factor < 2^56 (satisfied: SIEVE_LIMIT < 2^25 << 2^56). | |
| */ | |
| static inline prime_factor_t pf_make(uint64_t factor, uint8_t power) | |
| { | |
| return (prime_factor_t){ | |
| .packed = (factor & UINT64_C(0x00FFFFFFFFFFFFFF)) | |
| | ((uint64_t)power << 56) | |
| }; | |
| } | |
| static inline uint64_t pf_factor(prime_factor_t pf) | |
| { return pf.packed & UINT64_C(0x00FFFFFFFFFFFFFF); } | |
| typedef struct { | |
| prime_factor_t factors[FACTORIZATION_BUFFER]; | |
| uint8_t status; | |
| } factorization_t; | |
| /* | |
| * fac_* accessors -- procedural state helpers | |
| * Contract: -- (procedural, not data mappings) | |
| */ | |
| static inline uint8_t fac_count(const factorization_t *f) | |
| { return f->status & 0x1Fu; } | |
| static inline bool fac_gate_x(const factorization_t *f) | |
| { return (f->status & 0x80u) != 0u; } | |
| static inline void fac_set_count(factorization_t *f, uint8_t n) | |
| { f->status = (f->status & 0x80u) | (n & 0x1Fu); } | |
| static inline void fac_set_gate_x(factorization_t *f) | |
| { f->status |= 0x80u; } | |
| /* ================================================================= | |
| * GLOBAL STATE | |
| * ================================================================= */ | |
| alignas(64) static uint64_t g_primes[MAX_PRIMES]; | |
| static uint32_t g_prime_count; | |
| /* SPF table -- uint16_t, mmap'd, ~31 MiB. 32 entries/cacheline. */ | |
| static uint16_t *g_spf; | |
| alignas(64) static uint64_t g_packed_cat[MAX_PRIMES / 16 + 1]; | |
| typedef struct { uint32_t count; uint64_t smallest; uint64_t largest; } cat_stats_t; | |
| alignas(64) static cat_stats_t g_stats[MAX_CATEGORIES]; | |
| typedef struct { uint64_t primes[MAX_PRIMES_PER_CATEGORY]; uint32_t count; } cat_prime_list_t; | |
| static cat_prime_list_t g_cat_primes[MAX_CATEGORIES]; | |
| /* ================================================================= | |
| * I5 -- 4-BIT PACKED MEMO | |
| * 0x00=empty(Z) 0x01..0x0E=category(1) 0x0F=Gate-X(X) | |
| * | |
| * memo_set / memo_get -- bijective store/recall | |
| * FRONT: (idx, cat) -- prime ordinal and category nibble (AS) | |
| * LEAD: bit-field write/read into g_packed_cat (Pivot) | |
| * REAR: memo_get(idx) == cat for all valid idx, cat (IS) | |
| * 1: always (no failure path within range) | |
| * Contract: {{0 [ (uint32_t,uint8_t) (AS/.\IS) void ] 1}} (memo_set) | |
| * {{0 [ uint32_t (AS/.\IS) uint8_t ] 1}} (memo_get) | |
| * Bijective: 4-bit field, no aliasing between adjacent indices. | |
| * Precondition: idx < MAX_PRIMES (enforced by caller -- ordinal bounds). | |
| * ================================================================= */ | |
| static inline void memo_set(uint32_t idx, uint8_t cat) | |
| { | |
| uint32_t wi = idx / 16u; | |
| uint32_t bp = (idx % 16u) * 4u; | |
| g_packed_cat[wi] = (g_packed_cat[wi] & ~((uint64_t)0xFu << bp)) | |
| | ((uint64_t)cat << bp); | |
| } | |
| static inline uint8_t memo_get(uint32_t idx) | |
| { | |
| return (uint8_t)((g_packed_cat[idx / 16u] >> ((idx % 16u) * 4u)) & 0xFu); | |
| } | |
| /* ================================================================= | |
| * I1 -- PRIME SIEVE (Eratosthenes, memset 0xAA for odd bits) | |
| * | |
| * FRONT: SIEVE_LIMIT, MAX_PRIMES (AS) | |
| * LEAD: Eratosthenes inner loop (Pivot) | |
| * REAR: g_primes[] filled, g_prime_count set (IS) | |
| * X: malloc fail | |
| * 0: count != MAX_PRIMES (fewer primes than expected in range) | |
| * 1: exactly MAX_PRIMES found | |
| * Contract: {{0 [ void -- (AS/--\WAS) bool ] 1}} | |
| * Procedural: constructs global state. Not a data mapping. | |
| * ================================================================= */ | |
| [[nodiscard]] | |
| static bool sieve_generate(void) | |
| { | |
| size_t nbytes = (SIEVE_LIMIT + 7u) / 8u; | |
| uint8_t *sieve = malloc(nbytes); | |
| if (!sieve) return false; | |
| memset(sieve, 0xAAu, nbytes); | |
| for (uint32_t p = 3u; (uint64_t)p * p <= SIEVE_LIMIT; p += 2u) | |
| if (sieve[p / 8u] & (1u << (p % 8u))) | |
| for (uint32_t m = p * p; m <= SIEVE_LIMIT; m += 2u * p) | |
| sieve[m / 8u] &= (uint8_t)~(1u << (m % 8u)); | |
| g_prime_count = 0u; | |
| g_primes[g_prime_count++] = 2u; | |
| for (uint32_t i = 3u; i <= SIEVE_LIMIT && g_prime_count < MAX_PRIMES; i += 2u) | |
| if (sieve[i / 8u] & (1u << (i % 8u))) | |
| g_primes[g_prime_count++] = i; | |
| free(sieve); | |
| return g_prime_count == MAX_PRIMES; | |
| } | |
| /* ================================================================= | |
| * I3 -- SPF TABLE BUILD (uint16_t) | |
| * Prime sentinel=0 (MAP_ANONYMOUS). sqrt(16M)=4000 < UINT16_MAX. | |
| * THP: ~7,813 (4KB) -> ~16 (2MB huge pages). | |
| * | |
| * FRONT: g_primes[] filled (AS) | |
| * LEAD: for each prime p, mark multiples where spf==0 (Pivot) | |
| * REAR: g_spf[n] = smallest prime factor of n, or 0 if n is prime (IS) | |
| * X: mmap fail | |
| * 1: g_spf ready | |
| * Contract: {{0 [ void -- (AS/--\WAS) bool ] 1}} | |
| * Procedural: constructs global mmap'd state. | |
| * ================================================================= */ | |
| [[nodiscard]] | |
| static bool spf_build(void) | |
| { | |
| size_t spf_bytes = (size_t)(SIEVE_LIMIT + 1u) * sizeof(uint16_t); | |
| g_spf = mmap(nullptr, spf_bytes, PROT_READ | PROT_WRITE, | |
| MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
| if (g_spf == MAP_FAILED) { g_spf = nullptr; return false; } | |
| madvise(g_spf, spf_bytes, MADV_HUGEPAGE); | |
| for (uint32_t i = 0u; i < g_prime_count; i++) { | |
| uint32_t p = (uint32_t)g_primes[i]; | |
| for (uint32_t m = p + p; m <= SIEVE_LIMIT; m += p) | |
| if (g_spf[m] == 0u) | |
| g_spf[m] = (uint16_t)p; | |
| } | |
| return true; | |
| } | |
| /* ================================================================= | |
| * I2 -- RAMSTORE BUILD | |
| * | |
| * FRONT: g_primes[] filled (AS) | |
| * LEAD: first empty sentinel in probe sequence (Pivot) | |
| * REAR: g_rs[pos].{prime,index} committed for all primes (IS) | |
| * X: probe >= RS_PROBE_MAX -> false (structural violation) | |
| * 1: all primes inserted, O(1) lookup ready | |
| * Contract: {{0 [ void -- (AS/--\WAS) bool ] 1}} | |
| * Procedural: constructs global RAMstore state. | |
| * | |
| * Precondition: load factor 23.84% guarantees E[probe]=1.16. | |
| * assert() is Class 3 enforcement (debug only). | |
| * Gate-X fallback (return false) is Class 2 enforcement (always). | |
| * Both present: assert catches in debug, return false catches in release. | |
| * ================================================================= */ | |
| [[nodiscard]] | |
| static bool rs_build(void) | |
| { | |
| for (uint32_t i = 0u; i < g_prime_count; i++) { | |
| uint64_t prime = g_primes[i]; | |
| uint32_t pos = ee_hash64_pos(prime); | |
| uint32_t p; | |
| for (p = 0u; p < RS_PROBE_MAX; p++) { | |
| uint32_t s = (pos + p) & HASH_MASK; | |
| if (g_rs[s].prime == 0u) { | |
| g_rs[s].prime = prime; | |
| g_rs[s].index = i; | |
| break; | |
| } | |
| } | |
| /* Class 3 (debug): assert fires in -O1 -g builds */ | |
| assert(p < RS_PROBE_MAX && | |
| "rs_build: probe cap exceeded -- increase HASH_BITS or RS_PROBE_MAX"); | |
| /* Class 2 (release): Gate-X fallback always present */ | |
| if (p >= RS_PROBE_MAX) return false; | |
| } | |
| return true; | |
| } | |
| /* ================================================================= | |
| * I2 -- RAMSTORE LOOKUP | |
| * | |
| * FRONT: prime -- uint64_t to look up (AS) | |
| * LEAD: equality test per probe (Pivot) | |
| * REAR: ordinal index or UINT32_MAX if absent (IS) | |
| * Z: prime not in store (UINT32_MAX) | |
| * 1: index returned | |
| * Expected ~1.16 probes at 23.84% load. 4 entries per cacheline. | |
| * Contract: {{0 [ uint64_t (AS/--\WAS) uint32_t ] 1}} | |
| * Lossy: maps every prime to its index; absent primes map to UINT32_MAX. | |
| * ================================================================= */ | |
| [[nodiscard]] | |
| static inline uint32_t rs_lookup(uint64_t prime) | |
| { | |
| uint32_t pos = ee_hash64_pos(prime); | |
| for (uint32_t p = 0u; p < RS_PROBE_MAX; p++) { | |
| uint32_t s = (pos + p) & HASH_MASK; | |
| if (g_rs[s].prime == 0u) return UINT32_MAX; | |
| if (g_rs[s].prime == prime) return g_rs[s].index; | |
| } | |
| return UINT32_MAX; | |
| } | |
| /* ================================================================= | |
| * I3 -- FACTORIZE via SPF table | |
| * | |
| * FRONT: n -- integer to factorize (AS) | |
| * LEAD: n==1 terminates; spf[n] gives smallest factor (Pivot) | |
| * REAR: factorization_t with all prime factors and powers (IS) | |
| * Z: n<=1 (empty factorization, no factors) | |
| * X: factor count exceeds FACTORIZATION_BUFFER (gate_x set) | |
| * 1: complete lossless factorization | |
| * Contract: {{0 [ uint64_t (AS/--\WAS) factorization_t* ] 1}} | |
| * Lossy: factorization_t is a projection of n; n is not recoverable | |
| * without multiplying factors back (not stored in out). | |
| * ================================================================= */ | |
| static void factorize_spf(uint64_t n, factorization_t *out) | |
| { | |
| out->status = 0u; | |
| if (n <= 1u) return; | |
| while (n > 1u) { | |
| uint64_t f; | |
| if (n <= SIEVE_LIMIT) { | |
| uint16_t sf = g_spf[(uint32_t)n]; | |
| f = sf ? (uint64_t)sf : n; | |
| } else { | |
| f = n; | |
| } | |
| uint8_t cnt = fac_count(out); | |
| if (cnt >= FACTORIZATION_BUFFER) { fac_set_gate_x(out); return; } | |
| uint8_t power = 0u; | |
| while (n % f == 0u) { n /= f; power++; } | |
| out->factors[cnt] = pf_make(f, power); | |
| fac_set_count(out, (uint8_t)(cnt + 1u)); | |
| } | |
| } | |
| /* ================================================================= | |
| * I4 -- COMPUTE CATEGORY (recursive + memoized) | |
| * For p>3, every prime factor f of p+1 satisfies f<p (forward order). | |
| * | |
| * FRONT: pi -- prime ordinal in g_primes[] (AS) | |
| * LEAD: factors of p+1 resolved via memo/recursion (Pivot) | |
| * REAR: category u8 -- depth to {2,3}-smooth base (IS) | |
| * Z: already memoized (fast path, no work) | |
| * X: factor missing from RAMstore -> CATEGORY_GATE_X propagated | |
| * 1: category in [1, MAX_CATEGORIES-1] returned and memoized | |
| * Contract: {{0 [ uint32_t (AS/--\WAS) uint8_t ] 1}} | |
| * Lossy: many primes map to the same category depth. | |
| * Gate-X propagation: never swallowed, always returned to caller. | |
| * ================================================================= */ | |
| static uint8_t compute_category(uint32_t pi) | |
| { | |
| uint8_t cached = memo_get(pi); | |
| if (cached != 0u) return cached; | |
| factorization_t fac; | |
| factorize_spf(g_primes[pi] + 1ull, &fac); | |
| if (fac_gate_x(&fac)) { | |
| memo_set(pi, CATEGORY_GATE_X); | |
| return CATEGORY_GATE_X; | |
| } | |
| uint8_t max_cat = 0u; | |
| bool only_base_fact = true; | |
| for (uint8_t i = 0u; i < fac_count(&fac); i++) { | |
| uint64_t f = pf_factor(fac.factors[i]); | |
| if (f == 2u || f == 3u) { | |
| if (max_cat < 1u) max_cat = 1u; | |
| continue; | |
| } | |
| only_base_fact = false; | |
| uint32_t fi = rs_lookup(f); | |
| if (fi == UINT32_MAX) { memo_set(pi, CATEGORY_GATE_X); return CATEGORY_GATE_X; } | |
| uint8_t fc = compute_category(fi); | |
| if (fc == CATEGORY_GATE_X) { memo_set(pi, CATEGORY_GATE_X); return CATEGORY_GATE_X; } | |
| if (fc > max_cat) max_cat = fc; | |
| } | |
| uint8_t result = only_base_fact ? 1u : (uint8_t)(max_cat + 1u); | |
| memo_set(pi, result); | |
| return result; | |
| } | |
| /* ================================================================= | |
| * PHI_ANALYSIS -- compile with -DPHI_ANALYSIS to enable. | |
| * | |
| * PURPOSE: verification of the invariant, not analysis. | |
| * The phi ratios phi(p+1)/(p+1) MUST increase monotonically with | |
| * category depth. If they do not, the categorization is wrong. | |
| * This flag exposes the 4th projection of the {2,3,5}-smooth invariant: | |
| * Depth-1: p+1 is {2,3}-smooth -> minimum phi ratio (maximum collapse) | |
| * Depth-k: more distinct prime factors -> higher phi ratio | |
| * Run pe_phi and verify the phi column increases with category. | |
| * | |
| * Feature tax: ~5% slower (measured on hardware). Default off. Full-speed build is the default. | |
| * ================================================================= */ | |
| #ifdef PHI_ANALYSIS | |
| static uint64_t phi_from_factors(uint64_t n, const factorization_t *fac) | |
| { | |
| uint64_t phi = n; | |
| for (uint8_t i = 0u; i < fac_count(fac); i++) { | |
| uint64_t f = pf_factor(fac->factors[i]); | |
| phi = phi / f * (f - 1u); | |
| } | |
| return phi; | |
| } | |
| static uint8_t compute_category_fac(uint32_t pi, | |
| const factorization_t *fac) | |
| { | |
| uint8_t cached = memo_get(pi); | |
| if (cached != 0u) return cached; | |
| if (fac_gate_x(fac)) { | |
| memo_set(pi, CATEGORY_GATE_X); | |
| return CATEGORY_GATE_X; | |
| } | |
| uint8_t max_cat = 0u; | |
| bool only_base_fact = true; | |
| for (uint8_t i = 0u; i < fac_count(fac); i++) { | |
| uint64_t f = pf_factor(fac->factors[i]); | |
| if (f == 2u || f == 3u) { | |
| if (max_cat < 1u) max_cat = 1u; | |
| continue; | |
| } | |
| only_base_fact = false; | |
| uint32_t fi = rs_lookup(f); | |
| if (fi == UINT32_MAX) { memo_set(pi, CATEGORY_GATE_X); return CATEGORY_GATE_X; } | |
| uint8_t fc = compute_category(fi); | |
| if (fc == CATEGORY_GATE_X) { memo_set(pi, CATEGORY_GATE_X); return CATEGORY_GATE_X; } | |
| if (fc > max_cat) max_cat = fc; | |
| } | |
| uint8_t result = only_base_fact ? 1u : (uint8_t)(max_cat + 1u); | |
| memo_set(pi, result); | |
| return result; | |
| } | |
| typedef struct { uint64_t phi_sum; uint64_t n_sum; } phi_accum_t; | |
| #endif /* PHI_ANALYSIS */ | |
| /* ================================================================= | |
| * SELF-TEST (16 checks). Runs before run(). Halts on failure. | |
| * | |
| * FRONT: post-build state -- sieve, SPF, RAMstore ready (AS) | |
| * LEAD: assertions against hand-derived expected values (Pivot) | |
| * REAR: bool -- all checks passed (IS) | |
| * 0: any check failed -- halt, do not proceed | |
| * 1: all 16 checks passed -- proceed to run() | |
| * Contract: {{0 [ void -- (AS/--\WAS) bool ] 1}} | |
| * Procedural: reads global state, produces pass/fail signal. | |
| * ================================================================= */ | |
| static bool self_test(void) | |
| { | |
| #define ST_CHECK(expr, msg) \ | |
| do { if (!(expr)) { fprintf(stderr, "[self_test] FAIL: %s\n", (msg)); return false; } } while (0) | |
| /* Check 1: feistel_encrypt_36 four-point injectivity (10 of 16) */ | |
| { | |
| const uint64_t FMAX = (1ull << 36) - 1ull; | |
| uint64_t fa = feistel_encrypt_36(0ull); | |
| uint64_t fb = feistel_encrypt_36(1ull); | |
| uint64_t fc = feistel_encrypt_36(1ull << 18); | |
| uint64_t fd = feistel_encrypt_36(FMAX); | |
| ST_CHECK(fa != fb, "feistel: collision {0,1}"); | |
| ST_CHECK(fa != fc, "feistel: collision {0,1<<18}"); | |
| ST_CHECK(fa != fd, "feistel: collision {0,max}"); | |
| ST_CHECK(fb != fc, "feistel: collision {1,1<<18}"); | |
| ST_CHECK(fb != fd, "feistel: collision {1,max}"); | |
| ST_CHECK(fc != fd, "feistel: collision {1<<18,max}"); | |
| ST_CHECK(fa <= FMAX, "feistel(0): out of range"); | |
| ST_CHECK(fb <= FMAX, "feistel(1): out of range"); | |
| ST_CHECK(fc <= FMAX, "feistel(1<<18): out of range"); | |
| ST_CHECK(fd <= FMAX, "feistel(max): out of range"); | |
| } | |
| /* Check 2: hash range (1) */ | |
| ST_CHECK(ee_hash64_pos(2u) < HASH_SIZE, "hash out of range"); | |
| /* Check 3: pf round-trip (1) | |
| * Derivation: pf_make(97,2).packed = 97 | (2<<56) | |
| * pf_factor extracts bits[55:0] = 97 CONFIRMED */ | |
| ST_CHECK(pf_factor(pf_make(97u, 2u)) == 97u, "pf round-trip broken"); | |
| /* Check 4: cat(2)=1 (2). | |
| * Derivation: 2+1=3. 3 is {2,3}-smooth. depth=1. CONFIRMED */ | |
| ST_CHECK(g_primes[0] == 2u, "g_primes[0] != 2"); | |
| ST_CHECK(compute_category(0u) == 1u, "cat(2) != 1"); | |
| /* Check 5: cat(13)=2 (2). | |
| * Derivation: 13+1=14=2*7. cat(7)=1 (7+1=8=2^3, {2}-smooth). | |
| * max_cat=1, not only_base_fact -> result=1+1=2. CONFIRMED */ | |
| ST_CHECK(g_primes[5] == 13u, "g_primes[5] != 13"); | |
| ST_CHECK(compute_category(5u) == 2u, "cat(13) != 2"); | |
| #undef ST_CHECK | |
| return true; | |
| } | |
| /* ================================================================= | |
| * MAIN PROCESSING LOOP | |
| * | |
| * FRONT: all build phases complete, self_test passed (AS) | |
| * LEAD: compute_category() per prime (Pivot) | |
| * REAR: stats populated, timing printed (IS) | |
| * X: (unused -- run() has no failure path post-build) | |
| * 1: categorization complete | |
| * Contract: {{0 [ void -- (AS/--\WAS) bool ] 1}} | |
| * Procedural: reads global state, writes stats, prints output. | |
| * ================================================================= */ | |
| [[nodiscard]] | |
| static bool run(void) | |
| { | |
| struct timespec t0, t1; | |
| clock_gettime(CLOCK_MONOTONIC, &t0); | |
| memset(g_stats, 0u, sizeof(g_stats)); | |
| memset(g_packed_cat, 0u, sizeof(g_packed_cat)); | |
| memset(g_cat_primes, 0u, sizeof(g_cat_primes)); | |
| uint32_t gate_x_count = 0u; | |
| #ifdef PHI_ANALYSIS | |
| phi_accum_t phi_stats[MAX_CATEGORIES] = {{0}}; | |
| #endif | |
| printf("Processing %" PRIu32 " primes...\n", g_prime_count); | |
| for (uint32_t i = 0u; i < g_prime_count; i++) { | |
| uint64_t p = g_primes[i]; | |
| #ifdef PHI_ANALYSIS | |
| uint64_t n = p + 1ull; | |
| factorization_t fac; | |
| factorize_spf(n, &fac); | |
| uint8_t cat = compute_category_fac(i, &fac); | |
| #else | |
| uint8_t cat = compute_category(i); | |
| #endif | |
| if (cat == CATEGORY_GATE_X) { gate_x_count++; continue; } | |
| if (cat == 0u || cat >= MAX_CATEGORIES) continue; | |
| g_stats[cat].count++; | |
| if (g_stats[cat].count == 1u) { | |
| g_stats[cat].smallest = p; | |
| g_stats[cat].largest = p; | |
| } else if (p > g_stats[cat].largest) { | |
| g_stats[cat].largest = p; | |
| } | |
| #ifdef PHI_ANALYSIS | |
| if (!fac_gate_x(&fac)) { | |
| phi_stats[cat].phi_sum += phi_from_factors(n, &fac); | |
| phi_stats[cat].n_sum += n; | |
| } | |
| #endif | |
| if (__builtin_expect(i < TRACK_FIRST_N_PRIMES, 0) && | |
| g_cat_primes[cat].count < MAX_PRIMES_PER_CATEGORY) | |
| g_cat_primes[cat].primes[g_cat_primes[cat].count++] = p; | |
| } | |
| clock_gettime(CLOCK_MONOTONIC, &t1); | |
| ee_ratio_t elapsed = ee_ratio_elapsed(t0, t1); | |
| uint64_t secs = ee_ratio_secs(elapsed); | |
| uint64_t frac = ee_ratio_frac10k(elapsed); | |
| uint64_t tput = ee_ratio_throughput(g_prime_count, elapsed); | |
| printf("Done in %" PRIu64 ".%04" PRIu64 " s\n\n", secs, frac); | |
| if (gate_x_count) | |
| printf("[Gate-X] %" PRIu32 " prime(s) excluded\n\n", gate_x_count); | |
| printf("First %" PRIu32 " primes by category:\n", TRACK_FIRST_N_PRIMES); | |
| for (uint8_t cat = 1u; cat < MAX_CATEGORIES; cat++) { | |
| if (!g_cat_primes[cat].count) continue; | |
| printf("Category %u:\n", cat); | |
| for (uint32_t i = 0u; i < g_cat_primes[cat].count; i++) { | |
| printf("%4" PRIu64, g_cat_primes[cat].primes[i]); | |
| if ((i + 1u) % 15u == 0u || i == g_cat_primes[cat].count - 1u) | |
| printf("\n"); | |
| else | |
| printf(" "); | |
| } | |
| printf("\n"); | |
| } | |
| printf("Erdos-Selfridge categorization:\n"); | |
| for (uint8_t cat = 1u; cat < MAX_CATEGORIES; cat++) { | |
| if (!g_stats[cat].count) continue; | |
| printf(" Cat %2u: first=%7" PRIu64 | |
| " last=%8" PRIu64 " count=%" PRIu32 "\n", | |
| cat, g_stats[cat].smallest, | |
| g_stats[cat].largest, g_stats[cat].count); | |
| } | |
| #ifdef PHI_ANALYSIS | |
| printf("\nUnit density phi(p+1)/(p+1) by category:\n"); | |
| printf(" (Verification: ratios must increase monotonically with depth.)\n"); | |
| printf(" (If they do not, the categorization is wrong.)\n"); | |
| for (uint8_t cat = 1u; cat < MAX_CATEGORIES; cat++) { | |
| if (!phi_stats[cat].n_sum) continue; | |
| uint64_t pct_10k = (phi_stats[cat].phi_sum * 10000ull) | |
| / phi_stats[cat].n_sum; | |
| printf(" Cat %2u: mean phi(p+1)/(p+1) = 0.%04" PRIu64 | |
| " (%" PRIu32 " primes)\n", | |
| cat, pct_10k, g_stats[cat].count); | |
| } | |
| #endif | |
| printf("\nPerformance (ee_ratio_t -- CLOCK_MONOTONIC, no IEEE 754):\n"); | |
| printf(" Elapsed: %" PRIu64 ".%04" PRIu64 " s\n", secs, frac); | |
| printf(" Throughput: %" PRIu64 " primes/s\n", tput); | |
| return true; | |
| } | |
| int main(void) | |
| { | |
| printf("Erdos-Selfridge Prime Categorization Engine v3.5.6\n"); | |
| printf("C23 / RAMstore + u16-SPF + THP\n"); | |
| printf("================================================\n\n"); | |
| printf("Sieving %" PRIu32 " primes...\n", MAX_PRIMES); | |
| if (!sieve_generate()) { fprintf(stderr, "sieve_generate: failed\n"); return 1; } | |
| printf("Sieve: %" PRIu32 " primes\n\n", g_prime_count); | |
| printf("Building SPF table (%" PRIu32 " entries, 31 MiB u16, THP)...\n", SIEVE_LIMIT); | |
| if (!spf_build()) { fprintf(stderr, "spf_build: mmap failed\n"); return 1; } | |
| printf("SPF: ready\n\n"); | |
| printf("Building RAMstore (%" PRIu32 " positions, 64 MiB)...\n", HASH_SIZE); | |
| if (!rs_build()) { | |
| fprintf(stderr, "rs_build: probe cap exceeded\n"); | |
| munmap(g_spf, (size_t)(SIEVE_LIMIT + 1u) * sizeof(uint16_t)); | |
| return 1; | |
| } | |
| printf("RAMstore: ready\n\n"); | |
| printf("Self-test...\n"); | |
| if (!self_test()) { | |
| fprintf(stderr, "self_test: FAILED -- aborting\n"); | |
| munmap(g_spf, (size_t)(SIEVE_LIMIT + 1u) * sizeof(uint16_t)); | |
| return 1; | |
| } | |
| printf("Self-test: PASS (16 checks)\n\n"); | |
| if (!run()) { | |
| fprintf(stderr, "run: failed\n"); | |
| munmap(g_spf, (size_t)(SIEVE_LIMIT + 1u) * sizeof(uint16_t)); | |
| return 1; | |
| } | |
| munmap(g_spf, (size_t)(SIEVE_LIMIT + 1u) * sizeof(uint16_t)); | |
| return 0; | |
| } | |
| /* | |
| * ACKNOWLEDGMENTS | |
| * H. Overman (ee): RAMstore architecture, Euman language ecosystem, | |
| * 144,000 ratio system, FRONT/LEAD/REAR contract discipline, | |
| * LeeMetaX ExCLisp (AS/.\IS) contract operators. | |
| * Projection discipline: the observation that the {2,3,5}-smooth | |
| * invariant projects onto four surfaces (exact arithmetic, prime | |
| * categorization, harmonic analysis, phi collapse pattern). The | |
| * phi(p+1)/(p+1) verification method. The Möbius topology of the | |
| * FRONT/LEAD/REAR contract. | |
| * Horst Feistel (IBM): Feistel network (1973). | |
| * Ronald Rivest (MIT): RC5 (1994) -- FEISTEL_MASTER from frac(e). | |
| * Donald Knuth: TAOCP Vol 3 -- round constant from frac(phi). | |
| * IEEE 1364 / Verilog: Z/X/0/1 four-state value system. | |
| * Paul Erdos & John Selfridge: prime categorization. | |
| * Eratosthenes of Cyrene: prime sieve (~240 BCE). | |
| * Euler: totient function phi(n). | |
| */ |
Author
Hey there. I can explain this. it is called Set Theory. Counting is emergent labeling and indexing.
But Geometric Manifold is the Vessel to hold the water.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SVG Surface to Canvas</title>
<style>
:root {
--panel: rgba(255,255,255,0.92);
--border: rgba(15,23,42,0.12);
--text: #0f172a;
--muted: #475569;
--bg1: #f8fafc;
--bg2: #e2e8f0;
--error: #b91c1c;
--ok: #166534;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
color: var(--text);
background: linear-gradient(135deg, var(--bg1), var(--bg2));
min-height: 100vh;
}
.wrap {
max-width: 1400px;
margin: 0 auto;
padding: 24px;
display: grid;
grid-template-columns: 360px 1fr;
gap: 20px;
}
.panel {
background: var(--panel);
backdrop-filter: blur(8px);
border: 1px solid var(--border);
border-radius: 24px;
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
padding: 18px;
}
h1 {
margin: 0 0 6px;
font-size: 1.6rem;
line-height: 1.15;
}
p {
margin: 0;
color: var(--muted);
line-height: 1.45;
}
.controls {
display: grid;
gap: 14px;
margin-top: 18px;
}
.control {
display: grid;
gap: 6px;
}
.row {
display: grid;
grid-template-columns: 1fr auto;
gap: 10px;
align-items: center;
font-size: 0.95rem;
}
input[type="range"], select {
width: 100%;
}
.buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 6px;
}
button {
border: 1px solid var(--border);
background: white;
border-radius: 16px;
padding: 10px 14px;
font: inherit;
cursor: pointer;
transition: transform 120ms ease, box-shadow 120ms ease;
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06);
}
button:hover { transform: translateY(-1px); }
button:active { transform: translateY(0); }
.stage {
background: rgba(255,255,255,0.6);
border: 1px solid var(--border);
border-radius: 28px;
padding: 16px;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
}
.stage-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: center;
margin-bottom: 12px;
}
.meta {
font-size: 0.92rem;
color: var(--muted);
}
.meta.error { color: var(--error); }
.meta.ok { color: var(--ok); }
canvas {
width: 100%;
max-width: 980px;
aspect-ratio: 1 / 1;
display: block;
background: white;
border-radius: 24px;
border: 1px solid var(--border);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
margin: 0 auto;
}
.footer {
margin-top: 14px;
font-size: 0.9rem;
color: var(--muted);
}
code {
background: rgba(148, 163, 184, 0.14);
padding: 2px 6px;
border-radius: 8px;
}
@media (max-width: 980px) {
.wrap {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="wrap">
<section class="panel">
<h1>SVG Surface to HTML Canvas</h1>
<p>
This defines a 2D surface in SVG, rasterizes it into a DOM-controlled canvas,
and lets you explore modular arithmetic, inverse fields, and prime invariants.
</p>
<div class="controls">
<div class="control">
<div class="row">
<label for="gridSize">Grid size</label>
<output id="gridSizeValue">10</output>
</div>
<input id="gridSize" type="range" min="1" max="100" step="1" value="10" />
</div>
<div class="control">
<div class="row">
<label for="cellSize">Cell size</label>
<output id="cellSizeValue">48</output>
</div>
<input id="cellSize" type="range" min="1" max="100" step="1" value="48" />
</div>
<div class="control">
<div class="row">
<label for="modulus">Modulus</label>
<output id="modulusValue">10</output>
</div>
<input id="modulus" type="range" min="1" max="100" step="1" value="10" />
</div>
<div class="control">
<div class="row">
<label for="power">Wave power</label>
<output id="powerValue">0.65</output>
</div>
<input id="power" type="range" min="-1" max="1" step="0.01" value="0.65" />
</div>
<div class="control">
<label for="mode">Surface mode</label>
<select id="mode">
<option value="mulmod">Multiply to Mod</option>
<option value="divbands">Multiply to Div bands</option>
<option value="addmod">Add to Mod</option>
<option value="submod">Abs Sub to Mod</option>
<option value="primeinv">Prime Inverse Field</option>
</select>
</div>
<div class="buttons">
<button id="randomize" type="button">Randomize</button>
<button id="animate" type="button">Start drift</button>
<button id="downloadSvg" type="button">Save SVG</button>
<button id="analyzePrime" type="button">Analyze modulus</button>
<button id="scanPrimes" type="button">Scan primes 1 to max</button>
</div>
</div>
<div class="control" style="margin-top: 14px;">
<label for="primeReport">Prime / inverse analysis</label>
<div id="primeReport" style="padding: 12px 14px; background: rgba(148, 163, 184, 0.10); border: 1px solid var(--border); border-radius: 16px; color: var(--text); font-size: 0.92rem; line-height: 1.4; min-height: 72px; white-space: pre-wrap;">Prime analysis ready.</div>
</div>
<div class="footer">
Each rectangle is generated in <code><svg></code>, then drawn into <code><canvas></code>.
The canvas stays under DOM control, so the surface can be updated, animated, or exported.
</div>
</section>
<section class="stage">
<div class="stage-head">
<div>
<strong>Rendered surface</strong>
<div class="meta" id="status">Ready</div>
</div>
</div>
<canvas id="surfaceCanvas" width="960" height="960"></canvas>
</section>
</div>
<script>
'use strict';
const els = {
gridSize: document.getElementById('gridSize'),
gridSizeValue: document.getElementById('gridSizeValue'),
cellSize: document.getElementById('cellSize'),
cellSizeValue: document.getElementById('cellSizeValue'),
modulus: document.getElementById('modulus'),
modulusValue: document.getElementById('modulusValue'),
power: document.getElementById('power'),
powerValue: document.getElementById('powerValue'),
mode: document.getElementById('mode'),
randomize: document.getElementById('randomize'),
animate: document.getElementById('animate'),
downloadSvg: document.getElementById('downloadSvg'),
analyzePrime: document.getElementById('analyzePrime'),
scanPrimes: document.getElementById('scanPrimes'),
primeReport: document.getElementById('primeReport'),
status: document.getElementById('status'),
canvas: document.getElementById('surfaceCanvas')
};
const ctx = els.canvas.getContext('2d', { alpha: false });
ctx.imageSmoothingEnabled = true;
const state = {
gridSize: 10,
cellSize: 48,
modulus: 10,
power: 0.65,
mode: 'mulmod',
phase: 0,
drift: false,
lastSvg: '',
renderQueued: false,
renderPending: false,
renderToken: 0,
effectiveCellSize: 48,
lastDrawRect: { dx: 0, dy: 0, drawW: els.canvas.width, drawH: els.canvas.height }
};
function setStatus(text, kind) {
els.status.textContent = text;
els.status.className = kind ? 'meta ' + kind : 'meta';
}
function syncOutputs() {
els.gridSizeValue.value = String(state.gridSize);
els.cellSizeValue.value = String(state.cellSize);
els.modulusValue.value = String(state.modulus);
els.powerValue.value = state.power.toFixed(2);
els.mode.value = state.mode;
}
function gcd(a, b) {
let x = Math.abs(a);
let y = Math.abs(b);
while (y !== 0) {
const t = y;
y = x % y;
x = t;
}
return x;
}
function extendedGcd(a, b) {
let oldR = a;
let r = b;
let oldS = 1;
let s = 0;
let oldT = 0;
let t = 1;
while (r !== 0) {
const q = Math.floor(oldR / r);
[oldR, r] = [r, oldR - q * r];
[oldS, s] = [s, oldS - q * s];
[oldT, t] = [t, oldT - q * t];
}
return { gcd: oldR, x: oldS, y: oldT };
}
function modInverse(a, n) {
if (n <= 1) return null;
const value = ((a % n) + n) % n;
if (value === 0) return null;
const result = extendedGcd(value, n);
if (Math.abs(result.gcd) !== 1) return null;
return ((result.x % n) + n) % n;
}
function analyzePrimeInvariants(n) {
const modulus = Math.max(1, Math.floor(n));
const units = [];
const nonUnits = [];
const zeroDivisors = [];
let permutationRows = 0;
for (let a = 1; a < modulus; a += 1) {
const inv = modInverse(a, modulus);
if (inv === null) {
nonUnits.push(a);
} else {
units.push({ value: a, inverse: inv });
}
const seen = new Set();
let isPermutationRow = true;
for (let b = 1; b < modulus; b += 1) {
const residue = (a * b) % modulus;
if (residue === 0) {
zeroDivisors.push(a + '×' + b);
}
if (seen.has(residue)) {
isPermutationRow = false;
}
seen.add(residue);
}
if (inv !== null && isPermutationRow && seen.size === Math.max(0, modulus - 1)) {
permutationRows += 1;
}
}
return {
modulus,
isPrimeByInvariants: modulus > 1 && nonUnits.length === 0,
unitCount: units.length,
units,
nonUnits,
zeroDivisors: Array.from(new Set(zeroDivisors)),
permutationRows
};
}
function scanPrimeCandidates(limit) {
const max = Math.max(1, Math.floor(limit));
const primes = [];
const composites = [];
for (let n = 2; n <= max; n += 1) {
const analysis = analyzePrimeInvariants(n);
if (analysis.isPrimeByInvariants) {
primes.push(n);
} else {
composites.push({
n,
nonUnits: analysis.nonUnits.length,
zeroDivisors: analysis.zeroDivisors.length
});
}
}
return { max, primes, composites };
}
function updatePrimeReport(text) {
els.primeReport.textContent = text;
}
function computeValue(x, y) {
const xi = x + 1;
const yi = y + 1;
const rawMul = xi * yi;
const modulus = Math.max(1, state.modulus);
switch (state.mode) {
case 'divbands':
return Math.floor(rawMul / modulus);
case 'addmod':
return (xi + yi) % modulus;
case 'submod':
return Math.abs(xi - yi) % modulus;
case 'primeinv': {
const residue = rawMul % modulus;
const inv = modInverse(residue, modulus);
return inv === null ? 0 : inv;
}
case 'mulmod':
default:
return rawMul % modulus;
}
}
function colorFor(value, x, y) {
const mod = Math.max(1, state.modulus);
const angle = (value / mod) * Math.PI * 2;
const wave = Math.sin((x + state.phase) * 0.31) * Math.cos((y - state.phase) * 0.27);
const light = 55 + 18 * Math.sin(angle) + wave * 18 * state.power;
const hue = ((value * (360 / mod)) + state.phase * 28) % 360;
const sat = 60 + Math.abs(wave) * 28;
const safeHue = ((hue % 360) + 360) % 360;
const safeLight = Math.max(18, Math.min(88, light));
return 'hsl(' + safeHue + ', ' + sat + '%, ' + safeLight + '%)';
}
function getSurfaceMetrics() {
const pad = 24;
const maxSurface = 1600;
const effectiveCellSize = Math.max(
1,
Math.min(state.cellSize, Math.floor(maxSurface / Math.max(1, state.gridSize)) || 1)
);
const surfaceSpan = Math.max(1, state.gridSize * effectiveCellSize);
return {
pad,
effectiveCellSize,
width: surfaceSpan + pad * 2,
height: surfaceSpan + pad * 2,
compacted: effectiveCellSize !== state.cellSize
};
}
function escapeXml(value) {
return String(value)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function buildSvg() {
const metrics = getSurfaceMetrics();
state.effectiveCellSize = metrics.effectiveCellSize;
const cell = metrics.effectiveCellSize;
const dense = state.gridSize >= 60 || cell <= 12;
const ultraDense = state.gridSize >= 85 || cell <= 7;
const showLabels = !dense && cell >= 28 && state.gridSize <= 36;
const useShadow = !ultraDense;
const strokeWidth = cell <= 3 ? 0 : 1;
const radius = Math.max(0, Math.min(10, cell * 0.12));
const parts = [];
parts.push('<svg xmlns="http://www.w3.org/2000/svg" width="' + metrics.width + '" height="' + metrics.height + '" viewBox="0 0 ' + metrics.width + ' ' + metrics.height + '">');
if (useShadow) {
parts.push('<defs><filter id="softShadow"><feDropShadow dx="0" dy="6" stdDeviation="8" flood-opacity="0.16"/></filter></defs>');
}
parts.push('<rect x="0" y="0" width="' + metrics.width + '" height="' + metrics.height + '" rx="28" fill="#ffffff"/>');
parts.push(useShadow ? '<g filter="url(#softShadow)">' : '<g>');
for (let y = 0; y < state.gridSize; y += 1) {
const py = metrics.pad + y * cell;
for (let x = 0; x < state.gridSize; x += 1) {
const value = computeValue(x, y);
const px = metrics.pad + x * cell;
const fill = colorFor(value, x, y);
const rectW = Math.max(1, cell - (strokeWidth ? 2 : 0));
const rectH = Math.max(1, cell - (strokeWidth ? 2 : 0));
parts.push('<rect x="' + px + '" y="' + py + '" width="' + rectW + '" height="' + rectH + '" rx="' + radius + '" fill="' + fill + '"' + (strokeWidth ? ' stroke="#ffffff" stroke-opacity="0.35" stroke-width="1"' : '') + '/>');
if (showLabels) {
const fontSize = Math.max(10, cell * 0.24);
parts.push('<text x="' + (px + cell / 2 - 1) + '" y="' + (py + cell / 2 + 5) + '" text-anchor="middle" font-size="' + fontSize + '" font-family="Inter, Arial, sans-serif" font-weight="700" fill="#0f172a" fill-opacity="0.78">' + escapeXml(value) + '</text>');
}
}
}
parts.push('</g></svg>');
return parts.join('');
}
function renderDirectToCanvas() {
const metrics = getSurfaceMetrics();
state.effectiveCellSize = metrics.effectiveCellSize;
const cell = metrics.effectiveCellSize;
const dense = state.gridSize >= 60 || cell <= 12;
const showLabels = !dense && cell >= 28 && state.gridSize <= 36;
const strokeWidth = cell <= 3 ? 0 : 1;
const radius = Math.max(0, Math.min(10, cell * 0.12));
ctx.clearRect(0, 0, els.canvas.width, els.canvas.height);
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, els.canvas.width, els.canvas.height);
const scale = Math.min(els.canvas.width / metrics.width, els.canvas.height / metrics.height);
const drawW = metrics.width * scale;
const drawH = metrics.height * scale;
const dx = (els.canvas.width - drawW) / 2;
const dy = (els.canvas.height - drawH) / 2;
state.lastDrawRect = { dx, dy, drawW, drawH };
ctx.save();
ctx.translate(dx, dy);
ctx.scale(scale, scale);
ctx.fillStyle = '#ffffff';
roundRectPath(ctx, 0, 0, metrics.width, metrics.height, 28);
ctx.fill();
for (let y = 0; y < state.gridSize; y += 1) {
const py = metrics.pad + y * cell;
for (let x = 0; x < state.gridSize; x += 1) {
const value = computeValue(x, y);
const px = metrics.pad + x * cell;
const rectW = Math.max(1, cell - (strokeWidth ? 2 : 0));
const rectH = Math.max(1, cell - (strokeWidth ? 2 : 0));
ctx.fillStyle = colorFor(value, x, y);
roundRectPath(ctx, px, py, rectW, rectH, radius);
ctx.fill();
if (strokeWidth) {
ctx.strokeStyle = 'rgba(255,255,255,0.35)';
ctx.lineWidth = 1;
ctx.stroke();
}
if (showLabels) {
const fontSize = Math.max(10, cell * 0.24);
ctx.fillStyle = 'rgba(15,23,42,0.78)';
ctx.font = '700 ' + fontSize + 'px Inter, Arial, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(String(value), px + cell / 2 - 1, py + cell / 2 + 3);
}
}
}
ctx.restore();
}
function roundRectPath(context, x, y, width, height, radius) {
const r = Math.max(0, Math.min(radius, width / 2, height / 2));
context.beginPath();
if (r === 0) {
context.rect(x, y, width, height);
return;
}
context.moveTo(x + r, y);
context.arcTo(x + width, y, x + width, y + height, r);
context.arcTo(x + width, y + height, x, y + height, r);
context.arcTo(x, y + height, x, y, r);
context.arcTo(x, y, x + width, y, r);
context.closePath();
}
function updateStatus(extra) {
const metrics = getSurfaceMetrics();
const suffix = extra || '';
const compactTag = metrics.compacted ? ' • fit ' + state.effectiveCellSize + 'px' : '';
setStatus(state.mode + ' • ' + state.gridSize + '×' + state.gridSize + ' • mod ' + state.modulus + ' • phase ' + state.phase.toFixed(2) + compactTag + suffix, '');
}
async function renderToCanvas() {
const token = ++state.renderToken;
state.lastSvg = buildSvg();
try {
renderDirectToCanvas();
if (token !== state.renderToken) {
return;
}
updateStatus();
} catch (error) {
setStatus('Render error: ' + (error instanceof Error ? error.message : String(error)), 'error');
}
}
function scheduleRender() {
state.renderPending = true;
if (state.renderQueued) return;
state.renderQueued = true;
requestAnimationFrame(async () => {
state.renderQueued = false;
if (!state.renderPending) return;
state.renderPending = false;
await renderToCanvas();
if (state.renderPending) scheduleRender();
});
}
function pullStateFromDom() {
state.gridSize = Number(els.gridSize.value);
state.cellSize = Number(els.cellSize.value);
state.modulus = Number(els.modulus.value);
state.power = Number(els.power.value);
state.mode = els.mode.value;
syncOutputs();
}
function stepSlider(slider, direction) {
const min = Number(slider.min || 0);
const max = Number(slider.max || 100);
const step = Number(slider.step && slider.step !== 'any' ? slider.step : 1);
const decimals = step < 1 ? ((String(step).split('.')[1] || '').length) : 0;
let next = Number(slider.value) + direction * step;
next = Math.min(max, Math.max(min, next));
slider.value = decimals > 0 ? next.toFixed(decimals) : String(Math.round(next));
}
function formatAnalysis(analysis) {
const unitsPreview = analysis.units.slice(0, 12).map((entry) => entry.value + '↔' + entry.inverse).join(', ');
const nonUnitsPreview = analysis.nonUnits.slice(0, 18).join(', ') || 'none';
const zeroPreview = analysis.zeroDivisors.slice(0, 18).join(', ') || 'none';
return [
'mod ' + analysis.modulus,
'prime-by-invariants: ' + (analysis.isPrimeByInvariants ? 'YES' : 'NO'),
'units/invertible residues: ' + analysis.unitCount + '/' + Math.max(0, analysis.modulus - 1),
'permutation rows: ' + analysis.permutationRows + '/' + Math.max(0, analysis.modulus - 1),
'non-units: ' + nonUnitsPreview,
'zero divisors: ' + zeroPreview,
'inverse pairs: ' + (unitsPreview || 'none')
].join('\n');
}
function attachEvents() {
[els.gridSize, els.cellSize, els.modulus, els.power, els.mode].forEach((el) => {
el.addEventListener('input', () => {
pullStateFromDom();
scheduleRender();
});
});
[els.gridSize, els.cellSize, els.modulus, els.power].forEach((slider) => {
slider.addEventListener('wheel', (event) => {
event.preventDefault();
const direction = event.deltaY > 0 ? -1 : 1;
stepSlider(slider, direction);
pullStateFromDom();
scheduleRender();
}, { passive: false });
});
els.randomize.addEventListener('click', () => {
state.phase = Math.random() * Math.PI * 2;
state.modulus = 1 + Math.floor(Math.random() * 100);
state.gridSize = 1 + Math.floor(Math.random() * 100);
state.cellSize = 1 + Math.floor(Math.random() * 100);
state.power = Number(((Math.random() * 2) - 1).toFixed(2));
els.modulus.value = String(state.modulus);
els.gridSize.value = String(state.gridSize);
els.cellSize.value = String(state.cellSize);
els.power.value = String(state.power);
syncOutputs();
scheduleRender();
});
els.animate.addEventListener('click', () => {
state.drift = !state.drift;
els.animate.textContent = state.drift ? 'Stop drift' : 'Start drift';
});
els.downloadSvg.addEventListener('click', () => {
const blob = new Blob([state.lastSvg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'surface_' + state.mode + '_' + state.gridSize + 'x' + state.gridSize + '.svg';
a.click();
URL.revokeObjectURL(url);
});
els.analyzePrime.addEventListener('click', () => {
updatePrimeReport(formatAnalysis(analyzePrimeInvariants(state.modulus)));
});
els.scanPrimes.addEventListener('click', () => {
const result = scanPrimeCandidates(state.modulus);
const primeList = result.primes.join(', ') || 'none';
updatePrimeReport([
'scan 2..' + result.max,
'prime candidates by invariant test:',
primeList,
'',
'method:',
'n is prime iff every nonzero residue mod n has an inverse.'
].join('\n'));
});
els.canvas.addEventListener('mousemove', (event) => {
const bounds = els.canvas.getBoundingClientRect();
const localX = ((event.clientX - bounds.left) / bounds.width) * els.canvas.width;
const localY = ((event.clientY - bounds.top) / bounds.height) * els.canvas.height;
const { dx, dy, drawW, drawH } = state.lastDrawRect;
if (localX < dx || localX > dx + drawW || localY < dy || localY > dy + drawH) {
updateStatus(' • outside surface');
return;
}
const nx = (localX - dx) / drawW;
const ny = (localY - dy) / drawH;
const cx = Math.max(0, Math.min(state.gridSize - 1, Math.floor(nx * state.gridSize)));
const cy = Math.max(0, Math.min(state.gridSize - 1, Math.floor(ny * state.gridSize)));
const value = computeValue(cx, cy);
setStatus(state.mode + ' • cell (' + (cx + 1) + ', ' + (cy + 1) + ') • value ' + value, '');
});
els.canvas.addEventListener('mouseleave', () => {
updateStatus();
});
}
function tick() {
if (state.drift) {
state.phase += 0.035;
scheduleRender();
}
requestAnimationFrame(tick);
}
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
function runSelfTests() {
assert(gcd(12, 18) === 6, 'gcd failed');
assert(modInverse(3, 7) === 5, 'inverse 3 mod 7 should be 5');
assert(modInverse(2, 4) === null, 'inverse 2 mod 4 should not exist');
assert(analyzePrimeInvariants(7).isPrimeByInvariants === true, '7 should test prime');
assert(analyzePrimeInvariants(8).isPrimeByInvariants === false, '8 should test composite');
assert(scanPrimeCandidates(10).primes.join(',') === '2,3,5,7', 'prime scan to 10 failed');
assert(computePreviewValue('mulmod', 10, 2, 3) === 12 % 10, 'preview mulmod failed');
assert(computePreviewValue('primeinv', 7, 0, 0) === 1, 'preview prime inverse failed');
}
function computePreviewValue(mode, modulus, x, y) {
const xi = x + 1;
const yi = y + 1;
const rawMul = xi * yi;
const safeMod = Math.max(1, modulus);
switch (mode) {
case 'divbands':
return Math.floor(rawMul / safeMod);
case 'addmod':
return (xi + yi) % safeMod;
case 'submod':
return Math.abs(xi - yi) % safeMod;
case 'primeinv': {
const residue = rawMul % safeMod;
const inv = modInverse(residue, safeMod);
return inv === null ? 0 : inv;
}
case 'mulmod':
default:
return rawMul % safeMod;
}
}
function init() {
syncOutputs();
attachEvents();
updatePrimeReport([
'Prime analysis ready.',
'Use Analyze modulus to inspect inverse structure.',
'Use Scan primes 1 to max to identify primes by invariant closure.'
].join('\n'));
try {
runSelfTests();
} catch (error) {
setStatus('Self-test failed: ' + error.message, 'error');
throw error;
}
scheduleRender();
requestAnimationFrame(tick);
setStatus('Ready', 'ok');
}
init();
</script>
</body>
</html>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am very curious to know why some prime in category make them special prime.. not sure I have ever seen prime categorized this high is reason.. down the rabbit hole I go!!! send search party if I dont make it back.