/// <summary> /// Returns <c>this</c> minus <c>m</c>. /// </summary> /// <param name="m">Matrix to be subtracted.</param> /// <returns><c>this - m</c>.</returns> /// <exception cref="MatrixDimensionMismatchException"> if <c>m</c> is not the same /// size as <c>this</c>.</exception> public Array2DRowRealMatrix subtract(Array2DRowRealMatrix m) { MatrixUtils.checkSubtractionCompatible(this, m); int rowCount = getRowDimension(); int columnCount = getColumnDimension(); double[][] outData = new double[rowCount][]; for (int row = 0; row < rowCount; row++) { double[] dataRow = data[row]; double[] mRow = m.data[row]; double[] outDataRow = outData[row]; for (int col = 0; col < columnCount; col++) { outDataRow[col] = dataRow[col] - mRow[col]; } } return(new Array2DRowRealMatrix(outData, false)); }
/// <summary> /// Returns the result of postmultiplying <c>this</c> by <c>m</c>. /// </summary> /// <param name="m">matrix to postmultiply by</param> /// <returns><c>this * m</c></returns> /// <exception cref="DimensionMismatchException"> if /// <c>columnDimension(this) != rowDimension(m)</c></exception> public Array2DRowRealMatrix multiply(Array2DRowRealMatrix m) { MatrixUtils.checkMultiplicationCompatible(this, m); int nRows = this.getRowDimension(); int nCols = m.getColumnDimension(); int nSum = this.getColumnDimension(); double[][] outData = new double[nRows][]; // Will hold a column of "m". double[] mCol = new double[nSum]; double[][] mData = m.data; // Multiply. for (int col = 0; col < nCols; col++) { // Copy all elements of column "col" of "m" so that // will be in contiguous memory. for (int mRow = 0; mRow < nSum; mRow++) { mCol[mRow] = mData[mRow][col]; } for (int row = 0; row < nRows; row++) { double[] dataRow = data[row]; double sum = 0; for (int i = 0; i < nSum; i++) { sum += dataRow[i] * mCol[i]; } outData[row][col] = sum; } } return(new Array2DRowRealMatrix(outData, false)); }
/// <summary> /// Returns the n × n covariance matrix. /// <para>The covariance matrix is V × J × V^T /// where J is the diagonal matrix of the inverse of the squares of /// the singular values.</para> /// </summary> /// <param name="minSingularValue">value below which singular values are ignored /// (a 0 or negative value implies all singular value will be used)</param> /// <returns>covariance matrix</returns> /// <exception cref="IllegalArgumentException"> if minSingularValue is larger than /// the largest singular value, meaning all singular values are ignored</exception> public RealMatrix getCovariance(double minSingularValue) { // get the number of singular values to consider int p = singularValues.Length; int dimension = 0; while (dimension < p && singularValues[dimension] >= minSingularValue) { ++dimension; } if (dimension == 0) { throw new NumberIsTooLargeException <Double, Double>(new LocalizedFormats("TOO_LARGE_CUTOFF_SINGULAR_VALUE"), minSingularValue, singularValues[0], true); } double[][] data = new double[dimension][]; getVT().walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitorAnonymous(data, singularValues), 0, dimension - 1, 0, p - 1); RealMatrix jv = new Array2DRowRealMatrix(data, false); return(jv.transpose().multiply(jv)); }
/// <summary> /// Computes the inverse of the given matrix by splitting it into /// 4 sub-matrices. /// </summary> /// <param name="m">Matrix whose inverse must be computed.</param> /// <param name="splitIndex">Index that determines the "split" line and /// column. /// The element corresponding to this index will part of the /// upper-left sub-matrix.</param> /// <returns>the inverse of <c>m</c>.</returns> /// <exception cref="NonSquareMatrixException"> if <c>m</c> is not square.</exception> public static RealMatrix blockInverse(RealMatrix m, int splitIndex) { int n = m.getRowDimension(); if (m.getColumnDimension() != n) { throw new NonSquareMatrixException(m.getRowDimension(), m.getColumnDimension()); } int splitIndex1 = splitIndex + 1; RealMatrix a = m.getSubMatrix(0, splitIndex, 0, splitIndex); RealMatrix b = m.getSubMatrix(0, splitIndex, splitIndex1, n - 1); RealMatrix c = m.getSubMatrix(splitIndex1, n - 1, 0, splitIndex); RealMatrix d = m.getSubMatrix(splitIndex1, n - 1, splitIndex1, n - 1); SingularValueDecomposition aDec = new SingularValueDecomposition(a); DecompositionSolver aSolver = aDec.getSolver(); if (!aSolver.isNonSingular()) { throw new SingularMatrixException(); } RealMatrix aInv = aSolver.getInverse(); SingularValueDecomposition dDec = new SingularValueDecomposition(d); DecompositionSolver dSolver = dDec.getSolver(); if (!dSolver.isNonSingular()) { throw new SingularMatrixException(); } RealMatrix dInv = dSolver.getInverse(); RealMatrix tmp1 = a.subtract(b.multiply(dInv).multiply(c)); SingularValueDecomposition tmp1Dec = new SingularValueDecomposition(tmp1); DecompositionSolver tmp1Solver = tmp1Dec.getSolver(); if (!tmp1Solver.isNonSingular()) { throw new SingularMatrixException(); } RealMatrix result00 = tmp1Solver.getInverse(); RealMatrix tmp2 = d.subtract(c.multiply(aInv).multiply(b)); SingularValueDecomposition tmp2Dec = new SingularValueDecomposition(tmp2); DecompositionSolver tmp2Solver = tmp2Dec.getSolver(); if (!tmp2Solver.isNonSingular()) { throw new SingularMatrixException(); } RealMatrix result11 = tmp2Solver.getInverse(); RealMatrix result01 = aInv.multiply(b).multiply(result11).scalarMultiply(-1); RealMatrix result10 = dInv.multiply(c).multiply(result00).scalarMultiply(-1); RealMatrix result = new Array2DRowRealMatrix(n, n); result.setSubMatrix(result00.getData(), 0, 0); result.setSubMatrix(result01.getData(), 0, splitIndex1); result.setSubMatrix(result10.getData(), splitIndex1, 0); result.setSubMatrix(result11.getData(), splitIndex1, splitIndex1); return(result); }