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;
}
}