1#[cfg(target_arch = "aarch64")]
4use crate::Neon;
5#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
6use crate::{Avx2, Avx512};
7use crate::{DispatchedView, Scalar};
8use hermes_simd_core::{
9 align::Alignment, arch::SimdArch, execution::Unmasked, scalar::FloatElement, view::SimdView,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum TargetId {
20 Scalar,
22 Avx2,
24 Avx512,
26 Neon,
28}
29
30impl TargetId {
31 #[must_use]
33 pub const fn name(self) -> &'static str {
34 match self {
35 Self::Scalar => "scalar",
36 Self::Avx2 => "avx2",
37 Self::Avx512 => "avx512",
38 Self::Neon => "neon",
39 }
40 }
41
42 #[must_use]
44 pub fn is_supported(self) -> bool {
45 match self {
46 Self::Scalar => true,
47 Self::Avx2 => avx2_supported(),
48 Self::Avx512 => avx512_supported(),
49 Self::Neon => neon_supported(),
50 }
51 }
52}
53
54#[inline]
55fn avx2_supported() -> bool {
56 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
57 {
58 Avx2::is_runtime_supported()
59 }
60 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
61 {
62 false
63 }
64}
65
66#[inline]
67fn avx512_supported() -> bool {
68 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
69 {
70 Avx512::is_runtime_supported()
71 }
72 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
73 {
74 false
75 }
76}
77
78#[inline]
79fn neon_supported() -> bool {
80 #[cfg(target_arch = "aarch64")]
81 {
82 Neon::is_runtime_supported()
83 }
84 #[cfg(not(target_arch = "aarch64"))]
85 {
86 false
87 }
88}
89
90#[inline]
95#[allow(unreachable_code)]
96pub fn dispatch_view_to<'a, T, Align>(
97 target: TargetId,
98 data: &'a [T],
99) -> Option<DispatchedView<'a, T, Align, Unmasked, &'a [T]>>
100where
101 T: FloatElement,
102 Align: Alignment,
103{
104 match target {
105 TargetId::Scalar => {
106 SimdView::<T, Scalar, Align, Unmasked, &'a [T]>::new(data).map(DispatchedView::Scalar)
107 }
108 TargetId::Avx2 => {
109 if !target.is_supported() {
110 None
111 } else {
112 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
113 {
114 SimdView::<T, Avx2, Align, Unmasked, &'a [T]>::new(data)
115 .map(DispatchedView::Avx2)
116 }
117 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
118 {
119 None
120 }
121 }
122 }
123 TargetId::Avx512 => {
124 if !target.is_supported() {
125 None
126 } else {
127 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
128 {
129 SimdView::<T, Avx512, Align, Unmasked, &'a [T]>::new(data)
130 .map(DispatchedView::Avx512)
131 }
132 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
133 {
134 None
135 }
136 }
137 }
138 TargetId::Neon => {
139 if !target.is_supported() {
140 None
141 } else {
142 #[cfg(target_arch = "aarch64")]
143 {
144 SimdView::<T, Neon, Align, Unmasked, &'a [T]>::new(data)
145 .map(DispatchedView::Neon)
146 }
147 #[cfg(not(target_arch = "aarch64"))]
148 {
149 None
150 }
151 }
152 }
153 }
154}
155
156#[inline]
161#[allow(unreachable_code)]
162pub fn dispatch_view_mut_to<'a, T, Align>(
163 target: TargetId,
164 data: &'a mut [T],
165) -> Option<DispatchedView<'a, T, Align, Unmasked, &'a mut [T]>>
166where
167 T: FloatElement,
168 Align: Alignment,
169{
170 match target {
171 TargetId::Scalar => SimdView::<T, Scalar, Align, Unmasked, &'a mut [T]>::new_mut(data)
172 .map(DispatchedView::Scalar),
173 TargetId::Avx2 => {
174 if !target.is_supported() {
175 None
176 } else {
177 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
178 {
179 SimdView::<T, Avx2, Align, Unmasked, &'a mut [T]>::new_mut(data)
180 .map(DispatchedView::Avx2)
181 }
182 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
183 {
184 None
185 }
186 }
187 }
188 TargetId::Avx512 => {
189 if !target.is_supported() {
190 None
191 } else {
192 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
193 {
194 SimdView::<T, Avx512, Align, Unmasked, &'a mut [T]>::new_mut(data)
195 .map(DispatchedView::Avx512)
196 }
197 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
198 {
199 None
200 }
201 }
202 }
203 TargetId::Neon => {
204 if !target.is_supported() {
205 None
206 } else {
207 #[cfg(target_arch = "aarch64")]
208 {
209 SimdView::<T, Neon, Align, Unmasked, &'a mut [T]>::new_mut(data)
210 .map(DispatchedView::Neon)
211 }
212 #[cfg(not(target_arch = "aarch64"))]
213 {
214 None
215 }
216 }
217 }
218 }
219}