/// <summary>
        /// Replaces all cell values of the receiver with the values of another matrix.
        /// Both matrices must have the same number of Slices, Rows and Columns.
        /// If both matrices share the same cells (as is the case if they are views derived from the same matrix) and intersect in an ambiguous way, then replaces <i>as if</i> using an intermediate auxiliary deep copy of <i>other</i>.
        /// </summary>
        /// <param name="source">the source matrix to copy from (may be identical to the receiver).</param>
        /// <returns><i>this</i> (for convenience only).</returns>
        /// <exception cref="ArgumentException">if <i>Slices() != source.Slices() || Rows() != source.Rows() || Columns() != source.Columns()</i></exception>
        public override DoubleMatrix3D Assign(DoubleMatrix3D source)
        {
            // overriden for performance only
            if (!(source is DenseDoubleMatrix3D))
            {
                return(base.Assign(source));
            }
            DenseDoubleMatrix3D other = (DenseDoubleMatrix3D)source;

            if (other == this)
            {
                return(this);
            }
            CheckShape(other);
            if (HaveSharedCells(other))
            {
                DoubleMatrix3D c = other.Copy();
                if (!(c is DenseDoubleMatrix3D))
                { // should not happen
                    return(base.Assign(source));
                }
                other = (DenseDoubleMatrix3D)c;
            }

            if (!this.IsView && !other.IsView)
            { // quickest
                Array.Copy(other.Elements, 0, this.Elements, 0, this.Elements.Length);
                return(this);
            }
            return(base.Assign(other));
        }
 /// <summary>
 /// Returns <i>true</i> if both matrices share common cells.
 /// More formally, returns <i>true</i> if <i>other != null</i> and at least one of the following conditions is met
 /// <ul>
 /// <li>the receiver is a view of the other matrix
 /// <li>the other matrix is a view of the receiver
 /// <li><i>this == other</i>
 /// </ul>
 /// </summary>
 protected new Boolean HaveSharedCellsRaw(DoubleMatrix3D other)
 {
     if (other is SelectedDenseDoubleMatrix3D)
     {
         SelectedDenseDoubleMatrix3D otherMatrix = (SelectedDenseDoubleMatrix3D)other;
         return(this.Elements == otherMatrix.Elements);
     }
     else if (other is DenseDoubleMatrix3D)
     {
         DenseDoubleMatrix3D otherMatrix = (DenseDoubleMatrix3D)other;
         return(this.Elements == otherMatrix.Elements);
     }
     return(false);
 }
        /// <summary>
        /// 27 neighbor stencil transformation.For efficient finite difference operations.
        /// Applies a function to a moving<i>3 x 3 x 3</i> window.
        /// Does nothing if <i>Rows() < 3 || Columns() < 3 || Slices() < 3</i>.
        /// <pre>
        /// B[k, i, j] = function.apply(
        /// &nbsp;&nbsp;&nbsp;A[k - 1, i - 1, j - 1], A[k - 1, i - 1, j], A[k - 1, i - 1, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k - 1, i, j - 1], A[k - 1, i, j], A[k - 1, i, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k - 1, i + 1, j - 1], A[k - 1, i + 1, j], A[k - 1, i + 1, j + 1],
        ///
        /// &nbsp;&nbsp;&nbsp;A[k, i - 1, j - 1], A[k, i - 1, j], A[k, i - 1, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k, i, j - 1], A[k, i, j], A[k, i, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k, i + 1, j - 1], A[k, i + 1, j], A[k, i + 1, j + 1],
        ///
        /// &nbsp;&nbsp;&nbsp;A[k + 1, i - 1, j - 1], A[k + 1, i - 1, j], A[k + 1, i - 1, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k + 1, i, j - 1], A[k + 1, i, j], A[k + 1, i, j + 1],
        /// &nbsp;&nbsp;&nbsp;A[k + 1, i + 1, j - 1], A[k + 1, i + 1, j], A[k + 1, i + 1, j + 1]
        /// &nbsp;&nbsp;&nbsp;)
        ///
        /// x x x - &nbsp;&nbsp;&nbsp; - x x x &nbsp;&nbsp;&nbsp; - - - -
        /// x o x - &nbsp;&nbsp;&nbsp; - x o x &nbsp;&nbsp;&nbsp; - - - -
        /// x x x - &nbsp;&nbsp;&nbsp; - x x x..d - x x x
        /// - - - - &nbsp;&nbsp;&nbsp; - - - - &nbsp;&nbsp;&nbsp; - x o x
        /// - - - - &nbsp;&nbsp;&nbsp; - - - - &nbsp;&nbsp;&nbsp; - x x x
        /// </pre>
        /// Make sure that cells of<i>this</i> and<i> B</i> do not overlap.
        /// In case of overlapping views, behaviour is unspecified.
        /// </pre>
        /// <p>
        /// <b>Example:</b>
        /// <pre>
        /// double alpha = 0.25;
        ///         double beta = 0.75;
        ///
        ///         cern.colt.function.Double27Function f = new cern.colt.function.Double27Function() {
        /// &nbsp;&nbsp;&nbsp;public double apply(
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a000, double a001, double a002,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a010, double a011, double a012,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a020, double a021, double a022,
        ///
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a100, double a101, double a102,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a110, double a111, double a112,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a120, double a121, double a122,
        ///
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a200, double a201, double a202,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a210, double a211, double a212,
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a220, double a221, double a222) {
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return beta* a111 + alpha* (a000 + ..d + a222);
        /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
        /// };
        /// A.zAssign27Neighbors(B, f);
        /// </pre>
        /// </summary>
        /// <param name="B">the matrix to hold the results.</param>
        /// <param name="function">the function to be applied to the 27 cells.</param>
        /// <returns></returns>
        /// <exception cref="NullReferenceException">if <i>function==null</i>.</exception>
        /// <exception cref="ArgumentException">if <i>Rows() != B.Rows() || Columns() != B.Columns() || Slices() != B.Slices() </i>.</exception>
        public override void ZAssign27Neighbors(DoubleMatrix3D B, Cern.Colt.Function.Double27Function function)
        {
            // overridden for performance only
            if (!(B is DenseDoubleMatrix3D))
            {
                base.ZAssign27Neighbors(B, function);
                return;
            }
            if (function == null)
            {
                throw new NullReferenceException(Cern.LocalizedResources.Instance().Exception_FuncionMustNotBeNull);
            }
            CheckShape(B);
            int r = Rows - 1;
            int c = Columns - 1;

            if (Rows < 3 || Columns < 3 || Slices < 3)
            {
                return;                                        // nothing to do
            }
            DenseDoubleMatrix3D BB = (DenseDoubleMatrix3D)B;
            int A_ss = SliceStride;
            int A_rs = RowStride;
            int B_rs = BB.RowStride;
            int A_cs = ColumnStride;
            int B_cs = BB.ColumnStride;

            double[] elems   = this.Elements;
            double[] B_elems = BB.Elements;
            if (elems == null || B_elems == null)
            {
                throw new NullReferenceException();
            }

            for (int k = 1; k < Slices - 1; k++)
            {
                int A_index = Index(k, 1, 1);
                int B_index = BB.Index(k, 1, 1);

                for (int i = 1; i < r; i++)
                {
                    int A002 = A_index - A_ss - A_rs - A_cs;
                    int A012 = A002 + A_rs;
                    int A022 = A012 + A_rs;

                    int A102 = A002 + A_ss;
                    int A112 = A102 + A_rs;
                    int A122 = A112 + A_rs;

                    int A202 = A102 + A_ss;
                    int A212 = A202 + A_rs;
                    int A222 = A212 + A_rs;

                    double a000, a001, a002;
                    double a010, a011, a012;
                    double a020, a021, a022;

                    double a100, a101, a102;
                    double a110, a111, a112;
                    double a120, a121, a122;

                    double a200, a201, a202;
                    double a210, a211, a212;
                    double a220, a221, a222;

                    a000 = elems[A002]; A002 += A_cs; a001 = elems[A002];
                    a010 = elems[A012]; A012 += A_cs; a011 = elems[A012];
                    a020 = elems[A022]; A022 += A_cs; a021 = elems[A022];

                    a100 = elems[A102]; A102 += A_cs; a101 = elems[A102];
                    a110 = elems[A112]; A112 += A_cs; a111 = elems[A112];
                    a120 = elems[A122]; A122 += A_cs; a121 = elems[A122];

                    a200 = elems[A202]; A202 += A_cs; a201 = elems[A202];
                    a210 = elems[A212]; A212 += A_cs; a211 = elems[A212];
                    a220 = elems[A222]; A222 += A_cs; a221 = elems[A222];

                    int B11 = B_index;
                    for (int j = 1; j < c; j++)
                    {
                        // in each step 18 cells can be remembered in registers - they don't need to be reread from slow memory
                        // in each step 9 instead of 27 cells need to be read from memory.
                        a002 = elems[A002 += A_cs];
                        a012 = elems[A012 += A_cs];
                        a022 = elems[A022 += A_cs];

                        a102 = elems[A102 += A_cs];
                        a112 = elems[A112 += A_cs];
                        a122 = elems[A122 += A_cs];

                        a202 = elems[A202 += A_cs];
                        a212 = elems[A212 += A_cs];
                        a222 = elems[A222 += A_cs];

                        B_elems[B11] = function(
                            a000, a001, a002,
                            a010, a011, a012,
                            a020, a021, a022,

                            a100, a101, a102,
                            a110, a111, a112,
                            a120, a121, a122,

                            a200, a201, a202,
                            a210, a211, a212,
                            a220, a221, a222);
                        B11 += B_cs;

                        // move remembered cells
                        a000 = a001; a001 = a002;
                        a010 = a011; a011 = a012;
                        a020 = a021; a021 = a022;

                        a100 = a101; a101 = a102;
                        a110 = a111; a111 = a112;
                        a120 = a121; a121 = a122;

                        a200 = a201; a201 = a202;
                        a210 = a211; a211 = a212;
                        a220 = a221; a221 = a222;
                    }
                    A_index += A_rs;
                    B_index += B_rs;
                }
            }
        }