UNPKG

dist-javascript-algorithms-and-data-structures

Version:

Algorithms and data-structures implemented on JavaScript

89 lines (71 loc) 2.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = fastFourierTransform; var _ComplexNumber = _interopRequireDefault(require("../complex-number/ComplexNumber")); var _bitLength = _interopRequireDefault(require("../bits/bitLength")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Returns the number which is the flipped binary representation of input. * * @param {number} input * @param {number} bitsCount * @return {number} */ function reverseBits(input, bitsCount) { let reversedBits = 0; for (let bitIndex = 0; bitIndex < bitsCount; bitIndex += 1) { reversedBits *= 2; if (Math.floor(input / (1 << bitIndex)) % 2 === 1) { reversedBits += 1; } } return reversedBits; } /** * Returns the radix-2 fast fourier transform of the given array. * Optionally computes the radix-2 inverse fast fourier transform. * * @param {ComplexNumber[]} inputData * @param {boolean} [inverse] * @return {ComplexNumber[]} */ function fastFourierTransform(inputData, inverse = false) { const bitsCount = (0, _bitLength.default)(inputData.length - 1); const N = 1 << bitsCount; while (inputData.length < N) { inputData.push(new _ComplexNumber.default()); } const output = []; for (let dataSampleIndex = 0; dataSampleIndex < N; dataSampleIndex += 1) { output[dataSampleIndex] = inputData[reverseBits(dataSampleIndex, bitsCount)]; } for (let blockLength = 2; blockLength <= N; blockLength *= 2) { const imaginarySign = inverse ? -1 : 1; const phaseStep = new _ComplexNumber.default({ re: Math.cos(2 * Math.PI / blockLength), im: imaginarySign * Math.sin(2 * Math.PI / blockLength) }); for (let blockStart = 0; blockStart < N; blockStart += blockLength) { let phase = new _ComplexNumber.default({ re: 1, im: 0 }); for (let signalId = blockStart; signalId < blockStart + blockLength / 2; signalId += 1) { const component = output[signalId + blockLength / 2].multiply(phase); const upd1 = output[signalId].add(component); const upd2 = output[signalId].subtract(component); output[signalId] = upd1; output[signalId + blockLength / 2] = upd2; phase = phase.multiply(phaseStep); } } } if (inverse) { for (let signalId = 0; signalId < N; signalId += 1) { output[signalId] /= N; } } return output; }