package org.openlca.core.matrix;
import org.openlca.core.math.IMatrix;
import org.openlca.core.math.IMatrixFactory;
import org.openlca.expressions.FormulaInterpreter;
import gnu.trove.impl.Constants;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.map.hash.TIntObjectHashMap;
public class ExchangeMatrix {
private int columns;
private int rows;
private final TIntObjectHashMap<TIntObjectHashMap<ExchangeCell>> cells;
ExchangeMatrix(int rows, int columns) {
this.columns = columns;
this.rows = rows;
cells = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY,
Constants.DEFAULT_LOAD_FACTOR, -1);
}
public boolean isEmpty() {
return cells.isEmpty();
}
/**
* Returns <number of elements>/(rows * cols) which is an indicator for the
* occupation of the matrix.
*/
public double getLoadFactor() {
TIntObjectIterator<TIntObjectHashMap<ExchangeCell>> it = cells
.iterator();
double size = 0;
while (it.hasNext()) {
it.advance();
TIntObjectHashMap<?> map = it.value();
if (map == null)
continue;
size += map.size();
}
return size / (rows * columns);
}
void setEntry(int row, int col, ExchangeCell cell) {
TIntObjectHashMap<ExchangeCell> rowMap = cells.get(row);
if (rowMap == null) {
rowMap = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY,
Constants.DEFAULT_LOAD_FACTOR, -1);
cells.put(row, rowMap);
}
rowMap.put(col, cell);
}
ExchangeCell getEntry(int row, int col) {
TIntObjectHashMap<ExchangeCell> rowMap = cells.get(row);
if (rowMap == null)
return null;
return rowMap.get(col);
}
public double getValue(int row, int col) {
ExchangeCell cell = getEntry(row, col);
if (cell == null)
return 0;
else
return cell.getMatrixValue();
}
public <M extends IMatrix> M createRealMatrix(IMatrixFactory<M> factory) {
if(rows == 0 || columns == 0)
return null;
M matrix = factory.create(rows, columns);
iterate((row, col, cell) -> {
matrix.set(row, col, cell.getMatrixValue());
});
return matrix;
}
void eval(FormulaInterpreter interpreter) {
iterate((row, col, cell) -> {
cell.eval(interpreter);
});
}
void apply(IMatrix matrix) {
iterate((row, col, cell) -> {
matrix.set(row, col, cell.getMatrixValue());
});
}
void simulate(IMatrix matrix) {
iterate((row, col, cell) -> {
matrix.set(row, col, cell.getNextSimulationValue());
});
}
void iterate(CellFunction fn) {
TIntObjectIterator<TIntObjectHashMap<ExchangeCell>> rowIterator = cells
.iterator();
while (rowIterator.hasNext()) {
rowIterator.advance();
int row = rowIterator.key();
TIntObjectHashMap<ExchangeCell> rowMap = rowIterator.value();
if (rowMap == null)
continue;
TIntObjectIterator<ExchangeCell> colIterator = rowMap.iterator();
while (colIterator.hasNext()) {
colIterator.advance();
int col = colIterator.key();
ExchangeCell cell = colIterator.value();
if (cell == null)
continue;
fn.apply(row, col, cell);
}
}
}
@FunctionalInterface
interface CellFunction {
void apply(int row, int col, ExchangeCell cell);
}
}