fft.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.createFft = void 0;
  7. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  8. var _array = require("../../utils/array.js");
  9. var _factory = require("../../utils/factory.js");
  10. var name = 'fft';
  11. var dependencies = ['typed', 'matrix', 'addScalar', 'multiplyScalar', 'divideScalar', 'exp', 'tau', 'i'];
  12. var createFft = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  13. var typed = _ref.typed,
  14. matrix = _ref.matrix,
  15. addScalar = _ref.addScalar,
  16. multiplyScalar = _ref.multiplyScalar,
  17. divideScalar = _ref.divideScalar,
  18. exp = _ref.exp,
  19. tau = _ref.tau,
  20. I = _ref.i;
  21. /**
  22. * Calculate N-dimensional fourier transform
  23. *
  24. * Syntax:
  25. *
  26. * math.fft(arr)
  27. *
  28. * Examples:
  29. *
  30. * math.fft([[1, 0], [1, 0]]) // returns [[{re:2, im:0}, {re:2, im:0}], [{re:0, im:0}, {re:0, im:0}]]
  31. *
  32. *
  33. * See Also:
  34. *
  35. * ifft
  36. *
  37. * @param {Array | Matrix} arr An array or matrix
  38. * @return {Array | Matrix} N-dimensional fourier transformation of the array
  39. */
  40. return typed(name, {
  41. Array: _ndFft,
  42. Matrix: function Matrix(matrix) {
  43. return matrix.create(_ndFft(matrix.toArray()));
  44. }
  45. });
  46. /**
  47. * Perform an N-dimensional Fourier transform
  48. *
  49. * @param {Array} arr The array
  50. * @return {Array} resulting array
  51. */
  52. function _ndFft(arr) {
  53. var size = (0, _array.arraySize)(arr);
  54. if (size.length === 1) return _fft(arr, size[0]);
  55. // ndFft along dimension 1,...,N-1 then 1dFft along dimension 0
  56. return _1dFft(arr.map(function (slice) {
  57. return _ndFft(slice, size.slice(1));
  58. }), 0);
  59. }
  60. /**
  61. * Perform an 1-dimensional Fourier transform
  62. *
  63. * @param {Array} arr The array
  64. * @param {number} dim dimension of the array to perform on
  65. * @return {Array} resulting array
  66. */
  67. function _1dFft(arr, dim) {
  68. var size = (0, _array.arraySize)(arr);
  69. if (dim !== 0) return new Array(size[0]).fill(0).map(function (_, i) {
  70. return _1dFft(arr[i], dim - 1);
  71. });
  72. if (size.length === 1) return _fft(arr);
  73. function _transpose(arr) {
  74. // Swap first 2 dimensions
  75. var size = (0, _array.arraySize)(arr);
  76. return new Array(size[1]).fill(0).map(function (_, j) {
  77. return new Array(size[0]).fill(0).map(function (_, i) {
  78. return arr[i][j];
  79. });
  80. });
  81. }
  82. return _transpose(_1dFft(_transpose(arr), 1));
  83. }
  84. /**
  85. * Perform an 1-dimensional Fourier transform
  86. *
  87. * @param {Array} arr The array
  88. * @return {Array} resulting array
  89. */
  90. function _fft(arr) {
  91. var len = arr.length;
  92. if (len === 1) return [arr[0]];
  93. if (len % 2 === 0) {
  94. var ret = [].concat((0, _toConsumableArray2["default"])(_fft(arr.filter(function (_, i) {
  95. return i % 2 === 0;
  96. }), len / 2)), (0, _toConsumableArray2["default"])(_fft(arr.filter(function (_, i) {
  97. return i % 2 === 1;
  98. }), len / 2)));
  99. for (var k = 0; k < len / 2; k++) {
  100. var p = ret[k];
  101. var q = multiplyScalar(ret[k + len / 2], exp(multiplyScalar(multiplyScalar(tau, I), divideScalar(-k, len))));
  102. ret[k] = addScalar(p, q);
  103. ret[k + len / 2] = addScalar(p, multiplyScalar(-1, q));
  104. }
  105. return ret;
  106. }
  107. throw new Error('Can only calculate FFT of power-of-two size');
  108. }
  109. });
  110. exports.createFft = createFft;