diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c
index 17cbcd0c2f22232f09d49d43350bc1ad80cfd791..a339ab23e489e38acc3ac8ea60ebf2408166dd53 100644
--- a/src/modules/Gmp/mpz_glue.c
+++ b/src/modules/Gmp/mpz_glue.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mpz_glue.c,v 1.61 1999/10/29 08:22:07 hubbe Exp $");
+RCSID("$Id: mpz_glue.c,v 1.62 1999/10/30 09:31:33 hubbe Exp $");
 #include "gmp_machine.h"
 
 #if defined(HAVE_GMP2_GMP_H) && defined(HAVE_LIBGMP2)
@@ -638,40 +638,46 @@ static void return_temporary(INT32 args)
 #endif
 
 
-#define BINFUN(name, fun)				\
-static void name(INT32 args)				\
-{							\
-  INT32 e;						\
-  struct object *res;					\
-  for(e=0; e<args; e++)					\
-    get_mpz(sp+e-args, 1);				\
-  res = fast_clone_object(THIS_PROGRAM, 0);		\
-  mpz_set(OBTOMPZ(res), THIS);				\
-  for(e=0;e<args;e++)					\
-    fun(OBTOMPZ(res), OBTOMPZ(res),			\
-	OBTOMPZ(sp[e-args].u.object));			\
-  pop_n_elems(args);					\
-  PUSH_REDUCED(res);					\
+#define BINFUN2(name, fun)						\
+static void name(INT32 args)						\
+{									\
+  INT32 e;								\
+  struct object *res;							\
+  for(e=0; e<args; e++)							\
+   if(sp[e-args].type != T_INT || sp[e-args].u.integer<=0)		\
+    get_mpz(sp+e-args, 1);						\
+  res = fast_clone_object(THIS_PROGRAM, 0);				\
+  mpz_set(OBTOMPZ(res), THIS);						\
+  for(e=0;e<args;e++)							\
+    if(sp[e-args].type != T_INT)					\
+      fun(OBTOMPZ(res), OBTOMPZ(res), OBTOMPZ(sp[e-args].u.object));	\
+    else								\
+      PIKE_CONCAT(fun,_ui)(OBTOMPZ(res), OBTOMPZ(res),			\
+                           sp[e-args].u.integer);        		\
+									\
+  pop_n_elems(args);							\
+  PUSH_REDUCED(res);							\
+}									\
+									\
+static void PIKE_CONCAT(name,_eq)(INT32 args)				\
+{									\
+  INT32 e;								\
+  for(e=0; e<args; e++)							\
+   if(sp[e-args].type != T_INT || sp[e-args].u.integer<=0)		\
+    get_mpz(sp+e-args, 1);						\
+  for(e=0;e<args;e++)							\
+    if(sp[e-args].type != T_INT)					\
+      fun(THIS, THIS, OBTOMPZ(sp[e-args].u.object));			\
+    else								\
+      PIKE_CONCAT(fun,_ui)(THIS,THIS, sp[e-args].u.integer);      	\
+  add_ref(fp->current_object);						\
+  PUSH_REDUCED(fp->current_object);					\
 }
 
-BINFUN(mpzmod_add,mpz_add)
-BINFUN(mpzmod_mul,mpz_mul)
-BINFUN(mpzmod_gcd,mpz_gcd)
-
+BINFUN2(mpzmod_add,mpz_add)
+BINFUN2(mpzmod_mul,mpz_mul)
+BINFUN2(mpzmod_gcd,mpz_gcd)
 
-static void mpzmod_add_eq(INT32 args)
-{
-  INT32 e;
-  struct object *res;
-  for(e=0; e<args; e++)
-    get_mpz(sp+e-args, 1);
-  for(e=0;e<args;e++)
-    mpz_add(THIS, THIS, OBTOMPZ(sp[e-args].u.object));
-  pop_n_elems(args);
-
-  add_ref(fp->current_object);
-  PUSH_REDUCED(fp->current_object);
-}
 
 static void mpzmod_sub(INT32 args)
 {
@@ -855,6 +861,22 @@ static void mpzmod_invert(INT32 args)
   PUSH_REDUCED(res);
 }
 
+#define BINFUN(name, fun)				\
+static void name(INT32 args)				\
+{							\
+  INT32 e;						\
+  struct object *res;					\
+  for(e=0; e<args; e++)					\
+    get_mpz(sp+e-args, 1);				\
+  res = fast_clone_object(THIS_PROGRAM, 0);		\
+  mpz_set(OBTOMPZ(res), THIS);				\
+  for(e=0;e<args;e++)					\
+    fun(OBTOMPZ(res), OBTOMPZ(res),			\
+	OBTOMPZ(sp[e-args].u.object));			\
+  pop_n_elems(args);					\
+  PUSH_REDUCED(res);					\
+}
+
 BINFUN(mpzmod_and,mpz_and)
 BINFUN(mpzmod_or,mpz_ior)
 
@@ -1181,10 +1203,18 @@ void pike_module_exit(void)
 
 
 #define MPZ_ARG_TYPE "int|float|object"
-#define MPZ_SHIFT_TYPE "function(int|float|object:object)"
-#define MPZ_BINOP_TYPE ("function(" MPZ_ARG_TYPE "...:object)")
+#define MPZ_RET_TYPE "object"
+#define MPZ_SHIFT_TYPE "function(int|float|object:" MPZ_RET_TYPE")"
+#define MPZ_BINOP_TYPE ("function(" MPZ_ARG_TYPE "...:"MPZ_RET_TYPE")")
 #define MPZ_CMPOP_TYPE ("function(" MPZ_ARG_TYPE ":int)")
 
+#define tMpz_arg tOr3(tInt,tFloat,tObj)
+#define tMpz_ret tObj
+#define tMpz_int tInt
+#define tMpz_shift_type tFunc(tMpz_arg,tMpz_ret)
+#define tMpz_binop_type tFuncV(tNone, tMpz_arg, tMpz_ret)
+#define tMpz_cmpop_type tFunc(tMpz_arg, tMpz_ret)
+
 #define MPZ_DEFS()							\
   ADD_STORAGE(MP_INT);							\
   									\
@@ -1195,22 +1225,22 @@ void pike_module_exit(void)
 			      tObj),tVoid),				\
 		   tFunc(tStr tInt,tVoid)), 0);				\
 									\
