Exemplo n.º 1
0
        /// <summary>
        /// 8 neighbor stencil transformationd For efficient finite difference operations.
        /// Applies a function to a moving <tt>3 x 3</tt> window.
        /// Does nothing if <tt>rows() &lt; 3 || columns() &lt; 3</tt>.
        /// </summary>
        /// <param name="b">
        /// The matrix to hold the results.
        /// </param>
        /// <param name="function">
        /// The function to be applied to the 9 cells.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// If <tt>function==null</tt>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// If <tt>rows() != B.rows() || columns() != B.columns()</tt>.
        /// </exception>
        public virtual void ZAssign8Neighbors(DoubleMatrix2D b, Double9Function function)
        {
            if (function == null)
            {
                throw new ArgumentNullException("function", Cern.LocalizedResources.Instance().Exception_FuncionMustNotBeNull);
            }
            CheckShape(b);
            if (Rows < 3 || Columns < 3)
            {
                return;                          // nothing to do
            }
            int r = Rows - 1;
            int c = Columns - 1;

            for (int i = 1; i < r; i++)
            {
                double a00 = this[i - 1, 0];
                double a01 = this[i - 1, 1];
                double a10 = this[i, 0];
                double a11 = this[i, 1];
                double a20 = this[i + 1, 0];
                double a21 = this[i + 1, 1];

                for (int j = 1; j < c; j++)
                {
                    // in each step six cells can be remembered in registers - they don't need to be reread from slow memory
                    // in each step 3 instead of 9 cells need to be read from memory.
                    double a02 = this[i - 1, j + 1];
                    double a12 = this[i, j + 1];
                    double a22 = this[i + 1, j + 1];

                    b[i, j] = function(a00, a01, a02, a10, a11, a12, a20, a21, a22);

                    a00 = a01;
                    a10 = a11;
                    a20 = a21;

                    a01 = a02;
                    a11 = a12;
                    a21 = a22;
                }
            }
        }
        /// <summary>
        /// 8 neighbor stencil transformation. For efficient finite difference operations.
        /// Applies a function to a moving <tt>3 x 3</tt> window.
        /// Does nothing if <tt>rows() &lt; 3 || columns() &lt; 3</tt>.
        /// </summary>
        /// <param name="b">
        /// The matrix to hold the results.
        /// </param>
        /// <param name="function">
        /// The unction to be applied to the 9 cells.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// If <tt>rows() != B.rows() || columns() != B.columns()</tt>.
        /// </exception>
        public override void ZAssign8Neighbors(DoubleMatrix2D b, Double9Function function)
        {
            // 1. using only 4-5 out of the 9 cells in "function" is *not* the limiting factor for performance.
            // 2. if the "function" would be hardwired into the innermost loop, a speedup of 1.5-2.0 would be seen
            // but then the multi-purpose interface is gone...
            if (!(b is DenseDoubleMatrix2D))
            {
                base.ZAssign8Neighbors(b, function);
                return;
            }

            CheckShape(b);
            int r = Rows - 1;
            int c = Columns - 1;

            if (Rows < 3 || Columns < 3)
            {
                return;                          // nothing to do
            }
            var bb   = (DenseDoubleMatrix2D)b;
            int a_rs = RowStride;
            int b_rs = bb.RowStride;
            int a_cs = ColumnStride;
            int b_cs = bb.ColumnStride;

            double[] elems   = Elements;
            double[] b_elems = bb.Elements;
            if (elems == null || b_elems == null)
            {
                throw new ApplicationException();
            }

            int a_index = Index(1, 1);
            int b_index = bb.Index(1, 1);

            for (int i = 1; i < r; i++)
            {
                int b11 = b_index;

                int a02 = a_index - a_rs - a_cs;
                int a12 = a02 + a_rs;
                int a22 = a12 + a_rs;

                // in each step six cells can be remembered in registers - they don't need to be reread from slow memory
                double a00 = elems[a02];
                a02 += a_cs;
                double a01 = elems[a02];
                double a10 = elems[a12];
                a12 += a_cs;
                double a11 = elems[a12];
                double a20 = elems[a22];
                a22 += a_cs;
                double a21 = elems[a22];

                for (int j = 1; j < c; j++)
                {
                    // in each step 3 instead of 9 cells need to be read from memory.
                    double _a02 = elems[a02 += a_cs];
                    double _a12 = elems[a12 += a_cs];
                    double _a22 = elems[a22 += a_cs];

                    b_elems[b11] = function(a00, a01, _a02, a10, a11, _a12, a20, a21, _a22);
                    b11         += b_cs;

                    // move remembered cells
                    a00 = a01;
                    a01 = _a02;
                    a10 = a11;
                    a11 = _a12;
                    a20 = a21;
                    a21 = _a22;
                }

                a_index += a_rs;
                b_index += b_rs;
            }
        }