Home | History | Annotate | Line # | Download | only in generic
hgcd2_jacobi.c revision 1.1.1.1.8.2
      1 /* hgcd2_jacobi.c
      2 
      3    THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES.  IT IS ONLY
      4    SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
      5    GUARANTEED THAT THEY'LL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
      6 
      7 Copyright 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2008, 2011 Free Software
      8 Foundation, Inc.
      9 
     10 This file is part of the GNU MP Library.
     11 
     12 The GNU MP Library is free software; you can redistribute it and/or modify
     13 it under the terms of the GNU Lesser General Public License as published by
     14 the Free Software Foundation; either version 3 of the License, or (at your
     15 option) any later version.
     16 
     17 The GNU MP Library is distributed in the hope that it will be useful, but
     18 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     19 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     20 License for more details.
     21 
     22 You should have received a copy of the GNU Lesser General Public License
     23 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     24 
     25 #include "gmp.h"
     26 #include "gmp-impl.h"
     27 #include "longlong.h"
     28 
     29 #if GMP_NAIL_BITS > 0
     30 #error Nails not supported.
     31 #endif
     32 
     33 /* FIXME: Duplicated in hgcd2.c. Should move to gmp-impl.h, and
     34    possibly be renamed. */
     35 static inline mp_limb_t
     36 div1 (mp_ptr rp,
     37       mp_limb_t n0,
     38       mp_limb_t d0)
     39 {
     40   mp_limb_t q = 0;
     41 
     42   if ((mp_limb_signed_t) n0 < 0)
     43     {
     44       int cnt;
     45       for (cnt = 1; (mp_limb_signed_t) d0 >= 0; cnt++)
     46 	{
     47 	  d0 = d0 << 1;
     48 	}
     49 
     50       q = 0;
     51       while (cnt)
     52 	{
     53 	  q <<= 1;
     54 	  if (n0 >= d0)
     55 	    {
     56 	      n0 = n0 - d0;
     57 	      q |= 1;
     58 	    }
     59 	  d0 = d0 >> 1;
     60 	  cnt--;
     61 	}
     62     }
     63   else
     64     {
     65       int cnt;
     66       for (cnt = 0; n0 >= d0; cnt++)
     67 	{
     68 	  d0 = d0 << 1;
     69 	}
     70 
     71       q = 0;
     72       while (cnt)
     73 	{
     74 	  d0 = d0 >> 1;
     75 	  q <<= 1;
     76 	  if (n0 >= d0)
     77 	    {
     78 	      n0 = n0 - d0;
     79 	      q |= 1;
     80 	    }
     81 	  cnt--;
     82 	}
     83     }
     84   *rp = n0;
     85   return q;
     86 }
     87 
     88 /* Two-limb division optimized for small quotients.  */
     89 static inline mp_limb_t
     90 div2 (mp_ptr rp,
     91       mp_limb_t nh, mp_limb_t nl,
     92       mp_limb_t dh, mp_limb_t dl)
     93 {
     94   mp_limb_t q = 0;
     95 
     96   if ((mp_limb_signed_t) nh < 0)
     97     {
     98       int cnt;
     99       for (cnt = 1; (mp_limb_signed_t) dh >= 0; cnt++)
    100 	{
    101 	  dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
    102 	  dl = dl << 1;
    103 	}
    104 
    105       while (cnt)
    106 	{
    107 	  q <<= 1;
    108 	  if (nh > dh || (nh == dh && nl >= dl))
    109 	    {
    110 	      sub_ddmmss (nh, nl, nh, nl, dh, dl);
    111 	      q |= 1;
    112 	    }
    113 	  dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
    114 	  dh = dh >> 1;
    115 	  cnt--;
    116 	}
    117     }
    118   else
    119     {
    120       int cnt;
    121       for (cnt = 0; nh > dh || (nh == dh && nl >= dl); cnt++)
    122 	{
    123 	  dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
    124 	  dl = dl << 1;
    125 	}
    126 
    127       while (cnt)
    128 	{
    129 	  dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
    130 	  dh = dh >> 1;
    131 	  q <<= 1;
    132 	  if (nh > dh || (nh == dh && nl >= dl))
    133 	    {
    134 	      sub_ddmmss (nh, nl, nh, nl, dh, dl);
    135 	      q |= 1;
    136 	    }
    137 	  cnt--;
    138 	}
    139     }
    140 
    141   rp[0] = nl;
    142   rp[1] = nh;
    143 
    144   return q;
    145 }
    146 
    147 int
    148 mpn_hgcd2_jacobi (mp_limb_t ah, mp_limb_t al, mp_limb_t bh, mp_limb_t bl,
    149 		  struct hgcd_matrix1 *M, unsigned *bitsp)
    150 {
    151   mp_limb_t u00, u01, u10, u11;
    152   unsigned bits = *bitsp;
    153 
    154   if (ah < 2 || bh < 2)
    155     return 0;
    156 
    157   if (ah > bh || (ah == bh && al > bl))
    158     {
    159       sub_ddmmss (ah, al, ah, al, bh, bl);
    160       if (ah < 2)
    161 	return 0;
    162 
    163       u00 = u01 = u11 = 1;
    164       u10 = 0;
    165       bits = mpn_jacobi_update (bits, 1, 1);
    166     }
    167   else
    168     {
    169       sub_ddmmss (bh, bl, bh, bl, ah, al);
    170       if (bh < 2)
    171 	return 0;
    172 
    173       u00 = u10 = u11 = 1;
    174       u01 = 0;
    175       bits = mpn_jacobi_update (bits, 0, 1);
    176     }
    177 
    178   if (ah < bh)
    179     goto subtract_a;
    180 
    181   for (;;)
    182     {
    183       ASSERT (ah >= bh);
    184       if (ah == bh)
    185 	goto done;
    186 
    187       if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
    188 	{
    189 	  ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
    190 	  bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
    191 
    192 	  break;
    193 	}
    194 
    195       /* Subtract a -= q b, and multiply M from the right by (1 q ; 0
    196 	 1), affecting the second column of M. */
    197       ASSERT (ah > bh);
    198       sub_ddmmss (ah, al, ah, al, bh, bl);
    199 
    200       if (ah < 2)
    201 	goto done;
    202 
    203       if (ah <= bh)
    204 	{
    205 	  /* Use q = 1 */
    206 	  u01 += u00;
    207 	  u11 += u10;
    208 	  bits = mpn_jacobi_update (bits, 1, 1);
    209 	}
    210       else
    211 	{
    212 	  mp_limb_t r[2];
    213 	  mp_limb_t q = div2 (r, ah, al, bh, bl);
    214 	  al = r[0]; ah = r[1];
    215 	  if (ah < 2)
    216 	    {
    217 	      /* A is too small, but q is correct. */
    218 	      u01 += q * u00;
    219 	      u11 += q * u10;
    220 	      bits = mpn_jacobi_update (bits, 1, q & 3);
    221 	      goto done;
    222 	    }
    223 	  q++;
    224 	  u01 += q * u00;
    225 	  u11 += q * u10;
    226 	  bits = mpn_jacobi_update (bits, 1, q & 3);
    227 	}
    228     subtract_a:
    229       ASSERT (bh >= ah);
    230       if (ah == bh)
    231 	goto done;
    232 
    233       if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
    234 	{
    235 	  ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
    236 	  bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
    237 
    238 	  goto subtract_a1;
    239 	}
    240 
    241       /* Subtract b -= q a, and multiply M from the right by (1 0 ; q
    242 	 1), affecting the first column of M. */
    243       sub_ddmmss (bh, bl, bh, bl, ah, al);
    244 
    245       if (bh < 2)
    246 	goto done;
    247 
    248       if (bh <= ah)
    249 	{
    250 	  /* Use q = 1 */
    251 	  u00 += u01;
    252 	  u10 += u11;
    253 	  bits = mpn_jacobi_update (bits, 0, 1);
    254 	}
    255       else
    256 	{
    257 	  mp_limb_t r[2];
    258 	  mp_limb_t q = div2 (r, bh, bl, ah, al);
    259 	  bl = r[0]; bh = r[1];
    260 	  if (bh < 2)
    261 	    {
    262 	      /* B is too small, but q is correct. */
    263 	      u00 += q * u01;
    264 	      u10 += q * u11;
    265 	      bits = mpn_jacobi_update (bits, 0, q & 3);
    266 	      goto done;
    267 	    }
    268 	  q++;
    269 	  u00 += q * u01;
    270 	  u10 += q * u11;
    271 	  bits = mpn_jacobi_update (bits, 0, q & 3);
    272 	}
    273     }
    274 
    275   /* NOTE: Since we discard the least significant half limb, we don't
    276      get a truly maximal M (corresponding to |a - b| <
    277      2^{GMP_LIMB_BITS +1}). */
    278   /* Single precision loop */
    279   for (;;)
    280     {
    281       ASSERT (ah >= bh);
    282       if (ah == bh)
    283 	break;
    284 
    285       ah -= bh;
    286       if (ah < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
    287 	break;
    288 
    289       if (ah <= bh)
    290 	{
    291 	  /* Use q = 1 */
    292 	  u01 += u00;
    293 	  u11 += u10;
    294 	  bits = mpn_jacobi_update (bits, 1, 1);
    295 	}
    296       else
    297 	{
    298 	  mp_limb_t r;
    299 	  mp_limb_t q = div1 (&r, ah, bh);
    300 	  ah = r;
    301 	  if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
    302 	    {
    303 	      /* A is too small, but q is correct. */
    304 	      u01 += q * u00;
    305 	      u11 += q * u10;
    306 	      bits = mpn_jacobi_update (bits, 1, q & 3);
    307 	      break;
    308 	    }
    309 	  q++;
    310 	  u01 += q * u00;
    311 	  u11 += q * u10;
    312 	  bits = mpn_jacobi_update (bits, 1, q & 3);
    313 	}
    314     subtract_a1:
    315       ASSERT (bh >= ah);
    316       if (ah == bh)
    317 	break;
    318 
    319       bh -= ah;
    320       if (bh < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
    321 	break;
    322 
    323       if (bh <= ah)
    324 	{
    325 	  /* Use q = 1 */
    326 	  u00 += u01;
    327 	  u10 += u11;
    328 	  bits = mpn_jacobi_update (bits, 0, 1);
    329 	}
    330       else
    331 	{
    332 	  mp_limb_t r;
    333 	  mp_limb_t q = div1 (&r, bh, ah);
    334 	  bh = r;
    335 	  if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
    336 	    {
    337 	      /* B is too small, but q is correct. */
    338 	      u00 += q * u01;
    339 	      u10 += q * u11;
    340 	      bits = mpn_jacobi_update (bits, 0, q & 3);
    341 	      break;
    342 	    }
    343 	  q++;
    344 	  u00 += q * u01;
    345 	  u10 += q * u11;
    346 	  bits = mpn_jacobi_update (bits, 0, q & 3);
    347 	}
    348     }
    349 
    350  done:
    351   M->u[0][0] = u00; M->u[0][1] = u01;
    352   M->u[1][0] = u10; M->u[1][1] = u11;
    353   *bitsp = bits;
    354 
    355   return 1;
    356 }
    357