/// <summary>
        /// Constructs a diagonal block matrix from the given parts.
        /// </summary>
        /// <param name="a">
        /// The matrix A.
        /// </param>
        /// <param name="b">
        /// The matrix B.
        /// </param>
        /// <param name="c">
        /// The matrix C.
        /// </param>
        /// <returns>
        /// A diagonal block matrix.
        /// </returns>
        public DoubleMatrix2D ComposeDiagonal(DoubleMatrix2D a, DoubleMatrix2D b, DoubleMatrix2D c)
        {
            DoubleMatrix2D diag = Make(a.Rows + b.Rows + c.Rows, a.Columns + b.Columns + c.Columns);

            diag.ViewPart(0, 0, a.Rows, a.Columns).Assign(a);
            diag.ViewPart(a.Rows, a.Columns, b.Rows, b.Columns).Assign(b);
            diag.ViewPart(a.Rows + b.Rows, a.Columns + b.Columns, c.Rows, c.Columns).Assign(c);
            return(diag);
        }
        /// <summary>
        /// Constructs an identity matrix (having ones on the diagonal and zeros elsewhere).
        /// </summary>
        /// <param name="rowsAndColumns">
        /// The rows and columns.
        /// </param>
        /// <returns>
        /// An identity matrix.
        /// </returns>
        public DoubleMatrix2D Identity(int rowsAndColumns)
        {
            DoubleMatrix2D matrix = Make(rowsAndColumns, rowsAndColumns);

            for (int i = rowsAndColumns; --i >= 0;)
            {
                matrix[i, i] = 1;
            }
            return(matrix);
        }
        /// <summary>
        /// Constructs a new vector consisting of the diagonal elements of <tt>A</tt>.
        /// Cells values are copied. The new vector is not a view.
        /// </summary>
        /// <param name="a">
        /// The amatrix, need not be square.
        /// </param>
        /// <returns>
        /// A new vector.
        /// </returns>
        public DoubleMatrix1D Diagonal(DoubleMatrix2D a)
        {
            int            min  = Math.Min(a.Rows, a.Columns);
            DoubleMatrix1D diag = make1D(min);

            for (int i = min; --i >= 0;)
            {
                diag[i] = a[i, i];
            }
            return(diag);
        }
        /// <summary>
        /// Constructs a new diagonal matrix whose diagonal elements are the elements of <tt>vector</tt>.
        /// Cells values are copied. The new matrix is not a view.
        /// </summary>
        /// <param name="vector">
        /// The vector.
        /// </param>
        /// <returns>
        /// A new matrix.
        /// </returns>
        public DoubleMatrix2D Diagonal(DoubleMatrix1D vector)
        {
            int            size = vector.Size;
            DoubleMatrix2D diag = Make(size, size);

            for (int i = size; --i >= 0;)
            {
                diag[i, i] = vector[i];
            }
            return(diag);
        }
        /// <summary>
        /// Constructs a diagonal block matrix from the given parts (the <i>direct sum</i> of two matrices).
        /// </summary>
        /// <param name="a">
        /// The matrix A.
        /// </param>
        /// <param name="b">
        /// The matrix B.
        /// </param>
        /// <returns>
        /// A diagonal block matrix.
        /// </returns>
        public DoubleMatrix2D ComposeDiagonal(DoubleMatrix2D a, DoubleMatrix2D b)
        {
            int            ar  = a.Rows;
            int            ac  = a.Columns;
            int            br  = b.Rows;
            int            bc  = b.Columns;
            DoubleMatrix2D sum = Make(ar + br, ac + bc);

            sum.ViewPart(0, 0, ar, ac).Assign(a);
            sum.ViewPart(ar, ac, br, bc).Assign(b);
            return(sum);
        }
