Fix: DIV and MOD on negative args

This commit is contained in:
ceriel 1990-07-16 09:05:19 +00:00
parent 7f5abdd670
commit 109a357e95
4 changed files with 89 additions and 15 deletions

View file

@ -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:

View file

@ -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 '+':

View file

@ -19,6 +19,7 @@ ArraySort.mod
catch.c
Traps.mod
XXTermcap.c
dvi.c
Arguments.c
LtoUset.e
StrAss.c

68
lang/m2/libm2/dvi.c Normal file
View file

@ -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 <em_abs.h>
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;
}