diff --git a/.gitattributes b/.gitattributes
index eccd0100b87239b8076ea22f437dfd1a7b20a379..812f7c78807f5fcd8f366378bc92d198c41da603 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -67,7 +67,14 @@ testfont binary
 /src/mapping.c foreign_ident
 /src/modules/Gdbm/acconfig.h foreign_ident
 /src/modules/Gdbm/gdbmmod.c foreign_ident
+/src/modules/Gmp/Makefile.in foreign_ident
+/src/modules/Gmp/configure.in foreign_ident
+/src/modules/Gmp/gmp_machine.h.in foreign_ident
 /src/modules/Gmp/mpz_glue.c foreign_ident
+/src/modules/Gmp/my_gmp.h foreign_ident
+/src/modules/Gmp/next_prime.c foreign_ident
+/src/modules/Gmp/prime_table.c foreign_ident
+/src/modules/Gmp/testsuite.in foreign_ident
 /src/modules/Gz/acconfig.h foreign_ident
 /src/modules/Gz/zlibmod.c foreign_ident
 /src/modules/Image/acconfig.h foreign_ident
diff --git a/src/modules/Gmp/Makefile.in b/src/modules/Gmp/Makefile.in
index 35c6748e511b591cbbf61f17afbbba166868b719..ea6c1ef9612bf1b33c2f1fe4cb901704bcfbea69 100644
--- a/src/modules/Gmp/Makefile.in
+++ b/src/modules/Gmp/Makefile.in
@@ -1,3 +1,4 @@
+# $Id: Makefile.in,v 1.8 1998/07/11 18:35:19 grubba Exp $
 SRCDIR=@srcdir@
 VPATH=@srcdir@:@srcdir@/../..:../..
 MODULE_LDFLAGS=@LDFLAGS@ @LIBS@
diff --git a/src/modules/Gmp/configure.in b/src/modules/Gmp/configure.in
index 0df3eec9246412a615eb05ac4a7721ec12630c80..ea3ba815e71a71870e43e189d04d2595aafc3725 100644
--- a/src/modules/Gmp/configure.in
+++ b/src/modules/Gmp/configure.in
@@ -1,3 +1,4 @@
+# $Id: configure.in,v 1.2 1998/07/11 18:35:20 grubba Exp $
 AC_INIT(mpz_glue.c)
 AC_CONFIG_HEADER(gmp_machine.h)
 AC_ARG_WITH(gmp,     [  --with(out)-gmp        Support bignums],[],[with_gmp=yes])
