summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/arith.sail29
-rw-r--r--test/builtins/divmod.sail92
2 files changed, 87 insertions, 34 deletions
diff --git a/lib/arith.sail b/lib/arith.sail
index 6b064433..58f25bbc 100644
--- a/lib/arith.sail
+++ b/lib/arith.sail
@@ -88,13 +88,38 @@ val tdiv_int = {
} : (int, int) -> int
/*! Remainder for truncating division (has sign of dividend) */
-val tmod_int = {
+val _tmod_int = {
ocaml: "tmod_int",
interpreter: "tmod_int",
lem: "tmod_int",
c: "tmod_int",
coq: "Z.rem"
-} : (int, int) -> nat
+} : (int, int) -> int
+
+/*! If we know the second argument is positive, we know the result is positive */
+val _tmod_int_positive = {
+ ocaml: "tmod_int",
+ interpreter: "tmod_int",
+ lem: "tmod_int",
+ c: "tmod_int",
+ coq: "Z.rem"
+} : forall 'n, 'n >= 1. (int, int('n)) -> nat
+
+overload tmod_int = {_tmod_int_positive, _tmod_int}
+
+function fdiv_int(n: int, m: int) -> int = {
+ if n < 0 & m > 0 then {
+ tdiv_int(n + 1, m) - 1
+ } else if n > 0 & m < 0 then {
+ tdiv_int(n - 1, m) - 1
+ } else {
+ tdiv_int(n, m)
+ }
+}
+
+function fmod_int(n: int, m: int) -> int = {
+ n - (m * fdiv_int(n, m))
+}
val abs_int_plain = {
smt : "abs",
diff --git a/test/builtins/divmod.sail b/test/builtins/divmod.sail
index f9d7e7c5..458d8dfd 100644
--- a/test/builtins/divmod.sail
+++ b/test/builtins/divmod.sail
@@ -5,39 +5,67 @@ $include <arith.sail>
$include <smt.sail>
function main (() : unit) -> unit = {
- assert(ediv_int( 7 , 5) == 1);
- assert(ediv_int( 7 , -5) == -1);
- assert(ediv_int(-7 , 5) == -2);
- assert(ediv_int(-7 , -5) == 2);
- assert(ediv_int( 12 , 3) == 4);
- assert(ediv_int( 12 , -3) == -4);
- assert(ediv_int(-12 , 3) == -4);
- assert(ediv_int(-12 , -3) == 4);
+ assert(ediv_int(7, 5) == 1);
+ assert(ediv_int(7, -5) == -1);
+ assert(ediv_int(-7, 5) == -2);
+ assert(ediv_int(-7, -5) == 2);
+ assert(ediv_int(12, 3) == 4);
+ assert(ediv_int(12, -3) == -4);
+ assert(ediv_int(-12, 3) == -4);
+ assert(ediv_int(-12, -3) == 4);
- assert(emod_int( 7 , 5) == 2);
- assert(emod_int( 7 , -5) == 2);
- assert(emod_int(-7 , 5) == 3);
- assert(emod_int(-7 , -5) == 3);
- assert(emod_int( 12 , 3) == 0);
- assert(emod_int( 12 , -3) == 0);
- assert(emod_int(-12 , 3) == 0);
- assert(emod_int(-12 , -3) == 0);
+ assert(emod_int(7, 5) == 2);
+ assert(emod_int(7, -5) == 2);
+ assert(emod_int(-7, 5) == 3);
+ assert(emod_int(-7, -5) == 3);
+ assert(emod_int(12, 3) == 0);
+ assert(emod_int(12, -3) == 0);
+ assert(emod_int(-12, 3) == 0);
+ assert(emod_int(-12, -3) == 0);
- assert(tdiv_int( 7 , 5) == 1);
- assert(tdiv_int( 7 , -5) == -1);
- assert(tdiv_int(-7 , 5) == -1);
- assert(tdiv_int(-7 , -5) == 1);
- assert(tdiv_int( 12 , 3) == 4);
- assert(tdiv_int( 12 , -3) == -4);
- assert(tdiv_int(-12 , 3) == -4);
- assert(tdiv_int(-12 , -3) == 4);
+ assert(tdiv_int(7, 5) == 1);
+ assert(tdiv_int(7, -5) == -1);
+ assert(tdiv_int(-7, 5) == -1);
+ assert(tdiv_int(-7, -5) == 1);
+ assert(tdiv_int(12, 3) == 4);
+ assert(tdiv_int(12, -3) == -4);
+ assert(tdiv_int(-12, 3) == -4);
+ assert(tdiv_int(-12, -3) == 4);
- assert(tmod_int( 7 , 5) == 2);
- assert(tmod_int( 7 , -5) == 2);
- assert(tmod_int(-7 , 5) == -2);
- assert(tmod_int(-7 , -5) == -2);
- assert(tmod_int( 12 , 3) == 0);
- assert(tmod_int( 12 , -3) == 0);
- assert(tmod_int(-12 , 3) == 0);
- assert(tmod_int(-12 , -3) == 0);
+ assert(tmod_int(7, 5) == 2);
+ assert(tmod_int(7, -5) == 2);
+ assert(tmod_int(-7, 5) == -2);
+ assert(tmod_int(-7, -5) == -2);
+ assert(tmod_int(12, 3) == 0);
+ assert(tmod_int(12, -3) == 0);
+ assert(tmod_int(-12, 3) == 0);
+ assert(tmod_int(-12, -3) == 0);
+
+ assert(fdiv_int(7, 5) == 1);
+ assert(fdiv_int(7, -5) == -2);
+ assert(fdiv_int(-7, 5) == -2);
+ assert(fdiv_int(-7, -5) == 1);
+ assert(fdiv_int(12, 3) == 4);
+ assert(fdiv_int(12, -3) == -4);
+ assert(fdiv_int(-12, 3) == -4);
+ assert(fdiv_int(-12, -3) == 4);
+
+ assert(fmod_int(7, 5) == 2);
+ assert(fmod_int(7, -5) == -3);
+ assert(fmod_int(-7, 5) == 3);
+ assert(fmod_int(-7, -5) == -2);
+ assert(fmod_int(12, 3) == 0);
+ assert(fmod_int(12, -3) == 0);
+ assert(fmod_int(-12, 3) == 0);
+ assert(fmod_int(-12, -3) == 0);
+
+ assert(fdiv_int(5, 2) == 2);
+ assert(fdiv_int(-5, -2) == 2);
+ assert(fdiv_int(5, -2) == -3);
+ assert(fdiv_int(-5, 2) == -3);
+
+ assert(tdiv_int(5, 2) == 2);
+ assert(tdiv_int(-5, -2) == 2);
+ assert(tdiv_int(5, -2) == -2);
+ assert(tdiv_int(-5, 2) == -2);
} \ No newline at end of file