vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Op-aware pathological inputs for u32 operations.
//!
//! Unlike the generic pathological generator (which only handles Bytes),
//! this targets specific primitive op edge cases:
//! - Shifts at exact boundaries (0, 31, 32, 33, `u32::MAX`)
//! - Division/modulo by 0, 1, power-of-2, divisor > dividend
//! - Overflow/underflow (MAX+1, 0-1, MAX*MAX)
//! - Rotations at 0, 16, 31, 32
//! - Signed boundary values when reinterpreted as i32
//! - extractBits/insertBits boundary values

use super::{pair_bytes, sig, triple_bytes, u32_bytes, InputGenerator};
use crate::spec::types::OpSignature;

/// Generates pathological u32 inputs that target known GPU/CPU divergence vectors.
pub struct U32Pathological;

impl InputGenerator for U32Pathological {
    fn name(&self) -> &'static str {
        "`u32` pathological"
    }

    fn handles(&self, signature: &OpSignature) -> bool {
        sig::is_u32_any(signature)
    }

    fn generate(&self, signature: &OpSignature, _seed: u64) -> Vec<(String, Vec<u8>)> {
        if sig::is_unary_u32(signature) {
            unary_pathological()
        } else if sig::is_binary_u32(signature) {
            binary_pathological()
        } else if sig::is_ternary_u32(signature) {
            ternary_pathological()
        } else {
            Vec::new()
        }
    }
}

fn unary_pathological() -> Vec<(String, Vec<u8>)> {
    vec![
        // i32 boundary values (reinterpreted as u32)
        ("patho:i32_min", u32_bytes(0x8000_0000)),
        ("patho:i32_max", u32_bytes(0x7FFF_FFFF)),
        ("patho:i32_neg1", u32_bytes(0xFFFF_FFFF)),
        // Single-bit patterns
        ("patho:single_msb", u32_bytes(0x8000_0000)),
        ("patho:single_lsb", u32_bytes(0x0000_0001)),
        // CLZ/CTZ specific
        ("patho:clz_1", u32_bytes(1)),             // clz=31, ctz=0
        ("patho:clz_max", u32_bytes(u32::MAX)),    // clz=0, ctz=0
        ("patho:clz_zero", u32_bytes(0)),          // clz=32, ctz=32
        ("patho:clz_msb", u32_bytes(0x8000_0000)), // clz=0, ctz=31
        // Reverse-bits palindromes
        ("patho:reverse_palindrome", u32_bytes(0x8001_0080)),
        ("patho:reverse_all_high", u32_bytes(0xFFFF_0000)),
    ]
    .into_iter()
    .map(|(label, bytes)| (label.to_string(), bytes))
    .collect()
}

fn binary_pathological() -> Vec<(String, Vec<u8>)> {
    let mut out = Vec::new();

    // Shift boundaries — the #1 GPU/CPU divergence vector
    for shift in [0, 1, 15, 16, 30, 31, 32, 33, 63, u32::MAX] {
        out.push((
            format!("patho:shift:{shift}"),
            pair_bytes(0xDEAD_BEEF, shift),
        ));
        out.push((format!("patho:shift_one:{shift}"), pair_bytes(1, shift)));
        out.push((
            format!("patho:shift_max:{shift}"),
            pair_bytes(u32::MAX, shift),
        ));
    }

    // Division/modulo edge cases
    for divisor in [0, 1, 2, 3, 7, 16, 256, u32::MAX] {
        out.push((format!("patho:div_by:{divisor}"), pair_bytes(100, divisor)));
        out.push((
            format!("patho:div_max_by:{divisor}"),
            pair_bytes(u32::MAX, divisor),
        ));
        out.push((
            format!("patho:div_zero_by:{divisor}"),
            pair_bytes(0, divisor),
        ));
    }

    // Arithmetic overflow
    out.push(("patho:add_overflow".to_string(), pair_bytes(u32::MAX, 1)));
    out.push((
        "patho:add_overflow2".to_string(),
        pair_bytes(u32::MAX, u32::MAX),
    ));
    out.push(("patho:sub_underflow".to_string(), pair_bytes(0, 1)));
    out.push(("patho:sub_underflow2".to_string(), pair_bytes(0, u32::MAX)));
    out.push((
        "patho:mul_overflow".to_string(),
        pair_bytes(u32::MAX, u32::MAX),
    ));
    out.push((
        "patho:mul_overflow2".to_string(),
        pair_bytes(0x10000, 0x10000),
    ));
    out.push(("patho:mul_by_zero".to_string(), pair_bytes(u32::MAX, 0)));

    // Comparison boundary: equal values at extremes
    out.push(("patho:eq_zero".to_string(), pair_bytes(0, 0)));
    out.push(("patho:eq_max".to_string(), pair_bytes(u32::MAX, u32::MAX)));
    out.push((
        "patho:cmp_adjacent".to_string(),
        pair_bytes(u32::MAX - 1, u32::MAX),
    ));

    // Rotation at exact word boundary
    out.push(("patho:rot_0".to_string(), pair_bytes(0xDEAD_BEEF, 0)));
    out.push(("patho:rot_16".to_string(), pair_bytes(0xDEAD_BEEF, 16)));
    out.push(("patho:rot_32".to_string(), pair_bytes(0xDEAD_BEEF, 32)));

    // extractBits / insertBits edge cases (packed format)
    for offset in [0, 1, 16, 31] {
        for count in [0, 1, 16, 31] {
            let packed = offset | (count << 5);
            out.push((
                format!("patho:extract:off{offset}_cnt{count}"),
                pair_bytes(0xDEAD_BEEF, packed),
            ));
        }
    }

    // Clamp boundary cases (packed format: low=lower 16, high=upper 16 | low)
    out.push(("patho:clamp_zero_bounds".to_string(), pair_bytes(50, 0)));
    out.push((
        "patho:clamp_max_bounds".to_string(),
        pair_bytes(50, 0xFFFF_FFFF),
    ));
    out.push(("patho:clamp_at_low".to_string(), pair_bytes(0, 0x0005_0003)));
    out.push((
        "patho:clamp_at_high".to_string(),
        pair_bytes(u32::MAX, 0x0005_0003),
    ));

    out
}

fn ternary_pathological() -> Vec<(String, Vec<u8>)> {
    [
        ("patho:ternary_zero_span", 0, 0, 0),
        ("patho:ternary_full_span", u32::MAX, 0, 32),
        ("patho:ternary_cross_boundary", 0xDEAD_BEEF, 31, 33),
        (
            "patho:ternary_signed_edges",
            i32::MIN as u32,
            i32::MAX as u32,
            u32::MAX,
        ),
    ]
    .into_iter()
    .map(|(label, a, b, c)| (label.to_string(), triple_bytes(a, b, c)))
    .collect()
}