use super::super::super::super::*;
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn test_sum_of_squares_non_negative(
a in prop::collection::vec(-100.0f32..100.0, 1..100)
) {
let va = Vector::from_slice(&a);
let result = va.sum_of_squares().unwrap();
prop_assert!(
result >= 0.0,
"sum_of_squares should be non-negative: {} < 0",
result
);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn test_sum_of_squares_equals_dot_self(
a in prop::collection::vec(-100.0f32..100.0, 1..100)
) {
let va = Vector::from_slice(&a);
let sum_sq = va.sum_of_squares().unwrap();
let dot_self = va.dot(&va).unwrap();
prop_assert!(
(sum_sq - dot_self).abs() < 1e-4,
"sum_of_squares should equal dot(self, self): {} != {}",
sum_sq, dot_self
);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn test_sum_of_squares_scaling(
a in prop::collection::vec(-10.0f32..10.0, 1..50),
k in -5.0f32..5.0
) {
let va = Vector::from_slice(&a);
let scaled = va.scale(k).unwrap();
let sum_sq_original = va.sum_of_squares().unwrap();
let sum_sq_scaled = scaled.sum_of_squares().unwrap();
let expected = k * k * sum_sq_original;
let tolerance = 1e-3 * expected.abs().max(1.0);
prop_assert!(
(sum_sq_scaled - expected).abs() < tolerance,
"sum_of_squares({} * v) = {} != {}^2 * {} = {}",
k, sum_sq_scaled, k, sum_sq_original, expected
);
}
#[test]
fn test_mean_bounds(
a in prop::collection::vec(-100.0f32..100.0, 1..100)
) {
let va = Vector::from_slice(&a);
let mean_val = va.mean().unwrap();
let min_val = va.min().unwrap();
let max_val = va.max().unwrap();
prop_assert!(
mean_val >= min_val && mean_val <= max_val,
"mean({}) = {} not in range [{}, {}]",
mean_val, mean_val, min_val, max_val
);
}
#[test]
fn test_mean_translation(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
c in -10.0f32..10.0
) {
let va = Vector::from_slice(&a);
let mean_original = va.mean().unwrap();
let translated: Vec<f32> = a.iter().map(|x| x + c).collect();
let vt = Vector::from_slice(&translated);
let mean_translated = vt.mean().unwrap();
let expected = mean_original + c;
let tolerance = 1e-4 * expected.abs().max(1.0);
prop_assert!(
(mean_translated - expected).abs() < tolerance,
"mean(v + {}) = {} != mean(v) + {} = {}",
c, mean_translated, c, expected
);
}
#[test]
fn test_mean_scaling(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
k in -5.0f32..5.0
) {
let va = Vector::from_slice(&a);
let mean_original = va.mean().unwrap();
let scaled = va.scale(k).unwrap();
let mean_scaled = scaled.mean().unwrap();
let expected = k * mean_original;
let tolerance = 1e-4 * expected.abs().max(1.0);
prop_assert!(
(mean_scaled - expected).abs() < tolerance,
"mean({} * v) = {} != {} * mean(v) = {}",
k, mean_scaled, k, expected
);
}
#[test]
fn test_variance_non_negative(
a in prop::collection::vec(-100.0f32..100.0, 1..100)
) {
let va = Vector::from_slice(&a);
let var = va.variance().unwrap();
prop_assert!(
var >= -1e-5, "variance = {} should be non-negative",
var
);
}
#[test]
fn test_variance_scaling(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
k in -5.0f32..5.0
) {
let va = Vector::from_slice(&a);
let var_original = va.variance().unwrap();
let scaled = va.scale(k).unwrap();
let var_scaled = scaled.variance().unwrap();
let expected = k * k * var_original;
let tolerance = if expected.abs() < 1.0 {
1e-2 } else {
5e-3 * expected.abs() };
prop_assert!(
(var_scaled - expected).abs() < tolerance,
"variance({} * v) = {} != {}^2 * variance(v) = {}",
k, var_scaled, k, expected
);
}
#[test]
fn test_variance_translation_invariance(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
c in -10.0f32..10.0
) {
let va = Vector::from_slice(&a);
let var_original = va.variance().unwrap();
let translated: Vec<f32> = a.iter().map(|x| x + c).collect();
let vt = Vector::from_slice(&translated);
let var_translated = vt.variance().unwrap();
let tolerance = if var_original.abs() < 1.0 {
1e-2 } else {
1e-3 * var_original.abs() };
prop_assert!(
(var_translated - var_original).abs() < tolerance,
"variance(v + {}) = {} != variance(v) = {}",
c, var_translated, var_original
);
}
#[test]
fn test_stddev_non_negative(
a in prop::collection::vec(-100.0f32..100.0, 1..100)
) {
let va = Vector::from_slice(&a);
let sd = va.stddev().unwrap();
prop_assert!(
sd >= -1e-5, "stddev = {} should be non-negative",
sd
);
}
#[test]
fn test_stddev_scaling(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
k in -5.0f32..5.0
) {
let va = Vector::from_slice(&a);
let sd_original = va.stddev().unwrap();
let scaled = va.scale(k).unwrap();
let sd_scaled = scaled.stddev().unwrap();
let expected = k.abs() * sd_original;
let tolerance = if expected.abs() < 1.0 {
5e-2 } else {
1e-3 * expected.abs() };
prop_assert!(
(sd_scaled - expected).abs() < tolerance,
"stddev({} * v) = {} != |{}| * stddev(v) = {}",
k, sd_scaled, k, expected
);
}
#[test]
fn test_stddev_translation_invariance(
a in prop::collection::vec(-50.0f32..50.0, 1..100),
c in -10.0f32..10.0
) {
let va = Vector::from_slice(&a);
let sd_original = va.stddev().unwrap();
let translated: Vec<f32> = a.iter().map(|x| x + c).collect();
let vt = Vector::from_slice(&translated);
let sd_translated = vt.stddev().unwrap();
let tolerance = if sd_original.abs() < 1.0 {
1e-2 } else {
1e-3 * sd_original.abs() };
prop_assert!(
(sd_translated - sd_original).abs() < tolerance,
"stddev(v + {}) = {} != stddev(v) = {}",
c, sd_translated, sd_original
);
}
}