use super::{Scalar, Target, Target1, Target2, Target3, get_or_set_architecture};
use crate::{
Architecture, SIMDVector,
arch::{self, Dispatched1, Dispatched2, Dispatched3, FTarget1, FTarget2, FTarget3, Hidden},
lifetime::AddLifetime,
};
pub mod f16x8_;
pub use f16x8_::f16x8;
pub mod f16x16_;
pub use f16x16_::f16x16;
pub mod f32x4_;
pub use f32x4_::f32x4;
pub mod f32x8_;
pub use f32x8_::f32x8;
pub mod f32x16_;
pub use f32x16_::f32x16;
pub mod i8x16_;
pub use i8x16_::i8x16;
pub mod i8x32_;
pub use i8x32_::i8x32;
pub mod i8x64_;
pub use i8x64_::i8x64;
pub mod i16x8_;
pub use i16x8_::i16x8;
pub mod i16x16_;
pub use i16x16_::i16x16;
pub mod i16x32_;
pub use i16x32_::i16x32;
pub mod i32x4_;
pub use i32x4_::i32x4;
pub mod i32x8_;
pub use i32x8_::i32x8;
pub mod i32x16_;
pub use i32x16_::i32x16;
pub mod u8x16_;
pub use u8x16_::u8x16;
pub mod u8x32_;
pub use u8x32_::u8x32;
pub mod u8x64_;
pub use u8x64_::u8x64;
pub mod u32x4_;
pub use u32x4_::u32x4;
pub mod u32x8_;
pub use u32x8_::u32x8;
pub mod u32x16_;
pub use u32x16_::u32x16;
pub mod u64x2_;
pub use u64x2_::u64x2;
pub mod u64x4_;
pub use u64x4_::u64x4;
pub mod masks;
mod conversion;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct V3(Hidden);
impl arch::sealed::Sealed for V3 {}
macro_rules! v3_features {
($($args:tt)*) => {
#[target_feature(enable = "avx2,avx,bmi1,bmi2,f16c,fma,lzcnt,movbe,xsave")]
$($args)*
}
}
impl V3 {
pub const unsafe fn new() -> Self {
Self(Hidden)
}
pub fn new_checked() -> Option<Self> {
unsafe { Self::new_checked_with(get_or_set_architecture!()) }
}
pub fn retarget(self) -> Scalar {
Scalar::new()
}
#[cfg(test)]
pub(crate) fn new_checked_uncached() -> Option<Self> {
match unsafe { Self::new_checked_with(super::arch_number()) } {
Some(v) => Some(v),
None => {
if unsafe { Self::new_checked_with(super::test_arch_number()) }.is_some() {
panic!(
"V3 architecture was requested but is not compatible on the current hardware"
);
} else {
None
}
}
}
}
unsafe fn new_checked_with(version: u64) -> Option<Self> {
if version >= super::ARCH_V3 {
Some(unsafe { Self::new() })
} else {
None
}
}
v3_features! {
pub(super) unsafe fn run_with<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
f.run(self)
}
}
v3_features! {
#[inline]
pub(super) unsafe fn run_with_inline<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
f.run(self)
}
}
v3_features! {
pub(super) unsafe fn run_with_1<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
f.run(self, x0)
}
}
v3_features! {
#[inline]
pub(super) unsafe fn run_with_1_inline<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
f.run(self, x0)
}
}
v3_features! {
pub(super) unsafe fn run_with_2<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
f.run(self, x0, x1)
}
}
v3_features! {
#[inline]
pub(super) unsafe fn run_with_2_inline<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
f.run(self, x0, x1)
}
}
v3_features! {
pub(super) unsafe fn run_with_3<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
f.run(self, x0, x1, x2)
}
}
v3_features! {
#[inline]
pub(super) unsafe fn run_with_3_inline<F, T0, T1, T2, R>(
self,
f: F,
x0: T0,
x1: T1,
x2: T2,
) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
f.run(self, x0, x1, x2)
}
}
v3_features! {
pub(super) unsafe fn run_function_with_1<F, T0, R>(self, x0: T0::Of<'_>) -> R
where
T0: AddLifetime,
F: for<'a> FTarget1<Self, R, T0::Of<'a>>,
{
F::run(self, x0)
}
}
v3_features! {
pub(super) unsafe fn run_function_with_2<F, T0, T1, R>(
self,
x0: T0::Of<'_>,
x1: T1::Of<'_>,
) -> R
where
T0: AddLifetime,
T1: AddLifetime,
F: for<'a, 'b> FTarget2<Self, R, T0::Of<'a>, T1::Of<'b>>,
{
F::run(self, x0, x1)
}
}
v3_features! {
pub(super) unsafe fn run_function_with_3<F, T0, T1, T2, R>(
self,
x0: T0::Of<'_>,
x1: T1::Of<'_>,
x2: T2::Of<'_>,
) -> R
where
T0: AddLifetime,
T1: AddLifetime,
T2: AddLifetime,
F: for<'a, 'b, 'c> FTarget3<Self, R, T0::Of<'a>, T1::Of<'b>, T2::Of<'c>>,
{
F::run(self, x0, x1, x2)
}
}
}
impl Architecture for V3 {
arch::maskdef!();
arch::typedef!();
fn level() -> arch::Level {
arch::Level::v3()
}
#[inline(always)]
fn run<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
unsafe { Self::run_with(self, f) }
}
#[inline(always)]
fn run_inline<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
unsafe { Self::run_with_inline(self, f) }
}
#[inline(always)]
fn run1<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
unsafe { self.run_with_1(f, x0) }
}
#[inline(always)]
fn run1_inline<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
unsafe { self.run_with_1_inline(f, x0) }
}
#[inline(always)]
fn run2<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
unsafe { self.run_with_2(f, x0, x1) }
}
#[inline(always)]
fn run2_inline<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
unsafe { self.run_with_2_inline(f, x0, x1) }
}
#[inline(always)]
fn run3<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
unsafe { self.run_with_3(f, x0, x1, x2) }
}
#[inline(always)]
fn run3_inline<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
unsafe { self.run_with_3_inline(f, x0, x1, x2) }
}
fn dispatch1<F, R, T0>(self) -> Dispatched1<R, T0>
where
T0: AddLifetime,
F: for<'a> FTarget1<Self, R, T0::Of<'a>>,
{
let f: unsafe fn(Self, T0::Of<'_>) -> R = Self::run_function_with_1::<F, _, _>;
unsafe { arch::hide1(f) }
}
fn dispatch2<F, R, T0, T1>(self) -> Dispatched2<R, T0, T1>
where
T0: AddLifetime,
T1: AddLifetime,
F: for<'a, 'b> FTarget2<Self, R, T0::Of<'a>, T1::Of<'b>>,
{
let f: unsafe fn(Self, T0::Of<'_>, T1::Of<'_>) -> R =
Self::run_function_with_2::<F, _, _, _>;
unsafe { arch::hide2(f) }
}
fn dispatch3<F, R, T0, T1, T2>(self) -> Dispatched3<R, T0, T1, T2>
where
T0: AddLifetime,
T1: AddLifetime,
T2: AddLifetime,
F: for<'a, 'b, 'c> FTarget3<Self, R, T0::Of<'a>, T1::Of<'b>, T2::Of<'c>>,
{
let f: unsafe fn(Self, T0::Of<'_>, T1::Of<'_>, T2::Of<'_>) -> R =
Self::run_function_with_3::<F, _, _, _, _>;
unsafe { arch::hide3(f) }
}
}
impl From<V3> for Scalar {
fn from(_: V3) -> Scalar {
Scalar
}
}