#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![warn(clippy::print_stdout, clippy::print_stderr)]
#![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(non_camel_case_types, reason = "TODO")]
#![expect(clippy::unused_unit, reason = "easier for code generation")]
#![no_std]
#[cfg(feature = "std")]
extern crate std;
#[cfg(all(not(feature = "libm"), not(feature = "std")))]
compile_error!("fearless_simd requires either the `std` or `libm` feature");
#[cfg(all(feature = "std", feature = "libm"))]
use libm as _;
pub mod core_arch;
mod impl_macros;
mod generated;
mod macros;
mod support;
mod traits;
pub use generated::*;
pub use traits::*;
pub mod prelude {
pub use crate::generated::simd_trait::*;
pub use crate::traits::*;
}
#[cfg(target_arch = "aarch64")]
pub mod aarch64 {
pub use crate::generated::Neon;
}
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
pub mod wasm32 {
pub use crate::generated::WasmSimd128;
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod x86 {
pub use crate::generated::Avx2;
pub use crate::generated::Sse4_2;
}
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum Level {
#[cfg(any(
all(target_arch = "aarch64", not(target_feature = "neon")),
all(
any(target_arch = "x86", target_arch = "x86_64"),
not(all(
target_feature = "sse4.2",
target_feature = "cmpxchg16b",
target_feature = "popcnt"
))
),
all(target_arch = "wasm32", not(target_feature = "simd128")),
not(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "wasm32"
)),
feature = "force_support_fallback"
))]
Fallback(Fallback),
#[cfg(target_arch = "aarch64")]
Neon(Neon),
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
WasmSimd128(WasmSimd128),
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(all(
target_feature = "avx2",
target_feature = "bmi1",
target_feature = "bmi2",
target_feature = "cmpxchg16b",
target_feature = "f16c",
target_feature = "fma",
target_feature = "lzcnt",
target_feature = "movbe",
target_feature = "popcnt",
target_feature = "xsave"
))
))]
Sse4_2(Sse4_2),
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
Avx2(Avx2),
}
impl Level {
#[cfg(any(feature = "std", target_arch = "wasm32"))]
#[must_use]
#[expect(
clippy::new_without_default,
reason = "The `Level::new()` function is not always available, and we also want to be explicit about when runtime feature detection happens"
)]
pub fn new() -> Self {
#[cfg(target_arch = "aarch64")]
if std::arch::is_aarch64_feature_detected!("neon") {
return unsafe { Self::Neon(Neon::new_unchecked()) };
}
#[cfg(target_arch = "wasm32")]
{
#[cfg(target_feature = "simd128")]
return Self::WasmSimd128(WasmSimd128::new_unchecked());
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
if std::arch::is_x86_feature_detected!("avx2")
&& std::arch::is_x86_feature_detected!("bmi1")
&& std::arch::is_x86_feature_detected!("bmi2")
&& std::arch::is_x86_feature_detected!("cmpxchg16b")
&& std::arch::is_x86_feature_detected!("f16c")
&& std::arch::is_x86_feature_detected!("fma")
&& std::arch::is_x86_feature_detected!("lzcnt")
&& std::arch::is_x86_feature_detected!("movbe")
&& std::arch::is_x86_feature_detected!("popcnt")
&& std::arch::is_x86_feature_detected!("xsave")
{
return unsafe { Self::Avx2(Avx2::new_unchecked()) };
} else if std::arch::is_x86_feature_detected!("sse4.2")
&& std::arch::is_x86_feature_detected!("cmpxchg16b")
&& std::arch::is_x86_feature_detected!("popcnt")
{
#[cfg(not(all(
target_feature = "avx2",
target_feature = "bmi1",
target_feature = "bmi2",
target_feature = "cmpxchg16b",
target_feature = "f16c",
target_feature = "fma",
target_feature = "lzcnt",
target_feature = "movbe",
target_feature = "popcnt",
target_feature = "xsave"
)))]
return unsafe { Self::Sse4_2(Sse4_2::new_unchecked()) };
}
}
#[cfg(any(
all(target_arch = "aarch64", not(target_feature = "neon")),
all(
any(target_arch = "x86", target_arch = "x86_64"),
not(all(
target_feature = "sse4.2",
target_feature = "cmpxchg16b",
target_feature = "popcnt"
))
),
all(target_arch = "wasm32", not(target_feature = "simd128")),
not(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "wasm32"
)),
))]
{
return Self::Fallback(Fallback::new());
}
#[allow(
unreachable_code,
reason = "`is_x86_feature_detected` or equivalents will have returned `true`, or Fallback was used."
)]
{
unreachable!()
}
}
#[allow(clippy::allow_attributes, reason = "Only needed in some cfgs.")]
#[allow(unreachable_code, reason = "Fallback unreachable in some cfgs.")]
pub fn try_detect() -> Option<Self> {
#[cfg(any(feature = "std", target_arch = "wasm32"))]
return Some(Self::new());
None
}
pub fn is_fallback(self) -> bool {
#[cfg(any(
all(target_arch = "aarch64", not(target_feature = "neon")),
all(
any(target_arch = "x86", target_arch = "x86_64"),
not(all(
target_feature = "sse4.2",
target_feature = "cmpxchg16b",
target_feature = "popcnt"
))
),
all(target_arch = "wasm32", not(target_feature = "simd128")),
not(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "wasm32"
)),
feature = "force_support_fallback"
))]
return matches!(self, Self::Fallback(_));
#[allow(unreachable_code, reason = "Fallback unreachable in some cfgs.")]
false
}
#[cfg(target_arch = "aarch64")]
#[inline]
pub fn as_neon(self) -> Option<Neon> {
#[allow(
unreachable_patterns,
reason = "On machines which statically support `neon`, there is only one variant."
)]
match self {
Self::Neon(neon) => Some(neon),
_ => None,
}
}
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
#[inline]
pub fn as_wasm_simd128(self) -> Option<WasmSimd128> {
#[allow(
unreachable_patterns,
reason = "On machines which statically support `simd128`, there is only one variant."
)]
match self {
Self::WasmSimd128(simd128) => Some(simd128),
_ => None,
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[inline]
pub fn as_sse4_2(self) -> Option<Sse4_2> {
match self {
Self::Avx2(_avx) => unsafe { Some(Sse4_2::new_unchecked()) },
#[cfg(not(all(
target_feature = "avx2",
target_feature = "bmi1",
target_feature = "bmi2",
target_feature = "cmpxchg16b",
target_feature = "f16c",
target_feature = "fma",
target_feature = "lzcnt",
target_feature = "movbe",
target_feature = "popcnt",
target_feature = "xsave"
)))]
Self::Sse4_2(sse42) => Some(sse42),
#[allow(
unreachable_patterns,
reason = "This arm is reachable on baseline x86/x86_64."
)]
_ => None,
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[inline]
pub fn as_avx2(self) -> Option<Avx2> {
#[allow(
unreachable_patterns,
reason = "On machines which statically support `avx2`, there is only one variant."
)]
match self {
Self::Avx2(avx2) => Some(avx2),
_ => None,
}
}
pub const fn baseline() -> Self {
#[cfg(not(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "wasm32"
)))]
{
return Self::Fallback(Fallback::new());
}
#[cfg(target_arch = "aarch64")]
{
#[cfg(target_feature = "neon")]
return unsafe { Self::Neon(Neon::new_unchecked()) };
#[cfg(not(target_feature = "neon"))]
return Self::Fallback(Fallback::new());
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
#[cfg(all(
target_feature = "avx2",
target_feature = "bmi1",
target_feature = "bmi2",
target_feature = "cmpxchg16b",
target_feature = "f16c",
target_feature = "fma",
target_feature = "lzcnt",
target_feature = "movbe",
target_feature = "popcnt",
target_feature = "xsave"
))]
return unsafe { Self::Avx2(Avx2::new_unchecked()) };
#[cfg(all(
all(
target_feature = "sse4.2",
target_feature = "cmpxchg16b",
target_feature = "popcnt"
),
not(all(
target_feature = "avx2",
target_feature = "bmi1",
target_feature = "bmi2",
target_feature = "cmpxchg16b",
target_feature = "f16c",
target_feature = "fma",
target_feature = "lzcnt",
target_feature = "movbe",
target_feature = "popcnt",
target_feature = "xsave"
))
))]
return unsafe { Self::Sse4_2(Sse4_2::new_unchecked()) };
#[cfg(not(all(
target_feature = "sse4.2",
target_feature = "cmpxchg16b",
target_feature = "popcnt"
)))]
return Self::Fallback(Fallback::new());
}
#[cfg(target_arch = "wasm32")]
{
#[cfg(target_feature = "simd128")]
return Self::WasmSimd128(WasmSimd128::new_unchecked());
#[cfg(not(target_feature = "simd128"))]
return Self::Fallback(Fallback::new());
}
}
#[inline]
#[cfg(feature = "force_support_fallback")]
pub const fn fallback() -> Self {
Self::Fallback(Fallback::new())
}
#[inline]
#[expect(
unreachable_patterns,
reason = "Level is `non_exhaustive`, but we are in the crate it's defined."
)]
pub fn dispatch<W: WithSimd>(self, f: W) -> W::Output {
dispatch!(self, simd => f.with_simd(simd))
}
}
#[cfg(test)]
mod tests {
use crate::Level;
const fn assert_is_send_sync<T: Send + Sync>() {}
#[test]
fn level_is_send_sync() {
assert_is_send_sync::<Level>();
}
}