@@ -5,9 +6,16 @@ AC_ARG_WITH(gmp,     [  --with(out)-gmp        Support bignums],[],[with_gmp=yes
 sinclude(../module_configure.in)
 
 if test x$with_gmp = xyes ; then
-  AC_CHECK_HEADERS(gmp.h)
-  if test $ac_cv_header_gmp_h = yes ; then
-    AC_CHECK_LIB(gmp, mpz_set_d)
+  AC_CHECK_HEADERS(gmp2/gmp.h)
+  AC_CHECK_LIB(gmp2, mpz_set_d)
+  if test "$ac_cv_header_gmp2_gmp_h$ac_cv_lib_gmp2_mpz_set_d" = "yesyes";
+  then
+    echo Using gmp2.
+  else
+    AC_CHECK_HEADERS(gmp.h)
+    if test $ac_cv_header_gmp_h = yes ; then
+      AC_CHECK_LIB(gmp, mpz_set_d)
+    fi
   fi
 fi
 
diff --git a/src/modules/Gmp/gmp_machine.h.in b/src/modules/Gmp/gmp_machine.h.in
index f304d6b576f6b85fcce987ff7044b6c9d77386ee..95ba342dbdf19e0126285ed6a22a099c6e04589d 100644
--- a/src/modules/Gmp/gmp_machine.h.in
+++ b/src/modules/Gmp/gmp_machine.h.in
@@ -1,6 +1,13 @@
+/* $Id: gmp_machine.h.in,v 1.2 1998/07/11 18:35:22 grubba Exp $ */
 #ifndef GMP_MACHINE_H
 #define GMP_MACHINE_H
 
+/* Define this if you have <gmp2/gmp.h> */
+#undef HAVE_GMP2_GMP_H
+
+/* Define this if you have -lgmp2 */
+#undef HAVE_LIBGMP2
+
 /* Define this if you have <gmp.h> */
 #undef HAVE_GMP_H
 
diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c
index 1d128598775b732a49ebc68efb2553301877322f..62e003a0ee7d4fae198775aa512ca115fb8a858d 100644
--- a/src/modules/Gmp/mpz_glue.c
+++ b/src/modules/Gmp/mpz_glue.c
@@ -4,14 +4,18 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mpz_glue.c,v 1.26 1998/03/04 22:09:55 hubbe Exp $");
+RCSID("$Id: mpz_glue.c,v 1.27 1998/07/11 18:35:23 grubba Exp $");
 #include "gmp_machine.h"
 
-#if !defined(HAVE_LIBGMP)
-#undef HAVE_GMP_H
-#endif
+#if defined(HAVE_GMP2_GMP_H) && defined(HAVE_LIBGMP2)
+#define USE_GMP2
+#else /* !HAVE_GMP2_GMP_H || !HAVE_LIBGMP2 */
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+#define USE_GMP
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
+#endif /* HAVE_GMP2_GMP_H && HAVE_LIBGMP2 */
 
-#ifdef HAVE_GMP_H
+#if defined(USE_GMP) || defined(USE_GMP2)
 
 #include "interpret.h"
 #include "svalue.h"
@@ -27,11 +31,17 @@ RCSID("$Id: mpz_glue.c,v 1.26 1998/03/04 22:09:55 hubbe Exp $");
 #include "opcodes.h"
 #include "module_support.h"
 
+#ifdef USE_GMP2
+#include <gmp2/gmp.h>
+#else /* !USE_GMP2 */
 #include <gmp.h>
+#endif /* USE_GMP2 */
+
 #include "my_gmp.h"
 
 #include <limits.h>
 
+#undef THIS
 #define THIS ((MP_INT *)(fp->current_storage))
 #define OBTOMPZ(o) ((MP_INT *)(o->storage))
 
@@ -165,11 +175,14 @@ static struct pike_string *low_get_digits(MP_INT *mpz, int base)
   }
   else if (base == 256)
   {
-    INT32 i;
+    unsigned INT32 i;
+#if 0
     mpz_t tmp;
-    
+#endif
+
     if (mpz_sgn(mpz) < 0)
       error("only non-negative numbers can be converted to base 256.\n");
+#if 0
     len = (mpz_sizeinbase(mpz, 2) + 7) / 8;
     s = begin_shared_string(len);
     mpz_init_set(tmp, mpz);
@@ -180,6 +193,34 @@ static struct pike_string *low_get_digits(MP_INT *mpz, int base)
       mpz_fdiv_q_2exp(tmp, tmp, 8);
     }
     mpz_clear(tmp);
+#endif
+
+    /* lets optimize this /Mirar & Per */
+
+    /* len = mpz->_mp_size*sizeof(mp_limb_t); */
+    /* This function should not return any leading zeros. /Nisse */
+    len = (mpz_sizeinbase(mpz, 2) + 7) / 8;
+    s = begin_shared_string(len);
+
+    if (!mpz->_mp_size)
+    {
+      /* Zero is a special case. There are no limbs at all, but
+       * the size is still 1 bit, and one digit should be produced. */
+      if (len != 1)
+	fatal("mpz->low_get_digits: strange mpz state!\n");
+      s->str[0] = 0;
+    } else {
+      mp_limb_t *src = mpz->_mp_d;
+      unsigned char *dst = (unsigned char *)s->str+s->len;
+
+      while (len > 0)
+      {
+	mp_limb_t x=*(src++);
+	for (i=0; i<sizeof(mp_limb_t); i++)
+	  *(--dst)=x&0xff,x>>=8;
+	len-=sizeof(mp_limb_t);
+      }
+    }
     s = end_shared_string(s);
   }
   else
