use crate::common_simd::assets::validate_inputs;
use crate::indicators::adaptivemsw::{
min_data, output_length, IndicatorState, State, INPUTS_WIDTH, OPTIONS_WIDTH,
};
use crate::indicators::simd_indicators::adaptivemsw_simd::SimdState;
use crate::indicators::simd_indicators::road_train::{Asset, Driver, PrimeMover};
use crate::types::IndicatorError;
use std::simd::Simd;
struct AdaptiveMswDriver {
want_optional_outputs: (bool, bool),
}
impl Driver<State> for AdaptiveMswDriver {
fn next_run<const N: usize>(
&mut self,
inputs: Vec<Vec<&[f64]>>,
mut outputs: Vec<Vec<&mut [f64]>>,
mut states: Vec<&mut State>,
_options: Vec<Option<&()>>,
) {
let len = inputs[0][0].len();
let mut simd_state = SimdState::new(&mut states);
let (has_optional, want_dc) = self.want_optional_outputs;
let real_ptrs = crate::extract_input_ptrs!(inputs, N, real_ptrs);
let (sine_ptrs, lead_ptrs, dc_period_ptrs) =
crate::extract_output_ptrs!(outputs, N, sine_ptrs, lead_ptrs, dc_period_ptrs);
for i in 0..len {
let real = crate::extract_simd_inputs_at_index!(i, N, real @ real_ptrs);
let (sine, lead) = unsafe { simd_state.calc_simd_unchecked(real) };
crate::write_simd_at_indices!(N, i,
sine_ptrs => sine,
lead_ptrs => lead
);
if has_optional {
crate::store_simd_optional_outputs!(i, N,
want_dc, dc_period_ptrs => simd_state.hd.smooth_period
);
}
}
simd_state.write_states(&mut states);
}
}
pub fn indicator_by_assets<const N: usize>(
inputs: &[&[&[f64]; INPUTS_WIDTH]; N],
options: &[f64; OPTIONS_WIDTH],
optional_outputs: Option<&[bool]>,
) -> Result<(Vec<Vec<Vec<f64>>>, Vec<IndicatorState>), IndicatorError> {
validate_inputs::<INPUTS_WIDTH>(inputs, min_data(options))?;
let mut output_buffers = Vec::with_capacity(N);
let mut road_train = PrimeMover::<N, State>::new();
let mut want_optional_outputs = (false, false);
for i in 0..N {
let len = inputs[i][0].len();
let capacity = output_length(len, options);
let (mut sine_line, mut lead_line) = (
crate::uninit_vec!(f64, capacity),
crate::uninit_vec!(f64, capacity),
);
let mut dc_period_line = crate::init_optional_outputs!(
optional_outputs, &[false],
dc_period_line: capacity
);
let state = State::init_state(
inputs[i][0],
&mut sine_line,
&mut lead_line,
&mut dc_period_line,
);
if i == 0 {
want_optional_outputs = crate::calc_want_flags!(dc_period_line);
}
let mut output_buffer = vec![sine_line, lead_line, dc_period_line];
let mut asset_outputs = Vec::with_capacity(output_buffer.len());
for j in 0..output_buffer.len() {
unsafe {
let buf = &mut output_buffer[j];
let buf_len = buf.len();
let start = if buf_len > 0 { 1 } else { 0 };
asset_outputs.push(std::slice::from_raw_parts_mut(
buf.as_mut_ptr().add(start),
buf_len.saturating_sub(start),
));
}
}
road_train.add_asset(Asset::new(
vec![inputs[i][0]],
asset_outputs,
i,
min_data(options),
0,
state,
None,
));
output_buffers.push(output_buffer);
}
let mut driver = AdaptiveMswDriver {
want_optional_outputs,
};
let final_states = road_train.drive(&mut driver);
let states = final_states.into_iter().map(IndicatorState::new).collect();
Ok((output_buffers, states))
}