in commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java [129:277]
public void transformInPlace(final double[][] dataRI) {
if (dataRI.length != NUM_PARTS) {
throw new TransformException(TransformException.SIZE_MISMATCH,
dataRI.length, NUM_PARTS);
}
final double[] dataR = dataRI[0];
final double[] dataI = dataRI[1];
if (dataR.length != dataI.length) {
throw new TransformException(TransformException.SIZE_MISMATCH,
dataI.length, dataR.length);
}
final int n = dataR.length;
if (!ArithmeticUtils.isPowerOfTwo(n)) {
throw new TransformException(TransformException.NOT_POWER_OF_TWO,
Integer.valueOf(n));
}
if (n == 1) {
return;
} else if (n == 2) {
final double srcR0 = dataR[0];
final double srcI0 = dataI[0];
final double srcR1 = dataR[1];
final double srcI1 = dataI[1];
// X_0 = x_0 + x_1
dataR[0] = srcR0 + srcR1;
dataI[0] = srcI0 + srcI1;
// X_1 = x_0 - x_1
dataR[1] = srcR0 - srcR1;
dataI[1] = srcI0 - srcI1;
normalizeTransformedData(dataRI);
return;
}
bitReversalShuffle2(dataR, dataI);
// Do 4-term DFT.
if (inverse) {
for (int i0 = 0; i0 < n; i0 += 4) {
final int i1 = i0 + 1;
final int i2 = i0 + 2;
final int i3 = i0 + 3;
final double srcR0 = dataR[i0];
final double srcI0 = dataI[i0];
final double srcR1 = dataR[i2];
final double srcI1 = dataI[i2];
final double srcR2 = dataR[i1];
final double srcI2 = dataI[i1];
final double srcR3 = dataR[i3];
final double srcI3 = dataI[i3];
// 4-term DFT
// X_0 = x_0 + x_1 + x_2 + x_3
dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
// X_1 = x_0 - x_2 + j * (x_3 - x_1)
dataR[i1] = srcR0 - srcR2 + (srcI3 - srcI1);
dataI[i1] = srcI0 - srcI2 + (srcR1 - srcR3);
// X_2 = x_0 - x_1 + x_2 - x_3
dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
// X_3 = x_0 - x_2 + j * (x_1 - x_3)
dataR[i3] = srcR0 - srcR2 + (srcI1 - srcI3);
dataI[i3] = srcI0 - srcI2 + (srcR3 - srcR1);
}
} else {
for (int i0 = 0; i0 < n; i0 += 4) {
final int i1 = i0 + 1;
final int i2 = i0 + 2;
final int i3 = i0 + 3;
final double srcR0 = dataR[i0];
final double srcI0 = dataI[i0];
final double srcR1 = dataR[i2];
final double srcI1 = dataI[i2];
final double srcR2 = dataR[i1];
final double srcI2 = dataI[i1];
final double srcR3 = dataR[i3];
final double srcI3 = dataI[i3];
// 4-term DFT
// X_0 = x_0 + x_1 + x_2 + x_3
dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
// X_1 = x_0 - x_2 + j * (x_3 - x_1)
dataR[i1] = srcR0 - srcR2 + (srcI1 - srcI3);
dataI[i1] = srcI0 - srcI2 + (srcR3 - srcR1);
// X_2 = x_0 - x_1 + x_2 - x_3
dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
// X_3 = x_0 - x_2 + j * (x_1 - x_3)
dataR[i3] = srcR0 - srcR2 + (srcI3 - srcI1);
dataI[i3] = srcI0 - srcI2 + (srcR1 - srcR3);
}
}
int lastN0 = 4;
int lastLogN0 = 2;
while (lastN0 < n) {
final int n0 = lastN0 << 1;
final int logN0 = lastLogN0 + 1;
final double wSubN0R = W_SUB_N_R[logN0];
double wSubN0I = W_SUB_N_I[logN0];
if (inverse) {
wSubN0I = -wSubN0I;
}
// Combine even/odd transforms of size lastN0 into a transform of size N0 (lastN0 * 2).
for (int destEvenStartIndex = 0; destEvenStartIndex < n; destEvenStartIndex += n0) {
final int destOddStartIndex = destEvenStartIndex + lastN0;
double wSubN0ToRR = 1;
double wSubN0ToRI = 0;
for (int r = 0; r < lastN0; r++) {
final int destEvenStartIndexPlusR = destEvenStartIndex + r;
final int destOddStartIndexPlusR = destOddStartIndex + r;
final double grR = dataR[destEvenStartIndexPlusR];
final double grI = dataI[destEvenStartIndexPlusR];
final double hrR = dataR[destOddStartIndexPlusR];
final double hrI = dataI[destOddStartIndexPlusR];
final double a = wSubN0ToRR * hrR - wSubN0ToRI * hrI;
final double b = wSubN0ToRR * hrI + wSubN0ToRI * hrR;
// dest[destEvenStartIndex + r] = Gr + WsubN0ToR * Hr
dataR[destEvenStartIndexPlusR] = grR + a;
dataI[destEvenStartIndexPlusR] = grI + b;
// dest[destOddStartIndex + r] = Gr - WsubN0ToR * Hr
dataR[destOddStartIndexPlusR] = grR - a;
dataI[destOddStartIndexPlusR] = grI - b;
// WsubN0ToR *= WsubN0R
final double nextWsubN0ToRR = wSubN0ToRR * wSubN0R - wSubN0ToRI * wSubN0I;
final double nextWsubN0ToRI = wSubN0ToRR * wSubN0I + wSubN0ToRI * wSubN0R;
wSubN0ToRR = nextWsubN0ToRR;
wSubN0ToRI = nextWsubN0ToRI;
}
}
lastN0 = n0;
lastLogN0 = logN0;
}
normalizeTransformedData(dataRI);
}