Fix: DIV and MOD on negative args
authorceriel <none@none>
Mon, 16 Jul 1990 09:05:19 +0000 (09:05 +0000)
committerceriel <none@none>
Mon, 16 Jul 1990 09:05:19 +0000 (09:05 +0000)
lang/m2/comp/code.c
lang/m2/comp/cstoper.c
lang/m2/libm2/LIST
lang/m2/libm2/dvi.c [new file with mode: 0644]

index f29a3f5..05ef6c1 100644 (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:
index 2cb9133..197e302 100644 (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 '+':
index 5d8621c..4294f16 100644 (file)
@@ -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 (file)
index 0000000..d72076d
--- /dev/null
@@ -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;
+}