vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Algebraic property tests for CPU reference functions.
//!
//! Verifies mathematical invariants that must hold for all inputs:
//! commutativity, identity elements, annihilators, involution,
//! and complementarity relationships between operations.
//!
//! These tests catch semantic errors that golden samples alone cannot
//! (e.g., operand swaps, off-by-one in masking, wrong identity element).

#[cfg(test)]
mod tests {

    use crate::spec::primitive;

    fn cpu(id: &str, input: &[u8]) -> Vec<u8> {
        let specs = primitive::specs();
        let spec = specs.iter().find(|s| s.id == id).unwrap();
        (spec.cpu_fn)(input)
    }

    fn pair(a: u32, b: u32) -> Vec<u8> {
        let mut v = a.to_le_bytes().to_vec();
        v.extend_from_slice(&b.to_le_bytes());
        v
    }

    fn unary(a: u32) -> Vec<u8> {
        a.to_le_bytes().to_vec()
    }

    fn result_u32(bytes: &[u8]) -> u32 {
        u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
    }

    // ── Commutativity ────────────────────────────────────────

    #[test]
    fn xor_is_commutative() {
        for (a, b) in [(0, 0), (1, 2), (0xDEAD, 0xBEEF), (u32::MAX, 0)] {
            assert_eq!(
                cpu("primitive.bitwise.xor", &pair(a, b)),
                cpu("primitive.bitwise.xor", &pair(b, a)),
                "xor({a}, {b}) != xor({b}, {a})"
            );
        }
    }

    #[test]
    fn and_is_commutative() {
        for (a, b) in [(0xFF, 0x0F), (u32::MAX, 0), (123, 456)] {
            assert_eq!(
                cpu("primitive.bitwise.and", &pair(a, b)),
                cpu("primitive.bitwise.and", &pair(b, a))
            );
        }
    }

    #[test]
    fn or_is_commutative() {
        for (a, b) in [(0xF0, 0x0F), (0, u32::MAX), (42, 99)] {
            assert_eq!(
                cpu("primitive.bitwise.or", &pair(a, b)),
                cpu("primitive.bitwise.or", &pair(b, a))
            );
        }
    }

    #[test]
    fn add_is_commutative() {
        for (a, b) in [(0, 0), (1, u32::MAX), (0x8000_0000, 1)] {
            assert_eq!(
                cpu("primitive.math.add", &pair(a, b)),
                cpu("primitive.math.add", &pair(b, a))
            );
        }
    }

    #[test]
    fn mul_is_commutative() {
        for (a, b) in [(0, 1), (7, 13), (u32::MAX, 2)] {
            assert_eq!(
                cpu("primitive.math.mul", &pair(a, b)),
                cpu("primitive.math.mul", &pair(b, a))
            );
        }
    }

    #[test]
    fn min_is_commutative() {
        for (a, b) in [(5, 10), (u32::MAX, 0), (42, 42)] {
            assert_eq!(
                cpu("primitive.math.min", &pair(a, b)),
                cpu("primitive.math.min", &pair(b, a))
            );
        }
    }

    #[test]
    fn max_is_commutative() {
        for (a, b) in [(5, 10), (u32::MAX, 0), (42, 42)] {
            assert_eq!(
                cpu("primitive.math.max", &pair(a, b)),
                cpu("primitive.math.max", &pair(b, a))
            );
        }
    }

    #[test]
    fn eq_is_commutative() {
        for (a, b) in [(0, 0), (1, 2), (u32::MAX, u32::MAX)] {
            assert_eq!(
                cpu("primitive.compare.eq", &pair(a, b)),
                cpu("primitive.compare.eq", &pair(b, a))
            );
        }
    }

    #[test]
    fn ne_is_commutative() {
        for (a, b) in [(0, 0), (1, 2), (u32::MAX, 0)] {
            assert_eq!(
                cpu("primitive.compare.ne", &pair(a, b)),
                cpu("primitive.compare.ne", &pair(b, a))
            );
        }
    }

    // ── Identity elements ───────────────────────────────────

