use num_traits::{Float, FromPrimitive, One, Zero};
use crate::smooth::SmoothError;
pub fn sma<T>(data: &mut [T], period: usize) -> Result<(), SmoothError>
where
T: Float + FromPrimitive + Zero + Clone + One,
{
let len = data.len();
if period == 0 || len == 0 {
return Err(SmoothError::SMAApplyError);
}
let half = period / 2;
let left_padding = data[0];
let right_padding = data[len - 1];
let mut cache_sum = data[0] * T::from(half).unwrap();
for i in 0..half {
cache_sum = cache_sum + data[i];
}
data[0] = cache_sum / T::from(period).unwrap();
for i in 0..len {
let left;
let right;
if i < half {
left = left_padding;
right = data[i + half];
} else if i > len - half -1 {
left = data[i - half];
right = right_padding;
} else {
left = data[i - half];
right = data[i + half];
}
cache_sum = cache_sum + right - left;
let p = if let Some(d) = T::from(period){
d
}else{
return Err(SmoothError::SMAApplyError);
};
data[i] = cache_sum / p;
}
Ok(())
}