package mikera.matrixx.impl;
import java.util.List;
import mikera.arrayz.ISparse;
import mikera.matrixx.AMatrix;
import mikera.matrixx.Matrix;
import mikera.matrixx.Matrixx;
import mikera.vectorz.AVector;
import mikera.vectorz.IOperator;
import mikera.vectorz.Op;
import mikera.vectorz.Op2;
import mikera.vectorz.Vector;
import mikera.vectorz.Vectorz;
import mikera.vectorz.impl.SingleElementVector;
import mikera.vectorz.impl.SparseIndexedVector;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;
/**
* Matrix stored as a collection of normally sparse column vectors
*
* This format is especially efficient for:
* - transposeInnerProduct() with another matrix
* - access via getColumn() operation
* - transpose into SparseRowMatrix
*
* @author Mike
*
*/
public class SparseColumnMatrix extends ASparseRCMatrix implements ISparse, IFastColumns {
private static final long serialVersionUID = -5994473197711276621L;
private static final long SPARSE_ELEMENT_THRESHOLD = 1000L;
private final AVector emptyColumn;
protected SparseColumnMatrix(int rowCount, int columnCount) {
this(new AVector[columnCount],rowCount,columnCount);
}
protected SparseColumnMatrix(AVector[] data, int rowCount, int columnCount) {
super(rowCount,columnCount,data);
if (data.length != columnCount)
throw new IllegalArgumentException(ErrorMessages.incompatibleShapes(columnCount, data.length));
emptyColumn=Vectorz.createZeroVector(rowCount);
}
protected SparseColumnMatrix(List data, int rowCount, int columnCount) {
this(data.toArray(new AVector[0]),rowCount,columnCount);
}
// protected SparseColumnMatrix(HashMap data, int rowCount, int columnCount) {
// super(rowCount,columnCount,data);
// emptyColumn=Vectorz.createZeroVector(rowCount);
// }
public static SparseColumnMatrix create(int rows, int cols) {
return new SparseColumnMatrix(rows, cols);
}
public static SparseColumnMatrix create(AVector[] data, int rows, int cols) {
return new SparseColumnMatrix(data, rows, cols);
}
/**
* Create a SparseColumnMatrix wrapping a specified array of columns
* null may be provided after first row
* @param vecs
* @return
*/
public static SparseColumnMatrix create(AVector... vecs) {
int rows=vecs[0].length();
int cols=vecs.length;
for (int i=1; i columns) {
return create(columns.toArray(new AVector[columns.size()]));
}
public static SparseColumnMatrix wrap(AVector[] vecs, int rows, int cols) {
return create(vecs, rows, cols);
}
public static SparseColumnMatrix wrap(AVector... vecs) {
return create(vecs);
}
public static SparseColumnMatrix create(AMatrix source) {
if (source instanceof SparseRowMatrix) return ((SparseRowMatrix)source).toSparseColumnMatrix();
int cc=source.columnCount();
int rc=source.rowCount();
AVector[] data = new AVector[cc];
for (int i=0; i vecs) {
return create(vecs);
}
// public static SparseColumnMatrix wrap(HashMap cols, int rowCount, int columnCount) {
// return new SparseColumnMatrix(cols,rowCount,columnCount);
// }
@Override
public int componentCount() {
return cols;
}
@Override
public AVector getComponent(int k) {
AVector v=data[k];
if (v==null) return emptyColumn;
return v;
}
@Override
protected int lineLength() {
return rows;
}
@Override
public double get(int i, int j) {
return getColumn(j).get(i);
}
@Override
public void set(int i, int j, double value) {
checkIndex(i,j);
unsafeSet(i,j,value);
}
@Override
public double unsafeGet(int row, int column) {
return getColumn(column).unsafeGet(row);
}
@Override
public void unsafeSet(int i, int j, double value) {
AVector v = unsafeGetVector(j);
if (v==null) {
if (value == 0.0)
return;
v = SingleElementVector.create(value, i, rows);
} else if (v.isFullyMutable()) {
v.unsafeSet(i,value);
return;
} else {
v = v.sparseClone();
v.unsafeSet(i, value);
}
unsafeSetVec(j, v);
}
@Override
public void set(AMatrix a) {
checkSameShape(a);
List scols=a.getColumns();
for (int i=0; i bcols=b.getColumns();
for (int i = 0; i < cc; i++) {
getColumnView(i).applyOp(op,bcols.get(i));
}
}
@Override
public void applyOp(Op2 op, double b) {
int cc = columnCount();
for (int i = 0; i < cc; i++) {
getColumnView(i).applyOp(op,b);
}
}
@Override
public void applyOp(IOperator op) {
if (op instanceof Op) {applyOp((Op)op); return;}
int cc = columnCount();
for (int i = 0; i < cc; i++) {
getColumnView(i).applyOp(op);
}
}
@Override
public void applyOp(Op op) {
int cc = columnCount();
for (int i = 0; i < cc; i++) {
getColumnView(i).applyOp(op);
}
}
@Override
public double reduce(Op2 op, double init) {
// override this because getting rows individually is expensive for SparseColumnMatrix
double result=init;
for (AVector row: getRows()) {
result=row.reduce(op, result);
}
return result;
}
@Override
public List getRows() {
return getTransposeView().getColumns();
}
/**
* Coerces this matrix into a SparseRowMatrix format.
* @return
*/
public SparseRowMatrix toSparseRowMatrix() {
AVector[] rowVecs = getRows().toArray(new AVector[rows]);
SparseRowMatrix rm = SparseRowMatrix.create(rowVecs, rows, cols);
return rm;
}
/**
* Ensures that a specific column is stored as a non-null, fully mutable vector.
* @param i
* @return
*/
private AVector ensureMutableColumn(int i) {
AVector v = unsafeGetVector(i);
if (v == null) {
AVector nv=SparseIndexedVector.createLength(rows);
unsafeSetVec(i, nv);
return nv;
}
if (v.isFullyMutable()) return v;
AVector mv=v.mutable();
unsafeSetVec(i, mv);
return mv;
}
@Override
public AVector getColumn(int j) {
AVector v = unsafeGetVector(j);
if (v==null) return emptyColumn;
return v;
}
@Override
public AVector getColumnView(int j) {
return ensureMutableColumn(j);
}
@Override
public boolean isLowerTriangular() {
int cc=columnCount();
for (int i=1; i acols=a.getColumns(); // allows SparseRowMatrix to efficiently construct column vectors
for (int i=0; i acols=a.getColumns(); // allows SparseRowMatrix to efficiently construct column vectors
for (int i=0; i
Ads help maintain this website.