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
use std::f64;
use num_complex::Complex;
use num_traits::{FromPrimitive, One};
use common::FFTnum;
pub fn generate_twiddle_factors<T: FFTnum>(fft_len: usize, inverse: bool) -> Vec<Complex<T>> {
(0..fft_len).map(|i| single_twiddle(i, fft_len, inverse)).collect()
}
#[inline(always)]
pub fn single_twiddle<T: FFTnum>(i: usize, fft_len: usize, inverse: bool) -> Complex<T> {
let constant = if inverse {
2f64 * f64::consts::PI
} else {
-2f64 * f64::consts::PI
};
let c = Complex::from_polar(&One::one(), &(constant * i as f64 / fft_len as f64));
Complex {
re: FromPrimitive::from_f64(c.re).unwrap(),
im: FromPrimitive::from_f64(c.im).unwrap(),
}
}
pub fn rotate_90<T: FFTnum>(value: Complex<T>, inverse:bool) -> Complex<T>
{
if inverse {
Complex{re:-value.im, im: value.re}
} else {
Complex{re: value.im, im:-value.re}
}
}
#[cfg(test)]
mod unit_tests {
use super::*;
use std::f32;
use test_utils::{compare_vectors};
#[test]
fn test_generate() {
let zero_twiddles: Vec<Complex<f32>> = generate_twiddle_factors(0, false);
assert_eq!(0, zero_twiddles.len());
let constant = -2f32 * f32::consts::PI;
for len in 1..10 {
let actual: Vec<Complex<f32>> = generate_twiddle_factors(len, false);
let expected: Vec<Complex<f32>> = (0..len).map(|i| Complex::from_polar(&1f32, &(constant * i as f32 / len as f32))).collect();
assert!(compare_vectors(&actual, &expected), "len = {}", len)
}
for len in 1..10 {
let twiddles: Vec<Complex<f32>> = generate_twiddle_factors(len, false);
let mut twiddles_inverse: Vec<Complex<f32>> = generate_twiddle_factors(len, true);
for value in twiddles_inverse.iter_mut()
{
*value = value.conj();
}
assert!(compare_vectors(&twiddles, &twiddles_inverse), "len = {}", len)
}
}
#[test]
fn test_single() {
let len = 20;
let twiddles: Vec<Complex<f32>> = generate_twiddle_factors(len, false);
let twiddles_inverse: Vec<Complex<f32>> = generate_twiddle_factors(len, true);
for i in 0..len {
let single: Complex<f32> = single_twiddle(i, len, false);
let single_inverse: Complex<f32> = single_twiddle(i, len, true);
assert_eq!(single, twiddles[i], "forwards, i = {}", i);
assert_eq!(single_inverse, twiddles_inverse[i], "inverse, i = {}", i);
}
}
}