Skip to content

Commit 7d3115e

Browse files
committed
Use existing complex numbers implementation for Fourier.
1 parent 6f10b0e commit 7d3115e

File tree

3 files changed

+74
-81
lines changed

3 files changed

+74
-81
lines changed

Diff for: src/algorithms/math/fast-fourier-transform/__test__/fastFourierTransform.test.js

+48-33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import ComplexNumber from '../complex';
21
import fastFourierTransform from '../fastFourierTransform';
2+
import ComplexNumber from '../../complex-number/ComplexNumber';
3+
34
/**
45
* @param {ComplexNumber[]} [seq1]
56
* @param {ComplexNumber[]} [seq2]
@@ -20,48 +21,62 @@ function approximatelyEqual(seq1, seq2, eps) {
2021
describe('fastFourierTransform', () => {
2122
it('should calculate the radix-2 discrete fourier transform after zero padding', () => {
2223
const eps = 1e-6;
23-
const in1 = [new ComplexNumber(0, 0)];
24-
const expOut1 = [new ComplexNumber(0, 0)];
24+
const in1 = [new ComplexNumber({ real: 0, imaginary: 0 })];
25+
const expOut1 = [new ComplexNumber({ real: 0, imaginary: 0 })];
2526
const out1 = fastFourierTransform(in1);
2627
const invOut1 = fastFourierTransform(out1, true);
2728
expect(approximatelyEqual(expOut1, out1, eps)).toBe(true);
2829
expect(approximatelyEqual(in1, invOut1, eps)).toBe(true);
2930

30-
const in2 = [new ComplexNumber(1, 2), new ComplexNumber(2, 3),
31-
new ComplexNumber(8, 4)];
32-
const expOut2 = [new ComplexNumber(11, 9), new ComplexNumber(-10, 0),
33-
new ComplexNumber(7, 3), new ComplexNumber(-4, -4)];
31+
const in2 = [
32+
new ComplexNumber({ real: 1, imaginary: 2 }),
33+
new ComplexNumber({ real: 2, imaginary: 3 }),
34+
new ComplexNumber({ real: 8, imaginary: 4 }),
35+
];
36+
37+
const expOut2 = [
38+
new ComplexNumber({ real: 11, imaginary: 9 }),
39+
new ComplexNumber({ real: -10, imaginary: 0 }),
40+
new ComplexNumber({ real: 7, imaginary: 3 }),
41+
new ComplexNumber({ real: -4, imaginary: -4 }),
42+
];
3443
const out2 = fastFourierTransform(in2);
3544
const invOut2 = fastFourierTransform(out2, true);
3645
expect(approximatelyEqual(expOut2, out2, eps)).toBe(true);
3746
expect(approximatelyEqual(in2, invOut2, eps)).toBe(true);
3847

39-
const in3 = [new ComplexNumber(-83656.9359385182, 98724.08038374918),
40-
new ComplexNumber(-47537.415125808424, 88441.58381765135),
41-
new ComplexNumber(-24849.657029355192, -72621.79007878687),
42-
new ComplexNumber(31451.27290052717, -21113.301128347346),
43-
new ComplexNumber(13973.90836288876, -73378.36721594246),
44-
new ComplexNumber(14981.520420492234, 63279.524958963884),
45-
new ComplexNumber(-9892.575367044381, -81748.44671677813),
46-
new ComplexNumber(-35933.00356823792, -46153.47157161784),
47-
new ComplexNumber(-22425.008561855735, -86284.24507370662),
48-
new ComplexNumber(-39327.43830818355, 30611.949874562706)];
49-
const expOut3 = [new ComplexNumber(-203215.3322151, -100242.4827503),
50-
new ComplexNumber(99217.0805705, 270646.9331932),
51-
new ComplexNumber(-305990.9040412, 68224.8435751),
52-
new ComplexNumber(-14135.7758282, 199223.9878095),
53-
new ComplexNumber(-306965.6350922, 26030.1025439),
54-
new ComplexNumber(-76477.6755206, 40781.9078990),
55-
new ComplexNumber(-48409.3099088, 54674.7959662),
56-
new ComplexNumber(-329683.0131713, 164287.7995937),
57-
new ComplexNumber(-50485.2048527, -330375.0546527),
58-
new ComplexNumber(122235.7738708, 91091.6398019),
59-
new ComplexNumber(47625.8850387, 73497.3981523),
60-
new ComplexNumber(-15619.8231136, 80804.8685410),
61-
new ComplexNumber(192234.0276101, 160833.3072355),
62-
new ComplexNumber(-96389.4195635, 393408.4543872),
63-
new ComplexNumber(-173449.0825417, 146875.7724104),
64-
new ComplexNumber(-179002.5662573, 239821.0124341)];
48+
const in3 = [
49+
new ComplexNumber({ real: -83656.9359385182, imaginary: 98724.08038374918 }),
50+
new ComplexNumber({ real: -47537.415125808424, imaginary: 88441.58381765135 }),
51+
new ComplexNumber({ real: -24849.657029355192, imaginary: -72621.79007878687 }),
52+
new ComplexNumber({ real: 31451.27290052717, imaginary: -21113.301128347346 }),
53+
new ComplexNumber({ real: 13973.90836288876, imaginary: -73378.36721594246 }),
54+
new ComplexNumber({ real: 14981.520420492234, imaginary: 63279.524958963884 }),
55+
new ComplexNumber({ real: -9892.575367044381, imaginary: -81748.44671677813 }),
56+
new ComplexNumber({ real: -35933.00356823792, imaginary: -46153.47157161784 }),
57+
new ComplexNumber({ real: -22425.008561855735, imaginary: -86284.24507370662 }),
58+
new ComplexNumber({ real: -39327.43830818355, imaginary: 30611.949874562706 }),
59+
];
60+
61+
const expOut3 = [
62+
new ComplexNumber({ real: -203215.3322151, imaginary: -100242.4827503 }),
63+
new ComplexNumber({ real: 99217.0805705, imaginary: 270646.9331932 }),
64+
new ComplexNumber({ real: -305990.9040412, imaginary: 68224.8435751 }),
65+
new ComplexNumber({ real: -14135.7758282, imaginary: 199223.9878095 }),
66+
new ComplexNumber({ real: -306965.6350922, imaginary: 26030.1025439 }),
67+
new ComplexNumber({ real: -76477.6755206, imaginary: 40781.9078990 }),
68+
new ComplexNumber({ real: -48409.3099088, imaginary: 54674.7959662 }),
69+
new ComplexNumber({ real: -329683.0131713, imaginary: 164287.7995937 }),
70+
new ComplexNumber({ real: -50485.2048527, imaginary: -330375.0546527 }),
71+
new ComplexNumber({ real: 122235.7738708, imaginary: 91091.6398019 }),
72+
new ComplexNumber({ real: 47625.8850387, imaginary: 73497.3981523 }),
73+
new ComplexNumber({ real: -15619.8231136, imaginary: 80804.8685410 }),
74+
new ComplexNumber({ real: 192234.0276101, imaginary: 160833.3072355 }),
75+
new ComplexNumber({ real: -96389.4195635, imaginary: 393408.4543872 }),
76+
new ComplexNumber({ real: -173449.0825417, imaginary: 146875.7724104 }),
77+
new ComplexNumber({ real: -179002.5662573, imaginary: 239821.0124341 }),
78+
];
79+
6580
const out3 = fastFourierTransform(in3);
6681
const invOut3 = fastFourierTransform(out3, true);
6782
expect(approximatelyEqual(expOut3, out3, eps)).toBe(true);

Diff for: src/algorithms/math/fast-fourier-transform/complex.js

-36
This file was deleted.

Diff for: src/algorithms/math/fast-fourier-transform/fastFourierTransform.js

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import ComplexNumber from './complex';
1+
import ComplexNumber from '../complex-number/ComplexNumber';
22

33
/**
4-
* Return the no of bits used in the binary representation of input
4+
* Return the no of bits used in the binary representation of input.
5+
*
56
* @param {Number} [input]
67
* @return {Number}
78
*/
@@ -14,7 +15,8 @@ function bitLength(input) {
1415
}
1516

