DoubleFFT_2D { public void complexForward(final double[] a) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); if (isPowerOfTwo) { int oldn2 = columns; columns = 2 * columns; if (nthreads != oldNthreads) { nt = 8 * nthreads * rows; if (columns == 4 * nthreads) { nt >>= 1; } else if (columns < 4 * nthreads) { nt >>= 2; } t = new double[nt]; oldNthreads = nthreads; } if ((nthreads > 1) && useThreads) { xdft2d0_subth1(0, -1, a, true); cdft2d_subth(-1, a, true); } else { for (int r = 0; r < rows; r++) { fftColumns.complexForward(a, r * columns); } cdft2d_sub(-1, a, true); } columns = oldn2; } else { final int rowStride = 2 * columns; if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { Future<?>[] futures = new Future[nthreads]; int p = rows / nthreads; for (int l = 0; l < nthreads; l++) { final int firstRow = l * p; final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; futures[l] = ConcurrencyUtils.submit(new Runnable() { @Override public void run() { for (int r = firstRow; r < lastRow; r++) { fftColumns.complexForward(a, r * rowStride); } } }); } ConcurrencyUtils.waitForCompletion(futures); p = columns / nthreads; for (int l = 0; l < nthreads; l++) { final int firstColumn = l * p; final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; futures[l] = ConcurrencyUtils.submit(new Runnable() { @Override public void run() { double[] temp = new double[2 * rows]; for (int c = firstColumn; c < lastColumn; c++) { int idx0 = 2 * c; for (int r = 0; r < rows; r++) { int idx1 = 2 * r; int idx2 = r * rowStride + idx0; temp[idx1] = a[idx2]; temp[idx1 + 1] = a[idx2 + 1]; } fftRows.complexForward(temp); for (int r = 0; r < rows; r++) { int idx1 = 2 * r; int idx2 = r * rowStride + idx0; a[idx2] = temp[idx1]; a[idx2 + 1] = temp[idx1 + 1]; } } } }); } ConcurrencyUtils.waitForCompletion(futures); } else { for (int r = 0; r < rows; r++) { fftColumns.complexForward(a, r * rowStride); } double[] temp = new double[2 * rows]; for (int c = 0; c < columns; c++) { int idx0 = 2 * c; for (int r = 0; r < rows; r++) { int idx1 = 2 * r; int idx2 = r * rowStride + idx0; temp[idx1] = a[idx2]; temp[idx1 + 1] = a[idx2 + 1]; } fftRows.complexForward(temp); for (int r = 0; r < rows; r++) { int idx1 = 2 * r; int idx2 = r * rowStride + idx0; a[idx2] = temp[idx1]; a[idx2 + 1] = temp[idx1 + 1]; } } } } } DoubleFFT_2D(int rows, int columns); void complexForward(final double[] a); void complexForward(final double[][] a); void complexInverse(final double[] a, final boolean scale); void complexInverse(final double[][] a, final boolean scale); void realForward(double[] a); void realForward(double[][] a); void realForwardFull(double[] a); void realForwardFull(double[][] a); void realInverse(double[] a, boolean scale); void realInverse(double[][] a, boolean scale); void realInverseFull(double[] a, boolean scale); void realInverseFull(double[][] a, boolean scale);  }
@Test public void testComplexForward1dInput() { final FloatingPointEqualityChecker checker = createEqualityChecker( Math.ulp(1d), 0d); final double[] actual = new double[2 * numRows * numCols]; final double[][] expected = new double[numRows][2 * numCols]; for (int r = 0; r < numRows; r++) { for (int c = 0; c < 2 * numCols; c++) { final double rnd = random.nextDouble(); actual[2 * r * numCols + c] = rnd; expected[r][c] = rnd; } } fft.complexForward(actual); complexForward(expected); for (int r = 0; r < numRows; r++) { for (int c = 0; c < 2 * numCols; c++) { final double exp = expected[r][c]; final double act = actual[2 * r * numCols + c]; checker.assertEquals("[" + r + "][" + c + "]", exp, act); } } }
@Test public void testComplexForward2dInput() { final FloatingPointEqualityChecker checker = createEqualityChecker( Math.ulp(1d), 0d); final double[][] actual = new double[numRows][2 * numCols]; final double[][] expected = new double[numRows][2 * numCols]; for (int r = 0; r < numRows; r++) { for (int c = 0; c < 2 * numCols; c++) { final double rnd = random.nextDouble(); actual[r][c] = rnd; expected[r][c] = rnd; } } fft.complexForward(actual); complexForward(expected); for (int r = 0; r < numRows; r++) { for (int c = 0; c < 2 * numCols; c++) { final double exp = expected[r][c]; final double act = actual[r][c]; checker.assertEquals("[" + r + "][" + c + "]", exp, act); } } }