    #[test]
    fn xor_identity_is_zero() {
        for a in [0, 1, 42, u32::MAX, 0x8000_0000] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.xor", &pair(a, 0))), a);
        }
    }

    #[test]
    fn and_identity_is_max() {
        for a in [0, 1, 42, u32::MAX] {
            assert_eq!(
                result_u32(&cpu("primitive.bitwise.and", &pair(a, u32::MAX))),
                a
            );
        }
    }

    #[test]
    fn or_identity_is_zero() {
        for a in [0, 1, 42, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.or", &pair(a, 0))), a);
        }
    }

    #[test]
    fn add_identity_is_zero() {
        for a in [0, 1, u32::MAX, 0x8000_0000] {
            assert_eq!(result_u32(&cpu("primitive.math.add", &pair(a, 0))), a);
        }
    }

    #[test]
    fn mul_identity_is_one() {
        for a in [0, 1, 42, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.mul", &pair(a, 1))), a);
        }
    }

    #[test]
    fn sub_identity_is_zero() {
        for a in [0, 1, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.sub", &pair(a, 0))), a);
        }
    }

    #[test]
    fn div_identity_is_one() {
        for a in [0, 1, 42, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.div", &pair(a, 1))), a);
        }
    }

    // ── Annihilators and absorbers ──────────────────────────

    #[test]
    fn and_annihilator_is_zero() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.and", &pair(a, 0))), 0);
        }
    }

    #[test]
    fn or_annihilator_is_max() {
        for a in [0, 1, u32::MAX] {
            assert_eq!(
                result_u32(&cpu("primitive.bitwise.or", &pair(a, u32::MAX))),
                u32::MAX
            );
        }
    }

    #[test]
    fn mul_annihilator_is_zero() {
        for a in [0, 1, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.mul", &pair(a, 0))), 0);
        }
    }

    // ── Involution (self-inverse) ───────────────────────────

    #[test]
    fn xor_self_is_zero() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.xor", &pair(a, a))), 0);
        }
    }

    #[test]
    fn not_is_involution() {
        for a in [0, 1, u32::MAX, 0x5555_5555] {
            let once = cpu("primitive.bitwise.not", &unary(a));
            let twice = cpu("primitive.bitwise.not", &once);
            assert_eq!(result_u32(&twice), a, "not(not({a})) != {a}");
        }
    }

    #[test]
    fn negate_is_involution() {
        for a in [0, 1, u32::MAX, 0x8000_0000] {
            let once = cpu("primitive.math.negate", &unary(a));
            let twice = cpu("primitive.math.negate", &once);
            assert_eq!(result_u32(&twice), a, "negate(negate({a})) != {a}");
        }
    }

    #[test]
    fn reverse_bits_is_involution() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            let once = cpu("primitive.bitwise.reverse_bits", &unary(a));
            let twice = cpu("primitive.bitwise.reverse_bits", &once);
            assert_eq!(result_u32(&twice), a, "reverse(reverse({a})) != {a}");
        }
    }

    // ── Subtraction is not commutative (anti-symmetry check) ──

    #[test]
    fn sub_is_not_commutative() {
        let a_minus_b = result_u32(&cpu("primitive.math.sub", &pair(5, 3)));
        let b_minus_a = result_u32(&cpu("primitive.math.sub", &pair(3, 5)));
        assert_ne!(a_minus_b, b_minus_a, "sub must not be commutative");
    }

    // ── Comparison complementarity ──────────────────────────

    #[test]
    fn eq_and_ne_are_complementary() {
        for (a, b) in [(0, 0), (1, 2), (u32::MAX, u32::MAX - 1)] {
            let eq = result_u32(&cpu("primitive.compare.eq", &pair(a, b)));
            let ne = result_u32(&cpu("primitive.compare.ne", &pair(a, b)));
            assert_eq!(eq + ne, 1, "eq({a},{b}) + ne({a},{b}) should be 1");
        }
    }

    #[test]
    fn lt_and_ge_are_complementary() {
        for (a, b) in [(0, 1), (1, 0), (5, 5), (u32::MAX, 0)] {
            let lt = result_u32(&cpu("primitive.compare.lt", &pair(a, b)));
            let ge = result_u32(&cpu("primitive.compare.ge", &pair(a, b)));
            assert_eq!(lt + ge, 1, "lt({a},{b}) + ge({a},{b}) should be 1");
        }
    }

    #[test]
    fn gt_and_le_are_complementary() {
        for (a, b) in [(0, 1), (1, 0), (5, 5), (u32::MAX, 0)] {
            let gt = result_u32(&cpu("primitive.compare.gt", &pair(a, b)));
            let le = result_u32(&cpu("primitive.compare.le", &pair(a, b)));
            assert_eq!(gt + le, 1, "gt({a},{b}) + le({a},{b}) should be 1");
        }
    }

    // ── Shift boundary properties ───────────────────────────

    #[test]
    fn shl_by_zero_is_identity() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.shl", &pair(a, 0))), a);
        }
    }

    #[test]
    fn shr_by_zero_is_identity() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.shr", &pair(a, 0))), a);
        }
    }

    #[test]
    fn shl_by_32_is_zero() {
        for a in [1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.shl", &pair(a, 32))), 0);
        }
    }

    #[test]
    fn shr_by_32_is_zero() {
        for a in [1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.shr", &pair(a, 32))), 0);
        }
    }

    // ── Popcount cross-validation ───────────────────────────

    #[test]
    fn popcount_hw_matches_popcount_sw() {
        for a in [0, 1, 0xFF, 0x5555_5555, 0xAAAA_AAAA, u32::MAX, 0x8000_0000] {
            let hw = cpu("primitive.bitwise.popcount", &unary(a));
            let sw = cpu("primitive.bitwise.popcount_sw", &unary(a));
            assert_eq!(hw, sw, "popcount HW != SW for {a:#010x}");
        }
    }

    // ── Division by zero policy ─────────────────────────────

    #[test]
    fn div_by_zero_returns_zero() {
        for a in [0, 1, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.div", &pair(a, 0))), 0);
        }
    }

    #[test]
    fn mod_by_zero_returns_zero() {
        for a in [0, 1, u32::MAX] {
            assert_eq!(result_u32(&cpu("primitive.math.mod", &pair(a, 0))), 0);
        }
    }

    // ── CLZ + CTZ + popcount identity ───────────────────────

    #[test]
    fn clz_plus_ctz_plus_popcount_for_power_of_two() {
        // For a power of 2 (single bit set), clz + ctz + 1 = 32.
        for shift in 0..32 {
            let val = 1u32 << shift;
            let clz = result_u32(&cpu("primitive.bitwise.clz", &unary(val)));
            let ctz = result_u32(&cpu("primitive.bitwise.ctz", &unary(val)));
            let pop = result_u32(&cpu("primitive.bitwise.popcount", &unary(val)));
            assert_eq!(
                clz + ctz + pop,
                32,
                "clz({val}) + ctz({val}) + popcount({val}) = {clz}+{ctz}+{pop} != 32"
            );
        }
    }

    // ── Rotation identity ───────────────────────────────────

    #[test]
    fn rotl_by_zero_is_identity() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.rotl", &pair(a, 0))), a);
        }
    }

    #[test]
    fn rotr_by_zero_is_identity() {
        for a in [0, 1, u32::MAX, 0xDEAD_BEEF] {
            assert_eq!(result_u32(&cpu("primitive.bitwise.rotr", &pair(a, 0))), a);
        }
    }

    #[test]
    fn rotl_then_rotr_is_identity() {
        for a in [0xDEAD_BEEF, 0xFF00_00FF, 1] {
            for rot in [1, 7, 16, 31] {
                let rotated = result_u32(&cpu("primitive.bitwise.rotl", &pair(a, rot)));
                let restored = result_u32(&cpu("primitive.bitwise.rotr", &pair(rotated, rot)));
                assert_eq!(restored, a, "rotl({a:#x},{rot}) then rotr != identity");
            }
        }
    }

    mod declared_laws;
}