Package com.hpctoday.fada

Source Code of com.hpctoday.fada.Expression

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);}
}
TOP

Related Classes of com.hpctoday.fada.Expression

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.