/** A test of {@link FloatFFT_2D#realForwardFull(FloatLargeArray)}. */
 @Test
 public void testRealForwardFullLarge() {
   final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false);
   final float[][] expected0 = new float[numRows][2 * numCols];
   final FloatLargeArray expected = new FloatLargeArray(numRows * 2 * numCols, false);
   for (int r = 0; r < numRows; r++) {
     for (int c = 0; c < numCols; c++) {
       final float rnd = random.nextFloat();
       actual.setDouble(r * numCols + c, rnd);
       expected0[r][2 * c] = rnd;
     }
   }
   fft.realForwardFull(actual);
   complexForward(expected0);
   for (int r = 0; r < numRows; r++) {
     for (int c = 0; c < 2 * numCols; c++) {
       expected.setDouble(2 * r * numCols + c, expected0[r][c]);
     }
   }
   double rmse = IOUtils.computeRMSE(actual, expected);
   Assert.assertEquals(
       String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse,
       0.0,
       rmse,
       EPS);
 }
 /** A test of {@link FloatFFT_2D#realForward(FloatLargeArray)}. */
 @Test
 public void testRealForwardLarge() {
   if (!ConcurrencyUtils.isPowerOf2(numRows)) {
     return;
   }
   if (!ConcurrencyUtils.isPowerOf2(numCols)) {
     return;
   }
   final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false);
   final FloatLargeArray expected = new FloatLargeArray(numRows * 2 * numCols, false);
   for (int r = 0; r < numRows; r++) {
     for (int c = 0; c < numCols; c++) {
       final float rnd = random.nextFloat();
       actual.setDouble(r * numCols + c, rnd);
       expected.setDouble(r * 2 * numCols + 2 * c, rnd);
     }
   }
   fft.realForward(actual);
   fft.complexForward(expected);
   fillSymmetric(actual, numRows, numCols);
   double rmse = IOUtils.computeRMSE(actual, expected);
   Assert.assertEquals(
       String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse,
       0.0,
       rmse,
       EPS);
 }
 /**
  * A test of {@link FloatFFT_2D#complexInverse(FloatLargeArray, boolean)}, with the second
  * parameter set to <code>true</code>.
  */
 @Test
 public void testComplexInverseScaledLarge() {
   final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false);
   final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false);
   for (int i = 0; i < actual.length(); i++) {
     final float rnd = random.nextFloat();
     actual.setDouble(i, rnd);
     expected.setDouble(i, rnd);
   }
   fft.complexForward(actual);
   fft.complexInverse(actual, true);
   double rmse = IOUtils.computeRMSE(actual, expected);
   Assert.assertEquals(
       String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse,
       0.0,
       rmse,
       EPS);
 }
 /**
  * A test of {@link FloatFFT_2D#realInverseFull(FloatLargeArray, boolean)}, with the second
  * parameter set to <code>false</code>.
  */
 @Test
 public void testRealInverseFullUnscaledLarge() {
   final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false);
   final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false);
   for (int r = 0; r < numRows; r++) {
     for (int c = 0; c < numCols; c++) {
       final float rnd = random.nextFloat();
       final int index = r * numCols + c;
       actual.set(index, rnd);
       expected.setDouble(2 * index, rnd);
     }
   }
   // TODO If the two following lines are permuted, this causes an array
   // index out of bounds exception.
   fft.complexInverse(expected, false);
   fft.realInverseFull(actual, false);
   double rmse = IOUtils.computeRMSE(actual, expected);
   Assert.assertEquals(
       String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse,
       0.0,
       rmse,
       EPS);
 }
  private static void fillSymmetric(final FloatLargeArray a, int rowsl, int columnsl) {
    final long twon2 = 2 * columnsl;
    long idx1, idx2, idx3, idx4;
    long n1d2 = rowsl / 2;

    for (long r = (rowsl - 1); r >= 1; r--) {
      idx1 = r * columnsl;
      idx2 = 2 * idx1;
      for (long c = 0; c < columnsl; c += 2) {
        a.setDouble(idx2 + c, a.getDouble(idx1 + c));
        a.setDouble(idx1 + c, 0);
        a.setDouble(idx2 + c + 1, a.getDouble(idx1 + c + 1));
        a.setDouble(idx1 + c + 1, 0);
      }
    }

    for (long r = 1; r < n1d2; r++) {
      idx2 = r * twon2;
      idx3 = (rowsl - r) * twon2;
      a.setDouble(idx2 + columnsl, a.getDouble(idx3 + 1));
      a.setDouble(idx2 + columnsl + 1, -a.getDouble(idx3));
    }

    for (long r = 1; r < n1d2; r++) {
      idx2 = r * twon2;
      idx3 = (rowsl - r + 1) * twon2;
      for (long c = columnsl + 2; c < twon2; c += 2) {
        a.setDouble(idx2 + c, a.getDouble(idx3 - c));
        a.setDouble(idx2 + c + 1, -a.getDouble(idx3 - c + 1));
      }
    }
    for (long r = 0; r <= rowsl / 2; r++) {
      idx1 = r * twon2;
      idx4 = ((rowsl - r) % rowsl) * twon2;
      for (long c = 0; c < twon2; c += 2) {
        idx2 = idx1 + c;
        idx3 = idx4 + (twon2 - c) % twon2;
        a.setDouble(idx3, a.getDouble(idx2));
        a.setDouble(idx3 + 1, -a.getDouble(idx2 + 1));
      }
    }

    a.setDouble(columnsl, -a.getDouble(1));
    a.setDouble(1, 0);
    idx1 = n1d2 * twon2;
    a.setDouble(idx1 + columnsl, -a.getDouble(idx1 + 1));
    a.setDouble(idx1 + 1, 0);
    a.setDouble(idx1 + columnsl + 1, 0);
  }