New file.
[u/mdw/catacomb] / mpx.c
diff --git a/mpx.c b/mpx.c
index 4097b3e..6375c3e 100644 (file)
--- a/mpx.c
+++ b/mpx.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: mpx.c,v 1.12 2002/10/06 22:52:50 mdw Exp $
+ * $Id: mpx.c,v 1.15 2002/10/20 01:12:31 mdw Exp $
  *
  * Low-level multiprecision arithmetic
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: mpx.c,v $
+ * Revision 1.15  2002/10/20 01:12:31  mdw
+ * Two's complement I/O fixes.
+ *
+ * Revision 1.14  2002/10/19 18:55:08  mdw
+ * Fix overflows in shift primitives.
+ *
+ * Revision 1.13  2002/10/19 17:56:50  mdw
+ * Fix bit operations.  Test them (a bit) better.
+ *
  * Revision 1.12  2002/10/06 22:52:50  mdw
  * Pile of changes for supporting two's complement properly.
  *
@@ -81,6 +90,7 @@
 
 #include "mptypes.h"
 #include "mpx.h"
+#include "bitops.h"
 
 /*----- Loading and storing -----------------------------------------------*/
 
@@ -274,12 +284,12 @@ void mpx_storel2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
       bits -= 8;
     }
     b = U8(~b + c);
-    c = !b;
+    c = c && !b;
     *p++ = b;
   }
   while (p < q) {
     b = U8(~b + c);
-    c = !b;
+    c = c && !b;
     *p++ = b;
     b = 0;
   }
@@ -311,7 +321,7 @@ void mpx_loadl2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
     return;
   while (p < q) {
     n = U8(~(*p++) + c);
-    c = !n;
+    c = c && !n;
     w |= n << bits;
     bits += 8;
     if (bits >= MPW_BITS) {
@@ -364,12 +374,12 @@ void mpx_storeb2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
       bits -= 8;
     }
     b = U8(~b + c);
-    c = !b;
+    c = c && !b;
     *--q = b;
   }
   while (q > p) {
     b = ~b + c;
-    c = !(b & 0xff);
+    c = c && !(b & 0xff);
     *--q = b;
     b = 0;
   }
@@ -401,7 +411,7 @@ void mpx_loadb2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
     return;
   while (q > p) {
     n = U8(~(*--q) + c);
-    c = !n;
+    c = c && !n;
     w |= n << bits;
     bits += 8;
     if (bits >= MPW_BITS) {
@@ -466,8 +476,12 @@ void mpx_lsl(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
   /* --- Handle a shift by a multiple of the word size --- */
 
   if (nb == 0) {
-    MPX_COPY(dv + nw, dvl, av, avl);
-    memset(dv, 0, MPWS(nw));
+    if (nw >= dvl - dv)
+      MPX_ZERO(dv, dvl);
+    else {
+      MPX_COPY(dv + nw, dvl, av, avl);
+      memset(dv, 0, MPWS(nw));
+    }
   }
 
   /* --- And finally the difficult case --- *
@@ -558,8 +572,12 @@ void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
 
   /* --- Handle a shift by a multiple of the word size --- */
 
-  if (nb == 0)
-    MPX_COPY(dv, dvl, av + nw, avl);
+  if (nb == 0) {
+    if (nw >= avl - av)
+      MPX_ZERO(dv, dvl);
+    else
+      MPX_COPY(dv, dvl, av + nw, avl);
+  }
 
   /* --- And finally the difficult case --- */
 
@@ -568,7 +586,7 @@ void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
     size_t nr = MPW_BITS - nb;
 
     av += nw;
-    w = *av++;
+    w = av < avl ? *av++ : 0;
     while (av < avl) {
       mpw t;
       if (dv >= dvl)
@@ -611,7 +629,7 @@ void mpx_bit##string(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,      \
     mpw a, b;                                                          \
     a = (av < avl) ? *av++ : 0;                                                \
     b = (bv < bvl) ? *bv++ : 0;                                                \
-    *dv++ = MPX_B##string(a, b);                                       \
+    *dv++ = B##string(a, b);                                           \
   }                                                                    \
 }