Home | History | Annotate | Line # | Download | only in generic
divis.c revision 1.1.1.1.8.1
      1          1.1  mrg /* mpn_divisible_p -- mpn by mpn divisibility test
      2          1.1  mrg 
      3          1.1  mrg    THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
      4          1.1  mrg    CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
      5          1.1  mrg    FUTURE GNU MP RELEASES.
      6          1.1  mrg 
      7          1.1  mrg Copyright 2001, 2002, 2005, 2009 Free Software Foundation, Inc.
      8          1.1  mrg 
      9          1.1  mrg This file is part of the GNU MP Library.
     10          1.1  mrg 
     11          1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     12          1.1  mrg it under the terms of the GNU Lesser General Public License as published by
     13          1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     14          1.1  mrg option) any later version.
     15          1.1  mrg 
     16          1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     17          1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     18          1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     19          1.1  mrg License for more details.
     20          1.1  mrg 
     21          1.1  mrg You should have received a copy of the GNU Lesser General Public License
     22          1.1  mrg along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     23          1.1  mrg 
     24          1.1  mrg #include "gmp.h"
     25          1.1  mrg #include "gmp-impl.h"
     26          1.1  mrg #include "longlong.h"
     27          1.1  mrg 
     28          1.1  mrg 
     29  1.1.1.1.8.1  tls /* Determine whether A={ap,an} is divisible by D={dp,dn}.  Must have both
     30          1.1  mrg    operands normalized, meaning high limbs non-zero, except that an==0 is
     31          1.1  mrg    allowed.
     32          1.1  mrg 
     33  1.1.1.1.8.1  tls    There usually won't be many low zero bits on D, but the checks for this
     34          1.1  mrg    are fast and might pick up a few operand combinations, in particular they
     35  1.1.1.1.8.1  tls    might reduce D to fit the single-limb mod_1/modexact_1 code.
     36          1.1  mrg 
     37          1.1  mrg    Future:
     38          1.1  mrg 
     39          1.1  mrg    Getting the remainder limb by limb would make an early exit possible on
     40          1.1  mrg    finding a non-zero.  This would probably have to be bdivmod style so
     41          1.1  mrg    there's no addback, but it would need a multi-precision inverse and so
     42          1.1  mrg    might be slower than the plain method (on small sizes at least).
     43          1.1  mrg 
     44  1.1.1.1.8.1  tls    When D must be normalized (shifted to low bit set), it's possible to supress
     45  1.1.1.1.8.1  tls    the bit-shifting of A down, as long as it's already been checked that A has
     46  1.1.1.1.8.1  tls    at least as many trailing zero bits as D.  */
     47          1.1  mrg 
     48          1.1  mrg int
     49          1.1  mrg mpn_divisible_p (mp_srcptr ap, mp_size_t an,
     50          1.1  mrg 		 mp_srcptr dp, mp_size_t dn)
     51          1.1  mrg {
     52          1.1  mrg   mp_limb_t  alow, dlow, dmask;
     53          1.1  mrg   mp_ptr     qp, rp, tp;
     54          1.1  mrg   mp_size_t  i;
     55          1.1  mrg   mp_limb_t di;
     56          1.1  mrg   unsigned  twos;
     57          1.1  mrg   TMP_DECL;
     58          1.1  mrg 
     59          1.1  mrg   ASSERT (an >= 0);
     60          1.1  mrg   ASSERT (an == 0 || ap[an-1] != 0);
     61          1.1  mrg   ASSERT (dn >= 1);
     62          1.1  mrg   ASSERT (dp[dn-1] != 0);
     63          1.1  mrg   ASSERT_MPN (ap, an);
     64          1.1  mrg   ASSERT_MPN (dp, dn);
     65          1.1  mrg 
     66          1.1  mrg   /* When a<d only a==0 is divisible.
     67          1.1  mrg      Notice this test covers all cases of an==0. */
     68          1.1  mrg   if (an < dn)
     69          1.1  mrg     return (an == 0);
     70          1.1  mrg 
     71          1.1  mrg   /* Strip low zero limbs from d, requiring a==0 on those. */
     72          1.1  mrg   for (;;)
     73          1.1  mrg     {
     74          1.1  mrg       alow = *ap;
     75          1.1  mrg       dlow = *dp;
     76          1.1  mrg 
     77          1.1  mrg       if (dlow != 0)
     78          1.1  mrg 	break;
     79          1.1  mrg 
     80          1.1  mrg       if (alow != 0)
     81          1.1  mrg 	return 0;  /* a has fewer low zero limbs than d, so not divisible */
     82          1.1  mrg 
     83          1.1  mrg       /* a!=0 and d!=0 so won't get to n==0 */
     84          1.1  mrg       an--; ASSERT (an >= 1);
     85          1.1  mrg       dn--; ASSERT (dn >= 1);
     86          1.1  mrg       ap++;
     87          1.1  mrg       dp++;
     88          1.1  mrg     }
     89          1.1  mrg 
     90          1.1  mrg   /* a must have at least as many low zero bits as d */
     91          1.1  mrg   dmask = LOW_ZEROS_MASK (dlow);
     92          1.1  mrg   if ((alow & dmask) != 0)
     93          1.1  mrg     return 0;
     94          1.1  mrg 
     95          1.1  mrg   if (dn == 1)
     96          1.1  mrg     {
     97          1.1  mrg       if (ABOVE_THRESHOLD (an, BMOD_1_TO_MOD_1_THRESHOLD))
     98          1.1  mrg 	return mpn_mod_1 (ap, an, dlow) == 0;
     99          1.1  mrg 
    100          1.1  mrg       count_trailing_zeros (twos, dlow);
    101          1.1  mrg       dlow >>= twos;
    102          1.1  mrg       return mpn_modexact_1_odd (ap, an, dlow) == 0;
    103          1.1  mrg     }
    104          1.1  mrg 
    105          1.1  mrg   if (dn == 2)
    106          1.1  mrg     {
    107          1.1  mrg       mp_limb_t  dsecond = dp[1];
    108          1.1  mrg       if (dsecond <= dmask)
    109          1.1  mrg 	{
    110          1.1  mrg 	  count_trailing_zeros (twos, dlow);
    111          1.1  mrg 	  dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos));
    112          1.1  mrg 	  ASSERT_LIMB (dlow);
    113          1.1  mrg 	  return MPN_MOD_OR_MODEXACT_1_ODD (ap, an, dlow) == 0;
    114          1.1  mrg 	}
    115          1.1  mrg     }
    116          1.1  mrg 
    117          1.1  mrg   /* Should we compute Q = A * D^(-1) mod B^k,
    118          1.1  mrg                        R = A - Q * D  mod B^k
    119          1.1  mrg      here, for some small values of k?  Then check if R = 0 (mod B^k).  */
    120          1.1  mrg 
    121          1.1  mrg   /* We could also compute A' = A mod T and D' = D mod P, for some
    122          1.1  mrg      P = 3 * 5 * 7 * 11 ..., and then check if any prime factor from P
    123          1.1  mrg      dividing D' also divides A'.  */
    124          1.1  mrg 
    125          1.1  mrg   TMP_MARK;
    126          1.1  mrg 
    127          1.1  mrg   rp = TMP_ALLOC_LIMBS (an + 1);
    128  1.1.1.1.8.1  tls   qp = TMP_ALLOC_LIMBS (an - dn + 1); /* FIXME: Could we avoid this? */
    129          1.1  mrg 
    130          1.1  mrg   count_trailing_zeros (twos, dp[0]);
    131          1.1  mrg 
    132          1.1  mrg   if (twos != 0)
    133          1.1  mrg     {
    134          1.1  mrg       tp = TMP_ALLOC_LIMBS (dn);
    135          1.1  mrg       ASSERT_NOCARRY (mpn_rshift (tp, dp, dn, twos));
    136          1.1  mrg       dp = tp;
    137          1.1  mrg 
    138          1.1  mrg       ASSERT_NOCARRY (mpn_rshift (rp, ap, an, twos));
    139          1.1  mrg     }
    140          1.1  mrg   else
    141          1.1  mrg     {
    142          1.1  mrg       MPN_COPY (rp, ap, an);
    143          1.1  mrg     }
    144          1.1  mrg   if (rp[an - 1] >= dp[dn - 1])
    145          1.1  mrg     {
    146          1.1  mrg       rp[an] = 0;
    147          1.1  mrg       an++;
    148          1.1  mrg     }
    149          1.1  mrg   else if (an == dn)
    150          1.1  mrg     {
    151          1.1  mrg       TMP_FREE;
    152          1.1  mrg       return 0;
    153          1.1  mrg     }
    154          1.1  mrg 
    155          1.1  mrg   ASSERT (an > dn);		/* requirement of functions below */
    156          1.1  mrg 
    157          1.1  mrg   if (BELOW_THRESHOLD (dn, DC_BDIV_QR_THRESHOLD) ||
    158          1.1  mrg       BELOW_THRESHOLD (an - dn, DC_BDIV_QR_THRESHOLD))
    159          1.1  mrg     {
    160          1.1  mrg       binvert_limb (di, dp[0]);
    161          1.1  mrg       mpn_sbpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
    162          1.1  mrg       rp += an - dn;
    163          1.1  mrg     }
    164          1.1  mrg   else if (BELOW_THRESHOLD (dn, MU_BDIV_QR_THRESHOLD))
    165          1.1  mrg     {
    166          1.1  mrg       binvert_limb (di, dp[0]);
    167          1.1  mrg       mpn_dcpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
    168          1.1  mrg       rp += an - dn;
    169          1.1  mrg     }
    170          1.1  mrg   else
    171          1.1  mrg     {
    172          1.1  mrg       tp = TMP_ALLOC_LIMBS (mpn_mu_bdiv_qr_itch (an, dn));
    173          1.1  mrg       mpn_mu_bdiv_qr (qp, rp, rp, an, dp, dn, tp);
    174          1.1  mrg     }
    175          1.1  mrg 
    176          1.1  mrg   /* test for {rp,dn} zero or non-zero */
    177          1.1  mrg   i = 0;
    178          1.1  mrg   do
    179          1.1  mrg     {
    180          1.1  mrg       if (rp[i] != 0)
    181          1.1  mrg 	{
    182          1.1  mrg 	  TMP_FREE;
    183          1.1  mrg 	  return 0;
    184          1.1  mrg 	}
    185          1.1  mrg     }
    186          1.1  mrg   while (++i < dn);
    187          1.1  mrg 
    188          1.1  mrg   TMP_FREE;
    189          1.1  mrg   return 1;
    190          1.1  mrg }
    191