use of gov.sandia.n2a.language.type.Text in project n2a by frothga.
the class BuildMatrix method simplify.
public Operator simplify(Variable from, boolean evalOnly) {
int cols = operands.length;
if (cols == 0)
return this;
int rows = operands[0].length;
if (rows == 0)
return this;
// potential constant to replace us
Matrix A = new MatrixDense(rows, cols);
// any element that is not constant will change this to false
boolean isConstant = true;
// for fixed-point analysis
int cent = 0;
int pow = 0;
int count = 0;
for (int c = 0; c < cols; c++) {
for (int r = 0; r < rows; r++) {
if (operands[c][r] == null) {
A.set(r, c, 0);
} else {
operands[c][r] = operands[c][r].simplify(from, evalOnly);
// stop building A if we already know we are not constant
if (!isConstant)
continue;
if (operands[c][r] instanceof Constant) {
Constant op = (Constant) operands[c][r];
Type o = op.value;
if (o instanceof Scalar) {
double v = ((Scalar) o).value;
A.set(r, c, v);
if (v != 0) {
int tempCent = MSB / 2;
if (op.unitValue != null) {
int bits = (int) Math.ceil(op.unitValue.digits * Math.log(10) / Math.log(2));
tempCent = Math.max(tempCent, bits - 1);
tempCent = Math.min(tempCent, MSB);
}
cent += tempCent;
pow += Math.getExponent(v);
count++;
}
} else if (o instanceof Text)
A.set(r, c, Double.valueOf(((Text) o).value));
else if (o instanceof Matrix)
A.set(r, c, ((Matrix) o).get(0, 0));
else
throw new EvaluationException("Can't construct matrix element from the given type.");
} else {
isConstant = false;
}
}
}
}
if (isConstant) {
from.changed = true;
Constant result = new Constant(A);
result.parent = parent;
if (count > 0) {
cent /= count;
pow /= count;
result.center = cent;
result.exponent = pow + MSB - cent;
} else {
result.center = MSB / 2;
result.exponent = MSB - result.center;
}
return result;
}
return this;
}
use of gov.sandia.n2a.language.type.Text in project n2a by frothga.
the class Input method eval.
public Type eval(Instance context) {
double line = Double.NEGATIVE_INFINITY;
Type op1 = null;
if (operands.length > 1)
op1 = operands[1].eval(context);
if (op1 instanceof Scalar)
line = ((Scalar) op1).value;
Holder H = getRow(context, line);
if (H == null)
return getType();
int c = -1;
boolean namedColumn = false;
if (operands.length > 2) {
Type columnSpec = operands[2].eval(context);
if (columnSpec instanceof Text) {
Integer columnMapping = H.columnMap.get(((Text) columnSpec).value);
if (columnMapping == null)
return new Scalar(0);
c = columnMapping;
namedColumn = true;
} else // Otherwise, just assume it is a Scalar
{
c = (int) Math.round(((Scalar) columnSpec).value);
}
}
int columns = H.currentValues.length;
int lastColumn = columns - 1;
if (H.smooth && line >= H.currentLine && Double.isFinite(H.currentLine) && !Double.isNaN(H.nextLine)) {
// This should still work, even if line < H.currentLine.
double b = (line - H.currentLine) / (H.nextLine - H.currentLine);
double b1 = 1 - b;
if (c >= 0) {
// time column is not included in raw index
if (H.time && !namedColumn && c >= H.timeColumn)
c++;
if (c >= columns)
c = lastColumn;
return new Scalar(b * H.nextValues[c] + b1 * H.currentValues[c]);
} else {
if (H.Alast == line)
return H.A;
// Create a new matrix
if (columns > 1) {
columns--;
H.A = new MatrixDense(1, columns);
int from = 0;
for (int to = 0; to < columns; to++) {
if (from == H.timeColumn)
from++;
H.A.set(0, to, b * H.nextValues[from] + b1 * H.currentValues[from]);
from++;
}
} else // There is always at least 1 column, enforced by Holder.
{
H.A = new MatrixDense(1, 1);
H.A.set(0, 0, b * H.nextValues[0] + b1 * H.currentValues[0]);
}
H.Alast = line;
return H.A;
}
} else {
if (c >= 0) {
// time column is not included in raw index
if (H.time && !namedColumn && c >= H.timeColumn)
c++;
if (c >= columns)
c = lastColumn;
return new Scalar(H.currentValues[c]);
} else {
if (H.Alast == H.currentLine)
return H.A;
// Create a new matrix
if (H.time && columns > 1) {
columns--;
H.A = new MatrixDense(1, columns);
int from = 0;
for (int to = 0; to < columns; to++) {
if (from == H.timeColumn)
from++;
H.A.set(0, to, H.currentValues[from++]);
}
} else {
H.A = new MatrixDense(H.currentValues, 0, 1, columns, columns, 1);
}
H.Alast = H.currentLine;
return H.A;
}
}
}
use of gov.sandia.n2a.language.type.Text in project n2a by frothga.
the class RendererPython method render.
public boolean render(Operator op) {
if (op instanceof Add) {
Add a = (Add) op;
// Check if this is a string expression
if (a.name != null) {
result.append(a.name);
return true;
}
return false;
}
if (op instanceof AccessElement) {
AccessElement ae = (AccessElement) op;
ae.operands[0].render(this);
if (ae.operands.length >= 2) {
result.append("[");
ae.operands[1].render(this);
if (ae.operands.length >= 3) {
result.append(",");
ae.operands[2].render(this);
}
result.append("]");
}
return true;
}
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
result.append(job.resolve(av.reference, this, false));
return true;
}
if (op instanceof AND) {
AND and = (AND) op;
and.render(this, " and ");
return true;
}
if (op instanceof BuildMatrix) {
BuildMatrix b = (BuildMatrix) op;
result.append(b.name);
return true;
}
if (op instanceof Constant) {
Constant c = (Constant) op;
Type o = c.value;
if (o instanceof Scalar) {
result.append(print(((Scalar) o).value));
return true;
}
if (o instanceof Text) {
result.append("\"" + o.toString() + "\"");
return true;
}
if (o instanceof Matrix) {
result.append(c.name);
return true;
}
return false;
}
if (op instanceof Event) {
Event e = (Event) op;
// The cast to bool gets rid of the specific numeric value from flags.
// If used in a numeric expression, it will convert to either 1 or 0.
result.append("bool (flags & 0x1 << " + e.eventType.valueIndex + ")");
return true;
}
if (op instanceof Exp) {
Exp e = (Exp) op;
Operator a = e.operands[0];
result.append("exp(");
a.render(this);
result.append(")");
return true;
}
if (op instanceof Gaussian) {
Gaussian g = (Gaussian) op;
result.append("gaussian(");
if (g.operands.length > 0) {
g.operands[0].render(this);
}
result.append(")");
return true;
}
if (op instanceof Grid) {
// TODO: needs library implementation
Grid g = (Grid) op;
boolean raw = g.operands.length >= 5 && g.operands[4].getString().contains("raw");
result.append("grid");
if (raw)
result.append("Raw");
result.append("(");
int count = Math.min(4, g.operands.length);
if (count > 0)
g.operands[0].render(this);
for (int i = 1; i < count; i++) {
result.append(", ");
g.operands[i].render(this);
}
result.append(")");
return true;
}
if (op instanceof Input) {
// TODO: needs library implementation
Input i = (Input) op;
String mode = "";
if (i.operands.length == 2)
mode = i.operands[1].getString();
else if (i.operands.length >= 4)
mode = i.operands[3].getString();
if (mode.contains("columns")) {
result.append(i.name + "->getColumns ()");
} else {
Operator op1 = i.operands[1];
Operator op2 = i.operands[2];
result.append(i.name + ".get");
if (mode.contains("raw"))
result.append("Raw");
result.append("(");
op1.render(this);
result.append(", ");
op2.render(this);
result.append(")");
}
return true;
}
if (op instanceof Log) {
Log l = (Log) op;
Operator a = l.operands[0];
result.append("log(");
a.render(this);
return true;
}
if (op instanceof Modulo) {
Modulo m = (Modulo) op;
Operator a = m.operand0;
Operator b = m.operand1;
a.render(this);
result.append(" % ");
b.render(this);
return true;
}
if (op instanceof Norm) {
Norm n = (Norm) op;
Operator A = n.operands[0];
result.append("numpy.linalg.norm(");
A.render(this);
result.append(", ");
n.operands[1].render(this);
result.append(")");
return true;
}
if (op instanceof OR) {
OR or = (OR) op;
or.render(this, " or ");
return true;
}
if (op instanceof Output) {
Output o = (Output) op;
result.append(o.name + "->trace (Simulator::instance.currentEvent->t, ");
if (// column name is explicit
o.hasColumnName) {
o.operands[2].render(this);
} else // column name is generated, so use prepared string value
{
result.append(o.columnName);
}
result.append(", ");
o.operands[1].render(this);
result.append(")");
return true;
}
if (op instanceof Power) {
Power p = (Power) op;
Operator a = p.operand0;
Operator b = p.operand1;
result.append("pow(");
a.render(this);
result.append(", ");
b.render(this);
result.append(")");
return true;
}
if (op instanceof ReadMatrix) {
ReadMatrix r = (ReadMatrix) op;
String mode = "";
int lastParm = r.operands.length - 1;
if (lastParm > 0) {
if (r.operands[lastParm] instanceof Constant) {
Constant c = (Constant) r.operands[lastParm];
if (c.value instanceof Text) {
mode = ((Text) c.value).value;
}
}
}
if (mode.equals("rows")) {
result.append(r.name + "->rows ()");
} else if (mode.equals("columns")) {
result.append(r.name + "->columns ()");
} else {
result.append(r.name + "->get");
if (mode.equals("raw"))
result.append("Raw");
result.append("(");
r.operands[1].render(this);
result.append(", ");
r.operands[2].render(this);
result.append(")");
}
return true;
}
if (op instanceof SquareRoot) {
SquareRoot s = (SquareRoot) op;
Operator a = s.operands[0];
result.append("sqrt(");
a.render(this);
return true;
}
if (op instanceof Tangent) {
Tangent t = (Tangent) op;
Operator a = t.operands[0];
result.append("tan(");
a.render(this);
result.append(")");
return true;
}
if (op instanceof Uniform) {
Uniform u = (Uniform) op;
result.append("uniform(");
if (u.operands.length > 0) {
u.operands[0].render(this);
}
result.append(")");
return true;
}
return super.render(op);
}
use of gov.sandia.n2a.language.type.Text in project n2a by frothga.
the class RendererC method render.
public boolean render(Operator op) {
for (ProvideOperator po : job.extensions) {
Boolean result = po.render(this, op);
if (result != null)
return result;
}
if (op instanceof Add) {
Add a = (Add) op;
// Check if this is a string expression
if (a.name != null) {
result.append(a.name);
return true;
}
return false;
}
if (op instanceof AccessElement) {
AccessElement ae = (AccessElement) op;
ae.operands[0].render(this);
if (ae.operands.length == 2) {
result.append("[");
ae.operands[1].render(this);
result.append("]");
} else if (ae.operands.length == 3) {
result.append("(");
ae.operands[1].render(this);
result.append(",");
ae.operands[2].render(this);
result.append(")");
}
return true;
}
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
result.append(job.resolve(av.reference, this, false));
return true;
}
if (op instanceof Atan) {
Atan atan = (Atan) op;
int shift = atan.exponent - atan.exponentNext;
if (useExponent && shift != 0)
result.append("(");
if (atan.operands.length > 1 || useExponent)
result.append("atan2 (");
else
result.append("atan (");
Operator y = atan.operands[0];
if (y.getType() instanceof Matrix) {
y.render(this);
result.append("[1], ");
y.render(this);
result.append("[0]");
} else {
y.render(this);
if (atan.operands.length > 1) {
result.append(", ");
// x
atan.operands[1].render(this);
} else if (useExponent) {
int shiftX = Operator.MSB - y.exponent;
int x = shiftX >= 0 ? 0x1 << shiftX : 0;
result.append(", " + x);
}
}
result.append(")");
if (useExponent && shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (op instanceof BuildMatrix) {
BuildMatrix b = (BuildMatrix) op;
result.append(b.name);
return true;
}
if (op instanceof Columns) {
Columns c = (Columns) op;
c.operands[0].render(this);
result.append(".columns ()");
return true;
}
if (op instanceof Constant) {
Constant c = (Constant) op;
Type o = c.value;
if (o instanceof Scalar) {
result.append(print(((Scalar) o).value, c.exponentNext));
return true;
}
if (o instanceof Text) {
result.append("\"" + o.toString() + "\"");
return true;
}
if (o instanceof Matrix) {
result.append(c.name);
return true;
}
return false;
}
if (op instanceof Delay) {
Delay d = (Delay) op;
if (d.operands.length == 1) {
result.append("(");
d.operands[0].render(this);
result.append(")");
return true;
}
result.append("delay" + d.index + ".step (Simulator<" + job.T + ">::instance.currentEvent->t, ");
d.operands[1].render(this);
result.append(", ");
d.operands[0].render(this);
result.append(", ");
if (d.operands.length > 2)
d.operands[2].render(this);
else
result.append("0");
result.append(")");
return true;
}
if (op instanceof Event) {
Event e = (Event) op;
// The cast to bool gets rid of the specific numeric value from flags.
// If used in a numeric expression, it should convert to either 1 or 0.
result.append("((bool) (flags & (" + bed.localFlagType + ") 0x1 << " + e.eventType.valueIndex + "))");
return true;
}
if (op instanceof Exp) {
Exp e = (Exp) op;
Operator a = e.operands[0];
result.append("exp (");
a.render(this);
if (useExponent)
result.append(", " + e.exponentNext);
result.append(")");
return true;
}
if (op instanceof Gaussian) {
Gaussian g = (Gaussian) op;
result.append("gaussian<" + job.T + "> (");
if (g.operands.length > 0) {
g.operands[0].render(this);
}
result.append(")");
return true;
}
if (op instanceof Grid) {
Grid g = (Grid) op;
boolean raw = g.operands.length >= 5 && g.operands[4].getString().contains("raw");
int shift = g.exponent - g.exponentNext;
if (useExponent && shift != 0)
result.append("(");
result.append("grid");
if (raw)
result.append("Raw");
result.append("<" + job.T + "> (");
int count = Math.min(4, g.operands.length);
if (count > 0)
g.operands[0].render(this);
for (int i = 1; i < count; i++) {
result.append(", ");
g.operands[i].render(this);
}
result.append(")");
if (useExponent && shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (op instanceof HyperbolicTangent) {
HyperbolicTangent t = (HyperbolicTangent) op;
Operator a = t.operands[0];
result.append("tanh (");
a.render(this);
result.append(")");
return true;
}
if (op instanceof Input) {
Input i = (Input) op;
result.append(i.name + "->get (");
if (// return matrix
i.operands.length < 3 || i.operands[2].getDouble() < 0) {
boolean time = i.getMode().contains("time");
String defaultLine = time ? "-INFINITY" : "0";
if (i.operands.length > 1) {
Operator op1 = i.operands[1];
if (// expression for line
op1.getType() instanceof Scalar)
// expression for line
op1.render(this);
else
// op1 is probably the mode flag
result.append(defaultLine);
} else // line is not specified. We're probably just retrieving a dummy matrix to get column count.
{
result.append(defaultLine);
}
} else // return scalar
{
i.operands[1].render(this);
result.append(", ");
i.operands[2].render(this);
}
result.append(")");
return true;
}
if (op instanceof Log) {
Log l = (Log) op;
Operator a = l.operands[0];
result.append("log (");
a.render(this);
if (useExponent)
result.append(", " + a.exponentNext + ", " + l.exponentNext);
result.append(")");
return true;
}
if (op instanceof Max) {
Max m = (Max) op;
for (int i = 0; i < m.operands.length - 1; i++) {
Operator a = m.operands[i];
result.append("max (");
renderType(a);
result.append(", ");
}
Operator b = m.operands[m.operands.length - 1];
renderType(b);
for (int i = 0; i < m.operands.length - 1; i++) result.append(")");
return true;
}
if (op instanceof Min) {
Min m = (Min) op;
for (int i = 0; i < m.operands.length - 1; i++) {
Operator a = m.operands[i];
result.append("min (");
renderType(a);
result.append(", ");
}
Operator b = m.operands[m.operands.length - 1];
renderType(b);
for (int i = 0; i < m.operands.length - 1; i++) result.append(")");
return true;
}
if (op instanceof Modulo) {
Modulo m = (Modulo) op;
Operator a = m.operand0;
Operator b = m.operand1;
result.append("modFloor (");
moduloParam(a);
result.append(", ");
moduloParam(b);
result.append(")");
return true;
}
if (op instanceof Norm) {
Norm n = (Norm) op;
Operator A = n.operands[0];
result.append("norm (");
A.render(this);
result.append(", ");
n.operands[1].render(this);
if (useExponent)
result.append(", " + A.exponentNext + ", " + n.exponentNext);
result.append(")");
return true;
}
if (op instanceof Output) {
Output o = (Output) op;
result.append(o.name + "->trace (Simulator<" + job.T + ">::instance.currentEvent->t, ");
if (// column name is explicit
o.hasColumnName) {
o.operands[2].render(this);
} else // column name is generated, so use prepared string value
{
result.append(o.columnName);
}
result.append(", ");
o.operands[1].render(this);
if (useExponent)
result.append(", " + o.operands[1].exponentNext);
result.append(", ");
if (// No mode string
o.operands.length < 4) {
// null
result.append("0");
} else if (// Mode string is constant
o.operands[3] instanceof Constant) {
result.append("\"" + o.operands[3] + "\"");
} else if (// Mode string is calculated
o.operands[3] instanceof Add) {
Add a = (Add) o.operands[3];
// No need for cast or call c_str()
result.append(a.name);
}
// else badness
result.append(")");
return true;
}
if (op instanceof Power) {
Power p = (Power) op;
Operator a = p.operand0;
Operator b = p.operand1;
result.append("pow (");
a.render(this);
result.append(", ");
b.render(this);
if (useExponent)
result.append(", " + a.exponentNext + ", " + p.exponentNext);
result.append(")");
return true;
}
if (op instanceof Pulse) {
Pulse p = (Pulse) op;
Operator t = p.operands[0];
result.append("pulse (");
renderType(t);
for (int i = 1; i < p.operands.length; i++) {
result.append(", ");
renderType(p.operands[i]);
}
result.append(")");
return true;
}
if (op instanceof ReadMatrix) {
ReadMatrix r = (ReadMatrix) op;
// Currently, ReadMatrix sets its exponent = exponentNext, so we will never do a shift here.
// Any shifting should be handled by matrixHelper while loading and converting the matrix to integer.
// matrices are held in pointers, so need to dereference
result.append("*" + r.name + "->A");
return true;
}
if (op instanceof Rows) {
Rows r = (Rows) op;
r.operands[0].render(this);
result.append(".rows ()");
return true;
}
if (op instanceof Sat) {
Sat s = (Sat) op;
Operator a = s.operands[0];
Operator lower = s.operands[1];
Operator upper;
if (s.operands.length >= 3)
upper = s.operands[2];
else
upper = lower;
result.append("max (");
if (s.operands.length == 2)
result.append("-1 * (");
renderType(lower);
if (s.operands.length == 2)
result.append(")");
result.append(", min (");
renderType(upper);
result.append(", ");
renderType(a);
result.append("))");
return true;
}
if (op instanceof SquareRoot) {
SquareRoot s = (SquareRoot) op;
Operator a = s.operands[0];
result.append("sqrt (");
a.render(this);
if (useExponent)
result.append(", " + a.exponentNext + ", " + s.exponentNext);
result.append(")");
return true;
}
if (op instanceof SumSquares) {
SumSquares ss = (SumSquares) op;
Operator A = ss.operands[0];
result.append("sumSquares (");
A.render(this);
if (useExponent)
result.append(", " + A.exponentNext + ", " + ss.exponentNext);
result.append(")");
return true;
}
if (op instanceof Tangent) {
Tangent t = (Tangent) op;
Operator a = t.operands[0];
result.append("tan (");
a.render(this);
if (useExponent)
result.append(", " + a.exponentNext + ", " + t.exponentNext);
result.append(")");
return true;
}
if (op instanceof Uniform) {
Uniform u = (Uniform) op;
result.append("uniform<" + job.T + "> (");
for (int i = 0; i < u.operands.length; i++) {
if (i > 0)
result.append(", ");
u.operands[i].render(this);
}
result.append(")");
return true;
}
return super.render(op);
}
use of gov.sandia.n2a.language.type.Text in project n2a by frothga.
the class InternalBackendData method analyzeEvents.
public static void analyzeEvents(EquationSet s, List<EventTarget> eventTargets, List<Variable> eventReferences, List<Delay> delays) {
class EventVisitor implements Visitor {
public boolean found;
public boolean visit(Operator op) {
if (op instanceof Delay) {
delays.add((Delay) op);
} else if (op instanceof Event) {
found = true;
Event de = (Event) op;
if (// this event has not yet been analyzed
de.eventType == null) {
final EventTarget et = new EventTarget(de);
int targetIndex = eventTargets.indexOf(et);
if (// event target already exists
targetIndex >= 0) {
de.eventType = eventTargets.get(targetIndex);
} else // we must create a new event target, or more properly, fill in the event target we just used as a query object
{
// Create an entry and save the index
targetIndex = eventTargets.size();
eventTargets.add(et);
de.eventType = et;
et.container = s;
// Determine edge type
if (de.operands.length < 3) {
et.edge = EventTarget.RISE;
} else if (de.operands[2] instanceof Constant) {
Constant c = (Constant) de.operands[2];
if (c.value instanceof Text) {
Text t = (Text) c.value;
if (t.value.equalsIgnoreCase("nonzero"))
et.edge = EventTarget.NONZERO;
else if (t.value.equalsIgnoreCase("change"))
et.edge = EventTarget.CHANGE;
else if (t.value.equalsIgnoreCase("fall"))
et.edge = EventTarget.FALL;
else
et.edge = EventTarget.RISE;
} else {
Backend.err.get().println("ERROR: event() edge type must be a string.");
throw new Backend.AbortRun();
}
} else {
Backend.err.get().println("ERROR: event() edge type must be constant.");
throw new Backend.AbortRun();
}
// Allocate auxiliary variable
if (de.operands[0] instanceof AccessVariable) {
AccessVariable av = (AccessVariable) de.operands[0];
VariableReference reference = av.reference;
Variable v = reference.variable;
// then the user has broken the rule that we can't see temporaries in other parts.
if (v.hasAttribute("temporary") && v.container != s) {
Backend.err.get().println("WARNING: Cannot be temporary due to event monitor: " + v.fullName() + " from " + s.name);
v.removeAttribute("temporary");
}
// so fall through to the !trackOne case below.
if (!v.hasAttribute("temporary")) {
// ensure it's buffered, so we can detect change
v.addAttribute("externalRead");
et.trackOne = true;
// just a holder for the reference
et.track = new Variable("");
et.track.reference = reference;
}
}
if (// Expression, so create auxiliary variable. Aux not needed for NONZERO, because no change detection.
!et.trackOne && et.edge != EventTarget.NONZERO) {
et.track = new Variable("$eventAux" + targetIndex);
et.track.container = s;
et.track.type = new Scalar(0);
et.track.reference = new VariableReference();
et.track.reference.variable = et.track;
// Make executable so it can be directly evaluated during the init cycle.
et.track.equations = new TreeSet<EquationEntry>();
EquationEntry ee = new EquationEntry(et.track, "");
et.track.equations.add(ee);
ee.expression = et.event.operands[0].deepCopy();
ee.expression.addDependencies(et.track);
}
// Locate any temporaries for evaluation.
// Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
// TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
// TODO: for more efficiency, cut off search for temporaries along a given branch of the tree at the first non-temporary.
final Variable phantom = new Variable("event");
phantom.uses = new IdentityHashMap<Variable, Integer>();
phantom.container = s;
et.event.visit(new Visitor() {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable v = av.reference.variable;
if (v.hasAttribute("temporary") && !phantom.uses.containsKey(v))
phantom.uses.put(v, 1);
return false;
}
return true;
}
});
// Scan all variables in equation set to see if we need them
for (Variable t : s.ordered) {
if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
et.dependencies.add(t);
}
// Note the default is already set to -1 (no care)
class DelayVisitor implements Visitor {
TreeSet<EquationSet> containers = new TreeSet<EquationSet>();
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
// could include the target part itself, if in fact we use local variables
containers.add(av.reference.variable.container);
return false;
}
return true;
}
}
DelayVisitor dv = new DelayVisitor();
if (de.operands.length >= 2) {
if (de.operands[1] instanceof Constant) {
Constant c = (Constant) de.operands[1];
et.delay = (float) ((Scalar) c.value).value;
if (et.delay < 0)
et.delay = -1;
} else {
// indicates that we need to evaluate delay at run time
et.delay = -2;
de.operands[1].visit(dv);
}
}
// Set up monitors in source parts
class ConditionVisitor implements Visitor {
TreeSet<EquationSet> containers = new TreeSet<EquationSet>();
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable v = av.reference.variable;
EquationSet sourceContainer = v.container;
containers.add(sourceContainer);
// Set up monitors for values that can vary during update.
if (!v.hasAttribute("constant") && !v.hasAttribute("initOnly") && !et.monitors(sourceContainer)) {
EventSource es = new EventSource(sourceContainer, et);
// null means self-reference, a special case handled in Part
if (sourceContainer != s)
es.reference = av.reference;
et.sources.add(es);
}
return false;
}
return true;
}
}
ConditionVisitor cv = new ConditionVisitor();
de.operands[0].visit(cv);
// Special case for event with no references that vary
if (et.sources.isEmpty()) {
// We can avoid creating a self monitor if we know for certain that the event will never fire
boolean neverFires = false;
if (de.operands[0] instanceof Constant) {
if (et.edge == EventTarget.NONZERO) {
Type op0 = ((Constant) de.operands[0]).value;
if (op0 instanceof Scalar) {
neverFires = ((Scalar) op0).value == 0;
} else {
Backend.err.get().println("ERROR: Condition for event() must resolve to a number.");
throw new Backend.AbortRun();
}
} else {
neverFires = true;
}
}
if (!neverFires) {
EventSource es = new EventSource(s, et);
// This is a self-reference, so es.reference should be null.
et.sources.add(es);
}
}
// Determine if monitor needs to test every target, or if one representative target is sufficient
for (EventSource source : et.sources) {
// associated with any given source instance, so every target must be evaluated separately.
if (cv.containers.size() > 1)
source.testEach = true;
if (dv.containers.size() > 1 || (dv.containers.size() == 1 && dv.containers.first() != source.container))
source.delayEach = true;
}
}
}
}
return true;
}
}
EventVisitor eventVisitor = new EventVisitor();
for (Variable v : s.variables) {
eventVisitor.found = false;
v.visit(eventVisitor);
if ((eventVisitor.found || v.dependsOnEvent()) && v.reference.variable != v)
eventReferences.add(v);
}
}
Aggregations