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