lc3_codec/common/
kissfft.rs

1// Copyright (c) 2022 David Haig, Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
2// Ported to Rust from https://github.com/mborgerding/kissfft
3
4use super::complex::{Complex, Scaler};
5use core::f64::consts::PI;
6#[allow(unused_imports)]
7use num_traits::real::Real;
8
9pub struct KissFastFourierTransform<'a> {
10    inverse: bool,
11    twiddle: &'a [Complex],
12    nfft: usize,
13    factors: [usize; 64],
14}
15
16impl<'a> KissFastFourierTransform<'a> {
17    pub fn new(nfft: usize, inverse: bool, buf: &'a mut [Complex]) -> (Self, &'a mut [Complex]) {
18        let (twiddle, buf) = buf.split_at_mut(nfft);
19        for (i, tw) in twiddle.iter_mut().enumerate() {
20            let mut phase = -2.0 * PI * (i as f64) / (nfft as f64);
21            if inverse {
22                phase *= -1.0;
23            }
24
25            tw.r = phase.cos() as Scaler;
26            tw.i = phase.sin() as Scaler;
27        }
28
29        let mut factors: [usize; 64] = [0; 64];
30        Self::kf_factor(nfft, &mut factors);
31
32        (
33            Self {
34                nfft,
35                inverse,
36                twiddle,
37                factors,
38            },
39            buf,
40        )
41    }
42
43    // facbuf is populated by p1,m1,p2,m2, ...
44    // where
45    // p[i] * m[i] = m[i-1]
46    // m0 = n
47    fn kf_factor(mut n: usize, factors: &mut [usize]) {
48        let mut p = 4;
49        let floor_sqrt = (n as Scaler).sqrt().floor();
50        let mut i = 0;
51
52        // factor out powers of 4, powers of 2, then any remaining primes
53        loop {
54            while (n % p) != 0 {
55                match p {
56                    4 => p = 2,
57                    2 => p = 3,
58                    _ => p += 2,
59                };
60
61                if p as Scaler > floor_sqrt {
62                    p = n; // no more factors, skip to end
63                }
64            }
65
66            n /= p;
67            factors[i] = p;
68            i += 1;
69            factors[i] = n;
70            i += 1;
71
72            if n <= 1 {
73                break;
74            }
75        }
76    }
77
78    pub fn transform(&self, fin: &[Complex], fout: &mut [Complex]) {
79        self.kiss_fft_stride(fin, fout, 1);
80    }
81
82    fn kiss_fft_stride(&self, fin: &[Complex], fout: &mut [Complex], in_stride: usize) {
83        self.kf_work(fout, fin, 1, in_stride, 0, 0, 0);
84    }
85
86    fn kf_work(
87        &self,
88        fout: &mut [Complex],
89        fin: &[Complex],
90        fstride: usize,
91        in_stride: usize,
92        mut factor_idx: usize,
93        mut fin_idx: usize,
94        mut fout_idx: usize,
95    ) {
96        let p = self.factors[factor_idx]; // the radix
97        let m = self.factors[factor_idx + 1]; // stage's fft length/p
98        factor_idx += 2;
99
100        let fout_idx_begin = fout_idx;
101        let fout_idx_end = fout_idx + p * m;
102
103        if m == 1 {
104            for (fount_n, fin_n) in fout[fout_idx..fout_idx_end]
105                .iter_mut()
106                .zip(fin[fin_idx..].iter().step_by(fstride * in_stride))
107            {
108                *fount_n = *fin_n;
109            }
110        } else {
111            loop {
112                self.kf_work(fout, fin, fstride * p, in_stride, factor_idx, fin_idx, fout_idx);
113                fin_idx += fstride * in_stride;
114                fout_idx += m;
115
116                if fout_idx == fout_idx_end {
117                    break;
118                }
119            }
120        }
121
122        let fout_slice = &mut fout[fout_idx_begin..];
123
124        match p {
125            2 => self.kf_bfly2(fout_slice, fstride, m),
126            3 => self.kf_bfly3(fout_slice, fstride, m),
127            4 => self.kf_bfly4(fout_slice, fstride, m),
128            5 => self.kf_bfly5(fout_slice, fstride, m),
129            _ => self.kf_bfly_generic(fout_slice, fstride, m, p),
130        }
131    }
132
133    fn kf_bfly2(&self, fout: &mut [Complex], fstride: usize, m: usize) {
134        let (fout, fout2) = fout.split_at_mut(m);
135
136        for i in 0..m {
137            let t = fout2[i] * self.twiddle[i * fstride];
138            fout2[i] = fout[i] - t;
139            fout[i] += t;
140        }
141    }
142
143    fn kf_bfly4(&self, fout: &mut [Complex], fstride: usize, m: usize) {
144        let m2 = m * 2;
145        let m3 = m * 3;
146        let mut tw1 = 0;
147        let mut tw2 = 0;
148        let mut tw3 = 0;
149
150        for i in 0..m {
151            let scratch0 = fout[i + m] * self.twiddle[tw1];
152            let scratch1 = fout[i + m2] * self.twiddle[tw2];
153            let scratch2 = fout[i + m3] * self.twiddle[tw3];
154
155            let scratch5 = fout[i] - scratch1;
156            fout[i] += scratch1;
157            let scratch3 = scratch0 + scratch2;
158            let scratch4 = scratch0 - scratch2;
159            fout[i + m2] = fout[i] - scratch3;
160            fout[i] += scratch3;
161            tw1 += fstride;
162            tw2 += fstride * 2;
163            tw3 += fstride * 3;
164
165            if self.inverse {
166                fout[i + m] = Complex::new(scratch5.r - scratch4.i, scratch5.i + scratch4.r);
167                fout[i + m3] = Complex::new(scratch5.r + scratch4.i, scratch5.i - scratch4.r)
168            } else {
169                fout[i + m] = Complex::new(scratch5.r + scratch4.i, scratch5.i - scratch4.r);
170                fout[i + m3] = Complex::new(scratch5.r - scratch4.i, scratch5.i + scratch4.r)
171            }
172        }
173    }
174
175    fn kf_bfly3(&self, fout: &mut [Complex], fstride: usize, m: usize) {
176        let m2 = m * 2;
177        let epi3 = self.twiddle[fstride * m];
178        let mut tw1 = 0;
179        let mut tw2 = 0;
180
181        for i in 0..m {
182            let scratch1 = fout[i + m] * self.twiddle[tw1];
183            let scratch2 = fout[i + m2] * self.twiddle[tw2];
184
185            let scratch3 = scratch1 + scratch2;
186            let mut scratch0 = scratch1 - scratch2;
187            tw1 += fstride;
188            tw2 += fstride * 2;
189
190            let fouti = fout[i];
191            fout[i + m] = Complex {
192                r: fouti.r - (scratch3.r * 0.5),
193                i: fouti.i - (scratch3.i * 0.5),
194            };
195
196            scratch0 *= epi3.i;
197            fout[i] += scratch3;
198
199            let foutm = fout[i + m];
200            fout[i + m2] = Complex::new(foutm.r + scratch0.i, foutm.i - scratch0.r);
201            fout[i + m] = Complex::new(foutm.r - scratch0.i, foutm.i + scratch0.r);
202        }
203    }
204
205    fn kf_bfly5(&self, fout: &mut [Complex], fstride: usize, m: usize) {
206        let ya = self.twiddle[fstride * m];
207        let yb = self.twiddle[fstride * 2 * m];
208
209        let m1 = m;
210        let m2 = m * 2;
211        let m3 = m * 3;
212        let m4 = m * 4;
213
214        for i in 0..m {
215            let scratch0 = fout[i];
216
217            let scratch1 = fout[i + m1] * self.twiddle[i * fstride];
218            let scratch2 = fout[i + m2] * self.twiddle[i * 2 * fstride];
219            let scratch3 = fout[i + m3] * self.twiddle[i * 3 * fstride];
220            let scratch4 = fout[i + m4] * self.twiddle[i * 4 * fstride];
221
222            let scratch7 = scratch1 + scratch4;
223            let scratch10 = scratch1 - scratch4;
224            let scratch8 = scratch2 + scratch3;
225            let scratch9 = scratch2 - scratch3;
226
227            fout[i].r += scratch7.r + scratch8.r;
228            fout[i].i += scratch7.i + scratch8.i;
229
230            let scratch5 = Complex {
231                r: scratch0.r + (scratch7.r * ya.r) + (scratch8.r * yb.r),
232                i: scratch0.i + (scratch7.i * ya.r) + (scratch8.i * yb.r),
233            };
234
235            let scratch6 = Complex {
236                r: (scratch10.i * ya.i) + (scratch9.i * yb.i),
237                i: -(scratch10.r * ya.i) - (scratch9.r * yb.i),
238            };
239
240            fout[i + m1] = scratch5 - scratch6;
241            fout[i + m4] = scratch5 + scratch6;
242
243            let scratch11 = Complex {
244                r: scratch0.r + (scratch7.r * yb.r) + (scratch8.r * ya.r),
245                i: scratch0.i + (scratch7.i * yb.r) + (scratch8.i * ya.r),
246            };
247
248            let scratch12 = Complex {
249                r: -(scratch10.i * yb.i) + (scratch9.i * ya.i),
250                i: (scratch10.r * yb.i) - (scratch9.r * ya.i),
251            };
252
253            fout[i + m2] = scratch11 + scratch12;
254            fout[i + m3] = scratch11 - scratch12;
255        }
256    }
257
258    fn kf_bfly_generic(&self, fout: &mut [Complex], fstride: usize, m: usize, p: usize) {
259        let mut k;
260
261        // TODO: use a dynamic buffer somehow
262        let mut scratch = [Complex::default(); 480];
263
264        for u in 0..m {
265            k = u;
266            for scratch_q1 in &mut scratch[..m] {
267                *scratch_q1 = fout[k];
268                k += m;
269            }
270
271            k = u;
272            for _ in 0..p {
273                let mut twidx = 0;
274                fout[k] = scratch[0];
275                for scratch_q in &mut scratch[1..p] {
276                    twidx += fstride * k;
277                    if twidx >= self.nfft {
278                        twidx -= self.nfft;
279                    }
280
281                    let t = *scratch_q * self.twiddle[twidx];
282                    fout[k] += t;
283                }
284
285                k += m;
286            }
287        }
288    }
289}
290
291#[cfg(test)]
292mod tests {
293    extern crate std;
294    use super::*;
295    use heapless::Vec;
296
297    #[test]
298    fn kissfft_non_inverse() {
299        #[rustfmt::skip] // until the latest rustfmt is released with short_array_element_width_threshold support
300        let i = [
301            1.855615, -116.9618, 14.5051155, 174.72545, -120.26939, -170.81615, 50.498768, 29.882944, 10.935101,
302            49.613552, -237.16743, 457.65805, 166.74161, -21.331354, -293.06955, -421.02695, -43.089565, -236.74684,
303            -158.98152, -89.15972, -239.22202, 63.367065, -10.9238825, 63.89845, -22.31455, -23.430895, 107.762054,
304            66.95872, 21.984243, -14.36995, 171.00829, 210.63702, 52.828213, -172.75896, -62.871365, -64.52872,
305            15.716181, -13.96337, -8.880015, -14.489226, 13.111881, -19.8435, -2.8529816, -49.936447, -58.36318,
306            39.232166, 25.754477, -121.766396, 104.3299, 28.673597, 3.1306546, -26.594135, 49.70436, -9.31528,
307            -15.198294, 40.402843, -40.498585, 22.088074, -42.21869, 29.077738, -39.54687, 4.737952, -33.50602,
308            42.880722, -37.41781, -10.550791, 2.7522528, 4.6168604, -4.7794275, -3.046289, -12.713707, 8.274482,
309            -17.892733, 2.5210698, -2.371197, 1.1339488, 2.3877633, -7.4157476, 9.761844, -25.59829, -6.217507,
310            -12.569953, 0.78294086, -9.83709, 5.5962806, 2.8984036, -11.539186, 2.994965, -5.26814, -0.11291276,
311            -10.728054, -3.672079, -12.828666, 6.368055, 8.137624, -2.7822683, 11.612916, 0.3329181, -6.4356623,
312            -9.272606, 0.0, 6.5034328, 0.0, 6.4365535, -5.6137466, -11.167647, 1.4393897, -1.3767548, -8.357129,
313            -4.210443, 0.0, -1.1256523, 0.0, 14.775933, 0.0, 5.0709095, 4.606481, 9.646306, -4.669522, 0.0, -4.9205875,
314            4.692957, -0.32278347, -0.38587618, 0.0, 0.0, -9.644276, 19.285547, 5.3756537, 0.0, -4.2342334, 5.469494,
315            0.0, 2.746046, -9.667411, 5.591327, 4.1758385, 10.586916, 4.107868, 0.0, 4.2955832, -2.8468177, -1.4351681,
316            4.918048, 1.3821423, 0.3282499, -15.087164, 9.986603, 2.7261941, -9.2014265, 15.278996, -6.504345,
317            9.124997, -10.493915, 13.827347, -15.75687, 6.722817, -2.5194824, 1.3646965, 5.03867, 8.2033415,
318            -1.8157947, -19.182993, 24.903381, -12.887679, 3.9698439, 11.647475, 7.5046215, 20.741192, -5.567567,
319            -0.43412608, 3.9644055, 18.985268, 8.338453, -11.85746, 34.65426, -16.266304, -10.606885, 29.178452,
320            45.139923, -1.6687171, 6.683766, 12.766115, 17.879122, 18.518923, -53.55422, 41.24579, -22.229282,
321            36.130154, 2.5491073, -20.51049, -96.19117, -13.34205, 103.88622, -50.21851, 41.127357, 56.53239,
322            25.900309, -24.370209, 35.459366, 8.997509, 6.981312, 18.012835, -4.197822, 4.049564, 43.40604, 62.774452,
323            53.30865, -138.9981, -236.68228, -114.54468, 34.831924, -105.52745, -84.97478, 20.664078, 75.2232,
324            -126.548836, 66.99325, 54.068527, 268.94693, -291.25183, 3.4395313, 74.424446, 142.78764, 158.3345,
325            127.41658, 208.42499, -67.842674, 14.712677, -289.51437, -79.78527, 75.367485, 36.252354, -178.21283,
326            58.44521, -41.093452, 13.163652, -219.22577, 119.97857, 45.07003,
327        ];
328        #[rustfmt::skip] // until the latest rustfmt is released with short_array_element_width_threshold support
329        let r = [
330            -2268.1362, 15884.554, -1042.859, -8541.555, 4453.659, 5090.536, -1259.022, -640.3463, -205.43816, -829.74,
331            3573.6746, -6274.2817, -2096.7207, 247.70819, 3161.0686, 4239.2007, 406.76834, 2103.396, 1333.8778,
332            708.5689, 1805.6552, -455.3847, 74.90909, -418.95355, 140.14635, 141.19998, -624.07874, -373.19193,
333            -118.077156, 74.46896, -856.05585, -1019.6481, -247.5412, 784.3248, 276.79922, 275.7283, -65.22747,
334            56.331127, 34.845627, 55.340305, 49.49789, 71.93409, -83.632904, 172.19783, 196.44048, -41.29998,
335            3.1031866, 298.14954, -320.20282, -86.086266, -9.197882, -1.1975169, -63.744102, 25.702515, -17.486677,
336            -107.08196, 122.926926, -38.912254, 88.469284, -88.17956, 95.2541, 40.969517, 26.432041, -97.815445,
337            83.85707, 23.235506, -5.957274, 28.303192, 9.999217, 6.2674932, -10.877085, -16.472115, 35.045555,
338            -4.859095, 4.4979696, -2.1173005, -4.389146, 13.42149, -17.397625, 18.72114, 10.74872, -4.2159653,
339            -26.653864, 16.260973, -9.115551, 14.897083, -1.0913692, -4.670179, 8.0977125, 0.171099, -2.5562663,
340            -12.994965, 0.40452194, -9.120969, 6.395524, 3.8759496, -1.9462404, -0.45119837, -5.160027, -1.4159701,
341            0.0, 5.066773, 0.0, 5.151467, -4.553532, -9.180352, 9.565273, -9.57449, 9.768746, 4.8569202, 0.0,
342            -9.607248, 0.0, 4.4450912, 0.0, 4.7572193, -4.846271, 0.0071697235, 4.785559, 0.0, 4.912543, 4.76258,
343            9.640907, 9.638588, 0.0, 0.0, -0.1980052, 0.52224445, -4.832303, 0.0, -4.836194, -4.7258277, 0.0, 14.49062,
344            -0.32784557, -4.581033, 5.1653657, 0.051658154, 5.2195835, 0.0, 5.607607, 9.907007, -1.9252065, -7.228178,
345            1.9056323, 0.45886463, -3.4534411, -3.7460012, 3.9735973, -13.601632, 4.2780867, 8.922779, 14.076463,
346            -16.422688, 21.954798, -0.7839532, 10.990813, -4.180201, -23.11197, 8.612942, 14.235487, -3.1992202,
347            -7.7281303, 18.339417, 3.4489067, 7.441694, -12.700758, 14.522442, 5.011389, -11.128785, -0.88213927,
348            8.190503, 2.1540232, 17.818396, -25.776266, 116.01507, -36.615303, -24.30349, 16.492369, 107.23625,
349            -4.0379806, -0.41632032, 14.90279, 28.331722, 48.361664, -142.64403, 53.24363, -61.64924, 25.688564,
350            7.3704824, 18.976349, -290.37704, -41.177204, 327.9252, -162.19847, 135.97911, 191.42513, 89.86247,
351            -86.68163, 225.87943, 33.689384, 26.84368, 71.16971, -17.054327, 16.928648, 186.84947, 278.48138,
352            243.92023, -656.57544, -1155.2651, -578.32733, 182.10963, -571.9864, -478.1029, 120.85015, 457.95102,
353            -803.2506, 444.11896, 375.0647, 1956.2184, -2226.3508, 27.700428, 633.2471, 1287.5594, 1518.4009,
354            1304.6234, 2288.822, -803.1884, 188.91817, -4060.6724, -1232.7405, 1296.0394, 702.736, -3957.8958,
355            1519.2118, -1287.4844, 518.92303, -11649.14, 9776.242, 7869.8496,
356        ];
357        let fin: Vec<Complex, 240> = i.iter().zip(r.iter()).map(|(i, r)| Complex { i: *i, r: *r }).collect();
358        let mut fout = [Complex { r: 0., i: 0. }; 240];
359        let mut buf = [Complex { r: 0., i: 0. }; 960];
360        let (kiss, _) = KissFastFourierTransform::new(240, false, &mut buf);
361
362        kiss.transform(&fin, &mut fout);
363
364        #[rustfmt::skip] // until the latest rustfmt is released with short_array_element_width_threshold support
365        let i_expected = [
366            -896.3453, -4488.7217, -7348.4097, -8887.922, -9056.146, -8633.422, -7771.1133, -6862.5684, -5966.8647,
367            -4794.6694, -3277.541, -2362.5103, -2648.3076, -4637.6445, -7722.6855, -10517.553, -12167.851, -11895.811,
368            -10294.406, -6730.038, -3189.6895, -212.61719, 1695.5674, 3190.8154, 3974.3643, 4835.683, 5128.774,
369            4992.3984, 4730.4004, 4389.5146, 4860.956, 6220.8086, 8196.442, 9534.402, 9965.566, 10040.663, 8795.088,
370            6908.338, 5099.788, 4367.3115, 5261.6016, 7660.9775, 10635.146, 12834.795, 14190.124, 15401.457, 15966.678,
371            15080.604, 11752.904, 6528.422, -47.00586, -6731.8564, -12396.52, -15380.836, -14591.621, -11277.795,
372            -7294.1143, -4296.804, -2964.048, -2926.015, -4714.9014, -7532.2715, -9407.004, -10135.502, -9732.238,
373            -7904.591, -6192.056, -6940.635, -9606.486, -12903.244, -15492.834, -18961.992, -23103.61, -27405.797,
374            -29388.904, -29414.887, -28263.479, -26479.133, -25115.285, -23378.51, -20494.865, -16748.465, -14825.195,
375            -13741.304, -12949.355, -11320.935, -9801.74, -8669.303, -7205.6455, -4593.545, -1380.3279, 1307.0344,
376            3371.2295, 3574.2065, 457.13086, -4329.633, -10391.41, -17537.012, -24489.14, -29612.652, -31701.77,
377            -30683.785, -27333.87, -23373.05, -19662.098, -15592.686, -10969.874, -9652.483, -12050.671, -15667.203,
378            -17695.102, -17627.69, -17042.242, -15240.029, -10514.387, -4804.282, -2072.7874, -449.5752, 695.19995,
379            979.40796, -337.52313, -980.9072, -455.32568, 1171.4072, 3089.063, 7586.956, 13284.129, 16304.463,
380            17308.146, 17924.953, 17094.623, 13899.211, 10404.032, 9899.697, 13289.42, 17761.877, 21285.863, 25417.158,
381            29363.082, 31639.887, 31055.436, 27179.994, 21219.563, 13975.247, 7321.411, 1677.0073, -2168.726,
382            -3824.5117, -2663.2678, 221.7998, 3101.007, 6073.8594, 8232.202, 9236.254, 10254.33, 12356.3545, 13808.623,
383            14356.297, 15419.96, 18305.484, 22229.963, 24700.785, 26010.158, 27290.873, 28570.363, 29864.484,
384            28959.229, 25460.232, 21015.799, 16974.258, 14256.016, 11488.241, 8214.137, 6183.765, 6754.65, 9111.895,
385            10397.212, 9749.779, 8525.632, 6088.3584, 4015.7473, 2787.0684, 3240.4868, 5434.22, 9199.211, 13330.116,
386            15496.234, 14242.875, 9488.965, 3375.684, -3224.5352, -9347.34, -13943.14, -15577.625, -15884.67,
387            -15076.272, -13680.928, -11553.199, -9096.786, -6496.449, -4688.635, -4697.0884, -5807.9595, -7819.5557,
388            -9396.357, -10362.897, -10247.072, -8893.734, -6961.0557, -5423.092, -4749.4805, -4762.9385, -4830.626,
389            -5091.946, -4845.26, -4570.2734, -3763.0854, -2455.878, -831.5654, 1664.6982, 4887.417, 8525.93, 11249.24,
390            12326.012, 11468.231, 9091.9, 6077.5947, 3478.9658, 2179.4658, 2611.1597, 4045.4658, 5397.168, 6509.3906,
391            7333.2676, 8053.2095, 8909.406, 9262.348, 8129.1543, 6024.133, 2698.7732,
392        ];
393        #[rustfmt::skip] // until the latest rustfmt is released with short_array_element_width_threshold support
394        let r_expected = [
395            22463.031, 20687.656, 18938.639, 16552.432, 13054.607, 8478.361, 4482.206, 1863.2534, 2557.4702, 8585.197,
396            19899.19, 32245.17, 39807.28, 40962.65, 38021.574, 33295.973, 27790.02, 21848.932, 16815.977, 13104.005,
397            9667.043, 5442.6763, 775.18945, -2316.7344, -968.5049, 5868.5225, 15741.287, 24789.06, 30714.914, 33193.49,
398            33878.58, 34844.12, 35693.54, 35565.125, 33593.215, 29715.025, 23825.605, 15314.43, 7737.08, 3866.3477,
399            4978.002, 8941.834, 12872.077, 14767.818, 14871.5625, 15655.988, 18796.977, 23558.57, 28997.191, 33544.406,
400            36017.28, 34786.617, 29209.95, 23260.598, 19942.143, 18162.797, 14536.174, 7955.586, -627.1543, -9538.855,
401            -19004.139, -26946.303, -30561.172, -30699.252, -28782.04, -25127.66, -23012.48, -25992.322, -31707.596,
402            -35531.313, -35675.34, -35293.832, -36190.34, -37733.305, -37519.57, -35751.14, -34812.695, -35263.25,
403            -36943.71, -37698.863, -36002.227, -34473.12, -36260.977, -40381.52, -43735.594, -44696.824, -44037.0,
404            -43954.566, -44084.18, -42908.184, -40703.773, -37639.47, -33198.063, -28522.533, -24583.81, -19996.504,
405            -15642.409, -13006.758, -11780.721, -11306.558, -10891.8545, -11192.351, -12074.218, -14598.984, -18563.43,
406            -20779.35, -20379.64, -20249.375, -20987.2, -20362.086, -16455.709, -9746.61, -4073.0903, 255.51074,
407            6277.117, 13193.121, 17535.482, 18126.527, 16800.584, 15386.298, 14923.699, 15798.797, 17766.568,
408            18348.041, 15587.701, 9876.861, 3142.5303, -1758.3931, -6900.569, -13342.086, -18483.709, -20936.006,
409            -20818.42, -20057.115, -20887.691, -20048.611, -16067.883, -13299.018, -11584.943, -10958.364, -10984.371,
410            -11256.848, -12123.95, -14255.818, -17959.262, -22185.246, -26248.416, -30952.955, -35588.305, -39435.88,
411            -41809.953, -43599.926, -44190.477, -43873.47, -44160.754, -44626.99, -42515.285, -38196.797, -34631.055,
412            -34777.13, -37341.22, -37635.313, -35930.1, -34778.68, -34911.813, -36671.19, -37997.477, -37040.59,
413            -35457.625, -35227.188, -35935.273, -34238.93, -28718.543, -23645.973, -23746.943, -27160.195, -30056.264,
414            -30512.848, -29239.018, -23755.016, -14422.357, -4779.3516, 3928.8828, 11605.482, 16692.398, 18875.734,
415            21315.664, 26091.303, 32388.385, 36319.844, 34928.332, 31071.982, 26291.984, 21370.008, 17027.232,
416            14918.146, 14491.955, 14206.109, 11248.764, 6760.414, 4022.662, 4988.824, 11078.184, 19751.332, 27246.023,
417            31910.879, 34627.688, 35954.293, 35219.836, 34289.316, 33597.43, 32285.844, 28411.428, 20499.744,
418            10343.416, 2068.959, -2232.4482, -1369.6509, 3216.06, 7660.507, 11380.53, 14872.581, 19196.238, 24769.77,
419            30682.438, 35799.902, 40010.426, 40863.52, 36800.28, 26381.797, 14009.543, 4786.0664, 1523.4565, 2811.4375,
420            6413.793, 10949.314, 15123.091, 17686.055, 19688.299, 21926.379,
421        ];
422        let i_actual: Vec<f32, 240> = fout.iter().map(|x| x.i).collect();
423        let r_actual: Vec<f32, 240> = fout.iter().map(|x| x.r).collect();
424        assert_eq!(i_actual, i_expected);
425        assert_eq!(r_actual, r_expected);
426    }
427}