Fast Fourier transform: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (→{{header|SystemVerilog}}: Remove vanity tags) |
(add rust example) |
||
Line 2,642: | Line 2,642: | ||
6 0.0 0 |
6 0.0 0 |
||
7 1.0 2.41421356</pre> |
7 1.0 2.41421356</pre> |
||
=={{header|Rust}}== |
|||
{{trans|C}} |
|||
<lang rust>extern crate num; |
|||
use num::complex::Complex; |
|||
use std::f64::consts::PI; |
|||
const I: Complex<f64> = Complex { re: 0.0, im: 1.0 }; |
|||
pub fn fft(input: &[Complex<f64>]) -> Vec<Complex<f64>> { |
|||
fn fft_inner( |
|||
buf_a: &mut [Complex<f64>], |
|||
buf_b: &mut [Complex<f64>], |
|||
n: usize, // total length of the input array |
|||
step: usize, // precalculated values for t |
|||
) { |
|||
if step >= n { |
|||
return; |
|||
} |
|||
fft_inner(buf_b, buf_a, n, step * 2); |
|||
fft_inner(&mut buf_b[step..], &mut buf_a[step..], n, step * 2); |
|||
// create a slice for each half of buf_a: |
|||
let (left, right) = buf_a.split_at_mut(n / 2); |
|||
for i in (0..n).step_by(step * 2) { |
|||
let t = (-I * PI * (i as f64) / (n as f64)).exp() * buf_b[i + step]; |
|||
left[i / 2] = buf_b[i] + t; |
|||
right[i / 2] = buf_b[i] - t; |
|||
} |
|||
} |
|||
// round n (length) up to a power of 2: |
|||
let n_orig = input.len(); |
|||
let n = n_orig.next_power_of_two(); |
|||
// copy the input into a buffer: |
|||
let mut buf_a = input.to_vec(); |
|||
// right pad with zeros to a power of two: |
|||
buf_a.append(&mut vec![Complex { re: 0.0, im: 0.0 }; n - n_orig]); |
|||
// alternate between buf_a and buf_b to avoid allocating a new vector each time: |
|||
let mut buf_b = buf_a.clone(); |
|||
fft_inner(&mut buf_a, &mut buf_b, n, 1); |
|||
buf_a |
|||
} |
|||
fn show(label: &str, buf: &[Complex<f64>]) { |
|||
println!("{}", label); |
|||
let string = buf |
|||
.into_iter() |
|||
.map(|x| format!("{:.4}{:+.4}i", x.re, x.im)) |
|||
.collect::<Vec<_>>() |
|||
.join(", "); |
|||
println!("{}", string); |
|||
} |
|||
fn main() { |
|||
let input: Vec<_> = [1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0] |
|||
.into_iter() |
|||
.map(|x| Complex::from(x)) |
|||
.collect(); |
|||
show("input:", &input); |
|||
let output = fft(&input); |
|||
show("output:", &output); |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
input: |
|||
1.0000+0.0000i, 1.0000+0.0000i, 1.0000+0.0000i, 1.0000+0.0000i, 0.0000+0.0000i, 0.0000+0.0000i, 0.0000+0.0000i, 0.0000+0.0000i |
|||
output: |
|||
4.0000+0.0000i, 1.0000-2.4142i, 0.0000+0.0000i, 1.0000-0.4142i, 0.0000+0.0000i, 1.0000+0.4142i, 0.0000+0.0000i, 1.0000+2.4142i |
|||
</pre> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{libheader|Scala}} |
{{libheader|Scala}} |