//! Generated from token-registry.toml — DO NOT EDIT.
//!
//! Regenerate with: cargo xtask generate

use super::x86::X64V2Token;
use super::x86::X64V3Token;
use crate::tokens::SimdToken;
use crate::tokens::{Has128BitSimd, Has256BitSimd, Has512BitSimd, HasX64V2, HasX64V4};

/// Proof that AVX-512 (F + CD + VL + DQ + BW) is available.
///
/// This is the complete x86-64-v4 AVX-512 feature set, available on:
/// - Intel Skylake-X (2017+), Ice Lake, Sapphire Rapids
/// - AMD Zen 4+ (2022+)
///
/// Note: Intel 12th-14th gen consumer CPUs do NOT have AVX-512.
#[derive(Clone, Copy, Debug)]
pub struct X64V4Token {
    _private: (),
}

impl SimdToken for X64V4Token {
    const NAME: &'static str = "AVX-512";

    #[inline(always)]
    fn try_new() -> Option<Self> {
        if crate::is_x86_feature_available!("sse3")
            && crate::is_x86_feature_available!("ssse3")
            && crate::is_x86_feature_available!("sse4.1")
            && crate::is_x86_feature_available!("sse4.2")
            && crate::is_x86_feature_available!("popcnt")
            && crate::is_x86_feature_available!("avx")
            && crate::is_x86_feature_available!("avx2")
            && crate::is_x86_feature_available!("fma")
            && crate::is_x86_feature_available!("bmi1")
            && crate::is_x86_feature_available!("bmi2")
            && crate::is_x86_feature_available!("f16c")
            && crate::is_x86_feature_available!("lzcnt")
            && crate::is_x86_feature_available!("avx512f")
            && crate::is_x86_feature_available!("avx512bw")
            && crate::is_x86_feature_available!("avx512cd")
            && crate::is_x86_feature_available!("avx512dq")
            && crate::is_x86_feature_available!("avx512vl")
        {
            Some(unsafe { Self::forge_token_dangerously() })
        } else {
            None
        }
    }

    #[inline(always)]
    unsafe fn forge_token_dangerously() -> Self {
        Self { _private: () }
    }
}

impl X64V4Token {
    /// Get a X64V3Token (AVX-512 implies x86-64-v3)
    #[inline(always)]
    pub fn v3(self) -> X64V3Token {
        unsafe { X64V3Token::forge_token_dangerously() }
    }
    /// Get a X64V2Token (AVX-512 implies x86-64-v2)
    #[inline(always)]
    pub fn v2(self) -> X64V2Token {
        unsafe { X64V2Token::forge_token_dangerously() }
    }
}

/// Proof that modern AVX-512 features are available (Ice Lake / Zen 4 level).
///
/// This includes all of `X64V4Token` (F+CD+VL+DQ+BW) plus:
/// - VPOPCNTDQ, IFMA, VBMI, VBMI2, BITALG, VNNI, BF16
/// - VPCLMULQDQ, GFNI, VAES
///
/// Available on Intel Ice Lake (2019+), Sapphire Rapids, AMD Zen 4+.
/// NOT available on Skylake-X (lacks VBMI2, VNNI, BF16, etc.).
#[derive(Clone, Copy, Debug)]
pub struct Avx512ModernToken {
    _private: (),
}

impl SimdToken for Avx512ModernToken {
    const NAME: &'static str = "AVX-512Modern";

    #[inline(always)]
    fn try_new() -> Option<Self> {
        if crate::is_x86_feature_available!("sse3")
            && crate::is_x86_feature_available!("ssse3")
            && crate::is_x86_feature_available!("sse4.1")
            && crate::is_x86_feature_available!("sse4.2")
            && crate::is_x86_feature_available!("popcnt")
            && crate::is_x86_feature_available!("avx")
            && crate::is_x86_feature_available!("avx2")
            && crate::is_x86_feature_available!("fma")
            && crate::is_x86_feature_available!("bmi1")
            && crate::is_x86_feature_available!("bmi2")
            && crate::is_x86_feature_available!("f16c")
            && crate::is_x86_feature_available!("lzcnt")
            && crate::is_x86_feature_available!("avx512f")
            && crate::is_x86_feature_available!("avx512bw")
            && crate::is_x86_feature_available!("avx512cd")
            && crate::is_x86_feature_available!("avx512dq")
            && crate::is_x86_feature_available!("avx512vl")
            && crate::is_x86_feature_available!("avx512vpopcntdq")
            && crate::is_x86_feature_available!("avx512ifma")
            && crate::is_x86_feature_available!("avx512vbmi")
            && crate::is_x86_feature_available!("avx512vbmi2")
            && crate::is_x86_feature_available!("avx512bitalg")
            && crate::is_x86_feature_available!("avx512vnni")
            && crate::is_x86_feature_available!("avx512bf16")
            && crate::is_x86_feature_available!("vpclmulqdq")
            && crate::is_x86_feature_available!("gfni")
            && crate::is_x86_feature_available!("vaes")
        {
            Some(unsafe { Self::forge_token_dangerously() })
        } else {
            None
        }
    }

