package com.hpctoday.fada;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.Set;
import com.hpctoday.fada.pointers.IntegerPointer;
public class Control {
/*
* ! \enum FADA_Control \brief It models the kind of controls can be
* supported.
*/
public enum FADA_Control {
ADaAn_FOR, /* !< for loop */
ADaAn_IF, /* !< conditional */
ADaAn_IF_ELSE, /* !< alternative */
ADaAn_WHILE, /* !< while loop */
ADaAn_NONE
/* !< none */
};
/*
* ! \class Control \brief It models control structures.
*/
// ! \name Only for loops
private String loop_counter; // !< the identifier of the loop counter
// ! \name For "for-loops" only
private Expression for_lower_bound; // !< the lower bound
private Expression for_upper_bound; // !< the upper bound
// ! \name for while-loops and conditionals
private Condition if_while_condition; // !< while or if condition
// ! \name for if-then-else
private int else_first_assign; // !< the id of the first statement enclosed
// by the else-part.
private int else_last_assign; // !< the id of the last statement enclosed by
// the else-part.
// ! \name For any instance
private FADA_Control control_kind; // !< the kind of control
private int first_assign; // !< the id of the first enclosed statement
private int last_assign; // !< the id of the last enclosed statement
// ! \name properties can be computed
private List<List<Inequation>> affine_domain; // !< The normalized affine
// domain constraints of
// this control.
private List<List<Inequation>> non_affine_domain; // !< The normalized non
// affine domain
// constraints of this
// control.
private List<List<Inequation>> affine_else_domain; // !< The normalized
// affine domain
// constraints for
// statements enclosed
// by the else-part.
private List<List<Inequation>> non_affine_else_domain;// !< The normalized
// non affine domain
// constraints for
// statements
// enclosed by the
// else-part.
// ! \name Setters
// ! \brief A setter for "affine_domain"
private void SetAffineInequations(List<List<Inequation>> __ineq) {
affine_domain = __ineq;
}
// ! \brief A setter for "non_affine_domain"
private void SetNonAffineInequations(List<List<Inequation>> __ineq) {
non_affine_domain = __ineq;
}
// ! \brief A setter for "affine_else_domain"
@SuppressWarnings("unused")
private void SetAffineElseInequations(List<List<Inequation>> __ineq) {
affine_else_domain = __ineq;
}
// ! \brief A setter for "non-affine_else_domain"
@SuppressWarnings("unused")
private void SetNonAffineElseInequations(List<List<Inequation>> __ineq) {
non_affine_else_domain = __ineq;
}
// ! \brief A setter for "control_kind"
private void SetControlKind(FADA_Control control) {
control_kind = control;
}
// ! \brief A setter for "loop_counter"
private void SetCounterName(String name) {
loop_counter = name;
};
// ! \brief A setter for "for_upper_bound"
private void SetUpperBound(Expression __exp) {
for_upper_bound = __exp;
}
// ! \brief A setter for "for_lower_bound"
private void SetLowerBound(Expression __exp) {
for_lower_bound = __exp;
}
// ! \brief A setter for "if_while_condition"
private void SetCondition(Condition __cond) {
if_while_condition = __cond;
}
// ! \brief A setter for "first_assign" and "last_assign"
private void SetEnclosedAssigns(int assign1, int assign2) {
first_assign = assign1;
last_assign = assign2;
}
// ! \brief A setter for "else_first_assign" and "last_else_assign"
private void SetElseEnclosedAssigns(int assign1, int assign2) {
else_first_assign = assign1;
else_last_assign = assign2;
}
// ! \name Advanced Setters
/*
* ! \brief Set all properties to their NULL values.
*/
private void Initialize() {
SetControlKind(FADA_Control.ADaAn_NONE);
SetCounterName("");
SetUpperBound(null);
SetLowerBound(null);
SetCondition(null);
SetEnclosedAssigns(-1, -1);
SetElseEnclosedAssigns(-1, -1);
affine_domain = new ArrayList<List<Inequation>>();
non_affine_domain = new ArrayList<List<Inequation>>();
affine_else_domain = new ArrayList<List<Inequation>>();
non_affine_else_domain = new ArrayList<List<Inequation>>();
}
/*
* ! \brief Create a "for" control \param __lc[in] : the loop counter'
* identifier. \param __lb[in] : the lower bound. \param __ub[in] : the
* upper bound.
*/
private void Set(String __counter, Expression __lb, Expression __ub) {
SetControlKind(FADA_Control.ADaAn_FOR);
SetCounterName(__counter);
SetUpperBound(__ub);
SetLowerBound(__lb);
}
/*
* ! \brief Create a "while" control \param __lc[in] : its loop counter'
* indetifier. \param __c[in] : its condition.
*/
private void Set(String __counter, Condition __cond) {
SetControlKind(FADA_Control.ADaAn_WHILE);
SetCounterName(__counter);
SetCondition(__cond);
}
/*
* ! \brief Create a "if" control \param __c[in] : its condition.
*/
private void Set(Condition __cond) {
SetControlKind(FADA_Control.ADaAn_IF);
SetCondition(__cond);
}
public Condition GetDomainConstraints(int stmt) {
// Condition result;
if ((IsLoop() || IsIf())) {
if ((stmt >= first_assign) && (stmt <= last_assign)) {
if (IsForLoop()) {
Inequation ineq1 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_GREATER_EQ, GetForLowerBound());
Inequation ineq2 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_LESS_EQ, GetForUpperBound());
return new Condition(new Condition(ineq1), Condition.Logical_Operator.FADA_AND, new Condition(ineq2));
} else
return GetCondition();
} else
return new Condition(new Inequation(true));
}
if (IsIfElse()) {
if ((stmt >= first_assign) && (stmt <= last_assign))
return GetCondition();
else {
if ((stmt >= else_first_assign) && (stmt <= else_last_assign))
return GetCondition().FastNegation();
else
return new Condition(new Inequation(true));
}
}
throw new RuntimeException("Control::GetDomainConstraints .... fatal error (inapropriate case)");
}
public Condition GetRegularDomain() {
Condition result;
if (IsIf() || IsIfElse() || IsWhileLoop()) {
if (IsWhileLoop()) {
Inequation ineq = new Inequation(new Expression(GetCounter()), Inequation.Predicate.FADA_GREATER_EQ, new Expression(1));
Condition count_ge_0 = new Condition(ineq);
result = new Condition(count_ge_0, Condition.Logical_Operator.FADA_AND, GetCondition());
return result;
}
return GetCondition();
}
if (IsForLoop()) {
Inequation ineq1 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_GREATER_EQ, GetForLowerBound());
Inequation ineq2 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_LESS_EQ, GetForUpperBound());
result = new Condition(new Condition(ineq1), Condition.Logical_Operator.FADA_AND, new Condition(ineq2));
return result;
}
throw new RuntimeException("Control::GetRegularDomain(void) .... inappropriate case");
}
public void SwitchToIfElse() {
if (IsIfElse())
return;
if (IsIf()) {
SetControlKind(FADA_Control.ADaAn_IF_ELSE);
return;
}
throw new RuntimeException("Control::SwitchToIfElse .... fatal error (inapropriate case)");
}
public Control(String __counter, Expression __lb, Expression __ub) {
Initialize();
Set(__counter, __lb, __ub);
}
public Control(String __counter, Condition __cond) {
Initialize();
Set(__counter, __cond);
}
public Control(Condition __cond) {
Initialize();
Set(__cond);
}
// ! \name Getters
// ! \brief A getter for "first_assign" and "last_assign"
public void GetEnclosedAssignments(IntegerPointer assign1, IntegerPointer assign2) {
assign1.setValue(first_assign);
assign2.setValue(last_assign);
}
// ! \brief A getter for "else_first_assign" and "else_last_assign"
public void GetElsePartAssignments(IntegerPointer assign1, IntegerPointer assign2) {
assign1.setValue(else_first_assign);
assign2.setValue(else_last_assign);
}
// ! \brief A getter for "control_kind"
public FADA_Control GetControlKind() {
return control_kind;
}
// ! \brief A getter for "loop_counter"
public String GetLoopCounter() {
return loop_counter;
}
// ! \brief A getter for "for_upper_bound"
public Expression GetForUpperBound() {
return for_upper_bound;
}
// ! \brief A getter for "for_lower_bound"
public Expression GetForLowerBound() {
return for_lower_bound;
}
// ! \brief A getter for "if_while_condition"
public Condition GetCondition() {
return if_while_condition;
}
// ! \brief A getter for "loop_counter"
public String GetCounter() {
return loop_counter;
}
// ! \brief A getter for "affine_domain"
public List<List<Inequation>> GetAffineDomain() {
return affine_domain;
}
// ! \brief A getter for "affine_else_domain"
public List<List<Inequation>> GetAffineElseDomain() {
return affine_else_domain;
}
// ! \brief A getter for "non_affine_domain"
public List<List<Inequation>> GetNonAffineDomain() {
return non_affine_domain;
}
// ! \brief A getter for "non_affine_else_domain"
public List<List<Inequation>> GetNonAffineElseDomain() {
return non_affine_else_domain;
}
// ! \name Frequently Asked Questions
// ! \brief Am i a "for" loop ?
public boolean IsForLoop() {
return control_kind == FADA_Control.ADaAn_FOR;
}
// ! \brief Am i a "while" loop ?
public boolean IsWhileLoop() {
return control_kind == FADA_Control.ADaAn_WHILE;
}
// ! \brief Am i a loop ?
public boolean IsLoop() {
return control_kind == FADA_Control.ADaAn_FOR || control_kind == FADA_Control.ADaAn_WHILE;
}
// ! \brief Am i an conditional ?
public boolean IsIf() {
return control_kind == FADA_Control.ADaAn_IF;
}
// ! \brief Am i an alternative ?
public boolean IsIfElse() {
return control_kind == FADA_Control.ADaAn_IF_ELSE;
}
public Condition GetRegularDomain(int __id, List<String> __loop_counters, List<String> __param, LDemonstrator __loop_ppts) {
List<String> variables = new ArrayList<String>(__loop_counters);
if (IsLoop())
variables.add(GetLoopCounter());
NormalizeConditions(__id, variables, __param);
boolean simple_case = false;
switch (GetNonAffineDomain().size()) {
case 0:
simple_case = true;
break;
case 1: {
List<Inequation> v = GetNonAffineDomain().get(0);
if (v.size() <= 1)
simple_case = true;
}
default:
}
if (simple_case) {
// cout<<"\nSimple case";
if (IsIf() || IsIfElse() || IsWhileLoop()) {
if (IsWhileLoop()) {
// cout<<"\nComplicated domain";
Inequation ineq = new Inequation(new Expression(GetCounter()), Inequation.Predicate.FADA_GREATER_EQ, new Expression(0));
Condition count_ge_0 = new Condition(ineq);
return new Condition(GetCondition(), Condition.Logical_Operator.FADA_AND, count_ge_0);
}
return GetCondition();
}
if (IsForLoop()) {
Inequation ineq1 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_GREATER_EQ, GetForLowerBound());
Inequation ineq2 = new Inequation(new Expression(GetLoopCounter()), Inequation.Predicate.FADA_LESS_EQ, GetForUpperBound());
return new Condition(new Condition(ineq1), Condition.Logical_Operator.FADA_AND, new Condition(ineq2));
}
throw new RuntimeException("Control::GetRegularDomain ... inappropriate case 1");
} else {
// complicated_case:
// cout<<"\nComplicated domain";
Condition result = new Condition(new Inequation(true));
for (List<Inequation> it : GetAffineDomain()) {
result = new Condition(Global.ToDNFTerm(it), Condition.Logical_Operator.FADA_AND, result);
}
if (IsWhileLoop()) {
Inequation ineq = new Inequation(new Expression(GetCounter()), Inequation.Predicate.FADA_GREATER_EQ, new Expression(1));
Condition count_ge_0 = new Condition(ineq);
result = new Condition(count_ge_0, Condition.Logical_Operator.FADA_AND, result);
}
Expression non_affine = new Expression("domain_" + __id);
for (String it : __loop_counters)
non_affine.AddArgument(new Expression(it));
if (IsLoop())
non_affine.AddArgument(new Expression(GetLoopCounter()));
if (non_affine.IsVariable())
__param.add(non_affine.GetVariableName());
return new Condition(new Condition(new Inequation(non_affine, Inequation.Predicate.FADA_NEQ, new Expression(0))),
Condition.Logical_Operator.FADA_AND, result);
}
}
// ! \name Printing
@Override
public String toString(){
return Print_str(0);
}
/*
* ! \brief Print the control into a String.
*/
public String Print_str() {
return Print_str(0);
}
public String Print_str(int what_to_print) {
String result = "";
StringBuilder s = new StringBuilder();
IntegerPointer stmt1 = new IntegerPointer(), stmt2 = new IntegerPointer();
GetEnclosedAssignments(stmt1, stmt2);
s.append("[").append(stmt1).append(",").append(stmt2).append("]");
GetElsePartAssignments(stmt1, stmt2);
s.append("[").append(stmt1).append(",").append(stmt2).append("]");
switch (GetControlKind()) {
case ADaAn_FOR:
result = "for(" + GetLoopCounter() + ":" + GetForLowerBound() + ":" + GetForUpperBound() + ")";
break;
case ADaAn_WHILE:
result = "while(" + GetCondition() + ")";
break;
case ADaAn_IF:
result = "if(" + GetCondition() + ")";
break;
case ADaAn_IF_ELSE:
result = "if the else(" + GetCondition() + ")";
break;
default:
throw new RuntimeException("Fatal error, Control::Print_str(), unhandled operator ");
}
result += "\tcounter = " + GetLoopCounter() + "\t" + s.toString();
if (what_to_print == Global.__SECURE_PRINT)
return result;
result += "\n Affine constraints :";
for (List<Inequation> it : GetAffineDomain()) {
result += "\n";
for (Inequation iti : it)
result += "\t" + iti;
}
result += "\nNon Affine constraints :";
for (List<Inequation> it : GetNonAffineDomain()) {
result += "\n";
for (Inequation iti : it)
result += "\t" + iti;
}
result += "\n";
if (!IsIfElse())
return result;
result += "\n Affine NOT DOMAIN :";
for (List<Inequation> it : GetAffineElseDomain()) {
result += "\n";
for (Inequation iti : it)
result += "\t" + iti;
}
result += "\nNon Affine NOT_DOMAIN :";
for (List<Inequation> it : GetNonAffineElseDomain()) {
result += "\n";
for (Inequation iti : it)
result += "\t" + iti;
}
result += "\n";
return result;
}
/*
* ! \brief Print in a readable way the control into a String.
*/
public String PrettyPrint_str() {
String result = "";
switch (GetControlKind()) {
case ADaAn_FOR:
result = "for ( " + GetLoopCounter();
result += " = " + GetForLowerBound().Generate_C_Code();
result += "; " + GetLoopCounter() + " <= " + GetForUpperBound().Generate_C_Code();
result += "; ++" + GetLoopCounter() + ")";
return result;
case ADaAn_WHILE:
result = "while(" + GetCondition().Generate_C_Code() + ")";
return result;
case ADaAn_IF:
result = "if(" + GetCondition().Generate_C_Code() + ")";
return result;
case ADaAn_IF_ELSE:
result = "if(" + GetCondition().Generate_C_Code() + ")";
return result;
default:
throw new RuntimeException("Fatal error, Control::PrettyPrint_str(), unhandled operator ");
}
}
/*
* ! \brief Generate an appropriate control in a C format.
*/
public String Generate_C_Code() {
String result = "";
switch (GetControlKind()) {
case ADaAn_FOR:
result = "for ( " + GetLoopCounter();
result += " = " + GetForLowerBound().Generate_C_Code();
result += "; " + GetLoopCounter() + " <= " + GetForUpperBound().Generate_C_Code();
result += "; ++" + GetLoopCounter() + ")";
break;
case ADaAn_WHILE:
result = "while(" + GetCondition().Generate_C_Code() + ")";
break;
case ADaAn_IF:
result = "if(" + GetCondition().Generate_C_Code() + ")";
break;
case ADaAn_IF_ELSE:
result = "if/*then else*/(" + GetCondition().Generate_C_Code() + ")";
break;
default:
throw new RuntimeException("Fatal error, Control::Generate_C_Code(), unhandled operator ");
}
return result;
}
// !\name Miscellaneous
// ! \brief rename variables.
public void Substitute(Map<String, String> __mapping) {
switch (GetControlKind()) {
case ADaAn_FOR:
if (__mapping.containsKey(GetCounter()))
SetCounterName(__mapping.get(GetCounter()));
GetForLowerBound().SubstituteByString(__mapping);
GetForUpperBound().SubstituteByString(__mapping);
return;
case ADaAn_WHILE:
if (__mapping.containsKey(GetCounter()))
SetCounterName(__mapping.get(GetCounter()));
GetCondition().SubstituteByString(__mapping);
return;
case ADaAn_IF:
GetCondition().SubstituteByString(__mapping);
return;
case ADaAn_IF_ELSE:
GetCondition().SubstituteByString(__mapping);
return;
}
throw new RuntimeException("Control::Substitute, Fatal error(unhandled operator)");
}
// ! \brief Normalize domain constraints and sort them into affine and non
// affine constraints.
public void NormalizeConditions(int id_stmt, List<String> var, List<String> parameters) {
Condition __domain = GetRegularDomain();
__domain = __domain.EliminateNotOperations(true);
List<Condition> __terms = new ArrayList<Condition>(__domain.SplitToTerms());
List<List<Inequation>> affine_for_sure = new ArrayList<List<Inequation>>();
List<List<Inequation>> non_affine_for_the_moment = new ArrayList<List<Inequation>>();
for (Condition it : __terms) {
List<Inequation> all_term_inequations = it.GetTermInequations();
List<Inequation> term_affine = new ArrayList<Inequation>();
List<Inequation> term_non_affine = new ArrayList<Inequation>();
Condition.SortInequations(all_term_inequations, term_affine, term_non_affine, var, parameters);
Condition eliminate_neq = Global.ToDNFTerm(term_affine);
eliminate_neq = eliminate_neq.TraduceNEQInequations();
List<Condition> affine_affine_terms = new ArrayList<Condition>(eliminate_neq.SplitToTerms());
for (Condition itt : affine_affine_terms)
affine_for_sure.add(itt.GetTermInequations());
if (term_non_affine.size() > 0)
non_affine_for_the_moment.add(term_non_affine);
}
SetAffineInequations(affine_for_sure);
SetNonAffineInequations(non_affine_for_the_moment);
if (!IsIfElse())
return;
// hihiiii, i'm not obliged to rewrite code or/and redeclare other
// variables .... ngoul rani courage à 03:09 :-)
// {
// Condition __domain=GetRegularDomain();
// __domain=__domain.Negate(true);
//
// List<Condition> __terms=__domain.SplitToTerms();
//
// List<List<Inequation> > affine_for_sure;
// List<List<Inequation> > non_affine_for_the_moment;
//
// for(vector<Condition*>::iterator it=__terms.begin(); it!=
// __terms.end(); ++it){
// vector<Inequation*> all_term_inequations=(*it)->GetTermInequations();
// vector<Inequation*> term_affine, term_non_affine;
// SortInequations(&all_term_inequations,&term_affine,&term_non_affine,var,
// parameters);
// Condition* eliminate_neq=ToDNFTerm(&term_affine);
// eliminate_neq=eliminate_neq->TraduceNEQInequations();
// vector<Condition*> affine_affine_terms=eliminate_neq->SplitToTerms();
// for(vector<Condition*>::iterator itt=affine_affine_terms.begin(); itt
// != affine_affine_terms.end(); ++itt)
// affine_for_sure.push_back((*itt)->GetTermInequations());
//
// non_affine_for_the_moment.push_back(term_non_affine);
// }
// SetAffineElseInequations(&affine_for_sure);
// SetNonAffineElseInequations(&non_affine_for_the_moment);
// return;
// }
TagAllInequations(id_stmt, 0, var);
}
// ! \brief Tagg all constraints by the read operation (an instance of a
// statement)
public void TagAllInequations(int id, int __deep, List<String> var) {
List<Expression> iteration = new ArrayList<Expression>();
for (String it : var)
iteration.add(new Expression(it));
for (List<Inequation> it : GetNonAffineDomain())
for (Inequation iti : it)
iti.Tag(id, iteration);
for (List<Inequation> it : GetNonAffineElseDomain())
for (Inequation iti : it)
iti.Tag(id, iteration);
}
// ! \brief Collect scalars
public void ReferencedScalars(Set<String> scalars) {
if (IsIf() || IsIfElse() || IsWhileLoop()) {
GetCondition().ReferencedScalars(scalars);
return;
}
if (IsForLoop()) {
GetForLowerBound().ReferencedScalars(scalars);
GetForUpperBound().ReferencedScalars(scalars);
return;
}
throw new RuntimeException("Control::ReferencedScalars(), fatal error, unhandled control structure");
}
}