1617
/**
17-
* Returns the number which is the flipped binary representation of input
18+
* Returns the number which is the flipped binary representation of input.
19+
*
1820
* @param {Number} [input]
1921
* @param {Number} [bitlen]
2022
* @return {Number}
@@ -29,8 +31,9 @@ function reverseBits(input, bitlen) {
2931
}
3032

3133
/**
32-
* Returns the radix-2 fast fourier transform of the given array
33-
* Optionally computes the radix-2 inverse fast fourier transform
34+
* Returns the radix-2 fast fourier transform of the given array.
35+
* Optionally computes the radix-2 inverse fast fourier transform.
36+
*
3437
* @param {ComplexNumber[]} [inputData]
3538
* @param {Boolean} [inverse]
3639
* @return {ComplexNumber[]}
@@ -39,24 +42,35 @@ export default function fastFourierTransform(inputData, inverse = false) {
3942
const bitlen = bitLength(inputData.length - 1);
4043
const N = 1 << bitlen;
4144

42-
while (inputData.length < N) { inputData.push(new ComplexNumber(0, 0)); }
43-
45+
while (inputData.length < N) {
46+
inputData.push(new ComplexNumber({
47+
real: 0,
48+
imaginary: 0,
49+
}));
50+
}
4451

4552
const output = [];
4653
for (let i = 0; i < N; i += 1) { output[i] = inputData[reverseBits(i, bitlen)]; }
4754

4855
for (let blockLength = 2; blockLength <= N; blockLength *= 2) {
4956
let phaseStep;
5057
if (inverse) {
51-
phaseStep = new ComplexNumber(Math.cos(2 * Math.PI / blockLength),
52-
-1 * Math.sin(2 * Math.PI / blockLength));
58+
phaseStep = new ComplexNumber({
59+
real: Math.cos(2 * Math.PI / blockLength),
60+
imaginary: -1 * Math.sin(2 * Math.PI / blockLength),
61+
});
5362
} else {
54-
phaseStep = new ComplexNumber(Math.cos(2 * Math.PI / blockLength),
55-
Math.sin(2 * Math.PI / blockLength));
63+
phaseStep = new ComplexNumber({
64+
real: Math.cos(2 * Math.PI / blockLength),
65+
imaginary: Math.sin(2 * Math.PI / blockLength),
66+
});
5667
}
5768

5869
for (let blockStart = 0; blockStart < N; blockStart += blockLength) {
59-
let phase = new ComplexNumber(1, 0);
70+
let phase = new ComplexNumber({
71+
real: 1,
72+
imaginary: 0,
73+
});
6074

6175
for (let idx = blockStart; idx < blockStart + blockLength / 2; idx += 1) {
6276
const upd1 = output[idx].add(output[idx + blockLength / 2].multiply(phase));

0 commit comments

Comments
 (0)