From: ceriel Date: Mon, 16 Jul 1990 09:05:19 +0000 (+0000) Subject: Fix: DIV and MOD on negative args X-Git-Tag: release-5-5~1650 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=109a357e956927143d8372ee4683e9cd34850640;p=ack.git Fix: DIV and MOD on negative args --- diff --git a/lang/m2/comp/code.c b/lang/m2/comp/code.c index f29a3f536..05ef6c1d6 100644 --- a/lang/m2/comp/code.c +++ b/lang/m2/comp/code.c @@ -782,7 +782,13 @@ CodeOper(expr, true_label, false_label) Operands(expr); switch(tp->tp_fund) { case T_INTEGER: - C_dvi(tp->tp_size); + if ((int)(tp->tp_size) == word_size) { + C_cal((int)(tp->tp_size) == (int)word_size + ? "dvi" + : "dvil"); + } + C_asp(2*tp->tp_size); + C_lfr(tp->tp_size); break; case T_POINTER: case T_EQUAL: @@ -798,7 +804,13 @@ CodeOper(expr, true_label, false_label) Operands(expr); switch(tp->tp_fund) { case T_INTEGER: - C_rmi(tp->tp_size); + if ((int)(tp->tp_size) == word_size) { + C_cal((int)(tp->tp_size) == (int)word_size + ? "rmi" + : "rmil"); + } + C_asp(2*tp->tp_size); + C_lfr(tp->tp_size); break; case T_POINTER: case T_EQUAL: diff --git a/lang/m2/comp/cstoper.c b/lang/m2/comp/cstoper.c index 2cb9133ec..197e30258 100644 --- a/lang/m2/comp/cstoper.c +++ b/lang/m2/comp/cstoper.c @@ -186,35 +186,28 @@ cstibin(expp) node_error(expp, "division by 0"); return; } -#if (-1)/2==0 - o1 /= o2; -#else - if (o1 == 0) break; if ((o1 < 0) != (o2 < 0)) { - o1 = o1/o2 + 1; + if (o1 < 0) o1 = -o1; + else o2 = -o2; + o1 = -((o1+o2-1)/o2); } else { o1 /= o2; } -#endif break; - case MOD: if (o2 == 0) { node_error(expp, "modulo by 0"); return; } -#if (-1)/2==0 - o1 %= o2; -#else - if (o1 == 0) break; if ((o1 < 0) != (o2 < 0)) { - o1 -= (o1 / o2 + 1) * o2; + if (o1 < 0) o1 = -o1; + else o2 = -o2; + o1 = ((o1+o2-1)/o2) * o2 - o1; } else { o1 %= o2; } -#endif break; case '+': diff --git a/lang/m2/libm2/LIST b/lang/m2/libm2/LIST index 5d8621cb0..4294f16a6 100644 --- a/lang/m2/libm2/LIST +++ b/lang/m2/libm2/LIST @@ -19,6 +19,7 @@ ArraySort.mod catch.c Traps.mod XXTermcap.c +dvi.c Arguments.c LtoUset.e StrAss.c diff --git a/lang/m2/libm2/dvi.c b/lang/m2/libm2/dvi.c new file mode 100644 index 000000000..d72076def --- /dev/null +++ b/lang/m2/libm2/dvi.c @@ -0,0 +1,68 @@ +/* + (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands. + See the copyright notice in the ACK home directory, in the file "Copyright". +*/ + +/* + Module: implementation of DIV and MOD + Author: Ceriel J.H. Jacobs + Version: $Header$ + Reason: We cannot use DVI and RMI, because DVI rounds towards 0 + and Modula-2 requires truncation +*/ + +#include + +int +dvi(j,i) + int j,i; +{ + if (j == 0) TRP(EIDIVZ); + if ((i < 0) != (j < 0)) { + if (i < 0) i = -i; + else j = -j; + return -((i+j-1)/j); + } + else return i/j; +} + +long +dvil(j,i) + long j,i; +{ + if (j == 0) TRP(EIDIVZ); + if ((i < 0) != (j < 0)) { + if (i < 0) i = -i; + else j = -j; + return -((i+j-1)/j); + } + else return i/j; +} + +int +rmi(j,i) + int j,i; +{ + 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; +} + +long +rmil(j,i) + long j,i; +{ + 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; +}