Skip to content

Commit

Permalink
Fix int division (UnitTestBot#119)
Browse files Browse the repository at this point in the history
* cvc: fix int division

* core: fix int division rounding
  • Loading branch information
Saloed authored Jun 23, 2023
1 parent fe68394 commit 856cbfe
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ inline fun <T : KArithSort> KContext.simplifyArithDivLight(
}

if (lhs is KIntNumExpr) {
return mkIntNum(lhs.bigIntegerValue / rValue.numerator).uncheckedCast()
return mkIntNum(evalIntDiv(lhs.bigIntegerValue, rValue.numerator)).uncheckedCast()
}

if (lhs is KRealNumExpr) {
Expand Down Expand Up @@ -407,6 +407,26 @@ fun <T : KArithSort> KExpr<T>.toRealValue(): RealValue? = when (this) {
else -> null
}

/**
* Eval integer div wrt Int theory rules.
* */
fun evalIntDiv(a: BigInteger, b: BigInteger): BigInteger {
if (a >= BigInteger.ZERO) {
return a / b
}
val (divisionRes, rem) = a.divideAndRemainder(b)
if (rem == BigInteger.ZERO) {
return divisionRes
}

// round toward zero
return if (b >= BigInteger.ZERO) {
divisionRes - BigInteger.ONE
} else {
divisionRes + BigInteger.ONE
}
}

/**
* Eval integer mod wrt Int theory rules.
* */
Expand Down
6 changes: 5 additions & 1 deletion ksmt-core/src/test/kotlin/io/ksmt/ArithSimplifyTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ class ArithSimplifyTest : ExpressionSimplifyTest() {
@Test
fun testDiv() {
testOperation(isInt = true, KContext::mkArithDiv, KContext::mkArithDivNoSimplify) {
listOf(mkIntNum(0), mkIntNum(1), mkIntNum(-1)).uncheckedCast()
listOf(
mkIntNum(0), mkIntNum(1), mkIntNum(-1),
// Values with non-trivial rounding
mkIntNum(47), mkIntNum(-47), mkIntNum(13), mkIntNum(-13)
).uncheckedCast()
}

testOperation(isInt = false, KContext::mkArithDiv, KContext::mkArithDivNoSimplify) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,17 @@ class KCvc5ExprInternalizer(
}

override fun <T : KArithSort> transform(expr: KDivArithExpr<T>) = with(expr) {
transform(lhs, rhs) { lhs: Term, rhs: Term -> nsolver.mkTerm(Kind.DIVISION, lhs, rhs) }
transform(lhs, rhs) { lhs: Term, rhs: Term ->
arithDivide(sort, lhs, rhs)
}
}

private fun arithDivide(sort: KArithSort, lhs: Term, rhs: Term): Term = with(sort.ctx) {
when (sort) {
realSort -> nsolver.mkTerm(Kind.DIVISION, lhs, rhs)
intSort -> nsolver.mkTerm(Kind.INTS_DIVISION, lhs, rhs)
else -> throw KSolverUnsupportedFeatureException("Arith sort $sort is unsupported")
}
}

override fun <T : KArithSort> transform(expr: KPowerArithExpr<T>) = with(expr) {
Expand Down

0 comments on commit 856cbfe

Please sign in to comment.