Home | History | Annotate | Line # | Download | only in generic
remove.c revision 1.1.1.1
      1  1.1  mrg /* mpn_remove -- divide out all multiples of odd mpn number from another mpn
      2  1.1  mrg    number.
      3  1.1  mrg 
      4  1.1  mrg    Contributed to the GNU project by Torbjorn Granlund.
      5  1.1  mrg 
      6  1.1  mrg    THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
      7  1.1  mrg    SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
      8  1.1  mrg    GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
      9  1.1  mrg 
     10  1.1  mrg Copyright 2009 Free Software Foundation, Inc.
     11  1.1  mrg 
     12  1.1  mrg This file is part of the GNU MP Library.
     13  1.1  mrg 
     14  1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     15  1.1  mrg it under the terms of the GNU Lesser General Public License as published by
     16  1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     17  1.1  mrg option) any later version.
     18  1.1  mrg 
     19  1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     20  1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     21  1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     22  1.1  mrg License for more details.
     23  1.1  mrg 
     24  1.1  mrg You should have received a copy of the GNU Lesser General Public License
     25  1.1  mrg along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     26  1.1  mrg 
     27  1.1  mrg #include "gmp.h"
     28  1.1  mrg #include "gmp-impl.h"
     29  1.1  mrg 
     30  1.1  mrg #if GMP_LIMB_BITS > 50
     31  1.1  mrg #define LOG 50
     32  1.1  mrg #else
     33  1.1  mrg #define LOG GMP_LIMB_BITS
     34  1.1  mrg #endif
     35  1.1  mrg 
     36  1.1  mrg 
     37  1.1  mrg /* Input: U = {up,un}, V = {vp,vn} must be odd, cap
     38  1.1  mrg    Ouput  W = {wp,*wn} allocation need is exactly *wn
     39  1.1  mrg 
     40  1.1  mrg    Set W = U / V^k, where k is the largest integer <= cap such that the
     41  1.1  mrg    division yields an integer.
     42  1.1  mrg 
     43  1.1  mrg    FIXME: We currently allow any operand overlap.  This is quite non mpn-ish
     44  1.1  mrg    and might be changed, since it cost significant temporary space.
     45  1.1  mrg    * If we require W to have space for un limbs, we could save qp or qp2 (but
     46  1.1  mrg      we will still need to copy things into wp 50% of the time).
     47  1.1  mrg    * If we allow ourselves to clobber U, we could save the other of qp and qp2.
     48  1.1  mrg */
     49  1.1  mrg 
     50  1.1  mrg mp_bitcnt_t
     51  1.1  mrg mpn_remove (mp_ptr wp, mp_size_t *wn,
     52  1.1  mrg 	    mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn,
     53  1.1  mrg 	    mp_bitcnt_t cap)
     54  1.1  mrg {
     55  1.1  mrg   mp_ptr    pwpsp[LOG];
     56  1.1  mrg   mp_size_t pwpsn[LOG];
     57  1.1  mrg   mp_size_t npowers;
     58  1.1  mrg   mp_ptr tp, qp, np, pp, qp2, scratch_out;
     59  1.1  mrg   mp_size_t pn, nn, qn, i;
     60  1.1  mrg   mp_bitcnt_t pwr;
     61  1.1  mrg   TMP_DECL;
     62  1.1  mrg 
     63  1.1  mrg   ASSERT (un > 0);
     64  1.1  mrg   ASSERT (vn > 0);
     65  1.1  mrg   ASSERT (vp[0] % 2 != 0);	/* 2-adic division wants odd numbers */
     66  1.1  mrg   ASSERT (vn > 1 || vp[0] > 1);	/* else we would loop indefinitely */
     67  1.1  mrg 
     68  1.1  mrg   TMP_MARK;
     69  1.1  mrg 
     70  1.1  mrg   tp = TMP_ALLOC_LIMBS ((un + vn) / 2); /* remainder */
     71  1.1  mrg   qp = TMP_ALLOC_LIMBS (un);		/* quotient, alternating */
     72  1.1  mrg   qp2 = TMP_ALLOC_LIMBS (un);		/* quotient, alternating */
     73  1.1  mrg   np = TMP_ALLOC_LIMBS (un + LOG);	/* powers of V */
     74  1.1  mrg   pp = vp;
     75  1.1  mrg   pn = vn;
     76  1.1  mrg 
     77  1.1  mrg   /* FIXME: This allocation need indicate a flaw in the current itch mechanism:
     78  1.1  mrg      Which operands not greater than un,un will incur the worst itch?  We need
     79  1.1  mrg      a parallel foo_maxitch set of functions.  */
     80  1.1  mrg   scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (un, un >> 1));
     81  1.1  mrg 
     82  1.1  mrg   MPN_COPY (qp, up, un);
     83  1.1  mrg   qn = un;
     84  1.1  mrg 
     85  1.1  mrg   npowers = 0;
     86  1.1  mrg   while (qn >= pn)
     87  1.1  mrg     {
     88  1.1  mrg       mpn_bdiv_qr (qp2, tp, qp, qn, pp, pn, scratch_out);
     89  1.1  mrg       if (!mpn_zero_p (tp, pn))
     90  1.1  mrg 	break;			/* could not divide by V^npowers */
     91  1.1  mrg 
     92  1.1  mrg       MP_PTR_SWAP (qp, qp2);
     93  1.1  mrg       qn = qn - pn;
     94  1.1  mrg       qn += qp[qn] != 0;
     95  1.1  mrg 
     96  1.1  mrg       pwpsp[npowers] = pp;
     97  1.1  mrg       pwpsn[npowers] = pn;
     98  1.1  mrg       npowers++;
     99  1.1  mrg 
    100  1.1  mrg       if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
    101  1.1  mrg 	break;
    102  1.1  mrg 
    103  1.1  mrg       nn = 2 * pn - 1;		/* next power will be at least this many limbs */
    104  1.1  mrg       if (nn > qn)
    105  1.1  mrg 	break;			/* next power would be overlarge */
    106  1.1  mrg 
    107  1.1  mrg       mpn_sqr (np, pp, pn);
    108  1.1  mrg       nn += np[nn] != 0;
    109  1.1  mrg       pp = np;
    110  1.1  mrg       pn = nn;
    111  1.1  mrg       np += nn;
    112  1.1  mrg     }
    113  1.1  mrg 
    114  1.1  mrg   pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
    115  1.1  mrg 
    116  1.1  mrg   for (i = npowers - 1; i >= 0; i--)
    117  1.1  mrg     {
    118  1.1  mrg       pp = pwpsp[i];
    119  1.1  mrg       pn = pwpsn[i];
    120  1.1  mrg       if (qn < pn)
    121  1.1  mrg 	continue;
    122  1.1  mrg 
    123  1.1  mrg       if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
    124  1.1  mrg 	continue;		/* V^i would bring us past cap */
    125  1.1  mrg 
    126  1.1  mrg       mpn_bdiv_qr (qp2, tp, qp, qn, pp, pn, scratch_out);
    127  1.1  mrg       if (!mpn_zero_p (tp, pn))
    128  1.1  mrg 	continue;		/* could not divide by V^i */
    129  1.1  mrg 
    130  1.1  mrg       MP_PTR_SWAP (qp, qp2);
    131  1.1  mrg       qn = qn - pn;
    132  1.1  mrg       qn += qp[qn] != 0;
    133  1.1  mrg 
    134  1.1  mrg       pwr += (mp_bitcnt_t) 1 << i;
    135  1.1  mrg     }
    136  1.1  mrg 
    137  1.1  mrg   MPN_COPY (wp, qp, qn);
    138  1.1  mrg   *wn = qn;
    139  1.1  mrg 
    140  1.1  mrg   TMP_FREE;
    141  1.1  mrg 
    142  1.1  mrg   return pwr;
    143  1.1  mrg }
    144