Home | History | Annotate | Line # | Download | only in generic
divis.c revision 1.1.1.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  mrg /* Determine whether {ap,an} is divisible by {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  mrg    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  mrg    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  mrg    When d must be normalized (shifted to high bit set), it's possible to
     45  1.1  mrg    just append a low zero limb to "a" rather than bit-shifting as
     46  1.1  mrg    mpn_tdiv_qr does internally, so long as it's already been checked that a
     47  1.1  mrg    has at least as many trailing zeros bits as d.  Or equivalently, pass
     48  1.1  mrg    qxn==1 to mpn_tdiv_qr, if/when it accepts that.  */
     49  1.1  mrg 
     50  1.1  mrg int
     51  1.1  mrg mpn_divisible_p (mp_srcptr ap, mp_size_t an,
     52  1.1  mrg 		 mp_srcptr dp, mp_size_t dn)
     53  1.1  mrg {
     54  1.1  mrg   mp_limb_t  alow, dlow, dmask;
     55  1.1  mrg   mp_ptr     qp, rp, tp;
     56  1.1  mrg   mp_size_t  i;
     57  1.1  mrg   mp_limb_t di;
     58  1.1  mrg   unsigned  twos;
     59  1.1  mrg   TMP_DECL;
     60  1.1  mrg 
     61  1.1  mrg   ASSERT (an >= 0);
     62  1.1  mrg   ASSERT (an == 0 || ap[an-1] != 0);
     63  1.1  mrg   ASSERT (dn >= 1);
     64  1.1  mrg   ASSERT (dp[dn-1] != 0);
     65  1.1  mrg   ASSERT_MPN (ap, an);
     66  1.1  mrg   ASSERT_MPN (dp, dn);
     67  1.1  mrg 
     68  1.1  mrg   /* When a<d only a==0 is divisible.
     69  1.1  mrg      Notice this test covers all cases of an==0. */
     70  1.1  mrg   if (an < dn)
     71  1.1  mrg     return (an == 0);
     72  1.1  mrg 
     73  1.1  mrg   /* Strip low zero limbs from d, requiring a==0 on those. */
     74  1.1  mrg   for (;;)
     75  1.1  mrg     {
     76  1.1  mrg       alow = *ap;
     77  1.1  mrg       dlow = *dp;
     78  1.1  mrg 
     79  1.1  mrg       if (dlow != 0)
     80  1.1  mrg 	break;
     81  1.1  mrg 
     82  1.1  mrg       if (alow != 0)
     83  1.1  mrg 	return 0;  /* a has fewer low zero limbs than d, so not divisible */
     84  1.1  mrg 
     85  1.1  mrg       /* a!=0 and d!=0 so won't get to n==0 */
     86  1.1  mrg       an--; ASSERT (an >= 1);
     87  1.1  mrg       dn--; ASSERT (dn >= 1);
     88  1.1  mrg       ap++;
     89  1.1  mrg       dp++;
     90  1.1  mrg     }
     91  1.1  mrg 
     92  1.1  mrg   /* a must have at least as many low zero bits as d */
     93  1.1  mrg   dmask = LOW_ZEROS_MASK (dlow);
     94  1.1  mrg   if ((alow & dmask) != 0)
     95  1.1  mrg     return 0;
     96  1.1  mrg 
     97  1.1  mrg   if (dn == 1)
     98  1.1  mrg     {
     99  1.1  mrg       if (ABOVE_THRESHOLD (an, BMOD_1_TO_MOD_1_THRESHOLD))
    100  1.1  mrg 	return mpn_mod_1 (ap, an, dlow) == 0;
    101  1.1  mrg 
    102  1.1  mrg       count_trailing_zeros (twos, dlow);
    103  1.1  mrg       dlow >>= twos;
    104  1.1  mrg       return mpn_modexact_1_odd (ap, an, dlow) == 0;
    105  1.1  mrg     }
    106  1.1  mrg 
    107  1.1  mrg   if (dn == 2)
    108  1.1  mrg     {
    109  1.1  mrg       mp_limb_t  dsecond = dp[1];
    110  1.1  mrg       if (dsecond <= dmask)
    111  1.1  mrg 	{
    112  1.1  mrg 	  count_trailing_zeros (twos, dlow);
    113  1.1  mrg 	  dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos));
    114  1.1  mrg 	  ASSERT_LIMB (dlow);
    115  1.1  mrg 	  return MPN_MOD_OR_MODEXACT_1_ODD (ap, an, dlow) == 0;
    116  1.1  mrg 	}
    117  1.1  mrg     }
    118  1.1  mrg 
    119  1.1  mrg   /* Should we compute Q = A * D^(-1) mod B^k,
    120  1.1  mrg                        R = A - Q * D  mod B^k
    121  1.1  mrg      here, for some small values of k?  Then check if R = 0 (mod B^k).  */
    122  1.1  mrg 
    123  1.1  mrg   /* We could also compute A' = A mod T and D' = D mod P, for some
    124  1.1  mrg      P = 3 * 5 * 7 * 11 ..., and then check if any prime factor from P
    125  1.1  mrg      dividing D' also divides A'.  */
    126  1.1  mrg 
    127  1.1  mrg   TMP_MARK;
    128  1.1  mrg 
    129  1.1  mrg   rp = TMP_ALLOC_LIMBS (an + 1);
    130  1.1  mrg   qp = TMP_ALLOC_LIMBS (an - dn + 1); /* FIXME: Could we avoid this */
    131  1.1  mrg 
    132  1.1  mrg   count_trailing_zeros (twos, dp[0]);
    133  1.1  mrg 
    134  1.1  mrg   if (twos != 0)
    135  1.1  mrg     {
    136  1.1  mrg       tp = TMP_ALLOC_LIMBS (dn);
    137  1.1  mrg       ASSERT_NOCARRY (mpn_rshift (tp, dp, dn, twos));
    138  1.1  mrg       dp = tp;
    139  1.1  mrg 
    140  1.1  mrg       ASSERT_NOCARRY (mpn_rshift (rp, ap, an, twos));
    141  1.1  mrg     }
    142  1.1  mrg   else
    143  1.1  mrg     {
    144  1.1  mrg       MPN_COPY (rp, ap, an);
    145  1.1  mrg     }
    146  1.1  mrg   if (rp[an - 1] >= dp[dn - 1])
    147  1.1  mrg     {
    148  1.1  mrg       rp[an] = 0;
    149  1.1  mrg       an++;
    150  1.1  mrg     }
    151  1.1  mrg   else if (an == dn)
    152  1.1  mrg     {
    153  1.1  mrg       TMP_FREE;
    154  1.1  mrg       return 0;
    155  1.1  mrg     }
    156  1.1  mrg 
    157  1.1  mrg   ASSERT (an > dn);		/* requirement of functions below */
    158  1.1  mrg 
    159  1.1  mrg   if (BELOW_THRESHOLD (dn, DC_BDIV_QR_THRESHOLD) ||
    160  1.1  mrg       BELOW_THRESHOLD (an - dn, DC_BDIV_QR_THRESHOLD))
    161  1.1  mrg     {
    162  1.1  mrg       binvert_limb (di, dp[0]);
    163  1.1  mrg       mpn_sbpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
    164  1.1  mrg       rp += an - dn;
    165  1.1  mrg     }
    166  1.1  mrg   else if (BELOW_THRESHOLD (dn, MU_BDIV_QR_THRESHOLD))
    167  1.1  mrg     {
    168  1.1  mrg       binvert_limb (di, dp[0]);
    169  1.1  mrg       mpn_dcpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
    170  1.1  mrg       rp += an - dn;
    171  1.1  mrg     }
    172  1.1  mrg   else
    173  1.1  mrg     {
    174  1.1  mrg       tp = TMP_ALLOC_LIMBS (mpn_mu_bdiv_qr_itch (an, dn));
    175  1.1  mrg       mpn_mu_bdiv_qr (qp, rp, rp, an, dp, dn, tp);
    176  1.1  mrg     }
    177  1.1  mrg 
    178  1.1  mrg   /* test for {rp,dn} zero or non-zero */
    179  1.1  mrg   i = 0;
    180  1.1  mrg   do
    181  1.1  mrg     {
    182  1.1  mrg       if (rp[i] != 0)
    183  1.1  mrg 	{
    184  1.1  mrg 	  TMP_FREE;
    185  1.1  mrg 	  return 0;
    186  1.1  mrg 	}
    187  1.1  mrg     }
    188  1.1  mrg   while (++i < dn);
    189  1.1  mrg 
    190  1.1  mrg   TMP_FREE;
    191  1.1  mrg   return 1;
    192  1.1  mrg }
    193