use crate::ring_buffer::multi_buffer::multi_buffer::{
MirrorBuffer, MultiBuffer, RingBuffer,
};
use std::simd::Simd;
impl<const B: usize, const N: usize> MultiBuffer<B, Simd<f64, N>>{
fn to_simd_buffer(f64_buffers: &[&[&[f64]; B]; N], capacity: usize, mirror: bool) -> Self {
let actual_capacity = if mirror { capacity * 2 } else { capacity };
let mut simd_vals: [Vec<Simd<f64, N>>; B] = core::array::from_fn(|_| {
Vec::with_capacity(actual_capacity)
});
for i in 0..actual_capacity {
for b in 0..B {
let simd_elements: [f64; N] =
core::array::from_fn(|n| f64_buffers[n][b].get(i).copied().unwrap_or(0.0));
simd_vals[b].push(Simd::from_array(simd_elements));
}
}
if mirror {
for vec in simd_vals.iter_mut() {
vec.extend_from_within(..);
}
}
Self {
vals: simd_vals,
index: 0,
prev_idx: capacity - 1, capacity,
count: capacity,
}
}
pub fn to_f64_buffers(&self) -> [MultiBuffer<B, f64>; N] {
let actual_length = self.vals[0].len();
let mut storage: [[Vec<f64>; B]; N] =
core::array::from_fn(|_| core::array::from_fn(|_| Vec::with_capacity(actual_length)));
for b in 0..B {
for simd_val in &self.vals[b] {
let elements = simd_val.to_array();
for n in 0..N {
storage[n][b].push(elements[n]);
}
}
}
core::array::from_fn(|n| MultiBuffer {
vals: storage[n].clone(),
index: self.index,
capacity: self.capacity, count: self.count,
prev_idx: self.prev_idx,
})
}
}
pub trait SimdRingBuffer<const B: usize, const N: usize>: RingBuffer<B, Simd<f64, N>>{
fn from_f64_buffers(multi_buffers: [&MultiBuffer<B, f64>; N]) -> Self;
}
impl<const B: usize, const N: usize> SimdRingBuffer<B, N> for MultiBuffer<B, Simd<f64, N>>{
fn from_f64_buffers(multi_buffers: [&MultiBuffer<B, f64>; N]) -> Self {
let capacity = multi_buffers[0].get_capacity();
let ordered_data: [[Vec<f64>; B]; N] =
core::array::from_fn(|n| multi_buffers[n].to_ordered_vec());
let slices: [[&[f64]; B]; N] =
core::array::from_fn(|n| core::array::from_fn(|b| ordered_data[n][b].as_slice()));
let slice_refs: [&[&[f64]; B]; N] = core::array::from_fn(|n| &slices[n]);
Self::to_simd_buffer(&slice_refs, capacity, false)
}
}
pub trait SimdMirrorBuffer<const B: usize, const N: usize>: MirrorBuffer<B, Simd<f64, N>>{
fn from_f64_buffers(multi_buffers: [&MultiBuffer<B, f64>; N]) -> Self;
}
impl<const B: usize, const N: usize> SimdMirrorBuffer<B, N> for MultiBuffer<B, Simd<f64, N>> {
fn from_f64_buffers(multi_buffers: [&MultiBuffer<B, f64>; N]) -> Self {
let capacity = multi_buffers[0].get_capacity();
let mirror_slices: [[&[f64]; B]; N] = core::array::from_fn(|n| {
<MultiBuffer<B, f64> as MirrorBuffer<B, f64>>::get_slices(multi_buffers[n], 0)
});
let slice_refs: [&[&[f64]; B]; N] = core::array::from_fn(|n| &mirror_slices[n]);
Self::to_simd_buffer(&slice_refs, capacity, true) }
}
pub type SimdBuffer<const B: usize, const N: usize> = MultiBuffer<B, Simd<f64, N>>;