/// <summary> /// 9 point stencil operation. /// Applies a function to a moving <i>3 x 3</i> window. /// </summary> /// <param name="A"> /// the matrix to operate on. /// </param> /// <param name="function"> /// the function to be applied to each window. /// </param> /// <param name="maxIterations"> /// the maximum number of times the stencil shall be applied to the matrixd /// Should be a multiple of 2 because two iterations are always done in one atomic step. /// </param> /// <param name="hasConverged"> /// Convergence condition; will return before maxIterations are done when <i>hasConverged.apply(A)==true</i>. /// Set this parameter to <i>null</i> to indicate that no convergence checks shall be made. /// </param> /// <param name="convergenceIterations"> /// the number of iterations to pass between each convergence check. /// (Since a convergence may be expensive, you may want to do it only every 2,4 or 8 iterationsd) /// </param> /// <returns><the number of iterations actually executedd /returns> public static int Stencil9(DoubleMatrix2D A, Cern.Colt.Function.Double9Function function, int maxIterations, DoubleMatrix2DProcedure hasConverged, int convergenceIterations) { DoubleMatrix2D B = A.Copy(); if (convergenceIterations <= 1) { convergenceIterations = 2; } if (convergenceIterations % 2 != 0) { convergenceIterations++; // odd -> make it even } int i = 0; while (i < maxIterations) { // do two steps at a time for efficiency A.ZAssign8Neighbors(B, function); B.ZAssign8Neighbors(A, function); i = i + 2; if (i % convergenceIterations == 0 && hasConverged != null) { if (hasConverged(A)) { return(i); } } } return(i); }