@@ -245,73 +286,85 @@ static void mpzmod_size(INT32 args)
 
 static void mpzmod_cast(INT32 args)
 {
+  struct pike_string *s;
+
   if(args < 1)
     error("mpz->cast() called without arguments.\n");
   if(sp[-args].type != T_STRING)
     error("Bad argument 1 to mpz->cast().\n");
 
-  switch(sp[-args].u.string->str[0])
+  s = sp[-args].u.string;
+  add_ref(s);
+
+  pop_n_elems(args);
+
+  switch(s->str[0])
   {
   case 'i':
-    if(!strcmp(sp[-args].u.string->str, "int"))
+    if(!strcmp(s->str, "int"))
     {
-      mpzmod_get_int(args);
+      free_string(s);
+      mpzmod_get_int(0);
       return;
     }
     break;
 
   case 's':
-    if(!strcmp(sp[-args].u.string->str, "string"))
+    if(!strcmp(s->str, "string"))
     {
-      mpzmod_get_string(args);
+      free_string(s);
+      mpzmod_get_string(0);
       return;
     }
     break;
 
   case 'f':
-    if(!strcmp(sp[-args].u.string->str, "float"))
+    if(!strcmp(s->str, "float"))
     {
-      mpzmod_get_float(args);
+      free_string(s);
+      mpzmod_get_float(0);
       return;
     }
     break;
 
   case 'o':
-    if(!strcmp(sp[-args].u.string->str, "object"))
+    if(!strcmp(s->str, "object"))
     {
-      pop_n_elems(args);
       push_object(this_object());
     }
     break;
 
   case 'm':
-    if(!strcmp(sp[-args].u.string->str, "mixed"))
+    if(!strcmp(s->str, "mixed"))
     {
-      pop_n_elems(args);
       push_object(this_object());
     }
     break;
     
   }
 
-  error("mpz->cast() to other type than string, int or float.\n");
+  push_string(s);	/* To get it freed when error() pops the stack. */
+
+  error("mpz->cast() to \"%s\" is other type than string, int or float.\n",
+	s->str);
 }
 
-/* Converts an svalue, located on the stack, to an mpz object */
-#if defined(__GNUC__) && defined(DEBUG_MALLOC)
-#define get_mpz(X,Y) ({ check_svalue(X); debug_get_mpz((X), (Y)); })
+#ifdef DEBUG_MALLOC
+#define get_mpz(X,Y) \
+ (debug_get_mpz((X),(Y)),( (X)->type==T_OBJECT? debug_malloc_touch((X)->u.object) :0 ),debug_get_mpz((X),(Y)))
 #else
-#define get_mpz(X,Y) debug_get_mpz((X), (Y))
+#define get_mpz debug_get_mpz 
 #endif
 