Beispiel #6
0
 /// <summary>
 /// Returns <tt>true</tt> if both matrices share at least one identical cell.
 /// </summary>
 /// <param name="other">
 /// The other matrix.
 /// </param>
 /// <returns>
 /// <tt>true</tt> if both matrices share at least one identical cell.
 /// </returns>
 protected bool HaveSharedCells(DoubleMatrix2D other)
 {
     if (other == null)
     {
         return(false);
     }
     if (this == other)
     {
         return(true);
     }
     return(GetContent().HaveSharedCellsRaw(other.GetContent()));
 }
Beispiel #7
0
 /// <summary>
 /// Assigns the result of a function to each cell; <tt>x[row,col] = function(x[row,col],y[row,col])</tt>.
 /// </summary>
 /// <param name="y">
 /// The secondary matrix to operate on.
 /// </param>
 /// <param name="function">
 /// The function taking as first argument the current cell's value of <tt>this</tt>,
 /// and as second argument the current cell's value of <tt>y</tt>.
 /// </param>
 /// <returns>
 /// <tt>this</tt> (for convenience only).
 /// </returns>
 /// <exception cref="ArgumentException">
 /// If <tt>columns() != other.columns() || rows() != other.rows()</tt>
 /// </exception>
 public virtual DoubleMatrix2D Assign(DoubleMatrix2D y, DoubleDoubleFunction function)
 {
     CheckShape(y);
     for (int row = Rows; --row >= 0;)
     {
         for (int column = Columns; --column >= 0;)
         {
             this[row, column] = function(this[row, column], y[row, column]);
         }
     }
     return(this);
 }
        /// <summary>
        /// Constructs a matrix with cells having descending values.
        /// For debugging purposes.
        /// </summary>
        /// <param name="rows">
        /// The number of rows.
        /// </param>
        /// <param name="columns">
        /// The number of columns.
        /// </param>
        /// <returns>
        /// A matrix with cells having descending values.
        /// </returns>
        public DoubleMatrix2D Descending(int rows, int columns)
        {
            DoubleMatrix2D matrix = Make(rows, columns);
            int            v      = 0;

            for (int row = rows; --row >= 0;)
            {
                for (int column = columns; --column >= 0;)
                {
                    matrix[row, column] = v++;
                }
            }
            return(matrix);
        }
        /// <summary>
        /// Constructs a new matrix which is duplicated both along the row and column dimension.
        /// </summary>
        /// <param name="a">
        /// The matrix to duplicate.
        /// </param>
        /// <param name="rowRepeat">
        /// The number of row repetitions.
        /// </param>
        /// <param name="columnRepeat">
        /// The number of column repetitions.
        /// </param>
        /// <returns>
        /// A matrix.
        /// </returns>
        public DoubleMatrix2D Repeat(DoubleMatrix2D a, int rowRepeat, int columnRepeat)
        {
            int            r      = a.Rows;
            int            c      = a.Columns;
            DoubleMatrix2D matrix = Make(r * rowRepeat, c * columnRepeat);

            for (int i = rowRepeat; --i >= 0;)
            {
                for (int j = columnRepeat; --j >= 0;)
                {
                    matrix.ViewPart(r * i, c * j, r, c).Assign(a);
                }
            }

            return(matrix);
        }
