From 038fb6fb555a8a1c167af578f622f8f3cef5dcdb Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 28 Oct 2017 19:55:06 -0400 Subject: [PATCH] Get correct sign of a MOD b when (a > 0) and (b < 0). Reported by me in https://github.com/davidgiven/ack/issues/60 This doesn't change DIV. Right now a DIV b does floor division and a MOD b has the sign of b. This is the same as Lua, Python, Ruby, Tcl; but is different from other Modula-2 implementations. --- lang/m2/comp/cstoper.c | 25 ++++++++++++++++--------- lang/m2/libm2/dvi.c | 26 ++++++++++++++------------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/lang/m2/comp/cstoper.c b/lang/m2/comp/cstoper.c index 7629098c1..9d7fea099 100644 --- a/lang/m2/comp/cstoper.c +++ b/lang/m2/comp/cstoper.c @@ -159,22 +159,29 @@ cstibin(expp) break; case DIV: - case MOD: if (o2 == 0) { - node_error(exp, exp->nd_symb == DIV ? - "division by 0" : - "modulo by 0"); + node_error(exp, "division by 0"); return; } if ((o1 < 0) != (o2 < 0)) { if (o1 < 0) o1 = -o1; else o2 = -o2; - if (exp->nd_symb == DIV) o1 = -((o1+o2-1)/o2); - else o1 = ((o1+o2-1)/o2) * o2 - o1; + o1 = -((o1+o2-1)/o2); } - else { - if (exp->nd_symb == DIV) o1 /= o2; - else o1 %= o2; + else o1 /= o2; + break; + + case MOD: + if (o2 == 0) { + node_error(exp, "modulo by 0"); + return; + } + { + arith m = o1 % o2; + if (m != 0 && (o1 < 0) != (o2 < 0)) + o1 = m + o2; + else + o1 = m; } break; diff --git a/lang/m2/libm2/dvi.c b/lang/m2/libm2/dvi.c index 900e78561..4f85cf64e 100644 --- a/lang/m2/libm2/dvi.c +++ b/lang/m2/libm2/dvi.c @@ -43,26 +43,28 @@ int rmi(j,i) int j,i; { + int m; + if (j == 0) TRP(EIDIVZ); if (i == 0) return 0; - if ((i < 0) != (j < 0)) { - if (i < 0) i = -i; - else j = -j; - return j*((i+j-1)/j)-i; - } - else return i%j; + + m = i % j; + if (m != 0 && (i < 0) != (j < 0)) + m += j; + return m; } long rmil(j,i) long j,i; { + long m; + if (j == 0) TRP(EIDIVZ); if (i == 0) return 0L; - if ((i < 0) != (j < 0)) { - if (i < 0) i = -i; - else j = -j; - return j*((i+j-1)/j)-i; - } - else return i%j; + + m = i % j; + if (m != 0 && (i < 0) != (j < 0)) + m += j; + return m; } -- 2.34.1