From 08113e8da292f0a0cf682871af85bf68079fc067 Mon Sep 17 00:00:00 2001
From: Regis Blanc <regwblanc@gmail.com>
Date: Mon, 1 Jun 2015 13:14:07 +0200
Subject: [PATCH] Introduce Modulo as mod operator on BigInt

Refactor all existing Modulo into Remainder, as it is
the correct term in Scala for the operation %.

BigInt now supports `mod` operator, which gets represented
as Modulo in Leon.
---
 .../java/leon/codegen/runtime/BigInt.java     |  5 +++-
 .../scala/leon/codegen/CodeGeneration.scala   | 10 +++++--
 .../leon/evaluators/RecursiveEvaluator.scala  | 17 +++++++++--
 .../frontends/scalac/CodeExtraction.scala     |  4 ++-
 .../scala/leon/purescala/Expressions.scala    | 18 +++++++-----
 .../scala/leon/purescala/Extractors.scala     |  3 +-
 .../scala/leon/purescala/PrettyPrinter.scala  | 12 ++++----
 .../leon/solvers/smtlib/SMTLIBSolver.scala    |  7 +++--
 .../leon/solvers/z3/AbstractZ3Solver.scala    |  7 +++--
 .../evaluators/DefaultEvaluatorTests.scala    | 28 +++++++++++++-----
 .../test/evaluators/EvaluatorsTests.scala     | 29 ++++++++++++-------
 11 files changed, 96 insertions(+), 44 deletions(-)

