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>