package mikera.matrixx.impl; import java.util.Arrays; import mikera.arrayz.impl.IDense; import mikera.matrixx.AMatrix; import mikera.matrixx.Matrix; import mikera.vectorz.AVector; import mikera.vectorz.Op; import mikera.vectorz.impl.ArraySubVector; import mikera.vectorz.util.DoubleArrays; /** * A densely packed matrix organised in column-major format. * * Transposes to/from a regular dense Matrix * * This class is useful if your main performance requirement is fast access to columns of a matrix. * This is frequently true when the matrix is used as the *second* argument in matrix/matrix operations. * * @author Mike * */ public class DenseColumnMatrix extends AStridedMatrix implements IFastColumns, IDense { private static final long serialVersionUID = 5459617932072332096L; private DenseColumnMatrix(int rowCount, int columnCount, double[] data) { super(data, rowCount, columnCount); } private DenseColumnMatrix(int rowCount, int columnCount) { this(rowCount, columnCount, Matrix.createStorage(rowCount, columnCount)); } public static DenseColumnMatrix wrap(int rows, int cols, double[] data) { return new DenseColumnMatrix(rows, cols, data); } @Override public int getArrayOffset() { return 0; } @Override public int rowStride() { return 1; } @Override public int columnStride() { return rows; } @Override public ArraySubVector getColumnView(int j) { return ArraySubVector.wrap(data, j*rows, rows); } @Override public void copyRowTo(int i, double[] dest, int destOffset) { for (int j=0; j<cols; j++) { dest[destOffset+j]=data[i+j*rows]; } } @Override public void copyColumnTo(int j, double[] dest, int destOffset) { System.arraycopy(data, j*rows, dest, destOffset, rows); } @Override public void setRow(int i, AVector row) { int cc = checkColumnCount(row.length()); for (int j = 0; j < cc; i++) { data[index(i, j)] = row.unsafeGet(i); } } @Override public void setColumn(int j, AVector col) { int rc = checkRowCount(col.length()); col.getElements(data, j * rc); } @Override public void addMultiple(AMatrix m, double factor) { checkRowCount(m.rowCount()); int cc=checkColumnCount(m.columnCount()); for (int i=0; i<cc; i++) { getColumnView(i).addMultiple(m.getColumn(i), factor); } } @Override protected int index(int i, int j) { return i+j*rows; } @Override public double get(int i, int j) { checkRow(i); // we only need to check i is in range: out of range j will trigger exception anyway return data[(j * rows) + i]; } @Override public void set(int i, int j, double value) { checkRow(i); // we only need to check i is in range: out of range j will trigger exception anyway data[(j * rows) + i] = value; } @Override public void unsafeSet(int i, int j, double value) { data[(j * rows) + i] = value; } @Override public double unsafeGet(int i, int j) { return data[(j * rows) + i]; } @Override public void addAt(int i, int j, double d) { data[(j * rows) + i] += d; } @Override public boolean isFullyMutable() { return true; } @Override public boolean isPackedArray() { return (cols<=1); } @Override public boolean isBoolean() { return DoubleArrays.isBoolean(data, 0, data.length); } @Override public boolean isZero() { return DoubleArrays.isZero(data, 0, data.length); } @Override public double elementSum() { return DoubleArrays.elementSum(data); } @Override public double elementSquaredSum() { return DoubleArrays.elementSquaredSum(data); } @Override public double elementMax() { return DoubleArrays.elementMax(data); } @Override public double elementMin() { return DoubleArrays.elementMin(data); } @Override public void abs() { DoubleArrays.abs(data); } @Override public void signum() { DoubleArrays.signum(data); } @Override public void square() { DoubleArrays.square(data); } @Override public void exp() { DoubleArrays.exp(data); } @Override public void log() { DoubleArrays.log(data); } @Override public void applyOp(Op op) { op.applyTo(data); } @Override public long nonZeroCount() { return DoubleArrays.nonZeroCount(data); } @Override public void add(double d) { DoubleArrays.add(data, d); } @Override public void multiply(double factor) { DoubleArrays.multiply(data, factor); } @Override public void set(double value) { Arrays.fill(data, value); } @Override public void reciprocal() { DoubleArrays.reciprocal(data, 0, data.length); } @Override public void clamp(double min, double max) { DoubleArrays.clamp(data, 0, data.length, min, max); } @Override public Matrix getTranspose() { return getTransposeView(); } @Override public Matrix getTransposeView() { return Matrix.wrap(cols, rows, data); } @Override public DenseColumnMatrix exactClone() { return new DenseColumnMatrix(rows,cols,data.clone()); } @Override public DenseColumnMatrix dense() { return this; } @Override public DenseColumnMatrix copy() { return exactClone(); } @Override public DenseColumnMatrix clone() { return exactClone(); } @Override public Matrix toMatrixTranspose() { return Matrix.wrap(cols, rows, data); } }