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

Annotation of OpenXM_contrib/gmp/mpn/generic/tdiv_qr.c, Revision 1.1.1.1

1.1       maekawa     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 accordningly.  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. No argument overlap is permitted.  (??? relax this ???)
                     10:    3. nn >= dn, even if qxn is non-zero.  (??? relax this ???)
                     11:
                     12:    The time complexity of this is O(qn*qn+M(dn,qn)), where M(m,n) is the time
                     13:    complexity of multiplication.
                     14:
                     15: Copyright (C) 1997, 2000 Free Software Foundation, Inc.
                     16:
                     17: This file is part of the GNU MP Library.
                     18:
                     19: The GNU MP Library is free software; you can redistribute it and/or modify
                     20: it under the terms of the GNU Lesser General Public License as published by
                     21: the Free Software Foundation; either version 2.1 of the License, or (at your
                     22: option) any later version.
                     23:
                     24: The GNU MP Library is distributed in the hope that it will be useful, but
                     25: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     26: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     27: License for more details.
                     28:
                     29: You should have received a copy of the GNU Lesser General Public License
                     30: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     31: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     32: MA 02111-1307, USA. */
                     33:
                     34: #include "gmp.h"
                     35: #include "gmp-impl.h"
                     36: #include "longlong.h"
                     37:
                     38: #ifndef BZ_THRESHOLD
                     39: #define BZ_THRESHOLD (7 * KARATSUBA_MUL_THRESHOLD)
                     40: #endif
                     41:
                     42: /* Extract the middle limb from ((h,,l) << cnt) */
                     43: #define SHL(h,l,cnt) \
                     44:   ((h << cnt) | ((l >> 1) >> ((~cnt) & (BITS_PER_MP_LIMB - 1))))
                     45:
                     46: void
                     47: #if __STDC__
                     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: #else
                     51: mpn_tdiv_qr (qp, rp, qxn, np, nn, dp, dn)
                     52:      mp_ptr qp;
                     53:      mp_ptr rp;
                     54:      mp_size_t qxn;
                     55:      mp_srcptr np;
                     56:      mp_size_t nn;
                     57:      mp_srcptr dp;
                     58:      mp_size_t dn;
                     59: #endif
                     60: {
                     61:   /* FIXME:
                     62:      1. qxn
                     63:      2. pass allocated storage in additional parameter?
                     64:   */
                     65:   if (qxn != 0)
                     66:     abort ();
                     67:
                     68:   switch (dn)
                     69:     {
                     70:     case 0:
                     71:       DIVIDE_BY_ZERO;
                     72:
                     73:     case 1:
                     74:       {
                     75:        rp[0] = mpn_divmod_1 (qp, np, nn, dp[0]);
                     76:        return;
                     77:       }
                     78:
                     79:     case 2:
                     80:       {
                     81:        int cnt;
                     82:        mp_ptr n2p, d2p;
                     83:        mp_limb_t qhl, cy;
                     84:        TMP_DECL (marker);
                     85:        TMP_MARK (marker);
                     86:        count_leading_zeros (cnt, dp[dn - 1]);
                     87:        if (cnt != 0)
                     88:          {
                     89:            d2p = (mp_ptr) TMP_ALLOC (dn * BYTES_PER_MP_LIMB);
                     90:            mpn_lshift (d2p, dp, dn, cnt);
                     91:            n2p = (mp_ptr) TMP_ALLOC ((nn + 1) * BYTES_PER_MP_LIMB);
                     92:            cy = mpn_lshift (n2p, np, nn, cnt);
                     93:            n2p[nn] = cy;
                     94:            qhl = mpn_divrem_2 (qp, 0L, n2p, nn + (cy != 0), d2p);
                     95:            if (cy == 0)
                     96:              qp[nn - 2] = qhl; /* always store nn-dn+1 quotient limbs */
                     97:          }
                     98:        else
                     99:          {
                    100:            d2p = (mp_ptr) dp;
                    101:            n2p = (mp_ptr) TMP_ALLOC (nn * BYTES_PER_MP_LIMB);
                    102:            MPN_COPY (n2p, np, nn);
                    103:            qhl = mpn_divrem_2 (qp, 0L, n2p, nn, d2p);
                    104:            qp[nn - 2] = qhl;   /* always store nn-dn+1 quotient limbs */
                    105:          }
                    106:
                    107:        if (cnt != 0)
                    108:          mpn_rshift (rp, n2p, dn, cnt);
                    109:        else
                    110:          MPN_COPY (rp, n2p, dn);
                    111:        TMP_FREE (marker);
                    112:        return;
                    113:       }
                    114:
                    115:     default:
                    116:       {
                    117:        int adjust;
                    118:        TMP_DECL (marker);
                    119:        TMP_MARK (marker);
                    120:        adjust = np[nn - 1] >= dp[dn - 1];      /* conservative tests for quotient size */
                    121:        if (nn + adjust >= 2 * dn)
                    122:          {
                    123:            mp_ptr n2p, d2p;
                    124:            mp_limb_t cy;
                    125:            int cnt;
                    126:            count_leading_zeros (cnt, dp[dn - 1]);
                    127:
                    128:            qp[nn - dn] = 0;                    /* zero high quotient limb */
                    129:            if (cnt != 0)                       /* normalize divisor if needed */
                    130:              {
                    131:                d2p = (mp_ptr) TMP_ALLOC (dn * BYTES_PER_MP_LIMB);
                    132:                mpn_lshift (d2p, dp, dn, cnt);
                    133:                n2p = (mp_ptr) TMP_ALLOC ((nn + 1) * BYTES_PER_MP_LIMB);
                    134:                cy = mpn_lshift (n2p, np, nn, cnt);
                    135:                n2p[nn] = cy;
                    136:                nn += adjust;
                    137:              }
                    138:            else
                    139:              {
                    140:                d2p = (mp_ptr) dp;
                    141:                n2p = (mp_ptr) TMP_ALLOC ((nn + 1) * BYTES_PER_MP_LIMB);
                    142:                MPN_COPY (n2p, np, nn);
                    143:                n2p[nn] = 0;
                    144:                nn += adjust;
                    145:              }
                    146:
                    147:            if (dn == 2)
                    148:              mpn_divrem_2 (qp, 0L, n2p, nn, d2p);
                    149:            else if (dn < BZ_THRESHOLD)
                    150:              mpn_sb_divrem_mn (qp, n2p, nn, d2p, dn);
                    151:            else
                    152:              {
                    153:                /* Perform 2*dn / dn limb divisions as long as the limbs
                    154:                   in np last.  */
                    155:                mp_ptr q2p = qp + nn - 2 * dn;
                    156:                n2p += nn - 2 * dn;
                    157:                mpn_bz_divrem_n (q2p, n2p, d2p, dn);
                    158:                nn -= dn;
                    159:                while (nn >= 2 * dn)
                    160:                  {
                    161:                    mp_limb_t c;
                    162:                    q2p -= dn;  n2p -= dn;
                    163:                    c = mpn_bz_divrem_n (q2p, n2p, d2p, dn);
                    164:                    ASSERT_ALWAYS (c == 0);
                    165:                    nn -= dn;
                    166:                  }
                    167:
                    168:                if (nn != dn)
                    169:                  {
                    170:                    n2p -= nn - dn;
                    171:                    /* In theory, we could fall out to the cute code below
                    172:                       since we now have exactly the situation that code
                    173:                       is designed to handle.  We botch this badly and call
                    174:                       the basic mpn_sb_divrem_mn!  */
                    175:                    if (dn == 2)
                    176:                      mpn_divrem_2 (qp, 0L, n2p, nn, d2p);
                    177:                    else
                    178:                      mpn_sb_divrem_mn (qp, n2p, nn, d2p, dn);
                    179:                  }
                    180:              }
                    181:
                    182:
                    183:            if (cnt != 0)
                    184:              mpn_rshift (rp, n2p, dn, cnt);
                    185:            else
                    186:              MPN_COPY (rp, n2p, dn);
                    187:            TMP_FREE (marker);
                    188:            return;
                    189:          }
                    190:
                    191:        /* When we come here, the numerator/partial remainder is less
                    192:           than twice the size of the denominator.  */
                    193:
                    194:          {
                    195:            /* Problem:
                    196:
                    197:               Divide a numerator N with nn limbs by a denominator D with dn
                    198:               limbs forming a quotient of nn-dn+1 limbs.  When qn is small
                    199:               compared to dn, conventional division algorithms perform poorly.
                    200:               We want an algorithm that has an expected running time that is
                    201:               dependent only on qn.  It is assumed that the most significant
                    202:               limb of the numerator is smaller than the most significant limb
                    203:               of the denominator.
                    204:
                    205:               Algorithm (very informally stated):
                    206:
                    207:               1) Divide the 2 x qn most significant limbs from the numerator
                    208:                  by the qn most significant limbs from the denominator.  Call
                    209:                  the result qest.  This is either the correct quotient, but
                    210:                  might be 1 or 2 too large.  Compute the remainder from the
                    211:                  division.  (This step is implemented by a mpn_divrem call.)
                    212:
                    213:               2) Is the most significant limb from the remainder < p, where p
                    214:                  is the product of the most significant limb from the quotient
                    215:                  and the next(d).  (Next(d) denotes the next ignored limb from
                    216:                  the denominator.)  If it is, decrement qest, and adjust the
                    217:                  remainder accordingly.
                    218:
                    219:               3) Is the remainder >= qest?  If it is, qest is the desired
                    220:                  quotient.  The algorithm terminates.
                    221:
                    222:               4) Subtract qest x next(d) from the remainder.  If there is
                    223:                  borrow out, decrement qest, and adjust the remainder
                    224:                  accordingly.
                    225:
                    226:               5) Skip one word from the denominator (i.e., let next(d) denote
                    227:                  the next less significant limb.  */
                    228:
                    229:            mp_size_t qn;
                    230:            mp_ptr n2p, d2p;
                    231:            mp_ptr tp;
                    232:            mp_limb_t cy;
                    233:            mp_size_t in, rn;
                    234:            mp_limb_t quotient_too_large;
                    235:            int cnt;
                    236:
                    237:            qn = nn - dn;
                    238:            qp[qn] = 0;                         /* zero high quotient limb */
                    239:            qn += adjust;                       /* qn cannot become bigger */
                    240:
                    241:            if (qn == 0)
                    242:              {
                    243:                MPN_COPY (rp, np, dn);
                    244:                TMP_FREE (marker);
                    245:                return;
                    246:              }
                    247:
                    248:            in = dn - qn;               /* (at least partially) ignored # of limbs in ops */
                    249:            /* Normalize denominator by shifting it to the left such that its
                    250:               most significant bit is set.  Then shift the numerator the same
                    251:               amount, to mathematically preserve quotient.  */
                    252:            count_leading_zeros (cnt, dp[dn - 1]);
                    253:            if (cnt != 0)
                    254:              {
                    255:                d2p = (mp_ptr) TMP_ALLOC (qn * BYTES_PER_MP_LIMB);
                    256:
                    257:                mpn_lshift (d2p, dp + in, qn, cnt);
                    258:                d2p[0] |= dp[in - 1] >> (BITS_PER_MP_LIMB - cnt);
                    259:
                    260:                n2p = (mp_ptr) TMP_ALLOC ((2 * qn + 1) * BYTES_PER_MP_LIMB);
                    261:                cy = mpn_lshift (n2p, np + nn - 2 * qn, 2 * qn, cnt);
                    262:                if (adjust)
                    263:                  {
                    264:                    n2p[2 * qn] = cy;
                    265:                    n2p++;
                    266:                  }
                    267:                else
                    268:                  {
                    269:                    n2p[0] |= np[nn - 2 * qn - 1] >> (BITS_PER_MP_LIMB - cnt);
                    270:                  }
                    271:              }
                    272:            else
                    273:              {
                    274:                d2p = (mp_ptr) dp + in;
                    275:
                    276:                n2p = (mp_ptr) TMP_ALLOC ((2 * qn + 1) * BYTES_PER_MP_LIMB);
                    277:                MPN_COPY (n2p, np + nn - 2 * qn, 2 * qn);
                    278:                if (adjust)
                    279:                  {
                    280:                    n2p[2 * qn] = 0;
                    281:                    n2p++;
                    282:                  }
                    283:              }
                    284:
                    285:            /* Get an approximate quotient using the extracted operands.  */
                    286:            if (qn == 1)
                    287:              {
                    288:                mp_limb_t q0, r0;
                    289:                mp_limb_t gcc272bug_n1, gcc272bug_n0, gcc272bug_d0;
                    290:                /* Due to a gcc 2.7.2.3 reload pass bug, we have to use some
                    291:                   temps here.  This doesn't hurt code quality on any machines
                    292:                   so we do it unconditionally.  */
                    293:                gcc272bug_n1 = n2p[1];
                    294:                gcc272bug_n0 = n2p[0];
                    295:                gcc272bug_d0 = d2p[0];
                    296:                udiv_qrnnd (q0, r0, gcc272bug_n1, gcc272bug_n0, gcc272bug_d0);
                    297:                n2p[0] = r0;
                    298:                qp[0] = q0;
                    299:              }
                    300:            else if (qn == 2)
                    301:              mpn_divrem_2 (qp, 0L, n2p, 4L, d2p);
                    302:            else if (qn < BZ_THRESHOLD)
                    303:              mpn_sb_divrem_mn (qp, n2p, qn * 2, d2p, qn);
                    304:            else
                    305:              mpn_bz_divrem_n (qp, n2p, d2p, qn);
                    306:
                    307:            rn = qn;
                    308:            /* Multiply the first ignored divisor limb by the most significant
                    309:               quotient limb.  If that product is > the partial remainder's
                    310:               most significant limb, we know the quotient is too large.  This
                    311:               test quickly catches most cases where the quotient is too large;
                    312:               it catches all cases where the quotient is 2 too large.  */
                    313:            {
                    314:              mp_limb_t dl, x;
                    315:              mp_limb_t h, l;
                    316:
                    317:              if (in - 2 < 0)
                    318:                dl = 0;
                    319:              else
                    320:                dl = dp[in - 2];
                    321:
                    322:              x = SHL (dp[in - 1], dl, cnt);
                    323:              umul_ppmm (h, l, x, qp[qn - 1]);
                    324:
                    325:              if (n2p[qn - 1] < h)
                    326:                {
                    327:                  mp_limb_t cy;
                    328:
                    329:                  mpn_decr_u (qp, (mp_limb_t) 1);
                    330:                  cy = mpn_add_n (n2p, n2p, d2p, qn);
                    331:                  if (cy)
                    332:                    {
                    333:                      /* The partial remainder is safely large.  */
                    334:                      n2p[qn] = cy;
                    335:                      ++rn;
                    336:                    }
                    337:                }
                    338:            }
                    339:
                    340:            quotient_too_large = 0;
                    341:            if (cnt != 0)
                    342:              {
                    343:                mp_limb_t cy1, cy2;
                    344:
                    345:                /* Append partially used numerator limb to partial remainder.  */
                    346:                cy1 = mpn_lshift (n2p, n2p, rn, BITS_PER_MP_LIMB - cnt);
                    347:                n2p[0] |= np[in - 1] & (~(mp_limb_t) 0 >> cnt);
                    348:
                    349:                /* Update partial remainder with partially used divisor limb.  */
                    350:                cy2 = mpn_submul_1 (n2p, qp, qn, dp[in - 1] & (~(mp_limb_t) 0 >> cnt));
                    351:                if (qn != rn)
                    352:                  {
                    353:                    if (n2p[qn] < cy2)
                    354:                      abort ();
                    355:                    n2p[qn] -= cy2;
                    356:                  }
                    357:                else
                    358:                  {
                    359:                    n2p[qn] = cy1 - cy2;
                    360:
                    361:                    quotient_too_large = (cy1 < cy2);
                    362:                    ++rn;
                    363:                  }
                    364:                --in;
                    365:              }
                    366:            /* True: partial remainder now is neutral, i.e., it is not shifted up.  */
                    367:
                    368:            tp = (mp_ptr) TMP_ALLOC (dn * BYTES_PER_MP_LIMB);
                    369:
                    370:            if (in < qn)
                    371:              {
                    372:                if (in == 0)
                    373:                  {
                    374:                    MPN_COPY (rp, n2p, rn);
                    375:                    if (rn != dn)
                    376:                      abort ();
                    377:                    goto foo;
                    378:                  }
                    379:                mpn_mul (tp, qp, qn, dp, in);
                    380:              }
                    381:            else
                    382:              mpn_mul (tp, dp, in, qp, qn);
                    383:
                    384:            cy = mpn_sub (n2p, n2p, rn, tp + in, qn);
                    385:            MPN_COPY (rp + in, n2p, dn - in);
                    386:            quotient_too_large |= cy;
                    387:            cy = mpn_sub_n (rp, np, tp, in);
                    388:            cy = mpn_sub_1 (rp + in, rp + in, rn, cy);
                    389:            quotient_too_large |= cy;
                    390:          foo:
                    391:            if (quotient_too_large)
                    392:              {
                    393:                mpn_decr_u (qp, (mp_limb_t) 1);
                    394:                mpn_add_n (rp, rp, dp, dn);
                    395:              }
                    396:          }
                    397:        TMP_FREE (marker);
                    398:        return;
                    399:       }
                    400:     }
                    401: }

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