Annotation of OpenXM_contrib/gmp/mpfr/add1.c, Revision 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>