-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfft.rs
118 lines (108 loc) · 2.72 KB
/
fft.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// [ Reference ]
// Publication : An Algorithm for the Machine Calculation of Complex Fourier Series
// - Cooley & Tukey
// Streamlined : The Fast Fourier Transform
// - Reducible (YouTube)
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Mul;
use std::ops::MulAssign;
#[derive(Debug, Clone, Copy)]
struct Complex {
x: f64,
y: f64,
}
impl Add for Complex {
type Output = Complex;
fn add(self, other: Complex) -> Complex {
Complex {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl AddAssign for Complex {
fn add_assign(&mut self, other: Complex) {
*self = *self + other
}
}
impl Mul for Complex {
type Output = Complex;
fn mul(self, other: Complex) -> Complex {
Complex {
x: self.x * other.x - self.y * other.y,
y: self.x * other.y + self.y * other.x,
}
}
}
impl MulAssign for Complex {
fn mul_assign(&mut self, other: Complex) {
*self = *self * other
}
}
const ONE: Complex = Complex { x: 1., y: 0. };
const MINUS_ONE: Complex = Complex { x: -1., y: 0. };
fn fft_(vs: &Vec<Complex>, w: Complex) -> Vec<Complex> {
if vs.len() == 1 {
return vs.clone();
}
let mut ves = Vec::new();
let mut vos = Vec::new();
for i in 0..vs.len() {
if i & 1 == 0 {
ves.push(vs[i]);
} else {
vos.push(vs[i]);
}
}
let res = fft_(&ves, w * w);
let ros = fft_(&vos, w * w);
let mut rs = Vec::with_capacity(vs.len());
let mut wi = ONE;
for i in 0..res.len() {
rs.push(res[i] + wi * ros[i]);
wi *= w;
}
wi = ONE;
for i in 0..res.len() {
rs.push(res[i] + MINUS_ONE * wi * ros[i]);
wi *= w;
}
rs
}
fn fft(f: &Vec<Complex>, i: bool) -> Vec<Complex> {
assert!(f.len().count_ones() == 1);
let p = f.len() as f64;
let w = Complex {
x: (2. * std::f64::consts::PI / p).cos(),
y: (if i { -2. } else { 2. } * std::f64::consts::PI / p).sin(),
};
fft_(f, w)
.into_iter()
.map(|c| {
c * Complex {
x: 1. / p.sqrt(),
y: 0.,
}
})
.collect::<Vec<Complex>>()
}
fn main() {
let mut v: Vec<Complex> = Vec::new();
for i in 0..8 {
v.push(Complex { x: i as f64, y: 0. })
}
println!("initial vector:");
for &c in v.iter() {
print!(" {:.2}", c.x);
}
println!("\n\nfourier transform:");
for &c in fft(&v, false).iter() {
print!(" {:.2}", c.x);
}
println!("\n\ninverted fourier transform:");
for &c in fft(&fft(&v, false), true).iter() {
print!(" {:.2}", c.x);
}
println!("");
}