#!/usr/bin/env python3 # ============================================================================= # test_core.py — Phase 0 validation: DO NOT proceed while any test fails # Author: Simon-Pierre Boucher — contact@spboucher.ai # ============================================================================= # Validates every core building block against independently known values: # pi(10^k), maximal prime gaps below 10^6, strong-pseudoprime traps, # Carmichael numbers, cross-agreement sieve vs MR vs BPSW. # ============================================================================= import sys import time import numpy as np from core import (bpsw, gaps_in_range, is_prime, prime_count, primes_upto, sieve_segment) FAILURES = [] def check(name, got, expected): ok = got == expected print(f" [{'PASS' if ok else 'FAIL'}] {name}: got {got}, expected {expected}") if not ok: FAILURES.append(name) t0 = time.time() print("== pi(x) against known values ==") check("pi(10^2)", len(primes_upto(10**2)), 25) check("pi(10^4)", len(primes_upto(10**4)), 1229) check("pi(10^6)", len(primes_upto(10**6)), 78498) check("pi(10^7)", len(primes_upto(10**7)), 664579) check("pi(10^8) [segmented]", prime_count(10**8), 5761455) print("== segmented sieve == full sieve on random windows ==") full = primes_upto(2_000_000) for lo, hi in [(0, 1000), (999_000, 1_001_000), (1_500_000, 1_600_000)]: seg = sieve_segment(lo, hi) ref = full[(full >= lo) & (full < hi)] check(f"segment [{lo},{hi})", int(np.array_equal(seg, ref)), 1) print("== maximal prime gaps (known table, gaps starting below 10^6) ==") # (gap, prime after which it occurs) — classical table (OEIS A005250/A002386) KNOWN_MAXIMAL = [(4, 7), (6, 23), (8, 89), (14, 113), (18, 523), (20, 887), (22, 1129), (34, 1327), (36, 9551), (44, 15683), (52, 19609), (72, 31397), (86, 155921), (96, 360653), (112, 370261), (114, 492113)] best = 0 found = [] for p, g in gaps_in_range(2, 1_400_000): if g > best: best = g found.append((g, p)) found = [(g, p) for g, p in found if g >= 4 and p < 10**6] check("maximal gaps < 10^6", found, KNOWN_MAXIMAL) print("== Miller-Rabin deterministic: traps and cross-check ==") # strong pseudoprimes base 2 must be caught for n in [2047, 3277, 4033, 4681, 8321, 15841, 29341]: check(f"spsp(2) {n} composite", is_prime(n), False) # Carmichael numbers for n in [561, 1105, 1729, 41041, 825265, 321197185]: check(f"Carmichael {n} composite", is_prime(n), False) # known primes, including large check("2^31-1 prime", is_prime(2**31 - 1), True) check("2^61-1 prime", is_prime(2**61 - 1), True) check("2^67-1 composite (Mersenne)", is_prime(2**67 - 1), False) check("10^18+9 prime", is_prime(10**18 + 9), True) # cross-check MR vs sieve over [0, 40000) ref_set = set(primes_upto(40000).tolist()) mismatch = sum(1 for n in range(40000) if is_prime(n) != (n in ref_set)) check("MR == sieve on [0,40000)", mismatch, 0) print("== BPSW: same traps + cross-check ==") for n in [2047, 3277, 561, 1105, 1729, 41041]: check(f"BPSW {n} composite", bpsw(n), False) check("BPSW 2^61-1 prime", bpsw(2**61 - 1), True) check("BPSW 10^18+9 prime", bpsw(10**18 + 9), True) mismatch = sum(1 for n in range(3, 40000) if bpsw(n) != (n in ref_set)) check("BPSW == sieve on [3,40000)", mismatch, 0) # random 64-bit cross-check BPSW vs deterministic MR (fixed seed) rng = np.random.default_rng(42) vals = [int(x) for x in rng.integers(2**40, 2**62, size=300)] mismatch = sum(1 for n in vals if bpsw(n) != is_prime(n)) check("BPSW == det-MR on 300 random 62-bit (seed 42)", mismatch, 0) print(f"\nTotal time: {time.time()-t0:.1f}s") if FAILURES: print(f"FAILED: {FAILURES}") sys.exit(1) print("ALL TESTS PASSED")