package sim.util.matrix;
import sim.util.matrix.Block;
public class BlockSparseMatrix extends Matrix
{
private sim.util.Bag blocks;
public BlockSparseMatrix(int m, int n)
{
this.m = m;
this.n = n;
this.blocks = new sim.util.Bag();
}
public void setBlock(int rowoffset, int coloffset, double[][] vals)
{
Block block = new Block(vals.length, vals[0].length, rowoffset, coloffset, vals);
this.blocks.add(block);
}
public Vector times(Vector other)
{
return times(other, new Vector(this.m));
}
public Vector times(Vector other, Vector result)
{
result.clear();
int thism = this.m;
int thisn = this.n;
int otherm = other.m;
int resultm = result.m;
int numObjs = blocks.numObjs;
Object[] blockobjs = blocks.objs;
double[] othervals = other.vals;
double[] resultvals = result.vals;
for (int i = 0; i < numObjs; i++)
{
Block block = (Block)blockobjs[i];
int rowoffset = block.rowoffset;
int coloffset = block.coloffset;
double[][] vals = block.vals;
int blockm = block.m;
int blockn = block.n;
for (int j = 0; j < blockm; j++)
{
int absRow = rowoffset + j;
double curVectorVal = resultvals[absRow];
double[] row = vals[j];
for (int k = 0; k < blockn; k++)
curVectorVal += (row[k] * othervals[k + coloffset]);
resultvals[absRow] = curVectorVal;
}
}
return result;
}
public Vector transposeTimes(Vector other)
{
return transposeTimes(other, new Vector(this.n));
}
public Vector transposeTimes(Vector other, Vector C)
{
C.clear();
double[] othervals = other.vals;
double[] result = C.vals;
int numObjs = blocks.numObjs;
Object[] blockobjs = blocks.objs;
for (int k = 0; k < numObjs; k++)
{
Block block = (Block)blockobjs[k];
// these are reversed
int rowoffset = block.coloffset;
int coloffset = block.rowoffset;
int vectorOffset = block.rowoffset;
double[][] vals = block.vals;
int blockm = block.n;
int blockn = block.m;
// loop down the rows of the transpsed matrix
for (int i = 0; i < blockm; i++)
{
int absRow = rowoffset + i;
double curVectorVal = result[absRow];
// loop over the columns
for (int j = 0; j < blockn; j++)
{
// reverse the access to the block vals;
curVectorVal += vals[j][i] * othervals[j + vectorOffset];
}
result[absRow] = curVectorVal;
}
}
return C;
}
public DiagonalMatrix getDiagonalMatrix()
{
DiagonalMatrix diag = new DiagonalMatrix(this.m);
for (int k = 0; k < blocks.numObjs; k++)
{
Block block = (Block)blocks.objs[k];
int rowstart = 0;
int colstart = 0;
int absstart = -1;
if (block.rowoffset >= block.coloffset && block.rowoffset <= block.coloffset + block.n - 1)
{
rowstart = 0;
colstart = block.rowoffset - block.coloffset;
absstart = block.rowoffset;
int i = 0;
while (i < block.m && i < block.n - colstart)
{
diag.vals[absstart + i] = block.vals[rowstart + i][colstart + i];
i++;
}
}
else if (block.coloffset >= block.rowoffset && block.coloffset <= block.rowoffset + block.m - 1)
{
rowstart = block.coloffset - block.rowoffset;
colstart = 0;
absstart = block.coloffset;
int i = 0;
while (i < block.m - rowstart && i < block.n)
{
diag.vals[absstart + i] = block.vals[rowstart + i][colstart + i];
i++;
}
}
}
return diag;
}
public String toString()
{
double[][] vals = new double[this.m][this.n];
for (int k = 0; k < blocks.numObjs; k++)
{
Block block = (Block)blocks.objs[k];
for (int i = 0; i < block.m; i++)
for (int j = 0; j < block.n; j++)
vals[i + block.rowoffset][j + block.coloffset] = block.vals[i][j];
}
String result = "";
for (int i = 0; i < this.m; i++)
{
for (int j = 0; j < this.n; j++)
result += (" " + vals[i][j]);
result += "\n";
}
return result;
}
public DenseMatrix getDenseMatrix()
{
DenseMatrix denseMat = new DenseMatrix(this.m, this.n);
for (int k = 0; k < blocks.numObjs; k++)
{
Block block = (Block)blocks.objs[k];
denseMat.setSubMatrix(block.rowoffset, block.rowoffset + block.m - 1, block.coloffset, block.coloffset + block.n - 1, new DenseMatrix(block.vals));
}
return denseMat;
}
}