/*
* DoubleMatrix.java
*
* Copyright (c) 2009 by Kevin McGuinness
*/
package ie.dcu.matrix;
import ie.dcu.array.Arrays;
/**
* Two dimensional matrix of double values.
*
* @author Kevin McGuinness
*/
public class DoubleMatrix extends Matrix {
/**
* Serialization UID.
*/
private static final long serialVersionUID = 3466326831906456667L;
/**
* Shared empty matrix
*/
private static final DoubleMatrix EMPTY_MATRIX = new DoubleMatrix(0,0);
/**
* The double values of the matrix in row-major order.
*/
public final double[] values;
/**
* Construct an uninitialized matrix of the given size.
*
* @param rows
* The number of rows
* @param cols
* The number of columns
*/
public DoubleMatrix(int rows, int cols) {
super(Type.Double, rows, cols);
values = new double[size];
}
/**
* Construct a matrix of the given size with the given values.
*
* @param rows
* The number of rows
* @param cols
* The number of columns
* @param values
* The values to the matrix will have (not copied).
*/
public DoubleMatrix(int rows, int cols, double ... values) {
super(Type.Double, rows, cols, values.length);
this.values = values;
}
/**
* Construct a matrix of the given size by copying the values in the
* given two dimensional array.
*
* The passed two dimensional array must consist of arrays that have
* the same dimension.
*
* @param matrix
* A two dimensional array of double values.
* @throws IllegalArgumentException
* If the matrix does not contain arrays of the same dimension.
*/
public DoubleMatrix(double[][] matrix) {
this(rowsIn(matrix), colsIn(matrix));
flatten(matrix, values);
}
/**
* Returns the double value at the given row and column index.
*
* @param row
* The row index.
* @param col
* The column index.
* @return
* The double value at (row, col).
*/
public final double doubleAt(int row, int col) {
return values[offsetOf(row, col)];
}
/**
* Returns the double value at the index.
*
* @param index
* The index
* @return
* The double value
*/
public final double doubleAt(Index2D index) {
return values[offsetOf(index)];
}
/**
* Set the double value at the given row and column index.
*
* @param row
* The row index.
* @param col
* The column index.
* @param value
* The double value to set.
*/
public final void setDoubleAt(int row, int col, double value) {
values[offsetOf(row, col)] = value;
}
/**
* Set the double value at the given index.
*
* @param index
* The index.
* @param value
* The double value to set.
*/
public final void setDoubleAt(Index2D index, double value) {
values[offsetOf(index)] = value;
}
/**
* Returns the double value at the given offset in the matrix.
*
* @param offset
* The absolute offset in the matrix.
* @return
* The double value at the given offset.
*/
public final double doubleAt(int offset) {
return values[offset];
}
/**
* Set the double value at the given offset in the matrix.
*
* @param offset
* The matrix offset
* @param value
* The double value to set.
*/
public final void setDoubleAt(int offset, double value) {
values[offset] = value;
}
/**
* Returns the smallest double value in the matrix.
*
* @return
* The smallest double value, or null if the
* matrix is empty.
*/
public final Double minValue() {
return Arrays.min(values);
}
/**
* Returns the largest double value in the matrix.
*
* @return
* The largest double value, or null if the
* matrix is empty.
*/
public final Double maxValue() {
return Arrays.max(values);
}
/**
* Returns a transposed version of the matrix.
*/
public final DoubleMatrix transpose() {
DoubleMatrix m = new DoubleMatrix(cols, rows);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.values[offsetOf(j,i)] = values[offsetOf(i, j)];
}
}
return m;
}
/**
* Returns a deep copy of the matrix.
*/
@Override
public DoubleMatrix clone() {
return new DoubleMatrix(rows, cols, values.clone());
}
/**
* Returns true if both matrices are equal in value.
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof DoubleMatrix) {
DoubleMatrix m = (DoubleMatrix) obj;
if (sizeEquals(m)) {
return java.util.Arrays.equals(values, m.values);
}
return false;
}
return super.equals(obj);
}
/**
* Fills the matrix with the %{primative} value of the given number.
*
* @param number
* The number to fill the matrix with (will be truncated if
* necessary).
* @return
* This matrix.
*/
@Override
public final DoubleMatrix fill(Number number) {
java.util.Arrays.fill(values, number.doubleValue());
return this;
}
/**
* Returns the Double value at the given row and column index.
*
* @param row
* The row index.
* @param col
* The column index.
* @return
* The Double value at (row, col).
*/
@Override
public final Double valueAt(int row, int col) {
return values[offsetOf(row, col)];
}
/**
* Set the Number value at the given row and column index.
*
* @param row
* The row index.
* @param col
* The column index.
* @param value
* The Number value to set (will be truncated if necessary).
*/
@Override
public final void setValueAt(int row, int col, Number value) {
values[offsetOf(row, col)] = value.doubleValue();
}
/**
* Returns the Double value at the given matrix offset.
*
* @param offset
* The absolute offset in the matrix.
* @return
* The Double value at the given offset.
*/
@Override
public final Double valueAt(int offset) {
return values[offset];
}
/**
* Set the Number value at the given matrix offset.
*
* @param offset
* The absolute offset in the matrix.
* @param value
* The Number value to set (will be truncated if necessary).
*/
@Override
public final void setValueAt(int offset, Number value) {
values[offset] = value.doubleValue();
}
/**
* Returns the matrix values (not copied).
*/
@Override
public final double[] values() {
return values;
}
/**
* Returns a shared empty matrix instance.
*/
public static DoubleMatrix empty() {
return EMPTY_MATRIX;
}
/**
* Construct and return an identity matrix with the given number of rows.
*
* @param rows
* The number of rows/columns for the matrix to have.
* @return
* A new identity matrix.
*/
public static DoubleMatrix eye(int rows) {
DoubleMatrix m = new DoubleMatrix(rows, rows);
m.fill(0);
for (int i = 0; i < rows; i++) {
m.setDoubleAt(i, i, (double) 1);
}
return m;
}
/**
* Construct and return an zero matrix with the given number of rows
* and columns.
*
* @param rows
* The number of rows for the matrix to have.
* @param cols
* The number of cols for the matrix to have.
* @return
* A new zero matrix.
*/
public static DoubleMatrix zeros(int rows, int cols) {
DoubleMatrix m = new DoubleMatrix(rows, rows);
m.fill(0);
return m;
}
/**
* Construct and return a matrix of ones with the given number of rows
* and columns.
*
* @param rows
* The number of rows for the matrix to have.
* @param cols
* The number of cols for the matrix to have.
* @return
* A new matrix of ones.
*/
public static DoubleMatrix ones(int rows, int cols) {
DoubleMatrix m = new DoubleMatrix(rows, rows);
m.fill(1);
return m;
}
/**
* Copy the given two dimensional array of double values into the given
* array. If the passed array does not contain at enough room for the
* passed matrix, a new array is allocated and returned.
*
* The passed two dimensional array must consist of arrays that have
* the same dimension.
*
* The copy is performed such that the flattened array is in row major
* order.
*
* @param matrix
* The 2D array of double values to flatten
* @param array
* The array to copy to (can be null).
* @return
* A flattened version of the matrix.
* @throws IllegalArgumentException
* If the matrix does not contain arrays of the same dimension.
*/
public static final double[] flatten(double[][] matrix, double[] array) {
int rows = matrix.length;
int cols = matrix.length > 0 ? matrix[0].length : 0;
int size = rows * cols;
if (array == null || array.length < size) {
array = new double[size];
}
for (int i = 0; i < rows; i++) {
if (cols != matrix[i].length) {
throw new IllegalArgumentException();
}
System.arraycopy(matrix[i], 0, array, cols * i, cols);
}
return array;
}
/**
* Returns the number of rows in the given two dimensional array.
*
* @param matrix
* A two dimensional array.
* @return
* The number of rows.
*/
public static final int rowsIn(double[][] matrix) {
return matrix.length;
}
/**
* Returns the number of columns in the given two dimensional array.
*
* This method assumes that the arrays in the given matrix all have
* equal lengths.
*
* @param matrix
* A two dimensional array.
* @return
* The number of columns.
*/
public static final int colsIn(double[][] matrix) {
return matrix.length > 0 ? matrix[0].length : 0;
}
/**
* Returns the total number of elements in the given two dimensional
* array.
*
* This method assumes that the arrays in the given matrix all have
* equal lengths.
*
* @param matrix
* A two dimensional array.
* @return
* The total number of elements.
*/
public static final int sizeOf(double[][] matrix) {
return rowsIn(matrix) * colsIn(matrix);
}
}