-  add_function("`+",mpzmod_add,MPZ_BINOP_TYPE,0);			\
-  add_function("`+=",mpzmod_add_eq,MPZ_BINOP_TYPE,0);			\
-  add_function("``+",mpzmod_add,MPZ_BINOP_TYPE,0);			\
-  add_function("`-",mpzmod_sub,MPZ_BINOP_TYPE,0);			\
-  add_function("``-",mpzmod_rsub,MPZ_BINOP_TYPE,0);			\
-  add_function("`*",mpzmod_mul,MPZ_BINOP_TYPE,0);			\
-  add_function("``*",mpzmod_mul,MPZ_BINOP_TYPE,0);			\
-  add_function("`/",mpzmod_div,MPZ_BINOP_TYPE,0);			\
-  add_function("``/",mpzmod_rdiv,MPZ_BINOP_TYPE,0);			\
-  add_function("`%",mpzmod_mod,MPZ_BINOP_TYPE,0);			\
-  add_function("``%",mpzmod_rmod,MPZ_BINOP_TYPE,0);			\
-  add_function("`&",mpzmod_and,MPZ_BINOP_TYPE,0);			\
-  add_function("``&",mpzmod_and,MPZ_BINOP_TYPE,0);			\
-  add_function("`|",mpzmod_or,MPZ_BINOP_TYPE,0);			\
-  add_function("``|",mpzmod_or,MPZ_BINOP_TYPE,0);			\
-  /* function(:object) */						\
+  ADD_FUNCTION("`+",mpzmod_add,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`+=",mpzmod_add_eq,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``+",mpzmod_add,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`-",mpzmod_sub,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``-",mpzmod_rsub,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`*",mpzmod_mul,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``*",mpzmod_mul,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`*=",mpzmod_mul_eq,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`/",mpzmod_div,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``/",mpzmod_rdiv,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`%",mpzmod_mod,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``%",mpzmod_rmod,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`&",mpzmod_and,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``&",mpzmod_and,tMpz_binop_type,0);			\
+  ADD_FUNCTION("`|",mpzmod_or,tMpz_binop_type,0);			\
+  ADD_FUNCTION("``|",mpzmod_or,tMpz_binop_type,0);			\
   ADD_FUNCTION("`~",mpzmod_compl,tFunc(tNone,tObj),0);			\
 									\
   add_function("`<<",mpzmod_lsh,MPZ_SHIFT_TYPE,0);			\
@@ -1226,62 +1256,42 @@ void pike_module_exit(void)
   add_function("`==",mpzmod_eq,MPZ_CMPOP_TYPE,0);			\
   add_function("`!=",mpzmod_nq,MPZ_CMPOP_TYPE,0);			\
 									\
-  /* function(:int) */							\
   ADD_FUNCTION("`!",mpzmod_not,tFunc(tNone,tInt),0);			\
 									\
-  /* function(:int) */							\
   ADD_FUNCTION("__hash",mpzmod_get_int,tFunc(tNone,tInt),0);		\
-  /* function(string:mixed) */						\
   ADD_FUNCTION("cast",mpzmod_cast,tFunc(tStr,tMix),0);			\
 									\
-  /* function(int:string) */						\
   ADD_FUNCTION("_is_type", mpzmod__is_type, tFunc(tStr,tInt), 0);	\
   									\
-  /* function(void|int:string) */					\
   ADD_FUNCTION("digits", mpzmod_digits,tFunc(tOr(tVoid,tInt),tStr), 0);	\
-  /* function(int:string) */						\
   ADD_FUNCTION("_sprintf", mpzmod__sprintf, tFunc(tInt,tStr), 0);	\
-  /* function(void|int:int) */						\
   ADD_FUNCTION("size", mpzmod_size,tFunc(tOr(tVoid,tInt),tInt), 0);	\
 									\
-  /* function(:int) */							\
-  ADD_FUNCTION("cast_to_int",mpzmod_get_int,tFunc(tNone,tInt),0);	\
-  /* function(:string) */						\
+  ADD_FUNCTION("cast_to_int",mpzmod_get_int,tFunc(tNone,tMpz_int),0);	\
   ADD_FUNCTION("cast_to_string",mpzmod_get_string,tFunc(tNone,tStr),0);	\
-  /* function(:float) */						\
   ADD_FUNCTION("cast_to_float",mpzmod_get_float,tFunc(tNone,tFlt),0);	\
 									\
-  /* function(:int) */							\
   ADD_FUNCTION("probably_prime_p",mpzmod_probably_prime_p,		\
 	       tFunc(tNone,tInt),0);					\
-  /* function(int|void:int) */						\
   ADD_FUNCTION("small_factor", mpzmod_small_factor,			\
 	       tFunc(tOr(tInt,tVoid),tInt), 0);				\
-  /* function(int|void,int|void:object) */				\
   ADD_FUNCTION("next_prime", mpzmod_next_prime,				\
-	       tFunc(tOr(tInt,tVoid) tOr(tInt,tVoid),tObj), 0);		\
+	       tFunc(tOr(tInt,tVoid) tOr(tInt,tVoid),tMpz_ret), 0);	\
   									\
-  add_function("gcd",mpzmod_gcd, MPZ_BINOP_TYPE, 0);			\
-  add_function("gcdext", mpzmod_gcdext,					\
-  "function(" MPZ_ARG_TYPE ":array(object))", 0);			\
-  add_function("gcdext2", mpzmod_gcdext2,				\
-  "function(" MPZ_ARG_TYPE ":array(object))", 0);			\
-  add_function("invert", mpzmod_invert,					\
-  "function(" MPZ_ARG_TYPE ":object)", 0);				\
+  ADD_FUNCTION("gcd",mpzmod_gcd, tMpz_binop_type, 0);			\
+  ADD_FUNCTION("gcd_eq",mpzmod_gcd_eq, tMpz_binop_type, 0);		\
+  ADD_FUNCTION("gcdext",mpzmod_gcdext,tFunc(tMpz_arg,tArr(tMpz_ret)),0);\
+  ADD_FUNCTION("gcdext2",mpzmod_gcdext2,tFunc(tMpz_arg,tArr(tMpz_ret)),0);\
+  ADD_FUNCTION("invert", mpzmod_invert,tFunc(tMpz_arg,tMpz_ret),0);	\
 									\
-  /* function(:object) */						\
-  ADD_FUNCTION("sqrt", mpzmod_sqrt,tFunc(tNone,tObj),0);		\
-  /* function(:array(object)) */					\
-  ADD_FUNCTION("sqrtrem", mpzmod_sqrtrem,tFunc(tNone,tArr(tObj)), 0);	\
-  add_function("powm",mpzmod_powm,					\
-  "function(" MPZ_ARG_TYPE "," MPZ_ARG_TYPE ":object)", 0);		\
-  /* function(int:object) */						\
-  ADD_FUNCTION("pow", mpzmod_pow,tFunc(tInt,tObj), 0);			\
+  ADD_FUNCTION("sqrt", mpzmod_sqrt,tFunc(tNone,tMpz_ret),0);		\
+  ADD_FUNCTION("sqrtrem",mpzmod_sqrtrem,tFunc(tNone,tArr(tMpz_ret)),0);\
+  ADD_FUNCTION("powm",mpzmod_powm,tFunc(tMpz_arg tMpz_arg,tMpz_ret),0);	\
+  ADD_FUNCTION("pow", mpzmod_pow,tFunc(tInt,tMpz_ret), 0);		\
 									\
-  /* function(void:int) */						\
   ADD_FUNCTION("popcount", mpzmod_popcount,tFunc(tVoid,tInt), 0);	\
 									\
-  ADD_FUNCTION("_random",mpzmod_random,tFunc(tNone,tObj),0);		\
+  ADD_FUNCTION("_random",mpzmod_random,tFunc(tNone,tMpz_ret),0);	\
   									\
   set_init_callback(init_mpz_glue);					\
   set_exit_callback(exit_mpz_glue);
@@ -1320,6 +1330,11 @@ void pike_module_init(void)
      */
     start_new_program();
 
+#undef tMpz_ret
+#undef tMpz_int
+#define tMpz_ret tInt
+#define tMpz_int tInt
+
     /* I first tried to just do an inherit here, but it becomes too hard
      * to tell the programs apart when I do that..          /Hubbe
      */