#[macro_export]
macro_rules! dispatch {
($level:expr, $simd:pat => $op:expr) => {{ $crate::internal_unstable_dispatch_inner!($level, $simd => $op) }};
(@impl $level:expr, $simd:pat => $op:expr; $forced_fallback_arm: literal) => {{
#[inline(always)]
fn launder<S: $crate::Simd>(x: S) -> impl $crate::Simd {
x
}
match $level {
#[cfg(target_arch = "aarch64")]
$crate::Level::Neon(neon) => {
let $simd = launder(neon);
$crate::Simd::vectorize(
neon,
#[inline(always)]
|| $op,
)
}
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
$crate::Level::WasmSimd128(wasm) => {
let $simd = launder(wasm);
$crate::Simd::vectorize(
wasm,
#[inline(always)]
|| $op,
)
}
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(all(target_feature = "avx2", target_feature = "fma"))
))]
$crate::Level::Sse4_2(sse4_2) => {
let $simd = launder(sse4_2);
$crate::Simd::vectorize(
sse4_2,
#[inline(always)]
|| $op,
)
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
$crate::Level::Avx2(avx2) => {
let $simd = launder(avx2);
$crate::Simd::vectorize(
avx2,
#[inline(always)]
|| $op,
)
}
#[cfg(any(
all(target_arch = "aarch64", not(target_feature = "neon")),
all(
any(target_arch = "x86", target_arch = "x86_64"),
not(target_feature = "sse4.2")
),
all(target_arch = "wasm32", not(target_feature = "simd128")),
not(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "wasm32"
)),
$forced_fallback_arm
))]
$crate::Level::Fallback(fb) => {
let $simd = launder(fb);
$crate::Simd::vectorize(
fb,
#[inline(always)]
|| $op,
)
}
_ => unreachable!(),
}
}};
}
#[macro_export]
#[doc(hidden)]
#[cfg(feature = "force_support_fallback")]
macro_rules! internal_unstable_dispatch_inner {
($level:expr, $simd:pat => $op:expr) => {
$crate::dispatch!(
@impl $level, $simd => $op; true
)
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "force_support_fallback"))]
macro_rules! internal_unstable_dispatch_inner {
($level:expr, $simd:pat => $op:expr) => {
$crate::dispatch!(@impl $level, $simd => $op; false)
};
}
#[cfg(test)]
#[expect(
unreachable_patterns,
reason = "Level is non_exhaustive, but you must be exhaustive within the same crate."
)]
mod tests {
use crate::{Level, Simd};
#[allow(dead_code, reason = "Compile test")]
fn dispatch_generic() {
fn generic<S: Simd, T>(_: S, x: T) -> T {
x
}
dispatch!(Level::new(), simd => generic::<_, ()>(simd, ()));
}
#[allow(dead_code, reason = "Compile test")]
fn dispatch_value() {
fn make_fn<S: Simd>() -> impl FnOnce(S) {
|_| ()
}
dispatch!(Level::new(), simd => (make_fn())(simd));
}
#[test]
fn dispatch_output() {
assert_eq!(42, dispatch!(Level::new(), _simd => 42));
}
mod no_import_simd {
#[test]
fn dispatch_with_no_imports() {
let res = dispatch!(crate::Level::new(), _ => 1 + 2);
assert_eq!(res, 3);
}
}
}