/**
  * Compute a compound state representing possible results of adding the given summand compound
  * states up. This method provides a much weaker implementation of compound state addition than
  * {@link CompoundInterval#add(CompoundInterval)} and will thus usually return a much larger
  * result range.
  *
  * @param a the first summand.
  * @param b the second summand.
  * @return a state representing possible results of adding the given summand compound states up.
  */
 private CompoundInterval weakAdd(CompoundInterval pA, CompoundInterval pB) {
   if (pA.isSingleton() && pA.containsZero()) {
     return pB;
   }
   if (pB.isSingleton() && pB.containsZero()) {
     return pA;
   }
   return abstractionOf(pA.add(pB));
 }
 @Override
 public CompoundInterval visit(
     ShiftLeft<CompoundInterval> pShiftLeft,
     Map<? extends String, ? extends InvariantsFormula<CompoundInterval>> pEnvironment) {
   CompoundInterval toShift = pShiftLeft.getShifted().accept(this, pEnvironment);
   CompoundInterval shiftDistance = pShiftLeft.getShiftDistance().accept(this, pEnvironment);
   CompoundInterval evaluation = toShift.shiftLeft(shiftDistance);
   if (!shiftDistance.containsPositive()) {
     return evaluation;
   }
   return abstractionOf(evaluation);
 }
 /**
  * Compute a compound state representing possible results of multiplying the given factor compound
  * states. This method provides a much weaker implementation of compound state addition than
  * {@link CompoundInterval#multiply(CompoundInterval)} and will thus usually return a much larger
  * result range.
  *
  * @param a the first factor.
  * @param b the second factor.
  * @return a state representing possible results of multiplying the given factor compound states.
  */
 private CompoundInterval weakMultiply(CompoundInterval a, CompoundInterval b) {
   if (a.isSingleton() && a.containsZero()) {
     return a;
   }
   if (b.isSingleton() && b.containsZero()) {
     return b;
   }
   if (a.isSingleton() && a.contains(1)) {
     return b;
   }
   if (b.isSingleton() && b.contains(1)) {
     return a;
   }
   return abstractionOf(a.multiply(b));
 }
 @Override
 public CompoundInterval visit(
     Variable<CompoundInterval> pVariable,
     Map<? extends String, ? extends InvariantsFormula<CompoundInterval>> pEnvironment) {
   InvariantsFormula<CompoundInterval> varState = pEnvironment.get(pVariable.getName());
   if (varState == null) {
     return CompoundInterval.top();
   }
   return varState.accept(this, pEnvironment);
 }
 private static CompoundInterval abstractionOf(CompoundInterval pValue) {
   if (pValue.isBottom() || pValue.isTop()) {
     return pValue;
   }
   CompoundInterval result = pValue.signum();
   boolean extendToNeg = false;
   if (!pValue.lessThan(result).isDefinitelyFalse()) {
     extendToNeg = true;
   }
   if (!pValue.greaterThan(result).isDefinitelyFalse()) {
     result = result.extendToPositiveInfinity();
   }
   if (extendToNeg) {
     result = result.extendToNegativeInfinity();
   }
   assert result.unionWith(pValue).equals(result);
   return result;
 }