package org.archstudio.sysutils; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkPositionIndex; import java.text.DecimalFormat; public class Matrix { private int columns; private int rows; private double[] values; private Matrix(int columns, int rows) { this.columns = columns; this.rows = rows; values = new double[columns * rows]; } public static Matrix newMatrix(int columns, int rows) { return new Matrix(columns, rows); } public static Matrix newRowMajorMatrix(int columns, double... values) { checkArgument(values.length % columns == 0, "Incomplete matrix"); Matrix m = new Matrix(columns, values.length / columns); m.values = values.clone(); return m; } public static Matrix newColumnMajorMatrix(int rows, double... values) { checkArgument(values.length % rows == 0, "Incomplete matrix"); int columns = values.length / rows; Matrix m = new Matrix(columns, rows); int i = 0; for (int column = 0; column < columns; column++) { for (int row = 0; row < rows; row++) { m.values[row * columns + column] = values[i++]; } } return m; } public static Matrix newRowMajorMatrix(int columns, float... values) { checkArgument(values.length % columns == 0, "Incomplete matrix"); Matrix m = new Matrix(columns, values.length / columns); m.values = new double[values.length]; for (int i = 0; i < values.length; i++) { m.values[i] = values[i]; } return m; } public static Matrix newColumnMajorMatrix(int rows, float... values) { checkArgument(values.length % rows == 0, "Incomplete matrix"); int columns = values.length / rows; Matrix m = new Matrix(columns, rows); int i = 0; for (int column = 0; column < columns; column++) { for (int row = 0; row < rows; row++) { m.values[row * columns + column] = values[i++]; } } return m; } public static Matrix newIdentityMatrix(int size) { Matrix m = new Matrix(size, size); for (int i = 0; i < size; i++) { m.set(i, i, 1); } return m; } public int getColumns() { return columns; } public int getRows() { return rows; } public void resize(int columns, int rows) { double[] values = new double[columns * rows]; for (int i = 0; i < values.length; i++) { values[i] = 0; } for (int row = 0; row < Math.min(rows, this.rows); row++) { for (int column = 0; column < Math.min(columns, this.columns); column++) { values[row * columns + column] = this.values[row * this.columns + column]; } } this.columns = columns; this.rows = rows; this.values = values; } public double get(int column, int row) { checkPositionIndex(column, columns - 1); checkPositionIndex(row, rows - 1); return values[row * columns + column]; } public void set(int column, int row, double value) { checkPositionIndex(column, columns - 1); checkPositionIndex(row, rows - 1); values[row * columns + column] = value; } public Matrix product(Matrix other) { checkArgument(columns == other.rows, "Cannot multiply %sx%s with %sx%s", rows, columns, other.rows, other.columns); Matrix result = new Matrix(other.columns, rows); for (int row = 0; row < result.rows; row++) { for (int column = 0; column < result.columns; column++) { double value = 0; for (int i = 0; i < columns; i++) { value += values[row * columns + i] * other.values[i * other.columns + column]; } result.values[row * result.columns + column] = value; } } return result; } private static final DecimalFormat format = new DecimalFormat(" #,##0.000;-#,##0.000"); private static final String EOL = System.getProperty("line.separator"); @Override public String toString() { StringBuffer sb = new StringBuffer(); for (int row = 0; row < rows; row++) { if (row != 0) { sb.append(EOL); } sb.append("["); for (int column = 0; column < columns; column++) { if (column != 0) { sb.append(", "); } sb.append(format.format(values[row * columns + column])); } sb.append("]"); } return sb.toString(); } }