use crate::error::{StatsError, StatsResult};
use num_traits::ToPrimitive;
use std::fmt::Debug;
#[inline]
pub fn average<T>(data: &[T]) -> StatsResult<f64>
where
T: ToPrimitive + Debug,
{
if data.is_empty() {
return Err(StatsError::empty_data(
"prob::average: Cannot calculate average of empty dataset",
));
}
let mut sum = 0.0;
for (i, x) in data.iter().enumerate() {
let v = x.to_f64().ok_or_else(|| {
StatsError::conversion_error(format!(
"prob::average: Failed to convert value at index {} to f64",
i
))
})?;
sum += v;
}
Ok(sum / data.len() as f64)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_average_integers() {
let data = vec![1, 2, 3, 4, 5];
let result = average(&data).unwrap();
assert_eq!(result, 3.0);
}
#[test]
fn test_average_floats() {
let data = vec![1.5, 2.5, 3.5, 4.5];
let result = average(&data).unwrap();
assert_eq!(result, 3.0);
}
#[test]
fn test_average_mixed_types() {
let data = vec![1.0, 2.0, 3.0, 4.5, 5.5]; let result = average(&data).unwrap();
assert_eq!(result, 3.2);
}
#[test]
fn test_average_empty_slice() {
let data: Vec<f64> = Vec::new();
let result = average(&data);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), StatsError::EmptyData { .. }));
}
#[test]
fn test_average_single_value() {
let data = vec![10.0];
let result = average(&data).unwrap();
assert_eq!(result, 10.0);
}
}