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

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

1.1       maekawa     1: /* mpfr_add -- add two floating-point numbers
                      2:
                      3: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
                      4:
                      5: This file is part of the MPFR Library.
                      6:
                      7: The MPFR Library is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU Library General Public License as published by
                      9: the Free Software Foundation; either version 2 of the License, or (at your
                     10: option) any later version.
                     11:
                     12: The MPFR 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 Library General Public
                     15: License for more details.
                     16:
                     17: You should have received a copy of the GNU Library General Public License
                     18: along with the MPFR Library; see the file COPYING.LIB.  If not, write to
                     19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20: MA 02111-1307, USA. */
                     21:
                     22: #include <stdio.h>
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25: #include "mpfr.h"
                     26:
                     27: extern void mpfr_sub1 _PROTO((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
                     28:                              unsigned char, int));
                     29:
                     30: #define ONE ((mp_limb_t) 1)
                     31:
                     32: /* signs of b and c are supposed equal,
                     33:    diff_exp is the difference between the exponents of b and c,
                     34:    which is supposed >= 0 */
                     35:
                     36: void
                     37: #if __STDC__
                     38: mpfr_add1(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
                     39:          unsigned char rnd_mode, int diff_exp)
                     40: #else
                     41: mpfr_add1(a, b, c, rnd_mode, diff_exp)
                     42:      mpfr_ptr a;
                     43:      mpfr_srcptr b;
                     44:      mpfr_srcptr c;
                     45:      unsigned char rnd_mode;
                     46:      int diff_exp;
                     47: #endif
                     48: {
                     49:   mp_limb_t *ap, *bp, *cp, cc, c2, c3=0; unsigned int an,bn,cn; int sh,dif,k;
                     50:   TMP_DECL(marker);
                     51:
                     52:   TMP_MARK(marker);
                     53:   ap = MANT(a);
                     54:   bp = MANT(b);
                     55:   cp = MANT(c);
                     56:   if (ap == bp) {
                     57:     bp = (mp_ptr) TMP_ALLOC(ABSSIZE(b) * BYTES_PER_MP_LIMB);
                     58:     MPN_COPY (bp, ap, ABSSIZE(b));
                     59:     if (ap == cp) { cp = bp; }
                     60:   }
                     61:   else if (ap == cp)
                     62:     {
                     63:       cp = (mp_ptr) TMP_ALLOC (ABSSIZE(c) * BYTES_PER_MP_LIMB);
                     64:       MPN_COPY(cp, ap, ABSSIZE(c));
                     65:     }
                     66:
                     67:   an = (PREC(a)-1)/mp_bits_per_limb+1; /* number of significant limbs of a */
                     68:
                     69:   sh = an*mp_bits_per_limb-PREC(a); /* non-significant bits in low limb */
                     70:   bn = (PREC(b)-1)/mp_bits_per_limb+1; /* number of significant limbs of b */
                     71:   EXP(a) = EXP(b);
                     72:
                     73:   if (SIGN(a)!=SIGN(b)) CHANGE_SIGN(a);
                     74:
                     75:   /* case 1: diff_exp>=prec(a), i.e. c only affects the last bit
                     76:      through rounding */
                     77:   dif = PREC(a)-diff_exp;
                     78:
                     79:   if (dif<=0) {
                     80:
                     81:     /* diff_exp>=PREC(a): c does not overlap with a */
                     82:     /* either PREC(b)<=PREC(a), and we can copy the mantissa of b directly
                     83:        into that of a, or PREC(b)>PREC(a) and we have to round b+c */
                     84:
                     85:     if (PREC(b)<=PREC(a)) {
                     86:
                     87:       MPN_COPY(ap+(an-bn), bp, bn);
                     88:       /* fill low significant limbs with zero */
                     89:
                     90:       for (bp=ap;bn<an;bn++) *bp++=0;
                     91:
                     92:       /* now take c into account */
                     93:       if (rnd_mode==GMP_RNDN) {
                     94:
                     95:        /* to nearest */
                     96:        /* if diff_exp > PREC(a), no change */
                     97:
                     98:        if (diff_exp==PREC(a)) {
                     99:
                    100:          /* if c is not zero, then as it is normalized, we have to add
                    101:             one to the lsb of a if c>1/2, or c=1/2 and lsb(a)=1 (round to
                    102:             even) */
                    103:
                    104:          if (NOTZERO(c)) {
                    105:
                    106:            /* c is not zero */
                    107:            /* check whether mant(c)=1/2 or not */
                    108:
                    109:            cc = *cp - (ONE<<(mp_bits_per_limb-1));
                    110:            if (cc==0) {
                    111:              bp = cp+(PREC(c)-1)/mp_bits_per_limb;
                    112:              while (cp<bp && cc==0) cc = *++cp;
                    113:            }
                    114:
                    115:            if (cc || (ap[an-1] & (ONE<<sh))) goto add_one_ulp;
                    116:            /* mant(c) != 1/2 or mant(c) = 1/2: add 1 iff lsb(a)=1 */
                    117:          }
                    118:        }
                    119:       }
                    120:       else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
                    121:               (ISNEG(b) && rnd_mode==GMP_RNDD)) {
                    122:
                    123:        /* round up */
                    124:        if (NOTZERO(c)) goto add_one_ulp;
                    125:       }
                    126:       /* in the other cases (round to zero, or up/down with sign -/+),
                    127:          nothing to do */
                    128:     }
                    129:     else {
                    130:
                    131:       /* PREC(b)>PREC(a) : we have to round b+c */
                    132:       k=bn-an;
                    133:
                    134:       /* first copy the 'an' most significant limbs of b to a */
                    135:       MPN_COPY(ap, bp+k, an);
                    136:       if (rnd_mode==GMP_RNDN) {
                    137:
                    138:        /* to nearest */
                    139:        /* first check whether the truncated bits from b are 1/2*lsb(a) */
                    140:
                    141:        if (sh) {
                    142:          cc = *ap & ((ONE<<sh)-1);
                    143:          *ap &= ~cc; /* truncate last bits */
                    144:          cc -= ONE<<(sh-1);
                    145:        }
                    146:        else /* no bit to truncate */
                    147:          cc = bp[--k] - (ONE<<(mp_bits_per_limb-1));
                    148:
                    149:        if ((long)cc>0) goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
                    150:        else if (cc==0) {
                    151:
                    152:          while (k>1 && cc==0) cc=bp[--k];
                    153:
                    154:          /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
                    155:          if (NOTZERO(c) || (*ap & (ONE<<sh))) goto add_one_ulp;
                    156:          /* if trunc(b)+c is exactly 1/2*lsb(a) : round to even lsb */
                    157:        }
                    158:
                    159:        /* if cc<0 : trunc(b) < 1/2*lsb(a) -> round down, i.e. do nothing */
                    160:       }
                    161:       else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
                    162:               (ISNEG(b) && rnd_mode==GMP_RNDD)) {
                    163:
                    164:        /* first check whether trunc(b)+c is zero or not */
                    165:        if (sh) {
                    166:          cc = *ap & ((ONE<<sh)-1); *ap &= ~cc; /* truncate last bits */
                    167:        }
                    168:        else cc = bp[--k] - (ONE<<(mp_bits_per_limb-1));
                    169:        while (cc==0 && k>1) cc=bp[--k];
                    170:        if (cc || NOTZERO(c)) goto add_one_ulp;
                    171:       }
                    172:
                    173:       /* in the other cases (round to zero, or up/down with sign -/+),
                    174:          nothing to do, since b and c don't overlap, there can't be any
                    175:         carry */
                    176:
                    177:     }
                    178:   }
                    179:   else {
                    180:     /* diff_exp < PREC(a) : c overlaps with a by dif bits */
                    181:     /* first copy upper part of c into a (after shift) */
                    182:     unsigned char overlap;
                    183:
                    184:     k = (dif-1)/mp_bits_per_limb + 1; /* only the highest k limbs from c
                    185:                                         have to be considered */
                    186:     cn = (PREC(c)-1)/mp_bits_per_limb + 1;
                    187:     MPN_ZERO(ap+k, an-k); /* do it now otherwise ap[k] may be destroyed
                    188:                             in case dif<0 */
                    189:
                    190:     if (dif<=PREC(c)) {
                    191:       /* c has to be truncated */
                    192:       dif = dif % mp_bits_per_limb;
                    193:       dif = (dif) ? mp_bits_per_limb-dif-sh : -sh;
                    194:
                    195:       /* we have to shift by dif bits to the right */
                    196:
                    197:       if (dif>0) mpn_rshift(ap, cp+(cn-k), k, dif);
                    198:       else if (dif<0) {
                    199:        ap[k] = mpn_lshift(ap, cp+(cn-k), k, -dif);
                    200:
                    201:        /* put the non-significant bits in low limb for further rounding */
                    202:
                    203:        if (cn >= k+1)
                    204:          ap[0] += cp[cn-k-1]>>(mp_bits_per_limb+dif);
                    205:       }
                    206:       else MPN_COPY(ap, cp+(cn-k), k);
                    207:       overlap=1;
                    208:     }
                    209:     else {
                    210:
                    211:       /* c is not truncated, but we have to fill low limbs with 0 */
                    212:
                    213:       k = diff_exp/mp_bits_per_limb;
                    214:       overlap = diff_exp%mp_bits_per_limb;
                    215:
                    216:       /* warning: a shift of zero bit is not allowed */
                    217:       MPN_ZERO(ap, an-k-cn);
                    218:       if (overlap) {
                    219:        cc=mpn_rshift(ap+(an-k-cn), cp, cn, overlap);
                    220:        if (an-k-cn>0) ap[an-k-cn-1]=cc;
                    221:       }
                    222:       else MPN_COPY(ap+(an-k-cn), cp, cn);
                    223:       overlap=0;
                    224:     }
                    225:
                    226:     /* here overlap=1 iff ulp(c)<ulp(a) */
                    227:     /* then put high limbs to zero */
                    228:     /* now add 'an' upper limbs of b in place */
                    229:
                    230:     if (PREC(b)<=PREC(a)) {
                    231:       overlap += 2;
                    232:       cc = mpn_add_n(ap+(an-bn), ap+(an-bn), bp, bn);
                    233:     }
                    234:     else
                    235:       /* PREC(b) > PREC(a): we have to truncate b */
                    236:       cc = mpn_add_n(ap, ap, bp+(bn-an), an);
                    237:
                    238:     if (cc) {
                    239:
                    240:       /* shift one bit to the right */
                    241:
                    242:       c3 = (ap[0]&1) && (PREC(a)%mp_bits_per_limb==0);
                    243:       mpn_rshift(ap, ap, an, 1);
                    244:       ap[an-1] += ONE<<(mp_bits_per_limb-1);
                    245:       EXP(a)++;
                    246:     }
                    247:
                    248:     /* remains to do the rounding */
                    249:
                    250:     if (rnd_mode==GMP_RNDN) {
                    251:
                    252:       /* to nearest */
                    253:
                    254:       int kc;
                    255:
                    256:       /* four cases: overlap =
                    257:          (0) PREC(b) > PREC(a) and diff_exp+PREC(c) <= PREC(a)
                    258:          (1) PREC(b) > PREC(a) and diff_exp+PREC(c) > PREC(a)
                    259:          (2) PREC(b) <= PREC(a) and diff_exp+PREC(c) <= PREC(a)
                    260:          (3)  PREC(b) <= PREC(a) and diff_exp+PREC(c) > PREC(a) */
                    261:
                    262:       switch (overlap)
                    263:        {
                    264:         case 1: /* both b and c to round */
                    265:          kc = cn-k; /* remains kc limbs from c */
                    266:          k = bn-an; /* remains k limbs from b */
                    267:
                    268:          /* truncate last bits and store the difference with 1/2*ulp in cc */
                    269:
                    270:          cc = *ap & ((ONE<<sh)-1);
                    271:          *ap &= ~cc; /* truncate last bits */
                    272:          cc -= ONE<<(sh-1);
                    273:          while ((cc==0 || cc==-1) && k!=0 && kc!=0) {
                    274:            kc--;
                    275:            cc += mpn_add_1(&c2, bp+(--k), 1,(cp[kc+1]<<(mp_bits_per_limb-dif))
                    276:                            +(cp[kc]>>dif));
                    277:            if (cc==0 || cc==-1) cc=c2;
                    278:          }
                    279:          if ((long)cc>0) goto add_one_ulp;
                    280:          else if ((long)cc<-1)
                    281:            { TMP_FREE(marker); return; /* the carry can be at most 1 */ }
                    282:          else if (kc==0) goto round_b;
                    283:
                    284:          /* else round c: go through */
                    285:
                    286:        case 3: /* only c to round */
                    287:          bp=cp; k=cn-k; goto to_nearest;
                    288:
                    289:        case 0: /* only b to round */
                    290:         round_b:
                    291:          k=bn-an; dif=0; goto to_nearest;
                    292:
                    293:          /* otherwise the result is exact: nothing to do */
                    294:        }
                    295:     }
                    296:     else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
                    297:             (ISNEG(b) && rnd_mode==GMP_RNDD)) {
                    298:       cc = *ap & ((ONE<<sh)-1);
                    299:       *ap &= ~cc; /* truncate last bits */
                    300:       if (cc || c3) goto add_one_ulp; /* will happen most of the time */
                    301:       else {
                    302:
                    303:        /* same four cases too */
                    304:
                    305:        int kc = cn-k; /* remains kc limbs from c */
                    306:        switch (overlap)
                    307:        {
                    308:         case 1: /* both b and c to round */
                    309:          k = bn-an; /* remains k limbs from b */
                    310:          while (cc==0 && k!=0 && kc!=0) {
                    311:            kc--;
                    312:            cc = mpn_add_1(&c2, bp+(--k), 1,(cp[kc+1]<<(mp_bits_per_limb-dif))
                    313:                           + (cp[kc]>>dif));
                    314:          }
                    315:          if (cc) goto add_one_ulp;
                    316:          else if (kc==0) goto round_b2;
                    317:          /* else round c: go through */
                    318:        case 3: /* only c to round */
                    319:          while (kc) if (cp[--kc]) goto add_one_ulp;
                    320:          /* if dif>0 : remains to check last dif bits from c */
                    321:          if (dif>0 && (cp[0]<<(mp_bits_per_limb-dif))) goto add_one_ulp;
                    322:          break;
                    323:        case 0: /* only b to round */
                    324:         round_b2:
                    325:          k=bn-an;
                    326:          while (k) if (bp[--k]) goto add_one_ulp;
                    327:         /* otherwise the result is exact: nothing to do */
                    328:        }
                    329:       }
                    330:     }
                    331:     /* else nothing to do: round towards zero, i.e. truncate last sh bits */
                    332:     else
                    333:       *ap &= ~((ONE<<sh)-1);
                    334:   }
                    335:   goto end_of_add;
                    336:
                    337:   to_nearest: /* 0 <= sh < mp_bits_per_limb : number of bits of a to truncate
                    338:                  bp[k] : last significant limb from b */
                    339:         if (sh) {
                    340:          cc = *ap & ((ONE<<sh)-1);
                    341:          *ap &= ~cc; /* truncate last bits */
                    342:          c2 = ONE<<(sh-1);
                    343:        }
                    344:        else /* no bit to truncate */
                    345:          { if (k) cc = bp[--k]; else cc = 0; c2 = ONE<<(mp_bits_per_limb-1); }
                    346:        if (cc>c2) goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
                    347:        else if (cc==c2) {
                    348:          cc=0; while (k && cc==0) cc=bp[--k];
                    349:          /* special case of rouding c shifted to the right */
                    350:          if (cc==0 && dif>0) cc=cp[0]<<(mp_bits_per_limb-dif);
                    351:          /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
                    352:          if (cc || (*ap & (ONE<<sh))) goto add_one_ulp;
                    353:        }
                    354:         goto end_of_add;
                    355:
                    356:   add_one_ulp: /* add one unit in last place to a */
                    357:     cc = mpn_add_1(ap, ap, an, ONE<<sh);
                    358:     if (cc) { fprintf(stderr, "carry(3) in mpfr_add\n"); exit(1); }
                    359:
                    360:  end_of_add:
                    361:   TMP_FREE(marker);
                    362:   return;
                    363: }
                    364:
                    365: void
                    366: #if __STDC__
                    367: mpfr_add(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
                    368:              unsigned char rnd_mode)
                    369: #else
                    370: mpfr_add(a, b, c, rnd_mode)
                    371:      mpfr_ptr a;
                    372:      mpfr_srcptr b;
                    373:      mpfr_srcptr c;
                    374:      unsigned char rnd_mode;
                    375: #endif
                    376: {
                    377:   int diff_exp;
                    378:
                    379:   if (FLAG_NAN(b) || FLAG_NAN(c)) {
                    380:     SET_NAN(a); return;
                    381:   }
                    382:
                    383:   if (!NOTZERO(b)) { mpfr_set(a, c, rnd_mode); return; }
                    384:   if (!NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
                    385:
                    386:   diff_exp = EXP(b)-EXP(c);
                    387:   if (SIGN(b) != SIGN(c)) { /* signs differ, it's a subtraction */
                    388:     if (diff_exp<0) {
                    389:       mpfr_sub1(a, c, b, rnd_mode, -diff_exp);
                    390:     }
                    391:     else if (diff_exp>0) mpfr_sub1(a, b, c, rnd_mode, diff_exp);
                    392:     else { /* diff_exp=0 */
                    393:       diff_exp = mpfr_cmp3(b,c,-1);
                    394:       /* if b>0 and diff_exp>0 or b<0 and diff_exp<0: abs(b) > abs(c) */
                    395:       if (diff_exp==0) SET_ZERO(a);
                    396:       else if (diff_exp*SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
                    397:       else mpfr_sub1(a, c, b, rnd_mode, 0);
                    398:     }
                    399:   }
                    400:   else /* signs are equal, it's an addition */
                    401:     if (diff_exp<0) mpfr_add1(a, c, b, rnd_mode, -diff_exp);
                    402:     else mpfr_add1(a, b, c, rnd_mode, diff_exp);
                    403: }
                    404:

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