public void testFft2Slices() {
   DComplexMatrix3D Acopy = A.copy();
   ((WrapperDComplexMatrix3D) A).fft2Slices();
   ((WrapperDComplexMatrix3D) A).ifft2Slices(true);
   for (int s = 0; s < A.slices(); s++) {
     for (int r = 0; r < A.rows(); r++) {
       for (int c = 0; c < A.columns(); c++) {
         assertEquals(Acopy.getQuick(s, r, c), A.getQuick(s, r, c), TOL);
       }
     }
   }
 }
  public void compute() {
    int n = A.columns();

    // Distances to centroids
    DoubleMatrix2D D = new DenseDoubleMatrix2D(k, n);

    // Object-cluster assignments
    V = new DenseDoubleMatrix2D(n, k);

    // Initialize the centroids with some document vectors
    U = new DenseDoubleMatrix2D(A.rows(), k);
    U.assign(A.viewPart(0, 0, A.rows(), k));

    int[] minIndices = new int[D.columns()];
    double[] minValues = new double[D.columns()];

    for (iterationsCompleted = 0; iterationsCompleted < maxIterations; iterationsCompleted++) {
      // Calculate cosine distances
      U.zMult(A, D, 1, 0, true, false);

      V.assign(0);
      U.assign(0);

      // For each object
      MatrixUtils.maxInColumns(D, minIndices, minValues);
      for (int i = 0; i < minIndices.length; i++) {
        V.setQuick(i, minIndices[i], 1);
      }

      // Update centroids
      for (int c = 0; c < V.columns(); c++) {
        // Sum
        int count = 0;
        for (int d = 0; d < V.rows(); d++) {
          if (V.getQuick(d, c) != 0) {
            count++;
            U.viewColumn(c).assign(A.viewColumn(d), Functions.PLUS);
          }
        }

        // Divide
        U.viewColumn(c).assign(Mult.div(count));
        MatrixUtils.normalizeColumnL2(U, null);
      }
    }
  }