Open konnov opened 3 years ago
This is a summary of tests that show how integer division is implemented in different languages. The current version of TLC seems to be compatible with //
in python and incompatible with div
in SMTLIB. I am not even sure about possible fixes, as the book is only giving us the definition for the positive dividers.
C (clang 12) | Scala 2.13 | Rust | Python 3.8.6 | TLA+ (TLC) | SMT (z3 4.8.8) | |
---|---|---|---|---|---|---|
100 div 3 | 100 / 3 == 33 | 100 / 3 == 33 | 100 / 3 == 33 | 100 // 3 == 33 | (100 \div 3) = 33 | (assert (= 33 (div 100 3))) |
(-100) div 3 | -100 / 3 == -33 | -100 / 3 == -33 | -100 / 3 == -33 | -100 // 3 == -34 | ((-100) \div 3) = -34 | (assert (= (- 0 34) (div (- 0 100) 3))) |
100 div (-3) | 100 / (-3) == -33 | 100 / (-3) == -33 | 100 / (-3) == -33 | 100 // (-3) == -34 | (100 \div (-3)) = -34 | (assert (= (- 0 33) (div 100 (- 0 3)))) |
(-100) div (-3) | -100 / (-3) == 33 | -100 / (-3) == 33 | -100 / (-3) == 33 | -100 // (-3) == 33 | ((-100) \div (-3)) = 33 | (assert (= 34 (div (- 0 100) (- 0 3)))) |
Although it is a bug, it seems to be of low priority
It's even worse, our preprocessing uses Scala division, which makes it inconsistent
The problem is that Python and TLC allow a negative remainder, whereas SMT-LIB does not. In contrast, the PLs+TLC leave the remainder unconstrained and just favor a rounding direction for /
, either towards -\infty
or towards 0
.
It looks like we have to express integer division via (if ...)
in SMT, if we want to support the TLC definition.
The SMT-LIB definition actually nicely lines up with the one from Specifying Systems (modulo accounting for a negative divisor in the definition of mod
)
According to the definition in Specifying Systems:
This definition is incompatible with the definition of
div
in SMTLIB and integer division in programming languages. However, we have to be compatible with the book and TLC.