package com.hpctoday.fada;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import com.hpctoday.fada.pointers.BooleanPointer;
public class Expression {
private static final Logger log = Logger.getLogger(Expression.class.getName());
public class Location {
int line;
int column;
}
/*
* enum T_leaf
*
* Contain a description for the class Expression.
*/
public enum Leaf {
FADA_value, /* Value */
FADA_variable, /* variable : describes both : loop-counters, symbolic constants and scalar */
FADA_array, /* array cell */
FADA_function /* function call */
}
public enum Operation {
FADA_ADD, /* Addition operator */
FADA_SUB, /* Substraction operator */
FADA_MUL, /* Multiplication operator */
FADA_DIV, /* Divide operator operator */
FADA_MOD /* Modulo operator */
}
/*
* class Expression
*
* A type for different kinds of an expression-leaf Expressions are viewed as binary tries. Leaves represent atomic terms (numbers,
* variables, array-cells and function calls), where internal nodes represent the operation between the left child and the right one.
*/
// For all nodes
private boolean is_leaf; // Am i a leaf ?
private int id_stmt; // the ID of the statement reading this expression.
private List<Expression> iteration; // and its instance.
private int deep; // useless information for FADA analysis.
private int line; // useless information for FADA analysis.
private int column; // useless information for FADA analysis.
// For leaves only
private Leaf t_leaf; // kind of information held by this leaf
private int value; // if leaf is a number, we got its value here
private String name; // used as name for : variables, arrays and functions
private List<Expression> FuncArg_ArrayIndex; // list of arguments for
// functions, and the access
// function for arrays.
// For internal nodes only
private Operation operation; // ok not atomic expression : so we need the
// operator
private Expression right__child; // right child
private Expression left__child; // left child
// !\name Simple setters
// A setter for "right__child"
private void SetRightChild(Expression child) {
right__child = child;
}
// A setter for "left__child"
private void SetLeftChild(Expression child) {
left__child = child;
}
// A setter for "FuncArg_ArrayIndex"
private void SetArguments(List<Expression> v) {
FuncArg_ArrayIndex = v;
}
// A setter for "name"
private void SetName(String str) {
name = str;
}
private void Initialize() {
this.is_leaf = true;
this.t_leaf = Leaf.FADA_value;
this.value = -1;
right__child = null;
left__child = null;
FuncArg_ArrayIndex = new ArrayList<Expression>();
name = "";
iteration = new ArrayList<Expression>();
}
@SuppressWarnings("unused")
private Expression() {
Initialize();
}
// !\name Normalization
/*
* Normalize an arithmetic term
* \return The normalized expression.
* \remarks The expression has to be an arithmetic term.
* \see NormalizeTerm(), SerializeTerm(), MultiplyNormalizedExpressions(),MultiplyTermByNormalizedExpression
*/
private Expression NormalizeTerm() {
if (this.IsValue()) {
return new Expression(new Expression(1), Operation.FADA_MUL, this);
}
if (this.IsLeaf()) {
return new Expression(this, Operation.FADA_MUL, new Expression(1));
}
Expression FG, FD, Val, Others;
FG = this.GetLeftChild().NormalizeTerm();
FD = this.GetRightChild().NormalizeTerm();
Val = new Expression(FG.GetRightChild(), Operation.FADA_MUL, FD.GetRightChild());
Others = new Expression(FG.GetLeftChild(), Operation.FADA_MUL, FD.GetLeftChild());
Val.Simplify();
Others.Simplify();
return new Expression(Others, Operation.FADA_MUL, Val);
}
class ExpressionReference {
Expression expression;
}
/*
* It Serializes an arithmetic term.
* \return Serialized term.
* \remarks The expression has to be an arithmetic term. Serialization will
* be done by deeping the always the right child. Any left-child can have only deep of level 1 or 0
* \see NormalizeTerm(), SerializeTerm(), MultiplyNormalizedExpressions(),MultiplyTermByNormalizedExpression
*/
private Expression SerializeTerm(ExpressionReference LastInternNode) {
// TODO : (FROM FADA) another way todo, no need for "LastInterneNode",
// explore FD and traite all leafs in FG
if (this.IsLeaf()) {
LastInternNode.expression = null;
return this.Clone();
}
if (this.GetLeftChild().IsLeaf() && this.GetRightChild().IsLeaf()) {
LastInternNode.expression = this.Clone();
return LastInternNode.expression;
}
Expression FG, FD;
ExpressionReference Lfg = new ExpressionReference(), Lfd = new ExpressionReference();
// TODO: fix writing
FG = this.GetLeftChild().SerializeTerm(Lfg);
FD = this.GetRightChild().SerializeTerm(Lfd);
if (Lfd.expression == null) {
LastInternNode.expression = new Expression(Lfg.expression.GetLeftChild(), Operation.FADA_MUL, FD);
Lfg.expression.SetLeftChild(LastInternNode.expression);
return FG;
}
if (Lfg.expression == null) {
LastInternNode.expression = new Expression(FG, Operation.FADA_MUL, Lfd.expression.GetLeftChild());
Lfd.expression.SetLeftChild(LastInternNode.expression);
return FD;
}
Expression E = new Expression(FD, Operation.FADA_MUL, Lfg.expression.GetLeftChild());
Lfg.expression.SetLeftChild(E);
LastInternNode.expression = Lfd.expression;
return FG;
}
/*
* Multiply two normalized expressions. \param [in]__exp : the multiplier. \return The result of the multiplication in a normalized
* form. \remarks The current and the expression "__exp" are supposed to be normalized. \see NormalizeTerm(), SerializeTerm(),
* MultiplyNormalizedExpressions(),MultiplyTermByNormalizedExpression
*/
private Expression MultiplyNormalizedExpressions(Expression E) {
if (IsTermInNormalizedFormula()) {
return MultiplyTermByNormalizedExpression(E);
}
return new Expression(GetLeftChild().MultiplyNormalizedExpressions(E), operation, GetRightChild().MultiplyNormalizedExpressions(E));
}
/*
* Multiply an arithmetic term by a normalized expression.
* \param [in]__exp : the multiplier.
* \return The result of the multiplication in a normalized form.
* \remarks The current object is supposed to be an arithmetic term. __exp have to be a normalized expression.
* \see NormalizeTerm(), SerializeTerm(), MultiplyNormalizedExpressions(),MultiplyTermByNormalizedExpression
*/
private Expression MultiplyTermByNormalizedExpression(Expression E) {
if (E.IsTermInNormalizedFormula()) {
Expression Term = new Expression(this, Operation.FADA_MUL, E);
ExpressionReference notseful = new ExpressionReference();
return Term.SerializeTerm(notseful).NormalizeTerm();
}
return new Expression(MultiplyTermByNormalizedExpression(E.GetLeftChild()), operation,
MultiplyTermByNormalizedExpression(E.GetRightChild()));
}
private Expression one_pass_simplify() {
if (IsLeaf()) {
return Clone();
}
// if operation with immediate operandes, perform operation
if (this.GetLeftChild().IsValue() && this.GetRightChild().IsValue() && IsAddition()) {
return new Expression(this.GetRightChild().GetValue() + this.GetLeftChild().GetValue());
}
if (this.GetLeftChild().IsValue() && this.GetRightChild().IsValue() && IsSubstraction()) {
return new Expression(this.GetLeftChild().GetValue() - this.GetRightChild().GetValue());
}
if (this.GetLeftChild().IsValue() && this.GetRightChild().IsValue() && IsMultiplication()) {
return new Expression(this.GetLeftChild().GetValue() * this.GetRightChild().GetValue());
}
// 0+x = x+0 = x
if (IsAddition() && this.GetLeftChild().IsValue() && GetLeftChild().GetValue() == 0) {
return GetRightChild().one_pass_simplify();
}
if (IsAddition() && this.GetRightChild().IsValue() && GetRightChild().GetValue() == 0) {
return GetLeftChild().one_pass_simplify();
}
// x-0 = x
if (IsSubstraction() && this.GetRightChild().IsValue() && GetRightChild().GetValue() == 0) {
return GetLeftChild().one_pass_simplify();
}
// 1*x = x*1 = x
if (IsMultiplication() && this.GetLeftChild().IsValue() && GetLeftChild().GetValue() == 1) {
return GetRightChild().one_pass_simplify();
}
if (IsMultiplication() && this.GetRightChild().IsValue() && GetRightChild().GetValue() == 1) {
return GetLeftChild().one_pass_simplify();
}
// 0*x = x*0 = 0
if (IsMultiplication() && this.GetLeftChild().IsValue() && GetLeftChild().GetValue() == 0) {
return new Expression(0);
}
if (IsMultiplication() && this.GetRightChild().IsValue() && GetRightChild().GetValue() == 0) {
return new Expression(0);
}
// N*(x/N) = x ... PIP' new param
/*
* if(IsMultiplication() && GetLeftChild().IsValue() && GetRightChild().IsDivision() && GetRightChild().GetRightChild().IsValue() &&
* GetLeftChild().GetValue() %GetRightChild().GetRightChild().GetValue()==0){ int coef=GetLeftChild
* ().GetValue()/GetRightChild().GetRightChild().GetValue(); if (coef != 1) return new Expression(new
* Expression(coef),FADA_MUL,GetRightChild().GetLeftChild()); else return GetRightChild().GetLeftChild(); }
*/
// (N*x)/N
if (IsDivision() && GetRightChild().IsValue() && GetLeftChild().IsMultiplication() && GetLeftChild().GetLeftChild().IsValue()
&& GetLeftChild().GetLeftChild().GetValue() % GetRightChild().GetValue() == 0) {
int coef = GetLeftChild().GetLeftChild().GetValue() / GetRightChild().GetValue();
if (coef != 1) {
return new Expression(new Expression(coef), Operation.FADA_MUL, GetLeftChild().GetRightChild());
} else {
return GetLeftChild().GetRightChild();
}
}
// (x*N)/N ?
// x - x
if (IsSubstraction() && GetRightChild().IsVariable() && GetLeftChild().IsVariable()
&& GetRightChild().GetVariableName().equals(GetLeftChild().GetVariableName())) {
return new Expression(0);
}
// TODO: x+(-1*y) = x-y
// if(IsMultiplication( ) && this.GetRightChild().IsSubstraction( ) &&
// this.GetRightChild().GetLeftChild().GetValue() == 1)
// return new
// Expression(this.GetLeftChild(),FADA_SUB,this.GetRightChild().GetRightChild());
//
// if(IsSubstraction( ) && this.GetRightChild().IsSubstraction( ) &&
// this.GetRightChild().GetLeftChild().GetValue() == 1 )
// return new Expression(this.GetLeftChild(), FADA_ADD,
// this.GetRightChild().GetRightChild());
//
// //n*(x/n) = x (newparms)
// if( IsMultiplication( ) && GetLeftChild( ).IsValue( ) &&
// GetRightChild( ).IsDivision( ) &&
// GetRightChild( ).GetRightChild( ).IsValue( ) &&
// GetLeftChild ( ).GetValue( ) == GetRightChild( ).GetRightChild(
// ).GetValue( ))
// {
// cout << "newparm simplification ok" << endl;
// return GetRightChild( ).GetLeftChild( ).one_pass_simplify( );
// }
//
//
// //TODO: + and * combs
return new Expression(GetLeftChild().one_pass_simplify(), operation, GetRightChild().one_pass_simplify());
}
/********************* Public Functions ************************************/
public final void Set(int __id, List<Expression> __iter) {
id_stmt = __id;
iteration = new ArrayList<Expression>(__iter);
}
// Getters
// !\brief A getter for "deep"
public int GetDeep() {
return deep;
}
// !\brief A getter for "ietration
public List<Expression> GetIteration() {
return iteration;
}
// !\brief A getter for "id_stmt"
public int GetReadStmt() {
return id_stmt;
}
public Location GetLocation() {
Location loc = new Location();
loc.line = line;
loc.column = column;
return loc;
}
// Setters
// a setter for "deep"
public void SetDeep(int __deep) {
this.deep = __deep;
}
// a setter for "iteration"
public void SetIteration(List<Expression> iter) {
iteration = iter;
}
public final void SetLocation(int __line, int __column) {
line = __line;
column = __column;
}
public final void SetLocation(Location loc) {
line = loc.line;
column = loc.column;
}
// !\name Building expressions
/*
* expression is a number. \param __val : the value of the number
*/
public Expression(int val) {
Initialize();
Set(val);
}
/*
* expression is a scalar \param __var : the name of the variable
*/
public Expression(String var) {
Initialize();
Set(var);
}
/*
* expression is an array cell or a function call
* \param __kind : to choose a function call or an array-cell-access
* \param __name : the name of the function, or of the array.
* \param __vect : arguments for functions, and access-function for array-cells.
*/
public Expression(Leaf __kind, String __name, List<Expression> __vect) {
Initialize();
Set(__kind, __name, __vect);
}
/*
* expression is an operation \param __l_c : the first operator for the operation \param __op : the operation \param __r_c : the second
* operator
*/
public Expression(Expression __l_c, Operation __op, Expression __r_c) {
Initialize();
Set(__l_c, __op, __r_c);
}
/*
* duplicating expression \param __exp : the expression to be duplicated
*/
public Expression(Expression e) {
if (e.IsLeaf()) {
if (e.IsValue()) {
Set(e.GetValue());
}
if (e.IsVariable()) {
Set(e.GetVariableName());
}
if (e.IsFunction()) {
Set(Leaf.FADA_function, e.GetFunctionName(), e.GetArguments());
}
if (e.IsArray()) {
Set(Leaf.FADA_array, e.GetArrayName(), e.GetIndex());
}
Set(e.GetReadStmt(), e.GetIteration());
SetLocation(e.GetLocation());
} else {
Set(e.GetLeftChild(), e.GetOperation(), e.GetRightChild());
SetLocation(e.GetLocation());
}
}
// ~Expression();
// Advanced Setters
/*
* expression is a number. \param __val : the value of the number
*/
public final void Set(int __val) {
is_leaf = true;
t_leaf = Leaf.FADA_value;
value = __val;
}
/*
* expression is a scalar \param __var : the name of the variable
*/
public final void Set(String __name) {
is_leaf = true;
t_leaf = Leaf.FADA_variable;
name = __name;
}
public final void Set(Leaf leaf, String var, List<Expression> index) {
is_leaf = true;
t_leaf = leaf;
name = var;
SetArguments(index);
}
public final void Set(Expression l_c, Operation op, Expression r_c) {
is_leaf = false;
operation = op;
SetLeftChild(l_c);
SetRightChild(r_c);
}
// Simple getters
// Am i a leaf ?
public boolean IsLeaf() {
return this.is_leaf;
}
// Only for leaves
// Am i a number?
public boolean IsValue() {
return is_leaf && this.t_leaf == Leaf.FADA_value;
}
// Am i an array-cell?
public boolean IsArray() {
return is_leaf && this.t_leaf == Leaf.FADA_array;
}
// Am i a function call.
public boolean IsFunction() {
return is_leaf && this.t_leaf == Leaf.FADA_function;
}
// Am i a variables
public boolean IsVariable() {
return is_leaf && this.t_leaf == Leaf.FADA_variable;
}
// Only for internal nodes
// Am i an add operation
public boolean IsAddition() {
return !is_leaf && operation == Operation.FADA_ADD;
}
// Am i a substruction
public boolean IsSubstraction() {
return !is_leaf && operation == Operation.FADA_SUB;
}
// Am i a multiplication.
public boolean IsMultiplication() {
return !is_leaf && operation == Operation.FADA_MUL;
}
public boolean IsModulo() {
return !is_leaf && operation == Operation.FADA_MOD;
}
// Am i a division
public boolean IsDivision() {
return !is_leaf && operation == Operation.FADA_DIV;
}
// A getter for "right__child"
public Expression GetRightChild() {
return this.right__child;
}
// A getter for "left__child"
public Expression GetLeftChild() {
return this.left__child;
}
// A getter for "operation"
public Operation GetOperation() {
return this.operation;
}
// A getter for "FuncArg_ArrayIndex"
public List<Expression> GetArguments() {
return this.FuncArg_ArrayIndex;
}
// A getter for "FuncArg_ArrayIndex"
public List<Expression> GetIndex() {
return this.FuncArg_ArrayIndex;
}
// A getter for "name"
public String GetVariableName() {
return this.name;
}
// A getter for "name"
public String GetFunctionName() {
return this.name;
}
// A getter for "name"
public String GetArrayName() {
return this.name;
}
// A getter for "value"
public int GetValue() {
return value;
}
// Duplicating
/*
* Cloning \return a copy of the caller. \remarks The clone share with the caller the quasi-totality of references. Only root nodes are
* independent. \remarks This method is faster than Copy(). \see Copy()
*/
public Expression Clone() {
return new Expression(this);
}
/*
* Copying \return a copy of the caller. \remarks The copy is completely independent. \remarks This method can be a bit costiler in time
* for complicated long expressions. \see Clone()
*/
public Expression Copy() {
if (IsLeaf()) {
return new Expression(this);
}
return new Expression(GetLeftChild().Copy(), operation, GetRightChild().Copy());
}
// Printing
/*
* It prints the current object into the standard output file.
*/
// public void Print()
/*
* It returns the result of printing in a String.
*/
@Override
public String toString() {
StringBuilder sout = new StringBuilder();
if (IsLeaf()) {
if (IsValue()) {
sout.append(GetValue());
return sout.toString();
}
if (IsVariable()) {
sout.append(GetVariableName());
return sout.toString();
}
if (IsFunction()) {
sout.append(GetFunctionName());
sout.append(" (");
boolean comma = false;
for (Expression exp : FuncArg_ArrayIndex) {
if (comma) {
sout.append(" , ");
}
sout.append(exp);
if (!comma) {
comma = true;
}
}
sout.append(")");
return sout.toString();
}
if (IsArray()) {
sout.append(GetFunctionName());
sout.append(" [");
boolean comma = false;
for (Expression exp : FuncArg_ArrayIndex) {
if (comma) {
sout.append(" ][ ");
}
sout.append(exp);
if (!comma) {
comma = true;
}
}
sout.append("]");
return sout.toString();
}
}
if (!GetLeftChild().IsLeaf()) {
sout.append("(");
}
sout.append(GetLeftChild());
if (!GetLeftChild().IsLeaf()) {
sout.append(")");
}
switch (operation) {
case FADA_ADD:
sout.append("+");
break;
case FADA_SUB:
sout.append("-");
break;
case FADA_MUL:
sout.append("*");
break;
case FADA_DIV:
sout.append("/");
break;
case FADA_MOD:
sout.append("%");
break;
default:
throw new RuntimeException("Expression::ToString(void) unknown operator " + "\nLHS = " + GetLeftChild() + "\nRHS = "
+ GetRightChild());
}
if (!GetRightChild().IsLeaf()) {
sout.append("(");
}
sout.append(GetRightChild());
if (!GetRightChild().IsLeaf()) {
sout.append(")");
}
return sout.toString();
}
/*
* It prints the expression, and distingishes the non-affine entities. \param __var : list of variables. \param __param : list of
* parameters. \return the result of printing Non affine entities will be followed by a String if the format '<S:I>', where :(1) S is
* the identifier of the statement who references the expression; and (2) I is its instance. \see PrintAll(), Instanciate()
*/
public String PrintAll_str(List<String> var, List<String> param) {
StringBuilder sout = new StringBuilder();
if (IsLeaf()) {
if (IsValue()) {
sout.append(GetValue());
return sout.toString();
}
if (IsVariable()) {
if (var.contains(GetVariableName()) || param.contains(GetVariableName()))
return GetVariableName();
sout.append(GetVariableName()).append(Global.PrintOperation(GetReadStmt(), GetIteration()));
return sout.toString();
}
if (IsFunction()) {
sout.append(GetFunctionName()).append(" (");
boolean first = true;
for (Expression it : GetArguments()) {
if (first)
first = false;
else
sout.append(" , ");
sout.append(it.PrintAll_str(var, param));
}
sout.append(")");
return sout.toString();
}
if (IsArray()) {
sout.append(GetArrayName()).append(Global.PrintOperation(GetReadStmt(), GetIteration())).append(" [ ");
boolean first = true;
for (Expression it : GetArguments()) {
if (first)
first = false;
else
sout.append(" ][ ");
sout.append(it.PrintAll_str(var, param));
}
sout.append("]");
return sout.toString();
}
}
if (!GetLeftChild().IsLeaf())
sout.append("(");
sout.append(GetLeftChild().PrintAll_str(var, param));
if (!GetLeftChild().IsLeaf())
sout.append(")");
switch (operation) {
case FADA_ADD:
sout.append("+");
break;
case FADA_SUB:
sout.append("-");
break;
case FADA_MUL:
sout.append("*");
break;
case FADA_DIV:
sout.append("/");
break; // with newparms
default:
throw new RuntimeException("Expression::Print(void) unknown operator " + "\nLHS = " + GetLeftChild().PrintAll_str(var, param)
+ "\nRHS = " + GetRightChild().PrintAll_str(var, param));
}
if (!GetRightChild().IsLeaf())
sout.append("(");
sout.append(GetRightChild().PrintAll_str(var, param));
if (!GetRightChild().IsLeaf())
sout.append(")");
return sout.toString();
}
/*
* It prints the expression, and distingishes the non-affine entities. \param __var : list of variables. \param __param : list of
* parameters. Non affine entities will be followed by a String if the format '<S:I>', where :(1) S is the identifier of the statement
* who references the expression; and (2) I is its instance. \see PrintAll_str(), Instanciate()
*/
// inline void PrintAll(Vector<String>* var, Vector<String>* param) {
// cout << PrintAll_str(var, param);
// }
/*
* It prints the expression in a format that respects the language C.
*/
public String Generate_C_Code() {
StringBuilder sout = new StringBuilder();
if (IsLeaf()) {
if (IsValue()) {
sout.append(GetValue());
return sout.toString();
}
if (IsVariable()) {
return GetVariableName();
}
if (IsFunction()) {
sout.append(GetFunctionName());
sout.append(" (");
List<Expression> arguments = this.GetArguments();
for (int i = 0; i < arguments.size(); ++i) {
Expression it = arguments.get(i);
sout.append(it);
if (i + 1 < arguments.size()) {
sout.append(" , ");
}
}
sout.append(")");
return sout.toString();
}
if (IsArray()) {
sout.append(GetArrayName());
sout.append(" [ ");
List<Expression> arguments = this.GetArguments();
for (int i = 0; i < arguments.size(); ++i) {
Expression it = arguments.get(i);
sout.append(it.Generate_C_Code());
if (i + 1 < arguments.size()) {
sout.append(" ][ ");
}
}
sout.append("]");
return sout.toString();
}
}
if (!GetLeftChild().IsLeaf()) {
sout.append("(");
}
sout.append(GetLeftChild().Generate_C_Code());
if (!GetLeftChild().IsLeaf()) {
sout.append(")");
}
switch (operation) {
case FADA_ADD:
sout.append("+");
break;
case FADA_SUB:
sout.append("-");
break;
case FADA_MUL:
sout.append("*");
break;
case FADA_DIV:
sout.append("/");
break; // with newparms
default:
throw new RuntimeException("Expression::Print(void) unknown operator");
// cerr<<"\nLHS = "<<GetLeftChild( )->Generate_C_Code( );
// cerr<<"\nRHS = "<<GetRightChild( )->Generate_C_Code( )<<"\n";
}
if (!GetRightChild().IsLeaf()) {
sout.append("(");
}
sout.append(GetRightChild().Generate_C_Code());
if (!GetRightChild().IsLeaf()) {
sout.append(")");
}
return sout.toString();
}
// !\name Collecting
/*
* It collects all referenced variables. \param __scalars : all referenced scalars will be added here.
*/
public void ReferencedScalars(Set<String> scalars) {
if (IsLeaf()) {
if (IsVariable()) {
scalars.add(GetVariableName());
}
if (IsArray() && IsFunction()) {
for (Expression ex : GetArguments()) {
ex.ReferencedScalars(scalars);
}
}
return;
}
GetRightChild().ReferencedScalars(scalars);
GetLeftChild().ReferencedScalars(scalars);
}
// !\name Substitution
/*
* Substitute scalars by expression \param __mapping : the mapping between variables to be remplaced by their new values. \return The
* result of substitution. \remarks The caller is not modified by this method. The result is given as a partially independent
* expression.
*/
public Expression SubstituteByExpression(Map<String, Expression> __mapping) {
Expression result;
if (IsLeaf() && IsVariable() && __mapping.containsKey(GetVariableName())) {
result = __mapping.get(GetVariableName());
List<Expression> new_iter = new ArrayList<Expression>();
for (Expression ex : GetIteration()) {
new_iter.add(ex.SubstituteByExpression(__mapping, true));
}
result.Instanciate(GetReadStmt(), new_iter);
return result;
}
if (IsLeaf() && (IsArray() || IsFunction())) {
result = this.Clone();
List<Expression> new_arg = new ArrayList<Expression>();
for (Expression ex : GetArguments()) {
new_arg.add(ex.SubstituteByExpression(__mapping));
}
result.SetArguments(new_arg);
if (IsArray()) {
List<Expression> new_iter = new ArrayList<Expression>();
for (Expression ex : GetIteration()) {
new_iter.add(ex.SubstituteByExpression(__mapping, true));
}
result.Instanciate(GetReadStmt(), new_iter);
}
return result;
}
if (!IsLeaf()) {
return new Expression(GetLeftChild().SubstituteByExpression(__mapping), GetOperation(), GetRightChild().SubstituteByExpression(
__mapping));
}
return this; // is_leaf && is_value
}
public Expression SubstituteByExpression(Map<String, Expression> __mapping, boolean __use_less) {
// Expression result;
if (IsLeaf() && IsVariable()) {
if (__mapping.containsKey(GetVariableName())) {
return __mapping.get(GetVariableName());
}
return Clone();
}
if (IsLeaf() && IsValue()) {
return Clone();
}
if (IsLeaf()) {
throw new RuntimeException("Expression::Substitute (map<..>, bool) ... fatal error (inapropriate case)");
}
return new Expression(GetLeftChild().SubstituteByExpression(__mapping, __use_less), GetOperation(), GetRightChild()
.SubstituteByExpression(__mapping, __use_less));
}
/*
* Substitute scalars by anothers \param __mapping : the mapping between scalars the be subsituted and their new names. \remarks
* Substitution is performed on the same object.
*/
public void SubstituteByString(Map<String, String> __mapping) {
if (IsLeaf() && IsVariable() && __mapping.containsKey(GetVariableName())) {
SetName(__mapping.get(GetVariableName()));
return;
}
if (IsLeaf() && (IsArray() || IsFunction())) {
for (Expression ex : GetArguments()) {
ex.SubstituteByString(__mapping);
}
for (Expression ex : GetIteration()) {
ex.SubstituteByString(__mapping);
}
return;
}
if (!IsLeaf()) {
GetLeftChild().SubstituteByString(__mapping);
GetRightChild().SubstituteByString(__mapping);
return;
}
return;
}
// !\name Tagging
/*
* Tag the expression by an operation. \param __id : the identifier of the statement \param __iter : its instance.
*/
public void Instanciate(int __id, List<Expression> __iter) {
if (IsLeaf()) {
Set(__id, __iter);
if (IsValue() || IsVariable()) {
return;
}
if (IsArray() || IsFunction()) {
for (Expression ex : GetArguments()) {
ex.Instanciate(__id, __iter);
}
return;
}
throw new RuntimeException("Expression::Instanciate() ..... FATAL ERROR (inapropriate case)");
}
this.GetLeftChild().Instanciate(__id, __iter);
this.GetRightChild().Instanciate(__id, __iter);
}
// !\name Miscellaneous
/*
* It checks whether the expression is the incrementation of a variable. \param __var : a name of a variable. \return expression =
* __var+1;
*/
// public boolean IsInc(String __var);
/*
* It checks whether expression is a term in a normalized formula. \return a boolean value to say if the current can be considred as a
* term in a normalized formula. A normalized formula is the sum of arithmetic terms. A term is the multiplication and/or the division
* of atomic expressions.
*/
public boolean IsTermInNormalizedFormula() {
return ((IsLeaf()) || (!IsLeaf() && (IsMultiplication() || IsDivision())));
}
/*
* It checks whether expression is affine on parameters and variables. \param __var : list of variables. \param __param : list of
* parameters.
*/
public boolean IsAffine(List<String> var, List<String> param) {
if (IsLeaf()) {
if (IsValue()) {
return true;
}
if (IsVariable()) {
if (var.contains(GetVariableName()) || param.contains(GetVariableName())) {
return true;
}
}
return false;
}
if (IsAddition() || IsSubstraction()) {
return GetRightChild().IsAffine(var, param) && GetLeftChild().IsAffine(var, param);
}
if (IsMultiplication()) {
if (GetRightChild().IsValue()) {
return GetLeftChild().IsAffine(var, param);
} else if (GetLeftChild().IsValue()) {
return GetRightChild().IsAffine(var, param);
} else {
return false;
}
}
if (IsDivision() || IsModulo()) {
if (GetLeftChild().IsValue()) {
return GetRightChild().IsAffine(var, param);
} else {
return false;
}
}
throw new RuntimeException("Expression::IsAffine ...............UNHANDLED_CASE");
}
/*
* It checks whether the arithmetic term is affine or not
*/
public boolean IsAffineTerm(BooleanPointer Contain_LC_P, List<String> var, List<String> param) {
if (IsLeaf()) {
if (IsValue()) {
Contain_LC_P.setValue(false);
return true;
}
if (IsVariable()) {
if (var.contains(GetVariableName()) || param.contains(GetVariableName())) {
Contain_LC_P.setValue(true);
return true;
}
Contain_LC_P.setValue(false);
return false;
}
if (IsFunction() || IsArray()) {
Contain_LC_P.setValue(false);
return false;
}
throw new RuntimeException("Expression::IsAffineTerm, fatal error : unhandled case");
}
boolean Affine1, Affine2 = true;
BooleanPointer Contain1 = new BooleanPointer(), Contain2 = new BooleanPointer();
Affine1 = this.GetRightChild().IsAffineTerm(Contain1, var, param);
if (Affine1) {
Affine2 = this.GetLeftChild().IsAffineTerm(Contain2, var, param);
}
return (Affine1 && Affine2 && !(Contain1.getValue() && Contain2.getValue()));
}
/*
* It normalizes the expression. \return a normilized but semantically equivalent expression. The normilized is written as a sum of
* arithmetic terms?
*/
public Expression Normalize() {
if (IsLeaf()) {
return Clone();
}
if (GetLeftChild().IsLeaf() && GetRightChild().IsLeaf()) {
return Clone();
}
Expression new_left_child, new_right_child;
new_left_child = GetLeftChild().Normalize();
new_right_child = GetRightChild().Normalize();
if (IsMultiplication()) {
return new_right_child.MultiplyNormalizedExpressions(new_left_child);
}
return new Expression(new_left_child, operation, new_right_child);
}
/*
* Simplify the expression. \return simplified but semantically equivalent expression. This method performs operations when the
* operators are known.
*/
public Expression Simplify() {
Expression current = this;
Expression simplified = one_pass_simplify();
while (!current.toString().equals(simplified.toString())) // Fix-point iteration
{
current = simplified;
simplified = current.one_pass_simplify();
}
return simplified;
}
/*
* \remarks This operator performs a syntaxic comparison. Equivalent expressions, written differently will be considered as not
* equivalent.
*/
// boolean operator ==(Expression& e);
/*
* It codes the affine expression into a Vector of coefficients
*/
public List<Integer> ToVector(List<String> counters, Map<String, Integer> counters_ranks, List<String> parameters,
Map<String, Integer> parameters_ranks) {
int nb_counters = counters_ranks.size();
int nb_parameters = parameters.size();
int org_counter = 0;
int org_parameter = nb_counters;
int org_constant = nb_counters + nb_parameters;
int size = nb_counters + nb_parameters + 1;
List<Integer> result = new ArrayList<Integer>(size);
for(int i = 0; i < size; i++){
result.add(0);
}
if (this.IsLeaf()) {
if (this.IsValue()) {
result.set(org_constant, this.GetValue());
return result;
}
if (this.IsVariable()) {
if (counters.contains(this.GetVariableName())) {
result.set(org_counter + counters_ranks.get(GetVariableName()), 1);
return result;
}
if (parameters.contains(this.GetVariableName())) {
result.set(org_parameter + parameters_ranks.get(GetVariableName()), 1);
return result;
}
}
throw new RuntimeException(
"Expression::ToVector ... fatal error : leaf is not a counter, not a parameter and not an integer value '" + toString());
} else {
List<Integer> fg_vector = this.GetLeftChild().ToVector(counters, counters_ranks, parameters, parameters_ranks);
List<Integer> fd_vector = this.GetRightChild().ToVector(counters, counters_ranks, parameters, parameters_ranks);
switch (this.GetOperation()) {
case FADA_ADD: {
for (int i = 0; i < fg_vector.size(); i++) {
result.set(i, fg_vector.get(i) + fd_vector.get(i));
}
break;
}
case FADA_SUB: {
for (int i = 0; i < fg_vector.size(); i++) {
result.set(i, fg_vector.get(i) - fd_vector.get(i));
}
break;
}
case FADA_MUL: {
if (this.GetLeftChild().IsValue()) {
for (int i = 0; i < fg_vector.size(); i++) {
result.set(i, this.GetLeftChild().GetValue() * fd_vector.get(i));
}
break;
}
if (this.GetRightChild().IsValue()) {
for (int i = 0; i < fg_vector.size(); i++) {
result.set(i, fg_vector.get(i) * this.GetRightChild().GetValue());
}
break;
}
throw new RuntimeException("Expression::ToVector ... fatal error : non affine expression");
}
}
}
return result;
}
public boolean IsFuzzy(Set<String> fuzzy_variables) {
if (IsLeaf()) {
if (IsValue()) {
return false;
}
if (IsArray() && IsFunction()) {
return true;
}
if (IsVariable()) {
if (!fuzzy_variables.contains(GetVariableName())) {
return false;
} else {
return true;
}
}
throw new RuntimeException("Expression::IsFuzzy ............. inappropriate case");
}
if (!GetLeftChild().IsFuzzy(fuzzy_variables)) {
return GetRightChild().IsFuzzy(fuzzy_variables);
} else {
return true;
}
}
// public String Print_Tex_str();
// String Full_Tex_Print_str(Vector<String>* var, Vector<String> *param);
public Expression PIPize(List<String> new_variables, List<Inequation> new_inequations) {
if (IsDivision() && GetRightChild().IsValue()) { // E/nb <=> forall V,
// E-nb< nb*V <= E ... so: E/nb=V
Expression lhs = GetLeftChild().PIPize(new_variables, new_inequations);
String var1 = "__tmp__" + new_variables.size();
new_variables.add(var1);
Expression nb_x_tmp = new Expression(GetRightChild(), Operation.FADA_MUL, new Expression(var1));
Inequation ineq1 = new Inequation(new Expression(lhs, Operation.FADA_SUB, GetRightChild()), Inequation.Predicate.FADA_LESS,
nb_x_tmp);
Inequation ineq2 = new Inequation(nb_x_tmp, Inequation.Predicate.FADA_LESS_EQ, lhs);
new_inequations.add(ineq1);
new_inequations.add(ineq2);
return new Expression(var1);
}
if (IsModulo() && GetRightChild().IsValue()) { // E%nb=R sothat 0<=R<nb,
// forall X, E=nb*X+R
Expression lhs = GetLeftChild().PIPize(new_variables, new_inequations);
String R, X;
R = "__tmp__" + new_variables.size();
X = "__tmp__" + (new_variables.size() + 1);
new_variables.add(R);
new_variables.add(X);
Expression nb_x_X = new Expression(GetRightChild(), Operation.FADA_MUL, new Expression(X));
Expression R_expr = new Expression(R);
Inequation ineq1 = new Inequation(new Expression(0), Inequation.Predicate.FADA_LESS_EQ, R_expr);
Inequation ineq2 = new Inequation(R_expr, Inequation.Predicate.FADA_LESS, GetRightChild());
Inequation ineq3 = new Inequation(lhs, Inequation.Predicate.FADA_EQ, new Expression(nb_x_X, Operation.FADA_ADD, R_expr));
new_inequations.add(ineq1);
new_inequations.add(ineq2);
new_inequations.add(ineq3);
return R_expr;
}
return this;
}
public Expression add(Expression e2) {
return new Expression(this, Expression.Operation.FADA_ADD, e2);
}
public Expression add(int val) {
return new Expression(this, Expression.Operation.FADA_ADD, new Expression(val));
}
public Expression sub(Expression e2) {
return new Expression(this, Expression.Operation.FADA_SUB, e2);
}
public Expression sub(int val) {
return new Expression(this, Expression.Operation.FADA_SUB, new Expression(val));
}
public Expression mul(Expression e2) {
return new Expression(this, Expression.Operation.FADA_MUL, e2);
}
public Expression mul(int val) {
return new Expression(this, Expression.Operation.FADA_MUL, new Expression(val));
}
public Expression div(Expression e2) {
return new Expression(this, Expression.Operation.FADA_DIV, e2);
}
public Expression div(int val) {
return new Expression(this, Expression.Operation.FADA_DIV, new Expression(val));
}
// Expression operator=(Expression&e) {
// return *(e.Clone());
// }
// Expression operator=(Expression*e) {
// return *(e.Clone());
// }
// Expression operator=(String str) {
// return *(new Expression(str));
// }
// // Expression operator=(char* str) {return *(new
// Expression((String)str));}
// Expression operator=(int val) {
// return *(new Expression(val));
// }
//
// Inequation operator<(Expression&e);// {return *(new Inequation(this,
// FADA_LESS,&e));}
// Inequation operator<(Expression*e);// {return *(new Inequation(this,
// FADA_LESS,e));}
// Inequation operator<(int val);// {return *(new Inequation(this,
// FADA_LESS,new Expression(val)));}
//
// Inequation operator<=(Expression&e);// {return *(new Inequation(this,
// FADA_LESS_EQ,&e));}
// Inequation operator<=(Expression*e);// {return *(new Inequation(this,
// FADA_LESS_EQ,e));}
// Inequation operator<=(int val);// {return *(new Inequation(this,
// FADA_LESS_EQ,new Expression(val)));}
//
// // Inequation operator==(Expression&e) {return *(new Inequation(this,
// FADA_EQ,&e));}
// // Inequation operator==(Expression*e) {return *(new Inequation(this,
// FADA_EQ,e));}
// // Inequation operator==(int val) {return *(new Inequation(this,
// FADA_EQ,new Expression(val)));}
//
// Inequation operator!=(Expression&e);// {return *(new Inequation(this,
// FADA_NEQ,&e));}
// Inequation operator!=(Expression*e);// {return *(new Inequation(this,
// FADA_NEQ,e));}
// Inequation operator!=(int val);// {return *(new Inequation(this,
// FADA_NEQ,new Expression(val)));}
//
// Inequation operator>(Expression&e);// {return *(new Inequation(this,
// FADA_GREATER,&e));}
// Inequation operator>(Expression*e);// {return *(new Inequation(this,
// FADA_GREATER,e));}
// Inequation operator>(int val);// {return *(new Inequation(this,
// FADA_GREATER,new Expression(val)));}
//
// Inequation operator>=(Expression&e);// {return *(new Inequation(this,
// FADA_GREATER_EQ,&e));}
// Inequation operator>=(Expression*e);// {return *(new Inequation(this,
// FADA_GREATER_EQ,e));}
// Inequation operator>=(int val);// {return *(new Inequation(this,
// FADA_GREATER_EQ,new Expression(val)));}
public boolean AddIndex(Expression e) {
if (IsVariable() || IsArray() || IsFunction()) {
GetIndex().add(e);
t_leaf = Leaf.FADA_array;
return true; // legal
}
return false; // illegal
}
public boolean AddArgument(Expression e) {
if (IsVariable() || IsArray() || IsFunction()) {
GetArguments().add(e);
t_leaf = Leaf.FADA_function;
return true; // legal
}
return false; // illegal
}
//
// Expression* operator+(Expression&e2) {return new
// Expression(this,FADA_ADD,&e2);}
// Expression* operator+(Expression*e2) {return new
// Expression(this,FADA_ADD,e2);}
}