Beispiel #10
0
        /// <summary>
        /// Linear algebraic matrix-matrix multiplication; <tt>C = alpha * A x B + beta*C</tt>.
        /// </summary>
        /// <param name="b">
        /// The second source matrix.
        /// </param>
        /// <param name="c">
        /// The matrix where results are to be storedd Set this parameter to <tt>null</tt> to indicate that a new result matrix shall be constructed.
        /// </param>
        /// <param name="alpha">
        /// The alpha.
        /// </param>
        /// <param name="beta">
        /// The beta.
        /// </param>
        /// <param name="transposeA">
        /// Whether A must be transposed.
        /// </param>
        /// <param name="transposeB">
        /// Whether B must be transposed.
        /// </param>
        /// <returns>
        /// C (for convenience only).
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// If <tt>B.rows() != A.columns()</tt>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If <tt>C.rows() != A.rows() || C.columns() != B.columns()</tt>.
        /// </exception>
        /// <exception cref="ArithmeticException">
        /// If <tt>A == C || B == C</tt>.
        /// </exception>
        public virtual DoubleMatrix2D ZMult(DoubleMatrix2D b, DoubleMatrix2D c, double alpha, double beta, bool transposeA, bool transposeB)
        {
            if (transposeA)
            {
                return(ViewDice().ZMult(b, c, alpha, beta, false, transposeB));
            }
            if (transposeB)
            {
                return(ZMult(b.ViewDice(), c, alpha, beta, false, false));
            }

            int m = Rows;
            int n = Columns;
            int p = b.Columns;

            if (c == null)
            {
                c = new DenseDoubleMatrix2D(m, p);
            }
            if (b.Rows != n)
            {
                throw new ArgumentOutOfRangeException("b", String.Format(Cern.LocalizedResources.Instance().Exception_Matrix2DInnerDimensionMustAgree, this, b));
            }
            if (c.Rows != m || c.Columns != p)
            {
                throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_IncompatibleResultMatrix, this, b, c));
            }
            if (this == c || b == c)
            {
                throw new ArithmeticException(Cern.LocalizedResources.Instance().Exception_MatricesMustNotBeIdentical);
            }

            for (int j = p; --j >= 0;)
            {
                for (int i = m; --i >= 0;)
                {
                    double s = 0;
                    for (int k = n; --k >= 0;)
                    {
                        s += this[i, k] * b[k, j];
                    }
                    c[i, j] = (alpha * s) + (beta * c[i, j]);
                }
            }

            return(c);
        }
        /// <summary>
        /// Linear algebraic matrix-matrix multiplication; <tt>C = alpha * A x B + beta*C</tt>.
        /// </summary>
        /// <param name="b">
        /// The second source matrix.
        /// </param>
        /// <param name="c">
        /// The matrix where results are to be storedd Set this parameter to <tt>null</tt> to indicate that a new result matrix shall be constructed.
        /// </param>
        /// <param name="alpha">
        /// The alpha.
        /// </param>
        /// <param name="beta">
        /// The beta.
        /// </param>
        /// <param name="transposeA">
        /// Whether A must be transposed.
        /// </param>
        /// <param name="transposeB">
        /// Whether B must be transposed.
        /// </param>
        /// <returns>
        /// C (for convenience only).
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// If <tt>B.rows() != A.columns()</tt>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If <tt>C.rows() != A.rows() || C.columns() != B.columns()</tt>.
        /// </exception>
        /// <exception cref="ArithmeticException">
        /// If <tt>A == C || B == C</tt>.
        /// </exception>
        public virtual DoubleMatrix2D ZMult(DoubleMatrix2D b, DoubleMatrix2D c, double alpha, double beta, bool transposeA, bool transposeB)
        {
            if (transposeA)
            {
                return(ViewDice().ZMult(b, c, alpha, beta, false, transposeB));
            }
            if (transposeB)
            {
                return(ZMult(b.ViewDice(), c, alpha, beta, false, false));
            }

            int m = Rows;
            int n = Columns;
            int p = b.Columns;

            if (c == null)
            {
                c = new DenseDoubleMatrix2D(m, p);
            }
            if (b.Rows != n)
            {
                throw new ArgumentOutOfRangeException("b", "Matrix2D inner dimensions must agree:" + this + ", " + b);
            }
            if (c.Rows != m || c.Columns != p)
            {
                throw new ArgumentException("Incompatible result matrix: " + this + ", " + b + ", " + c);
            }
            if (this == c || b == c)
            {
                throw new ArithmeticException("Matrices must not be identical");
            }

            for (int j = p; --j >= 0;)
            {
                for (int i = m; --i >= 0;)
                {
                    double s = 0;
                    for (int k = n; --k >= 0;)
                    {
                        s += this[i, k] * b[k, j];
                    }
                    c[i, j] = (alpha * s) + (beta * c[i, j]);
                }
            }

            return(c);
        }
