Tries to rewrite arithmetic operations. @param cc compilation context @return optimized or original expression @throws QueryException query exception
(final CompileContext cc)
| 139 | * @throws QueryException query exception |
| 140 | */ |
| 141 | private Expr optArith(final CompileContext cc) throws QueryException { |
| 142 | final Expr expr1 = exprs[0], expr2 = exprs[1]; |
| 143 | Expr ex = null; |
| 144 | |
| 145 | if(expr1 instanceof final Arith arth && expr2.seqType().instanceOf(Types.NUMERIC_O)) { |
| 146 | final Expr op11 = expr1.arg(0), op12 = expr1.arg(1), op22 = expr2.arg(1); |
| 147 | final double num12 = op12 instanceof final ANum num ? num.dbl() : Double.NaN; |
| 148 | if(op12.seqType().instanceOf(Types.NUMERIC_O)) { |
| 149 | final Calc calc1 = arth.calc; |
| 150 | if(calc1 == Calc.SUBTRACT && expr2 == Itr.ZERO) { |
| 151 | // E - NUMERIC = 0 → E = NUMERIC |
| 152 | ex = new CmpG(info, op11, op12, op); |
| 153 | } else if(( |
| 154 | POSITION.is(op11) || |
| 155 | !Double.isNaN(num12) && |
| 156 | (expr2 instanceof ANum || expr2 instanceof Arith && op22 instanceof ANum) |
| 157 | ) && ( |
| 158 | calc1.oneOf(Calc.ADD, Calc.SUBTRACT) || |
| 159 | calc1.oneOf(Calc.MULTIPLY, Calc.DIVIDE) && num12 != 0 && |
| 160 | (op.oneOf(CmpOp.EQ, CmpOp.NE) || num12 > 0) |
| 161 | )) { |
| 162 | // position() + 1 < last() → position() < last() - 1 |
| 163 | // count(E) div 2 = 1 → count(E) = 1 * 2 |
| 164 | // $a - 1 = $b + 1 → $a = $b + 2 |
| 165 | // $x * -1 = 1 → $x = 1 div -1 (no rewrite if RHS of */div (<,<=,>=,>) is negative) |
| 166 | final Expr arg2 = new Arith(info, expr2, op12, calc1.invert()).optimize(cc); |
| 167 | ex = new CmpG(info, op11, arg2, op); |
| 168 | } |
| 169 | } |
| 170 | } |
| 171 | return ex != null ? ex.optimize(cc) : this; |
| 172 | } |
| 173 | |
| 174 | @Override |
| 175 | public final Bln item(final QueryContext qc, final InputInfo ii) throws QueryException { |