/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2008, Benedikt Huber (benedikt.huber@gmail.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.wcet.ipet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* A term of the form
* <code>c_1 * v_1 + ... + c_n * v_n</code>,
* where v_i denotes a variable and c_i an (integral) coefficient.
*
* @author Benedikt Huber <benedikt.huber@gmail.com>
*
* @param <T> type of the variables
*/
public class LinearVector<T> {
private HashMap<T,Long> coeffs;
/**
* Initialize the linear vector, with all coefficient 0.
*/
public LinearVector() {
coeffs = new HashMap<T,Long>();
}
/**
* Create a copy of the given linear vector
* @param vector
*/
public LinearVector(LinearVector<T> vector) {
this.coeffs = new HashMap<T,Long>(vector.getCoeffs());
}
/**
* the number of non-zero coefficients
*/
public int size() {
return this.coeffs.size();
}
/**
* Add the product <code>coeff * var</code> to the linear vector
* @param var
* @param coeff
*/
public void add(T var, long coeff) {
if(coeff == 0) return;
Long oldCoeff = this.coeffs.get(var);
if (oldCoeff == null) {
this.coeffs.put(var,coeff);
} else {
long newCoeff = coeff+oldCoeff;
if(newCoeff == 0) {
this.coeffs.remove(var);
} else {
this.coeffs.put(var,newCoeff);
}
}
}
/**
* Multiply the vector with the given scalar
* @param c the number to multiply each coefficient with
*/
public void mul(long c) {
for(Entry<T,Long> e : this.coeffs.entrySet()) {
this.coeffs.put(e.getKey(), e.getValue() * c);
}
}
/**
* Return the linear vector as a map
* @return map from variables to <emph>non-zero</emph> coefficients
*/
public Map<T, Long> getCoeffs() {
return this.coeffs;
}
@Override
public LinearVector<T> clone() {
return new LinearVector<T>(this);
}
@Override
public String toString() {
StringBuffer s = new StringBuffer();
toStringWith(s,0);
return s.toString();
}
/**
* Append the string representation of <code>a x + d</code>
* @param s the string buffer to append to
* @param d
*/
public void toStringWith(StringBuffer s, long d) {
boolean first = true;
for(Entry<T,Long> e : coeffs.entrySet()) {
if(e.getValue() == 0) continue;
if(first) {
first=false;
if(e.getValue() < 0) s.append('-');
appendAbsCoeff(s,e);
} else {
s.append(e.getValue() >= 0 ? " + " : " - ");
appendAbsCoeff(s,e);
}
}
if(d !=0 || first) {
if(first) {
if(d < 0) s.append("- ");
} else {
s.append(d >= 0 ? " + " : " - ");
}
s.append(Math.abs(d));
}
}
private void appendAbsCoeff(StringBuffer s, Entry<T, Long> e) {
long c = Math.abs(e.getValue());
if(c != 1) s.append(c+" ");
s.append(e.getKey());
}
}