Home | History | Annotate | Line # | Download | only in generic
jacobi_2.c revision 1.1.1.2
      1 /* jacobi_2.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-2004, 2008, 2010 Free Software Foundation, Inc.
      8 
      9 This file is part of the GNU MP Library.
     10 
     11 The GNU MP Library is free software; you can redistribute it and/or modify
     12 it under the terms of either:
     13 
     14   * the GNU Lesser General Public License as published by the Free
     15     Software Foundation; either version 3 of the License, or (at your
     16     option) any later version.
     17 
     18 or
     19 
     20   * the GNU General Public License as published by the Free Software
     21     Foundation; either version 2 of the License, or (at your option) any
     22     later version.
     23 
     24 or both in parallel, as here.
     25 
     26 The GNU MP Library is distributed in the hope that it will be useful, but
     27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     28 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     29 for more details.
     30 
     31 You should have received copies of the GNU General Public License and the
     32 GNU Lesser General Public License along with the GNU MP Library.  If not,
     33 see https://www.gnu.org/licenses/.  */
     34 
     35 #include "gmp.h"
     36 #include "gmp-impl.h"
     37 #include "longlong.h"
     38 
     39 #ifndef JACOBI_2_METHOD
     40 #define JACOBI_2_METHOD 2
     41 #endif
     42 
     43 /* Computes (a / b) where b is odd, and a and b are otherwise arbitrary
     44    two-limb numbers. */
     45 #if JACOBI_2_METHOD == 1
     46 int
     47 mpn_jacobi_2 (mp_srcptr ap, mp_srcptr bp, unsigned bit)
     48 {
     49   mp_limb_t ah, al, bh, bl;
     50   int c;
     51 
     52   al = ap[0];
     53   ah = ap[1];
     54   bl = bp[0];
     55   bh = bp[1];
     56 
     57   ASSERT (bl & 1);
     58 
     59   bl = ((bh << (GMP_NUMB_BITS - 1)) & GMP_NUMB_MASK) | (bl >> 1);
     60   bh >>= 1;
     61 
     62   if ( (bh | bl) == 0)
     63     return 1 - 2*(bit & 1);
     64 
     65   if ( (ah | al) == 0)
     66     return 0;
     67 
     68   if (al == 0)
     69     {
     70       al = ah;
     71       ah = 0;
     72       bit ^= GMP_NUMB_BITS & (bl ^ (bl >> 1));
     73     }
     74   count_trailing_zeros (c, al);
     75   bit ^= c & (bl ^ (bl >> 1));
     76 
     77   c++;
     78   if (UNLIKELY (c == GMP_NUMB_BITS))
     79     {
     80       al = ah;
     81       ah = 0;
     82     }
     83   else
     84     {
     85       al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
     86       ah >>= c;
     87     }
     88   while ( (ah | bh) > 0)
     89     {
     90       mp_limb_t th, tl;
     91       mp_limb_t bgta;
     92 
     93       sub_ddmmss (th, tl, ah, al, bh, bl);
     94       if ( (tl | th) == 0)
     95 	return 0;
     96 
     97       bgta = LIMB_HIGHBIT_TO_MASK (th);
     98 
     99       /* If b > a, invoke reciprocity */
    100       bit ^= (bgta & al & bl);
    101 
    102       /* b <-- min (a, b) */
    103       add_ssaaaa (bh, bl, bh, bl, th & bgta, tl & bgta);
    104 
    105       if ( (bh | bl) == 0)
    106 	return 1 - 2*(bit & 1);
    107 
    108       /* a <-- |a - b| */
    109       al = (bgta ^ tl) - bgta;
    110       ah = (bgta ^ th);
    111 
    112       if (UNLIKELY (al == 0))
    113 	{
    114 	  /* If b > a, al == 0 implies that we have a carry to
    115 	     propagate. */
    116 	  al = ah - bgta;
    117 	  ah = 0;
    118 	  bit ^= GMP_NUMB_BITS & (bl ^ (bl >> 1));
    119 	}
    120       count_trailing_zeros (c, al);
    121       c++;
    122       bit ^= c & (bl ^ (bl >> 1));
    123 
    124       if (UNLIKELY (c == GMP_NUMB_BITS))
    125 	{
    126 	  al = ah;
    127 	  ah = 0;
    128 	}
    129       else
    130 	{
    131 	  al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
    132 	  ah >>= c;
    133 	}
    134     }
    135 
    136   ASSERT (bl > 0);
    137 
    138   while ( (al | bl) & GMP_LIMB_HIGHBIT)
    139     {
    140       /* Need an extra comparison to get the mask. */
    141       mp_limb_t t = al - bl;
    142       mp_limb_t bgta = - (bl > al);
    143 
    144       if (t == 0)
    145 	return 0;
    146 
    147       /* If b > a, invoke reciprocity */
    148       bit ^= (bgta & al & bl);
    149 
    150       /* b <-- min (a, b) */
    151       bl += (bgta & t);
    152 
    153       /* a <-- |a - b| */
    154       al = (t ^ bgta) - bgta;
    155 
    156       /* Number of trailing zeros is the same no matter if we look at
    157        * t or a, but using t gives more parallelism. */
    158       count_trailing_zeros (c, t);
    159       c ++;
    160       /* (2/b) = -1 if b = 3 or 5 mod 8 */
    161       bit ^= c & (bl ^ (bl >> 1));
    162 
    163       if (UNLIKELY (c == GMP_NUMB_BITS))
    164 	return 1 - 2*(bit & 1);
    165 
    166       al >>= c;
    167     }
    168 
    169   /* Here we have a little impedance mismatch. Better to inline it? */
    170   return mpn_jacobi_base (2*al+1, 2*bl+1, bit << 1);
    171 }
    172 #elif JACOBI_2_METHOD == 2
    173 int
    174 mpn_jacobi_2 (mp_srcptr ap, mp_srcptr bp, unsigned bit)
    175 {
    176   mp_limb_t ah, al, bh, bl;
    177   int c;
    178 
    179   al = ap[0];
    180   ah = ap[1];
    181   bl = bp[0];
    182   bh = bp[1];
    183 
    184   ASSERT (bl & 1);
    185 
    186   /* Use bit 1. */
    187   bit <<= 1;
    188 
    189   if (bh == 0 && bl == 1)
    190     /* (a|1) = 1 */
    191     return 1 - (bit & 2);
    192 
    193   if (al == 0)
    194     {
    195       if (ah == 0)
    196 	/* (0|b) = 0, b > 1 */
    197 	return 0;
    198 
    199       count_trailing_zeros (c, ah);
    200       bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
    201 
    202       al = bl;
    203       bl = ah >> c;
    204 
    205       if (bl == 1)
    206 	/* (1|b) = 1 */
    207 	return 1 - (bit & 2);
    208 
    209       ah = bh;
    210 
    211       bit ^= al & bl;
    212 
    213       goto b_reduced;
    214     }
    215   if ( (al & 1) == 0)
    216     {
    217       count_trailing_zeros (c, al);
    218 
    219       al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
    220       ah >>= c;
    221       bit ^= (c << 1) & (bl ^ (bl >> 1));
    222     }
    223   if (ah == 0)
    224     {
    225       if (bh > 0)
    226 	{
    227 	  bit ^= al & bl;
    228 	  MP_LIMB_T_SWAP (al, bl);
    229 	  ah = bh;
    230 	  goto b_reduced;
    231 	}
    232       goto ab_reduced;
    233     }
    234 
    235   while (bh > 0)
    236     {
    237       /* Compute (a|b) */
    238       while (ah > bh)
    239 	{
    240 	  sub_ddmmss (ah, al, ah, al, bh, bl);
    241 	  if (al == 0)
    242 	    {
    243 	      count_trailing_zeros (c, ah);
    244 	      bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
    245 
    246 	      al = bl;
    247 	      bl = ah >> c;
    248 	      ah = bh;
    249 
    250 	      bit ^= al & bl;
    251 	      goto b_reduced;
    252 	    }
    253 	  count_trailing_zeros (c, al);
    254 	  bit ^= (c << 1) & (bl ^ (bl >> 1));
    255 	  al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
    256 	  ah >>= c;
    257 	}
    258       if (ah == bh)
    259 	goto cancel_hi;
    260 
    261       if (ah == 0)
    262 	{
    263 	  bit ^= al & bl;
    264 	  MP_LIMB_T_SWAP (al, bl);
    265 	  ah = bh;
    266 	  break;
    267 	}
    268 
    269       bit ^= al & bl;
    270 
    271       /* Compute (b|a) */
    272       while (bh > ah)
    273 	{
    274 	  sub_ddmmss (bh, bl, bh, bl, ah, al);
    275 	  if (bl == 0)
    276 	    {
    277 	      count_trailing_zeros (c, bh);
    278 	      bit ^= ((GMP_NUMB_BITS + c) << 1) & (al ^ (al >> 1));
    279 
    280 	      bl = bh >> c;
    281 	      bit ^= al & bl;
    282 	      goto b_reduced;
    283 	    }
    284 	  count_trailing_zeros (c, bl);
    285 	  bit ^= (c << 1) & (al ^ (al >> 1));
    286 	  bl = ((bh << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (bl >> c);
    287 	  bh >>= c;
    288 	}
    289       bit ^= al & bl;
    290 
    291       /* Compute (a|b) */
    292       if (ah == bh)
    293 	{
    294 	cancel_hi:
    295 	  if (al < bl)
    296 	    {
    297 	      MP_LIMB_T_SWAP (al, bl);
    298 	      bit ^= al & bl;
    299 	    }
    300 	  al -= bl;
    301 	  if (al == 0)
    302 	    return 0;
    303 
    304 	  count_trailing_zeros (c, al);
    305 	  bit ^= (c << 1) & (bl ^ (bl >> 1));
    306 	  al >>= c;
    307 
    308 	  if (al == 1)
    309 	    return 1 - (bit & 2);
    310 
    311 	  MP_LIMB_T_SWAP (al, bl);
    312 	  bit ^= al & bl;
    313 	  break;
    314 	}
    315     }
    316 
    317  b_reduced:
    318   /* Compute (a|b), with b a single limb. */
    319   ASSERT (bl & 1);
    320 
    321   if (bl == 1)
    322     /* (a|1) = 1 */
    323     return 1 - (bit & 2);
    324 
    325   while (ah > 0)
    326     {
    327       ah -= (al < bl);
    328       al -= bl;
    329       if (al == 0)
    330 	{
    331 	  if (ah == 0)
    332 	    return 0;
    333 	  count_trailing_zeros (c, ah);
    334 	  bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
    335 	  al = ah >> c;
    336 	  goto ab_reduced;
    337 	}
    338       count_trailing_zeros (c, al);
    339 
    340       al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
    341       ah >>= c;
    342       bit ^= (c << 1) & (bl ^ (bl >> 1));
    343     }
    344  ab_reduced:
    345   ASSERT (bl & 1);
    346   ASSERT (bl > 1);
    347 
    348   return mpn_jacobi_base (al, bl, bit);
    349 }
    350 #else
    351 #error Unsupported value for JACOBI_2_METHOD
    352 #endif
    353