Search in sources :

Example 1 with Add

use of gov.sandia.n2a.language.operator.Add in project n2a by frothga.

the class Variable method flattenExpressions.

public void flattenExpressions(Variable v) {
    if (assignment != v.assignment && !(// This line and the next say that * and / are compatible with each other, so ignore that case.
    (assignment == MULTIPLY && v.assignment == DIVIDE) || (assignment == DIVIDE && v.assignment == MULTIPLY))) {
        Backend.err.get().println("WARNING: Flattened variable " + v.container.prefix() + "." + v.nameString() + " has different combining operator than target (" + container.prefix() + "." + nameString() + "). Resolving in favor of higher-precedence operator.");
        v.assignment = assignment = Math.max(v.assignment, assignment);
    }
    if (v.assignment == REPLACE) {
        // We want equations from the lower level to override any pre-existing equations in the upper level.
        // Why? Because the lower-level equations represent an elaboration of the model, and are thus more specific.
        // Note that Internal executes contained populations after the upper-level equations, so the contained
        // populations take precedence even without flattening.
        NavigableSet<EquationEntry> equations0 = equations;
        equations = new TreeSet<EquationEntry>();
        // First add the lower-level equations, so they take precedence.
        for (EquationEntry e2 : v.equations) add(e2);
        for (EquationEntry e0 : equations0) add(e0);
    } else {
        // For combiners, it is necessary to create new equations for every combination of conditions.
        // Of course, unconditional equations and equations with matching conditions can be combined more directly.
        // First step is to augment both equation sets with an unconditional form, if they lack it.
        EquationEntry query = new EquationEntry(this, "");
        EquationEntry e = find(query);
        // expression and condition are null; we deal with this below
        if (e == null)
            add(query);
        query = new EquationEntry(v, "");
        e = v.find(query);
        if (e == null)
            v.add(query);
        NavigableSet<EquationEntry> equations0 = equations;
        equations = new TreeSet<EquationEntry>();
        for (EquationEntry e0 : equations0) {
            for (EquationEntry e1 : v.equations) {
                if (// Condition strings are exactly the same. TODO: compare ASTs for actual logic equivalence.
                e0.compareTo(e1) == 0) {
                    e = new EquationEntry(this, "");
                    e.condition = e0.condition;
                } else if (e0.condition == null) {
                    // If so, then only those equations should be merged, so skip this one.
                    if (find(e1) != null)
                        continue;
                    e = new EquationEntry(this, "");
                    e.condition = e1.condition;
                } else if (e1.condition == null) {
                    // Check if e0.condition exists in v.equations
                    if (v.find(e0) != null)
                        continue;
                    e = new EquationEntry(this, "");
                    e.condition = e0.condition;
                } else {
                    e = new EquationEntry(this, "");
                    AND and = new AND();
                    e.condition = and;
                    and.operand0 = e0.condition;
                    and.operand1 = e1.condition;
                }
                if (e.condition != null)
                    e.ifString = e.condition.render();
                // merge expressions
                if (e0.expression == null) {
                    // which could also be null
                    e.expression = e1.expression;
                } else if (e1.expression == null) {
                    e.expression = e0.expression;
                } else // Both expressions exist
                {
                    OperatorBinary op = null;
                    Function f = null;
                    switch(v.assignment) {
                        case ADD:
                            op = new Add();
                            break;
                        case MULTIPLY:
                            op = new Multiply();
                            break;
                        case DIVIDE:
                            op = new Divide();
                            break;
                        case MIN:
                            f = new Min();
                            break;
                        case MAX:
                            f = new Max();
                            break;
                    }
                    if (op != null) {
                        op.operand0 = e0.expression;
                        op.operand1 = e1.expression;
                        e.expression = op;
                    } else if (f != null) {
                        f.operands[0] = e0.expression;
                        f.operands[1] = e1.expression;
                        e.expression = f;
                    }
                }
                if (e.expression != null)
                    equations.add(e);
            }
        }
    }
    v.equations.clear();
}
Also used : Add(gov.sandia.n2a.language.operator.Add) Function(gov.sandia.n2a.language.Function) Divide(gov.sandia.n2a.language.operator.Divide) Min(gov.sandia.n2a.language.function.Min) Max(gov.sandia.n2a.language.function.Max) AND(gov.sandia.n2a.language.operator.AND) Multiply(gov.sandia.n2a.language.operator.Multiply) OperatorBinary(gov.sandia.n2a.language.OperatorBinary)

