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>