diff --git a/src/bignum.c b/src/bignum.c
index 2f6ad8caf2816df5718396dcf1085e8b3bc31b02..f60992c1f9558f83307f35e340eca171a2e60a72 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -55,6 +55,17 @@ struct object *bignum_from_svalue(struct svalue *s)
   return  (--sp)->u.object;
 }
 
+struct pike_string *string_from_bignum(struct object *o, int base)
+{
+  push_int(base);
+  safe_apply(o, "digits", 1);
+  
+  if(sp[-1].type != T_STRING)
+    error("Gmp.mpz string conversion failed.\n");
+  
+  return (--sp)->u.string;
+}
+
 void convert_svalue_to_bignum(struct svalue *s)
 {
   push_svalue(s);
diff --git a/src/bignum.h b/src/bignum.h
index 83ea61aaa6667a75ec97bdd77c42978c7ca4c3fa..544d10494e6bd1bb8ede394b83172c80d1a494d1 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -5,10 +5,9 @@
 
 #ifdef AUTO_BIGNUM
 
+/* Note: These functions assume some properties of the CPU. */
 
-/* NOTE: These functions assume some properties of the CPU. */
-
-#define INT_TYPE_SIGN(x)             ((x) < 0 ? -1 : 1)
+#define INT_TYPE_SIGN(x)             ((x) < 0)
 
 #define INT_TYPE_MUL_OVERFLOW(a, b)  ((b) && ((a)*(b))/(b) != (a))
 
@@ -18,16 +17,23 @@
         (INT_TYPE_SIGN(a) == INT_TYPE_SIGN(b) &&                           \
 	 INT_TYPE_SIGN(a) != INT_TYPE_SIGN((a)+(b)))
 
-#define INT_TYPE_SUB_OVERFFLOW(a, b) INT_TYPE_ADD_OVERFLOW((a), -(b))
+#define INT_TYPE_SUB_OVERFLOW(a, b)                                        \
+        (INT_TYPE_SIGN(a) != INT_TYPE_SIGN(b) &&                           \
+	 INT_TYPE_SIGN(a) != INT_TYPE_SIGN((a)-(b)))
 
-#define INT_TYPE_SUB_OVERFLOW(a, b)  INT_TYPE_ADD_OVERFLOW((a), -(b))
-#define INT_TYPE_ASL_OVERFLOW(a, b)  ((((a)<<(b))>>(b)) != (a))
+#define INT_TYPE_LSH_OVERFLOW(a, b)                                        \
+        (((INT_TYPE)sizeof(INT_TYPE))*CHAR_BIT <= (b) ||                   \
+	 (((a)<<(b))>>(b)) != (a))
 
+/* Note: If this gives overflow, set the result to zero. */
+#define INT_TYPE_RSH_OVERFLOW(a, b)                                        \
+        (((INT_TYPE)sizeof(INT_TYPE))*CHAR_BIT <= (b))
 
 /* Prototypes begin here */
 void convert_stack_top_to_bignum(void);
 struct object *make_bignum_object(void);
 struct object *bignum_from_svalue(struct svalue *s);
+struct pike_string *string_from_bignum(struct object *o, int base);
 void convert_svalue_to_bignum(struct svalue *s);
 /* Prototypes end here */
 
diff --git a/src/operators.c b/src/operators.c
index 0c02531d5f4c50eb9184d4004ae2c8c466c5e713..a8f5afd07176d2c2098c5db52dd1a25182413e20 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -6,7 +6,7 @@
 /**/
 #include "global.h"
 #include <math.h>
-RCSID("$Id: operators.c,v 1.62 1999/10/09 23:29:01 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.63 1999/10/15 21:08:44 noring Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -675,6 +675,14 @@ void o_subtract(void)
     return;
 
   case T_INT:
+#ifdef AUTO_BIGNUM
+    if(INT_TYPE_SUB_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+    {
+      convert_stack_top_to_bignum();
+      f_minus(2);
+      return;
+    }
+#endif /* AUTO_BIGNUM */
     sp--;
     sp[-1].u.integer -= sp[0].u.integer;
     return;
@@ -1116,6 +1124,11 @@ static int generate_xor(node *n)
 
 void o_lsh(void)
 {
+#ifdef AUTO_BIGNUM
+  if(INT_TYPE_LSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+    convert_stack_top_to_bignum();
+#endif /* AUTO_BIGNUM */
+  
   if(sp[-1].type != T_INT || sp[-2].type != T_INT)
   {
     int args = 2;
@@ -1161,6 +1174,16 @@ void o_rsh(void)
       SIMPLE_BAD_ARG_ERROR("`>>", 1, "int|object");
     SIMPLE_BAD_ARG_ERROR("`>>", 2, "int|object");
   }
+  
+#ifdef AUTO_BIGNUM
+  if(INT_TYPE_RSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+  {
+    sp--;
+    sp[-1].u.integer = 0;
+    return;
+  }
+#endif /* AUTO_BIGNUM */
+  
   sp--;
   sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer;
 }
@@ -1832,6 +1855,7 @@ void o_negate(void)
   switch(sp[-1].type)
   {
   case T_OBJECT:
+  do_lfun_negate:
     CALL_OPERATOR(LFUN_SUBTRACT,1);
     break;
 
@@ -1840,6 +1864,13 @@ void o_negate(void)
     return;
     
   case T_INT:
+#ifdef AUTO_BIGNUM
+    if(INT_TYPE_NEG_OVERFLOW(sp[-1].u.integer))
+    {
+      convert_stack_top_to_bignum();
+      goto do_lfun_negate;
+    }
+#endif /* AUTO_BIGNUM */
     sp[-1].u.integer = - sp[-1].u.integer;
     return;