spectral_vm 0.1.6

HYPERION: Production-ready zero-knowledge virtual machine with spectral analysis
Documentation
/*
 * ═══════════════════════════════════════════════════════════════════════════
 * UNIT TESTS: Goldilocks Field Arithmetic
 * ═══════════════════════════════════════════════════════════════════════════
 */

use spectral_vm::field::Goldilocks;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_goldilocks_creation() {
        let a = Goldilocks::from_i64(42);
        assert_eq!(a.0, 42);

        let b = Goldilocks::new(100);
        assert_eq!(b.0, 100);
    }

    #[test]
    fn test_goldilocks_addition() {
        let a = Goldilocks::from_i64(10);
        let b = Goldilocks::from_i64(20);
        let c = a.add(b);
        assert_eq!(c.0, 30);

        // Test modular reduction
        let d = Goldilocks::from_i64(0xFFFFFFFF00000000); // Large number
        let e = Goldilocks::from_i64(1);
        let f = d.add(e);
        // Should be properly reduced
        assert!(f.0 < 0xFFFFFFFF00000001); // Less than P
    }

    #[test]
    fn test_goldilocks_subtraction() {
        let a = Goldilocks::from_i64(20);
        let b = Goldilocks::from_i64(10);
        let c = a.sub(b);
        assert_eq!(c.0, 10);

        // Test underflow handling
        let d = Goldilocks::from_i64(10);
        let e = Goldilocks::from_i64(20);
        let f = d.sub(e);
        // Should wrap around: P - (20 - 10) = P - 10
        assert_eq!(f.0, 0xFFFFFFFF00000001 - 10);
    }

    #[test]
    fn test_goldilocks_multiplication() {
        let a = Goldilocks::from_i64(6);
        let b = Goldilocks::from_i64(7);
        let c = a.mul(b);
        assert_eq!(c.0, 42);

        // Test with larger numbers requiring reduction
        let d = Goldilocks::from_i64(1000000);
        let e = Goldilocks::from_i64(2000000);
        let f = d.mul(e);
        // Should be properly reduced
        assert!(f.0 < 0xFFFFFFFF00000001);
    }

    #[test]
    fn test_goldilocks_arithmetic_properties() {
        let a = Goldilocks::from_i64(12345);
        let b = Goldilocks::from_i64(67890);
        let c = Goldilocks::from_i64(11111);

        // Test associativity: (a + b) + c == a + (b + c)
        let left = a.add(b).add(c);
        let right = a.add(b.add(c));
        assert_eq!(left, right);

        // Test commutativity: a + b == b + a
        let ab = a.add(b);
        let ba = b.add(a);
        assert_eq!(ab, ba);

        // Test distributivity: a * (b + c) == a*b + a*c
        let dist_left = a.mul(b.add(c));
        let dist_right = a.mul(b).add(a.mul(c));
        assert_eq!(dist_left, dist_right);
    }

    #[test]
    fn test_goldilocks_edge_cases() {
        // Test with zero
        let zero = Goldilocks::from_i64(0);
        let a = Goldilocks::from_i64(42);
        assert_eq!(a.add(zero), a);
        assert_eq!(a.mul(zero), zero);

        // Test with one
        let one = Goldilocks::from_i64(1);
        assert_eq!(a.mul(one), a);

        // Test with P-1 (largest field element)
        let max_val = Goldilocks::new(0xFFFFFFFF00000000);
        let result = max_val.add(one);
        assert_eq!(result.0, 0); // Should wrap to 0
    }

    #[test]
    fn test_goldilocks_inverse() {
        let a = Goldilocks::from_i64(42);
        let inv_a = a.inv();

        // Test that a * a^(-1) = 1
        let product = a.mul(inv_a);
        assert_eq!(product.0, 1);

        // Test inverse of inverse
        let inv_inv_a = inv_a.inv();
        assert_eq!(inv_inv_a, a);
    }

    #[test]
    fn test_goldilocks_constants() {
        use spectral_vm::field::P;
        assert_eq!(P, 0xFFFFFFFF00000001);

        // Test that P is prime (basic check)
        let p_minus_1 = Goldilocks::new(P - 1);
        let one = Goldilocks::from_i64(1);
        // Fermat's little theorem: a^(p-1) ≡ 1 mod p for a ≠ 0
        // We can't easily test this for large exponents, but basic properties hold
        assert_eq!(p_minus_1.add(one).0, 0); // P - 1 + 1 = P ≡ 0
    }

    #[test]
    fn test_goldilocks_serialization() {
        let a = Goldilocks::from_i64(12345);

        // Test serde serialization (requires serde feature)
        let serialized = serde_json::to_string(&a).unwrap();
        let deserialized: Goldilocks = serde_json::from_str(&serialized).unwrap();

        assert_eq!(a, deserialized);
    }

    #[test]
    fn test_goldilocks_display() {
        let a = Goldilocks::from_i64(42);
        assert_eq!(format!("{}", a), "42");
    }
}