Beispiel #12
0
        /// <summary>
        /// Modifies the given matrix to be a randomly sampled matrix.
        /// Randomly picks exactly <i>System.Math.Round(rows*columns*nonZeroFraction)</i> cells and initializes them to <i>value</i>, all the rest will be initialized to zero.
        /// Note that this is not the same as setting each cell with probability <i>nonZeroFraction</i> to <i>value</i>.
        /// Note: The random seed is a constant.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="matrix"></param>
        /// <param name="value"></param>
        /// <param name="nonZeroFraction"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">if nonZeroFraction &lt; 0 || nonZeroFraction > 1.</exception>
        /// <see cref="Cern.Jet.Random.Sampling.RandomSamplingAssistant"/>
        public static DoubleMatrix2D Sample(this DoubleFactory2D factory, DoubleMatrix2D matrix, double value, double nonZeroFraction)
        {
            int    rows    = matrix.Rows;
            int    columns = matrix.Columns;
            double epsilon = 1e-09;

            if (nonZeroFraction < 0 - epsilon || nonZeroFraction > 1 + epsilon)
            {
                throw new ArgumentException();
            }
            if (nonZeroFraction < 0)
            {
                nonZeroFraction = 0;
            }
            if (nonZeroFraction > 1)
            {
                nonZeroFraction = 1;
            }

            matrix.Assign(0);

            int size = rows * columns;
            int n    = (int)System.Math.Round(size * nonZeroFraction);

            if (n == 0)
            {
                return(matrix);
            }

            var sampler = new Cern.Jet.Random.Sampling.RandomSamplingAssistant(n, size, new Cern.Jet.Random.Engine.MersenneTwister());

            for (int i = 0; i < size; i++)
            {
                if (sampler.SampleNextElement())
                {
                    int row    = (int)(i / columns);
                    int column = (int)(i % columns);
                    matrix[row, column] = value;
                }
            }

            return(matrix);
        }
Beispiel #13
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>
        /// Construct a matrix from a one-dimensional column-major packed array, ala Fortran.
        /// </summary>
        /// <param name="values">
        /// One-dimensional array of doubles, packed by columns (ala Fortran).
        /// </param>
        /// <param name="rows">
        /// The number of rows.
        /// </param>
        /// <returns>
        /// A matrix.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// <tt>values.length</tt> must be a multiple of <tt>rows</tt>.
        /// </exception>
        public DoubleMatrix2D Make(double[] values, int rows)
        {
            int columns = rows != 0 ? values.Length / rows : 0;

            if (rows * columns != values.Length)
            {
                throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_ArrayLengthMustBeAMultipleOfM);
            }

            DoubleMatrix2D matrix = Make(rows, columns);

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < columns; column++)
                {
                    matrix[row, column] = values[row + (column * rows)];
                }
            }

            return(matrix);
        }
        /// <summary>
        /// Construct a matrix from a one-dimensional column-major packed array, ala Fortran.
        /// </summary>
        /// <param name="values">
        /// One-dimensional array of doubles, packed by columns (ala Fortran).
        /// </param>
        /// <param name="rows">
        /// The number of rows.
        /// </param>
        /// <returns>
        /// A matrix.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// <tt>values.length</tt> must be a multiple of <tt>rows</tt>.
        /// </exception>
        public DoubleMatrix2D Make(double[] values, int rows)
        {
            int columns = rows != 0 ? values.Length / rows : 0;

            if (rows * columns != values.Length)
            {
                throw new ArgumentException("Array length must be a multiple of m.");
            }

            DoubleMatrix2D matrix = Make(rows, columns);

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < columns; column++)
                {
                    matrix[row, column] = values[row + (column * rows)];
                }
            }

            return(matrix);
        }
