vsimd/
native.rs

1#[derive(Debug, Clone, Copy)]
2pub struct Native(Arch);
3
4#[derive(Debug, Clone, Copy)]
5enum Arch {
6    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
7    Avx2,
8
9    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
10    Sse41,
11
12    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
13    Sse2,
14
15    #[cfg(any(all(feature = "unstable", target_arch = "arm"), target_arch = "aarch64"))]
16    Neon,
17
18    #[cfg(target_arch = "wasm32")]
19    Simd128,
20
21    Fallback,
22}
23
24impl Native {
25    #[inline]
26    #[must_use]
27    pub fn detect() -> Self {
28        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
29        {
30            if is_feature_detected!("avx2") {
31                return Self(Arch::Avx2);
32            }
33
34            if is_feature_detected!("sse4.1") {
35                return Self(Arch::Sse41);
36            }
37
38            if is_feature_detected!("sse2") {
39                return Self(Arch::Sse2);
40            }
41        }
42        #[cfg(any(all(feature = "unstable", target_arch = "arm"), target_arch = "aarch64"))]
43        {
44            if is_feature_detected!("neon") {
45                return Self(Arch::Neon);
46            }
47        }
48        #[cfg(target_arch = "wasm32")]
49        {
50            if is_feature_detected!("simd128") {
51                return Self(Arch::Simd128);
52            }
53        }
54        Self(Arch::Fallback)
55    }
56
57    #[inline]
58    pub fn exec<F, O>(self, f: F) -> O
59    where
60        F: FnOnce() -> O,
61    {
62        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
63        {
64            match self.0 {
65                Arch::Avx2 => unsafe { x86::avx2(f) },
66                Arch::Sse41 => unsafe { x86::sse41(f) },
67                Arch::Sse2 => unsafe { x86::sse2(f) },
68                Arch::Fallback => f(),
69            }
70        }
71        #[cfg(any(all(feature = "unstable", target_arch = "arm"), target_arch = "aarch64"))]
72        {
73            match self.0 {
74                Arch::Neon => unsafe { arm::neon(f) },
75                Arch::Fallback => f(),
76            }
77        }
78        #[cfg(target_arch = "wasm32")]
79        {
80            match self.0 {
81                Arch::Simd128 => unsafe { wasm::simd128(f) },
82                Arch::Fallback => f(),
83            }
84        }
85        #[cfg(not(any( //
86            any(target_arch = "x86", target_arch = "x86_64"), //
87            any(all(feature = "unstable", target_arch = "arm"), target_arch = "aarch64"), //
88            target_arch = "wasm32" //
89        )))]
90        {
91            f()
92        }
93    }
94}
95
96#[allow(unused_macros)]
97macro_rules! generic_dispatch {
98    ($name: ident, $feature: tt) => {
99        #[inline]
100        #[target_feature(enable = $feature)]
101        pub unsafe fn $name<F, O>(f: F) -> O
102        where
103            F: FnOnce() -> O,
104        {
105            f()
106        }
107    };
108}
109
110#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
111mod x86 {
112    generic_dispatch!(avx2, "avx2");
113    generic_dispatch!(sse41, "sse4.1");
114    generic_dispatch!(sse2, "sse2");
115}
116
117#[cfg(any(all(feature = "unstable", target_arch = "arm"), target_arch = "aarch64"))]
118mod arm {
119    generic_dispatch!(neon, "neon");
120}
121
122#[cfg(target_arch = "wasm32")]
123mod wasm {
124    generic_dispatch!(simd128, "simd128");
125}