diff -ur ../gcl-2.6.5-old/h/gmp_wrappers.h ./h/gmp_wrappers.h
--- ../gcl-2.6.5-old/h/gmp_wrappers.h	2004-08-16 19:28:20.000000000 +0200
+++ ./h/gmp_wrappers.h	2005-03-12 16:26:53.000000000 +0100
@@ -96,8 +96,8 @@
 
 #define MEM_GMP_CALL(n_,rt_,a_,s_,b_...) \
    GMP_EXTERN_INLINE Join(RF_,rt_) Join(m,a_)(Join(P,n_)(b_)) { \
-           Join(RD_,rt_);\
            int j;\
+	   Join(RD_,rt_);\
 	   jmp_gmp=0;\
            if ((j=setjmp(gmp_jmp)))\
               GBC(j);\
@@ -136,6 +136,10 @@
 /*MEM_GMP_CALL(2,void *,mpz_realloc,mpz_t,mp_size_t)*/
 MEM_GMP_CALL(1,size_t,mpz_size,0,mpz_t)
 MEM_GMP_CALL(2,size_t,mpz_sizeinbase,0,mpz_t,int)
+MEM_GMP_CALL(3,void,mpz_gcd,1,mpz_t,mpz_t,mpz_t)
+MEM_GMP_CALL(3,gmp_ulint,mpz_gcd_ui,1,mpz_t,mpz_t,unsigned long int)
+MEM_GMP_CALL(3,void,mpz_divexact,1,mpz_t,mpz_t,mpz_t)
+MEM_GMP_CALL(3,void,mpz_divexact_ui,1,mpz_t,mpz_t,unsigned long int)
 
      /* FIXME: find a way to have this follow the convention in gmp.h*/
 
@@ -167,3 +171,7 @@
 /*#define __gmpz_realloc m__gmpz_realloc*/
 #define __gmpz_size m__gmpz_size
 #define __gmpz_sizeinbase m__gmpz_sizeinbase
+#define __gmpz_mpz_gcd m__gmpz_mpz_gcd
+#define __gmpz_mpz_gcd_ui m__gmpz_mpz_gcd_ui
+#define __gmpz_mpz_divexact m__gmpz_mpz_divexact
+#define __gmpz_mpz_divexact_ui m__gmpz_mpz_divexact_ui
diff -ur ../gcl-2.6.5-old/o/num_arith.c ./o/num_arith.c
--- ../gcl-2.6.5-old/o/num_arith.c	2004-03-30 23:50:19.000000000 +0200
+++ ./o/num_arith.c	2005-03-08 21:55:28.000000000 +0100
@@ -30,6 +30,106 @@
 void
 zero_divisor(void);
 
+
+
+static object
+integer_exact_quotient(object x,object y,int in_place) {
+
+  object r;
+
+  if (y==small_fixnum(1) || x==small_fixnum(0))
+    return x;
+
+  if (type_of(y)==t_fixnum && type_of(x)==t_fixnum) 
+    return make_fixnum(fix(x)/fix(y)); /* no in_place for fixnums as could be small */;
+
+  r=in_place ? x : new_bignum();
+
+  if (type_of(y)==t_fixnum) 
+    mpz_divexact_ui(MP(r),MP(x),fix(y));
+  else
+    mpz_divexact(MP(r),MP(x),MP(y));
+
+  return normalize_big(r);
+
+}
+
+static object
+make_cancelled_ratio(object num, object den)
+{
+	object r, integer_divide1(object x, object y), get_gcd(object x, object y);
+	vs_mark;
+
+	if (den==small_fixnum(0) /* number_zerop(den) */)
+		FEerror("Zero denominator.", 0);
+	if (num==small_fixnum(0)/* number_zerop(num) */)
+		return(num);
+	if (number_minusp(den)) {
+		num = number_negate(num);
+		vs_push(num);
+		den = number_negate(den);
+		vs_push(den);
+	}
+	if (den==small_fixnum(1)/* type_of(den) == t_fixnum && fix(den) == 1 */)
+		return(num);
+
+	r = alloc_object(t_ratio);
+	r->rat.rat_num = num;
+	r->rat.rat_den = den;
+	vs_reset;
+	return(r);
+}
+
+static object
+ratio_op_with_cancellation(object a,object b,object c,object d,object (*op)(object,object)) {
+
+  object b0,d0,g,t,g1;
+  
+  b0=b;
+  d0=d;
+
+  g=get_gcd(b,d);
+  
+  b=integer_exact_quotient(b,g,0); /* Try to handle g==1 case quickly above and keep generic */
+  d=integer_exact_quotient(d,g,0);
+
+  t=op(number_times(a,d),number_times(b,c));
+  
+  g1=get_gcd(t,g);
+    
+  t=integer_exact_quotient(t,g1,t!=a&&t!=b0&&t!=c&&t!=d0);
+  b=integer_exact_quotient(b0,g1,0);
+
+  b=number_times(b,d);
+  
+  return make_cancelled_ratio(t,b);
+  
+}
+
+
+static object
+ratio_mult_with_cancellation(object a,object b,object c,object d) {
+
+  object g;
+  
+  g=get_gcd(a,d);
+  
+  a=integer_exact_quotient(a,g,0);
+  d=integer_exact_quotient(d,g,0);
+
+  g=get_gcd(b,c);
+  
+  b=integer_exact_quotient(b,g,0);
+  c=integer_exact_quotient(c,g,0);
+
+  a=number_times(a,c);
+  b=number_times(b,d);
+
+  return make_cancelled_ratio(a,b);
+  
+}
+
+
 object fixnum_add(int i, int j)
 {
 
@@ -108,9 +208,9 @@
 		case t_bignum:
 		  MPOP(return, addsi,fix(x),MP(y));
 		case t_ratio:
-			z = number_plus(number_times(x, y->rat.rat_den),
-					y->rat.rat_num);
-			return make_ratio(z, y->rat.rat_den);
+		  	return ratio_op_with_cancellation(x,small_fixnum(1),
+						    y->rat.rat_num,y->rat.rat_den,
+						    number_plus);
 		case t_shortfloat:
 			dx = (double)(fix(x));
 			dy = (double)(sf(y));
@@ -132,8 +232,9 @@
 		case t_bignum:
 		  MPOP(return,addii,MP(y),MP(x)); 
 		case t_ratio:
-			z = number_plus(number_times(x, y->rat.rat_den), y->rat.rat_num);
-			return make_ratio(z, y->rat.rat_den);
+			return ratio_op_with_cancellation(x,small_fixnum(1),
+						    y->rat.rat_num,y->rat.rat_den,
+						    number_plus);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -152,17 +253,12 @@
 		switch (type_of(y)) {
 		case t_fixnum:
 		case t_bignum:
-			
-			z = number_plus(x->rat.rat_num,
-					number_times(x->rat.rat_den, y));
-			z = make_ratio(z, x->rat.rat_den);
-			return(z);
+			return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						    y,small_fixnum(1),
+						    number_plus);
 		case t_ratio:
-
-			z = number_plus(number_times(x->rat.rat_num,y->rat.rat_den),
-					number_times(x->rat.rat_den,y->rat.rat_num));
-			z = make_ratio(z,number_times(x->rat.rat_den,y->rat.rat_den));
-			return(z);
+			return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						    y->rat.rat_num,y->rat.rat_den,number_plus);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -258,10 +354,9 @@
 	case t_bignum:
 	  MPOP(return,addsi,1,MP(x));
 	case t_ratio:
-		z = number_plus(x->rat.rat_num, x->rat.rat_den);
-		z = make_ratio(z, x->rat.rat_den);
-		return(z);
-
+	  	return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+					    small_fixnum(1),small_fixnum(1),
+					    number_plus);
 	case t_shortfloat:
 		dx = (double)(sf(x));
 		z = alloc_object(t_shortfloat);
