package de.gaalop.tba.cfgImport.optimization.maxima;
import de.gaalop.OptimizationException;
import de.gaalop.api.cfg.AssignmentNodeCollector;
import de.gaalop.cfg.AssignmentNode;
import de.gaalop.cfg.ControlFlowGraph;
import de.gaalop.dfg.Expression;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.tba.Plugin;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* Defines a facade class for transforming a graph with maxima
* @author Christian Steinmetz
*/
public class MaximaOptimizer {
private MaximaConnection connection;
private AssignmentNodeCollector assignmentNodeCollector;
private Plugin plugin;
private StoreResultNodesCollector collector;
public MaximaOptimizer(MaximaConnection connection, Plugin plugin) {
this.connection = connection;
this.plugin = plugin;
}
/**
* Transforms a given ControlFlowGraph using the maxima optimization
* @param graph The ControlFlowGraph to be transformed
* @throws RecognitionException
*/
public void transformGraph(ControlFlowGraph graph) throws OptimizationException {
collector = new StoreResultNodesCollector();
graph.accept(collector);
MaximaInput input = new MaximaInput();
input.add("display2d:false;"); // very important!
input.add("ratprint:false;"); // very important!
input.add("keepfloat:true;");
fillMaximaInput(graph, input);
input.add("quit();"); // very important!
MaximaOutput output = connection.optimizeWithMaxima(input);
//connect in and output
LinkedList<String> connected = new LinkedList<String>();
MaximaRoutines.groupMaximaInAndOutputs(connected, output);
connected.removeFirst(); // remove display2d
connected.removeFirst(); // remove ratsimp
connected.removeFirst(); // remove keepfloat
ListIterator<AssignmentNode> listIterator = assignmentNodeCollector.getAssignmentNodes().listIterator();
for (String io : connected) {
Expression exp = MaximaRoutines.getExpressionFromMaximaOutput(io);
listIterator.next().setValue(exp);
}
/*
if (plugin.isOptInserting() && plugin.isScalarFunctions()) {
removeUnusedAssignments(graph, collector.getVariables());
}
*/
}
/**
* Fills a given MaximaInput instance with input for maxima, determined from a given graph
* @param graph The graph to be transformed in MaximaInput
* @param input The MaximaInput instance to be filled
*/
private void fillMaximaInput(ControlFlowGraph graph, MaximaInput input) {
assignmentNodeCollector = new AssignmentNodeCollector();
graph.accept(assignmentNodeCollector);
for (AssignmentNode node : assignmentNodeCollector.getAssignmentNodes()) {
DFGToMaximaCode dfg = new DFGToMaximaCode();
node.getVariable().accept(dfg);
String variable = "";
//using the store result nodes for marking to evaluate immediately is not possible in all cases,
//reason: consider a large cluscript with only one StoreResultNode add the end
//all non-marked assignments were inserted in the assignment with the StoreResultNode.getValue() as desitination variable
//this expression can be very long. Possible too long for the java code limit per method (65535 bytes)
//Splitting isn't trivial except of splitting the methods between two assignments, so the using of store result nodes can be expensive to compile time.
dfg = new DFGToMaximaCode();
node.getValue().accept(dfg);
String value = "ratsimp("+dfg.getResultString() + ");";
if (plugin.isOptInserting()) {
String name = node.getVariable().getName();
if (!graph.getPragmaOnlyEvaluateVariables().contains(name) && !collector.containsStoreResultVariableName(name)) { // see comment above
dfg = new DFGToMaximaCode();
node.getVariable().accept(dfg);
variable = dfg.getResultString() + "::";
}
}
if (!plugin.isScalarFunctions() & !(node.getVariable() instanceof MultivectorComponent)) {
variable = "";
}
if (plugin.isMaximaExpand())
input.add(variable + "expand(ratsimp("+value.substring(0, value.length()-1)+"));");
else
input.add(variable + value);
}
}
}