Annotation of OpenXM_contrib/gmp/mpfr/round.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpfr_round_raw2, mpfr_round_raw, mpfr_round, mpfr_can_round,
2: mpfr_can_round_raw -- various rounding functions
3:
4: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
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 Library General Public License as published by
10: the Free Software Foundation; either version 2 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 Library General Public
16: License for more details.
17:
18: You should have received a copy of the GNU Library 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 <stdio.h>
24: #include "gmp.h"
25: #include "gmp-impl.h"
26: #include "mpfr.h"
27:
28: #ifdef Exp
29: #include "longlong.h"
30: #endif
31:
32: /* returns 0 if round(sign*xp[0..xn-1], prec, rnd) =
33: round(sign*xp[0..xn-1], prec, GMP_RNDZ), 1 otherwise,
34: where sign=1 if neg=0, sign=-1 otherwise.
35:
36: Does *not* modify anything.
37: */
38: int
39: #if __STDC__
40: mpfr_round_raw2(mp_limb_t *xp, unsigned long xn,
41: char neg, char rnd, unsigned long prec)
42: #else
43: mpfr_round_raw2(xp, xn, neg, rnd, prec)
44: mp_limb_t *xp;
45: unsigned long xn;
46: char neg;
47: char rnd;
48: unsigned long prec;
49: #endif
50: {
51: unsigned long nw; long wd; char rw; short l; mp_limb_t mask;
52:
53: nw = prec / BITS_PER_MP_LIMB; rw = prec & (BITS_PER_MP_LIMB - 1);
54: if (rw) nw++;
55: if (rnd==GMP_RNDZ || xn<nw || (rnd==GMP_RNDU && neg)
56: || (rnd==GMP_RNDD && neg==0)) return 0;
57:
58: mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - 1);
59: switch (rnd)
60: {
61: case GMP_RNDU:
62: case GMP_RNDD:
63: if (xp[xn - nw] & ~mask) return 1;
64: for (l = nw + 1;l <= xn; l++)
65: if (xp[xn - l]) break;
66: return (l <= xn);
67:
68: case GMP_RNDN:
69: /* First check if we are just halfway between two representable numbers */
70: wd = xn - nw;
71: if (!rw)
72: {
73: if (!wd) /* all bits are significative */ return 0;
74: wd--;
75: if (xp[wd] == ((mp_limb_t)1 << (BITS_PER_MP_LIMB - 1)))
76: {
77: do wd--; while (wd > 0 && !xp[wd]);
78: if (!wd) { return 1; } else return xp[xn - nw] & 1;
79: }
80:
81: return xp[wd]>>(BITS_PER_MP_LIMB - 1);
82: }
83: else
84: if (rw + 1 < BITS_PER_MP_LIMB)
85: {
86: if ((xp[wd] & (~mask)) == (((mp_limb_t)1) << (BITS_PER_MP_LIMB - rw - 1)))
87: do { wd--; } while (wd >= 0 && !xp[wd]);
88: else return ((xp[wd]>>(BITS_PER_MP_LIMB - rw - 1)) & 1);
89:
90: /* first limb was in the middle, and others down to wd+1 were 0 */
91: if (wd>=0) return 1;
92: else
93: return ((xp[xn - nw] & mask) >> (BITS_PER_MP_LIMB - rw)) & 1;
94: }
95: else
96: /* Modified PZ, 27 May 1999:
97: rw, i.e. the number of bits stored in xp[xn-nw], is
98: BITS_PER_MP_LIMB-1, i.e. there is exactly one non significant bit.
99: We are just halfway iff xp[wd] has its low significant bit
100: set and all limbs xp[0]...xp[wd-1] are zero */
101: {
102: if (xp[wd] & 1)
103: do wd--; while (wd >= 0 && !xp[wd]);
104: return ((wd<0) ? xp[xn-nw]>>1 : xp[xn-nw]) & 1;
105: }
106: default: return 0;
107: }
108: }
109:
110: /* puts in y the value of xp (with precision xprec and sign 1 if negative=0,
111: -1 otherwise) rounded to precision yprec and direction RND_MODE
112: Supposes x is not zero nor NaN nor +/- Infinity (i.e. *xp != 0).
113: */
114: int
115: #if __STDC__
116: mpfr_round_raw(mp_limb_t *y, mp_limb_t *xp, unsigned long xprec, char negative,
117: unsigned long yprec, char RND_MODE)
118: #else
119: mpfr_round_raw(y, xp, xprec, negative, yprec, RND_MODE)
120: mp_limb_t *y;
121: mp_limb_t *xp;
122: unsigned long xprec;
123: char negative;
124: unsigned long yprec;
125: char RND_MODE;
126: #endif
127: {
128: unsigned long nw, xsize; mp_limb_t mask;
129: char rw, xrw, carry = 0;
130:
131: xsize = (xprec-1)/BITS_PER_MP_LIMB + 1;
132: xrw = xprec % BITS_PER_MP_LIMB; if (xrw == 0) { xrw = BITS_PER_MP_LIMB; }
133:
134: #ifdef Exp
135: count_leading_zeros(flag, xp[xsize-1]);
136: yprec += flag;
137: #endif
138:
139: nw = yprec / BITS_PER_MP_LIMB; rw = yprec & (BITS_PER_MP_LIMB - 1);
140: if (rw) nw++;
141: /* number of words needed to represent x */
142:
143: mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - (mp_limb_t)1);
144:
145: /* precision is larger than the size of x. No rounding is necessary.
146: Just add zeroes at the end */
147: if (xsize < nw) {
148: MPN_COPY(y + nw - xsize, xp, xsize);
149: MPN_ZERO(y, nw - xsize); /* PZ 27 May 99 */
150: y[0] &= mask;
151: return 0;
152: }
153:
154: if (mpfr_round_raw2(xp, xsize, negative, RND_MODE, yprec))
155: carry = mpn_add_1(y, xp + xsize - nw, nw,
156: ((mp_limb_t)1) << (BITS_PER_MP_LIMB - rw));
157: else MPN_COPY(y, xp + xsize - nw, nw);
158:
159: y[0] &= mask;
160: return carry;
161: }
162:
163: void
164: #if __STDC__
165: mpfr_round(mpfr_t x, char RND_MODE, unsigned long prec)
166: #else
167: mpfr_round(x, RND_MODE, prec)
168: mpfr_t x;
169: char RND_MODE;
170: unsigned long prec;
171: #endif
172: {
173: mp_limb_t *tmp; int carry; unsigned long nw;
174: TMP_DECL(marker);
175:
176: nw = prec / BITS_PER_MP_LIMB;
177: if (prec & (BITS_PER_MP_LIMB - 1)) nw++;
178: TMP_MARK(marker);
179: tmp = TMP_ALLOC (nw * BYTES_PER_MP_LIMB);
180: carry = mpfr_round_raw(tmp, MANT(x), PREC(x), (SIGN(x)<0), prec, RND_MODE);
181:
182: if (carry)
183: {
184: mpn_rshift(tmp, tmp, nw, 1);
185: tmp [nw-1] |= (((mp_limb_t)1) << (BITS_PER_MP_LIMB - 1));
186: EXP(x)++;
187: }
188:
189: if (SIGN(x)<0) { SIZE(x)=nw; CHANGE_SIGN(x); } else SIZE(x)=nw;
190: PREC(x) = prec;
191: MPN_COPY(MANT(x), tmp, nw);
192: TMP_FREE(marker);
193: }
194:
195: /* hypotheses : BITS_PER_MP_LIMB est une puissance de 2
196: dans un test, la premiere partie du && est evaluee d'abord */
197:
198:
199: /* assuming b is an approximation of x in direction rnd1
200: with error at most 2^(EXP(b)-err), returns 1 if one is
201: able to round exactly x to precision prec with direction rnd2,
202: and 0 otherwise.
203:
204: Side effects: none.
205: */
206:
207: int
208: #if __STDC__
209: mpfr_can_round(mpfr_t b, unsigned long err, unsigned char rnd1,
210: unsigned char rnd2, unsigned long prec)
211: #else
212: mpfr_can_round(b, err, rnd1, rnd2, prec)
213: mpfr_t b;
214: unsigned long err;
215: unsigned char rnd1;
216: unsigned char rnd2;
217: unsigned long prec;
218: #endif
219: {
220: return mpfr_can_round_raw(MANT(b), (PREC(b) - 1)/BITS_PER_MP_LIMB + 1,
221: SIGN(b), err, rnd1, rnd2, prec);
222: }
223:
224: int
225: #if __STDC__
226: mpfr_can_round_raw(mp_limb_t *bp, unsigned long bn, int neg,
227: unsigned long err, unsigned char rnd1, unsigned char rnd2,
228: unsigned long prec)
229: #else
230: mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
231: mp_limb_t *bp;
232: unsigned long bn;
233: int neg;
234: unsigned long err;
235: unsigned char rnd1;
236: unsigned char rnd2;
237: unsigned long prec;
238: #endif
239: {
240: int k, k1, l, l1, tn; mp_limb_t cc, cc2, *tmp;
241: TMP_DECL(marker);
242:
243: if (err<=prec) return 0;
244: neg = (neg > 0 ? 0 : 1);
245:
246: /* warning: if k = m*BITS_PER_MP_LIMB, consider limb m-1 and not m */
247: k = (err-1)/BITS_PER_MP_LIMB;
248: l = err % BITS_PER_MP_LIMB; if (l) l = BITS_PER_MP_LIMB-l;
249: /* the error corresponds to bit l in limb k */
250: k1 = (prec-1)/BITS_PER_MP_LIMB;
251: l1 = prec%BITS_PER_MP_LIMB; if (l1) l1 = BITS_PER_MP_LIMB-l1;
252:
253: /* the last significant bit is bit l1 in limb k1 */
254:
255: /* don't need to consider the k1 most significant limbs */
256: k -= k1; bn -= k1; prec -= k1*BITS_PER_MP_LIMB; k1=0;
257:
258: if (rnd1==GMP_RNDU) { if (neg) rnd1=GMP_RNDZ; }
259: if (rnd1==GMP_RNDD) { if (neg) rnd1=GMP_RNDU; else rnd1=GMP_RNDZ; }
260:
261: /* in the sequel, RNDU = towards infinity, RNDZ = towards zero */
262:
263: TMP_MARK(marker);
264: tn = bn;
265: k++; /* since we work with k+1 everywhere */
266:
267: switch (rnd1) {
268:
269: case GMP_RNDZ: /* b <= x <= b+2^(EXP(b)-err) */
270: tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
271: cc = (bp[bn-1]>>l1) & 1;
272: cc ^= mpfr_round_raw2(bp, bn, neg, rnd2, prec);
273:
274: /* now round b+2^(EXP(b)-err) */
275: cc2 = mpn_add_1(tmp+bn-k, bp+bn-k, k, (mp_limb_t)1<<l);
276: /* if carry, then all bits up to err were to 1, and we can round only
277: if cc==0 and mpfr_round_raw2 returns 0 below */
278: if (cc2 && cc) { TMP_FREE(marker); return 0; }
279: cc2 = (tmp[bn-1]>>l1) & 1; /* gives 0 when carry */
280: cc2 ^= mpfr_round_raw2(tmp, bn, neg, rnd2, prec);
281:
282: TMP_FREE(marker);
283: return (cc == cc2);
284:
285: case GMP_RNDU: /* b-2^(EXP(b)-err) <= x <= b */
286: tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
287: /* first round b */
288: cc = (bp[bn-1]>>l1) & 1;
289: cc ^= mpfr_round_raw2(bp, bn, neg, rnd2, prec);
290:
291: /* now round b-2^(EXP(b)-err) */
292: cc2 = mpn_sub_1(tmp+bn-k, bp+bn-k, k, (mp_limb_t)1<<l);
293: /* if borrow, then all bits up to err were to 0, and we can round only
294: if cc==0 and mpfr_round_raw2 returns 1 below */
295: if (cc2 && cc) { TMP_FREE(marker); return 0; }
296: cc2 = (tmp[bn-1]>>l1) & 1; /* gives 1 when carry */
297: cc2 ^= mpfr_round_raw2(tmp, bn, neg, rnd2, prec);
298:
299: TMP_FREE(marker);
300: return (cc == cc2);
301:
302: case GMP_RNDN: /* b-2^(EXP(b)-err-1) <= x <= b+2^(EXP(b)-err-1) */
303: if (l==0) tn++;
304: tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
305:
306: /* this case is the same than GMP_RNDZ, except we first have to
307: subtract 2^(EXP(b)-err-1) from b */
308:
309: if (l) {
310: l--; /* tn=bn */
311: mpn_sub_1(tmp+tn-k, bp+bn-k, k, (mp_limb_t)1<<l);
312: }
313: else {
314: MPN_COPY(tmp+1, bp, bn); *tmp=0; /* extra limb to add or subtract 1 */
315: k++; l=BITS_PER_MP_LIMB-1;
316: mpn_sub_1(tmp+tn-k, tmp+tn-k, k, (mp_limb_t)1<<l);
317: }
318:
319: /* round b-2^(EXP(b)-err-1) */
320: /* we can disregard borrow, since we start from tmp in 2nd case too */
321: cc = (tmp[tn-1]>>l1) & 1;
322: cc ^= mpfr_round_raw2(tmp, tn, neg, rnd2, prec);
323:
324: if (l==BITS_PER_MP_LIMB-1) { l=0; k--; } else l++;
325:
326: /* round b+2^(EXP(b)-err-1) = b-2^(EXP(b)-err-1) + 2^(EXP(b)-err) */
327: cc2 = mpn_add_1(tmp+tn-k, tmp+tn-k, k, (mp_limb_t)1<<l);
328: /* if carry, then all bits up to err were to 1, and we can round only
329: if cc==0 and mpfr_round_raw2 returns 0 below */
330: if (cc2 && cc) { TMP_FREE(marker); return 0; }
331: cc2 = (tmp[tn-1]>>l1) & 1; /* gives 0 when carry */
332: cc2 ^= mpfr_round_raw2(tmp, tn, neg, rnd2, prec);
333:
334: TMP_FREE(marker);
335: return (cc == cc2);
336: }
337: return 0;
338: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>