Home | History | Annotate | Line # | Download | only in generic
      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.4  mrg Copyright 2009, 2012-2014, 2017 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.1.3  mrg it under the terms of either:
     16  1.1.1.3  mrg 
     17  1.1.1.3  mrg   * the GNU Lesser General Public License as published by the Free
     18  1.1.1.3  mrg     Software Foundation; either version 3 of the License, or (at your
     19  1.1.1.3  mrg     option) any later version.
     20  1.1.1.3  mrg 
     21  1.1.1.3  mrg or
     22  1.1.1.3  mrg 
     23  1.1.1.3  mrg   * the GNU General Public License as published by the Free Software
     24  1.1.1.3  mrg     Foundation; either version 2 of the License, or (at your option) any
     25  1.1.1.3  mrg     later version.
     26  1.1.1.3  mrg 
     27  1.1.1.3  mrg or both in parallel, as here.
     28      1.1  mrg 
     29      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     30      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     31  1.1.1.3  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     32  1.1.1.3  mrg for more details.
     33      1.1  mrg 
     34  1.1.1.3  mrg You should have received copies of the GNU General Public License and the
     35  1.1.1.3  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     36  1.1.1.3  mrg see https://www.gnu.org/licenses/.  */
     37      1.1  mrg 
     38      1.1  mrg #include "gmp-impl.h"
     39      1.1  mrg 
     40      1.1  mrg #if GMP_LIMB_BITS > 50
     41      1.1  mrg #define LOG 50
     42      1.1  mrg #else
     43      1.1  mrg #define LOG GMP_LIMB_BITS
     44      1.1  mrg #endif
     45      1.1  mrg 
     46      1.1  mrg 
     47      1.1  mrg /* Input: U = {up,un}, V = {vp,vn} must be odd, cap
     48      1.1  mrg    Ouput  W = {wp,*wn} allocation need is exactly *wn
     49      1.1  mrg 
     50      1.1  mrg    Set W = U / V^k, where k is the largest integer <= cap such that the
     51      1.1  mrg    division yields an integer.
     52      1.1  mrg 
     53      1.1  mrg    FIXME: We currently allow any operand overlap.  This is quite non mpn-ish
     54      1.1  mrg    and might be changed, since it cost significant temporary space.
     55  1.1.1.3  mrg    * If we require W to have space for un + 1 limbs, we could save qp or qp2
     56  1.1.1.3  mrg      (but we will still need to copy things into wp 50% of the time).
     57  1.1.1.3  mrg    * If we allow ourselves to clobber U, we could save the other of qp and qp2,
     58  1.1.1.3  mrg      and the initial COPY (but also here we would need un + 1 limbs).
     59      1.1  mrg */
     60      1.1  mrg 
     61  1.1.1.2  mrg /* FIXME: We need to wrap mpn_bdiv_qr due to the itch interface.  This need
     62  1.1.1.2  mrg    indicates a flaw in the current itch mechanism: Which operands not greater
     63  1.1.1.2  mrg    than un,un will incur the worst itch?  We need a parallel foo_maxitch set
     64  1.1.1.2  mrg    of functions.  */
     65  1.1.1.2  mrg static void
     66  1.1.1.2  mrg mpn_bdiv_qr_wrap (mp_ptr qp, mp_ptr rp,
     67  1.1.1.2  mrg 		  mp_srcptr np, mp_size_t nn,
     68  1.1.1.2  mrg 		  mp_srcptr dp, mp_size_t dn)
     69  1.1.1.2  mrg {
     70  1.1.1.2  mrg   mp_ptr scratch_out;
     71  1.1.1.2  mrg   TMP_DECL;
     72  1.1.1.2  mrg 
     73  1.1.1.2  mrg   TMP_MARK;
     74  1.1.1.2  mrg   scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (nn, dn));
     75  1.1.1.2  mrg   mpn_bdiv_qr (qp, rp, np, nn, dp, dn, scratch_out);
     76  1.1.1.2  mrg 
     77  1.1.1.2  mrg   TMP_FREE;
     78  1.1.1.2  mrg }
     79  1.1.1.2  mrg 
     80      1.1  mrg mp_bitcnt_t
     81      1.1  mrg mpn_remove (mp_ptr wp, mp_size_t *wn,
     82  1.1.1.3  mrg 	    mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn,
     83      1.1  mrg 	    mp_bitcnt_t cap)
     84      1.1  mrg {
     85  1.1.1.3  mrg   mp_srcptr pwpsp[LOG];
     86      1.1  mrg   mp_size_t pwpsn[LOG];
     87      1.1  mrg   mp_size_t npowers;
     88  1.1.1.3  mrg   mp_ptr tp, qp, np, qp2;
     89  1.1.1.3  mrg   mp_srcptr pp;
     90      1.1  mrg   mp_size_t pn, nn, qn, i;
     91      1.1  mrg   mp_bitcnt_t pwr;
     92      1.1  mrg   TMP_DECL;
     93      1.1  mrg 
     94      1.1  mrg   ASSERT (un > 0);
     95      1.1  mrg   ASSERT (vn > 0);
     96      1.1  mrg   ASSERT (vp[0] % 2 != 0);	/* 2-adic division wants odd numbers */
     97      1.1  mrg   ASSERT (vn > 1 || vp[0] > 1);	/* else we would loop indefinitely */
     98      1.1  mrg 
     99      1.1  mrg   TMP_MARK;
    100      1.1  mrg 
    101  1.1.1.3  mrg   TMP_ALLOC_LIMBS_3 (qp, un + 1,	/* quotient, alternating */
    102  1.1.1.3  mrg 		     qp2, un + 1,	/* quotient, alternating */
    103  1.1.1.3  mrg 		     tp, (un + 1 + vn) / 2); /* remainder */
    104      1.1  mrg   pp = vp;
    105      1.1  mrg   pn = vn;
    106      1.1  mrg 
    107      1.1  mrg   MPN_COPY (qp, up, un);
    108      1.1  mrg   qn = un;
    109      1.1  mrg 
    110      1.1  mrg   npowers = 0;
    111      1.1  mrg   while (qn >= pn)
    112      1.1  mrg     {
    113  1.1.1.2  mrg       qp[qn] = 0;
    114  1.1.1.2  mrg       mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
    115      1.1  mrg       if (!mpn_zero_p (tp, pn))
    116  1.1.1.4  mrg 	{
    117  1.1.1.4  mrg 	  if (mpn_cmp (tp, pp, pn) != 0)
    118  1.1.1.4  mrg 	    break;		/* could not divide by V^npowers */
    119  1.1.1.4  mrg 	}
    120      1.1  mrg 
    121      1.1  mrg       MP_PTR_SWAP (qp, qp2);
    122      1.1  mrg       qn = qn - pn;
    123  1.1.1.4  mrg       mpn_neg (qp, qp, qn+1);
    124  1.1.1.4  mrg 
    125      1.1  mrg       qn += qp[qn] != 0;
    126      1.1  mrg 
    127      1.1  mrg       pwpsp[npowers] = pp;
    128      1.1  mrg       pwpsn[npowers] = pn;
    129  1.1.1.3  mrg       ++npowers;
    130      1.1  mrg 
    131      1.1  mrg       if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
    132      1.1  mrg 	break;
    133      1.1  mrg 
    134  1.1.1.2  mrg       nn = 2 * pn - 1;		/* next power will be at least this large */
    135      1.1  mrg       if (nn > qn)
    136      1.1  mrg 	break;			/* next power would be overlarge */
    137      1.1  mrg 
    138  1.1.1.3  mrg       if (npowers == 1)		/* Alloc once, but only if it's needed */
    139  1.1.1.3  mrg 	np = TMP_ALLOC_LIMBS (qn + LOG);	/* powers of V */
    140  1.1.1.3  mrg       else
    141  1.1.1.3  mrg 	np += pn;
    142  1.1.1.3  mrg 
    143      1.1  mrg       mpn_sqr (np, pp, pn);
    144  1.1.1.3  mrg       pn = nn + (np[nn] != 0);
    145      1.1  mrg       pp = np;
    146      1.1  mrg     }
    147      1.1  mrg 
    148      1.1  mrg   pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
    149      1.1  mrg 
    150  1.1.1.3  mrg   for (i = npowers; --i >= 0;)
    151      1.1  mrg     {
    152      1.1  mrg       pn = pwpsn[i];
    153      1.1  mrg       if (qn < pn)
    154      1.1  mrg 	continue;
    155      1.1  mrg 
    156      1.1  mrg       if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
    157      1.1  mrg 	continue;		/* V^i would bring us past cap */
    158      1.1  mrg 
    159  1.1.1.2  mrg       qp[qn] = 0;
    160  1.1.1.3  mrg       mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pwpsp[i], pn);
    161      1.1  mrg       if (!mpn_zero_p (tp, pn))
    162  1.1.1.4  mrg 	{
    163  1.1.1.4  mrg 	  if (mpn_cmp (tp, pwpsp[i], pn) != 0)
    164  1.1.1.4  mrg 	    continue;		/* could not divide by V^i */
    165  1.1.1.4  mrg 	}
    166      1.1  mrg 
    167      1.1  mrg       MP_PTR_SWAP (qp, qp2);
    168      1.1  mrg       qn = qn - pn;
    169  1.1.1.4  mrg       mpn_neg (qp, qp, qn+1);
    170  1.1.1.4  mrg 
    171      1.1  mrg       qn += qp[qn] != 0;
    172      1.1  mrg 
    173      1.1  mrg       pwr += (mp_bitcnt_t) 1 << i;
    174      1.1  mrg     }
    175      1.1  mrg 
    176      1.1  mrg   MPN_COPY (wp, qp, qn);
    177      1.1  mrg   *wn = qn;
    178      1.1  mrg 
    179      1.1  mrg   TMP_FREE;
    180      1.1  mrg 
    181      1.1  mrg   return pwr;
    182      1.1  mrg }
    183