001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math3.linear; 018 019 import java.io.Serializable; 020 import org.apache.commons.math3.exception.DimensionMismatchException; 021 import org.apache.commons.math3.exception.NotStrictlyPositiveException; 022 import org.apache.commons.math3.exception.OutOfRangeException; 023 import org.apache.commons.math3.exception.MathUnsupportedOperationException; 024 025 /** 026 * Implementation of a diagonal matrix. 027 * <br/> 028 * Caveat: This implementation is minimal; it is currently solely aimed 029 * at solving issue MATH-924. In particular many methods just throw 030 * {@code MathUnsupportedOperationException}. 031 * 032 * @version $Id$ 033 */ 034 public class DiagonalMatrix extends AbstractRealMatrix 035 implements Serializable { 036 /** Serializable version identifier. */ 037 private static final long serialVersionUID = 20121229L; 038 /** Entries of the diagonal. */ 039 private final double[] data; 040 041 /** 042 * Creates a matrix with the supplied dimension. 043 * 044 * @param dimension Number of rows and columns in the new matrix. 045 * @throws NotStrictlyPositiveException if the dimension is 046 * not positive. 047 */ 048 public DiagonalMatrix(final int dimension) 049 throws NotStrictlyPositiveException { 050 super(dimension, dimension); 051 data = new double[dimension]; 052 } 053 054 /** 055 * Creates a matrix using the input array as the underlying data. 056 * <br/> 057 * The input array is copied, not referenced. 058 * 059 * @param d Data for the new matrix. 060 */ 061 public DiagonalMatrix(final double[] d) { 062 this(d, true); 063 } 064 065 /** 066 * Creates a matrix using the input array as the underlying data. 067 * <br/> 068 * If an array is created specially in order to be embedded in a 069 * this instance and not used directly, the {@code copyArray} may be 070 * set to {@code false}. 071 * This will prevent the copying and improve performance as no new 072 * array will be built and no data will be copied. 073 * 074 * @param d Data for new matrix. 075 * @param copyArray if {@code true}, the input array will be copied, 076 * otherwise it will be referenced. 077 */ 078 public DiagonalMatrix(final double[] d, final boolean copyArray) { 079 data = copyArray ? d.clone() : d; 080 } 081 082 /** 083 * {@inheritDoc} 084 * 085 * @throws DimensionMismatchException if the requested dimensions are not equal. 086 */ 087 @Override 088 public RealMatrix createMatrix(final int rowDimension, 089 final int columnDimension) 090 throws NotStrictlyPositiveException, 091 DimensionMismatchException { 092 if (rowDimension != columnDimension) { 093 throw new DimensionMismatchException(rowDimension, columnDimension); 094 } 095 096 return new DiagonalMatrix(rowDimension); 097 } 098 099 /** {@inheritDoc} */ 100 @Override 101 public RealMatrix copy() { 102 return new DiagonalMatrix(data); 103 } 104 105 /** 106 * Compute the sum of {@code this} and {@code m}. 107 * 108 * @param m Matrix to be added. 109 * @return {@code this + m}. 110 * @throws MatrixDimensionMismatchException if {@code m} is not the same 111 * size as {@code this}. 112 */ 113 public DiagonalMatrix add(final DiagonalMatrix m) 114 throws MatrixDimensionMismatchException { 115 // Safety check. 116 MatrixUtils.checkAdditionCompatible(this, m); 117 118 final int dim = getRowDimension(); 119 final double[] outData = new double[dim]; 120 for (int i = 0; i < dim; i++) { 121 outData[i] = data[i] + m.data[i]; 122 } 123 124 return new DiagonalMatrix(outData, false); 125 } 126 127 /** 128 * Returns {@code this} minus {@code m}. 129 * 130 * @param m Matrix to be subtracted. 131 * @return {@code this - m} 132 * @throws MatrixDimensionMismatchException if {@code m} is not the same 133 * size as {@code this}. 134 */ 135 public DiagonalMatrix subtract(final DiagonalMatrix m) 136 throws MatrixDimensionMismatchException { 137 MatrixUtils.checkSubtractionCompatible(this, m); 138 139 final int dim = getRowDimension(); 140 final double[] outData = new double[dim]; 141 for (int i = 0; i < dim; i++) { 142 outData[i] = data[i] - m.data[i]; 143 } 144 145 return new DiagonalMatrix(outData, false); 146 } 147 148 /** 149 * Returns the result of postmultiplying {@code this} by {@code m}. 150 * 151 * @param m matrix to postmultiply by 152 * @return {@code this * m} 153 * @throws DimensionMismatchException if 154 * {@code columnDimension(this) != rowDimension(m)} 155 */ 156 public DiagonalMatrix multiply(final DiagonalMatrix m) 157 throws DimensionMismatchException { 158 MatrixUtils.checkMultiplicationCompatible(this, m); 159 160 final int dim = getRowDimension(); 161 final double[] outData = new double[dim]; 162 for (int i = 0; i < dim; i++) { 163 outData[i] = data[i] * m.data[i]; 164 } 165 166 return new DiagonalMatrix(outData, false); 167 } 168 169 /** 170 * Returns the result of postmultiplying {@code this} by {@code m}. 171 * 172 * @param m matrix to postmultiply by 173 * @return {@code this * m} 174 * @throws DimensionMismatchException if 175 * {@code columnDimension(this) != rowDimension(m)} 176 */ 177 public RealMatrix multiply(final RealMatrix m) 178 throws DimensionMismatchException { 179 if (m instanceof DiagonalMatrix) { 180 return multiply((DiagonalMatrix) m); 181 } else { 182 MatrixUtils.checkMultiplicationCompatible(this, m); 183 final int nRows = m.getRowDimension(); 184 final int nCols = m.getColumnDimension(); 185 final double[][] product = new double[nRows][nCols]; 186 for (int r = 0; r < nRows; r++) { 187 for (int c = 0; c < nCols; c++) { 188 product[r][c] = data[r] * m.getEntry(r, c); 189 } 190 } 191 return new Array2DRowRealMatrix(product, false); 192 } 193 } 194 195 /** {@inheritDoc} */ 196 @Override 197 public double[][] getData() { 198 final int dim = getRowDimension(); 199 final double[][] out = new double[dim][dim]; 200 201 for (int i = 0; i < dim; i++) { 202 out[i][i] = data[i]; 203 } 204 205 return out; 206 } 207 208 /** 209 * Gets a reference to the underlying data array. 210 * 211 * @return 1-dimensional array of entries. 212 */ 213 public double[] getDataRef() { 214 return data; 215 } 216 217 /** {@inheritDoc} 218 * @throws MathUnsupportedOperationException 219 */ 220 @Override 221 public void setSubMatrix(final double[][] subMatrix, 222 final int row, 223 final int column) 224 throws MathUnsupportedOperationException { 225 throw new MathUnsupportedOperationException(); 226 } 227 228 /** {@inheritDoc} */ 229 @Override 230 public double getEntry(final int row, final int column) 231 throws OutOfRangeException { 232 MatrixUtils.checkMatrixIndex(this, row, column); 233 return row == column ? data[row] : 0; 234 } 235 236 /** {@inheritDoc} 237 * @throws MathUnsupportedOperationException if {@code row != column}. 238 */ 239 @Override 240 public void setEntry(final int row, final int column, final double value) 241 throws OutOfRangeException, 242 MathUnsupportedOperationException { 243 if (row != column) { 244 throw new MathUnsupportedOperationException(); 245 } 246 MatrixUtils.checkMatrixIndex(this, row, column); 247 data[row] = value; 248 } 249 250 /** {@inheritDoc} 251 * @throws MathUnsupportedOperationException if {@code row != column}. 252 */ 253 @Override 254 public void addToEntry(final int row, 255 final int column, 256 final double increment) 257 throws OutOfRangeException, 258 MathUnsupportedOperationException { 259 if (row != column) { 260 throw new MathUnsupportedOperationException(); 261 } 262 MatrixUtils.checkMatrixIndex(this, row, column); 263 data[row] += increment; 264 } 265 266 /** {@inheritDoc} 267 * @throws MathUnsupportedOperationException if {@code row != column}. 268 */ 269 @Override 270 public void multiplyEntry(final int row, 271 final int column, 272 final double factor) 273 throws OutOfRangeException, 274 MathUnsupportedOperationException { 275 if (row != column) { 276 throw new MathUnsupportedOperationException(); 277 } 278 MatrixUtils.checkMatrixIndex(this, row, column); 279 data[row] *= factor; 280 } 281 282 /** {@inheritDoc} */ 283 @Override 284 public int getRowDimension() { 285 return data == null ? 0 : data.length; 286 } 287 288 /** {@inheritDoc} */ 289 @Override 290 public int getColumnDimension() { 291 return getRowDimension(); 292 } 293 294 /** {@inheritDoc} */ 295 @Override 296 public double[] operate(final double[] v) 297 throws DimensionMismatchException { 298 return multiply(new DiagonalMatrix(v, false)).getDataRef(); 299 } 300 301 /** {@inheritDoc} */ 302 @Override 303 public double[] preMultiply(final double[] v) 304 throws DimensionMismatchException { 305 return operate(v); 306 } 307 308 /** {@inheritDoc} */ 309 @Override 310 public double walkInRowOrder(final RealMatrixChangingVisitor visitor) 311 throws MathUnsupportedOperationException { 312 throw new MathUnsupportedOperationException(); 313 } 314 315 /** {@inheritDoc} */ 316 @Override 317 public double walkInRowOrder(final RealMatrixPreservingVisitor visitor) 318 throws MathUnsupportedOperationException { 319 throw new MathUnsupportedOperationException(); 320 } 321 322 /** {@inheritDoc} */ 323 @Override 324 public double walkInRowOrder(final RealMatrixChangingVisitor visitor, 325 final int startRow, final int endRow, 326 final int startColumn, final int endColumn) 327 throws MathUnsupportedOperationException { 328 throw new MathUnsupportedOperationException(); 329 } 330 331 /** {@inheritDoc} */ 332 @Override 333 public double walkInRowOrder(final RealMatrixPreservingVisitor visitor, 334 final int startRow, final int endRow, 335 final int startColumn, final int endColumn) 336 throws MathUnsupportedOperationException { 337 throw new MathUnsupportedOperationException(); 338 } 339 340 /** {@inheritDoc} */ 341 @Override 342 public double walkInColumnOrder(final RealMatrixChangingVisitor visitor) 343 throws MathUnsupportedOperationException { 344 throw new MathUnsupportedOperationException(); 345 } 346 347 /** {@inheritDoc} */ 348 @Override 349 public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor) 350 throws MathUnsupportedOperationException { 351 throw new MathUnsupportedOperationException(); 352 } 353 354 /** {@inheritDoc} */ 355 @Override 356 public double walkInColumnOrder(final RealMatrixChangingVisitor visitor, 357 final int startRow, final int endRow, 358 final int startColumn, final int endColumn) 359 throws MathUnsupportedOperationException { 360 throw new MathUnsupportedOperationException(); 361 } 362 363 /** {@inheritDoc} */ 364 @Override 365 public double walkInColumnOrder(final RealMatrixPreservingVisitor visitor, 366 final int startRow, final int endRow, 367 final int startColumn, final int endColumn) 368 throws MathUnsupportedOperationException { 369 throw new MathUnsupportedOperationException(); 370 } 371 }