div_q.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:10k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. /* mpn_div_q -- division for arbitrary size operands.
  2.    Contributed to the GNU project by Torbjorn Granlund.
  3.    THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
  4.    SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
  5.    GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
  6. Copyright 2009, 2010 Free Software Foundation, Inc.
  7. This file is part of the GNU MP Library.
  8. The GNU MP Library is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU Lesser General Public License as published by
  10. the Free Software Foundation; either version 3 of the License, or (at your
  11. option) any later version.
  12. The GNU MP Library is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14. or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  15. License for more details.
  16. You should have received a copy of the GNU Lesser General Public License
  17. along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
  18. #include "gmp.h"
  19. #include "gmp-impl.h"
  20. #include "longlong.h"
  21. /* Compute Q = N/D with truncation.
  22.      N = {np,nn}
  23.      D = {dp,dn}
  24.      Q = {qp,nn-dn+1}
  25.      T = {scratch,nn+1} is scratch space
  26.    N and D are both untouched by the computation.
  27.    N and T may overlap; pass the same space if N is irrelevant after the call,
  28.    but note that tp needs an extra limb.
  29.    Operand requirements:
  30.      N >= D > 0
  31.      dp[dn-1] != 0
  32.      No overlap between the N, D, and Q areas.
  33.    This division function does not clobber its input operands, since it is
  34.    intended to support average-O(qn) division, and for that to be effective, it
  35.    cannot put requirements on callers to copy a O(nn) operand.
  36.    If a caller does not care about the value of {np,nn+1} after calling this
  37.    function, it should pass np also for the scratch argument.  This function
  38.    will then save some time and space by avoiding allocation and copying.
  39.    (FIXME: Is this a good design?  We only really save any copying for
  40.    already-normalised divisors, which should be rare.  It also prevents us from
  41.    reasonably asking for all scratch space we need.)
  42.    We write nn-dn+1 limbs for the quotient, but return void.  Why not return
  43.    the most significant quotient limb?  Look at the 4 main code blocks below
  44.    (consisting of an outer if-else where each arm contains an if-else). It is
  45.    tricky for the first code block, since the mpn_*_div_q calls will typically
  46.    generate all nn-dn+1 and return 0 or 1.  I don't see how to fix that unless
  47.    we generate the most significant quotient limb here, before calling
  48.    mpn_*_div_q, or put the quotient in a temporary area.  Since this is a
  49.    critical division case (the SB sub-case in particular) copying is not a good
  50.    idea.
  51.    It might make sense to split the if-else parts of the (qn + FUDGE
  52.    >= dn) blocks into separate functions, since we could promise quite
  53.    different things to callers in these two cases.  The 'then' case
  54.    benefits from np=scratch, and it could perhaps even tolerate qp=np,
  55.    saving some headache for many callers.
  56.    FIXME: Scratch allocation leaves a lot to be desired.  E.g., for the MU size
  57.    operands, we do not reuse the huge scratch for adjustments.  This can be a
  58.    serious waste of memory for the largest operands.
  59. */
  60. /* FUDGE determines when to try getting an approximate quotient from the upper
  61.    parts of the dividend and divisor, then adjust.  N.B. FUDGE must be >= 2
  62.    for the code to be correct.  */
  63. #define FUDGE 5 /* FIXME: tune this */
  64. #define DC_DIV_Q_THRESHOLD      DC_DIVAPPR_Q_THRESHOLD
  65. #define MU_DIV_Q_THRESHOLD      MU_DIVAPPR_Q_THRESHOLD
  66. #define MUPI_DIV_Q_THRESHOLD  MUPI_DIVAPPR_Q_THRESHOLD
  67. #ifndef MUPI_DIVAPPR_Q_THRESHOLD
  68. #define MUPI_DIVAPPR_Q_THRESHOLD  MUPI_DIV_QR_THRESHOLD
  69. #endif
  70. void
  71. mpn_div_q (mp_ptr qp,
  72.    mp_srcptr np, mp_size_t nn,
  73.    mp_srcptr dp, mp_size_t dn, mp_ptr scratch)
  74. {
  75.   mp_ptr new_dp, new_np, tp, rp;
  76.   mp_limb_t cy, dh, qh;
  77.   mp_size_t new_nn, qn;
  78.   gmp_pi1_t dinv;
  79.   int cnt;
  80.   TMP_DECL;
  81.   TMP_MARK;
  82.   ASSERT (nn >= dn);
  83.   ASSERT (dn > 0);
  84.   ASSERT (dp[dn - 1] != 0);
  85.   ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1, np, nn));
  86.   ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1, dp, dn));
  87.   ASSERT (MPN_SAME_OR_SEPARATE_P (np, scratch, nn));
  88.   ASSERT_ALWAYS (FUDGE >= 2);
  89.   if (dn == 1)
  90.     {
  91.       mpn_divrem_1 (qp, 0L, np, nn, dp[dn - 1]);
  92.       return;
  93.     }
  94.   qn = nn - dn + 1; /* Quotient size, high limb might be zero */
  95.   if (qn + FUDGE >= dn)
  96.     {
  97.       /* |________________________|
  98.                           |_______|  */
  99.       new_np = scratch;
  100.       dh = dp[dn - 1];
  101.       if (LIKELY ((dh & GMP_NUMB_HIGHBIT) == 0))
  102. {
  103.   count_leading_zeros (cnt, dh);
  104.   cy = mpn_lshift (new_np, np, nn, cnt);
  105.   new_np[nn] = cy;
  106.   new_nn = nn + (cy != 0);
  107.   new_dp = TMP_ALLOC_LIMBS (dn);
  108.   mpn_lshift (new_dp, dp, dn, cnt);
  109.   if (dn == 2)
  110.     {
  111.       qh = mpn_divrem_2 (qp, 0L, new_np, new_nn, new_dp);
  112.     }
  113.   else if (BELOW_THRESHOLD (dn, DC_DIV_Q_THRESHOLD) ||
  114.    BELOW_THRESHOLD (new_nn - dn, DC_DIV_Q_THRESHOLD))
  115.     {
  116.       invert_pi1 (dinv, new_dp[dn - 1], new_dp[dn - 2]);
  117.       qh = mpn_sbpi1_div_q (qp, new_np, new_nn, new_dp, dn, dinv.inv32);
  118.     }
  119.   else if (BELOW_THRESHOLD (dn, MUPI_DIV_Q_THRESHOLD) ||   /* fast condition */
  120.    BELOW_THRESHOLD (nn, 2 * MU_DIV_Q_THRESHOLD) || /* fast condition */
  121.    (double) (2 * (MU_DIV_Q_THRESHOLD - MUPI_DIV_Q_THRESHOLD)) * dn /* slow... */
  122.    + (double) MUPI_DIV_Q_THRESHOLD * nn > (double) dn * nn)   /* ...condition */
  123.     {
  124.       invert_pi1 (dinv, new_dp[dn - 1], new_dp[dn - 2]);
  125.       qh = mpn_dcpi1_div_q (qp, new_np, new_nn, new_dp, dn, &dinv);
  126.     }
  127.   else
  128.     {
  129.       mp_size_t itch = mpn_mu_div_q_itch (new_nn, dn, 0);
  130.       mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
  131.       qh = mpn_mu_div_q (qp, new_np, new_nn, new_dp, dn, scratch);
  132.     }
  133.   if (cy == 0)
  134.     qp[qn - 1] = qh;
  135.   else if (UNLIKELY (qh != 0))
  136.     {
  137.       /* This happens only when the quotient is close to B^n and
  138.  mpn_*_divappr_q returned B^n.  */
  139.       mp_size_t i, n;
  140.       n = new_nn - dn;
  141.       for (i = 0; i < n; i++)
  142. qp[i] = GMP_NUMB_MAX;
  143.       qh = 0; /* currently ignored */
  144.     }
  145. }
  146.       else  /* divisor is already normalised */
  147. {
  148.   if (new_np != np)
  149.     MPN_COPY (new_np, np, nn);
  150.   if (dn == 2)
  151.     {
  152.       qh = mpn_divrem_2 (qp, 0L, new_np, nn, dp);
  153.     }
  154.   else if (BELOW_THRESHOLD (dn, DC_DIV_Q_THRESHOLD) ||
  155.    BELOW_THRESHOLD (nn - dn, DC_DIV_Q_THRESHOLD))
  156.     {
  157.       invert_pi1 (dinv, dh, dp[dn - 2]);
  158.       qh = mpn_sbpi1_div_q (qp, new_np, nn, dp, dn, dinv.inv32);
  159.     }
  160.   else if (BELOW_THRESHOLD (dn, MUPI_DIV_Q_THRESHOLD) ||   /* fast condition */
  161.    BELOW_THRESHOLD (nn, 2 * MU_DIV_Q_THRESHOLD) || /* fast condition */
  162.    (double) (2 * (MU_DIV_Q_THRESHOLD - MUPI_DIV_Q_THRESHOLD)) * dn /* slow... */
  163.    + (double) MUPI_DIV_Q_THRESHOLD * nn > (double) dn * nn)   /* ...condition */
  164.     {
  165.       invert_pi1 (dinv, dh, dp[dn - 2]);
  166.       qh = mpn_dcpi1_div_q (qp, new_np, nn, dp, dn, &dinv);
  167.     }
  168.   else
  169.     {
  170.       mp_size_t itch = mpn_mu_div_q_itch (nn, dn, 0);
  171.       mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
  172.       qh = mpn_mu_div_q (qp, np, nn, dp, dn, scratch);
  173.     }
  174.   qp[nn - dn] = qh;
  175. }
  176.     }
  177.   else
  178.     {
  179.       /* |________________________|
  180.                 |_________________|  */
  181.       tp = TMP_ALLOC_LIMBS (qn + 1);
  182.       new_np = scratch;
  183.       new_nn = 2 * qn + 1;
  184.       if (new_np == np)
  185. /* We need {np,nn} to remain untouched until the final adjustment, so
  186.    we need to allocate separate space for new_np.  */
  187. new_np = TMP_ALLOC_LIMBS (new_nn + 1);
  188.       dh = dp[dn - 1];
  189.       if (LIKELY ((dh & GMP_NUMB_HIGHBIT) == 0))
  190. {
  191.   count_leading_zeros (cnt, dh);
  192.   cy = mpn_lshift (new_np, np + nn - new_nn, new_nn, cnt);
  193.   new_np[new_nn] = cy;
  194.   new_nn += (cy != 0);
  195.   new_dp = TMP_ALLOC_LIMBS (qn + 1);
  196.   mpn_lshift (new_dp, dp + dn - (qn + 1), qn + 1, cnt);
  197.   new_dp[0] |= dp[dn - (qn + 1) - 1] >> (GMP_NUMB_BITS - cnt);
  198.   if (qn + 1 == 2)
  199.     {
  200.       qh = mpn_divrem_2 (tp, 0L, new_np, new_nn, new_dp);
  201.     }
  202.   else if (BELOW_THRESHOLD (qn, DC_DIVAPPR_Q_THRESHOLD - 1))
  203.     {
  204.       invert_pi1 (dinv, new_dp[qn], new_dp[qn - 1]);
  205.       qh = mpn_sbpi1_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, dinv.inv32);
  206.     }
  207.   else if (BELOW_THRESHOLD (qn, MU_DIVAPPR_Q_THRESHOLD - 1))
  208.     {
  209.       invert_pi1 (dinv, new_dp[qn], new_dp[qn - 1]);
  210.       qh = mpn_dcpi1_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, &dinv);
  211.     }
  212.   else
  213.     {
  214.       mp_size_t itch = mpn_mu_divappr_q_itch (new_nn, qn + 1, 0);
  215.       mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
  216.       qh = mpn_mu_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, scratch);
  217.     }
  218.   if (cy == 0)
  219.     tp[qn] = qh;
  220.   else if (UNLIKELY (qh != 0))
  221.     {
  222.       /* This happens only when the quotient is close to B^n and
  223.  mpn_*_divappr_q returned B^n.  */
  224.       mp_size_t i, n;
  225.       n = new_nn - (qn + 1);
  226.       for (i = 0; i < n; i++)
  227. tp[i] = GMP_NUMB_MAX;
  228.       qh = 0; /* currently ignored */
  229.     }
  230. }
  231.       else  /* divisor is already normalised */
  232. {
  233.   MPN_COPY (new_np, np + nn - new_nn, new_nn); /* pointless of MU will be used */
  234.   new_dp = (mp_ptr) dp + dn - (qn + 1);
  235.   if (qn == 2 - 1)
  236.     {
  237.       qh = mpn_divrem_2 (tp, 0L, new_np, new_nn, new_dp);
  238.     }
  239.   else if (BELOW_THRESHOLD (qn, DC_DIVAPPR_Q_THRESHOLD - 1))
  240.     {
  241.       invert_pi1 (dinv, dh, new_dp[qn - 1]);
  242.       qh = mpn_sbpi1_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, dinv.inv32);
  243.     }
  244.   else if (BELOW_THRESHOLD (qn, MU_DIVAPPR_Q_THRESHOLD - 1))
  245.     {
  246.       invert_pi1 (dinv, dh, new_dp[qn - 1]);
  247.       qh = mpn_dcpi1_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, &dinv);
  248.     }
  249.   else
  250.     {
  251.       mp_size_t itch = mpn_mu_divappr_q_itch (new_nn, qn + 1, 0);
  252.       mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
  253.       qh = mpn_mu_divappr_q (tp, new_np, new_nn, new_dp, qn + 1, scratch);
  254.     }
  255.   tp[qn] = qh;
  256. }
  257.       MPN_COPY (qp, tp + 1, qn);
  258.       if (tp[0] <= 4)
  259.         {
  260.   mp_size_t rn;
  261.           rp = TMP_ALLOC_LIMBS (dn + qn);
  262.           mpn_mul (rp, dp, dn, tp + 1, qn);
  263.   rn = dn + qn;
  264.   rn -= rp[rn - 1] == 0;
  265.           if (rn > nn || mpn_cmp (np, rp, nn) < 0)
  266.             mpn_decr_u (qp, 1);
  267.         }
  268.     }
  269.   TMP_FREE;
  270. }