You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.0 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. //! Transformation of complex data.
  2. // The implementation is based on:
  3. // http://www.librow.com/articles/article-10
  4. use number::c64;
  5. /// Perform the forward transform.
  6. ///
  7. /// The number of points should be a power of two.
  8. pub fn forward(data: &mut [c64]) {
  9. let n = power_of_two!(data);
  10. rearrange(data, n);
  11. transform(data, n, false);
  12. }
  13. /// Perform the backward transform.
  14. ///
  15. /// The number of points should be a power of two.
  16. pub fn backward(data: &mut [c64]) {
  17. let n = power_of_two!(data);
  18. rearrange(data, n);
  19. transform(data, n, true);
  20. }
  21. /// Perform the inverse transform.
  22. ///
  23. /// The number of points should be a power of two.
  24. pub fn inverse(data: &mut [c64]) {
  25. let n = power_of_two!(data);
  26. rearrange(data, n);
  27. transform(data, n, true);
  28. scale(data, n);
  29. }
  30. fn rearrange(data: &mut [c64], n: usize) {
  31. let mut j = 0;
  32. for i in 0..n {
  33. if j > i {
  34. data.swap(i, j);
  35. }
  36. let mut mask = n >> 1;
  37. while j & mask != 0 {
  38. j &= !mask;
  39. mask >>= 1;
  40. }
  41. j |= mask;
  42. }
  43. }
  44. fn transform(data: &mut [c64], n: usize, inverse: bool) {
  45. let sign = if inverse { 1.0 } else { -1.0 };
  46. let mut step = 1;
  47. while step < n {
  48. let jump = step << 1;
  49. let (multiplier, mut factor) = {
  50. use std::f64::consts::PI;
  51. let theta = sign * PI / step as f64;
  52. let sine = (0.5 * theta).sin();
  53. (c64(-2.0 * sine * sine, theta.sin()), c64(1.0, 0.0))
  54. };
  55. for mut i in 0..step {
  56. while i < n {
  57. let j = i + step;
  58. let product = factor * data[j];
  59. data[j] = data[i] - product;
  60. data[i] = data[i] + product;
  61. i += jump;
  62. }
  63. factor = multiplier * factor + factor;
  64. }
  65. step <<= 1;
  66. }
  67. }
  68. fn scale(data: &mut [c64], n: usize) {
  69. let factor = 1.0 / n as f64;
  70. for i in 0..n {
  71. data[i] = data[i] * factor;
  72. }
  73. }