use crate::indicators::fosc::State;
#[cfg(feature = "simd_assets")]
pub use crate::indicators::simd_indicators::by_asset::fosc::indicator_by_assets;
#[cfg(feature = "simd_options")]
pub use crate::indicators::simd_indicators::by_option::fosc::indicator_by_options;
use crate::indicators::simd_indicators::{
simd_types::F64Constants,
tsf_simd::{calc_simd as tsf_calc_simd, SimdState as SimdLinregState},
};
use std::simd::Simd;
pub struct SimdState<const N: usize> {
linreg_state: SimdLinregState<N>,
tsf: Simd<f64, N>,
}
impl<const N: usize> SimdState<N> {
pub fn new(states: &[&mut State]) -> Self {
let mut linreg_state = Vec::with_capacity(N);
let mut tsf = [0.0; N];
for i in 0..N {
linreg_state.push(&states[i].linreg_state);
tsf[i] = states[i].tsf;
}
let linreg_state = SimdLinregState::new(linreg_state.as_slice());
Self {
linreg_state,
tsf: Simd::from_array(tsf),
}
}
pub fn to_states(&self) -> [State; N] {
let linreg_states = self.linreg_state.to_states();
let tsf = self.tsf.to_array();
let states: [State; N] = std::array::from_fn(|i| {
State::new(
tsf[i],
linreg_states[i].sum_x,
linreg_states[i].sum_y,
linreg_states[i].sum_xy,
linreg_states[i].per,
)
});
states
}
pub fn write_states(&self, states: &mut [&mut State]) {
let linreg_states = self.linreg_state.to_states();
let tsf = self.tsf.to_array();
for (i, linreg_state) in linreg_states.into_iter().enumerate() {
states[i].linreg_state = linreg_state;
states[i].tsf = tsf[i];
}
}
}
#[inline(always)]
pub fn calc_simd<const N: usize>(
state: &mut SimdState<N>,
prev_value: Simd<f64, N>,
value: Simd<f64, N>,
period: Simd<f64, N>,
) -> (
Simd<f64, N>,
Simd<f64, N>,
Simd<f64, N>,
Simd<f64, N>,
Simd<f64, N>,
) {
let fosc = F64Constants::HUNDRED * (value - state.tsf) / value;
let (tsf, linreg, slope, intercept) =
tsf_calc_simd(&mut state.linreg_state, prev_value, value, period);
state.tsf = tsf;
(fosc, tsf, linreg, slope, intercept)
}