AbstractRealMatrix.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.linear;

  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Locale;

  25. import org.hipparchus.exception.LocalizedCoreFormats;
  26. import org.hipparchus.exception.MathIllegalArgumentException;
  27. import org.hipparchus.exception.NullArgumentException;
  28. import org.hipparchus.util.FastMath;
  29. import org.hipparchus.util.MathUtils;

  30. /**
  31.  * Basic implementation of RealMatrix methods regardless of the underlying storage.
  32.  * <p>All the methods implemented here use {@link #getEntry(int, int)} to access
  33.  * matrix elements. Derived class can provide faster implementations.</p>
  34.  *
  35.  */
  36. public abstract class AbstractRealMatrix
  37.     implements RealMatrix, RealLinearOperator {

  38.     /** Default format. */
  39.     private static final RealMatrixFormat DEFAULT_FORMAT = RealMatrixFormat.getRealMatrixFormat(Locale.US);
  40.     static {
  41.         // set the minimum fraction digits to 1 to keep compatibility
  42.         DEFAULT_FORMAT.getFormat().setMinimumFractionDigits(1);
  43.     }

  44.     /**
  45.      * Creates a matrix with no data
  46.      */
  47.     protected AbstractRealMatrix() {
  48.         // This constructor is intentionally empty. Nothing special is needed here.
  49.     }

  50.     /**
  51.      * Create a new RealMatrix with the supplied row and column dimensions.
  52.      *
  53.      * @param rowDimension  the number of rows in the new matrix
  54.      * @param columnDimension  the number of columns in the new matrix
  55.      * @throws MathIllegalArgumentException if row or column dimension is not positive
  56.      */
  57.     protected AbstractRealMatrix(final int rowDimension,
  58.         final int columnDimension)
  59.         throws MathIllegalArgumentException {
  60.         if (rowDimension < 1) {
  61.             throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_ROW);
  62.         }
  63.         if (columnDimension < 1) {
  64.             throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_COLUMN);
  65.         }
  66.     }

  67.     /** {@inheritDoc} */
  68.     @Override
  69.     public RealMatrix add(RealMatrix m)
  70.         throws MathIllegalArgumentException {
  71.         MatrixUtils.checkAdditionCompatible(this, m);

  72.         final int rowCount    = getRowDimension();
  73.         final int columnCount = getColumnDimension();
  74.         final RealMatrix out = createMatrix(rowCount, columnCount);
  75.         for (int row = 0; row < rowCount; ++row) {
  76.             for (int col = 0; col < columnCount; ++col) {
  77.                 out.setEntry(row, col, getEntry(row, col) + m.getEntry(row, col));
  78.             }
  79.         }

  80.         return out;
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     public RealMatrix subtract(final RealMatrix m)
  85.         throws MathIllegalArgumentException {
  86.         MatrixUtils.checkSubtractionCompatible(this, m);

  87.         final int rowCount    = getRowDimension();
  88.         final int columnCount = getColumnDimension();
  89.         final RealMatrix out = createMatrix(rowCount, columnCount);
  90.         for (int row = 0; row < rowCount; ++row) {
  91.             for (int col = 0; col < columnCount; ++col) {
  92.                 out.setEntry(row, col, getEntry(row, col) - m.getEntry(row, col));
  93.             }
  94.         }

  95.         return out;
  96.     }

  97.     /** {@inheritDoc} */
  98.     @Override
  99.     public RealMatrix scalarAdd(final double d) {
  100.         final int rowCount    = getRowDimension();
  101.         final int columnCount = getColumnDimension();
  102.         final RealMatrix out = createMatrix(rowCount, columnCount);
  103.         for (int row = 0; row < rowCount; ++row) {
  104.             for (int col = 0; col < columnCount; ++col) {
  105.                 out.setEntry(row, col, getEntry(row, col) + d);
  106.             }
  107.         }

  108.         return out;
  109.     }

  110.     /** {@inheritDoc} */
  111.     @Override
  112.     public RealMatrix scalarMultiply(final double d) {
  113.         final int rowCount    = getRowDimension();
  114.         final int columnCount = getColumnDimension();
  115.         final RealMatrix out = createMatrix(rowCount, columnCount);
  116.         for (int row = 0; row < rowCount; ++row) {
  117.             for (int col = 0; col < columnCount; ++col) {
  118.                 out.setEntry(row, col, getEntry(row, col) * d);
  119.             }
  120.         }

  121.         return out;
  122.     }

  123.     /** {@inheritDoc} */
  124.     @Override
  125.     public RealMatrix multiply(final RealMatrix m)
  126.         throws MathIllegalArgumentException {
  127.         MatrixUtils.checkMultiplicationCompatible(this, m);

  128.         final int nRows = getRowDimension();
  129.         final int nCols = m.getColumnDimension();
  130.         final int nSum  = getColumnDimension();
  131.         final RealMatrix out = createMatrix(nRows, nCols);
  132.         for (int row = 0; row < nRows; ++row) {
  133.             for (int col = 0; col < nCols; ++col) {
  134.                 double sum = 0;
  135.                 for (int i = 0; i < nSum; ++i) {
  136.                     sum += getEntry(row, i) * m.getEntry(i, col);
  137.                 }
  138.                 out.setEntry(row, col, sum);
  139.             }
  140.         }

  141.         return out;
  142.     }

  143.     /** {@inheritDoc} */
  144.     @Override
  145.     public RealMatrix preMultiply(final RealMatrix m)
  146.         throws MathIllegalArgumentException {
  147.         return m.multiply(this);
  148.     }

  149.     /** {@inheritDoc} */
  150.     @Override
  151.     public RealMatrix power(final int p)
  152.         throws MathIllegalArgumentException {
  153.         if (p < 0) {
  154.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NOT_POSITIVE_EXPONENT, p);
  155.         }

  156.         if (!isSquare()) {
  157.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
  158.                                                    getRowDimension(), getColumnDimension());
  159.         }

  160.         if (p == 0) {
  161.             return MatrixUtils.createRealIdentityMatrix(this.getRowDimension());
  162.         }

  163.         if (p == 1) {
  164.             return this.copy();
  165.         }

  166.         final int power = p - 1;

  167.         /*
  168.          * Only log_2(p) operations is used by doing as follows:
  169.          * 5^214 = 5^128 * 5^64 * 5^16 * 5^4 * 5^2
  170.          *
  171.          * In general, the same approach is used for A^p.
  172.          */

  173.         final char[]        binaryRepresentation = Integer.toBinaryString(power).toCharArray();
  174.         final List<Integer> nonZeroPositions     = new ArrayList<>();
  175.         int                 maxI                 = -1;

  176.         for (int i = 0; i < binaryRepresentation.length; ++i) {
  177.             if (binaryRepresentation[i] == '1') {
  178.                 final int pos = binaryRepresentation.length - i - 1;
  179.                 nonZeroPositions.add(pos);

  180.                 // The positions are taken in turn, so maxI is only changed once
  181.                 if (maxI == -1) {
  182.                     maxI = pos;
  183.                 }
  184.             }
  185.         }

  186.         RealMatrix[] results = new RealMatrix[maxI + 1];
  187.         results[0] = this.copy();

  188.         for (int i = 1; i <= maxI; ++i) {
  189.             results[i] = results[i-1].multiply(results[i-1]);
  190.         }

  191.         RealMatrix result = this.copy();

  192.         for (Integer i : nonZeroPositions) {
  193.             result = result.multiply(results[i]);
  194.         }

  195.         return result;
  196.     }

  197.     /** {@inheritDoc} */
  198.     @Override
  199.     public double[][] getData() {
  200.         final double[][] data = new double[getRowDimension()][getColumnDimension()];

  201.         for (int i = 0; i < data.length; ++i) {
  202.             final double[] dataI = data[i];
  203.             for (int j = 0; j < dataI.length; ++j) {
  204.                 dataI[j] = getEntry(i, j);
  205.             }
  206.         }

  207.         return data;
  208.     }

  209.     /** {@inheritDoc} */
  210.     @Override
  211.     public double getFrobeniusNorm() {
  212.         return walkInOptimizedOrder(new RealMatrixPreservingVisitor() {

  213.             /** Sum of squared entries. */
  214.             private double sum;

  215.             /** {@inheritDoc} */
  216.             @Override
  217.             public void start(final int rows, final int columns,
  218.                               final int startRow, final int endRow,
  219.                               final int startColumn, final int endColumn) {
  220.                 sum = 0;
  221.             }

  222.             /** {@inheritDoc} */
  223.             @Override
  224.             public void visit(final int row, final int column, final double value) {
  225.                 sum += value * value;
  226.             }

  227.             /** {@inheritDoc} */
  228.             @Override
  229.             public double end() {
  230.                 return FastMath.sqrt(sum);
  231.             }
  232.         });
  233.     }

  234.     /** {@inheritDoc} */
  235.     @Override
  236.     public RealMatrix getSubMatrix(final int startRow, final int endRow,
  237.                                    final int startColumn, final int endColumn)
  238.         throws MathIllegalArgumentException {
  239.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);

  240.         final RealMatrix subMatrix =
  241.             createMatrix(endRow - startRow + 1, endColumn - startColumn + 1);
  242.         for (int i = startRow; i <= endRow; ++i) {
  243.             for (int j = startColumn; j <= endColumn; ++j) {
  244.                 subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j));
  245.             }
  246.         }

  247.         return subMatrix;
  248.     }

  249.     /** {@inheritDoc} */
  250.     @Override
  251.     public RealMatrix getSubMatrix(final int[] selectedRows,
  252.                                    final int[] selectedColumns)
  253.         throws MathIllegalArgumentException, NullArgumentException {
  254.         MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns);

  255.         final RealMatrix subMatrix =
  256.             createMatrix(selectedRows.length, selectedColumns.length);
  257.         subMatrix.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {

  258.             /** {@inheritDoc} */
  259.             @Override
  260.             public double visit(final int row, final int column, final double value) {
  261.                 return getEntry(selectedRows[row], selectedColumns[column]);
  262.             }

  263.         });

  264.         return subMatrix;
  265.     }

  266.     /** {@inheritDoc} */
  267.     @Override
  268.     public void copySubMatrix(final int startRow, final int endRow,
  269.                               final int startColumn, final int endColumn,
  270.                               final double[][] destination)
  271.         throws MathIllegalArgumentException {
  272.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
  273.         final int rowsCount    = endRow + 1 - startRow;
  274.         final int columnsCount = endColumn + 1 - startColumn;
  275.         if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) {
  276.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  277.                                                    destination.length, destination[0].length,
  278.                                                    rowsCount, columnsCount);
  279.         }

  280.         for (int i = 1; i < rowsCount; i++) {
  281.             if (destination[i].length < columnsCount) {
  282.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  283.                                                        destination.length, destination[i].length,
  284.                                                        rowsCount, columnsCount);
  285.             }
  286.         }

  287.         walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {

  288.             /** Initial row index. */
  289.             private int startRow;

  290.             /** Initial column index. */
  291.             private int startColumn;

  292.             /** {@inheritDoc} */
  293.             @Override
  294.             public void start(final int rows, final int columns,
  295.                               final int startRow, final int endRow,
  296.                               final int startColumn, final int endColumn) {
  297.                 this.startRow    = startRow;
  298.                 this.startColumn = startColumn;
  299.             }

  300.             /** {@inheritDoc} */
  301.             @Override
  302.             public void visit(final int row, final int column, final double value) {
  303.                 destination[row - startRow][column - startColumn] = value;
  304.             }

  305.         }, startRow, endRow, startColumn, endColumn);
  306.     }

  307.     /** {@inheritDoc} */
  308.     @Override
  309.     public void copySubMatrix(int[] selectedRows, int[] selectedColumns,
  310.                               double[][] destination)
  311.         throws MathIllegalArgumentException, NullArgumentException {
  312.         MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns);
  313.         final int nCols = selectedColumns.length;
  314.         if ((destination.length < selectedRows.length) ||
  315.             (destination[0].length < nCols)) {
  316.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  317.                                                    destination.length, destination[0].length,
  318.                                                    selectedRows.length, selectedColumns.length);
  319.         }

  320.         for (int i = 0; i < selectedRows.length; i++) {
  321.             final double[] destinationI = destination[i];
  322.             if (destinationI.length < nCols) {
  323.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  324.                                                        destination.length, destinationI.length,
  325.                                                        selectedRows.length, selectedColumns.length);
  326.             }
  327.             for (int j = 0; j < selectedColumns.length; j++) {
  328.                 destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]);
  329.             }
  330.         }
  331.     }

  332.     /** {@inheritDoc} */
  333.     @Override
  334.     public void setSubMatrix(final double[][] subMatrix, final int row, final int column)
  335.         throws MathIllegalArgumentException, NullArgumentException {
  336.         MathUtils.checkNotNull(subMatrix);
  337.         final int nRows = subMatrix.length;
  338.         if (nRows == 0) {
  339.             throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_ROW);
  340.         }

  341.         final int nCols = subMatrix[0].length;
  342.         if (nCols == 0) {
  343.             throw new MathIllegalArgumentException(LocalizedCoreFormats.AT_LEAST_ONE_COLUMN);
  344.         }

  345.         for (int r = 1; r < nRows; ++r) {
  346.             if (subMatrix[r].length != nCols) {
  347.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  348.                                                        nCols, subMatrix[r].length);
  349.             }
  350.         }

  351.         MatrixUtils.checkRowIndex(this, row);
  352.         MatrixUtils.checkColumnIndex(this, column);
  353.         MatrixUtils.checkRowIndex(this, nRows + row - 1);
  354.         MatrixUtils.checkColumnIndex(this, nCols + column - 1);

  355.         for (int i = 0; i < nRows; ++i) {
  356.             for (int j = 0; j < nCols; ++j) {
  357.                 setEntry(row + i, column + j, subMatrix[i][j]);
  358.             }
  359.         }
  360.     }

  361.     /** {@inheritDoc} */
  362.     @Override
  363.     public RealMatrix getRowMatrix(final int row) throws MathIllegalArgumentException {
  364.         MatrixUtils.checkRowIndex(this, row);
  365.         final int nCols = getColumnDimension();
  366.         final RealMatrix out = createMatrix(1, nCols);
  367.         for (int i = 0; i < nCols; ++i) {
  368.             out.setEntry(0, i, getEntry(row, i));
  369.         }

  370.         return out;
  371.     }

  372.     /** {@inheritDoc} */
  373.     @Override
  374.     public void setRowMatrix(final int row, final RealMatrix matrix)
  375.         throws MathIllegalArgumentException {
  376.         MatrixUtils.checkRowIndex(this, row);
  377.         final int nCols = getColumnDimension();
  378.         if ((matrix.getRowDimension() != 1) ||
  379.             (matrix.getColumnDimension() != nCols)) {
  380.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  381.                                                    matrix.getRowDimension(), matrix.getColumnDimension(),
  382.                                                    1, nCols);
  383.         }
  384.         for (int i = 0; i < nCols; ++i) {
  385.             setEntry(row, i, matrix.getEntry(0, i));
  386.         }
  387.     }

  388.     /** {@inheritDoc} */
  389.     @Override
  390.     public RealMatrix getColumnMatrix(final int column)
  391.         throws MathIllegalArgumentException {
  392.         MatrixUtils.checkColumnIndex(this, column);
  393.         final int nRows = getRowDimension();
  394.         final RealMatrix out = createMatrix(nRows, 1);
  395.         for (int i = 0; i < nRows; ++i) {
  396.             out.setEntry(i, 0, getEntry(i, column));
  397.         }

  398.         return out;
  399.     }

  400.     /** {@inheritDoc} */
  401.     @Override
  402.     public void setColumnMatrix(final int column, final RealMatrix matrix)
  403.         throws MathIllegalArgumentException {
  404.         MatrixUtils.checkColumnIndex(this, column);
  405.         final int nRows = getRowDimension();
  406.         if ((matrix.getRowDimension() != nRows) ||
  407.             (matrix.getColumnDimension() != 1)) {
  408.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  409.                                                    matrix.getRowDimension(), matrix.getColumnDimension(),
  410.                                                    nRows, 1);
  411.         }
  412.         for (int i = 0; i < nRows; ++i) {
  413.             setEntry(i, column, matrix.getEntry(i, 0));
  414.         }
  415.     }

  416.     /** {@inheritDoc} */
  417.     @Override
  418.     public RealVector getRowVector(final int row)
  419.         throws MathIllegalArgumentException {
  420.         return new ArrayRealVector(getRow(row), false);
  421.     }

  422.     /** {@inheritDoc} */
  423.     @Override
  424.     public void setRowVector(final int row, final RealVector vector)
  425.         throws MathIllegalArgumentException {
  426.         MatrixUtils.checkRowIndex(this, row);
  427.         final int nCols = getColumnDimension();
  428.         if (vector.getDimension() != nCols) {
  429.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  430.                                                    1, vector.getDimension(),
  431.                                                    1, nCols);
  432.         }
  433.         for (int i = 0; i < nCols; ++i) {
  434.             setEntry(row, i, vector.getEntry(i));
  435.         }
  436.     }

  437.     /** {@inheritDoc} */
  438.     @Override
  439.     public RealVector getColumnVector(final int column)
  440.         throws MathIllegalArgumentException {
  441.         return new ArrayRealVector(getColumn(column), false);
  442.     }

  443.     /** {@inheritDoc} */
  444.     @Override
  445.     public void setColumnVector(final int column, final RealVector vector)
  446.         throws MathIllegalArgumentException {
  447.         MatrixUtils.checkColumnIndex(this, column);
  448.         final int nRows = getRowDimension();
  449.         if (vector.getDimension() != nRows) {
  450.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  451.                                                    vector.getDimension(), 1,
  452.                                                    nRows, 1);
  453.         }
  454.         for (int i = 0; i < nRows; ++i) {
  455.             setEntry(i, column, vector.getEntry(i));
  456.         }
  457.     }

  458.     /** {@inheritDoc} */
  459.     @Override
  460.     public double[] getRow(final int row) throws MathIllegalArgumentException {
  461.         MatrixUtils.checkRowIndex(this, row);
  462.         final int nCols = getColumnDimension();
  463.         final double[] out = new double[nCols];
  464.         for (int i = 0; i < nCols; ++i) {
  465.             out[i] = getEntry(row, i);
  466.         }

  467.         return out;
  468.     }

  469.     /** {@inheritDoc} */
  470.     @Override
  471.     public void setRow(final int row, final double[] array)
  472.         throws MathIllegalArgumentException {
  473.         MatrixUtils.checkRowIndex(this, row);
  474.         final int nCols = getColumnDimension();
  475.         if (array.length != nCols) {
  476.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  477.                                                    1, array.length,
  478.                                                    1, nCols);
  479.         }
  480.         for (int i = 0; i < nCols; ++i) {
  481.             setEntry(row, i, array[i]);
  482.         }
  483.     }

  484.     /** {@inheritDoc} */
  485.     @Override
  486.     public double[] getColumn(final int column) throws MathIllegalArgumentException {
  487.         MatrixUtils.checkColumnIndex(this, column);
  488.         final int nRows = getRowDimension();
  489.         final double[] out = new double[nRows];
  490.         for (int i = 0; i < nRows; ++i) {
  491.             out[i] = getEntry(i, column);
  492.         }

  493.         return out;
  494.     }

  495.     /** {@inheritDoc} */
  496.     @Override
  497.     public void setColumn(final int column, final double[] array)
  498.         throws MathIllegalArgumentException {
  499.         MatrixUtils.checkColumnIndex(this, column);
  500.         final int nRows = getRowDimension();
  501.         if (array.length != nRows) {
  502.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
  503.                                                    array.length, 1,
  504.                                                    nRows, 1);
  505.         }
  506.         for (int i = 0; i < nRows; ++i) {
  507.             setEntry(i, column, array[i]);
  508.         }
  509.     }

  510.     /** {@inheritDoc} */
  511.     @Override
  512.     public void addToEntry(int row, int column, double increment)
  513.         throws MathIllegalArgumentException {
  514.         MatrixUtils.checkMatrixIndex(this, row, column);
  515.         setEntry(row, column, getEntry(row, column) + increment);
  516.     }

  517.     /** {@inheritDoc} */
  518.     @Override
  519.     public void multiplyEntry(int row, int column, double factor)
  520.         throws MathIllegalArgumentException {
  521.         MatrixUtils.checkMatrixIndex(this, row, column);
  522.         setEntry(row, column, getEntry(row, column) * factor);
  523.     }

  524.     /** {@inheritDoc} */
  525.     @Override
  526.     public RealMatrix transpose() {
  527.         final int nRows = getRowDimension();
  528.         final int nCols = getColumnDimension();
  529.         final RealMatrix out = createMatrix(nCols, nRows);
  530.         walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {

  531.             /** {@inheritDoc} */
  532.             @Override
  533.             public void visit(final int row, final int column, final double value) {
  534.                 out.setEntry(column, row, value);
  535.             }

  536.         });

  537.         return out;
  538.     }

  539.     /** {@inheritDoc} */
  540.     @Override
  541.     public boolean isSquare() {
  542.         return getColumnDimension() == getRowDimension();
  543.     }

  544.     /**
  545.      * Returns the number of rows of this matrix.
  546.      *
  547.      * @return the number of rows.
  548.      */
  549.     @Override
  550.     public abstract int getRowDimension();

  551.     /**
  552.      * Returns the number of columns of this matrix.
  553.      *
  554.      * @return the number of columns.
  555.      */
  556.     @Override
  557.     public abstract int getColumnDimension();

  558.     /** {@inheritDoc} */
  559.     @Override
  560.     public double getTrace() throws MathIllegalArgumentException {
  561.         final int nRows = getRowDimension();
  562.         final int nCols = getColumnDimension();
  563.         if (nRows != nCols) {
  564.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_MATRIX,
  565.                                                    nRows, nCols);
  566.        }
  567.         double trace = 0;
  568.         for (int i = 0; i < nRows; ++i) {
  569.             trace += getEntry(i, i);
  570.         }
  571.         return trace;
  572.     }

  573.     /** {@inheritDoc} */
  574.     @Override
  575.     public double[] operate(final double[] v)
  576.         throws MathIllegalArgumentException {
  577.         final int nRows = getRowDimension();
  578.         final int nCols = getColumnDimension();
  579.         if (v.length != nCols) {
  580.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  581.                                                    v.length, nCols);
  582.         }

  583.         final double[] out = new double[nRows];
  584.         for (int row = 0; row < nRows; ++row) {
  585.             double sum = 0;
  586.             for (int i = 0; i < nCols; ++i) {
  587.                 sum += getEntry(row, i) * v[i];
  588.             }
  589.             out[row] = sum;
  590.         }

  591.         return out;
  592.     }

  593.     /** {@inheritDoc} */
  594.     @Override
  595.     public RealVector operate(final RealVector v)
  596.         throws MathIllegalArgumentException {
  597.         if (v instanceof ArrayRealVector) {
  598.             return new ArrayRealVector(operate(((ArrayRealVector) v).getDataRef()), false);
  599.         } else {
  600.             final int nRows = getRowDimension();
  601.             final int nCols = getColumnDimension();
  602.             if (v.getDimension() != nCols) {
  603.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  604.                                                        v.getDimension(), nCols);
  605.             }

  606.             final double[] out = new double[nRows];
  607.             for (int row = 0; row < nRows; ++row) {
  608.                 double sum = 0;
  609.                 for (int i = 0; i < nCols; ++i) {
  610.                     sum += getEntry(row, i) * v.getEntry(i);
  611.                 }
  612.                 out[row] = sum;
  613.             }

  614.             return new ArrayRealVector(out, false);
  615.         }
  616.     }

  617.     /** {@inheritDoc} */
  618.     @Override
  619.     public double[] preMultiply(final double[] v) throws MathIllegalArgumentException {

  620.         final int nRows = getRowDimension();
  621.         final int nCols = getColumnDimension();
  622.         if (v.length != nRows) {
  623.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  624.                                                    v.length, nRows);
  625.         }

  626.         final double[] out = new double[nCols];
  627.         for (int col = 0; col < nCols; ++col) {
  628.             double sum = 0;
  629.             for (int i = 0; i < nRows; ++i) {
  630.                 sum += getEntry(i, col) * v[i];
  631.             }
  632.             out[col] = sum;
  633.         }

  634.         return out;
  635.     }

  636.     /** {@inheritDoc} */
  637.     @Override
  638.     public RealVector preMultiply(final RealVector v) throws MathIllegalArgumentException {
  639.         if (v instanceof ArrayRealVector) {
  640.             return new ArrayRealVector(preMultiply(((ArrayRealVector) v).getDataRef()), false);
  641.         } else {

  642.             final int nRows = getRowDimension();
  643.             final int nCols = getColumnDimension();
  644.             if (v.getDimension() != nRows) {
  645.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  646.                                                        v.getDimension(), nRows);
  647.             }

  648.             final double[] out = new double[nCols];
  649.             for (int col = 0; col < nCols; ++col) {
  650.                 double sum = 0;
  651.                 for (int i = 0; i < nRows; ++i) {
  652.                     sum += getEntry(i, col) * v.getEntry(i);
  653.                 }
  654.                 out[col] = sum;
  655.             }

  656.             return new ArrayRealVector(out, false);
  657.         }
  658.     }

  659.     /** {@inheritDoc} */
  660.     @Override
  661.     public double walkInRowOrder(final RealMatrixChangingVisitor visitor) {
  662.         final int rows    = getRowDimension();
  663.         final int columns = getColumnDimension();
  664.         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
  665.         for (int row = 0; row < rows; ++row) {
  666.             for (int column = 0; column < columns; ++column) {
  667.                 final double oldValue = getEntry(row, column);
  668.                 final double newValue = visitor.visit(row, column, oldValue);
  669.                 setEntry(row, column, newValue);
  670.             }
  671.         }
  672.         return visitor.end();
  673.     }

  674.     /** {@inheritDoc} */
  675.     @Override
  676.     public double walkInRowOrder(final RealMatrixPreservingVisitor visitor) {
  677.         final int rows    = getRowDimension();
  678.         final int columns = getColumnDimension();
  679.         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
  680.         for (int row = 0; row < rows; ++row) {
  681.             for (int column = 0; column < columns; ++column) {
  682.                 visitor.visit(row, column, getEntry(row, column));
  683.             }
  684.         }
  685.         return visitor.end();
  686.     }

  687.     /** {@inheritDoc} */
  688.     @Override
  689.     public double walkInRowOrder(final RealMatrixChangingVisitor visitor,
  690.                                  final int startRow, final int endRow,
  691.                                  final int startColumn, final int endColumn)
  692.         throws MathIllegalArgumentException {
  693.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
  694.         visitor.start(getRowDimension(), getColumnDimension(),
  695.                       startRow, endRow, startColumn, endColumn);
  696.         for (int row = startRow; row <= endRow; ++row) {
  697.             for (int column = startColumn; column <= endColumn; ++column) {
  698.                 final double oldValue = getEntry(row, column);
  699.                 final double newValue = visitor.visit(row, column, oldValue);
  700.                 setEntry(row, column, newValue);
  701.             }
  702.         }
  703.         return visitor.end();
  704.     }

  705.     /** {@inheritDoc} */
  706.     @Override
  707.     public double walkInRowOrder(final RealMatrixPreservingVisitor visitor,
  708.                                  final int startRow, final int endRow,
  709.                                  final int startColumn, final int endColumn)
  710.         throws MathIllegalArgumentException {
  711.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
  712.         visitor.start(getRowDimension(), getColumnDimension(),
  713.                       startRow, endRow, startColumn, endColumn);
  714.         for (int row = startRow; row <= endRow; ++row) {
  715.             for (int column = startColumn; column <= endColumn; ++column) {
  716.                 visitor.visit(row, column, getEntry(row, column));
  717.             }
  718.         }
  719.         return visitor.end();
  720.     }

  721.     /** {@inheritDoc} */
  722.     @Override
  723.     public double walkInColumnOrder(final RealMatrixChangingVisitor visitor) {
  724.         final int rows    = getRowDimension();
  725.         final int columns = getColumnDimension();
  726.         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
  727.         for (int column = 0; column < columns; ++column) {
  728.             for (int row = 0; row < rows; ++row) {
  729.                 final double oldValue = getEntry(row, column);
  730.                 final double newValue = visitor.visit(row, column, oldValue);
  731.                 setEntry(row, column, newValue);
  732.             }
  733.         }
  734.         return visitor.end();
  735.     }

  736.     /** {@inheritDoc} */
  737.     @Override
  738.     public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor) {
  739.         final int rows    = getRowDimension();
  740.         final int columns = getColumnDimension();
  741.         visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
  742.         for (int column = 0; column < columns; ++column) {
  743.             for (int row = 0; row < rows; ++row) {
  744.                 visitor.visit(row, column, getEntry(row, column));
  745.             }
  746.         }
  747.         return visitor.end();
  748.     }

  749.     /** {@inheritDoc} */
  750.     @Override
  751.     public double walkInColumnOrder(final RealMatrixChangingVisitor visitor,
  752.                                     final int startRow, final int endRow,
  753.                                     final int startColumn, final int endColumn)
  754.         throws MathIllegalArgumentException {
  755.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
  756.         visitor.start(getRowDimension(), getColumnDimension(),
  757.                       startRow, endRow, startColumn, endColumn);
  758.         for (int column = startColumn; column <= endColumn; ++column) {
  759.             for (int row = startRow; row <= endRow; ++row) {
  760.                 final double oldValue = getEntry(row, column);
  761.                 final double newValue = visitor.visit(row, column, oldValue);
  762.                 setEntry(row, column, newValue);
  763.             }
  764.         }
  765.         return visitor.end();
  766.     }

  767.     /** {@inheritDoc} */
  768.     @Override
  769.     public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor,
  770.                                     final int startRow, final int endRow,
  771.                                     final int startColumn, final int endColumn)
  772.         throws MathIllegalArgumentException {
  773.         MatrixUtils.checkSubMatrixIndex(this, startRow, endRow, startColumn, endColumn);
  774.         visitor.start(getRowDimension(), getColumnDimension(),
  775.                       startRow, endRow, startColumn, endColumn);
  776.         for (int column = startColumn; column <= endColumn; ++column) {
  777.             for (int row = startRow; row <= endRow; ++row) {
  778.                 visitor.visit(row, column, getEntry(row, column));
  779.             }
  780.         }
  781.         return visitor.end();
  782.     }

  783.     /** {@inheritDoc} */
  784.     @Override
  785.     public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor) {
  786.         return walkInRowOrder(visitor);
  787.     }

  788.     /** {@inheritDoc} */
  789.     @Override
  790.     public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor) {
  791.         return walkInRowOrder(visitor);
  792.     }

  793.     /** {@inheritDoc} */
  794.     @Override
  795.     public double walkInOptimizedOrder(final RealMatrixChangingVisitor visitor,
  796.                                        final int startRow, final int endRow,
  797.                                        final int startColumn,
  798.                                        final int endColumn)
  799.         throws MathIllegalArgumentException {
  800.         return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
  801.     }

  802.     /** {@inheritDoc} */
  803.     @Override
  804.     public double walkInOptimizedOrder(final RealMatrixPreservingVisitor visitor,
  805.                                        final int startRow, final int endRow,
  806.                                        final int startColumn,
  807.                                        final int endColumn)
  808.         throws MathIllegalArgumentException {
  809.         return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
  810.     }

  811.     /**
  812.      * Get a string representation for this matrix.
  813.      * @return a string representation for this matrix
  814.      */
  815.     @Override
  816.     public String toString() {
  817.         final StringBuilder res = new StringBuilder();
  818.         String fullClassName = getClass().getName();
  819.         String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
  820.         res.append(shortClassName).append(DEFAULT_FORMAT.format(this));
  821.         return res.toString();
  822.     }

  823.     /**
  824.      * Returns true iff <code>object</code> is a
  825.      * <code>RealMatrix</code> instance with the same dimensions as this
  826.      * and all corresponding matrix entries are equal.
  827.      *
  828.      * @param object the object to test equality against.
  829.      * @return true if object equals this
  830.      */
  831.     @Override
  832.     public boolean equals(final Object object) {
  833.         if (object == this) {
  834.             return true;
  835.         }
  836.         if (!(object instanceof RealMatrix)) {
  837.             return false;
  838.         }
  839.         RealMatrix m = (RealMatrix) object;
  840.         final int nRows = getRowDimension();
  841.         final int nCols = getColumnDimension();
  842.         if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
  843.             return false;
  844.         }
  845.         for (int row = 0; row < nRows; ++row) {
  846.             for (int col = 0; col < nCols; ++col) {
  847.                 if (getEntry(row, col) != m.getEntry(row, col)) {
  848.                     return false;
  849.                 }
  850.             }
  851.         }
  852.         return true;
  853.     }

  854.     /**
  855.      * Computes a hashcode for the matrix.
  856.      *
  857.      * @return hashcode for matrix
  858.      */
  859.     @Override
  860.     public int hashCode() {
  861.         int ret = 7;
  862.         final int nRows = getRowDimension();
  863.         final int nCols = getColumnDimension();
  864.         ret = ret * 31 + nRows;
  865.         ret = ret * 31 + nCols;
  866.         for (int row = 0; row < nRows; ++row) {
  867.             for (int col = 0; col < nCols; ++col) {
  868.                ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) *
  869.                    MathUtils.hash(getEntry(row, col));
  870.            }
  871.         }
  872.         return ret;
  873.     }


  874.     /*
  875.      * Empty implementations of these methods are provided in order to allow for
  876.      * the use of the @Override tag with Java 1.5.
  877.      */

  878.     /** {@inheritDoc} */
  879.     @Override
  880.     public abstract RealMatrix createMatrix(int rowDimension, int columnDimension)
  881.         throws MathIllegalArgumentException;

  882.     /** {@inheritDoc} */
  883.     @Override
  884.     public abstract RealMatrix copy();

  885.     /** {@inheritDoc} */
  886.     @Override
  887.     public abstract double getEntry(int row, int column)
  888.         throws MathIllegalArgumentException;

  889.     /** {@inheritDoc} */
  890.     @Override
  891.     public abstract void setEntry(int row, int column, double value)
  892.         throws MathIllegalArgumentException;
  893. }