package mikera.matrixx.impl; import java.nio.DoubleBuffer; import mikera.arrayz.impl.IDenseArray; import mikera.matrixx.AMatrix; import mikera.matrixx.Matrix; import mikera.vectorz.AVector; import mikera.vectorz.Vector; import mikera.vectorz.impl.ImmutableVector; import mikera.vectorz.util.DoubleArrays; import mikera.vectorz.util.ErrorMessages; /** * Immutable dense matrix class * * This is the immutable equivalent of mikera.matrixx.Matrix * * @author Mike * */ public final class ImmutableMatrix extends ARectangularMatrix implements IDenseArray, IFastRows { private static final long serialVersionUID = 2848013010449128820L; private final double[] data; private ImmutableMatrix(int rows, int cols, double[] data) { super(rows,cols); this.data=data; } public ImmutableMatrix(AMatrix m) { super(m.rowCount(),m.columnCount()); data=m.toDoubleArray(); } /** * Creates a new ImmutableMatrix wrapping the data array of a given Matrix * * WARNING: does not take a defensive copy. Should be used only if you can guarantee that * the underlying data array will not be mutated elsewhere. */ public static ImmutableMatrix wrap(Matrix source) { double[] data=source.data; return new ImmutableMatrix(source.rowCount(), source.columnCount(), data); } /** * Creates a new ImmutableMatrix wrapping the specified source array * * WARNING: does not take a defensive copy. Should be used only if you can guarantee that * the data array will not be mutated elsewhere. */ public static ImmutableMatrix wrap(int rows, int cols, double[] data) { return new ImmutableMatrix(rows,cols, data); } private Matrix asMatrix() { return Matrix.wrap(rows, cols, data); } @Override public boolean isMutable() { return false; } @Override public boolean isFullyMutable() { return false; } @Override public boolean isView() { return false; } @Override public long nonZeroCount() { return DoubleArrays.nonZeroCount(data); } @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 get(int i, int j) { checkIndex(i,j); return unsafeGet(i,j); } @Override public ImmutableVector getRowView(int row) { if ((row<0)||(row>=rows)) throw new IllegalArgumentException(ErrorMessages.invalidSlice(this, row)); return ImmutableVector.wrap(data,row*cols,cols); } @Override public double unsafeGet(int i, int j) { return data[i*cols+j]; } @Override public void set(int row, int column, double value) { throw new UnsupportedOperationException(ErrorMessages.immutable(this)); } @Override public final void copyRowTo(int row, double[] dest, int destOffset) { int srcOffset=row*cols; System.arraycopy(data, srcOffset, dest, destOffset, cols); } @Override public Vector innerProduct(AVector a) { return asMatrix().transform(a); } @Override public Vector transform (AVector a) { return asMatrix().transform(a); } @Override public void transform(Vector source, Vector dest) { asMatrix().transform(source, dest); } @Override public final void copyColumnTo(int col, double[] dest, int destOffset) { int colOffset=col; for (int i=0;i<rows; i++) { dest[destOffset+i]=data[colOffset+i*cols]; } } @Override public double elementSum() { return DoubleArrays.elementSum(data); } @Override public double elementSquaredSum() { return DoubleArrays.elementSquaredSum(data); } @Override public Vector toVector() { return Vector.create(data); } @Override public Matrix toMatrix() { return Matrix.wrap(rows, cols, DoubleArrays.copyOf(data)); } public Matrix toMatrixTranspose() { Matrix m = Matrix.create(cols, rows); for (int j=0; j<cols; j++) { copyColumnTo(j,m.data,rows*j); } return m; } @Override public void toDoubleBuffer(DoubleBuffer dest) { dest.put(data); } @Override public void getElements(double[] dest, int offset) { System.arraycopy(data, 0, dest, offset, data.length); } @Override public void addToArray(double[] data, int offset) { DoubleArrays.add(this.data, 0, data,offset,rows*cols); } @Override public Matrix clone() { return Matrix.create(this); } @Override public AMatrix exactClone() { return new ImmutableMatrix(this); } @Override public boolean equals(AMatrix a) { if (!isSameShape(a)) return false; return a.equalsArray(data, 0); } @Override public boolean equalsArray(double[] data, int offset) { return DoubleArrays.equals(this.data, 0, data, offset, rows*cols); } /** * Unsafe method that returns the internal data array * @return */ public double[] getInternalData() { return data; } public static ImmutableMatrix create(AMatrix a) { int rows=a.rowCount(); int cols=a.columnCount(); return ImmutableMatrix.wrap(rows,cols,a.getElements()); } @Override public double[] getArray() { return data; } @Override public int getArrayOffset() { return 0; } }