use core::ops::{Index, IndexMut};
use core::slice::SliceIndex;
use fearless_simd::{Level, Simd, SimdBase, SimdInto, f32x8, i16x16, i32x8, u32x8};
#[cfg(feature = "std")]
#[inline]
pub fn detect_level() -> Level {
static LEVEL: std::sync::OnceLock<Level> = std::sync::OnceLock::new();
*LEVEL.get_or_init(|| Level::try_detect().unwrap_or_else(Level::baseline))
}
#[cfg(not(feature = "std"))]
#[inline]
pub fn detect_level() -> Level {
Level::try_detect().unwrap_or_else(Level::baseline)
}
#[inline(always)]
pub fn min_lane_f32x8<S: Simd>(v: f32x8<S>) -> f32 {
let v = v.min(v.slide::<4>(v));
let v = v.min(v.slide::<2>(v));
let v = v.min(v.slide::<1>(v));
v[0]
}
#[inline(always)]
pub fn min_lane_u32x8<S: Simd>(v: u32x8<S>) -> u32 {
let v = v.min(v.slide::<4>(v));
let v = v.min(v.slide::<2>(v));
let v = v.min(v.slide::<1>(v));
v[0]
}
macro_rules! define_vector {
($(#[$attr:meta])* $name:ident, $elem:ty, $lanes:literal, $simd:ident) => {
$(#[$attr])*
#[derive(Default, Copy, Clone, Debug)]
pub struct $name([$elem; $lanes]);
impl $name {
#[inline(always)]
pub fn to_simd<S: Simd>(self, simd: S) -> $simd<S> {
self.0.simd_into(simd)
}
#[inline(always)]
pub fn from_simd<S: Simd>(value: $simd<S>) -> Self {
Self(value.into())
}
}
impl From<[$elem; $lanes]> for $name {
#[inline(always)]
fn from(value: [$elem; $lanes]) -> Self {
Self(value)
}
}
impl<I: SliceIndex<[$elem]>> Index<I> for $name {
type Output = I::Output;
#[inline(always)]
fn index(&self, index: I) -> &Self::Output {
&self.0[index]
}
}
impl<I: SliceIndex<[$elem]>> IndexMut<I> for $name {
#[inline(always)]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
&mut self.0[index]
}
}
};
}
define_vector!(Mem256f, f32, 8, f32x8);
define_vector!(Mem256i, i32, 8, i32x8);
define_vector!(Mem16x16, i16, 16, i16x16);
define_vector!(
PDF,
i16,
16,
i16x16
);
pub type v256 = Mem256f;
pub type v256i = Mem256i;