use of gov.sandia.n2a.language.operator.NOT in project n2a by frothga.
the class RendererCfp method render.
public boolean render(Operator op) {
if (op == latch) {
latch = null;
return super.render(op);
}
// one or more exponent parameters to the end of the usual function call.
if (operatorsWithExponent.contains(op.getClass()))
return super.render(op);
// These are ordered to trap specific cases before more general ones.
if (op instanceof OperatorLogical) {
// Return the boolean itself if being consumed by a condition or by another logical operator.
if (op.parent == null || op.parent instanceof OperatorLogical)
return super.render(op);
result.append("(");
escalate(op);
result.append(" ? ");
if (op instanceof NOT) {
result.append("0 : " + print(1, op.exponentNext) + ")");
} else {
result.append(print(1, op.exponentNext) + " : 0)");
}
return true;
}
if (op instanceof Multiply || op instanceof MultiplyElementwise) {
OperatorBinary b = (OperatorBinary) op;
// Explanation of shift -- The exponent of the result will be the sum of the exponents
// of the two operands. That new exponent will be associated with bit position 2*MSB.
// We want the exponent at bit position MSB.
// Exponent at MSB position after a direct integer multiply.
int exponentRaw = b.operand0.exponentNext + b.operand1.exponentNext - Operator.MSB;
int shift = exponentRaw - b.exponentNext;
if (shift == 0) {
escalate(b);
} else {
if (b.getType() instanceof Matrix) {
if (shift > 0) {
result.append("shift (");
escalate(b);
result.append(", " + shift + ")");
} else {
if (b instanceof Multiply || b.operand0.isScalar() || b.operand1.isScalar()) {
result.append("multiply (");
} else // MultiplyElementwise and both operands are matrices
{
result.append("multiplyElementwise (");
}
if (b.operand0.isScalar()) {
// Always put the scalar in second position, so we need only one form of multiply().
b.operand1.render(this);
result.append(", ");
b.operand0.render(this);
} else {
b.operand0.render(this);
result.append(", ");
b.operand1.render(this);
}
result.append(", " + -shift + ")");
}
} else {
if (shift > 0) {
result.append("(");
escalate(b);
result.append(" << " + shift);
result.append(")");
} else {
if (!parentAccepts64bit(b))
result.append("(int32_t) ");
result.append("(");
if (!provides64bit(b.operand0))
result.append("(int64_t) ");
escalate(b);
result.append(" >> " + -shift);
result.append(")");
}
}
}
return true;
}
if (op instanceof Divide) {
Divide d = (Divide) op;
// Explanation of shift -- In a division, the quotient is effectively down-shifted by
// the number of bits in the denominator, and its exponent is the difference between
// the exponents of the numerator and denominator.
// Exponent in MSB from a direct integer division.
int exponentRaw = d.operand0.exponentNext - d.operand1.exponentNext + Operator.MSB;
int shift = exponentRaw - d.exponentNext;
if (shift == 0) {
escalate(d);
} else {
if (d.getType() instanceof Matrix) {
if (shift > 0) {
result.append("divide (");
d.operand0.render(this);
result.append(", ");
d.operand1.render(this);
result.append(", " + shift + ")");
} else {
result.append("shift (");
escalate(d);
result.append(", " + shift + ")");
}
} else {
if (shift > 0) {
if (!parentAccepts64bit(d))
result.append("(int32_t) ");
result.append("((");
if (!provides64bit(d.operand0))
result.append("(int64_t) ");
// OperatorBinary.render() will add parentheses around operand0 if it has lower
// precedence than division. This includes the case where it has lower precedence
// than shift, so we are safe.
d.render(this, " << " + shift + ") / ");
result.append(")");
} else {
result.append("(");
escalate(d);
result.append(" >> " + -shift + ")");
}
}
}
return true;
}
if (op instanceof Modulo) {
Modulo m = (Modulo) op;
int shift = m.exponent - m.exponentNext;
if (m.operand0.exponentNext == m.operand1.exponentNext) {
if (shift == 0)
return super.render(m);
result.append("(");
escalate(m);
result.append(printShift(shift) + ")");
} else {
if (shift != 0)
result.append("(");
result.append("modFloor (");
m.operand0.render(this);
result.append(", ");
m.operand1.render(this);
result.append(", " + m.operand0.exponentNext + ", " + m.operand1.exponentNext + ")");
if (shift != 0)
result.append(printShift(shift) + ")");
}
return true;
}
if (// Add, Subtract, Negate, Transpose
op instanceof OperatorArithmetic) {
int exponentOperand;
if (op instanceof OperatorBinary)
exponentOperand = ((OperatorBinary) op).operand0.exponentNext;
else
exponentOperand = ((OperatorUnary) op).operand.exponentNext;
int shift = exponentOperand - op.exponentNext;
if (shift == 0)
return super.render(op);
if (op.getType() instanceof Matrix) {
result.append("shift (");
escalate(op);
result.append(", " + shift + ")");
} else {
result.append("(");
// In C++, shift is just below addition in precedence.
boolean needParens = op.precedence() > new Add().precedence();
if (needParens)
result.append("(");
escalate(op);
if (needParens)
result.append(")");
result.append(printShift(shift));
result.append(")");
}
return true;
}
// These are listed in alphabetical order, with a catch-all at the end.
if (// Actually just an operator, not a function
op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
int shift = av.exponent - av.exponentNext;
if (shift != 0) {
if (av.getType() instanceof Matrix)
result.append("shift ");
result.append("(");
}
result.append(job.resolve(av.reference, this, false));
if (useExponent && shift != 0) {
if (av.getType() instanceof Matrix) {
result.append(", " + shift);
} else {
result.append(printShift(shift));
}
result.append(")");
}
return true;
}
if (op instanceof Ceil) {
Ceil f = (Ceil) op;
Operator a = f.operands[0];
// Ceil always sets operands[0].exponentNext to be same as f.exponentNext, so no shift is necessary.
if (// LSB is above decimal, so ceil() operation is impossible.
f.exponentNext >= Operator.MSB) {
a.render(this);
} else if (// All bits are below decimal
f.exponentNext < 0) {
result.append("0");
} else {
// Create a mask for bits below the decimal point.
// When this mask is added to the number, it will add 1 to the first bit position
// above the decimal if any bit is set under the mask. Afterward, used AND to remove
// any residual bits below the decimal.
// This works for both positive and negative numbers.
int zeroes = Operator.MSB - f.exponentNext;
int wholeMask = 0xFFFFFFFF << zeroes;
int decimalMask = ~wholeMask;
boolean needParens = a.precedence() >= new Add().precedence();
result.append("(");
if (needParens)
result.append("(");
a.render(this);
if (needParens)
result.append(")");
result.append(" + " + decimalMask + " & " + wholeMask + ")");
}
return true;
}
if (op instanceof Cosine) {
Cosine c = (Cosine) op;
Operator a = c.operands[0];
int shift = c.exponent - c.exponentNext;
if (shift != 0)
result.append("(");
result.append("cos (");
a.render(this);
result.append(", " + a.exponentNext + ")");
if (shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (op instanceof Event) {
// See comment on OperatorLogical above. Since event() returns a boolean, we follow the same behavior here.
if (op.parent == null || op.parent instanceof OperatorLogical)
return super.render(op);
Event e = (Event) op;
int exponentRaw = Operator.MSB - e.eventType.valueIndex;
int shift = exponentRaw - e.exponentNext;
if (shift != 0)
result.append("(");
result.append("(flags & (" + bed.localFlagType + ") 0x1 << " + e.eventType.valueIndex + ")");
if (shift != 0) {
result.append(printShift(shift));
result.append(")");
}
return true;
}
if (op instanceof Floor) {
// See Ceil above for similar code.
Floor f = (Floor) op;
Operator a = f.operands[0];
if (f.exponentNext >= Operator.MSB) {
a.render(this);
} else if (f.exponentNext < 0) {
result.append("0");
} else {
// Mask off bits below the decimal point. This works for both positive and negative numbers.
int zeroes = Operator.MSB - f.exponentNext;
int wholeMask = 0xFFFFFFFF << zeroes;
boolean needParens = a.precedence() >= new AND().precedence();
result.append("(");
if (needParens)
result.append("(");
a.render(this);
if (needParens)
result.append(")");
result.append(" & " + wholeMask + ")");
}
return true;
}
if (op instanceof HyperbolicTangent) {
HyperbolicTangent ht = (HyperbolicTangent) op;
Operator a = ht.operands[0];
int shift = ht.exponent - ht.exponentNext;
if (shift != 0)
result.append("(");
result.append("tanh (");
a.render(this);
result.append(", " + a.exponentNext + ")");
if (shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (op instanceof Round) {
Round r = (Round) op;
Operator a = r.operands[0];
int shift = a.exponentNext - r.exponentNext;
int decimalPlaces = Math.max(0, Operator.MSB - a.exponentNext);
int mask = 0xFFFFFFFF << decimalPlaces;
int half = 0;
if (decimalPlaces > 0)
half = 0x1 << decimalPlaces - 1;
if (shift != 0)
result.append("(");
// Bitwise operators are low precedence, so we parenthesize them regardless.
result.append("(");
boolean needParens = a.precedence() > new Add().precedence();
if (needParens)
result.append("(");
a.render(this);
if (needParens)
result.append(")");
result.append(" + " + half + " & " + mask);
// Close parens around bitwise operator
result.append(")");
if (shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (op instanceof Signum) {
Signum s = (Signum) op;
Operator a = s.operands[0];
int one = 0x1 << Operator.MSB - s.exponentNext;
boolean needParens = a.precedence() >= new LT().precedence();
if (needParens)
result.append("(");
a.render(this);
if (needParens)
result.append(")");
result.append(" < 0 ? " + -one + ":" + one + ")");
return true;
}
if (op instanceof Sine) {
Sine s = (Sine) op;
Operator a = s.operands[0];
int shift = s.exponent - s.exponentNext;
if (shift != 0)
result.append("(");
result.append("sin (");
a.render(this);
result.append(", " + a.exponentNext + ")");
if (shift != 0)
result.append(printShift(shift) + ")");
return true;
}
if (// AbsoluteValue, Grid, Max, Min
op instanceof Function) {
int shift = op.exponent - op.exponentNext;
if (shift == 0)
return super.render(op);
if (op.getType() instanceof Matrix) {
result.append("shift (");
escalate(op);
result.append(", " + shift + ")");
} else {
result.append("(");
escalate(op);
result.append(printShift(shift) + ")");
}
return true;
}
return super.render(op);
}
Aggregations