diff --git a/build.sbt b/build.sbt
index de14da5952368a72ed5f88fd42c10af7599f5b63..4b8234b849d852eaa8db6a7a9073dcb9bd530307 100644
--- a/build.sbt
+++ b/build.sbt
@@ -110,10 +110,16 @@ sourcesInBase in Compile := false
 
 lazy val PerfTest = config("perf") extend(Test)
 
+lazy val UnitTest = config("unit-test") extend(Test)
+
 scalaSource in PerfTest := baseDirectory.value / "src/test/scala/"
 
+scalaSource in UnitTest := baseDirectory.value / "src/unit-test/scala/"
+
 parallelExecution in PerfTest := false
 
+parallelExecution in UnitTest := true
+
 testOptions in (PerfTest, test) := Seq(Tests.Filter(s => s.endsWith("PerfTest")))
 
 def ghProject(repo: String, version: String) = RootProject(uri(s"${repo}#${version}"))
@@ -124,6 +130,8 @@ lazy val scalaSmtLib = ghProject("git://github.com/regb/scala-smtlib.git", "6b74
 
 lazy val root = (project in file(".")).
   configs(PerfTest).
+  configs(UnitTest).
   dependsOn(bonsai, scalaSmtLib).
-  settings(inConfig(PerfTest)(Defaults.testSettings): _*)
+  settings(inConfig(PerfTest)(Defaults.testSettings): _*).
+  settings(inConfig(UnitTest)(Defaults.testSettings): _*)
 
diff --git a/src/unit-test/scala/leon/LeonTestSuite.scala b/src/unit-test/scala/leon/LeonTestSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..050ddf976980986b46084e681f3da06ae8a84d84
--- /dev/null
+++ b/src/unit-test/scala/leon/LeonTestSuite.scala
@@ -0,0 +1,105 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+
+import utils._
+
+import org.scalatest._
+import org.scalatest.exceptions.TestFailedException
+
+trait LeonTestSuite extends FunSuite {
+
+  def createLeonContext(opts: String*): LeonContext = {
+    val reporter = new TestSilentReporter
+
+    Main.processOptions(opts.toList).copy(reporter = reporter, interruptManager = new InterruptManager(reporter))
+  }
+
+  //var testContext: LeonContext = null
+
+  //override def beforeEach() = {
+  //  testContext = createLeonContext()
+  //  super.beforeEach()
+  //}
+
+  //def testIdentifier(name: String): String = {
+  //  def sanitize(s: String) = s.replaceAll("[^0-9a-zA-Z-]", "")
+
+  //  sanitize(this.getClass.getName)+"/"+sanitize(name)
+  //}
+
+  //def bookKeepingFile(id: String) = {
+  //  import java.io.File
+
+  //  val f = new File(System.getProperty("user.dir")+"/.test-history/"+id+".log")
+
+  //  f.getParentFile.mkdirs()
+
+  //  f
+  //}
+
+  //def getStats(id: String): Statistics = {
+  //  val f = bookKeepingFile(id)
+
+  //  if (f.canRead) {
+  //    Statistics(Source.fromFile(f).getLines().flatMap{ line =>
+  //      val l = line.trim
+  //      if (l.length > 0) {
+  //        Some(line.toLong)
+  //      } else {
+  //        None
+  //      }
+  //    }.toList)
+  //  } else {
+  //    Statistics(Nil)
+  //  }
+  //}
+
+  //def storeStats(id: String, stats: Statistics) {
+  //  import java.io.FileWriter
+
+  //  val f = bookKeepingFile(id)
+
+  //  val fw = new FileWriter(f, true)
+  //  fw.write(stats.values.head+"\n")
+  //  fw.close()
+  //}
+
+  //override implicit val defaultInterruptor = new Interruptor {
+  //  def apply(t: Thread) {
+  //    testContext.interruptManager.interrupt()
+  //  }
+  //}
+
+  //def testWithTimeout(name: String, timeout: Span)(body: => Unit) {
+  //  super.test(name) {
+  //    val id = testIdentifier(name)
+
+  //    val ts = now()
+
+  //    failAfter(timeout) {
+  //      try {
+  //        body
+  //      } catch {
+  //        case fe: LeonFatalError =>
+  //          testContext.reporter match {
+  //            case sr: TestSilentReporter =>
+  //              sr.lastErrors ++= fe.msg
+  //              throw new TestFailedException(sr.lastErrors.mkString("\n"), fe, 5)
+  //          }
+  //      }
+  //    }
+
+  //    val total = now()-ts
+
+  //    val stats = getStats(id)
+
+  //    if (!stats.accountsFor(total)) {
+  //      info(Console.YELLOW+"[warning] Test took too long to run: "+total+"ms (avg: "+stats.avg+", stddev: "+stats.stddev+")")
+  //    }
+
+  //    storeStats(id, stats.withValue(total))
+  //  }
+  //}
+
+}
diff --git a/src/unit-test/scala/leon/TestSilentReporter.scala b/src/unit-test/scala/leon/TestSilentReporter.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9802995c66f505e0820842898045d4a8fcfc74a9
--- /dev/null
+++ b/src/unit-test/scala/leon/TestSilentReporter.scala
@@ -0,0 +1,13 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+
+class TestSilentReporter extends DefaultReporter(Set()) {
+  var lastErrors: List[String] = Nil
+
+  override def emit(msg: Message): Unit = msg match { 
+    case Message(this.ERROR, _, msg) => lastErrors ++= List(msg.toString)
+    case Message(this.FATAL, _, msg) => lastErrors ++= List(msg.toString)
+    case _ =>
+  }
+}
diff --git a/src/unit-test/scala/leon/evaluators/DefaultEvaluatorSuite.scala b/src/unit-test/scala/leon/evaluators/DefaultEvaluatorSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..8ac29542fc1a2ee0f78a2bae5bdb9e5eedc47022
--- /dev/null
+++ b/src/unit-test/scala/leon/evaluators/DefaultEvaluatorSuite.scala
@@ -0,0 +1,359 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import leon._
+import leon.evaluators._
+import leon.purescala.Common._
+import leon.purescala.Definitions._
+import leon.purescala.Expressions._
+import leon.purescala.Types._
+import leon.purescala.Constructors._
+
+class DefaultEvaluatorSuite extends leon.test.LeonTestSuite {
+
+  private implicit lazy val leonContext: LeonContext = createLeonContext()
+  private val emptyProgram = Program.empty
+
+  private val defaultEvaluator = new DefaultEvaluator(leonContext, emptyProgram)
+
+  def expectSuccessful(res: EvaluationResults.Result, expected: Expr): Unit = {
+    res match {
+      case EvaluationResults.Successful(value) => assert(value === expected)
+      case _ => assert(false)
+    }
+  }
+
+  test("eval correctly evaluates literals") {
+    expectSuccessful(defaultEvaluator.eval(BooleanLiteral(true)), BooleanLiteral(true))
+    expectSuccessful(defaultEvaluator.eval(BooleanLiteral(false)), BooleanLiteral(false))
+    expectSuccessful(defaultEvaluator.eval(IntLiteral(0)), IntLiteral(0))
+    expectSuccessful(defaultEvaluator.eval(IntLiteral(42)), IntLiteral(42))
+    expectSuccessful(defaultEvaluator.eval(UnitLiteral()), UnitLiteral())
+    expectSuccessful(defaultEvaluator.eval(InfiniteIntegerLiteral(0)), InfiniteIntegerLiteral(0))
+    expectSuccessful(defaultEvaluator.eval(InfiniteIntegerLiteral(42)), InfiniteIntegerLiteral(42))
+    expectSuccessful(defaultEvaluator.eval(RealLiteral(0)), RealLiteral(0))
+    expectSuccessful(defaultEvaluator.eval(RealLiteral(42)), RealLiteral(42))
+    expectSuccessful(defaultEvaluator.eval(RealLiteral(13.255)), RealLiteral(13.255))
+  }
+
+  test("eval of simple bit vector arithmetic expressions") {
+    expectSuccessful(defaultEvaluator.eval(BVPlus(IntLiteral(3), IntLiteral(5))), IntLiteral(8))
+    expectSuccessful(defaultEvaluator.eval(BVPlus(IntLiteral(0), IntLiteral(5))), IntLiteral(5))
+    expectSuccessful(defaultEvaluator.eval(BVTimes(IntLiteral(3), IntLiteral(3))), IntLiteral(9))
+  }
+
+  test("eval bitwise operations") {
+    expectSuccessful(defaultEvaluator.eval(BVAnd(IntLiteral(3), IntLiteral(1))), IntLiteral(1))
+    expectSuccessful(defaultEvaluator.eval(BVAnd(IntLiteral(3), IntLiteral(3))), IntLiteral(3))
+    expectSuccessful(defaultEvaluator.eval(BVAnd(IntLiteral(5), IntLiteral(3))), IntLiteral(1))
+    expectSuccessful(defaultEvaluator.eval(BVAnd(IntLiteral(5), IntLiteral(4))), IntLiteral(4))
+    expectSuccessful(defaultEvaluator.eval(BVAnd(IntLiteral(5), IntLiteral(2))), IntLiteral(0))
+
+    expectSuccessful(defaultEvaluator.eval(BVOr(IntLiteral(3), IntLiteral(1))), IntLiteral(3))
+    expectSuccessful(defaultEvaluator.eval(BVOr(IntLiteral(3), IntLiteral(3))), IntLiteral(3))
+    expectSuccessful(defaultEvaluator.eval(BVOr(IntLiteral(5), IntLiteral(3))), IntLiteral(7))
+    expectSuccessful(defaultEvaluator.eval(BVOr(IntLiteral(5), IntLiteral(4))), IntLiteral(5))
+    expectSuccessful(defaultEvaluator.eval(BVOr(IntLiteral(5), IntLiteral(2))), IntLiteral(7))
+
+    expectSuccessful(defaultEvaluator.eval(BVXOr(IntLiteral(3), IntLiteral(1))), IntLiteral(2))
+    expectSuccessful(defaultEvaluator.eval(BVXOr(IntLiteral(3), IntLiteral(3))), IntLiteral(0))
+
+    expectSuccessful(defaultEvaluator.eval(BVNot(IntLiteral(1))), IntLiteral(-2))
+
+    expectSuccessful(defaultEvaluator.eval(BVShiftLeft(IntLiteral(3), IntLiteral(1))), IntLiteral(6))
+    expectSuccessful(defaultEvaluator.eval(BVShiftLeft(IntLiteral(4), IntLiteral(2))), IntLiteral(16))
+
+    expectSuccessful(defaultEvaluator.eval(BVLShiftRight(IntLiteral(8), IntLiteral(1))), IntLiteral(4))
+    expectSuccessful(defaultEvaluator.eval(BVAShiftRight(IntLiteral(8), IntLiteral(1))), IntLiteral(4))
+  }
+
+  test("eval of simple arithmetic expressions") {
+    expectSuccessful(
+      defaultEvaluator.eval(Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(5))), 
+      InfiniteIntegerLiteral(8))
+    expectSuccessful(
+      defaultEvaluator.eval(Minus(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(2))), 
+      InfiniteIntegerLiteral(5))
+    expectSuccessful(
+      defaultEvaluator.eval(UMinus(InfiniteIntegerLiteral(7))),
+      InfiniteIntegerLiteral(-7))
+    expectSuccessful(
+      defaultEvaluator.eval(Times(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3))), 
+      InfiniteIntegerLiteral(6))
+  }
+
+  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))
+
+    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(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(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 simple arithmetic comparisons over integers") {
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(4))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(7))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(InfiniteIntegerLiteral(4), InfiniteIntegerLiteral(7))), BooleanLiteral(false)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(4))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(7))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(InfiniteIntegerLiteral(4), InfiniteIntegerLiteral(7))), BooleanLiteral(false)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(4))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(7))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(InfiniteIntegerLiteral(4), InfiniteIntegerLiteral(7))), BooleanLiteral(true)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(4))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(7))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(InfiniteIntegerLiteral(4), InfiniteIntegerLiteral(7))), BooleanLiteral(true)
+    )
+  }
+
+
+  test("Eval of division and remainder semantics for bit vectors") {
+    expectSuccessful(
+      defaultEvaluator.eval(BVDivision(IntLiteral(10), IntLiteral(3))), 
+      IntLiteral(3))
+    expectSuccessful(
+      defaultEvaluator.eval(BVRemainder(IntLiteral(10), IntLiteral(3))), 
+      IntLiteral(1))
+
+    expectSuccessful(
+      defaultEvaluator.eval(BVDivision(IntLiteral(-1), IntLiteral(3))), 
+      IntLiteral(0))
+    expectSuccessful(
+      defaultEvaluator.eval(BVRemainder(IntLiteral(-1), IntLiteral(3))), 
+      IntLiteral(-1))
+
+    expectSuccessful(
+      defaultEvaluator.eval(BVDivision(IntLiteral(-1), IntLiteral(-3))), 
+      IntLiteral(0))
+    expectSuccessful(
+      defaultEvaluator.eval(BVRemainder(IntLiteral(-1), IntLiteral(-3))), 
+      IntLiteral(-1))
+
+    expectSuccessful(
+      defaultEvaluator.eval(BVDivision(IntLiteral(1), IntLiteral(-3))), 
+      IntLiteral(0))
+    expectSuccessful(
+      defaultEvaluator.eval(BVRemainder(IntLiteral(1), IntLiteral(-3))), 
+      IntLiteral(1))
+  }
+
+  test("Eval of simple boolean operations") {
+    expectSuccessful(
+      defaultEvaluator.eval(And(BooleanLiteral(true), BooleanLiteral(true))),
+      BooleanLiteral(true))
+    expectSuccessful(
+      defaultEvaluator.eval(And(BooleanLiteral(true), BooleanLiteral(false))),
+      BooleanLiteral(false))
+    expectSuccessful(
+      defaultEvaluator.eval(And(BooleanLiteral(false), BooleanLiteral(false))),
+      BooleanLiteral(false))
+    expectSuccessful(
+      defaultEvaluator.eval(And(BooleanLiteral(false), BooleanLiteral(true))),
+      BooleanLiteral(false))
+    expectSuccessful(
+      defaultEvaluator.eval(Or(BooleanLiteral(true), BooleanLiteral(true))),
+      BooleanLiteral(true))
+    expectSuccessful(
+      defaultEvaluator.eval(Or(BooleanLiteral(true), BooleanLiteral(false))),
+      BooleanLiteral(true))
+    expectSuccessful(
+      defaultEvaluator.eval(Or(BooleanLiteral(false), BooleanLiteral(false))),
+      BooleanLiteral(false))
+    expectSuccessful(
+      defaultEvaluator.eval(Or(BooleanLiteral(false), BooleanLiteral(true))),
+      BooleanLiteral(true))
+    expectSuccessful(
+      defaultEvaluator.eval(Not(BooleanLiteral(false))),
+      BooleanLiteral(true))
+    expectSuccessful(
+      defaultEvaluator.eval(Not(BooleanLiteral(true))),
+      BooleanLiteral(false))
+  }
+
+  test("eval of simple arithmetic expressions over real") {
+    expectSuccessful(
+      defaultEvaluator.eval(RealPlus(RealLiteral(3), RealLiteral(5))), 
+      RealLiteral(8))
+    expectSuccessful(
+      defaultEvaluator.eval(RealMinus(RealLiteral(7), RealLiteral(2))), 
+      RealLiteral(5))
+    expectSuccessful(
+      defaultEvaluator.eval(RealUMinus(RealLiteral(7))),
+      RealLiteral(-7))
+    expectSuccessful(
+      defaultEvaluator.eval(RealTimes(RealLiteral(2), RealLiteral(3))), 
+      RealLiteral(6))
+
+    expectSuccessful(
+      defaultEvaluator.eval(RealPlus(RealLiteral(2.5), RealLiteral(3.5))), 
+      RealLiteral(6))
+  }
+
+  test("eval of simple arithmetic comparisons over real") {
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(RealLiteral(7), RealLiteral(4))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(RealLiteral(7), RealLiteral(7))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterEquals(RealLiteral(4), RealLiteral(7))), BooleanLiteral(false)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(RealLiteral(7), RealLiteral(4))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(RealLiteral(7), RealLiteral(7))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(GreaterThan(RealLiteral(4), RealLiteral(7))), BooleanLiteral(false)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(RealLiteral(7), RealLiteral(4))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(RealLiteral(7), RealLiteral(7))), BooleanLiteral(true)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessEquals(RealLiteral(4), RealLiteral(7))), BooleanLiteral(true)
+    )
+
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(RealLiteral(7), RealLiteral(4))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(RealLiteral(7), RealLiteral(7))), BooleanLiteral(false)
+    )
+    expectSuccessful(
+      defaultEvaluator.eval(LessThan(RealLiteral(4), RealLiteral(7))), BooleanLiteral(true)
+    )
+  }
+
+  test("eval simple variable") {
+    val id = FreshIdentifier("id", Int32Type)
+    expectSuccessful(
+      defaultEvaluator.eval(Variable(id), Map(id -> IntLiteral(23))),
+      IntLiteral(23))
+  }
+
+  test("eval with unbound variable should return EvaluatorError") {
+    val id = FreshIdentifier("id", Int32Type)
+    val foo = FreshIdentifier("foo", Int32Type)
+    val res = defaultEvaluator.eval(Variable(id), Map(foo -> IntLiteral(23)))
+    assert(res.isInstanceOf[EvaluationResults.EvaluatorError])
+  }
+
+  test("eval let expression") {
+    val id = FreshIdentifier("id")
+    expectSuccessful(
+      defaultEvaluator.eval(Let(id, IntLiteral(42), Variable(id))),
+      IntLiteral(42))
+  }
+
+
+  test("eval literal array ops") {
+    expectSuccessful(
+      defaultEvaluator.eval(finiteArray(Map[Int,Expr](), Some(IntLiteral(12), IntLiteral(7)), Int32Type)),
+      finiteArray(Map[Int,Expr](), Some(IntLiteral(12), IntLiteral(7)), Int32Type))
+    expectSuccessful(
+      defaultEvaluator.eval(
+        ArrayLength(finiteArray(Map[Int,Expr](), Some(IntLiteral(12), IntLiteral(7)), Int32Type))),
+      IntLiteral(7))
+    expectSuccessful(
+      defaultEvaluator.eval(ArraySelect(
+        finiteArray(Seq(IntLiteral(2), IntLiteral(4), IntLiteral(7))),
+        IntLiteral(1))),
+      IntLiteral(4))
+    expectSuccessful(
+      defaultEvaluator.eval(
+        ArrayUpdated(
+          finiteArray(Seq(IntLiteral(2), IntLiteral(4), IntLiteral(7))),
+          IntLiteral(1),
+          IntLiteral(42))),
+      finiteArray(Seq(IntLiteral(2), IntLiteral(42), IntLiteral(7))))
+  }
+
+  test("eval variable length of array") {
+    val id = FreshIdentifier("id", Int32Type)
+    expectSuccessful(
+      defaultEvaluator.eval(
+        ArrayLength(
+          finiteArray(Map[Int, Expr](), Some(IntLiteral(12), Variable(id)), Int32Type)),
+        Map(id -> IntLiteral(27))),
+      IntLiteral(27))
+  }
+
+  test("eval variable default value of array") {
+    val id = FreshIdentifier("id", Int32Type)
+    expectSuccessful(
+      defaultEvaluator.eval(
+        finiteArray(Map[Int, Expr](), Some(Variable(id), IntLiteral(7)), Int32Type),
+        Map(id -> IntLiteral(27))),
+      finiteArray(Map[Int, Expr](), Some(IntLiteral(27), IntLiteral(7)), Int32Type))
+  }
+
+}
diff --git a/src/unit-test/scala/leon/purescala/LikelyEqSuite.scala b/src/unit-test/scala/leon/purescala/LikelyEqSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..71115fac6993239883da8773f95ba1c09979c7bc
--- /dev/null
+++ b/src/unit-test/scala/leon/purescala/LikelyEqSuite.scala
@@ -0,0 +1,48 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.test.purescala
+
+import leon.test._
+import leon.purescala.Common._
+import leon.purescala.Expressions._
+import leon.purescala.Types._
+
+class LikelyEqSuite extends LeonTestSuite with WithLikelyEq {
+  def i(x: Int) = InfiniteIntegerLiteral(x)
+
+  val xId = FreshIdentifier("x", IntegerType)
+  val x = Variable(xId)
+  val yId = FreshIdentifier("y", IntegerType)
+  val y = Variable(yId)
+  val zId = FreshIdentifier("z", IntegerType)
+  val z = Variable(zId)
+
+  test("apply") {
+    assert(LikelyEq(Plus(x, x), Times(i(2), x), Set(xId)))
+    assert(LikelyEq(Plus(x, x), Times(x, i(2)), Set(xId)))
+
+    assert(LikelyEq(Plus(x, y), Plus(y, x), Set(xId, yId)))
+    assert(LikelyEq(Plus(Plus(x, y), y), Plus(x, Times(i(2), y)), Set(xId, yId)))
+
+    def defaultCompare(e1: Expr, e2: Expr) = e1 == e2
+
+    assert(LikelyEq(
+      Plus(i(2), Plus(x, y)), 
+      Plus(i(3), Plus(x, z)), 
+      Set(xId), 
+      BooleanLiteral(true),
+      defaultCompare, 
+      Map(yId -> i(2), zId -> i(1)))
+    )
+
+
+    assert(LikelyEq(
+      Plus(x, Times(i(2), Division(y, i(2))))
+      , Plus(x, y)
+      , Set(xId, yId)
+      , Equals(Modulo(y, i(2)), i(0))
+    ))
+
+  }
+  
+}
diff --git a/src/unit-test/scala/leon/purescala/TreeNormalizationsSuite.scala b/src/unit-test/scala/leon/purescala/TreeNormalizationsSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fc11c8a0911d937e3c81195bbca99490eb31ee39
--- /dev/null
+++ b/src/unit-test/scala/leon/purescala/TreeNormalizationsSuite.scala
@@ -0,0 +1,84 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.test.purescala
+
+import leon.test._
+
+import leon.purescala.Common._
+import leon.purescala.Types._
+import leon.purescala.Expressions._
+import leon.purescala.TreeNormalizations._
+
+class TreeNormalizationsSuite extends LeonTestSuite with WithLikelyEq {
+  def i(x: Int) = InfiniteIntegerLiteral(x)
+
+  val xId = FreshIdentifier("x", IntegerType)
+  val x = Variable(xId)
+  val yId = FreshIdentifier("y", IntegerType)
+  val y = Variable(yId)
+  val xs = Set(xId, yId)
+
+  val aId = FreshIdentifier("a", IntegerType)
+  val a = Variable(aId)
+  val bId = FreshIdentifier("b", IntegerType)
+  val b = Variable(bId)
+  val as = Set(aId, bId)
+  
+
+  def checkSameExpr(e1: Expr, e2: Expr, vs: Set[Identifier]) {
+    assert( //this outer assert should not be needed because of the nested one
+      LikelyEq(e1, e2, vs, BooleanLiteral(true), (e1, e2) => {assert(e1 === e2); true})
+    )
+  }
+
+  def toSum(es: Seq[Expr]) = es.reduceLeft(Plus)
+  def coefToSum(es: Array[Expr], vs: Array[Expr]) = es.zip(Array[Expr](InfiniteIntegerLiteral(1)) ++ vs).foldLeft[Expr](InfiniteIntegerLiteral(0))((acc, p) => Plus(acc, Times(p._1, p._2)))
+  
+  test("checkSameExpr") {
+    checkSameExpr(Plus(x, y), Plus(y, x), xs)
+    checkSameExpr(Plus(x, x), Times(x, i(2)), xs)
+    checkSameExpr(Plus(x, Plus(x, x)), Times(x, i(3)), xs)
+  }
+
+  test("multiply") {
+    val lhs = Seq(x, i(2))
+    val rhs = Seq(y, i(1))
+    checkSameExpr(Times(toSum(lhs), toSum(rhs)), toSum(multiply(lhs, rhs)), xs)
+    checkSameExpr(Times(toSum(rhs), toSum(lhs)), toSum(multiply(rhs, lhs)), xs)
+
+    val lhs2 = Seq(x, y, i(2))
+    val rhs2 = Seq(y, i(1), Times(i(2), x))
+    checkSameExpr(Times(toSum(lhs2), toSum(rhs2)), toSum(multiply(lhs2, rhs2)), xs)
+  }
+
+  test("expandedForm") {
+    val e1 = Times(Plus(x, i(2)), Plus(y, i(1)))
+    checkSameExpr(toSum(expandedForm(e1)), e1, xs)
+
+    val e2 = Times(Plus(x, Times(i(2), y)), Plus(Plus(x, y), i(1)))
+    checkSameExpr(toSum(expandedForm(e2)), e2, xs)
+
+    val e3 = Minus(Plus(x, Times(i(2), y)), Plus(Plus(x, y), i(1)))
+    checkSameExpr(toSum(expandedForm(e3)), e3, xs)
+
+    val e4 = UMinus(Plus(x, Times(i(2), y)))
+    checkSameExpr(toSum(expandedForm(e4)), e4, xs)
+  }
+
+  test("linearArithmeticForm") {
+    val xsOrder = Array(xId, yId)
+
+    val e1 = Plus(Times(Plus(x, i(2)), i(3)), Times(i(4), y))
+    checkSameExpr(coefToSum(linearArithmeticForm(e1, xsOrder), Array(x, y)), e1, xs)
+
+    val e2 = Plus(Times(Plus(x, i(2)), i(3)), Plus(Plus(a, Times(i(5), b)), Times(i(4), y)))
+    checkSameExpr(coefToSum(linearArithmeticForm(e2, xsOrder), Array(x, y)), e2, xs ++ as)
+
+    val e3 = Minus(Plus(x, i(3)), Plus(y, i(2)))
+    checkSameExpr(coefToSum(linearArithmeticForm(e3, xsOrder), Array(x, y)), e3, xs)
+
+    val e4 = Plus(Plus(i(0), i(2)), Times(i(-1), i(3)))
+    assert(linearArithmeticForm(e4, Array()) === Array(i(-1)))
+
+  }
+}
diff --git a/src/unit-test/scala/leon/purescala/TreeOpsSuite.scala b/src/unit-test/scala/leon/purescala/TreeOpsSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b73eec580ce50ed4dbde963b3ddeffe6db50d2d7
--- /dev/null
+++ b/src/unit-test/scala/leon/purescala/TreeOpsSuite.scala
@@ -0,0 +1,152 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.test.purescala
+
+import leon.test._
+import leon.purescala.Common._
+import leon.purescala.Expressions._
+import leon.purescala.Types._
+import leon.purescala.ExprOps._
+
+class TreeOpsSuite extends LeonTestSuite with WithLikelyEq {
+  
+  test("Path-aware simplifications") {
+    // TODO actually testing something here would be better, sorry
+    // PS
+
+    assert(true)
+  }
+
+  /**
+   * If the formula consist of some top level AND, find a top level
+   * Equals and extract it, return the remaining formula as well
+   */
+  def extractEquals(expr: Expr): (Option[Equals], Expr) = expr match {
+    case And(es) =>
+      // OK now I'm just messing with you.
+      val (r, nes) = es.foldLeft[(Option[Equals],Seq[Expr])]((None, Seq())) {
+        case ((None, nes), eq @ Equals(_,_)) => (Some(eq), nes)
+        case ((o, nes), e) => (o, e +: nes)
+      }
+      (r, And(nes.reverse))
+
+    case e => (None, e)
+  }
+
+
+  def i(x: Int) = InfiniteIntegerLiteral(x)
+
+  val xId = FreshIdentifier("x", IntegerType)
+  val x = Variable(xId)
+  val yId = FreshIdentifier("y", IntegerType)
+  val y = Variable(yId)
+  val xs = Set(xId, yId)
+
+  val aId = FreshIdentifier("a", IntegerType)
+  val a = Variable(aId)
+  val bId = FreshIdentifier("b", IntegerType)
+  val b = Variable(bId)
+  val as = Set(aId, bId)
+
+  def checkSameExpr(e1: Expr, e2: Expr, vs: Set[Identifier]) {
+    assert( //this outer assert should not be needed because of the nested one
+      LikelyEq(e1, e2, vs, BooleanLiteral(true), (e1, e2) => {assert(e1 === e2); true})
+    )
+  }
+
+  test("simplifyArithmetic") {
+    val e1 = Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))
+    checkSameExpr(e1, simplifyArithmetic(e1), Set())
+    val e2 = Plus(x, Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)))
+    checkSameExpr(e2, simplifyArithmetic(e2), Set(xId))
+
+    val e3 = Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))
+    checkSameExpr(e3, simplifyArithmetic(e3), Set())
+    val e4 = Plus(x, Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)))
+    checkSameExpr(e4, simplifyArithmetic(e4), Set(xId))
+    val e5 = Plus(x, Minus(x, InfiniteIntegerLiteral(2)))
+    checkSameExpr(e5, simplifyArithmetic(e5), Set(xId))
+
+    val e6 = Times(InfiniteIntegerLiteral(9), Plus(Division(x, InfiniteIntegerLiteral(3)), Division(x, InfiniteIntegerLiteral(6))))
+    checkSameExpr(e6, simplifyArithmetic(e6), Set(xId))
+  }
+
+  test("expandAndSimplifyArithmetic") {
+    val e1 = Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))
+    checkSameExpr(e1, expandAndSimplifyArithmetic(e1), Set())
+    val e2 = Plus(x, Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)))
+    checkSameExpr(e2, expandAndSimplifyArithmetic(e2), Set(xId))
+
+    val e3 = Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))
+    checkSameExpr(e3, expandAndSimplifyArithmetic(e3), Set())
+    val e4 = Plus(x, Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)))
+    checkSameExpr(e4, expandAndSimplifyArithmetic(e4), Set(xId))
+    val e5 = Plus(x, Minus(x, InfiniteIntegerLiteral(2)))
+    checkSameExpr(e5, expandAndSimplifyArithmetic(e5), Set(xId))
+
+    val e6 = Times(InfiniteIntegerLiteral(9), Plus(Division(x, InfiniteIntegerLiteral(3)), Division(x, InfiniteIntegerLiteral(6))))
+    checkSameExpr(e6, expandAndSimplifyArithmetic(e6), Set(xId))
+  }
+
+  test("extractEquals") {
+    val eq = Equals(a, b)
+    val lt1 = LessThan(a, b)
+    val lt2 = LessThan(b, a)
+    val lt3 = LessThan(x, y)
+
+    val f1 = And(Seq(eq, lt1, lt2, lt3))
+    val (eq1, r1) = extractEquals(f1)
+    assert(eq1 != None)
+    assert(eq1.get === eq)
+    assert(extractEquals(r1)._1 === None)
+
+    val f2 = And(Seq(lt1, lt2, eq, lt3))
+    val (eq2, r2) = extractEquals(f2)
+    assert(eq2 != None)
+    assert(eq2.get === eq)
+    assert(extractEquals(r2)._1 === None)
+
+    val f3 = And(Seq(lt1, eq, lt2, lt3, eq))
+    val (eq3, r3) = extractEquals(f3)
+    assert(eq3 != None)
+    assert(eq3.get === eq)
+    val (eq4, r4) = extractEquals(r3)
+    assert(eq4 != None)
+    assert(eq4.get === eq)
+    assert(extractEquals(r4)._1 === None)
+  }
+
+  test("pre and post traversal") {
+    val expr = Plus(InfiniteIntegerLiteral(1), Minus(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3)))
+    var res = ""
+    def f(e: Expr): Unit = e match {
+      case InfiniteIntegerLiteral(i) => res += i
+      case _ : Plus      => res += "P"
+      case _ : Minus     => res += "M"
+    }
+
+    preTraversal(f)(expr)
+    assert(res === "P1M23")
+
+    res = ""
+    postTraversal(f)(expr)
+    assert(res === "123MP")
+  }
+
+  test("pre- and postMap") {
+    val expr = Plus(InfiniteIntegerLiteral(1), Minus(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3)))
+    def op(e : Expr ) = e match {
+      case Minus(InfiniteIntegerLiteral(two), e2) if two == BigInt(2) => Some(InfiniteIntegerLiteral(2))
+      case InfiniteIntegerLiteral(one) if one == BigInt(1) => Some(InfiniteIntegerLiteral(2))
+      case InfiniteIntegerLiteral(two) if two == BigInt(2) => Some(InfiniteIntegerLiteral(42))
+      case _ => None
+    }
+    
+    assert( preMap(op, false)(expr) == Plus(InfiniteIntegerLiteral(2),  InfiniteIntegerLiteral(2))  )
+    assert( preMap(op, true )(expr) == Plus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(42)) )
+    assert( postMap(op, false)(expr) == Plus(InfiniteIntegerLiteral(2),  Minus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(3))) )
+    assert( postMap(op, true)(expr)  == Plus(InfiniteIntegerLiteral(42), Minus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(3))) )
+    
+  }
+  
+}
diff --git a/src/unit-test/scala/leon/purescala/TreeTestsSuite.scala b/src/unit-test/scala/leon/purescala/TreeTestsSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..933ba02dc4397850965c14d5dbf22ee8f5fe3f97
--- /dev/null
+++ b/src/unit-test/scala/leon/purescala/TreeTestsSuite.scala
@@ -0,0 +1,38 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.test.purescala
+
+import leon.test._
+
+import leon.purescala.Common._
+import leon.purescala.Constructors._
+import leon.purescala.Expressions._
+import leon.purescala.Types._
+
+class TreeTestsSuite extends LeonTestSuite {
+
+  test("And- and Or- simplifications") {
+    val x = Variable(FreshIdentifier("x", BooleanType))
+    val t = BooleanLiteral(true)
+    val f = BooleanLiteral(false)
+
+    def and(es : Expr*) : Expr = andJoin(es)
+    def or(es : Expr*) : Expr = orJoin(es)
+
+    assert(and(x, and(x, x), x) === and(x, x, x, x))
+    assert(and(x, t, x, t) === and(x, x))
+    assert(and(x, t, f, x) === and(x, f))
+    assert(and(x) === x)
+    assert(and() === t)
+    assert(and(t, t) === t)
+    assert(and(f) === f)
+
+    assert(or(x, or(x, x), x) === or(x, x, x, x))
+    assert(or(x, f, x, f) === or(x, x))
+    assert(or(x, f, t, x) === or(x, t))
+    assert(or(x) === x)
+    assert(or() === f)
+    assert(or(f, f) === f)
+    assert(or(t) === t)
+  }
+}
diff --git a/src/unit-test/scala/leon/purescala/WithLikelyEq.scala b/src/unit-test/scala/leon/purescala/WithLikelyEq.scala
new file mode 100644
index 0000000000000000000000000000000000000000..705f2ba403fd60ac500641d9d5c13559788d2354
--- /dev/null
+++ b/src/unit-test/scala/leon/purescala/WithLikelyEq.scala
@@ -0,0 +1,87 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package purescala
+
+import leon.evaluators._
+import leon.purescala.Common._
+import leon.purescala.Definitions._
+import leon.purescala.ExprOps.replace
+import leon.purescala.Expressions._
+
+/*
+ * Determine if two expressions over arithmetic variables are likely to be equal.
+ *
+ * This is a probabilistic based approach, it does not rely on any external solver and can
+ * only prove the non equality of two expressions.
+ */
+trait WithLikelyEq {
+  this: LeonTestSuite =>
+
+  object LikelyEq {
+    private val min = -5
+    private val max = 5
+
+    /*
+     * compare e1 and e2, using a list of assignment of integer to the variables in vs.
+     * Pre is a boolean expression precondition over the same variables that must be evaluated to true
+     * before testing equality.
+     * Add a default mapping for some set parameters
+     * Note that the default map could contain a mapping for variables to other parameters
+     * It is thus necessary to first select values for those parameters and then substitute
+     * into the default map !
+     */
+    def apply(e1: Expr, e2: Expr, vs: Set[Identifier], pre: Expr = BooleanLiteral(true),
+              compare: (Expr, Expr) => Boolean = (e1, e2) => e1 == e2, 
+              defaultMap: Map[Identifier, Expr] = Map()): Boolean = {
+      val evaluator = new DefaultEvaluator(createLeonContext(), Program.empty)
+      if(vs.isEmpty) {
+        val ndm = defaultMap.map { case (id, expr) => (id, evaluator.eval(expr).asInstanceOf[EvaluationResults.Successful].value) } //TODO: not quite sure why I need to do this...
+        (evaluator.eval(e1, ndm), evaluator.eval(e2, defaultMap)) match {
+          case (EvaluationResults.Successful(v1), EvaluationResults.Successful(v2)) => compare(v1, v2)
+          case (err1, err2) => sys.error("evaluation could not complete, got: (" + err1 + ", " + err2 + ")")
+        }
+      } else {
+        var isEq = true
+        val vsOrder = vs.toArray
+        val counters: Array[Int] = vsOrder.map(_ => min)
+        var i = 0
+
+        while(i < counters.length && isEq) {
+          val m: Map[Expr, Expr] = vsOrder.zip(counters).map{case (v, c) => (Variable(v), InfiniteIntegerLiteral(c))}.toMap
+          val ne1 = replace(m, e1)
+          val ne2 = replace(m, e2)
+          val npre = replace(m, pre)
+          val ndm = defaultMap.map{ case (id, expr) => (id, evaluator.eval(expr, m.map{case (Variable(id), t) => (id, t)}).asInstanceOf[EvaluationResults.Successful].value) }
+          evaluator.eval(npre, ndm) match {
+            case EvaluationResults.Successful(BooleanLiteral(false)) =>
+            case EvaluationResults.Successful(BooleanLiteral(true)) =>
+              val ev1 = evaluator.eval(ne1, ndm)
+              val ev2 = evaluator.eval(ne2, ndm)
+              (ev1, ev2) match {
+                case (EvaluationResults.Successful(v1), EvaluationResults.Successful(v2)) => if(!compare(v1, v2)) isEq = false
+                case (err1, err2) => sys.error("evaluation could not complete, got: (" + err1 + ", " + err2 + ")")
+              }
+            case err => sys.error("evaluation of precondition could not complete, got: " + err)
+          }
+
+          if(counters(i) < max)
+            counters(i) += 1
+          else {
+            while(i < counters.length && counters(i) >= max) {
+              counters(i) = min
+              i += 1
+            }
+            if(i < counters.length) {
+              counters(i) += 1
+              i = 0
+            }
+          }
+        }
+        isEq
+      }
+    }
+
+  }
+
+}
diff --git a/src/unit-test/scala/leon/synthesis/AlgebraSuite.scala b/src/unit-test/scala/leon/synthesis/AlgebraSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..cb0eed3dd924512507e89bcfee95c4e00c64539f
--- /dev/null
+++ b/src/unit-test/scala/leon/synthesis/AlgebraSuite.scala
@@ -0,0 +1,204 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package synthesis
+
+import Algebra._
+
+class AlgebraSuite extends LeonTestSuite {
+
+  test("remainder") {
+    assert(remainder(1,1) === 0)
+    assert(remainder(2,2) === 0)
+    assert(remainder(2,1) === 0)
+    assert(remainder(0,1) === 0)
+    assert(remainder(0,4) === 0)
+    assert(remainder(1,3) === 1)
+    assert(remainder(1,8) === 1)
+    assert(remainder(4,2) === 0)
+    assert(remainder(17,3) === 2)
+    assert(remainder(25,5) === 0)
+    assert(remainder(26,5) === 1)
+    assert(remainder(29,5) === 4)
+
+    assert(remainder(1,-1) === 0)
+    assert(remainder(-1,1) === 0)
+    assert(remainder(2,-2) === 0)
+    assert(remainder(-2,-2) === 0)
+    assert(remainder(-2,1) === 0)
+    assert(remainder(0,-1) === 0)
+    assert(remainder(1,-2) === 1)
+    assert(remainder(-1,2) === 1)
+    assert(remainder(-1,3) === 2)
+    assert(remainder(-1,-3) === 2)
+    assert(remainder(1,-3) === 1)
+    assert(remainder(17,-3) === 2)
+    assert(remainder(-25,5) === 0)
+  }
+
+  test("divide") {
+    assert(divide(1,1) === (1, 0))
+    assert(divide(2,2) === (1, 0))
+    assert(divide(2,1) === (2, 0))
+    assert(divide(0,1) === (0, 0))
+    assert(divide(0,4) === (0, 0))
+    assert(divide(1,3) === (0, 1))
+    assert(divide(1,8) === (0, 1))
+    assert(divide(4,2) === (2, 0))
+    assert(divide(17,3) === (5, 2))
+    assert(divide(25,5) === (5, 0))
+    assert(divide(26,5) === (5, 1))
+    assert(divide(29,5) === (5, 4))
+
+    assert(divide(1,-1) === (-1, 0))
+    assert(divide(-1,1) === (-1, 0))
+    assert(divide(2,-2) === (-1, 0))
+    assert(divide(-2,-2) === (1, 0))
+    assert(divide(-2,1) === (-2, 0))
+    assert(divide(0,-1) === (0, 0))
+    assert(divide(1,-2) === (0, 1))
+    assert(divide(-1,2) === (-1, 1))
+    assert(divide(-1,3) === (-1, 2))
+    assert(divide(-1,-3) === (1, 2))
+    assert(divide(1,-3) === (0, 1))
+    assert(divide(17,-3) === (-5, 2))
+    assert(divide(-25,5) === (-5, 0))
+  }
+
+  test("binary gcd") {
+    assert(gcd(1,1) === 1)
+    assert(gcd(1,3) === 1)
+    assert(gcd(3,1) === 1)
+    assert(gcd(3,3) === 3)
+    assert(gcd(4,3) === 1)
+    assert(gcd(5,3) === 1)
+    assert(gcd(6,3) === 3)
+    assert(gcd(2,12) === 2)
+    assert(gcd(4,10) === 2)
+    assert(gcd(10,4) === 2)
+    assert(gcd(12,8) === 4)
+    assert(gcd(23,41) === 1)
+    assert(gcd(0,41) === 41)
+    assert(gcd(4,0) === 4)
+
+    assert(gcd(-4,0) === 4)
+    assert(gcd(-23,41) === 1)
+    assert(gcd(23,-41) === 1)
+    assert(gcd(-23,-41) === 1)
+    assert(gcd(2,-12) === 2)
+    assert(gcd(-4,10) === 2)
+    assert(gcd(-4,-8) === 4)
+  }
+
+  test("n-ary gcd") {
+    assert(gcd(1,1,1) === 1)
+    assert(gcd(1,3,5) === 1)
+    assert(gcd(3,1,2) === 1)
+    assert(gcd(3,3,3) === 3)
+    assert(gcd(4,3,8,6) === 1)
+    assert(gcd(5,3,2) === 1)
+    assert(gcd(6,3,9) === 3)
+    assert(gcd(6,3,8) === 1)
+    assert(gcd(2,12,16,4) === 2)
+    assert(gcd(4,10,8,22) === 2)
+    assert(gcd(10,4,20) === 2)
+    assert(gcd(12,8,4) === 4)
+    assert(gcd(12,8,2) === 2)
+    assert(gcd(12,8,6) === 2)
+    assert(gcd(23,41,11) === 1)
+    assert(gcd(2,4,8,12,16,4) === 2)
+    assert(gcd(2,4,8,11,16,4) === 1)
+    assert(gcd(6,3,8, 0) === 1)
+    assert(gcd(2,12, 0,16,4) === 2)
+
+    assert(gcd(-12,8,6) === 2)
+    assert(gcd(23,-41,11) === 1)
+    assert(gcd(23,-41, 0,11) === 1)
+    assert(gcd(2,4,-8,-12,16,4) === 2)
+    assert(gcd(-2,-4,-8,-11,-16,-4) === 1)
+  }
+
+  test("seq gcd") {
+    assert(gcd(Seq(1)) === 1)
+    assert(gcd(Seq(4)) === 4)
+    assert(gcd(Seq(7)) === 7)
+    assert(gcd(Seq(1,1,1)) === 1)
+    assert(gcd(Seq(1,3,5)) === 1)
+    assert(gcd(Seq(3,1,2)) === 1)
+    assert(gcd(Seq(3,3,3)) === 3)
+    assert(gcd(Seq(4,3,8,6)) === 1)
+    assert(gcd(Seq(5,3,2)) === 1)
+    assert(gcd(Seq(6,3,9)) === 3)
+    assert(gcd(Seq(6,3,8)) === 1)
+    assert(gcd(Seq(2,12,16,4)) === 2)
+    assert(gcd(Seq(4,10,8,22)) === 2)
+    assert(gcd(Seq(10,4,20)) === 2)
+    assert(gcd(Seq(12,8,4)) === 4)
+    assert(gcd(Seq(12,8,2)) === 2)
+    assert(gcd(Seq(12,8,6)) === 2)
+    assert(gcd(Seq(23,41,11)) === 1)
+    assert(gcd(Seq(2,4,8,12,16,4)) === 2)
+    assert(gcd(Seq(2,4,8,11,16,4)) === 1)
+    assert(gcd(Seq(6,3,8, 0)) === 1)
+    assert(gcd(Seq(2,12, 0,16,4)) === 2)
+
+    assert(gcd(Seq(-1)) === 1)
+    assert(gcd(Seq(-7)) === 7)
+    assert(gcd(Seq(-12,8,6)) === 2)
+    assert(gcd(Seq(23,-41,11)) === 1)
+    assert(gcd(Seq(23,-41, 0,11)) === 1)
+    assert(gcd(Seq(2,4,-8,-12,16,4)) === 2)
+    assert(gcd(Seq(-2,-4,-8,-11,-16,-4)) === 1)
+  }
+
+  test("binary lcm") {
+    assert(lcm(1,3) === 3)
+    assert(lcm(1,1) === 1)
+    assert(lcm(0,1) === 0)
+    assert(lcm(2,3) === 6)
+    assert(lcm(4,3) === 12)
+    assert(lcm(4,6) === 12)
+    assert(lcm(8,6) === 24)
+  }
+  test("n-ary lcm") {
+    assert(lcm(1,2,3) === 6)
+    assert(lcm(1,2,3,4) === 12)
+    assert(lcm(5,2,3,4) === 60)
+  }
+  test("seq lcm") {
+    assert(lcm(Seq(1,2,3)) === 6)
+    assert(lcm(Seq(1,2,3,4)) === 12)
+    assert(lcm(Seq(5,2,3,4)) === 60)
+  }
+
+  def checkExtendedEuclid(a: Int, b: Int) {
+    val (x, y) = extendedEuclid(a, b)
+    assert(x*a + y*b === gcd(a, b))
+  }
+
+  test("extendedEuclid") {
+    checkExtendedEuclid(1, 1)
+    checkExtendedEuclid(3, 1)
+    checkExtendedEuclid(1, 2)
+    checkExtendedEuclid(1, 15)
+    checkExtendedEuclid(4, 1)
+    checkExtendedEuclid(4, 3)
+    checkExtendedEuclid(12, 23)
+    checkExtendedEuclid(11, 10)
+    checkExtendedEuclid(10, 15)
+
+    checkExtendedEuclid(-1, 1)
+    checkExtendedEuclid(-1, -1)
+    checkExtendedEuclid(3, -1)
+    checkExtendedEuclid(-3, -1)
+    checkExtendedEuclid(-3, 1)
+    checkExtendedEuclid(1, -2)
+    checkExtendedEuclid(-1, 2)
+    checkExtendedEuclid(-1, -2)
+    checkExtendedEuclid(12, -23)
+    checkExtendedEuclid(-11, 10)
+    checkExtendedEuclid(10, -15)
+  }
+}
+
+// vim: set ts=4 sw=4 et:
diff --git a/src/unit-test/scala/leon/synthesis/LinearEquationsSuite.scala b/src/unit-test/scala/leon/synthesis/LinearEquationsSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9506b271326f35c33c0ff53b36178b0c74ad47d0
--- /dev/null
+++ b/src/unit-test/scala/leon/synthesis/LinearEquationsSuite.scala
@@ -0,0 +1,260 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package synthesis
+
+import leon.purescala.WithLikelyEq
+import leon.purescala.Expressions._
+import leon.purescala.Types._
+import leon.purescala.ExprOps._
+import leon.purescala.Common._
+import leon.purescala.Definitions._
+import leon.evaluators._
+
+import leon.synthesis.LinearEquations._
+
+class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq {
+
+  def i(x: Int) = InfiniteIntegerLiteral(x)
+
+  val xId = FreshIdentifier("x", IntegerType)
+  val x = Variable(xId)
+  val yId = FreshIdentifier("y", IntegerType)
+  val y = Variable(yId)
+  val zId = FreshIdentifier("z", IntegerType)
+  val z = Variable(zId)
+
+  val aId = FreshIdentifier("a", IntegerType)
+  val a = Variable(aId)
+  val bId = FreshIdentifier("b", IntegerType)
+  val b = Variable(bId)
+
+  def toSum(es: Seq[Expr]) = es.reduceLeft(Plus)
+  
+  def checkSameExpr(e1: Expr, e2: Expr, vs: Set[Identifier], prec: Expr, defaultMap: Map[Identifier, Expr] = Map()) {
+    assert( //this outer assert should not be needed because of the nested one
+      LikelyEq(e1, e2, vs, prec, (e1, e2) => {assert(e1 === e2); true}, defaultMap)
+    )
+  }
+
+
+  //use some random values to check that any vector in the basis is a valid solution to
+  //the equation
+  def checkVectorSpace(basis: Array[Array[Int]], equation: Array[Int]): Unit = 
+    checkVectorSpace(basis.map(_.map(i => BigInt(i))), equation.map(i => BigInt(i)))
+  def checkVectorSpace(basis: Array[Array[BigInt]], equation: Array[BigInt]): Unit = {
+    require(basis.length == basis(0).length + 1 && basis.length == equation.length)
+    val n = basis(0).length
+    val min: BigInt = -5
+    val max: BigInt = 5
+    val components = Array.fill(n)(min)
+    var counter = 0
+
+    while(counter < n) {
+      val sol = mult(basis, components) //one linear combination of the basis
+      assert(eval(sol, equation) === 0)
+
+      //next components
+      if(components(counter) < max)
+        components(counter) += 1
+      else {
+        while(counter < n && components(counter) >= max) {
+          components(counter) = min
+          counter += 1
+        }
+        if(counter < n) {
+          components(counter) += 1
+          counter = 0
+        }
+      }
+    }
+  }
+
+  //val that the sol vector with the term in the equation
+  def eval(sol: Array[BigInt], equation: Array[BigInt]): BigInt = {
+    require(sol.length == equation.length)
+    sol.zip(equation).foldLeft(BigInt(0))((acc, p) => acc + p._1 * p._2)
+  }
+
+  //multiply the matrix by the vector: [M1 M2 .. Mn] * [v1 .. vn] = v1*M1 + ... + vn*Mn]
+  def mult(matrix: Array[Array[BigInt]], vector: Array[BigInt]): Array[BigInt] = {
+    require(vector.length == matrix(0).length && vector.length > 0)
+    val tmat = matrix.transpose
+    var tmp: Array[BigInt] = null
+    tmp = mult(vector(0), tmat(0))
+    var i = 1
+    while(i < vector.length) {
+      tmp = add(tmp, mult(vector(i), tmat(i)))
+      i += 1
+    }
+    tmp
+  }
+
+  def mult(c: BigInt, v: Array[BigInt]): Array[BigInt] = v.map(_ * c)
+  def add(v1: Array[BigInt], v2: Array[BigInt]): Array[BigInt] = {
+    require(v1.length == v2.length)
+    v1.zip(v2).map(p => p._1 + p._2)
+  }
+
+  test("checkVectorSpace") {
+    checkVectorSpace(Array(Array(1), Array(2)), Array(-2, 1))
+    checkVectorSpace(Array(Array(4, 0), Array(-3, 2), Array(0, -1)), Array(3, 4, 8))
+  }
+
+  
+  test("particularSolution basecase") {
+    def toExpr(es: Array[Expr]): Expr = {
+      val vars: Array[Expr] = Array[Expr](i(1)) ++ Array[Expr](x, y)
+      es.zip(vars).foldLeft[Expr](i(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) )
+    }
+
+    val t1: Expr = Plus(a, b)
+    val c1: Expr = i(4)
+    val d1: Expr = i(22)
+    val e1: Array[Expr] = Array(t1, c1, d1)
+    val (pre1, (w1, w2)) = particularSolution(Set(aId, bId), t1, c1, d1)
+    checkSameExpr(toExpr(e1), i(0), Set(aId, bId), pre1, Map(xId -> w1, yId -> w2))
+
+    val t2: Expr = i(-1)
+    val c2: Expr = i(1)
+    val d2: Expr = i(-1)
+    val e2: Array[Expr] = Array(t2, c2, d2)
+    val (pre2, (w3, w4)) = particularSolution(Set(), t2, c2, d2)
+    checkSameExpr(toExpr(e2), i(0), Set(), pre2, Map(xId -> w3, yId -> w4))
+  }
+
+  test("particularSolution preprocess") {
+    def toExpr(es: Array[Expr], vs: Array[Expr]): Expr = {
+      val vars: Array[Expr] = Array[Expr](i(1)) ++ vs
+      es.zip(vars).foldLeft[Expr](i(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) )
+    }
+
+    val t1: Expr = Plus(a, b)
+    val c1: Expr = i(4)
+    val d1: Expr = i(22)
+    val e1: Array[Expr] = Array(t1, c1, d1)
+    val (pre1, s1) = particularSolution(Set(aId, bId), e1.toList)
+    checkSameExpr(toExpr(e1, Array(x, y)), i(0), Set(aId, bId), pre1, Array(xId, yId).zip(s1).toMap)
+
+    val t2: Expr = Plus(a, b)
+    val c2: Expr = i(4)
+    val d2: Expr = i(22)
+    val f2: Expr = i(10)
+    val e2: Array[Expr] = Array(t2, c2, d2, f2)
+    val (pre2, s2) = particularSolution(Set(aId, bId), e2.toList)
+    checkSameExpr(toExpr(e2, Array(x, y, z)), i(0), Set(aId, bId), pre2, Array(xId, yId, zId).zip(s2).toMap)
+
+    val t3: Expr = Plus(a, Times(i(2), b))
+    val c3: Expr = i(6)
+    val d3: Expr = i(24)
+    val f3: Expr = i(9)
+    val e3: Array[Expr] = Array(t3, c3, d3, f3)
+    val (pre3, s3) = particularSolution(Set(aId, bId), e3.toList)
+    checkSameExpr(toExpr(e3, Array(x, y, z)), i(0), Set(aId, bId), pre3, Array(xId, yId, zId).zip(s3).toMap)
+
+    val t4: Expr = Plus(a, b)
+    val c4: Expr = i(4)
+    val e4: Array[Expr] = Array(t4, c4)
+    val (pre4, s4) = particularSolution(Set(aId, bId), e4.toList)
+    checkSameExpr(toExpr(e4, Array(x)), i(0), Set(aId, bId), pre4, Array(xId).zip(s4).toMap)
+  }
+
+
+  test("linearSet") {
+    val as = Set[Identifier]()
+
+    val evaluator = new DefaultEvaluator(createLeonContext(), Program.empty)
+
+    val eq1 = Array[BigInt](3, 4, 8)
+    val basis1 = linearSet(evaluator, as, eq1)
+    checkVectorSpace(basis1, eq1)
+
+    val eq2 = Array[BigInt](1, 2, 3)
+    val basis2 = linearSet(evaluator, as, eq2)
+    checkVectorSpace(basis2, eq2)
+
+    val eq3 = Array[BigInt](1, 1)
+    val basis3 = linearSet(evaluator, as, eq3)
+    checkVectorSpace(basis3, eq3)
+
+    val eq4 = Array[BigInt](1, 1, 2, 7)
+    val basis4 = linearSet(evaluator, as, eq4)
+    checkVectorSpace(basis4, eq4)
+
+    val eq5 = Array[BigInt](1, -1)
+    val basis5 = linearSet(evaluator, as, eq5)
+    checkVectorSpace(basis5, eq5)
+
+    val eq6 = Array[BigInt](1, -6, 3)
+    val basis6 = linearSet(evaluator, as, eq6)
+    checkVectorSpace(basis6, eq6)
+  }
+
+
+  def enumerate(nbValues: Int, app: (Array[Int] => Unit)) {
+    val min = -5
+    val max = 5
+    val counters: Array[Int] = (1 to nbValues).map(_ => min).toArray
+    var i = 0
+
+    while(i < counters.length) {
+      app(counters)
+      if(counters(i) < max)
+        counters(i) += 1
+      else {
+        while(i < counters.length && counters(i) >= max) {
+          counters(i) = min
+          i += 1
+        }
+        if(i < counters.length) {
+          counters(i) += 1
+          i = 0
+        }
+      }
+    }
+
+  }
+
+  //TODO: automatic check result
+  test("elimVariable") {
+    val as = Set[Identifier](aId, bId)
+
+    val evaluator = new DefaultEvaluator(createLeonContext(), Program.empty)
+
+    def check(t: Expr, c: List[Expr], prec: Expr, witnesses: List[Expr], freshVars: List[Identifier]) {
+      enumerate(freshVars.size, (vals: Array[Int]) => {
+        val mapping: Map[Expr, Expr] = freshVars.zip(vals.toList).map(t => (Variable(t._1), i(t._2))).toMap
+        val cWithVars: Expr = c.zip(witnesses).foldLeft[Expr](i(0)){ case (acc, (coef, wit)) => Plus(acc, Times(coef, replace(mapping, wit))) }
+        checkSameExpr(Plus(t, cWithVars), i(0), as, prec)
+      })
+    }
+
+    val t1 = Minus(Times(i(2), a), b)
+    val c1 = List(i(3), i(4), i(8))
+    val (pre1, wit1, f1) = elimVariable(evaluator, as, t1::c1)
+    check(t1, c1, pre1, wit1, f1)
+
+    val t2 = Plus(Plus(i(0), i(2)), Times(i(-1), i(3)))
+    val c2 = List(i(1), i(-1))
+    val (pre2, wit2, f2) = elimVariable(evaluator, Set(), t2::c2)
+    check(t2, c2, pre2, wit2, f2)
+
+
+    val t3 = Minus(Times(i(2), a), i(3))
+    val c3 = List(i(2))
+    val (pre3, wit3, f3) = elimVariable(evaluator, Set(aId), t3::c3)
+    check(t3, c3, pre3, wit3, f3)
+
+    val t4 = Times(i(2), a)
+    val c4 = List(i(2), i(4))
+    val (pre4, wit4, f4) = elimVariable(evaluator, Set(aId), t4::c4)
+    check(t4, c4, pre4, wit4, f4)
+
+    val t5 = Minus(a, b)
+    val c5 = List(i(-60), i(-3600))
+    val (pre5, wit5, f5) = elimVariable(evaluator, Set(aId, bId), t5::c5)
+    check(t5, c5, pre5, wit5, f5)
+
+  }
+
+}
diff --git a/src/unit-test/scala/leon/utils/StreamsSuite.scala b/src/unit-test/scala/leon/utils/StreamsSuite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ee87d8ea3eb4b711114ed788193a35d376ba6e11
--- /dev/null
+++ b/src/unit-test/scala/leon/utils/StreamsSuite.scala
@@ -0,0 +1,66 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package utils
+
+import purescala.Common._
+import utils.StreamUtils._
+
+class StreamsSuite extends LeonTestSuite {
+  test("Cartesian Product 1") {
+    val s1 = FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #:: Stream.empty
+
+    val s2 = FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #:: Stream.empty
+
+    val ss = cartesianProduct(List(s1, s2))
+
+    assert(ss.size === s1.size * s2.size)
+
+
+  }
+
+  test("Cartesian Product 2") {
+    val s1 = FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #:: Stream.empty
+
+    val s2 = FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #::
+             FreshIdentifier("B", alwaysShowUniqueID = true) #:: Stream.empty
+
+    val tmp1 = s1.mkString
+    val tmp2 = s2.mkString
+
+    val ss = cartesianProduct(List(s1, s2))
+
+    assert(ss.size === s1.size * s2.size)
+  }
+
+
+  test("Cartesian Product 3") {
+    val s1 = 1 #::
+             2 #::
+             3 #::
+             4 #:: Stream.empty
+
+    val s2 = 5 #::
+             6 #::
+             7 #::
+             8 #:: Stream.empty
+
+    val tmp1 = s1.mkString
+    val tmp2 = s2.mkString
+
+    val ss = cartesianProduct(List(s1, s2))
+
+    assert(ss.size === s1.size * s2.size)
+  }
+}