diff --git a/src/main/java/leon/codegen/runtime/BigInt.java b/src/main/java/leon/codegen/runtime/BigInt.java
index 83de0fbb4..f2b99a6d9 100644
--- a/src/main/java/leon/codegen/runtime/BigInt.java
+++ b/src/main/java/leon/codegen/runtime/BigInt.java
@@ -40,7 +40,10 @@ public final class BigInt {
   }
 
   public BigInt mod(BigInt that) {
-    return new BigInt(_underlying.mod(that.underlying()));
+    if(that.underlying().compareTo(new BigInteger("0")) < 0)
+      return new BigInt(_underlying.mod(that.underlying().negate()));
+    else
+      return new BigInt(_underlying.mod(that.underlying()));
   }
 
   public BigInt neg() {
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 4125eaddd..5d2b7fd41 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -645,12 +645,16 @@ trait CodeGeneration {
         mkExpr(r, ch)
         ch << InvokeVirtual(BigIntClass, "div", s"(L$BigIntClass;)L$BigIntClass;")
 
-      //Modulo in Leon corresponds to the "rem" operator on java/Scala BigInt
-      case Modulo(l, r) =>
+      case Remainder(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
         ch << InvokeVirtual(BigIntClass, "rem", s"(L$BigIntClass;)L$BigIntClass;")
 
+      case Modulo(l, r) =>
+        mkExpr(l, ch)
+        mkExpr(r, ch)
+        ch << InvokeVirtual(BigIntClass, "mod", s"(L$BigIntClass;)L$BigIntClass;")
+
       case UMinus(e) =>
         mkExpr(e, ch)
         ch << InvokeVirtual(BigIntClass, "neg", s"()L$BigIntClass;")
@@ -676,7 +680,7 @@ trait CodeGeneration {
         mkExpr(r, ch)
         ch << IDIV
 
-      case BVModulo(l, r) =>
+      case BVRemainder(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
         ch << IREM
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index 86e6ef578..90ea4ace4 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -289,10 +289,21 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType))
       }
 
+    case Remainder(l,r) =>
+      (e(l), e(r)) match {
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) =>
+          if(i2 != BigInt(0)) InfiniteIntegerLiteral(i1 % i2) else throw RuntimeError("Remainder of division by 0.")
+        case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType))
+      }
     case Modulo(l,r) =>
       (e(l), e(r)) match {
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => 
-          if(i2 != BigInt(0)) InfiniteIntegerLiteral(i1 % i2) else throw RuntimeError("Modulo by 0.")
+          if(i2 < 0)
+            InfiniteIntegerLiteral(i1 mod (-i2))
+          else if(i2 != BigInt(0)) 
+            InfiniteIntegerLiteral(i1 mod i2) 
+          else 
+            throw RuntimeError("Modulo of division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType))
       }
 
@@ -309,10 +320,10 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
 
-    case BVModulo(l,r) =>
+    case BVRemainder(l,r) =>
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => 
-          if(i2 != 0) IntLiteral(i1 % i2) else throw RuntimeError("Modulo by 0.")
+          if(i2 != 0) IntLiteral(i1 % i2) else throw RuntimeError("Remainder of division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
 
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 204720092..4466dbc23 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -1596,6 +1596,8 @@ trait CodeExtraction extends ASTExtractors {
             case (IsTyped(a1, IntegerType), "*", List(IsTyped(a2, IntegerType))) =>
               Times(a1, a2)
             case (IsTyped(a1, IntegerType), "%", List(IsTyped(a2, IntegerType))) =>
+              Remainder(a1, a2)
+            case (IsTyped(a1, IntegerType), "mod", List(IsTyped(a2, IntegerType))) =>
               Modulo(a1, a2)
             case (IsTyped(a1, IntegerType), "/", List(IsTyped(a2, IntegerType))) =>
               Division(a1, a2)
@@ -1616,7 +1618,7 @@ trait CodeExtraction extends ASTExtractors {
             case (IsTyped(a1, Int32Type), "*", List(IsTyped(a2, Int32Type))) =>
               BVTimes(a1, a2)
             case (IsTyped(a1, Int32Type), "%", List(IsTyped(a2, Int32Type))) =>
-              BVModulo(a1, a2)
+              BVRemainder(a1, a2)
             case (IsTyped(a1, Int32Type), "/", List(IsTyped(a2, Int32Type))) =>
               BVDivision(a1, a2)
 
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index 2a75af65c..e852d55c0 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -326,19 +326,23 @@ object Expressions {
     val getType = IntegerType
   }
   /*
-   * Division and Modulo follows Java/Scala semantics. Division corresponds
-   * to / operator on BigInt and Modulo corresponds to %. Note that in
-   * Java/Scala % is rather called remainder and the "mod" operator is also
-   * defined on BigInteger and differs from our Modulo. The "mod" operator
-   * returns an always positive remainder, while our Modulo could return
+   * Division and Remainder follows Java/Scala semantics. Division corresponds
+   * to / operator on BigInt and Remainder corresponds to %. Note that in
+   * Java/Scala % is called remainder and the "mod" operator (Modulo in Leon) is also
+   * defined on BigInteger and differs from Remainder. The "mod" operator
+   * returns an always positive remainder, while Remainder could return
    * a negative remainder. The following must hold:
    *
-   *    Division(x, y) * y + Modulo(x, y) == x
+   *    Division(x, y) * y + Remainder(x, y) == x
    */
   case class Division(lhs: Expr, rhs: Expr) extends Expr { 
     require(lhs.getType == IntegerType && rhs.getType == IntegerType)
     val getType = IntegerType
   }
+  case class Remainder(lhs: Expr, rhs: Expr) extends Expr { 
+    require(lhs.getType == IntegerType && rhs.getType == IntegerType)
+    val getType = IntegerType
+  }
   case class Modulo(lhs: Expr, rhs: Expr) extends Expr { 
     require(lhs.getType == IntegerType && rhs.getType == IntegerType)
     val getType = IntegerType
@@ -377,7 +381,7 @@ object Expressions {
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
-  case class BVModulo(lhs: Expr, rhs: Expr) extends Expr { 
+  case class BVRemainder(lhs: Expr, rhs: Expr) extends Expr { 
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala
index 249c4622e..0bacc4a72 100644
--- a/src/main/scala/leon/purescala/Extractors.scala
+++ b/src/main/scala/leon/purescala/Extractors.scala
@@ -52,6 +52,7 @@ object Extractors {
       case Minus(t1,t2) => Some((t1,t2,Minus))
       case Times(t1,t2) => Some((t1,t2,Times))
       case Division(t1,t2) => Some((t1,t2,Division))
+      case Remainder(t1,t2) => Some((t1,t2,Remainder))
       case Modulo(t1,t2) => Some((t1,t2,Modulo))
       case LessThan(t1,t2) => Some((t1,t2,LessThan))
       case GreaterThan(t1,t2) => Some((t1,t2,GreaterThan))
@@ -61,7 +62,7 @@ object Extractors {
       case BVMinus(t1,t2) => Some((t1,t2,BVMinus))
       case BVTimes(t1,t2) => Some((t1,t2,BVTimes))
       case BVDivision(t1,t2) => Some((t1,t2,BVDivision))
-      case BVModulo(t1,t2) => Some((t1,t2,BVModulo))
+      case BVRemainder(t1,t2) => Some((t1,t2,BVRemainder))
       case BVAnd(t1,t2) => Some((t1,t2,BVAnd))
       case BVOr(t1,t2) => Some((t1,t2,BVOr))
       case BVXOr(t1,t2) => Some((t1,t2,BVXOr))
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index b274f8eda..9dbcf0989 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -357,7 +357,8 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case Minus(l,r)                => optP { p"$l - $r" }
       case Times(l,r)                => optP { p"$l * $r" }
       case Division(l,r)             => optP { p"$l / $r" }
-      case Modulo(l,r)               => optP { p"$l % $r" }
+      case Remainder(l,r)            => optP { p"$l % $r" }
+      case Modulo(l,r)               => optP { p"$l mod $r" }
       case LessThan(l,r)             => optP { p"$l < $r" }
       case GreaterThan(l,r)          => optP { p"$l > $r" }
       case LessEquals(l,r)           => optP { p"$l <= $r" }
@@ -366,7 +367,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case BVMinus(l,r)              => optP { p"$l - $r" }
       case BVTimes(l,r)              => optP { p"$l * $r" }
       case BVDivision(l,r)           => optP { p"$l / $r" }
-      case BVModulo(l,r)             => optP { p"$l % $r" }
+      case BVRemainder(l,r)          => optP { p"$l % $r" }
       case BVAnd(l,r)                => optP { p"$l & $r" }
       case BVOr(l,r)                 => optP { p"$l | $r" }
       case BVXOr(l,r)                => optP { p"$l ^ $r" }
@@ -741,9 +742,10 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
     case (_: And | BinaryMethodCall(_, "&&", _)) => 3
     case (_: GreaterThan | _: GreaterEquals  | _: LessEquals | _: LessThan) => 4
     case (_: Equals | _: Not) => 5
-    case (_: Plus | _: BVPlus | _: Minus | _: BVMinus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 6
-    case (_: Times | _: BVTimes | _: Division | _: BVDivision | _: Modulo | _: BVModulo | BinaryMethodCall(_, "*" | "/", _)) => 7
-    case _ => 7
+    case (_: Modulo) => 6
+    case (_: Plus | _: BVPlus | _: Minus | _: BVMinus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 7
+    case (_: Times | _: BVTimes | _: Division | _: BVDivision | _: Remainder | _: BVRemainder | BinaryMethodCall(_, "*" | "/", _)) => 8
+    case _ => 9
   }
 
   def requiresParentheses(ex: Tree, within: Option[Tree]): Boolean = (ex, within) match {
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
index ae77673d8..0ac1f11e6 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
@@ -649,10 +649,13 @@ abstract class SMTLIBSolver(val context: LeonContext,
           Ints.Div(ar, br),
           Ints.Neg(Ints.Div(Ints.Neg(ar), br)))
       }
-      case Modulo(a,b) => {
+      case Remainder(a,b) => {
         val q = toSMT(Division(a, b))
         Ints.Sub(toSMT(a), Ints.Mul(toSMT(b), q))
       }
+      case Modulo(a,b) => {
+        Ints.Mod(toSMT(a), toSMT(b))
+      }
       case LessThan(a,b) => a.getType match {
         case Int32Type => FixedSizeBitVectors.SLessThan(toSMT(a), toSMT(b))
         case IntegerType => Ints.LessThan(toSMT(a), toSMT(b))
@@ -677,7 +680,7 @@ abstract class SMTLIBSolver(val context: LeonContext,
       case BVMinus(a,b) => FixedSizeBitVectors.Sub(toSMT(a), toSMT(b))
       case BVTimes(a,b) => FixedSizeBitVectors.Mul(toSMT(a), toSMT(b))
       case BVDivision(a,b) => FixedSizeBitVectors.SDiv(toSMT(a), toSMT(b))
-      case BVModulo(a,b) => FixedSizeBitVectors.SRem(toSMT(a), toSMT(b))
+      case BVRemainder(a,b) => FixedSizeBitVectors.SRem(toSMT(a), toSMT(b))
       case BVAnd(a,b) => FixedSizeBitVectors.And(toSMT(a), toSMT(b))
       case BVOr(a,b) => FixedSizeBitVectors.Or(toSMT(a), toSMT(b))
       case BVXOr(a,b) => FixedSizeBitVectors.XOr(toSMT(a), toSMT(b))
diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
index d8ac22b21..e036c86eb 100644
--- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
@@ -569,16 +569,19 @@ trait AbstractZ3Solver
           z3.mkUnaryMinus(z3.mkDiv(z3.mkUnaryMinus(rl), rr))
         )
       }
-      case Modulo(l, r) => {
+      case Remainder(l, r) => {
         val q = rec(Division(l, r))
         z3.mkSub(rec(l), z3.mkMul(rec(r), q))
       }
+      case Modulo(l, r) => {
+        z3.mkMod(rec(l), rec(r))
+      }
       case UMinus(e) => z3.mkUnaryMinus(rec(e))
       case BVPlus(l, r) => z3.mkBVAdd(rec(l), rec(r))
       case BVMinus(l, r) => z3.mkBVSub(rec(l), rec(r))
       case BVTimes(l, r) => z3.mkBVMul(rec(l), rec(r))
       case BVDivision(l, r) => z3.mkBVSdiv(rec(l), rec(r))
-      case BVModulo(l, r) => z3.mkBVSrem(rec(l), rec(r))
+      case BVRemainder(l, r) => z3.mkBVSrem(rec(l), rec(r))
       case BVUMinus(e) => z3.mkBVNeg(rec(e))
       case BVNot(e) => z3.mkBVNot(rec(e))
       case BVAnd(l, r) => z3.mkBVAnd(rec(l), rec(r))
diff --git a/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala b/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala
index b4b4540cd..ad359346a 100644
--- a/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala
+++ b/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala
@@ -79,10 +79,13 @@ class DefaultEvaluatorTests extends leon.test.LeonTestSuite {
       InfiniteIntegerLiteral(6))
   }
 
-  test("Eval of division and modulo semantics for BigInt") {
+  test("Eval of division, remainder and modulo semantics for BigInt") {
     expectSuccessful(
       defaultEvaluator.eval(Division(InfiniteIntegerLiteral(10), InfiniteIntegerLiteral(3))), 
       InfiniteIntegerLiteral(3))
+    expectSuccessful(
+      defaultEvaluator.eval(Remainder(InfiniteIntegerLiteral(10), InfiniteIntegerLiteral(3))), 
+      InfiniteIntegerLiteral(1))
     expectSuccessful(
       defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(10), InfiniteIntegerLiteral(3))), 
       InfiniteIntegerLiteral(1))
@@ -91,51 +94,60 @@ class DefaultEvaluatorTests extends leon.test.LeonTestSuite {
       defaultEvaluator.eval(Division(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(3))), 
       InfiniteIntegerLiteral(0))
     expectSuccessful(
-      defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(3))), 
+      defaultEvaluator.eval(Remainder(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(3))), 
       InfiniteIntegerLiteral(-1))
+    expectSuccessful(
+      defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(3))), 
+      InfiniteIntegerLiteral(2))
 
     expectSuccessful(
       defaultEvaluator.eval(Division(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(-3))), 
       InfiniteIntegerLiteral(0))
     expectSuccessful(
-      defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(-3))), 
+      defaultEvaluator.eval(Remainder(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(-3))), 
       InfiniteIntegerLiteral(-1))
+    expectSuccessful(
+      defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(-1), InfiniteIntegerLiteral(-3))), 
+      InfiniteIntegerLiteral(2))
 
     expectSuccessful(
       defaultEvaluator.eval(Division(InfiniteIntegerLiteral(1), InfiniteIntegerLiteral(-3))), 
       InfiniteIntegerLiteral(0))
+    expectSuccessful(
+      defaultEvaluator.eval(Remainder(InfiniteIntegerLiteral(1), InfiniteIntegerLiteral(-3))), 
+      InfiniteIntegerLiteral(1))
     expectSuccessful(
       defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(1), InfiniteIntegerLiteral(-3))), 
       InfiniteIntegerLiteral(1))
   }
 
-  test("Eval of division and modulo semantics for bit vectors") {
+  test("Eval of division and remainder semantics for bit vectors") {
     expectSuccessful(
       defaultEvaluator.eval(BVDivision(IntLiteral(10), IntLiteral(3))), 
       IntLiteral(3))
     expectSuccessful(
-      defaultEvaluator.eval(BVModulo(IntLiteral(10), IntLiteral(3))), 
+      defaultEvaluator.eval(BVRemainder(IntLiteral(10), IntLiteral(3))), 
       IntLiteral(1))
 
     expectSuccessful(
       defaultEvaluator.eval(BVDivision(IntLiteral(-1), IntLiteral(3))), 
       IntLiteral(0))
     expectSuccessful(
-      defaultEvaluator.eval(BVModulo(IntLiteral(-1), IntLiteral(3))), 
+      defaultEvaluator.eval(BVRemainder(IntLiteral(-1), IntLiteral(3))), 
       IntLiteral(-1))
 
     expectSuccessful(
       defaultEvaluator.eval(BVDivision(IntLiteral(-1), IntLiteral(-3))), 
       IntLiteral(0))
     expectSuccessful(
-      defaultEvaluator.eval(BVModulo(IntLiteral(-1), IntLiteral(-3))), 
+      defaultEvaluator.eval(BVRemainder(IntLiteral(-1), IntLiteral(-3))), 
       IntLiteral(-1))
 
     expectSuccessful(
       defaultEvaluator.eval(BVDivision(IntLiteral(1), IntLiteral(-3))), 
       IntLiteral(0))
     expectSuccessful(
-      defaultEvaluator.eval(BVModulo(IntLiteral(1), IntLiteral(-3))), 
+      defaultEvaluator.eval(BVRemainder(IntLiteral(1), IntLiteral(-3))), 
       IntLiteral(1))
   }
 
diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
index 20bd91732..f34d82dee 100644
--- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
+++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
@@ -174,7 +174,7 @@ class EvaluatorsTests extends leon.test.LeonTestSuite {
                |    if(s > n) c else intSqrt0(n, c+1)
                |  }
                |  def div(x : Int, y : Int) : Int = (x / y)
-               |  def mod(x : Int, y : Int) : Int = (x % y)
+               |  def rem(x : Int, y : Int) : Int = (x % y)
                |}
                |""".stripMargin
 
@@ -191,15 +191,15 @@ class EvaluatorsTests extends leon.test.LeonTestSuite {
       checkComp(e, mkCall("div", IL(7), IL(-5)), IL(-1))
       checkComp(e, mkCall("div", IL(-7), IL(5)), IL(-1))
       checkComp(e, mkCall("div", IL(-7), IL(-5)), IL(1))
-      checkComp(e, mkCall("mod", IL(7), IL(5)), IL(2))
-      checkComp(e, mkCall("mod", IL(7), IL(-5)), IL(2))
-      checkComp(e, mkCall("mod", IL(-7), IL(5)), IL(-2))
-      checkComp(e, mkCall("mod", IL(-7), IL(-5)), IL(-2))
-      checkComp(e, mkCall("mod", IL(-1), IL(5)), IL(-1))
+      checkComp(e, mkCall("rem", IL(7), IL(5)), IL(2))
+      checkComp(e, mkCall("rem", IL(7), IL(-5)), IL(2))
+      checkComp(e, mkCall("rem", IL(-7), IL(5)), IL(-2))
+      checkComp(e, mkCall("rem", IL(-7), IL(-5)), IL(-2))
+      checkComp(e, mkCall("rem", IL(-1), IL(5)), IL(-1))
 
       // Things that should crash.
       checkError(e, mkCall("div", IL(42), IL(0))) 
-      checkError(e, mkCall("mod", IL(42), IL(0)))
+      checkError(e, mkCall("rem", IL(42), IL(0)))
     }
   }
 
@@ -215,7 +215,8 @@ class EvaluatorsTests extends leon.test.LeonTestSuite {
                |    if(s > n) c else intSqrt0(n, c+1)
                |  }
                |  def div(x : BigInt, y : BigInt) : BigInt = (x / y)
-               |  def mod(x : BigInt, y : BigInt) : BigInt = (x % y)
+               |  def rem(x : BigInt, y : BigInt) : BigInt = (x % y)
+               |  def mod(x : BigInt, y : BigInt) : BigInt = (x mod y)
                |}
                |""".stripMargin
 
@@ -232,14 +233,20 @@ class EvaluatorsTests extends leon.test.LeonTestSuite {
       checkComp(e, mkCall("div", BIL(7), BIL(-5)), BIL(-1))
       checkComp(e, mkCall("div", BIL(-7), BIL(5)), BIL(-1))
       checkComp(e, mkCall("div", BIL(-7), BIL(-5)), BIL(1))
+      checkComp(e, mkCall("rem", BIL(7), BIL(5)), BIL(2))
+      checkComp(e, mkCall("rem", BIL(7), BIL(-5)), BIL(2))
+      checkComp(e, mkCall("rem", BIL(-7), BIL(5)), BIL(-2))
+      checkComp(e, mkCall("rem", BIL(-7), BIL(-5)), BIL(-2))
+      checkComp(e, mkCall("rem", BIL(-1), BIL(5)), BIL(-1))
       checkComp(e, mkCall("mod", BIL(7), BIL(5)), BIL(2))
       checkComp(e, mkCall("mod", BIL(7), BIL(-5)), BIL(2))
-      checkComp(e, mkCall("mod", BIL(-7), BIL(5)), BIL(-2))
-      checkComp(e, mkCall("mod", BIL(-7), BIL(-5)), BIL(-2))
-      checkComp(e, mkCall("mod", BIL(-1), BIL(5)), BIL(-1))
+      checkComp(e, mkCall("mod", BIL(-7), BIL(5)), BIL(3))
+      checkComp(e, mkCall("mod", BIL(-7), BIL(-5)), BIL(3))
+      checkComp(e, mkCall("mod", BIL(-1), BIL(5)), BIL(4))
 
       // Things that should crash.
       checkError(e, mkCall("div", BIL(42), BIL(0))) 
+      checkError(e, mkCall("rem", BIL(42), BIL(0)))
       checkError(e, mkCall("mod", BIL(42), BIL(0)))
     }
   }
-- 
GitLab