package de.gaalop.gapp.importing;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.gapp.ConstantSetVectorArgument;
import de.gaalop.gapp.GAPP;
import de.gaalop.gapp.PairSetOfVariablesAndIndices;
import de.gaalop.gapp.PosSelector;
import de.gaalop.gapp.PosSelectorset;
import de.gaalop.gapp.Selector;
import de.gaalop.gapp.Selectorset;
import de.gaalop.gapp.SetVectorArgument;
import de.gaalop.gapp.Valueset;
import de.gaalop.gapp.Variableset;
import de.gaalop.gapp.importing.parallelObjects.Constant;
import de.gaalop.gapp.importing.parallelObjects.DotProduct;
import de.gaalop.gapp.importing.parallelObjects.ExtCalculation;
import de.gaalop.gapp.importing.parallelObjects.MvComponent;
import de.gaalop.gapp.importing.parallelObjects.ParVariable;
import de.gaalop.gapp.importing.parallelObjects.ParallelObject;
import de.gaalop.gapp.importing.parallelObjects.ParallelObjectType;
import de.gaalop.gapp.importing.parallelObjects.ParallelObjectVisitor;
import de.gaalop.gapp.importing.parallelObjects.Product;
import de.gaalop.gapp.importing.parallelObjects.Sum;
import de.gaalop.gapp.instructionSet.GAPPAssignMv;
import de.gaalop.gapp.instructionSet.GAPPCalculateMvCoeff;
import de.gaalop.gapp.instructionSet.GAPPDotVectors;
import de.gaalop.gapp.instructionSet.GAPPResetMv;
import de.gaalop.gapp.instructionSet.GAPPSetMv;
import de.gaalop.gapp.instructionSet.GAPPSetVector;
import de.gaalop.gapp.variables.GAPPConstant;
import de.gaalop.gapp.variables.GAPPMultivector;
import de.gaalop.gapp.variables.GAPPMultivectorComponent;
import de.gaalop.gapp.variables.GAPPVector;
import de.gaalop.tba.Algebra;
import java.util.HashSet;
import java.util.LinkedList;
/**
* Creates GAPP code from the ParallelObject data structure
* @author Christian Steinmetz
*/
public class GAPPCreator implements ParallelObjectVisitor {
// arg: GAPPMultivectorComponent: destination of this operation, otherwise null
// return: GAPPMultivectorComponent if a new one is created, otherwise null
private static final boolean USE_DOTPRODUCT_OPTIMIZER = false;
public GAPP gapp;
private int curTmp = -1;
private final String PREFIX_VE = "ve";
private final String PREFIX_TMPMV = "tempmv";
private HashSet<String> variables;
private int bladeCount;
private Algebra algebra;
public GAPPCreator(HashSet<String> variables, int bladeCount, Algebra algebra) {
this.variables = variables;
this.bladeCount = bladeCount;
this.algebra = algebra;
}
public void setGapp(GAPP gapp) {
this.gapp = gapp;
}
/**
* Creates a new temp variable name with a prefix
* @param prefix The prefix that should be used
* @return The temp variable name
*/
private String createTMP(String prefix) {
curTmp++;
while (variables.contains(prefix + curTmp)) {
curTmp++;
}
return prefix + curTmp;
}
/**
* Creates a new temporary GAPPMultivector and inserts a resetMv command in GAPP
* @param The number of entries in the new multivector
* @return The new GAPPMultivector
*/
public GAPPMultivector createMv() {
GAPPMultivector mv = new GAPPMultivector(createTMP(PREFIX_TMPMV));
gapp.addInstruction(new GAPPResetMv(mv, 1));
return mv;
}
/**
* Creates a temporary multivector with one entry and returns the according GAPPMultivectorComponent
* @return The GAPPMultivectorComponent
*/
public GAPPMultivectorComponent createMvComp() {
GAPPMultivector mv = new GAPPMultivector(createTMP(PREFIX_TMPMV));
gapp.addInstruction(new GAPPResetMv(mv, 1));
return new GAPPMultivectorComponent(mv.getName(), 0);
}
/**
* Creates a new GAPPVector
* @return The new GAPPVector
*/
private GAPPVector createVe() {
return new GAPPVector(createTMP(PREFIX_VE));
}
@Override
public Object visitProduct(Product product, Object arg) {
DotProduct dp = new DotProduct();
dp.setNegated(product.isNegated());
int factorNo = 0;
for (ParallelObject obj : product.getFactors()) {
dp.set(0, factorNo, obj);
factorNo++;
}
return dp.accept(this, arg);
}
@Override
public Object visitVariable(ParVariable variable, Object arg) {
throw new IllegalStateException("Variable should not appear in GAPPCreator!");
}
@Override
public Object visitExtCalculation(ExtCalculation extCalculation, Object arg) {
//arg must be filled! Note that this method is only called for scalar destinations!
GAPPMultivectorComponent destination = (GAPPMultivectorComponent) arg;
GAPPMultivectorComponent altDestination = destination;
if (extCalculation.isNegated()) {
destination = createMvComp();
}
if (!extCalculation.getOperand1().isTerminal()) {
GAPPMultivector mvTmp1 = createMv();
GAPPMultivectorComponent gMvC1 = new GAPPMultivectorComponent(mvTmp1.getName(), 0);
extCalculation.getOperand1().accept(this, gMvC1);
extCalculation.setOperand1(new MvComponent(new MultivectorComponent(mvTmp1.getName(), 0)));
}
if (extCalculation.getOperand2() != null) {
if (!extCalculation.getOperand2().isTerminal()) {
GAPPMultivector mvTmp2 = createMv();
GAPPMultivectorComponent gMvC2 = new GAPPMultivectorComponent(mvTmp2.getName(), 0);
extCalculation.getOperand2().accept(this, gMvC2);
extCalculation.setOperand2(new MvComponent(new MultivectorComponent(mvTmp2.getName(), 0)));
}
}
gapp.addInstruction(new GAPPCalculateMvCoeff(extCalculation.getType(),
destination,
createMultivectorFromParallelObjectTerminal(extCalculation.getOperand1()),
(extCalculation.getOperand2() == null)
? null
: createMultivectorFromParallelObjectTerminal(extCalculation.getOperand2())));
if (extCalculation.isNegated()) {
PosSelectorset selDest = new PosSelectorset();
selDest.add(new PosSelector(altDestination.getBladeIndex(), algebra.getBlade(altDestination.getBladeIndex()).toString()));
Selectorset selSrc = new Selectorset();
selSrc.add(new Selector(destination.getBladeIndex(), (byte) -1, algebra.getBlade(destination.getBladeIndex()).toString()));
GAPPSetMv setMv = new GAPPSetMv(
new GAPPMultivector(altDestination.getName()),
new GAPPMultivector(destination.getName()),
selDest, selSrc);
gapp.addInstruction(setMv);
}
return null;
}
/**
* Creates a new GAPPMultivector from ParallelObject which is a terminal
* @param object The ParallelObject which is a terminal
* @return The new GAPPMultivector
*/
private GAPPMultivector createMultivectorFromParallelObjectTerminal(ParallelObject object) {
GAPPMultivectorCreator creator = new GAPPMultivectorCreator(this, bladeCount, algebra);
return (GAPPMultivector) object.accept(creator, null);
}
@Override
public Object visitConstant(Constant constant, Object arg) {
//arg must be filled!
GAPPMultivectorComponent destination = (GAPPMultivectorComponent) arg;
PosSelectorset selSet = new PosSelectorset();
selSet.add(new PosSelector(destination.getBladeIndex(), algebra.getBlade(destination.getBladeIndex()).toString()));
Valueset valSet = new Valueset();
valSet.add(new GAPPConstant(((constant.isNegated()) ? -1 : 1) * constant.getValue()));
gapp.addInstruction(new GAPPAssignMv(new GAPPMultivector(destination.getName()), selSet, valSet));
return null;
}
@Override
public Object visitMvComponent(MvComponent mvComponent, Object arg) {
//arg must be filled!
GAPPMultivectorComponent destination = (GAPPMultivectorComponent) arg;
PosSelectorset selDestSet = new PosSelectorset();
selDestSet.add(new PosSelector(destination.getBladeIndex(), algebra.getBlade(destination.getBladeIndex()).toString()));
Selectorset selSrcSet = new Selectorset();
selSrcSet.add(new Selector(
mvComponent.getMultivectorComponent().getBladeIndex(),
(mvComponent.isNegated()) ? (byte) -1 : (byte) 1,
algebra.getBlade(mvComponent.getMultivectorComponent().getBladeIndex()).toString()));
gapp.addInstruction(new GAPPSetMv(
new GAPPMultivector(destination.getName()),
new GAPPMultivector(mvComponent.getMultivectorComponent().getName()),
selDestSet, selSrcSet));
return null;
}
@Override
public Object visitDotProduct(DotProduct dotProduct, Object arg) {
//make all inner elements to terminals
for (int row = 0; row < dotProduct.getHeight(); row++) {
for (int col = 0; col < dotProduct.getWidth(); col++) {
if (!dotProduct.get(row, col).isTerminal()) {
ParallelObject nonTerminalObj = dotProduct.get(row, col);
GAPPMultivector mvTmp = createMv();
GAPPMultivectorComponent gMvC = new GAPPMultivectorComponent(mvTmp.getName(), 0);
nonTerminalObj.accept(this, gMvC);
dotProduct.set(row, col, new MvComponent(new MultivectorComponent(mvTmp.getName(), 0)));
}
}
}
//now all inner elements are terminals
//transformation is now easier
//optimize order in every row
if (USE_DOTPRODUCT_OPTIMIZER) {
new DotProductOptimizer().optimizeOrder(dotProduct);
}
GAPPMultivectorComponent destination = (arg == null)
? createMvComp()
: (GAPPMultivectorComponent) arg;
GAPPMultivectorComponent altDestination = destination;
if (dotProduct.isNegated()) {
destination = createMvComp();
}
//create vectors for GAPPDotProduct
LinkedList<GAPPVector> parts = new LinkedList<GAPPVector>();
GAPPDotVectors dotVectors = new GAPPDotVectors(destination, parts, algebra.getBlade(destination.getBladeIndex()).toString());
for (ParallelVector vector : dotProduct.getFactors()) {
parts.add(createVectorFromParallelVector(vector));
}
gapp.addInstruction(dotVectors);
if (dotProduct.isNegated()) {
PosSelectorset selDest = new PosSelectorset();
selDest.add(new PosSelector(altDestination.getBladeIndex(), algebra.getBlade(altDestination.getBladeIndex()).toString()));
Selectorset selSrc = new Selectorset();
selSrc.add(new Selector(destination.getBladeIndex(), (byte) -1, algebra.getBlade(destination.getBladeIndex()).toString()));
GAPPSetMv setMv = new GAPPSetMv(
new GAPPMultivector(altDestination.getName()),
new GAPPMultivector(destination.getName()),
selDest, selSrc);
gapp.addInstruction(setMv);
}
return (arg == null) ? destination : null;
}
/**
* Creates a GAPPVector from a ParallelVector
* @param vector The ParallelVector
* @return The new GAPPVector
*/
private GAPPVector createVectorFromParallelVector(ParallelVector vector) {
GAPPVector destination = createVe();
//It may occour:
// - MvComponent
// - Constant
LinkedList<SetVectorArgument> list = new LinkedList<SetVectorArgument>();
SetVectorArgument last = null;
for (ParallelObject object : vector.getSlots()) {
switch (ParallelObjectType.getType(object)) {
case constant:
last = new ConstantSetVectorArgument(((object.isNegated()) ? -1 : 1) * ((Constant) object).getValue());
list.add(last);
break;
case mvComponent:
MultivectorComponent mvC = ((MvComponent) object).getMultivectorComponent();
Selector sel = new Selector(mvC.getBladeIndex(), object.isNegated() ? (byte) -1 : (byte) 1, algebra.getBlade(mvC.getBladeIndex()).toString());
if (last != null && !last.isConstant()) {
PairSetOfVariablesAndIndices pair = (PairSetOfVariablesAndIndices) last;
if (pair.getSetOfVariable().getName().equals(mvC.getName())) {
//merge
pair.getSelectors().add(sel);
} else {
Selectorset selSet = new Selectorset();
selSet.add(sel);
last = new PairSetOfVariablesAndIndices(new GAPPMultivector(mvC.getName()), selSet);
list.add(last);
}
} else {
Selectorset selSet = new Selectorset();
selSet.add(sel);
last = new PairSetOfVariablesAndIndices(new GAPPMultivector(mvC.getName()), selSet);
list.add(last);
}
break;
default:
System.err.println("createVectorFromParallelVector for "+ParallelObjectType.getType(object)+" is not implemented!");
break;
}
}
gapp.addInstruction(new GAPPSetVector(destination, list));
return destination;
}
// ========================= Illegal methods ===============================
@Override
public Object visitSum(Sum sum, Object arg) {
throw new IllegalStateException("Sums should have been removed by DotProductCreator&Finder");
}
}