use vyre::DispatchConfig;
use vyre_driver_cuda::cuda_factory;
use weir::may_alias;
struct Lcg(u64);
impl Lcg {
fn new(seed: u64) -> Self {
Self(seed)
}
fn next_u32(&mut self) -> u32 {
self.0 = self
.0
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
(self.0 >> 32) as u32
}
}
#[test]
fn may_alias_cpu_gpu_parity_1000_fuzz_batch() {
let backend = cuda_factory().expect("CUDA backend unavailable on a GPU-required test host");
let words: u32 = 256;
let node_count = words * 32;
let prog = may_alias::may_alias(node_count, "pts_p", "pts_q", "intersect", "out_scalar");
let cfg = DispatchConfig::default();
let mut rng = Lcg::new(0xA11A_5C0F_F0E5);
for run in 0..1024 {
let mode = run % 4;
let p: Vec<u32> = (0..words).map(|_| rng.next_u32()).collect();
let q: Vec<u32> = match mode {
0 => p.iter().map(|w| !w).collect(), 1 => p.clone(), 2 => (0..words).map(|_| rng.next_u32()).collect(),
_ => (0..words)
.map(|i| if i == 0 { rng.next_u32() } else { 0 })
.collect(),
};
let p_b: Vec<u8> = vyre_primitives::wire::pack_u32_slice(&p);
let q_b: Vec<u8> = vyre_primitives::wire::pack_u32_slice(&q);
let inter_b: Vec<u8> = vec![0u8; (words as usize) * 4];
let inputs: [&[u8]; 3] = [&p_b, &q_b, &inter_b];
let outputs = backend
.dispatch_borrowed(&prog, &inputs, &cfg)
.unwrap_or_else(|e| panic!("may_alias run {run} dispatch failed: {e}"));
let scalar_bytes = outputs.last().expect("dispatch returned no outputs");
assert!(
scalar_bytes.len() >= 4,
"may_alias run {run}: scalar buffer too short ({} bytes)",
scalar_bytes.len()
);
let actual = u32::from_le_bytes([
scalar_bytes[0],
scalar_bytes[1],
scalar_bytes[2],
scalar_bytes[3],
]);
let expected = weir::oracle::summary::may_alias(&p, &q);
assert_eq!(
actual, expected,
"may_alias run {run}: GPU={actual} CPU={expected}"
);
}
}