Home | History | Annotate | Line # | Download | only in generic
remove.c revision 1.1.1.2
      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.1.2  mrg Copyright 2009, 2012 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.1.2  mrg /* FIXME: We need to wrap mpn_bdiv_qr due to the itch interface.  This need
     51  1.1.1.2  mrg    indicates a flaw in the current itch mechanism: Which operands not greater
     52  1.1.1.2  mrg    than un,un will incur the worst itch?  We need a parallel foo_maxitch set
     53  1.1.1.2  mrg    of functions.  */
     54  1.1.1.2  mrg static void
     55  1.1.1.2  mrg mpn_bdiv_qr_wrap (mp_ptr qp, mp_ptr rp,
     56  1.1.1.2  mrg 		  mp_srcptr np, mp_size_t nn,
     57  1.1.1.2  mrg 		  mp_srcptr dp, mp_size_t dn)
     58  1.1.1.2  mrg {
     59  1.1.1.2  mrg   mp_ptr scratch_out;
     60  1.1.1.2  mrg   TMP_DECL;
     61  1.1.1.2  mrg 
     62  1.1.1.2  mrg   TMP_MARK;
     63  1.1.1.2  mrg   scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (nn, dn));
     64  1.1.1.2  mrg   mpn_bdiv_qr (qp, rp, np, nn, dp, dn, scratch_out);
     65  1.1.1.2  mrg 
     66  1.1.1.2  mrg   TMP_FREE;
     67  1.1.1.2  mrg }
     68  1.1.1.2  mrg 
     69      1.1  mrg mp_bitcnt_t
     70      1.1  mrg mpn_remove (mp_ptr wp, mp_size_t *wn,
     71      1.1  mrg 	    mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn,
     72      1.1  mrg 	    mp_bitcnt_t cap)
     73      1.1  mrg {
     74      1.1  mrg   mp_ptr    pwpsp[LOG];
     75      1.1  mrg   mp_size_t pwpsn[LOG];
     76      1.1  mrg   mp_size_t npowers;
     77  1.1.1.2  mrg   mp_ptr tp, qp, np, pp, qp2;
     78      1.1  mrg   mp_size_t pn, nn, qn, i;
     79      1.1  mrg   mp_bitcnt_t pwr;
     80      1.1  mrg   TMP_DECL;
     81      1.1  mrg 
     82      1.1  mrg   ASSERT (un > 0);
     83      1.1  mrg   ASSERT (vn > 0);
     84      1.1  mrg   ASSERT (vp[0] % 2 != 0);	/* 2-adic division wants odd numbers */
     85      1.1  mrg   ASSERT (vn > 1 || vp[0] > 1);	/* else we would loop indefinitely */
     86      1.1  mrg 
     87      1.1  mrg   TMP_MARK;
     88      1.1  mrg 
     89  1.1.1.2  mrg   tp = TMP_ALLOC_LIMBS ((un + 1 + vn) / 2); /* remainder */
     90  1.1.1.2  mrg   qp = TMP_ALLOC_LIMBS (un + 1);	/* quotient, alternating */
     91  1.1.1.2  mrg   qp2 = TMP_ALLOC_LIMBS (un + 1);	/* quotient, alternating */
     92      1.1  mrg   np = TMP_ALLOC_LIMBS (un + LOG);	/* powers of V */
     93      1.1  mrg   pp = vp;
     94      1.1  mrg   pn = vn;
     95      1.1  mrg 
     96      1.1  mrg   MPN_COPY (qp, up, un);
     97      1.1  mrg   qn = un;
     98      1.1  mrg 
     99      1.1  mrg   npowers = 0;
    100      1.1  mrg   while (qn >= pn)
    101      1.1  mrg     {
    102  1.1.1.2  mrg       qp[qn] = 0;
    103  1.1.1.2  mrg       mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
    104      1.1  mrg       if (!mpn_zero_p (tp, pn))
    105      1.1  mrg 	break;			/* could not divide by V^npowers */
    106      1.1  mrg 
    107      1.1  mrg       MP_PTR_SWAP (qp, qp2);
    108      1.1  mrg       qn = qn - pn;
    109      1.1  mrg       qn += qp[qn] != 0;
    110      1.1  mrg 
    111      1.1  mrg       pwpsp[npowers] = pp;
    112      1.1  mrg       pwpsn[npowers] = pn;
    113      1.1  mrg       npowers++;
    114      1.1  mrg 
    115      1.1  mrg       if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
    116      1.1  mrg 	break;
    117      1.1  mrg 
    118  1.1.1.2  mrg       nn = 2 * pn - 1;		/* next power will be at least this large */
    119      1.1  mrg       if (nn > qn)
    120      1.1  mrg 	break;			/* next power would be overlarge */
    121      1.1  mrg 
    122      1.1  mrg       mpn_sqr (np, pp, pn);
    123      1.1  mrg       nn += np[nn] != 0;
    124      1.1  mrg       pp = np;
    125      1.1  mrg       pn = nn;
    126      1.1  mrg       np += nn;
    127      1.1  mrg     }
    128      1.1  mrg 
    129      1.1  mrg   pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
    130      1.1  mrg 
    131      1.1  mrg   for (i = npowers - 1; i >= 0; i--)
    132      1.1  mrg     {
    133      1.1  mrg       pp = pwpsp[i];
    134      1.1  mrg       pn = pwpsn[i];
    135      1.1  mrg       if (qn < pn)
    136      1.1  mrg 	continue;
    137      1.1  mrg 
    138      1.1  mrg       if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
    139      1.1  mrg 	continue;		/* V^i would bring us past cap */
    140      1.1  mrg 
    141  1.1.1.2  mrg       qp[qn] = 0;
    142  1.1.1.2  mrg       mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
    143      1.1  mrg       if (!mpn_zero_p (tp, pn))
    144      1.1  mrg 	continue;		/* could not divide by V^i */
    145      1.1  mrg 
    146      1.1  mrg       MP_PTR_SWAP (qp, qp2);
    147      1.1  mrg       qn = qn - pn;
    148      1.1  mrg       qn += qp[qn] != 0;
    149      1.1  mrg 
    150      1.1  mrg       pwr += (mp_bitcnt_t) 1 << i;
    151      1.1  mrg     }
    152      1.1  mrg 
    153      1.1  mrg   MPN_COPY (wp, qp, qn);
    154      1.1  mrg   *wn = qn;
    155      1.1  mrg 
    156      1.1  mrg   TMP_FREE;
    157      1.1  mrg 
    158      1.1  mrg   return pwr;
    159      1.1  mrg }
    160