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

Annotation of OpenXM_contrib/gmp/mpfr/sub.c, Revision 1.1

1.1     ! maekawa     1: /* mpfr_sub -- subtract 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: /* #define DEBUG */
        !            28:
        !            29: extern void mpfr_add1 _PROTO((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
        !            30:                              unsigned char, int));
        !            31:
        !            32: /* put in ap[0]..ap[an-1] the value of bp[0]..bp[n-1] shifted by sh bits
        !            33:    to the left minus ap[0]..ap[n-1], with 0 <= sh < mp_bits_per_limb, and
        !            34:    returns the borrow.
        !            35: */
        !            36: mp_limb_t
        !            37: #if __STDC__
        !            38: mpn_sub_lshift_n (mp_limb_t *ap, mp_limb_t *bp, int n, int sh, int an)
        !            39: #else
        !            40: mpn_sub_lshift_n (ap, bp, n, sh, an) mp_limb_t *ap, *bp; int n,sh,an;
        !            41: #endif
        !            42: {
        !            43:   mp_limb_t c, bh;
        !            44:
        !            45:   /* shift b to the left */
        !            46:   if (sh) bh = mpn_lshift(bp, bp, n, sh);
        !            47:   c = (n<an) ? mpn_sub_n(ap, bp, ap, n) : mpn_sub_n(ap, bp+(n-an), ap, an);
        !            48:   /* shift back b to the right */
        !            49:   if (sh) {
        !            50:     mpn_rshift(bp, bp, n, sh);
        !            51:     bp[n-1] += bh<<(mp_bits_per_limb-sh);
        !            52:   }
        !            53:   return c;
        !            54: }
        !            55:
        !            56: /* signs of b and c differ, abs(b)>=abs(c), diff_exp>=0 */
        !            57: void
        !            58: #if __STDC__
        !            59: mpfr_sub1(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, unsigned char rnd_mode, int diff_exp)
        !            60: #else
        !            61: mpfr_sub1(a, b, c, rnd_mode, diff_exp)
        !            62:      mpfr_ptr a;
        !            63:      mpfr_srcptr b;
        !            64:      mpfr_srcptr c;
        !            65:      unsigned char rnd_mode;
        !            66:      int diff_exp;
        !            67: #endif
        !            68: {
        !            69:   mp_limb_t *ap, *bp, *cp, cc, c2; unsigned int an,bn,cn;
        !            70:   int sh,dif,k,cancel,cancel1,cancel2;
        !            71:   TMP_DECL(marker);
        !            72:
        !            73: #ifdef DEBUG
        !            74:   printf("b=  "); if (SIGN(b)>=0) putchar(' ');
        !            75:   mpfr_print_raw(b); putchar('\n');
        !            76:   printf("c=  "); if (SIGN(c)>=0) putchar(' ');
        !            77:   for (k=0;k<diff_exp;k++) putchar(' '); mpfr_print_raw(c);
        !            78:   putchar('\n');
        !            79:   printf("b=%1.20e c=%1.20e\n",mpfr_get_d(b),mpfr_get_d(c));
        !            80: #endif
        !            81:   cancel = mpfr_cmp2(b, c);
        !            82:   /* we have to take into account the first (PREC(a)+cancel) bits from b */
        !            83:   cancel1 = cancel/mp_bits_per_limb; cancel2 = cancel%mp_bits_per_limb;
        !            84:   TMP_MARK(marker);
        !            85:   ap = MANT(a);
        !            86:   bp = MANT(b);
        !            87:   cp = MANT(c);
        !            88:   if (ap == bp) {
        !            89:     bp = (mp_ptr) TMP_ALLOC(ABSSIZE(b) * BYTES_PER_MP_LIMB);
        !            90:     MPN_COPY (bp, ap, ABSSIZE(b));
        !            91:     if (ap == cp) { cp = bp; }
        !            92:   }
        !            93:   else if (ap == cp)
        !            94:     {
        !            95:       cp = (mp_ptr) TMP_ALLOC (ABSSIZE(c) * BYTES_PER_MP_LIMB);
        !            96:       MPN_COPY(cp, ap, ABSSIZE(c));
        !            97:     }
        !            98:   an = (PREC(a)-1)/mp_bits_per_limb+1; /* number of significant limbs of a */
        !            99:   sh = an*mp_bits_per_limb-PREC(a); /* non-significant bits in low limb */
        !           100:   bn = (PREC(b)-1)/mp_bits_per_limb+1; /* number of significant limbs of b */
        !           101:   cn = (PREC(c)-1)/mp_bits_per_limb + 1;
        !           102:   EXP(a) = EXP(b)-cancel;
        !           103:   /* adjust sign to that of b */
        !           104:   if (SIGN(a)*SIGN(b)<0) CHANGE_SIGN(a);
        !           105:   /* case 1: diff_exp>=prec(a), i.e. c only affects the last bit
        !           106:      through rounding */
        !           107:   dif = PREC(a)-diff_exp;
        !           108: #ifdef DEBUG
        !           109:   printf("PREC(a)=%d an=%u PREC(b)=%d bn=%u PREC(c)=%d diff_exp=%u dif=%d cancel=%d\n",
        !           110:         PREC(a),an,PREC(b),bn,PREC(c),diff_exp,dif,cancel);
        !           111: #endif
        !           112:   if (dif<=0) { /* diff_exp>=PREC(a): c does not overlap with a */
        !           113:     /* either PREC(b)<=PREC(a), and we can copy the mantissa of b directly
        !           114:        into that of a, or PREC(b)>PREC(a) and we have to round b-c */
        !           115:     if (PREC(b)<=PREC(a)+cancel) {
        !           116:       if (cancel2) mpn_lshift(ap+(an-bn+cancel1), bp, bn-cancel1, cancel2);
        !           117:       else MPN_COPY(ap+(an-bn+cancel1), bp, bn-cancel1);
        !           118:       /* fill low significant limbs with zero */
        !           119:       MPN_ZERO(ap, an-bn+cancel1);
        !           120:       /* now take c into account */
        !           121:       if (rnd_mode==GMP_RNDN) { /* to nearest */
        !           122:        /* if diff_exp > PREC(a), no change */
        !           123:        if (diff_exp==PREC(a)) {
        !           124:          /* if c is not zero, then as it is normalized, we have to subtract
        !           125:             one to the lsb of a if c>1/2, or c=1/2 and lsb(a)=1 (round to
        !           126:             even) */
        !           127:          if (NOTZERO(c)) { /* c is not zero */
        !           128:            /* check whether mant(c)=1/2 or not */
        !           129:            cc = *cp - ((mp_limb_t)1<<(mp_bits_per_limb-1));
        !           130:            if (cc==0) {
        !           131:              bp = cp+(PREC(c)-1)/mp_bits_per_limb;
        !           132:              while (cp<bp && cc==0) cc = *++cp;
        !           133:            }
        !           134:            if (cc || (ap[an-1] & (mp_limb_t)1<<sh)) goto sub_one_ulp;
        !           135:              /* mant(c) > 1/2 or mant(c) = 1/2: subtract 1 iff lsb(a)=1 */
        !           136:          }
        !           137:        }
        !           138:        else if (ap[an-1]==0) { /* case b=2^n */
        !           139:          ap[an-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
        !           140:          EXP(a)++;
        !           141:        }
        !           142:       }
        !           143:       else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
        !           144:               (ISNEG(b) && rnd_mode==GMP_RNDD)) {
        !           145:        /* round up: nothing to do */
        !           146:        if (ap[an-1]==0) { /* case b=2^n */
        !           147:          ap[an-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
        !           148:          EXP(a)++;
        !           149:        }
        !           150:       }
        !           151:       else {
        !           152:        /* round down: subtract 1 ulp iff c<>0 */
        !           153:        if (NOTZERO(c)) goto sub_one_ulp;
        !           154:       }
        !           155:     }
        !           156:     else { /* PREC(b)>PREC(a) : we have to round b-c */
        !           157:       k=bn-an;
        !           158:       /* first copy the 'an' most significant limbs of b to a */
        !           159:       MPN_COPY(ap, bp+k, an);
        !           160:       if (rnd_mode==GMP_RNDN) { /* to nearest */
        !           161:        /* first check whether the truncated bits from b are 1/2*lsb(a) */
        !           162:        if (sh) {
        !           163:          cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           164:          *ap &= ~cc; /* truncate last bits */
        !           165:          cc -= (mp_limb_t)1<<(sh-1);
        !           166:        }
        !           167:        else /* no bit to truncate */
        !           168:          cc = bp[--k] - ((mp_limb_t)1<<(mp_bits_per_limb-1));
        !           169:        if ((long)cc>0) { /* suppose sizeof(long)=sizeof(mp_limb_t) */
        !           170:          goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
        !           171:        }
        !           172:        else if (cc==0) {
        !           173:          while (k>1 && cc==0) cc=bp[--k];
        !           174:          /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
        !           175:          if (NOTZERO(c) || (*ap & ((mp_limb_t)1<<sh))) goto sub_one_ulp;
        !           176:          /* if trunc(b)-c is exactly 1/2*lsb(a) : round to even lsb */
        !           177:        }
        !           178:        /* if cc<0 : trunc(b) < 1/2*lsb(a) -> round down, i.e. do nothing */
        !           179:       }
        !           180:       else { /* round towards infinity or zero */
        !           181:        if (sh) {
        !           182:          cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           183:          *ap &= ~cc; /* truncate last bits */
        !           184:        }
        !           185:        else cc=0;
        !           186:        cn--;
        !           187:         c2 = (dif>-sh) ? cp[cn]>>(mp_bits_per_limb-dif-sh) : 0;
        !           188:        while (cc==c2 && (k || cn)) {
        !           189:          if (k) cc = bp[--k];
        !           190:          if (cn) {
        !           191:            c2 = cp[cn]<<(dif+sh);
        !           192:            if (--cn) c2 += cp[cn]>>(mp_bits_per_limb-dif-sh);
        !           193:          }
        !           194:        }
        !           195:        dif = ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
        !           196:               (ISNEG(b) && rnd_mode==GMP_RNDD));
        !           197:        /* round towards infinity if dif=1, towards zero otherwise */
        !           198:        if (dif && cc>c2) goto add_one_ulp;
        !           199:        else if (dif==0 && cc<c2) goto sub_one_ulp;
        !           200:       }
        !           201:     }
        !           202:   }
        !           203:   else { /* case 2: diff_exp < PREC(a) : c overlaps with a by dif bits */
        !           204:     /* first copy upper part of c into a (after shift) */
        !           205:     int overlap;
        !           206:     dif += cancel;
        !           207:     k = (dif-1)/mp_bits_per_limb + 1; /* only the highest k limbs from c
        !           208:                                         have to be considered */
        !           209:     if (k<an) {
        !           210:       MPN_ZERO(ap+k, an-k); /* do it now otherwise ap[k] may be
        !           211:                                       destroyed in case dif<0 */
        !           212:     }
        !           213: #ifdef DEBUG
        !           214:     printf("cancel=%d dif=%d k=%d cn=%d sh=%d\n",cancel,dif,k,cn,sh);
        !           215: #endif
        !           216:     if (dif<=PREC(c)) { /* c has to be truncated */
        !           217:       dif = dif % mp_bits_per_limb;
        !           218:       dif = (dif) ? mp_bits_per_limb-dif-sh : -sh;
        !           219:       /* we have to shift by dif bits to the right */
        !           220:       if (dif>0) {
        !           221:        mpn_rshift(ap, cp+(cn-k), (k<=an) ? k : an, dif);
        !           222:         if (k>an) ap[an-1] += cp[cn-k+an]<<(mp_bits_per_limb-dif);
        !           223:       }
        !           224:       else if (dif<0) {
        !           225:        cc = mpn_lshift(ap, cp+(cn-k), k, -dif);
        !           226:        if (k<an) ap[k]=cc;
        !           227:        /* put the non-significant bits in low limb for further rounding */
        !           228:        if (cn >= k+1)
        !           229:          ap[0] += cp[cn-k-1]>>(mp_bits_per_limb+dif);
        !           230:       }
        !           231:       else MPN_COPY(ap, cp+(cn-k), k);
        !           232:       overlap=1;
        !           233:     }
        !           234:     else { /* c is not truncated, but we have to fill low limbs with 0 */
        !           235:       MPN_ZERO(ap, k-cn);
        !           236:       overlap = cancel-diff_exp;
        !           237: #ifdef DEBUG
        !           238:       printf("0:a="); mpfr_print_raw(a); putchar('\n');
        !           239:       printf("overlap=%d\n",overlap);
        !           240: #endif
        !           241:       if (overlap>=0) {
        !           242:        cn -= overlap/mp_bits_per_limb;
        !           243:        overlap %= mp_bits_per_limb;
        !           244:        /* warning: a shift of zero with mpn_lshift is not allowed */
        !           245:        if (overlap) {
        !           246:          if (an<cn) {
        !           247:            mpn_lshift(ap, cp+(cn-an), an, overlap);
        !           248:            ap[0] += cp[cn-an-1]>>(mp_bits_per_limb-overlap);
        !           249:          }
        !           250:          else mpn_lshift(ap+(an-cn), cp, cn, overlap);
        !           251:        }
        !           252:        else MPN_COPY(ap+(an-cn), cp, cn);
        !           253:       }
        !           254:       else { /* shift to the right by -overlap bits */
        !           255:        overlap = -overlap;
        !           256:        k = overlap/mp_bits_per_limb;
        !           257:        overlap = overlap % mp_bits_per_limb;
        !           258:        if (overlap) cc = mpn_rshift(ap+(an-k-cn), cp, cn, overlap);
        !           259:        else {
        !           260:          MPN_COPY(ap+(an-k-cn), cp, cn);
        !           261:          cc = 0;
        !           262:        }
        !           263:        if (an>k+cn) ap[an-k-cn-1]=cc;
        !           264:       }
        !           265:       overlap=0;
        !           266:     }
        !           267: #ifdef DEBUG
        !           268:       printf("1:a="); mpfr_print_raw(a); putchar('\n');
        !           269: #endif
        !           270:     /* here overlap=1 iff ulp(c)<ulp(a) */
        !           271:     /* then put high limbs to zero */
        !           272:     /* now add 'an' upper limbs of b in place */
        !           273:     if (PREC(b)<=PREC(a)+cancel) { int i, imax;
        !           274:       overlap += 2;
        !           275:       /* invert low limbs */
        !           276:       imax = (int)an-(int)bn+cancel1;
        !           277:       for (i=0;i<imax;i++) ap[i] = ~ap[i];
        !           278:       cc = (i) ? mpn_add_1(ap, ap, i, 1) : 1;
        !           279:       mpn_sub_lshift_n(ap+i, bp, bn-cancel1, cancel2, an);
        !           280:       mpn_sub_1(ap+i, ap+i, an-i, (mp_limb_t)1-cc);
        !           281:     }
        !           282:     else /* PREC(b) > PREC(a): we have to truncate b */
        !           283:       mpn_sub_lshift_n(ap, bp+(bn-an-cancel1), an, cancel2, an);
        !           284:     /* remains to do the rounding */
        !           285: #ifdef DEBUG
        !           286:       printf("2:a="); mpfr_print_raw(a); putchar('\n');
        !           287:       printf("overlap=%d\n",overlap);
        !           288: #endif
        !           289:     if (rnd_mode==GMP_RNDN) { /* to nearest */
        !           290:       int kc;
        !           291:       /* four cases: overlap =
        !           292:          (0) PREC(b) > PREC(a) and diff_exp+PREC(c) <= PREC(a)
        !           293:          (1) PREC(b) > PREC(a) and diff_exp+PREC(c) > PREC(a)
        !           294:          (2) PREC(b) <= PREC(a) and diff_exp+PREC(c) <= PREC(a)
        !           295:          (3)  PREC(b) <= PREC(a) and diff_exp+PREC(c) > PREC(a) */
        !           296:       switch (overlap)
        !           297:        {
        !           298:         case 1: /* both b and c to round */
        !           299:          kc = cn-k; /* remains kc limbs from c */
        !           300:          k = bn-an; /* remains k limbs from b */
        !           301:          /* truncate last bits and store the difference with 1/2*ulp in cc */
        !           302:          cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           303:          *ap &= ~cc; /* truncate last bits */
        !           304:          cc -= (mp_limb_t)1<<(sh-1);
        !           305:          while ((cc==0 || cc==-1) && k!=0 && kc!=0) {
        !           306:            kc--;
        !           307:            cc -= mpn_sub_1(&c2, bp+(--k), 1, (cp[kc]>>dif) +
        !           308:                            (cp[kc+1]<<(mp_bits_per_limb-dif)));
        !           309:            if (cc==0 || cc==-1) cc=c2;
        !           310:          }
        !           311:          if ((long)cc>0) goto add_one_ulp;
        !           312:          else if ((long)cc<-1) goto end_of_sub; /* the carry can be at most 1 */
        !           313:          else if (kc==0) goto round_b;
        !           314:          /* else round c: go through */
        !           315:        case 3: /* only c to round */
        !           316:          bp=cp; k=cn-k; goto to_nearest;
        !           317:        case 0: /* only b to round */
        !           318:         round_b:
        !           319:          k=bn-an; dif=0; goto to_nearest;
        !           320:         /* otherwise the result is exact: nothing to do */
        !           321:        }
        !           322:     }
        !           323:     else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
        !           324:             (ISNEG(b) && rnd_mode==GMP_RNDD)) {
        !           325:       cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           326:       *ap &= ~cc; /* truncate last bits */
        !           327:       if (cc) goto add_one_ulp; /* will happen most of the time */
        !           328:       else { /* same four cases too */
        !           329:        int kc = cn-k; /* remains kc limbs from c */
        !           330:        switch (overlap)
        !           331:        {
        !           332:         case 1: /* both b and c to round */
        !           333:          k = bn-an; /* remains k limbs from b */
        !           334:           dif = diff_exp % mp_bits_per_limb;
        !           335:          while (cc==0 && k!=0 && kc!=0) {
        !           336:            kc--;
        !           337:            cc = bp[--k] - (cp[kc]>>dif);
        !           338:            if (dif) cc -= (cp[kc+1]<<(mp_bits_per_limb-dif));
        !           339:          }
        !           340:          if (cc) goto add_one_ulp;
        !           341:          else if (kc==0) goto round_b2;
        !           342:          /* else round c: go through */
        !           343:        case 3: /* only c to round: nothing to do */
        !           344:          /* while (kc) if (cp[--kc]) goto add_one_ulp; */
        !           345:          /* if dif>0 : remains to check last dif bits from c */
        !           346:          /* if (dif>0 && (cp[0]<<(mp_bits_per_limb-dif))) goto add_one_ulp; */
        !           347:          break;
        !           348:        case 0: /* only b to round */
        !           349:         round_b2:
        !           350:          k=bn-an;
        !           351:          while (k) if (bp[--k]) goto add_one_ulp;
        !           352:         /* otherwise the result is exact: nothing to do */
        !           353:        }
        !           354:       }
        !           355:     }
        !           356:     /* else round to zero: remove 1 ulp if neglected bits from b-c are < 0 */
        !           357:     else {
        !           358:       cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           359:       *ap &= ~cc;
        !           360:       if (cc==0) { /* otherwise neglected difference cannot be < 0 */
        !           361:        /* take into account bp[0]..bp[bn-cancel1-1] shifted by cancel2 to left
        !           362:           and cp[0]..cp[cn-k-1] shifted by dif bits to right */
        !           363:        switch (overlap) {
        !           364:        case 0:
        !           365:        case 2:
        !           366:          break; /* c is not truncated ==> no borrow */
        !           367:        case 1: /* both b and c are truncated */
        !           368:          break;
        !           369:        case 3: /* only c is truncated */
        !           370:          cn -= k; /* take into account cp[0]..cp[cn-1] shifted by dif bits
        !           371:                      to the right */
        !           372:          cc = (dif>0) ? cp[cn]<<(mp_bits_per_limb-dif) : 0;
        !           373:          while (cc==0 && cn>0) cc = cp[--cn];
        !           374:           if (cc) goto sub_one_ulp;
        !           375:          break;
        !           376:        }
        !           377:       }
        !           378:     }
        !           379:   }
        !           380:   goto end_of_sub;
        !           381:
        !           382:   to_nearest: /* 0 <= sh < mp_bits_per_limb : number of bits of a to truncate
        !           383:                  bp[k] : last significant limb from b */
        !           384: #ifdef DEBUG
        !           385: mpfr_print_raw(a); putchar('\n');
        !           386: #endif
        !           387:         if (sh) {
        !           388:          cc = *ap & (((mp_limb_t)1<<sh)-1);
        !           389:          *ap &= ~cc; /* truncate last bits */
        !           390:          c2 = (mp_limb_t)1<<(sh-1);
        !           391:        }
        !           392:        else /* no bit to truncate */
        !           393:          { if (k) cc = bp[--k]; else cc = 0; c2 = (mp_limb_t)1<<(mp_bits_per_limb-1); }
        !           394: #ifdef DEBUG
        !           395:        printf("cc=%lu c2=%lu k=%u\n",cc,c2,k);
        !           396: #endif
        !           397:        if (cc>c2) goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
        !           398:        else if (cc==c2) {
        !           399:          cc=0; while (k && cc==0) cc=bp[--k];
        !           400: #ifdef DEBUG
        !           401:          printf("cc=%lu\n",cc);
        !           402: #endif
        !           403:          /* special case of rouding c shifted to the right */
        !           404:          if (cc==0 && dif>0) cc=bp[0]<<(mp_bits_per_limb-dif);
        !           405:          /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
        !           406:           if (bp!=cp) {
        !           407:            if (cc || (*ap & ((mp_limb_t)1<<sh))) goto add_one_ulp;
        !           408:          }
        !           409:          else {
        !           410:            /* subtract: if cc>0, do nothing */
        !           411:            if (cc==0 && (*ap & ((mp_limb_t)1<<sh))) goto add_one_ulp;
        !           412:          }
        !           413:        }
        !           414:         goto end_of_sub;
        !           415:
        !           416:  sub_one_ulp:
        !           417:     cc = mpn_sub_1(ap, ap, an, (mp_limb_t)1<<sh);
        !           418:   goto end_of_sub;
        !           419:
        !           420:   add_one_ulp: /* add one unit in last place to a */
        !           421:     cc = mpn_add_1(ap, ap, an, (mp_limb_t)1<<sh);
        !           422:
        !           423:  end_of_sub:
        !           424: #ifdef DEBUG
        !           425: printf("b-c="); if (SIGN(a)>0) putchar(' '); mpfr_print_raw(a); putchar('\n');
        !           426: #endif
        !           427:   TMP_FREE(marker);
        !           428:   return;
        !           429: }
        !           430:
        !           431: void
        !           432: #if __STDC__
        !           433: mpfr_sub(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, unsigned char rnd_mode)
        !           434: #else
        !           435: mpfr_sub(a, b, c, rnd_mode)
        !           436:      mpfr_ptr a;
        !           437:      mpfr_srcptr b;
        !           438:      mpfr_srcptr c;
        !           439:      unsigned char rnd_mode;
        !           440: #endif
        !           441: {
        !           442:   int diff_exp;
        !           443:
        !           444:   if (FLAG_NAN(b) || FLAG_NAN(c)) { SET_NAN(a); return; }
        !           445:
        !           446:   if (!NOTZERO(b)) { mpfr_neg(a, c, rnd_mode); return; }
        !           447:   if (!NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
        !           448:
        !           449:   diff_exp = EXP(b)-EXP(c);
        !           450:   if (SIGN(b) == SIGN(c)) { /* signs are equal, it's a real subtraction */
        !           451:     if (diff_exp<0) {
        !           452:       /* exchange rounding modes towards +/- infinity */
        !           453:       if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
        !           454:       else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
        !           455:       mpfr_sub1(a, c, b, rnd_mode, -diff_exp);
        !           456:       CHANGE_SIGN(a);
        !           457:     }
        !           458:     else if (diff_exp>0) mpfr_sub1(a, b, c, rnd_mode, diff_exp);
        !           459:     else { /* diff_exp=0 */
        !           460:       diff_exp = mpfr_cmp3(b,c,1);
        !           461:       /* if b>0 and diff_exp>0 or b<0 and diff_exp<0: abs(b) > abs(c) */
        !           462:       if (diff_exp==0) SET_ZERO(a);
        !           463:       else if (diff_exp*SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
        !           464:       else {
        !           465:        /* exchange rounding modes towards +/- infinity */
        !           466:        if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
        !           467:        else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
        !           468:        mpfr_sub1(a, c, b, rnd_mode, 0);
        !           469:        CHANGE_SIGN(a);
        !           470:       }
        !           471:     }
        !           472:   }
        !           473:   else /* signs differ, it's an addition */
        !           474:     if (diff_exp<0) {
        !           475:       /* exchange rounding modes towards +/- infinity */
        !           476:       if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
        !           477:       else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
        !           478:       mpfr_add1(a, c, b, rnd_mode, -diff_exp);
        !           479:       CHANGE_SIGN(a);
        !           480:     }
        !           481:     else mpfr_add1(a, b, c, rnd_mode, diff_exp);
        !           482: }
        !           483:

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