vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
#![cfg(feature = "gpu")]

use vyre::engine::dfa::GpuDfa;

const CLASSES: usize = 256;

#[test]
fn gpu_dfa_scans_ab_and_cd() {
    let (device, queue) = match vyre_wgpu::runtime::cached_device() {
        Ok(pair) => pair,
        Err(error) => {
            panic!("GPU required on this machine (RTX 5090 / 4090 available per project invariant) — do not silently skip: DFA integration test: {error}");
            return;
        }
    };

    let state_count = 5;
    let mut transitions = vec![0u32; state_count * CLASSES];
    transitions[b'a' as usize] = 1;
    transitions[CLASSES + b'b' as usize] = 2;
    transitions[b'c' as usize] = 3;
    transitions[3 * CLASSES + b'd' as usize] = 4;

    let dfa = GpuDfa::compile(
        device,
        &transitions,
        state_count,
        &[(2, 0), (4, 1)],
        &[0xFFFF_FFFF; 5],
        &[2, 2],
    )
    .expect("valid DFA");

    let matches = dfa
        .scan(device, queue, b"xxabxxcdxx", None)
        .expect("GPU scan");
    // The DFA dispatches one thread per byte position. Each thread independently
    // scans from its start offset, so multiple threads can find the same patterns
    // at different starting positions. Verify both pattern IDs are present.
    assert!(
        matches.len() >= 2,
        "expected at least 2 matches, got {}",
        matches.len()
    );
    let found_ids: std::collections::BTreeSet<u32> = matches.iter().map(|m| m.pattern_id).collect();
    assert!(
        found_ids.contains(&0),
        "pattern 0 ('ab') not found: {matches:?}"
    );
    assert!(
        found_ids.contains(&1),
        "pattern 1 ('cd') not found: {matches:?}"
    );
}