package de.gaalop.gapp.executer; import de.gaalop.gapp.ConstantSetVectorArgument; 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.instructionSet.GAPPAssignMv; import de.gaalop.gapp.instructionSet.GAPPAssignInputsVector; import de.gaalop.gapp.instructionSet.GAPPCalculateMv; 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.GAPPValueHolder; import de.gaalop.gapp.variables.GAPPVariable; import de.gaalop.gapp.variables.GAPPVector; import de.gaalop.gapp.visitor.CFGGAPPVisitor; import java.util.Arrays; import java.util.HashMap; /** * GAPP Visitor to execute (simulate) a GAPP Program * @author Christian Steinmetz */ public class Executer extends CFGGAPPVisitor { /** * Maps names of multivectors to their values */ private HashMap<String, MultivectorWithValues> values = new HashMap<String, MultivectorWithValues>(); /** * Maps the scalar inputs to their values */ private HashMap<String, Double> inputValues; /** * Returns the MultivectorWithValues object which stores the current values * of the multivector with a specific name * @param name The name of the multivector whose values were returned * @return The values of the multivector with the given name */ public MultivectorWithValues getValue(String name) { return values.get(name); } public HashMap<String, MultivectorWithValues> getValues() { return values; } public Executer(HashMap<String, Double> inputValues) { this.inputValues = inputValues; } /** * Returns the MultivectorWithValues object which stores the current values * of the multivector with a specific name, if it exits in values map, or create a new values object otherwise. * * The possible new values object will be putted in the values map * * The difference to the public method getValue is that this method creates a new values object, * if the multivector with the given name is not in values map * * @param name The name of the multivector whose values were returned * @return The values of the multlivector with the given name */ private MultivectorWithValues getMultivector(String name) { if (values.containsKey(name)) { return values.get(name); } else { System.err.println("Multivector " + name + " does not exist!"); return null; } } /** * Creates a vector with a name and a size * @param name The name * @param size The size */ private void createVector(String name, int size) { values.put(name, new MultivectorWithValues(size, false)); } /** * Returns the value of the scalar input variable with a specific name * @param name The name of the scalar input variable * @return The value of the calar input variable with the given name */ private double getVariableValue(String name) { return inputValues.get(name); } @Override public Object visitResetMv(GAPPResetMv gappResetMv, Object arg) { MultivectorWithValues mv = new MultivectorWithValues(gappResetMv.getSize(),true); values.put(gappResetMv.getDestination().getName(), mv); mv.clear(); return null; } @Override public Object visitSetMv(GAPPSetMv gappSetMv, Object arg) { MultivectorWithValues destination = getMultivector(gappSetMv.getDestination().getName()); MultivectorWithValues source = getMultivector(gappSetMv.getSource().getName()); Selectorset selSrc = gappSetMv.getSelectorsSrc(); PosSelectorset selDest = gappSetMv.getSelectorsDest(); int selCount = gappSetMv.getSelectorsSrc().size(); for (int sel = 0; sel < selCount; sel++) { PosSelector sDest = selDest.get(sel); Selector sSrc = selSrc.get(sel); destination.getEntries()[sDest.getIndex()] = sSrc.getSign() * source.getEntries()[sSrc.getIndex()]; } return null; } @Override public Object visitDotVectors(GAPPDotVectors gappDotVectors, Object arg) { MultivectorWithValues destination = getMultivector(gappDotVectors.getDestination().getName()); // calculate the dot product double sum = 0; int size = getMultivector(gappDotVectors.getParts().getFirst().getName()).getEntries().length; for (int slot = 0; slot < size; slot++) { double prod = 1; for (GAPPVector part : gappDotVectors.getParts()) { prod *= getMultivector(part.getName()).getEntry(slot); } sum += prod; } Selector sDest = gappDotVectors.getDestSelector(); destination.setEntry(sDest.getIndex(), sDest.getSign() * sum); return null; } @Override public Object visitSetVector(GAPPSetVector gappSetVector, Object arg) { //estimiate size int size = 0; for (SetVectorArgument curArg: gappSetVector.getEntries()) { if (curArg.isConstant()) { //ConstantSetVectorArgument c = (ConstantSetVectorArgument) curArg; size += 1; } else { PairSetOfVariablesAndIndices p = (PairSetOfVariablesAndIndices) curArg; size += p.getSelectors().size(); } } String destName = gappSetVector.getDestination().getName(); createVector(destName, size); MultivectorWithValues destination = getMultivector(destName); destination.setEntries(new double[size]); int i = 0; for (SetVectorArgument curArg: gappSetVector.getEntries()) { if (curArg.isConstant()) { ConstantSetVectorArgument c = (ConstantSetVectorArgument) curArg; destination.setEntry(i, c.getValue()); i++; } else { PairSetOfVariablesAndIndices p = (PairSetOfVariablesAndIndices) curArg; MultivectorWithValues source = getMultivector(p.getSetOfVariable().getName()); for (Selector sel: p.getSelectors()) { destination.setEntry(i, sel.getSign() * source.getEntries()[sel.getIndex()]); i++; } } } return null; } @Override public Object visitAssignMv(GAPPAssignMv gappAssignMv, Object arg) { MultivectorWithValues destination = getMultivector(gappAssignMv.getDestination().getName()); PosSelectorset selector = gappAssignMv.getSelectors(); int selCount = selector.size(); for (int sel = 0; sel < selCount; sel++) { GAPPValueHolder scalarVar = gappAssignMv.getValues().get(sel); double value = (scalarVar.isVariable()) ? getVariableValue(((GAPPVariable) scalarVar).getName()) : ((GAPPConstant) scalarVar).getValue(); destination.getEntries()[selector.get(sel).getIndex()] = value; } return null; } @Override public Object visitCalculateMv(GAPPCalculateMv gappCalculate, Object arg) { MultivectorWithValues mv1 = getMultivector(gappCalculate.getOperand1().getName()); double op1 = mv1.getEntry(0); MultivectorWithValues mv2 = null; double op2 = 0; if (gappCalculate.getOperand2() != null) { mv2 = getMultivector(gappCalculate.getOperand2().getName()); op2 = mv2.getEntry(0); } MultivectorWithValues target = getMultivector(gappCalculate.getDestination().getName()); double result; switch (gappCalculate.getType()) { case ABS: result = Math.abs(op1); break; case ACOS: result = Math.acos(op1); break; case ASIN: result = Math.asin(op1); break; case ATAN: result = Math.atan(op1); break; case CEIL: result = Math.ceil(op1); break; case COS: result = Math.cos(op1); break; case DIVISION: result = op1 / op2; break; case EXP: result = Math.exp(op1); break; case EXPONENTIATION: result = Math.pow(op1, op2); break; case FACT: result = 1; for (int i = 2; i <= (int) op1; i++) { result *= i; } break; case FLOOR: result = Math.floor(op1); break; case LOG: result = Math.log(op1); break; case SIN: result = Math.sin(op1); break; case SQRT: result = Math.sqrt(op1); break; case TAN: result = Math.tan(op1); break; default: throw new UnsupportedOperationException("Executer: " + gappCalculate.getType() + " is not supported yet."); } target.setEntry(0, result); return null; } /** * Prints all values, vectors and their contents. * * This is used commonly for debug purposes. */ public void printAllValues() { String[] keys = values.keySet().toArray(new String[0]); Arrays.sort(keys); for (String m : keys) { System.out.println(m + " = " + Arrays.toString(values.get(m).getEntries())); } } @Override public Object visitAssignInputsVector(GAPPAssignInputsVector gappAssignInputsVector, Object arg) { int size = gappAssignInputsVector.getValues().size(); String name = "inputsVector"; createVector(name, size); MultivectorWithValues destination = getMultivector(name); for (int sel = 0; sel < size; sel++) { GAPPValueHolder scalarVar = gappAssignInputsVector.getValues().get(sel); double value = (scalarVar.isVariable()) ? getVariableValue(((GAPPVariable) scalarVar).getName()) : ((GAPPConstant) scalarVar).getValue(); destination.getEntries()[sel] = value; } return null; } @Override public Object visitCalculateMvCoeff(GAPPCalculateMvCoeff gappCalculateCoeff, Object arg) { MultivectorWithValues mv1 = getMultivector(gappCalculateCoeff.getOperand1().getName()); double op1 = mv1.getEntry(0); MultivectorWithValues mv2 = null; double op2 = 0; if (gappCalculateCoeff.getOperand2() != null) { mv2 = getMultivector(gappCalculateCoeff.getOperand2().getName()); op2 = mv2.getEntry(0); } MultivectorWithValues target = getMultivector(gappCalculateCoeff.getDestination().getName()); double result; switch (gappCalculateCoeff.getType()) { case ABS: result = Math.abs(op1); break; case ACOS: result = Math.acos(op1); break; case ASIN: result = Math.asin(op1); break; case ATAN: result = Math.atan(op1); break; case CEIL: result = Math.ceil(op1); break; case COS: result = Math.cos(op1); break; case DIVISION: result = op1 / op2; break; case EXP: result = Math.exp(op1); break; case EXPONENTIATION: result = Math.pow(op1, op2); break; case FACT: result = 1; for (int i = 2; i <= (int) op1; i++) { result *= i; } break; case FLOOR: result = Math.floor(op1); break; case LOG: result = Math.log(op1); break; case SIN: result = Math.sin(op1); break; case SQRT: result = Math.sqrt(op1); break; case TAN: result = Math.tan(op1); break; default: throw new UnsupportedOperationException("Executer: " + gappCalculateCoeff.getType() + " is not supported yet."); } target.setEntry(gappCalculateCoeff.getDestination().getBladeIndex(), result); return null; } }