github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/generic/tdiv_qr.c (about)

     1  /* mpn_tdiv_qr -- Divide the numerator (np,nn) by the denominator (dp,dn) and
     2     write the nn-dn+1 quotient limbs at qp and the dn remainder limbs at rp.  If
     3     qxn is non-zero, generate that many fraction limbs and append them after the
     4     other quotient limbs, and update the remainder accordingly.  The input
     5     operands are unaffected.
     6  
     7     Preconditions:
     8     1. The most significant limb of of the divisor must be non-zero.
     9     2. nn >= dn, even if qxn is non-zero.  (??? relax this ???)
    10  
    11     The time complexity of this is O(qn*qn+M(dn,qn)), where M(m,n) is the time
    12     complexity of multiplication.
    13  
    14  Copyright 1997, 2000-2002, 2005, 2009 Free Software Foundation, Inc.
    15  
    16  This file is part of the GNU MP Library.
    17  
    18  The GNU MP Library is free software; you can redistribute it and/or modify
    19  it under the terms of either:
    20  
    21    * the GNU Lesser General Public License as published by the Free
    22      Software Foundation; either version 3 of the License, or (at your
    23      option) any later version.
    24  
    25  or
    26  
    27    * the GNU General Public License as published by the Free Software
    28      Foundation; either version 2 of the License, or (at your option) any
    29      later version.
    30  
    31  or both in parallel, as here.
    32  
    33  The GNU MP Library is distributed in the hope that it will be useful, but
    34  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    35  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    36  for more details.
    37  
    38  You should have received copies of the GNU General Public License and the
    39  GNU Lesser General Public License along with the GNU MP Library.  If not,
    40  see https://www.gnu.org/licenses/.  */
    41  
    42  #include "gmp.h"
    43  #include "gmp-impl.h"
    44  #include "longlong.h"
    45  
    46  
    47  void
    48  mpn_tdiv_qr (mp_ptr qp, mp_ptr rp, mp_size_t qxn,
    49  	     mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
    50  {
    51    ASSERT_ALWAYS (qxn == 0);
    52  
    53    ASSERT (nn >= 0);
    54    ASSERT (dn >= 0);
    55    ASSERT (dn == 0 || dp[dn - 1] != 0);
    56    ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, np, nn));
    57    ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, dp, dn));
    58  
    59    switch (dn)
    60      {
    61      case 0:
    62        DIVIDE_BY_ZERO;
    63  
    64      case 1:
    65        {
    66  	rp[0] = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, dp[0]);
    67  	return;
    68        }
    69  
    70      case 2:
    71        {
    72  	mp_ptr n2p, d2p;
    73  	mp_limb_t qhl, cy;
    74  	TMP_DECL;
    75  	TMP_MARK;
    76  	if ((dp[1] & GMP_NUMB_HIGHBIT) == 0)
    77  	  {
    78  	    int cnt;
    79  	    mp_limb_t dtmp[2];
    80  	    count_leading_zeros (cnt, dp[1]);
    81  	    cnt -= GMP_NAIL_BITS;
    82  	    d2p = dtmp;
    83  	    d2p[1] = (dp[1] << cnt) | (dp[0] >> (GMP_NUMB_BITS - cnt));
    84  	    d2p[0] = (dp[0] << cnt) & GMP_NUMB_MASK;
    85  	    n2p = TMP_ALLOC_LIMBS (nn + 1);
    86  	    cy = mpn_lshift (n2p, np, nn, cnt);
    87  	    n2p[nn] = cy;
    88  	    qhl = mpn_divrem_2 (qp, 0L, n2p, nn + (cy != 0), d2p);
    89  	    if (cy == 0)
    90  	      qp[nn - 2] = qhl;	/* always store nn-2+1 quotient limbs */
    91  	    rp[0] = (n2p[0] >> cnt)
    92  	      | ((n2p[1] << (GMP_NUMB_BITS - cnt)) & GMP_NUMB_MASK);
    93  	    rp[1] = (n2p[1] >> cnt);
    94  	  }
    95  	else
    96  	  {
    97  	    d2p = (mp_ptr) dp;
    98  	    n2p = TMP_ALLOC_LIMBS (nn);
    99  	    MPN_COPY (n2p, np, nn);
   100  	    qhl = mpn_divrem_2 (qp, 0L, n2p, nn, d2p);
   101  	    qp[nn - 2] = qhl;	/* always store nn-2+1 quotient limbs */
   102  	    rp[0] = n2p[0];
   103  	    rp[1] = n2p[1];
   104  	  }
   105  	TMP_FREE;
   106  	return;
   107        }
   108  
   109      default:
   110        {
   111  	int adjust;
   112  	gmp_pi1_t dinv;
   113  	TMP_DECL;
   114  	TMP_MARK;
   115  	adjust = np[nn - 1] >= dp[dn - 1];	/* conservative tests for quotient size */
   116  	if (nn + adjust >= 2 * dn)
   117  	  {
   118  	    mp_ptr n2p, d2p;
   119  	    mp_limb_t cy;
   120  	    int cnt;
   121  
   122  	    qp[nn - dn] = 0;			  /* zero high quotient limb */
   123  	    if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0) /* normalize divisor */
   124  	      {
   125  		count_leading_zeros (cnt, dp[dn - 1]);
   126  		cnt -= GMP_NAIL_BITS;
   127  		d2p = TMP_ALLOC_LIMBS (dn);
   128  		mpn_lshift (d2p, dp, dn, cnt);
   129  		n2p = TMP_ALLOC_LIMBS (nn + 1);
   130  		cy = mpn_lshift (n2p, np, nn, cnt);
   131  		n2p[nn] = cy;
   132  		nn += adjust;
   133  	      }
   134  	    else
   135  	      {
   136  		cnt = 0;
   137  		d2p = (mp_ptr) dp;
   138  		n2p = TMP_ALLOC_LIMBS (nn + 1);
   139  		MPN_COPY (n2p, np, nn);
   140  		n2p[nn] = 0;
   141  		nn += adjust;
   142  	      }
   143  
   144  	    invert_pi1 (dinv, d2p[dn - 1], d2p[dn - 2]);
   145  	    if (BELOW_THRESHOLD (dn, DC_DIV_QR_THRESHOLD))
   146  	      mpn_sbpi1_div_qr (qp, n2p, nn, d2p, dn, dinv.inv32);
   147  	    else if (BELOW_THRESHOLD (dn, MUPI_DIV_QR_THRESHOLD) ||   /* fast condition */
   148  		     BELOW_THRESHOLD (nn, 2 * MU_DIV_QR_THRESHOLD) || /* fast condition */
   149  		     (double) (2 * (MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD)) * dn /* slow... */
   150  		     + (double) MUPI_DIV_QR_THRESHOLD * nn > (double) dn * nn)    /* ...condition */
   151  	      mpn_dcpi1_div_qr (qp, n2p, nn, d2p, dn, &dinv);
   152  	    else
   153  	      {
   154  		mp_size_t itch = mpn_mu_div_qr_itch (nn, dn, 0);
   155  		mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
   156  		mpn_mu_div_qr (qp, rp, n2p, nn, d2p, dn, scratch);
   157  		n2p = rp;
   158  	      }
   159  
   160  	    if (cnt != 0)
   161  	      mpn_rshift (rp, n2p, dn, cnt);
   162  	    else
   163  	      MPN_COPY (rp, n2p, dn);
   164  	    TMP_FREE;
   165  	    return;
   166  	  }
   167  
   168  	/* When we come here, the numerator/partial remainder is less
   169  	   than twice the size of the denominator.  */
   170  
   171  	  {
   172  	    /* Problem:
   173  
   174  	       Divide a numerator N with nn limbs by a denominator D with dn
   175  	       limbs forming a quotient of qn=nn-dn+1 limbs.  When qn is small
   176  	       compared to dn, conventional division algorithms perform poorly.
   177  	       We want an algorithm that has an expected running time that is
   178  	       dependent only on qn.
   179  
   180  	       Algorithm (very informally stated):
   181  
   182  	       1) Divide the 2 x qn most significant limbs from the numerator
   183  		  by the qn most significant limbs from the denominator.  Call
   184  		  the result qest.  This is either the correct quotient, but
   185  		  might be 1 or 2 too large.  Compute the remainder from the
   186  		  division.  (This step is implemented by an mpn_divrem call.)
   187  
   188  	       2) Is the most significant limb from the remainder < p, where p
   189  		  is the product of the most significant limb from the quotient
   190  		  and the next(d)?  (Next(d) denotes the next ignored limb from
   191  		  the denominator.)  If it is, decrement qest, and adjust the
   192  		  remainder accordingly.
   193  
   194  	       3) Is the remainder >= qest?  If it is, qest is the desired
   195  		  quotient.  The algorithm terminates.
   196  
   197  	       4) Subtract qest x next(d) from the remainder.  If there is
   198  		  borrow out, decrement qest, and adjust the remainder
   199  		  accordingly.
   200  
   201  	       5) Skip one word from the denominator (i.e., let next(d) denote
   202  		  the next less significant limb.  */
   203  
   204  	    mp_size_t qn;
   205  	    mp_ptr n2p, d2p;
   206  	    mp_ptr tp;
   207  	    mp_limb_t cy;
   208  	    mp_size_t in, rn;
   209  	    mp_limb_t quotient_too_large;
   210  	    unsigned int cnt;
   211  
   212  	    qn = nn - dn;
   213  	    qp[qn] = 0;				/* zero high quotient limb */
   214  	    qn += adjust;			/* qn cannot become bigger */
   215  
   216  	    if (qn == 0)
   217  	      {
   218  		MPN_COPY (rp, np, dn);
   219  		TMP_FREE;
   220  		return;
   221  	      }
   222  
   223  	    in = dn - qn;		/* (at least partially) ignored # of limbs in ops */
   224  	    /* Normalize denominator by shifting it to the left such that its
   225  	       most significant bit is set.  Then shift the numerator the same
   226  	       amount, to mathematically preserve quotient.  */
   227  	    if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0)
   228  	      {
   229  		count_leading_zeros (cnt, dp[dn - 1]);
   230  		cnt -= GMP_NAIL_BITS;
   231  
   232  		d2p = TMP_ALLOC_LIMBS (qn);
   233  		mpn_lshift (d2p, dp + in, qn, cnt);
   234  		d2p[0] |= dp[in - 1] >> (GMP_NUMB_BITS - cnt);
   235  
   236  		n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
   237  		cy = mpn_lshift (n2p, np + nn - 2 * qn, 2 * qn, cnt);
   238  		if (adjust)
   239  		  {
   240  		    n2p[2 * qn] = cy;
   241  		    n2p++;
   242  		  }
   243  		else
   244  		  {
   245  		    n2p[0] |= np[nn - 2 * qn - 1] >> (GMP_NUMB_BITS - cnt);
   246  		  }
   247  	      }
   248  	    else
   249  	      {
   250  		cnt = 0;
   251  		d2p = (mp_ptr) dp + in;
   252  
   253  		n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
   254  		MPN_COPY (n2p, np + nn - 2 * qn, 2 * qn);
   255  		if (adjust)
   256  		  {
   257  		    n2p[2 * qn] = 0;
   258  		    n2p++;
   259  		  }
   260  	      }
   261  
   262  	    /* Get an approximate quotient using the extracted operands.  */
   263  	    if (qn == 1)
   264  	      {
   265  		mp_limb_t q0, r0;
   266  		udiv_qrnnd (q0, r0, n2p[1], n2p[0] << GMP_NAIL_BITS, d2p[0] << GMP_NAIL_BITS);
   267  		n2p[0] = r0 >> GMP_NAIL_BITS;
   268  		qp[0] = q0;
   269  	      }
   270  	    else if (qn == 2)
   271  	      mpn_divrem_2 (qp, 0L, n2p, 4L, d2p); /* FIXME: obsolete function */
   272  	    else
   273  	      {
   274  		invert_pi1 (dinv, d2p[qn - 1], d2p[qn - 2]);
   275  		if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
   276  		  mpn_sbpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, dinv.inv32);
   277  		else if (BELOW_THRESHOLD (qn, MU_DIV_QR_THRESHOLD))
   278  		  mpn_dcpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, &dinv);
   279  		else
   280  		  {
   281  		    mp_size_t itch = mpn_mu_div_qr_itch (2 * qn, qn, 0);
   282  		    mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
   283  		    mp_ptr r2p = rp;
   284  		    if (np == r2p)	/* If N and R share space, put ... */
   285  		      r2p += nn - qn;	/* intermediate remainder at N's upper end. */
   286  		    mpn_mu_div_qr (qp, r2p, n2p, 2 * qn, d2p, qn, scratch);
   287  		    MPN_COPY (n2p, r2p, qn);
   288  		  }
   289  	      }
   290  
   291  	    rn = qn;
   292  	    /* Multiply the first ignored divisor limb by the most significant
   293  	       quotient limb.  If that product is > the partial remainder's
   294  	       most significant limb, we know the quotient is too large.  This
   295  	       test quickly catches most cases where the quotient is too large;
   296  	       it catches all cases where the quotient is 2 too large.  */
   297  	    {
   298  	      mp_limb_t dl, x;
   299  	      mp_limb_t h, dummy;
   300  
   301  	      if (in - 2 < 0)
   302  		dl = 0;
   303  	      else
   304  		dl = dp[in - 2];
   305  
   306  #if GMP_NAIL_BITS == 0
   307  	      x = (dp[in - 1] << cnt) | ((dl >> 1) >> ((~cnt) % GMP_LIMB_BITS));
   308  #else
   309  	      x = (dp[in - 1] << cnt) & GMP_NUMB_MASK;
   310  	      if (cnt != 0)
   311  		x |= dl >> (GMP_NUMB_BITS - cnt);
   312  #endif
   313  	      umul_ppmm (h, dummy, x, qp[qn - 1] << GMP_NAIL_BITS);
   314  
   315  	      if (n2p[qn - 1] < h)
   316  		{
   317  		  mp_limb_t cy;
   318  
   319  		  mpn_decr_u (qp, (mp_limb_t) 1);
   320  		  cy = mpn_add_n (n2p, n2p, d2p, qn);
   321  		  if (cy)
   322  		    {
   323  		      /* The partial remainder is safely large.  */
   324  		      n2p[qn] = cy;
   325  		      ++rn;
   326  		    }
   327  		}
   328  	    }
   329  
   330  	    quotient_too_large = 0;
   331  	    if (cnt != 0)
   332  	      {
   333  		mp_limb_t cy1, cy2;
   334  
   335  		/* Append partially used numerator limb to partial remainder.  */
   336  		cy1 = mpn_lshift (n2p, n2p, rn, GMP_NUMB_BITS - cnt);
   337  		n2p[0] |= np[in - 1] & (GMP_NUMB_MASK >> cnt);
   338  
   339  		/* Update partial remainder with partially used divisor limb.  */
   340  		cy2 = mpn_submul_1 (n2p, qp, qn, dp[in - 1] & (GMP_NUMB_MASK >> cnt));
   341  		if (qn != rn)
   342  		  {
   343  		    ASSERT_ALWAYS (n2p[qn] >= cy2);
   344  		    n2p[qn] -= cy2;
   345  		  }
   346  		else
   347  		  {
   348  		    n2p[qn] = cy1 - cy2; /* & GMP_NUMB_MASK; */
   349  
   350  		    quotient_too_large = (cy1 < cy2);
   351  		    ++rn;
   352  		  }
   353  		--in;
   354  	      }
   355  	    /* True: partial remainder now is neutral, i.e., it is not shifted up.  */
   356  
   357  	    tp = TMP_ALLOC_LIMBS (dn);
   358  
   359  	    if (in < qn)
   360  	      {
   361  		if (in == 0)
   362  		  {
   363  		    MPN_COPY (rp, n2p, rn);
   364  		    ASSERT_ALWAYS (rn == dn);
   365  		    goto foo;
   366  		  }
   367  		mpn_mul (tp, qp, qn, dp, in);
   368  	      }
   369  	    else
   370  	      mpn_mul (tp, dp, in, qp, qn);
   371  
   372  	    cy = mpn_sub (n2p, n2p, rn, tp + in, qn);
   373  	    MPN_COPY (rp + in, n2p, dn - in);
   374  	    quotient_too_large |= cy;
   375  	    cy = mpn_sub_n (rp, np, tp, in);
   376  	    cy = mpn_sub_1 (rp + in, rp + in, rn, cy);
   377  	    quotient_too_large |= cy;
   378  	  foo:
   379  	    if (quotient_too_large)
   380  	      {
   381  		mpn_decr_u (qp, (mp_limb_t) 1);
   382  		mpn_add_n (rp, rp, dp, dn);
   383  	      }
   384  	  }
   385  	TMP_FREE;
   386  	return;
   387        }
   388      }
   389  }