summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobert Norton2019-03-22 16:50:48 +0000
committerRobert Norton2019-03-22 16:55:23 +0000
commitf4acbce30be2aecdfc491478a24c5eb551824f24 (patch)
treed09f2561e19ab1c4928f053c9f5226c06ce94ee6 /lib
parentc9471630ad64af00a58a3c92f4b6a22f2194e9ee (diff)
Tidy up of div and mod operators (C implementation was previously inconsistent with ocaml etc.). Rename div and mod builtins to ediv_int/emod_int and tdiv_int/tmod_int and add corresponding implementations. Add a test with negative operands. This will break existing models but will mean users have to think about which versions they want and won't accidentally use the wrong one.
Diffstat (limited to 'lib')
-rw-r--r--lib/arith.sail26
-rw-r--r--lib/sail.c21
-rw-r--r--lib/sail.h2
-rw-r--r--lib/smt.sail13
4 files changed, 38 insertions, 24 deletions
diff --git a/lib/arith.sail b/lib/arith.sail
index 20231de1..798bde12 100644
--- a/lib/arith.sail
+++ b/lib/arith.sail
@@ -78,26 +78,20 @@ overload shr_int = {_shr32, _shr_int}
// ***** div and mod *****
-val div_int = {
- smt: "div",
- ocaml: "quotient",
- lem: "integerDiv",
- c: "tdiv_int",
- coq: "Z.quot"
+/*! Truncating division (rounds towards zero) */
+val tdiv_int = {
+ ocaml: "tdiv_int",
+ lem: "integerDiv_t",
+ c: "tdiv_int"
} : (int, int) -> int
-overload operator / = {div_int}
-
-val mod_int = {
- smt: "mod",
- ocaml: "modulus",
- lem: "integerMod",
- c: "tmod_int",
- coq: "Z.rem"
+/*! Remainder for truncating division (has sign of dividend) */
+val tmod_int = {
+ ocaml: "tmod_int",
+ lem: "integerMod_t",
+ c: "tmod_int"
} : (int, int) -> nat
-overload operator % = {mod_int}
-
val abs_int = {
smt : "abs",
ocaml: "abs_int",
diff --git a/lib/sail.c b/lib/sail.c
index 6c71d7ae..2d47939e 100644
--- a/lib/sail.c
+++ b/lib/sail.c
@@ -350,6 +350,27 @@ void mult_int(sail_int *rop, const sail_int op1, const sail_int op2)
mpz_mul(*rop, op1, op2);
}
+
+inline
+void ediv_int(sail_int *rop, const sail_int op1, const sail_int op2)
+{
+ /* GMP doesn't have Euclidean division but we can emulate it using
+ flooring and ceiling division. */
+ if (mpz_sgn(op2) >= 0) {
+ mpz_fdiv_q(*rop, op1, op2);
+ } else {
+ mpz_cdiv_q(*rop, op1, op2);
+ }
+}
+
+inline
+void emod_int(sail_int *rop, const sail_int op1, const sail_int op2)
+{
+ /* The documentation isn't that explicit but I think this is
+ Euclidean mod. */
+ mpz_mod(*rop, op1, op2);
+}
+
inline
void tdiv_int(sail_int *rop, const sail_int op1, const sail_int op2)
{
diff --git a/lib/sail.h b/lib/sail.h
index 5a7722de..666c75fe 100644
--- a/lib/sail.h
+++ b/lib/sail.h
@@ -138,6 +138,8 @@ SAIL_INT_FUNCTION(add_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(sub_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(sub_nat, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(mult_int, sail_int, const sail_int, const sail_int);
+SAIL_INT_FUNCTION(ediv_int, sail_int, const sail_int, const sail_int);
+SAIL_INT_FUNCTION(emod_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tdiv_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tmod_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(fdiv_int, sail_int, const sail_int, const sail_int);
diff --git a/lib/smt.sail b/lib/smt.sail
index d886c127..4d250bef 100644
--- a/lib/smt.sail
+++ b/lib/smt.sail
@@ -3,24 +3,21 @@ $define _SMT
// see http://smtlib.cs.uiowa.edu/theories-Ints.shtml
-val div = {
+/*! Euclidean division */
+val ediv_int = {
ocaml: "quotient",
lem: "integerDiv",
- c: "tdiv_int",
+ c: "ediv_int",
coq: "ediv_with_eq"
} : forall 'n 'm. (int('n), int('m)) -> int(div('n, 'm))
-overload operator / = {div}
-
-val mod = {
+val emod_int = {
ocaml: "modulus",
lem: "integerMod",
- c: "tmod_int",
+ c: "emod_int",
coq: "emod_with_eq"
} : forall 'n 'm. (int('n), int('m)) -> int(mod('n, 'm))
-overload operator % = {mod}
-
val abs_int = {
ocaml: "abs_int",
lem: "abs_int",