use std::f64::consts::TAU;
const D: usize = 1024;
const FACTORS: usize = 3;
const ITERS: usize = 40;
const SEEDS: u64 = 24;
const TRIALS: usize = 32;
type Cx = (Vec<f64>, Vec<f64>);
fn mix(x: u64, k: u64) -> u64 {
let mut h = x.wrapping_mul(0x9E37_79B9_7F4A_7C15) ^ k.wrapping_mul(0xC2B2_AE3D_27D4_EB4F);
h ^= h >> 29;
h = h.wrapping_mul(0xBF58_476D_1CE4_E5B9);
h ^= h >> 32;
h
}
fn phase_vec(id: usize, axis: usize, seed: u64, n: u32) -> Cx {
let mut re = vec![0.0; D];
let mut im = vec![0.0; D];
for d in 0..D {
let raw = mix((id as u64) << 20 | (axis as u64) << 40 | d as u64, seed);
let phase = if n == 0 {
(raw as f64 / u64::MAX as f64) * TAU
} else {
TAU * (raw % n as u64) as f64 / n as f64
};
re[d] = phase.cos();
im[d] = phase.sin();
}
(re, im)
}
fn g(v: &mut Cx, n: u32) {
for d in 0..D {
let phase = v.1[d].atan2(v.0[d]);
let p = if n == 0 {
phase
} else {
let idx = (phase / TAU * n as f64).round() as i64;
TAU * idx.rem_euclid(n as i64) as f64 / n as f64
};
v.0[d] = p.cos();
v.1[d] = p.sin();
}
}
fn cmul(a: &Cx, b: &Cx) -> Cx {
let mut r = vec![0.0; D];
let mut i = vec![0.0; D];
for d in 0..D {
r[d] = a.0[d] * b.0[d] - a.1[d] * b.1[d];
i[d] = a.0[d] * b.1[d] + a.1[d] * b.0[d];
}
(r, i)
}
fn conj(a: &Cx) -> Cx {
(a.0.clone(), a.1.iter().map(|&x| -x).collect())
}
fn sim(cb: &Cx, v: &Cx) -> f64 {
let mut s = 0.0;
for d in 0..D {
s += cb.0[d] * v.0[d] + cb.1[d] * v.1[d];
}
s
}
fn cleanup(cb: &[Cx], v: &Cx, n: u32) -> Cx {
let sims: Vec<f64> = cb.iter().map(|c| sim(c, v)).collect();
let mut out: Cx = (vec![0.0; D], vec![0.0; D]);
for (k, c) in cb.iter().enumerate() {
let s = sims[k];
for d in 0..D {
out.0[d] += s * c.0[d];
out.1[d] += s * c.1[d];
}
}
g(&mut out, n);
out
}
fn argmax(cb: &[Cx], v: &Cx) -> usize {
(0..cb.len())
.map(|k| (k, sim(&cb[k], v)))
.max_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
.unwrap()
.0
}
fn superpose_init(cb: &[Cx], n: u32) -> Cx {
let mut acc: Cx = (vec![0.0; D], vec![0.0; D]);
for c in cb {
for d in 0..D {
acc.0[d] += c.0[d];
acc.1[d] += c.1[d];
}
}
g(&mut acc, n);
acc
}
fn accuracy(f: usize, n: u32) -> (f64, f64) {
let mut per_seed = Vec::with_capacity(SEEDS as usize);
for seed in 0..SEEDS {
let books: Vec<Vec<Cx>> = (0..FACTORS)
.map(|axis| (0..f).map(|i| phase_vec(i, axis, seed, n)).collect())
.collect();
let mut ok = 0i64;
for t in 0..TRIALS {
let truth: Vec<usize> = (0..FACTORS)
.map(|axis| (mix(t as u64, seed ^ (0x10 + axis as u64)) % f as u64) as usize)
.collect();
let mut comp = books[0][truth[0]].clone();
for axis in 1..FACTORS {
comp = cmul(&comp, &books[axis][truth[axis]]);
}
let mut est: Vec<Cx> = (0..FACTORS)
.map(|axis| superpose_init(&books[axis], n))
.collect();
let mut prev = vec![usize::MAX; FACTORS];
let mut stable = 0;
for _ in 0..ITERS {
for axis in 0..FACTORS {
let mut ub = comp.clone();
for (j, e) in est.iter().enumerate() {
if j != axis {
ub = cmul(&ub, &conj(e));
}
}
est[axis] = cleanup(&books[axis], &ub, n);
}
let cur: Vec<usize> = (0..FACTORS)
.map(|axis| argmax(&books[axis], &est[axis]))
.collect();
if cur == prev {
stable += 1;
if stable >= 3 {
break;
}
} else {
stable = 0;
}
prev = cur;
}
ok += (prev == truth) as i64;
}
per_seed.push(100.0 * ok as f64 / TRIALS as f64);
}
let mean = per_seed.iter().sum::<f64>() / per_seed.len() as f64;
let var = per_seed.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / per_seed.len() as f64;
(mean, var.sqrt())
}
fn main() {
let fs = [16usize, 24, 32, 40, 48];
let ns: [(u32, &str); 3] = [(0, "float"), (256, "N=256"), (16, "N=16(4bit)")];
println!(
"resonator-factorize | D={D} factors={FACTORS} iters={ITERS} seeds={SEEDS} trials={TRIALS}"
);
println!("3-factor factorization accuracy mean±std over seeds (%), chance = 1/F^3\n");
print!("{:>10}", "F(F^3)");
for (_, label) in ns {
print!(" {label:>11}");
}
println!();
for f in fs {
print!("{:>10}", format!("{f}({})", f * f * f));
for (n, _) in ns {
let (m, sd) = accuracy(f, n);
print!(" {:>7.0}±{:<3.0}", m, sd);
}
println!();
}
println!("\nStrong: N=256 (even N=16-32) tracks float across the knee -> quantization is");
println!("free for factorization -> deterministic resonator is real (qFHRR + Frady/Kent).");
println!("Kill: quantized knee shifts left of float -> quantization costs capacity.");
}