[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     ! 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>