Beispiel #16
0
        /// <summary>
        /// Applies a function to each corresponding cell of two matrices and aggregates the results.
        /// </summary>
        /// <param name="other">
        /// The other.
        /// </param>
        /// <param name="aggr">
        /// An aggregation function taking as first argument the current aggregation and as second argument the transformed current cell values.
        /// </param>
        /// <param name="f">
        /// A function transforming the current cell values.
        /// </param>
        /// <returns>
        /// The aggregated measure.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If <tt>columns() != other.columns() || rows() != other.rows()</tt>
        /// </exception>
        public double Aggregate(DoubleMatrix2D other, DoubleDoubleFunction aggr, DoubleDoubleFunction f)
        {
            CheckShape(other);
            if (Size == 0)
            {
                return(double.NaN);
            }
            double a = f(this[Rows - 1, Columns - 1], other[Rows - 1, Columns - 1]);
            int    d = 1; // last cell already done

            for (int row = Rows; --row >= 0;)
            {
                for (int column = Columns - d; --column >= 0;)
                {
                    a = aggr(a, f(this[row, column], other[row, column]));
                }
                d = 0;
            }

            return(a);
        }
Beispiel #17
0
        /// <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 <tt>other</tt>.
        /// </summary>
        /// <param name="other">
        /// The source matrix to copy from (may be identical to the receiver).
        /// </param>
        /// <returns>
        /// <tt>this</tt> (for convenience only).
        /// </returns>
        /// <exception cref="ArgumentException">
        /// If <tt>columns() != other.columns() || rows() != other.rows()</tt>
        /// </exception>
        public virtual DoubleMatrix2D Assign(DoubleMatrix2D other)
        {
            if (other == this)
            {
                return(this);
            }
            CheckShape(other);
            if (HaveSharedCells(other))
            {
                other = other.Copy();
            }

            for (int row = Rows; --row >= 0;)
            {
                for (int column = Columns; --column >= 0;)
                {
                    this[row, column] = other[row, column];
                }
            }
            return(this);
        }
        /// <summary>
        /// C = A||B; Constructs a new matrix which is the row-wise concatenation of two other matrices.
        /// </summary>
        /// <param name="a">
        /// The matrix A.
        /// </param>
        /// <param name="b">
        /// The matrix B.
        /// </param>
        /// <returns>
        /// A new matrix which is the row-wise concatenation of A and B.
        /// </returns>
        public DoubleMatrix2D AppendRows(DoubleMatrix2D a, DoubleMatrix2D b)
        {
            // force both to have maximal shared number of columns.
            if (b.Columns > a.Columns)
            {
                b = b.ViewPart(0, 0, b.Rows, a.Columns);
            }
            else if (b.Columns < a.Columns)
            {
                a = a.ViewPart(0, 0, a.Rows, b.Columns);
            }

            // concatenate
            int            ar     = a.Rows;
            int            br     = b.Rows;
            int            c      = a.Columns;
            DoubleMatrix2D matrix = Make(ar + br, c);

            matrix.ViewPart(0, 0, ar, c).Assign(a);
            matrix.ViewPart(ar, 0, br, c).Assign(b);
            return(matrix);
        }
        /// <summary>
        /// C = A||B; Constructs a new matrix which is the column-wise concatenation of two other matrices.
        /// </summary>
        /// <param name="a">
        /// The matrix A.
        /// </param>
        /// <param name="b">
        /// The matrix B.
        /// </param>
        /// <returns>
        /// The column-wise concatenation of A and B.
        /// </returns>
        public DoubleMatrix2D AppendColumns(DoubleMatrix2D a, DoubleMatrix2D b)
        {
            // force both to have maximal shared number of rows.
            if (b.Rows > a.Rows)
            {
                b = b.ViewPart(0, 0, a.Rows, b.Columns);
            }
            else if (b.Rows < a.Rows)
            {
                a = a.ViewPart(0, 0, b.Rows, a.Columns);
            }

            // concatenate
            int            ac     = a.Columns;
            int            bc     = b.Columns;
            int            r      = a.Rows;
            DoubleMatrix2D matrix = Make(r, ac + bc);

            matrix.ViewPart(0, 0, r, ac).Assign(a);
            matrix.ViewPart(0, ac, r, bc).Assign(b);
            return(matrix);
        }
