use ferric_tensor::sched::Device;
use ferric_tensor::ws;
use std::process::{Command, Stdio};
use std::time::{Duration, Instant};
fn seq(n: usize, s: f32) -> Vec<f32> { (0..n).map(|i| (((i as f32 * 0.21 + s).sin())) * 0.3).collect() }
fn maxdiff(a: &[f32], b: &[f32]) -> f32 { a.iter().zip(b).map(|(x, y)| (x - y).abs()).fold(0.0, f32::max) }
fn main() {
let site = format!("{}/site", env!("CARGO_MANIFEST_DIR"));
let bridge = ws::start(site);
let url = format!("{}npu_worker.html", bridge.url());
println!("bridge serving {url} — launching Chrome with WebNN enabled…");
let chrome = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
let _ = std::fs::remove_dir_all("/tmp/ferric-npu");
let mut child = Command::new(chrome)
.args(["--headless=new", "--no-sandbox",
"--enable-features=WebMachineLearningNeuralNetwork,WebNN,Vulkan,WebGPU",
"--enable-experimental-web-platform-features", "--enable-unsafe-webgpu", "--use-angle=metal",
"--user-data-dir=/tmp/ferric-npu", &url])
.stdout(Stdio::null()).stderr(Stdio::null()).spawn().expect("launch chrome");
let t0 = Instant::now();
let conn = loop {
if let Some(c) = bridge.take_worker() { break c; }
if t0.elapsed() > Duration::from_secs(30) { let _ = child.kill(); panic!("browser never connected"); }
std::thread::sleep(Duration::from_millis(100));
};
let status = String::from_utf8_lossy(&conn.recv().expect("status frame")).into_owned(); let device = status.strip_prefix("WEBNN:").unwrap_or("?").to_string();
println!(" WebNN reported device: {device}");
if device == "NO_WEBNN" {
let _ = child.kill();
println!("⚠️ This Chrome build has no WebNN — code path is ready; enable WebNN or run on hardware/OS with an NPU driver.");
return;
}
let dev = Device::BrowserWorker(conn);
let (batch, m, k, n) = (2usize, 8, 6, 5);
let a = seq(batch * m * k, 1.0);
let b = seq(k * n, 2.0);
let got = dev.bmm(&a, &b, batch, m, k, n);
let cpu = Device::Cpu.bmm(&a, &b, batch, m, k, n);
let diff = maxdiff(&got, &cpu);
let _ = child.kill();
let tol = if device == "npu" { 2e-1 } else { 1e-3 };
println!(" matmul via WebNN:{device} · max|webnn-cpu| = {diff:.2e} (tol {tol:.0e})");
assert!(diff < tol, "WebNN result mismatch {diff}");
if device == "npu" {
println!("✅ Ferric ran compute ON THE NPU — WebNN(npu) → CoreML → Apple Neural Engine, matches CPU to fp16 precision ({diff:.1e})");
} else {
println!("✅ Ferric ran compute via WebNN (device: {device}) — NPU code path works; bound to {device} on this machine");
}
}