[BACK]Return to add1.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpfr

Annotation of OpenXM_contrib/gmp/mpfr/add1.c, Revision 1.1.1.1

1.1       ohara       1: /* mpfr_add1 -- internal function to perform a "real" addition
                      2:
                      3: Copyright 1999, 2000, 2001 Free Software Foundation.
                      4: Contributed by the Spaces project, INRIA Lorraine.
                      5:
                      6: This file is part of the MPFR Library.
                      7:
                      8: The MPFR 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 2.1 of the License, or (at your
                     11: option) any later version.
                     12:
                     13: The MPFR Library is distributed in the hope that it will be useful, but
                     14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     16: License for more details.
                     17:
                     18: You should have received a copy of the GNU Lesser General Public License
                     19: along with the MPFR Library; see the file COPYING.LIB.  If not, write to
                     20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     21: MA 02111-1307, USA. */
                     22:
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25: #include "mpfr.h"
                     26: #include "mpfr-impl.h"
                     27:
                     28: /* compute sign(b) * (|b| + |c|)
                     29:    diff_exp is the difference between the exponents of b and c,
                     30:    which is >= 0 */
                     31:
                     32: int
                     33: mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
                     34:           mp_rnd_t rnd_mode, mp_exp_unsigned_t diff_exp)
                     35: {
                     36:   mp_limb_t *ap, *bp, *cp;
                     37:   mp_prec_t aq, bq, cq, aq2;
                     38:   mp_size_t an, bn, cn;
                     39:   mp_exp_t difw;
                     40:   int sh, rb, fb, inex;
                     41:   TMP_DECL(marker);
                     42:
                     43:   MPFR_ASSERTN(MPFR_IS_FP(b) && MPFR_NOTZERO(b));
                     44:   MPFR_ASSERTN(MPFR_IS_FP(c) && MPFR_NOTZERO(c));
                     45:
                     46:   TMP_MARK(marker);
                     47:   ap = MPFR_MANT(a);
                     48:   bp = MPFR_MANT(b);
                     49:   cp = MPFR_MANT(c);
                     50:
                     51:   if (ap == bp)
                     52:     {
                     53:       bp = (mp_ptr) TMP_ALLOC((size_t) MPFR_ABSSIZE(b) * BYTES_PER_MP_LIMB);
                     54:       MPN_COPY (bp, ap, MPFR_ABSSIZE(b));
                     55:       if (ap == cp)
                     56:         { cp = bp; }
                     57:     }
                     58:   else if (ap == cp)
                     59:     {
                     60:       cp = (mp_ptr) TMP_ALLOC ((size_t) MPFR_ABSSIZE(c) * BYTES_PER_MP_LIMB);
                     61:       MPN_COPY(cp, ap, MPFR_ABSSIZE(c));
                     62:     }
                     63:
                     64:   aq = MPFR_PREC(a);
                     65:   bq = MPFR_PREC(b);
                     66:   cq = MPFR_PREC(c);
                     67:
                     68:   an = (aq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of a */
                     69:   aq2 = an * BITS_PER_MP_LIMB;
                     70:   sh = aq2 - aq;                    /* non-significant bits in low limb */
                     71:   bn = (bq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of b */
                     72:   cn = (cq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of c */
                     73:
                     74:   MPFR_EXP(a) = MPFR_EXP(b);
                     75:   MPFR_SET_SAME_SIGN(a, b);
                     76:
                     77:   /*
                     78:    * 1. Compute the significant part A', the non-significant bits of A
                     79:    * are taken into account.
                     80:    *
                     81:    * 2. Perform the rounding. At each iteration, we remember:
                     82:    *     _ r = rounding bit
                     83:    *     _ f = following bits (same value)
                     84:    * where the result has the form: [number A]rfff...fff + a remaining
                     85:    * value in the interval [0,2) ulp. We consider the most significant
                     86:    * bits of the remaining value to update the result; a possible carry
                     87:    * is immediately taken into account and A is updated accordingly. As
                     88:    * soon as the bits f don't have the same value, A can be rounded.
                     89:    * Variables:
                     90:    *     _ rb = rounding bit (0 or 1).
                     91:    *     _ fb = following bits (0 or 1), then sticky bit.
                     92:    * If fb == 0, the only thing that can change is the sticky bit.
                     93:    */
                     94:
                     95:   rb = fb = -1; /* means: not initialized */
                     96:
                     97:   if (aq2 <= diff_exp)
                     98:     { /* c does not overlap with a' */
                     99:       if (an > bn)
                    100:         { /* a has more limbs than b */
                    101:           /* copy b to the most significant limbs of a */
                    102:           MPN_COPY(ap + (an - bn), bp, bn);
                    103:           /* zero the least significant limbs of a */
                    104:           MPN_ZERO(ap, an - bn);
                    105:         }
                    106:       else /* an <= bn */
                    107:         {
                    108:           /* copy the most significant limbs of b to a */
                    109:           MPN_COPY(ap, bp + (bn - an), an);
                    110:         }
                    111:     }
                    112:   else /* aq2 > diff_exp */
                    113:     { /* c overlaps with a' */
                    114:       mp_limb_t *a2p;
                    115:       mp_limb_t cc;
                    116:       mp_prec_t dif;
                    117:       mp_size_t difn, k;
                    118:       int shift;
                    119:
                    120:       /* copy c (shifted) into a */
                    121:
                    122:       dif = aq2 - diff_exp;
                    123:       /* dif is the number of bits of c which overlap with a' */
                    124:
                    125:       difn = (dif-1)/BITS_PER_MP_LIMB + 1;
                    126:       /* only the highest difn limbs from c have to be considered */
                    127:       if (difn > cn)
                    128:         {
                    129:           /* c doesn't have enough limbs; take into account the virtual
                    130:              zero limbs now by zeroing the least significant limbs of a' */
                    131:           MPFR_ASSERTN(difn - cn <= an);
                    132:           MPN_ZERO(ap, difn - cn);
                    133:           difn = cn;
                    134:         }
                    135:
                    136:       k = diff_exp / BITS_PER_MP_LIMB;
                    137:
                    138:       /* zero the most significant k limbs of a */
                    139:       a2p = ap + (an - k);
                    140:       MPN_ZERO(a2p, k);
                    141:
                    142:       shift = diff_exp % BITS_PER_MP_LIMB;
                    143:
                    144:       if (shift)
                    145:         {
                    146:           MPFR_ASSERTN(a2p - difn >= ap);
                    147:           cc = mpn_rshift(a2p - difn, cp + (cn - difn), difn, shift);
                    148:           if (a2p - difn > ap)
                    149:             *(a2p - difn - 1) = cc;
                    150:         }
                    151:       else
                    152:         MPN_COPY(a2p - difn, cp + (cn - difn), difn);
                    153:
                    154:       /* add b to a */
                    155:
                    156:       cc = an > bn
                    157:         ? mpn_add_n(ap + (an - bn), ap + (an - bn), bp, bn)
                    158:         : mpn_add_n(ap, ap, bp + (bn - an), an);
                    159:
                    160:       if (cc) /* carry */
                    161:         {
                    162:           mp_exp_t exp = MPFR_EXP(a);
                    163:           if (exp == __mpfr_emax)
                    164:             {
                    165:               inex = mpfr_set_overflow(a, rnd_mode, MPFR_SIGN(a));
                    166:               goto end_of_add;
                    167:             }
                    168:           MPFR_EXP(a)++;
                    169:           rb = (ap[0] >> sh) & 1; /* LSB(a) --> rounding bit after the shift */
                    170:           if (sh)
                    171:             {
                    172:               mp_limb_t mask, bb;
                    173:
                    174:               mask = (MP_LIMB_T_ONE << sh) - 1;
                    175:               bb = ap[0] & mask;
                    176:               ap[0] &= (~mask) << 1;
                    177:               if (bb == 0)
                    178:                 fb = 0;
                    179:               else if (bb == mask)
                    180:                 fb = 1;
                    181:             }
                    182:           mpn_rshift(ap, ap, an, 1);
                    183:           ap[an-1] += GMP_LIMB_HIGHBIT;
                    184:           if (sh && fb < 0)
                    185:             goto rounding;
                    186:         } /* cc */
                    187:     } /* aq2 > diff_exp */
                    188:
                    189:   /* non-significant bits of a */
                    190:   if (rb < 0 && sh)
                    191:     {
                    192:       mp_limb_t mask, bb;
                    193:
                    194:       mask = (MP_LIMB_T_ONE << sh) - 1;
                    195:       bb = ap[0] & mask;
                    196:       ap[0] &= ~mask;
                    197:       rb = bb >> (sh - 1);
                    198:       if (sh > 1)
                    199:         {
                    200:           mask >>= 1;
                    201:           bb &= mask;
                    202:           if (bb == 0)
                    203:             fb = 0;
                    204:           else if (bb == mask)
                    205:             fb = 1;
                    206:           else
                    207:             goto rounding;
                    208:         }
                    209:     }
                    210:
                    211:   /* determine rounding and sticky bits (and possible carry) */
                    212:
                    213:   difw = (mp_exp_t) an - (mp_exp_t) (diff_exp / BITS_PER_MP_LIMB);
                    214:   /* difw is the number of limbs from b (regarded as having an infinite
                    215:      precision) that have already been combined with c; -n if the next
                    216:      n limbs from b won't be combined with c. */
                    217:
                    218:   if (bn > an)
                    219:     { /* there are still limbs from b that haven't been taken into account */
                    220:       mp_size_t bk;
                    221:
                    222:       if (fb == 0 && difw <= 0)
                    223:         {
                    224:           fb = 1; /* c hasn't been taken into account ==> sticky bit != 0 */
                    225:           goto rounding;
                    226:         }
                    227:
                    228:       bk = bn - an; /* index of lowest considered limb from b, > 0 */
                    229:       while (difw < 0)
                    230:         { /* ulp(next limb from b) > msb(c) */
                    231:           mp_limb_t bb;
                    232:
                    233:           bb = bp[--bk];
                    234:
                    235:           MPFR_ASSERTD(fb != 0);
                    236:           if (fb > 0)
                    237:             {
                    238:               if (bb != MP_LIMB_T_MAX)
                    239:                 {
                    240:                   fb = 1; /* c hasn't been taken into account
                    241:                              ==> sticky bit != 0 */
                    242:                   goto rounding;
                    243:                 }
                    244:             }
                    245:           else /* fb not initialized yet */
                    246:             {
                    247:               if (rb < 0) /* rb not initialized yet */
                    248:                 {
                    249:                   rb = bb >> (BITS_PER_MP_LIMB - 1);
                    250:                   bb |= GMP_LIMB_HIGHBIT;
                    251:                 }
                    252:               fb = 1;
                    253:               if (bb != MP_LIMB_T_MAX)
                    254:                 goto rounding;
                    255:             }
                    256:
                    257:           if (bk == 0)
                    258:             { /* b has entirely been read */
                    259:               fb = 1; /* c hasn't been taken into account
                    260:                          ==> sticky bit != 0 */
                    261:               goto rounding;
                    262:             }
                    263:
                    264:           difw++;
                    265:         } /* while */
                    266:       MPFR_ASSERTN(bk > 0 && difw >= 0);
                    267:
                    268:       if (difw <= cn)
                    269:         {
                    270:           mp_size_t ck;
                    271:           mp_limb_t cprev;
                    272:           int difs;
                    273:
                    274:           ck = cn - difw;
                    275:           difs = diff_exp % BITS_PER_MP_LIMB;
                    276:
                    277:           if (difs == 0 && ck == 0)
                    278:             goto c_read;
                    279:
                    280:           cprev = ck == cn ? 0 : cp[ck];
                    281:
                    282:           if (fb < 0)
                    283:             {
                    284:               mp_limb_t bb, cc;
                    285:
                    286:               if (difs)
                    287:                 {
                    288:                   cc = cprev << (BITS_PER_MP_LIMB - difs);
                    289:                   if (--ck >= 0)
                    290:                     {
                    291:                       cprev = cp[ck];
                    292:                       cc += cprev >> difs;
                    293:                     }
                    294:                 }
                    295:               else
                    296:                 cc = cp[--ck];
                    297:
                    298:               bb = bp[--bk] + cc;
                    299:
                    300:               if (bb < cc /* carry */
                    301:                   && (rb < 0 || (rb ^= 1) == 0)
                    302:                   && mpn_add_1(ap, ap, an, MP_LIMB_T_ONE << sh))
                    303:                 {
                    304:                   mp_exp_t exp = MPFR_EXP(a);
                    305:                   if (exp == __mpfr_emax)
                    306:                     {
                    307:                       inex = mpfr_set_overflow(a, rnd_mode, MPFR_SIGN(a));
                    308:                       goto end_of_add;
                    309:                     }
                    310:                   MPFR_EXP(a)++;
                    311:                   ap[an-1] = GMP_LIMB_HIGHBIT;
                    312:                   rb = 0;
                    313:                 }
                    314:
                    315:               if (rb < 0) /* rb not initialized yet */
                    316:                 {
                    317:                   rb = bb >> (BITS_PER_MP_LIMB - 1);
                    318:                   bb <<= 1;
                    319:                   bb |= bb >> (BITS_PER_MP_LIMB - 1);
                    320:                 }
                    321:
                    322:               fb = bb != 0;
                    323:               if (fb && bb != MP_LIMB_T_MAX)
                    324:                 goto rounding;
                    325:             } /* fb < 0 */
                    326:
                    327:           while (bk > 0)
                    328:             {
                    329:               mp_limb_t bb, cc;
                    330:
                    331:               if (difs)
                    332:                 {
                    333:                   if (ck < 0)
                    334:                     goto c_read;
                    335:                   cc = cprev << (BITS_PER_MP_LIMB - difs);
                    336:                   if (--ck >= 0)
                    337:                     {
                    338:                       cprev = cp[ck];
                    339:                       cc += cprev >> difs;
                    340:                     }
                    341:                 }
                    342:               else
                    343:                 {
                    344:                   if (ck == 0)
                    345:                     goto c_read;
                    346:                   cc = cp[--ck];
                    347:                 }
                    348:
                    349:               bb = bp[--bk] + cc;
                    350:               if (bb < cc) /* carry */
                    351:                 {
                    352:                   fb ^= 1;
                    353:                   if (fb)
                    354:                     goto rounding;
                    355:                   rb ^= 1;
                    356:                   if (rb == 0 && mpn_add_1(ap, ap, an, MP_LIMB_T_ONE << sh))
                    357:                     {
                    358:                       mp_exp_t exp = MPFR_EXP(a);
                    359:                       if (exp == __mpfr_emax)
                    360:                         {
                    361:                           inex = mpfr_set_overflow(a, rnd_mode, MPFR_SIGN(a));
                    362:                           goto end_of_add;
                    363:                         }
                    364:                       MPFR_EXP(a)++;
                    365:                       ap[an-1] = GMP_LIMB_HIGHBIT;
                    366:                     }
                    367:                 } /* bb < cc */
                    368:
                    369:               if (!fb && bb != 0)
                    370:                 {
                    371:                   fb = 1;
                    372:                   goto rounding;
                    373:                 }
                    374:               if (fb && bb != MP_LIMB_T_MAX)
                    375:                 goto rounding;
                    376:             } /* while */
                    377:
                    378:           /* b has entirely been read */
                    379:
                    380:           if (fb || ck < 0)
                    381:             goto rounding;
                    382:           if (difs && cprev << (BITS_PER_MP_LIMB - difs))
                    383:             {
                    384:               fb = 1;
                    385:               goto rounding;
                    386:             }
                    387:           while (ck)
                    388:             {
                    389:               if (cp[--ck])
                    390:                 {
                    391:                   fb = 1;
                    392:                   goto rounding;
                    393:                 }
                    394:             } /* while */
                    395:         } /* difw <= cn */
                    396:       else
                    397:         { /* c has entirely been read */
                    398:         c_read:
                    399:           if (fb < 0) /* fb not initialized yet */
                    400:             {
                    401:               mp_limb_t bb;
                    402:
                    403:               MPFR_ASSERTN(bk > 0);
                    404:               bb = bp[--bk];
                    405:               if (rb < 0) /* rb not initialized yet */
                    406:                 {
                    407:                   rb = bb >> (BITS_PER_MP_LIMB - 1);
                    408:                   bb &= ~GMP_LIMB_HIGHBIT;
                    409:                 }
                    410:               fb = bb != 0;
                    411:             } /* fb < 0 */
                    412:           if (fb)
                    413:             goto rounding;
                    414:           while (bk)
                    415:             {
                    416:               if (bp[--bk])
                    417:                 {
                    418:                   fb = 1;
                    419:                   goto rounding;
                    420:                 }
                    421:             } /* while */
                    422:         } /* difw > cn */
                    423:     } /* bn > an */
                    424:   else if (fb != 1) /* if fb == 1, the sticky bit is 1 (no possible carry) */
                    425:     { /* b has entirely been read */
                    426:       if (difw > cn)
                    427:         { /* c has entirely been read */
                    428:           if (rb < 0)
                    429:             rb = 0;
                    430:           fb = 0;
                    431:         }
                    432:       else if (diff_exp > aq2)
                    433:         { /* b is followed by at least a zero bit, then by c */
                    434:           if (rb < 0)
                    435:             rb = 0;
                    436:           fb = 1;
                    437:         }
                    438:       else
                    439:         {
                    440:           mp_size_t ck;
                    441:           int difs;
                    442:
                    443:           MPFR_ASSERTN(difw >= 0 && cn >= difw);
                    444:           ck = cn - difw;
                    445:           difs = diff_exp % BITS_PER_MP_LIMB;
                    446:
                    447:           if (difs == 0 && ck == 0)
                    448:             { /* c has entirely been read */
                    449:               if (rb < 0)
                    450:                 rb = 0;
                    451:               fb = 0;
                    452:             }
                    453:           else
                    454:             {
                    455:               mp_limb_t cc;
                    456:
                    457:               cc = difs ? (MPFR_ASSERTN(ck < cn),
                    458:                            cp[ck] << (BITS_PER_MP_LIMB - difs)) : cp[--ck];
                    459:               if (rb < 0)
                    460:                 {
                    461:                   rb = cc >> (BITS_PER_MP_LIMB - 1);
                    462:                   cc &= ~GMP_LIMB_HIGHBIT;
                    463:                 }
                    464:               while (cc == 0)
                    465:                 {
                    466:                   if (ck == 0)
                    467:                     {
                    468:                       fb = 0;
                    469:                       goto rounding;
                    470:                     }
                    471:                   cc = cp[--ck];
                    472:                 } /* while */
                    473:               fb = 1;
                    474:             }
                    475:         }
                    476:     } /* fb != 1 */
                    477:
                    478:  rounding:
                    479:   switch (rnd_mode)
                    480:     {
                    481:     case GMP_RNDN:
                    482:       if (fb == 0)
                    483:         {
                    484:           if (rb == 0)
                    485:             {
                    486:               inex = 0;
                    487:               goto end_of_add;
                    488:             }
                    489:           /* round to even */
                    490:           if (ap[0] & (MP_LIMB_T_ONE << sh))
                    491:             goto rndn_away;
                    492:           else
                    493:             goto rndn_zero;
                    494:         }
                    495:       if (rb == 0)
                    496:         {
                    497:         rndn_zero:
                    498:           inex = MPFR_ISNEG(a) ? 1 : -1;
                    499:           goto end_of_add;
                    500:         }
                    501:       else
                    502:         {
                    503:         rndn_away:
                    504:           inex = MPFR_ISNONNEG(a) ? 1 : -1;
                    505:           goto add_one_ulp;
                    506:         }
                    507:
                    508:     case GMP_RNDZ:
                    509:       inex = rb || fb ? (MPFR_ISNEG(a) ? 1 : -1) : 0;
                    510:       goto end_of_add;
                    511:
                    512:     case GMP_RNDU:
                    513:       inex = rb || fb;
                    514:       if (inex && MPFR_ISNONNEG(a))
                    515:         goto add_one_ulp;
                    516:       else
                    517:         goto end_of_add;
                    518:
                    519:     case GMP_RNDD:
                    520:       inex = - (rb || fb);
                    521:       if (inex && MPFR_ISNEG(a))
                    522:         goto add_one_ulp;
                    523:       else
                    524:         goto end_of_add;
                    525:
                    526:     default:
                    527:       MPFR_ASSERTN(0);
                    528:       inex = 0;
                    529:       goto end_of_add;
                    530:     }
                    531:
                    532:  add_one_ulp: /* add one unit in last place to a */
                    533:   if (mpn_add_1(ap, ap, an, MP_LIMB_T_ONE << sh))
                    534:     {
                    535:       mp_exp_t exp = MPFR_EXP(a);
                    536:       if (exp == __mpfr_emax)
                    537:         inex = mpfr_set_overflow(a, rnd_mode, MPFR_SIGN(a));
                    538:       else
                    539:         {
                    540:           MPFR_EXP(a)++;
                    541:           ap[an-1] = GMP_LIMB_HIGHBIT;
                    542:         }
                    543:     }
                    544:
                    545:  end_of_add:
                    546:   TMP_FREE(marker);
                    547:   return inex;
                    548: }

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