[BACK]Return to divrem_2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / generic

Diff for /OpenXM_contrib/gmp/mpn/generic/Attic/divrem_2.c between version 1.1 and 1.1.1.2

version 1.1, 2000/09/09 14:12:24 version 1.1.1.2, 2003/08/25 16:06:20
Line 7 
Line 7 
    RELEASE.     RELEASE.
   
   
 Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000 Free Software Foundation,  Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
 Inc.  Foundation, Inc.
   
 This file is part of the GNU MP Library.  This file is part of the GNU MP Library.
   
Line 31  MA 02111-1307, USA. */
Line 31  MA 02111-1307, USA. */
 #include "gmp-impl.h"  #include "gmp-impl.h"
 #include "longlong.h"  #include "longlong.h"
   
   
   /* The size where udiv_qrnnd_preinv should be used rather than udiv_qrnnd,
      meaning the quotient size where that should happen, the quotient size
      being how many udiv divisions will be done.
   
      The default is to use preinv always, CPUs where this doesn't suit have
      tuned thresholds.  Note in particular that preinv should certainly be
      used if that's the only division available (USE_PREINV_ALWAYS).  */
   
   #ifndef DIVREM_2_THRESHOLD
   #define DIVREM_2_THRESHOLD  0
   #endif
   
   
 /* Divide num (NP/NSIZE) by den (DP/2) and write  /* Divide num (NP/NSIZE) by den (DP/2) and write
    the NSIZE-2 least significant quotient limbs at QP     the NSIZE-2 least significant quotient limbs at QP
    and the 2 long remainder at NP.  If QEXTRA_LIMBS is     and the 2 long remainder at NP.  If QEXTRA_LIMBS is
Line 48  MA 02111-1307, USA. */
Line 62  MA 02111-1307, USA. */
    3. NSIZE >= 2, even if QEXTRA_LIMBS is non-zero.  */     3. NSIZE >= 2, even if QEXTRA_LIMBS is non-zero.  */
   
 mp_limb_t  mp_limb_t
 #if __STDC__  
 mpn_divrem_2 (mp_ptr qp, mp_size_t qxn,  mpn_divrem_2 (mp_ptr qp, mp_size_t qxn,
               mp_ptr np, mp_size_t nsize,                mp_ptr np, mp_size_t nn,
               mp_srcptr dp)                mp_srcptr dp)
 #else  
 mpn_divrem_2 (qp, qxn, np, nsize, dp)  
      mp_ptr qp;  
      mp_size_t qxn;  
      mp_ptr np;  
      mp_size_t nsize;  
      mp_srcptr dp;  
 #endif  
 {  {
   mp_limb_t most_significant_q_limb = 0;    mp_limb_t most_significant_q_limb = 0;
   mp_size_t i;    mp_size_t i;
   mp_limb_t n1, n0, n2;    mp_limb_t n1, n0, n2;
   mp_limb_t d1, d0;    mp_limb_t d1, d0;
   mp_limb_t d1inv;    mp_limb_t d1inv;
   int have_preinv;    int use_preinv;
   
   np += nsize - 2;    ASSERT (nn >= 2);
     ASSERT (qxn >= 0);
     ASSERT (dp[1] & GMP_NUMB_HIGHBIT);
     ASSERT (! MPN_OVERLAP_P (qp, nn-2+qxn, np, nn) || qp+2 >= np);
     ASSERT_MPN (np, nn);
     ASSERT_MPN (dp, 2);
   
     np += nn - 2;
   d1 = dp[1];    d1 = dp[1];
   d0 = dp[0];    d0 = dp[0];
   n1 = np[1];    n1 = np[1];
Line 76  mpn_divrem_2 (qp, qxn, np, nsize, dp)
Line 88  mpn_divrem_2 (qp, qxn, np, nsize, dp)
   
   if (n1 >= d1 && (n1 > d1 || n0 >= d0))    if (n1 >= d1 && (n1 > d1 || n0 >= d0))
     {      {
   #if GMP_NAIL_BITS == 0
       sub_ddmmss (n1, n0, n1, n0, d1, d0);        sub_ddmmss (n1, n0, n1, n0, d1, d0);
   #else
         n0 = n0 - d0;
         n1 = n1 - d1 - (n0 >> GMP_LIMB_BITS - 1);
         n0 &= GMP_NUMB_MASK;
   #endif
       most_significant_q_limb = 1;        most_significant_q_limb = 1;
     }      }
   
   /* If multiplication is much faster than division, preinvert the most    use_preinv = ABOVE_THRESHOLD (qxn + nn - 2, DIVREM_2_THRESHOLD);
      significant divisor limb before entering the loop.  */    if (use_preinv)
   if (UDIV_TIME > 2 * UMUL_TIME + 6)      invert_limb (d1inv, d1);
     {  
       have_preinv = 0;  
       if ((UDIV_TIME - (2 * UMUL_TIME + 6)) * (nsize - 2) > UDIV_TIME)  
         {  
           invert_limb (d1inv, d1);  
           have_preinv = 1;  
         }  
     }  
   
   for (i = qxn + nsize - 2 - 1; i >= 0; i--)    for (i = qxn + nn - 2 - 1; i >= 0; i--)
     {      {
       mp_limb_t q;        mp_limb_t q;
       mp_limb_t r;        mp_limb_t r;
Line 104  mpn_divrem_2 (qp, qxn, np, nsize, dp)
Line 114  mpn_divrem_2 (qp, qxn, np, nsize, dp)
   
       if (n1 == d1)        if (n1 == d1)
         {          {
           /* Q should be either 111..111 or 111..110.  Need special treatment            /* Q should be either 111..111 or 111..110.  Need special handling
              of this rare case as normal division would give overflow.  */               of this rare case as normal division would give overflow.  */
           q = ~(mp_limb_t) 0;            q = GMP_NUMB_MASK;
   
           r = n0 + d1;            r = (n0 + d1) & GMP_NUMB_MASK;
           if (r < d1)   /* Carry in the addition? */            if (r < d1)   /* Carry in the addition? */
             {              {
   #if GMP_NAIL_BITS == 0
               add_ssaaaa (n1, n0, r - d0, np[0], 0, d0);                add_ssaaaa (n1, n0, r - d0, np[0], 0, d0);
   #else
                 n0 = np[0] + d0;
                 n1 = (r - d0 + (n0 >> GMP_NUMB_BITS)) & GMP_NUMB_MASK;
                 n0 &= GMP_NUMB_MASK;
   #endif
               qp[i] = q;                qp[i] = q;
               continue;                continue;
             }              }
           n1 = d0 - (d0 != 0);            n1 = d0 - (d0 != 0);
           n0 = -d0;            n0 = -d0 & GMP_NUMB_MASK;
         }          }
       else        else
         {          {
           if (UDIV_TIME > 2 * UMUL_TIME + 6 && have_preinv)            if (use_preinv)
             udiv_qrnnd_preinv (q, r, n1, n0, d1, d1inv);              udiv_qrnnd_preinv (q, r, n1, n0, d1, d1inv);
           else            else
             udiv_qrnnd (q, r, n1, n0, d1);              udiv_qrnnd (q, r, n1, n0 << GMP_NAIL_BITS, d1 << GMP_NAIL_BITS);
           umul_ppmm (n1, n0, d0, q);            r >>= GMP_NAIL_BITS;
             umul_ppmm (n1, n0, d0, q << GMP_NAIL_BITS);
             n0 >>= GMP_NAIL_BITS;
         }          }
   
       n2 = np[0];        n2 = np[0];
Line 135  mpn_divrem_2 (qp, qxn, np, nsize, dp)
Line 153  mpn_divrem_2 (qp, qxn, np, nsize, dp)
           /* The estimated Q was too large.  */            /* The estimated Q was too large.  */
           q--;            q--;
   
   #if GMP_NAIL_BITS == 0
           sub_ddmmss (n1, n0, n1, n0, 0, d0);            sub_ddmmss (n1, n0, n1, n0, 0, d0);
   #else
             n0 = n0 - d0;
             n1 = n1 - (n0 >> GMP_LIMB_BITS - 1);
             n0 &= GMP_NUMB_MASK;
   #endif
           r += d1;            r += d1;
           if (r >= d1)  /* If not carry, test Q again.  */            if (r >= d1)  /* If not carry, test Q again.  */
             goto q_test;              goto q_test;
         }          }
   
       qp[i] = q;        qp[i] = q;
   #if GMP_NAIL_BITS == 0
       sub_ddmmss (n1, n0, r, n2, n1, n0);        sub_ddmmss (n1, n0, r, n2, n1, n0);
   #else
         n0 = n2 - n0;
         n1 = r - n1 - (n0 >> GMP_LIMB_BITS - 1);
         n0 &= GMP_NUMB_MASK;
   #endif
     }      }
   np[1] = n1;    np[1] = n1;
   np[0] = n0;    np[0] = n0;

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.1.2

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>