use proptest::prelude::*;
use trueno::{Backend, Vector};
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn integration_backend_consistency(
data in prop::collection::vec(-50.0f32..50.0, 50..100)
) {
let v_auto = Vector::from_slice(&data);
let v_scalar = Vector::from_slice_with_backend(&data, Backend::Scalar);
let sum_auto = v_auto.sum()?;
let sum_scalar = v_scalar.sum()?;
prop_assert!((sum_auto - sum_scalar).abs() < 1e-3 * sum_scalar.abs().max(1.0));
let max_auto = v_auto.max()?;
let max_scalar = v_scalar.max()?;
prop_assert_eq!(max_auto, max_scalar);
}
#[test]
fn integration_backend_equivalence_activations(
data in prop::collection::vec(-10.0f32..10.0, 50..100)
) {
let v_scalar = Vector::from_slice_with_backend(&data, Backend::Scalar);
let v_auto = Vector::from_slice(&data);
let relu_scalar = v_scalar.relu()?;
let relu_auto = v_auto.relu()?;
for (s, a) in relu_scalar.as_slice().iter().zip(relu_auto.as_slice().iter()) {
prop_assert!((s - a).abs() < 1e-5, "ReLU mismatch: scalar={}, auto={}", s, a);
}
let sigmoid_scalar = v_scalar.sigmoid()?;
let sigmoid_auto = v_auto.sigmoid()?;
for (s, a) in sigmoid_scalar.as_slice().iter().zip(sigmoid_auto.as_slice().iter()) {
prop_assert!((s - a).abs() < 1e-5, "Sigmoid mismatch: scalar={}, auto={}", s, a);
}
let gelu_scalar = v_scalar.gelu()?;
let gelu_auto = v_auto.gelu()?;
for (s, a) in gelu_scalar.as_slice().iter().zip(gelu_auto.as_slice().iter()) {
prop_assert!((s - a).abs() < 1e-4, "GELU mismatch: scalar={}, auto={}", s, a);
}
let swish_scalar = v_scalar.swish()?;
let swish_auto = v_auto.swish()?;
for (s, a) in swish_scalar.as_slice().iter().zip(swish_auto.as_slice().iter()) {
prop_assert!((s - a).abs() < 1e-5, "Swish mismatch: scalar={}, auto={}", s, a);
}
}
#[test]
fn integration_backend_equivalence_norms(
data in prop::collection::vec(-50.0f32..50.0, 50..100)
) {
let v_scalar = Vector::from_slice_with_backend(&data, Backend::Scalar);
let v_auto = Vector::from_slice(&data);
let l1_scalar = v_scalar.norm_l1()?;
let l1_auto = v_auto.norm_l1()?;
prop_assert!((l1_scalar - l1_auto).abs() < 1e-3 * l1_scalar.abs().max(1.0),
"L1 norm mismatch: scalar={}, auto={}", l1_scalar, l1_auto);
let l2_scalar = v_scalar.norm_l2()?;
let l2_auto = v_auto.norm_l2()?;
prop_assert!((l2_scalar - l2_auto).abs() < 1e-3 * l2_scalar.abs().max(1.0),
"L2 norm mismatch: scalar={}, auto={}", l2_scalar, l2_auto);
let dot_scalar = v_scalar.dot(&v_scalar)?;
let dot_auto = v_auto.dot(&v_auto)?;
prop_assert!((dot_scalar - dot_auto).abs() < 1e-3 * dot_scalar.abs().max(1.0),
"Dot product mismatch: scalar={}, auto={}", dot_scalar, dot_auto);
}
}
#[test]
fn integration_error_handling() {
use trueno::Matrix;
let a = Vector::from_slice(&[1.0, 2.0, 3.0]);
let b = Vector::from_slice(&[1.0, 2.0]);
assert!(a.add(&b).is_err());
assert!(a.dot(&b).is_err());
let empty = Vector::from_slice(&[]);
assert_eq!(empty.sum().unwrap(), 0.0);
assert!(empty.mean().is_err());
let single = Vector::from_slice(&[1.0]);
assert_eq!(single.variance().unwrap(), 0.0);
let m1 = Matrix::zeros(2, 3);
let m2 = Matrix::zeros(2, 2);
assert!(m1.matmul(&m2).is_err());
let data = vec![1.0, 2.0, 3.0];
assert!(Matrix::from_vec(2, 2, data).is_err());
}
#[test]
fn integration_backend_selection() {
use trueno::select_best_available_backend;
let backend = select_best_available_backend();
assert!(matches!(
backend,
Backend::Scalar
| Backend::SSE2
| Backend::AVX
| Backend::AVX2
| Backend::AVX512
| Backend::NEON
| Backend::WasmSIMD
));
let backend2 = Backend::select_best();
assert_eq!(backend, backend2);
let data = vec![1.0, 2.0, 3.0];
let _v_auto = Vector::from_slice(&data);
let _v_scalar = Vector::from_slice_with_backend(&data, Backend::Scalar);
}