Beispiel #20
0
 /// <summary>
 /// Returns <tt>true</tt> if both matrices share at least one identical cell.
 /// </summary>
 /// <param name="other">
 /// The other matrix.
 /// </param>
 /// <returns>
 /// <tt>true</tt> if both matrices share at least one identical cell.
 /// </returns>
 protected virtual bool HaveSharedCellsRaw(DoubleMatrix2D other)
 {
     return(false);
 }
        /// <summary>
        /// Constructs a block matrix made from the given parts.
        /// <para>
        /// All matrices of a given column within <tt>parts</tt> must have the same number of columns.
        /// All matrices of a given row within <tt>parts</tt> must have the same number of rows.
        /// Otherwise an <tt>IllegalArgumentException</tt> is thrown.
        /// <tt>null</tt>s within <tt>parts[row,col]</tt> are an exception to this rule: they are ignored.
        /// Cells are copied.
        /// </para>
        /// </summary>
        /// <param name="parts">
        /// The parts.
        /// </param>
        /// <returns>
        /// A block matrix.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// If the parts are not subject to the conditions outlined above.
        /// </exception>
        public DoubleMatrix2D Compose(DoubleMatrix2D[][] parts)
        {
            checkRectangularShape(parts);
            int rows    = parts.Length;
            int columns = 0;

            if (parts.Length > 0)
            {
                columns = parts[0].Length;
            }
            DoubleMatrix2D empty = Make(0, 0);

            if (rows == 0 || columns == 0)
            {
                return(empty);
            }

            // determine maximum column width of each column
            var maxWidths = new int[columns];

            for (int column = columns; --column >= 0;)
            {
                int maxWidth = 0;
                for (int row = rows; --row >= 0;)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        int width = part.Columns;
                        if (maxWidth > 0 && width > 0 && width != maxWidth)
                        {
                            throw new ArgumentOutOfRangeException("parts", "Different number of columns.");
                        }
                        maxWidth = Math.Max(maxWidth, width);
                    }
                }

                maxWidths[column] = maxWidth;
            }

            // determine row height of each row
            var maxHeights = new int[rows];

            for (int row = rows; --row >= 0;)
            {
                int maxHeight = 0;
                for (int column = columns; --column >= 0;)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        int height = part.Rows;
                        if (maxHeight > 0 && height > 0 && height != maxHeight)
                        {
                            throw new ArgumentOutOfRangeException("parts", "Different number of rows.");
                        }
                        maxHeight = Math.Max(maxHeight, height);
                    }
                }

                maxHeights[row] = maxHeight;
            }

            // shape of result
            int resultRows = 0;

            for (int row = rows; --row >= 0;)
            {
                resultRows += maxHeights[row];
            }
            int resultCols = 0;

            for (int column = columns; --column >= 0;)
            {
                resultCols += maxWidths[column];
            }

            DoubleMatrix2D matrix = Make(resultRows, resultCols);

            // copy
            int r = 0;

            for (int row = 0; row < rows; row++)
            {
                int c = 0;
                for (int column = 0; column < columns; column++)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        matrix.ViewPart(r, c, part.Rows, part.Columns).Assign(part);
                    }
                    c += maxWidths[column];
                }

                r += maxHeights[row];
            }

            return(matrix);
        }
        /// <summary>
        /// Splits a block matrix into its constituent blocks; Copies blocks of a matrix into the given parts.
        /// <para>
        /// All matrices of a given column within <tt>parts</tt> must have the same number of columns.
        /// All matrices of a given row within <tt>parts</tt> must have the same number of rows.
        /// Otherwise an <tt>IllegalArgumentException</tt> is thrown.
        /// <tt>null</tt>s within <tt>parts[row,col]</tt> are an exception to this rule: they are ignored.
        /// Cells are copied.
        /// </para>
        /// </summary>
        /// <param name="parts">
        /// The parts.
        /// </param>
        /// <param name="matrix">
        /// The matrix.
        /// </param>
        /// <exception cref="ArgumentException">
        /// subject to the conditions outlined above.
        /// </exception>
        public void Decompose(DoubleMatrix2D[][] parts, DoubleMatrix2D matrix)
        {
            checkRectangularShape(parts);
            int rows    = parts.Length;
            int columns = 0;

            if (parts.Length > 0)
            {
                columns = parts[0].Length;
            }
            if (rows == 0 || columns == 0)
            {
                return;
            }

            // determine maximum column width of each column
            var maxWidths = new int[columns];

            for (int column = columns; --column >= 0;)
            {
                int maxWidth = 0;
                for (int row = rows; --row >= 0;)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        int width = part.Columns;
                        if (maxWidth > 0 && width > 0 && width != maxWidth)
                        {
                            throw new ArgumentException("Different number of columns.");
                        }
                        maxWidth = Math.Max(maxWidth, width);
                    }
                }

                maxWidths[column] = maxWidth;
            }

            // determine row height of each row
            var maxHeights = new int[rows];

            for (int row = rows; --row >= 0;)
            {
                int maxHeight = 0;
                for (int column = columns; --column >= 0;)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        int height = part.Rows;
                        if (maxHeight > 0 && height > 0 && height != maxHeight)
                        {
                            throw new ArgumentException("Different number of rows.");
                        }
                        maxHeight = Math.Max(maxHeight, height);
                    }
                }

                maxHeights[row] = maxHeight;
            }

            // shape of result parts
            int resultRows = 0;

            for (int row = rows; --row >= 0;)
            {
                resultRows += maxHeights[row];
            }
            int resultCols = 0;

            for (int column = columns; --column >= 0;)
            {
                resultCols += maxWidths[column];
            }

            if (matrix.Rows < resultRows || matrix.Columns < resultCols)
            {
                throw new ArgumentException("Parts larger than matrix.");
            }

            // copy
            int r = 0;

            for (int row = 0; row < rows; row++)
            {
                int c = 0;
                for (int column = 0; column < columns; column++)
                {
                    DoubleMatrix2D part = parts[row][column];
                    if (part != null)
                    {
                        part.Assign(matrix.ViewPart(r, c, part.Rows, part.Columns));
                    }
                    c += maxWidths[column];
                }

                r += maxHeights[row];
            }
        }
