use crate::indicators::kama::State;
#[cfg(feature = "simd_assets")]
pub use crate::indicators::simd_indicators::by_asset::kama::indicator_by_assets;
use crate::indicators::simd_indicators::{
ef_simd::calc_simd as calc_simd_ef, simd_types::F64Constants,
};
#[cfg(feature = "simd_options")]
pub use crate::indicators::simd_indicators::by_option::kama::indicator_by_options;
use std::simd::{Simd, StdFloat};
pub struct SimdState<const N: usize> {
pub kama: Simd<f64, N>,
pub sum: Simd<f64, N>,
}
impl<const N: usize> SimdState<N> {
pub fn new(states: &[&mut State]) -> Self {
let mut kama = [0.0; N];
let mut sum = [0.0; N];
for i in 0..N {
kama[i] = states[i].kama;
sum[i] = states[i].sum;
}
Self {
kama: Simd::from_array(kama),
sum: Simd::from_array(sum),
}
}
pub fn to_states(&self) -> [State; N] {
let kama = self.kama.to_array();
let sum = self.sum.to_array();
let states: [State; N] = std::array::from_fn(|i| State::new(kama[i], sum[i]));
states
}
pub fn write_states(&self, states: &mut [&mut State]) {
let kama = self.kama.to_array();
let sum = self.sum.to_array();
for (i, state) in states.iter_mut().enumerate() {
state.kama = kama[i];
state.sum = sum[i];
}
}
}
#[inline(always)]
pub fn calc_simd<const N: usize>(
state: &mut SimdState<N>,
values: (Simd<f64, N>, Simd<f64, N>, Simd<f64, N>, Simd<f64, N>),
multipliers: (Simd<f64, N>, Simd<f64, N>),
) -> (Simd<f64, N>, Simd<f64, N>) {
let (fast_ema, slow_ema) = multipliers;
let mut kama = state.kama;
let value = values.0;
let efficiency_ratio = calc_simd_ef(&mut state.sum, values);
let smoothing_constant = {
let temp = (fast_ema - slow_ema).mul_add(efficiency_ratio, slow_ema);
temp * temp };
let per1 = F64Constants::ONE - smoothing_constant;
kama = kama.mul_add(per1, value * smoothing_constant);
state.kama = kama;
(kama, efficiency_ratio)
}