Example 2 with Add

use of gov.sandia.n2a.language.operator.Add in project n2a by frothga.

the class Output method isStringExpression.

/**
 *        Determines if the given operator is a string expression.
 *        This is the case if any operator it depends on is a string.
 *        If an operand is a variable, then its equations must contain a string.
 */
public static boolean isStringExpression(Variable v, Operator op) {
    class StringVisitor extends Visitor {

        boolean foundString;

        Variable from;

        public StringVisitor(Variable from) {
            this.from = from;
            from.visited = null;
        }

        public boolean visit(Operator op) {
            if (op instanceof Constant) {
                Constant c = (Constant) op;
                if (c.value instanceof Text)
                    foundString = true;
                return false;
            }
            if (op instanceof AccessVariable) {
                AccessVariable av = (AccessVariable) op;
                Variable v = av.reference.variable;
                // Prevent infinite recursion
                Variable p = from;
                while (p != null) {
                    if (p == v)
                        return false;
                    p = p.visited;
                }
                v.visited = from;
                from = v;
                v.visit(this);
                from = v.visited;
                return false;
            }
            // no reason to dig any further
            if (foundString)
                return false;
            // Add is the only operator that can propagate string values. All other operators and functions return scalars or matrices.
            return op instanceof Add;
        }
    }
    StringVisitor visitor = new StringVisitor(v);
    op.visit(visitor);
    return visitor.foundString;
}
Also used : Operator(gov.sandia.n2a.language.Operator) Add(gov.sandia.n2a.language.operator.Add) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) Text(gov.sandia.n2a.language.type.Text)

Example 3 with Add

use of gov.sandia.n2a.language.operator.Add in project n2a by frothga.

the class JobC method prepareDynamicObjects.

/**
 *        Build complex sub-expressions into a single local variable that can be referenced by the equation.
 */
