1use crate::fft_helper::{fft_helper_immut, fft_helper_inplace, fft_helper_outofplace};
2use crate::{Fft, FftDirection, FftNum};
3use std::arch::x86_64::{__m256, __m256d};
4use std::sync::Arc;
5
6pub trait AvxNum: FftNum {
7 type VectorType: AvxVector256<ScalarType = Self>;
8}
9
10impl AvxNum for f32 {
11 type VectorType = __m256;
12}
13impl AvxNum for f64 {
14 type VectorType = __m256d;
15}
16
17struct CommonSimdData<T, V> {
20 inner_fft: Arc<dyn Fft<T>>,
21 twiddles: Box<[V]>,
22
23 len: usize,
24
25 inplace_scratch_len: usize,
26 outofplace_scratch_len: usize,
27 immut_scratch_len: usize,
28
29 direction: FftDirection,
30}
31
32macro_rules! boilerplate_avx_fft {
33 ($struct_name:ident, $len_fn:expr, $inplace_scratch_len_fn:expr, $out_of_place_scratch_len_fn:expr, $immut_scratch_len_fn:expr) => {
34 impl<A: AvxNum, T: FftNum> Fft<T> for $struct_name<A, T> {
35 fn process_immutable_with_scratch(
36 &self,
37 input: &[Complex<T>],
38 output: &mut [Complex<T>],
39 scratch: &mut [Complex<T>],
40 ) {
41 unsafe {
42 super::avx_fft_helper_immut(
43 input,
44 output,
45 scratch,
46 self.len(),
47 self.get_immutable_scratch_len(),
48 |in_chunk, out_chunk, scratch| {
49 self.perform_fft_immut(in_chunk, out_chunk, scratch)
50 },
51 )
52 }
53 }
54
55 fn process_outofplace_with_scratch(
56 &self,
57 input: &mut [Complex<T>],
58 output: &mut [Complex<T>],
59 scratch: &mut [Complex<T>],
60 ) {
61 unsafe {
62 super::avx_fft_helper_outofplace(
63 input,
64 output,
65 scratch,
66 self.len(),
67 self.get_outofplace_scratch_len(),
68 |in_chunk, out_chunk, scratch| {
69 self.perform_fft_out_of_place(in_chunk, out_chunk, scratch)
70 },
71 )
72 }
73 }
74 fn process_with_scratch(&self, buffer: &mut [Complex<T>], scratch: &mut [Complex<T>]) {
75 unsafe {
76 super::avx_fft_helper_inplace(
77 buffer,
78 scratch,
79 self.len(),
80 self.get_inplace_scratch_len(),
81 |chunk, scratch| self.perform_fft_inplace(chunk, scratch),
82 )
83 }
84 }
85 #[inline(always)]
86 fn get_inplace_scratch_len(&self) -> usize {
87 $inplace_scratch_len_fn(self)
88 }
89 #[inline(always)]
90 fn get_outofplace_scratch_len(&self) -> usize {
91 $out_of_place_scratch_len_fn(self)
92 }
93 #[inline(always)]
94 fn get_immutable_scratch_len(&self) -> usize {
95 $immut_scratch_len_fn(self)
96 }
97 }
98 impl<A: AvxNum, T> Length for $struct_name<A, T> {
99 #[inline(always)]
100 fn len(&self) -> usize {
101 $len_fn(self)
102 }
103 }
104 impl<A: AvxNum, T> Direction for $struct_name<A, T> {
105 #[inline(always)]
106 fn fft_direction(&self) -> FftDirection {
107 self.direction
108 }
109 }
110 };
111}
112
113macro_rules! boilerplate_avx_fft_commondata {
114 ($struct_name:ident) => {
115 impl<A: AvxNum, T: FftNum> Fft<T> for $struct_name<A, T> {
116 fn process_immutable_with_scratch(
117 &self,
118 input: &[Complex<T>],
119 output: &mut [Complex<T>],
120 scratch: &mut [Complex<T>],
121 ) {
122 unsafe {
123 super::avx_fft_helper_immut(
124 input,
125 output,
126 scratch,
127 self.len(),
128 self.get_immutable_scratch_len(),
129 |in_chunk, out_chunk, scratch| {
130 self.perform_fft_immut(in_chunk, out_chunk, scratch)
131 },
132 )
133 }
134 }
135 fn process_outofplace_with_scratch(
136 &self,
137 input: &mut [Complex<T>],
138 output: &mut [Complex<T>],
139 scratch: &mut [Complex<T>],
140 ) {
141 unsafe {
142 super::avx_fft_helper_outofplace(
143 input,
144 output,
145 scratch,
146 self.len(),
147 self.get_outofplace_scratch_len(),
148 |in_chunk, out_chunk, scratch| {
149 self.perform_fft_out_of_place(in_chunk, out_chunk, scratch)
150 },
151 )
152 }
153 }
154 fn process_with_scratch(&self, buffer: &mut [Complex<T>], scratch: &mut [Complex<T>]) {
155 unsafe {
156 super::avx_fft_helper_inplace(
157 buffer,
158 scratch,
159 self.len(),
160 self.get_inplace_scratch_len(),
161 |chunk, scratch| self.perform_fft_inplace(chunk, scratch),
162 )
163 }
164 }
165 #[inline(always)]
166 fn get_inplace_scratch_len(&self) -> usize {
167 self.common_data.inplace_scratch_len
168 }
169 #[inline(always)]
170 fn get_outofplace_scratch_len(&self) -> usize {
171 self.common_data.outofplace_scratch_len
172 }
173 #[inline(always)]
174 fn get_immutable_scratch_len(&self) -> usize {
175 self.common_data.immut_scratch_len
176 }
177 }
178 impl<A: AvxNum, T> Length for $struct_name<A, T> {
179 #[inline(always)]
180 fn len(&self) -> usize {
181 self.common_data.len
182 }
183 }
184 impl<A: AvxNum, T> Direction for $struct_name<A, T> {
185 #[inline(always)]
186 fn fft_direction(&self) -> FftDirection {
187 self.common_data.direction
188 }
189 }
190 };
191}
192
193#[target_feature(enable = "avx", enable = "fma")]
196pub unsafe fn avx_fft_helper_immut<T>(
197 input: &[T],
198 output: &mut [T],
199 scratch: &mut [T],
200 chunk_size: usize,
201 required_scratch: usize,
202 chunk_fn: impl FnMut(&[T], &mut [T], &mut [T]),
203) {
204 fft_helper_immut(
205 input,
206 output,
207 scratch,
208 chunk_size,
209 required_scratch,
210 chunk_fn,
211 )
212}
213
214#[target_feature(enable = "avx", enable = "fma")]
217pub unsafe fn avx_fft_helper_outofplace<T>(
218 input: &mut [T],
219 output: &mut [T],
220 scratch: &mut [T],
221 chunk_size: usize,
222 required_scratch: usize,
223 chunk_fn: impl FnMut(&mut [T], &mut [T], &mut [T]),
224) {
225 fft_helper_outofplace(
226 input,
227 output,
228 scratch,
229 chunk_size,
230 required_scratch,
231 chunk_fn,
232 )
233}
234
235#[target_feature(enable = "avx", enable = "fma")]
238pub unsafe fn avx_fft_helper_inplace<T>(
239 buffer: &mut [T],
240 scratch: &mut [T],
241 chunk_size: usize,
242 required_scratch: usize,
243 chunk_fn: impl FnMut(&mut [T], &mut [T]),
244) {
245 fft_helper_inplace(buffer, scratch, chunk_size, required_scratch, chunk_fn)
246}
247
248#[macro_use]
249mod avx_vector;
250
251mod avx32_butterflies;
252mod avx32_utils;
253
254mod avx64_butterflies;
255mod avx64_utils;
256
257mod avx_bluesteins;
258mod avx_mixed_radix;
259mod avx_raders;
260
261pub mod avx_planner;
262
263pub use self::avx32_butterflies::{
264 Butterfly11Avx, Butterfly128Avx, Butterfly12Avx, Butterfly16Avx, Butterfly24Avx,
265 Butterfly256Avx, Butterfly27Avx, Butterfly32Avx, Butterfly36Avx, Butterfly48Avx,
266 Butterfly512Avx, Butterfly54Avx, Butterfly5Avx, Butterfly64Avx, Butterfly72Avx, Butterfly7Avx,
267 Butterfly8Avx, Butterfly9Avx,
268};
269
270pub use self::avx64_butterflies::{
271 Butterfly11Avx64, Butterfly128Avx64, Butterfly12Avx64, Butterfly16Avx64, Butterfly18Avx64,
272 Butterfly24Avx64, Butterfly256Avx64, Butterfly27Avx64, Butterfly32Avx64, Butterfly36Avx64,
273 Butterfly512Avx64, Butterfly5Avx64, Butterfly64Avx64, Butterfly7Avx64, Butterfly8Avx64,
274 Butterfly9Avx64,
275};
276
277pub use self::avx_bluesteins::BluesteinsAvx;
278pub use self::avx_mixed_radix::{
279 MixedRadix11xnAvx, MixedRadix12xnAvx, MixedRadix16xnAvx, MixedRadix2xnAvx, MixedRadix3xnAvx,
280 MixedRadix4xnAvx, MixedRadix5xnAvx, MixedRadix6xnAvx, MixedRadix7xnAvx, MixedRadix8xnAvx,
281 MixedRadix9xnAvx,
282};
283pub use self::avx_raders::RadersAvx2;
284use self::avx_vector::AvxVector256;