+/* Converts an svalue, located on the stack, to an mpz object */
 static MP_INT *debug_get_mpz(struct svalue *s, int throw_error)
 {
-#define ERROR(x) if (throw_error) error(x)
+#define MPZ_ERROR(x) if (throw_error) error(x)
   struct object *o;
   switch(s->type)
   {
   default:
-    ERROR("Wrong type of object, cannot convert to mpz.\n");
+    MPZ_ERROR("Wrong type of object, cannot convert to mpz.\n");
     return 0;
 
   case T_INT:
@@ -321,7 +374,6 @@ static MP_INT *debug_get_mpz(struct svalue *s, int throw_error)
   case T_ARRAY:
 #endif
     o=clone_object(mpzmod_program,0);
-    debug_malloc_touch(o);
     get_new_mpz(OBTOMPZ(o), s);
     free_svalue(s);
     s->u.object=o;
@@ -331,7 +383,7 @@ static MP_INT *debug_get_mpz(struct svalue *s, int throw_error)
   case T_OBJECT:
     if(s->u.object->prog != mpzmod_program)
       {
-	ERROR("Wrong type of object, cannot convert to mpz.\n");
+	MPZ_ERROR("Wrong type of object, cannot convert to mpz.\n");
 	return 0;
       }
     return (MP_INT *)s->u.object->storage;
@@ -833,14 +885,14 @@ static void exit_mpz_glue(struct object *o)
 
 void pike_module_exit(void)
 {
-#ifdef HAVE_GMP_H
+#if defined(USE_GMP) || defined(USE_GMP2)
   free_program(mpzmod_program);
 #endif
 }
 
 void pike_module_init(void)
 {
-#ifdef HAVE_GMP_H
+#if defined(USE_GMP) || defined(USE_GMP2)
   start_new_program();
   add_storage(sizeof(MP_INT));
   
diff --git a/src/modules/Gmp/my_gmp.h b/src/modules/Gmp/my_gmp.h
index fde101801145ebb0ce51f15f98599d9920e72dff..aa9b46ed6409e52887efd5586dd2933b312e5541 100644
--- a/src/modules/Gmp/my_gmp.h
+++ b/src/modules/Gmp/my_gmp.h
@@ -1,4 +1,4 @@
-/* my_gmp.h
+/* $Id: my_gmp.h,v 1.3 1998/07/11 18:35:24 grubba Exp $
  *
  * These functions or something similar will hopefully be included
  * with Gmp-2.1 .
diff --git a/src/modules/Gmp/next_prime.c b/src/modules/Gmp/next_prime.c
index 1d96d7816fa7e815c86f033761f6cdacde3a76dc..c463f81befd4097818ae03e7f53ab7b117305478 100644
--- a/src/modules/Gmp/next_prime.c
+++ b/src/modules/Gmp/next_prime.c
@@ -1,4 +1,4 @@
-/* next_prime.c
+/* $Id: next_prime.c,v 1.6 1998/07/11 18:35:26 grubba Exp $
  *
  * Prime number test using trial division for small primes and then
  * Miller-Rabin, as suggested in Schneier's Applied Cryptography.
@@ -9,17 +9,27 @@
 
 #include "global.h"
 
-#include "gmp_machine.h"
+RCSID("$Id: next_prime.c,v 1.6 1998/07/11 18:35:26 grubba Exp $");
 
-#if !defined(HAVE_LIBGMP)
-#undef HAVE_GMP_H
-#endif
+#include "gmp_machine.h"
 
+#if defined(HAVE_GMP2_GMP_H) && defined(HAVE_LIBGMP2)
+#define USE_GMP2
+#else /* !HAVE_GMP2_GMP_H || !HAVE_LIBGMP2 */
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+#define USE_GMP
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
+#endif /* HAVE_GMP2_GMP_H && HAVE_LIBGMP2 */
 
-#ifdef HAVE_GMP_H
+#if defined(USE_GMP) || defined(USE_GMP2)
 
 #include <limits.h>
+
+#ifdef USE_GMP2
+#include <gmp2/gmp.h>
+#else /* !USE_GMP2 */
 #include <gmp.h>
+#endif /* USE_GMP2 */
 
 #include "my_gmp.h"
 
diff --git a/src/modules/Gmp/prime_table.c b/src/modules/Gmp/prime_table.c
index a9263cfe8a55eb4f1c37cb09cc9bf62f427f4d96..254e69ee11ca754cc78adc6e67ab6625bd87c93d 100644
--- a/src/modules/Gmp/prime_table.c
+++ b/src/modules/Gmp/prime_table.c
@@ -1,4 +1,4 @@
-/* prime_table.c
+/* $Id: prime_table.c,v 1.3 1998/07/11 18:35:27 grubba Exp $
  *
  * Generates a table of small odd primes.
  */
diff --git a/src/modules/Gmp/testsuite.in b/src/modules/Gmp/testsuite.in
index 6c8c34e3d3d42847b4d96e872e90e068f3257233..606458da53d8041717cc4083422c0dbf303c8cc3 100644
--- a/src/modules/Gmp/testsuite.in
+++ b/src/modules/Gmp/testsuite.in
@@ -1,8 +1,11 @@
+// $Id: testsuite.in,v 1.8 1998/07/11 18:35:28 grubba Exp $
+
 // mpz
 cond( [[ master()->resolv("Gmp")->mpz ]],
 [[
   test_true(programp(Gmp.mpz))
   test_false(clone(Gmp.mpz))
+  test_false(!Gmp.mpz(1))
   test_do(destruct(clone(Gmp.mpz)))
 
   test_eq(Gmp.mpz(10),10)
@@ -36,6 +39,7 @@ cond( [[ master()->resolv("Gmp")->mpz ]],
   test_binop(17,|,7,23)
   test_binop(17,&,18,16)
 
+  test_eq([[`+(1,1,1,Gmp.mpz(1),1,1)]],6)
   test_eq(-clone(Gmp.mpz,17),-17)
   test_eq((~clone(Gmp.mpz,17)) & 255,238)
   test_true(stringp((string)clone(Gmp.mpz,17)))
@@ -45,28 +49,51 @@ cond( [[ master()->resolv("Gmp")->mpz ]],
   test_false(clone(Gmp.mpz,0))
   test_true(clone(Gmp.mpz,1))
   test_eq(clone(Gmp.mpz,17)->powm(12,4711),85)
+]])
 
   define([[mpz_test_cmp]],[[
-    test_cmp(clone(Gmp.mpz,$1), $2)
-    test_cmp($1, clone(Gmp.mpz,$2))
-    test_cmp(clone(Gmp.mpz, $1), clone(Gmp.mpz, $2))
+    cond( [[ master()->resolv("Gmp")->mpz ]],
+    [[
+    test_cmp3(Gmp.mpz($1), $2, $3)
+    test_cmp3($1, Gmp.mpz($2), $3)
+    ]])
+    cond( [[ master()->resolv("Gmp")->mpz ]],
+    [[
+    test_cmp3(Gmp.mpz($1), Gmp.mpz($2), $3)
+    test_cmp3(Gmp.mpz($1), $2, Gmp.mpz($3))
+    ]])
+    cond( [[ master()->resolv("Gmp")->mpz ]],
+    [[
+    test_cmp3($1, Gmp.mpz($2), Gmp.mpz($3))
+    test_cmp3(Gmp.mpz($1), Gmp.mpz($2), Gmp.mpz($3))
+    ]])
   ]])
 
   define([[mpz_test_type1]],[[
-    mpz_test_cmp($1,$2)
-    mpz_test_cmp($1.0,$2)
+    mpz_test_cmp($1,$2,$3)
+    mpz_test_cmp($1.0,$2,$3)
   ]])
 
   define([[mpz_test_type2]],[[
-    mpz_test_type1($1,$2)
-    mpz_test_type1($1,$2.0)
+    mpz_test_type1($1,$2,$3)
+    mpz_test_type1($1,$2.0,$3)
+  ]])
+
+  define([[mpz_test_type3]],[[
+    mpz_test_type2($1,$2,$3)
+    mpz_test_type2($1,$2,$3.0)
   ]])
 
-  mpz_test_type2(1,2)
-  mpz_test_type2(-2,1)
+  mpz_test_type3(1,2,3)
+  mpz_test_type3(-2,1,4)
+  mpz_test_type3(-2,-1,4)
 
+cond( [[ master()->resolv("Gmp")->mpz ]],
+[[
   test_true(catch(Gmp.mpz("abcd", 47)))
   test_true(catch(Gmp.mpz(-17)->digits(256)))
+  test_eq(Gmp.mpz(0)->digits(256), "\0");
+  test_eq(Gmp.mpz(17)->digits(256), "\021");
   test_eq(Gmp.mpz(4711)->size(2), 13)
   test_true(catch(Gmp.mpz(17) + 18 + "19"))
   test_true(catch(Gmp.mpz(17) - 18 - "19"))