package ai.domain.interval;
import ai.domain.DomainException;
import ai.domain.generic.AbstractNumericExpressionSemantics;
/**
* Implementation of INTEGER interval domain semantics
*
*
* @author kjk@mimuw.edu.pl
*
*/
public class IntervalExpressionSemantics implements AbstractNumericExpressionSemantics<Interval>{
private static Interval ZERO = new Interval(0,0);
private static Interval MINUS_ONE_TO_ONE = new Interval(-1, 1);
private static Interval ZERO_TO_INTF = new Interval(0, Double.POSITIVE_INFINITY);
@Override
public Interval getZero() {
return ZERO;
}
@Override
public Interval getMinus1to1() {
return MINUS_ONE_TO_ONE;
}
@Override
public Interval minus(Interval arg) {
if (arg.isBottom())
return arg;
return new Interval(-arg.getRight(), -arg.getLeft());
}
@Override
public Interval plus(Interval leftArg, Interval rightArg) {
if (leftArg.isBottom() || rightArg.isBottom())
return Interval.BOTTOM;
return new Interval(leftArg.getLeft() + rightArg.getLeft(), leftArg.getRight() + rightArg.getRight());
}
@Override
public Interval minus(Interval leftArg, Interval rightArg) {
if (leftArg.isBottom() || rightArg.isBottom())
return Interval.BOTTOM;
return new Interval(leftArg.getLeft() - rightArg.getRight(), leftArg.getRight() - rightArg.getLeft());
}
private double fixNaN(double possibleNan, double fixValue) {
return Double.isNaN(possibleNan) ? fixValue : possibleNan;
}
@Override
public Interval times(Interval a, Interval b) {
if (a.isBottom() || b.isBottom())
return Interval.BOTTOM;
double possible1 = fixNaN(a.getLeft()*b.getLeft(), 0);
double possible2 = fixNaN(a.getLeft()* b.getRight(), 0);
double possible3 = fixNaN(a.getRight()*b.getLeft(), 0);
double possible4 = fixNaN(a.getRight()*b.getRight(), 0);
double left = Math.min(Math.min(possible1, possible2), Math.min(possible3, possible4));
double right = Math.max(Math.max(possible1, possible2), Math.max(possible3, possible4));
return new Interval(left, right);
}
private double adj(double x) {
if (0 <= x)
return (x == Double.POSITIVE_INFINITY) ? x : Math.floor(x);
else
return (x == Double.NEGATIVE_INFINITY) ? x : Math.ceil(x);
}
private Interval divideHelper(Interval a, Interval b) {
if (!(0 <= b.getLeft()))
throw new DomainException("Hmm, invalid usage??");
// 0 / 0 = NaN
double possible1 = fixNaN(a.getLeft()/b.getLeft(), 0);
double possible2 = fixNaN(a.getLeft()/b.getRight(), 0);
double possible3 = fixNaN(a.getRight()/b.getLeft(), 0);
double possible4 = fixNaN(a.getRight()/b.getRight(), 0);
double left = adj(Math.min(Math.min(possible1, possible2), Math.min(possible3, possible4)));
double right = adj(Math.max(Math.max(possible1, possible2), Math.max(possible3, possible4)));
return new Interval(left, right);
}
@Override
public Interval divide(Interval a, Interval b) {
if (a.isBottom() || b.isBottom())
return Interval.BOTTOM;
if (ZERO.equals(b)) // division by 0!!
return Interval.BOTTOM;
if (0 <= b.getLeft())
return divideHelper(a, b);
return divide(a, b.meet(ZERO_TO_INTF)).join(divide(minus(a), minus(b).meet(ZERO_TO_INTF)));
}
//FIXME: now we have dummy implementations :(
private Interval dummy(Interval... args) {
//FIXME: dummy implementation!!
for(Interval arg: args)
if (arg.isBottom())
return Interval.BOTTOM;
return Interval.TOP;
}
@Override
public Interval leftShift(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval rightShiftSigned(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval rightShiftUnsigned(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval and(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval or(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval xor(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval plus(Interval arg) {
return arg;
}
@Override
public Interval complement(Interval arg) {
return dummy(arg);
}
@Override
public Interval remainder(Interval leftArg, Interval rightArg) {
return dummy(leftArg, rightArg);
}
@Override
public Interval delta(Interval arg, int value) {
return new Interval(arg.getValue().add(value));
}
}