Annotation of OpenXM_contrib/gmp/mpf/sub.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpf_sub -- Subtract two floats.
2:
3: Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
4:
5: This file is part of the GNU MP Library.
6:
7: The GNU MP 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 GNU MP 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 GNU MP 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 "gmp.h"
23: #include "gmp-impl.h"
24:
25: void
26: #if __STDC__
27: mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
28: #else
29: mpf_sub (r, u, v)
30: mpf_ptr r;
31: mpf_srcptr u;
32: mpf_srcptr v;
33: #endif
34: {
35: mp_srcptr up, vp;
36: mp_ptr rp, tp;
37: mp_size_t usize, vsize, rsize;
38: mp_size_t prec;
39: mp_exp_t exp;
40: mp_size_t ediff;
41: int negate;
42: TMP_DECL (marker);
43:
44: usize = u->_mp_size;
45: vsize = v->_mp_size;
46:
47: /* Handle special cases that don't work in generic code below. */
48: if (usize == 0)
49: {
50: mpf_neg (r, v);
51: return;
52: }
53: if (vsize == 0)
54: {
55: mpf_set (r, u);
56: return;
57: }
58:
59: /* If signs of U and V are different, perform addition. */
60: if ((usize ^ vsize) < 0)
61: {
62: __mpf_struct v_negated;
63: v_negated._mp_size = -vsize;
64: v_negated._mp_exp = v->_mp_exp;
65: v_negated._mp_d = v->_mp_d;
66: mpf_add (r, u, &v_negated);
67: return;
68: }
69:
70: TMP_MARK (marker);
71:
72: /* Signs are now known to be the same. */
73: negate = usize < 0;
74:
75: /* Make U be the operand with the largest exponent. */
76: if (u->_mp_exp < v->_mp_exp)
77: {
78: mpf_srcptr t;
79: t = u; u = v; v = t;
80: negate ^= 1;
81: usize = u->_mp_size;
82: vsize = v->_mp_size;
83: }
84:
85: usize = ABS (usize);
86: vsize = ABS (vsize);
87: up = u->_mp_d;
88: vp = v->_mp_d;
89: rp = r->_mp_d;
90: prec = r->_mp_prec + 1;
91: exp = u->_mp_exp;
92: ediff = u->_mp_exp - v->_mp_exp;
93:
94: /* If ediff is 0 or 1, we might have a situation where the operands are
95: extremely close. We need to scan the operands from the most significant
96: end ignore the initial parts that are equal. */
97: if (ediff <= 1)
98: {
99: if (ediff == 0)
100: {
101: /* Skip leading limbs in U and V that are equal. */
102: if (up[usize - 1] == vp[vsize - 1])
103: {
104: /* This loop normally exits immediately. Optimize for that. */
105: do
106: {
107: usize--;
108: vsize--;
109: exp--;
110:
111: if (usize == 0)
112: {
113: rsize = vsize;
114: tp = (mp_ptr) vp;
115: negate ^= 1;
116: goto normalize;
117: }
118: if (vsize == 0)
119: {
120: rsize = usize;
121: tp = (mp_ptr) up;
122: goto normalize;
123: }
124: }
125: while (up[usize - 1] == vp[vsize - 1]);
126: }
127:
128: if (up[usize - 1] < vp[vsize - 1])
129: {
130: /* For simplicity, swap U and V. Note that since the loop above
131: wouldn't have exited unless up[usize - 1] and vp[vsize - 1]
132: were non-equal, this if-statement catches all cases where U
133: is smaller than V. */
134: { mp_srcptr tp = up; up = vp; vp = tp; }
135: { mp_size_t tsize = usize; usize = vsize; vsize = tsize; }
136: negate ^= 1;
137: /* negating ediff not necessary since it is 0. */
138: }
139:
140: /* Check for
141: x+1 00000000 ...
142: x ffffffff ... */
143: if (up[usize - 1] != vp[vsize - 1] + 1)
144: goto general_case;
145: usize--;
146: vsize--;
147: exp--;
148: }
149: else /* ediff == 1 */
150: {
151: /* Check for
152: 1 00000000 ...
153: 0 ffffffff ... */
154:
155: if (up[usize - 1] != 1 || vp[vsize - 1] != ~(mp_limb_t) 0
156: || (usize >= 2 && up[usize - 2] != 0))
157: goto general_case;
158:
159: usize--;
160: exp--;
161: }
162:
163: /* Skip sequences of 00000000/ffffffff */
164: while (vsize != 0 && usize != 0 && up[usize - 1] == 0
165: && vp[vsize - 1] == ~(mp_limb_t) 0)
166: {
167: usize--;
168: vsize--;
169: exp--;
170: }
171:
172: if (usize == 0)
173: {
174: while (vsize != 0 && vp[vsize - 1] == ~(mp_limb_t) 0)
175: {
176: vsize--;
177: exp--;
178: }
179: }
180:
181: if (usize > prec - 1)
182: {
183: up += usize - (prec - 1);
184: usize = prec - 1;
185: }
186: if (vsize > prec - 1)
187: {
188: vp += vsize - (prec - 1);
189: vsize = prec - 1;
190: }
191:
192: tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
193: {
194: mp_limb_t cy_limb;
195: if (vsize == 0)
196: {
197: mp_size_t size, i;
198: size = usize;
199: for (i = 0; i < size; i++)
200: tp[i] = up[i];
201: tp[size] = 1;
202: rsize = size + 1;
203: exp++;
204: goto normalize;
205: }
206: if (usize == 0)
207: {
208: mp_size_t size, i;
209: size = vsize;
210: for (i = 0; i < size; i++)
211: tp[i] = ~vp[i];
212: cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
213: rsize = vsize;
214: if (cy_limb == 0)
215: {
216: tp[rsize] = 1;
217: rsize++;
218: exp++;
219: }
220: goto normalize;
221: }
222: if (usize >= vsize)
223: {
224: /* uuuu */
225: /* vv */
226: mp_size_t size;
227: size = usize - vsize;
228: MPN_COPY (tp, up, size);
229: cy_limb = mpn_sub_n (tp + size, up + size, vp, vsize);
230: rsize = usize;
231: }
232: else /* (usize < vsize) */
233: {
234: /* uuuu */
235: /* vvvvvvv */
236: mp_size_t size, i;
237: size = vsize - usize;
238: for (i = 0; i < size; i++)
239: tp[i] = ~vp[i];
240: cy_limb = mpn_sub_n (tp + size, up, vp + size, usize);
241: cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
242: cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
243: rsize = vsize;
244: }
245: if (cy_limb == 0)
246: {
247: tp[rsize] = 1;
248: rsize++;
249: exp++;
250: }
251: goto normalize;
252: }
253: }
254:
255: general_case:
256: /* If U extends beyond PREC, ignore the part that does. */
257: if (usize > prec)
258: {
259: up += usize - prec;
260: usize = prec;
261: }
262:
263: /* If V extends beyond PREC, ignore the part that does.
264: Note that this may make vsize negative. */
265: if (vsize + ediff > prec)
266: {
267: vp += vsize + ediff - prec;
268: vsize = prec - ediff;
269: }
270:
271: /* Allocate temp space for the result. Allocate
272: just vsize + ediff later??? */
273: tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
274:
275: if (ediff >= prec)
276: {
277: /* V completely cancelled. */
278: if (tp != up)
279: MPN_COPY (rp, up, usize);
280: rsize = usize;
281: }
282: else
283: {
284: /* Locate the least significant non-zero limb in (the needed
285: parts of) U and V, to simplify the code below. */
286: for (;;)
287: {
288: if (vsize == 0)
289: {
290: MPN_COPY (rp, up, usize);
291: rsize = usize;
292: goto done;
293: }
294: if (vp[0] != 0)
295: break;
296: vp++, vsize--;
297: }
298: for (;;)
299: {
300: if (usize == 0)
301: {
302: MPN_COPY (rp, vp, vsize);
303: rsize = vsize;
304: negate ^= 1;
305: goto done;
306: }
307: if (up[0] != 0)
308: break;
309: up++, usize--;
310: }
311:
312: /* uuuu | uuuu | uuuu | uuuu | uuuu */
313: /* vvvvvvv | vv | vvvvv | v | vv */
314:
315: if (usize > ediff)
316: {
317: /* U and V partially overlaps. */
318: if (ediff == 0)
319: {
320: /* Have to compare the leading limbs of u and v
321: to determine whether to compute u - v or v - u. */
322: if (usize >= vsize)
323: {
324: /* uuuu */
325: /* vv */
326: mp_size_t size;
327: size = usize - vsize;
328: MPN_COPY (tp, up, size);
329: mpn_sub_n (tp + size, up + size, vp, vsize);
330: rsize = usize;
331: }
332: else /* (usize < vsize) */
333: {
334: /* uuuu */
335: /* vvvvvvv */
336: mp_size_t size, i;
337: size = vsize - usize;
338: tp[0] = -vp[0];
339: for (i = 1; i < size; i++)
340: tp[i] = ~vp[i];
341: mpn_sub_n (tp + size, up, vp + size, usize);
342: mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
343: rsize = vsize;
344: }
345: }
346: else
347: {
348: if (vsize + ediff <= usize)
349: {
350: /* uuuu */
351: /* v */
352: mp_size_t size;
353: size = usize - ediff - vsize;
354: MPN_COPY (tp, up, size);
355: mpn_sub (tp + size, up + size, usize - size, vp, vsize);
356: rsize = usize;
357: }
358: else
359: {
360: /* uuuu */
361: /* vvvvv */
362: mp_size_t size, i;
363: size = vsize + ediff - usize;
364: tp[0] = -vp[0];
365: for (i = 1; i < size; i++)
366: tp[i] = ~vp[i];
367: mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
368: mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
369: rsize = vsize + ediff;
370: }
371: }
372: }
373: else
374: {
375: /* uuuu */
376: /* vv */
377: mp_size_t size, i;
378: size = vsize + ediff - usize;
379: tp[0] = -vp[0];
380: for (i = 1; i < vsize; i++)
381: tp[i] = ~vp[i];
382: for (i = vsize; i < size; i++)
383: tp[i] = ~(mp_limb_t) 0;
384: mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
385: rsize = size + usize;
386: }
387:
388: normalize:
389: /* Full normalize. Optimize later. */
390: while (rsize != 0 && tp[rsize - 1] == 0)
391: {
392: rsize--;
393: exp--;
394: }
395: MPN_COPY (rp, tp, rsize);
396: }
397:
398: done:
399: r->_mp_size = negate ? -rsize : rsize;
400: r->_mp_exp = exp;
401: TMP_FREE (marker);
402: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>