Beispiel #23
0
 /// <summary>
 /// Linear algebraic matrix-matrix multiplication; <tt>C = A x B</tt>.
 /// </summary>
 /// <param name="b">
 /// The matrix B.
 /// </param>
 /// <param name="c">
 /// The matrix C.
 /// </param>
 /// <returns>
 /// The matrix C (for convenience only).
 /// </returns>
 public DoubleMatrix2D ZMult(DoubleMatrix2D b, DoubleMatrix2D c)
 {
     return(ZMult(b, c, 1, (c == null ? 1 : 0), false, false));
 }
Beispiel #24
0
        /// <summary>
        /// Constructs a randomly sampled matrix with the given shape.
        /// Randomly picks exactly<tt>Math.round(rows* columns* nonZeroFraction)</tt> cells and initializes them to<tt> value</tt>, all the rest will be initialized to zero.
        /// Note that this is not the same as setting each cell with probability<tt> nonZeroFraction</tt> to<tt> value</tt>.
        /// Note: The random seed is a constant.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="rows"></param>
        /// <param name="columns"></param>
        /// <param name="value"></param>
        /// <param name="nonZeroFraction"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">if nonZeroFraction &lt; 0 || nonZeroFraction > 1.</exception>
        /// <see cref="Cern.Jet.Random.Sampling.RandomSamplingAssistant"/>
        public static DoubleMatrix2D Sample(this DoubleFactory2D factory, int rows, int columns, double value, double nonZeroFraction)
        {
            DoubleMatrix2D matrix = factory.Make(rows, columns);

            return(Sample(factory, matrix, value, nonZeroFraction));
        }