1
2#[derive(Clone, Copy)]
5pub struct ComplexF32 {pub re: f32, pub im: f32}
6
7#[derive(Clone, Copy)]
8pub struct ComplexF64 {pub re: f64, pub im: f64}
9
10impl ComplexF32{
11 pub fn magnitude(self)->f32{(self.re*self.re + self.im *self.im).sqrt()}
12}
13
14pub fn cf64(re: f64, im: f64) -> ComplexF64 {ComplexF64 {re, im}}
15pub fn cf32(re: f32, im: f32) -> ComplexF32 {ComplexF32 {re, im}}
16
17impl From<ComplexF32> for ComplexF64 {
18 fn from(v: ComplexF32) -> Self {
19 cf64(v.re as f64, v.im as f64)
20 }
21}
22
23impl From<ComplexF64> for ComplexF32 {
24 fn from(v: ComplexF64) -> Self {
25 cf32(v.re as f32, v.im as f32)
26 }
27}
28
29impl std::ops::Mul<ComplexF64> for ComplexF64 {
30 type Output = ComplexF64;
31 fn mul(self, rhs: ComplexF64) -> ComplexF64 {
32 cf64(
33 self.re * rhs.re - self.im * rhs.im,
34 self.re * rhs.im + self.im * rhs.re
35 )
36 }
37}
38
39impl std::ops::Add<ComplexF64> for ComplexF64 {
40 type Output = ComplexF64;
41 fn add(self, rhs: ComplexF64) -> ComplexF64 {
42 cf64(self.re + rhs.re, self.im + rhs.im)
43 }
44}
45
46impl std::ops::Sub<ComplexF64> for ComplexF64 {
47 type Output = ComplexF64;
48 fn sub(self, rhs: ComplexF64) -> ComplexF64 {
49 cf64(self.re - rhs.re, self.im - rhs.im)
50 }
51}
52
53fn fft_f32_recursive_pow2_inner(data: &mut [ComplexF32], scratch: &mut [ComplexF32], n: usize, theta_pi: f64, stride: usize) {
56 if stride < n {
57 let stride2 = stride * 2;
58 fft_f32_recursive_pow2_inner(scratch, data, n, theta_pi, stride2);
59 fft_f32_recursive_pow2_inner(&mut scratch[stride..], &mut data[stride..], n, theta_pi, stride2);
60
61 let theta = (stride2 as f64 * theta_pi) / n as f64;
62 let wn = cf64(theta.cos(), theta.sin());
63 let mut wnk = cf64(1.0, 0.0);
64
65 for k in (0..n).step_by(stride2) {
66 let kd2 = k >> 1;
67 let kpnd2 = (k + n) >> 1;
68
69 let u: ComplexF64 = scratch[k].into();
70 let t: ComplexF64 = wnk * scratch[k + stride].into();
71
72 data[kd2] = (u + t).into();
73 data[kpnd2] = (u - t).into();
74
75 wnk = wnk * wn;
76 }
77 }
78}
79
80use std::f64::consts::PI;
81
82pub fn fft_f32_recursive_pow2_forward(data: &mut [ComplexF32], scratch: &mut [ComplexF32]) {
83 fft_f32_recursive_pow2(data, scratch, -PI)
84}
85
86pub fn fft_f32_recursive_pow2_inverse(data: &mut [ComplexF32], scratch: &mut [ComplexF32]) {
87 fft_f32_recursive_pow2(data, scratch, PI)
88}
89
90fn fft_f32_recursive_pow2(data: &mut [ComplexF32], scratch: &mut [ComplexF32], theta_pi: f64) {
91 let n = data.len();
92 if data.len() != scratch.len() {panic!()}
93 fn is_power_of_2(n: usize)->bool{n != 0 && (!(n & (n - 1))) != 0 }
94 if !is_power_of_2(n){ panic!("fft data length must be power of 2");
96 };
97 scratch.copy_from_slice(data);
98 fft_f32_recursive_pow2_inner(data, scratch, n, theta_pi, 1);
99}