    #[inline(always)]
    unsafe fn forge_token_dangerously() -> Self {
        Self { _private: () }
    }
}

impl Avx512ModernToken {
    /// Get a X64V4Token (AVX-512Modern implies AVX-512)
    #[inline(always)]
    pub fn v4(self) -> X64V4Token {
        unsafe { X64V4Token::forge_token_dangerously() }
    }

    /// Get a X64V4Token (alias for `.v4()`)
    #[inline(always)]
    pub fn avx512(self) -> X64V4Token {
        unsafe { X64V4Token::forge_token_dangerously() }
    }
    /// Get a X64V3Token (AVX-512Modern implies x86-64-v3)
    #[inline(always)]
    pub fn v3(self) -> X64V3Token {
        unsafe { X64V3Token::forge_token_dangerously() }
    }
    /// Get a X64V2Token (AVX-512Modern implies x86-64-v2)
    #[inline(always)]
    pub fn v2(self) -> X64V2Token {
        unsafe { X64V2Token::forge_token_dangerously() }
    }
}

/// Proof that AVX-512 FP16 (half-precision) is available.
///
/// AVX-512 FP16 provides native 16-bit floating-point arithmetic in 512-bit
/// vectors, enabling efficient ML inference and scientific computing.
///
/// Available on Intel Sapphire Rapids (2023+), Emerald Rapids.
/// NOT available on Skylake-X, Ice Lake, AMD Zen 4.
#[derive(Clone, Copy, Debug)]
pub struct Avx512Fp16Token {
    _private: (),
}

impl SimdToken for Avx512Fp16Token {
    const NAME: &'static str = "AVX-512FP16";

    #[inline(always)]
    fn try_new() -> Option<Self> {
        if crate::is_x86_feature_available!("sse3")
            && crate::is_x86_feature_available!("ssse3")
            && crate::is_x86_feature_available!("sse4.1")
            && crate::is_x86_feature_available!("sse4.2")
            && crate::is_x86_feature_available!("popcnt")
            && crate::is_x86_feature_available!("avx")
            && crate::is_x86_feature_available!("avx2")
            && crate::is_x86_feature_available!("fma")
            && crate::is_x86_feature_available!("bmi1")
            && crate::is_x86_feature_available!("bmi2")
            && crate::is_x86_feature_available!("f16c")
            && crate::is_x86_feature_available!("lzcnt")
            && crate::is_x86_feature_available!("avx512f")
            && crate::is_x86_feature_available!("avx512bw")
            && crate::is_x86_feature_available!("avx512cd")
            && crate::is_x86_feature_available!("avx512dq")
            && crate::is_x86_feature_available!("avx512vl")
            && crate::is_x86_feature_available!("avx512fp16")
        {
            Some(unsafe { Self::forge_token_dangerously() })
        } else {
            None
        }
    }

    #[inline(always)]
    unsafe fn forge_token_dangerously() -> Self {
        Self { _private: () }
    }
}

impl Avx512Fp16Token {
    /// Get a X64V4Token (AVX-512FP16 implies AVX-512)
    #[inline(always)]
    pub fn v4(self) -> X64V4Token {
        unsafe { X64V4Token::forge_token_dangerously() }
    }

    /// Get a X64V4Token (alias for `.v4()`)
    #[inline(always)]
    pub fn avx512(self) -> X64V4Token {
        unsafe { X64V4Token::forge_token_dangerously() }
    }
    /// Get a X64V3Token (AVX-512FP16 implies x86-64-v3)
    #[inline(always)]
    pub fn v3(self) -> X64V3Token {
        unsafe { X64V3Token::forge_token_dangerously() }
    }
    /// Get a X64V2Token (AVX-512FP16 implies x86-64-v2)
    #[inline(always)]
    pub fn v2(self) -> X64V2Token {
        unsafe { X64V2Token::forge_token_dangerously() }
    }
}

/// Type alias for [`X64V4Token`].
pub type Avx512Token = X64V4Token;

/// Type alias for [`X64V4Token`].
pub type Server64 = X64V4Token;

impl Has128BitSimd for X64V4Token {}
impl Has128BitSimd for Avx512ModernToken {}
impl Has128BitSimd for Avx512Fp16Token {}
impl Has256BitSimd for X64V4Token {}
impl Has256BitSimd for Avx512ModernToken {}
impl Has256BitSimd for Avx512Fp16Token {}
impl Has512BitSimd for X64V4Token {}
impl Has512BitSimd for Avx512ModernToken {}
impl Has512BitSimd for Avx512Fp16Token {}
impl HasX64V2 for X64V4Token {}
impl HasX64V2 for Avx512ModernToken {}
impl HasX64V2 for Avx512Fp16Token {}
impl HasX64V4 for X64V4Token {}
impl HasX64V4 for Avx512ModernToken {}
impl HasX64V4 for Avx512Fp16Token {}
