package gve.calc.formula; public class OperatorMult extends InfixBinaryOp { public String getName() { return "*"; } public int getPri() { return 1900; } public OperatorMult(Part l,Part r) { super(l,r); } public Part evaluate(Evaluator ev) { Object l = left.evaluate(ev); Object r = right.evaluate(ev); return multiply(ev,l,r); } private static Part multiply(Evaluator ev,Object l,Object r) { if (l instanceof Real && r instanceof Real) { return new Real(((Real)l).doubleValue * ((Real)r).doubleValue); } else if (l instanceof Real && r instanceof Interval) { Interval inter = (Interval)r; double left = ((Real)l).doubleValue; if (left == 0) return new Real(0); else if (left > 0) return new Interval(inter.low*left,inter.high*left,inter.openLow,inter.openHigh); else // left < 0 return new Interval(inter.high*left,inter.low*left,inter.openHigh,inter.openLow); } else if (l instanceof Interval && r instanceof Real) { Interval inter = (Interval)l; double right = ((Real)r).doubleValue; if (right == 0) return new Real(0); else if (right > 0) return new Interval(inter.low*right,inter.high*right,inter.openLow,inter.openHigh); else // left < 0 return new Interval(inter.high*right,inter.low*right,inter.openHigh,inter.openLow); } else if (l instanceof Interval && r instanceof Interval) { Interval left = (Interval)l; Interval right = (Interval)r; // Strategy: we know for sure that two of the 4 numbers {left.low,left.high} * {right.low,right.high} // form the boundaries of the new interval double min,max,test; boolean openL,openH; // test left.low * right.low min = max = left.low * right.low; openL = openH = left.openLow || right.openLow; // test left.low * right.high test = left.low * right.high; if (test < min) { min = test; openL = left.openLow || right.openHigh; } if (test > max) { max = test; openH = left.openLow || right.openHigh; } // test next number test = left.high * right.low; if (test < min) { min = test; openL = left.openHigh || right.openLow; } if (test > max) { max = test; openH = left.openHigh || right.openLow; } // test last number test = left.high * right.high; if (test < min) { min = test; openL = left.openHigh || right.openHigh; } if (test > max) { max = test; openH = left.openHigh || right.openHigh; } return new Interval(min,max,openL,openH); } else if (l instanceof Real && r instanceof OperatorUnion) { OperatorUnion un = (OperatorUnion)r; return new OperatorUnion( (Part)multiply(ev,l,un.left), (Part)multiply(ev,l,un.right) ); } else return null; } }