1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/* 2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more 3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements. See the NOTICE file distributed with 4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership. 5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0 6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with 7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License. You may obtain a copy of the License at 8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * http://www.apache.org/licenses/LICENSE-2.0 10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software 12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS, 13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and 15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License. 16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.linear; 19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable; 20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.math.BigDecimal; 21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException; 23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats; 24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** 26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Implementation of {@link BigMatrix} using a BigDecimal[][] array to store entries 27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf"> 28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * LU decompostion</a> to support linear system 29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * solution and inverse. 30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The LU decompostion is performed as needed, to support the following operations: <ul> 32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>solve</li> 33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>isSingular</li> 34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>getDeterminant</li> 35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>inverse</li> </ul></p> 36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond* <strong>Usage notes</strong>:<br> 38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul><li> 39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The LU decomposition is stored and reused on subsequent calls. If matrix 40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * data are modified using any of the public setXxx methods, the saved 41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * decomposition is discarded. If data are modified via references to the 42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * underlying array obtained using <code>getDataRef()</code>, then the stored 43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * LU decomposition will not be discarded. In this case, you need to 44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * explicitly invoke <code>LUDecompose()</code> to recompute the decomposition 45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * before using any of the methods above.</li> 46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> 47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * As specified in the {@link BigMatrix} interface, matrix element indexing 48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is 0-based -- e.g., <code>getEntry(0, 0)</code> 49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * returns the element in the first row, first column of the matrix.</li></ul></p> 50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @deprecated as of 2.0, replaced by {@link Array2DRowFieldMatrix} with a {@link 52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * org.apache.commons.math.util.BigReal} parameter 53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1042376 $ $Date: 2010-12-05 16:54:55 +0100 (dim. 05 déc. 2010) $ 54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond@Deprecated 56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class BigMatrixImpl implements BigMatrix, Serializable { 57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** BigDecimal 0 */ 59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond static final BigDecimal ZERO = new BigDecimal(0); 60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** BigDecimal 1 */ 62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond static final BigDecimal ONE = new BigDecimal(1); 63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Bound to determine effective singularity in LU decomposition */ 65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final BigDecimal TOO_SMALL = new BigDecimal(10E-12); 66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Serialization id */ 68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final long serialVersionUID = -1011428905656140431L; 69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Entries of the matrix */ 71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected BigDecimal data[][] = null; 72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Entries of cached LU decomposition. 74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * All updates to data (other than luDecompose()) *must* set this to null 75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected BigDecimal lu[][] = null; 77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Permutation associated with LU decomposition */ 79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected int[] permutation = null; 80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Parity of the permutation associated with the LU decomposition */ 82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected int parity = 1; 83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Rounding mode for divisions **/ 85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int roundingMode = BigDecimal.ROUND_HALF_UP; 86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /*** BigDecimal scale ***/ 88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int scale = 64; 89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Creates a matrix with no data 92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl() { 94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix with the supplied row and column dimensions. 98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param rowDimension the number of rows in the new matrix 100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param columnDimension the number of columns in the new matrix 101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if row or column dimension is not 102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * positive 103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(int rowDimension, int columnDimension) { 105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (rowDimension < 1 ) { 106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.INSUFFICIENT_DIMENSION, rowDimension, 1); 108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (columnDimension < 1) { 110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.INSUFFICIENT_DIMENSION, columnDimension, 1); 112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = new BigDecimal[rowDimension][columnDimension]; 114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix using <code>d</code> as the underlying 119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * data array. 120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The input array is copied, not referenced. This constructor has 121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the same effect as calling {@link #BigMatrixImpl(BigDecimal[][], boolean)} 122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * with the second argument set to <code>true</code>.</p> 123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d data for new matrix 125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>d</code> is not rectangular 126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (not all rows have the same length) or empty 127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if <code>d</code> is null 128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(BigDecimal[][] d) { 130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.copyIn(d); 131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix using the input array as the underlying 136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * data array. 137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>If an array is built specially in order to be embedded in a 138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * BigMatrix and not used directly, the <code>copyArray</code> may be 139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * set to <code>false</code. This will prevent the copying and improve 140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * performance as no new array will be built and no data will be copied.</p> 141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d data for new matrix 142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param copyArray if true, the input array will be copied, otherwise 143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * it will be referenced 144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>d</code> is not rectangular 145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (not all rows have the same length) or empty 146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if <code>d</code> is null 147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see #BigMatrixImpl(BigDecimal[][]) 148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(BigDecimal[][] d, boolean copyArray) { 150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (copyArray) { 151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond copyIn(d); 152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (d == null) { 154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new NullPointerException(); 155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = d.length; 157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nRows == 0) { 158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = d[0].length; 162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nCols == 0) { 163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int r = 1; r < nRows; r++) { 166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (d[r].length != nCols) { 167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nCols, d[r].length); 170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = d; 173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix using <code>d</code> as the underlying 179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * data array. 180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Since the underlying array will hold <code>BigDecimal</code> 181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * instances, it will be created.</p> 182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d data for new matrix 184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>d</code> is not rectangular 185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (not all rows have the same length) or empty 186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if <code>d</code> is null 187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(double[][] d) { 189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = d.length; 190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nRows == 0) { 191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = d[0].length; 195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nCols == 0) { 196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 1; row < nRows; row++) { 199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (d[row].length != nCols) { 200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nCols, d[row].length); 203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.copyIn(d); 206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix using the values represented by the strings in 211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>d</code> as the underlying data array. 212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d data for new matrix 214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>d</code> is not rectangular 215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (not all rows have the same length) or empty 216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if <code>d</code> is null 217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(String[][] d) { 219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = d.length; 220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nRows == 0) { 221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = d[0].length; 225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nCols == 0) { 226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 1; row < nRows; row++) { 229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (d[row].length != nCols) { 230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nCols, d[row].length); 233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.copyIn(d); 236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new (column) BigMatrix using <code>v</code> as the 241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * data for the unique column of the <code>v.length x 1</code> matrix 242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * created. 243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The input array is copied, not referenced.</p> 245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param v column vector holding data for new matrix 247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl(BigDecimal[] v) { 249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = v.length; 250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = new BigDecimal[nRows][1]; 251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data[row][0] = v[row]; 253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a new BigMatrix which is a copy of this. 258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the cloned matrix 260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix copy() { 262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(this.copyOut(), false); 263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Compute the sum of this and <code>m</code>. 267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to be added 269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this + m 270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if m is not the same size as this 271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix add(BigMatrix m) throws IllegalArgumentException { 273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return add((BigMatrixImpl) m); 275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ClassCastException cce) { 276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkAdditionCompatible(this, m); 279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].add(m.getEntry(row, col)); 288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Compute the sum of this and <code>m</code>. 296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to be added 298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this + m 299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if m is not the same size as this 300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl add(BigMatrixImpl m) throws IllegalArgumentException { 302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkAdditionCompatible(this, m); 305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] mRow = m.data[row]; 312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].add(mRow[col]); 315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Compute this minus <code>m</code>. 322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to be subtracted 324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this + m 325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if m is not the same size as this 326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix subtract(BigMatrix m) throws IllegalArgumentException { 328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return subtract((BigMatrixImpl) m); 330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ClassCastException cce) { 331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkSubtractionCompatible(this, m); 334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].subtract(getEntry(row, col)); 343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Compute this minus <code>m</code>. 351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to be subtracted 353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this + m 354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if m is not the same size as this 355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl subtract(BigMatrixImpl m) throws IllegalArgumentException { 357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkSubtractionCompatible(this, m); 360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] mRow = m.data[row]; 367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].subtract(mRow[col]); 370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of adding d to each entry of this. 377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d value to be added to each entry 379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return d + this 380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix scalarAdd(BigDecimal d) { 382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].add(d); 390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of multiplying each entry of this by <code>d</code> 397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param d value to multiply all entries by 398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return d * this 399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix scalarMultiply(BigDecimal d) { 401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int rowCount = getRowDimension(); 402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int columnCount = getColumnDimension(); 403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount]; 404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < rowCount; row++) { 405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < columnCount; col++) { 408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = dataRow[col].multiply(d); 409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of postmultiplying this by <code>m</code>. 416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to postmultiply by 417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this*m 418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException 419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if columnDimension(this) != rowDimension(m) 420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix multiply(BigMatrix m) throws IllegalArgumentException { 422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return multiply((BigMatrixImpl) m); 424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ClassCastException cce) { 425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkMultiplicationCompatible(this, m); 428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = m.getColumnDimension(); 431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nSum = this.getColumnDimension(); 432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[nRows][nCols]; 433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nSum; i++) { 439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.add(dataRow[i].multiply(m.getEntry(i, col))); 440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = sum; 442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of postmultiplying this by <code>m</code>. 450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to postmultiply by 451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this*m 452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException 453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if columnDimension(this) != rowDimension(m) 454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrixImpl multiply(BigMatrixImpl m) throws IllegalArgumentException { 456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // safety check 458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkMultiplicationCompatible(this, m); 459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = m.getColumnDimension(); 462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nSum = this.getColumnDimension(); 463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[nRows][nCols]; 464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] outDataRow = outData[row]; 467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nSum; i++) { 470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.add(dataRow[i].multiply(m.data[i][col])); 471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outDataRow[col] = sum; 473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result premultiplying this by <code>m</code>. 480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param m matrix to premultiply by 481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return m * this 482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException 483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if rowDimension(this) != columnDimension(m) 484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix preMultiply(BigMatrix m) throws IllegalArgumentException { 486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return m.multiply(this); 487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns matrix entries as a two-dimensional array. 491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Makes a fresh copy of the underlying data.</p> 493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return 2-dimensional array of entries 495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[][] getData() { 497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return copyOut(); 498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns matrix entries as a two-dimensional array. 502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Makes a fresh copy of the underlying data converted to 504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>double</code> values.</p> 505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return 2-dimensional array of entries 507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[][] getDataAsDoubleArray() { 509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = getRowDimension(); 510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = getColumnDimension(); 511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double d[][] = new double[nRows][nCols]; 512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nCols; j++) { 514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond d[i][j] = data[i][j].doubleValue(); 515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return d; 518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a reference to the underlying data array. 522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Does not make a fresh copy of the underlying data.</p> 524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return 2-dimensional array of entries 526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[][] getDataRef() { 528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return data; 529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /*** 532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Gets the rounding mode for division operations 533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The default is {@link java.math.BigDecimal#ROUND_HALF_UP} 534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see BigDecimal 535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the rounding mode. 536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getRoundingMode() { 538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return roundingMode; 539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /*** 542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Sets the rounding mode for decimal divisions. 543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see BigDecimal 544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param roundingMode rounding mode for decimal divisions 545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setRoundingMode(int roundingMode) { 547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.roundingMode = roundingMode; 548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /*** 551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Sets the scale for division operations. 552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The default is 64 553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see BigDecimal 554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the scale 555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getScale() { 557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return scale; 558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /*** 561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Sets the scale for division operations. 562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see BigDecimal 563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param scale scale for division operations 564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setScale(int scale) { 566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.scale = scale; 567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the <a href="http://mathworld.wolfram.com/MaximumAbsoluteRowSumNorm.html"> 571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * maximum absolute row sum norm</a> of the matrix. 572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return norm 574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal getNorm() { 576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal maxColSum = ZERO; 577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < this.getColumnDimension(); col++) { 578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < this.getRowDimension(); row++) { 580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.add(data[row][col].abs()); 581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond maxColSum = maxColSum.max(sum); 583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return maxColSum; 585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Gets a submatrix. Rows and columns are indicated 589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * counting from 0 to n-1. 590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param startRow Initial row index 592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param endRow Final row index 593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param startColumn Initial column index 594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param endColumn Final column index 595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return The subMatrix containing the data of the 596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * specified rows and columns 597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @exception MatrixIndexException if row or column selections are not valid 598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix getSubMatrix(int startRow, int endRow, 600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int startColumn, int endColumn) 601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws MatrixIndexException { 602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, startRow); 604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, endRow); 605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (startRow > endRow) { 606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new MatrixIndexException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, 607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond startRow, endRow); 608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, startColumn); 611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, endColumn); 612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (startColumn > endColumn) { 613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new MatrixIndexException(LocalizedFormats.INITIAL_COLUMN_AFTER_FINAL_COLUMN, 614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond startColumn, endColumn); 615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] subMatrixData = 618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond new BigDecimal[endRow - startRow + 1][endColumn - startColumn + 1]; 619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = startRow; i <= endRow; i++) { 620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(data[i], startColumn, 621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond subMatrixData[i - startRow], 0, 622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond endColumn - startColumn + 1); 623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(subMatrixData, false); 626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Gets a submatrix. Rows and columns are indicated 631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * counting from 0 to n-1. 632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param selectedRows Array of row indices must be non-empty 634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param selectedColumns Array of column indices must be non-empty 635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return The subMatrix containing the data in the 636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * specified rows and columns 637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @exception MatrixIndexException if supplied row or column index arrays 638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * are not valid 639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix getSubMatrix(int[] selectedRows, int[] selectedColumns) 641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws MatrixIndexException { 642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (selectedRows.length * selectedColumns.length == 0) { 644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (selectedRows.length == 0) { 645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_ROW_INDEX_ARRAY); 646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new MatrixIndexException(LocalizedFormats.EMPTY_SELECTED_COLUMN_INDEX_ARRAY); 648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] subMatrixData = 651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond new BigDecimal[selectedRows.length][selectedColumns.length]; 652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < selectedRows.length; i++) { 654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] subI = subMatrixData[i]; 655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataSelectedI = data[selectedRows[i]]; 656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < selectedColumns.length; j++) { 657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond subI[j] = dataSelectedI[selectedColumns[j]]; 658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ArrayIndexOutOfBoundsException e) { 661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // we redo the loop with checks enabled 662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // in order to generate an appropriate message 663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (final int row : selectedRows) { 664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, row); 665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (final int column : selectedColumns) { 667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, column); 668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(subMatrixData, false); 671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Replace the submatrix starting at <code>row, column</code> using data in 675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the input <code>subMatrix</code> array. Indexes are 0-based. 676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Example:<br> 678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Starting with <pre> 679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1 2 3 4 680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 5 6 7 8 681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 9 0 1 2 682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </pre> 683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and <code>subMatrix = {{3, 4} {5,6}}</code>, invoking 684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>setSubMatrix(subMatrix,1,1))</code> will result in <pre> 685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1 2 3 4 686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 5 3 4 8 687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 9 5 6 2 688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </pre></p> 689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param subMatrix array containing the submatrix replacement data 691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row row coordinate of the top, left element to be replaced 692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param column column coordinate of the top, left element to be replaced 693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if subMatrix does not fit into this 694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * matrix from element in (row, column) 695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>subMatrix</code> is not rectangular 696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (not all rows have the same length) or empty 697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if <code>subMatrix</code> is null 698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 1.1 699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setSubMatrix(BigDecimal[][] subMatrix, int row, int column) 701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws MatrixIndexException { 702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = subMatrix.length; 704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nRows == 0) { 705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_ROW); 706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = subMatrix[0].length; 709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nCols == 0) { 710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.AT_LEAST_ONE_COLUMN); 711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int r = 1; r < nRows; r++) { 714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (subMatrix[r].length != nCols) { 715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.DIFFERENT_ROWS_LENGTHS, 717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond nCols, subMatrix[r].length); 718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (data == null) { 722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (row > 0) { 723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalStateException( 724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.FIRST_ROWS_NOT_INITIALIZED_YET, 725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond row); 726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (column > 0) { 728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalStateException( 729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.FIRST_COLUMNS_NOT_INITIALIZED_YET, 730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond column); 731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = new BigDecimal[nRows][nCols]; 733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(subMatrix, 0, data, 0, subMatrix.length); 734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, row); 736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, column); 737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, nRows + row - 1); 738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, nCols + column - 1); 739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(subMatrix[i], 0, data[row + i], column, nCols); 742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in row number <code>row</code> 750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * as a row matrix. Row indices start at 0. 751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row the row to be fetched 753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return row matrix 754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified row index is invalid 755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix getRowMatrix(int row) throws MatrixIndexException { 757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, row); 758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int ncols = this.getColumnDimension(); 759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] out = new BigDecimal[1][ncols]; 760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(data[row], 0, out[0], 0, ncols); 761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(out, false); 762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in column number <code>column</code> 766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * as a column matrix. Column indices start at 0. 767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param column the column to be fetched 769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return column matrix 770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified column index is invalid 771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix getColumnMatrix(int column) throws MatrixIndexException { 773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, column); 774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] out = new BigDecimal[nRows][1]; 776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[row][0] = data[row][column]; 778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(out, false); 780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in row number <code>row</code> as an array. 784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Row indices start at 0. A <code>MatrixIndexException</code> is thrown 786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * unless <code>0 <= row < rowDimension.</code></p> 787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row the row to be fetched 789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array of entries in the row 790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified row index is not valid 791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] getRow(int row) throws MatrixIndexException { 793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, row); 794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int ncols = this.getColumnDimension(); 795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] out = new BigDecimal[ncols]; 796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(data[row], 0, out, 0, ncols); 797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in row number <code>row</code> as an array 802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * of double values. 803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Row indices start at 0. A <code>MatrixIndexException</code> is thrown 805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * unless <code>0 <= row < rowDimension.</code></p> 806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row the row to be fetched 808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array of entries in the row 809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified row index is not valid 810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[] getRowAsDoubleArray(int row) throws MatrixIndexException { 812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkRowIndex(this, row); 813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int ncols = this.getColumnDimension(); 814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] out = new double[ncols]; 815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i=0;i<ncols;i++) { 816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[i] = data[row][i].doubleValue(); 817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in column number <code>col</code> as an array. 823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Column indices start at 0. A <code>MatrixIndexException</code> is thrown 825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * unless <code>0 <= column < columnDimension.</code></p> 826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param col the column to be fetched 828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array of entries in the column 829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified column index is not valid 830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] getColumn(int col) throws MatrixIndexException { 832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, col); 833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] out = new BigDecimal[nRows]; 835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[i] = data[i][col]; 837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entries in column number <code>col</code> as an array 843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * of double values. 844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Column indices start at 0. A <code>MatrixIndexException</code> is thrown 846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * unless <code>0 <= column < columnDimension.</code></p> 847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param col the column to be fetched 849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array of entries in the column 850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the specified column index is not valid 851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[] getColumnAsDoubleArray(int col) throws MatrixIndexException { 853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond MatrixUtils.checkColumnIndex(this, col); 854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nrows = this.getRowDimension(); 855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] out = new double[nrows]; 856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i=0;i<nrows;i++) { 857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[i] = data[i][col].doubleValue(); 858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entry in the specified row and column. 864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Row and column indices start at 0 and must satisfy 866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li><code>0 <= row < rowDimension</code></li> 868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li><code> 0 <= column < columnDimension</code></li> 869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul> 870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * otherwise a <code>MatrixIndexException</code> is thrown.</p> 871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row row location of entry to be fetched 873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param column column location of entry to be fetched 874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return matrix entry in row,column 875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the row or column index is not valid 876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal getEntry(int row, int column) 878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws MatrixIndexException { 879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return data[row][column]; 881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ArrayIndexOutOfBoundsException e) { 882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new MatrixIndexException( 883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.NO_SUCH_MATRIX_ENTRY, 884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond row, column, getRowDimension(), getColumnDimension()); 885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the entry in the specified row and column as a double. 890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Row and column indices start at 0 and must satisfy 892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li><code>0 <= row < rowDimension</code></li> 894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li><code> 0 <= column < columnDimension</code></li> 895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul> 896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * otherwise a <code>MatrixIndexException</code> is thrown.</p> 897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param row row location of entry to be fetched 899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param column column location of entry to be fetched 900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return matrix entry in row,column 901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws MatrixIndexException if the row 902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * or column index is not valid 903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getEntryAsDouble(int row, int column) throws MatrixIndexException { 905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return getEntry(row,column).doubleValue(); 906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the transpose matrix. 910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return transpose matrix 912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix transpose() { 914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = this.getColumnDimension(); 916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] outData = new BigDecimal[nCols][nRows]; 917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond outData[col][row] = dataRow[col]; 921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(outData, false); 924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the inverse matrix if this matrix is invertible. 928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return inverse matrix 930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if this is not invertible 931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix inverse() throws InvalidMatrixException { 933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return solve(MatrixUtils.createBigIdentityMatrix(getRowDimension())); 934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the determinant of this matrix. 938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return determinant 940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if matrix is not square 941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal getDeterminant() throws InvalidMatrixException { 943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (!isSquare()) { 944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new NonSquareMatrixException(getRowDimension(), getColumnDimension()); 945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (isSingular()) { // note: this has side effect of attempting LU decomp if lu == null 947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return ZERO; 948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal det = (parity == 1) ? ONE : ONE.negate(); 950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < getRowDimension(); i++) { 951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond det = det.multiply(lu[i][i]); 952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return det; 954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Is this a square matrix? 959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return true if the matrix is square (rowDimension = columnDimension) 960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public boolean isSquare() { 962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return getColumnDimension() == getRowDimension(); 963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Is this a singular matrix? 967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return true if the matrix is singular 968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public boolean isSingular() { 970dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (lu == null) { 971dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 972dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond luDecompose(); 973dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return false; 974dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (InvalidMatrixException ex) { 975dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return true; 976dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 977dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { // LU decomp must have been successfully performed 978dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return false; // so the matrix is not singular 979dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 980dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 981dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 982dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 983dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the number of rows in the matrix. 984dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 985dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return rowDimension 986dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 987dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getRowDimension() { 988dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return data.length; 989dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 990dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 991dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 992dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the number of columns in the matrix. 993dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 994dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return columnDimension 995dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 996dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getColumnDimension() { 997dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return data[0].length; 998dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 999dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1000dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1001dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the <a href="http://mathworld.wolfram.com/MatrixTrace.html"> 1002dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * trace</a> of the matrix (the sum of the elements on the main diagonal). 1003dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1004dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return trace 1005dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1006dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if this matrix is not square. 1007dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1008dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal getTrace() throws IllegalArgumentException { 1009dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (!isSquare()) { 1010dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new NonSquareMatrixException(getRowDimension(), getColumnDimension()); 1011dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1012dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal trace = data[0][0]; 1013dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 1; i < this.getRowDimension(); i++) { 1014dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond trace = trace.add(data[i][i]); 1015dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1016dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return trace; 1017dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1018dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1019dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1020dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of multiplying this by the vector <code>v</code>. 1021dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1022dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param v the vector to operate on 1023dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this*v 1024dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if columnDimension != v.size() 1025dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1026dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] operate(BigDecimal[] v) throws IllegalArgumentException { 1027dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (v.length != getColumnDimension()) { 1028dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 1029dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.VECTOR_LENGTH_MISMATCH, 1030dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond v.length, getColumnDimension() ); 1031dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1032dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 1033dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = this.getColumnDimension(); 1034dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] out = new BigDecimal[nRows]; 1035dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 1036dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 1037dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nCols; i++) { 1038dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.add(data[row][i].multiply(v[i])); 1039dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1040dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[row] = sum; 1041dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1042dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 1043dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1044dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1045dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1046dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of multiplying this by the vector <code>v</code>. 1047dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1048dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param v the vector to operate on 1049dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return this*v 1050dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if columnDimension != v.size() 1051dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1052dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] operate(double[] v) throws IllegalArgumentException { 1053dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal bd[] = new BigDecimal[v.length]; 1054dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < bd.length; i++) { 1055dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bd[i] = new BigDecimal(v[i]); 1056dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1057dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return operate(bd); 1058dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1059dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1060dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1061dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the (row) vector result of premultiplying this by the vector <code>v</code>. 1062dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1063dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param v the row vector to premultiply by 1064dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return v*this 1065dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if rowDimension != v.size() 1066dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1067dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] preMultiply(BigDecimal[] v) throws IllegalArgumentException { 1068dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 1069dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (v.length != nRows) { 1070dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 1071dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.VECTOR_LENGTH_MISMATCH, 1072dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond v.length, nRows ); 1073dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1074dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = this.getColumnDimension(); 1075dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] out = new BigDecimal[nCols]; 1076dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 1077dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 1078dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 1079dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.add(data[i][col].multiply(v[i])); 1080dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1081dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[col] = sum; 1082dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1083dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 1084dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1085dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1086dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1087dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a matrix of (column) solution vectors for linear systems with 1088dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * coefficient matrix = this and constant vectors = columns of 1089dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>b</code>. 1090dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1091dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param b array of constants forming RHS of linear systems to 1092dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to solve 1093dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return solution array 1094dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if this.rowDimension != row dimension 1095dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if this matrix is not square or is singular 1096dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1097dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] solve(BigDecimal[] b) throws IllegalArgumentException, InvalidMatrixException { 1098dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 1099dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (b.length != nRows) { 1100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 1101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.VECTOR_LENGTH_MISMATCH, 1102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond b.length, nRows); 1103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigMatrix bMatrix = new BigMatrixImpl(b); 1105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] solution = ((BigMatrixImpl) (solve(bMatrix))).getDataRef(); 1106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] out = new BigDecimal[nRows]; 1107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 1108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond out[row] = solution[row][0]; 1109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 1111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a matrix of (column) solution vectors for linear systems with 1115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * coefficient matrix = this and constant vectors = columns of 1116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>b</code>. 1117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param b array of constants forming RHS of linear systems to 1119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to solve 1120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return solution array 1121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if this.rowDimension != row dimension 1122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if this matrix is not square or is singular 1123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigDecimal[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException { 1125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal bd[] = new BigDecimal[b.length]; 1126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < bd.length; i++) { 1127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bd[i] = new BigDecimal(b[i]); 1128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return solve(bd); 1130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a matrix of (column) solution vectors for linear systems with 1134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * coefficient matrix = this and constant vectors = columns of 1135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>b</code>. 1136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param b matrix of constant vectors forming RHS of linear systems to 1138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to solve 1139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return matrix of solution vectors 1140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if this.rowDimension != row dimension 1141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if this matrix is not square or is singular 1142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public BigMatrix solve(BigMatrix b) throws IllegalArgumentException, InvalidMatrixException { 1144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (b.getRowDimension() != getRowDimension()) { 1145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 1146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.DIMENSIONS_MISMATCH_2x2, 1147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond b.getRowDimension(), b.getColumnDimension(), getRowDimension(), "n"); 1148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (!isSquare()) { 1150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new NonSquareMatrixException(getRowDimension(), getColumnDimension()); 1151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (this.isSingular()) { // side effect: compute LU decomp 1153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new SingularMatrixException(); 1154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCol = this.getColumnDimension(); 1157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nColB = b.getColumnDimension(); 1158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRowB = b.getRowDimension(); 1159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Apply permutations to b 1161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] bp = new BigDecimal[nRowB][nColB]; 1162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRowB; row++) { 1163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] bpRow = bp[row]; 1164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nColB; col++) { 1165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bpRow[col] = b.getEntry(permutation[row], col); 1166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Solve LY = b 1170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCol; col++) { 1171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = col + 1; i < nCol; i++) { 1172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] bpI = bp[i]; 1173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] luI = lu[i]; 1174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nColB; j++) { 1175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bpI[j] = bpI[j].subtract(bp[col][j].multiply(luI[col])); 1176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Solve UX = Y 1181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = nCol - 1; col >= 0; col--) { 1182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] bpCol = bp[col]; 1183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal luDiag = lu[col][col]; 1184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nColB; j++) { 1185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bpCol[j] = bpCol[j].divide(luDiag, scale, roundingMode); 1186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < col; i++) { 1188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] bpI = bp[i]; 1189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] luI = lu[i]; 1190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nColB; j++) { 1191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond bpI[j] = bpI[j].subtract(bp[col][j].multiply(luI[col])); 1192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(bp, false); 1197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Computes a new 1202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf"> 1203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * LU decompostion</a> for this matrix, storing the result for use by other methods. 1204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <strong>Implementation Note</strong>:<br> 1206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Uses <a href="http://www.damtp.cam.ac.uk/user/fdl/people/sd/lectures/nummeth98/linear.htm"> 1207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Crout's algortithm</a>, with partial pivoting.</p> 1208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <strong>Usage Note</strong>:<br> 1210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This method should rarely be invoked directly. Its only use is 1211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to force recomputation of the LU decomposition when changes have been 1212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * made to the underlying data using direct array references. Changes 1213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * made using setXxx methods will trigger recomputation when needed 1214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * automatically.</p> 1215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if the matrix is non-square or singular. 1217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void luDecompose() throws InvalidMatrixException { 1219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 1221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = this.getColumnDimension(); 1222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (nRows != nCols) { 1223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new NonSquareMatrixException(getRowDimension(), getColumnDimension()); 1224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = this.getData(); 1226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Initialize permutation array and parity 1228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond permutation = new int[nRows]; 1229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 1230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond permutation[row] = row; 1231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond parity = 1; 1233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Loop over columns 1235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 1236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal sum = ZERO; 1238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // upper 1240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < col; row++) { 1241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] luRow = lu[row]; 1242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = luRow[col]; 1243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < row; i++) { 1244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.subtract(luRow[i].multiply(lu[i][col])); 1245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond luRow[col] = sum; 1247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // lower 1250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int max = col; // permutation row 1251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal largest = ZERO; 1252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = col; row < nRows; row++) { 1253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] luRow = lu[row]; 1254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = luRow[col]; 1255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < col; i++) { 1256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sum = sum.subtract(luRow[i].multiply(lu[i][col])); 1257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond luRow[col] = sum; 1259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // maintain best permutation choice 1261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (sum.abs().compareTo(largest) == 1) { 1262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond largest = sum.abs(); 1263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond max = row; 1264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Singularity check 1268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (lu[max][col].abs().compareTo(TOO_SMALL) <= 0) { 1269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 1270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new SingularMatrixException(); 1271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Pivot if necessary 1274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (max != col) { 1275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond BigDecimal tmp = ZERO; 1276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nCols; i++) { 1277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond tmp = lu[max][i]; 1278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu[max][i] = lu[col][i]; 1279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu[col][i] = tmp; 1280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int temp = permutation[max]; 1282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond permutation[max] = permutation[col]; 1283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond permutation[col] = temp; 1284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond parity = -parity; 1285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Divide the lower elements by the "winning" diagonal elt. 1288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal luDiag = lu[col][col]; 1289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = col + 1; row < nRows; row++) { 1290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] luRow = lu[row]; 1291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond luRow[col] = luRow[col].divide(luDiag, scale, roundingMode); 1292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Get a string representation for this matrix. 1300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return a string representation for this matrix 1301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 1303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public String toString() { 1304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond StringBuilder res = new StringBuilder(); 1305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append("BigMatrixImpl{"); 1306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (data != null) { 1307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < data.length; i++) { 1308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (i > 0) { 1309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append(","); 1310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append("{"); 1312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < data[0].length; j++) { 1313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (j > 0) { 1314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append(","); 1315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append(data[i][j]); 1317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append("}"); 1319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond res.append("}"); 1322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return res.toString(); 1323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns true iff <code>object</code> is a 1327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>BigMatrixImpl</code> instance with the same dimensions as this 1328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and all corresponding matrix entries are equal. BigDecimal.equals 1329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is used to compare corresponding entries. 1330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param object the object to test equality against. 1332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return true if object equals this 1333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 1335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public boolean equals(Object object) { 1336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (object == this ) { 1337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return true; 1338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (object instanceof BigMatrixImpl == false) { 1340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return false; 1341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigMatrix m = (BigMatrix) object; 1343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = getRowDimension(); 1344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = getColumnDimension(); 1345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) { 1346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return false; 1347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 1349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 1350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 1351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (!dataRow[col].equals(m.getEntry(row, col))) { 1352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return false; 1353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return true; 1357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Computes a hashcode for the matrix. 1361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return hashcode for matrix 1363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 1365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int hashCode() { 1366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int ret = 7; 1367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = getRowDimension(); 1368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = getColumnDimension(); 1369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ret = ret * 31 + nRows; 1370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ret = ret * 31 + nCols; 1371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int row = 0; row < nRows; row++) { 1372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataRow = data[row]; 1373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int col = 0; col < nCols; col++) { 1374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * 1375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond dataRow[col].hashCode(); 1376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return ret; 1379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond //------------------------ Protected methods 1382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the LU decomposition as a BigMatrix. 1385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a fresh copy of the cached LU matrix if this has been computed; 1386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * otherwise the composition is computed and cached for use by other methods. 1387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Since a copy is returned in either case, changes to the returned matrix do not 1388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * affect the LU decomposition property. 1389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The matrix returned is a compact representation of the LU decomposition. 1391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Elements below the main diagonal correspond to entries of the "L" matrix; 1392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * elements on and above the main diagonal correspond to entries of the "U" 1393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * matrix.</p> 1394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Example: <pre> 1396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returned matrix L U 1398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 1 1 0 0 2 3 1 1399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 5 4 6 5 1 0 0 4 6 1400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1 7 8 1 7 1 0 0 8 1401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </pre> 1402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The L and U matrices satisfy the matrix equation LU = permuteRows(this), <br> 1404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * where permuteRows reorders the rows of the matrix to follow the order determined 1405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * by the <a href=#getPermutation()>permutation</a> property.</p> 1406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return LU decomposition matrix 1408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws InvalidMatrixException if the matrix is non-square or singular. 1409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected BigMatrix getLUMatrix() throws InvalidMatrixException { 1411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (lu == null) { 1412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond luDecompose(); 1413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return new BigMatrixImpl(lu); 1415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the permutation associated with the lu decomposition. 1419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The entries of the array represent a permutation of the numbers 0, ... , nRows - 1. 1420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Example: 1422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * permutation = [1, 2, 0] means current 2nd row is first, current third row is second 1423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and current first row is last.</p> 1424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a fresh copy of the array.</p> 1426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the permutation 1428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected int[] getPermutation() { 1430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int[] out = new int[permutation.length]; 1431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(permutation, 0, out, 0, permutation.length); 1432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 1433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond //------------------------ Private methods 1436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns a fresh copy of the underlying data array. 1439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return a copy of the underlying data array. 1441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private BigDecimal[][] copyOut() { 1443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = this.getRowDimension(); 1444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[][] out = new BigDecimal[nRows][this.getColumnDimension()]; 1445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // can't copy 2-d array in one shot, otherwise get row references 1446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 1447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(data[i], 0, out[i], 0, data[i].length); 1448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return out; 1450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Replaces data with a fresh copy of the input array. 1454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 1455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Verifies that the input array is rectangular and non-empty.</p> 1456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param in data to copy in 1458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if input array is emtpy or not 1459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * rectangular 1460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if input array is null 1461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private void copyIn(BigDecimal[][] in) { 1463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setSubMatrix(in,0,0); 1464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Replaces data with a fresh copy of the input array. 1468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param in data to copy in 1470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private void copyIn(double[][] in) { 1472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = in.length; 1473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = in[0].length; 1474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = new BigDecimal[nRows][nCols]; 1475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 1476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataI = data[i]; 1477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double[] inI = in[i]; 1478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nCols; j++) { 1479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond dataI[j] = new BigDecimal(inI[j]); 1480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 1483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 1486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Replaces data with BigDecimals represented by the strings in the input 1487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * array. 1488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 1489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param in data to copy in 1490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 1491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private void copyIn(String[][] in) { 1492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nRows = in.length; 1493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int nCols = in[0].length; 1494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond data = new BigDecimal[nRows][nCols]; 1495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < nRows; i++) { 1496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final BigDecimal[] dataI = data[i]; 1497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final String[] inI = in[i]; 1498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 0; j < nCols; j++) { 1499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond dataI[j] = new BigDecimal(inI[j]); 1500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lu = null; 1503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 1504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 1505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond} 1506