/// <summary>
        /// Replaces all cell values of the receiver with the values of another matrix.
        /// Both matrices must have the same number of 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>columns() != source.columns() || rows() != source.rows()</i></exception>
        public override DoubleMatrix2D Assign(DoubleMatrix2D source)
        {
            // overriden for performance only
            if (source == this)
            {
                return(this);                // nothing to do
            }
            CheckShape(source);

            if (source is TridiagonalDoubleMatrix2D)
            {
                // quickest
                TridiagonalDoubleMatrix2D other = (TridiagonalDoubleMatrix2D)source;

                Array.Copy(other.Values, 0, this.Values, 0, this.Values.Length);
                Array.Copy(other.dims, 0, this.dims, 0, this.dims.Length);
                return(this);
            }

            if (source is RCDoubleMatrix2D || source is SparseDoubleMatrix2D)
            {
                Assign(0);
                source.ForEachNonZero(
                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = value;
                    return(value);
                }
                                                                ));
                return(this);
            }

            return(base.Assign(source));
        }
        public DoubleMatrix2D Assign(DoubleMatrix2D matrixY, Cern.Colt.Function.DoubleDoubleFunction function, Double x = 0, Double y = 0)
        {
            CheckShape(matrixY);

            if (Cern.Jet.Math.Functions.EvaluateDoubleDoubleFunctionEquality(function, F2.PlusMult(x)))
            {                     // x[i] = x[i] + alpha*y[i]
                double alpha = x; // ((Cern.Jet.Math.PlusMult)function).multiplicator;
                if (alpha == 0)
                {
                    return(this);            // nothing to do
                }
                matrixY.ForEachNonZero(
                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = this[i, j] + alpha * value;
                    return(value);
                }
                                                                ));
                return(this);
            }

            if (Cern.Jet.Math.Functions.EvaluateFunctionEquality(function.Method, F2.Mult.Method))
            { // x[i] = x[i] * y[i]
                ForEachNonZero(

                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = this[i, j] * matrixY[i, j];
                    return(value);
                }
                                                                ));
                return(this);
            }

            if (Cern.Jet.Math.Functions.EvaluateFunctionEquality(function.Method, F2.Div.Method))
            { // x[i] = x[i] / y[i]
                ForEachNonZero(

                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = this[i, j] / matrixY[i, j];
                    return(value);
                }
                                                                ));
                return(this);
            }

            return(base.Assign(matrixY, function));
        }
        /// <summary>
        /// Replaces all cell values of the receiver with the values of another matrix.
        /// Both matrices must have the same number of 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>columns() != source.columns() || rows() != source.rows()</i></exception>
        public override DoubleMatrix2D Assign(DoubleMatrix2D source)
        {
            if (source == this)
            {
                return(this);                // nothing to do
            }
            CheckShape(source);
            // overriden for performance only
            if (!(source is RCDoubleMatrix2D))
            {
                //return base.Assign(source);

                Assign(0);
                source.ForEachNonZero(
                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = value;
                    return(value);
                }));

                return(this);
            }

            // even quicker
            RCDoubleMatrix2D other = (RCDoubleMatrix2D)source;

            Array.Copy(other.Starts, 0, this.Starts, 0, this.Starts.Length);
            int s = other.Indexes.Count;

            this.Indexes.SetSize(s);
            this.Values.SetSize(s);
            this.Indexes.ReplaceFromToWithFrom(0, s - 1, other.Indexes, 0);
            this.Values.ReplaceFromToWithFrom(0, s - 1, other.Values, 0);

            return(this);
        }
        public DoubleMatrix2D Assign(DoubleMatrix2D matrixY, Cern.Colt.Function.DoubleDoubleFunction function, Double x = 0, Double y = 0)
        {
            CheckShape(matrixY);

            if (Cern.Jet.Math.Functions.EvaluateDoubleDoubleFunctionEquality(function, F2.PlusMult(x)))
            {
                double alpha = x;

                //if (function is Cern.Jet.Math.PlusMult) { // x[i] = x[i] + alpha*y[i]
                //double alpha = ((Cern.Jet.Math.PlusMult)function).multiplicator;
                if (alpha == 0)
                {
                    return(this);            // nothing to do
                }
                matrixY.ForEachNonZero(
                    new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) =>
                {
                    this[i, j] = this[i, j] + alpha * value;
                    return(value);
                }
                                                                ));
                return(this);
            }

            //if (function==Cern.Jet.Math.Functions.mult) { // x[i] = x[i] * y[i]
            var mult = F2.Mult(x, y);

            if (Cern.Jet.Math.Functions.EvaluateFunctionEquality(function.Method, F2.Mult.Method))
            {
                int[]    idx  = Indexes.ToArray();
                double[] vals = Values.ToArray();

                for (int i = Starts.Length - 1; --i >= 0;)
                {
                    int low = Starts[i];
                    for (int k = Starts[i + 1]; --k >= low;)
                    {
                        int j = idx[k];
                        vals[k] *= matrixY[i, j];
                        if (vals[k] == 0)
                        {
                            Remove(i, j);
                        }
                    }
                }
                return(this);
            }

            if (Cern.Jet.Math.Functions.EvaluateFunctionEquality(function.Method, F2.Div.Method))
            {
                //	if (function==Cern.Jet.Math.Functions.Div) { // x[i] = x[i] / y[i]
                int[]    idx  = Indexes.ToArray();
                double[] vals = Values.ToArray();

                for (int i = Starts.Length - 1; --i >= 0;)
                {
                    int low = Starts[i];
                    for (int k = Starts[i + 1]; --k >= low;)
                    {
                        int j = idx[k];
                        vals[k] /= matrixY[i, j];
                        if (vals[k] == 0)
                        {
                            Remove(i, j);
                        }
                    }
                }
                return(this);
            }

            return(base.Assign(matrixY, function));
        }