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 }