// Returns se1<op>se2 with constant evaluation. private static SimpleExpression compute(SimpleExpression se1, int op, SimpleExpression se2) { SimpleExpression ret = null; if (se1.sop == LIT && se2.sop == LIT) { Double result = null, v1 = se1.getValue(), v2 = se2.getValue(); switch (op) { case ADD: result = v1 + v2; break; case MUL: result = v1 * v2; break; case DIV: result = v1 / v2; break; case MOD: result = v1 % v2; break; default: Tools.exit("[SimpleExpression] unknown operation in normalization"); } if (se1.expr instanceof IntegerLiteral && se2.expr instanceof IntegerLiteral) ret = getInt(result.intValue()); else ret = getDouble(result.doubleValue()); } else { ret = new SimpleExpression(se1, op, se2); ret = ret.normalize(); } // Tools.printlnStatus("[COM] "+se1+" "+cop.get(op)+" "+se2+" --> "+ret, 1); return ret; }
// Removes division by replacing with modulus operations. // The returned list contains the modified simple expression (get(0)) and // the additionally multiplied value (get(1)). // e.g., a*(b/c)*(d/e) returns {a*(b-b%c)*(d-d%e), c*e}. // It is important to notice that the legality check of this transformation // is up to the callers. // It is assumed that the original simple expressions has been normalized. protected List<SimpleExpression> multiplyByLCM() { List<SimpleExpression> ret = new ArrayList<SimpleExpression>(2); if (sop == DIV) { ret.add(subtract(getChild(0), mod(getChild(0), getChild(1)))); ret.add(getChild(1)); } else if (sop == ADD) { List<SimpleExpression> terms = new LinkedList<SimpleExpression>(); List<SimpleExpression> factors = new LinkedList<SimpleExpression>(); SimpleExpression lcm = sone; for (SimpleExpression child : children) { List<SimpleExpression> ret0 = child.multiplyByLCM(); terms.add(ret0.get(0)); factors.add(ret0.get(1)); lcm = computeLCM(lcm, ret0.get(1)); } SimpleExpression ret1 = new SimpleExpression(ADD); for (int i = 0; i < terms.size(); i++) ret1.add(multiply(divide(lcm, factors.get(i)), terms.get(i))); ret.add(ret1.normalize()); ret.add(lcm); } else if (sop == MUL) { SimpleExpression terms = new SimpleExpression(MUL); SimpleExpression factors = sone; for (SimpleExpression child : children) { List<SimpleExpression> ret0 = child.multiplyByLCM(); terms.add(ret0.get(0)); factors = multiply(factors, ret0.get(1)); } ret.add(terms.normalize()); ret.add(factors); } else { ret.add(this); ret.add(sone); } return ret; }
// Normalizes this simple expression recursively. protected SimpleExpression normalize() { SimpleExpression ret = new SimpleExpression(this); for (SimpleExpression child : children) ret.add(child.normalize()); if (contains_side_effect) return ret; switch (ret.sop) { case ID: case LIT: case LEAF: ret = this; break; case ADD: ret = ret.normalizeADD(); break; case MUL: ret = ret.normalizeMUL(); break; case DIV: ret = ret.normalizeDIV(); break; case MOD: ret = ret.normalizeMOD(); break; case SFTL: case SFTR: case BAND: case BOR: case BXOR: ret = ret.normalizeBitOperation(); break; case BCMP: ret = ret.normalizeBCMP(); break; case AND: case OR: ret = ret.normalizeLogic(); break; case EQ: case NE: case LE: case LT: case GE: case GT: ret = ret.normalizeCompare(); break; case NEG: ret = ret.normalizeNEG(); break; case MIN: case MAX: ret = ret.normalizeMINMAX(); break; default: } if (ret.isCommAssoc()) ret.sort(); // Tools.printlnStatus("[NORM] "+this+" --> "+ret, 1); return ret; }