scientific-cal 0.2.4

scientific cal
Documentation

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]);
    }

    // 应用 EMA
    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())
}