use num_traits::{Float, FromPrimitive, One, Zero};
use crate::smooth::SmoothError;
pub fn ema<T>(data: &[T], period: usize) -> Result<Vec<T>, SmoothError> where
T: Float + FromPrimitive + Zero + Clone + One,
{
let len = data.len();
if period == 0 || len == 0 {
return Err(SmoothError::EMAApplyError);
}
let alpha = T::from(2.0 / (period as f32 + 1.0)).unwrap();
let half = period / 2;
let mut extended = Vec::with_capacity(len + 2 * half);
for _ in 0..half {
extended.push(data[0]);
}
extended.extend_from_slice(data);
for _ in 0..half {
extended.push(data[len - 1]);
}
let mut result = Vec::with_capacity(extended.len());
let mut ema = extended[0];
result.push(ema);
for &x in extended.iter().skip(1) {
ema = alpha * x + (T::one() - alpha) * ema;
result.push(ema);
}
let start = half;
let end = start + len;
Ok(result[start..end].to_vec())
}