From 673f4faebd6bcc0c797a2c16539edf354bb685df Mon Sep 17 00:00:00 2001 From: Regis Blanc <regwblanc@gmail.com> Date: Tue, 26 May 2015 15:44:07 +0200 Subject: [PATCH] fix codegen evaluator for Modulo --- .../java/leon/codegen/runtime/BigInt.java | 4 ++ .../scala/leon/codegen/CodeGeneration.scala | 3 +- .../test/evaluators/EvaluatorsTests.scala | 43 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/main/java/leon/codegen/runtime/BigInt.java b/src/main/java/leon/codegen/runtime/BigInt.java index 03f12972c..83de0fbb4 100644 --- a/src/main/java/leon/codegen/runtime/BigInt.java +++ b/src/main/java/leon/codegen/runtime/BigInt.java @@ -35,6 +35,10 @@ public final class BigInt { return new BigInt(_underlying.divide(that.underlying())); } + public BigInt rem(BigInt that) { + return new BigInt(_underlying.remainder(that.underlying())); + } + public BigInt mod(BigInt that) { return new BigInt(_underlying.mod(that.underlying())); } diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index 34cd1a9db..1d5dee8b4 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -644,10 +644,11 @@ 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) => mkExpr(l, ch) mkExpr(r, ch) - ch << InvokeVirtual(BigIntClass, "mod", s"(L$BigIntClass;)L$BigIntClass;") + ch << InvokeVirtual(BigIntClass, "rem", s"(L$BigIntClass;)L$BigIntClass;") case UMinus(e) => mkExpr(e, ch) diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala index 81eee7077..9c4418137 100644 --- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala +++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala @@ -161,6 +161,7 @@ class EvaluatorsTests extends leon.test.LeonTestSuite { private def T = BooleanLiteral(true) private def F = BooleanLiteral(false) private def IL(i : Int) = IntLiteral(i) + private def BIL(i : Int) = InfiniteIntegerLiteral(i) test("Arithmetic") { val p = """|object Program { @@ -195,6 +196,7 @@ class EvaluatorsTests extends leon.test.LeonTestSuite { 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)) // Things that should crash. checkError(e, mkCall("div", IL(42), IL(0))) @@ -202,6 +204,47 @@ class EvaluatorsTests extends leon.test.LeonTestSuite { } } + test("BigInt Arithmetic") { + val p = """|object Program { + | def plus(x : BigInt, y : BigInt) : BigInt = x + y + | def max(x : BigInt, y : BigInt) : BigInt = if(x >= y) x else y + | def square(i : BigInt) : BigInt = { val j = i; j * i } + | def abs(i : BigInt) : BigInt = if(i < 0) -i else i + | def intSqrt(n : BigInt) : BigInt = intSqrt0(abs(n), 0) + | def intSqrt0(n : BigInt, c : BigInt) : BigInt = { + | val s = square(c+1) + | 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) + |} + |""".stripMargin + + implicit val prog = parseString(p) + val evaluators = prepareEvaluators + + for(e <- evaluators) { + // Some simple math. + checkComp(e, mkCall("plus", BIL(60), UMinus(BIL(18))), BIL(42)) + checkComp(e, mkCall("max", BIL(4), BIL(42)), BIL(42)) + checkComp(e, mkCall("max", BIL(42), UMinus(BIL(42))), BIL(42)) + checkComp(e, mkCall("intSqrt", UMinus(BIL(1800))), BIL(42)) + 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("div", BIL(-7), 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)) + + // Things that should crash. + checkError(e, mkCall("div", BIL(42), BIL(0))) + checkError(e, mkCall("mod", BIL(42), BIL(0))) + } + } + test("Booleans") { val p = """|object Program { |def and1(x : Boolean, y : Boolean) : Boolean = x && y -- GitLab