use crate::ring_buffer::fixed_single_buffer::{FixedMirrorBuffer, FixedRingBuffer};
use std::simd::Simd;
impl<const LANES: usize, const CAP: usize> FixedRingBuffer<Simd<f64, LANES>, CAP> {
pub fn to_f64_buffers(&self) -> [FixedRingBuffer<f64, CAP>; LANES] {
std::array::from_fn(|lane| FixedRingBuffer {
vals: std::array::from_fn(|i| self.vals[i].to_array()[lane]),
index: self.index,
count: self.count,
})
}
}
pub trait FixedSimdRingBuffer<const LANES: usize, const CAP: usize> {
fn from_f64_buffers(buffers: &[&FixedRingBuffer<f64, CAP>]) -> Self;
}
impl<const LANES: usize, const CAP: usize> FixedSimdRingBuffer<LANES, CAP>
for FixedRingBuffer<Simd<f64, LANES>, CAP>
{
fn from_f64_buffers(buffers: &[&FixedRingBuffer<f64, CAP>]) -> Self {
debug_assert_eq!(
buffers.len(),
LANES,
"number of buffers must match SIMD width"
);
debug_assert!(
buffers.windows(2).all(|w| w[0].count == w[1].count),
"all scalar buffers must have the same count"
);
let ordered: [Vec<f64>; LANES] = std::array::from_fn(|j| buffers[j].to_ordered_vec());
let count = buffers[0].count;
Self {
vals: std::array::from_fn(|i| {
Simd::from_array(std::array::from_fn(|j| {
if i < ordered[j].len() {
ordered[j][i]
} else {
0.0
}
}))
}),
index: 0,
count,
}
}
}
impl<const LANES: usize, const CAP: usize> FixedMirrorBuffer<Simd<f64, LANES>, CAP> {
pub fn to_f64_buffers(&self) -> [FixedMirrorBuffer<f64, CAP>; LANES] {
std::array::from_fn(|lane| FixedMirrorBuffer {
ring: std::array::from_fn(|i| self.ring[i].to_array()[lane]),
view: std::array::from_fn(|i| self.view[i].to_array()[lane]),
index: self.index,
count: self.count,
})
}
}
pub trait FixedSimdMirrorBuffer<const LANES: usize, const CAP: usize> {
fn from_f64_buffers(buffers: &[&FixedMirrorBuffer<f64, CAP>]) -> Self;
}
impl<const LANES: usize, const CAP: usize> FixedSimdMirrorBuffer<LANES, CAP>
for FixedMirrorBuffer<Simd<f64, LANES>, CAP>
{
fn from_f64_buffers(buffers: &[&FixedMirrorBuffer<f64, CAP>]) -> Self {
debug_assert_eq!(
buffers.len(),
LANES,
"number of buffers must match SIMD width"
);
debug_assert!(
buffers.windows(2).all(|w| w[0].count == w[1].count),
"all scalar buffers must have the same count"
);
let ordered: [Vec<f64>; LANES] = std::array::from_fn(|j| buffers[j].to_ordered_vec());
let count = buffers[0].count;
Self {
ring: std::array::from_fn(|i| {
Simd::from_array(std::array::from_fn(|j| {
if i < ordered[j].len() {
ordered[j][i]
} else {
0.0
}
}))
}),
view: std::array::from_fn(|i| {
Simd::from_array(std::array::from_fn(|j| {
if i < ordered[j].len() {
ordered[j][i]
} else {
0.0
}
}))
}),
index: 0,
count,
}
}
}
pub type FixedSimdRingBuf<const LANES: usize, const CAP: usize> =
FixedRingBuffer<Simd<f64, LANES>, CAP>;
pub type FixedSimdMirrorBuf<const LANES: usize, const CAP: usize> =
FixedMirrorBuffer<Simd<f64, LANES>, CAP>;