Suggested mpn/generic/gcd.c patch

Torbjörn Granlund tg at gmplib.org
Mon Sep 9 19:23:24 UTC 2019


This patch gets rid of the gcd_1 call and instead handles everything
with gcd_11 and gcd_22.  It also lifts the operands into registers.

Niels, do you agree with this?  Marco?

We discussed a gcd_21 in the past, and here again is a utility for it.
It is behind an UNLIKELY just as it is unlikely within gcd_22, so not
super important.  Perhaps gcd_21 is more common as operands directly
from user code.

We surely could make gcd_21 fast now with the table based algorithm; 4
bits per iteration is easy when the operands have different sizes of > 4
bits.  Or even binary euclid for machines with fast small quotient
division.

2019-09-09  Torbjörn Granlund  <tg at gmplib.org>

	* mpn/generic/gcd.c: Rewrite tail of function.

*** /tmp/extdiff.zlppJi/gmp-main.cf5765234af8/mpn/generic/gcd.c	Sun Sep  8 21:55:22 2019
--- /home/tege/prec/gmp-main/mpn/generic/gcd.c	Mon Sep  9 21:10:41 2019
***************
*** 218,252 ****
    ASSERT(up[n-1] | vp[n-1]);
  
!   if (n == 1)
!     {
!       *gp = mpn_gcd_1(up, 1, vp[0]);
!       ctx.gn = 1;
!       goto done;
!     }
! 
!   /* Due to the calling convention for mpn_gcd, at most one can be
!      even. */
! 
    if (! (up[0] & 1))
      MP_PTR_SWAP (up, vp);
  
!   ASSERT (up[0] & 1);
  
!   if (vp[0] == 0)
!     {
!       *gp = mpn_gcd_1 (up, 2, vp[1]);
!       ctx.gn = 1;
!       goto done;
!     }
!   else if (! (vp[0] & 1))
!     {
!       int r;
!       count_trailing_zeros (r, vp[0]);
!       vp[0] = ((vp[1] << (GMP_NUMB_BITS - r)) & GMP_NUMB_MASK) | (vp[0] >> r);
!       vp[1] >>= r;
!     }
  
!   {
!     mp_double_limb_t g = mpn_gcd_22 (up[1], up[0], vp[1], vp[0]);
      gp[0] = g.d0;
      gp[1] = g.d1;
--- 218,261 ----
    ASSERT(up[n-1] | vp[n-1]);
  
!   /* Due to the calling convention for mpn_gcd, at most one can be even. */
    if (! (up[0] & 1))
      MP_PTR_SWAP (up, vp);
  
!   {
!     mp_limb_t u0, u1, v0, v1;
!     mp_double_limb_t g;
  
!     u0 = up[0];
!     v0 = vp[0];
  
!     if (n == 1)
!       {
! 	int cnt;
! 	count_trailing_zeros (cnt, v0);
! 	*gp = mpn_gcd_11 (u0, v0 >> cnt);
! 	ctx.gn = 1;
! 	goto done;
!       }
! 
!     ASSERT ((u0 & 1) != 0);
! 
!     v1 = vp[1];
!     if (UNLIKELY (v0 == 0))
!       {
! 	v0 = v1;
! 	v1 = 0;
! 	/* FIXME: We could invoke a mpn_gcd_21 here, just like mpn_gcd_22 could
! 	   when this situation occurs internally.
!       }
!     if ((v0 & 1) == 0)
!       {
! 	int cnt;
! 	count_trailing_zeros (cnt, v0);
! 	v0 = ((v1 << (GMP_NUMB_BITS - cnt)) & GMP_NUMB_MASK) | (v0 >> cnt);
! 	v1 >>= cnt;
!       }
! 
!     u1 = up[1];
!     g = mpn_gcd_22 (u1, u0, v1, v0);
      gp[0] = g.d0;
      gp[1] = g.d1;


-- 
Torbjörn
Please encrypt, key id 0xC8601622


More information about the gmp-devel mailing list