public void prepareDynamicObjects(Operator op, final CRenderer context, final boolean init, final String pad) throws Exception {
    // Pass 1 -- Strings and matrix expressions
    Visitor visitor1 = new Visitor() {

        public boolean visit(Operator op) {
            if (op instanceof BuildMatrix) {
                BuildMatrix m = (BuildMatrix) op;
                int rows = m.getRows();
                int cols = m.getColumns();
                String matrixName = "Matrix" + matrixNames.size();
                matrixNames.put(m, matrixName);
                if (rows == 3 && cols == 1)
                    context.result.append(pad + "Vector3 " + matrixName + ";\n");
                else
                    context.result.append(pad + "Matrix<float> " + matrixName + " (" + rows + ", " + cols + ");\n");
                for (int r = 0; r < rows; r++) {
                    if (cols == 1) {
                        context.result.append(pad + matrixName + "[" + r + "] = ");
                        m.operands[0][r].render(context);
                        context.result.append(";\n");
                    } else {
                        for (int c = 0; c < cols; c++) {
                            context.result.append(pad + matrixName + "(" + r + "," + c + ") = ");
                            m.operands[c][r].render(context);
                            context.result.append(";\n");
                        }
                    }
                }
                return false;
            }
            if (op instanceof Add) {
                Add a = (Add) op;
                String stringName = stringNames.get(a);
                if (stringName != null) {
                    context.result.append(pad + "String " + stringName + ";\n");
                    for (Operator o : flattenAdd(a)) {
                        context.result.append(pad + stringName + " += ");
                        o.render(context);
                        context.result.append(";\n");
                    }
                    return false;
                }
            }
            return true;
        }
    };
    op.visit(visitor1);
    // Pass 2 -- Input functions
    Visitor visitor2 = new Visitor() {

        public boolean visit(Operator op) {
            if (op instanceof ReadMatrix) {
                ReadMatrix r = (ReadMatrix) op;
                if (!(r.operands[0] instanceof Constant)) {
                    String matrixName = matrixNames.get(r);
                    String stringName = stringNames.get(r.operands[0]);
                    context.result.append(pad + "MatrixInput * " + matrixName + " = matrixHelper (" + stringName + ");\n");
                }
                return false;
            }
            if (op instanceof Input) {
                Input i = (Input) op;
                if (!(i.operands[0] instanceof Constant)) {
                    String inputName = inputNames.get(i);
                    String stringName = stringNames.get(i.operands[0]);
                    context.result.append(pad + "InputHolder * " + inputName + " = inputHelper (" + stringName + ");\n");
                    if (!context.global) {
                        context.result.append(pad + inputName + "->epsilon = " + resolve(context.bed.dt.reference, context, false) + " / 1000;\n");
                    }
                    // Detect time flag
                    String mode = "";
                    if (i.operands.length > 3) {
                        // just assuming it's a constant string
                        mode = i.operands[3].toString();
                    } else if (i.operands[1] instanceof Constant) {
                        Constant c = (Constant) i.operands[1];
                        if (c.value instanceof Text)
                            mode = c.toString();
                    }
                    if (mode.contains("time")) {
                        context.result.append(pad + inputName + "->time = true;\n");
                    }
                }
                // I/O functions can be nested
                return true;
            }
            if (op instanceof Output) {
                Output o = (Output) op;
                if (!(o.operands[0] instanceof Constant)) {
                    String outputName = outputNames.get(o);
                    String stringName = stringNames.get(o.operands[0]);
                    context.result.append(pad + "OutputHolder * " + outputName + " = outputHelper (" + stringName + ");\n");
                    // Detect raw flag
                    if (o.operands.length > 3) {
                        Operator op3 = o.operands[3];
                        if (op3 instanceof Constant) {
                            if (op3.toString().contains("raw")) {
                                context.result.append(pad + outputName + "->raw = true;\n");
                            }
                        }
                    }
                }
                return true;
            }
            return true;
        }
    };
    op.visit(visitor2);
}
Also used : Operator(gov.sandia.n2a.language.Operator) Add(gov.sandia.n2a.language.operator.Add) Input(gov.sandia.n2a.language.function.Input) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) BuildMatrix(gov.sandia.n2a.language.BuildMatrix) Output(gov.sandia.n2a.language.function.Output) Text(gov.sandia.n2a.language.type.Text) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix)

Aggregations

Add (gov.sandia.n2a.language.operator.Add)3 Constant (gov.sandia.n2a.language.Constant)2 Operator (gov.sandia.n2a.language.Operator)2 Visitor (gov.sandia.n2a.language.Visitor)2 Text (gov.sandia.n2a.language.type.Text)2 Variable (gov.sandia.n2a.eqset.Variable)1 AccessVariable (gov.sandia.n2a.language.AccessVariable)1 BuildMatrix (gov.sandia.n2a.language.BuildMatrix)1 Function (gov.sandia.n2a.language.Function)1 OperatorBinary (gov.sandia.n2a.language.OperatorBinary)1 Input (gov.sandia.n2a.language.function.Input)1 Max (gov.sandia.n2a.language.function.Max)1 Min (gov.sandia.n2a.language.function.Min)1 Output (gov.sandia.n2a.language.function.Output)1 ReadMatrix (gov.sandia.n2a.language.function.ReadMatrix)1 AND (gov.sandia.n2a.language.operator.AND)1 Divide (gov.sandia.n2a.language.operator.Divide)1 Multiply (gov.sandia.n2a.language.operator.Multiply)1