#[cfg(target_arch = "aarch64")]
use crate::Neon;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use crate::{Avx2, Avx512};
use crate::{DispatchedView, Scalar};
use hermes_simd_core::{
align::Alignment, arch::SimdArch, execution::Unmasked, scalar::FloatElement, view::SimdView,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TargetId {
Scalar,
Avx2,
Avx512,
Neon,
}
impl TargetId {
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Scalar => "scalar",
Self::Avx2 => "avx2",
Self::Avx512 => "avx512",
Self::Neon => "neon",
}
}
#[must_use]
pub fn is_supported(self) -> bool {
match self {
Self::Scalar => true,
Self::Avx2 => avx2_supported(),
Self::Avx512 => avx512_supported(),
Self::Neon => neon_supported(),
}
}
}
#[inline]
fn avx2_supported() -> bool {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
Avx2::is_runtime_supported()
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
false
}
}
#[inline]
fn avx512_supported() -> bool {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
Avx512::is_runtime_supported()
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
false
}
}
#[inline]
fn neon_supported() -> bool {
#[cfg(target_arch = "aarch64")]
{
Neon::is_runtime_supported()
}
#[cfg(not(target_arch = "aarch64"))]
{
false
}
}
#[inline]
#[allow(unreachable_code)]
pub fn dispatch_view_to<'a, T, Align>(
target: TargetId,
data: &'a [T],
) -> Option<DispatchedView<'a, T, Align, Unmasked, &'a [T]>>
where
T: FloatElement,
Align: Alignment,
{
match target {
TargetId::Scalar => {
SimdView::<T, Scalar, Align, Unmasked, &'a [T]>::new(data).map(DispatchedView::Scalar)
}
TargetId::Avx2 => {
if !target.is_supported() {
None
} else {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
SimdView::<T, Avx2, Align, Unmasked, &'a [T]>::new(data)
.map(DispatchedView::Avx2)
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
None
}
}
}
TargetId::Avx512 => {
if !target.is_supported() {
None
} else {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
SimdView::<T, Avx512, Align, Unmasked, &'a [T]>::new(data)
.map(DispatchedView::Avx512)
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
None
}
}
}
TargetId::Neon => {
if !target.is_supported() {
None
} else {
#[cfg(target_arch = "aarch64")]
{
SimdView::<T, Neon, Align, Unmasked, &'a [T]>::new(data)
.map(DispatchedView::Neon)
}
#[cfg(not(target_arch = "aarch64"))]
{
None
}
}
}
}
}
#[inline]
#[allow(unreachable_code)]
pub fn dispatch_view_mut_to<'a, T, Align>(
target: TargetId,
data: &'a mut [T],
) -> Option<DispatchedView<'a, T, Align, Unmasked, &'a mut [T]>>
where
T: FloatElement,
Align: Alignment,
{
match target {
TargetId::Scalar => SimdView::<T, Scalar, Align, Unmasked, &'a mut [T]>::new_mut(data)
.map(DispatchedView::Scalar),
TargetId::Avx2 => {
if !target.is_supported() {
None
} else {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
SimdView::<T, Avx2, Align, Unmasked, &'a mut [T]>::new_mut(data)
.map(DispatchedView::Avx2)
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
None
}
}
}
TargetId::Avx512 => {
if !target.is_supported() {
None
} else {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
SimdView::<T, Avx512, Align, Unmasked, &'a mut [T]>::new_mut(data)
.map(DispatchedView::Avx512)
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
None
}
}
}
TargetId::Neon => {
if !target.is_supported() {
None
} else {
#[cfg(target_arch = "aarch64")]
{
SimdView::<T, Neon, Align, Unmasked, &'a mut [T]>::new_mut(data)
.map(DispatchedView::Neon)
}
#[cfg(not(target_arch = "aarch64"))]
{
None
}
}
}
}
}