@@ -300,9 +395,9 @@
 		case t_bignum:
 		  MPOP(return, subsi,fix(x),MP(y));
 		case t_ratio:
-			z = number_minus(number_times(x, y->rat.rat_den), y->rat.rat_num);
-			z = make_ratio(z, y->rat.rat_den);
-			return(z);
+		 	return ratio_op_with_cancellation(x,small_fixnum(1),
+						    y->rat.rat_num,y->rat.rat_den,
+						    number_minus);
 		case t_shortfloat:
 			dx = (double)(fix(x));
 			dy = (double)(sf(y));
@@ -324,9 +419,9 @@
 		case t_bignum:
 		  MPOP(return,subii,MP(x),MP(y));
 		case t_ratio:
-			z = number_minus(number_times(x, y->rat.rat_den), y->rat.rat_num);
-			z = make_ratio(z, y->rat.rat_den);
-			return(z);
+		  	return ratio_op_with_cancellation(x,small_fixnum(1),
+						    y->rat.rat_num,y->rat.rat_den,
+						    number_minus);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -345,14 +440,12 @@
 		switch (type_of(y)) {
 		case t_fixnum:
 		case t_bignum:
-			z = number_minus(x->rat.rat_num, number_times(x->rat.rat_den, y));
-			z = make_ratio(z, x->rat.rat_den);
-			return(z);
+			return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						    y,small_fixnum(1),
+						    number_minus);
 		case t_ratio:
-			z = number_minus(number_times(x->rat.rat_num,y->rat.rat_den),
-					 (number_times(x->rat.rat_den,y->rat.rat_num)));
-			z = make_ratio(z,number_times(x->rat.rat_den,y->rat.rat_den));
-			return(z);
+			return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						    y->rat.rat_num,y->rat.rat_den,number_minus);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -441,10 +534,9 @@
 	case t_bignum:
 	  MPOP(return,addsi,-1,MP(x));
 	case t_ratio:
