axiolid_backend_cpu/
features.rs1#[non_exhaustive]
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub enum CpuInstructionSet {
7 Portable,
9 Sse42,
11 Avx2,
13 Avx512,
15 Neon,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct CpuFeatures {
23 pub sse42: bool,
25 pub avx2_fma: bool,
27 pub avx512: bool,
29 pub neon: bool,
31}
32
33impl CpuFeatures {
34 pub fn detect() -> Self {
36 let mut features = Self {
37 sse42: false,
38 avx2_fma: false,
39 avx512: false,
40 neon: false,
41 };
42 #[cfg(target_arch = "x86_64")]
43 {
44 features.sse42 = std::is_x86_feature_detected!("sse4.2");
45 features.avx2_fma =
46 std::is_x86_feature_detected!("avx2") && std::is_x86_feature_detected!("fma");
47 features.avx512 = std::is_x86_feature_detected!("avx512f")
48 && std::is_x86_feature_detected!("avx512dq");
49 }
50 #[cfg(target_arch = "aarch64")]
51 {
52 features.neon = std::arch::is_aarch64_feature_detected!("neon");
53 }
54 features
55 }
56
57 pub const fn supports(self, instruction_set: CpuInstructionSet) -> bool {
59 match instruction_set {
60 CpuInstructionSet::Portable => true,
61 CpuInstructionSet::Sse42 => self.sse42,
62 CpuInstructionSet::Avx2 => self.avx2_fma,
63 CpuInstructionSet::Avx512 => self.avx512,
64 CpuInstructionSet::Neon => self.neon,
65 }
66 }
67
68 pub const fn best(self) -> CpuInstructionSet {
70 if self.avx512 {
71 CpuInstructionSet::Avx512
72 } else if self.avx2_fma {
73 CpuInstructionSet::Avx2
74 } else if self.sse42 {
75 CpuInstructionSet::Sse42
76 } else if self.neon {
77 CpuInstructionSet::Neon
78 } else {
79 CpuInstructionSet::Portable
80 }
81 }
82}