private Expression constructArIntExprMod(
     final ILocation loc,
     final Expression exp1,
     final Expression exp2,
     final boolean bothAreIntegerLiterals,
     final BigInteger leftValue,
     final BigInteger rightValue) {
   final BinaryExpression.Operator operator;
   operator = Operator.ARITHMOD;
   /*
    * In C the semantics of integer division is "rounding towards zero". In Boogie euclidian division is used. We
    * translate a % b into (a < 0 && a%b != 0) ? ( (b < 0) ? (a%b)-b : (a%b)+b) : a%b
    */
   // modulo on bigInteger does not seem to follow the "multiply, add, and get the result
   // back"-rule, together
   // with its division..
   if (bothAreIntegerLiterals) {
     final String constantResult;
     if (leftValue.signum() == 1 || leftValue.signum() == 0) {
       if (rightValue.signum() == 1) {
         constantResult = leftValue.mod(rightValue).toString();
       } else if (rightValue.signum() == -1) {
         constantResult = leftValue.mod(rightValue.negate()).toString();
       } else {
         constantResult = "0";
       }
     } else if (leftValue.signum() == -1) {
       if (rightValue.signum() == 1) {
         constantResult = (leftValue.negate().mod(rightValue)).negate().toString();
       } else if (rightValue.signum() == -1) {
         constantResult = (leftValue.negate().mod(rightValue.negate())).negate().toString();
       } else {
         constantResult = "0";
       }
     } else {
       throw new UnsupportedOperationException("constant is not assigned");
     }
     return new IntegerLiteral(loc, constantResult);
   } else {
     final Expression leftSmallerZeroAndThereIsRemainder =
         getLeftSmallerZeroAndThereIsRemainder(loc, exp1, exp2);
     final Expression rightSmallerZero =
         ExpressionFactory.newBinaryExpression(
             loc, BinaryExpression.Operator.COMPLT, exp2, new IntegerLiteral(loc, SFO.NR0));
     final Expression normalModulo =
         ExpressionFactory.newBinaryExpression(loc, operator, exp1, exp2);
     if (exp1 instanceof IntegerLiteral) {
       if (leftValue.signum() == 1) {
         return normalModulo;
       } else if (leftValue.signum() == -1) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             rightSmallerZero,
             ExpressionFactory.newBinaryExpression(
                 loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2),
             ExpressionFactory.newBinaryExpression(
                 loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2));
       } else {
         return new IntegerLiteral(loc, SFO.NR0);
       }
     } else if (exp2 instanceof IntegerLiteral) {
       if (rightValue.signum() == 1 || rightValue.signum() == 0) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             leftSmallerZeroAndThereIsRemainder,
             ExpressionFactory.newBinaryExpression(
                 loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2),
             normalModulo);
       } else if (rightValue.signum() == -1) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             leftSmallerZeroAndThereIsRemainder,
             ExpressionFactory.newBinaryExpression(
                 loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2),
             normalModulo);
       }
       throw new UnsupportedOperationException(
           "Is it expected that this is a fall-through switch?");
     } else {
       return ExpressionFactory.newIfThenElseExpression(
           loc,
           leftSmallerZeroAndThereIsRemainder,
           ExpressionFactory.newIfThenElseExpression(
               loc,
               rightSmallerZero,
               ExpressionFactory.newBinaryExpression(
                   loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2),
               ExpressionFactory.newBinaryExpression(
                   loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2)),
           normalModulo);
     }
   }
 }
  private void convertToIntegerType(
      final ILocation loc, final ExpressionResult operand, final CPrimitive resultType) {
    assert resultType.isIntegerType();
    final CPrimitive oldType = (CPrimitive) operand.lrVal.getCType();
    if (oldType.isIntegerType()) {
      final Expression newExpression;
      if (mTypeSizes.isUnsigned(resultType)) {
        final Expression oldWrappedIfNeeded;
        if (mTypeSizes.isUnsigned(oldType)
            && mTypeSizes.getSize(resultType.getType()) > mTypeSizes.getSize(oldType.getType())) {
          // required for sound Nutz transformation
          // (see examples/programs/regression/c/NutzTransformation03.c)
          oldWrappedIfNeeded = applyWraparound(loc, mTypeSizes, oldType, operand.lrVal.getValue());
        } else {
          oldWrappedIfNeeded = operand.lrVal.getValue();
        }
        if (mUnsignedTreatment == UnsignedTreatment.ASSERT) {
          final BigInteger maxValuePlusOne =
              mTypeSizes.getMaxValueOfPrimitiveType(resultType).add(BigInteger.ONE);
          final AssertStatement assertGeq0 =
              new AssertStatement(
                  loc,
                  ExpressionFactory.newBinaryExpression(
                      loc,
                      BinaryExpression.Operator.COMPGEQ,
                      oldWrappedIfNeeded,
                      new IntegerLiteral(loc, SFO.NR0)));
          final Check chk1 = new Check(Spec.UINT_OVERFLOW);
          chk1.addToNodeAnnot(assertGeq0);
          operand.stmt.add(assertGeq0);

          final AssertStatement assertLtMax =
              new AssertStatement(
                  loc,
                  ExpressionFactory.newBinaryExpression(
                      loc,
                      BinaryExpression.Operator.COMPLT,
                      oldWrappedIfNeeded,
                      new IntegerLiteral(loc, maxValuePlusOne.toString())));
          final Check chk2 = new Check(Spec.UINT_OVERFLOW);
          chk2.addToNodeAnnot(assertLtMax);
          operand.stmt.add(assertLtMax);
        } else {
          // do nothing
        }
        newExpression = oldWrappedIfNeeded;
      } else {
        assert !mTypeSizes.isUnsigned(resultType);
        final Expression oldWrappedIfUnsigned;
        if (mTypeSizes.isUnsigned(oldType)) {
          // required for sound Nutz transformation
          // (see examples/programs/regression/c/NutzTransformation01.c)
          oldWrappedIfUnsigned =
              applyWraparound(loc, mTypeSizes, oldType, operand.lrVal.getValue());
        } else {
          oldWrappedIfUnsigned = operand.lrVal.getValue();
        }
        if (mTypeSizes.getSize(resultType.getType()) > mTypeSizes.getSize(oldType.getType())
            || (mTypeSizes
                    .getSize(resultType.getType())
                    .equals(mTypeSizes.getSize(oldType.getType()))
                && !mTypeSizes.isUnsigned(oldType))) {
          newExpression = oldWrappedIfUnsigned;
        } else {
          // According to C11 6.3.1.3.3 the result is implementation-defined
          // it the value cannot be represented by the new type
          // We have chosen an implementation that is similar to
          // taking the lowest bits in a two's complement representation:
          // First we take the value modulo the cardinality of the
          // data range (which is 2*(MAX_VALUE+1) for signed )
          // If the number is strictly larger than MAX_VALUE we
          // subtract the cardinality of the data range.
          final CPrimitive correspondingUnsignedType =
              mTypeSizes.getCorrespondingUnsignedType(resultType);
          final Expression wrapped =
              applyWraparound(loc, mTypeSizes, correspondingUnsignedType, oldWrappedIfUnsigned);
          final Expression maxValue =
              constructLiteralForIntegerType(
                  loc, oldType, mTypeSizes.getMaxValueOfPrimitiveType(resultType));
          final Expression condition =
              ExpressionFactory.newBinaryExpression(loc, Operator.COMPLEQ, wrapped, maxValue);
          final Expression range =
              constructLiteralForIntegerType(
                  loc,
                  oldType,
                  mTypeSizes
                      .getMaxValueOfPrimitiveType(correspondingUnsignedType)
                      .add(BigInteger.ONE));
          newExpression =
              ExpressionFactory.newIfThenElseExpression(
                  loc,
                  condition,
                  wrapped,
                  ExpressionFactory.newBinaryExpression(loc, Operator.ARITHMINUS, wrapped, range));
        }
      }
      final RValue newRValue = new RValue(newExpression, resultType, false, false);
      operand.lrVal = newRValue;
    } else {
      throw new UnsupportedOperationException("not yet supported: conversion from " + oldType);
    }
  }
 private Expression constructArIntExprDiv(
     final ILocation loc,
     final Expression exp1,
     final Expression exp2,
     final boolean bothAreIntegerLiterals,
     final BigInteger leftValue,
     final BigInteger rightValue) {
   final BinaryExpression.Operator operator;
   operator = Operator.ARITHDIV;
   /*
    * In C the semantics of integer division is "rounding towards zero". In Boogie euclidian division is used. We
    * translate a / b into (a < 0 && a%b != 0) ? ( (b < 0) ? (a/b)+1 : (a/b)-1) : a/b
    */
   if (bothAreIntegerLiterals) {
     final String constantResult = leftValue.divide(rightValue).toString();
     return new IntegerLiteral(loc, constantResult);
   } else {
     final Expression leftSmallerZeroAndThereIsRemainder =
         getLeftSmallerZeroAndThereIsRemainder(loc, exp1, exp2);
     final Expression rightSmallerZero =
         ExpressionFactory.newBinaryExpression(
             loc, BinaryExpression.Operator.COMPLT, exp2, new IntegerLiteral(loc, SFO.NR0));
     final Expression normalDivision =
         ExpressionFactory.newBinaryExpression(loc, operator, exp1, exp2);
     if (exp1 instanceof IntegerLiteral) {
       if (leftValue.signum() == 1) {
         return normalDivision;
       } else if (leftValue.signum() == -1) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             rightSmallerZero,
             ExpressionFactory.newBinaryExpression(
                 loc,
                 BinaryExpression.Operator.ARITHMINUS,
                 normalDivision,
                 new IntegerLiteral(loc, SFO.NR1)),
             ExpressionFactory.newBinaryExpression(
                 loc,
                 BinaryExpression.Operator.ARITHPLUS,
                 normalDivision,
                 new IntegerLiteral(loc, SFO.NR1)));
       } else {
         return new IntegerLiteral(loc, SFO.NR0);
       }
     } else if (exp2 instanceof IntegerLiteral) {
       if (rightValue.signum() == 1 || rightValue.signum() == 0) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             leftSmallerZeroAndThereIsRemainder,
             ExpressionFactory.newBinaryExpression(
                 loc,
                 BinaryExpression.Operator.ARITHPLUS,
                 normalDivision,
                 new IntegerLiteral(loc, SFO.NR1)),
             normalDivision);
       } else if (rightValue.signum() == -1) {
         return ExpressionFactory.newIfThenElseExpression(
             loc,
             leftSmallerZeroAndThereIsRemainder,
             ExpressionFactory.newBinaryExpression(
                 loc,
                 BinaryExpression.Operator.ARITHMINUS,
                 normalDivision,
                 new IntegerLiteral(loc, SFO.NR1)),
             normalDivision);
       }
       throw new UnsupportedOperationException(
           "Is it expected that this is a fall-through switch?");
     } else {
       return ExpressionFactory.newIfThenElseExpression(
           loc,
           leftSmallerZeroAndThereIsRemainder,
           ExpressionFactory.newIfThenElseExpression(
               loc,
               rightSmallerZero,
               ExpressionFactory.newBinaryExpression(
                   loc,
                   BinaryExpression.Operator.ARITHMINUS,
                   normalDivision,
                   new IntegerLiteral(loc, SFO.NR1)),
               ExpressionFactory.newBinaryExpression(
                   loc,
                   BinaryExpression.Operator.ARITHPLUS,
                   normalDivision,
                   new IntegerLiteral(loc, SFO.NR1))),
           normalDivision);
     }
   }
 }