-		z = number_minus(x->rat.rat_num, x->rat.rat_den);
-		z = make_ratio(z, x->rat.rat_den);
-		return(z);
-
+	  	return ratio_op_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+					    small_fixnum(1),small_fixnum(1),
+					    number_minus);
 	case t_shortfloat:
 		dx = (double)(sf(x));
 		z = alloc_object(t_shortfloat);
@@ -524,8 +616,8 @@
 		case t_bignum:
 		  MPOP(return,mulsi,fix(x),MP(y));
 		case t_ratio:
-			z = make_ratio(number_times(x, y->rat.rat_num), y->rat.rat_den);
-			return(z);
+		  	return ratio_mult_with_cancellation(x,small_fixnum(1),
+						      y->rat.rat_num,y->rat.rat_den);
 		case t_shortfloat:
 			dx = (double)(fix(x));
 			dy = (double)(sf(y));
@@ -548,8 +640,8 @@
 		case t_bignum:
 		  MPOP(return,mulii,MP(y),MP(x));
 		case t_ratio:
-			z = make_ratio(number_times(x, y->rat.rat_num), y->rat.rat_den);
-			return(z);
+		  	return ratio_mult_with_cancellation(x,small_fixnum(1),
+						      y->rat.rat_num,y->rat.rat_den);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -568,12 +660,11 @@
 		switch (type_of(y)) {
 		case t_fixnum:
 		case t_bignum:
-			z = make_ratio(number_times(x->rat.rat_num, y), x->rat.rat_den);
-			return(z);
+			return ratio_mult_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						      y,small_fixnum(1));
 		case t_ratio:
-			z = make_ratio(number_times(x->rat.rat_num,y->rat.rat_num),
-				       number_times(x->rat.rat_den,y->rat.rat_den));
-			return(z);
+			return ratio_mult_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						      y->rat.rat_num,y->rat.rat_den);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -683,8 +774,8 @@
 		case t_ratio:
 			if(number_zerop(y->rat.rat_num))
 				zero_divisor();
-			z = make_ratio(number_times(x, y->rat.rat_den), y->rat.rat_num);
-			return(z);
+			return ratio_mult_with_cancellation(x,small_fixnum(1),
+							    y->rat.rat_den,y->rat.rat_num);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -705,12 +796,11 @@
 		case t_bignum:
 			if (number_zerop(y))
 				zero_divisor();
-			z = make_ratio(x->rat.rat_num, number_times(x->rat.rat_den, y));
-			return(z);
+			return ratio_mult_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+							    small_fixnum(1),y);
 		case t_ratio:
-			z = make_ratio(number_times(x->rat.rat_num,y->rat.rat_den),
-				       number_times(x->rat.rat_den,y->rat.rat_num));
-			return(z);
+			return ratio_mult_with_cancellation(x->rat.rat_num,x->rat.rat_den,
+						      y->rat.rat_den,y->rat.rat_num);
 		case t_shortfloat:
 			dx = number_to_double(x);
 			dy = (double)(sf(y));
@@ -820,28 +910,15 @@
 get_gcd(object x, object y)
 {
 	object	q, r;
+	if (x==small_fixnum(1) || y==small_fixnum(1))
+		return small_fixnum(1);
 
 	if (number_minusp(x))
 		x = number_negate(x);
 	if (number_minusp(y))
 		y = number_negate(y);
 
-L:
 	if (type_of(x) == t_fixnum && type_of(y) == t_fixnum) {
-	  /* LL: */
-	  /* 		if (i < j) { */
-	  /* 			k = i; */
-	  /* 			i = j; */
-	  /* 			j = k; */
-	  /* 		} */
-	  /* 		if (j == 0) { */
-	  /* 			return(make_fixnum(i)); */
-	  /* 		} */
-	  /* 		k = i % j; */
-	  /* 		i = j; */
-	  /* 		j = k; */
-	  /* 		goto LL; */
-	  
 	  register fixnum i, j, k, t;
 
 	  if (!(i = fix(x)))
@@ -869,13 +946,17 @@
 		x = y;
 		y = r;
 	}
-	if (type_of(y) == t_fixnum && fix(y) == 0) {
-		return(x);
+
+	if (type_of(y) == t_fixnum) {
+	  if (fix(y))
+	    return make_fixnum(mpz_gcd_ui(NULL,MP(x),fix(y)));
+	  else
+	    return(x);
 	}
-	integer_quotient_remainder_1(x, y, &q, &r);
-	 x = y;
-	 y = r;
-	goto L;
+
+	r=new_bignum();
+	mpz_gcd(MP(r),MP(x),MP(y));
+	return normalize_big(r);
 }
 
 /* (+          )   */

