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.
This commit is contained in:
parent
649410bb27
commit
038fb6fb55
|
@ -159,22 +159,29 @@ cstibin(expp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIV:
|
case DIV:
|
||||||
case MOD:
|
|
||||||
if (o2 == 0) {
|
if (o2 == 0) {
|
||||||
node_error(exp, exp->nd_symb == DIV ?
|
node_error(exp, "division by 0");
|
||||||
"division by 0" :
|
|
||||||
"modulo by 0");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((o1 < 0) != (o2 < 0)) {
|
if ((o1 < 0) != (o2 < 0)) {
|
||||||
if (o1 < 0) o1 = -o1;
|
if (o1 < 0) o1 = -o1;
|
||||||
else o2 = -o2;
|
else o2 = -o2;
|
||||||
if (exp->nd_symb == DIV) o1 = -((o1+o2-1)/o2);
|
o1 = -((o1+o2-1)/o2);
|
||||||
else o1 = ((o1+o2-1)/o2) * o2 - o1;
|
|
||||||
}
|
}
|
||||||
else {
|
else o1 /= o2;
|
||||||
if (exp->nd_symb == DIV) o1 /= o2;
|
break;
|
||||||
else o1 %= o2;
|
|
||||||
|
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;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -43,26 +43,28 @@ int
|
||||||
rmi(j,i)
|
rmi(j,i)
|
||||||
int j,i;
|
int j,i;
|
||||||
{
|
{
|
||||||
|
int m;
|
||||||
|
|
||||||
if (j == 0) TRP(EIDIVZ);
|
if (j == 0) TRP(EIDIVZ);
|
||||||
if (i == 0) return 0;
|
if (i == 0) return 0;
|
||||||
if ((i < 0) != (j < 0)) {
|
|
||||||
if (i < 0) i = -i;
|
m = i % j;
|
||||||
else j = -j;
|
if (m != 0 && (i < 0) != (j < 0))
|
||||||
return j*((i+j-1)/j)-i;
|
m += j;
|
||||||
}
|
return m;
|
||||||
else return i%j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
rmil(j,i)
|
rmil(j,i)
|
||||||
long j,i;
|
long j,i;
|
||||||
{
|
{
|
||||||
|
long m;
|
||||||
|
|
||||||
if (j == 0) TRP(EIDIVZ);
|
if (j == 0) TRP(EIDIVZ);
|
||||||
if (i == 0) return 0L;
|
if (i == 0) return 0L;
|
||||||
if ((i < 0) != (j < 0)) {
|
|
||||||
if (i < 0) i = -i;
|
m = i % j;
|
||||||
else j = -j;
|
if (m != 0 && (i < 0) != (j < 0))
|
||||||
return j*((i+j-1)/j)-i;
|
m += j;
|
||||||
}
|
return m;
|
||||||
else return i%j;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue